1*440d1414Stb /* $OpenBSD: prime.c,v 1.18 2023/07/23 11:39:29 tb Exp $ */
2dab3f910Sjsing /* ====================================================================
3dab3f910Sjsing * Copyright (c) 2004 The OpenSSL Project. All rights reserved.
4dab3f910Sjsing *
5dab3f910Sjsing * Redistribution and use in source and binary forms, with or without
6dab3f910Sjsing * modification, are permitted provided that the following conditions
7dab3f910Sjsing * are met:
8dab3f910Sjsing *
9dab3f910Sjsing * 1. Redistributions of source code must retain the above copyright
10dab3f910Sjsing * notice, this list of conditions and the following disclaimer.
11dab3f910Sjsing *
12dab3f910Sjsing * 2. Redistributions in binary form must reproduce the above copyright
13dab3f910Sjsing * notice, this list of conditions and the following disclaimer in
14dab3f910Sjsing * the documentation and/or other materials provided with the
15dab3f910Sjsing * distribution.
16dab3f910Sjsing *
17dab3f910Sjsing * 3. All advertising materials mentioning features or use of this
18dab3f910Sjsing * software must display the following acknowledgment:
19dab3f910Sjsing * "This product includes software developed by the OpenSSL Project
20dab3f910Sjsing * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
21dab3f910Sjsing *
22dab3f910Sjsing * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23dab3f910Sjsing * endorse or promote products derived from this software without
24dab3f910Sjsing * prior written permission. For written permission, please contact
25dab3f910Sjsing * openssl-core@openssl.org.
26dab3f910Sjsing *
27dab3f910Sjsing * 5. Products derived from this software may not be called "OpenSSL"
28dab3f910Sjsing * nor may "OpenSSL" appear in their names without prior written
29dab3f910Sjsing * permission of the OpenSSL Project.
30dab3f910Sjsing *
31dab3f910Sjsing * 6. Redistributions of any form whatsoever must retain the following
32dab3f910Sjsing * acknowledgment:
33dab3f910Sjsing * "This product includes software developed by the OpenSSL Project
34dab3f910Sjsing * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
35dab3f910Sjsing *
36dab3f910Sjsing * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37dab3f910Sjsing * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38dab3f910Sjsing * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39dab3f910Sjsing * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
40dab3f910Sjsing * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41dab3f910Sjsing * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42dab3f910Sjsing * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43dab3f910Sjsing * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44dab3f910Sjsing * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45dab3f910Sjsing * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46dab3f910Sjsing * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47dab3f910Sjsing * OF THE POSSIBILITY OF SUCH DAMAGE.
48dab3f910Sjsing *
49dab3f910Sjsing */
50dab3f910Sjsing
51dab3f910Sjsing #include <string.h>
52dab3f910Sjsing #include <limits.h>
53dab3f910Sjsing
54dab3f910Sjsing #include "apps.h"
55dab3f910Sjsing
56dab3f910Sjsing #include <openssl/bn.h>
57a7b8f3c1Sdoug #include <openssl/err.h>
58dab3f910Sjsing
59efc7e65fStb static struct {
604058704fSjsing int bits;
614058704fSjsing int checks;
624058704fSjsing int generate;
634058704fSjsing int hex;
644058704fSjsing int safe;
65e7718adaStb } cfg;
664058704fSjsing
67ea149709Sguenther static const struct option prime_options[] = {
684058704fSjsing {
694058704fSjsing .name = "bits",
704058704fSjsing .argname = "n",
714058704fSjsing .desc = "Number of bits in the generated prime number",
724058704fSjsing .type = OPTION_ARG_INT,
73e7718adaStb .opt.value = &cfg.bits,
744058704fSjsing },
754058704fSjsing {
764058704fSjsing .name = "checks",
774058704fSjsing .argname = "n",
78b6fa500dSjmc .desc = "Miller-Rabin probabilistic primality test iterations",
794058704fSjsing .type = OPTION_ARG_INT,
80e7718adaStb .opt.value = &cfg.checks,
814058704fSjsing },
824058704fSjsing {
834058704fSjsing .name = "generate",
844058704fSjsing .desc = "Generate a pseudo-random prime number",
854058704fSjsing .type = OPTION_FLAG,
86e7718adaStb .opt.flag = &cfg.generate,
874058704fSjsing },
884058704fSjsing {
894058704fSjsing .name = "hex",
904058704fSjsing .desc = "Hexadecimal prime numbers",
914058704fSjsing .type = OPTION_FLAG,
92e7718adaStb .opt.flag = &cfg.hex,
934058704fSjsing },
944058704fSjsing {
954058704fSjsing .name = "safe",
964058704fSjsing .desc = "Generate only \"safe\" prime numbers",
974058704fSjsing .type = OPTION_FLAG,
98e7718adaStb .opt.flag = &cfg.safe,
994058704fSjsing },
100d220e929Sbcook {NULL},
1014058704fSjsing };
1024058704fSjsing
1034058704fSjsing static void
prime_usage(void)104*440d1414Stb prime_usage(void)
1054058704fSjsing {
1064058704fSjsing fprintf(stderr,
1074058704fSjsing "usage: prime [-bits n] [-checks n] [-generate] [-hex] [-safe] "
1084058704fSjsing "p\n");
1094058704fSjsing options_usage(prime_options);
1104058704fSjsing }
1114058704fSjsing
112dab3f910Sjsing int
prime_main(int argc,char ** argv)113dab3f910Sjsing prime_main(int argc, char **argv)
114dab3f910Sjsing {
115dab3f910Sjsing BIGNUM *bn = NULL;
1164058704fSjsing char *prime = NULL;
117dab3f910Sjsing BIO *bio_out;
1184058704fSjsing char *s;
119d1ddd169Stb int is_prime, ret = 1;
120dab3f910Sjsing
121e370f0eeSdoug if (pledge("stdio rpath", NULL) == -1) {
1229bc487adSdoug perror("pledge");
123e370f0eeSdoug exit(1);
124e370f0eeSdoug }
1259bc487adSdoug
126e7718adaStb memset(&cfg, 0, sizeof(cfg));
1274058704fSjsing
1284058704fSjsing /* Default iterations for Miller-Rabin probabilistic primality test. */
129e7718adaStb cfg.checks = 20;
1304058704fSjsing
131beba0da1Sjsing if (options_parse(argc, argv, prime_options, &prime, NULL) != 0) {
1324058704fSjsing prime_usage();
1334058704fSjsing return (1);
134dab3f910Sjsing }
135dab3f910Sjsing
136e7718adaStb if (prime == NULL && cfg.generate == 0) {
1374058704fSjsing BIO_printf(bio_err, "No prime specified.\n");
1384058704fSjsing prime_usage();
1394058704fSjsing return (1);
140dab3f910Sjsing }
1414058704fSjsing
14227f75401Slteo if ((bio_out = BIO_new(BIO_s_file())) == NULL) {
14327f75401Slteo ERR_print_errors(bio_err);
14427f75401Slteo return (1);
145dab3f910Sjsing }
14627f75401Slteo BIO_set_fp(bio_out, stdout, BIO_NOCLOSE);
147dab3f910Sjsing
148e7718adaStb if (cfg.generate != 0) {
149e7718adaStb if (cfg.bits == 0) {
1504058704fSjsing BIO_printf(bio_err, "Specify the number of bits.\n");
15127f75401Slteo goto end;
152dab3f910Sjsing }
15327f75401Slteo bn = BN_new();
15427f75401Slteo if (!bn) {
15527f75401Slteo BIO_printf(bio_err, "Out of memory.\n");
15627f75401Slteo goto end;
15727f75401Slteo }
158e7718adaStb if (!BN_generate_prime_ex(bn, cfg.bits,
159e7718adaStb cfg.safe, NULL, NULL, NULL)) {
16027f75401Slteo BIO_printf(bio_err, "Prime generation error.\n");
16127f75401Slteo goto end;
16227f75401Slteo }
163e7718adaStb s = cfg.hex ? BN_bn2hex(bn) : BN_bn2dec(bn);
16427f75401Slteo if (s == NULL) {
16527f75401Slteo BIO_printf(bio_err, "Out of memory.\n");
16627f75401Slteo goto end;
16727f75401Slteo }
168dab3f910Sjsing BIO_printf(bio_out, "%s\n", s);
169dab3f910Sjsing free(s);
170dab3f910Sjsing } else {
171e7718adaStb if (cfg.hex) {
17227f75401Slteo if (!BN_hex2bn(&bn, prime)) {
17327f75401Slteo BIO_printf(bio_err, "%s is an invalid hex "
17427f75401Slteo "value.\n", prime);
17527f75401Slteo goto end;
17627f75401Slteo }
17727f75401Slteo } else {
17827f75401Slteo if (!BN_dec2bn(&bn, prime)) {
17927f75401Slteo BIO_printf(bio_err, "%s is an invalid decimal "
18027f75401Slteo "value.\n", prime);
18127f75401Slteo goto end;
18227f75401Slteo }
18327f75401Slteo }
184dab3f910Sjsing
185e7718adaStb is_prime = BN_is_prime_ex(bn, cfg.checks, NULL, NULL);
186d1ddd169Stb if (is_prime < 0) {
187d1ddd169Stb BIO_printf(bio_err, "BN_is_prime_ex failed.\n");
188d1ddd169Stb goto end;
189d1ddd169Stb }
190e97f7a80Slteo BIO_printf(bio_out, "%s is %sprime\n", prime,
191d1ddd169Stb is_prime == 1 ? "" : "not ");
192dab3f910Sjsing }
193dab3f910Sjsing
19427f75401Slteo ret = 0;
19527f75401Slteo
19627f75401Slteo end:
197dab3f910Sjsing BN_free(bn);
198dab3f910Sjsing BIO_free_all(bio_out);
199dab3f910Sjsing
20027f75401Slteo return (ret);
201dab3f910Sjsing }
202