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_pbkdf1_new;
|
---|
27 | static OSSL_FUNC_kdf_dupctx_fn kdf_pbkdf1_dup;
|
---|
28 | static OSSL_FUNC_kdf_freectx_fn kdf_pbkdf1_free;
|
---|
29 | static OSSL_FUNC_kdf_reset_fn kdf_pbkdf1_reset;
|
---|
30 | static OSSL_FUNC_kdf_derive_fn kdf_pbkdf1_derive;
|
---|
31 | static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_pbkdf1_settable_ctx_params;
|
---|
32 | static OSSL_FUNC_kdf_set_ctx_params_fn kdf_pbkdf1_set_ctx_params;
|
---|
33 | static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_pbkdf1_gettable_ctx_params;
|
---|
34 | static OSSL_FUNC_kdf_get_ctx_params_fn kdf_pbkdf1_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 | } KDF_PBKDF1;
|
---|
45 |
|
---|
46 | /*
|
---|
47 | * PKCS5 PBKDF1 compatible key/IV generation as specified in:
|
---|
48 | * https://tools.ietf.org/html/rfc8018#page-10
|
---|
49 | */
|
---|
50 |
|
---|
51 | static int kdf_pbkdf1_do_derive(const unsigned char *pass, size_t passlen,
|
---|
52 | const unsigned char *salt, size_t saltlen,
|
---|
53 | uint64_t iter, const EVP_MD *md_type,
|
---|
54 | unsigned char *out, size_t n)
|
---|
55 | {
|
---|
56 | uint64_t i;
|
---|
57 | int mdsize, ret = 0;
|
---|
58 | unsigned char md_tmp[EVP_MAX_MD_SIZE];
|
---|
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 err;
|
---|
65 | }
|
---|
66 |
|
---|
67 | if (!EVP_DigestInit_ex(ctx, md_type, NULL)
|
---|
68 | || !EVP_DigestUpdate(ctx, pass, passlen)
|
---|
69 | || !EVP_DigestUpdate(ctx, salt, saltlen)
|
---|
70 | || !EVP_DigestFinal_ex(ctx, md_tmp, NULL))
|
---|
71 | goto err;
|
---|
72 | mdsize = EVP_MD_size(md_type);
|
---|
73 | if (mdsize < 0)
|
---|
74 | goto err;
|
---|
75 | for (i = 1; i < iter; i++) {
|
---|
76 | if (!EVP_DigestInit_ex(ctx, md_type, NULL))
|
---|
77 | goto err;
|
---|
78 | if (!EVP_DigestUpdate(ctx, md_tmp, mdsize))
|
---|
79 | goto err;
|
---|
80 | if (!EVP_DigestFinal_ex(ctx, md_tmp, NULL))
|
---|
81 | goto err;
|
---|
82 | }
|
---|
83 |
|
---|
84 | memcpy(out, md_tmp, n);
|
---|
85 | ret = 1;
|
---|
86 | err:
|
---|
87 | EVP_MD_CTX_free(ctx);
|
---|
88 | return ret;
|
---|
89 | }
|
---|
90 |
|
---|
91 | static void *kdf_pbkdf1_new(void *provctx)
|
---|
92 | {
|
---|
93 | KDF_PBKDF1 *ctx;
|
---|
94 |
|
---|
95 | if (!ossl_prov_is_running())
|
---|
96 | return NULL;
|
---|
97 |
|
---|
98 | ctx = OPENSSL_zalloc(sizeof(*ctx));
|
---|
99 | if (ctx == NULL) {
|
---|
100 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
---|
101 | return NULL;
|
---|
102 | }
|
---|
103 | ctx->provctx = provctx;
|
---|
104 | return ctx;
|
---|
105 | }
|
---|
106 |
|
---|
107 | static void kdf_pbkdf1_cleanup(KDF_PBKDF1 *ctx)
|
---|
108 | {
|
---|
109 | ossl_prov_digest_reset(&ctx->digest);
|
---|
110 | OPENSSL_free(ctx->salt);
|
---|
111 | OPENSSL_clear_free(ctx->pass, ctx->pass_len);
|
---|
112 | memset(ctx, 0, sizeof(*ctx));
|
---|
113 | }
|
---|
114 |
|
---|
115 | static void kdf_pbkdf1_free(void *vctx)
|
---|
116 | {
|
---|
117 | KDF_PBKDF1 *ctx = (KDF_PBKDF1 *)vctx;
|
---|
118 |
|
---|
119 | if (ctx != NULL) {
|
---|
120 | kdf_pbkdf1_cleanup(ctx);
|
---|
121 | OPENSSL_free(ctx);
|
---|
122 | }
|
---|
123 | }
|
---|
124 |
|
---|
125 | static void kdf_pbkdf1_reset(void *vctx)
|
---|
126 | {
|
---|
127 | KDF_PBKDF1 *ctx = (KDF_PBKDF1 *)vctx;
|
---|
128 | void *provctx = ctx->provctx;
|
---|
129 |
|
---|
130 | kdf_pbkdf1_cleanup(ctx);
|
---|
131 | ctx->provctx = provctx;
|
---|
132 | }
|
---|
133 |
|
---|
134 | static void *kdf_pbkdf1_dup(void *vctx)
|
---|
135 | {
|
---|
136 | const KDF_PBKDF1 *src = (const KDF_PBKDF1 *)vctx;
|
---|
137 | KDF_PBKDF1 *dest;
|
---|
138 |
|
---|
139 | dest = kdf_pbkdf1_new(src->provctx);
|
---|
140 | if (dest != NULL) {
|
---|
141 | if (!ossl_prov_memdup(src->salt, src->salt_len,
|
---|
142 | &dest->salt, &dest->salt_len)
|
---|
143 | || !ossl_prov_memdup(src->pass, src->pass_len,
|
---|
144 | &dest->pass , &dest->pass_len)
|
---|
145 | || !ossl_prov_digest_copy(&dest->digest, &src->digest))
|
---|
146 | goto err;
|
---|
147 | dest->iter = src->iter;
|
---|
148 | }
|
---|
149 | return dest;
|
---|
150 |
|
---|
151 | err:
|
---|
152 | kdf_pbkdf1_free(dest);
|
---|
153 | return NULL;
|
---|
154 | }
|
---|
155 |
|
---|
156 | static int kdf_pbkdf1_set_membuf(unsigned char **buffer, size_t *buflen,
|
---|
157 | const OSSL_PARAM *p)
|
---|
158 | {
|
---|
159 | OPENSSL_clear_free(*buffer, *buflen);
|
---|
160 | *buffer = NULL;
|
---|
161 | *buflen = 0;
|
---|
162 |
|
---|
163 | if (p->data_size == 0) {
|
---|
164 | if ((*buffer = OPENSSL_malloc(1)) == NULL) {
|
---|
165 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
---|
166 | return 0;
|
---|
167 | }
|
---|
168 | } else if (p->data != NULL) {
|
---|
169 | if (!OSSL_PARAM_get_octet_string(p, (void **)buffer, 0, buflen))
|
---|
170 | return 0;
|
---|
171 | }
|
---|
172 | return 1;
|
---|
173 | }
|
---|
174 |
|
---|
175 | static int kdf_pbkdf1_derive(void *vctx, unsigned char *key, size_t keylen,
|
---|
176 | const OSSL_PARAM params[])
|
---|
177 | {
|
---|
178 | KDF_PBKDF1 *ctx = (KDF_PBKDF1 *)vctx;
|
---|
179 | const EVP_MD *md;
|
---|
180 |
|
---|
181 | if (!ossl_prov_is_running() || !kdf_pbkdf1_set_ctx_params(ctx, params))
|
---|
182 | return 0;
|
---|
183 |
|
---|
184 | if (ctx->pass == NULL) {
|
---|
185 | ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_PASS);
|
---|
186 | return 0;
|
---|
187 | }
|
---|
188 |
|
---|
189 | if (ctx->salt == NULL) {
|
---|
190 | ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SALT);
|
---|
191 | return 0;
|
---|
192 | }
|
---|
193 |
|
---|
194 | md = ossl_prov_digest_md(&ctx->digest);
|
---|
195 | return kdf_pbkdf1_do_derive(ctx->pass, ctx->pass_len, ctx->salt, ctx->salt_len,
|
---|
196 | ctx->iter, md, key, keylen);
|
---|
197 | }
|
---|
198 |
|
---|
199 | static int kdf_pbkdf1_set_ctx_params(void *vctx, const OSSL_PARAM params[])
|
---|
200 | {
|
---|
201 | const OSSL_PARAM *p;
|
---|
202 | KDF_PBKDF1 *ctx = vctx;
|
---|
203 | OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
|
---|
204 |
|
---|
205 | if (!ossl_prov_digest_load_from_params(&ctx->digest, params, libctx))
|
---|
206 | return 0;
|
---|
207 |
|
---|
208 | if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PASSWORD)) != NULL)
|
---|
209 | if (!kdf_pbkdf1_set_membuf(&ctx->pass, &ctx->pass_len, p))
|
---|
210 | return 0;
|
---|
211 |
|
---|
212 | if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL)
|
---|
213 | if (!kdf_pbkdf1_set_membuf(&ctx->salt, &ctx->salt_len,p))
|
---|
214 | return 0;
|
---|
215 |
|
---|
216 | if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_ITER)) != NULL)
|
---|
217 | if (!OSSL_PARAM_get_uint64(p, &ctx->iter))
|
---|
218 | return 0;
|
---|
219 | return 1;
|
---|
220 | }
|
---|
221 |
|
---|
222 | static const OSSL_PARAM *kdf_pbkdf1_settable_ctx_params(ossl_unused void *ctx,
|
---|
223 | ossl_unused void *p_ctx)
|
---|
224 | {
|
---|
225 | static const OSSL_PARAM known_settable_ctx_params[] = {
|
---|
226 | OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
|
---|
227 | OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
|
---|
228 | OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PASSWORD, NULL, 0),
|
---|
229 | OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0),
|
---|
230 | OSSL_PARAM_uint64(OSSL_KDF_PARAM_ITER, NULL),
|
---|
231 | OSSL_PARAM_END
|
---|
232 | };
|
---|
233 | return known_settable_ctx_params;
|
---|
234 | }
|
---|
235 |
|
---|
236 | static int kdf_pbkdf1_get_ctx_params(void *vctx, OSSL_PARAM params[])
|
---|
237 | {
|
---|
238 | OSSL_PARAM *p;
|
---|
239 |
|
---|
240 | if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)
|
---|
241 | return OSSL_PARAM_set_size_t(p, SIZE_MAX);
|
---|
242 | return -2;
|
---|
243 | }
|
---|
244 |
|
---|
245 | static const OSSL_PARAM *kdf_pbkdf1_gettable_ctx_params(ossl_unused void *ctx,
|
---|
246 | ossl_unused void *p_ctx)
|
---|
247 | {
|
---|
248 | static const OSSL_PARAM known_gettable_ctx_params[] = {
|
---|
249 | OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
|
---|
250 | OSSL_PARAM_END
|
---|
251 | };
|
---|
252 | return known_gettable_ctx_params;
|
---|
253 | }
|
---|
254 |
|
---|
255 | const OSSL_DISPATCH ossl_kdf_pbkdf1_functions[] = {
|
---|
256 | { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_pbkdf1_new },
|
---|
257 | { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))kdf_pbkdf1_dup },
|
---|
258 | { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_pbkdf1_free },
|
---|
259 | { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_pbkdf1_reset },
|
---|
260 | { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_pbkdf1_derive },
|
---|
261 | { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
|
---|
262 | (void(*)(void))kdf_pbkdf1_settable_ctx_params },
|
---|
263 | { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_pbkdf1_set_ctx_params },
|
---|
264 | { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
|
---|
265 | (void(*)(void))kdf_pbkdf1_gettable_ctx_params },
|
---|
266 | { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_pbkdf1_get_ctx_params },
|
---|
267 | { 0, NULL }
|
---|
268 | };
|
---|