mirror of
https://github.com/ipxe/ipxe
synced 2026-06-29 00:07:28 +03:00
[crypto] Use generic implementations of slow-path big integer functions
In the original big integer implementation, big integers were entirely opaque to the caller and only the architecture-dependent code knew any details of the internal structure. This has long since ceased to be the case: for the sake of arithmetic efficiency, many portions of the codebase now presume that big integers are represented as an array of elements, with each element being a native-endian unsigned value (with the precise type being chosen by the architecture-specific header file) and with the least significant element being first in the array. The functions bigint_init(), bigint_done(), bigint_is_zero(), bigint_is_geq(), and bigint_max_bit_set() are never used on fast code paths, and most architectures use a generic C implementation of these functions. Provide generic implementations of these slow-path functions to be used on all architectures. Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
@@ -10,33 +10,10 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
/** Element of a big integer */
|
||||
typedef uint32_t bigint_element_t;
|
||||
|
||||
/**
|
||||
* Initialise big integer
|
||||
*
|
||||
* @v value0 Element 0 of big integer to initialise
|
||||
* @v size Number of elements
|
||||
* @v data Raw data
|
||||
* @v len Length of raw data
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
bigint_init_raw ( uint32_t *value0, unsigned int size,
|
||||
const void *data, size_t len ) {
|
||||
size_t pad_len = ( sizeof ( bigint_t ( size ) ) - len );
|
||||
uint8_t *value_byte = ( ( void * ) value0 );
|
||||
const uint8_t *data_byte = ( data + len );
|
||||
|
||||
/* Copy raw data in reverse order, padding with zeros */
|
||||
while ( len-- )
|
||||
*(value_byte++) = *(--data_byte);
|
||||
while ( pad_len-- )
|
||||
*(value_byte++) = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add big integers
|
||||
*
|
||||
@@ -182,76 +159,6 @@ bigint_shr_raw ( uint32_t *value0, unsigned int size ) {
|
||||
return carry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if big integer is equal to zero
|
||||
*
|
||||
* @v value0 Element 0 of big integer
|
||||
* @v size Number of elements
|
||||
* @ret is_zero Big integer is equal to zero
|
||||
*/
|
||||
static inline __attribute__ (( always_inline, pure )) int
|
||||
bigint_is_zero_raw ( const uint32_t *value0, unsigned int size ) {
|
||||
const uint32_t *value = value0;
|
||||
uint32_t value_i;
|
||||
|
||||
do {
|
||||
value_i = *(value++);
|
||||
if ( value_i )
|
||||
break;
|
||||
} while ( --size );
|
||||
|
||||
return ( value_i == 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare big integers
|
||||
*
|
||||
* @v value0 Element 0 of big integer
|
||||
* @v reference0 Element 0 of reference big integer
|
||||
* @v size Number of elements
|
||||
* @ret geq Big integer is greater than or equal to the reference
|
||||
*/
|
||||
static inline __attribute__ (( always_inline, pure )) int
|
||||
bigint_is_geq_raw ( const uint32_t *value0, const uint32_t *reference0,
|
||||
unsigned int size ) {
|
||||
const uint32_t *value = ( value0 + size );
|
||||
const uint32_t *reference = ( reference0 + size );
|
||||
uint32_t value_i;
|
||||
uint32_t reference_i;
|
||||
|
||||
do {
|
||||
value_i = *(--value);
|
||||
reference_i = *(--reference);
|
||||
if ( value_i != reference_i )
|
||||
break;
|
||||
} while ( --size );
|
||||
|
||||
return ( value_i >= reference_i );
|
||||
}
|
||||
|
||||
/**
|
||||
* Find highest bit set in big integer
|
||||
*
|
||||
* @v value0 Element 0 of big integer
|
||||
* @v size Number of elements
|
||||
* @ret max_bit Highest bit set + 1 (or 0 if no bits set)
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) int
|
||||
bigint_max_set_bit_raw ( const uint32_t *value0, unsigned int size ) {
|
||||
const uint32_t *value = ( value0 + size );
|
||||
int max_bit = ( 8 * sizeof ( bigint_t ( size ) ) );
|
||||
uint32_t value_i;
|
||||
|
||||
do {
|
||||
value_i = *(--value);
|
||||
max_bit -= ( 32 - fls ( value_i ) );
|
||||
if ( value_i )
|
||||
break;
|
||||
} while ( --size );
|
||||
|
||||
return max_bit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grow big integer
|
||||
*
|
||||
@@ -284,25 +191,6 @@ bigint_shrink_raw ( const uint32_t *source0, unsigned int source_size __unused,
|
||||
memcpy ( dest0, source0, sizeof ( bigint_t ( dest_size ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalise big integer
|
||||
*
|
||||
* @v value0 Element 0 of big integer to finalise
|
||||
* @v size Number of elements
|
||||
* @v out Output buffer
|
||||
* @v len Length of output buffer
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
bigint_done_raw ( const uint32_t *value0, unsigned int size __unused,
|
||||
void *out, size_t len ) {
|
||||
const uint8_t *value_byte = ( ( const void * ) value0 );
|
||||
uint8_t *out_byte = ( out + len );
|
||||
|
||||
/* Copy raw data in reverse order */
|
||||
while ( len-- )
|
||||
*(--out_byte) = *(value_byte++);
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiply big integer elements
|
||||
*
|
||||
|
||||
@@ -11,33 +11,10 @@ FILE_SECBOOT ( PERMITTED );
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
/** Element of a big integer */
|
||||
typedef uint64_t bigint_element_t;
|
||||
|
||||
/**
|
||||
* Initialise big integer
|
||||
*
|
||||
* @v value0 Element 0 of big integer to initialise
|
||||
* @v size Number of elements
|
||||
* @v data Raw data
|
||||
* @v len Length of raw data
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
bigint_init_raw ( uint64_t *value0, unsigned int size,
|
||||
const void *data, size_t len ) {
|
||||
size_t pad_len = ( sizeof ( bigint_t ( size ) ) - len );
|
||||
uint8_t *value_byte = ( ( void * ) value0 );
|
||||
const uint8_t *data_byte = ( data + len );
|
||||
|
||||
/* Copy raw data in reverse order, padding with zeros */
|
||||
while ( len-- )
|
||||
*(value_byte++) = *(--data_byte);
|
||||
while ( pad_len-- )
|
||||
*(value_byte++) = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add big integers
|
||||
*
|
||||
@@ -183,76 +160,6 @@ bigint_shr_raw ( uint64_t *value0, unsigned int size ) {
|
||||
return ( low & 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if big integer is equal to zero
|
||||
*
|
||||
* @v value0 Element 0 of big integer
|
||||
* @v size Number of elements
|
||||
* @ret is_zero Big integer is equal to zero
|
||||
*/
|
||||
static inline __attribute__ (( always_inline, pure )) int
|
||||
bigint_is_zero_raw ( const uint64_t *value0, unsigned int size ) {
|
||||
const uint64_t *value = value0;
|
||||
uint64_t value_i;
|
||||
|
||||
do {
|
||||
value_i = *(value++);
|
||||
if ( value_i )
|
||||
break;
|
||||
} while ( --size );
|
||||
|
||||
return ( value_i == 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare big integers
|
||||
*
|
||||
* @v value0 Element 0 of big integer
|
||||
* @v reference0 Element 0 of reference big integer
|
||||
* @v size Number of elements
|
||||
* @ret geq Big integer is greater than or equal to the reference
|
||||
*/
|
||||
static inline __attribute__ (( always_inline, pure )) int
|
||||
bigint_is_geq_raw ( const uint64_t *value0, const uint64_t *reference0,
|
||||
unsigned int size ) {
|
||||
const uint64_t *value = ( value0 + size );
|
||||
const uint64_t *reference = ( reference0 + size );
|
||||
uint64_t value_i;
|
||||
uint64_t reference_i;
|
||||
|
||||
do {
|
||||
value_i = *(--value);
|
||||
reference_i = *(--reference);
|
||||
if ( value_i != reference_i )
|
||||
break;
|
||||
} while ( --size );
|
||||
|
||||
return ( value_i >= reference_i );
|
||||
}
|
||||
|
||||
/**
|
||||
* Find highest bit set in big integer
|
||||
*
|
||||
* @v value0 Element 0 of big integer
|
||||
* @v size Number of elements
|
||||
* @ret max_bit Highest bit set + 1 (or 0 if no bits set)
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) int
|
||||
bigint_max_set_bit_raw ( const uint64_t *value0, unsigned int size ) {
|
||||
const uint64_t *value = ( value0 + size );
|
||||
int max_bit = ( 8 * sizeof ( bigint_t ( size ) ) );
|
||||
uint64_t value_i;
|
||||
|
||||
do {
|
||||
value_i = *(--value);
|
||||
max_bit -= ( 64 - fls ( value_i ) );
|
||||
if ( value_i )
|
||||
break;
|
||||
} while ( --size );
|
||||
|
||||
return max_bit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grow big integer
|
||||
*
|
||||
@@ -285,25 +192,6 @@ bigint_shrink_raw ( const uint64_t *source0, unsigned int source_size __unused,
|
||||
memcpy ( dest0, source0, sizeof ( bigint_t ( dest_size ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalise big integer
|
||||
*
|
||||
* @v value0 Element 0 of big integer to finalise
|
||||
* @v size Number of elements
|
||||
* @v out Output buffer
|
||||
* @v len Length of output buffer
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
bigint_done_raw ( const uint64_t *value0, unsigned int size __unused,
|
||||
void *out, size_t len ) {
|
||||
const uint8_t *value_byte = ( ( const void * ) value0 );
|
||||
uint8_t *out_byte = ( out + len );
|
||||
|
||||
/* Copy raw data in reverse order */
|
||||
while ( len-- )
|
||||
*(--out_byte) = *(value_byte++);
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiply big integer elements
|
||||
*
|
||||
|
||||
@@ -11,33 +11,10 @@ FILE_SECBOOT ( PERMITTED );
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
/** Element of a big integer */
|
||||
typedef uint64_t bigint_element_t;
|
||||
|
||||
/**
|
||||
* Initialise big integer
|
||||
*
|
||||
* @v value0 Element 0 of big integer to initialise
|
||||
* @v size Number of elements
|
||||
* @v data Raw data
|
||||
* @v len Length of raw data
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
bigint_init_raw ( uint64_t *value0, unsigned int size,
|
||||
const void *data, size_t len ) {
|
||||
size_t pad_len = ( sizeof ( bigint_t ( size ) ) - len );
|
||||
uint8_t *value_byte = ( ( void * ) value0 );
|
||||
const uint8_t *data_byte = ( data + len );
|
||||
|
||||
/* Copy raw data in reverse order, padding with zeros */
|
||||
while ( len-- )
|
||||
*(value_byte++) = *(--data_byte);
|
||||
while ( pad_len-- )
|
||||
*(value_byte++) = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add big integers
|
||||
*
|
||||
@@ -226,76 +203,6 @@ bigint_shr_raw ( uint64_t *value0, unsigned int size ) {
|
||||
return ( carry & 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if big integer is equal to zero
|
||||
*
|
||||
* @v value0 Element 0 of big integer
|
||||
* @v size Number of elements
|
||||
* @ret is_zero Big integer is equal to zero
|
||||
*/
|
||||
static inline __attribute__ (( always_inline, pure )) int
|
||||
bigint_is_zero_raw ( const uint64_t *value0, unsigned int size ) {
|
||||
const uint64_t *value = value0;
|
||||
uint64_t value_i;
|
||||
|
||||
do {
|
||||
value_i = *(value++);
|
||||
if ( value_i )
|
||||
break;
|
||||
} while ( --size );
|
||||
|
||||
return ( value_i == 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare big integers
|
||||
*
|
||||
* @v value0 Element 0 of big integer
|
||||
* @v reference0 Element 0 of reference big integer
|
||||
* @v size Number of elements
|
||||
* @ret geq Big integer is greater than or equal to the reference
|
||||
*/
|
||||
static inline __attribute__ (( always_inline, pure )) int
|
||||
bigint_is_geq_raw ( const uint64_t *value0, const uint64_t *reference0,
|
||||
unsigned int size ) {
|
||||
const uint64_t *value = ( value0 + size );
|
||||
const uint64_t *reference = ( reference0 + size );
|
||||
uint64_t value_i;
|
||||
uint64_t reference_i;
|
||||
|
||||
do {
|
||||
value_i = *(--value);
|
||||
reference_i = *(--reference);
|
||||
if ( value_i != reference_i )
|
||||
break;
|
||||
} while ( --size );
|
||||
|
||||
return ( value_i >= reference_i );
|
||||
}
|
||||
|
||||
/**
|
||||
* Find highest bit set in big integer
|
||||
*
|
||||
* @v value0 Element 0 of big integer
|
||||
* @v size Number of elements
|
||||
* @ret max_bit Highest bit set + 1 (or 0 if no bits set)
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) int
|
||||
bigint_max_set_bit_raw ( const uint64_t *value0, unsigned int size ) {
|
||||
const uint64_t *value = ( value0 + size );
|
||||
int max_bit = ( 8 * sizeof ( bigint_t ( size ) ) );
|
||||
uint64_t value_i;
|
||||
|
||||
do {
|
||||
value_i = *(--value);
|
||||
max_bit -= ( 64 - fls ( value_i ) );
|
||||
if ( value_i )
|
||||
break;
|
||||
} while ( --size );
|
||||
|
||||
return max_bit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grow big integer
|
||||
*
|
||||
@@ -328,25 +235,6 @@ bigint_shrink_raw ( const uint64_t *source0, unsigned int source_size __unused,
|
||||
memcpy ( dest0, source0, sizeof ( bigint_t ( dest_size ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalise big integer
|
||||
*
|
||||
* @v value0 Element 0 of big integer to finalise
|
||||
* @v size Number of elements
|
||||
* @v out Output buffer
|
||||
* @v len Length of output buffer
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
bigint_done_raw ( const uint64_t *value0, unsigned int size __unused,
|
||||
void *out, size_t len ) {
|
||||
const uint8_t *value_byte = ( ( const void * ) value0 );
|
||||
uint8_t *out_byte = ( out + len );
|
||||
|
||||
/* Copy raw data in reverse order */
|
||||
while ( len-- )
|
||||
*(--out_byte) = *(value_byte++);
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiply big integer elements
|
||||
*
|
||||
|
||||
@@ -11,33 +11,10 @@ FILE_SECBOOT ( PERMITTED );
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
/** Element of a big integer */
|
||||
typedef unsigned long bigint_element_t;
|
||||
|
||||
/**
|
||||
* Initialise big integer
|
||||
*
|
||||
* @v value0 Element 0 of big integer to initialise
|
||||
* @v size Number of elements
|
||||
* @v data Raw data
|
||||
* @v len Length of raw data
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
bigint_init_raw ( unsigned long *value0, unsigned int size,
|
||||
const void *data, size_t len ) {
|
||||
size_t pad_len = ( sizeof ( bigint_t ( size ) ) - len );
|
||||
uint8_t *value_byte = ( ( void * ) value0 );
|
||||
const uint8_t *data_byte = ( data + len );
|
||||
|
||||
/* Copy raw data in reverse order, padding with zeros */
|
||||
while ( len-- )
|
||||
*(value_byte++) = *(--data_byte);
|
||||
while ( pad_len-- )
|
||||
*(value_byte++) = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add big integers
|
||||
*
|
||||
@@ -221,76 +198,6 @@ bigint_shr_raw ( unsigned long *value0, unsigned int size ) {
|
||||
return ( !! carry );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if big integer is equal to zero
|
||||
*
|
||||
* @v value0 Element 0 of big integer
|
||||
* @v size Number of elements
|
||||
* @ret is_zero Big integer is equal to zero
|
||||
*/
|
||||
static inline __attribute__ (( always_inline, pure )) int
|
||||
bigint_is_zero_raw ( const unsigned long *value0, unsigned int size ) {
|
||||
const unsigned long *value = value0;
|
||||
unsigned long value_i;
|
||||
|
||||
do {
|
||||
value_i = *(value++);
|
||||
if ( value_i )
|
||||
break;
|
||||
} while ( --size );
|
||||
|
||||
return ( value_i == 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare big integers
|
||||
*
|
||||
* @v value0 Element 0 of big integer
|
||||
* @v reference0 Element 0 of reference big integer
|
||||
* @v size Number of elements
|
||||
* @ret geq Big integer is greater than or equal to the reference
|
||||
*/
|
||||
static inline __attribute__ (( always_inline, pure )) int
|
||||
bigint_is_geq_raw ( const unsigned long *value0,
|
||||
const unsigned long *reference0, unsigned int size ) {
|
||||
const unsigned long *value = ( value0 + size );
|
||||
const unsigned long *reference = ( reference0 + size );
|
||||
unsigned long value_i;
|
||||
unsigned long reference_i;
|
||||
|
||||
do {
|
||||
value_i = *(--value);
|
||||
reference_i = *(--reference);
|
||||
if ( value_i != reference_i )
|
||||
break;
|
||||
} while ( --size );
|
||||
|
||||
return ( value_i >= reference_i );
|
||||
}
|
||||
|
||||
/**
|
||||
* Find highest bit set in big integer
|
||||
*
|
||||
* @v value0 Element 0 of big integer
|
||||
* @v size Number of elements
|
||||
* @ret max_bit Highest bit set + 1 (or 0 if no bits set)
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) int
|
||||
bigint_max_set_bit_raw ( const unsigned long *value0, unsigned int size ) {
|
||||
const unsigned long *value = ( value0 + size );
|
||||
int max_bit = ( 8 * sizeof ( bigint_t ( size ) ) );
|
||||
unsigned long value_i;
|
||||
|
||||
do {
|
||||
value_i = *(--value);
|
||||
max_bit -= ( ( 8 * sizeof ( *value0 ) ) - fls ( value_i ) );
|
||||
if ( value_i )
|
||||
break;
|
||||
} while ( --size );
|
||||
|
||||
return max_bit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grow big integer
|
||||
*
|
||||
@@ -324,25 +231,6 @@ bigint_shrink_raw ( const unsigned long *source0,
|
||||
memcpy ( dest0, source0, sizeof ( bigint_t ( dest_size ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalise big integer
|
||||
*
|
||||
* @v value0 Element 0 of big integer to finalise
|
||||
* @v size Number of elements
|
||||
* @v out Output buffer
|
||||
* @v len Length of output buffer
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
bigint_done_raw ( const unsigned long *value0, unsigned int size __unused,
|
||||
void *out, size_t len ) {
|
||||
const uint8_t *value_byte = ( ( const void * ) value0 );
|
||||
uint8_t *out_byte = ( out + len );
|
||||
|
||||
/* Copy raw data in reverse order */
|
||||
while ( len-- )
|
||||
*(--out_byte) = *(value_byte++);
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiply big integer elements
|
||||
*
|
||||
|
||||
@@ -10,45 +10,10 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
FILE_SECBOOT ( PERMITTED );
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
/** Element of a big integer */
|
||||
typedef uint32_t bigint_element_t;
|
||||
|
||||
/**
|
||||
* Initialise big integer
|
||||
*
|
||||
* @v value0 Element 0 of big integer to initialise
|
||||
* @v size Number of elements
|
||||
* @v data Raw data
|
||||
* @v len Length of raw data
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
bigint_init_raw ( uint32_t *value0, unsigned int size,
|
||||
const void *data, size_t len ) {
|
||||
bigint_t ( size ) __attribute__ (( may_alias )) *value =
|
||||
( ( void * ) value0 );
|
||||
long pad_len = ( sizeof ( *value ) - len );
|
||||
void *discard_D;
|
||||
long discard_c;
|
||||
|
||||
/* Copy raw data in reverse order, padding with zeros */
|
||||
__asm__ __volatile__ ( "jecxz 2f\n\t"
|
||||
"\n1:\n\t"
|
||||
"movb -1(%3,%1), %%al\n\t"
|
||||
"stosb\n\t"
|
||||
"loop 1b\n\t"
|
||||
"\n2:\n\t"
|
||||
"xorl %%eax, %%eax\n\t"
|
||||
"mov %4, %1\n\t"
|
||||
"rep stosb\n\t"
|
||||
: "=&D" ( discard_D ), "=&c" ( discard_c ),
|
||||
"+m" ( *value )
|
||||
: "r" ( data ), "g" ( pad_len ), "0" ( value0 ),
|
||||
"1" ( len )
|
||||
: "eax" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add big integers
|
||||
*
|
||||
@@ -164,81 +129,6 @@ bigint_shr_raw ( uint32_t *value0, unsigned int size ) {
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if big integer is equal to zero
|
||||
*
|
||||
* @v value0 Element 0 of big integer
|
||||
* @v size Number of elements
|
||||
* @ret is_zero Big integer is equal to zero
|
||||
*/
|
||||
static inline __attribute__ (( always_inline, pure )) int
|
||||
bigint_is_zero_raw ( const uint32_t *value0, unsigned int size ) {
|
||||
void *discard_D;
|
||||
long discard_c;
|
||||
int result;
|
||||
|
||||
__asm__ __volatile__ ( "xor %0, %0\n\t" /* Set ZF */
|
||||
"repe scasl\n\t"
|
||||
"sete %b0\n\t"
|
||||
: "=&a" ( result ), "=&D" ( discard_D ),
|
||||
"=&c" ( discard_c )
|
||||
: "1" ( value0 ), "2" ( size ) );
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare big integers
|
||||
*
|
||||
* @v value0 Element 0 of big integer
|
||||
* @v reference0 Element 0 of reference big integer
|
||||
* @v size Number of elements
|
||||
* @ret geq Big integer is greater than or equal to the reference
|
||||
*/
|
||||
static inline __attribute__ (( always_inline, pure )) int
|
||||
bigint_is_geq_raw ( const uint32_t *value0, const uint32_t *reference0,
|
||||
unsigned int size ) {
|
||||
long discard_c;
|
||||
long discard_tmp;
|
||||
int result;
|
||||
|
||||
__asm__ __volatile__ ( "\n1:\n\t"
|
||||
"movl -4(%3, %1, 4), %k2\n\t"
|
||||
"cmpl -4(%4, %1, 4), %k2\n\t"
|
||||
"loope 1b\n\t"
|
||||
"setae %b0\n\t"
|
||||
: "=q" ( result ), "=&c" ( discard_c ),
|
||||
"=&r" ( discard_tmp )
|
||||
: "r" ( value0 ), "r" ( reference0 ),
|
||||
"0" ( 0 ), "1" ( size ) );
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find highest bit set in big integer
|
||||
*
|
||||
* @v value0 Element 0 of big integer
|
||||
* @v size Number of elements
|
||||
* @ret max_bit Highest bit set + 1 (or 0 if no bits set)
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) int
|
||||
bigint_max_set_bit_raw ( const uint32_t *value0, unsigned int size ) {
|
||||
long discard_c;
|
||||
int result;
|
||||
|
||||
__asm__ __volatile__ ( "\n1:\n\t"
|
||||
"bsrl -4(%2,%1,4), %0\n\t"
|
||||
"loopz 1b\n\t"
|
||||
"rol %1\n\t" /* Does not affect ZF */
|
||||
"rol %1\n\t"
|
||||
"leal 1(%k0,%k1,8), %k0\n\t"
|
||||
"jnz 2f\n\t"
|
||||
"xor %0, %0\n\t"
|
||||
"\n2:\n\t"
|
||||
: "=&r" ( result ), "=&c" ( discard_c )
|
||||
: "r" ( value0 ), "1" ( size ) );
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grow big integer
|
||||
*
|
||||
@@ -293,36 +183,6 @@ bigint_shrink_raw ( const uint32_t *source0, unsigned int source_size __unused,
|
||||
: "eax" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalise big integer
|
||||
*
|
||||
* @v value0 Element 0 of big integer to finalise
|
||||
* @v size Number of elements
|
||||
* @v out Output buffer
|
||||
* @v len Length of output buffer
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
bigint_done_raw ( const uint32_t *value0, unsigned int size __unused,
|
||||
void *out, size_t len ) {
|
||||
struct {
|
||||
uint8_t bytes[len];
|
||||
} __attribute__ (( may_alias )) *out_bytes = out;
|
||||
void *discard_D;
|
||||
long discard_c;
|
||||
|
||||
/* Copy raw data in reverse order */
|
||||
__asm__ __volatile__ ( "jecxz 2f\n\t"
|
||||
"\n1:\n\t"
|
||||
"movb -1(%3,%1), %%al\n\t"
|
||||
"stosb\n\t"
|
||||
"loop 1b\n\t"
|
||||
"\n2:\n\t"
|
||||
: "=&D" ( discard_D ), "=&c" ( discard_c ),
|
||||
"+m" ( *out_bytes )
|
||||
: "r" ( value0 ), "0" ( out ), "1" ( len )
|
||||
: "eax" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiply big integer elements
|
||||
*
|
||||
|
||||
@@ -26,7 +26,9 @@ FILE_SECBOOT ( PERMITTED );
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <assert.h>
|
||||
#include <byteswap.h>
|
||||
#include <stdio.h>
|
||||
#include <ipxe/bigint.h>
|
||||
|
||||
@@ -81,6 +83,138 @@ const char * bigint_ntoa_raw ( const bigint_element_t *value0,
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise big integer
|
||||
*
|
||||
* @v value0 Element 0 of big integer to initialise
|
||||
* @v size Number of elements
|
||||
* @v data Raw data
|
||||
* @v len Length of raw data
|
||||
*/
|
||||
void bigint_init_raw ( bigint_element_t *value0, unsigned int size,
|
||||
const void *data, size_t len ) {
|
||||
bigint_t ( size ) __attribute__ (( may_alias ))
|
||||
*value = ( ( void * ) value0 );
|
||||
uint8_t *value_byte = ( ( void * ) value0 );
|
||||
const uint8_t *data_byte = data;
|
||||
unsigned int toggle;
|
||||
unsigned int i;
|
||||
|
||||
/* Zero big integer */
|
||||
memset ( value, 0, sizeof ( *value ) );
|
||||
|
||||
/* Copy data, byte-swapping as needed */
|
||||
toggle = ( ( __BYTE_ORDER == __LITTLE_ENDIAN ) ? 0 :
|
||||
( sizeof ( value->element[0] ) - 1 ) );
|
||||
for ( i = 0 ; len-- ; i++ )
|
||||
value_byte[ i ^ toggle ] = data_byte[len];
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalise big integer
|
||||
*
|
||||
* @v value0 Element 0 of big integer to finalise
|
||||
* @v size Number of elements
|
||||
* @v out Output buffer
|
||||
* @v len Length of output buffer
|
||||
*/
|
||||
void bigint_done_raw ( const bigint_element_t *value0, unsigned int size,
|
||||
void *out, size_t len ) {
|
||||
const bigint_t ( size ) __attribute__ (( may_alias ))
|
||||
*value = ( ( const void * ) value0 );
|
||||
const uint8_t *value_byte = ( ( const void * ) value0 );
|
||||
uint8_t *out_byte = out;
|
||||
unsigned int toggle;
|
||||
unsigned int i;
|
||||
|
||||
/* Zero output buffer */
|
||||
memset ( out, 0, len );
|
||||
|
||||
/* Copy data, byte-swapping as needed */
|
||||
toggle = ( ( __BYTE_ORDER == __LITTLE_ENDIAN ) ? 0 :
|
||||
( sizeof ( value->element[0] ) - 1 ) );
|
||||
for ( i = 0 ; len-- ; i++ )
|
||||
out_byte[len] = value_byte[ i ^ toggle ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if big integer is equal to zero
|
||||
*
|
||||
* @v value0 Element 0 of big integer
|
||||
* @v size Number of elements
|
||||
* @ret is_zero Big integer is equal to zero
|
||||
*/
|
||||
int bigint_is_zero_raw ( const bigint_element_t *value0, unsigned int size ) {
|
||||
const bigint_t ( size ) __attribute__ (( may_alias )) *value =
|
||||
( ( const void * ) value0 );
|
||||
bigint_element_t or;
|
||||
unsigned int i;
|
||||
|
||||
/* Construct binary OR of all elements */
|
||||
for ( i = 0, or = 0 ; i < size ; i++ )
|
||||
or |= value->element[i];
|
||||
|
||||
return ( or == 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare big integers
|
||||
*
|
||||
* @v value0 Element 0 of big integer
|
||||
* @v reference0 Element 0 of reference big integer
|
||||
* @v size Number of elements
|
||||
* @ret geq Big integer is greater than or equal to the reference
|
||||
*/
|
||||
int bigint_is_geq_raw ( const bigint_element_t *value0,
|
||||
const bigint_element_t *reference0,
|
||||
unsigned int size ) {
|
||||
const bigint_t ( size ) __attribute__ (( may_alias )) *value =
|
||||
( ( const void * ) value0 );
|
||||
const bigint_t ( size ) __attribute__ (( may_alias )) *reference =
|
||||
( ( const void * ) reference0 );
|
||||
bigint_element_t value_element;
|
||||
bigint_element_t reference_element;
|
||||
|
||||
/* Find highest differing element */
|
||||
do {
|
||||
value_element = value->element[ size - 1 ];
|
||||
reference_element = reference->element[ size - 1 ];
|
||||
if ( value_element != reference_element )
|
||||
break;
|
||||
} while ( --size );
|
||||
|
||||
return ( value_element >= reference_element );
|
||||
}
|
||||
|
||||
/**
|
||||
* Find highest bit set in big integer
|
||||
*
|
||||
* @v value0 Element 0 of big integer
|
||||
* @v size Number of elements
|
||||
* @ret max_bit Highest bit set + 1 (or 0 if no bits set)
|
||||
*/
|
||||
int bigint_max_set_bit_raw ( const bigint_element_t *value0,
|
||||
unsigned int size ) {
|
||||
const bigint_t ( size ) __attribute__ (( may_alias )) *value =
|
||||
( ( const void * ) value0 );
|
||||
bigint_element_t element;
|
||||
unsigned int max_bit;
|
||||
unsigned int i;
|
||||
|
||||
/* Find highest set bit in highest non-zero element */
|
||||
max_bit = ( sizeof ( *value ) * 8 );
|
||||
for ( i = 0 ; i < size ; i++ ) {
|
||||
element = value->element[ size - i - 1 ];
|
||||
max_bit -= ( sizeof ( element) * 8 );
|
||||
if ( element ) {
|
||||
max_bit += flsll ( element );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return max_bit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Conditionally swap big integers (in constant time)
|
||||
*
|
||||
|
||||
@@ -42,6 +42,7 @@ FILE_SECBOOT ( PERMITTED );
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ipxe/ffdhe.h>
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ FILE_SECBOOT ( PERMITTED );
|
||||
* implementation of the big integer operations.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ipxe/weierstrass.h>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user