mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-11 05:33:47 +01:00
Add a sha256 hmac function, with tests
This commit is contained in:
parent
c0bbcf138f
commit
fdbb9cdf74
@ -1740,6 +1740,74 @@ crypto_hmac_sha1(char *hmac_out,
|
|||||||
(unsigned char*)hmac_out, NULL);
|
(unsigned char*)hmac_out, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Compute the HMAC-SHA-256 of the <b>msg_len</b> bytes in <b>msg</b>, using
|
||||||
|
* the <b>key</b> of length <b>key_len</b>. Store the DIGEST_LEN-byte result
|
||||||
|
* in <b>hmac_out</b>.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
crypto_hmac_sha256(char *hmac_out,
|
||||||
|
const char *key, size_t key_len,
|
||||||
|
const char *msg, size_t msg_len)
|
||||||
|
{
|
||||||
|
#if (OPENSSL_VERSION_NUMBER >= 0x00908000l)
|
||||||
|
/* If we've got OpenSSL >=0.9.8 we can use its hmac implementation. */
|
||||||
|
tor_assert(key_len < INT_MAX);
|
||||||
|
tor_assert(msg_len < INT_MAX);
|
||||||
|
HMAC(EVP_sha256(), key, (int)key_len, (unsigned char*)msg, (int)msg_len,
|
||||||
|
(unsigned char*)hmac_out, NULL);
|
||||||
|
#else
|
||||||
|
/* OpenSSL doesn't have an EVP implementation for SHA256. We'll need
|
||||||
|
to do HMAC on our own.
|
||||||
|
|
||||||
|
HMAC isn't so hard: To compute HMAC(key, msg):
|
||||||
|
1. If len(key) > blocksize, key = H(key).
|
||||||
|
2. If len(key) < blocksize, right-pad key up to blocksize with 0 bytes.
|
||||||
|
3. let ipad = key xor 0x363636363636....36
|
||||||
|
let opad = key xor 0x5c5c5c5c5c5c....5c
|
||||||
|
The result is H(opad | H( ipad | msg ) )
|
||||||
|
*/
|
||||||
|
#define BLOCKSIZE 64
|
||||||
|
#define DIGESTSIZE 32
|
||||||
|
uint8_t k[BLOCKSIZE];
|
||||||
|
uint8_t pad[BLOCKSIZE];
|
||||||
|
uint8_t d[DIGESTSIZE];
|
||||||
|
int i;
|
||||||
|
SHA256_CTX st;
|
||||||
|
|
||||||
|
tor_assert(key_len < INT_MAX);
|
||||||
|
tor_assert(msg_len < INT_MAX);
|
||||||
|
|
||||||
|
if (key_len <= BLOCKSIZE) {
|
||||||
|
memset(k, 0, sizeof(k));
|
||||||
|
memcpy(k, key, key_len); /* not time invariant in key_len */
|
||||||
|
} else {
|
||||||
|
SHA256((const uint8_t *)key, key_len, k);
|
||||||
|
memset(k+DIGESTSIZE, 0, sizeof(k)-DIGESTSIZE);
|
||||||
|
}
|
||||||
|
for (i = 0; i < BLOCKSIZE; ++i)
|
||||||
|
pad[i] = k[i] ^ 0x36;
|
||||||
|
SHA256_Init(&st);
|
||||||
|
SHA256_Update(&st, pad, BLOCKSIZE);
|
||||||
|
SHA256_Update(&st, (uint8_t*)msg, msg_len);
|
||||||
|
SHA256_Final(d, &st);
|
||||||
|
|
||||||
|
for (i = 0; i < BLOCKSIZE; ++i)
|
||||||
|
pad[i] = k[i] ^ 0x5c;
|
||||||
|
SHA256_Init(&st);
|
||||||
|
SHA256_Update(&st, pad, BLOCKSIZE);
|
||||||
|
SHA256_Update(&st, d, DIGESTSIZE);
|
||||||
|
SHA256_Final((uint8_t*)hmac_out, &st);
|
||||||
|
|
||||||
|
/* Now clear everything. */
|
||||||
|
memset(k, 0, sizeof(k));
|
||||||
|
memset(pad, 0, sizeof(pad));
|
||||||
|
memset(d, 0, sizeof(d));
|
||||||
|
memset(&st, 0, sizeof(st));
|
||||||
|
#undef BLOCKSIZE
|
||||||
|
#undef DIGESTSIZE
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* DH */
|
/* DH */
|
||||||
|
|
||||||
/** Shared P parameter for our circuit-crypto DH key exchanges. */
|
/** Shared P parameter for our circuit-crypto DH key exchanges. */
|
||||||
|
@ -196,6 +196,9 @@ void crypto_digest_assign(crypto_digest_env_t *into,
|
|||||||
void crypto_hmac_sha1(char *hmac_out,
|
void crypto_hmac_sha1(char *hmac_out,
|
||||||
const char *key, size_t key_len,
|
const char *key, size_t key_len,
|
||||||
const char *msg, size_t msg_len);
|
const char *msg, size_t msg_len);
|
||||||
|
void crypto_hmac_sha256(char *hmac_out,
|
||||||
|
const char *key, size_t key_len,
|
||||||
|
const char *msg, size_t msg_len);
|
||||||
|
|
||||||
/* Key negotiation */
|
/* Key negotiation */
|
||||||
#define DH_TYPE_CIRCUIT 1
|
#define DH_TYPE_CIRCUIT 1
|
||||||
|
@ -231,7 +231,7 @@ test_crypto_sha(void)
|
|||||||
{
|
{
|
||||||
crypto_digest_env_t *d1 = NULL, *d2 = NULL;
|
crypto_digest_env_t *d1 = NULL, *d2 = NULL;
|
||||||
int i;
|
int i;
|
||||||
char key[80];
|
char key[160];
|
||||||
char digest[32];
|
char digest[32];
|
||||||
char data[50];
|
char data[50];
|
||||||
char d_out1[DIGEST_LEN], d_out2[DIGEST256_LEN];
|
char d_out1[DIGEST_LEN], d_out2[DIGEST256_LEN];
|
||||||
@ -276,6 +276,75 @@ test_crypto_sha(void)
|
|||||||
test_streq(hex_str(digest, 20),
|
test_streq(hex_str(digest, 20),
|
||||||
"AA4AE5E15272D00E95705637CE8A3B55ED402112");
|
"AA4AE5E15272D00E95705637CE8A3B55ED402112");
|
||||||
|
|
||||||
|
/* Test HMAC-SHA256 with test cases from wikipedia and RFC 4231 */
|
||||||
|
|
||||||
|
/* Case empty (wikipedia) */
|
||||||
|
crypto_hmac_sha256(digest, "", 0, "", 0);
|
||||||
|
test_streq(hex_str(digest, 32),
|
||||||
|
"B613679A0814D9EC772F95D778C35FC5FF1697C493715653C6C712144292C5AD");
|
||||||
|
|
||||||
|
/* Case quick-brown (wikipedia) */
|
||||||
|
crypto_hmac_sha256(digest, "key", 3,
|
||||||
|
"The quick brown fox jumps over the lazy dog", 43);
|
||||||
|
test_streq(hex_str(digest, 32),
|
||||||
|
"F7BC83F430538424B13298E6AA6FB143EF4D59A14946175997479DBC2D1A3CD8");
|
||||||
|
|
||||||
|
/* "Test Case 1" from RFC 4231 */
|
||||||
|
memset(key, 0x0b, 20);
|
||||||
|
crypto_hmac_sha256(digest, key, 20, "Hi There", 8);
|
||||||
|
test_memeq_hex(digest,
|
||||||
|
"b0344c61d8db38535ca8afceaf0bf12b"
|
||||||
|
"881dc200c9833da726e9376c2e32cff7");
|
||||||
|
|
||||||
|
/* "Test Case 2" from RFC 4231 */
|
||||||
|
memset(key, 0x0b, 20);
|
||||||
|
crypto_hmac_sha256(digest, "Jefe", 4, "what do ya want for nothing?", 28);
|
||||||
|
test_memeq_hex(digest,
|
||||||
|
"5bdcc146bf60754e6a042426089575c7"
|
||||||
|
"5a003f089d2739839dec58b964ec3843");
|
||||||
|
|
||||||
|
/* "Test case 3" from RFC 4231 */
|
||||||
|
memset(key, 0xaa, 20);
|
||||||
|
memset(data, 0xdd, 50);
|
||||||
|
crypto_hmac_sha256(digest, key, 20, data, 50);
|
||||||
|
test_memeq_hex(digest,
|
||||||
|
"773ea91e36800e46854db8ebd09181a7"
|
||||||
|
"2959098b3ef8c122d9635514ced565fe");
|
||||||
|
|
||||||
|
/* "Test case 4" from RFC 4231 */
|
||||||
|
base16_decode(key, 25,
|
||||||
|
"0102030405060708090a0b0c0d0e0f10111213141516171819", 50);
|
||||||
|
memset(data, 0xcd, 50);
|
||||||
|
crypto_hmac_sha256(digest, key, 25, data, 50);
|
||||||
|
test_memeq_hex(digest,
|
||||||
|
"82558a389a443c0ea4cc819899f2083a"
|
||||||
|
"85f0faa3e578f8077a2e3ff46729665b");
|
||||||
|
|
||||||
|
/* "Test case 5" from RFC 4231 */
|
||||||
|
memset(key, 0x0c, 20);
|
||||||
|
crypto_hmac_sha256(digest, key, 20, "Test With Truncation", 20);
|
||||||
|
test_memeq_hex(digest,
|
||||||
|
"a3b6167473100ee06e0c796c2955552b");
|
||||||
|
|
||||||
|
/* "Test case 6" from RFC 4231 */
|
||||||
|
memset(key, 0xaa, 131);
|
||||||
|
crypto_hmac_sha256(digest, key, 131,
|
||||||
|
"Test Using Larger Than Block-Size Key - Hash Key First",
|
||||||
|
54);
|
||||||
|
test_memeq_hex(digest,
|
||||||
|
"60e431591ee0b67f0d8a26aacbf5b77f"
|
||||||
|
"8e0bc6213728c5140546040f0ee37f54");
|
||||||
|
|
||||||
|
/* "Test case 7" from RFC 4231 */
|
||||||
|
memset(key, 0xaa, 131);
|
||||||
|
crypto_hmac_sha256(digest, key, 131,
|
||||||
|
"This is a test using a larger than block-size key and a "
|
||||||
|
"larger than block-size data. The key needs to be hashed "
|
||||||
|
"before being used by the HMAC algorithm.", 152);
|
||||||
|
test_memeq_hex(digest,
|
||||||
|
"9b09ffa71b942fcb27635fbcd5b0e944"
|
||||||
|
"bfdc63644f0713938a7f51535c3a35e2");
|
||||||
|
|
||||||
/* Incremental digest code. */
|
/* Incremental digest code. */
|
||||||
d1 = crypto_new_digest_env();
|
d1 = crypto_new_digest_env();
|
||||||
test_assert(d1);
|
test_assert(d1);
|
||||||
|
Loading…
Reference in New Issue
Block a user