1 1.1 christos /* 2 1.1 christos * Copyright 2004-2022 The OpenSSL Project Authors. All Rights Reserved. 3 1.1 christos * 4 1.1 christos * Licensed under the Apache License 2.0 (the "License"). You may not use 5 1.1 christos * this file except in compliance with the License. You can obtain a copy 6 1.1 christos * in the file LICENSE in the source distribution or at 7 1.1 christos * https://www.openssl.org/source/license.html 8 1.1 christos */ 9 1.1 christos 10 1.1 christos #include <string.h> 11 1.1 christos 12 1.1 christos #include "apps.h" 13 1.1 christos #include "progs.h" 14 1.1 christos #include <openssl/bn.h> 15 1.1 christos 16 1.1 christos typedef enum OPTION_choice { 17 1.1 christos OPT_COMMON, 18 1.1.1.2 christos OPT_HEX, 19 1.1.1.2 christos OPT_GENERATE, 20 1.1.1.2 christos OPT_BITS, 21 1.1.1.2 christos OPT_SAFE, 22 1.1.1.2 christos OPT_CHECKS, 23 1.1 christos OPT_PROV_ENUM 24 1.1 christos } OPTION_CHOICE; 25 1.1 christos 26 1.1 christos static int check_num(const char *s, const int is_hex) 27 1.1 christos { 28 1.1 christos int i; 29 1.1 christos /* 30 1.1 christos * It would make sense to use ossl_isxdigit and ossl_isdigit here, 31 1.1 christos * but ossl_ctype_check is a local symbol in libcrypto.so. 32 1.1 christos */ 33 1.1 christos if (is_hex) { 34 1.1 christos for (i = 0; ('0' <= s[i] && s[i] <= '9') 35 1.1.1.2 christos || ('A' <= s[i] && s[i] <= 'F') 36 1.1.1.2 christos || ('a' <= s[i] && s[i] <= 'f'); 37 1.1.1.2 christos i++) 38 1.1.1.2 christos ; 39 1.1 christos } else { 40 1.1.1.2 christos for (i = 0; '0' <= s[i] && s[i] <= '9'; i++) 41 1.1.1.2 christos ; 42 1.1 christos } 43 1.1 christos return s[i] == 0; 44 1.1 christos } 45 1.1 christos 46 1.1 christos const OPTIONS prime_options[] = { 47 1.1.1.2 christos { OPT_HELP_STR, 1, '-', "Usage: %s [options] [number...]\n" }, 48 1.1 christos 49 1.1 christos OPT_SECTION("General"), 50 1.1.1.2 christos { "help", OPT_HELP, '-', "Display this summary" }, 51 1.1.1.2 christos { "bits", OPT_BITS, 'p', "Size of number in bits" }, 52 1.1.1.2 christos { "checks", OPT_CHECKS, 'p', "Number of checks" }, 53 1.1 christos 54 1.1 christos OPT_SECTION("Output"), 55 1.1.1.2 christos { "hex", OPT_HEX, '-', "Hex output" }, 56 1.1.1.2 christos { "generate", OPT_GENERATE, '-', "Generate a prime" }, 57 1.1.1.2 christos { "safe", OPT_SAFE, '-', 58 1.1.1.2 christos "When used with -generate, generate a safe prime" }, 59 1.1 christos 60 1.1 christos OPT_PROV_OPTIONS, 61 1.1 christos 62 1.1 christos OPT_PARAMETERS(), 63 1.1.1.2 christos { "number", 0, 0, "Number(s) to check for primality if not generating" }, 64 1.1.1.2 christos { NULL } 65 1.1 christos }; 66 1.1 christos 67 1.1 christos int prime_main(int argc, char **argv) 68 1.1 christos { 69 1.1 christos BIGNUM *bn = NULL; 70 1.1 christos int hex = 0, generate = 0, bits = 0, safe = 0, ret = 1; 71 1.1 christos char *prog; 72 1.1 christos OPTION_CHOICE o; 73 1.1 christos 74 1.1 christos prog = opt_init(argc, argv, prime_options); 75 1.1 christos while ((o = opt_next()) != OPT_EOF) { 76 1.1 christos switch (o) { 77 1.1 christos case OPT_EOF: 78 1.1 christos case OPT_ERR: 79 1.1.1.2 christos opthelp: 80 1.1 christos BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 81 1.1 christos goto end; 82 1.1 christos case OPT_HELP: 83 1.1 christos opt_help(prime_options); 84 1.1 christos ret = 0; 85 1.1 christos goto end; 86 1.1 christos case OPT_HEX: 87 1.1 christos hex = 1; 88 1.1 christos break; 89 1.1 christos case OPT_GENERATE: 90 1.1 christos generate = 1; 91 1.1 christos break; 92 1.1 christos case OPT_BITS: 93 1.1 christos bits = atoi(opt_arg()); 94 1.1 christos break; 95 1.1 christos case OPT_SAFE: 96 1.1 christos safe = 1; 97 1.1 christos break; 98 1.1 christos case OPT_CHECKS: 99 1.1 christos /* ignore parameter and argument */ 100 1.1 christos opt_arg(); 101 1.1 christos break; 102 1.1 christos case OPT_PROV_CASES: 103 1.1 christos if (!opt_provider(o)) 104 1.1 christos goto end; 105 1.1 christos break; 106 1.1 christos } 107 1.1 christos } 108 1.1 christos 109 1.1 christos /* Optional arguments are numbers to check. */ 110 1.1 christos if (generate && !opt_check_rest_arg(NULL)) 111 1.1 christos goto opthelp; 112 1.1 christos argc = opt_num_rest(); 113 1.1 christos argv = opt_rest(); 114 1.1 christos if (!generate && argc == 0) { 115 1.1 christos BIO_printf(bio_err, "Missing number (s) to check\n"); 116 1.1 christos goto opthelp; 117 1.1 christos } 118 1.1 christos 119 1.1 christos if (generate) { 120 1.1 christos char *s; 121 1.1 christos 122 1.1 christos if (!bits) { 123 1.1 christos BIO_printf(bio_err, "Specify the number of bits.\n"); 124 1.1 christos goto end; 125 1.1 christos } 126 1.1 christos bn = BN_new(); 127 1.1 christos if (bn == NULL) { 128 1.1 christos BIO_printf(bio_err, "Out of memory.\n"); 129 1.1 christos goto end; 130 1.1 christos } 131 1.1 christos if (!BN_generate_prime_ex(bn, bits, safe, NULL, NULL, NULL)) { 132 1.1 christos BIO_printf(bio_err, "Failed to generate prime.\n"); 133 1.1 christos goto end; 134 1.1 christos } 135 1.1 christos s = hex ? BN_bn2hex(bn) : BN_bn2dec(bn); 136 1.1 christos if (s == NULL) { 137 1.1 christos BIO_printf(bio_err, "Out of memory.\n"); 138 1.1 christos goto end; 139 1.1 christos } 140 1.1 christos BIO_printf(bio_out, "%s\n", s); 141 1.1 christos OPENSSL_free(s); 142 1.1 christos } else { 143 1.1.1.2 christos for (; *argv; argv++) { 144 1.1 christos int r = check_num(argv[0], hex); 145 1.1 christos 146 1.1 christos if (r) 147 1.1 christos r = hex ? BN_hex2bn(&bn, argv[0]) : BN_dec2bn(&bn, argv[0]); 148 1.1 christos 149 1.1 christos if (!r) { 150 1.1 christos BIO_printf(bio_err, "Failed to process value (%s)\n", argv[0]); 151 1.1 christos goto end; 152 1.1 christos } 153 1.1 christos 154 1.1 christos BN_print(bio_out, bn); 155 1.1 christos r = BN_check_prime(bn, NULL, NULL); 156 1.1 christos if (r < 0) { 157 1.1 christos BIO_printf(bio_err, "Error checking prime\n"); 158 1.1 christos goto end; 159 1.1 christos } 160 1.1 christos BIO_printf(bio_out, " (%s) %s prime\n", 161 1.1.1.2 christos argv[0], 162 1.1.1.2 christos r == 1 ? "is" : "is not"); 163 1.1 christos } 164 1.1 christos } 165 1.1 christos 166 1.1 christos ret = 0; 167 1.1.1.2 christos end: 168 1.1 christos BN_free(bn); 169 1.1 christos return ret; 170 1.1 christos } 171