]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[crypto] Split out Weierstrass point initialisation and finalisation
authorMichael Brown <mcb30@ipxe.org>
Fri, 5 Dec 2025 16:08:49 +0000 (16:08 +0000)
committerMichael Brown <mcb30@ipxe.org>
Fri, 5 Dec 2025 16:13:02 +0000 (16:13 +0000)
Prepare for adding an operation to add arbitrary curve points by
splitting out initialisation and finalisation from the multiplication
operation.

Pass explicit temporary buffer pointers to weierstrass_init() and
weierstrass_done(), to ensure that stack consumption does not increase
as a result of splitting out this functionality.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/crypto/weierstrass.c

index ecc468af2d2f9d3a82e808239951dbd92211e66e..ecc9699a146eb339c28cefecdc185005e4319e99 100644 (file)
@@ -170,7 +170,7 @@ enum weierstrass_opcode {
  *
  * @v curve            Weierstrass curve
  */
-static void weierstrass_init ( struct weierstrass_curve *curve ) {
+static void weierstrass_init_curve ( struct weierstrass_curve *curve ) {
        unsigned int size = curve->size;
        bigint_t ( size ) __attribute__ (( may_alias )) *prime =
                ( ( void * ) curve->prime[0] );
@@ -759,39 +759,33 @@ static int weierstrass_verify_raw ( const struct weierstrass_curve *curve,
        } )
 
 /**
- * Multiply curve point by scalar
+ * Initialise curve point
  *
  * @v curve            Weierstrass curve
- * @v base             Base point
- * @v scalar           Scalar multiple
- * @v result           Result point to fill in
+ * @v point0           Element 0 of point (x,y,z) to be filled in
+ * @v temp0            Element 0 of temporary point buffer
+ * @v data             Raw curve point
  * @ret rc             Return status code
  */
-int weierstrass_multiply ( struct weierstrass_curve *curve, const void *base,
-                          const void *scalar, void *result ) {
+static int weierstrass_init_raw ( struct weierstrass_curve *curve,
+                                 bigint_element_t *point0,
+                                 bigint_element_t *temp0, const void *data ) {
        unsigned int size = curve->size;
        size_t len = curve->len;
        const bigint_t ( size ) __attribute__ (( may_alias )) *prime =
                ( ( const void * ) curve->prime[0] );
        const bigint_t ( size ) __attribute__ (( may_alias )) *prime2 =
                ( ( const void * ) curve->prime[WEIERSTRASS_2N] );
-       const bigint_t ( size ) __attribute__ (( may_alias )) *fermat =
-               ( ( const void * ) curve->fermat );
        const bigint_t ( size ) __attribute__ (( may_alias )) *square =
                ( ( const void * ) curve->square );
        const bigint_t ( size ) __attribute__ (( may_alias )) *one =
                ( ( const void * ) curve->one );
-       struct {
-               union {
-                       weierstrass_t ( size ) result;
-                       bigint_t ( size * 2 ) product_in;
-               };
-               union {
-                       weierstrass_t ( size ) multiple;
-                       bigint_t ( size * 2 ) product_out;
-               };
-               bigint_t ( bigint_required_size ( len ) ) scalar;
-       } temp;
+       weierstrass_t ( size ) __attribute__ (( may_alias ))
+               *point = ( ( void * ) point0 );
+       union {
+               bigint_t ( size * 2 ) product;
+               weierstrass_t ( size ) point;
+       } __attribute__ (( may_alias )) *temp = ( ( void * ) temp0 );
        size_t offset;
        unsigned int i;
        int rc;
@@ -804,26 +798,140 @@ int weierstrass_multiply ( struct weierstrass_curve *curve, const void *base,
         * non-zero.
         */
        if ( ! prime2->element[0] )
-               weierstrass_init ( curve );
+               weierstrass_init_curve ( curve );
 
        /* Convert input to projective coordinates in Montgomery form */
-       DBGC ( curve, "WEIERSTRASS %s base (", curve->name );
+       DBGC ( curve, "WEIERSTRASS %s point (", curve->name );
        for ( i = 0, offset = 0 ; i < WEIERSTRASS_AXES ; i++, offset += len ) {
-               bigint_init ( &temp.multiple.axis[i], ( base + offset ), len );
+               bigint_init ( &point->axis[i], ( data + offset ), len );
                DBGC ( curve, "%s%s", ( i ? "," : "" ),
-                      bigint_ntoa ( &temp.multiple.axis[i] ) );
-               bigint_multiply ( &temp.multiple.axis[i], square,
-                                 &temp.product_in );
-               bigint_montgomery_relaxed ( prime, &temp.product_in,
-                                           &temp.multiple.axis[i] );
+                      bigint_ntoa ( &point->axis[i] ) );
+               bigint_multiply ( &point->axis[i], square, &temp->product );
+               bigint_montgomery_relaxed ( prime, &temp->product,
+                                           &point->axis[i] );
        }
-       bigint_copy ( one, &temp.multiple.z );
+       bigint_copy ( one, &point->z );
        DBGC ( curve, ")\n" );
 
        /* Verify point is on curve */
-       if ( ( rc = weierstrass_verify ( curve, &temp.multiple ) ) != 0 )
+       if ( ( rc = weierstrass_verify ( curve, point ) ) != 0 )
                return rc;
 
+       return 0;
+}
+
+/**
+ * Initialise curve point
+ *
+ * @v curve            Weierstrass curve
+ * @v point            Point (x,y,z) to be filled in
+ * @v temp             Temporary point buffer
+ * @v data             Raw curve point
+ * @ret rc             Return status code
+ */
+#define weierstrass_init( curve, point, temp, data ) ( {               \
+       weierstrass_init_raw ( (curve), (point)->all.element,           \
+                              (temp)->all.element, (data) );           \
+       } )
+
+/**
+ * Finalise curve point
+ *
+ * @v curve            Weierstrass 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 ) {
+       unsigned int size = curve->size;
+       size_t len = curve->len;
+       const bigint_t ( size ) __attribute__ (( may_alias )) *prime =
+               ( ( const void * ) curve->prime[0] );
+       const bigint_t ( size ) __attribute__ (( may_alias )) *fermat =
+               ( ( const void * ) curve->fermat );
+       const bigint_t ( size ) __attribute__ (( may_alias )) *one =
+               ( ( const void * ) curve->one );
+       weierstrass_t ( size ) __attribute__ (( may_alias ))
+               *point = ( ( void * ) point0 );
+       union {
+               bigint_t ( size * 2 ) product;
+               weierstrass_t ( size ) point;
+       } __attribute__ (( may_alias )) *temp = ( ( void * ) temp0 );
+       size_t offset;
+       unsigned int i;
+
+       /* Invert result Z co-ordinate (via Fermat's little theorem) */
+       bigint_copy ( one, &temp->point.z );
+       bigint_ladder ( &temp->point.z, &point->z, fermat,
+                       bigint_mod_exp_ladder, prime, &temp->product );
+
+       /* Convert result back to affine co-ordinates */
+       DBGC ( curve, "WEIERSTRASS %s result (", curve->name );
+       for ( i = 0, offset = 0 ; i < WEIERSTRASS_AXES ; i++, offset += len ) {
+               bigint_multiply ( &point->axis[i], &temp->point.z,
+                                 &temp->product );
+               bigint_montgomery_relaxed ( prime, &temp->product,
+                                           &point->axis[i] );
+               bigint_grow ( &point->axis[i], &temp->product );
+               bigint_montgomery ( prime, &temp->product, &point->axis[i] );
+               DBGC ( curve, "%s%s", ( i ? "," : "" ),
+                      bigint_ntoa ( &point->axis[i] ) );
+               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;
+}
+
+/**
+ * Finalise curve point
+ *
+ * @v curve            Weierstrass curve
+ * @v point            Point (x,y,z)
+ * @v temp             Temporary point buffer
+ * @v out              Output buffer
+ * @ret rc             Return status code
+ */
+#define weierstrass_done( curve, point, temp, out ) ( {                        \
+       weierstrass_done_raw ( (curve), (point)->all.element,           \
+                              (temp)->all.element, (out) );            \
+       } )
+
+/**
+ * Multiply curve point by scalar
+ *
+ * @v curve            Weierstrass curve
+ * @v base             Base point
+ * @v scalar           Scalar multiple
+ * @v result           Result point to fill in
+ * @ret rc             Return status code
+ */
+int weierstrass_multiply ( struct weierstrass_curve *curve, const void *base,
+                          const void *scalar, void *result ) {
+       unsigned int size = curve->size;
+       size_t len = curve->len;
+       const bigint_t ( size ) __attribute__ (( may_alias )) *one =
+               ( ( const void * ) curve->one );
+       struct {
+               weierstrass_t ( size ) result;
+               weierstrass_t ( size ) multiple;
+               bigint_t ( bigint_required_size ( len ) ) scalar;
+       } temp;
+       int rc;
+
+       /* Convert input to projective coordinates in Montgomery form */
+       if ( ( rc = weierstrass_init ( curve, &temp.multiple, &temp.result,
+                                      base ) ) != 0 ) {
+               return rc;
+       }
+
        /* Construct identity element (the point at infinity) */
        memset ( &temp.result, 0, sizeof ( temp.result ) );
        bigint_copy ( one, &temp.result.y );
@@ -837,30 +945,11 @@ int weierstrass_multiply ( struct weierstrass_curve *curve, const void *base,
        bigint_ladder ( &temp.result.all, &temp.multiple.all, &temp.scalar,
                        weierstrass_add_ladder, curve, NULL );
 
-       /* Invert result Z co-ordinate (via Fermat's little theorem) */
-       bigint_copy ( one, &temp.multiple.z );
-       bigint_ladder ( &temp.multiple.z, &temp.result.z, fermat,
-                       bigint_mod_exp_ladder, prime, &temp.product_out );
-
        /* Convert result back to affine co-ordinates */
-       DBGC ( curve, "WEIERSTRASS %s result (", curve->name );
-       for ( i = 0, offset = 0 ; i < WEIERSTRASS_AXES ; i++, offset += len ) {
-               bigint_multiply ( &temp.result.axis[i], &temp.multiple.z,
-                                 &temp.product_out );
-               bigint_montgomery_relaxed ( prime, &temp.product_out,
-                                           &temp.result.axis[i] );
-               bigint_grow ( &temp.result.axis[i], &temp.product_out );
-               bigint_montgomery ( prime, &temp.product_out,
-                                   &temp.result.axis[i] );
-               DBGC ( curve, "%s%s", ( i ? "," : "" ),
-                      bigint_ntoa ( &temp.result.axis[i] ) );
-               bigint_done ( &temp.result.axis[i], ( result + offset ), len );
+       if ( ( rc = weierstrass_done ( curve, &temp.result, &temp.multiple,
+                                      result ) ) != 0 ) {
+               return rc;
        }
-       DBGC ( curve, ")\n" );
-
-       /* Verify result is not the point at infinity */
-       if ( bigint_is_zero ( &temp.multiple.z ) )
-               return -EINVAL;
 
        return 0;
 }