[crypto] Provide X25519 as a generic key exchange algorithm

Provide X25519 as a generic key exchange algorithm (independent of the
elliptic curve abstraction).

The existing RFC7748 test vectors are not structured in a way amenable
to treatment as a generic key exchange algorithm.  Retain these test
vectors unaltered for completeness, add the single "Alice/Bob" key
exchange example presented in RFC7748, and add a selection of test
vectors from Project Wycheproof (including some known edge cases).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2026-06-05 15:07:33 +01:00
parent 5179c22cde
commit 4dc99fc040
4 changed files with 165 additions and 1 deletions
+1 -1
View File
@@ -33,7 +33,7 @@ FILE_SECBOOT ( PERMITTED );
static uint8_t oid_x25519[] = { ASN1_OID_X25519 };
/** "x25519" OID-identified algorithm */
struct asn1_algorithm x25519_algorithm __asn1_algorithm = {
struct asn1_algorithm oid_x25519_algorithm __asn1_algorithm = {
.name = "x25519",
.curve = &x25519_curve,
.oid = ASN1_CURSOR ( oid_x25519 ),
+43
View File
@@ -882,3 +882,46 @@ struct elliptic_curve x25519_curve = {
.multiply = x25519_curve_multiply,
.add = x25519_curve_add,
};
/**
* Calculate public key
*
* @v private Private key
* @v public Public key to fill in
*/
static void x25519_public ( const void *private, void *public ) {
/* Calculate public key */
x25519_key ( &x25519_generator, private, public );
}
/**
* Calculate shared secret
*
* @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,
void *shared ) {
/* Calculate shared secret */
x25519_key ( partner, private, shared );
/* Check for point at infinity (all zeros as per RFC8422) */
if ( x25519_is_zero ( shared ) )
return -EPERM;
return 0;
}
/** X25519 key exchange algorithm */
struct exchange_algorithm x25519_algorithm = {
.name = "x25519",
.privsize = sizeof ( struct x25519_value ),
.pubsize = sizeof ( struct x25519_value ),
.sharedsize = sizeof ( struct x25519_value ),
.public = x25519_public,
.shared = x25519_shared,
};
+1
View File
@@ -92,5 +92,6 @@ extern void x25519_key ( const struct x25519_value *base,
extern int x25519_is_zero ( const struct x25519_value *value );
extern struct elliptic_curve x25519_curve;
extern struct exchange_algorithm x25519_algorithm;
#endif /* _IPXE_X25519_H */
+120
View File
@@ -38,6 +38,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <string.h>
#include <ipxe/x25519.h>
#include <ipxe/test.h>
#include "exchange_test.h"
/** Define inline multiplicand */
#define MULTIPLICAND(...) { __VA_ARGS__ }
@@ -562,6 +563,118 @@ X25519_KEY_TEST ( malicious, 1, 1,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00 ) );
/* Private: 0x77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a
* Partner: 0xde9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f
* Public: 0x8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a
* Shared: 0x4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742
*/
EXCHANGE_TEST ( rfc7748_alice, &x25519_algorithm,
PRIVATE ( 0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d, 0x3c, 0x16,
0xc1, 0x72, 0x51, 0xb2, 0x66, 0x45, 0xdf, 0x4c, 0x2f, 0x87,
0xeb, 0xc0, 0x99, 0x2a, 0xb1, 0x77, 0xfb, 0xa5, 0x1d, 0xb9,
0x2c, 0x2a ),
PARTNER ( 0xde, 0x9e, 0xdb, 0x7d, 0x7b, 0x7d, 0xc1, 0xb4, 0xd3, 0x5b,
0x61, 0xc2, 0xec, 0xe4, 0x35, 0x37, 0x3f, 0x83, 0x43, 0xc8,
0x5b, 0x78, 0x67, 0x4d, 0xad, 0xfc, 0x7e, 0x14, 0x6f, 0x88,
0x2b, 0x4f ),
PUBLIC ( 0x85, 0x20, 0xf0, 0x09, 0x89, 0x30, 0xa7, 0x54, 0x74, 0x8b,
0x7d, 0xdc, 0xb4, 0x3e, 0xf7, 0x5a, 0x0d, 0xbf, 0x3a, 0x0d,
0x26, 0x38, 0x1a, 0xf4, 0xeb, 0xa4, 0xa9, 0x8e, 0xaa, 0x9b,
0x4e, 0x6a ),
SHARED ( 0x4a, 0x5d, 0x9d, 0x5b, 0xa4, 0xce, 0x2d, 0xe1, 0x72, 0x8e,
0x3b, 0xf4, 0x80, 0x35, 0x0f, 0x25, 0xe0, 0x7e, 0x21, 0xc9,
0x47, 0xd1, 0x9e, 0x33, 0x76, 0xf0, 0x9b, 0x3c, 0x1e, 0x16,
0x17, 0x42 ) );
/* Private: 0x5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb
* Partner: 0x8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a
* Public: 0xde9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f
* Shared: 0x4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742
*/
EXCHANGE_TEST ( rfc7748_bob, &x25519_algorithm,
PRIVATE ( 0x5d, 0xab, 0x08, 0x7e, 0x62, 0x4a, 0x8a, 0x4b, 0x79, 0xe1,
0x7f, 0x8b, 0x83, 0x80, 0x0e, 0xe6, 0x6f, 0x3b, 0xb1, 0x29,
0x26, 0x18, 0xb6, 0xfd, 0x1c, 0x2f, 0x8b, 0x27, 0xff, 0x88,
0xe0, 0xeb ),
PARTNER ( 0x85, 0x20, 0xf0, 0x09, 0x89, 0x30, 0xa7, 0x54, 0x74, 0x8b,
0x7d, 0xdc, 0xb4, 0x3e, 0xf7, 0x5a, 0x0d, 0xbf, 0x3a, 0x0d,
0x26, 0x38, 0x1a, 0xf4, 0xeb, 0xa4, 0xa9, 0x8e, 0xaa, 0x9b,
0x4e, 0x6a ),
PUBLIC ( 0xde, 0x9e, 0xdb, 0x7d, 0x7b, 0x7d, 0xc1, 0xb4, 0xd3, 0x5b,
0x61, 0xc2, 0xec, 0xe4, 0x35, 0x37, 0x3f, 0x83, 0x43, 0xc8,
0x5b, 0x78, 0x67, 0x4d, 0xad, 0xfc, 0x7e, 0x14, 0x6f, 0x88,
0x2b, 0x4f ),
SHARED ( 0x4a, 0x5d, 0x9d, 0x5b, 0xa4, 0xce, 0x2d, 0xe1, 0x72, 0x8e,
0x3b, 0xf4, 0x80, 0x35, 0x0f, 0x25, 0xe0, 0x7e, 0x21, 0xc9,
0x47, 0xd1, 0x9e, 0x33, 0x76, 0xf0, 0x9b, 0x3c, 0x1e, 0x16,
0x17, 0x42 ) );
/* Private: 0x106221fe5694a710d6e147696c5d5b93d6887d584f24f228182ebe1b1d2db85d
* Partner: 0xffffff0f000000ffffff0f000000ffffff0f000000ffffff0f000000ffffff0f
* Public: 0xecba343f4a89013fea83e869ea3f7a670715d833ab0ec43adb3acd4b48229607
* Shared: 0x5e64924b91873b499a5402fa64337c65d4b2ed54beeb3fa5d7347809e43aef1c
*/
EXCHANGE_TEST ( wycheproof_49, &x25519_algorithm,
PRIVATE ( 0x10, 0x62, 0x21, 0xfe, 0x56, 0x94, 0xa7, 0x10, 0xd6, 0xe1,
0x47, 0x69, 0x6c, 0x5d, 0x5b, 0x93, 0xd6, 0x88, 0x7d, 0x58,
0x4f, 0x24, 0xf2, 0x28, 0x18, 0x2e, 0xbe, 0x1b, 0x1d, 0x2d,
0xb8, 0x5d ),
PARTNER ( 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
0x0f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00,
0x00, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0xff, 0xff,
0xff, 0x0f ),
PUBLIC ( 0xec, 0xba, 0x34, 0x3f, 0x4a, 0x89, 0x01, 0x3f, 0xea, 0x83,
0xe8, 0x69, 0xea, 0x3f, 0x7a, 0x67, 0x07, 0x15, 0xd8, 0x33,
0xab, 0x0e, 0xc4, 0x3a, 0xdb, 0x3a, 0xcd, 0x4b, 0x48, 0x22,
0x96, 0x07 ),
SHARED ( 0x5e, 0x64, 0x92, 0x4b, 0x91, 0x87, 0x3b, 0x49, 0x9a, 0x54,
0x02, 0xfa, 0x64, 0x33, 0x7c, 0x65, 0xd4, 0xb2, 0xed, 0x54,
0xbe, 0xeb, 0x3f, 0xa5, 0xd7, 0x34, 0x78, 0x09, 0xe4, 0x3a,
0xef, 0x1c ) );
/* Private: 0xe0f978dfcd3a8f1a5093418de54136a584c20b7b349afdf6c0520886f95b1272
* Partner: 0xe0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b800
* Public: 0x124e0f1487c9b38f1c7fd4a6518a47699d158d44cc18665c7bcca03bdc726e5d
* Shared: Failure (all zeros)
*/
EXCHANGE_TEST ( wycheproof_63, &x25519_algorithm,
PRIVATE ( 0xe0, 0xf9, 0x78, 0xdf, 0xcd, 0x3a, 0x8f, 0x1a, 0x50, 0x93,
0x41, 0x8d, 0xe5, 0x41, 0x36, 0xa5, 0x84, 0xc2, 0x0b, 0x7b,
0x34, 0x9a, 0xfd, 0xf6, 0xc0, 0x52, 0x08, 0x86, 0xf9, 0x5b,
0x12, 0x72 ),
PARTNER ( 0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56,
0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb,
0x9c, 0x32, 0xb1, 0xfd, 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49,
0xb8, 0x00 ),
PUBLIC ( 0x12, 0x4e, 0x0f, 0x14, 0x87, 0xc9, 0xb3, 0x8f, 0x1c, 0x7f,
0xd4, 0xa6, 0x51, 0x8a, 0x47, 0x69, 0x9d, 0x15, 0x8d, 0x44,
0xcc, 0x18, 0x66, 0x5c, 0x7b, 0xcc, 0xa0, 0x3b, 0xdc, 0x72,
0x6e, 0x5d ),
SHARED_FAIL );
/* Private: 0x60a3a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a9767f
* Partner: 0x8d612c5831aa64b057300e7e310f3aa332af34066fefcab2b089c9592878f832
* Public: 0x7c6ccba92ff00a6e83382cd06b9ec9e6581eafe3c243f0c52cf68e067843e37a
* Shared: 0xe3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f
*/
EXCHANGE_TEST ( wycheproof_112, &x25519_algorithm,
PRIVATE ( 0x60, 0xa3, 0xa4, 0xf1, 0x30, 0xb9, 0x8a, 0x5b, 0xe4, 0xb1,
0xce, 0xdb, 0x7c, 0xb8, 0x55, 0x84, 0xa3, 0x52, 0x0e, 0x14,
0x2d, 0x47, 0x4d, 0xc9, 0xcc, 0xb9, 0x09, 0xa0, 0x73, 0xa9,
0x76, 0x7f ),
PARTNER ( 0x8d, 0x61, 0x2c, 0x58, 0x31, 0xaa, 0x64, 0xb0, 0x57, 0x30,
0x0e, 0x7e, 0x31, 0x0f, 0x3a, 0xa3, 0x32, 0xaf, 0x34, 0x06,
0x6f, 0xef, 0xca, 0xb2, 0xb0, 0x89, 0xc9, 0x59, 0x28, 0x78,
0xf8, 0x32 ),
PUBLIC ( 0x7c, 0x6c, 0xcb, 0xa9, 0x2f, 0xf0, 0x0a, 0x6e, 0x83, 0x38,
0x2c, 0xd0, 0x6b, 0x9e, 0xc9, 0xe6, 0x58, 0x1e, 0xaf, 0xe3,
0xc2, 0x43, 0xf0, 0xc5, 0x2c, 0xf6, 0x8e, 0x06, 0x78, 0x43,
0xe3, 0x7a ),
SHARED ( 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x7f ) );
/**
* Perform X25519 self-tests
*
@@ -590,6 +703,13 @@ static void x25519_test_exec ( void ) {
x25519_key_ok ( &rfc7748_3 );
x25519_key_ok ( &rfc7748_4_100 );
x25519_key_ok ( &malicious );
/* Perform key exchange tests via generic key exchange algorithm */
exchange_ok ( &rfc7748_alice );
exchange_ok ( &rfc7748_bob );
exchange_ok ( &wycheproof_49 );
exchange_ok ( &wycheproof_63 );
exchange_ok ( &wycheproof_112 );
}
/** X25519 self-test */