[crypto] Allow for an explicit representation of point at infinity

ECDSA requires the ability to add two arbitrary curve points, either
of which may legitimately be the point at infinity.

Update the API so that curves must choose an explicit affine
representation for the point at infinity, and provide a method to test
for this representation.  Multiplication and addition will now allow
this representation to be provided as an input, and will not fail if
the result is the point at infinity.  Callers must explicitly check
for the point at infinity where needed (e.g. after computing the ECDHE
shared secret curve point).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2025-12-18 15:38:11 +00:00
parent af99310f55
commit cfbf0da93c
11 changed files with 225 additions and 58 deletions
+4 -3
View File
@@ -62,13 +62,14 @@ void elliptic_curve_okx ( struct elliptic_curve *curve, const char *file,
/* Check that curve has the required properties */
okx ( curve->base != NULL, file, line );
okx ( curve->order != NULL, file, line );
okx ( ( ! elliptic_is_infinity ( curve, curve->base ) ), file, line );
/* Test multiplying base point by group order. Result should
* be the point at infinity, which should not be representable
* as a point in affine coordinates (and so should fail).
* be the point at infinity.
*/
okx ( elliptic_multiply ( curve, curve->base, curve->order,
point ) != 0, file, line );
point ) == 0, file, line );
okx ( elliptic_is_infinity ( curve, point ), file, line );
/* Test multiplying base point by group order plus one, to get
* back to the base point.
+36 -3
View File
@@ -119,8 +119,8 @@ ELLIPTIC_MULTIPLY_TEST ( poi_large, &p256_curve, BASE_GENERATOR,
0xd4, 0x31, 0xcc, 0xa9, 0x94, 0xce, 0xa1, 0x31,
0x34, 0x49, 0xbf, 0x97, 0xc8, 0x40, 0xae, 0x0a ) );
/* Invalid curve point zero */
ELLIPTIC_MULTIPLY_TEST ( invalid_zero, &p256_curve,
/* Point at infinity */
ELLIPTIC_MULTIPLY_TEST ( infinity, &p256_curve,
BASE ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -129,6 +129,29 @@ ELLIPTIC_MULTIPLY_TEST ( invalid_zero, &p256_curve,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ),
SCALAR ( 0x8d, 0x50, 0x48, 0x0c, 0xbe, 0x22, 0x4d, 0x01,
0xbc, 0xff, 0x67, 0x8d, 0xad, 0xb1, 0x87, 0x99,
0x47, 0xb9, 0x79, 0x02, 0xb0, 0x70, 0x47, 0xf0,
0x9f, 0x17, 0x25, 0x7e, 0xcf, 0x0b, 0x3e, 0x73 ),
EXPECTED ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ) );
/* Invalid curve point (zero, base_y) */
ELLIPTIC_MULTIPLY_TEST ( invalid_zero, &p256_curve,
BASE ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b,
0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16,
0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce,
0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf4 ),
SCALAR ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -223,7 +246,14 @@ ELLIPTIC_ADD_TEST ( poi_1_n_1, &p256_curve,
0x71, 0x18, 0x14, 0xb5, 0x83, 0xf0, 0x61, 0xe9,
0xd4, 0x31, 0xcc, 0xa9, 0x94, 0xce, 0xa1, 0x31,
0x34, 0x49, 0xbf, 0x97, 0xc8, 0x40, 0xae, 0x0a ),
EXPECTED_FAIL );
EXPECTED ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ) );
/**
* Perform P-256 self-test
@@ -241,6 +271,9 @@ static void p256_test_exec ( void ) {
elliptic_multiply_ok ( &poi_mid );
elliptic_multiply_ok ( &poi_large );
/* Point at infinity */
elliptic_multiply_ok ( &infinity );
/* Invalid point tests */
elliptic_multiply_ok ( &invalid_zero );
elliptic_multiply_ok ( &invalid_one );
+62 -15
View File
@@ -153,8 +153,8 @@ ELLIPTIC_MULTIPLY_TEST ( poi_large, &p384_curve, BASE_GENERATOR,
0xf5, 0x9f, 0x4e, 0x30, 0xe2, 0x81, 0x7e, 0x62,
0x85, 0xbc, 0xe2, 0x84, 0x6f, 0x15, 0xf1, 0xa0 ) );
/* Invalid curve point zero */
ELLIPTIC_MULTIPLY_TEST ( invalid_zero, &p384_curve,
/* Point at infinity */
ELLIPTIC_MULTIPLY_TEST ( infinity, &p384_curve,
BASE ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -173,22 +173,55 @@ ELLIPTIC_MULTIPLY_TEST ( invalid_zero, &p384_curve,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ),
EXPECTED ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ) );
/* Invalid curve point (zero, base_y) */
ELLIPTIC_MULTIPLY_TEST ( invalid_zero, &p384_curve,
BASE ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f,
0x5d, 0x9e, 0x98, 0xbf, 0x92, 0x92, 0xdc, 0x29,
0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c,
0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0,
0x0a, 0x60, 0xb1, 0xce, 0x1d, 0x7e, 0x81, 0x9d,
0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5e ),
SCALAR ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ),
EXPECTED_FAIL );
/* Invalid curve point (base_x, base_y - 1) */
ELLIPTIC_MULTIPLY_TEST ( invalid_one, &p384_curve,
BASE ( 0xaa, 0x87, 0xca, 0x22, 0xbe, 0x8b, 0x05, 0x37,
0x8e, 0xb1, 0xc7, 0x1e, 0xf3, 0x20, 0xad, 0x74,
0x6e, 0x1d, 0x3b, 0x62, 0x8b, 0xa7, 0x9b, 0x98,
0x59, 0xf7, 0x41, 0xe0, 0x82, 0x54, 0x2a, 0x38,
0x55, 0x02, 0xf2, 0x5d, 0xbf, 0x55, 0x29, 0x6c,
0x3a, 0x54, 0x5e, 0x38, 0x72, 0x76, 0x0a, 0xb7,
0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f,
0x5d, 0x9e, 0x98, 0xbf, 0x92, 0x92, 0xdc, 0x29,
0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c,
0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0,
0x0a, 0x60, 0xb1, 0xce, 0x1d, 0x7e, 0x81, 0x9d,
0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5e ),
BASE ( 0xaa, 0x87, 0xca, 0x22, 0xbe, 0x8b, 0x05, 0x37,
0x8e, 0xb1, 0xc7, 0x1e, 0xf3, 0x20, 0xad, 0x74,
0x6e, 0x1d, 0x3b, 0x62, 0x8b, 0xa7, 0x9b, 0x98,
0x59, 0xf7, 0x41, 0xe0, 0x82, 0x54, 0x2a, 0x38,
0x55, 0x02, 0xf2, 0x5d, 0xbf, 0x55, 0x29, 0x6c,
0x3a, 0x54, 0x5e, 0x38, 0x72, 0x76, 0x0a, 0xb7,
0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f,
0x5d, 0x9e, 0x98, 0xbf, 0x92, 0x92, 0xdc, 0x29,
0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c,
0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0,
0x0a, 0x60, 0xb1, 0xce, 0x1d, 0x7e, 0x81, 0x9d,
0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5e ),
SCALAR ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -301,7 +334,18 @@ ELLIPTIC_ADD_TEST ( poi_1_n_1, &p384_curve,
0x16, 0x25, 0xce, 0xec, 0x4a, 0x0f, 0x47, 0x3e,
0xf5, 0x9f, 0x4e, 0x30, 0xe2, 0x81, 0x7e, 0x62,
0x85, 0xbc, 0xe2, 0x84, 0x6f, 0x15, 0xf1, 0xa0 ),
EXPECTED_FAIL );
EXPECTED ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ) );
/**
* Perform P-384 self-test
@@ -319,6 +363,9 @@ static void p384_test_exec ( void ) {
elliptic_multiply_ok ( &poi_mid );
elliptic_multiply_ok ( &poi_large );
/* Point at infinity */
elliptic_multiply_ok ( &infinity );
/* Invalid point tests */
elliptic_multiply_ok ( &invalid_zero );
elliptic_multiply_ok ( &invalid_one );
+3 -4
View File
@@ -263,7 +263,6 @@ static void x25519_key_okx ( struct x25519_key_test *test,
struct x25519_value scalar;
struct x25519_value actual;
unsigned int i;
int rc;
/* Construct input values */
memcpy ( &base, &test->base, sizeof ( test->base ) );
@@ -277,11 +276,11 @@ static void x25519_key_okx ( struct x25519_key_test *test,
/* Calculate key */
for ( i = 0 ; i < test->count ; i++ ) {
rc = x25519_key ( &base, &scalar, &actual );
x25519_key ( &base, &scalar, &actual );
if ( test->fail ) {
okx ( rc != 0, file, line );
okx ( x25519_is_zero ( &actual ), file, line );
} else {
okx ( rc == 0, file, line );
okx ( ( ! x25519_is_zero ( &actual ) ), file, line );
}
memcpy ( &base, &scalar, sizeof ( base ) );
memcpy ( &scalar, &actual, sizeof ( scalar ) );