-/* $OpenBSD: genpkey.c,v 1.11 2018/02/07 05:47:55 jsing Exp $ */
+/* $OpenBSD: genpkey.c,v 1.12 2018/02/08 11:17:44 jsing Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2006
*/
#include <openssl/evp.h>
#include <openssl/pem.h>
-static int
-init_keygen_file(BIO * err, EVP_PKEY_CTX ** pctx, const char *file);
+static int init_keygen_file(BIO * err, EVP_PKEY_CTX **pctx, const char *file);
static int genpkey_cb(EVP_PKEY_CTX * ctx);
+struct {
+ const EVP_CIPHER *cipher;
+ EVP_PKEY_CTX **ctx;
+ int do_param;
+ char *outfile;
+ int outformat;
+ char *passarg;
+ int text;
+} genpkey_config;
+
+static int
+genpkey_opt_algorithm(char *arg)
+{
+ if (!init_gen_str(bio_err, genpkey_config.ctx, arg,
+ genpkey_config.do_param))
+ return (1);
+
+ return (0);
+}
+
+static int
+genpkey_opt_cipher(int argc, char **argv, int *argsused)
+{
+ char *name = argv[0];
+
+ if (*name++ != '-')
+ return (1);
+
+ if (genpkey_config.do_param == 1)
+ return (1);
+
+ if (strcmp(name, "none") == 0) {
+ genpkey_config.cipher = NULL;
+ *argsused = 1;
+ return (0);
+ }
+
+ if ((genpkey_config.cipher = EVP_get_cipherbyname(name)) != NULL) {
+ *argsused = 1;
+ return (0);
+ }
+
+ return (1);
+}
+
+static int
+genpkey_opt_paramfile(char *arg)
+{
+ if (genpkey_config.do_param == 1)
+ return (1);
+ if (!init_keygen_file(bio_err, genpkey_config.ctx, arg))
+ return (1);
+
+ return (0);
+}
+
+static int
+genpkey_opt_pkeyopt(char *arg)
+{
+ if (*genpkey_config.ctx == NULL) {
+ BIO_puts(bio_err, "No keytype specified\n");
+ return (1);
+ }
+
+ if (pkey_ctrl_string(*genpkey_config.ctx, arg) <= 0) {
+ BIO_puts(bio_err, "parameter setting error\n");
+ ERR_print_errors(bio_err);
+ return (1);
+ }
+
+ return (0);
+}
+
+struct option genpkey_options[] = {
+ {
+ .name = "algorithm",
+ .argname = "name",
+ .desc = "Public key algorithm to use (must precede -pkeyopt)",
+ .type = OPTION_ARG_FUNC,
+ .opt.argfunc = genpkey_opt_algorithm,
+ },
+ {
+ .name = "genparam",
+ .desc = "Generate a set of parameters instead of a private key",
+ .type = OPTION_FLAG,
+ .opt.flag = &genpkey_config.do_param,
+ },
+ {
+ .name = "out",
+ .argname = "file",
+ .desc = "Output file to write to (default stdout)",
+ .type = OPTION_ARG,
+ .opt.arg = &genpkey_config.outfile,
+ },
+ {
+ .name = "outform",
+ .argname = "format",
+ .desc = "Output format (DER or PEM)",
+ .type = OPTION_ARG_FORMAT,
+ .opt.value = &genpkey_config.outformat,
+ },
+ {
+ .name = "paramfile",
+ .argname = "file",
+ .desc = "File to load public key algorithm parameters from\n"
+ "(must precede -pkeyopt)",
+ .type = OPTION_ARG_FUNC,
+ .opt.argfunc = genpkey_opt_paramfile,
+ },
+ {
+ .name = "pass",
+ .argname = "arg",
+ .desc = "Output file password source",
+ .type = OPTION_ARG,
+ .opt.arg = &genpkey_config.passarg,
+ },
+ {
+ .name = "pkeyopt",
+ .argname = "opt:value",
+ .desc = "Set public key algorithm option to the given value",
+ .type = OPTION_ARG_FUNC,
+ .opt.argfunc = genpkey_opt_pkeyopt,
+ },
+ {
+ .name = "text",
+ .desc = "Print the private/public key in human readable form",
+ .type = OPTION_FLAG,
+ .opt.flag = &genpkey_config.text,
+ },
+ {
+ .name = NULL,
+ .type = OPTION_ARGV_FUNC,
+ .opt.argvfunc = genpkey_opt_cipher,
+ },
+ {NULL},
+};
+
+static void
+genpkey_usage()
+{
+ fprintf(stderr,
+ "usage: genpkey [-algorithm alg] [cipher] [-genparam] [-out file]\n"
+ " [-outform der | pem] [-paramfile file] [-pass arg]\n"
+ " [-pkeyopt opt:value] [-text]\n\n");
+ options_usage(genpkey_options);
+}
+
int
genpkey_main(int argc, char **argv)
{
- char **args, *outfile = NULL;
- char *passarg = NULL;
BIO *in = NULL, *out = NULL;
- const EVP_CIPHER *cipher = NULL;
- int outformat;
- int text = 0;
- EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *ctx = NULL;
+ EVP_PKEY *pkey = NULL;
char *pass = NULL;
- int badarg = 0;
int ret = 1, rv;
- int do_param = 0;
-
if (single_execution) {
if (pledge("stdio cpath wpath rpath tty", NULL) == -1) {
perror("pledge");
}
}
- outformat = FORMAT_PEM;
-
- args = argv + 1;
- while (!badarg && *args && *args[0] == '-') {
- if (!strcmp(*args, "-outform")) {
- if (args[1]) {
- args++;
- outformat = str2fmt(*args);
- } else
- badarg = 1;
- } else if (!strcmp(*args, "-pass")) {
- if (!args[1])
- goto bad;
- passarg = *(++args);
- }
- else if (!strcmp(*args, "-paramfile")) {
- if (!args[1])
- goto bad;
- args++;
- if (do_param == 1)
- goto bad;
- if (!init_keygen_file(bio_err, &ctx, *args))
- goto end;
- } else if (!strcmp(*args, "-out")) {
- if (args[1]) {
- args++;
- outfile = *args;
- } else
- badarg = 1;
- } else if (strcmp(*args, "-algorithm") == 0) {
- if (!args[1])
- goto bad;
- if (!init_gen_str(bio_err, &ctx, *(++args), do_param))
- goto end;
- } else if (strcmp(*args, "-pkeyopt") == 0) {
- if (!args[1])
- goto bad;
- if (!ctx) {
- BIO_puts(bio_err, "No keytype specified\n");
- goto bad;
- } else if (pkey_ctrl_string(ctx, *(++args)) <= 0) {
- BIO_puts(bio_err, "parameter setting error\n");
- ERR_print_errors(bio_err);
- goto end;
- }
- } else if (strcmp(*args, "-genparam") == 0) {
- if (ctx)
- goto bad;
- do_param = 1;
- } else if (strcmp(*args, "-text") == 0)
- text = 1;
- else {
- cipher = EVP_get_cipherbyname(*args + 1);
- if (!cipher) {
- BIO_printf(bio_err, "Unknown cipher %s\n",
- *args + 1);
- badarg = 1;
- }
- if (do_param == 1)
- badarg = 1;
- }
- args++;
+ memset(&genpkey_config, 0, sizeof(genpkey_config));
+ genpkey_config.ctx = &ctx;
+ genpkey_config.outformat = FORMAT_PEM;
+
+ if (options_parse(argc, argv, genpkey_options, NULL, NULL) != 0) {
+ genpkey_usage();
+ goto end;
}
- if (!ctx)
- badarg = 1;
-
- if (badarg) {
- bad:
- BIO_printf(bio_err, "Usage: genpkey [options]\n");
- BIO_printf(bio_err, "where options may be\n");
- BIO_printf(bio_err, "-out file output file\n");
- BIO_printf(bio_err, "-outform X output format (DER or PEM)\n");
- BIO_printf(bio_err, "-pass arg output file pass phrase source\n");
- BIO_printf(bio_err, "-<cipher> use cipher <cipher> to encrypt the key\n");
- BIO_printf(bio_err, "-paramfile file parameters file\n");
- BIO_printf(bio_err, "-algorithm alg the public key algorithm\n");
- BIO_printf(bio_err, "-pkeyopt opt:value set the public key algorithm option <opt>\n"
- " to value <value>\n");
- BIO_printf(bio_err, "-genparam generate parameters, not key\n");
- BIO_printf(bio_err, "-text print the in text\n");
- BIO_printf(bio_err, "NB: options order may be important! See the manual page.\n");
+ if (ctx == NULL) {
+ genpkey_usage();
goto end;
}
- if (!app_passwd(bio_err, passarg, NULL, &pass, NULL)) {
+
+ if (!app_passwd(bio_err, genpkey_config.passarg, NULL, &pass, NULL)) {
BIO_puts(bio_err, "Error getting password\n");
goto end;
}
- if (outfile) {
- if (!(out = BIO_new_file(outfile, "wb"))) {
- BIO_printf(bio_err,
- "Can't open output file %s\n", outfile);
+ if (genpkey_config.outfile != NULL) {
+ if ((out = BIO_new_file(genpkey_config.outfile, "wb")) ==
+ NULL) {
+ BIO_printf(bio_err, "Can't open output file %s\n",
+ genpkey_config.outfile);
goto end;
}
} else {
EVP_PKEY_CTX_set_cb(ctx, genpkey_cb);
EVP_PKEY_CTX_set_app_data(ctx, bio_err);
- if (do_param) {
+ if (genpkey_config.do_param) {
if (EVP_PKEY_paramgen(ctx, &pkey) <= 0) {
BIO_puts(bio_err, "Error generating parameters\n");
ERR_print_errors(bio_err);
}
}
- if (do_param)
+ if (genpkey_config.do_param)
rv = PEM_write_bio_Parameters(out, pkey);
- else if (outformat == FORMAT_PEM)
- rv = PEM_write_bio_PrivateKey(out, pkey, cipher, NULL, 0,
- NULL, pass);
- else if (outformat == FORMAT_ASN1)
+ else if (genpkey_config.outformat == FORMAT_PEM)
+ rv = PEM_write_bio_PrivateKey(out, pkey, genpkey_config.cipher,
+ NULL, 0, NULL, pass);
+ else if (genpkey_config.outformat == FORMAT_ASN1)
rv = i2d_PrivateKey_bio(out, pkey);
else {
BIO_printf(bio_err, "Bad format specified for key\n");
BIO_puts(bio_err, "Error writing key\n");
ERR_print_errors(bio_err);
}
- if (text) {
- if (do_param)
+ if (genpkey_config.text) {
+ if (genpkey_config.do_param)
rv = EVP_PKEY_print_params(out, pkey, 0, NULL);
else
rv = EVP_PKEY_print_private(out, pkey, 0, NULL);
}
static int
-init_keygen_file(BIO * err, EVP_PKEY_CTX ** pctx,
- const char *file)
+init_keygen_file(BIO * err, EVP_PKEY_CTX ** pctx, const char *file)
{
BIO *pbio;
EVP_PKEY *pkey = NULL;
}
int
-init_gen_str(BIO * err, EVP_PKEY_CTX ** pctx,
- const char *algname, int do_param)
+init_gen_str(BIO * err, EVP_PKEY_CTX ** pctx, const char *algname, int do_param)
{
- EVP_PKEY_CTX *ctx = NULL;
const EVP_PKEY_ASN1_METHOD *ameth;
+ EVP_PKEY_CTX *ctx = NULL;
int pkey_id;
if (*pctx) {