Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/openssl/apps/kdf.c
104134 views
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
218