kdf.c revision 1.1.1.2 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