From c43c2829ec89e92971d78a63575e7d4b8737be11 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 17 Jun 2026 12:30:52 +0100 Subject: [PATCH] [crypto] Provide a mechanism to check FFDHE group parameters Provide is_ffdhe() and ffdhe_has_params() as a way to check if a key exchange algorithm happens to match against an explicit pair of prime modulus and generator values. Signed-off-by: Michael Brown --- src/crypto/ffdhe.c | 50 ++++++++++++++++++++++++++++++++++++++++ src/include/ipxe/ffdhe.h | 15 ++++++++++++ 2 files changed, 65 insertions(+) diff --git a/src/crypto/ffdhe.c b/src/crypto/ffdhe.c index 004170ddb..f2b682d42 100644 --- a/src/crypto/ffdhe.c +++ b/src/crypto/ffdhe.c @@ -45,6 +45,7 @@ FILE_SECBOOT ( PERMITTED ); * servers. */ +#include #include #include #include @@ -283,6 +284,55 @@ int ffdhe_shared ( struct exchange_algorithm *exchange, const void *private, return ffdhe ( group, partner, private, shared ); } +/** + * Check group parameters + * + * @v exchange Key exchange algorithm + * @v dh_p Prime modulus + * @v dh_p_len Length of prime modulus + * @v dh_g Generator + * @v dh_g_len Length of generator + * @ret match Field parameters are correct for this group + * + * Leading zeros in the modulus and generator will be tolerated. + */ +int ffdhe_has_params ( struct exchange_algorithm *exchange, + const void *dh_p, size_t dh_p_len, + const void *dh_g, size_t dh_g_len ) { + struct ffdhe_group *group = exchange->priv; + const ffdhe_modulus_t ( group->len ) *modulus; + const uint8_t *generator; + + /* Sanity check */ + assert ( is_ffdhe ( exchange ) ); + + /* Strip leading zeros from modulus and check length */ + while ( dh_p_len && ( ! *( ( uint8_t * ) dh_p ) ) ) { + dh_p++; + dh_p_len--; + } + if ( dh_p_len != sizeof ( *modulus ) ) + return 0; + modulus = dh_p; + + /* Strip leading zeros from generator and check length */ + while ( dh_g_len && ( ! *( ( uint8_t * ) dh_g ) ) ) { + dh_g++; + dh_g_len--; + } + if ( dh_g_len != sizeof ( *generator ) ) + return 0; + generator = dh_g; + + /* Check values */ + return ( ( modulus->high == ~( ( uint64_t ) 0 ) ) && + ( memcmp ( modulus->constant, group->constant, + sizeof ( modulus->constant ) ) == 0 ) && + ( modulus->lsb32 == group->lsb32 ) && + ( modulus->low == ~( ( uint64_t ) 0 ) ) && + ( *generator == 2 ) ); +} + /* Supported groups */ FFDHE_GROUP ( ffdhe2048, ffdhe2048_algorithm, euler, 2048, 225, 0x61285c97 ); FFDHE_GROUP ( ffdhe3072, ffdhe3072_algorithm, euler, 3072, 275, 0x66c62e37 ); diff --git a/src/include/ipxe/ffdhe.h b/src/include/ipxe/ffdhe.h index 12e0e3160..b3a11cc36 100644 --- a/src/include/ipxe/ffdhe.h +++ b/src/include/ipxe/ffdhe.h @@ -38,6 +38,21 @@ extern void ffdhe_public ( struct exchange_algorithm *exchange, extern int ffdhe_shared ( struct exchange_algorithm *exchange, const void *private, const void *partner, void *shared ); +extern int ffdhe_has_params ( struct exchange_algorithm *exchange, + const void *modulus, size_t len, + const void *generator, size_t generator_len ); + +/** + * Check if key exchange algorithm is a finite field DHE group + * + * @v exchange Key exchange algorithm + * @ret is_ffdhe Key exchange algorithm is a finite field DHE group + */ +static inline __attribute__ (( always_inline )) int +is_ffdhe ( struct exchange_algorithm *exchange ) { + + return ( exchange->public == ffdhe_public ); +} /** Define a finite field DHE group */ #define FFDHE_GROUP( _name, _exchange, _constant, _bits, _expbits, _lsb ) \