[crypto] Expose carry flag from big integer addition and subtraction

Expose the effective carry (or borrow) out flag from big integer
addition and subtraction, and use this to elide an explicit bit test
when performing x25519 reduction.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2024-11-26 12:53:01 +00:00
parent da6da6eb3b
commit 167a08f089
8 changed files with 140 additions and 85 deletions

View File

@@ -43,8 +43,9 @@ bigint_init_raw ( uint32_t *value0, unsigned int size,
* @v addend0 Element 0 of big integer to add
* @v value0 Element 0 of big integer to be added to
* @v size Number of elements
* @ret carry Carry out
*/
static inline __attribute__ (( always_inline )) void
static inline __attribute__ (( always_inline )) int
bigint_add_raw ( const uint32_t *addend0, uint32_t *value0,
unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
@@ -54,8 +55,9 @@ bigint_add_raw ( const uint32_t *addend0, uint32_t *value0,
uint32_t *discard_end;
uint32_t discard_addend_i;
uint32_t discard_value_i;
int carry;
__asm__ __volatile__ ( "adds %2, %0, %8, lsl #2\n\t" /* clear CF */
__asm__ __volatile__ ( "adds %2, %0, %9, lsl #2\n\t" /* clear CF */
"\n1:\n\t"
"ldmia %0!, {%3}\n\t"
"ldr %4, [%1]\n\t"
@@ -68,9 +70,11 @@ bigint_add_raw ( const uint32_t *addend0, uint32_t *value0,
"=l" ( discard_end ),
"=l" ( discard_addend_i ),
"=l" ( discard_value_i ),
"=@cccs" ( carry ),
"+m" ( *value )
: "0" ( addend0 ), "1" ( value0 ), "l" ( size )
: "cc" );
: "0" ( addend0 ), "1" ( value0 ),
"l" ( size ) );
return carry;
}
/**
@@ -79,8 +83,9 @@ bigint_add_raw ( const uint32_t *addend0, uint32_t *value0,
* @v subtrahend0 Element 0 of big integer to subtract
* @v value0 Element 0 of big integer to be subtracted from
* @v size Number of elements
* @ret borrow Borrow out
*/
static inline __attribute__ (( always_inline )) void
static inline __attribute__ (( always_inline )) int
bigint_subtract_raw ( const uint32_t *subtrahend0, uint32_t *value0,
unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
@@ -90,8 +95,9 @@ bigint_subtract_raw ( const uint32_t *subtrahend0, uint32_t *value0,
uint32_t *discard_end;
uint32_t discard_subtrahend_i;
uint32_t discard_value_i;
int borrow;
__asm__ __volatile__ ( "add %2, %0, %8, lsl #2\n\t"
__asm__ __volatile__ ( "add %2, %0, %9, lsl #2\n\t"
"cmp %2, %0\n\t" /* set CF */
"\n1:\n\t"
"ldmia %0!, {%3}\n\t"
@@ -105,10 +111,11 @@ bigint_subtract_raw ( const uint32_t *subtrahend0, uint32_t *value0,
"=l" ( discard_end ),
"=l" ( discard_subtrahend_i ),
"=l" ( discard_value_i ),
"=@cccc" ( borrow ),
"+m" ( *value )
: "0" ( subtrahend0 ), "1" ( value0 ),
"l" ( size )
: "cc" );
"l" ( size ) );
return borrow;
}
/**

View File

@@ -43,8 +43,9 @@ bigint_init_raw ( uint64_t *value0, unsigned int size,
* @v addend0 Element 0 of big integer to add
* @v value0 Element 0 of big integer to be added to
* @v size Number of elements
* @ret carry Carry out
*/
static inline __attribute__ (( always_inline )) void
static inline __attribute__ (( always_inline )) int
bigint_add_raw ( const uint64_t *addend0, uint64_t *value0,
unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
@@ -54,6 +55,7 @@ bigint_add_raw ( const uint64_t *addend0, uint64_t *value0,
uint64_t discard_addend_i;
uint64_t discard_value_i;
unsigned int discard_size;
int carry;
__asm__ __volatile__ ( "cmn xzr, xzr\n\t" /* clear CF */
"\n1:\n\t"
@@ -68,9 +70,11 @@ bigint_add_raw ( const uint64_t *addend0, uint64_t *value0,
"=r" ( discard_size ),
"=r" ( discard_addend_i ),
"=r" ( discard_value_i ),
"=@cccs" ( carry ),
"+m" ( *value )
: "0" ( addend0 ), "1" ( value0 ), "2" ( size )
: "cc" );
: "0" ( addend0 ), "1" ( value0 ),
"2" ( size ) );
return carry;
}
/**
@@ -79,8 +83,9 @@ bigint_add_raw ( const uint64_t *addend0, uint64_t *value0,
* @v subtrahend0 Element 0 of big integer to subtract
* @v value0 Element 0 of big integer to be subtracted from
* @v size Number of elements
* @ret borrow Borrow out
*/
static inline __attribute__ (( always_inline )) void
static inline __attribute__ (( always_inline )) int
bigint_subtract_raw ( const uint64_t *subtrahend0, uint64_t *value0,
unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
@@ -90,6 +95,7 @@ bigint_subtract_raw ( const uint64_t *subtrahend0, uint64_t *value0,
uint64_t discard_subtrahend_i;
uint64_t discard_value_i;
unsigned int discard_size;
int borrow;
__asm__ __volatile__ ( "cmp xzr, xzr\n\t" /* set CF */
"\n1:\n\t"
@@ -104,10 +110,11 @@ bigint_subtract_raw ( const uint64_t *subtrahend0, uint64_t *value0,
"=r" ( discard_size ),
"=r" ( discard_subtrahend_i ),
"=r" ( discard_value_i ),
"=@cccc" ( borrow ),
"+m" ( *value )
: "0" ( subtrahend0 ), "1" ( value0 ),
"2" ( size )
: "cc" );
"2" ( size ) );
return borrow;
}
/**

View File

@@ -43,8 +43,9 @@ bigint_init_raw ( uint64_t *value0, unsigned int size,
* @v addend0 Element 0 of big integer to add
* @v value0 Element 0 of big integer to be added to
* @v size Number of elements
* @ret carry Carry out
*/
static inline __attribute__ (( always_inline )) void
static inline __attribute__ (( always_inline )) int
bigint_add_raw ( const uint64_t *addend0, uint64_t *value0,
unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
@@ -53,20 +54,20 @@ bigint_add_raw ( const uint64_t *addend0, uint64_t *value0,
uint64_t *discard_value;
uint64_t discard_addend_i;
uint64_t discard_value_i;
uint64_t discard_carry;
uint64_t discard_temp;
unsigned int discard_size;
uint64_t carry;
__asm__ __volatile__ ( "\n1:\n\t"
/* Load addend[i] and value[i] */
"ld.d %3, %0, 0\n\t"
"ld.d %4, %1, 0\n\t"
/* Add carry flag and addend */
"add.d %4, %4, %5\n\t"
"sltu %6, %4, %5\n\t"
"add.d %4, %4, %6\n\t"
"sltu %5, %4, %6\n\t"
"add.d %4, %4, %3\n\t"
"sltu %5, %4, %3\n\t"
"or %5, %5, %6\n\t"
"sltu %6, %4, %3\n\t"
"or %6, %5, %6\n\t"
/* Store value[i] */
"st.d %4, %1, 0\n\t"
/* Loop */
@@ -79,11 +80,12 @@ bigint_add_raw ( const uint64_t *addend0, uint64_t *value0,
"=r" ( discard_size ),
"=r" ( discard_addend_i ),
"=r" ( discard_value_i ),
"=r" ( discard_carry ),
"=r" ( discard_temp ),
"=r" ( carry ),
"+m" ( *value )
: "0" ( addend0 ), "1" ( value0 ),
"2" ( size ), "5" ( 0 ) );
"2" ( size ), "6" ( 0 ) );
return carry;
}
/**
@@ -92,8 +94,9 @@ bigint_add_raw ( const uint64_t *addend0, uint64_t *value0,
* @v subtrahend0 Element 0 of big integer to subtract
* @v value0 Element 0 of big integer to be subtracted from
* @v size Number of elements
* @ret borrow Borrow out
*/
static inline __attribute__ (( always_inline )) void
static inline __attribute__ (( always_inline )) int
bigint_subtract_raw ( const uint64_t *subtrahend0, uint64_t *value0,
unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
@@ -102,20 +105,20 @@ bigint_subtract_raw ( const uint64_t *subtrahend0, uint64_t *value0,
uint64_t *discard_value;
uint64_t discard_subtrahend_i;
uint64_t discard_value_i;
uint64_t discard_carry;
uint64_t discard_temp;
unsigned int discard_size;
uint64_t borrow;
__asm__ __volatile__ ( "\n1:\n\t"
/* Load subtrahend[i] and value[i] */
"ld.d %3, %0, 0\n\t"
"ld.d %4, %1, 0\n\t"
/* Subtract carry flag and subtrahend */
"sltu %6, %4, %5\n\t"
"sub.d %4, %4, %5\n\t"
"sltu %5, %4, %3\n\t"
"sltu %5, %4, %6\n\t"
"sub.d %4, %4, %6\n\t"
"sltu %6, %4, %3\n\t"
"sub.d %4, %4, %3\n\t"
"or %5, %5, %6\n\t"
"or %6, %5, %6\n\t"
/* Store value[i] */
"st.d %4, %1, 0\n\t"
/* Loop */
@@ -128,11 +131,12 @@ bigint_subtract_raw ( const uint64_t *subtrahend0, uint64_t *value0,
"=r" ( discard_size ),
"=r" ( discard_subtrahend_i ),
"=r" ( discard_value_i ),
"=r" ( discard_carry ),
"=r" ( discard_temp ),
"=r" ( borrow ),
"+m" ( *value )
: "0" ( subtrahend0 ), "1" ( value0 ),
"2" ( size ), "5" ( 0 ) );
"2" ( size ), "6" ( 0 ) );
return borrow;
}
/**

View File

@@ -43,8 +43,9 @@ bigint_init_raw ( unsigned long *value0, unsigned int size,
* @v addend0 Element 0 of big integer to add
* @v value0 Element 0 of big integer to be added to
* @v size Number of elements
* @ret carry Carry out
*/
static inline __attribute__ (( always_inline )) void
static inline __attribute__ (( always_inline )) int
bigint_add_raw ( const unsigned long *addend0, unsigned long *value0,
unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
@@ -54,19 +55,19 @@ bigint_add_raw ( const unsigned long *addend0, unsigned long *value0,
unsigned long *discard_value;
unsigned long discard_addend_i;
unsigned long discard_value_i;
unsigned long discard_carry;
unsigned long discard_temp;
unsigned long carry;
__asm__ __volatile__ ( "\n1:\n\t"
/* Load addend[i] and value[i] */
LOADN " %2, (%0)\n\t"
LOADN " %3, (%1)\n\t"
/* Add carry flag and addend */
"add %3, %3, %4\n\t"
"sltu %5, %3, %4\n\t"
"add %3, %3, %5\n\t"
"sltu %4, %3, %5\n\t"
"add %3, %3, %2\n\t"
"sltu %4, %3, %2\n\t"
"or %4, %4, %5\n\t"
"sltu %5, %3, %2\n\t"
"or %5, %4, %5\n\t"
/* Store value[i] */
STOREN " %3, (%1)\n\t"
/* Loop */
@@ -77,12 +78,13 @@ bigint_add_raw ( const unsigned long *addend0, unsigned long *value0,
"=&r" ( discard_value ),
"=&r" ( discard_addend_i ),
"=&r" ( discard_value_i ),
"=&r" ( discard_carry ),
"=&r" ( discard_temp ),
"=&r" ( carry ),
"+m" ( *value )
: "r" ( valueN ),
"i" ( sizeof ( unsigned long ) ),
"0" ( addend0 ), "1" ( value0 ), "4" ( 0 ) );
"0" ( addend0 ), "1" ( value0 ), "5" ( 0 ) );
return carry;
}
/**
@@ -91,8 +93,9 @@ bigint_add_raw ( const unsigned long *addend0, unsigned long *value0,
* @v subtrahend0 Element 0 of big integer to subtract
* @v value0 Element 0 of big integer to be subtracted from
* @v size Number of elements
* @ret borrow Borrow out
*/
static inline __attribute__ (( always_inline )) void
static inline __attribute__ (( always_inline )) int
bigint_subtract_raw ( const unsigned long *subtrahend0, unsigned long *value0,
unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
@@ -102,19 +105,19 @@ bigint_subtract_raw ( const unsigned long *subtrahend0, unsigned long *value0,
unsigned long *discard_value;
unsigned long discard_subtrahend_i;
unsigned long discard_value_i;
unsigned long discard_carry;
unsigned long discard_temp;
unsigned long borrow;
__asm__ __volatile__ ( "\n1:\n\t"
/* Load subtrahend[i] and value[i] */
LOADN " %2, (%0)\n\t"
LOADN " %3, (%1)\n\t"
/* Subtract carry flag and subtrahend */
"sltu %5, %3, %4\n\t"
"sub %3, %3, %4\n\t"
"sltu %4, %3, %2\n\t"
"sltu %4, %3, %5\n\t"
"sub %3, %3, %5\n\t"
"sltu %5, %3, %2\n\t"
"sub %3, %3, %2\n\t"
"or %4, %4, %5\n\t"
"or %5, %5, %4\n\t"
/* Store value[i] */
STOREN " %3, (%1)\n\t"
/* Loop */
@@ -125,13 +128,14 @@ bigint_subtract_raw ( const unsigned long *subtrahend0, unsigned long *value0,
"=&r" ( discard_value ),
"=&r" ( discard_subtrahend_i ),
"=&r" ( discard_value_i ),
"=&r" ( discard_carry ),
"=&r" ( discard_temp ),
"=&r" ( borrow ),
"+m" ( *value )
: "r" ( valueN ),
"i" ( sizeof ( unsigned long ) ),
"0" ( subtrahend0 ), "1" ( value0 ),
"4" ( 0 ) );
"5" ( 0 ) );
return borrow;
}
/**

View File

@@ -52,8 +52,9 @@ bigint_init_raw ( uint32_t *value0, unsigned int size,
* @v addend0 Element 0 of big integer to add
* @v value0 Element 0 of big integer to be added to
* @v size Number of elements
* @ret carry Carry flag
*/
static inline __attribute__ (( always_inline )) void
static inline __attribute__ (( always_inline )) int
bigint_add_raw ( const uint32_t *addend0, uint32_t *value0,
unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
@@ -61,17 +62,20 @@ bigint_add_raw ( const uint32_t *addend0, uint32_t *value0,
long index;
void *discard_S;
long discard_c;
int carry;
__asm__ __volatile__ ( "xor %0, %0\n\t" /* Zero %0 and clear CF */
"\n1:\n\t"
"lodsl\n\t"
"adcl %%eax, (%4,%0,4)\n\t"
"adcl %%eax, (%5,%0,4)\n\t"
"inc %0\n\t" /* Does not affect CF */
"loop 1b\n\t"
: "=&r" ( index ), "=&S" ( discard_S ),
"=&c" ( discard_c ), "+m" ( *value )
"=&c" ( discard_c ), "=@ccc" ( carry ),
"+m" ( *value )
: "r" ( value0 ), "1" ( addend0 ), "2" ( size )
: "eax" );
return carry;
}
/**
@@ -80,8 +84,9 @@ bigint_add_raw ( const uint32_t *addend0, uint32_t *value0,
* @v subtrahend0 Element 0 of big integer to subtract
* @v value0 Element 0 of big integer to be subtracted from
* @v size Number of elements
* @ret borrow Borrow flag
*/
static inline __attribute__ (( always_inline )) void
static inline __attribute__ (( always_inline )) int
bigint_subtract_raw ( const uint32_t *subtrahend0, uint32_t *value0,
unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
@@ -89,18 +94,21 @@ bigint_subtract_raw ( const uint32_t *subtrahend0, uint32_t *value0,
long index;
void *discard_S;
long discard_c;
int borrow;
__asm__ __volatile__ ( "xor %0, %0\n\t" /* Zero %0 and clear CF */
"\n1:\n\t"
"lodsl\n\t"
"sbbl %%eax, (%4,%0,4)\n\t"
"sbbl %%eax, (%5,%0,4)\n\t"
"inc %0\n\t" /* Does not affect CF */
"loop 1b\n\t"
: "=&r" ( index ), "=&S" ( discard_S ),
"=&c" ( discard_c ), "+m" ( *value )
"=&c" ( discard_c ), "=@ccc" ( borrow ),
"+m" ( *value )
: "r" ( value0 ), "1" ( subtrahend0 ),
"2" ( size )
: "eax" );
return borrow;
}
/**