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