From 1bb34487bfe7ecd074b42bafca055adfe89d14df Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Thu, 15 Aug 2013 02:44:26 +0200 Subject: Replace NaCl's HMAC implementation --- src/protocol_ec25519_fhmqvc.c | 57 +++++++++------------- src/sha256.c | 111 ++++++++++++++++++++++++++++++++---------- src/sha256.h | 16 ++++-- 3 files changed, 121 insertions(+), 63 deletions(-) diff --git a/src/protocol_ec25519_fhmqvc.c b/src/protocol_ec25519_fhmqvc.c index f6c170b..75ad055 100644 --- a/src/protocol_ec25519_fhmqvc.c +++ b/src/protocol_ec25519_fhmqvc.c @@ -32,17 +32,18 @@ #include -#include #define PUBLICKEYBYTES 32 #define SECRETKEYBYTES 32 -#define HMACBYTES crypto_auth_hmacsha256_BYTES +#define HMACWORDS FASTD_SHA256_HASH_WORDS +#define HMACBYTES FASTD_SHA256_HASH_BYTES +#define HASHWORDS FASTD_SHA256_HASH_WORDS #define HASHBYTES FASTD_SHA256_HASH_BYTES -#if HASHBYTES != crypto_auth_hmacsha256_KEYBYTES -#error bug: HASHBYTES != crypto_auth_hmacsha256_KEYBYTES +#if HASHWORDS != FASTD_HMACSHA256_KEY_WORDS +#error bug: HASHWORDS != FASTD_HMACSHA256_KEY_WORDS #endif #if HASHBYTES != SECRETKEYBYTES @@ -278,9 +279,8 @@ static void respond_handshake(fastd_context_t *ctx, const fastd_socket_t *sock, const handshake_key_t *handshake_key, const ecc_int256_t *peer_handshake_key, const fastd_handshake_t *handshake, const fastd_method_t *method) { pr_debug(ctx, "responding handshake with %P[%I]...", peer, remote_addr); - uint8_t hashinput[2*PUBLICKEYBYTES]; - uint8_t hashbuf[HASHBYTES]; - uint8_t hmacbuf[HMACBYTES]; + uint32_t hashbuf[HASHWORDS]; + uint32_t hmacbuf[HMACWORDS]; fastd_sha256_blocks(hashbuf, handshake_key->public_key.p, @@ -292,7 +292,7 @@ static void respond_handshake(fastd_context_t *ctx, const fastd_socket_t *sock, ecc_int256_t d = {{0}}, e = {{0}}, eb, s; memcpy(d.p, hashbuf, HASHBYTES/2); - memcpy(e.p, hashbuf+HASHBYTES/2, HASHBYTES/2); + memcpy(e.p, hashbuf+HASHWORDS/2, HASHBYTES/2); d.p[15] |= 0x80; e.p[15] |= 0x80; @@ -321,7 +321,7 @@ static void respond_handshake(fastd_context_t *ctx, const fastd_socket_t *sock, ecc_int256_t sigma; ecc_25519_store_packed(&sigma, &work); - uint8_t shared_handshake_key[HASHBYTES]; + uint32_t shared_handshake_key[HASHWORDS]; fastd_sha256_blocks(shared_handshake_key, handshake_key->public_key.p, peer_handshake_key->p, @@ -330,10 +330,7 @@ static void respond_handshake(fastd_context_t *ctx, const fastd_socket_t *sock, sigma.p, NULL); - memcpy(hashinput, ctx->conf->protocol_config->public_key.p, PUBLICKEYBYTES); - memcpy(hashinput+PUBLICKEYBYTES, handshake_key->public_key.p, PUBLICKEYBYTES); - - crypto_auth_hmacsha256(hmacbuf, hashinput, 2*PUBLICKEYBYTES, shared_handshake_key); + fastd_hmacsha256_blocks(hmacbuf, shared_handshake_key, ctx->conf->protocol_config->public_key.p, handshake_key->public_key.p, NULL); fastd_buffer_t buffer = fastd_handshake_new_reply(ctx, handshake, method, 4*(4+PUBLICKEYBYTES) + 4+HMACBYTES); @@ -373,14 +370,14 @@ static bool establish(fastd_context_t *ctx, fastd_peer_t *peer, const fastd_meth peer->protocol_state->old_session = (protocol_session_t){}; } - uint8_t hash[HASHBYTES]; + uint32_t hash[HASHWORDS]; fastd_sha256_blocks(hash, X->p, Y->p, A->p, B->p, sigma->p, NULL); peer->protocol_state->session.established = ctx->now; peer->protocol_state->session.handshakes_cleaned = false; peer->protocol_state->session.refreshing = false; peer->protocol_state->session.method = method; - peer->protocol_state->session.method_state = method->session_init(ctx, hash, HASHBYTES, initiator); + peer->protocol_state->session.method_state = method->session_init(ctx, (uint8_t*)hash, HASHBYTES, initiator); peer->protocol_state->last_serial = serial; fastd_peer_seen(ctx, peer); @@ -407,9 +404,8 @@ static void finish_handshake(fastd_context_t *ctx, fastd_socket_t *sock, const f const fastd_handshake_t *handshake, const fastd_method_t *method) { pr_debug(ctx, "finishing handshake with %P[%I]...", peer, remote_addr); - uint8_t hashinput[2*PUBLICKEYBYTES]; - uint8_t hashbuf[HASHBYTES]; - uint8_t hmacbuf[HMACBYTES]; + uint32_t hashbuf[HASHWORDS]; + uint32_t hmacbuf[HMACWORDS]; fastd_sha256_blocks(hashbuf, peer_handshake_key->p, @@ -421,7 +417,7 @@ static void finish_handshake(fastd_context_t *ctx, fastd_socket_t *sock, const f ecc_int256_t d = {{0}}, e = {{0}}, da, s; memcpy(d.p, hashbuf, HASHBYTES/2); - memcpy(e.p, hashbuf+HASHBYTES/2, HASHBYTES/2); + memcpy(e.p, hashbuf+HASHWORDS/2, HASHBYTES/2); d.p[15] |= 0x80; e.p[15] |= 0x80; @@ -450,7 +446,7 @@ static void finish_handshake(fastd_context_t *ctx, fastd_socket_t *sock, const f ecc_int256_t sigma; ecc_25519_store_packed(&sigma, &work); - uint8_t shared_handshake_key[HASHBYTES]; + uint32_t shared_handshake_key[HASHWORDS]; fastd_sha256_blocks(shared_handshake_key, peer_handshake_key->p, handshake_key->public_key.p, @@ -459,17 +455,12 @@ static void finish_handshake(fastd_context_t *ctx, fastd_socket_t *sock, const f sigma.p, NULL); - memcpy(hashinput, peer->protocol_config->public_key.p, PUBLICKEYBYTES); - memcpy(hashinput+PUBLICKEYBYTES, peer_handshake_key->p, PUBLICKEYBYTES); - - if(crypto_auth_hmacsha256_verify(handshake->records[RECORD_T].data, hashinput, 2*PUBLICKEYBYTES, shared_handshake_key) != 0) { + if(!fastd_hmacsha256_blocks_verify(handshake->records[RECORD_T].data, shared_handshake_key, peer->protocol_config->public_key.p, peer_handshake_key->p, NULL)) { pr_warn(ctx, "received invalid protocol handshake response from %P[%I]", peer, remote_addr); return; } - memcpy(hashinput, ctx->conf->protocol_config->public_key.p, PUBLICKEYBYTES); - memcpy(hashinput+PUBLICKEYBYTES, handshake_key->public_key.p, PUBLICKEYBYTES); - crypto_auth_hmacsha256(hmacbuf, hashinput, 2*PUBLICKEYBYTES, shared_handshake_key); + fastd_hmacsha256_blocks(hmacbuf, shared_handshake_key, ctx->conf->protocol_config->public_key.p, handshake_key->public_key.p, NULL); if (!establish(ctx, peer, method, sock, local_addr, remote_addr, true, &handshake_key->public_key, peer_handshake_key, &ctx->conf->protocol_config->public_key, &peer->protocol_config->public_key, &sigma, handshake_key->serial)) @@ -491,8 +482,7 @@ static void handle_finish_handshake(fastd_context_t *ctx, fastd_socket_t *sock, const fastd_handshake_t *handshake, const fastd_method_t *method) { pr_debug(ctx, "handling handshake finish with %P[%I]...", peer, remote_addr); - uint8_t hashinput[2*PUBLICKEYBYTES]; - uint8_t hashbuf[HASHBYTES]; + uint32_t hashbuf[HASHWORDS]; fastd_sha256_blocks(hashbuf, handshake_key->public_key.p, @@ -504,7 +494,7 @@ static void handle_finish_handshake(fastd_context_t *ctx, fastd_socket_t *sock, ecc_int256_t d = {{0}}, e = {{0}}, eb, s; memcpy(d.p, hashbuf, HASHBYTES/2); - memcpy(e.p, hashbuf+HASHBYTES/2, HASHBYTES/2); + memcpy(e.p, hashbuf+HASHWORDS/2, HASHBYTES/2); d.p[15] |= 0x80; e.p[15] |= 0x80; @@ -533,7 +523,7 @@ static void handle_finish_handshake(fastd_context_t *ctx, fastd_socket_t *sock, ecc_int256_t sigma; ecc_25519_store_packed(&sigma, &work); - uint8_t shared_handshake_key[HASHBYTES]; + uint32_t shared_handshake_key[HASHWORDS]; fastd_sha256_blocks(shared_handshake_key, handshake_key->public_key.p, peer_handshake_key->p, @@ -542,10 +532,7 @@ static void handle_finish_handshake(fastd_context_t *ctx, fastd_socket_t *sock, sigma.p, NULL); - memcpy(hashinput, peer->protocol_config->public_key.p, PUBLICKEYBYTES); - memcpy(hashinput+PUBLICKEYBYTES, peer_handshake_key->p, PUBLICKEYBYTES); - - if(crypto_auth_hmacsha256_verify(handshake->records[RECORD_T].data, hashinput, 2*PUBLICKEYBYTES, shared_handshake_key) != 0) { + if (!fastd_hmacsha256_blocks_verify(handshake->records[RECORD_T].data, shared_handshake_key, peer->protocol_config->public_key.p, peer_handshake_key->p, NULL)) { pr_warn(ctx, "received invalid protocol handshake finish from %P[%I]", peer, remote_addr); return; } diff --git a/src/sha256.c b/src/sha256.c index 639185c..4722272 100644 --- a/src/sha256.c +++ b/src/sha256.c @@ -27,7 +27,6 @@ #include "sha256.h" #include -#include #include #include @@ -37,7 +36,7 @@ static inline uint32_t rotr(uint32_t x, int r) { return (x >> r) | (x << (32-r)); } -void fastd_sha256_blocks(uint8_t out[FASTD_SHA256_HASH_BYTES], ...) { +static void sha256_blocks_va(uint32_t out[FASTD_SHA256_HASH_WORDS], const uint32_t *in1, const uint32_t *in2, va_list ap) { static const uint32_t k[64] = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, @@ -59,28 +58,11 @@ void fastd_sha256_blocks(uint8_t out[FASTD_SHA256_HASH_BYTES], ...) { 0x1f83d9ab, 0x5be0cd19 }; - unsigned count = 0, i; - va_list ap; - const uint32_t *in1, *in2; - - va_start(ap, out); + unsigned count = in2 ? 2 : in1 ? 1 : 0, i; - do { + while (true) { uint32_t w[64], v[8]; - in1 = va_arg(ap, const uint32_t*); - - if (in1) { - count++; - in2 = va_arg(ap, const uint32_t*); - - if (in2) - count++; - } - else { - in2 = NULL; - } - if (in1) { for (i = 0; i < 8; i++) w[i] = ntohl(in1[i]); @@ -129,11 +111,90 @@ void fastd_sha256_blocks(uint8_t out[FASTD_SHA256_HASH_BYTES], ...) { for (i = 0; i < 8; i++) h[i] += v[i]; - } while (in1 && in2); - va_end(ap); + if (!in2) + break; + + + in1 = va_arg(ap, const uint32_t*); + if (in1) { + count++; + in2 = va_arg(ap, const uint32_t*); + + if (in2) + count++; + } + else { + in2 = NULL; + } + } - uint32_t *out32 = (uint32_t*)out; for (i = 0; i < 8; i++) - out32[i] = htonl(h[i]); + out[i] = htonl(h[i]); +} + +static void hmacsha256_blocks_va(uint32_t out[FASTD_SHA256_HASH_WORDS], const uint32_t key[FASTD_HMACSHA256_KEY_WORDS], va_list ap) { + static const uint32_t ipad2[8] = { + 0x36363636, + 0x36363636, + 0x36363636, + 0x36363636, + 0x36363636, + 0x36363636, + 0x36363636, + 0x36363636 + }; + static const uint32_t opad2[8] = { + 0x5c5c5c5c, + 0x5c5c5c5c, + 0x5c5c5c5c, + 0x5c5c5c5c, + 0x5c5c5c5c, + 0x5c5c5c5c, + 0x5c5c5c5c, + 0x5c5c5c5c + }; + + uint32_t ipad[8], opad[8]; + unsigned i; + + for (i = 0; i < 8; i++) { + ipad[i] = key[i] ^ 0x36363636; + opad[i] = key[i] ^ 0x5c5c5c5c; + } + + uint32_t temp[8]; + sha256_blocks_va(temp, ipad, ipad2, ap); + + fastd_sha256_blocks(out, opad, opad2, temp, NULL); +} + + +void fastd_sha256_blocks(uint32_t out[FASTD_SHA256_HASH_WORDS], ...) { + va_list ap; + + va_start(ap, out); + const uint32_t *in1 = va_arg(ap, const uint32_t*); + const uint32_t *in2 = in1 ? va_arg(ap, const uint32_t*) : NULL; + sha256_blocks_va(out, in1, in2, ap); + va_end(ap); +} + +void fastd_hmacsha256_blocks(uint32_t out[FASTD_SHA256_HASH_WORDS], const uint32_t key[FASTD_HMACSHA256_KEY_WORDS], ...) { + va_list ap; + + va_start(ap, key); + hmacsha256_blocks_va(out, key, ap); + va_end(ap); +} + +bool fastd_hmacsha256_blocks_verify(const uint8_t mac[FASTD_SHA256_HASH_BYTES], const uint32_t key[FASTD_HMACSHA256_KEY_WORDS], ...) { + va_list ap; + uint32_t out[8]; + + va_start(ap, key); + hmacsha256_blocks_va(out, key, ap); + va_end(ap); + + return !memcmp(out, mac, sizeof(out)); } diff --git a/src/sha256.h b/src/sha256.h index c6acadb..acafe7e 100644 --- a/src/sha256.h +++ b/src/sha256.h @@ -27,13 +27,23 @@ #ifndef _FASTD_SHA256_H_ #define _FASTD_SHA256_H_ +#include #include -#define FASTD_SHA256_HASH_BYTES 32 -#define FASTD_SHA256_HASH_BLOCK_BYTES 32 +#define FASTD_SHA256_HASH_WORDS 8 +#define FASTD_SHA256_BLOCK_WORDS 8 +#define FASTD_HMACSHA256_KEY_WORDS 8 -void fastd_sha256_blocks(uint8_t out[FASTD_SHA256_HASH_BYTES], ...); +#define FASTD_SHA256_HASH_BYTES (4*FASTD_SHA256_HASH_WORDS) +#define FASTD_SHA256_BLOCK_BYTES (4*FASTD_SHA256_BLOCK_WORDS) + +#define FASTD_HMACSHA256_KEY_BYTES (4*FASTD_HMACSHA256_KEY_WORDS) + + +void fastd_sha256_blocks(uint32_t out[FASTD_SHA256_HASH_WORDS], ...); +void fastd_hmacsha256_blocks(uint32_t out[FASTD_SHA256_HASH_WORDS], const uint32_t key[FASTD_HMACSHA256_KEY_WORDS], ...); +bool fastd_hmacsha256_blocks_verify(const uint8_t mac[FASTD_SHA256_HASH_BYTES], const uint32_t key[FASTD_HMACSHA256_KEY_WORDS], ...); #endif /* _FASTD_SHA256_H_ */ -- cgit v1.2.3