xref: /openbsd-src/usr.bin/openssl/prime.c (revision 440d141494672caa7e8d231fced157bd3b6b7448)
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