diff options
author | Shane Lontis <shane.lontis@oracle.com> | 2019-04-16 12:10:04 +0200 |
---|---|---|
committer | Richard Levitte <levitte@openssl.org> | 2019-04-24 11:56:47 +0200 |
commit | c54492ecf8331fd87f6ac163f9fc5b576af128e8 (patch) | |
tree | 8feaa7436bd5868c0708bcb43c96ee1f9235675e /apps/kdf.c | |
parent | Recognise clang -fsanitize options and translate them (diff) | |
download | openssl-c54492ecf8331fd87f6ac163f9fc5b576af128e8.tar.xz openssl-c54492ecf8331fd87f6ac163f9fc5b576af128e8.zip |
Added app for EVP_KDF
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/8762)
Diffstat (limited to 'apps/kdf.c')
-rw-r--r-- | apps/kdf.c | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/apps/kdf.c b/apps/kdf.c new file mode 100644 index 0000000000..684fd44cc0 --- /dev/null +++ b/apps/kdf.c @@ -0,0 +1,158 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <string.h> + +#include "apps.h" +#include "progs.h" +#include <openssl/bio.h> +#include <openssl/err.h> +#include <openssl/evp.h> +#include <openssl/kdf.h> + +typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_KDFOPT, OPT_BIN, OPT_KEYLEN, OPT_OUT +} OPTION_CHOICE; + +const OPTIONS kdf_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] kdf_name\n"}, + {OPT_HELP_STR, 1, '-', "kdf_name\t KDF algorithm.\n"}, + {"help", OPT_HELP, '-', "Display this summary"}, + {"kdfopt", OPT_KDFOPT, 's', "KDF algorithm control parameters in n:v form. " + "See 'Supported Controls' in the EVP_KDF_ docs"}, + {"keylen", OPT_KEYLEN, 's', "The size of the output derived key"}, + {"out", OPT_OUT, '>', "Output to filename rather than stdout"}, + {"binary", OPT_BIN, '-', "Output in binary format (Default is hexadecimal " + "output)"}, + {NULL} +}; + +static int kdf_ctrl_string(EVP_KDF_CTX *ctx, const char *value) +{ + int rv; + char *stmp, *vtmp = NULL; + + stmp = OPENSSL_strdup(value); + if (stmp == NULL) + return -1; + vtmp = strchr(stmp, ':'); + if (vtmp != NULL) { + *vtmp = 0; + vtmp++; + } + rv = EVP_KDF_ctrl_str(ctx, stmp, vtmp); + OPENSSL_free(stmp); + return rv; +} + +int kdf_main(int argc, char **argv) +{ + int ret = 1, i, id, out_bin = 0; + OPTION_CHOICE o; + STACK_OF(OPENSSL_STRING) *opts = NULL; + char *prog, *hexout = NULL; + const char *outfile = NULL; + unsigned char *dkm_bytes = NULL; + size_t dkm_len = 0; + BIO *out = NULL; + EVP_KDF_CTX *ctx = NULL; + + prog = opt_init(argc, argv, kdf_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + default: +opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto err; + case OPT_HELP: + opt_help(kdf_options); + ret = 0; + goto err; + case OPT_BIN: + out_bin = 1; + break; + case OPT_KEYLEN: + dkm_len = (size_t)atoi(opt_arg()); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_KDFOPT: + if (opts == NULL) + opts = sk_OPENSSL_STRING_new_null(); + if (opts == NULL || !sk_OPENSSL_STRING_push(opts, opt_arg())) + goto opthelp; + break; + } + } + argc = opt_num_rest(); + argv = opt_rest(); + + if (argc != 1) { + BIO_printf(bio_err, "Invalid number of extra arguments\n"); + goto opthelp; + } + + id = OBJ_sn2nid(argv[0]); + if (id == NID_undef) { + BIO_printf(bio_err, "Invalid KDF name %s\n", argv[0]); + goto opthelp; + } + + ctx = EVP_KDF_CTX_new_id(id); + if (ctx == NULL) + goto err; + + if (opts != NULL) { + for (i = 0; i < sk_OPENSSL_STRING_num(opts); i++) { + char *opt = sk_OPENSSL_STRING_value(opts, i); + if (kdf_ctrl_string(ctx, opt) <= 0) { + BIO_printf(bio_err, "KDF parameter error '%s'\n", opt); + ERR_print_errors(bio_err); + goto err; + } + } + } + + out = bio_open_default(outfile, 'w', out_bin ? FORMAT_BINARY : FORMAT_TEXT); + if (out == NULL) + goto err; + + if (dkm_len <= 0) { + BIO_printf(bio_err, "Invalid derived key length.\n"); + goto err; + } + dkm_bytes = app_malloc(dkm_len, "out buffer"); + if (dkm_bytes == NULL) + goto err; + + if (!EVP_KDF_derive(ctx, dkm_bytes, dkm_len)) { + BIO_printf(bio_err, "EVP_KDF_derive failed\n"); + goto err; + } + + if (out_bin) { + BIO_write(out, dkm_bytes, dkm_len); + } else { + hexout = OPENSSL_buf2hexstr(dkm_bytes, dkm_len); + BIO_printf(out, "%s\n\n", hexout); + } + + ret = 0; +err: + if (ret != 0) + ERR_print_errors(bio_err); + OPENSSL_clear_free(dkm_bytes, dkm_len); + sk_OPENSSL_STRING_free(opts); + EVP_KDF_CTX_free(ctx); + BIO_free(out); + OPENSSL_free(hexout); + return ret; +} |