Annotation of src/usr.bin/openssl/rsa.c, Revision 1.1
1.1 ! jsing 1: /* $OpenBSD: rsa.c,v 1.27 2014/07/14 00:35:10 deraadt Exp $ */
! 2: /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
! 3: * All rights reserved.
! 4: *
! 5: * This package is an SSL implementation written
! 6: * by Eric Young (eay@cryptsoft.com).
! 7: * The implementation was written so as to conform with Netscapes SSL.
! 8: *
! 9: * This library is free for commercial and non-commercial use as long as
! 10: * the following conditions are aheared to. The following conditions
! 11: * apply to all code found in this distribution, be it the RC4, RSA,
! 12: * lhash, DES, etc., code; not just the SSL code. The SSL documentation
! 13: * included with this distribution is covered by the same copyright terms
! 14: * except that the holder is Tim Hudson (tjh@cryptsoft.com).
! 15: *
! 16: * Copyright remains Eric Young's, and as such any Copyright notices in
! 17: * the code are not to be removed.
! 18: * If this package is used in a product, Eric Young should be given attribution
! 19: * as the author of the parts of the library used.
! 20: * This can be in the form of a textual message at program startup or
! 21: * in documentation (online or textual) provided with the package.
! 22: *
! 23: * Redistribution and use in source and binary forms, with or without
! 24: * modification, are permitted provided that the following conditions
! 25: * are met:
! 26: * 1. Redistributions of source code must retain the copyright
! 27: * notice, this list of conditions and the following disclaimer.
! 28: * 2. Redistributions in binary form must reproduce the above copyright
! 29: * notice, this list of conditions and the following disclaimer in the
! 30: * documentation and/or other materials provided with the distribution.
! 31: * 3. All advertising materials mentioning features or use of this software
! 32: * must display the following acknowledgement:
! 33: * "This product includes cryptographic software written by
! 34: * Eric Young (eay@cryptsoft.com)"
! 35: * The word 'cryptographic' can be left out if the rouines from the library
! 36: * being used are not cryptographic related :-).
! 37: * 4. If you include any Windows specific code (or a derivative thereof) from
! 38: * the apps directory (application code) you must include an acknowledgement:
! 39: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
! 40: *
! 41: * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
! 42: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 43: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 44: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
! 45: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 46: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 47: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 48: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 49: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 50: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 51: * SUCH DAMAGE.
! 52: *
! 53: * The licence and distribution terms for any publically available version or
! 54: * derivative of this code cannot be changed. i.e. this code cannot simply be
! 55: * copied and put under another distribution licence
! 56: * [including the GNU Public Licence.]
! 57: */
! 58:
! 59: #include <openssl/opensslconf.h>
! 60:
! 61:
! 62: #include <stdio.h>
! 63: #include <stdlib.h>
! 64: #include <string.h>
! 65: #include <time.h>
! 66:
! 67: #include "apps.h"
! 68:
! 69: #include <openssl/bio.h>
! 70: #include <openssl/bn.h>
! 71: #include <openssl/err.h>
! 72: #include <openssl/evp.h>
! 73: #include <openssl/pem.h>
! 74: #include <openssl/rsa.h>
! 75: #include <openssl/x509.h>
! 76:
! 77: /* -inform arg - input format - default PEM (one of DER, NET or PEM)
! 78: * -outform arg - output format - default PEM
! 79: * -in arg - input file - default stdin
! 80: * -out arg - output file - default stdout
! 81: * -des - encrypt output if PEM format with DES in cbc mode
! 82: * -des3 - encrypt output if PEM format
! 83: * -idea - encrypt output if PEM format
! 84: * -seed - encrypt output if PEM format
! 85: * -aes128 - encrypt output if PEM format
! 86: * -aes192 - encrypt output if PEM format
! 87: * -aes256 - encrypt output if PEM format
! 88: * -camellia128 - encrypt output if PEM format
! 89: * -camellia192 - encrypt output if PEM format
! 90: * -camellia256 - encrypt output if PEM format
! 91: * -text - print a text version
! 92: * -modulus - print the RSA key modulus
! 93: * -check - verify key consistency
! 94: * -pubin - Expect a public key in input file.
! 95: * -pubout - Output a public key.
! 96: */
! 97:
! 98: int rsa_main(int, char **);
! 99:
! 100: int
! 101: rsa_main(int argc, char **argv)
! 102: {
! 103: ENGINE *e = NULL;
! 104: int ret = 1;
! 105: RSA *rsa = NULL;
! 106: int i, badops = 0, sgckey = 0;
! 107: const EVP_CIPHER *enc = NULL;
! 108: BIO *out = NULL;
! 109: int informat, outformat, text = 0, check = 0, noout = 0;
! 110: int pubin = 0, pubout = 0;
! 111: char *infile, *outfile, *prog;
! 112: char *passargin = NULL, *passargout = NULL;
! 113: char *passin = NULL, *passout = NULL;
! 114: #ifndef OPENSSL_NO_ENGINE
! 115: char *engine = NULL;
! 116: #endif
! 117: int modulus = 0;
! 118:
! 119: int pvk_encr = 2;
! 120:
! 121: infile = NULL;
! 122: outfile = NULL;
! 123: informat = FORMAT_PEM;
! 124: outformat = FORMAT_PEM;
! 125:
! 126: prog = argv[0];
! 127: argc--;
! 128: argv++;
! 129: while (argc >= 1) {
! 130: if (strcmp(*argv, "-inform") == 0) {
! 131: if (--argc < 1)
! 132: goto bad;
! 133: informat = str2fmt(*(++argv));
! 134: } else if (strcmp(*argv, "-outform") == 0) {
! 135: if (--argc < 1)
! 136: goto bad;
! 137: outformat = str2fmt(*(++argv));
! 138: } else if (strcmp(*argv, "-in") == 0) {
! 139: if (--argc < 1)
! 140: goto bad;
! 141: infile = *(++argv);
! 142: } else if (strcmp(*argv, "-out") == 0) {
! 143: if (--argc < 1)
! 144: goto bad;
! 145: outfile = *(++argv);
! 146: } else if (strcmp(*argv, "-passin") == 0) {
! 147: if (--argc < 1)
! 148: goto bad;
! 149: passargin = *(++argv);
! 150: } else if (strcmp(*argv, "-passout") == 0) {
! 151: if (--argc < 1)
! 152: goto bad;
! 153: passargout = *(++argv);
! 154: }
! 155: #ifndef OPENSSL_NO_ENGINE
! 156: else if (strcmp(*argv, "-engine") == 0) {
! 157: if (--argc < 1)
! 158: goto bad;
! 159: engine = *(++argv);
! 160: }
! 161: #endif
! 162: else if (strcmp(*argv, "-sgckey") == 0)
! 163: sgckey = 1;
! 164: else if (strcmp(*argv, "-pubin") == 0)
! 165: pubin = 1;
! 166: else if (strcmp(*argv, "-pubout") == 0)
! 167: pubout = 1;
! 168: else if (strcmp(*argv, "-RSAPublicKey_in") == 0)
! 169: pubin = 2;
! 170: else if (strcmp(*argv, "-RSAPublicKey_out") == 0)
! 171: pubout = 2;
! 172: else if (strcmp(*argv, "-pvk-strong") == 0)
! 173: pvk_encr = 2;
! 174: else if (strcmp(*argv, "-pvk-weak") == 0)
! 175: pvk_encr = 1;
! 176: else if (strcmp(*argv, "-pvk-none") == 0)
! 177: pvk_encr = 0;
! 178: else if (strcmp(*argv, "-noout") == 0)
! 179: noout = 1;
! 180: else if (strcmp(*argv, "-text") == 0)
! 181: text = 1;
! 182: else if (strcmp(*argv, "-modulus") == 0)
! 183: modulus = 1;
! 184: else if (strcmp(*argv, "-check") == 0)
! 185: check = 1;
! 186: else if ((enc = EVP_get_cipherbyname(&(argv[0][1]))) == NULL) {
! 187: BIO_printf(bio_err, "unknown option %s\n", *argv);
! 188: badops = 1;
! 189: break;
! 190: }
! 191: argc--;
! 192: argv++;
! 193: }
! 194:
! 195: if (badops) {
! 196: bad:
! 197: BIO_printf(bio_err, "%s [options] <infile >outfile\n", prog);
! 198: BIO_printf(bio_err, "where options are\n");
! 199: BIO_printf(bio_err, " -inform arg input format - one of DER NET PEM\n");
! 200: BIO_printf(bio_err, " -outform arg output format - one of DER NET PEM\n");
! 201: BIO_printf(bio_err, " -in arg input file\n");
! 202: BIO_printf(bio_err, " -sgckey Use IIS SGC key format\n");
! 203: BIO_printf(bio_err, " -passin arg input file pass phrase source\n");
! 204: BIO_printf(bio_err, " -out arg output file\n");
! 205: BIO_printf(bio_err, " -passout arg output file pass phrase source\n");
! 206: BIO_printf(bio_err, " -des encrypt PEM output with cbc des\n");
! 207: BIO_printf(bio_err, " -des3 encrypt PEM output with ede cbc des using 168 bit key\n");
! 208: #ifndef OPENSSL_NO_IDEA
! 209: BIO_printf(bio_err, " -idea encrypt PEM output with cbc idea\n");
! 210: #endif
! 211: #ifndef OPENSSL_NO_AES
! 212: BIO_printf(bio_err, " -aes128, -aes192, -aes256\n");
! 213: BIO_printf(bio_err, " encrypt PEM output with cbc aes\n");
! 214: #endif
! 215: #ifndef OPENSSL_NO_CAMELLIA
! 216: BIO_printf(bio_err, " -camellia128, -camellia192, -camellia256\n");
! 217: BIO_printf(bio_err, " encrypt PEM output with cbc camellia\n");
! 218: #endif
! 219: BIO_printf(bio_err, " -text print the key in text\n");
! 220: BIO_printf(bio_err, " -noout don't print key out\n");
! 221: BIO_printf(bio_err, " -modulus print the RSA key modulus\n");
! 222: BIO_printf(bio_err, " -check verify key consistency\n");
! 223: BIO_printf(bio_err, " -pubin expect a public key in input file\n");
! 224: BIO_printf(bio_err, " -pubout output a public key\n");
! 225: #ifndef OPENSSL_NO_ENGINE
! 226: BIO_printf(bio_err, " -engine e use engine e, possibly a hardware device.\n");
! 227: #endif
! 228: goto end;
! 229: }
! 230: ERR_load_crypto_strings();
! 231:
! 232: #ifndef OPENSSL_NO_ENGINE
! 233: e = setup_engine(bio_err, engine, 0);
! 234: #endif
! 235:
! 236: if (!app_passwd(bio_err, passargin, passargout, &passin, &passout)) {
! 237: BIO_printf(bio_err, "Error getting passwords\n");
! 238: goto end;
! 239: }
! 240: if (check && pubin) {
! 241: BIO_printf(bio_err, "Only private keys can be checked\n");
! 242: goto end;
! 243: }
! 244: out = BIO_new(BIO_s_file());
! 245:
! 246: {
! 247: EVP_PKEY *pkey;
! 248:
! 249: if (pubin) {
! 250: int tmpformat = -1;
! 251: if (pubin == 2) {
! 252: if (informat == FORMAT_PEM)
! 253: tmpformat = FORMAT_PEMRSA;
! 254: else if (informat == FORMAT_ASN1)
! 255: tmpformat = FORMAT_ASN1RSA;
! 256: } else if (informat == FORMAT_NETSCAPE && sgckey)
! 257: tmpformat = FORMAT_IISSGC;
! 258: else
! 259: tmpformat = informat;
! 260:
! 261: pkey = load_pubkey(bio_err, infile, tmpformat, 1,
! 262: passin, e, "Public Key");
! 263: } else
! 264: pkey = load_key(bio_err, infile,
! 265: (informat == FORMAT_NETSCAPE && sgckey ?
! 266: FORMAT_IISSGC : informat), 1,
! 267: passin, e, "Private Key");
! 268:
! 269: if (pkey != NULL)
! 270: rsa = EVP_PKEY_get1_RSA(pkey);
! 271: EVP_PKEY_free(pkey);
! 272: }
! 273:
! 274: if (rsa == NULL) {
! 275: ERR_print_errors(bio_err);
! 276: goto end;
! 277: }
! 278: if (outfile == NULL) {
! 279: BIO_set_fp(out, stdout, BIO_NOCLOSE);
! 280: } else {
! 281: if (BIO_write_filename(out, outfile) <= 0) {
! 282: perror(outfile);
! 283: goto end;
! 284: }
! 285: }
! 286:
! 287: if (text)
! 288: if (!RSA_print(out, rsa, 0)) {
! 289: perror(outfile);
! 290: ERR_print_errors(bio_err);
! 291: goto end;
! 292: }
! 293: if (modulus) {
! 294: BIO_printf(out, "Modulus=");
! 295: BN_print(out, rsa->n);
! 296: BIO_printf(out, "\n");
! 297: }
! 298: if (check) {
! 299: int r = RSA_check_key(rsa);
! 300:
! 301: if (r == 1)
! 302: BIO_printf(out, "RSA key ok\n");
! 303: else if (r == 0) {
! 304: unsigned long err;
! 305:
! 306: while ((err = ERR_peek_error()) != 0 &&
! 307: ERR_GET_LIB(err) == ERR_LIB_RSA &&
! 308: ERR_GET_FUNC(err) == RSA_F_RSA_CHECK_KEY &&
! 309: ERR_GET_REASON(err) != ERR_R_MALLOC_FAILURE) {
! 310: BIO_printf(out, "RSA key error: %s\n", ERR_reason_error_string(err));
! 311: ERR_get_error(); /* remove e from error
! 312: * stack */
! 313: }
! 314: }
! 315: if (r == -1 || ERR_peek_error() != 0) { /* should happen only if
! 316: * r == -1 */
! 317: ERR_print_errors(bio_err);
! 318: goto end;
! 319: }
! 320: }
! 321: if (noout) {
! 322: ret = 0;
! 323: goto end;
! 324: }
! 325: BIO_printf(bio_err, "writing RSA key\n");
! 326: if (outformat == FORMAT_ASN1) {
! 327: if (pubout || pubin) {
! 328: if (pubout == 2)
! 329: i = i2d_RSAPublicKey_bio(out, rsa);
! 330: else
! 331: i = i2d_RSA_PUBKEY_bio(out, rsa);
! 332: } else
! 333: i = i2d_RSAPrivateKey_bio(out, rsa);
! 334: }
! 335: #ifndef OPENSSL_NO_RC4
! 336: else if (outformat == FORMAT_NETSCAPE) {
! 337: unsigned char *p, *pp;
! 338: int size;
! 339:
! 340: i = 1;
! 341: size = i2d_RSA_NET(rsa, NULL, NULL, sgckey);
! 342: if ((p = malloc(size)) == NULL) {
! 343: BIO_printf(bio_err, "Memory allocation failure\n");
! 344: goto end;
! 345: }
! 346: pp = p;
! 347: i2d_RSA_NET(rsa, &p, NULL, sgckey);
! 348: BIO_write(out, (char *) pp, size);
! 349: free(pp);
! 350: }
! 351: #endif
! 352: else if (outformat == FORMAT_PEM) {
! 353: if (pubout || pubin) {
! 354: if (pubout == 2)
! 355: i = PEM_write_bio_RSAPublicKey(out, rsa);
! 356: else
! 357: i = PEM_write_bio_RSA_PUBKEY(out, rsa);
! 358: } else
! 359: i = PEM_write_bio_RSAPrivateKey(out, rsa,
! 360: enc, NULL, 0, NULL, passout);
! 361: #if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4)
! 362: } else if (outformat == FORMAT_MSBLOB || outformat == FORMAT_PVK) {
! 363: EVP_PKEY *pk;
! 364: pk = EVP_PKEY_new();
! 365: EVP_PKEY_set1_RSA(pk, rsa);
! 366: if (outformat == FORMAT_PVK)
! 367: i = i2b_PVK_bio(out, pk, pvk_encr, 0, passout);
! 368: else if (pubin || pubout)
! 369: i = i2b_PublicKey_bio(out, pk);
! 370: else
! 371: i = i2b_PrivateKey_bio(out, pk);
! 372: EVP_PKEY_free(pk);
! 373: #endif
! 374: } else {
! 375: BIO_printf(bio_err, "bad output format specified for outfile\n");
! 376: goto end;
! 377: }
! 378: if (i <= 0) {
! 379: BIO_printf(bio_err, "unable to write key\n");
! 380: ERR_print_errors(bio_err);
! 381: } else
! 382: ret = 0;
! 383: end:
! 384: if (out != NULL)
! 385: BIO_free_all(out);
! 386: if (rsa != NULL)
! 387: RSA_free(rsa);
! 388: free(passin);
! 389: free(passout);
! 390:
! 391: return (ret);
! 392: }