diff --git a/src/common/crypto_dh.c b/src/common/crypto_dh.c
index 625a270254..09e6ca5063 100644
--- a/src/common/crypto_dh.c
+++ b/src/common/crypto_dh.c
@@ -12,6 +12,7 @@
#include "compat_openssl.h"
#include "crypto_dh.h"
#include "crypto_digest.h"
+#include "crypto_hkdf.h"
#include "crypto_util.h"
DISABLE_GCC_WARNING(redundant-decls)
@@ -493,103 +494,6 @@ crypto_dh_free_(crypto_dh_t *dh)
tor_free(dh);
}
-/** Given key_in_len bytes of negotiated randomness in key_in
- * ("K"), expand it into key_out_len bytes of negotiated key material in
- * key_out by taking the first key_out_len bytes of
- * H(K | [00]) | H(K | [01]) | ....
- *
- * This is the key expansion algorithm used in the "TAP" circuit extension
- * mechanism; it shouldn't be used for new protocols.
- *
- * Return 0 on success, -1 on failure.
- */
-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)
-{
- int i, r = -1;
- uint8_t *cp, *tmp = tor_malloc(key_in_len+1);
- uint8_t digest[DIGEST_LEN];
-
- /* If we try to get more than this amount of key data, we'll repeat blocks.*/
- tor_assert(key_out_len <= DIGEST_LEN*256);
-
- memcpy(tmp, key_in, key_in_len);
- for (cp = key_out, i=0; cp < key_out+key_out_len;
- ++i, cp += DIGEST_LEN) {
- tmp[key_in_len] = i;
- if (crypto_digest((char*)digest, (const char *)tmp, key_in_len+1) < 0)
- goto exit;
- memcpy(cp, digest, MIN(DIGEST_LEN, key_out_len-(cp-key_out)));
- }
-
- r = 0;
- exit:
- memwipe(tmp, 0, key_in_len+1);
- tor_free(tmp);
- memwipe(digest, 0, sizeof(digest));
- return r;
-}
-
-/** Expand some secret key material according to RFC5869, using SHA256 as the
- * underlying hash. The key_in_len bytes at key_in are the
- * secret key material; the salt_in_len bytes at salt_in and the
- * info_in_len bytes in info_in_len are the algorithm's "salt"
- * and "info" parameters respectively. On success, write key_out_len
- * bytes to key_out and return 0. Assert on failure.
- */
-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)
-{
- uint8_t prk[DIGEST256_LEN];
- uint8_t tmp[DIGEST256_LEN + 128 + 1];
- uint8_t mac[DIGEST256_LEN];
- int i;
- uint8_t *outp;
- size_t tmp_len;
-
- crypto_hmac_sha256((char*)prk,
- (const char*)salt_in, salt_in_len,
- (const char*)key_in, key_in_len);
-
- /* If we try to get more than this amount of key data, we'll repeat blocks.*/
- tor_assert(key_out_len <= DIGEST256_LEN * 256);
- tor_assert(info_in_len <= 128);
- memset(tmp, 0, sizeof(tmp));
- outp = key_out;
- i = 1;
-
- while (key_out_len) {
- size_t n;
- if (i > 1) {
- memcpy(tmp, mac, DIGEST256_LEN);
- memcpy(tmp+DIGEST256_LEN, info_in, info_in_len);
- tmp[DIGEST256_LEN+info_in_len] = i;
- tmp_len = DIGEST256_LEN + info_in_len + 1;
- } else {
- memcpy(tmp, info_in, info_in_len);
- tmp[info_in_len] = i;
- tmp_len = info_in_len + 1;
- }
- crypto_hmac_sha256((char*)mac,
- (const char*)prk, DIGEST256_LEN,
- (const char*)tmp, tmp_len);
- n = key_out_len < DIGEST256_LEN ? key_out_len : DIGEST256_LEN;
- memcpy(outp, mac, n);
- key_out_len -= n;
- outp += n;
- ++i;
- }
-
- memwipe(tmp, 0, sizeof(tmp));
- memwipe(mac, 0, sizeof(mac));
- return 0;
-}
-
void
crypto_dh_free_all(void)
{
diff --git a/src/common/crypto_dh.h b/src/common/crypto_dh.h
index 7c78d8c907..111c199faa 100644
--- a/src/common/crypto_dh.h
+++ b/src/common/crypto_dh.h
@@ -37,15 +37,6 @@ ssize_t crypto_dh_compute_secret(int severity, crypto_dh_t *dh,
void crypto_dh_free_(crypto_dh_t *dh);
#define crypto_dh_free(dh) FREE_AND_NULL(crypto_dh_t, crypto_dh_free_, (dh))
-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);
-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);
-
/* Crypto DH free */
void crypto_dh_free_all(void);
diff --git a/src/common/crypto_hkdf.c b/src/common/crypto_hkdf.c
new file mode 100644
index 0000000000..6256f632dd
--- /dev/null
+++ b/src/common/crypto_hkdf.c
@@ -0,0 +1,112 @@
+/* Copyright (c) 2001, Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file crypto_hkdf.c
+ * \brief Block of functions related with HKDF utilities and operations.
+ **/
+
+#include "crypto_hkdf.h"
+#include "crypto_util.h"
+#include "crypto_digest.h"
+
+/** Given key_in_len bytes of negotiated randomness in key_in
+ * ("K"), expand it into key_out_len bytes of negotiated key material in
+ * key_out by taking the first key_out_len bytes of
+ * H(K | [00]) | H(K | [01]) | ....
+ *
+ * This is the key expansion algorithm used in the "TAP" circuit extension
+ * mechanism; it shouldn't be used for new protocols.
+ *
+ * Return 0 on success, -1 on failure.
+ */
+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)
+{
+ int i, r = -1;
+ uint8_t *cp, *tmp = tor_malloc(key_in_len+1);
+ uint8_t digest[DIGEST_LEN];
+
+ /* If we try to get more than this amount of key data, we'll repeat blocks.*/
+ tor_assert(key_out_len <= DIGEST_LEN*256);
+
+ memcpy(tmp, key_in, key_in_len);
+ for (cp = key_out, i=0; cp < key_out+key_out_len;
+ ++i, cp += DIGEST_LEN) {
+ tmp[key_in_len] = i;
+ if (crypto_digest((char*)digest, (const char *)tmp, key_in_len+1) < 0)
+ goto exit;
+ memcpy(cp, digest, MIN(DIGEST_LEN, key_out_len-(cp-key_out)));
+ }
+
+ r = 0;
+ exit:
+ memwipe(tmp, 0, key_in_len+1);
+ tor_free(tmp);
+ memwipe(digest, 0, sizeof(digest));
+ return r;
+}
+
+/** Expand some secret key material according to RFC5869, using SHA256 as the
+ * underlying hash. The key_in_len bytes at key_in are the
+ * secret key material; the salt_in_len bytes at salt_in and the
+ * info_in_len bytes in info_in_len are the algorithm's "salt"
+ * and "info" parameters respectively. On success, write key_out_len
+ * bytes to key_out and return 0. Assert on failure.
+ */
+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)
+{
+ uint8_t prk[DIGEST256_LEN];
+ uint8_t tmp[DIGEST256_LEN + 128 + 1];
+ uint8_t mac[DIGEST256_LEN];
+ int i;
+ uint8_t *outp;
+ size_t tmp_len;
+
+ crypto_hmac_sha256((char*)prk,
+ (const char*)salt_in, salt_in_len,
+ (const char*)key_in, key_in_len);
+
+ /* If we try to get more than this amount of key data, we'll repeat blocks.*/
+ tor_assert(key_out_len <= DIGEST256_LEN * 256);
+ tor_assert(info_in_len <= 128);
+ memset(tmp, 0, sizeof(tmp));
+ outp = key_out;
+ i = 1;
+
+ while (key_out_len) {
+ size_t n;
+ if (i > 1) {
+ memcpy(tmp, mac, DIGEST256_LEN);
+ memcpy(tmp+DIGEST256_LEN, info_in, info_in_len);
+ tmp[DIGEST256_LEN+info_in_len] = i;
+ tmp_len = DIGEST256_LEN + info_in_len + 1;
+ } else {
+ memcpy(tmp, info_in, info_in_len);
+ tmp[info_in_len] = i;
+ tmp_len = info_in_len + 1;
+ }
+ crypto_hmac_sha256((char*)mac,
+ (const char*)prk, DIGEST256_LEN,
+ (const char*)tmp, tmp_len);
+ n = key_out_len < DIGEST256_LEN ? key_out_len : DIGEST256_LEN;
+ memcpy(outp, mac, n);
+ key_out_len -= n;
+ outp += n;
+ ++i;
+ }
+
+ memwipe(tmp, 0, sizeof(tmp));
+ memwipe(mac, 0, sizeof(mac));
+ return 0;
+}
+
diff --git a/src/common/crypto_hkdf.h b/src/common/crypto_hkdf.h
new file mode 100644
index 0000000000..5b55172090
--- /dev/null
+++ b/src/common/crypto_hkdf.h
@@ -0,0 +1,28 @@
+/* Copyright (c) 2001, Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file crypto_hkdf.h
+ *
+ * \brief Headers for crypto_hkdf.h
+ **/
+
+#ifndef TOR_CRYPTO_HKDF_H
+#define TOR_CRYPTO_HKDF_H
+
+#include "util.h"
+
+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);
+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);
+
+#endif /* !defined(TOR_CRYPTO_HKDF_H) */
+
diff --git a/src/common/crypto_s2k.c b/src/common/crypto_s2k.c
index 47cb62d076..2977a2d127 100644
--- a/src/common/crypto_s2k.c
+++ b/src/common/crypto_s2k.c
@@ -15,7 +15,7 @@
#include "compat.h"
#include "crypto.h"
#include "crypto_digest.h"
-#include "crypto_dh.h"
+#include "crypto_hkdf.h"
#include "crypto_rand.h"
#include "crypto_s2k.h"
#include "crypto_util.h"
diff --git a/src/common/crypto_util.c b/src/common/crypto_util.c
index 1e1e7284e2..2933579cf9 100644
--- a/src/common/crypto_util.c
+++ b/src/common/crypto_util.c
@@ -106,6 +106,9 @@ memwipe(void *mem, uint8_t byte, size_t sz)
memset(mem, byte, sz);
}
+/** Log all pending crypto errors at level severity. Use
+ * doing to describe our current activities.
+ */
void
crypto_log_errors(int severity, const char *doing)
{
diff --git a/src/common/include.am b/src/common/include.am
index 6dafcea206..c9706c6b4b 100644
--- a/src/common/include.am
+++ b/src/common/include.am
@@ -118,6 +118,7 @@ LIBOR_CRYPTO_A_SRC = \
src/common/crypto_dh.c \
src/common/crypto_digest.c \
src/common/crypto_format.c \
+ src/common/crypto_hkdf.c \
src/common/crypto_openssl_mgt.c \
src/common/crypto_pwbox.c \
src/common/crypto_rand.c \
@@ -175,6 +176,7 @@ COMMONHEADERS = \
src/common/crypto_curve25519.h \
src/common/crypto_ed25519.h \
src/common/crypto_format.h \
+ src/common/crypto_hkdf.h \
src/common/crypto_openssl_mgt.h \
src/common/crypto_pwbox.h \
src/common/crypto_rand.h \
diff --git a/src/or/onion_ntor.c b/src/or/onion_ntor.c
index 74403ac7ae..3df8c2ab60 100644
--- a/src/or/onion_ntor.c
+++ b/src/or/onion_ntor.c
@@ -22,7 +22,7 @@
#define ONION_NTOR_PRIVATE
#include "crypto.h"
-#include "crypto_dh.h"
+#include "crypto_hkdf.h"
#include "crypto_digest.h"
#include "crypto_util.h"
#include "onion_ntor.h"
diff --git a/src/or/or.h b/src/or/or.h
index e64ad1d4b7..30a9828aa8 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -69,6 +69,7 @@
#include "crypto.h"
#include "crypto_format.h"
#include "crypto_dh.h"
+#include "crypto_hkdf.h"
#include "tortls.h"
#include "torlog.h"
#include "container.h"