]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[crypto] Use generic implementations of slow-path big integer functions
authorMichael Brown <mcb30@ipxe.org>
Sat, 13 Jun 2026 14:28:52 +0000 (15:28 +0100)
committerMichael Brown <mcb30@ipxe.org>
Sat, 13 Jun 2026 14:53:19 +0000 (15:53 +0100)
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>
src/arch/arm32/include/bits/bigint.h
src/arch/arm64/include/bits/bigint.h
src/arch/loong64/include/bits/bigint.h
src/arch/riscv/include/bits/bigint.h
src/arch/x86/include/bits/bigint.h
src/crypto/bigint.c
src/crypto/ffdhe.c
src/crypto/weierstrass.c

index 988bef5ff68451666d217a7156672ac1843c79be..da6cfbf30e265441e78ee4f33eedb4f0fe18d899 100644 (file)
@@ -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
  *
index a4c351c9360749d02bb1af2e72d4090d23bb5151..8d7a795310b6b5156a4e381d73d5c7b357b773c7 100644 (file)
@@ -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
  *
index ac475da67dff04433b82bcca82f4b1b3cd4275ed..b2938f849827dbb40534d659cfdaa51bbd500d53 100644 (file)
@@ -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
  *
index 89718f3ebdb58e2a799b1e7e7ac6c4b7a67e1f08..70a267bbef59892c33b0cfc25d1962609e5a67e0 100644 (file)
@@ -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
  *
index 21cffa0cf7c5f27c06b5f63f92b5bb5b3e11e2df..e4ac52d1e8f31a03097550102505ae78d33e3223 100644 (file)
@@ -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
  *
index 5d2f7b5601de7525f13bf63a4ca7e48b1428134d..d3eafe19afdac23ab669999f525c8802ec12e8bf 100644 (file)
@@ -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)
  *
index 7dc9457fca2af3a7d536c44b80543fb8832d6543..41bd90813bbc8ad2258dd132d9b7de85167e308a 100644 (file)
@@ -42,6 +42,7 @@ FILE_SECBOOT ( PERMITTED );
  */
 
 #include <stdint.h>
+#include <string.h>
 #include <errno.h>
 #include <ipxe/ffdhe.h>
 
index 783e07a9037d5dc85fecdc91b133ab85033c4abe..ab2df240794ecd0890f03d1827f9e4849a8d1a0b 100644 (file)
@@ -45,6 +45,7 @@ FILE_SECBOOT ( PERMITTED );
  * implementation of the big integer operations.
  */
 
+#include <string.h>
 #include <errno.h>
 #include <ipxe/weierstrass.h>