-
Notifications
You must be signed in to change notification settings - Fork 188
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
1,932 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,45 @@ | ||
#include "fd_secp256r1.h" | ||
|
||
#include <stdint.h> | ||
#include <s2n-bignum.h> | ||
#include "fd_secp256r1_private.h" | ||
|
||
int | ||
fd_secp256r1_verify( uchar const msg[], /* msg_sz */ | ||
ulong msg_sz, | ||
uchar const sig[ 64 ], | ||
uchar const public_key[ 33 ], | ||
fd_sha256_t * sha ) { | ||
(void)msg; | ||
(void)msg_sz; | ||
(void)sig; | ||
(void)public_key; | ||
(void)sha; | ||
fd_secp256r1_scalar_t r[1], s[1], u1[1], u2[1]; | ||
fd_secp256r1_point_t pub[1], Rcmp[1]; | ||
|
||
/* Deserialize signature. | ||
Note: we enforce 0 < r < n, 0 < s <= (n-1)/2. | ||
The condition on s is required to avoid signature malleability. */ | ||
if( FD_UNLIKELY( !fd_secp256r1_scalar_frombytes( r, sig ) ) ) { | ||
return FD_SECP256R1_FAILURE; | ||
} | ||
if( FD_UNLIKELY( !fd_secp256r1_scalar_frombytes_positive( s, sig+32 ) ) ) { | ||
return FD_SECP256R1_FAILURE; | ||
} | ||
if( FD_UNLIKELY( fd_secp256r1_scalar_is_zero( r ) || fd_secp256r1_scalar_is_zero( s ) ) ) { | ||
return FD_SECP256R1_FAILURE; | ||
} | ||
|
||
/* Deserialize public key. */ | ||
if( FD_UNLIKELY( !fd_secp256r1_point_frombytes( pub, public_key ) ) ) { | ||
return FD_SECP256R1_FAILURE; | ||
} | ||
|
||
/* Hash message. */ | ||
uchar hash[ FD_SHA256_HASH_SZ ]; | ||
fd_sha256_fini( fd_sha256_append( fd_sha256_init( sha ), msg, msg_sz ), hash ); | ||
fd_secp256r1_scalar_from_digest( u1, hash ); | ||
|
||
//TODO | ||
/* ECDSA sig verify. */ | ||
fd_secp256r1_scalar_inv( s, s ); | ||
fd_secp256r1_scalar_mul( u1, u1, s ); | ||
fd_secp256r1_scalar_mul( u2, r, s ); | ||
fd_secp256r1_double_scalar_mul_base( Rcmp, u1, pub, u2 ); | ||
if( FD_LIKELY( fd_secp256r1_point_eq_x( Rcmp, r ) ) ) { | ||
return FD_SECP256R1_SUCCESS; | ||
} | ||
|
||
return FD_SECP256R1_FAILURE; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
#ifndef HEADER_fd_src_ballet_secp256r1_fd_secp256r1_private_h | ||
#define HEADER_fd_src_ballet_secp256r1_fd_secp256r1_private_h | ||
|
||
/* fd_secp256r1 provides APIs for secp256r1 signature verification. */ | ||
|
||
#include "fd_secp256r1.h" | ||
#include "../bigint/fd_uint256.h" | ||
|
||
FD_PROTOTYPES_BEGIN | ||
|
||
/* Field element: uint256 */ | ||
typedef fd_uint256_t fd_secp256r1_fp_t; | ||
|
||
/* Scalar field element: uint256 */ | ||
typedef fd_uint256_t fd_secp256r1_scalar_t; | ||
|
||
/* Point, in Jacobian coordinates (X : Y : Z). | ||
These correspond to affine x=X/Z^2, y=Y/Z^3. | ||
Field elements are in Montgomery form. */ | ||
struct fd_secp256r1_point { | ||
fd_secp256r1_fp_t x[1]; | ||
fd_secp256r1_fp_t y[1]; | ||
fd_secp256r1_fp_t z[1]; | ||
}; | ||
typedef struct fd_secp256r1_point fd_secp256r1_point_t; | ||
|
||
/* const 0. */ | ||
static const fd_uint256_t fd_secp256r1_const_zero[1] = {{{ | ||
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, | ||
}}}; | ||
|
||
/* const p, used to validate a field element. | ||
NOT Montgomery. | ||
0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff */ | ||
static const fd_secp256r1_fp_t fd_secp256r1_const_p[1] = {{{ | ||
0xffffffffffffffff, 0x00000000ffffffff, 0x0000000000000000, 0xffffffff00000001, | ||
}}}; | ||
|
||
/* const 1. Montgomery. | ||
0x00000000fffffffeffffffffffffffffffffffff000000000000000000000001 */ | ||
static const fd_secp256r1_fp_t fd_secp256r1_const_one_mont[1] = {{{ | ||
0x0000000000000001, 0xffffffff00000000, 0xffffffffffffffff, 0x00000000fffffffe, | ||
}}}; | ||
|
||
/* const a=-3, in curve equation y^2 = x^3 + ax + b. Montgomery. | ||
0xfffffffc00000004000000000000000000000003fffffffffffffffffffffffc */ | ||
static const fd_secp256r1_fp_t fd_secp256r1_const_a_mont[1] = {{{ | ||
0xfffffffffffffffc, 0x00000003ffffffff, 0x0000000000000000, 0xfffffffc00000004, | ||
}}}; | ||
|
||
/* const b, in curve equation y^2 = x^3 + ax + b. Montgomery. | ||
0xdc30061d04874834e5a220abf7212ed6acf005cd78843090d89cdf6229c4bddf */ | ||
static const fd_secp256r1_fp_t fd_secp256r1_const_b_mont[1] = {{{ | ||
0xd89cdf6229c4bddf, 0xacf005cd78843090, 0xe5a220abf7212ed6, 0xdc30061d04874834 | ||
}}}; | ||
|
||
/* const n, used to validate a scalar field element. | ||
NOT Montgomery. | ||
0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 */ | ||
static const fd_secp256r1_scalar_t fd_secp256r1_const_n[1] = {{{ | ||
0xf3b9cac2fc632551, 0xbce6faada7179e84, 0xffffffffffffffff, 0xffffffff00000000, | ||
}}}; | ||
|
||
/* const (n-1)/2, used to validate a signature s component. | ||
NOT Montgomery. | ||
0x7fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a8 */ | ||
static const fd_secp256r1_scalar_t fd_secp256r1_const_n_m1_half[1] = {{{ | ||
0x79dce5617e3192a8, 0xde737d56d38bcf42, 0x7fffffffffffffff, 0x7fffffff80000000, | ||
}}}; | ||
|
||
FD_PROTOTYPES_END | ||
|
||
#include "fd_secp256r1_s2n.c" | ||
|
||
#endif /* HEADER_fd_src_ballet_secp256r1_fd_secp256r1_private_h */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
#include "fd_secp256r1_private.h" | ||
#include <stdint.h> | ||
#include <s2n-bignum.h> | ||
|
||
#include "fd_secp256r1_table.c" | ||
|
||
/* Scalars */ | ||
|
||
static inline int | ||
fd_secp256r1_scalar_is_zero( fd_secp256r1_scalar_t const * a ) { | ||
return fd_uint256_eq( a, fd_secp256r1_const_zero ); | ||
} | ||
|
||
static inline fd_secp256r1_scalar_t * | ||
fd_secp256r1_scalar_frombytes( fd_secp256r1_scalar_t * r, | ||
uchar const in[ 32 ] ) { | ||
memcpy( r, in, 32 ); | ||
fd_uint256_bswap( r, r ); | ||
if( FD_LIKELY( fd_uint256_cmp( r, fd_secp256r1_const_n )<0 ) ) { | ||
return r; | ||
}; | ||
return NULL; | ||
} | ||
|
||
static inline fd_secp256r1_scalar_t * | ||
fd_secp256r1_scalar_frombytes_positive( fd_secp256r1_scalar_t * r, | ||
uchar const in[ 32 ] ) { | ||
memcpy( r, in, 32 ); | ||
fd_uint256_bswap( r, r ); | ||
if( FD_LIKELY( fd_uint256_cmp( r, fd_secp256r1_const_n_m1_half )<=0 ) ) { | ||
return r; | ||
}; | ||
return NULL; | ||
} | ||
|
||
static inline void | ||
fd_secp256r1_scalar_from_digest( fd_secp256r1_scalar_t * r, | ||
uchar const in[ 32 ] ) { | ||
memcpy( r, in, 32 ); | ||
fd_uint256_bswap( r, r ); | ||
bignum_mod_n256_4( r->limbs, r->limbs ); | ||
} | ||
|
||
static inline fd_secp256r1_scalar_t * | ||
fd_secp256r1_scalar_mul( fd_secp256r1_scalar_t * r, | ||
fd_secp256r1_scalar_t const * a, | ||
fd_secp256r1_scalar_t const * b ) { | ||
ulong t[ 8 ]; | ||
bignum_mul_4_8( t, (ulong *)a->limbs, (ulong *)b->limbs ); | ||
bignum_mod_n256( r->limbs, 8, t ); | ||
return r; | ||
} | ||
|
||
static inline fd_secp256r1_scalar_t * | ||
fd_secp256r1_scalar_inv( fd_secp256r1_scalar_t * r, | ||
fd_secp256r1_scalar_t const * a ) { | ||
ulong t[ 12 ]; | ||
bignum_modinv( 4, r->limbs, (ulong *)a->limbs, (ulong *)fd_secp256r1_const_n[0].limbs, t ); | ||
return r; | ||
} | ||
|
||
/* Field */ | ||
|
||
static inline fd_secp256r1_fp_t * | ||
fd_secp256r1_fp_set( fd_secp256r1_fp_t * r, | ||
fd_secp256r1_fp_t const * a ) { | ||
r->limbs[0] = a->limbs[0]; | ||
r->limbs[1] = a->limbs[1]; | ||
r->limbs[2] = a->limbs[2]; | ||
r->limbs[3] = a->limbs[3]; | ||
return r; | ||
} | ||
|
||
static inline fd_secp256r1_fp_t * | ||
fd_secp256r1_fp_frombytes( fd_secp256r1_fp_t * r, | ||
uchar const in[ 32 ] ) { | ||
memcpy( r, in, 32 ); | ||
fd_uint256_bswap( r, r ); | ||
if( FD_LIKELY( fd_uint256_cmp( r, fd_secp256r1_const_p )<0 ) ) { | ||
return r; | ||
}; | ||
return NULL; | ||
} | ||
|
||
static inline fd_secp256r1_fp_t * | ||
fd_secp256r1_fp_sqrt( fd_secp256r1_fp_t * r, | ||
fd_secp256r1_fp_t const * a ) { | ||
/* https://github.com/golang/go/blob/master/src/crypto/internal/fips140/nistec/p256.go#L656 */ | ||
fd_secp256r1_fp_t _t0[1], _t1[1]; | ||
ulong * t0 = _t0->limbs; | ||
ulong * t1 = _t1->limbs; | ||
ulong * x = (ulong *)a->limbs; | ||
|
||
bignum_montsqr_p256( t0, x ); | ||
bignum_montmul_p256( t0, t0, x ); | ||
bignum_montsqr_p256( t1, t0 ); for( int i=1; i<2; i++ ) bignum_montsqr_p256( t1, t1 ); | ||
bignum_montmul_p256( t0, t0, t1); | ||
bignum_montsqr_p256( t1, t0 ); for( int i=1; i<4; i++ ) bignum_montsqr_p256( t1, t1 ); | ||
bignum_montmul_p256( t0, t0, t1); | ||
bignum_montsqr_p256( t1, t0 ); for( int i=1; i<8; i++ ) bignum_montsqr_p256( t1, t1 ); | ||
bignum_montmul_p256( t0, t0, t1); | ||
bignum_montsqr_p256( t1, t0 ); for( int i=1; i<16; i++ ) bignum_montsqr_p256( t1, t1 ); | ||
bignum_montmul_p256( t0, t0, t1); | ||
for( int i=0; i<32; i++ ) bignum_montsqr_p256( t0, t0 ); | ||
bignum_montmul_p256( t0, t0, x ); | ||
for( int i=0; i<96; i++ ) bignum_montsqr_p256( t0, t0 ); | ||
bignum_montmul_p256( t0, t0, x ); | ||
for( int i=0; i<94; i++ ) bignum_montsqr_p256( t0, t0 ); | ||
|
||
bignum_montsqr_p256( t1, t0 ); | ||
if( FD_UNLIKELY( !fd_uint256_eq( _t1, a ) ) ) { | ||
return NULL; | ||
} | ||
|
||
return fd_secp256r1_fp_set( r, _t0 ); | ||
} | ||
|
||
/* Points */ | ||
|
||
static inline fd_secp256r1_point_t * | ||
fd_secp256r1_point_frombytes( fd_secp256r1_point_t * r, | ||
uchar const in[ 33 ] ) { | ||
fd_secp256r1_fp_t y2[1], neg_y[1]; | ||
|
||
uchar sgn = in[0]; | ||
if( FD_UNLIKELY( sgn!=2U && sgn!=3U ) ) { | ||
return FD_SECP256R1_FAILURE; | ||
} | ||
|
||
if( FD_UNLIKELY( !fd_secp256r1_fp_frombytes( r->x, in+1 ) ) ) { | ||
return FD_SECP256R1_FAILURE; | ||
} | ||
|
||
bignum_tomont_p256( r->x->limbs, r->x->limbs ); | ||
|
||
/* y^2 = x^3 + ax + b */ | ||
bignum_montsqr_p256( y2->limbs, r->x->limbs ); | ||
bignum_add_p256 ( y2->limbs, y2->limbs, (ulong *)fd_secp256r1_const_a_mont[0].limbs ); | ||
bignum_montmul_p256( y2->limbs, y2->limbs, r->x->limbs ); | ||
bignum_add_p256 ( y2->limbs, y2->limbs, (ulong *)fd_secp256r1_const_b_mont[0].limbs ); | ||
|
||
/* y = sqrt(y^2) */ | ||
if( FD_UNLIKELY( !fd_secp256r1_fp_sqrt( r->y, y2 ) ) ) { | ||
return FD_SECP256R1_FAILURE; | ||
} | ||
|
||
/* choose y or -y */ | ||
bignum_neg_p256( neg_y->limbs, r->y->limbs ); | ||
ulong cond = fd_uint256_cmp( neg_y, r->y ) == (sgn == 2 ? -1 : 1); | ||
bignum_mux_4( cond, r->y->limbs, r->y->limbs, neg_y->limbs ); | ||
|
||
fd_secp256r1_fp_set( r->z, fd_secp256r1_const_one_mont ); | ||
|
||
return r; | ||
} | ||
|
||
static inline int | ||
fd_secp256r1_point_eq_x( fd_secp256r1_point_t const * p, | ||
fd_secp256r1_scalar_t const * r ) { | ||
fd_secp256r1_fp_t affine_x[1]; | ||
fd_secp256r1_scalar_t * affine_x_mod_n = affine_x; | ||
|
||
if( FD_UNLIKELY( fd_uint256_eq( p->z, fd_secp256r1_const_zero ) ) ) { | ||
return FD_SECP256R1_FAILURE; | ||
} | ||
|
||
/* x = demont(X / Z^2) mod n */ | ||
bignum_montinv_p256( affine_x->limbs, (ulong *)p->z->limbs ); | ||
bignum_montsqr_p256( affine_x->limbs, affine_x->limbs ); | ||
bignum_montmul_p256( affine_x->limbs, affine_x->limbs, (ulong *)p->x->limbs ); | ||
bignum_demont_p256( affine_x_mod_n->limbs, affine_x->limbs ); | ||
bignum_mod_n256_4 ( affine_x_mod_n->limbs, affine_x_mod_n->limbs ); | ||
|
||
if( FD_LIKELY( fd_uint256_eq( r, affine_x_mod_n ) ) ) { | ||
return FD_SECP256R1_SUCCESS; | ||
} | ||
return FD_SECP256R1_FAILURE; | ||
} | ||
|
||
static inline void | ||
fd_secp256r1_double_scalar_mul_base( fd_secp256r1_point_t * r, | ||
fd_secp256r1_scalar_t const * u1, | ||
fd_secp256r1_point_t const * a, | ||
fd_secp256r1_scalar_t const * u2 ) { | ||
/* u1*G + u2*A */ | ||
ulong rtmp[ 8 ]; | ||
p256_scalarmulbase( rtmp, (ulong *)u1->limbs, 6, (ulong *)fd_secp256r1_base_point_table ); | ||
bignum_tomont_p256( rtmp, rtmp ); | ||
bignum_tomont_p256( rtmp+4, rtmp+4 ); | ||
|
||
p256_montjscalarmul( (ulong *)r, (ulong *)u2->limbs, (ulong *)a ); | ||
|
||
p256_montjmixadd( (ulong *)r, (ulong *)r, rtmp ); | ||
} |
Oops, something went wrong.