mirror of
https://github.com/ipxe/ipxe
synced 2026-01-26 17:31:17 +03:00
[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>
This commit is contained in:
@@ -36,19 +36,23 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
* Multiply big integers
|
||||
*
|
||||
* @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 multiplier_size Number of elements in multiplier
|
||||
* @v result0 Element 0 of big integer to hold result
|
||||
* @v size Number of elements
|
||||
*/
|
||||
void bigint_multiply_raw ( const uint32_t *multiplicand0,
|
||||
unsigned int multiplicand_size,
|
||||
const uint32_t *multiplier0,
|
||||
uint32_t *result0, unsigned int size ) {
|
||||
const bigint_t ( size ) __attribute__ (( may_alias )) *multiplicand =
|
||||
( ( const void * ) multiplicand0 );
|
||||
const bigint_t ( size ) __attribute__ (( may_alias )) *multiplier =
|
||||
( ( const void * ) multiplier0 );
|
||||
bigint_t ( size * 2 ) __attribute__ (( may_alias )) *result =
|
||||
( ( void * ) result0 );
|
||||
unsigned int multiplier_size,
|
||||
uint32_t *result0 ) {
|
||||
unsigned int result_size = ( multiplicand_size + multiplier_size );
|
||||
const bigint_t ( multiplicand_size ) __attribute__ (( may_alias ))
|
||||
*multiplicand = ( ( const void * ) multiplicand0 );
|
||||
const bigint_t ( multiplier_size ) __attribute__ (( may_alias ))
|
||||
*multiplier = ( ( const void * ) multiplier0 );
|
||||
bigint_t ( result_size ) __attribute__ (( may_alias ))
|
||||
*result = ( ( void * ) result0 );
|
||||
unsigned int i;
|
||||
unsigned int j;
|
||||
uint32_t multiplicand_element;
|
||||
@@ -62,9 +66,9 @@ void bigint_multiply_raw ( const uint32_t *multiplicand0,
|
||||
memset ( result, 0, sizeof ( *result ) );
|
||||
|
||||
/* 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];
|
||||
for ( j = 0 ; j < size ; j++ ) {
|
||||
for ( j = 0 ; j < multiplier_size ; j++ ) {
|
||||
multiplier_element = multiplier->element[j];
|
||||
result_elements = &result->element[ i + j ];
|
||||
/* 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
|
||||
* 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"
|
||||
"ldr %3, [%0]\n\t"
|
||||
|
||||
@@ -310,7 +310,9 @@ bigint_done_raw ( const uint32_t *value0, unsigned int size __unused,
|
||||
}
|
||||
|
||||
extern void bigint_multiply_raw ( const uint32_t *multiplicand0,
|
||||
unsigned int multiplicand_size,
|
||||
const uint32_t *multiplier0,
|
||||
uint32_t *value0, unsigned int size );
|
||||
unsigned int multiplier_size,
|
||||
uint32_t *value0 );
|
||||
|
||||
#endif /* _BITS_BIGINT_H */
|
||||
|
||||
@@ -36,19 +36,23 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
* Multiply big integers
|
||||
*
|
||||
* @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 multiplier_size Number of elements in multiplier
|
||||
* @v result0 Element 0 of big integer to hold result
|
||||
* @v size Number of elements
|
||||
*/
|
||||
void bigint_multiply_raw ( const uint64_t *multiplicand0,
|
||||
unsigned int multiplicand_size,
|
||||
const uint64_t *multiplier0,
|
||||
uint64_t *result0, unsigned int size ) {
|
||||
const bigint_t ( size ) __attribute__ (( may_alias )) *multiplicand =
|
||||
( ( const void * ) multiplicand0 );
|
||||
const bigint_t ( size ) __attribute__ (( may_alias )) *multiplier =
|
||||
( ( const void * ) multiplier0 );
|
||||
bigint_t ( size * 2 ) __attribute__ (( may_alias )) *result =
|
||||
( ( void * ) result0 );
|
||||
unsigned int multiplier_size,
|
||||
uint64_t *result0 ) {
|
||||
unsigned int result_size = ( multiplicand_size + multiplier_size );
|
||||
const bigint_t ( multiplicand_size ) __attribute__ (( may_alias ))
|
||||
*multiplicand = ( ( const void * ) multiplicand0 );
|
||||
const bigint_t ( multiplier_size ) __attribute__ (( may_alias ))
|
||||
*multiplier = ( ( const void * ) multiplier0 );
|
||||
bigint_t ( result_size ) __attribute__ (( may_alias ))
|
||||
*result = ( ( void * ) result0 );
|
||||
unsigned int i;
|
||||
unsigned int j;
|
||||
uint64_t multiplicand_element;
|
||||
@@ -63,9 +67,9 @@ void bigint_multiply_raw ( const uint64_t *multiplicand0,
|
||||
memset ( result, 0, sizeof ( *result ) );
|
||||
|
||||
/* 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];
|
||||
for ( j = 0 ; j < size ; j++ ) {
|
||||
for ( j = 0 ; j < multiplier_size ; j++ ) {
|
||||
multiplier_element = multiplier->element[j];
|
||||
result_elements = &result->element[ i + j ];
|
||||
/* 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
|
||||
* 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"
|
||||
"umulh %2, %6, %7\n\t"
|
||||
|
||||
@@ -311,7 +311,9 @@ bigint_done_raw ( const uint64_t *value0, unsigned int size __unused,
|
||||
}
|
||||
|
||||
extern void bigint_multiply_raw ( const uint64_t *multiplicand0,
|
||||
unsigned int multiplicand_size,
|
||||
const uint64_t *multiplier0,
|
||||
uint64_t *value0, unsigned int size );
|
||||
unsigned int multiplier_size,
|
||||
uint64_t *value0 );
|
||||
|
||||
#endif /* _BITS_BIGINT_H */
|
||||
|
||||
@@ -37,19 +37,23 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
* Multiply big integers
|
||||
*
|
||||
* @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 multiplier_size Number of elements in multiplier
|
||||
* @v result0 Element 0 of big integer to hold result
|
||||
* @v size Number of elements
|
||||
*/
|
||||
void bigint_multiply_raw ( const uint64_t *multiplicand0,
|
||||
unsigned int multiplicand_size,
|
||||
const uint64_t *multiplier0,
|
||||
uint64_t *result0, unsigned int size ) {
|
||||
const bigint_t ( size ) __attribute__ (( may_alias )) *multiplicand =
|
||||
( ( const void * ) multiplicand0 );
|
||||
const bigint_t ( size ) __attribute__ (( may_alias )) *multiplier =
|
||||
( ( const void * ) multiplier0 );
|
||||
bigint_t ( size * 2 ) __attribute__ (( may_alias )) *result =
|
||||
( ( void * ) result0 );
|
||||
unsigned int multiplier_size,
|
||||
uint64_t *result0 ) {
|
||||
unsigned int result_size = ( multiplicand_size + multiplier_size );
|
||||
const bigint_t ( multiplicand_size ) __attribute__ (( may_alias ))
|
||||
*multiplicand = ( ( const void * ) multiplicand0 );
|
||||
const bigint_t ( multiplier_size ) __attribute__ (( may_alias ))
|
||||
*multiplier = ( ( const void * ) multiplier0 );
|
||||
bigint_t ( result_size ) __attribute__ (( may_alias ))
|
||||
*result = ( ( void * ) result0 );
|
||||
unsigned int i;
|
||||
unsigned int j;
|
||||
uint64_t multiplicand_element;
|
||||
@@ -64,9 +68,9 @@ void bigint_multiply_raw ( const uint64_t *multiplicand0,
|
||||
memset ( result, 0, sizeof ( *result ) );
|
||||
|
||||
/* 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];
|
||||
for ( j = 0 ; j < size ; j++ ) {
|
||||
for ( j = 0 ; j < multiplier_size ; j++ ) {
|
||||
multiplier_element = multiplier->element[j];
|
||||
result_elements = &result->element[ i + j ];
|
||||
/* 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
|
||||
* 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"
|
||||
"mulh.du %2, %6, %7\n\t"
|
||||
|
||||
@@ -330,7 +330,9 @@ bigint_done_raw ( const uint64_t *value0, unsigned int size __unused,
|
||||
}
|
||||
|
||||
extern void bigint_multiply_raw ( const uint64_t *multiplicand0,
|
||||
unsigned int multiplicand_size,
|
||||
const uint64_t *multiplier0,
|
||||
uint64_t *value0, unsigned int size );
|
||||
unsigned int multiplier_size,
|
||||
uint64_t *value0 );
|
||||
|
||||
#endif /* _BITS_BIGINT_H */
|
||||
|
||||
@@ -36,19 +36,23 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
* Multiply big integers
|
||||
*
|
||||
* @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 multiplier_size Number of elements in multiplier
|
||||
* @v result0 Element 0 of big integer to hold result
|
||||
* @v size Number of elements
|
||||
*/
|
||||
void bigint_multiply_raw ( const uint32_t *multiplicand0,
|
||||
unsigned int multiplicand_size,
|
||||
const uint32_t *multiplier0,
|
||||
uint32_t *result0, unsigned int size ) {
|
||||
const bigint_t ( size ) __attribute__ (( may_alias )) *multiplicand =
|
||||
( ( const void * ) multiplicand0 );
|
||||
const bigint_t ( size ) __attribute__ (( may_alias )) *multiplier =
|
||||
( ( const void * ) multiplier0 );
|
||||
bigint_t ( size * 2 ) __attribute__ (( may_alias )) *result =
|
||||
( ( void * ) result0 );
|
||||
unsigned int multiplier_size,
|
||||
uint32_t *result0 ) {
|
||||
unsigned int result_size = ( multiplicand_size + multiplier_size );
|
||||
const bigint_t ( multiplicand_size ) __attribute__ (( may_alias ))
|
||||
*multiplicand = ( ( const void * ) multiplicand0 );
|
||||
const bigint_t ( multiplier_size ) __attribute__ (( may_alias ))
|
||||
*multiplier = ( ( const void * ) multiplier0 );
|
||||
bigint_t ( result_size ) __attribute__ (( may_alias ))
|
||||
*result = ( ( void * ) result0 );
|
||||
unsigned int i;
|
||||
unsigned int j;
|
||||
uint32_t multiplicand_element;
|
||||
@@ -62,9 +66,9 @@ void bigint_multiply_raw ( const uint32_t *multiplicand0,
|
||||
memset ( result, 0, sizeof ( *result ) );
|
||||
|
||||
/* 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];
|
||||
for ( j = 0 ; j < size ; j++ ) {
|
||||
for ( j = 0 ; j < multiplier_size ; j++ ) {
|
||||
multiplier_element = multiplier->element[j];
|
||||
result_elements = &result->element[ i + j ];
|
||||
/* 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
|
||||
* 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"
|
||||
"addl %%eax, (%6,%2,4)\n\t"
|
||||
|
||||
@@ -323,7 +323,9 @@ bigint_done_raw ( const uint32_t *value0, unsigned int size __unused,
|
||||
}
|
||||
|
||||
extern void bigint_multiply_raw ( const uint32_t *multiplicand0,
|
||||
unsigned int multiplicand_size,
|
||||
const uint32_t *multiplier0,
|
||||
uint32_t *value0, unsigned int size );
|
||||
unsigned int multiplier_size,
|
||||
uint32_t *value0 );
|
||||
|
||||
#endif /* _BITS_BIGINT_H */
|
||||
|
||||
Reference in New Issue
Block a user