2 * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
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
10 #include <openssl/evp.h>
11 #include <openssl/core_names.h>
12 #include <openssl/proverr.h>
13 #include <openssl/err.h>
14 #include "internal/numbers.h" /* SIZE_MAX */
15 #include "prov/provider_ctx.h"
16 #include "prov/providercommon.h"
17 #include "prov/implementations.h"
18 #include "prov/provider_util.h"
20 static OSSL_FUNC_kdf_newctx_fn kdf_pvk_new
;
21 static OSSL_FUNC_kdf_dupctx_fn kdf_pvk_dup
;
22 static OSSL_FUNC_kdf_freectx_fn kdf_pvk_free
;
23 static OSSL_FUNC_kdf_reset_fn kdf_pvk_reset
;
24 static OSSL_FUNC_kdf_derive_fn kdf_pvk_derive
;
25 static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_pvk_settable_ctx_params
;
26 static OSSL_FUNC_kdf_set_ctx_params_fn kdf_pvk_set_ctx_params
;
27 static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_pvk_gettable_ctx_params
;
28 static OSSL_FUNC_kdf_get_ctx_params_fn kdf_pvk_get_ctx_params
;
39 static void kdf_pvk_init(KDF_PVK
*ctx
);
41 static void *kdf_pvk_new(void *provctx
)
45 if (!ossl_prov_is_running())
48 ctx
= OPENSSL_zalloc(sizeof(*ctx
));
51 ctx
->provctx
= provctx
;
56 static void kdf_pvk_cleanup(KDF_PVK
*ctx
)
58 ossl_prov_digest_reset(&ctx
->digest
);
59 OPENSSL_free(ctx
->salt
);
60 OPENSSL_clear_free(ctx
->pass
, ctx
->pass_len
);
61 OPENSSL_cleanse(ctx
, sizeof(*ctx
));
64 static void kdf_pvk_free(void *vctx
)
66 KDF_PVK
*ctx
= (KDF_PVK
*)vctx
;
74 static void *kdf_pvk_dup(void *vctx
)
76 const KDF_PVK
*src
= (const KDF_PVK
*)vctx
;
79 dest
= kdf_pvk_new(src
->provctx
);
81 if (!ossl_prov_memdup(src
->salt
, src
->salt_len
,
82 &dest
->salt
, &dest
->salt_len
)
83 || !ossl_prov_memdup(src
->pass
, src
->pass_len
,
84 &dest
->pass
, &dest
->pass_len
)
85 || !ossl_prov_digest_copy(&dest
->digest
, &src
->digest
))
94 static void kdf_pvk_reset(void *vctx
)
96 KDF_PVK
*ctx
= (KDF_PVK
*)vctx
;
97 void *provctx
= ctx
->provctx
;
100 ctx
->provctx
= provctx
;
104 static void kdf_pvk_init(KDF_PVK
*ctx
)
106 OSSL_PARAM params
[2] = { OSSL_PARAM_END
, OSSL_PARAM_END
};
107 OSSL_LIB_CTX
*provctx
= PROV_LIBCTX_OF(ctx
->provctx
);
109 params
[0] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST
,
111 if (!ossl_prov_digest_load_from_params(&ctx
->digest
, params
, provctx
))
112 /* This is an error, but there is no way to indicate such directly */
113 ossl_prov_digest_reset(&ctx
->digest
);
116 static int pvk_set_membuf(unsigned char **buffer
, size_t *buflen
,
119 OPENSSL_clear_free(*buffer
, *buflen
);
123 if (p
->data_size
== 0) {
124 if ((*buffer
= OPENSSL_malloc(1)) == NULL
)
126 } else if (p
->data
!= NULL
) {
127 if (!OSSL_PARAM_get_octet_string(p
, (void **)buffer
, 0, buflen
))
133 static int kdf_pvk_derive(void *vctx
, unsigned char *key
, size_t keylen
,
134 const OSSL_PARAM params
[])
136 KDF_PVK
*ctx
= (KDF_PVK
*)vctx
;
141 if (!ossl_prov_is_running() || !kdf_pvk_set_ctx_params(ctx
, params
))
144 if (ctx
->pass
== NULL
) {
145 ERR_raise(ERR_LIB_PROV
, PROV_R_MISSING_PASS
);
149 if (ctx
->salt
== NULL
) {
150 ERR_raise(ERR_LIB_PROV
, PROV_R_MISSING_SALT
);
154 md
= ossl_prov_digest_md(&ctx
->digest
);
156 ERR_raise(ERR_LIB_PROV
, PROV_R_INVALID_DIGEST
);
159 res
= EVP_MD_get_size(md
);
161 ERR_raise(ERR_LIB_PROV
, PROV_R_BAD_LENGTH
);
164 if ((size_t)res
> keylen
) {
165 ERR_raise(ERR_LIB_PROV
, PROV_R_LENGTH_TOO_LARGE
);
169 mctx
= EVP_MD_CTX_new();
171 && EVP_DigestInit_ex(mctx
, md
, NULL
)
172 && EVP_DigestUpdate(mctx
, ctx
->salt
, ctx
->salt_len
)
173 && EVP_DigestUpdate(mctx
, ctx
->pass
, ctx
->pass_len
)
174 && EVP_DigestFinal_ex(mctx
, key
, NULL
);
175 EVP_MD_CTX_free(mctx
);
179 static int kdf_pvk_set_ctx_params(void *vctx
, const OSSL_PARAM params
[])
183 OSSL_LIB_CTX
*provctx
= PROV_LIBCTX_OF(ctx
->provctx
);
188 if (!ossl_prov_digest_load_from_params(&ctx
->digest
, params
, provctx
))
191 if ((p
= OSSL_PARAM_locate_const(params
, OSSL_KDF_PARAM_PASSWORD
)) != NULL
)
192 if (!pvk_set_membuf(&ctx
->pass
, &ctx
->pass_len
, p
))
195 if ((p
= OSSL_PARAM_locate_const(params
, OSSL_KDF_PARAM_SALT
)) != NULL
) {
196 if (!pvk_set_membuf(&ctx
->salt
, &ctx
->salt_len
, p
))
203 static const OSSL_PARAM
*kdf_pvk_settable_ctx_params(ossl_unused
void *ctx
,
204 ossl_unused
void *p_ctx
)
206 static const OSSL_PARAM known_settable_ctx_params
[] = {
207 OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES
, NULL
, 0),
208 OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST
, NULL
, 0),
209 OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PASSWORD
, NULL
, 0),
210 OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT
, NULL
, 0),
213 return known_settable_ctx_params
;
216 static int kdf_pvk_get_ctx_params(void *vctx
, OSSL_PARAM params
[])
220 if ((p
= OSSL_PARAM_locate(params
, OSSL_KDF_PARAM_SIZE
)) != NULL
)
221 return OSSL_PARAM_set_size_t(p
, SIZE_MAX
);
225 static const OSSL_PARAM
*kdf_pvk_gettable_ctx_params(ossl_unused
void *ctx
,
226 ossl_unused
void *p_ctx
)
228 static const OSSL_PARAM known_gettable_ctx_params
[] = {
229 OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE
, NULL
),
232 return known_gettable_ctx_params
;
235 const OSSL_DISPATCH ossl_kdf_pvk_functions
[] = {
236 { OSSL_FUNC_KDF_NEWCTX
, (void(*)(void))kdf_pvk_new
},
237 { OSSL_FUNC_KDF_DUPCTX
, (void(*)(void))kdf_pvk_dup
},
238 { OSSL_FUNC_KDF_FREECTX
, (void(*)(void))kdf_pvk_free
},
239 { OSSL_FUNC_KDF_RESET
, (void(*)(void))kdf_pvk_reset
},
240 { OSSL_FUNC_KDF_DERIVE
, (void(*)(void))kdf_pvk_derive
},
241 { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS
,
242 (void(*)(void))kdf_pvk_settable_ctx_params
},
243 { OSSL_FUNC_KDF_SET_CTX_PARAMS
, (void(*)(void))kdf_pvk_set_ctx_params
},
244 { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS
,
245 (void(*)(void))kdf_pvk_gettable_ctx_params
},
246 { OSSL_FUNC_KDF_GET_CTX_PARAMS
, (void(*)(void))kdf_pvk_get_ctx_params
},