Annotation of src/usr.bin/openssl/genrsa.c, Revision 1.1
1.1 ! jsing 1: /* $OpenBSD: genrsa.c,v 1.37 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: /* Until the key-gen callbacks are modified to use newer prototypes, we allow
! 62: * deprecated functions for openssl-internal code */
! 63: #ifdef OPENSSL_NO_DEPRECATED
! 64: #undef OPENSSL_NO_DEPRECATED
! 65: #endif
! 66:
! 67:
! 68: #include <sys/types.h>
! 69: #include <sys/stat.h>
! 70:
! 71: #include <stdio.h>
! 72: #include <string.h>
! 73:
! 74: #include "apps.h"
! 75:
! 76: #include <openssl/bio.h>
! 77: #include <openssl/bn.h>
! 78: #include <openssl/err.h>
! 79: #include <openssl/evp.h>
! 80: #include <openssl/pem.h>
! 81: #include <openssl/rand.h>
! 82: #include <openssl/rsa.h>
! 83: #include <openssl/x509.h>
! 84:
! 85: #define DEFBITS 2048
! 86:
! 87: static int genrsa_cb(int p, int n, BN_GENCB * cb);
! 88:
! 89: int genrsa_main(int, char **);
! 90:
! 91: int
! 92: genrsa_main(int argc, char **argv)
! 93: {
! 94: BN_GENCB cb;
! 95: #ifndef OPENSSL_NO_ENGINE
! 96: ENGINE *e = NULL;
! 97: #endif
! 98: int ret = 1;
! 99: int i, num = DEFBITS;
! 100: long l;
! 101: const EVP_CIPHER *enc = NULL;
! 102: unsigned long f4 = RSA_F4;
! 103: char *outfile = NULL;
! 104: char *passargout = NULL, *passout = NULL;
! 105: #ifndef OPENSSL_NO_ENGINE
! 106: char *engine = NULL;
! 107: #endif
! 108: BIO *out = NULL;
! 109: BIGNUM *bn = BN_new();
! 110: RSA *rsa = NULL;
! 111:
! 112: if (!bn)
! 113: goto err;
! 114:
! 115: BN_GENCB_set(&cb, genrsa_cb, bio_err);
! 116:
! 117: if ((out = BIO_new(BIO_s_file())) == NULL) {
! 118: BIO_printf(bio_err, "unable to create BIO for output\n");
! 119: goto err;
! 120: }
! 121: argv++;
! 122: argc--;
! 123: for (;;) {
! 124: if (argc <= 0)
! 125: break;
! 126: if (strcmp(*argv, "-out") == 0) {
! 127: if (--argc < 1)
! 128: goto bad;
! 129: outfile = *(++argv);
! 130: } else if (strcmp(*argv, "-3") == 0)
! 131: f4 = 3;
! 132: else if (strcmp(*argv, "-F4") == 0 || strcmp(*argv, "-f4") == 0)
! 133: f4 = RSA_F4;
! 134: #ifndef OPENSSL_NO_ENGINE
! 135: else if (strcmp(*argv, "-engine") == 0) {
! 136: if (--argc < 1)
! 137: goto bad;
! 138: engine = *(++argv);
! 139: }
! 140: #endif
! 141: #ifndef OPENSSL_NO_DES
! 142: else if (strcmp(*argv, "-des") == 0)
! 143: enc = EVP_des_cbc();
! 144: else if (strcmp(*argv, "-des3") == 0)
! 145: enc = EVP_des_ede3_cbc();
! 146: #endif
! 147: #ifndef OPENSSL_NO_IDEA
! 148: else if (strcmp(*argv, "-idea") == 0)
! 149: enc = EVP_idea_cbc();
! 150: #endif
! 151: #ifndef OPENSSL_NO_AES
! 152: else if (strcmp(*argv, "-aes128") == 0)
! 153: enc = EVP_aes_128_cbc();
! 154: else if (strcmp(*argv, "-aes192") == 0)
! 155: enc = EVP_aes_192_cbc();
! 156: else if (strcmp(*argv, "-aes256") == 0)
! 157: enc = EVP_aes_256_cbc();
! 158: #endif
! 159: #ifndef OPENSSL_NO_CAMELLIA
! 160: else if (strcmp(*argv, "-camellia128") == 0)
! 161: enc = EVP_camellia_128_cbc();
! 162: else if (strcmp(*argv, "-camellia192") == 0)
! 163: enc = EVP_camellia_192_cbc();
! 164: else if (strcmp(*argv, "-camellia256") == 0)
! 165: enc = EVP_camellia_256_cbc();
! 166: #endif
! 167: else if (strcmp(*argv, "-passout") == 0) {
! 168: if (--argc < 1)
! 169: goto bad;
! 170: passargout = *(++argv);
! 171: } else
! 172: break;
! 173: argv++;
! 174: argc--;
! 175: }
! 176: if ((argc >= 1) && ((sscanf(*argv, "%d", &num) == 0) || (num < 0))) {
! 177: bad:
! 178: BIO_printf(bio_err, "usage: genrsa [args] [numbits]\n");
! 179: BIO_printf(bio_err, " -des encrypt the generated key with DES in cbc mode\n");
! 180: BIO_printf(bio_err, " -des3 encrypt the generated key with DES in ede cbc mode (168 bit key)\n");
! 181: #ifndef OPENSSL_NO_IDEA
! 182: BIO_printf(bio_err, " -idea encrypt the generated key with IDEA in cbc mode\n");
! 183: #endif
! 184: #ifndef OPENSSL_NO_AES
! 185: BIO_printf(bio_err, " -aes128, -aes192, -aes256\n");
! 186: BIO_printf(bio_err, " encrypt PEM output with cbc aes\n");
! 187: #endif
! 188: #ifndef OPENSSL_NO_CAMELLIA
! 189: BIO_printf(bio_err, " -camellia128, -camellia192, -camellia256\n");
! 190: BIO_printf(bio_err, " encrypt PEM output with cbc camellia\n");
! 191: #endif
! 192: BIO_printf(bio_err, " -out file output the key to 'file\n");
! 193: BIO_printf(bio_err, " -passout arg output file pass phrase source\n");
! 194: BIO_printf(bio_err, " -f4 use F4 (0x10001) for the E value\n");
! 195: BIO_printf(bio_err, " -3 use 3 for the E value\n");
! 196: #ifndef OPENSSL_NO_ENGINE
! 197: BIO_printf(bio_err, " -engine e use engine e, possibly a hardware device.\n");
! 198: #endif
! 199: goto err;
! 200: }
! 201: ERR_load_crypto_strings();
! 202:
! 203: if (!app_passwd(bio_err, NULL, passargout, NULL, &passout)) {
! 204: BIO_printf(bio_err, "Error getting password\n");
! 205: goto err;
! 206: }
! 207: #ifndef OPENSSL_NO_ENGINE
! 208: e = setup_engine(bio_err, engine, 0);
! 209: #endif
! 210:
! 211: if (outfile == NULL) {
! 212: BIO_set_fp(out, stdout, BIO_NOCLOSE);
! 213: } else {
! 214: if (BIO_write_filename(out, outfile) <= 0) {
! 215: perror(outfile);
! 216: goto err;
! 217: }
! 218: }
! 219:
! 220: BIO_printf(bio_err, "Generating RSA private key, %d bit long modulus\n",
! 221: num);
! 222: #ifdef OPENSSL_NO_ENGINE
! 223: rsa = RSA_new();
! 224: #else
! 225: rsa = RSA_new_method(e);
! 226: #endif
! 227: if (!rsa)
! 228: goto err;
! 229:
! 230: if (!BN_set_word(bn, f4) || !RSA_generate_key_ex(rsa, num, bn, &cb))
! 231: goto err;
! 232:
! 233: /*
! 234: * We need to do the following for when the base number size is <
! 235: * long, esp windows 3.1 :-(.
! 236: */
! 237: l = 0L;
! 238: for (i = 0; i < rsa->e->top; i++) {
! 239: #ifndef _LP64
! 240: l <<= BN_BITS4;
! 241: l <<= BN_BITS4;
! 242: #endif
! 243: l += rsa->e->d[i];
! 244: }
! 245: BIO_printf(bio_err, "e is %ld (0x%lX)\n", l, l);
! 246: {
! 247: PW_CB_DATA cb_data;
! 248: cb_data.password = passout;
! 249: cb_data.prompt_info = outfile;
! 250: if (!PEM_write_bio_RSAPrivateKey(out, rsa, enc, NULL, 0,
! 251: password_callback, &cb_data))
! 252: goto err;
! 253: }
! 254:
! 255: ret = 0;
! 256: err:
! 257: if (bn)
! 258: BN_free(bn);
! 259: if (rsa)
! 260: RSA_free(rsa);
! 261: if (out)
! 262: BIO_free_all(out);
! 263: free(passout);
! 264: if (ret != 0)
! 265: ERR_print_errors(bio_err);
! 266:
! 267: return (ret);
! 268: }
! 269:
! 270: static int
! 271: genrsa_cb(int p, int n, BN_GENCB * cb)
! 272: {
! 273: char c = '*';
! 274:
! 275: if (p == 0)
! 276: c = '.';
! 277: if (p == 1)
! 278: c = '+';
! 279: if (p == 2)
! 280: c = '*';
! 281: if (p == 3)
! 282: c = '\n';
! 283: BIO_write(cb->arg, &c, 1);
! 284: (void) BIO_flush(cb->arg);
! 285: return 1;
! 286: }