1 | /*
|
---|
2 | * Copyright 1999-2022 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 <openssl/trace.h>
|
---|
11 | #include <stdlib.h>
|
---|
12 | #include <stdarg.h>
|
---|
13 | #include <string.h>
|
---|
14 | #include <openssl/evp.h>
|
---|
15 | #include <openssl/kdf.h>
|
---|
16 | #include <openssl/core_names.h>
|
---|
17 | #include <openssl/proverr.h>
|
---|
18 | #include "internal/cryptlib.h"
|
---|
19 | #include "internal/numbers.h"
|
---|
20 | #include "crypto/evp.h"
|
---|
21 | #include "prov/provider_ctx.h"
|
---|
22 | #include "prov/providercommon.h"
|
---|
23 | #include "prov/implementations.h"
|
---|
24 | #include "prov/provider_util.h"
|
---|
25 |
|
---|
26 | static OSSL_FUNC_kdf_newctx_fn kdf_pkcs12_new;
|
---|
27 | static OSSL_FUNC_kdf_dupctx_fn kdf_pkcs12_dup;
|
---|
28 | static OSSL_FUNC_kdf_freectx_fn kdf_pkcs12_free;
|
---|
29 | static OSSL_FUNC_kdf_reset_fn kdf_pkcs12_reset;
|
---|
30 | static OSSL_FUNC_kdf_derive_fn kdf_pkcs12_derive;
|
---|
31 | static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_pkcs12_settable_ctx_params;
|
---|
32 | static OSSL_FUNC_kdf_set_ctx_params_fn kdf_pkcs12_set_ctx_params;
|
---|
33 | static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_pkcs12_gettable_ctx_params;
|
---|
34 | static OSSL_FUNC_kdf_get_ctx_params_fn kdf_pkcs12_get_ctx_params;
|
---|
35 |
|
---|
36 | typedef struct {
|
---|
37 | void *provctx;
|
---|
38 | PROV_DIGEST digest;
|
---|
39 | unsigned char *pass;
|
---|
40 | size_t pass_len;
|
---|
41 | unsigned char *salt;
|
---|
42 | size_t salt_len;
|
---|
43 | uint64_t iter;
|
---|
44 | int id;
|
---|
45 | } KDF_PKCS12;
|
---|
46 |
|
---|
47 | /* PKCS12 compatible key/IV generation */
|
---|
48 |
|
---|
49 | static int pkcs12kdf_derive(const unsigned char *pass, size_t passlen,
|
---|
50 | const unsigned char *salt, size_t saltlen,
|
---|
51 | int id, uint64_t iter, const EVP_MD *md_type,
|
---|
52 | unsigned char *out, size_t n)
|
---|
53 | {
|
---|
54 | unsigned char *B = NULL, *D = NULL, *I = NULL, *p = NULL, *Ai = NULL;
|
---|
55 | size_t Slen, Plen, Ilen;
|
---|
56 | size_t i, j, k, u, v;
|
---|
57 | uint64_t iter_cnt;
|
---|
58 | int ret = 0, ui, vi;
|
---|
59 | EVP_MD_CTX *ctx = NULL;
|
---|
60 |
|
---|
61 | ctx = EVP_MD_CTX_new();
|
---|
62 | if (ctx == NULL) {
|
---|
63 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
---|
64 | goto end;
|
---|
65 | }
|
---|
66 | vi = EVP_MD_get_block_size(md_type);
|
---|
67 | ui = EVP_MD_get_size(md_type);
|
---|
68 | if (ui <= 0 || vi <= 0) {
|
---|
69 | ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_SIZE);
|
---|
70 | goto end;
|
---|
71 | }
|
---|
72 | u = (size_t)ui;
|
---|
73 | v = (size_t)vi;
|
---|
74 | D = OPENSSL_malloc(v);
|
---|
75 | Ai = OPENSSL_malloc(u);
|
---|
76 | B = OPENSSL_malloc(v + 1);
|
---|
77 | Slen = v * ((saltlen + v - 1) / v);
|
---|
78 | if (passlen != 0)
|
---|
79 | Plen = v * ((passlen + v - 1) / v);
|
---|
80 | else
|
---|
81 | Plen = 0;
|
---|
82 | Ilen = Slen + Plen;
|
---|
83 | I = OPENSSL_malloc(Ilen);
|
---|
84 | if (D == NULL || Ai == NULL || B == NULL || I == NULL) {
|
---|
85 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
---|
86 | goto end;
|
---|
87 | }
|
---|
88 | for (i = 0; i < v; i++)
|
---|
89 | D[i] = id;
|
---|
90 | p = I;
|
---|
91 | for (i = 0; i < Slen; i++)
|
---|
92 | *p++ = salt[i % saltlen];
|
---|
93 | for (i = 0; i < Plen; i++)
|
---|
94 | *p++ = pass[i % passlen];
|
---|
95 | for (;;) {
|
---|
96 | if (!EVP_DigestInit_ex(ctx, md_type, NULL)
|
---|
97 | || !EVP_DigestUpdate(ctx, D, v)
|
---|
98 | || !EVP_DigestUpdate(ctx, I, Ilen)
|
---|
99 | || !EVP_DigestFinal_ex(ctx, Ai, NULL))
|
---|
100 | goto end;
|
---|
101 | for (iter_cnt = 1; iter_cnt < iter; iter_cnt++) {
|
---|
102 | if (!EVP_DigestInit_ex(ctx, md_type, NULL)
|
---|
103 | || !EVP_DigestUpdate(ctx, Ai, u)
|
---|
104 | || !EVP_DigestFinal_ex(ctx, Ai, NULL))
|
---|
105 | goto end;
|
---|
106 | }
|
---|
107 | memcpy(out, Ai, n < u ? n : u);
|
---|
108 | if (u >= n) {
|
---|
109 | ret = 1;
|
---|
110 | break;
|
---|
111 | }
|
---|
112 | n -= u;
|
---|
113 | out += u;
|
---|
114 | for (j = 0; j < v; j++)
|
---|
115 | B[j] = Ai[j % u];
|
---|
116 | for (j = 0; j < Ilen; j += v) {
|
---|
117 | unsigned char *Ij = I + j;
|
---|
118 | uint16_t c = 1;
|
---|
119 |
|
---|
120 | /* Work out Ij = Ij + B + 1 */
|
---|
121 | for (k = v; k > 0;) {
|
---|
122 | k--;
|
---|
123 | c += Ij[k] + B[k];
|
---|
124 | Ij[k] = (unsigned char)c;
|
---|
125 | c >>= 8;
|
---|
126 | }
|
---|
127 | }
|
---|
128 | }
|
---|
129 |
|
---|
130 | end:
|
---|
131 | OPENSSL_free(Ai);
|
---|
132 | OPENSSL_free(B);
|
---|
133 | OPENSSL_free(D);
|
---|
134 | OPENSSL_free(I);
|
---|
135 | EVP_MD_CTX_free(ctx);
|
---|
136 | return ret;
|
---|
137 | }
|
---|
138 |
|
---|
139 | static void *kdf_pkcs12_new(void *provctx)
|
---|
140 | {
|
---|
141 | KDF_PKCS12 *ctx;
|
---|
142 |
|
---|
143 | if (!ossl_prov_is_running())
|
---|
144 | return NULL;
|
---|
145 |
|
---|
146 | ctx = OPENSSL_zalloc(sizeof(*ctx));
|
---|
147 | if (ctx == NULL) {
|
---|
148 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
---|
149 | return NULL;
|
---|
150 | }
|
---|
151 | ctx->provctx = provctx;
|
---|
152 | return ctx;
|
---|
153 | }
|
---|
154 |
|
---|
155 | static void kdf_pkcs12_cleanup(KDF_PKCS12 *ctx)
|
---|
156 | {
|
---|
157 | ossl_prov_digest_reset(&ctx->digest);
|
---|
158 | OPENSSL_free(ctx->salt);
|
---|
159 | OPENSSL_clear_free(ctx->pass, ctx->pass_len);
|
---|
160 | memset(ctx, 0, sizeof(*ctx));
|
---|
161 | }
|
---|
162 |
|
---|
163 | static void kdf_pkcs12_free(void *vctx)
|
---|
164 | {
|
---|
165 | KDF_PKCS12 *ctx = (KDF_PKCS12 *)vctx;
|
---|
166 |
|
---|
167 | if (ctx != NULL) {
|
---|
168 | kdf_pkcs12_cleanup(ctx);
|
---|
169 | OPENSSL_free(ctx);
|
---|
170 | }
|
---|
171 | }
|
---|
172 |
|
---|
173 | static void kdf_pkcs12_reset(void *vctx)
|
---|
174 | {
|
---|
175 | KDF_PKCS12 *ctx = (KDF_PKCS12 *)vctx;
|
---|
176 | void *provctx = ctx->provctx;
|
---|
177 |
|
---|
178 | kdf_pkcs12_cleanup(ctx);
|
---|
179 | ctx->provctx = provctx;
|
---|
180 | }
|
---|
181 |
|
---|
182 | static void *kdf_pkcs12_dup(void *vctx)
|
---|
183 | {
|
---|
184 | const KDF_PKCS12 *src = (const KDF_PKCS12 *)vctx;
|
---|
185 | KDF_PKCS12 *dest;
|
---|
186 |
|
---|
187 | dest = kdf_pkcs12_new(src->provctx);
|
---|
188 | if (dest != NULL) {
|
---|
189 | if (!ossl_prov_memdup(src->salt, src->salt_len,
|
---|
190 | &dest->salt, &dest->salt_len)
|
---|
191 | || !ossl_prov_memdup(src->pass, src->pass_len,
|
---|
192 | &dest->pass , &dest->pass_len)
|
---|
193 | || !ossl_prov_digest_copy(&dest->digest, &src->digest))
|
---|
194 | goto err;
|
---|
195 | dest->iter = src->iter;
|
---|
196 | dest->id = src->id;
|
---|
197 | }
|
---|
198 | return dest;
|
---|
199 |
|
---|
200 | err:
|
---|
201 | kdf_pkcs12_free(dest);
|
---|
202 | return NULL;
|
---|
203 | }
|
---|
204 |
|
---|
205 | static int pkcs12kdf_set_membuf(unsigned char **buffer, size_t *buflen,
|
---|
206 | const OSSL_PARAM *p)
|
---|
207 | {
|
---|
208 | OPENSSL_clear_free(*buffer, *buflen);
|
---|
209 | *buffer = NULL;
|
---|
210 | *buflen = 0;
|
---|
211 |
|
---|
212 | if (p->data_size == 0) {
|
---|
213 | if ((*buffer = OPENSSL_malloc(1)) == NULL) {
|
---|
214 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
---|
215 | return 0;
|
---|
216 | }
|
---|
217 | } else if (p->data != NULL) {
|
---|
218 | if (!OSSL_PARAM_get_octet_string(p, (void **)buffer, 0, buflen))
|
---|
219 | return 0;
|
---|
220 | }
|
---|
221 | return 1;
|
---|
222 | }
|
---|
223 |
|
---|
224 | static int kdf_pkcs12_derive(void *vctx, unsigned char *key, size_t keylen,
|
---|
225 | const OSSL_PARAM params[])
|
---|
226 | {
|
---|
227 | KDF_PKCS12 *ctx = (KDF_PKCS12 *)vctx;
|
---|
228 | const EVP_MD *md;
|
---|
229 |
|
---|
230 | if (!ossl_prov_is_running() || !kdf_pkcs12_set_ctx_params(ctx, params))
|
---|
231 | return 0;
|
---|
232 |
|
---|
233 | if (ctx->pass == NULL) {
|
---|
234 | ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_PASS);
|
---|
235 | return 0;
|
---|
236 | }
|
---|
237 |
|
---|
238 | if (ctx->salt == NULL) {
|
---|
239 | ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SALT);
|
---|
240 | return 0;
|
---|
241 | }
|
---|
242 |
|
---|
243 | md = ossl_prov_digest_md(&ctx->digest);
|
---|
244 | return pkcs12kdf_derive(ctx->pass, ctx->pass_len, ctx->salt, ctx->salt_len,
|
---|
245 | ctx->id, ctx->iter, md, key, keylen);
|
---|
246 | }
|
---|
247 |
|
---|
248 | static int kdf_pkcs12_set_ctx_params(void *vctx, const OSSL_PARAM params[])
|
---|
249 | {
|
---|
250 | const OSSL_PARAM *p;
|
---|
251 | KDF_PKCS12 *ctx = vctx;
|
---|
252 | OSSL_LIB_CTX *provctx = PROV_LIBCTX_OF(ctx->provctx);
|
---|
253 |
|
---|
254 | if (params == NULL)
|
---|
255 | return 1;
|
---|
256 |
|
---|
257 | if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx))
|
---|
258 | return 0;
|
---|
259 |
|
---|
260 | if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PASSWORD)) != NULL)
|
---|
261 | if (!pkcs12kdf_set_membuf(&ctx->pass, &ctx->pass_len, p))
|
---|
262 | return 0;
|
---|
263 |
|
---|
264 | if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL)
|
---|
265 | if (!pkcs12kdf_set_membuf(&ctx->salt, &ctx->salt_len,p))
|
---|
266 | return 0;
|
---|
267 |
|
---|
268 | if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PKCS12_ID)) != NULL)
|
---|
269 | if (!OSSL_PARAM_get_int(p, &ctx->id))
|
---|
270 | return 0;
|
---|
271 |
|
---|
272 | if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_ITER)) != NULL)
|
---|
273 | if (!OSSL_PARAM_get_uint64(p, &ctx->iter))
|
---|
274 | return 0;
|
---|
275 | return 1;
|
---|
276 | }
|
---|
277 |
|
---|
278 | static const OSSL_PARAM *kdf_pkcs12_settable_ctx_params(
|
---|
279 | ossl_unused void *ctx, ossl_unused void *provctx)
|
---|
280 | {
|
---|
281 | static const OSSL_PARAM known_settable_ctx_params[] = {
|
---|
282 | OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
|
---|
283 | OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
|
---|
284 | OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PASSWORD, NULL, 0),
|
---|
285 | OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0),
|
---|
286 | OSSL_PARAM_uint64(OSSL_KDF_PARAM_ITER, NULL),
|
---|
287 | OSSL_PARAM_int(OSSL_KDF_PARAM_PKCS12_ID, NULL),
|
---|
288 | OSSL_PARAM_END
|
---|
289 | };
|
---|
290 | return known_settable_ctx_params;
|
---|
291 | }
|
---|
292 |
|
---|
293 | static int kdf_pkcs12_get_ctx_params(void *vctx, OSSL_PARAM params[])
|
---|
294 | {
|
---|
295 | OSSL_PARAM *p;
|
---|
296 |
|
---|
297 | if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)
|
---|
298 | return OSSL_PARAM_set_size_t(p, SIZE_MAX);
|
---|
299 | return -2;
|
---|
300 | }
|
---|
301 |
|
---|
302 | static const OSSL_PARAM *kdf_pkcs12_gettable_ctx_params(
|
---|
303 | ossl_unused void *ctx, ossl_unused void *provctx)
|
---|
304 | {
|
---|
305 | static const OSSL_PARAM known_gettable_ctx_params[] = {
|
---|
306 | OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
|
---|
307 | OSSL_PARAM_END
|
---|
308 | };
|
---|
309 | return known_gettable_ctx_params;
|
---|
310 | }
|
---|
311 |
|
---|
312 | const OSSL_DISPATCH ossl_kdf_pkcs12_functions[] = {
|
---|
313 | { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_pkcs12_new },
|
---|
314 | { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))kdf_pkcs12_dup },
|
---|
315 | { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_pkcs12_free },
|
---|
316 | { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_pkcs12_reset },
|
---|
317 | { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_pkcs12_derive },
|
---|
318 | { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
|
---|
319 | (void(*)(void))kdf_pkcs12_settable_ctx_params },
|
---|
320 | { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_pkcs12_set_ctx_params },
|
---|
321 | { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
|
---|
322 | (void(*)(void))kdf_pkcs12_gettable_ctx_params },
|
---|
323 | { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_pkcs12_get_ctx_params },
|
---|
324 | { 0, NULL }
|
---|
325 | };
|
---|