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
13 #include <openssl/evp.h>
14 #include <openssl/kdf.h>
15 #include <openssl/core_names.h>
16 #include <openssl/proverr.h>
17 #include "internal/cryptlib.h"
18 #include "internal/numbers.h"
19 #include "crypto/evp.h"
20 #include "prov/provider_ctx.h"
21 #include "prov/providercommon.h"
22 #include "prov/implementations.h"
23 #include "prov/provider_util.h"
25 /* See RFC 4253, Section 7.2 */
26 static OSSL_FUNC_kdf_newctx_fn kdf_sshkdf_new
;
27 static OSSL_FUNC_kdf_dupctx_fn kdf_sshkdf_dup
;
28 static OSSL_FUNC_kdf_freectx_fn kdf_sshkdf_free
;
29 static OSSL_FUNC_kdf_reset_fn kdf_sshkdf_reset
;
30 static OSSL_FUNC_kdf_derive_fn kdf_sshkdf_derive
;
31 static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_sshkdf_settable_ctx_params
;
32 static OSSL_FUNC_kdf_set_ctx_params_fn kdf_sshkdf_set_ctx_params
;
33 static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_sshkdf_gettable_ctx_params
;
34 static OSSL_FUNC_kdf_get_ctx_params_fn kdf_sshkdf_get_ctx_params
;
36 static int SSHKDF(const EVP_MD
*evp_md
,
37 const unsigned char *key
, size_t key_len
,
38 const unsigned char *xcghash
, size_t xcghash_len
,
39 const unsigned char *session_id
, size_t session_id_len
,
40 char type
, unsigned char *okey
, size_t okey_len
);
45 unsigned char *key
; /* K */
47 unsigned char *xcghash
; /* H */
50 unsigned char *session_id
;
51 size_t session_id_len
;
54 static void *kdf_sshkdf_new(void *provctx
)
58 if (!ossl_prov_is_running())
61 if ((ctx
= OPENSSL_zalloc(sizeof(*ctx
))) != NULL
)
62 ctx
->provctx
= provctx
;
66 static void kdf_sshkdf_free(void *vctx
)
68 KDF_SSHKDF
*ctx
= (KDF_SSHKDF
*)vctx
;
71 kdf_sshkdf_reset(ctx
);
76 static void kdf_sshkdf_reset(void *vctx
)
78 KDF_SSHKDF
*ctx
= (KDF_SSHKDF
*)vctx
;
79 void *provctx
= ctx
->provctx
;
81 ossl_prov_digest_reset(&ctx
->digest
);
82 OPENSSL_clear_free(ctx
->key
, ctx
->key_len
);
83 OPENSSL_clear_free(ctx
->xcghash
, ctx
->xcghash_len
);
84 OPENSSL_clear_free(ctx
->session_id
, ctx
->session_id_len
);
85 memset(ctx
, 0, sizeof(*ctx
));
86 ctx
->provctx
= provctx
;
89 static void *kdf_sshkdf_dup(void *vctx
)
91 const KDF_SSHKDF
*src
= (const KDF_SSHKDF
*)vctx
;
94 dest
= kdf_sshkdf_new(src
->provctx
);
96 if (!ossl_prov_memdup(src
->key
, src
->key_len
,
97 &dest
->key
, &dest
->key_len
)
98 || !ossl_prov_memdup(src
->xcghash
, src
->xcghash_len
,
99 &dest
->xcghash
, &dest
->xcghash_len
)
100 || !ossl_prov_memdup(src
->session_id
, src
->session_id_len
,
101 &dest
->session_id
, &dest
->session_id_len
)
102 || !ossl_prov_digest_copy(&dest
->digest
, &src
->digest
))
104 dest
->type
= src
->type
;
109 kdf_sshkdf_free(dest
);
113 static int sshkdf_set_membuf(unsigned char **dst
, size_t *dst_len
,
116 OPENSSL_clear_free(*dst
, *dst_len
);
119 return OSSL_PARAM_get_octet_string(p
, (void **)dst
, 0, dst_len
);
122 static int kdf_sshkdf_derive(void *vctx
, unsigned char *key
, size_t keylen
,
123 const OSSL_PARAM params
[])
125 KDF_SSHKDF
*ctx
= (KDF_SSHKDF
*)vctx
;
128 if (!ossl_prov_is_running() || !kdf_sshkdf_set_ctx_params(ctx
, params
))
131 md
= ossl_prov_digest_md(&ctx
->digest
);
133 ERR_raise(ERR_LIB_PROV
, PROV_R_MISSING_MESSAGE_DIGEST
);
136 if (ctx
->key
== NULL
) {
137 ERR_raise(ERR_LIB_PROV
, PROV_R_MISSING_KEY
);
140 if (ctx
->xcghash
== NULL
) {
141 ERR_raise(ERR_LIB_PROV
, PROV_R_MISSING_XCGHASH
);
144 if (ctx
->session_id
== NULL
) {
145 ERR_raise(ERR_LIB_PROV
, PROV_R_MISSING_SESSION_ID
);
148 if (ctx
->type
== 0) {
149 ERR_raise(ERR_LIB_PROV
, PROV_R_MISSING_TYPE
);
152 return SSHKDF(md
, ctx
->key
, ctx
->key_len
,
153 ctx
->xcghash
, ctx
->xcghash_len
,
154 ctx
->session_id
, ctx
->session_id_len
,
155 ctx
->type
, key
, keylen
);
158 static int kdf_sshkdf_set_ctx_params(void *vctx
, const OSSL_PARAM params
[])
161 KDF_SSHKDF
*ctx
= vctx
;
162 OSSL_LIB_CTX
*provctx
= PROV_LIBCTX_OF(ctx
->provctx
);
167 if (!ossl_prov_digest_load_from_params(&ctx
->digest
, params
, provctx
))
170 if ((p
= OSSL_PARAM_locate_const(params
, OSSL_KDF_PARAM_KEY
)) != NULL
)
171 if (!sshkdf_set_membuf(&ctx
->key
, &ctx
->key_len
, p
))
174 if ((p
= OSSL_PARAM_locate_const(params
, OSSL_KDF_PARAM_SSHKDF_XCGHASH
))
176 if (!sshkdf_set_membuf(&ctx
->xcghash
, &ctx
->xcghash_len
, p
))
179 if ((p
= OSSL_PARAM_locate_const(params
, OSSL_KDF_PARAM_SSHKDF_SESSION_ID
))
181 if (!sshkdf_set_membuf(&ctx
->session_id
, &ctx
->session_id_len
, p
))
184 if ((p
= OSSL_PARAM_locate_const(params
, OSSL_KDF_PARAM_SSHKDF_TYPE
))
188 if (!OSSL_PARAM_get_utf8_string_ptr(p
, &kdftype
))
190 /* Expect one character (byte in this case) */
191 if (kdftype
== NULL
|| p
->data_size
!= 1)
193 if (kdftype
[0] < 65 || kdftype
[0] > 70) {
194 ERR_raise(ERR_LIB_PROV
, PROV_R_VALUE_ERROR
);
197 ctx
->type
= kdftype
[0];
202 static const OSSL_PARAM
*kdf_sshkdf_settable_ctx_params(ossl_unused
void *ctx
,
203 ossl_unused
void *p_ctx
)
205 static const OSSL_PARAM known_settable_ctx_params
[] = {
206 OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES
, NULL
, 0),
207 OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST
, NULL
, 0),
208 OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY
, NULL
, 0),
209 OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SSHKDF_XCGHASH
, NULL
, 0),
210 OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SSHKDF_SESSION_ID
, NULL
, 0),
211 OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_SSHKDF_TYPE
, NULL
, 0),
214 return known_settable_ctx_params
;
217 static int kdf_sshkdf_get_ctx_params(void *vctx
, OSSL_PARAM params
[])
221 if ((p
= OSSL_PARAM_locate(params
, OSSL_KDF_PARAM_SIZE
)) != NULL
)
222 return OSSL_PARAM_set_size_t(p
, SIZE_MAX
);
226 static const OSSL_PARAM
*kdf_sshkdf_gettable_ctx_params(ossl_unused
void *ctx
,
227 ossl_unused
void *p_ctx
)
229 static const OSSL_PARAM known_gettable_ctx_params
[] = {
230 OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE
, NULL
),
233 return known_gettable_ctx_params
;
236 const OSSL_DISPATCH ossl_kdf_sshkdf_functions
[] = {
237 { OSSL_FUNC_KDF_NEWCTX
, (void(*)(void))kdf_sshkdf_new
},
238 { OSSL_FUNC_KDF_DUPCTX
, (void(*)(void))kdf_sshkdf_dup
},
239 { OSSL_FUNC_KDF_FREECTX
, (void(*)(void))kdf_sshkdf_free
},
240 { OSSL_FUNC_KDF_RESET
, (void(*)(void))kdf_sshkdf_reset
},
241 { OSSL_FUNC_KDF_DERIVE
, (void(*)(void))kdf_sshkdf_derive
},
242 { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS
,
243 (void(*)(void))kdf_sshkdf_settable_ctx_params
},
244 { OSSL_FUNC_KDF_SET_CTX_PARAMS
, (void(*)(void))kdf_sshkdf_set_ctx_params
},
245 { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS
,
246 (void(*)(void))kdf_sshkdf_gettable_ctx_params
},
247 { OSSL_FUNC_KDF_GET_CTX_PARAMS
, (void(*)(void))kdf_sshkdf_get_ctx_params
},
251 static int SSHKDF(const EVP_MD
*evp_md
,
252 const unsigned char *key
, size_t key_len
,
253 const unsigned char *xcghash
, size_t xcghash_len
,
254 const unsigned char *session_id
, size_t session_id_len
,
255 char type
, unsigned char *okey
, size_t okey_len
)
257 EVP_MD_CTX
*md
= NULL
;
258 unsigned char digest
[EVP_MAX_MD_SIZE
];
259 unsigned int dsize
= 0;
263 md
= EVP_MD_CTX_new();
267 if (!EVP_DigestInit_ex(md
, evp_md
, NULL
))
270 if (!EVP_DigestUpdate(md
, key
, key_len
))
273 if (!EVP_DigestUpdate(md
, xcghash
, xcghash_len
))
276 if (!EVP_DigestUpdate(md
, &type
, 1))
279 if (!EVP_DigestUpdate(md
, session_id
, session_id_len
))
282 if (!EVP_DigestFinal_ex(md
, digest
, &dsize
))
285 if (okey_len
< dsize
) {
286 memcpy(okey
, digest
, okey_len
);
291 memcpy(okey
, digest
, dsize
);
293 for (cursize
= dsize
; cursize
< okey_len
; cursize
+= dsize
) {
295 if (!EVP_DigestInit_ex(md
, evp_md
, NULL
))
298 if (!EVP_DigestUpdate(md
, key
, key_len
))
301 if (!EVP_DigestUpdate(md
, xcghash
, xcghash_len
))
304 if (!EVP_DigestUpdate(md
, okey
, cursize
))
307 if (!EVP_DigestFinal_ex(md
, digest
, &dsize
))
310 if (okey_len
< cursize
+ dsize
) {
311 memcpy(okey
+ cursize
, digest
, okey_len
- cursize
);
316 memcpy(okey
+ cursize
, digest
, dsize
);
323 OPENSSL_cleanse(digest
, EVP_MAX_MD_SIZE
);