]>
Commit | Line | Data |
---|---|---|
c54492ec | 1 | /* |
33388b44 | 2 | * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved. |
c54492ec | 3 | * |
a6ed19dc | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
c54492ec SL |
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> | |
55accfd2 | 18 | #include <openssl/params.h> |
c54492ec | 19 | |
852c2ed2 RS |
20 | DEFINE_STACK_OF_STRING() |
21 | ||
c54492ec SL |
22 | typedef enum OPTION_choice { |
23 | OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, | |
6bd4e3f2 P |
24 | OPT_KDFOPT, OPT_BIN, OPT_KEYLEN, OPT_OUT, |
25 | OPT_PROV_ENUM | |
c54492ec SL |
26 | } OPTION_CHOICE; |
27 | ||
28 | const OPTIONS kdf_options[] = { | |
29 | {OPT_HELP_STR, 1, '-', "Usage: %s [options] kdf_name\n"}, | |
5388f986 RS |
30 | |
31 | OPT_SECTION("General"), | |
c54492ec | 32 | {"help", OPT_HELP, '-', "Display this summary"}, |
92de469f RS |
33 | {"kdfopt", OPT_KDFOPT, 's', "KDF algorithm control parameters in n:v form"}, |
34 | {OPT_MORE_STR, 1, '-', "See 'Supported Controls' in the EVP_KDF_ docs\n"}, | |
c54492ec | 35 | {"keylen", OPT_KEYLEN, 's', "The size of the output derived key"}, |
5388f986 RS |
36 | |
37 | OPT_SECTION("Output"), | |
c54492ec | 38 | {"out", OPT_OUT, '>', "Output to filename rather than stdout"}, |
92de469f RS |
39 | {"binary", OPT_BIN, '-', |
40 | "Output in binary format (default is hexadecimal)"}, | |
41 | ||
6bd4e3f2 P |
42 | OPT_PROV_OPTIONS, |
43 | ||
92de469f RS |
44 | OPT_PARAMETERS(), |
45 | {"kdf_name", 0, 0, "Name of the KDF algorithm"}, | |
c54492ec SL |
46 | {NULL} |
47 | }; | |
48 | ||
c54492ec SL |
49 | int kdf_main(int argc, char **argv) |
50 | { | |
55accfd2 | 51 | int ret = 1, out_bin = 0; |
c54492ec SL |
52 | OPTION_CHOICE o; |
53 | STACK_OF(OPENSSL_STRING) *opts = NULL; | |
54 | char *prog, *hexout = NULL; | |
55 | const char *outfile = NULL; | |
56 | unsigned char *dkm_bytes = NULL; | |
57 | size_t dkm_len = 0; | |
58 | BIO *out = NULL; | |
55accfd2 | 59 | EVP_KDF *kdf = NULL; |
c54492ec SL |
60 | EVP_KDF_CTX *ctx = NULL; |
61 | ||
62 | prog = opt_init(argc, argv, kdf_options); | |
63 | while ((o = opt_next()) != OPT_EOF) { | |
64 | switch (o) { | |
65 | default: | |
66 | opthelp: | |
67 | BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); | |
68 | goto err; | |
69 | case OPT_HELP: | |
70 | opt_help(kdf_options); | |
71 | ret = 0; | |
72 | goto err; | |
73 | case OPT_BIN: | |
74 | out_bin = 1; | |
75 | break; | |
76 | case OPT_KEYLEN: | |
77 | dkm_len = (size_t)atoi(opt_arg()); | |
78 | break; | |
79 | case OPT_OUT: | |
80 | outfile = opt_arg(); | |
81 | break; | |
82 | case OPT_KDFOPT: | |
83 | if (opts == NULL) | |
84 | opts = sk_OPENSSL_STRING_new_null(); | |
85 | if (opts == NULL || !sk_OPENSSL_STRING_push(opts, opt_arg())) | |
86 | goto opthelp; | |
87 | break; | |
6bd4e3f2 P |
88 | case OPT_PROV_CASES: |
89 | if (!opt_provider(o)) | |
90 | goto err; | |
91 | break; | |
c54492ec SL |
92 | } |
93 | } | |
94 | argc = opt_num_rest(); | |
95 | argv = opt_rest(); | |
96 | ||
97 | if (argc != 1) { | |
98 | BIO_printf(bio_err, "Invalid number of extra arguments\n"); | |
99 | goto opthelp; | |
100 | } | |
101 | ||
55accfd2 | 102 | if ((kdf = EVP_KDF_fetch(NULL, argv[0], NULL)) == NULL) { |
c54492ec SL |
103 | BIO_printf(bio_err, "Invalid KDF name %s\n", argv[0]); |
104 | goto opthelp; | |
105 | } | |
106 | ||
55accfd2 | 107 | ctx = EVP_KDF_CTX_new(kdf); |
c54492ec SL |
108 | if (ctx == NULL) |
109 | goto err; | |
110 | ||
111 | if (opts != NULL) { | |
55accfd2 P |
112 | int ok = 1; |
113 | OSSL_PARAM *params = | |
41f7ecf3 | 114 | app_params_new_from_opts(opts, EVP_KDF_settable_ctx_params(kdf)); |
55accfd2 P |
115 | |
116 | if (params == NULL) | |
117 | goto err; | |
118 | ||
119 | if (!EVP_KDF_CTX_set_params(ctx, params)) { | |
120 | BIO_printf(bio_err, "KDF parameter error\n"); | |
121 | ERR_print_errors(bio_err); | |
122 | ok = 0; | |
c54492ec | 123 | } |
55accfd2 P |
124 | app_params_free(params); |
125 | if (!ok) | |
126 | goto err; | |
c54492ec SL |
127 | } |
128 | ||
129 | out = bio_open_default(outfile, 'w', out_bin ? FORMAT_BINARY : FORMAT_TEXT); | |
130 | if (out == NULL) | |
131 | goto err; | |
132 | ||
133 | if (dkm_len <= 0) { | |
134 | BIO_printf(bio_err, "Invalid derived key length.\n"); | |
135 | goto err; | |
136 | } | |
137 | dkm_bytes = app_malloc(dkm_len, "out buffer"); | |
138 | if (dkm_bytes == NULL) | |
139 | goto err; | |
140 | ||
141 | if (!EVP_KDF_derive(ctx, dkm_bytes, dkm_len)) { | |
142 | BIO_printf(bio_err, "EVP_KDF_derive failed\n"); | |
143 | goto err; | |
144 | } | |
145 | ||
146 | if (out_bin) { | |
147 | BIO_write(out, dkm_bytes, dkm_len); | |
148 | } else { | |
149 | hexout = OPENSSL_buf2hexstr(dkm_bytes, dkm_len); | |
17197a2f MC |
150 | if (hexout == NULL) { |
151 | BIO_printf(bio_err, "Memory allocation failure\n"); | |
152 | goto err; | |
153 | } | |
c54492ec SL |
154 | BIO_printf(out, "%s\n\n", hexout); |
155 | } | |
156 | ||
157 | ret = 0; | |
158 | err: | |
159 | if (ret != 0) | |
160 | ERR_print_errors(bio_err); | |
161 | OPENSSL_clear_free(dkm_bytes, dkm_len); | |
162 | sk_OPENSSL_STRING_free(opts); | |
55accfd2 | 163 | EVP_KDF_free(kdf); |
c54492ec SL |
164 | EVP_KDF_CTX_free(ctx); |
165 | BIO_free(out); | |
166 | OPENSSL_free(hexout); | |
167 | return ret; | |
168 | } |