Tor 0.4.9.2-alpha-dev
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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#include <openssl/kdf.h>
24#define HAVE_OPENSSL_HKDF
25#endif /* defined(ENABLE_OPENSSL) */
26
27#include <string.h>
28
29/** Given <b>key_in_len</b> bytes of negotiated randomness in <b>key_in</b>
30 * ("K"), expand it into <b>key_out_len</b> bytes of negotiated key material in
31 * <b>key_out</b> by taking the first <b>key_out_len</b> bytes of
32 * H(K | [00]) | H(K | [01]) | ....
33 *
34 * This is the key expansion algorithm used in the "TAP" circuit extension
35 * mechanism; it shouldn't be used for new protocols.
36 *
37 * Return 0 on success, -1 on failure.
38 */
39int
40crypto_expand_key_material_TAP(const uint8_t *key_in, size_t key_in_len,
41 uint8_t *key_out, size_t key_out_len)
42{
43 int i, r = -1;
44 uint8_t *cp, *tmp = tor_malloc(key_in_len+1);
45 uint8_t digest[DIGEST_LEN];
46
47 /* If we try to get more than this amount of key data, we'll repeat blocks.*/
48 tor_assert(key_out_len <= DIGEST_LEN*256);
49
50 memcpy(tmp, key_in, key_in_len);
51 for (cp = key_out, i=0; cp < key_out+key_out_len;
52 ++i, cp += DIGEST_LEN) {
53 tmp[key_in_len] = i;
54 if (crypto_digest((char*)digest, (const char *)tmp, key_in_len+1) < 0)
55 goto exit;
56 memcpy(cp, digest, MIN(DIGEST_LEN, key_out_len-(cp-key_out)));
57 }
58
59 r = 0;
60 exit:
61 memwipe(tmp, 0, key_in_len+1);
62 tor_free(tmp);
63 memwipe(digest, 0, sizeof(digest));
64 return r;
65}
66
67#ifdef HAVE_OPENSSL_HKDF
68/**
69 * Perform RFC5869 HKDF computation using OpenSSL (only to be called from
70 * crypto_expand_key_material_rfc5869_sha256_openssl). Note that OpenSSL
71 * requires input key to be nonempty and salt length to be equal or less
72 * than 1024.
73 */
74static int
75crypto_expand_key_material_rfc5869_sha256_openssl(
76 const uint8_t *key_in, size_t key_in_len,
77 const uint8_t *salt_in, size_t salt_in_len,
78 const uint8_t *info_in, size_t info_in_len,
79 uint8_t *key_out, size_t key_out_len)
80{
81 int r;
82 EVP_PKEY_CTX *evp_pkey_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
83 tor_assert(evp_pkey_ctx);
84 tor_assert(key_in_len != 0);
85 tor_assert(salt_in_len <= 1024);
86
87 r = EVP_PKEY_derive_init(evp_pkey_ctx);
88 tor_assert(r == 1);
89
90 r = EVP_PKEY_CTX_set_hkdf_md(evp_pkey_ctx, EVP_sha256());
91 tor_assert(r == 1);
92
93 r = EVP_PKEY_CTX_set1_hkdf_salt(evp_pkey_ctx, salt_in, (int)salt_in_len);
94 tor_assert(r == 1);
95
96 r = EVP_PKEY_CTX_set1_hkdf_key(evp_pkey_ctx, key_in, (int)key_in_len);
97 tor_assert(r == 1);
98
99 r = EVP_PKEY_CTX_add1_hkdf_info(evp_pkey_ctx, info_in, (int)info_in_len);
100 tor_assert(r == 1);
101
102 r = EVP_PKEY_derive(evp_pkey_ctx, key_out, &key_out_len);
103 tor_assert(r == 1);
104
105 EVP_PKEY_CTX_free(evp_pkey_ctx);
106 return 0;
107}
108
109#else /* !defined(HAVE_OPENSSL_HKDF) */
110
111/**
112 * Perform RFC5869 HKDF computation using our own legacy implementation.
113 * Only to be called from crypto_expand_key_material_rfc5869_sha256_openssl.
114 */
115static int
117 const uint8_t *key_in, size_t key_in_len,
118 const uint8_t *salt_in, size_t salt_in_len,
119 const uint8_t *info_in, size_t info_in_len,
120 uint8_t *key_out, size_t key_out_len)
121{
122 uint8_t prk[DIGEST256_LEN];
123 uint8_t tmp[DIGEST256_LEN + 128 + 1];
124 uint8_t mac[DIGEST256_LEN];
125 int i;
126 uint8_t *outp;
127 size_t tmp_len;
128
129 crypto_hmac_sha256((char*)prk,
130 (const char*)salt_in, salt_in_len,
131 (const char*)key_in, key_in_len);
132
133 /* If we try to get more than this amount of key data, we'll repeat blocks.*/
134 tor_assert(key_out_len <= DIGEST256_LEN * 256);
135 tor_assert(info_in_len <= 128);
136 memset(tmp, 0, sizeof(tmp));
137 outp = key_out;
138 i = 1;
139
140 while (key_out_len) {
141 size_t n;
142 if (i > 1) {
143 memcpy(tmp, mac, DIGEST256_LEN);
144 memcpy(tmp+DIGEST256_LEN, info_in, info_in_len);
145 tmp[DIGEST256_LEN+info_in_len] = i;
146 tmp_len = DIGEST256_LEN + info_in_len + 1;
147 } else {
148 memcpy(tmp, info_in, info_in_len);
149 tmp[info_in_len] = i;
150 tmp_len = info_in_len + 1;
151 }
152 crypto_hmac_sha256((char*)mac,
153 (const char*)prk, DIGEST256_LEN,
154 (const char*)tmp, tmp_len);
155 n = key_out_len < DIGEST256_LEN ? key_out_len : DIGEST256_LEN;
156 memcpy(outp, mac, n);
157 key_out_len -= n;
158 outp += n;
159 ++i;
160 }
161
162 memwipe(tmp, 0, sizeof(tmp));
163 memwipe(mac, 0, sizeof(mac));
164 return 0;
165}
166#endif /* defined(HAVE_OPENSSL_HKDF) */
167
168/** Expand some secret key material according to RFC5869, using SHA256 as the
169 * underlying hash. The <b>key_in_len</b> bytes at <b>key_in</b> are the
170 * secret key material; the <b>salt_in_len</b> bytes at <b>salt_in</b> and the
171 * <b>info_in_len</b> bytes in <b>info_in_len</b> are the algorithm's "salt"
172 * and "info" parameters respectively. On success, write <b>key_out_len</b>
173 * bytes to <b>key_out</b> and return 0. Assert on failure.
174 */
175int
177 const uint8_t *key_in, size_t key_in_len,
178 const uint8_t *salt_in, size_t salt_in_len,
179 const uint8_t *info_in, size_t info_in_len,
180 uint8_t *key_out, size_t key_out_len)
181{
182 tor_assert(key_in);
183 tor_assert(key_in_len > 0);
184
185#ifdef HAVE_OPENSSL_HKDF
186 return crypto_expand_key_material_rfc5869_sha256_openssl(key_in,
187 key_in_len, salt_in,
188 salt_in_len, info_in,
189 info_in_len,
190 key_out, key_out_len);
191#else /* !defined(HAVE_OPENSSL_HKDF) */
193 key_in_len, salt_in,
194 salt_in_len, info_in,
195 info_in_len,
196 key_out, key_out_len);
197#endif /* defined(HAVE_OPENSSL_HKDF) */
198}
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:40
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:116
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:176
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:56
Macros to manage assertions, fatal and non-fatal.
#define tor_assert(expr)
Definition: util_bug.h:103