]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[crypto] Allow for an explicit representation of point at infinity
authorMichael Brown <mcb30@ipxe.org>
Thu, 18 Dec 2025 15:38:11 +0000 (15:38 +0000)
committerMichael Brown <mcb30@ipxe.org>
Thu, 18 Dec 2025 15:47:29 +0000 (15:47 +0000)
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>
src/crypto/ecdhe.c
src/crypto/weierstrass.c
src/crypto/x25519.c
src/include/ipxe/crypto.h
src/include/ipxe/errfile.h
src/include/ipxe/weierstrass.h
src/include/ipxe/x25519.h
src/tests/elliptic_test.c
src/tests/p256_test.c
src/tests/p384_test.c
src/tests/x25519_test.c

index 592c8ca1aafcc1571b7e989ac8bc0ed54ed403aa..6c86b1c903b85501bf287a363b38d9bd132b81c9 100644 (file)
@@ -30,6 +30,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  */
 
 #include <string.h>
+#include <errno.h>
 #include <ipxe/ecdhe.h>
 
 /**
@@ -62,5 +63,12 @@ int ecdhe_key ( struct elliptic_curve *curve, const void *partner,
                return rc;
        }
 
+       /* Check that partner and shared keys are not the point at infinity */
+       if ( elliptic_is_infinity ( curve, shared ) ) {
+               DBGC ( curve, "CURVE %s constructed point at infinity\n",
+                      curve->name );
+               return -EPERM;
+       }
+
        return 0;
 }
index b19970cef99f31526cd97ee4a5f96c13c747b452..bb9b50bf8aabf5f845315ab68080b3a5d65edbf8 100644 (file)
@@ -658,7 +658,7 @@ static void weierstrass_add_ladder ( const bigint_element_t *operand0,
 }
 
 /**
- * Verify point is on curve
+ * Verify freshly initialised point is on curve
  *
  * @v curve            Weierstrass curve
  * @v point0           Element 0 of point (x,y,z) to be verified
@@ -667,6 +667,10 @@ static void weierstrass_add_ladder ( const bigint_element_t *operand0,
  * As with point addition, points are represented in projective
  * coordinates, with all values in Montgomery form and in the range
  * [0,4N) where N is the field prime.
+ *
+ * This verification logic is valid only for points that have been
+ * freshly constructed via weierstrass_init() (i.e. must either have
+ * z=1 or be the point at infinity (0,1,0)).
  */
 static int weierstrass_verify_raw ( const struct weierstrass_curve *curve,
                                    const bigint_element_t *point0 ) {
@@ -719,6 +723,10 @@ static int weierstrass_verify_raw ( const struct weierstrass_curve *curve,
                 *              = 3*(x^3 + a*x + b - y^2)           (mod 13N)
                 */
                WEIERSTRASS_ADD2 ( Wt, 3b ),
+               /* [Wt] check   = 3Txaxyb * z                       (mod 2N)
+                *              = 3*(x^3 + a*x + b - y^2) * z       (mod 2N)
+                */
+               WEIERSTRASS_MUL2 ( Wt, z1 ),
                /* Stop */
                WEIERSTRASS_STOP
        };
@@ -728,6 +736,7 @@ static int weierstrass_verify_raw ( const struct weierstrass_curve *curve,
        regs[WEIERSTRASS_3b] = ( ( void * ) b3 );
        regs[WEIERSTRASS_x1] = ( ( void * ) &point->x );
        regs[WEIERSTRASS_y1] = ( ( void * ) &point->y );
+       regs[WEIERSTRASS_z1] = ( ( void * ) &point->z );
        regs[WEIERSTRASS_Wt] = &temp.Wt;
        regs[WEIERSTRASS_Wp] = &temp.Wp;
 
@@ -748,7 +757,7 @@ static int weierstrass_verify_raw ( const struct weierstrass_curve *curve,
 }
 
 /**
- * Verify point is on curve
+ * Verify freshly initialised point is on curve
  *
  * @v curve            Weierstrass curve
  * @v point            Point (x,y,z) to be verified
@@ -787,6 +796,7 @@ static int weierstrass_init_raw ( struct weierstrass_curve *curve,
                weierstrass_t ( size ) point;
        } __attribute__ (( may_alias )) *temp = ( ( void * ) temp0 );
        size_t offset;
+       int is_infinite;
        unsigned int i;
        int rc;
 
@@ -810,7 +820,9 @@ static int weierstrass_init_raw ( struct weierstrass_curve *curve,
                bigint_montgomery_relaxed ( prime, &temp->product,
                                            &point->axis[i] );
        }
-       bigint_copy ( one, &point->z );
+       memset ( &point->z, 0, sizeof ( point->z ) );
+       is_infinite = bigint_is_zero ( &point->xy );
+       bigint_copy ( one, &point->axis[ is_infinite ? 1 : 2 ] );
        DBGC ( curve, ")\n" );
 
        /* Verify point is on curve */
@@ -841,11 +853,10 @@ static int weierstrass_init_raw ( struct weierstrass_curve *curve,
  * @v point0           Element 0 of point (x,y,z)
  * @v temp0            Element 0 of temporary point buffer
  * @v out              Output buffer
- * @ret rc             Return status code
  */
-static int weierstrass_done_raw ( struct weierstrass_curve *curve,
-                                 bigint_element_t *point0,
-                                 bigint_element_t *temp0, void *out ) {
+static void weierstrass_done_raw ( struct weierstrass_curve *curve,
+                                  bigint_element_t *point0,
+                                  bigint_element_t *temp0, void *out ) {
        unsigned int size = curve->size;
        size_t len = curve->len;
        const bigint_t ( size ) __attribute__ (( may_alias )) *prime =
@@ -882,12 +893,6 @@ static int weierstrass_done_raw ( struct weierstrass_curve *curve,
                bigint_done ( &point->axis[i], ( out + offset ), len );
        }
        DBGC ( curve, ")\n" );
-
-       /* Verify result is not the point at infinity */
-       if ( bigint_is_zero ( &temp->point.z ) )
-               return -EINVAL;
-
-       return 0;
 }
 
 /**
@@ -904,6 +909,36 @@ static int weierstrass_done_raw ( struct weierstrass_curve *curve,
                               (temp)->all.element, (out) );            \
        } )
 
+/**
+ * Check if this is the point at infinity
+ *
+ * @v point            Curve point
+ * @ret is_infinity    This is the point at infinity
+ */
+int weierstrass_is_infinity ( struct weierstrass_curve *curve,
+                             const void *point ) {
+       unsigned int size = curve->size;
+       size_t len = curve->len;
+       struct {
+               bigint_t ( size ) axis;
+       } temp;
+       size_t offset;
+       int is_finite = 0;
+       unsigned int i;
+
+       /* We use all zeroes to represent the point at infinity */
+       DBGC ( curve, "WEIERSTRASS %s point (", curve->name );
+       for ( i = 0, offset = 0 ; i < WEIERSTRASS_AXES ; i++, offset += len ) {
+               bigint_init ( &temp.axis, ( point + offset ), len );
+               DBGC ( curve, "%s%s", ( i ? "," : "" ),
+                      bigint_ntoa ( &temp.axis ) );
+               is_finite |= ( ! bigint_is_zero ( &temp.axis ) );
+       }
+       DBGC ( curve, ") is%s infinity\n", ( is_finite ? " not" : "" ) );
+
+       return ( ! is_finite );
+}
+
 /**
  * Multiply curve point by scalar
  *
@@ -946,10 +981,7 @@ int weierstrass_multiply ( struct weierstrass_curve *curve, const void *base,
                        weierstrass_add_ladder, curve, NULL );
 
        /* Convert result back to affine co-ordinates */
-       if ( ( rc = weierstrass_done ( curve, &temp.result, &temp.multiple,
-                                      result ) ) != 0 ) {
-               return rc;
-       }
+       weierstrass_done ( curve, &temp.result, &temp.multiple, result );
 
        return 0;
 }
@@ -963,8 +995,9 @@ int weierstrass_multiply ( struct weierstrass_curve *curve, const void *base,
  * @v result           Curve point to hold result
  * @ret rc             Return status code
  */
-int weierstrass_add_once ( struct weierstrass_curve *curve, const void *addend,
-                          const void *augend, void *result ) {
+int weierstrass_add_once ( struct weierstrass_curve *curve,
+                          const void *addend, const void *augend,
+                          void *result ) {
        unsigned int size = curve->size;
        struct {
                weierstrass_t ( size ) addend;
@@ -987,10 +1020,7 @@ int weierstrass_add_once ( struct weierstrass_curve *curve, const void *addend,
        weierstrass_add ( curve, &temp.augend, &temp.addend, &temp.result );
 
        /* Convert result back to affine co-ordinates */
-       if ( ( rc = weierstrass_done ( curve, &temp.result, &temp.addend,
-                                      result ) ) != 0 ) {
-               return rc;
-       }
+       weierstrass_done ( curve, &temp.result, &temp.addend, result );
 
        return 0;
 }
index 11094ba6e440dc2fbeaec588a1fbea16b75f1da5..4b4c489da4c095c18229b19895ac2884cbfd8410 100644 (file)
@@ -783,17 +783,30 @@ static void x25519_reverse ( struct x25519_value *value ) {
        } while ( ++low < --high );
 }
 
+/**
+ * Check if X25519 value is zero
+ *
+ * @v value            Value to check
+ * @ret is_zero                Value is zero
+ */
+int x25519_is_zero ( const struct x25519_value *value ) {
+       x25519_t point;
+
+       /* Check if value is zero */
+       bigint_init ( &point, value->raw, sizeof ( value->raw ) );
+       return bigint_is_zero ( &point );
+}
+
 /**
  * Calculate X25519 key
  *
  * @v base             Base point
  * @v scalar           Scalar multiple
  * @v result           Point to hold result (may overlap base point)
- * @ret rc             Return status code
  */
-int x25519_key ( const struct x25519_value *base,
-                const struct x25519_value *scalar,
-                struct x25519_value *result ) {
+void x25519_key ( const struct x25519_value *base,
+                 const struct x25519_value *scalar,
+                 struct x25519_value *result ) {
        struct x25519_value *tmp = result;
        union x25519_quad257 point;
 
@@ -814,9 +827,18 @@ int x25519_key ( const struct x25519_value *base,
        /* Reverse result */
        bigint_done ( &point.value, result->raw, sizeof ( result->raw ) );
        x25519_reverse ( result );
+}
+
+/**
+ * Check if this is the point at infinity
+ *
+ * @v point            Curve point
+ * @ret is_infinity    This is the point at infinity
+ */
+static int x25519_curve_is_infinity ( const void *point ) {
 
-       /* Fail if result was all zeros (as required by RFC8422) */
-       return ( bigint_is_zero ( &point.value ) ? -EPERM : 0 );
+       /* We use all zeroes for the point at infinity (as per RFC8422) */
+       return x25519_is_zero ( point );
 }
 
 /**
@@ -830,7 +852,8 @@ int x25519_key ( const struct x25519_value *base,
 static int x25519_curve_multiply ( const void *base, const void *scalar,
                                   void *result ) {
 
-       return x25519_key ( base, scalar, result );
+       x25519_key ( base, scalar, result );
+       return 0;
 }
 
 /**
@@ -854,6 +877,7 @@ struct elliptic_curve x25519_curve = {
        .pointsize = sizeof ( struct x25519_value ),
        .keysize = sizeof ( struct x25519_value ),
        .base = x25519_generator.raw,
+       .is_infinity = x25519_curve_is_infinity,
        .multiply = x25519_curve_multiply,
        .add = x25519_curve_add,
 };
index 93b718e15a266004f1b00c93d3df425ca6f6c40c..dd567fb2c965254111662112465782e5c27ab98e 100644 (file)
@@ -185,6 +185,16 @@ struct elliptic_curve {
        const void *base;
        /** Order of the generator (if prime) */
        const void *order;
+       /** Check if this is the point at infinity
+        *
+        * @v point             Curve point
+        * @ret is_infinity     This is the point at infinity
+        *
+        * The point at infinity cannot be represented in affine
+        * coordinates.  Each curve must choose a representation of
+        * the point at infinity (e.g. all zeroes).
+        */
+       int ( * is_infinity ) ( const void *point );
        /** Multiply scalar by curve point
         *
         * @v base              Base point
@@ -307,6 +317,11 @@ pubkey_match ( struct pubkey_algorithm *pubkey,
        return pubkey->match ( private_key, public_key );
 }
 
+static inline __attribute__ (( always_inline )) int
+elliptic_is_infinity ( struct elliptic_curve *curve, const void *point ) {
+       return curve->is_infinity ( point );
+}
+
 static inline __attribute__ (( always_inline )) int
 elliptic_multiply ( struct elliptic_curve *curve,
                    const void *base, const void *scalar, void *result ) {
index 0c28810ea733f4657269c09495f809814c99fc87..e8d010475120163f133ec07915ca6a63432ac1bc 100644 (file)
@@ -443,6 +443,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #define ERRFILE_usb_settings         ( ERRFILE_OTHER | 0x00650000 )
 #define ERRFILE_weierstrass          ( ERRFILE_OTHER | 0x00660000 )
 #define ERRFILE_efi_cacert           ( ERRFILE_OTHER | 0x00670000 )
+#define ERRFILE_ecdhe                ( ERRFILE_OTHER | 0x00680000 )
 
 /** @} */
 
index ca3c216e62c8dcc7d5d9c6fd323320aeb0605f95..15dd9ce03c58998aa786d8c717bf32e24004f064 100644 (file)
@@ -62,6 +62,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
                        bigint_t ( size ) y;                            \
                        bigint_t ( size ) z;                            \
                };                                                      \
+               bigint_t ( size * 2 ) xy;                               \
                bigint_t ( size * 3 ) all;                              \
        }
 
@@ -123,6 +124,8 @@ struct weierstrass_curve {
        };
 };
 
+extern int weierstrass_is_infinity ( struct weierstrass_curve *curve,
+                                    const void *point );
 extern int weierstrass_multiply ( struct weierstrass_curve *curve,
                                  const void *base, const void *scalar,
                                  void *result );
@@ -154,6 +157,10 @@ extern int weierstrass_add_once ( struct weierstrass_curve *curve,
                .a = (_name ## _cache)[6].element,                      \
                .b3 = (_name ## _cache)[7].element,                     \
        };                                                              \
+       static int _name ## _is_infinity ( const void *point) {         \
+               return weierstrass_is_infinity ( &_name ## _weierstrass,\
+                                                point );               \
+       }                                                               \
        static int _name ## _multiply ( const void *base,               \
                                        const void *scalar,             \
                                        void *result ) {                \
@@ -171,6 +178,7 @@ extern int weierstrass_add_once ( struct weierstrass_curve *curve,
                .keysize = (_len),                                      \
                .base = (_base),                                        \
                .order = (_order),                                      \
+               .is_infinity = _name ## _is_infinity,                   \
                .multiply = _name ## _multiply,                         \
                .add = _name ## _add,                                   \
        }
index fd7caeee989ea154e2eb781a1bdb6cb9044aebed..d570282c5d793d1392aedca2d3c42f254d87af30 100644 (file)
@@ -85,9 +85,10 @@ extern void x25519_multiply ( const union x25519_oct258 *multiplicand,
 extern void x25519_invert ( const union x25519_oct258 *invertend,
                            union x25519_quad257 *result );
 extern void x25519_reduce ( union x25519_quad257 *value );
-extern int x25519_key ( const struct x25519_value *base,
-                       const struct x25519_value *scalar,
-                       struct x25519_value *result );
+extern void x25519_key ( const struct x25519_value *base,
+                        const struct x25519_value *scalar,
+                        struct x25519_value *result );
+extern int x25519_is_zero ( const struct x25519_value *value );
 
 extern struct elliptic_curve x25519_curve;
 
index 5b21ee00edce1b7b5e2e98038a8bc017f943f9ff..614257d92e06194ef235ebed899e19d3094ba970 100644 (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.
index b7bbe47b6cb161330eeddd30c81fadccc1ba6bbb..2a04b69c86df601ac23a8a6efded4e6f835c09c1 100644 (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 );
index c67cfbc796d04cbe3716403c3470e60aa1a25109..b1b93faa406bd660bf9a527293893bfb3dff9409 100644 (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 );
index 3dfbd3393e5417dc3635fa88cd97a474f62946e4..bd348b832e74636d30e66e582ff16dca896d5ec9 100644 (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 ) );