]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[crypto] Expose the (prime) group order as an elliptic curve property
authorMichael Brown <mcb30@ipxe.org>
Fri, 5 Dec 2025 14:47:55 +0000 (14:47 +0000)
committerMichael Brown <mcb30@ipxe.org>
Fri, 5 Dec 2025 15:10:22 +0000 (15:10 +0000)
ECDSA requires knowledge of the group order of the base point, and is
defined only for curves with a prime group order (e.g. the NIST
curves).

Add the group order as an explicit property of an elliptic curve, and
add tests to verify that the order is correct.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/crypto/p256.c
src/crypto/p384.c
src/include/ipxe/crypto.h
src/include/ipxe/weierstrass.h
src/tests/elliptic_test.c
src/tests/elliptic_test.h
src/tests/p256_test.c
src/tests/p384_test.c

index 9b0b542a1675e8d7c597e1d3871179a9856b08ee..2ba66e72c634324c0e095c35287538039e28dfa1 100644 (file)
@@ -62,6 +62,13 @@ static const uint8_t p256_base[ P256_LEN * 2 ] = {
        0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5
 };
 
+/** P-256 group order */
+static const uint8_t p256_order[P256_LEN] = {
+       0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17,
+       0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51
+};
+
 /** P-256 elliptic curve */
 WEIERSTRASS_CURVE ( p256, p256_curve, P256_LEN,
-                   p256_prime, p256_a, p256_b, p256_base );
+                   p256_prime, p256_a, p256_b, p256_base, p256_order );
index 887bf161d5fa4be25bf91e2f801594c922f6a3f9..a53a9ce9dc49549e054897ccda4032be9a986fc1 100644 (file)
@@ -71,6 +71,15 @@ static const uint8_t p384_base[ P384_LEN * 2 ] = {
        0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5f
 };
 
+/** P-384 group order */
+static const uint8_t p384_order[P384_LEN] = {
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xc7, 0x63, 0x4d, 0x81, 0xf4, 0x37, 0x2d, 0xdf, 0x58,
+       0x1a, 0x0d, 0xb2, 0x48, 0xb0, 0xa7, 0x7a, 0xec, 0xec, 0x19, 0x6a,
+       0xcc, 0xc5, 0x29, 0x73
+};
+
 /** P-384 elliptic curve */
 WEIERSTRASS_CURVE ( p384, p384_curve, P384_LEN,
-                   p384_prime, p384_a, p384_b, p384_base );
+                   p384_prime, p384_a, p384_b, p384_base, p384_order );
index d2adea5d6e02257674ccbdd2059d97b78371d6c1..8941ffa01e3380a9fd96d63698a0e0a6fec7015f 100644 (file)
@@ -183,6 +183,8 @@ struct elliptic_curve {
        size_t keysize;
        /** Generator base point */
        const void *base;
+       /** Order of the generator (if prime) */
+       const void *order;
        /** Multiply scalar by curve point
         *
         * @v base              Base point
index e5e411499cbb57ce2f83f26d7f947b374849598f..b718886f6302acccabcd5c0d9aca9576aeed4970 100644 (file)
@@ -128,7 +128,8 @@ extern int weierstrass_multiply ( struct weierstrass_curve *curve,
                                  void *result );
 
 /** Define a Weierstrass curve */
-#define WEIERSTRASS_CURVE( _name, _curve, _len, _prime, _a, _b, _base )        \
+#define WEIERSTRASS_CURVE( _name, _curve, _len, _prime, _a, _b, _base, \
+                          _order )                                     \
        static bigint_t ( weierstrass_size(_len) )                      \
                _name ## _cache[WEIERSTRASS_NUM_CACHED];                \
        static struct weierstrass_curve _name ## _weierstrass = {       \
@@ -161,6 +162,7 @@ extern int weierstrass_multiply ( struct weierstrass_curve *curve,
                .pointsize = ( WEIERSTRASS_AXES * (_len) ),             \
                .keysize = (_len),                                      \
                .base = (_base),                                        \
+               .order = (_order),                                      \
                .multiply = _name ## _multiply,                         \
        }
 
index f856dcc7e0f5b5559239f62d27c87f464a2a11e2..a2266626d4a7dd2cd91753e764f4f8a9ad7ab556 100644 (file)
@@ -35,10 +35,53 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #include <stdint.h>
 #include <string.h>
 #include <assert.h>
+#include <ipxe/bigint.h>
 #include <ipxe/crypto.h>
 #include <ipxe/test.h>
 #include "elliptic_test.h"
 
+/**
+ * Report elliptic curve sanity test result
+ *
+ * @v curve            Elliptic curve
+ * @v file             Test code file
+ * @v line             Test code line
+ */
+void elliptic_curve_okx ( struct elliptic_curve *curve, const char *file,
+                         unsigned int line ) {
+       static const uint8_t one[] = { 1 };
+       size_t pointsize = curve->pointsize;
+       size_t keysize = curve->keysize;
+       uint8_t point[pointsize];
+       uint8_t scalar[keysize];
+       struct {
+               bigint_t ( bigint_required_size ( keysize ) ) scalar;
+               bigint_t ( bigint_required_size ( keysize ) ) one;
+       } temp;
+
+       /* Check that curve has the required properties */
+       okx ( curve->base != NULL, file, line );
+       okx ( curve->order != NULL, 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).
+        */
+       okx ( elliptic_multiply ( curve, curve->base, curve->order,
+                                 point ) != 0, file, line );
+
+       /* Test multiplying base point by group order plus one, to get
+        * back to the base point.
+        */
+       bigint_init ( &temp.scalar, curve->order, keysize );
+       bigint_init ( &temp.one, one, sizeof ( one ) );
+       bigint_add ( &temp.one, &temp.scalar );
+       bigint_done ( &temp.scalar, scalar, sizeof ( scalar ) );
+       okx ( elliptic_multiply ( curve, curve->base, scalar, point ) == 0,
+             file, line );
+       okx ( memcmp ( point, curve->base, pointsize ) == 0, file, line );
+}
+
 /**
  * Report elliptic curve point multiplication test result
  *
index ea2fb97d9e2daacf5e31f3302e5416b17693f9d4..1fcc4b108480d415fa191ce3df6807d044ccca0b 100644 (file)
@@ -64,9 +64,19 @@ struct elliptic_multiply_test {
                .expected_len = sizeof ( name ## _expected ),           \
        };
 
+extern void elliptic_curve_okx ( struct elliptic_curve *curve,
+                                const char *file, unsigned int line );
 extern void elliptic_multiply_okx ( struct elliptic_multiply_test *test,
                                    const char *file, unsigned int line );
 
+/**
+ * Report an elliptic curve sanity test result
+ *
+ * @v curve            Elliptic curve
+ */
+#define elliptic_curve_ok( curve ) \
+       elliptic_curve_okx ( curve, __FILE__, __LINE__ )
+
 /**
  * Report an elliptic curve point multiplication test result
  *
index e6db61a53ecd344d27a1be08f25ad844868de15a..8b425f2154045d4c0458d94e7449f47f6a7b0391 100644 (file)
@@ -157,6 +157,9 @@ ELLIPTIC_MULTIPLY_TEST ( invalid_one, &p256_curve,
  */
 static void p256_test_exec ( void ) {
 
+       /* Curve sanity test */
+       elliptic_curve_ok ( &p256_curve );
+
        /* Tests from http://point-at-infinity.org/ecc/nisttv */
        elliptic_multiply_ok ( &poi_1 );
        elliptic_multiply_ok ( &poi_2 );
index 35c5679f8286d7bd3a19cd329c35dee6bdcbf222..0b172c6489b9166b416cf80d563de42fa4cf62b0 100644 (file)
@@ -203,6 +203,9 @@ ELLIPTIC_MULTIPLY_TEST ( invalid_one, &p384_curve,
  */
 static void p384_test_exec ( void ) {
 
+       /* Curve sanity test */
+       elliptic_curve_ok ( &p384_curve );
+
        /* Tests from http://point-at-infinity.org/ecc/nisttv */
        elliptic_multiply_ok ( &poi_1 );
        elliptic_multiply_ok ( &poi_2 );