xref: /openbsd-src/usr.bin/openssl/gendsa.c (revision e7718adaf9bdf5a32db0f291795197a85ccbb6ed)
1*e7718adaStb /* $OpenBSD: gendsa.c,v 1.17 2023/03/06 14:32:06 tb Exp $ */
2dab3f910Sjsing /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3dab3f910Sjsing  * All rights reserved.
4dab3f910Sjsing  *
5dab3f910Sjsing  * This package is an SSL implementation written
6dab3f910Sjsing  * by Eric Young (eay@cryptsoft.com).
7dab3f910Sjsing  * The implementation was written so as to conform with Netscapes SSL.
8dab3f910Sjsing  *
9dab3f910Sjsing  * This library is free for commercial and non-commercial use as long as
10dab3f910Sjsing  * the following conditions are aheared to.  The following conditions
11dab3f910Sjsing  * apply to all code found in this distribution, be it the RC4, RSA,
12dab3f910Sjsing  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13dab3f910Sjsing  * included with this distribution is covered by the same copyright terms
14dab3f910Sjsing  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15dab3f910Sjsing  *
16dab3f910Sjsing  * Copyright remains Eric Young's, and as such any Copyright notices in
17dab3f910Sjsing  * the code are not to be removed.
18dab3f910Sjsing  * If this package is used in a product, Eric Young should be given attribution
19dab3f910Sjsing  * as the author of the parts of the library used.
20dab3f910Sjsing  * This can be in the form of a textual message at program startup or
21dab3f910Sjsing  * in documentation (online or textual) provided with the package.
22dab3f910Sjsing  *
23dab3f910Sjsing  * Redistribution and use in source and binary forms, with or without
24dab3f910Sjsing  * modification, are permitted provided that the following conditions
25dab3f910Sjsing  * are met:
26dab3f910Sjsing  * 1. Redistributions of source code must retain the copyright
27dab3f910Sjsing  *    notice, this list of conditions and the following disclaimer.
28dab3f910Sjsing  * 2. Redistributions in binary form must reproduce the above copyright
29dab3f910Sjsing  *    notice, this list of conditions and the following disclaimer in the
30dab3f910Sjsing  *    documentation and/or other materials provided with the distribution.
31dab3f910Sjsing  * 3. All advertising materials mentioning features or use of this software
32dab3f910Sjsing  *    must display the following acknowledgement:
33dab3f910Sjsing  *    "This product includes cryptographic software written by
34dab3f910Sjsing  *     Eric Young (eay@cryptsoft.com)"
35dab3f910Sjsing  *    The word 'cryptographic' can be left out if the rouines from the library
36dab3f910Sjsing  *    being used are not cryptographic related :-).
37dab3f910Sjsing  * 4. If you include any Windows specific code (or a derivative thereof) from
38dab3f910Sjsing  *    the apps directory (application code) you must include an acknowledgement:
39dab3f910Sjsing  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40dab3f910Sjsing  *
41dab3f910Sjsing  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42dab3f910Sjsing  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43dab3f910Sjsing  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44dab3f910Sjsing  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45dab3f910Sjsing  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46dab3f910Sjsing  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47dab3f910Sjsing  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48dab3f910Sjsing  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49dab3f910Sjsing  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50dab3f910Sjsing  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51dab3f910Sjsing  * SUCH DAMAGE.
52dab3f910Sjsing  *
53dab3f910Sjsing  * The licence and distribution terms for any publically available version or
54dab3f910Sjsing  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55dab3f910Sjsing  * copied and put under another distribution licence
56dab3f910Sjsing  * [including the GNU Public Licence.]
57dab3f910Sjsing  */
58dab3f910Sjsing 
59dab3f910Sjsing #include <openssl/opensslconf.h>	/* for OPENSSL_NO_DSA */
60dab3f910Sjsing 
61dab3f910Sjsing 
62dab3f910Sjsing #include <sys/types.h>
63dab3f910Sjsing #include <sys/stat.h>
64dab3f910Sjsing 
65dab3f910Sjsing #include <stdio.h>
66dab3f910Sjsing #include <string.h>
67dab3f910Sjsing 
68dab3f910Sjsing #include "apps.h"
69dab3f910Sjsing 
70dab3f910Sjsing #include <openssl/bio.h>
71dab3f910Sjsing #include <openssl/bn.h>
72dab3f910Sjsing #include <openssl/dsa.h>
73dab3f910Sjsing #include <openssl/err.h>
74dab3f910Sjsing #include <openssl/pem.h>
75dab3f910Sjsing #include <openssl/x509.h>
76dab3f910Sjsing 
77eb6e8935Sinoguchi static struct {
78eb6e8935Sinoguchi 	const EVP_CIPHER *enc;
79eb6e8935Sinoguchi 	char *outfile;
80eb6e8935Sinoguchi 	char *passargout;
81*e7718adaStb } cfg;
82eb6e8935Sinoguchi 
get_cipher_by_name(char * name)834b6ea4e7Sinoguchi static const EVP_CIPHER *get_cipher_by_name(char *name)
844b6ea4e7Sinoguchi {
854b6ea4e7Sinoguchi 	if (name == NULL || strcmp(name, "") == 0)
864b6ea4e7Sinoguchi 		return (NULL);
874b6ea4e7Sinoguchi #ifndef OPENSSL_NO_AES
884b6ea4e7Sinoguchi 	else if (strcmp(name, "aes128") == 0)
894b6ea4e7Sinoguchi 		return EVP_aes_128_cbc();
904b6ea4e7Sinoguchi 	else if (strcmp(name, "aes192") == 0)
914b6ea4e7Sinoguchi 		return EVP_aes_192_cbc();
924b6ea4e7Sinoguchi 	else if (strcmp(name, "aes256") == 0)
934b6ea4e7Sinoguchi 		return EVP_aes_256_cbc();
944b6ea4e7Sinoguchi #endif
954b6ea4e7Sinoguchi #ifndef OPENSSL_NO_CAMELLIA
964b6ea4e7Sinoguchi 	else if (strcmp(name, "camellia128") == 0)
974b6ea4e7Sinoguchi 		return EVP_camellia_128_cbc();
984b6ea4e7Sinoguchi 	else if (strcmp(name, "camellia192") == 0)
994b6ea4e7Sinoguchi 		return EVP_camellia_192_cbc();
1004b6ea4e7Sinoguchi 	else if (strcmp(name, "camellia256") == 0)
1014b6ea4e7Sinoguchi 		return EVP_camellia_256_cbc();
1024b6ea4e7Sinoguchi #endif
1034b6ea4e7Sinoguchi #ifndef OPENSSL_NO_DES
1044b6ea4e7Sinoguchi 	else if (strcmp(name, "des") == 0)
1054b6ea4e7Sinoguchi 		return EVP_des_cbc();
1064b6ea4e7Sinoguchi 	else if (strcmp(name, "des3") == 0)
1074b6ea4e7Sinoguchi 		return EVP_des_ede3_cbc();
1084b6ea4e7Sinoguchi #endif
1094b6ea4e7Sinoguchi #ifndef OPENSSL_NO_IDEA
1104b6ea4e7Sinoguchi 	else if (strcmp(name, "idea") == 0)
1114b6ea4e7Sinoguchi 		return EVP_idea_cbc();
1124b6ea4e7Sinoguchi #endif
1134b6ea4e7Sinoguchi 	else
1144b6ea4e7Sinoguchi 		return (NULL);
1154b6ea4e7Sinoguchi }
1164b6ea4e7Sinoguchi 
1174b6ea4e7Sinoguchi static int
set_enc(int argc,char ** argv,int * argsused)1184b6ea4e7Sinoguchi set_enc(int argc, char **argv, int *argsused)
1194b6ea4e7Sinoguchi {
1204b6ea4e7Sinoguchi 	char *name = argv[0];
1214b6ea4e7Sinoguchi 
1224b6ea4e7Sinoguchi 	if (*name++ != '-')
1234b6ea4e7Sinoguchi 		return (1);
1244b6ea4e7Sinoguchi 
125*e7718adaStb 	if ((cfg.enc = get_cipher_by_name(name)) == NULL)
1264b6ea4e7Sinoguchi 		return (1);
1274b6ea4e7Sinoguchi 
1284b6ea4e7Sinoguchi 	*argsused = 1;
1294b6ea4e7Sinoguchi 	return (0);
1304b6ea4e7Sinoguchi }
1314b6ea4e7Sinoguchi 
132ea149709Sguenther static const struct option gendsa_options[] = {
133eb6e8935Sinoguchi #ifndef OPENSSL_NO_AES
134eb6e8935Sinoguchi 	{
135eb6e8935Sinoguchi 		.name = "aes128",
13607a5d217Sinoguchi 		.desc = "Encrypt PEM output with CBC AES",
137eb6e8935Sinoguchi 		.type = OPTION_ARGV_FUNC,
138eb6e8935Sinoguchi 		.opt.argvfunc = set_enc,
139eb6e8935Sinoguchi 	},
140eb6e8935Sinoguchi 	{
141eb6e8935Sinoguchi 		.name = "aes192",
14207a5d217Sinoguchi 		.desc = "Encrypt PEM output with CBC AES",
143eb6e8935Sinoguchi 		.type = OPTION_ARGV_FUNC,
144eb6e8935Sinoguchi 		.opt.argvfunc = set_enc,
145eb6e8935Sinoguchi 	},
146eb6e8935Sinoguchi 	{
147eb6e8935Sinoguchi 		.name = "aes256",
14807a5d217Sinoguchi 		.desc = "Encrypt PEM output with CBC AES",
149eb6e8935Sinoguchi 		.type = OPTION_ARGV_FUNC,
150eb6e8935Sinoguchi 		.opt.argvfunc = set_enc,
151eb6e8935Sinoguchi 	},
152eb6e8935Sinoguchi #endif
153eb6e8935Sinoguchi #ifndef OPENSSL_NO_CAMELLIA
154eb6e8935Sinoguchi 	{
155eb6e8935Sinoguchi 		.name = "camellia128",
15607a5d217Sinoguchi 		.desc = "Encrypt PEM output with CBC Camellia",
157eb6e8935Sinoguchi 		.type = OPTION_ARGV_FUNC,
158eb6e8935Sinoguchi 		.opt.argvfunc = set_enc,
159eb6e8935Sinoguchi 	},
160eb6e8935Sinoguchi 	{
161eb6e8935Sinoguchi 		.name = "camellia192",
16207a5d217Sinoguchi 		.desc = "Encrypt PEM output with CBC Camellia",
163eb6e8935Sinoguchi 		.type = OPTION_ARGV_FUNC,
164eb6e8935Sinoguchi 		.opt.argvfunc = set_enc,
165eb6e8935Sinoguchi 	},
166eb6e8935Sinoguchi 	{
167eb6e8935Sinoguchi 		.name = "camellia256",
16807a5d217Sinoguchi 		.desc = "Encrypt PEM output with CBC Camellia",
169eb6e8935Sinoguchi 		.type = OPTION_ARGV_FUNC,
170eb6e8935Sinoguchi 		.opt.argvfunc = set_enc,
171eb6e8935Sinoguchi 	},
172eb6e8935Sinoguchi #endif
173eb6e8935Sinoguchi #ifndef OPENSSL_NO_DES
174eb6e8935Sinoguchi 	{
175eb6e8935Sinoguchi 		.name = "des",
17607a5d217Sinoguchi 		.desc = "Encrypt the generated key with DES in CBC mode",
177eb6e8935Sinoguchi 		.type = OPTION_ARGV_FUNC,
178eb6e8935Sinoguchi 		.opt.argvfunc = set_enc,
179eb6e8935Sinoguchi 	},
180eb6e8935Sinoguchi 	{
181eb6e8935Sinoguchi 		.name = "des3",
18207a5d217Sinoguchi 		.desc = "Encrypt the generated key with DES in EDE CBC mode (168 bit key)",
183eb6e8935Sinoguchi 		.type = OPTION_ARGV_FUNC,
184eb6e8935Sinoguchi 		.opt.argvfunc = set_enc,
185eb6e8935Sinoguchi 	},
186eb6e8935Sinoguchi #endif
187eb6e8935Sinoguchi #ifndef OPENSSL_NO_IDEA
188eb6e8935Sinoguchi 	{
189eb6e8935Sinoguchi 		.name = "idea",
19007a5d217Sinoguchi 		.desc = "Encrypt the generated key with IDEA in CBC mode",
191eb6e8935Sinoguchi 		.type = OPTION_ARGV_FUNC,
192eb6e8935Sinoguchi 		.opt.argvfunc = set_enc,
193eb6e8935Sinoguchi 	},
194eb6e8935Sinoguchi #endif
195eb6e8935Sinoguchi 	{
196eb6e8935Sinoguchi 		.name = "out",
197eb6e8935Sinoguchi 		.argname = "file",
198eb6e8935Sinoguchi 		.desc = "Output the key to 'file'",
199eb6e8935Sinoguchi 		.type = OPTION_ARG,
200*e7718adaStb 		.opt.arg = &cfg.outfile,
201eb6e8935Sinoguchi 	},
202eb6e8935Sinoguchi 	{
203eb6e8935Sinoguchi 		.name = "passout",
204eb6e8935Sinoguchi 		.argname = "src",
205eb6e8935Sinoguchi 		.desc = "Output file passphrase source",
206eb6e8935Sinoguchi 		.type = OPTION_ARG,
207*e7718adaStb 		.opt.arg = &cfg.passargout,
208eb6e8935Sinoguchi 	},
209eb6e8935Sinoguchi 	{ NULL },
210eb6e8935Sinoguchi };
211eb6e8935Sinoguchi 
212eb6e8935Sinoguchi static void
gendsa_usage(void)213eb6e8935Sinoguchi gendsa_usage(void)
214eb6e8935Sinoguchi {
215eb6e8935Sinoguchi 	fprintf(stderr, "usage: gendsa [-aes128 | -aes192 | -aes256 |\n");
216eb6e8935Sinoguchi 	fprintf(stderr, "    -camellia128 | -camellia192 | -camellia256 |\n");
217eb6e8935Sinoguchi 	fprintf(stderr, "    -des | -des3 | -idea] [-out file] [-passout src]");
218eb6e8935Sinoguchi 	fprintf(stderr, " paramfile\n\n");
219eb6e8935Sinoguchi 	options_usage(gendsa_options);
220eb6e8935Sinoguchi 	fprintf(stderr, "\n");
221eb6e8935Sinoguchi }
222eb6e8935Sinoguchi 
223dab3f910Sjsing int
gendsa_main(int argc,char ** argv)224dab3f910Sjsing gendsa_main(int argc, char **argv)
225dab3f910Sjsing {
226dab3f910Sjsing 	DSA *dsa = NULL;
227dab3f910Sjsing 	int ret = 1;
228dab3f910Sjsing 	char *dsaparams = NULL;
229eb6e8935Sinoguchi 	char *passout = NULL;
230dab3f910Sjsing 	BIO *out = NULL, *in = NULL;
231dab3f910Sjsing 
23251811eadSderaadt 	if (pledge("stdio cpath wpath rpath tty", NULL) == -1) {
2339bc487adSdoug 		perror("pledge");
234e370f0eeSdoug 		exit(1);
235e370f0eeSdoug 	}
2369bc487adSdoug 
237*e7718adaStb 	memset(&cfg, 0, sizeof(cfg));
238eb6e8935Sinoguchi 
239eb6e8935Sinoguchi 	if (options_parse(argc, argv, gendsa_options, &dsaparams, NULL) != 0) {
240eb6e8935Sinoguchi 		gendsa_usage();
241eb6e8935Sinoguchi 		goto end;
242dab3f910Sjsing 	}
243dab3f910Sjsing 
244dab3f910Sjsing 	if (dsaparams == NULL) {
245eb6e8935Sinoguchi 		gendsa_usage();
246dab3f910Sjsing 		goto end;
247dab3f910Sjsing 	}
248*e7718adaStb 	if (!app_passwd(bio_err, NULL, cfg.passargout, NULL,
249eb6e8935Sinoguchi 	    &passout)) {
250dab3f910Sjsing 		BIO_printf(bio_err, "Error getting password\n");
251dab3f910Sjsing 		goto end;
252dab3f910Sjsing 	}
253dab3f910Sjsing 	in = BIO_new(BIO_s_file());
254dab3f910Sjsing 	if (!(BIO_read_filename(in, dsaparams))) {
255dab3f910Sjsing 		perror(dsaparams);
256dab3f910Sjsing 		goto end;
257dab3f910Sjsing 	}
258dab3f910Sjsing 	if ((dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL)) == NULL) {
259dab3f910Sjsing 		BIO_printf(bio_err, "unable to load DSA parameter file\n");
260dab3f910Sjsing 		goto end;
261dab3f910Sjsing 	}
262dab3f910Sjsing 	BIO_free(in);
263dab3f910Sjsing 	in = NULL;
264dab3f910Sjsing 
265dab3f910Sjsing 	out = BIO_new(BIO_s_file());
266dab3f910Sjsing 	if (out == NULL)
267dab3f910Sjsing 		goto end;
268dab3f910Sjsing 
269*e7718adaStb 	if (cfg.outfile == NULL) {
270dab3f910Sjsing 		BIO_set_fp(out, stdout, BIO_NOCLOSE);
271dab3f910Sjsing 	} else {
272*e7718adaStb 		if (BIO_write_filename(out, cfg.outfile) <= 0) {
273*e7718adaStb 			perror(cfg.outfile);
274dab3f910Sjsing 			goto end;
275dab3f910Sjsing 		}
276dab3f910Sjsing 	}
277dab3f910Sjsing 
278dab3f910Sjsing 	BIO_printf(bio_err, "Generating DSA key, %d bits\n",
279f9413cc6Stb 	    BN_num_bits(DSA_get0_p(dsa)));
280dab3f910Sjsing 	if (!DSA_generate_key(dsa))
281dab3f910Sjsing 		goto end;
282dab3f910Sjsing 
283*e7718adaStb 	if (!PEM_write_bio_DSAPrivateKey(out, dsa, cfg.enc, NULL, 0,
284eb6e8935Sinoguchi 	    NULL, passout))
285dab3f910Sjsing 		goto end;
286dab3f910Sjsing 	ret = 0;
287dab3f910Sjsing  end:
288dab3f910Sjsing 	if (ret != 0)
289dab3f910Sjsing 		ERR_print_errors(bio_err);
290dab3f910Sjsing 	BIO_free(in);
291dab3f910Sjsing 	BIO_free_all(out);
292dab3f910Sjsing 	DSA_free(dsa);
293dab3f910Sjsing 	free(passout);
294dab3f910Sjsing 
295dab3f910Sjsing 	return (ret);
296dab3f910Sjsing }
297