tor  0.4.0.1-alpha
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-2019, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
6 
15 
17 #include "lib/intmath/cmp.h"
18 #include "lib/log/util_bug.h"
19 
20 #ifdef ENABLE_OPENSSL
21 #include <openssl/opensslv.h>
22 
23 #if defined(HAVE_ERR_LOAD_KDF_STRINGS)
24 #include <openssl/kdf.h>
25 #define HAVE_OPENSSL_HKDF 1
26 #endif
27 #endif
28 
29 #include <string.h>
30 
41 int
42 crypto_expand_key_material_TAP(const uint8_t *key_in, size_t key_in_len,
43  uint8_t *key_out, size_t key_out_len)
44 {
45  int i, r = -1;
46  uint8_t *cp, *tmp = tor_malloc(key_in_len+1);
47  uint8_t digest[DIGEST_LEN];
48 
49  /* If we try to get more than this amount of key data, we'll repeat blocks.*/
50  tor_assert(key_out_len <= DIGEST_LEN*256);
51 
52  memcpy(tmp, key_in, key_in_len);
53  for (cp = key_out, i=0; cp < key_out+key_out_len;
54  ++i, cp += DIGEST_LEN) {
55  tmp[key_in_len] = i;
56  if (crypto_digest((char*)digest, (const char *)tmp, key_in_len+1) < 0)
57  goto exit;
58  memcpy(cp, digest, MIN(DIGEST_LEN, key_out_len-(cp-key_out)));
59  }
60 
61  r = 0;
62  exit:
63  memwipe(tmp, 0, key_in_len+1);
64  tor_free(tmp);
65  memwipe(digest, 0, sizeof(digest));
66  return r;
67 }
68 
69 #ifdef HAVE_OPENSSL_HKDF
70 
76 static int
77 crypto_expand_key_material_rfc5869_sha256_openssl(
78  const uint8_t *key_in, size_t key_in_len,
79  const uint8_t *salt_in, size_t salt_in_len,
80  const uint8_t *info_in, size_t info_in_len,
81  uint8_t *key_out, size_t key_out_len)
82 {
83  int r;
84  EVP_PKEY_CTX *evp_pkey_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
85  tor_assert(evp_pkey_ctx);
86  tor_assert(key_in_len != 0);
87  tor_assert(salt_in_len <= 1024);
88 
89  r = EVP_PKEY_derive_init(evp_pkey_ctx);
90  tor_assert(r == 1);
91 
92  r = EVP_PKEY_CTX_set_hkdf_md(evp_pkey_ctx, EVP_sha256());
93  tor_assert(r == 1);
94 
95  r = EVP_PKEY_CTX_set1_hkdf_salt(evp_pkey_ctx, salt_in, (int)salt_in_len);
96  tor_assert(r == 1);
97 
98  r = EVP_PKEY_CTX_set1_hkdf_key(evp_pkey_ctx, key_in, (int)key_in_len);
99  tor_assert(r == 1);
100 
101  r = EVP_PKEY_CTX_add1_hkdf_info(evp_pkey_ctx, info_in, (int)info_in_len);
102  tor_assert(r == 1);
103 
104  r = EVP_PKEY_derive(evp_pkey_ctx, key_out, &key_out_len);
105  tor_assert(r == 1);
106 
107  EVP_PKEY_CTX_free(evp_pkey_ctx);
108  return 0;
109 }
110 
111 #else
112 
117 static int
119  const uint8_t *key_in, size_t key_in_len,
120  const uint8_t *salt_in, size_t salt_in_len,
121  const uint8_t *info_in, size_t info_in_len,
122  uint8_t *key_out, size_t key_out_len)
123 {
124  uint8_t prk[DIGEST256_LEN];
125  uint8_t tmp[DIGEST256_LEN + 128 + 1];
126  uint8_t mac[DIGEST256_LEN];
127  int i;
128  uint8_t *outp;
129  size_t tmp_len;
130 
131  crypto_hmac_sha256((char*)prk,
132  (const char*)salt_in, salt_in_len,
133  (const char*)key_in, key_in_len);
134 
135  /* If we try to get more than this amount of key data, we'll repeat blocks.*/
136  tor_assert(key_out_len <= DIGEST256_LEN * 256);
137  tor_assert(info_in_len <= 128);
138  memset(tmp, 0, sizeof(tmp));
139  outp = key_out;
140  i = 1;
141 
142  while (key_out_len) {
143  size_t n;
144  if (i > 1) {
145  memcpy(tmp, mac, DIGEST256_LEN);
146  memcpy(tmp+DIGEST256_LEN, info_in, info_in_len);
147  tmp[DIGEST256_LEN+info_in_len] = i;
148  tmp_len = DIGEST256_LEN + info_in_len + 1;
149  } else {
150  memcpy(tmp, info_in, info_in_len);
151  tmp[info_in_len] = i;
152  tmp_len = info_in_len + 1;
153  }
154  crypto_hmac_sha256((char*)mac,
155  (const char*)prk, DIGEST256_LEN,
156  (const char*)tmp, tmp_len);
157  n = key_out_len < DIGEST256_LEN ? key_out_len : DIGEST256_LEN;
158  memcpy(outp, mac, n);
159  key_out_len -= n;
160  outp += n;
161  ++i;
162  }
163 
164  memwipe(tmp, 0, sizeof(tmp));
165  memwipe(mac, 0, sizeof(mac));
166  return 0;
167 }
168 #endif
169 
177 int
179  const uint8_t *key_in, size_t key_in_len,
180  const uint8_t *salt_in, size_t salt_in_len,
181  const uint8_t *info_in, size_t info_in_len,
182  uint8_t *key_out, size_t key_out_len)
183 {
184  tor_assert(key_in);
185  tor_assert(key_in_len > 0);
186 
187 #ifdef HAVE_OPENSSL_HKDF
188  return crypto_expand_key_material_rfc5869_sha256_openssl(key_in,
189  key_in_len, salt_in,
190  salt_in_len, info_in,
191  info_in_len,
192  key_out, key_out_len);
193 #else
195  key_in_len, salt_in,
196  salt_in_len, info_in,
197  info_in_len,
198  key_out, key_out_len);
199 #endif
200 }
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:42
Macro definitions for MIN, MAX, and CLAMP.
Headers for crypto_openssl_mgt.c.
#define tor_free(p)
Definition: malloc.h:52
void memwipe(void *mem, uint8_t byte, size_t sz)
Definition: crypto_util.c:57
void crypto_hmac_sha256(char *hmac_out, const char *key, size_t key_len, const char *msg, size_t msg_len)
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:118
#define DIGEST256_LEN
Definition: digest_sizes.h:23
Headers for crypto_hkdf.h.
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:178
Common functions for cryptographic routines.
tor_assert(buffer)
#define DIGEST_LEN
Definition: digest_sizes.h:20
Headers for crypto_digest.c.
Macros to manage assertions, fatal and non-fatal.