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