2 * Copyright 2018-2018 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the OpenSSL license (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 "internal/cryptlib.h"
16 #include "internal/numbers.h"
17 #include "internal/evp_int.h"
18 #include "kdf_local.h"
20 /* See RFC 4253, Section 7.2 */
22 static void kdf_sshkdf_reset(EVP_KDF_IMPL
*impl
);
23 static int SSHKDF(const EVP_MD
*evp_md
,
24 const unsigned char *key
, size_t key_len
,
25 const unsigned char *xcghash
, size_t xcghash_len
,
26 const unsigned char *session_id
, size_t session_id_len
,
27 char type
, unsigned char *okey
, size_t okey_len
);
29 struct evp_kdf_impl_st
{
31 unsigned char *key
; /* K */
33 unsigned char *xcghash
; /* H */
36 unsigned char *session_id
;
37 size_t session_id_len
;
40 static EVP_KDF_IMPL
*kdf_sshkdf_new(void)
44 if ((impl
= OPENSSL_zalloc(sizeof(*impl
))) == NULL
)
45 KDFerr(KDF_F_KDF_SSHKDF_NEW
, ERR_R_MALLOC_FAILURE
);
49 static void kdf_sshkdf_free(EVP_KDF_IMPL
*impl
)
51 kdf_sshkdf_reset(impl
);
55 static void kdf_sshkdf_reset(EVP_KDF_IMPL
*impl
)
57 OPENSSL_clear_free(impl
->key
, impl
->key_len
);
58 OPENSSL_clear_free(impl
->xcghash
, impl
->xcghash_len
);
59 OPENSSL_clear_free(impl
->session_id
, impl
->session_id_len
);
60 memset(impl
, 0, sizeof(*impl
));
63 static int kdf_sshkdf_parse_buffer_arg(unsigned char **dst
, size_t *dst_len
,
66 const unsigned char *p
;
69 p
= va_arg(args
, const unsigned char *);
70 len
= va_arg(args
, size_t);
71 OPENSSL_clear_free(*dst
, *dst_len
);
72 *dst
= OPENSSL_memdup(p
, len
);
80 static int kdf_sshkdf_ctrl(EVP_KDF_IMPL
*impl
, int cmd
, va_list args
)
85 case EVP_KDF_CTRL_SET_MD
:
86 impl
->md
= va_arg(args
, const EVP_MD
*);
92 case EVP_KDF_CTRL_SET_KEY
:
93 return kdf_sshkdf_parse_buffer_arg(&impl
->key
,
94 &impl
->key_len
, args
);
96 case EVP_KDF_CTRL_SET_SSHKDF_XCGHASH
:
97 return kdf_sshkdf_parse_buffer_arg(&impl
->xcghash
,
98 &impl
->xcghash_len
, args
);
100 case EVP_KDF_CTRL_SET_SSHKDF_SESSION_ID
:
101 return kdf_sshkdf_parse_buffer_arg(&impl
->session_id
,
102 &impl
->session_id_len
, args
);
104 case EVP_KDF_CTRL_SET_SSHKDF_TYPE
:
105 t
= va_arg(args
, int);
106 if (t
< 65 || t
> 70) {
107 KDFerr(KDF_F_KDF_SSHKDF_CTRL
, KDF_R_VALUE_ERROR
);
111 impl
->type
= (char)t
;
120 static int kdf_sshkdf_ctrl_str(EVP_KDF_IMPL
*impl
, const char *type
,
124 KDFerr(KDF_F_KDF_SSHKDF_CTRL_STR
, KDF_R_VALUE_MISSING
);
128 if (strcmp(type
, "digest") == 0)
129 return kdf_md2ctrl(impl
, kdf_sshkdf_ctrl
, EVP_KDF_CTRL_SET_MD
, value
);
130 /* alias, for historical reasons */
131 if (strcmp(type
, "md") == 0)
132 return kdf_md2ctrl(impl
, kdf_sshkdf_ctrl
, EVP_KDF_CTRL_SET_MD
, value
);
134 if (strcmp(type
, "key") == 0)
135 return kdf_str2ctrl(impl
, kdf_sshkdf_ctrl
,
136 EVP_KDF_CTRL_SET_KEY
, value
);
138 if (strcmp(type
, "hexkey") == 0)
139 return kdf_hex2ctrl(impl
, kdf_sshkdf_ctrl
,
140 EVP_KDF_CTRL_SET_KEY
, value
);
142 if (strcmp(type
, "xcghash") == 0)
143 return kdf_str2ctrl(impl
, kdf_sshkdf_ctrl
,
144 EVP_KDF_CTRL_SET_SSHKDF_XCGHASH
, value
);
146 if (strcmp(type
, "hexxcghash") == 0)
147 return kdf_hex2ctrl(impl
, kdf_sshkdf_ctrl
,
148 EVP_KDF_CTRL_SET_SSHKDF_XCGHASH
, value
);
150 if (strcmp(type
, "session_id") == 0)
151 return kdf_str2ctrl(impl
, kdf_sshkdf_ctrl
,
152 EVP_KDF_CTRL_SET_SSHKDF_SESSION_ID
, value
);
154 if (strcmp(type
, "hexsession_id") == 0)
155 return kdf_hex2ctrl(impl
, kdf_sshkdf_ctrl
,
156 EVP_KDF_CTRL_SET_SSHKDF_SESSION_ID
, value
);
158 if (strcmp(type
, "type") == 0) {
159 if (strlen(value
) != 1) {
160 KDFerr(KDF_F_KDF_SSHKDF_CTRL_STR
, KDF_R_VALUE_ERROR
);
164 return call_ctrl(kdf_sshkdf_ctrl
, impl
, EVP_KDF_CTRL_SET_SSHKDF_TYPE
,
168 KDFerr(KDF_F_KDF_SSHKDF_CTRL_STR
, KDF_R_UNKNOWN_PARAMETER_TYPE
);
172 static size_t kdf_sshkdf_size(EVP_KDF_IMPL
*impl
)
177 static int kdf_sshkdf_derive(EVP_KDF_IMPL
*impl
, unsigned char *key
,
180 if (impl
->md
== NULL
) {
181 KDFerr(KDF_F_KDF_SSHKDF_DERIVE
, KDF_R_MISSING_MESSAGE_DIGEST
);
184 if (impl
->key
== NULL
) {
185 KDFerr(KDF_F_KDF_SSHKDF_DERIVE
, KDF_R_MISSING_KEY
);
188 if (impl
->xcghash
== NULL
) {
189 KDFerr(KDF_F_KDF_SSHKDF_DERIVE
, KDF_R_MISSING_XCGHASH
);
192 if (impl
->session_id
== NULL
) {
193 KDFerr(KDF_F_KDF_SSHKDF_DERIVE
, KDF_R_MISSING_SESSION_ID
);
196 if (impl
->type
== 0) {
197 KDFerr(KDF_F_KDF_SSHKDF_DERIVE
, KDF_R_MISSING_TYPE
);
200 return SSHKDF(impl
->md
, impl
->key
, impl
->key_len
,
201 impl
->xcghash
, impl
->xcghash_len
,
202 impl
->session_id
, impl
->session_id_len
,
203 impl
->type
, key
, keylen
);
206 const EVP_KDF sshkdf_kdf_meth
= {
217 static int SSHKDF(const EVP_MD
*evp_md
,
218 const unsigned char *key
, size_t key_len
,
219 const unsigned char *xcghash
, size_t xcghash_len
,
220 const unsigned char *session_id
, size_t session_id_len
,
221 char type
, unsigned char *okey
, size_t okey_len
)
223 EVP_MD_CTX
*md
= NULL
;
224 unsigned char digest
[EVP_MAX_MD_SIZE
];
225 unsigned int dsize
= 0;
229 md
= EVP_MD_CTX_new();
233 if (!EVP_DigestInit_ex(md
, evp_md
, NULL
))
236 if (!EVP_DigestUpdate(md
, key
, key_len
))
239 if (!EVP_DigestUpdate(md
, xcghash
, xcghash_len
))
242 if (!EVP_DigestUpdate(md
, &type
, 1))
245 if (!EVP_DigestUpdate(md
, session_id
, session_id_len
))
248 if (!EVP_DigestFinal_ex(md
, digest
, &dsize
))
251 if (okey_len
< dsize
) {
252 memcpy(okey
, digest
, okey_len
);
257 memcpy(okey
, digest
, dsize
);
259 for (cursize
= dsize
; cursize
< okey_len
; cursize
+= dsize
) {
261 if (!EVP_DigestInit_ex(md
, evp_md
, NULL
))
264 if (!EVP_DigestUpdate(md
, key
, key_len
))
267 if (!EVP_DigestUpdate(md
, xcghash
, xcghash_len
))
270 if (!EVP_DigestUpdate(md
, okey
, cursize
))
273 if (!EVP_DigestFinal_ex(md
, digest
, &dsize
))
276 if (okey_len
< cursize
+ dsize
) {
277 memcpy(okey
+ cursize
, digest
, okey_len
- cursize
);
282 memcpy(okey
+ cursize
, digest
, dsize
);
289 OPENSSL_cleanse(digest
, EVP_MAX_MD_SIZE
);