[BACK]Return to pkcs8.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / openssl

Annotation of src/usr.bin/openssl/pkcs8.c, Revision 1.3

1.3     ! jsing       1: /* $OpenBSD: pkcs8.c,v 1.2 2014/08/28 14:23:52 jsing Exp $ */
1.1       jsing       2: /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
                      3:  * project 1999-2004.
                      4:  */
                      5: /* ====================================================================
                      6:  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  *
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  *
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in
                     17:  *    the documentation and/or other materials provided with the
                     18:  *    distribution.
                     19:  *
                     20:  * 3. All advertising materials mentioning features or use of this
                     21:  *    software must display the following acknowledgment:
                     22:  *    "This product includes software developed by the OpenSSL Project
                     23:  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
                     24:  *
                     25:  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
                     26:  *    endorse or promote products derived from this software without
                     27:  *    prior written permission. For written permission, please contact
                     28:  *    licensing@OpenSSL.org.
                     29:  *
                     30:  * 5. Products derived from this software may not be called "OpenSSL"
                     31:  *    nor may "OpenSSL" appear in their names without prior written
                     32:  *    permission of the OpenSSL Project.
                     33:  *
                     34:  * 6. Redistributions of any form whatsoever must retain the following
                     35:  *    acknowledgment:
                     36:  *    "This product includes software developed by the OpenSSL Project
                     37:  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
                     38:  *
                     39:  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
                     40:  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     41:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     42:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
                     43:  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
                     44:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     45:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
                     46:  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     47:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     48:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     49:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
                     50:  * OF THE POSSIBILITY OF SUCH DAMAGE.
                     51:  * ====================================================================
                     52:  *
                     53:  * This product includes cryptographic software written by Eric Young
                     54:  * (eay@cryptsoft.com).  This product includes software written by Tim
                     55:  * Hudson (tjh@cryptsoft.com).
                     56:  *
                     57:  */
                     58:
                     59: #include <stdio.h>
                     60: #include <string.h>
                     61:
                     62: #include "apps.h"
                     63:
                     64: #include <openssl/err.h>
                     65: #include <openssl/evp.h>
                     66: #include <openssl/pem.h>
                     67: #include <openssl/pkcs12.h>
                     68:
                     69: int pkcs8_main(int, char **);
                     70:
                     71: int
                     72: pkcs8_main(int argc, char **argv)
                     73: {
                     74:        ENGINE *e = NULL;
                     75:        char **args, *infile = NULL, *outfile = NULL;
                     76:        char *passargin = NULL, *passargout = NULL;
                     77:        BIO *in = NULL, *out = NULL;
                     78:        int topk8 = 0;
                     79:        int pbe_nid = -1;
                     80:        const EVP_CIPHER *cipher = NULL;
                     81:        int iter = PKCS12_DEFAULT_ITER;
                     82:        int informat, outformat;
                     83:        int p8_broken = PKCS8_OK;
                     84:        int nocrypt = 0;
                     85:        X509_SIG *p8 = NULL;
                     86:        PKCS8_PRIV_KEY_INFO *p8inf = NULL;
                     87:        EVP_PKEY *pkey = NULL;
                     88:        char pass[50], *passin = NULL, *passout = NULL, *p8pass = NULL;
                     89:        int badarg = 0;
                     90:        int ret = 1;
                     91: #ifndef OPENSSL_NO_ENGINE
                     92:        char *engine = NULL;
                     93: #endif
                     94:
                     95:        informat = FORMAT_PEM;
                     96:        outformat = FORMAT_PEM;
                     97:
                     98:        args = argv + 1;
                     99:        while (!badarg && *args && *args[0] == '-') {
                    100:                if (!strcmp(*args, "-v2")) {
                    101:                        if (args[1]) {
                    102:                                args++;
                    103:                                cipher = EVP_get_cipherbyname(*args);
                    104:                                if (!cipher) {
                    105:                                        BIO_printf(bio_err,
                    106:                                            "Unknown cipher %s\n", *args);
                    107:                                        badarg = 1;
                    108:                                }
                    109:                        } else
                    110:                                badarg = 1;
                    111:                } else if (!strcmp(*args, "-v1")) {
                    112:                        if (args[1]) {
                    113:                                args++;
                    114:                                pbe_nid = OBJ_txt2nid(*args);
                    115:                                if (pbe_nid == NID_undef) {
                    116:                                        BIO_printf(bio_err,
                    117:                                            "Unknown PBE algorithm %s\n", *args);
                    118:                                        badarg = 1;
                    119:                                }
                    120:                        } else
                    121:                                badarg = 1;
                    122:                } else if (!strcmp(*args, "-inform")) {
                    123:                        if (args[1]) {
                    124:                                args++;
                    125:                                informat = str2fmt(*args);
                    126:                        } else
                    127:                                badarg = 1;
                    128:                } else if (!strcmp(*args, "-outform")) {
                    129:                        if (args[1]) {
                    130:                                args++;
                    131:                                outformat = str2fmt(*args);
                    132:                        } else
                    133:                                badarg = 1;
                    134:                } else if (!strcmp(*args, "-topk8"))
                    135:                        topk8 = 1;
                    136:                else if (!strcmp(*args, "-noiter"))
                    137:                        iter = 1;
                    138:                else if (!strcmp(*args, "-nocrypt"))
                    139:                        nocrypt = 1;
                    140:                else if (!strcmp(*args, "-nooct"))
                    141:                        p8_broken = PKCS8_NO_OCTET;
                    142:                else if (!strcmp(*args, "-nsdb"))
                    143:                        p8_broken = PKCS8_NS_DB;
                    144:                else if (!strcmp(*args, "-embed"))
                    145:                        p8_broken = PKCS8_EMBEDDED_PARAM;
                    146:                else if (!strcmp(*args, "-passin")) {
                    147:                        if (!args[1])
                    148:                                goto bad;
                    149:                        passargin = *(++args);
                    150:                } else if (!strcmp(*args, "-passout")) {
                    151:                        if (!args[1])
                    152:                                goto bad;
                    153:                        passargout = *(++args);
                    154:                }
                    155: #ifndef OPENSSL_NO_ENGINE
                    156:                else if (strcmp(*args, "-engine") == 0) {
                    157:                        if (!args[1])
                    158:                                goto bad;
                    159:                        engine = *(++args);
                    160:                }
                    161: #endif
                    162:                else if (!strcmp(*args, "-in")) {
                    163:                        if (args[1]) {
                    164:                                args++;
                    165:                                infile = *args;
                    166:                        } else
                    167:                                badarg = 1;
                    168:                } else if (!strcmp(*args, "-out")) {
                    169:                        if (args[1]) {
                    170:                                args++;
                    171:                                outfile = *args;
                    172:                        } else
                    173:                                badarg = 1;
                    174:                } else
                    175:                        badarg = 1;
                    176:                args++;
                    177:        }
                    178:
                    179:        if (badarg) {
                    180: bad:
                    181:                BIO_printf(bio_err, "Usage pkcs8 [options]\n");
                    182:                BIO_printf(bio_err, "where options are\n");
                    183:                BIO_printf(bio_err, "-in file        input file\n");
                    184:                BIO_printf(bio_err, "-inform X       input format (DER or PEM)\n");
                    185:                BIO_printf(bio_err, "-passin arg     input file pass phrase source\n");
                    186:                BIO_printf(bio_err, "-outform X      output format (DER or PEM)\n");
                    187:                BIO_printf(bio_err, "-out file       output file\n");
                    188:                BIO_printf(bio_err, "-passout arg    output file pass phrase source\n");
                    189:                BIO_printf(bio_err, "-topk8          output PKCS8 file\n");
                    190:                BIO_printf(bio_err, "-nooct          use (nonstandard) no octet format\n");
                    191:                BIO_printf(bio_err, "-embed          use (nonstandard) embedded DSA parameters format\n");
                    192:                BIO_printf(bio_err, "-nsdb           use (nonstandard) DSA Netscape DB format\n");
                    193:                BIO_printf(bio_err, "-noiter         use 1 as iteration count\n");
                    194:                BIO_printf(bio_err, "-nocrypt        use or expect unencrypted private key\n");
                    195:                BIO_printf(bio_err, "-v2 alg         use PKCS#5 v2.0 and cipher \"alg\"\n");
                    196:                BIO_printf(bio_err, "-v1 obj         use PKCS#5 v1.5 and cipher \"alg\"\n");
                    197: #ifndef OPENSSL_NO_ENGINE
                    198:                BIO_printf(bio_err, " -engine e       use engine e, possibly a hardware device.\n");
                    199: #endif
                    200:                goto end;
                    201:        }
                    202: #ifndef OPENSSL_NO_ENGINE
                    203:        e = setup_engine(bio_err, engine, 0);
                    204: #endif
                    205:
                    206:        if (!app_passwd(bio_err, passargin, passargout, &passin, &passout)) {
                    207:                BIO_printf(bio_err, "Error getting passwords\n");
                    208:                goto end;
                    209:        }
                    210:        if ((pbe_nid == -1) && !cipher)
                    211:                pbe_nid = NID_pbeWithMD5AndDES_CBC;
                    212:
                    213:        if (infile) {
                    214:                if (!(in = BIO_new_file(infile, "rb"))) {
                    215:                        BIO_printf(bio_err,
                    216:                            "Can't open input file %s\n", infile);
                    217:                        goto end;
                    218:                }
                    219:        } else
                    220:                in = BIO_new_fp(stdin, BIO_NOCLOSE);
                    221:
                    222:        if (outfile) {
                    223:                if (!(out = BIO_new_file(outfile, "wb"))) {
                    224:                        BIO_printf(bio_err,
                    225:                            "Can't open output file %s\n", outfile);
                    226:                        goto end;
                    227:                }
                    228:        } else {
                    229:                out = BIO_new_fp(stdout, BIO_NOCLOSE);
                    230:        }
                    231:        if (topk8) {
                    232:                pkey = load_key(bio_err, infile, informat, 1,
                    233:                    passin, e, "key");
                    234:                if (!pkey)
                    235:                        goto end;
                    236:                if (!(p8inf = EVP_PKEY2PKCS8_broken(pkey, p8_broken))) {
                    237:                        BIO_printf(bio_err, "Error converting key\n");
                    238:                        ERR_print_errors(bio_err);
                    239:                        goto end;
                    240:                }
                    241:                if (nocrypt) {
                    242:                        if (outformat == FORMAT_PEM)
                    243:                                PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8inf);
                    244:                        else if (outformat == FORMAT_ASN1)
                    245:                                i2d_PKCS8_PRIV_KEY_INFO_bio(out, p8inf);
                    246:                        else {
                    247:                                BIO_printf(bio_err, "Bad format specified for key\n");
                    248:                                goto end;
                    249:                        }
                    250:                } else {
                    251:                        if (passout)
                    252:                                p8pass = passout;
                    253:                        else {
                    254:                                p8pass = pass;
                    255:                                if (EVP_read_pw_string(pass, sizeof pass, "Enter Encryption Password:", 1))
                    256:                                        goto end;
                    257:                        }
                    258:                        if (!(p8 = PKCS8_encrypt(pbe_nid, cipher,
                    259:                                    p8pass, strlen(p8pass),
                    260:                                    NULL, 0, iter, p8inf))) {
                    261:                                BIO_printf(bio_err, "Error encrypting key\n");
                    262:                                ERR_print_errors(bio_err);
                    263:                                goto end;
                    264:                        }
                    265:                        if (outformat == FORMAT_PEM)
                    266:                                PEM_write_bio_PKCS8(out, p8);
                    267:                        else if (outformat == FORMAT_ASN1)
                    268:                                i2d_PKCS8_bio(out, p8);
                    269:                        else {
                    270:                                BIO_printf(bio_err, "Bad format specified for key\n");
                    271:                                goto end;
                    272:                        }
                    273:                }
                    274:
                    275:                ret = 0;
                    276:                goto end;
                    277:        }
                    278:        if (nocrypt) {
                    279:                if (informat == FORMAT_PEM)
                    280:                        p8inf = PEM_read_bio_PKCS8_PRIV_KEY_INFO(in, NULL, NULL, NULL);
                    281:                else if (informat == FORMAT_ASN1)
                    282:                        p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(in, NULL);
                    283:                else {
                    284:                        BIO_printf(bio_err, "Bad format specified for key\n");
                    285:                        goto end;
                    286:                }
                    287:        } else {
                    288:                if (informat == FORMAT_PEM)
                    289:                        p8 = PEM_read_bio_PKCS8(in, NULL, NULL, NULL);
                    290:                else if (informat == FORMAT_ASN1)
                    291:                        p8 = d2i_PKCS8_bio(in, NULL);
                    292:                else {
                    293:                        BIO_printf(bio_err, "Bad format specified for key\n");
                    294:                        goto end;
                    295:                }
                    296:
                    297:                if (!p8) {
                    298:                        BIO_printf(bio_err, "Error reading key\n");
                    299:                        ERR_print_errors(bio_err);
                    300:                        goto end;
                    301:                }
                    302:                if (passin)
                    303:                        p8pass = passin;
                    304:                else {
                    305:                        p8pass = pass;
                    306:                        EVP_read_pw_string(pass, sizeof pass, "Enter Password:", 0);
                    307:                }
                    308:                p8inf = PKCS8_decrypt(p8, p8pass, strlen(p8pass));
                    309:        }
                    310:
                    311:        if (!p8inf) {
                    312:                BIO_printf(bio_err, "Error decrypting key\n");
                    313:                ERR_print_errors(bio_err);
                    314:                goto end;
                    315:        }
                    316:        if (!(pkey = EVP_PKCS82PKEY(p8inf))) {
                    317:                BIO_printf(bio_err, "Error converting key\n");
                    318:                ERR_print_errors(bio_err);
                    319:                goto end;
                    320:        }
                    321:        if (p8inf->broken) {
                    322:                BIO_printf(bio_err, "Warning: broken key encoding: ");
                    323:                switch (p8inf->broken) {
                    324:                case PKCS8_NO_OCTET:
                    325:                        BIO_printf(bio_err, "No Octet String in PrivateKey\n");
                    326:                        break;
                    327:
                    328:                case PKCS8_EMBEDDED_PARAM:
                    329:                        BIO_printf(bio_err, "DSA parameters included in PrivateKey\n");
                    330:                        break;
                    331:
                    332:                case PKCS8_NS_DB:
                    333:                        BIO_printf(bio_err, "DSA public key include in PrivateKey\n");
                    334:                        break;
                    335:
                    336:                case PKCS8_NEG_PRIVKEY:
                    337:                        BIO_printf(bio_err, "DSA private key value is negative\n");
                    338:                        break;
                    339:
                    340:                default:
                    341:                        BIO_printf(bio_err, "Unknown broken type\n");
                    342:                        break;
                    343:                }
                    344:        }
                    345:        if (outformat == FORMAT_PEM)
                    346:                PEM_write_bio_PrivateKey(out, pkey, NULL, NULL, 0, NULL, passout);
                    347:        else if (outformat == FORMAT_ASN1)
                    348:                i2d_PrivateKey_bio(out, pkey);
                    349:        else {
                    350:                BIO_printf(bio_err, "Bad format specified for key\n");
                    351:                goto end;
                    352:        }
                    353:        ret = 0;
                    354:
                    355: end:
                    356:        X509_SIG_free(p8);
                    357:        PKCS8_PRIV_KEY_INFO_free(p8inf);
                    358:        EVP_PKEY_free(pkey);
                    359:        BIO_free_all(out);
                    360:        BIO_free(in);
                    361:        free(passin);
                    362:        free(passout);
                    363:
                    364:        return ret;
                    365: }