From 9bc547ebbc435c2db6c418f8f42cf359e7ce385e Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sat, 28 Mar 2026 14:48:02 +0100 Subject: [PATCH] Move constant time equality comparison function to utils --- src/chacha-poly1305/chacha-poly1305.c | 3 +- src/ed25519/verify.c | 43 ++------------------------- src/gcrypt/digest.c | 3 +- src/invitation.c | 3 +- src/openssl/digest.c | 3 +- src/utils.c | 14 ++++++++- src/utils.h | 4 ++- 7 files changed, 25 insertions(+), 48 deletions(-) diff --git a/src/chacha-poly1305/chacha-poly1305.c b/src/chacha-poly1305/chacha-poly1305.c index 77d531ad..98218243 100644 --- a/src/chacha-poly1305/chacha-poly1305.c +++ b/src/chacha-poly1305/chacha-poly1305.c @@ -1,4 +1,5 @@ #include "../system.h" +#include "../utils.h" #include "../xalloc.h" #include "chacha.h" @@ -88,7 +89,7 @@ bool chacha_poly1305_decrypt(chacha_poly1305_ctx_t *ctx, uint64_t seqnr, const v poly1305_auth(expected_tag, indata, inlen, poly_key); - if(memcmp(expected_tag, tag, POLY1305_TAGLEN)) { + if(!mem_eq(expected_tag, tag, POLY1305_TAGLEN)) { return false; } diff --git a/src/ed25519/verify.c b/src/ed25519/verify.c index 415e94fc..74881aac 100644 --- a/src/ed25519/verify.c +++ b/src/ed25519/verify.c @@ -3,46 +3,7 @@ #include "ge.h" #include "sc.h" -static int consttime_equal(const unsigned char *x, const unsigned char *y) { - unsigned char r = 0; - - r = x[0] ^ y[0]; -#define F(i) r |= x[i] ^ y[i] - F(1); - F(2); - F(3); - F(4); - F(5); - F(6); - F(7); - F(8); - F(9); - F(10); - F(11); - F(12); - F(13); - F(14); - F(15); - F(16); - F(17); - F(18); - F(19); - F(20); - F(21); - F(22); - F(23); - F(24); - F(25); - F(26); - F(27); - F(28); - F(29); - F(30); - F(31); -#undef F - - return !r; -} +#include "../utils.h" int ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key) { unsigned char h[64]; @@ -69,7 +30,7 @@ int ed25519_verify(const unsigned char *signature, const unsigned char *message, ge_double_scalarmult_vartime(&R, h, &A, signature + 32); ge_tobytes(checker, &R); - if(!consttime_equal(checker, signature)) { + if(!mem_eq(checker, signature, sizeof checker)) { return 0; } diff --git a/src/gcrypt/digest.c b/src/gcrypt/digest.c index e0291689..f4723648 100644 --- a/src/gcrypt/digest.c +++ b/src/gcrypt/digest.c @@ -17,6 +17,7 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "../utils.h" #include "../system.h" #include "digest.h" @@ -161,7 +162,7 @@ bool digest_verify(digest_t *digest, const void *indata, size_t inlen, const voi size_t len = digest->maclength; uint8_t *outdata = alloca(len); - return digest_create(digest, indata, inlen, outdata) && !memcmp(cmpdata, outdata, len); + return digest_create(digest, indata, inlen, outdata) && mem_eq(cmpdata, outdata, len); } nid_t digest_get_nid(const digest_t *digest) { diff --git a/src/invitation.c b/src/invitation.c index ecbf1fa7..34f77f06 100644 --- a/src/invitation.c +++ b/src/invitation.c @@ -1399,11 +1399,10 @@ next: return 1; } - if(memcmp(hishash, hash, 18)) { + if(!mem_eq(hishash, hash, 18)) { fprintf(stderr, "Peer has an invalid key. Please make sure you're using the correct URL.\n%s\n", line + 2); ecdsa_free(key); return 1; - } ecdsa_t *hiskey = ecdsa_set_base64_public_key(fingerprint); diff --git a/src/openssl/digest.c b/src/openssl/digest.c index b497c93b..4ac72296 100644 --- a/src/openssl/digest.c +++ b/src/openssl/digest.c @@ -17,6 +17,7 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "../utils.h" #include "../system.h" #include @@ -186,7 +187,7 @@ bool digest_verify(digest_t *digest, const void *indata, size_t inlen, const voi size_t len = digest->maclength; unsigned char *outdata = alloca(len); - return digest_create(digest, indata, inlen, outdata) && !memcmp(cmpdata, outdata, digest->maclength); + return digest_create(digest, indata, inlen, outdata) && mem_eq(cmpdata, outdata, digest->maclength); } nid_t digest_get_nid(const digest_t *digest) { diff --git a/src/utils.c b/src/utils.c index 47b2a5d7..8c8c6526 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,7 +1,7 @@ /* utils.c -- gathering of some stupid small functions Copyright (C) 1999-2005 Ivo Timmermans - 2000-2013 Guus Sliepen + 2000-2026 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -298,3 +298,15 @@ bool string_eq(const char *first, const char *second) { return !first == !second && !(first && second && strcmp(first, second)); } + +bool mem_eq(const void *s1, const void *s2, size_t n) { + uint8_t diff = 0; + const uint8_t *p1 = s1; + const uint8_t *p2 = s2; + + for(size_t i = 0; i < n; i++) { + diff |= p1[i] ^ p2[i]; + } + + return diff == 0; +} diff --git a/src/utils.h b/src/utils.h index c33e28eb..6add6b42 100644 --- a/src/utils.h +++ b/src/utils.h @@ -4,7 +4,7 @@ /* utils.h -- header file for utils.c Copyright (C) 1999-2005 Ivo Timmermans - 2000-2013 Guus Sliepen + 2000-2026 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -77,4 +77,6 @@ char *replace_name(const char *name) ATTR_MALLOC; // NULL-safe wrapper around strcmp(). extern bool string_eq(const char *first, const char *second); +extern bool mem_eq(const void* s1, const void* s2, size_t n); + #endif -- 2.47.3