2 * Copyright 2022-2023 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
12 #include <openssl/crypto.h>
13 #include <openssl/err.h>
14 #include <openssl/kdf.h>
15 #include <openssl/proverr.h>
16 #include <openssl/core_names.h>
17 #include "prov/providercommon.h"
18 #include "prov/implementations.h"
19 #include "prov/hmac_drbg.h"
20 #include "prov/provider_ctx.h"
22 static OSSL_FUNC_kdf_newctx_fn hmac_drbg_kdf_new
;
23 static OSSL_FUNC_kdf_dupctx_fn hmac_drbg_kdf_dup
;
24 static OSSL_FUNC_kdf_freectx_fn hmac_drbg_kdf_free
;
25 static OSSL_FUNC_kdf_reset_fn hmac_drbg_kdf_reset
;
26 static OSSL_FUNC_kdf_derive_fn hmac_drbg_kdf_derive
;
27 static OSSL_FUNC_kdf_settable_ctx_params_fn hmac_drbg_kdf_settable_ctx_params
;
28 static OSSL_FUNC_kdf_set_ctx_params_fn hmac_drbg_kdf_set_ctx_params
;
29 static OSSL_FUNC_kdf_gettable_ctx_params_fn hmac_drbg_kdf_gettable_ctx_params
;
30 static OSSL_FUNC_kdf_get_ctx_params_fn hmac_drbg_kdf_get_ctx_params
;
35 unsigned char *entropy
, *nonce
;
36 size_t entropylen
, noncelen
;
40 static void *hmac_drbg_kdf_new(void *provctx
)
44 if (!ossl_prov_is_running())
47 ctx
= OPENSSL_zalloc(sizeof(*ctx
));
49 ERR_raise(ERR_LIB_PROV
, ERR_R_MALLOC_FAILURE
);
52 ctx
->provctx
= provctx
;
56 static void hmac_drbg_kdf_reset(void *vctx
)
58 KDF_HMAC_DRBG
*ctx
= (KDF_HMAC_DRBG
*)vctx
;
59 PROV_DRBG_HMAC
*drbg
= &ctx
->base
;
60 void *provctx
= ctx
->provctx
;
62 EVP_MAC_CTX_free(drbg
->ctx
);
63 ossl_prov_digest_reset(&drbg
->digest
);
64 OPENSSL_clear_free(ctx
->entropy
, ctx
->entropylen
);
65 OPENSSL_clear_free(ctx
->nonce
, ctx
->noncelen
);
66 OPENSSL_cleanse(ctx
, sizeof(*ctx
));
67 ctx
->provctx
= provctx
;
70 static void hmac_drbg_kdf_free(void *vctx
)
72 KDF_HMAC_DRBG
*ctx
= (KDF_HMAC_DRBG
*)vctx
;
75 hmac_drbg_kdf_reset(ctx
);
80 static int ossl_drbg_hmac_dup(PROV_DRBG_HMAC
*dst
, const PROV_DRBG_HMAC
*src
) {
81 if (src
->ctx
!= NULL
) {
82 dst
->ctx
= EVP_MAC_CTX_dup(src
->ctx
);
86 if (!ossl_prov_digest_copy(&dst
->digest
, &src
->digest
))
88 memcpy(dst
->K
, src
->K
, sizeof(dst
->K
));
89 memcpy(dst
->V
, src
->V
, sizeof(dst
->V
));
90 dst
->blocklen
= src
->blocklen
;
94 static void *hmac_drbg_kdf_dup(void *vctx
)
96 const KDF_HMAC_DRBG
*src
= (const KDF_HMAC_DRBG
*)vctx
;
99 dst
= hmac_drbg_kdf_new(src
->provctx
);
101 if (!ossl_drbg_hmac_dup(&dst
->base
, &src
->base
)
102 || !ossl_prov_memdup(src
->entropy
, src
->entropylen
,
103 &dst
->entropy
, &dst
->entropylen
)
104 || !ossl_prov_memdup(src
->nonce
, src
->noncelen
,
105 &dst
->nonce
, &dst
->noncelen
))
107 dst
->init
= src
->init
;
112 hmac_drbg_kdf_free(dst
);
116 static int hmac_drbg_kdf_derive(void *vctx
, unsigned char *out
, size_t outlen
,
117 const OSSL_PARAM params
[])
119 KDF_HMAC_DRBG
*ctx
= (KDF_HMAC_DRBG
*)vctx
;
120 PROV_DRBG_HMAC
*drbg
= &ctx
->base
;
122 if (!ossl_prov_is_running()
123 || !hmac_drbg_kdf_set_ctx_params(vctx
, params
))
126 if (ctx
->entropy
== NULL
127 || ctx
->entropylen
== 0
128 || ctx
->nonce
== NULL
129 || ctx
->noncelen
== 0
130 || !ossl_drbg_hmac_init(drbg
, ctx
->entropy
, ctx
->entropylen
,
131 ctx
->nonce
, ctx
->noncelen
, NULL
, 0))
136 return ossl_drbg_hmac_generate(drbg
, out
, outlen
, NULL
, 0);
139 static int hmac_drbg_kdf_get_ctx_params(void *vctx
, OSSL_PARAM params
[])
141 KDF_HMAC_DRBG
*hmac
= (KDF_HMAC_DRBG
*)vctx
;
142 PROV_DRBG_HMAC
*drbg
= &hmac
->base
;
147 p
= OSSL_PARAM_locate(params
, OSSL_KDF_PARAM_MAC
);
149 if (drbg
->ctx
== NULL
)
151 name
= EVP_MAC_get0_name(EVP_MAC_CTX_get0_mac(drbg
->ctx
));
152 if (!OSSL_PARAM_set_utf8_string(p
, name
))
156 p
= OSSL_PARAM_locate(params
, OSSL_KDF_PARAM_DIGEST
);
158 md
= ossl_prov_digest_md(&drbg
->digest
);
159 if (md
== NULL
|| !OSSL_PARAM_set_utf8_string(p
, EVP_MD_get0_name(md
)))
165 static const OSSL_PARAM
*hmac_drbg_kdf_gettable_ctx_params(
166 ossl_unused
void *vctx
, ossl_unused
void *p_ctx
)
168 static const OSSL_PARAM known_gettable_ctx_params
[] = {
169 OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MAC
, NULL
, 0),
170 OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST
, NULL
, 0),
173 return known_gettable_ctx_params
;
176 static int hmac_drbg_kdf_set_ctx_params(void *vctx
,
177 const OSSL_PARAM params
[])
179 KDF_HMAC_DRBG
*hmac
= (KDF_HMAC_DRBG
*)vctx
;
180 PROV_DRBG_HMAC
*drbg
= &hmac
->base
;
181 OSSL_LIB_CTX
*libctx
= PROV_LIBCTX_OF(hmac
->provctx
);
190 p
= OSSL_PARAM_locate_const(params
, OSSL_KDF_PARAM_HMACDRBG_ENTROPY
);
192 if (!OSSL_PARAM_get_octet_string(p
, &ptr
, 0, &size
))
194 OPENSSL_free(hmac
->entropy
);
196 hmac
->entropylen
= size
;
201 p
= OSSL_PARAM_locate_const(params
, OSSL_KDF_PARAM_HMACDRBG_NONCE
);
203 if (!OSSL_PARAM_get_octet_string(p
, &ptr
, 0, &size
))
205 OPENSSL_free(hmac
->nonce
);
207 hmac
->noncelen
= size
;
211 p
= OSSL_PARAM_locate_const(params
, OSSL_ALG_PARAM_DIGEST
);
213 if (!ossl_prov_digest_load_from_params(&drbg
->digest
, params
, libctx
))
216 /* Confirm digest is allowed. Allow all digests that are not XOF */
217 md
= ossl_prov_digest_md(&drbg
->digest
);
219 if ((EVP_MD_get_flags(md
) & EVP_MD_FLAG_XOF
) != 0) {
220 ERR_raise(ERR_LIB_PROV
, PROV_R_XOF_DIGESTS_NOT_ALLOWED
);
223 drbg
->blocklen
= EVP_MD_get_size(md
);
225 return ossl_prov_macctx_load_from_params(&drbg
->ctx
, params
,
226 "HMAC", NULL
, NULL
, libctx
);
231 static const OSSL_PARAM
*hmac_drbg_kdf_settable_ctx_params(
232 ossl_unused
void *vctx
, ossl_unused
void *p_ctx
)
234 static const OSSL_PARAM known_settable_ctx_params
[] = {
235 OSSL_PARAM_octet_string(OSSL_KDF_PARAM_HMACDRBG_ENTROPY
, NULL
, 0),
236 OSSL_PARAM_octet_string(OSSL_KDF_PARAM_HMACDRBG_NONCE
, NULL
, 0),
237 OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST
, NULL
, 0),
238 OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES
, NULL
, 0),
241 return known_settable_ctx_params
;
244 const OSSL_DISPATCH ossl_kdf_hmac_drbg_functions
[] = {
245 { OSSL_FUNC_KDF_NEWCTX
, (void(*)(void))hmac_drbg_kdf_new
},
246 { OSSL_FUNC_KDF_FREECTX
, (void(*)(void))hmac_drbg_kdf_free
},
247 { OSSL_FUNC_KDF_DUPCTX
, (void(*)(void))hmac_drbg_kdf_dup
},
248 { OSSL_FUNC_KDF_RESET
, (void(*)(void))hmac_drbg_kdf_reset
},
249 { OSSL_FUNC_KDF_DERIVE
, (void(*)(void))hmac_drbg_kdf_derive
},
250 { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS
,
251 (void(*)(void))hmac_drbg_kdf_settable_ctx_params
},
252 { OSSL_FUNC_KDF_SET_CTX_PARAMS
,
253 (void(*)(void))hmac_drbg_kdf_set_ctx_params
},
254 { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS
,
255 (void(*)(void))hmac_drbg_kdf_gettable_ctx_params
},
256 { OSSL_FUNC_KDF_GET_CTX_PARAMS
,
257 (void(*)(void))hmac_drbg_kdf_get_ctx_params
},