rsa.c revision 162912
161861Sru/* apps/rsa.c */
261861Sru/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
361861Sru * All rights reserved.
461861Sru *
561861Sru * This package is an SSL implementation written
661861Sru * by Eric Young (eay@cryptsoft.com).
761861Sru * The implementation was written so as to conform with Netscapes SSL.
861861Sru *
961861Sru * This library is free for commercial and non-commercial use as long as
1061861Sru * the following conditions are aheared to.  The following conditions
1161861Sru * apply to all code found in this distribution, be it the RC4, RSA,
1261861Sru * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1361861Sru * included with this distribution is covered by the same copyright terms
1461861Sru * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1561861Sru *
1661861Sru * Copyright remains Eric Young's, and as such any Copyright notices in
1761861Sru * the code are not to be removed.
1861861Sru * If this package is used in a product, Eric Young should be given attribution
1961861Sru * as the author of the parts of the library used.
2061861Sru * This can be in the form of a textual message at program startup or
2161861Sru * in documentation (online or textual) provided with the package.
2261861Sru *
2361861Sru * Redistribution and use in source and binary forms, with or without
2461861Sru * modification, are permitted provided that the following conditions
2561861Sru * are met:
2661861Sru * 1. Redistributions of source code must retain the copyright
2761861Sru *    notice, this list of conditions and the following disclaimer.
2861861Sru * 2. Redistributions in binary form must reproduce the above copyright
2961861Sru *    notice, this list of conditions and the following disclaimer in the
3061861Sru *    documentation and/or other materials provided with the distribution.
3161861Sru * 3. All advertising materials mentioning features or use of this software
3261861Sru *    must display the following acknowledgement:
3361861Sru *    "This product includes cryptographic software written by
3461861Sru *     Eric Young (eay@cryptsoft.com)"
3561861Sru *    The word 'cryptographic' can be left out if the rouines from the library
3661861Sru *    being used are not cryptographic related :-).
3761861Sru * 4. If you include any Windows specific code (or a derivative thereof) from
3861861Sru *    the apps directory (application code) you must include an acknowledgement:
3984195Sdillon *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
4084195Sdillon *
4184195Sdillon * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42162674Spiso * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43162674Spiso * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44162674Spiso * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45162674Spiso * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46162674Spiso * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47162674Spiso * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48162674Spiso * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49162674Spiso * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50162674Spiso * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51162674Spiso * SUCH DAMAGE.
52162674Spiso *
53162674Spiso * The licence and distribution terms for any publically available version or
54162674Spiso * derivative of this code cannot be changed.  i.e. this code cannot simply be
55162674Spiso * copied and put under another distribution licence
56162674Spiso * [including the GNU Public Licence.]
57162674Spiso */
58162674Spiso
59162674Spiso#include <openssl/opensslconf.h>
60162674Spiso#ifndef OPENSSL_NO_RSA
61162674Spiso#include <stdio.h>
62162674Spiso#include <stdlib.h>
63162674Spiso#include <string.h>
64162674Spiso#include <time.h>
65162674Spiso#include "apps.h"
66162674Spiso#include <openssl/bio.h>
67162674Spiso#include <openssl/err.h>
68162674Spiso#include <openssl/rsa.h>
69162674Spiso#include <openssl/evp.h>
70162674Spiso#include <openssl/x509.h>
71162674Spiso#include <openssl/pem.h>
72162674Spiso#include <openssl/bn.h>
73162674Spiso
74162674Spiso#undef PROG
75162674Spiso#define PROG	rsa_main
76162674Spiso
77162674Spiso/* -inform arg	- input format - default PEM (one of DER, NET or PEM)
78162674Spiso * -outform arg - output format - default PEM
79162674Spiso * -in arg	- input file - default stdin
80162674Spiso * -out arg	- output file - default stdout
81162674Spiso * -des		- encrypt output if PEM format with DES in cbc mode
82190841Spiso * -des3	- encrypt output if PEM format
83162674Spiso * -idea	- encrypt output if PEM format
84162674Spiso * -aes128	- encrypt output if PEM format
85162674Spiso * -aes192	- encrypt output if PEM format
86162674Spiso * -aes256	- encrypt output if PEM format
87162674Spiso * -camellia128 - encrypt output if PEM format
88162674Spiso * -camellia192 - encrypt output if PEM format
89162674Spiso * -camellia256 - encrypt output if PEM format
90162674Spiso * -text	- print a text version
91162674Spiso * -modulus	- print the RSA key modulus
92162674Spiso * -check	- verify key consistency
93162674Spiso * -pubin	- Expect a public key in input file.
94190841Spiso * -pubout	- Output a public key.
95162674Spiso */
96162674Spiso
97162674Spisoint MAIN(int, char **);
98162674Spiso
99162674Spisoint MAIN(int argc, char **argv)
100162674Spiso	{
101162674Spiso	ENGINE *e = NULL;
102162674Spiso	int ret=1;
103162674Spiso	RSA *rsa=NULL;
104162674Spiso	int i,badops=0, sgckey=0;
105162674Spiso	const EVP_CIPHER *enc=NULL;
106162674Spiso	BIO *out=NULL;
107162674Spiso	int informat,outformat,text=0,check=0,noout=0;
108162674Spiso	int pubin = 0, pubout = 0;
109162674Spiso	char *infile,*outfile,*prog;
110162674Spiso	char *passargin = NULL, *passargout = NULL;
111162674Spiso	char *passin = NULL, *passout = NULL;
112162674Spiso#ifndef OPENSSL_NO_ENGINE
113162674Spiso	char *engine=NULL;
114162674Spiso#endif
115162674Spiso	int modulus=0;
116162674Spiso
117162674Spiso	apps_startup();
118162674Spiso
119162674Spiso	if (bio_err == NULL)
120162674Spiso		if ((bio_err=BIO_new(BIO_s_file())) != NULL)
121162674Spiso			BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
122162674Spiso
123162674Spiso	if (!load_config(bio_err, NULL))
124162674Spiso		goto end;
125162674Spiso
126162674Spiso	infile=NULL;
127162674Spiso	outfile=NULL;
128162674Spiso	informat=FORMAT_PEM;
129162674Spiso	outformat=FORMAT_PEM;
130162674Spiso
131162674Spiso	prog=argv[0];
132162674Spiso	argc--;
133162674Spiso	argv++;
134162674Spiso	while (argc >= 1)
135162674Spiso		{
136162674Spiso		if 	(strcmp(*argv,"-inform") == 0)
137162674Spiso			{
138162674Spiso			if (--argc < 1) goto bad;
139162674Spiso			informat=str2fmt(*(++argv));
140162674Spiso			}
141162674Spiso		else if (strcmp(*argv,"-outform") == 0)
142162674Spiso			{
143162674Spiso			if (--argc < 1) goto bad;
144162674Spiso			outformat=str2fmt(*(++argv));
145162674Spiso			}
146162674Spiso		else if (strcmp(*argv,"-in") == 0)
147162674Spiso			{
148162674Spiso			if (--argc < 1) goto bad;
149162674Spiso			infile= *(++argv);
150162674Spiso			}
151162674Spiso		else if (strcmp(*argv,"-out") == 0)
152162674Spiso			{
153162674Spiso			if (--argc < 1) goto bad;
154162674Spiso			outfile= *(++argv);
155162674Spiso			}
156162674Spiso		else if (strcmp(*argv,"-passin") == 0)
157162674Spiso			{
158162674Spiso			if (--argc < 1) goto bad;
159162674Spiso			passargin= *(++argv);
160162674Spiso			}
161162674Spiso		else if (strcmp(*argv,"-passout") == 0)
162162674Spiso			{
163162674Spiso			if (--argc < 1) goto bad;
164162674Spiso			passargout= *(++argv);
165162674Spiso			}
166162674Spiso#ifndef OPENSSL_NO_ENGINE
167162674Spiso		else if (strcmp(*argv,"-engine") == 0)
168162674Spiso			{
169162674Spiso			if (--argc < 1) goto bad;
170162674Spiso			engine= *(++argv);
171162674Spiso			}
172162674Spiso#endif
173162674Spiso		else if (strcmp(*argv,"-sgckey") == 0)
174162674Spiso			sgckey=1;
175162674Spiso		else if (strcmp(*argv,"-pubin") == 0)
176162674Spiso			pubin=1;
177162674Spiso		else if (strcmp(*argv,"-pubout") == 0)
178162674Spiso			pubout=1;
179162674Spiso		else if (strcmp(*argv,"-noout") == 0)
180162674Spiso			noout=1;
181162674Spiso		else if (strcmp(*argv,"-text") == 0)
182162674Spiso			text=1;
183162674Spiso		else if (strcmp(*argv,"-modulus") == 0)
184162674Spiso			modulus=1;
185162674Spiso		else if (strcmp(*argv,"-check") == 0)
186162674Spiso			check=1;
187162674Spiso		else if ((enc=EVP_get_cipherbyname(&(argv[0][1]))) == NULL)
188162674Spiso			{
189162674Spiso			BIO_printf(bio_err,"unknown option %s\n",*argv);
190162674Spiso			badops=1;
191162674Spiso			break;
192162674Spiso			}
193162674Spiso		argc--;
194162674Spiso		argv++;
195162674Spiso		}
196162674Spiso
197162674Spiso	if (badops)
198162674Spiso		{
199162674Spisobad:
200162674Spiso		BIO_printf(bio_err,"%s [options] <infile >outfile\n",prog);
201162674Spiso		BIO_printf(bio_err,"where options are\n");
202162674Spiso		BIO_printf(bio_err," -inform arg     input format - one of DER NET PEM\n");
203162674Spiso		BIO_printf(bio_err," -outform arg    output format - one of DER NET PEM\n");
204162674Spiso		BIO_printf(bio_err," -in arg         input file\n");
20561861Sru		BIO_printf(bio_err," -sgckey         Use IIS SGC key format\n");
20661861Sru		BIO_printf(bio_err," -passin arg     input file pass phrase source\n");
20761861Sru		BIO_printf(bio_err," -out arg        output file\n");
20861861Sru		BIO_printf(bio_err," -passout arg    output file pass phrase source\n");
20961861Sru		BIO_printf(bio_err," -des            encrypt PEM output with cbc des\n");
21061861Sru		BIO_printf(bio_err," -des3           encrypt PEM output with ede cbc des using 168 bit key\n");
21161861Sru#ifndef OPENSSL_NO_IDEA
21264452Sru		BIO_printf(bio_err," -idea           encrypt PEM output with cbc idea\n");
21364452Sru#endif
21461861Sru#ifndef OPENSSL_NO_AES
21561861Sru		BIO_printf(bio_err," -aes128, -aes192, -aes256\n");
21661861Sru		BIO_printf(bio_err,"                 encrypt PEM output with cbc aes\n");
21761861Sru#endif
21861861Sru#ifndef OPENSSL_NO_CAMELLIA
21961861Sru		BIO_printf(bio_err," -camellia128, -camellia192, -camellia256\n");
22061861Sru		BIO_printf(bio_err,"                 encrypt PEM output with cbc camellia\n");
22161861Sru#endif
22261861Sru		BIO_printf(bio_err," -text           print the key in text\n");
22361861Sru		BIO_printf(bio_err," -noout          don't print key out\n");
22461861Sru		BIO_printf(bio_err," -modulus        print the RSA key modulus\n");
22561861Sru		BIO_printf(bio_err," -check          verify key consistency\n");
22661861Sru		BIO_printf(bio_err," -pubin          expect a public key in input file\n");
22761861Sru		BIO_printf(bio_err," -pubout         output a public key\n");
22861861Sru#ifndef OPENSSL_NO_ENGINE
22961861Sru		BIO_printf(bio_err," -engine e       use engine e, possibly a hardware device.\n");
23061861Sru#endif
23161861Sru		goto end;
23261861Sru		}
23361861Sru
23461861Sru	ERR_load_crypto_strings();
235127094Sdes
236127094Sdes#ifndef OPENSSL_NO_ENGINE
237127094Sdes        e = setup_engine(bio_err, engine, 0);
238127094Sdes#endif
239127094Sdes
240127094Sdes	if(!app_passwd(bio_err, passargin, passargout, &passin, &passout)) {
241127094Sdes		BIO_printf(bio_err, "Error getting passwords\n");
242127094Sdes		goto end;
24361861Sru	}
244127094Sdes
24561861Sru	if(check && pubin) {
24661861Sru		BIO_printf(bio_err, "Only private keys can be checked\n");
24761861Sru		goto end;
24861861Sru	}
24961861Sru
25061861Sru	out=BIO_new(BIO_s_file());
25161861Sru
25261861Sru	{
25361861Sru		EVP_PKEY	*pkey;
25461861Sru
25561861Sru		if (pubin)
25661861Sru			pkey = load_pubkey(bio_err, infile,
257127094Sdes				(informat == FORMAT_NETSCAPE && sgckey ?
258127094Sdes					FORMAT_IISSGC : informat), 1,
259127094Sdes				passin, e, "Public Key");
260127094Sdes		else
261127094Sdes			pkey = load_key(bio_err, infile,
262127094Sdes				(informat == FORMAT_NETSCAPE && sgckey ?
263127094Sdes					FORMAT_IISSGC : informat), 1,
264127094Sdes				passin, e, "Private Key");
265127094Sdes
266127094Sdes		if (pkey != NULL)
267127094Sdes		rsa = pkey == NULL ? NULL : EVP_PKEY_get1_RSA(pkey);
268127094Sdes		EVP_PKEY_free(pkey);
269127094Sdes	}
270127094Sdes
271127094Sdes	if (rsa == NULL)
27261861Sru		{
27361861Sru		ERR_print_errors(bio_err);
274127094Sdes		goto end;
275127094Sdes		}
276127094Sdes
277127094Sdes	if (outfile == NULL)
278127094Sdes		{
279127094Sdes		BIO_set_fp(out,stdout,BIO_NOCLOSE);
280127094Sdes#ifdef OPENSSL_SYS_VMS
281127094Sdes		{
282127094Sdes		BIO *tmpbio = BIO_new(BIO_f_linebuffer());
28361861Sru		out = BIO_push(tmpbio, out);
284127094Sdes		}
285127094Sdes#endif
286127094Sdes		}
287127094Sdes	else
288127094Sdes		{
28967966Sru		if (BIO_write_filename(out,outfile) <= 0)
290127094Sdes			{
291127094Sdes			perror(outfile);
292127094Sdes			goto end;
293127094Sdes			}
294127094Sdes		}
29561861Sru
29661861Sru	if (text)
29761861Sru		if (!RSA_print(out,rsa,0))
29861861Sru			{
299162674Spiso			perror(outfile);
300124621Sphk			ERR_print_errors(bio_err);
301127094Sdes			goto end;
302131614Sdes			}
303127094Sdes
304131614Sdes	if (modulus)
305127094Sdes		{
306127094Sdes		BIO_printf(out,"Modulus=");
307127094Sdes		BN_print(out,rsa->n);
308127094Sdes		BIO_printf(out,"\n");
30961861Sru		}
310127094Sdes
311127094Sdes	if (check)
312127094Sdes		{
31361861Sru		int r = RSA_check_key(rsa);
314127094Sdes
315127094Sdes		if (r == 1)
316127094Sdes			BIO_printf(out,"RSA key ok\n");
317127094Sdes		else if (r == 0)
318127094Sdes			{
319127094Sdes			unsigned long err;
320127094Sdes
321127094Sdes			while ((err = ERR_peek_error()) != 0 &&
322127094Sdes				ERR_GET_LIB(err) == ERR_LIB_RSA &&
323127094Sdes				ERR_GET_FUNC(err) == RSA_F_RSA_CHECK_KEY &&
324131614Sdes				ERR_GET_REASON(err) != ERR_R_MALLOC_FAILURE)
325131614Sdes				{
326127094Sdes				BIO_printf(out, "RSA key error: %s\n", ERR_reason_error_string(err));
327127094Sdes				ERR_get_error(); /* remove e from error stack */
328127094Sdes				}
329127094Sdes			}
330127094Sdes
331127094Sdes		if (r == -1 || ERR_peek_error() != 0) /* should happen only if r == -1 */
332127094Sdes			{
333131614Sdes			ERR_print_errors(bio_err);
334131614Sdes			goto end;
335127094Sdes			}
336127094Sdes		}
337127094Sdes
338127094Sdes	if (noout)
339127094Sdes		{
34061861Sru		ret = 0;
341131614Sdes		goto end;
342127094Sdes		}
34364334Sru	BIO_printf(bio_err,"writing RSA key\n");
344127094Sdes	if 	(outformat == FORMAT_ASN1) {
345131614Sdes		if(pubout || pubin) i=i2d_RSA_PUBKEY_bio(out,rsa);
34661861Sru		else i=i2d_RSAPrivateKey_bio(out,rsa);
347127094Sdes	}
348131699Sdes#ifndef OPENSSL_NO_RC4
349127094Sdes	else if (outformat == FORMAT_NETSCAPE)
350127094Sdes		{
35167966Sru		unsigned char *p,*pp;
352127094Sdes		int size;
353127094Sdes
354127094Sdes		i=1;
355127094Sdes		size=i2d_RSA_NET(rsa,NULL,NULL, sgckey);
356127094Sdes		if ((p=(unsigned char *)OPENSSL_malloc(size)) == NULL)
357127094Sdes			{
358131614Sdes			BIO_printf(bio_err,"Memory allocation failure\n");
359127094Sdes			goto end;
360127094Sdes			}
361127094Sdes		pp=p;
362131614Sdes		i2d_RSA_NET(rsa,&p,NULL, sgckey);
363127094Sdes		BIO_write(out,(char *)pp,size);
364127094Sdes		OPENSSL_free(pp);
365131614Sdes		}
366127094Sdes#endif
367127094Sdes	else if (outformat == FORMAT_PEM) {
36867966Sru		if(pubout || pubin)
36961861Sru		    i=PEM_write_bio_RSA_PUBKEY(out,rsa);
37061861Sru		else i=PEM_write_bio_RSAPrivateKey(out,rsa,
371162674Spiso						enc,NULL,0,NULL,passout);
372127094Sdes	} else	{
373127094Sdes		BIO_printf(bio_err,"bad output format specified for outfile\n");
374131614Sdes		goto end;
375127094Sdes		}
376131614Sdes	if (!i)
377127094Sdes		{
378127094Sdes		BIO_printf(bio_err,"unable to write key\n");
379127094Sdes		ERR_print_errors(bio_err);
380127094Sdes		}
38161861Sru	else
382127094Sdes		ret=0;
383127094Sdesend:
384127094Sdes	if(out != NULL) BIO_free_all(out);
38561861Sru	if(rsa != NULL) RSA_free(rsa);
386127094Sdes	if(passin) OPENSSL_free(passin);
387127094Sdes	if(passout) OPENSSL_free(passout);
388127094Sdes	apps_shutdown();
389127094Sdes	OPENSSL_EXIT(ret);
390127094Sdes	}
391127094Sdes#else /* !OPENSSL_NO_RSA */
392127094Sdes
393127094Sdes# if PEDANTIC
394127094Sdesstatic void *dummy=&dummy;
395127094Sdes# endif
396127094Sdes
397127094Sdes#endif
398131614Sdes