[crypto] Allow multiplicand and multiplier to differ in size

Big integer multiplication is currently used only as part of modular
exponentiation, where both multiplicand and multiplier will be the
same size.

Relax this requirement to allow for the use of big integer
multiplication in other contexts.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
pull/118/head
Michael Brown 2024-01-16 16:09:16 +00:00
parent 4b7d9a6af0
commit 26d3ef062b
10 changed files with 103 additions and 68 deletions

View File

@ -36,19 +36,23 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* Multiply big integers * Multiply big integers
* *
* @v multiplicand0 Element 0 of big integer to be multiplied * @v multiplicand0 Element 0 of big integer to be multiplied
* @v multiplicand_size Number of elements in multiplicand
* @v multiplier0 Element 0 of big integer to be multiplied * @v multiplier0 Element 0 of big integer to be multiplied
* @v multiplier_size Number of elements in multiplier
* @v result0 Element 0 of big integer to hold result * @v result0 Element 0 of big integer to hold result
* @v size Number of elements
*/ */
void bigint_multiply_raw ( const uint32_t *multiplicand0, void bigint_multiply_raw ( const uint32_t *multiplicand0,
unsigned int multiplicand_size,
const uint32_t *multiplier0, const uint32_t *multiplier0,
uint32_t *result0, unsigned int size ) { unsigned int multiplier_size,
const bigint_t ( size ) __attribute__ (( may_alias )) *multiplicand = uint32_t *result0 ) {
( ( const void * ) multiplicand0 ); unsigned int result_size = ( multiplicand_size + multiplier_size );
const bigint_t ( size ) __attribute__ (( may_alias )) *multiplier = const bigint_t ( multiplicand_size ) __attribute__ (( may_alias ))
( ( const void * ) multiplier0 ); *multiplicand = ( ( const void * ) multiplicand0 );
bigint_t ( size * 2 ) __attribute__ (( may_alias )) *result = const bigint_t ( multiplier_size ) __attribute__ (( may_alias ))
( ( void * ) result0 ); *multiplier = ( ( const void * ) multiplier0 );
bigint_t ( result_size ) __attribute__ (( may_alias ))
*result = ( ( void * ) result0 );
unsigned int i; unsigned int i;
unsigned int j; unsigned int j;
uint32_t multiplicand_element; uint32_t multiplicand_element;
@ -62,9 +66,9 @@ void bigint_multiply_raw ( const uint32_t *multiplicand0,
memset ( result, 0, sizeof ( *result ) ); memset ( result, 0, sizeof ( *result ) );
/* Multiply integers one element at a time */ /* Multiply integers one element at a time */
for ( i = 0 ; i < size ; i++ ) { for ( i = 0 ; i < multiplicand_size ; i++ ) {
multiplicand_element = multiplicand->element[i]; multiplicand_element = multiplicand->element[i];
for ( j = 0 ; j < size ; j++ ) { for ( j = 0 ; j < multiplier_size ; j++ ) {
multiplier_element = multiplier->element[j]; multiplier_element = multiplier->element[j];
result_elements = &result->element[ i + j ]; result_elements = &result->element[ i + j ];
/* Perform a single multiply, and add the /* Perform a single multiply, and add the
@ -73,7 +77,7 @@ void bigint_multiply_raw ( const uint32_t *multiplicand0,
* never overflow beyond the end of the * never overflow beyond the end of the
* result, since: * result, since:
* *
* a < 2^{n}, b < 2^{n} => ab < 2^{2n} * a < 2^{n}, b < 2^{m} => ab < 2^{n+m}
*/ */
__asm__ __volatile__ ( "umull %1, %2, %5, %6\n\t" __asm__ __volatile__ ( "umull %1, %2, %5, %6\n\t"
"ldr %3, [%0]\n\t" "ldr %3, [%0]\n\t"

View File

@ -310,7 +310,9 @@ bigint_done_raw ( const uint32_t *value0, unsigned int size __unused,
} }
extern void bigint_multiply_raw ( const uint32_t *multiplicand0, extern void bigint_multiply_raw ( const uint32_t *multiplicand0,
unsigned int multiplicand_size,
const uint32_t *multiplier0, const uint32_t *multiplier0,
uint32_t *value0, unsigned int size ); unsigned int multiplier_size,
uint32_t *value0 );
#endif /* _BITS_BIGINT_H */ #endif /* _BITS_BIGINT_H */

View File

@ -36,19 +36,23 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* Multiply big integers * Multiply big integers
* *
* @v multiplicand0 Element 0 of big integer to be multiplied * @v multiplicand0 Element 0 of big integer to be multiplied
* @v multiplicand_size Number of elements in multiplicand
* @v multiplier0 Element 0 of big integer to be multiplied * @v multiplier0 Element 0 of big integer to be multiplied
* @v multiplier_size Number of elements in multiplier
* @v result0 Element 0 of big integer to hold result * @v result0 Element 0 of big integer to hold result
* @v size Number of elements
*/ */
void bigint_multiply_raw ( const uint64_t *multiplicand0, void bigint_multiply_raw ( const uint64_t *multiplicand0,
unsigned int multiplicand_size,
const uint64_t *multiplier0, const uint64_t *multiplier0,
uint64_t *result0, unsigned int size ) { unsigned int multiplier_size,
const bigint_t ( size ) __attribute__ (( may_alias )) *multiplicand = uint64_t *result0 ) {
( ( const void * ) multiplicand0 ); unsigned int result_size = ( multiplicand_size + multiplier_size );
const bigint_t ( size ) __attribute__ (( may_alias )) *multiplier = const bigint_t ( multiplicand_size ) __attribute__ (( may_alias ))
( ( const void * ) multiplier0 ); *multiplicand = ( ( const void * ) multiplicand0 );
bigint_t ( size * 2 ) __attribute__ (( may_alias )) *result = const bigint_t ( multiplier_size ) __attribute__ (( may_alias ))
( ( void * ) result0 ); *multiplier = ( ( const void * ) multiplier0 );
bigint_t ( result_size ) __attribute__ (( may_alias ))
*result = ( ( void * ) result0 );
unsigned int i; unsigned int i;
unsigned int j; unsigned int j;
uint64_t multiplicand_element; uint64_t multiplicand_element;
@ -63,9 +67,9 @@ void bigint_multiply_raw ( const uint64_t *multiplicand0,
memset ( result, 0, sizeof ( *result ) ); memset ( result, 0, sizeof ( *result ) );
/* Multiply integers one element at a time */ /* Multiply integers one element at a time */
for ( i = 0 ; i < size ; i++ ) { for ( i = 0 ; i < multiplicand_size ; i++ ) {
multiplicand_element = multiplicand->element[i]; multiplicand_element = multiplicand->element[i];
for ( j = 0 ; j < size ; j++ ) { for ( j = 0 ; j < multiplier_size ; j++ ) {
multiplier_element = multiplier->element[j]; multiplier_element = multiplier->element[j];
result_elements = &result->element[ i + j ]; result_elements = &result->element[ i + j ];
/* Perform a single multiply, and add the /* Perform a single multiply, and add the
@ -74,7 +78,7 @@ void bigint_multiply_raw ( const uint64_t *multiplicand0,
* never overflow beyond the end of the * never overflow beyond the end of the
* result, since: * result, since:
* *
* a < 2^{n}, b < 2^{n} => ab < 2^{2n} * a < 2^{n}, b < 2^{m} => ab < 2^{n+m}
*/ */
__asm__ __volatile__ ( "mul %1, %6, %7\n\t" __asm__ __volatile__ ( "mul %1, %6, %7\n\t"
"umulh %2, %6, %7\n\t" "umulh %2, %6, %7\n\t"

View File

@ -311,7 +311,9 @@ bigint_done_raw ( const uint64_t *value0, unsigned int size __unused,
} }
extern void bigint_multiply_raw ( const uint64_t *multiplicand0, extern void bigint_multiply_raw ( const uint64_t *multiplicand0,
unsigned int multiplicand_size,
const uint64_t *multiplier0, const uint64_t *multiplier0,
uint64_t *value0, unsigned int size ); unsigned int multiplier_size,
uint64_t *value0 );
#endif /* _BITS_BIGINT_H */ #endif /* _BITS_BIGINT_H */

View File

@ -37,19 +37,23 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* Multiply big integers * Multiply big integers
* *
* @v multiplicand0 Element 0 of big integer to be multiplied * @v multiplicand0 Element 0 of big integer to be multiplied
* @v multiplicand_size Number of elements in multiplicand
* @v multiplier0 Element 0 of big integer to be multiplied * @v multiplier0 Element 0 of big integer to be multiplied
* @v multiplier_size Number of elements in multiplier
* @v result0 Element 0 of big integer to hold result * @v result0 Element 0 of big integer to hold result
* @v size Number of elements
*/ */
void bigint_multiply_raw ( const uint64_t *multiplicand0, void bigint_multiply_raw ( const uint64_t *multiplicand0,
unsigned int multiplicand_size,
const uint64_t *multiplier0, const uint64_t *multiplier0,
uint64_t *result0, unsigned int size ) { unsigned int multiplier_size,
const bigint_t ( size ) __attribute__ (( may_alias )) *multiplicand = uint64_t *result0 ) {
( ( const void * ) multiplicand0 ); unsigned int result_size = ( multiplicand_size + multiplier_size );
const bigint_t ( size ) __attribute__ (( may_alias )) *multiplier = const bigint_t ( multiplicand_size ) __attribute__ (( may_alias ))
( ( const void * ) multiplier0 ); *multiplicand = ( ( const void * ) multiplicand0 );
bigint_t ( size * 2 ) __attribute__ (( may_alias )) *result = const bigint_t ( multiplier_size ) __attribute__ (( may_alias ))
( ( void * ) result0 ); *multiplier = ( ( const void * ) multiplier0 );
bigint_t ( result_size ) __attribute__ (( may_alias ))
*result = ( ( void * ) result0 );
unsigned int i; unsigned int i;
unsigned int j; unsigned int j;
uint64_t multiplicand_element; uint64_t multiplicand_element;
@ -64,9 +68,9 @@ void bigint_multiply_raw ( const uint64_t *multiplicand0,
memset ( result, 0, sizeof ( *result ) ); memset ( result, 0, sizeof ( *result ) );
/* Multiply integers one element at a time */ /* Multiply integers one element at a time */
for ( i = 0 ; i < size ; i++ ) { for ( i = 0 ; i < multiplicand_size ; i++ ) {
multiplicand_element = multiplicand->element[i]; multiplicand_element = multiplicand->element[i];
for ( j = 0 ; j < size ; j++ ) { for ( j = 0 ; j < multiplier_size ; j++ ) {
multiplier_element = multiplier->element[j]; multiplier_element = multiplier->element[j];
result_elements = &result->element[ i + j ]; result_elements = &result->element[ i + j ];
/* Perform a single multiply, and add the /* Perform a single multiply, and add the
@ -75,7 +79,7 @@ void bigint_multiply_raw ( const uint64_t *multiplicand0,
* never overflow beyond the end of the * never overflow beyond the end of the
* result, since: * result, since:
* *
* a < 2^{n}, b < 2^{n} => ab < 2^{2n} * a < 2^{n}, b < 2^{m} => ab < 2^{n+m}
*/ */
__asm__ __volatile__ ( "mul.d %1, %6, %7\n\t" __asm__ __volatile__ ( "mul.d %1, %6, %7\n\t"
"mulh.du %2, %6, %7\n\t" "mulh.du %2, %6, %7\n\t"

View File

@ -330,7 +330,9 @@ bigint_done_raw ( const uint64_t *value0, unsigned int size __unused,
} }
extern void bigint_multiply_raw ( const uint64_t *multiplicand0, extern void bigint_multiply_raw ( const uint64_t *multiplicand0,
unsigned int multiplicand_size,
const uint64_t *multiplier0, const uint64_t *multiplier0,
uint64_t *value0, unsigned int size ); unsigned int multiplier_size,
uint64_t *value0 );
#endif /* _BITS_BIGINT_H */ #endif /* _BITS_BIGINT_H */

View File

@ -36,19 +36,23 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* Multiply big integers * Multiply big integers
* *
* @v multiplicand0 Element 0 of big integer to be multiplied * @v multiplicand0 Element 0 of big integer to be multiplied
* @v multiplicand_size Number of elements in multiplicand
* @v multiplier0 Element 0 of big integer to be multiplied * @v multiplier0 Element 0 of big integer to be multiplied
* @v multiplier_size Number of elements in multiplier
* @v result0 Element 0 of big integer to hold result * @v result0 Element 0 of big integer to hold result
* @v size Number of elements
*/ */
void bigint_multiply_raw ( const uint32_t *multiplicand0, void bigint_multiply_raw ( const uint32_t *multiplicand0,
unsigned int multiplicand_size,
const uint32_t *multiplier0, const uint32_t *multiplier0,
uint32_t *result0, unsigned int size ) { unsigned int multiplier_size,
const bigint_t ( size ) __attribute__ (( may_alias )) *multiplicand = uint32_t *result0 ) {
( ( const void * ) multiplicand0 ); unsigned int result_size = ( multiplicand_size + multiplier_size );
const bigint_t ( size ) __attribute__ (( may_alias )) *multiplier = const bigint_t ( multiplicand_size ) __attribute__ (( may_alias ))
( ( const void * ) multiplier0 ); *multiplicand = ( ( const void * ) multiplicand0 );
bigint_t ( size * 2 ) __attribute__ (( may_alias )) *result = const bigint_t ( multiplier_size ) __attribute__ (( may_alias ))
( ( void * ) result0 ); *multiplier = ( ( const void * ) multiplier0 );
bigint_t ( result_size ) __attribute__ (( may_alias ))
*result = ( ( void * ) result0 );
unsigned int i; unsigned int i;
unsigned int j; unsigned int j;
uint32_t multiplicand_element; uint32_t multiplicand_element;
@ -62,9 +66,9 @@ void bigint_multiply_raw ( const uint32_t *multiplicand0,
memset ( result, 0, sizeof ( *result ) ); memset ( result, 0, sizeof ( *result ) );
/* Multiply integers one element at a time */ /* Multiply integers one element at a time */
for ( i = 0 ; i < size ; i++ ) { for ( i = 0 ; i < multiplicand_size ; i++ ) {
multiplicand_element = multiplicand->element[i]; multiplicand_element = multiplicand->element[i];
for ( j = 0 ; j < size ; j++ ) { for ( j = 0 ; j < multiplier_size ; j++ ) {
multiplier_element = multiplier->element[j]; multiplier_element = multiplier->element[j];
result_elements = &result->element[ i + j ]; result_elements = &result->element[ i + j ];
/* Perform a single multiply, and add the /* Perform a single multiply, and add the
@ -73,7 +77,7 @@ void bigint_multiply_raw ( const uint32_t *multiplicand0,
* never overflow beyond the end of the * never overflow beyond the end of the
* result, since: * result, since:
* *
* a < 2^{n}, b < 2^{n} => ab < 2^{2n} * a < 2^{n}, b < 2^{m} => ab < 2^{n+m}
*/ */
__asm__ __volatile__ ( "mull %5\n\t" __asm__ __volatile__ ( "mull %5\n\t"
"addl %%eax, (%6,%2,4)\n\t" "addl %%eax, (%6,%2,4)\n\t"

View File

@ -323,7 +323,9 @@ bigint_done_raw ( const uint32_t *value0, unsigned int size __unused,
} }
extern void bigint_multiply_raw ( const uint32_t *multiplicand0, extern void bigint_multiply_raw ( const uint32_t *multiplicand0,
unsigned int multiplicand_size,
const uint32_t *multiplier0, const uint32_t *multiplier0,
uint32_t *value0, unsigned int size ); unsigned int multiplier_size,
uint32_t *value0 );
#endif /* _BITS_BIGINT_H */ #endif /* _BITS_BIGINT_H */

View File

@ -184,10 +184,11 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* @v result Big integer to hold result * @v result Big integer to hold result
*/ */
#define bigint_multiply( multiplicand, multiplier, result ) do { \ #define bigint_multiply( multiplicand, multiplier, result ) do { \
unsigned int size = bigint_size (multiplicand); \ unsigned int multiplicand_size = bigint_size (multiplicand); \
unsigned int multiplier_size = bigint_size (multiplier); \
bigint_multiply_raw ( (multiplicand)->element, \ bigint_multiply_raw ( (multiplicand)->element, \
(multiplier)->element, (result)->element, \ multiplicand_size, (multiplier)->element, \
size ); \ multiplier_size, (result)->element ); \
} while ( 0 ) } while ( 0 )
/** /**
@ -283,9 +284,10 @@ void bigint_shrink_raw ( const bigint_element_t *source0,
unsigned int source_size, bigint_element_t *dest0, unsigned int source_size, bigint_element_t *dest0,
unsigned int dest_size ); unsigned int dest_size );
void bigint_multiply_raw ( const bigint_element_t *multiplicand0, void bigint_multiply_raw ( const bigint_element_t *multiplicand0,
unsigned int multiplicand_size,
const bigint_element_t *multiplier0, const bigint_element_t *multiplier0,
bigint_element_t *result0, unsigned int multiplier_size,
unsigned int size ); bigint_element_t *result0 );
void bigint_mod_multiply_raw ( const bigint_element_t *multiplicand0, void bigint_mod_multiply_raw ( const bigint_element_t *multiplicand0,
const bigint_element_t *multiplier0, const bigint_element_t *multiplier0,
const bigint_element_t *modulus0, const bigint_element_t *modulus0,

View File

@ -150,15 +150,17 @@ void bigint_shrink_sample ( const bigint_element_t *source0,
} }
void bigint_multiply_sample ( const bigint_element_t *multiplicand0, void bigint_multiply_sample ( const bigint_element_t *multiplicand0,
unsigned int multiplicand_size,
const bigint_element_t *multiplier0, const bigint_element_t *multiplier0,
bigint_element_t *result0, unsigned int multiplier_size,
unsigned int size ) { bigint_element_t *result0 ) {
const bigint_t ( size ) *multiplicand __attribute__ (( may_alias )) unsigned int result_size = ( multiplicand_size + multiplier_size );
= ( ( const void * ) multiplicand0 ); const bigint_t ( multiplicand_size ) __attribute__ (( may_alias ))
const bigint_t ( size ) *multiplier __attribute__ (( may_alias )) *multiplicand = ( ( const void * ) multiplicand0 );
= ( ( const void * ) multiplier0 ); const bigint_t ( multiplier_size ) __attribute__ (( may_alias ))
bigint_t ( size * 2 ) *result __attribute__ (( may_alias )) *multiplier = ( ( const void * ) multiplier0 );
= ( ( void * ) result0 ); bigint_t ( result_size ) __attribute__ (( may_alias ))
*result = ( ( void * ) result0 );
bigint_multiply ( multiplicand, multiplier, result ); bigint_multiply ( multiplicand, multiplier, result );
} }
@ -430,17 +432,18 @@ void bigint_mod_exp_sample ( const bigint_element_t *base0,
static const uint8_t multiplier_raw[] = multiplier; \ static const uint8_t multiplier_raw[] = multiplier; \
static const uint8_t expected_raw[] = expected; \ static const uint8_t expected_raw[] = expected; \
uint8_t result_raw[ sizeof ( expected_raw ) ]; \ uint8_t result_raw[ sizeof ( expected_raw ) ]; \
unsigned int size = \ unsigned int multiplicand_size = \
bigint_required_size ( sizeof ( multiplicand_raw ) ); \ bigint_required_size ( sizeof ( multiplicand_raw ) ); \
bigint_t ( size ) multiplicand_temp; \ unsigned int multiplier_size = \
bigint_t ( size ) multiplier_temp; \ bigint_required_size ( sizeof ( multiplier_raw ) ); \
bigint_t ( size * 2 ) result_temp; \ bigint_t ( multiplicand_size ) multiplicand_temp; \
bigint_t ( multiplier_size ) multiplier_temp; \
bigint_t ( multiplicand_size + multiplier_size ) result_temp; \
{} /* Fix emacs alignment */ \ {} /* Fix emacs alignment */ \
\ \
assert ( bigint_size ( &multiplier_temp ) == \
bigint_size ( &multiplicand_temp ) ); \
assert ( bigint_size ( &result_temp ) == \ assert ( bigint_size ( &result_temp ) == \
( 2 * bigint_size ( &multiplicand_temp ) ) ); \ ( bigint_size ( &multiplicand_temp ) + \
bigint_size ( &multiplier_temp ) ) ); \
bigint_init ( &multiplicand_temp, multiplicand_raw, \ bigint_init ( &multiplicand_temp, multiplicand_raw, \
sizeof ( multiplicand_raw ) ); \ sizeof ( multiplicand_raw ) ); \
bigint_init ( &multiplier_temp, multiplier_raw, \ bigint_init ( &multiplier_temp, multiplier_raw, \
@ -1373,6 +1376,12 @@ static void bigint_test_exec ( void ) {
BIGINT ( 0x67, 0x3c, 0x5a, 0x16 ), BIGINT ( 0x67, 0x3c, 0x5a, 0x16 ),
BIGINT ( 0x3c, 0xdb, 0x7f, 0xae, 0x12, 0x7e, BIGINT ( 0x3c, 0xdb, 0x7f, 0xae, 0x12, 0x7e,
0xef, 0x16 ) ); 0xef, 0x16 ) );
bigint_multiply_ok ( BIGINT ( 0x39, 0x1f, 0xc8, 0x6a ),
BIGINT ( 0xba, 0x39, 0x4a, 0xb8, 0xac, 0xb3,
0x4f, 0x64, 0x28, 0x46, 0xa6, 0x99 ),
BIGINT ( 0x29, 0x8d, 0xe0, 0x5d, 0x08, 0xea,
0x0d, 0xc7, 0x82, 0x5d, 0xba, 0x96,
0x1c, 0xef, 0x83, 0x5a ) );
bigint_multiply_ok ( BIGINT ( 0xe8, 0x08, 0x0b, 0xe9, 0x29, 0x36, bigint_multiply_ok ( BIGINT ( 0xe8, 0x08, 0x0b, 0xe9, 0x29, 0x36,
0xea, 0x51, 0x1d, 0x75, 0x1a, 0xd5, 0xea, 0x51, 0x1d, 0x75, 0x1a, 0xd5,
0xba, 0xc6, 0xa0, 0xf3, 0x48, 0x5c, 0xba, 0xc6, 0xa0, 0xf3, 0x48, 0x5c,