diff --git a/src/crypto/mishmash/oid_x25519.c b/src/crypto/mishmash/oid_x25519.c index 2907eb461..96d1c2b57 100644 --- a/src/crypto/mishmash/oid_x25519.c +++ b/src/crypto/mishmash/oid_x25519.c @@ -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 ), diff --git a/src/crypto/x25519.c b/src/crypto/x25519.c index 95c42ea13..2a174a501 100644 --- a/src/crypto/x25519.c +++ b/src/crypto/x25519.c @@ -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, +}; diff --git a/src/include/ipxe/x25519.h b/src/include/ipxe/x25519.h index ef294f7b2..358746366 100644 --- a/src/include/ipxe/x25519.h +++ b/src/include/ipxe/x25519.h @@ -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 */ diff --git a/src/tests/x25519_test.c b/src/tests/x25519_test.c index bd348b832..ab719e25b 100644 --- a/src/tests/x25519_test.c +++ b/src/tests/x25519_test.c @@ -38,6 +38,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include #include +#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 */