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
check_num(const char * s,const int is_hex)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
prime_main(int argc,char ** argv)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