#ifndef _IPXE_BIGINT_H #define _IPXE_BIGINT_H /** @file * * Big integer support */ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** * Define a big-integer type * * @v size Number of elements * @ret bigint_t Big integer type */ #define bigint_t( size ) \ struct { \ bigint_element_t element[ (size) ]; \ } /** * Determine number of elements required for a big-integer type * * @v len Maximum length of big integer, in bytes * @ret size Number of elements */ #define bigint_required_size( len ) \ ( ( (len) + sizeof ( bigint_element_t ) - 1 ) / \ sizeof ( bigint_element_t ) ) /** * Determine number of elements in big-integer type * * @v bigint Big integer * @ret size Number of elements */ #define bigint_size( bigint ) \ ( sizeof ( *(bigint) ) / sizeof ( (bigint)->element[0] ) ) /** * Initialise big integer * * @v value Big integer to initialise * @v data Raw data * @v len Length of raw data */ #define bigint_init( value, data, len ) do { \ unsigned int size = bigint_size (value); \ assert ( (len) <= ( size * sizeof ( (value)->element[0] ) ) ); \ bigint_init_raw ( (value)->element, size, (data), (len) ); \ } while ( 0 ) /** * Finalise big integer * * @v value Big integer to finalise * @v out Output buffer * @v len Length of output buffer */ #define bigint_done( value, out, len ) do { \ unsigned int size = bigint_size (value); \ bigint_done_raw ( (value)->element, size, (out), (len) ); \ } while ( 0 ) /** * Add big integers * * @v addend Big integer to add * @v value Big integer to be added to */ #define bigint_add( addend, value ) do { \ unsigned int size = bigint_size (addend); \ bigint_add_raw ( (addend)->element, (value)->element, size ); \ } while ( 0 ) /** * Subtract big integers * * @v subtrahend Big integer to subtract * @v value Big integer to be subtracted from */ #define bigint_subtract( subtrahend, value ) do { \ unsigned int size = bigint_size (subtrahend); \ bigint_subtract_raw ( (subtrahend)->element, (value)->element, \ size ); \ } while ( 0 ) /** * Rotate big integer left * * @v value Big integer */ #define bigint_rol( value ) do { \ unsigned int size = bigint_size (value); \ bigint_rol_raw ( (value)->element, size ); \ } while ( 0 ) /** * Rotate big integer right * * @v value Big integer */ #define bigint_ror( value ) do { \ unsigned int size = bigint_size (value); \ bigint_ror_raw ( (value)->element, size ); \ } while ( 0 ) /** * Test if big integer is equal to zero * * @v value Big integer * @v size Number of elements * @ret is_zero Big integer is equal to zero */ #define bigint_is_zero( value ) ( { \ unsigned int size = bigint_size (value); \ bigint_is_zero_raw ( (value)->element, size ); } ) /** * Compare big integers * * @v value Big integer * @v reference Reference big integer * @ret geq Big integer is greater than or equal to the reference */ #define bigint_is_geq( value, reference ) ( { \ unsigned int size = bigint_size (value); \ bigint_is_geq_raw ( (value)->element, (reference)->element, \ size ); } ) /** * Test if bit is set in big integer * * @v value Big integer * @v bit Bit to test * @ret is_set Bit is set */ #define bigint_bit_is_set( value, bit ) ( { \ unsigned int size = bigint_size (value); \ bigint_bit_is_set_raw ( (value)->element, size, bit ); } ) /** * Find highest bit set in big integer * * @v value Big integer * @ret max_bit Highest bit set + 1 (or 0 if no bits set) */ #define bigint_max_set_bit( value ) ( { \ unsigned int size = bigint_size (value); \ bigint_max_set_bit_raw ( (value)->element, size ); } ) /** * Grow big integer * * @v source Source big integer * @v dest Destination big integer */ #define bigint_grow( source, dest ) do { \ unsigned int source_size = bigint_size (source); \ unsigned int dest_size = bigint_size (dest); \ bigint_grow_raw ( (source)->element, source_size, \ (dest)->element, dest_size ); \ } while ( 0 ) /** * Shrink big integer * * @v source Source big integer * @v dest Destination big integer */ #define bigint_shrink( source, dest ) do { \ unsigned int source_size = bigint_size (source); \ unsigned int dest_size = bigint_size (dest); \ bigint_shrink_raw ( (source)->element, source_size, \ (dest)->element, dest_size ); \ } while ( 0 ) /** * Multiply big integers * * @v multiplicand Big integer to be multiplied * @v multiplier Big integer to be multiplied * @v result Big integer to hold result */ #define bigint_multiply( multiplicand, multiplier, result ) do { \ unsigned int size = bigint_size (multiplicand); \ bigint_multiply_raw ( (multiplicand)->element, \ (multiplier)->element, (result)->element, \ size ); \ } while ( 0 ) /** * Perform modular multiplication of big integers * * @v multiplicand Big integer to be multiplied * @v multiplier Big integer to be multiplied * @v modulus Big integer modulus * @v result Big integer to hold result * @v tmp Temporary working space */ #define bigint_mod_multiply( multiplicand, multiplier, modulus, \ result, tmp ) do { \ unsigned int size = bigint_size (multiplicand); \ bigint_mod_multiply_raw ( (multiplicand)->element, \ (multiplier)->element, \ (modulus)->element, \ (result)->element, size, tmp ); \ } while ( 0 ) /** * Calculate temporary working space required for moduluar multiplication * * @v modulus Big integer modulus * @ret len Length of temporary working space */ #define bigint_mod_multiply_tmp_len( modulus ) ( { \ unsigned int size = bigint_size (modulus); \ sizeof ( struct { \ bigint_t ( size * 2 ) temp_result; \ bigint_t ( size * 2 ) temp_modulus; \ } ); } ) /** * Perform modular exponentiation of big integers * * @v base Big integer base * @v modulus Big integer modulus * @v exponent Big integer exponent * @v result Big integer to hold result * @v tmp Temporary working space */ #define bigint_mod_exp( base, modulus, exponent, result, tmp ) do { \ unsigned int size = bigint_size (base); \ unsigned int exponent_size = bigint_size (exponent); \ bigint_mod_exp_raw ( (base)->element, (modulus)->element, \ (exponent)->element, (result)->element, \ size, exponent_size, tmp ); \ } while ( 0 ) /** * Calculate temporary working space required for moduluar exponentiation * * @v modulus Big integer modulus * @v exponent Big integer exponent * @ret len Length of temporary working space */ #define bigint_mod_exp_tmp_len( modulus, exponent ) ( { \ unsigned int size = bigint_size (modulus); \ unsigned int exponent_size = bigint_size (exponent); \ size_t mod_multiply_len = \ bigint_mod_multiply_tmp_len (modulus); \ sizeof ( struct { \ bigint_t ( size ) temp_base; \ bigint_t ( exponent_size ) temp_exponent; \ uint8_t mod_multiply[mod_multiply_len]; \ } ); } ) #include void bigint_init_raw ( bigint_element_t *value0, unsigned int size, const void *data, size_t len ); void bigint_done_raw ( const bigint_element_t *value0, unsigned int size, void *out, size_t len ); void bigint_add_raw ( const bigint_element_t *addend0, bigint_element_t *value0, unsigned int size ); void bigint_subtract_raw ( const bigint_element_t *subtrahend0, bigint_element_t *value0, unsigned int size ); void bigint_rol_raw ( bigint_element_t *value0, unsigned int size ); void bigint_ror_raw ( bigint_element_t *value0, unsigned int size ); int bigint_is_zero_raw ( const bigint_element_t *value0, unsigned int size ); int bigint_is_geq_raw ( const bigint_element_t *value0, const bigint_element_t *reference0, unsigned int size ); int bigint_bit_is_set_raw ( const bigint_element_t *value0, unsigned int size, unsigned int bit ); int bigint_max_set_bit_raw ( const bigint_element_t *value0, unsigned int size ); void bigint_grow_raw ( const bigint_element_t *source0, unsigned int source_size, bigint_element_t *dest0, unsigned int dest_size ); void bigint_shrink_raw ( const bigint_element_t *source0, unsigned int source_size, bigint_element_t *dest0, unsigned int dest_size ); void bigint_multiply_raw ( const bigint_element_t *multiplicand0, const bigint_element_t *multiplier0, bigint_element_t *result0, unsigned int size ); void bigint_mod_multiply_raw ( const bigint_element_t *multiplicand0, const bigint_element_t *multiplier0, const bigint_element_t *modulus0, bigint_element_t *result0, unsigned int size, void *tmp ); void bigint_mod_exp_raw ( const bigint_element_t *base0, const bigint_element_t *modulus0, const bigint_element_t *exponent0, bigint_element_t *result0, unsigned int size, unsigned int exponent_size, void *tmp ); #endif /* _IPXE_BIGINT_H */