diff options
| author | Dimitri Staessens <dimitri@ouroboros.rocks> | 2026-06-21 13:20:30 +0200 |
|---|---|---|
| committer | Sander Vrijders <sander@ouroboros.rocks> | 2026-06-29 08:32:59 +0200 |
| commit | 84e1a6c0e9f6a7aed3c367e5b6fce029db0fc453 (patch) | |
| tree | 1182b290d3dda2820f4f94a98c77cf281e82b2ba | |
| parent | a169a1cef5332a409efc2db07bcc1ae9b72f217e (diff) | |
| download | ouroboros-84e1a6c0e9f6a7aed3c367e5b6fce029db0fc453.tar.gz ouroboros-84e1a6c0e9f6a7aed3c367e5b6fce029db0fc453.zip | |
lib: Add constant-time comparison helper
Add a function crypt_ct_cmp() that wraps CRYPTO_memcmp (OpenSSL) with
a volatile-loop fallback, for comparing authentication tags without
leaking timing.
Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks>
Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
| -rw-r--r-- | include/ouroboros/crypt.h | 8 | ||||
| -rw-r--r-- | src/lib/crypt.c | 19 |
2 files changed, 25 insertions, 2 deletions
diff --git a/include/ouroboros/crypt.h b/include/ouroboros/crypt.h index 41e44cee..9feaa610 100644 --- a/include/ouroboros/crypt.h +++ b/include/ouroboros/crypt.h @@ -40,7 +40,7 @@ * Some have a different spelling. This header avoids the double definitions. */ - #define NID_undef 0 +#define NID_undef 0 /* Cipher NIDs (match OpenSSL values) */ #define NID_aes_128_gcm 895 @@ -51,7 +51,7 @@ #define NID_aes_256_ctr 906 #define NID_chacha20_poly1305 1018 - #if !defined (__APPLE__) || !defined ( HAVE_OPENSSL ) +#if !defined (__APPLE__) || !defined ( HAVE_OPENSSL ) /* KEX algorithm NIDs (match OpenSSL values) */ #define NID_X9_62_prime256v1 415 #define NID_secp384r1 715 @@ -398,6 +398,10 @@ int crypt_load_pubkey_raw_file(const char * path, int crypt_load_privkey_raw_file(const char * path, void ** key); +int crypt_ct_cmp(const void * a, + const void * b, + size_t len); + int crypt_cmp_key(const void * key1, const void * key2); diff --git a/src/lib/crypt.c b/src/lib/crypt.c index a34e7298..5da9d392 100644 --- a/src/lib/crypt.c +++ b/src/lib/crypt.c @@ -1033,6 +1033,25 @@ int crypt_load_privkey_raw_file(const char * path, #endif } +int crypt_ct_cmp(const void * a, + const void * b, + size_t len) +{ +#ifdef HAVE_OPENSSL + return CRYPTO_memcmp(a, b, len); +#else + const volatile uint8_t * pa = a; + const volatile uint8_t * pb = b; + uint8_t d = 0; + size_t i; + + for (i = 0; i < len; i++) + d |= pa[i] ^ pb[i]; + + return d != 0; +#endif +} + int crypt_cmp_key(const void * key1, const void * key2) { |
