1b077aed3SPierre Pronchery /*
2*e0c4386eSCy Schubert * Copyright 1999-2024 The OpenSSL Project Authors. All Rights Reserved.
3b077aed3SPierre Pronchery *
4b077aed3SPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use
5b077aed3SPierre Pronchery * this file except in compliance with the License. You can obtain a copy
6b077aed3SPierre Pronchery * in the file LICENSE in the source distribution or at
7b077aed3SPierre Pronchery * https://www.openssl.org/source/license.html
8b077aed3SPierre Pronchery */
9b077aed3SPierre Pronchery
10b077aed3SPierre Pronchery #include <openssl/trace.h>
11b077aed3SPierre Pronchery #include <stdlib.h>
12b077aed3SPierre Pronchery #include <stdarg.h>
13b077aed3SPierre Pronchery #include <string.h>
14b077aed3SPierre Pronchery #include <openssl/evp.h>
15b077aed3SPierre Pronchery #include <openssl/kdf.h>
16b077aed3SPierre Pronchery #include <openssl/core_names.h>
17b077aed3SPierre Pronchery #include <openssl/proverr.h>
18b077aed3SPierre Pronchery #include "internal/cryptlib.h"
19b077aed3SPierre Pronchery #include "internal/numbers.h"
20b077aed3SPierre Pronchery #include "crypto/evp.h"
21b077aed3SPierre Pronchery #include "prov/provider_ctx.h"
22b077aed3SPierre Pronchery #include "prov/providercommon.h"
23b077aed3SPierre Pronchery #include "prov/implementations.h"
24b077aed3SPierre Pronchery #include "prov/provider_util.h"
25b077aed3SPierre Pronchery
26b077aed3SPierre Pronchery static OSSL_FUNC_kdf_newctx_fn kdf_pbkdf1_new;
27b077aed3SPierre Pronchery static OSSL_FUNC_kdf_freectx_fn kdf_pbkdf1_free;
28b077aed3SPierre Pronchery static OSSL_FUNC_kdf_reset_fn kdf_pbkdf1_reset;
29b077aed3SPierre Pronchery static OSSL_FUNC_kdf_derive_fn kdf_pbkdf1_derive;
30b077aed3SPierre Pronchery static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_pbkdf1_settable_ctx_params;
31b077aed3SPierre Pronchery static OSSL_FUNC_kdf_set_ctx_params_fn kdf_pbkdf1_set_ctx_params;
32b077aed3SPierre Pronchery static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_pbkdf1_gettable_ctx_params;
33b077aed3SPierre Pronchery static OSSL_FUNC_kdf_get_ctx_params_fn kdf_pbkdf1_get_ctx_params;
34b077aed3SPierre Pronchery
35b077aed3SPierre Pronchery typedef struct {
36b077aed3SPierre Pronchery void *provctx;
37b077aed3SPierre Pronchery PROV_DIGEST digest;
38b077aed3SPierre Pronchery unsigned char *pass;
39b077aed3SPierre Pronchery size_t pass_len;
40b077aed3SPierre Pronchery unsigned char *salt;
41b077aed3SPierre Pronchery size_t salt_len;
42b077aed3SPierre Pronchery uint64_t iter;
43b077aed3SPierre Pronchery } KDF_PBKDF1;
44b077aed3SPierre Pronchery
45b077aed3SPierre Pronchery /*
46b077aed3SPierre Pronchery * PKCS5 PBKDF1 compatible key/IV generation as specified in:
47b077aed3SPierre Pronchery * https://tools.ietf.org/html/rfc8018#page-10
48b077aed3SPierre Pronchery */
49b077aed3SPierre Pronchery
kdf_pbkdf1_do_derive(const unsigned char * pass,size_t passlen,const unsigned char * salt,size_t saltlen,uint64_t iter,const EVP_MD * md_type,unsigned char * out,size_t n)50b077aed3SPierre Pronchery static int kdf_pbkdf1_do_derive(const unsigned char *pass, size_t passlen,
51b077aed3SPierre Pronchery const unsigned char *salt, size_t saltlen,
52b077aed3SPierre Pronchery uint64_t iter, const EVP_MD *md_type,
53b077aed3SPierre Pronchery unsigned char *out, size_t n)
54b077aed3SPierre Pronchery {
55b077aed3SPierre Pronchery uint64_t i;
56b077aed3SPierre Pronchery int mdsize, ret = 0;
57b077aed3SPierre Pronchery unsigned char md_tmp[EVP_MAX_MD_SIZE];
58b077aed3SPierre Pronchery EVP_MD_CTX *ctx = NULL;
59b077aed3SPierre Pronchery
60b077aed3SPierre Pronchery ctx = EVP_MD_CTX_new();
61b077aed3SPierre Pronchery if (ctx == NULL) {
62b077aed3SPierre Pronchery ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
63b077aed3SPierre Pronchery goto err;
64b077aed3SPierre Pronchery }
65b077aed3SPierre Pronchery
66b077aed3SPierre Pronchery if (!EVP_DigestInit_ex(ctx, md_type, NULL)
67b077aed3SPierre Pronchery || !EVP_DigestUpdate(ctx, pass, passlen)
68b077aed3SPierre Pronchery || !EVP_DigestUpdate(ctx, salt, saltlen)
69b077aed3SPierre Pronchery || !EVP_DigestFinal_ex(ctx, md_tmp, NULL))
70b077aed3SPierre Pronchery goto err;
71b077aed3SPierre Pronchery mdsize = EVP_MD_size(md_type);
72b077aed3SPierre Pronchery if (mdsize < 0)
73b077aed3SPierre Pronchery goto err;
74*e0c4386eSCy Schubert if (n > (size_t)mdsize) {
75*e0c4386eSCy Schubert ERR_raise(ERR_LIB_PROV, PROV_R_LENGTH_TOO_LARGE);
76*e0c4386eSCy Schubert goto err;
77*e0c4386eSCy Schubert }
78*e0c4386eSCy Schubert
79b077aed3SPierre Pronchery for (i = 1; i < iter; i++) {
80b077aed3SPierre Pronchery if (!EVP_DigestInit_ex(ctx, md_type, NULL))
81b077aed3SPierre Pronchery goto err;
82b077aed3SPierre Pronchery if (!EVP_DigestUpdate(ctx, md_tmp, mdsize))
83b077aed3SPierre Pronchery goto err;
84b077aed3SPierre Pronchery if (!EVP_DigestFinal_ex(ctx, md_tmp, NULL))
85b077aed3SPierre Pronchery goto err;
86b077aed3SPierre Pronchery }
87b077aed3SPierre Pronchery
88b077aed3SPierre Pronchery memcpy(out, md_tmp, n);
89b077aed3SPierre Pronchery ret = 1;
90b077aed3SPierre Pronchery err:
91*e0c4386eSCy Schubert OPENSSL_cleanse(md_tmp, EVP_MAX_MD_SIZE);
92b077aed3SPierre Pronchery EVP_MD_CTX_free(ctx);
93b077aed3SPierre Pronchery return ret;
94b077aed3SPierre Pronchery }
95b077aed3SPierre Pronchery
kdf_pbkdf1_new(void * provctx)96b077aed3SPierre Pronchery static void *kdf_pbkdf1_new(void *provctx)
97b077aed3SPierre Pronchery {
98b077aed3SPierre Pronchery KDF_PBKDF1 *ctx;
99b077aed3SPierre Pronchery
100b077aed3SPierre Pronchery if (!ossl_prov_is_running())
101b077aed3SPierre Pronchery return NULL;
102b077aed3SPierre Pronchery
103b077aed3SPierre Pronchery ctx = OPENSSL_zalloc(sizeof(*ctx));
104b077aed3SPierre Pronchery if (ctx == NULL) {
105b077aed3SPierre Pronchery ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
106b077aed3SPierre Pronchery return NULL;
107b077aed3SPierre Pronchery }
108b077aed3SPierre Pronchery ctx->provctx = provctx;
109b077aed3SPierre Pronchery return ctx;
110b077aed3SPierre Pronchery }
111b077aed3SPierre Pronchery
kdf_pbkdf1_cleanup(KDF_PBKDF1 * ctx)112b077aed3SPierre Pronchery static void kdf_pbkdf1_cleanup(KDF_PBKDF1 *ctx)
113b077aed3SPierre Pronchery {
114b077aed3SPierre Pronchery ossl_prov_digest_reset(&ctx->digest);
115b077aed3SPierre Pronchery OPENSSL_free(ctx->salt);
116b077aed3SPierre Pronchery OPENSSL_clear_free(ctx->pass, ctx->pass_len);
117b077aed3SPierre Pronchery memset(ctx, 0, sizeof(*ctx));
118b077aed3SPierre Pronchery }
119b077aed3SPierre Pronchery
kdf_pbkdf1_free(void * vctx)120b077aed3SPierre Pronchery static void kdf_pbkdf1_free(void *vctx)
121b077aed3SPierre Pronchery {
122b077aed3SPierre Pronchery KDF_PBKDF1 *ctx = (KDF_PBKDF1 *)vctx;
123b077aed3SPierre Pronchery
124b077aed3SPierre Pronchery if (ctx != NULL) {
125b077aed3SPierre Pronchery kdf_pbkdf1_cleanup(ctx);
126b077aed3SPierre Pronchery OPENSSL_free(ctx);
127b077aed3SPierre Pronchery }
128b077aed3SPierre Pronchery }
129b077aed3SPierre Pronchery
kdf_pbkdf1_reset(void * vctx)130b077aed3SPierre Pronchery static void kdf_pbkdf1_reset(void *vctx)
131b077aed3SPierre Pronchery {
132b077aed3SPierre Pronchery KDF_PBKDF1 *ctx = (KDF_PBKDF1 *)vctx;
133b077aed3SPierre Pronchery void *provctx = ctx->provctx;
134b077aed3SPierre Pronchery
135b077aed3SPierre Pronchery kdf_pbkdf1_cleanup(ctx);
136b077aed3SPierre Pronchery ctx->provctx = provctx;
137b077aed3SPierre Pronchery }
138b077aed3SPierre Pronchery
kdf_pbkdf1_set_membuf(unsigned char ** buffer,size_t * buflen,const OSSL_PARAM * p)139b077aed3SPierre Pronchery static int kdf_pbkdf1_set_membuf(unsigned char **buffer, size_t *buflen,
140b077aed3SPierre Pronchery const OSSL_PARAM *p)
141b077aed3SPierre Pronchery {
142b077aed3SPierre Pronchery OPENSSL_clear_free(*buffer, *buflen);
143b077aed3SPierre Pronchery *buffer = NULL;
144b077aed3SPierre Pronchery *buflen = 0;
145b077aed3SPierre Pronchery
146b077aed3SPierre Pronchery if (p->data_size == 0) {
147b077aed3SPierre Pronchery if ((*buffer = OPENSSL_malloc(1)) == NULL) {
148b077aed3SPierre Pronchery ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
149b077aed3SPierre Pronchery return 0;
150b077aed3SPierre Pronchery }
151b077aed3SPierre Pronchery } else if (p->data != NULL) {
152b077aed3SPierre Pronchery if (!OSSL_PARAM_get_octet_string(p, (void **)buffer, 0, buflen))
153b077aed3SPierre Pronchery return 0;
154b077aed3SPierre Pronchery }
155b077aed3SPierre Pronchery return 1;
156b077aed3SPierre Pronchery }
157b077aed3SPierre Pronchery
kdf_pbkdf1_derive(void * vctx,unsigned char * key,size_t keylen,const OSSL_PARAM params[])158b077aed3SPierre Pronchery static int kdf_pbkdf1_derive(void *vctx, unsigned char *key, size_t keylen,
159b077aed3SPierre Pronchery const OSSL_PARAM params[])
160b077aed3SPierre Pronchery {
161b077aed3SPierre Pronchery KDF_PBKDF1 *ctx = (KDF_PBKDF1 *)vctx;
162b077aed3SPierre Pronchery const EVP_MD *md;
163b077aed3SPierre Pronchery
164b077aed3SPierre Pronchery if (!ossl_prov_is_running() || !kdf_pbkdf1_set_ctx_params(ctx, params))
165b077aed3SPierre Pronchery return 0;
166b077aed3SPierre Pronchery
167b077aed3SPierre Pronchery if (ctx->pass == NULL) {
168b077aed3SPierre Pronchery ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_PASS);
169b077aed3SPierre Pronchery return 0;
170b077aed3SPierre Pronchery }
171b077aed3SPierre Pronchery
172b077aed3SPierre Pronchery if (ctx->salt == NULL) {
173b077aed3SPierre Pronchery ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SALT);
174b077aed3SPierre Pronchery return 0;
175b077aed3SPierre Pronchery }
176b077aed3SPierre Pronchery
177b077aed3SPierre Pronchery md = ossl_prov_digest_md(&ctx->digest);
178b077aed3SPierre Pronchery return kdf_pbkdf1_do_derive(ctx->pass, ctx->pass_len, ctx->salt, ctx->salt_len,
179b077aed3SPierre Pronchery ctx->iter, md, key, keylen);
180b077aed3SPierre Pronchery }
181b077aed3SPierre Pronchery
kdf_pbkdf1_set_ctx_params(void * vctx,const OSSL_PARAM params[])182b077aed3SPierre Pronchery static int kdf_pbkdf1_set_ctx_params(void *vctx, const OSSL_PARAM params[])
183b077aed3SPierre Pronchery {
184b077aed3SPierre Pronchery const OSSL_PARAM *p;
185b077aed3SPierre Pronchery KDF_PBKDF1 *ctx = vctx;
186b077aed3SPierre Pronchery OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
187b077aed3SPierre Pronchery
188b077aed3SPierre Pronchery if (!ossl_prov_digest_load_from_params(&ctx->digest, params, libctx))
189b077aed3SPierre Pronchery return 0;
190b077aed3SPierre Pronchery
191b077aed3SPierre Pronchery if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PASSWORD)) != NULL)
192b077aed3SPierre Pronchery if (!kdf_pbkdf1_set_membuf(&ctx->pass, &ctx->pass_len, p))
193b077aed3SPierre Pronchery return 0;
194b077aed3SPierre Pronchery
195b077aed3SPierre Pronchery if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL)
196b077aed3SPierre Pronchery if (!kdf_pbkdf1_set_membuf(&ctx->salt, &ctx->salt_len,p))
197b077aed3SPierre Pronchery return 0;
198b077aed3SPierre Pronchery
199b077aed3SPierre Pronchery if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_ITER)) != NULL)
200b077aed3SPierre Pronchery if (!OSSL_PARAM_get_uint64(p, &ctx->iter))
201b077aed3SPierre Pronchery return 0;
202b077aed3SPierre Pronchery return 1;
203b077aed3SPierre Pronchery }
204b077aed3SPierre Pronchery
kdf_pbkdf1_settable_ctx_params(ossl_unused void * ctx,ossl_unused void * p_ctx)205b077aed3SPierre Pronchery static const OSSL_PARAM *kdf_pbkdf1_settable_ctx_params(ossl_unused void *ctx,
206b077aed3SPierre Pronchery ossl_unused void *p_ctx)
207b077aed3SPierre Pronchery {
208b077aed3SPierre Pronchery static const OSSL_PARAM known_settable_ctx_params[] = {
209b077aed3SPierre Pronchery OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
210b077aed3SPierre Pronchery OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
211b077aed3SPierre Pronchery OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PASSWORD, NULL, 0),
212b077aed3SPierre Pronchery OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0),
213b077aed3SPierre Pronchery OSSL_PARAM_uint64(OSSL_KDF_PARAM_ITER, NULL),
214b077aed3SPierre Pronchery OSSL_PARAM_END
215b077aed3SPierre Pronchery };
216b077aed3SPierre Pronchery return known_settable_ctx_params;
217b077aed3SPierre Pronchery }
218b077aed3SPierre Pronchery
kdf_pbkdf1_get_ctx_params(void * vctx,OSSL_PARAM params[])219b077aed3SPierre Pronchery static int kdf_pbkdf1_get_ctx_params(void *vctx, OSSL_PARAM params[])
220b077aed3SPierre Pronchery {
221b077aed3SPierre Pronchery OSSL_PARAM *p;
222b077aed3SPierre Pronchery
223b077aed3SPierre Pronchery if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)
224b077aed3SPierre Pronchery return OSSL_PARAM_set_size_t(p, SIZE_MAX);
225b077aed3SPierre Pronchery return -2;
226b077aed3SPierre Pronchery }
227b077aed3SPierre Pronchery
kdf_pbkdf1_gettable_ctx_params(ossl_unused void * ctx,ossl_unused void * p_ctx)228b077aed3SPierre Pronchery static const OSSL_PARAM *kdf_pbkdf1_gettable_ctx_params(ossl_unused void *ctx,
229b077aed3SPierre Pronchery ossl_unused void *p_ctx)
230b077aed3SPierre Pronchery {
231b077aed3SPierre Pronchery static const OSSL_PARAM known_gettable_ctx_params[] = {
232b077aed3SPierre Pronchery OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
233b077aed3SPierre Pronchery OSSL_PARAM_END
234b077aed3SPierre Pronchery };
235b077aed3SPierre Pronchery return known_gettable_ctx_params;
236b077aed3SPierre Pronchery }
237b077aed3SPierre Pronchery
238b077aed3SPierre Pronchery const OSSL_DISPATCH ossl_kdf_pbkdf1_functions[] = {
239b077aed3SPierre Pronchery { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_pbkdf1_new },
240b077aed3SPierre Pronchery { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_pbkdf1_free },
241b077aed3SPierre Pronchery { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_pbkdf1_reset },
242b077aed3SPierre Pronchery { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_pbkdf1_derive },
243b077aed3SPierre Pronchery { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
244b077aed3SPierre Pronchery (void(*)(void))kdf_pbkdf1_settable_ctx_params },
245b077aed3SPierre Pronchery { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_pbkdf1_set_ctx_params },
246b077aed3SPierre Pronchery { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
247b077aed3SPierre Pronchery (void(*)(void))kdf_pbkdf1_gettable_ctx_params },
248b077aed3SPierre Pronchery { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_pbkdf1_get_ctx_params },
249b077aed3SPierre Pronchery { 0, NULL }
250b077aed3SPierre Pronchery };
251