1 /* Copyright (c) 2001, Matej Pfajfar.
2 * Copyright (c) 2001-2004, Roger Dingledine.
3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
4 * Copyright (c) 2007-2021, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
9 * \brief Block of functions related with HKDF utilities and operations.
12 #include "lib/crypt_ops/crypto_hkdf.h"
13 #include "lib/crypt_ops/crypto_util.h"
14 #include "lib/crypt_ops/crypto_digest.h"
16 #include "lib/crypt_ops/crypto_openssl_mgt.h"
17 #include "lib/intmath/cmp.h"
18 #include "lib/log/util_bug.h"
21 #include <openssl/evp.h>
22 #include <openssl/opensslv.h>
24 #if defined(HAVE_ERR_LOAD_KDF_STRINGS)
25 #include <openssl/kdf.h>
26 #define HAVE_OPENSSL_HKDF 1
28 #endif /* defined(ENABLE_OPENSSL) */
32 /** Given <b>key_in_len</b> bytes of negotiated randomness in <b>key_in</b>
33 * ("K"), expand it into <b>key_out_len</b> bytes of negotiated key material in
34 * <b>key_out</b> by taking the first <b>key_out_len</b> bytes of
35 * H(K | [00]) | H(K | [01]) | ....
37 * This is the key expansion algorithm used in the "TAP" circuit extension
38 * mechanism; it shouldn't be used for new protocols.
40 * Return 0 on success, -1 on failure.
43 crypto_expand_key_material_TAP(const uint8_t *key_in
, size_t key_in_len
,
44 uint8_t *key_out
, size_t key_out_len
)
47 uint8_t *cp
, *tmp
= tor_malloc(key_in_len
+1);
48 uint8_t digest
[DIGEST_LEN
];
50 /* If we try to get more than this amount of key data, we'll repeat blocks.*/
51 tor_assert(key_out_len
<= DIGEST_LEN
*256);
53 memcpy(tmp
, key_in
, key_in_len
);
54 for (cp
= key_out
, i
=0; cp
< key_out
+key_out_len
;
55 ++i
, cp
+= DIGEST_LEN
) {
57 if (crypto_digest((char*)digest
, (const char *)tmp
, key_in_len
+1) < 0)
59 memcpy(cp
, digest
, MIN(DIGEST_LEN
, key_out_len
-(cp
-key_out
)));
64 memwipe(tmp
, 0, key_in_len
+1);
66 memwipe(digest
, 0, sizeof(digest
));
70 #ifdef HAVE_OPENSSL_HKDF
72 * Perform RFC5869 HKDF computation using OpenSSL (only to be called from
73 * crypto_expand_key_material_rfc5869_sha256_openssl). Note that OpenSSL
74 * requires input key to be nonempty and salt length to be equal or less
78 crypto_expand_key_material_rfc5869_sha256_openssl(
79 const uint8_t *key_in
, size_t key_in_len
,
80 const uint8_t *salt_in
, size_t salt_in_len
,
81 const uint8_t *info_in
, size_t info_in_len
,
82 uint8_t *key_out
, size_t key_out_len
)
85 EVP_PKEY_CTX
*evp_pkey_ctx
= EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF
, NULL
);
86 tor_assert(evp_pkey_ctx
);
87 tor_assert(key_in_len
!= 0);
88 tor_assert(salt_in_len
<= 1024);
90 r
= EVP_PKEY_derive_init(evp_pkey_ctx
);
93 r
= EVP_PKEY_CTX_set_hkdf_md(evp_pkey_ctx
, EVP_sha256());
96 r
= EVP_PKEY_CTX_set1_hkdf_salt(evp_pkey_ctx
, salt_in
, (int)salt_in_len
);
99 r
= EVP_PKEY_CTX_set1_hkdf_key(evp_pkey_ctx
, key_in
, (int)key_in_len
);
102 r
= EVP_PKEY_CTX_add1_hkdf_info(evp_pkey_ctx
, info_in
, (int)info_in_len
);
105 r
= EVP_PKEY_derive(evp_pkey_ctx
, key_out
, &key_out_len
);
108 EVP_PKEY_CTX_free(evp_pkey_ctx
);
112 #else /* !defined(HAVE_OPENSSL_HKDF) */
115 * Perform RFC5869 HKDF computation using our own legacy implementation.
116 * Only to be called from crypto_expand_key_material_rfc5869_sha256_openssl.
119 crypto_expand_key_material_rfc5869_sha256_legacy(
120 const uint8_t *key_in
, size_t key_in_len
,
121 const uint8_t *salt_in
, size_t salt_in_len
,
122 const uint8_t *info_in
, size_t info_in_len
,
123 uint8_t *key_out
, size_t key_out_len
)
125 uint8_t prk
[DIGEST256_LEN
];
126 uint8_t tmp
[DIGEST256_LEN
+ 128 + 1];
127 uint8_t mac
[DIGEST256_LEN
];
132 crypto_hmac_sha256((char*)prk
,
133 (const char*)salt_in
, salt_in_len
,
134 (const char*)key_in
, key_in_len
);
136 /* If we try to get more than this amount of key data, we'll repeat blocks.*/
137 tor_assert(key_out_len
<= DIGEST256_LEN
* 256);
138 tor_assert(info_in_len
<= 128);
139 memset(tmp
, 0, sizeof(tmp
));
143 while (key_out_len
) {
146 memcpy(tmp
, mac
, DIGEST256_LEN
);
147 memcpy(tmp
+DIGEST256_LEN
, info_in
, info_in_len
);
148 tmp
[DIGEST256_LEN
+info_in_len
] = i
;
149 tmp_len
= DIGEST256_LEN
+ info_in_len
+ 1;
151 memcpy(tmp
, info_in
, info_in_len
);
152 tmp
[info_in_len
] = i
;
153 tmp_len
= info_in_len
+ 1;
155 crypto_hmac_sha256((char*)mac
,
156 (const char*)prk
, DIGEST256_LEN
,
157 (const char*)tmp
, tmp_len
);
158 n
= key_out_len
< DIGEST256_LEN
? key_out_len
: DIGEST256_LEN
;
159 memcpy(outp
, mac
, n
);
165 memwipe(tmp
, 0, sizeof(tmp
));
166 memwipe(mac
, 0, sizeof(mac
));
169 #endif /* defined(HAVE_OPENSSL_HKDF) */
171 /** Expand some secret key material according to RFC5869, using SHA256 as the
172 * underlying hash. The <b>key_in_len</b> bytes at <b>key_in</b> are the
173 * secret key material; the <b>salt_in_len</b> bytes at <b>salt_in</b> and the
174 * <b>info_in_len</b> bytes in <b>info_in_len</b> are the algorithm's "salt"
175 * and "info" parameters respectively. On success, write <b>key_out_len</b>
176 * bytes to <b>key_out</b> and return 0. Assert on failure.
179 crypto_expand_key_material_rfc5869_sha256(
180 const uint8_t *key_in
, size_t key_in_len
,
181 const uint8_t *salt_in
, size_t salt_in_len
,
182 const uint8_t *info_in
, size_t info_in_len
,
183 uint8_t *key_out
, size_t key_out_len
)
186 tor_assert(key_in_len
> 0);
188 #ifdef HAVE_OPENSSL_HKDF
189 return crypto_expand_key_material_rfc5869_sha256_openssl(key_in
,
191 salt_in_len
, info_in
,
193 key_out
, key_out_len
);
194 #else /* !defined(HAVE_OPENSSL_HKDF) */
195 return crypto_expand_key_material_rfc5869_sha256_legacy(key_in
,
197 salt_in_len
, info_in
,
199 key_out
, key_out_len
);
200 #endif /* defined(HAVE_OPENSSL_HKDF) */