[crypto] Use private data field for key exchange algorithms For historical reasons, TLS versions 1.2 and earlier identify FFDHE groups by specifying the raw group prime and generator (the "dh_p" and "dh_g" fields in ServerDHParams), rather than using a numeric code to identify a named group. This adds complexity to the process of identifying the internal key exchange algorithm. One option would be to extend the definition of struct tls_key_exchange_algorithm to include the identifying values for the field prime and generator, but this is undesirable since the field prime values may be large, and these values are already available (indirectly) in ffdhe.c. Extend our definition of a key exchange algorithm to include an opaque private data field. This allows us to remove the wrapper functions currently created by FFDHE_GROUP() and WEIERSTRASS_CURVE(), and opens up the option of accessing the existing FFDHE field prime and generator values from within the TLS layer. Signed-off-by: Michael Brown <mcb30@ipxe.org>
diff --git a/src/crypto/ffdhe.c b/src/crypto/ffdhe.c index d6f9449..004170d 100644 --- a/src/crypto/ffdhe.c +++ b/src/crypto/ffdhe.c
@@ -194,8 +194,8 @@ * @v shared Shared result to fill in * @ret rc Return status code */ -int ffdhe ( struct ffdhe_group *group, const void *public, const void *private, - void *shared ) { +static int ffdhe ( struct ffdhe_group *group, const void *public, + const void *private, void *shared ) { unsigned int expsize = group->expsize; unsigned int size = group->size; size_t explen = group->explen; @@ -253,6 +253,36 @@ return 0; } +/** + * Calculate public key + * + * @v exchange Key exchange algorithm + * @v private Private key + * @v public Public key to fill in + */ +void ffdhe_public ( struct exchange_algorithm *exchange, const void *private, + void *public ) { + struct ffdhe_group *group = exchange->priv; + + ffdhe ( group, NULL, private, public ); +} + +/** + * Calculate shared secret + * + * @v exchange Key exchange algorithm + * @v private Private key + * @v partner Partner public key + * @v shared Shared secret to fill in + * @ret rc Return status code + */ +int ffdhe_shared ( struct exchange_algorithm *exchange, const void *private, + const void *partner, void *shared ) { + struct ffdhe_group *group = exchange->priv; + + return ffdhe ( group, partner, private, shared ); +} + /* Supported groups */ FFDHE_GROUP ( ffdhe2048, ffdhe2048_algorithm, euler, 2048, 225, 0x61285c97 ); FFDHE_GROUP ( ffdhe3072, ffdhe3072_algorithm, euler, 3072, 275, 0x66c62e37 );
diff --git a/src/crypto/weierstrass.c b/src/crypto/weierstrass.c index ab2df24..7fa18ca 100644 --- a/src/crypto/weierstrass.c +++ b/src/crypto/weierstrass.c
@@ -1030,12 +1030,13 @@ /** * Calculate public key * - * @v curve Weierstrass curve + * @v exchange Key exchange algorithm * @v private Private key * @v public Public key to fill in */ -void weierstrass_public ( struct weierstrass_curve *curve, const void *private, - void *public ) { +void weierstrass_public ( struct exchange_algorithm *exchange, + const void *private, void *public ) { + struct weierstrass_curve *curve = exchange->priv; size_t len = curve->len; weierstrass_uncompressed_t ( len ) *uncompressed = public; int rc; @@ -1052,14 +1053,16 @@ /** * Calculate shared secret * - * @v curve Weierstrass curve + * @v exchange Key exchange algorithm * @v private Private key * @v partner Partner public key * @v shared Shared secret to fill in * @ret rc Return status code */ -int weierstrass_shared ( struct weierstrass_curve *curve, const void *private, - const void *partner, void *shared ) { +int weierstrass_shared ( struct exchange_algorithm *exchange, + const void *private, const void *partner, + void *shared ) { + struct weierstrass_curve *curve = exchange->priv; size_t len = curve->len; const weierstrass_uncompressed_t ( len ) *uncompressed = partner; weierstrass_raw_t ( len ) point;
diff --git a/src/crypto/x25519.c b/src/crypto/x25519.c index 58382bc..5eb74b6 100644 --- a/src/crypto/x25519.c +++ b/src/crypto/x25519.c
@@ -833,10 +833,12 @@ /** * Calculate public key * + * @v exchange Key exchange algorithm * @v private Private key * @v public Public key to fill in */ -static void x25519_public ( const void *private, void *public ) { +static void x25519_public ( struct exchange_algorithm *exchange __unused, + const void *private, void *public ) { /* Calculate public key */ x25519_key ( &x25519_generator, private, public ); @@ -845,12 +847,14 @@ /** * Calculate shared secret * + * @v exchange Key exchange algorithm * @v private Private key * @v partner Partner public key * @v shared Shared secret to fill in * @ret rc Return status code */ -static int x25519_shared ( const void *private, const void *partner, +static int x25519_shared ( struct exchange_algorithm *exchange __unused, + const void *private, const void *partner, void *shared ) { /* Calculate shared secret */
diff --git a/src/include/ipxe/crypto.h b/src/include/ipxe/crypto.h index ad08553..e512ae0 100644 --- a/src/include/ipxe/crypto.h +++ b/src/include/ipxe/crypto.h
@@ -187,20 +187,26 @@ /** * Calculate public key * + * @v exchange Key exchange algorithm * @v private Private key * @v public Public key to fill in */ - void ( * public ) ( const void *private, void *public ); + void ( * public ) ( struct exchange_algorithm *exchange, + const void *private, void *public ); /** * Calculate shared secret * + * @v exchange Key exchange algorithm * @v private Private key * @v partner Partner public key * @v shared Shared secret to fill in * @ret rc Return status code */ - int ( * shared ) ( const void *private, const void *partner, + int ( * shared ) ( struct exchange_algorithm *exchange, + const void *private, const void *partner, void *shared ); + /** Algorithm private data */ + void *priv; }; /** An elliptic curve */ @@ -350,13 +356,13 @@ static inline __attribute__ (( always_inline )) void exchange_public ( struct exchange_algorithm *exchange, const void *private, void *public ) { - exchange->public ( private, public ); + exchange->public ( exchange, private, public ); } static inline __attribute__ (( always_inline )) int exchange_shared ( struct exchange_algorithm *exchange, const void *private, const void *partner, void *shared ) { - return exchange->shared ( private, partner, shared ); + return exchange->shared ( exchange, private, partner, shared ); } static inline __attribute__ (( always_inline )) int
diff --git a/src/include/ipxe/ffdhe.h b/src/include/ipxe/ffdhe.h index 349680f..12e0e31 100644 --- a/src/include/ipxe/ffdhe.h +++ b/src/include/ipxe/ffdhe.h
@@ -33,8 +33,11 @@ uint32_t lsb32; }; -extern int ffdhe ( struct ffdhe_group *group, const void *public, - const void *private, void *shared ); +extern void ffdhe_public ( struct exchange_algorithm *exchange, + const void *private, void *public ); +extern int ffdhe_shared ( struct exchange_algorithm *exchange, + const void *private, const void *partner, + void *shared ); /** Define a finite field DHE group */ #define FFDHE_GROUP( _name, _exchange, _constant, _bits, _expbits, _lsb ) \ @@ -47,23 +50,14 @@ .expsize = bigint_required_size ( ( _expbits + 7 ) / 8 ), \ .lsb32 = cpu_to_be32 ( _lsb ), \ }; \ - static void _name ## _public ( const void *private, \ - void *public ) { \ - ffdhe ( &_name ## _group, NULL, private, public ); \ - } \ - static int _name ## _shared ( const void *private, \ - const void *partner, \ - void *shared ) { \ - return ffdhe ( &_name ## _group, partner, private, \ - shared ); \ - } \ struct exchange_algorithm _exchange = { \ .name = #_name, \ .privsize = ( ( _expbits + 7 ) / 8 ), \ .pubsize = ( _bits / 8 ), \ .sharedsize = ( _bits / 8 ), \ - .public = _name ## _public, \ - .shared = _name ## _shared, \ + .public = ffdhe_public, \ + .shared = ffdhe_shared, \ + .priv = &_name ## _group, \ } extern struct exchange_algorithm ffdhe2048_algorithm;
diff --git a/src/include/ipxe/weierstrass.h b/src/include/ipxe/weierstrass.h index fa2e53c..4095b4a 100644 --- a/src/include/ipxe/weierstrass.h +++ b/src/include/ipxe/weierstrass.h
@@ -164,9 +164,9 @@ extern int weierstrass_add_once ( struct weierstrass_curve *curve, const void *addend, const void *augend, void *result ); -extern void weierstrass_public ( struct weierstrass_curve *curve, +extern void weierstrass_public ( struct exchange_algorithm *exchange, const void *private, void *public ); -extern int weierstrass_shared ( struct weierstrass_curve *curve, +extern int weierstrass_shared ( struct exchange_algorithm *exchange, const void *private, const void *partner, void *shared ); @@ -209,17 +209,6 @@ return weierstrass_add_once ( &_name ## _weierstrass, \ addend, augend, result ); \ } \ - static void _name ## _public ( const void *private, \ - void *public ) { \ - weierstrass_public ( &_name ## _weierstrass, \ - private, public ); \ - } \ - static int _name ## _shared ( const void *private, \ - const void *partner, \ - void *shared ) { \ - return weierstrass_shared ( &_name ## _weierstrass, \ - private, partner, shared ); \ - } \ struct elliptic_curve _curve = { \ .name = #_name, \ .pointsize = sizeof ( weierstrass_raw_t(_len) ), \ @@ -235,8 +224,9 @@ .privsize = (_len), \ .pubsize = sizeof ( weierstrass_uncompressed_t(_len) ), \ .sharedsize = (_len), \ - .public = _name ## _public, \ - .shared = _name ## _shared, \ + .public = weierstrass_public, \ + .shared = weierstrass_shared, \ + .priv = &_name ## _weierstrass, \ } #endif /* _IPXE_WEIERSTRASS_H */