]> tinc-vpn.org Git - tinc/commitdiff
Move constant time equality comparison function to utils
authorGuus Sliepen <guus@tinc-vpn.org>
Sat, 28 Mar 2026 13:48:02 +0000 (14:48 +0100)
committerGuus Sliepen <guus@tinc-vpn.org>
Sat, 28 Mar 2026 14:09:05 +0000 (15:09 +0100)
src/chacha-poly1305/chacha-poly1305.c
src/ed25519/verify.c
src/gcrypt/digest.c
src/invitation.c
src/openssl/digest.c
src/utils.c
src/utils.h

index 77d531add2ab6a291a52557bb9e85720c88d01dc..98218243f14108e67165f252a2515043f61c63f3 100644 (file)
@@ -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;
        }
 
index 415e94fc659f7ff820ae8606e7bd140648fd19c9..74881aaccc56e1b2b3edbd7ead6681b475567a29 100644 (file)
@@ -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;
        }
 
index e0291689be161378d236b5f2819449a828dab12f..f472364876104b0fc93b37189b39b7f186a0e9db 100644 (file)
@@ -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) {
index ecbf1fa703c0aaec92373f8685c8874facf41449..34f77f06f27be40aee04846b9910b22ca0749a74 100644 (file)
@@ -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);
index b497c93bbdfe143c3dbd0117c09addc3e0710832..4ac722969505350e1163b5d5b53cdd59336e2ef4 100644 (file)
@@ -17,6 +17,7 @@
     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
+#include "../utils.h"
 #include "../system.h"
 
 #include <openssl/err.h>
@@ -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) {
index 47b2a5d779987dbbe164f80b2c20ba38af5d44d2..8c8c6526fd3038898bde60cb388d7616902e300f 100644 (file)
@@ -1,7 +1,7 @@
 /*
     utils.c -- gathering of some stupid small functions
     Copyright (C) 1999-2005 Ivo Timmermans
-                  2000-2013 Guus Sliepen <guus@tinc-vpn.org>
+                  2000-2026 Guus Sliepen <guus@tinc-vpn.org>
 
     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;
+}
index c33e28ebe2b42ebbc91f269fde2f0d5c17409b30..6add6b42a1391cd428f5874423fa0d03f54d1e9c 100644 (file)
@@ -4,7 +4,7 @@
 /*
     utils.h -- header file for utils.c
     Copyright (C) 1999-2005 Ivo Timmermans
-                  2000-2013 Guus Sliepen <guus@tinc-vpn.org>
+                  2000-2026 Guus Sliepen <guus@tinc-vpn.org>
 
     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