mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-27 22:03:31 +01:00
Refactor crypto.[ch] into smaller HKDF module.
Add two new files (crypto_hkdf.c, crypto_hkdf.h) as new module of crypto.[ch]. This new module includes all functions and dependencies related to HKDF operations. Those have been removed from crypto.[ch]. Follows #24658. Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
This commit is contained in:
parent
827b85e907
commit
d38e7ddf5b
@ -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 <b>key_in_len</b> bytes of negotiated randomness in <b>key_in</b>
|
||||
* ("K"), expand it into <b>key_out_len</b> bytes of negotiated key material in
|
||||
* <b>key_out</b> by taking the first <b>key_out_len</b> 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 <b>key_in_len</b> bytes at <b>key_in</b> are the
|
||||
* secret key material; the <b>salt_in_len</b> bytes at <b>salt_in</b> and the
|
||||
* <b>info_in_len</b> bytes in <b>info_in_len</b> are the algorithm's "salt"
|
||||
* and "info" parameters respectively. On success, write <b>key_out_len</b>
|
||||
* bytes to <b>key_out</b> 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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
112
src/common/crypto_hkdf.c
Normal file
112
src/common/crypto_hkdf.c
Normal file
@ -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 <b>key_in_len</b> bytes of negotiated randomness in <b>key_in</b>
|
||||
* ("K"), expand it into <b>key_out_len</b> bytes of negotiated key material in
|
||||
* <b>key_out</b> by taking the first <b>key_out_len</b> 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 <b>key_in_len</b> bytes at <b>key_in</b> are the
|
||||
* secret key material; the <b>salt_in_len</b> bytes at <b>salt_in</b> and the
|
||||
* <b>info_in_len</b> bytes in <b>info_in_len</b> are the algorithm's "salt"
|
||||
* and "info" parameters respectively. On success, write <b>key_out_len</b>
|
||||
* bytes to <b>key_out</b> 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;
|
||||
}
|
||||
|
28
src/common/crypto_hkdf.h
Normal file
28
src/common/crypto_hkdf.h
Normal file
@ -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) */
|
||||
|
@ -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"
|
||||
|
@ -106,6 +106,9 @@ memwipe(void *mem, uint8_t byte, size_t sz)
|
||||
memset(mem, byte, sz);
|
||||
}
|
||||
|
||||
/** Log all pending crypto errors at level <b>severity</b>. Use
|
||||
* <b>doing</b> to describe our current activities.
|
||||
*/
|
||||
void
|
||||
crypto_log_errors(int severity, const char *doing)
|
||||
{
|
||||
|
@ -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 \
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user