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