1 /* 2 * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include <string.h> 11 12 #include "apps.h" 13 #include "progs.h" 14 #include <openssl/bio.h> 15 #include <openssl/err.h> 16 #include <openssl/evp.h> 17 #include <openssl/kdf.h> 18 #include <openssl/params.h> 19 20 typedef enum OPTION_choice { 21 OPT_COMMON, 22 OPT_KDFOPT, OPT_BIN, OPT_KEYLEN, OPT_OUT, 23 OPT_CIPHER, OPT_DIGEST, OPT_MAC, 24 OPT_PROV_ENUM 25 } OPTION_CHOICE; 26 27 const OPTIONS kdf_options[] = { 28 {OPT_HELP_STR, 1, '-', "Usage: %s [options] kdf_name\n"}, 29 30 OPT_SECTION("General"), 31 {"help", OPT_HELP, '-', "Display this summary"}, 32 {"kdfopt", OPT_KDFOPT, 's', "KDF algorithm control parameters in n:v form"}, 33 {"cipher", OPT_CIPHER, 's', "Cipher"}, 34 {"digest", OPT_DIGEST, 's', "Digest"}, 35 {"mac", OPT_MAC, 's', "MAC"}, 36 {OPT_MORE_STR, 1, '-', "See 'Supported Controls' in the EVP_KDF_ docs\n"}, 37 {"keylen", OPT_KEYLEN, 's', "The size of the output derived key"}, 38 39 OPT_SECTION("Output"), 40 {"out", OPT_OUT, '>', "Output to filename rather than stdout"}, 41 {"binary", OPT_BIN, '-', 42 "Output in binary format (default is hexadecimal)"}, 43 44 OPT_PROV_OPTIONS, 45 46 OPT_PARAMETERS(), 47 {"kdf_name", 0, 0, "Name of the KDF algorithm"}, 48 {NULL} 49 }; 50 51 static char *alloc_kdf_algorithm_name(STACK_OF(OPENSSL_STRING) **optp, 52 const char *name, const char *arg) 53 { 54 size_t len = strlen(name) + strlen(arg) + 2; 55 char *res; 56 57 if (*optp == NULL) 58 *optp = sk_OPENSSL_STRING_new_null(); 59 if (*optp == NULL) 60 return NULL; 61 62 res = app_malloc(len, "algorithm name"); 63 BIO_snprintf(res, len, "%s:%s", name, arg); 64 if (sk_OPENSSL_STRING_push(*optp, res)) 65 return res; 66 OPENSSL_free(res); 67 return NULL; 68 } 69 70 int kdf_main(int argc, char **argv) 71 { 72 int ret = 1, out_bin = 0; 73 OPTION_CHOICE o; 74 STACK_OF(OPENSSL_STRING) *opts = NULL; 75 char *prog, *hexout = NULL; 76 const char *outfile = NULL; 77 unsigned char *dkm_bytes = NULL; 78 size_t dkm_len = 0; 79 BIO *out = NULL; 80 EVP_KDF *kdf = NULL; 81 EVP_KDF_CTX *ctx = NULL; 82 char *digest = NULL, *cipher = NULL, *mac = NULL; 83 84 prog = opt_init(argc, argv, kdf_options); 85 while ((o = opt_next()) != OPT_EOF) { 86 switch (o) { 87 default: 88 opthelp: 89 BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 90 goto err; 91 case OPT_HELP: 92 opt_help(kdf_options); 93 ret = 0; 94 goto err; 95 case OPT_BIN: 96 out_bin = 1; 97 break; 98 case OPT_KEYLEN: 99 dkm_len = (size_t)atoi(opt_arg()); 100 break; 101 case OPT_OUT: 102 outfile = opt_arg(); 103 break; 104 case OPT_KDFOPT: 105 if (opts == NULL) 106 opts = sk_OPENSSL_STRING_new_null(); 107 if (opts == NULL || !sk_OPENSSL_STRING_push(opts, opt_arg())) 108 goto opthelp; 109 break; 110 case OPT_CIPHER: 111 OPENSSL_free(cipher); 112 cipher = alloc_kdf_algorithm_name(&opts, "cipher", opt_arg()); 113 if (cipher == NULL) 114 goto opthelp; 115 break; 116 case OPT_DIGEST: 117 OPENSSL_free(digest); 118 digest = alloc_kdf_algorithm_name(&opts, "digest", opt_arg()); 119 if (digest == NULL) 120 goto opthelp; 121 break; 122 case OPT_MAC: 123 OPENSSL_free(mac); 124 mac = alloc_kdf_algorithm_name(&opts, "mac", opt_arg()); 125 if (mac == NULL) 126 goto opthelp; 127 break; 128 case OPT_PROV_CASES: 129 if (!opt_provider(o)) 130 goto err; 131 break; 132 } 133 } 134 135 /* One argument, the KDF name. */ 136 argc = opt_num_rest(); 137 argv = opt_rest(); 138 if (argc != 1) 139 goto opthelp; 140 141 if ((kdf = EVP_KDF_fetch(app_get0_libctx(), argv[0], 142 app_get0_propq())) == NULL) { 143 BIO_printf(bio_err, "Invalid KDF name %s\n", argv[0]); 144 goto opthelp; 145 } 146 147 ctx = EVP_KDF_CTX_new(kdf); 148 if (ctx == NULL) 149 goto err; 150 151 if (opts != NULL) { 152 int ok = 1; 153 OSSL_PARAM *params = 154 app_params_new_from_opts(opts, EVP_KDF_settable_ctx_params(kdf)); 155 156 if (params == NULL) 157 goto err; 158 159 if (!EVP_KDF_CTX_set_params(ctx, params)) { 160 BIO_printf(bio_err, "KDF parameter error\n"); 161 ERR_print_errors(bio_err); 162 ok = 0; 163 } 164 app_params_free(params); 165 if (!ok) 166 goto err; 167 } 168 169 out = bio_open_default(outfile, 'w', out_bin ? FORMAT_BINARY : FORMAT_TEXT); 170 if (out == NULL) 171 goto err; 172 173 if (dkm_len <= 0) { 174 BIO_printf(bio_err, "Invalid derived key length.\n"); 175 goto err; 176 } 177 dkm_bytes = app_malloc(dkm_len, "out buffer"); 178 if (dkm_bytes == NULL) 179 goto err; 180 181 if (!EVP_KDF_derive(ctx, dkm_bytes, dkm_len, NULL)) { 182 BIO_printf(bio_err, "EVP_KDF_derive failed\n"); 183 goto err; 184 } 185 186 if (out_bin) { 187 BIO_write(out, dkm_bytes, dkm_len); 188 } else { 189 hexout = OPENSSL_buf2hexstr(dkm_bytes, dkm_len); 190 if (hexout == NULL) { 191 BIO_printf(bio_err, "Memory allocation failure\n"); 192 goto err; 193 } 194 BIO_printf(out, "%s\n\n", hexout); 195 } 196 197 ret = 0; 198 err: 199 if (ret != 0) 200 ERR_print_errors(bio_err); 201 OPENSSL_clear_free(dkm_bytes, dkm_len); 202 sk_OPENSSL_STRING_free(opts); 203 EVP_KDF_free(kdf); 204 EVP_KDF_CTX_free(ctx); 205 BIO_free(out); 206 OPENSSL_free(hexout); 207 OPENSSL_free(cipher); 208 OPENSSL_free(digest); 209 OPENSSL_free(mac); 210 return ret; 211 } 212