From: Michael Brown Date: Fri, 5 Dec 2025 16:08:49 +0000 (+0000) Subject: [crypto] Split out Weierstrass point initialisation and finalisation X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1e353ff361f9a1646d1f730423adf77d6c63fa9e;p=thirdparty%2Fipxe.git [crypto] Split out Weierstrass point initialisation and finalisation 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 --- diff --git a/src/crypto/weierstrass.c b/src/crypto/weierstrass.c index ecc468af2..ecc9699a1 100644 --- a/src/crypto/weierstrass.c +++ b/src/crypto/weierstrass.c @@ -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; }