diff options
Diffstat (limited to 'src/include/ipxe/weierstrass.h')
-rw-r--r-- | src/include/ipxe/weierstrass.h | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/src/include/ipxe/weierstrass.h b/src/include/ipxe/weierstrass.h new file mode 100644 index 000000000..fb09fa6fa --- /dev/null +++ b/src/include/ipxe/weierstrass.h @@ -0,0 +1,166 @@ +#ifndef _IPXE_WEIERSTRASS_H +#define _IPXE_WEIERSTRASS_H + +/** @file + * + * Weierstrass elliptic curves + * + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +#include <ipxe/bigint.h> +#include <ipxe/crypto.h> + +/** Number of axes in Weierstrass curve point representation */ +#define WEIERSTRASS_AXES 2 + +/** + * Maximum multiple of field prime encountered during calculations + * + * Calculations are performed using values modulo a small multiple of + * the field prime, rather than modulo the field prime itself. This + * allows explicit reductions after additions, subtractions, and + * relaxed Montgomery multiplications to be omitted entirely, provided + * that we keep careful track of the field prime multiple for each + * intermediate value. + * + * Relaxed Montgomery multiplication will produce a result in the + * range t < (1+m/k)N, where m is this maximum multiple of the field + * prime, and k is the constant in R > kN representing the leading + * zero padding in the big integer representation of the field prime. + * We choose to set k=m so that multiplications will always produce a + * result in the range t < 2N. + * + * This is expressed as the base-two logarithm of the multiple + * (rounded up), to simplify compile-time calculations. + */ +#define WEIERSTRASS_MAX_MULTIPLE_LOG2 5 /* maximum reached is mod 20N */ + +/** + * Determine number of elements in scalar values for a Weierstrass curve + * + * @v len Length of field prime, in bytes + * @ret size Number of elements + */ +#define weierstrass_size( len ) \ + bigint_required_size ( (len) + \ + ( ( WEIERSTRASS_MAX_MULTIPLE_LOG2 + 7 ) \ + / 8 ) ) + +/** + * Define a Weierstrass projective co-ordinate type + * + * @v size Number of elements in scalar values + * @ret weierstrass_t Projective co-ordinate type + */ +#define weierstrass_t( size ) \ + union { \ + bigint_t ( size ) axis[3]; \ + struct { \ + bigint_t ( size ) x; \ + bigint_t ( size ) y; \ + bigint_t ( size ) z; \ + }; \ + bigint_t ( size * 3 ) all; \ + } + +/** Indexes for stored multiples of the field prime */ +enum weierstrass_multiple { + WEIERSTRASS_N = 0, + WEIERSTRASS_2N, + WEIERSTRASS_4N, + WEIERSTRASS_NUM_MULTIPLES +}; + +/** Number of cached in Montgomery form for each Weierstrass curve */ +#define WEIERSTRASS_NUM_MONT 3 + +/** Number of cached big integers for each Weierstrass curve */ +#define WEIERSTRASS_NUM_CACHED \ + ( WEIERSTRASS_NUM_MULTIPLES + \ + 1 /* fermat */ + 1 /* mont */ + \ + WEIERSTRASS_NUM_MONT ) + +/** + * A Weierstrass elliptic curve + * + * This is an elliptic curve y^2 = x^3 + ax + b + */ +struct weierstrass_curve { + /** Number of elements in scalar values */ + const unsigned int size; + /** Curve name */ + const char *name; + /** Length of raw scalar values */ + size_t len; + /** Field prime */ + const uint8_t *prime_raw; + /** Constant "a" */ + const uint8_t *a_raw; + /** Constant "b" */ + const uint8_t *b_raw; + /** Base point */ + const uint8_t *base; + + /** Cached field prime "N" (and multiples thereof) */ + bigint_element_t *prime[WEIERSTRASS_NUM_CACHED]; + /** Cached constant "N-2" (for Fermat's little theorem) */ + bigint_element_t *fermat; + /** Cached Montgomery constant (R^2 mod N) */ + bigint_element_t *square; + /** Cached constants in Montgomery form */ + union { + struct { + /** Cached constant "1", in Montgomery form */ + bigint_element_t *one; + /** Cached constant "a", in Montgomery form */ + bigint_element_t *a; + /** Cached constant "3b", in Montgomery form */ + bigint_element_t *b3; + }; + bigint_element_t *mont[WEIERSTRASS_NUM_MONT]; + }; +}; + +extern int weierstrass_multiply ( struct weierstrass_curve *curve, + const void *base, const void *scalar, + void *result ); + +/** Define a Weierstrass curve */ +#define WEIERSTRASS_CURVE( _name, _curve, _len, _prime, _a, _b, _base ) \ + static bigint_t ( weierstrass_size(_len) ) \ + _name ## _cache[WEIERSTRASS_NUM_CACHED]; \ + static struct weierstrass_curve _name ## _weierstrass = { \ + .size = weierstrass_size(_len), \ + .name = #_name, \ + .len = (_len), \ + .prime_raw = (_prime), \ + .a_raw = (_a), \ + .b_raw = (_b), \ + .base = (_base), \ + .prime = { \ + (_name ## _cache)[0].element, \ + (_name ## _cache)[1].element, \ + (_name ## _cache)[2].element, \ + }, \ + .fermat = (_name ## _cache)[3].element, \ + .square = (_name ## _cache)[4].element, \ + .one = (_name ## _cache)[5].element, \ + .a = (_name ## _cache)[6].element, \ + .b3 = (_name ## _cache)[7].element, \ + }; \ + static int _name ## _multiply ( const void *base, \ + const void *scalar, \ + void *result ) { \ + return weierstrass_multiply ( &_name ## _weierstrass, \ + base, scalar, result ); \ + } \ + struct elliptic_curve _curve = { \ + .name = #_name, \ + .pointsize = ( WEIERSTRASS_AXES * (_len) ), \ + .keysize = (_len), \ + .multiply = _name ## _multiply, \ + } + +#endif /* _IPXE_WEIERSTRASS_H */ |