genrsa.c revision 160814
155714Skris/* apps/genrsa.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
855714Skris *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1555714Skris *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
2255714Skris *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
3755714Skris * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
4055714Skris *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
5255714Skris *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
59160814Ssimon#include <openssl/opensslconf.h>
60160814Ssimon/* Until the key-gen callbacks are modified to use newer prototypes, we allow
61160814Ssimon * deprecated functions for openssl-internal code */
62160814Ssimon#ifdef OPENSSL_NO_DEPRECATED
63160814Ssimon#undef OPENSSL_NO_DEPRECATED
64160814Ssimon#endif
65160814Ssimon
66109998Smarkm#ifndef OPENSSL_NO_RSA
6755714Skris#include <stdio.h>
6855714Skris#include <string.h>
6955714Skris#include <sys/types.h>
7055714Skris#include <sys/stat.h>
7155714Skris#include "apps.h"
7255714Skris#include <openssl/bio.h>
7355714Skris#include <openssl/err.h>
7455714Skris#include <openssl/bn.h>
7555714Skris#include <openssl/rsa.h>
7655714Skris#include <openssl/evp.h>
7755714Skris#include <openssl/x509.h>
7855714Skris#include <openssl/pem.h>
79109998Smarkm#include <openssl/rand.h>
8055714Skris
8155714Skris#define DEFBITS	512
8255714Skris#undef PROG
8355714Skris#define PROG genrsa_main
8455714Skris
85160814Ssimonstatic int MS_CALLBACK genrsa_cb(int p, int n, BN_GENCB *cb);
8659191Skris
8759191Skrisint MAIN(int, char **);
8859191Skris
8955714Skrisint MAIN(int argc, char **argv)
9055714Skris	{
91160814Ssimon	BN_GENCB cb;
92111147Snectar#ifndef OPENSSL_NO_ENGINE
93109998Smarkm	ENGINE *e = NULL;
94111147Snectar#endif
9555714Skris	int ret=1;
9655714Skris	int i,num=DEFBITS;
9759191Skris	long l;
98109998Smarkm	const EVP_CIPHER *enc=NULL;
9955714Skris	unsigned long f4=RSA_F4;
10055714Skris	char *outfile=NULL;
10159191Skris	char *passargout = NULL, *passout = NULL;
102111147Snectar#ifndef OPENSSL_NO_ENGINE
103109998Smarkm	char *engine=NULL;
104111147Snectar#endif
10559191Skris	char *inrand=NULL;
10655714Skris	BIO *out=NULL;
107160814Ssimon	BIGNUM *bn = BN_new();
108160814Ssimon	RSA *rsa = RSA_new();
10955714Skris
110160814Ssimon	if(!bn || !rsa) goto err;
111160814Ssimon
11255714Skris	apps_startup();
113160814Ssimon	BN_GENCB_set(&cb, genrsa_cb, bio_err);
11455714Skris
11555714Skris	if (bio_err == NULL)
11655714Skris		if ((bio_err=BIO_new(BIO_s_file())) != NULL)
11755714Skris			BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
118109998Smarkm
119109998Smarkm	if (!load_config(bio_err, NULL))
120109998Smarkm		goto err;
12155714Skris	if ((out=BIO_new(BIO_s_file())) == NULL)
12255714Skris		{
12359191Skris		BIO_printf(bio_err,"unable to create BIO for output\n");
12455714Skris		goto err;
12555714Skris		}
12655714Skris
12755714Skris	argv++;
12855714Skris	argc--;
12955714Skris	for (;;)
13055714Skris		{
13155714Skris		if (argc <= 0) break;
13255714Skris		if (strcmp(*argv,"-out") == 0)
13355714Skris			{
13455714Skris			if (--argc < 1) goto bad;
13555714Skris			outfile= *(++argv);
13655714Skris			}
13755714Skris		else if (strcmp(*argv,"-3") == 0)
13855714Skris			f4=3;
13968651Skris		else if (strcmp(*argv,"-F4") == 0 || strcmp(*argv,"-f4") == 0)
14055714Skris			f4=RSA_F4;
141111147Snectar#ifndef OPENSSL_NO_ENGINE
142109998Smarkm		else if (strcmp(*argv,"-engine") == 0)
143109998Smarkm			{
144109998Smarkm			if (--argc < 1) goto bad;
145109998Smarkm			engine= *(++argv);
146109998Smarkm			}
147111147Snectar#endif
14855714Skris		else if (strcmp(*argv,"-rand") == 0)
14955714Skris			{
15055714Skris			if (--argc < 1) goto bad;
15155714Skris			inrand= *(++argv);
15255714Skris			}
153109998Smarkm#ifndef OPENSSL_NO_DES
15455714Skris		else if (strcmp(*argv,"-des") == 0)
15555714Skris			enc=EVP_des_cbc();
15655714Skris		else if (strcmp(*argv,"-des3") == 0)
15755714Skris			enc=EVP_des_ede3_cbc();
15855714Skris#endif
159109998Smarkm#ifndef OPENSSL_NO_IDEA
16055714Skris		else if (strcmp(*argv,"-idea") == 0)
16155714Skris			enc=EVP_idea_cbc();
16255714Skris#endif
163109998Smarkm#ifndef OPENSSL_NO_AES
164109998Smarkm		else if (strcmp(*argv,"-aes128") == 0)
165109998Smarkm			enc=EVP_aes_128_cbc();
166109998Smarkm		else if (strcmp(*argv,"-aes192") == 0)
167109998Smarkm			enc=EVP_aes_192_cbc();
168109998Smarkm		else if (strcmp(*argv,"-aes256") == 0)
169109998Smarkm			enc=EVP_aes_256_cbc();
170109998Smarkm#endif
17159191Skris		else if (strcmp(*argv,"-passout") == 0)
17259191Skris			{
17359191Skris			if (--argc < 1) goto bad;
17459191Skris			passargout= *(++argv);
17559191Skris			}
17655714Skris		else
17755714Skris			break;
17855714Skris		argv++;
17955714Skris		argc--;
18055714Skris		}
18155714Skris	if ((argc >= 1) && ((sscanf(*argv,"%d",&num) == 0) || (num < 0)))
18255714Skris		{
18355714Skrisbad:
18455714Skris		BIO_printf(bio_err,"usage: genrsa [args] [numbits]\n");
18559191Skris		BIO_printf(bio_err," -des            encrypt the generated key with DES in cbc mode\n");
18659191Skris		BIO_printf(bio_err," -des3           encrypt the generated key with DES in ede cbc mode (168 bit key)\n");
187109998Smarkm#ifndef OPENSSL_NO_IDEA
18859191Skris		BIO_printf(bio_err," -idea           encrypt the generated key with IDEA in cbc mode\n");
18955714Skris#endif
190109998Smarkm#ifndef OPENSSL_NO_AES
191109998Smarkm		BIO_printf(bio_err," -aes128, -aes192, -aes256\n");
192109998Smarkm		BIO_printf(bio_err,"                 encrypt PEM output with cbc aes\n");
193109998Smarkm#endif
19459191Skris		BIO_printf(bio_err," -out file       output the key to 'file\n");
19559191Skris		BIO_printf(bio_err," -passout arg    output file pass phrase source\n");
19659191Skris		BIO_printf(bio_err," -f4             use F4 (0x10001) for the E value\n");
19759191Skris		BIO_printf(bio_err," -3              use 3 for the E value\n");
198111147Snectar#ifndef OPENSSL_NO_ENGINE
199109998Smarkm		BIO_printf(bio_err," -engine e       use engine e, possibly a hardware device.\n");
200111147Snectar#endif
20159191Skris		BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
20259191Skris		BIO_printf(bio_err,"                 load the file (or the files in the directory) into\n");
20359191Skris		BIO_printf(bio_err,"                 the random number generator\n");
20455714Skris		goto err;
20555714Skris		}
20655714Skris
20755714Skris	ERR_load_crypto_strings();
20859191Skris
20959191Skris	if(!app_passwd(bio_err, NULL, passargout, NULL, &passout)) {
21059191Skris		BIO_printf(bio_err, "Error getting password\n");
21159191Skris		goto err;
21259191Skris	}
21359191Skris
214111147Snectar#ifndef OPENSSL_NO_ENGINE
215109998Smarkm        e = setup_engine(bio_err, engine, 0);
216111147Snectar#endif
217109998Smarkm
21855714Skris	if (outfile == NULL)
21968651Skris		{
22055714Skris		BIO_set_fp(out,stdout,BIO_NOCLOSE);
221109998Smarkm#ifdef OPENSSL_SYS_VMS
22268651Skris		{
22368651Skris		BIO *tmpbio = BIO_new(BIO_f_linebuffer());
22468651Skris		out = BIO_push(tmpbio, out);
22568651Skris		}
22668651Skris#endif
22768651Skris		}
22855714Skris	else
22955714Skris		{
23055714Skris		if (BIO_write_filename(out,outfile) <= 0)
23155714Skris			{
23255714Skris			perror(outfile);
23355714Skris			goto err;
23455714Skris			}
23555714Skris		}
23655714Skris
237109998Smarkm	if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL
238109998Smarkm		&& !RAND_status())
23955714Skris		{
24059191Skris		BIO_printf(bio_err,"warning, not much extra random data, consider using the -rand option\n");
24155714Skris		}
24259191Skris	if (inrand != NULL)
24359191Skris		BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
24459191Skris			app_RAND_load_files(inrand));
24555714Skris
24655714Skris	BIO_printf(bio_err,"Generating RSA private key, %d bit long modulus\n",
24755714Skris		num);
248160814Ssimon
249160814Ssimon	if(!BN_set_word(bn, f4) || !RSA_generate_key_ex(rsa, num, bn, &cb))
250160814Ssimon		goto err;
25155714Skris
25259191Skris	app_RAND_write_file(NULL, bio_err);
25355714Skris
25459191Skris	/* We need to do the following for when the base number size is <
25555714Skris	 * long, esp windows 3.1 :-(. */
25655714Skris	l=0L;
25755714Skris	for (i=0; i<rsa->e->top; i++)
25855714Skris		{
25955714Skris#ifndef SIXTY_FOUR_BIT
26055714Skris		l<<=BN_BITS4;
26155714Skris		l<<=BN_BITS4;
26255714Skris#endif
26355714Skris		l+=rsa->e->d[i];
26455714Skris		}
26555714Skris	BIO_printf(bio_err,"e is %ld (0x%lX)\n",l,l);
266109998Smarkm	{
267109998Smarkm	PW_CB_DATA cb_data;
268109998Smarkm	cb_data.password = passout;
269109998Smarkm	cb_data.prompt_info = outfile;
270109998Smarkm	if (!PEM_write_bio_RSAPrivateKey(out,rsa,enc,NULL,0,
271109998Smarkm		(pem_password_cb *)password_callback,&cb_data))
27255714Skris		goto err;
273109998Smarkm	}
27455714Skris
27555714Skris	ret=0;
27655714Skriserr:
277160814Ssimon	if (bn) BN_free(bn);
278160814Ssimon	if (rsa) RSA_free(rsa);
279160814Ssimon	if (out) BIO_free_all(out);
28068651Skris	if(passout) OPENSSL_free(passout);
28155714Skris	if (ret != 0)
28255714Skris		ERR_print_errors(bio_err);
283109998Smarkm	apps_shutdown();
284109998Smarkm	OPENSSL_EXIT(ret);
28555714Skris	}
28655714Skris
287160814Ssimonstatic int MS_CALLBACK genrsa_cb(int p, int n, BN_GENCB *cb)
28855714Skris	{
28955714Skris	char c='*';
29055714Skris
29155714Skris	if (p == 0) c='.';
29255714Skris	if (p == 1) c='+';
29355714Skris	if (p == 2) c='*';
29455714Skris	if (p == 3) c='\n';
295160814Ssimon	BIO_write(cb->arg,&c,1);
296160814Ssimon	(void)BIO_flush(cb->arg);
29755714Skris#ifdef LINT
29855714Skris	p=n;
29955714Skris#endif
300160814Ssimon	return 1;
30155714Skris	}
302109998Smarkm#else /* !OPENSSL_NO_RSA */
30355714Skris
30459191Skris# if PEDANTIC
30559191Skrisstatic void *dummy=&dummy;
30659191Skris# endif
30755714Skris
30855714Skris#endif
309