From 9225a4550abebd26ff3642d8f5ed4f96b2e4bff7 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sun, 31 Aug 2014 16:21:24 +0200 Subject: Replace memcmp with a constant-time version in some places --- src/crypto.h | 22 ++++++++++++++++++++++ src/methods/composed_gmac/composed_gmac.c | 2 +- src/methods/composed_umac/composed_umac.c | 2 +- src/methods/generic_gmac/generic_gmac.c | 2 +- src/methods/generic_umac/generic_umac.c | 2 +- src/protocols/ec25519_fhmqvc/handshake.c | 13 +++++++------ src/sha256.c | 5 +++-- 7 files changed, 36 insertions(+), 12 deletions(-) diff --git a/src/crypto.h b/src/crypto.h index 07b7d46..561eb27 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -96,6 +96,28 @@ static inline void secure_memzero(void *s, size_t n) { __asm__ volatile("" : : "m"(s)); } +static inline bool secure_memequal(const void *s1, const void *s2, size_t n) { + uint8_t v = 0; + const uint8_t *i1 = s1, *i2 = s2; + size_t i; + + for (i = 0; i < n; i++) + v |= i1[i] ^ i2[i]; + + return (v == 0); +} + +static inline bool block_equal(const fastd_block128_t *a, const fastd_block128_t *b) { + uint32_t v = 0; + + v |= a->dw[0] ^ b->dw[0]; + v |= a->dw[1] ^ b->dw[1]; + v |= a->dw[2] ^ b->dw[2]; + v |= a->dw[3] ^ b->dw[3]; + + return (v == 0); +} + /** XORs two blocks of data */ static inline void xor(fastd_block128_t *x, const fastd_block128_t *a, const fastd_block128_t *b) { x->qw[0] = a->qw[0] ^ b->qw[0]; diff --git a/src/methods/composed_gmac/composed_gmac.c b/src/methods/composed_gmac/composed_gmac.c index 72f5c8b..86ae66b 100644 --- a/src/methods/composed_gmac/composed_gmac.c +++ b/src/methods/composed_gmac/composed_gmac.c @@ -301,7 +301,7 @@ static bool method_decrypt(fastd_peer_t *peer, fastd_method_session_state_t *ses ok = session->ghash->digest(session->ghash_state, &tag, inblocks+1, n_blocks*sizeof(fastd_block128_t)); } - if (!ok || memcmp(&tag, &outblocks[0], sizeof(fastd_block128_t)) != 0) { + if (!ok || !block_equal(&tag, &outblocks[0])) { fastd_buffer_free(*out); return false; } diff --git a/src/methods/composed_umac/composed_umac.c b/src/methods/composed_umac/composed_umac.c index 02fdda6..6c01bff 100644 --- a/src/methods/composed_umac/composed_umac.c +++ b/src/methods/composed_umac/composed_umac.c @@ -265,7 +265,7 @@ static bool method_decrypt(fastd_peer_t *peer, fastd_method_session_state_t *ses ok = session->uhash->digest(session->uhash_state, &tag, inblocks+1, in_len); } - if (!ok || memcmp(&tag, &outblocks[0], sizeof(fastd_block128_t)) != 0) { + if (!ok || !block_equal(&tag, &outblocks[0])) { fastd_buffer_free(*out); return false; } diff --git a/src/methods/generic_gmac/generic_gmac.c b/src/methods/generic_gmac/generic_gmac.c index 30a2f2f..519c354 100644 --- a/src/methods/generic_gmac/generic_gmac.c +++ b/src/methods/generic_gmac/generic_gmac.c @@ -261,7 +261,7 @@ static bool method_decrypt(fastd_peer_t *peer, fastd_method_session_state_t *ses ok = session->ghash->digest(session->ghash_state, &tag, inblocks+1, n_blocks*sizeof(fastd_block128_t)); } - if (!ok || memcmp(&tag, &outblocks[0], sizeof(fastd_block128_t)) != 0) { + if (!ok || !block_equal(&tag, &outblocks[0])) { fastd_buffer_free(*out); return false; } diff --git a/src/methods/generic_umac/generic_umac.c b/src/methods/generic_umac/generic_umac.c index aaaf9e7..167ee79 100644 --- a/src/methods/generic_umac/generic_umac.c +++ b/src/methods/generic_umac/generic_umac.c @@ -224,7 +224,7 @@ static bool method_decrypt(fastd_peer_t *peer, fastd_method_session_state_t *ses if (ok) ok = session->uhash->digest(session->uhash_state, &tag, inblocks+1, in_len); - if (!ok || memcmp(&tag, &outblocks[0], sizeof(fastd_block128_t)) != 0) { + if (!ok || !block_equal(&tag, &outblocks[0])) { fastd_buffer_free(*out); return false; } diff --git a/src/protocols/ec25519_fhmqvc/handshake.c b/src/protocols/ec25519_fhmqvc/handshake.c index 7487100..d7b7bfc 100644 --- a/src/protocols/ec25519_fhmqvc/handshake.c +++ b/src/protocols/ec25519_fhmqvc/handshake.c @@ -30,6 +30,7 @@ */ #include "handshake.h" +#include "../../crypto.h" #include "../../handshake.h" #include "../../hkdf_sha256.h" #include "../../verify.h" @@ -270,7 +271,7 @@ static bool make_shared_handshake_key(const ecc_int256_t *handshake_key, bool in /** Checks if the currently cached shared handshake key is valid and generates a new one otherwise */ static bool update_shared_handshake_key(const fastd_peer_t *peer, const handshake_key_t *handshake_key, const aligned_int256_t *peer_handshake_key) { if (peer->protocol_state->last_handshake_serial == handshake_key->serial) { - if (memcmp(&peer->protocol_state->peer_handshake_key, peer_handshake_key, PUBLICKEYBYTES) == 0) + if (secure_memequal(&peer->protocol_state->peer_handshake_key, peer_handshake_key, PUBLICKEYBYTES)) return true; } @@ -442,7 +443,7 @@ static fastd_peer_t * find_key(const uint8_t key[PUBLICKEYBYTES], const fastd_pe if (address && !fastd_peer_is_enabled(peer)) continue; - if (memcmp(&peer->key->key, key, PUBLICKEYBYTES) == 0) { + if (secure_memequal(&peer->key->key, key, PUBLICKEYBYTES)) { if (!address) return peer; @@ -480,7 +481,7 @@ static fastd_peer_t * match_sender_key(const fastd_socket_t *sock, const fastd_p exit_bug("packet without correct peer set on dynamic socket"); if (peer) { - if (memcmp(&peer->key->key, key, PUBLICKEYBYTES) == 0) + if (secure_memequal(&peer->key->key, key, PUBLICKEYBYTES)) return peer; if (fastd_peer_owns_address(peer, address)) { @@ -658,7 +659,7 @@ void fastd_protocol_ec25519_fhmqvc_handshake_handle(fastd_socket_t *sock, const } if (has_field(handshake, RECORD_RECIPIENT_KEY, PUBLICKEYBYTES)) { - if (memcmp(&conf.protocol_config->key.public, handshake->records[RECORD_RECIPIENT_KEY].data, PUBLICKEYBYTES) != 0) { + if (!secure_memequal(&conf.protocol_config->key.public, handshake->records[RECORD_RECIPIENT_KEY].data, PUBLICKEYBYTES)) { pr_debug("received protocol handshake with wrong recipient key from %P[%I]", peer, remote_addr); return; } @@ -708,11 +709,11 @@ void fastd_protocol_ec25519_fhmqvc_handshake_handle(fastd_socket_t *sock, const handshake_key_t *handshake_key; if (is_handshake_key_valid(&ctx.protocol_state->handshake_key) && - memcmp(&ctx.protocol_state->handshake_key.key.public, handshake->records[RECORD_RECIPIENT_HANDSHAKE_KEY].data, PUBLICKEYBYTES) == 0) { + secure_memequal(&ctx.protocol_state->handshake_key.key.public, handshake->records[RECORD_RECIPIENT_HANDSHAKE_KEY].data, PUBLICKEYBYTES)) { handshake_key = &ctx.protocol_state->handshake_key; } else if (is_handshake_key_valid(&ctx.protocol_state->prev_handshake_key) && - memcmp(&ctx.protocol_state->prev_handshake_key.key.public, handshake->records[RECORD_RECIPIENT_HANDSHAKE_KEY].data, PUBLICKEYBYTES) == 0) { + secure_memequal(&ctx.protocol_state->prev_handshake_key.key.public, handshake->records[RECORD_RECIPIENT_HANDSHAKE_KEY].data, PUBLICKEYBYTES)) { handshake_key = &ctx.protocol_state->prev_handshake_key; } else { diff --git a/src/sha256.c b/src/sha256.c index 3d6401f..2e9a7a7 100644 --- a/src/sha256.c +++ b/src/sha256.c @@ -31,6 +31,7 @@ #include "sha256.h" +#include "crypto.h" #include #include @@ -261,7 +262,7 @@ bool fastd_hmacsha256_blocks_verify(const uint8_t mac[FASTD_SHA256_HASH_BYTES], hmacsha256_blocks_va(&out, key, ap); va_end(ap); - return !memcmp(out.b, mac, FASTD_SHA256_HASH_BYTES); + return secure_memequal(out.b, mac, FASTD_SHA256_HASH_BYTES); } /** Computes the HMAC-SHA256 of an arbitraty input buffer */ @@ -280,5 +281,5 @@ bool fastd_hmacsha256_verify(const uint8_t mac[FASTD_SHA256_HASH_BYTES], const u fastd_sha256_t out; fastd_hmacsha256(&out, key, in, len); - return !memcmp(out.b, mac, FASTD_SHA256_HASH_BYTES); + return secure_memequal(out.b, mac, FASTD_SHA256_HASH_BYTES); } -- cgit v1.2.3