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