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