=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/openssl/pkcs8.c,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- src/usr.bin/openssl/pkcs8.c 2014/08/28 14:25:48 1.3 +++ src/usr.bin/openssl/pkcs8.c 2015/01/08 11:06:12 1.4 @@ -1,4 +1,4 @@ -/* $OpenBSD: pkcs8.c,v 1.3 2014/08/28 14:25:48 jsing Exp $ */ +/* $OpenBSD: pkcs8.c,v 1.4 2015/01/08 11:06:12 doug Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 1999-2004. */ @@ -66,185 +66,241 @@ #include #include -int pkcs8_main(int, char **); +static struct { + const EVP_CIPHER *cipher; +#ifndef OPENSSL_NO_ENGINE + char *engine; +#endif + char *infile; + int informat; + int iter; + int nocrypt; + char *outfile; + int outformat; + int p8_broken; + char *passargin; + char *passargout; + int pbe_nid; + int topk8; +} pkcs8_config; +static int +pkcs8_opt_v1(char *arg) +{ + if ((pkcs8_config.pbe_nid = OBJ_txt2nid(arg)) == NID_undef) { + fprintf(stderr, "Unknown PBE algorithm '%s'\n", arg); + return (1); + } + + return (0); +} + +static int +pkcs8_opt_v2(char *arg) +{ + if ((pkcs8_config.cipher = EVP_get_cipherbyname(arg)) == NULL) { + fprintf(stderr, "Unknown cipher '%s'\n", arg); + return (1); + } + + return (0); +} + +static struct option pkcs8_options[] = { + { + .name = "embed", + .desc = "Generate DSA keys in a broken format", + .type = OPTION_VALUE, + .value = PKCS8_EMBEDDED_PARAM, + .opt.value = &pkcs8_config.p8_broken, + }, +#ifndef OPENSSL_NO_ENGINE + { + .name = "engine", + .argname = "id", + .desc = "Use the engine specified by the given identifier", + .type = OPTION_ARG, + .opt.arg = &pkcs8_config.engine, + }, +#endif + { + .name = "in", + .argname = "file", + .desc = "Input file (default stdin)", + .type = OPTION_ARG, + .opt.arg = &pkcs8_config.infile, + }, + { + .name = "inform", + .argname = "format", + .desc = "Input format (DER or PEM (default))", + .type = OPTION_ARG_FORMAT, + .opt.value = &pkcs8_config.informat, + }, + { + .name = "nocrypt", + .desc = "Use or expect unencrypted private key", + .type = OPTION_FLAG, + .opt.flag = &pkcs8_config.nocrypt, + }, + { + .name = "noiter", + .desc = "Use 1 as iteration count", + .type = OPTION_VALUE, + .value = 1, + .opt.value = &pkcs8_config.iter, + }, + { + .name = "nooct", + .desc = "Generate RSA keys in a broken format (no octet)", + .type = OPTION_VALUE, + .value = PKCS8_NO_OCTET, + .opt.value = &pkcs8_config.p8_broken, + }, + { + .name = "nsdb", + .desc = "Generate DSA keys in the broken Netscape DB format", + .type = OPTION_VALUE, + .value = PKCS8_NS_DB, + .opt.value = &pkcs8_config.p8_broken, + }, + { + .name = "out", + .argname = "file", + .desc = "Output file (default stdout)", + .type = OPTION_ARG, + .opt.arg = &pkcs8_config.outfile, + }, + { + .name = "outform", + .argname = "format", + .desc = "Output format (DER or PEM (default))", + .type = OPTION_ARG_FORMAT, + .opt.value = &pkcs8_config.outformat, + }, + { + .name = "passin", + .argname = "source", + .desc = "Input file passphrase source", + .type = OPTION_ARG, + .opt.arg = &pkcs8_config.passargin, + }, + { + .name = "passout", + .argname = "source", + .desc = "Output file passphrase source", + .type = OPTION_ARG, + .opt.arg = &pkcs8_config.passargout, + }, + { + .name = "topk8", + .desc = "Read traditional format key and write PKCS#8 format" + " key", + .type = OPTION_FLAG, + .opt.flag = &pkcs8_config.topk8, + }, + { + .name = "v1", + .argname = "algorithm", + .desc = "Use PKCS#5 v1.5 or PKCS#12 with given algorithm", + .type = OPTION_ARG_FUNC, + .opt.argfunc = pkcs8_opt_v1, + }, + { + .name = "v2", + .argname = "cipher", + .desc = "Use PKCS#5 v2.0 with given cipher", + .type = OPTION_ARG_FUNC, + .opt.argfunc = pkcs8_opt_v2, + }, + { NULL }, +}; + +static void +pkcs8_usage() +{ + fprintf(stderr, "usage: pkcs8 [-embed] [-engine id] [-in file] " + "[-inform fmt] [-nocrypt]\n" + " [-noiter] [-nooct] [-nsdb] [-out file] [-outform fmt] " + "[-passin src]\n" + " [-passout src] [-topk8] [-v1 alg] [-v2 alg]\n\n"); + options_usage(pkcs8_options); +} + int pkcs8_main(int argc, char **argv) { ENGINE *e = NULL; - char **args, *infile = NULL, *outfile = NULL; - char *passargin = NULL, *passargout = NULL; BIO *in = NULL, *out = NULL; - int topk8 = 0; - int pbe_nid = -1; - const EVP_CIPHER *cipher = NULL; - int iter = PKCS12_DEFAULT_ITER; - int informat, outformat; - int p8_broken = PKCS8_OK; - int nocrypt = 0; X509_SIG *p8 = NULL; PKCS8_PRIV_KEY_INFO *p8inf = NULL; EVP_PKEY *pkey = NULL; char pass[50], *passin = NULL, *passout = NULL, *p8pass = NULL; - int badarg = 0; int ret = 1; -#ifndef OPENSSL_NO_ENGINE - char *engine = NULL; -#endif - informat = FORMAT_PEM; - outformat = FORMAT_PEM; + memset(&pkcs8_config, 0, sizeof(pkcs8_config)); - args = argv + 1; - while (!badarg && *args && *args[0] == '-') { - if (!strcmp(*args, "-v2")) { - if (args[1]) { - args++; - cipher = EVP_get_cipherbyname(*args); - if (!cipher) { - BIO_printf(bio_err, - "Unknown cipher %s\n", *args); - badarg = 1; - } - } else - badarg = 1; - } else if (!strcmp(*args, "-v1")) { - if (args[1]) { - args++; - pbe_nid = OBJ_txt2nid(*args); - if (pbe_nid == NID_undef) { - BIO_printf(bio_err, - "Unknown PBE algorithm %s\n", *args); - badarg = 1; - } - } else - badarg = 1; - } else if (!strcmp(*args, "-inform")) { - if (args[1]) { - args++; - informat = str2fmt(*args); - } else - badarg = 1; - } else if (!strcmp(*args, "-outform")) { - if (args[1]) { - args++; - outformat = str2fmt(*args); - } else - badarg = 1; - } else if (!strcmp(*args, "-topk8")) - topk8 = 1; - else if (!strcmp(*args, "-noiter")) - iter = 1; - else if (!strcmp(*args, "-nocrypt")) - nocrypt = 1; - else if (!strcmp(*args, "-nooct")) - p8_broken = PKCS8_NO_OCTET; - else if (!strcmp(*args, "-nsdb")) - p8_broken = PKCS8_NS_DB; - else if (!strcmp(*args, "-embed")) - p8_broken = PKCS8_EMBEDDED_PARAM; - else if (!strcmp(*args, "-passin")) { - if (!args[1]) - goto bad; - passargin = *(++args); - } else if (!strcmp(*args, "-passout")) { - if (!args[1]) - goto bad; - passargout = *(++args); - } -#ifndef OPENSSL_NO_ENGINE - else if (strcmp(*args, "-engine") == 0) { - if (!args[1]) - goto bad; - engine = *(++args); - } -#endif - else if (!strcmp(*args, "-in")) { - if (args[1]) { - args++; - infile = *args; - } else - badarg = 1; - } else if (!strcmp(*args, "-out")) { - if (args[1]) { - args++; - outfile = *args; - } else - badarg = 1; - } else - badarg = 1; - args++; + pkcs8_config.iter = PKCS12_DEFAULT_ITER; + pkcs8_config.informat = FORMAT_PEM; + pkcs8_config.outformat = FORMAT_PEM; + pkcs8_config.p8_broken = PKCS8_OK; + pkcs8_config.pbe_nid = -1; + + if (options_parse(argc, argv, pkcs8_options, NULL, NULL) != 0) { + pkcs8_usage(); + return (1); } - if (badarg) { -bad: - BIO_printf(bio_err, "Usage pkcs8 [options]\n"); - BIO_printf(bio_err, "where options are\n"); - BIO_printf(bio_err, "-in file input file\n"); - BIO_printf(bio_err, "-inform X input format (DER or PEM)\n"); - BIO_printf(bio_err, "-passin arg input file pass phrase source\n"); - BIO_printf(bio_err, "-outform X output format (DER or PEM)\n"); - BIO_printf(bio_err, "-out file output file\n"); - BIO_printf(bio_err, "-passout arg output file pass phrase source\n"); - BIO_printf(bio_err, "-topk8 output PKCS8 file\n"); - BIO_printf(bio_err, "-nooct use (nonstandard) no octet format\n"); - BIO_printf(bio_err, "-embed use (nonstandard) embedded DSA parameters format\n"); - BIO_printf(bio_err, "-nsdb use (nonstandard) DSA Netscape DB format\n"); - BIO_printf(bio_err, "-noiter use 1 as iteration count\n"); - BIO_printf(bio_err, "-nocrypt use or expect unencrypted private key\n"); - BIO_printf(bio_err, "-v2 alg use PKCS#5 v2.0 and cipher \"alg\"\n"); - BIO_printf(bio_err, "-v1 obj use PKCS#5 v1.5 and cipher \"alg\"\n"); #ifndef OPENSSL_NO_ENGINE - BIO_printf(bio_err, " -engine e use engine e, possibly a hardware device.\n"); + e = setup_engine(bio_err, pkcs8_config.engine, 0); #endif - goto end; - } -#ifndef OPENSSL_NO_ENGINE - e = setup_engine(bio_err, engine, 0); -#endif - if (!app_passwd(bio_err, passargin, passargout, &passin, &passout)) { + if (!app_passwd(bio_err, pkcs8_config.passargin, + pkcs8_config.passargout, &passin, &passout)) { BIO_printf(bio_err, "Error getting passwords\n"); goto end; } - if ((pbe_nid == -1) && !cipher) - pbe_nid = NID_pbeWithMD5AndDES_CBC; + if ((pkcs8_config.pbe_nid == -1) && !pkcs8_config.cipher) + pkcs8_config.pbe_nid = NID_pbeWithMD5AndDES_CBC; - if (infile) { - if (!(in = BIO_new_file(infile, "rb"))) { + if (pkcs8_config.infile) { + if (!(in = BIO_new_file(pkcs8_config.infile, "rb"))) { BIO_printf(bio_err, - "Can't open input file %s\n", infile); + "Can't open input file '%s'\n", + pkcs8_config.infile); goto end; } } else in = BIO_new_fp(stdin, BIO_NOCLOSE); - if (outfile) { - if (!(out = BIO_new_file(outfile, "wb"))) { - BIO_printf(bio_err, - "Can't open output file %s\n", outfile); + if (pkcs8_config.outfile) { + if (!(out = BIO_new_file(pkcs8_config.outfile, "wb"))) { + BIO_printf(bio_err, "Can't open output file '%s'\n", + pkcs8_config.outfile); goto end; } } else { out = BIO_new_fp(stdout, BIO_NOCLOSE); } - if (topk8) { - pkey = load_key(bio_err, infile, informat, 1, - passin, e, "key"); + if (pkcs8_config.topk8) { + pkey = load_key(bio_err, pkcs8_config.infile, + pkcs8_config.informat, 1, passin, e, "key"); if (!pkey) goto end; - if (!(p8inf = EVP_PKEY2PKCS8_broken(pkey, p8_broken))) { + if (!(p8inf = EVP_PKEY2PKCS8_broken(pkey, + pkcs8_config.p8_broken))) { BIO_printf(bio_err, "Error converting key\n"); ERR_print_errors(bio_err); goto end; } - if (nocrypt) { - if (outformat == FORMAT_PEM) + if (pkcs8_config.nocrypt) { + if (pkcs8_config.outformat == FORMAT_PEM) PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8inf); - else if (outformat == FORMAT_ASN1) + else if (pkcs8_config.outformat == FORMAT_ASN1) i2d_PKCS8_PRIV_KEY_INFO_bio(out, p8inf); else { - BIO_printf(bio_err, "Bad format specified for key\n"); + BIO_printf(bio_err, + "Bad format specified for key\n"); goto end; } } else { @@ -252,22 +308,24 @@ p8pass = passout; else { p8pass = pass; - if (EVP_read_pw_string(pass, sizeof pass, "Enter Encryption Password:", 1)) + if (EVP_read_pw_string(pass, sizeof pass, + "Enter Encryption Password:", 1)) goto end; } - if (!(p8 = PKCS8_encrypt(pbe_nid, cipher, - p8pass, strlen(p8pass), - NULL, 0, iter, p8inf))) { + if (!(p8 = PKCS8_encrypt(pkcs8_config.pbe_nid, + pkcs8_config.cipher, p8pass, strlen(p8pass), + NULL, 0, pkcs8_config.iter, p8inf))) { BIO_printf(bio_err, "Error encrypting key\n"); ERR_print_errors(bio_err); goto end; } - if (outformat == FORMAT_PEM) + if (pkcs8_config.outformat == FORMAT_PEM) PEM_write_bio_PKCS8(out, p8); - else if (outformat == FORMAT_ASN1) + else if (pkcs8_config.outformat == FORMAT_ASN1) i2d_PKCS8_bio(out, p8); else { - BIO_printf(bio_err, "Bad format specified for key\n"); + BIO_printf(bio_err, + "Bad format specified for key\n"); goto end; } } @@ -275,19 +333,20 @@ ret = 0; goto end; } - if (nocrypt) { - if (informat == FORMAT_PEM) - p8inf = PEM_read_bio_PKCS8_PRIV_KEY_INFO(in, NULL, NULL, NULL); - else if (informat == FORMAT_ASN1) + if (pkcs8_config.nocrypt) { + if (pkcs8_config.informat == FORMAT_PEM) + p8inf = PEM_read_bio_PKCS8_PRIV_KEY_INFO(in, NULL, + NULL, NULL); + else if (pkcs8_config.informat == FORMAT_ASN1) p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(in, NULL); else { BIO_printf(bio_err, "Bad format specified for key\n"); goto end; } } else { - if (informat == FORMAT_PEM) + if (pkcs8_config.informat == FORMAT_PEM) p8 = PEM_read_bio_PKCS8(in, NULL, NULL, NULL); - else if (informat == FORMAT_ASN1) + else if (pkcs8_config.informat == FORMAT_ASN1) p8 = d2i_PKCS8_bio(in, NULL); else { BIO_printf(bio_err, "Bad format specified for key\n"); @@ -303,7 +362,8 @@ p8pass = passin; else { p8pass = pass; - EVP_read_pw_string(pass, sizeof pass, "Enter Password:", 0); + EVP_read_pw_string(pass, sizeof pass, + "Enter Password:", 0); } p8inf = PKCS8_decrypt(p8, p8pass, strlen(p8pass)); } @@ -326,11 +386,13 @@ break; case PKCS8_EMBEDDED_PARAM: - BIO_printf(bio_err, "DSA parameters included in PrivateKey\n"); + BIO_printf(bio_err, + "DSA parameters included in PrivateKey\n"); break; case PKCS8_NS_DB: - BIO_printf(bio_err, "DSA public key include in PrivateKey\n"); + BIO_printf(bio_err, + "DSA public key include in PrivateKey\n"); break; case PKCS8_NEG_PRIVKEY: @@ -342,9 +404,10 @@ break; } } - if (outformat == FORMAT_PEM) - PEM_write_bio_PrivateKey(out, pkey, NULL, NULL, 0, NULL, passout); - else if (outformat == FORMAT_ASN1) + if (pkcs8_config.outformat == FORMAT_PEM) + PEM_write_bio_PrivateKey(out, pkey, NULL, NULL, 0, NULL, + passout); + else if (pkcs8_config.outformat == FORMAT_ASN1) i2d_PrivateKey_bio(out, pkey); else { BIO_printf(bio_err, "Bad format specified for key\n");