Tor  0.4.7.0-alpha-dev
crypto_hkdf.c
Go to the documentation of this file.
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 */
6 
7 /**
8  * \file crypto_hkdf.c
9  * \brief Block of functions related with HKDF utilities and operations.
10  **/
11 
15 
17 #include "lib/intmath/cmp.h"
18 #include "lib/log/util_bug.h"
19 
20 #ifdef ENABLE_OPENSSL
21 #include <openssl/evp.h>
22 #include <openssl/opensslv.h>
23 
24 #if defined(HAVE_ERR_LOAD_KDF_STRINGS)
25 #include <openssl/kdf.h>
26 #define HAVE_OPENSSL_HKDF 1
27 #endif
28 #endif /* defined(ENABLE_OPENSSL) */
29 
30 #include <string.h>
31 
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]) | ....
36  *
37  * This is the key expansion algorithm used in the "TAP" circuit extension
38  * mechanism; it shouldn't be used for new protocols.
39  *
40  * Return 0 on success, -1 on failure.
41  */
42 int
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)
45 {
46  int i, r = -1;
47  uint8_t *cp, *tmp = tor_malloc(key_in_len+1);
48  uint8_t digest[DIGEST_LEN];
49 
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);
52 
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) {
56  tmp[key_in_len] = i;
57  if (crypto_digest((char*)digest, (const char *)tmp, key_in_len+1) < 0)
58  goto exit;
59  memcpy(cp, digest, MIN(DIGEST_LEN, key_out_len-(cp-key_out)));
60  }
61 
62  r = 0;
63  exit:
64  memwipe(tmp, 0, key_in_len+1);
65  tor_free(tmp);
66  memwipe(digest, 0, sizeof(digest));
67  return r;
68 }
69 
70 #ifdef HAVE_OPENSSL_HKDF
71 /**
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
75  * than 1024.
76  */
77 static int
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)
83 {
84  int r;
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);
89 
90  r = EVP_PKEY_derive_init(evp_pkey_ctx);
91  tor_assert(r == 1);
92 
93  r = EVP_PKEY_CTX_set_hkdf_md(evp_pkey_ctx, EVP_sha256());
94  tor_assert(r == 1);
95 
96  r = EVP_PKEY_CTX_set1_hkdf_salt(evp_pkey_ctx, salt_in, (int)salt_in_len);
97  tor_assert(r == 1);
98 
99  r = EVP_PKEY_CTX_set1_hkdf_key(evp_pkey_ctx, key_in, (int)key_in_len);
100  tor_assert(r == 1);
101 
102  r = EVP_PKEY_CTX_add1_hkdf_info(evp_pkey_ctx, info_in, (int)info_in_len);
103  tor_assert(r == 1);
104 
105  r = EVP_PKEY_derive(evp_pkey_ctx, key_out, &key_out_len);
106  tor_assert(r == 1);
107 
108  EVP_PKEY_CTX_free(evp_pkey_ctx);
109  return 0;
110 }
111 
112 #else /* !defined(HAVE_OPENSSL_HKDF) */
113 
114 /**
115  * Perform RFC5869 HKDF computation using our own legacy implementation.
116  * Only to be called from crypto_expand_key_material_rfc5869_sha256_openssl.
117  */
118 static int
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)
124 {
125  uint8_t prk[DIGEST256_LEN];
126  uint8_t tmp[DIGEST256_LEN + 128 + 1];
127  uint8_t mac[DIGEST256_LEN];
128  int i;
129  uint8_t *outp;
130  size_t tmp_len;
131 
132  crypto_hmac_sha256((char*)prk,
133  (const char*)salt_in, salt_in_len,
134  (const char*)key_in, key_in_len);
135 
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));
140  outp = key_out;
141  i = 1;
142 
143  while (key_out_len) {
144  size_t n;
145  if (i > 1) {
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;
150  } else {
151  memcpy(tmp, info_in, info_in_len);
152  tmp[info_in_len] = i;
153  tmp_len = info_in_len + 1;
154  }
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);
160  key_out_len -= n;
161  outp += n;
162  ++i;
163  }
164 
165  memwipe(tmp, 0, sizeof(tmp));
166  memwipe(mac, 0, sizeof(mac));
167  return 0;
168 }
169 #endif /* defined(HAVE_OPENSSL_HKDF) */
170 
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.
177  */
178 int
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)
184 {
185  tor_assert(key_in);
186  tor_assert(key_in_len > 0);
187 
188 #ifdef HAVE_OPENSSL_HKDF
189  return crypto_expand_key_material_rfc5869_sha256_openssl(key_in,
190  key_in_len, salt_in,
191  salt_in_len, info_in,
192  info_in_len,
193  key_out, key_out_len);
194 #else /* !defined(HAVE_OPENSSL_HKDF) */
196  key_in_len, salt_in,
197  salt_in_len, info_in,
198  info_in_len,
199  key_out, key_out_len);
200 #endif /* defined(HAVE_OPENSSL_HKDF) */
201 }
Macro definitions for MIN, MAX, and CLAMP.
Headers for crypto_digest.c.
void crypto_hmac_sha256(char *hmac_out, const char *key, size_t key_len, const char *msg, size_t msg_len)
int crypto_digest(char *digest, const char *m, size_t len)
int crypto_expand_key_material_TAP(const uint8_t *key_in, size_t key_in_len, uint8_t *key_out, size_t key_out_len)
Definition: crypto_hkdf.c:43
static int crypto_expand_key_material_rfc5869_sha256_legacy(const uint8_t *key_in, size_t key_in_len, const uint8_t *salt_in, size_t salt_in_len, const uint8_t *info_in, size_t info_in_len, uint8_t *key_out, size_t key_out_len)
Definition: crypto_hkdf.c:119
int crypto_expand_key_material_rfc5869_sha256(const uint8_t *key_in, size_t key_in_len, const uint8_t *salt_in, size_t salt_in_len, const uint8_t *info_in, size_t info_in_len, uint8_t *key_out, size_t key_out_len)
Definition: crypto_hkdf.c:179
Headers for crypto_hkdf.h.
Headers for crypto_openssl_mgt.c.
void memwipe(void *mem, uint8_t byte, size_t sz)
Definition: crypto_util.c:55
Common functions for cryptographic routines.
#define DIGEST_LEN
Definition: digest_sizes.h:20
#define DIGEST256_LEN
Definition: digest_sizes.h:23
#define tor_free(p)
Definition: malloc.h:52
Macros to manage assertions, fatal and non-fatal.
#define tor_assert(expr)
Definition: util_bug.h:102