iPXE
bigint.c File Reference

Big integer support. More...

#include <stdint.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include <ipxe/bigint.h>

Go to the source code of this file.

Macros

#define BIGINT_NTOA_LSB_MIN   16
 Minimum number of least significant bytes included in transcription.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 FILE_SECBOOT (PERMITTED)
const char * bigint_ntoa_raw (const bigint_element_t *value0, unsigned int size)
 Transcribe big integer (for debugging)
void bigint_swap_raw (bigint_element_t *first0, bigint_element_t *second0, unsigned int size, int swap)
 Conditionally swap big integers (in constant time)
void bigint_multiply_raw (const bigint_element_t *multiplicand0, unsigned int multiplicand_size, const bigint_element_t *multiplier0, unsigned int multiplier_size, bigint_element_t *result0)
 Multiply big integers.
void bigint_reduce_raw (const bigint_element_t *modulus0, bigint_element_t *result0, unsigned int size)
 Reduce big integer R^2 modulo N.
void bigint_mod_invert_raw (const bigint_element_t *invertend0, bigint_element_t *inverse0, unsigned int size)
 Compute inverse of odd big integer modulo any power of two.
int bigint_montgomery_relaxed_raw (const bigint_element_t *modulus0, bigint_element_t *value0, bigint_element_t *result0, unsigned int size)
 Perform relaxed Montgomery reduction (REDC) of a big integer.
void bigint_montgomery_raw (const bigint_element_t *modulus0, bigint_element_t *value0, bigint_element_t *result0, unsigned int size)
 Perform classic Montgomery reduction (REDC) of a big integer.
void bigint_ladder_raw (bigint_element_t *result0, bigint_element_t *multiple0, unsigned int size, const bigint_element_t *exponent0, unsigned int exponent_size, bigint_ladder_op_t *op, const void *ctx, void *tmp)
 Perform generalised exponentiation via a Montgomery ladder.
void bigint_mod_exp_ladder (const bigint_element_t *multiplier0, bigint_element_t *result0, unsigned int size, const void *ctx, void *tmp)
 Perform modular multiplication as part of a Montgomery ladder.
void bigint_mod_exp_raw (const bigint_element_t *base0, const bigint_element_t *modulus0, const bigint_element_t *exponent0, bigint_element_t *result0, unsigned int size, unsigned int exponent_size, void *tmp)
 Perform modular exponentiation of big integers.

Detailed Description

Big integer support.

Definition in file bigint.c.

Macro Definition Documentation

◆ BIGINT_NTOA_LSB_MIN

#define BIGINT_NTOA_LSB_MIN   16

Minimum number of least significant bytes included in transcription.

Definition at line 39 of file bigint.c.

Referenced by bigint_ntoa_raw().

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ bigint_ntoa_raw()

const char * bigint_ntoa_raw ( const bigint_element_t * value0,
unsigned int size )

Transcribe big integer (for debugging)

Parameters
value0Element 0 of big integer to be transcribed
sizeNumber of elements
Return values
stringBig integer in string form (may be abbreviated)

Definition at line 48 of file bigint.c.

49 {
50 const bigint_t ( size ) __attribute__ (( may_alias ))
51 *value = ( ( const void * ) value0 );
53 static char buf[256];
54 unsigned int count;
55 int threshold;
57 char *tmp;
58 int i;
59
60 /* Calculate abbreviation threshold, if any */
61 count = ( size * sizeof ( element ) );
62 threshold = count;
63 if ( count >= ( ( sizeof ( buf ) - 1 /* NUL */ ) / 2 /* "xx" */ ) ) {
64 threshold -= ( ( sizeof ( buf ) - 3 /* "..." */
65 - ( BIGINT_NTOA_LSB_MIN * 2 /* "xx" */ )
66 - 1 /* NUL */ ) / 2 /* "xx" */ );
67 }
68
69 /* Transcribe bytes, abbreviating with "..." if necessary */
70 for ( tmp = buf, i = ( count - 1 ) ; i >= 0 ; i-- ) {
71 element = value->element[ i / sizeof ( element ) ];
72 byte = ( element >> ( 8 * ( i % sizeof ( element ) ) ) );
73 tmp += sprintf ( tmp, "%02x", byte );
74 if ( i == threshold ) {
75 tmp += sprintf ( tmp, "..." );
77 }
78 }
79 assert ( tmp < ( buf + sizeof ( buf ) ) );
80
81 return buf;
82}
pseudo_bit_t value[0x00020]
Definition arbel.h:2
unsigned char uint8_t
Definition stdint.h:10
uint32_t bigint_element_t
Element of a big integer.
Definition bigint.h:16
static uint32_t * value0
Definition bigint.h:61
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
#define BIGINT_NTOA_LSB_MIN
Minimum number of least significant bytes included in transcription.
Definition bigint.c:39
uint16_t size
Buffer size.
Definition dwmac.h:3
static unsigned int count
Number of entries.
Definition dwmac.h:220
#define __attribute__(x)
Definition compiler.h:10
value element[index]
Definition bigint.h:398
#define bigint_t(size)
Define a big-integer type.
Definition bigint.h:20
unsigned long tmp
Definition linux_pci.h:65
unsigned char byte
Definition smc9000.h:38
#define sprintf(buf, fmt,...)
Write a formatted string to a buffer.
Definition stdio.h:37

References __attribute__, assert, BIGINT_NTOA_LSB_MIN, bigint_t, count, element, size, sprintf, tmp, value, and value0.

◆ bigint_swap_raw()

void bigint_swap_raw ( bigint_element_t * first0,
bigint_element_t * second0,
unsigned int size,
int swap )

Conditionally swap big integers (in constant time)

Parameters
first0Element 0 of big integer to be conditionally swapped
second0Element 0 of big integer to be conditionally swapped
sizeNumber of elements in big integers
swapSwap first and second big integers

Definition at line 92 of file bigint.c.

93 {
96 unsigned int i;
97
98 /* Construct mask */
99 mask = ( ( bigint_element_t ) ( ! swap ) - 1 );
100
101 /* Conditionally swap elements */
102 for ( i = 0 ; i < size ; i++ ) {
103 xor = ( mask & ( first0[i] ^ second0[i] ) );
104 first0[i] ^= xor;
105 second0[i] ^= xor;
106 }
107}
static u32 xor(u32 a, u32 b)
Definition tlan.h:457

References size, and xor().

◆ bigint_multiply_raw()

void bigint_multiply_raw ( const bigint_element_t * multiplicand0,
unsigned int multiplicand_size,
const bigint_element_t * multiplier0,
unsigned int multiplier_size,
bigint_element_t * result0 )

Multiply big integers.

Parameters
multiplicand0Element 0 of big integer to be multiplied
multiplicand_sizeNumber of elements in multiplicand
multiplier0Element 0 of big integer to be multiplied
multiplier_sizeNumber of elements in multiplier
result0Element 0 of big integer to hold result

Definition at line 118 of file bigint.c.

122 {
123 unsigned int result_size = ( multiplicand_size + multiplier_size );
124 const bigint_t ( multiplicand_size ) __attribute__ (( may_alias ))
125 *multiplicand = ( ( const void * ) multiplicand0 );
126 const bigint_t ( multiplier_size ) __attribute__ (( may_alias ))
127 *multiplier = ( ( const void * ) multiplier0 );
128 bigint_t ( result_size ) __attribute__ (( may_alias ))
129 *result = ( ( void * ) result0 );
130 bigint_element_t multiplicand_element;
131 const bigint_element_t *multiplier_element;
132 bigint_element_t *result_element;
133 bigint_element_t carry_element;
134 unsigned int i;
135 unsigned int j;
136
137 /* Zero required portion of result
138 *
139 * All elements beyond the length of the multiplier will be
140 * written before they are read, and so do not need to be
141 * zeroed in advance.
142 */
143 memset ( result, 0, sizeof ( *multiplier ) );
144
145 /* Multiply integers one element at a time, adding the low
146 * half of the double-element product directly into the
147 * result, and maintaining a running single-element carry.
148 *
149 * The running carry can never overflow beyond a single
150 * element. At each step, the calculation we perform is:
151 *
152 * carry:result[i+j] := ( ( multiplicand[i] * multiplier[j] )
153 * + result[i+j] + carry )
154 *
155 * The maximum value (for n-bit elements) is therefore:
156 *
157 * (2^n - 1)*(2^n - 1) + (2^n - 1) + (2^n - 1) = 2^(2n) - 1
158 *
159 * This is precisely the maximum value for a 2n-bit integer,
160 * and so the carry out remains within the range of an n-bit
161 * integer, i.e. a single element.
162 */
163 for ( i = 0 ; i < multiplicand_size ; i++ ) {
164 multiplicand_element = multiplicand->element[i];
165 multiplier_element = &multiplier->element[0];
166 result_element = &result->element[i];
167 carry_element = 0;
168 for ( j = 0 ; j < multiplier_size ; j++ ) {
169 bigint_multiply_one ( multiplicand_element,
170 *(multiplier_element++),
171 result_element++,
172 &carry_element );
173 }
174 *result_element = carry_element;
175 }
176}
uint16_t result
Definition hyperv.h:33
static const uint32_t multiplier
Port multiplier number.
Definition bigint.h:335
void bigint_multiply_one(const bigint_element_t multiplicand, const bigint_element_t multiplier, bigint_element_t *result, bigint_element_t *carry)
void * memset(void *dest, int character, size_t len) __nonnull

References __attribute__, bigint_multiply_one(), bigint_t, memset(), multiplier, and result.

◆ bigint_reduce_raw()

void bigint_reduce_raw ( const bigint_element_t * modulus0,
bigint_element_t * result0,
unsigned int size )

Reduce big integer R^2 modulo N.

Parameters
modulus0Element 0 of big integer modulus
result0Element 0 of big integer to hold result
sizeNumber of elements in modulus and result

Reduce the value R^2 modulo N, where R=2^n and n is the number of bits in the representation of the modulus N, including any leading zero bits.

Definition at line 189 of file bigint.c.

190 {
191 const bigint_t ( size ) __attribute__ (( may_alias ))
192 *modulus = ( ( const void * ) modulus0 );
193 bigint_t ( size ) __attribute__ (( may_alias ))
194 *result = ( ( void * ) result0 );
195 const unsigned int width = ( 8 * sizeof ( bigint_element_t ) );
196 unsigned int shift;
197 int max;
198 int sign;
199 int msb;
200 int carry;
201
202 /* We have the constants:
203 *
204 * N = modulus
205 *
206 * n = number of bits in the modulus (including any leading zeros)
207 *
208 * R = 2^n
209 *
210 * Let r be the extension of the n-bit result register by a
211 * separate two's complement sign bit, such that -R <= r < R,
212 * and define:
213 *
214 * x = r * 2^k
215 *
216 * as the value being reduced modulo N, where k is a
217 * non-negative integer bit shift.
218 *
219 * We want to reduce the initial value R^2=2^(2n), which we
220 * may trivially represent using r=1 and k=2n.
221 *
222 * We then iterate over decrementing k, maintaining the loop
223 * invariant:
224 *
225 * -N <= r < N
226 *
227 * On each iteration we must first double r, to compensate for
228 * having decremented k:
229 *
230 * k' = k - 1
231 *
232 * r' = 2r
233 *
234 * x = r * 2^k = 2r * 2^(k-1) = r' * 2^k'
235 *
236 * Note that doubling the n-bit result register will create a
237 * value of n+1 bits: this extra bit needs to be handled
238 * separately during the calculation.
239 *
240 * We then subtract N (if r is currently non-negative) or add
241 * N (if r is currently negative) to restore the loop
242 * invariant:
243 *
244 * 0 <= r < N => r" = 2r - N => -N <= r" < N
245 * -N <= r < 0 => r" = 2r + N => -N <= r" < N
246 *
247 * Note that since N may use all n bits, the most significant
248 * bit of the n-bit result register is not a valid two's
249 * complement sign bit for r: the extra sign bit therefore
250 * also needs to be handled separately.
251 *
252 * Once we reach k=0, we have x=r and therefore:
253 *
254 * -N <= x < N
255 *
256 * After this last loop iteration (with k=0), we may need to
257 * add a single multiple of N to ensure that x is positive,
258 * i.e. lies within the range 0 <= x < N.
259 *
260 * Since neither the modulus nor the value R^2 are secret, we
261 * may elide approximately half of the total number of
262 * iterations by constructing the initial representation of
263 * R^2 as r=2^m and k=2n-m (for some m such that 2^m < N).
264 */
265
266 /* Initialise x=R^2 */
267 memset ( result, 0, sizeof ( *result ) );
268 max = ( bigint_max_set_bit ( modulus ) - 2 );
269 if ( max < 0 ) {
270 /* Degenerate case of N=0 or N=1: return a zero result */
271 return;
272 }
274 shift = ( ( 2 * size * width ) - max );
275 sign = 0;
276
277 /* Iterate as described above */
278 while ( shift-- ) {
279
280 /* Calculate 2r, storing extra bit separately */
281 msb = bigint_shl ( result );
282
283 /* Add or subtract N according to current sign */
284 if ( sign ) {
285 carry = bigint_add ( modulus, result );
286 } else {
287 carry = bigint_subtract ( modulus, result );
288 }
289
290 /* Calculate new sign of result
291 *
292 * We know the result lies in the range -N <= r < N
293 * and so the tuple (old sign, msb, carry) cannot ever
294 * take the values (0, 1, 0) or (1, 0, 0). We can
295 * therefore treat these as don't-care inputs, which
296 * allows us to simplify the boolean expression by
297 * ignoring the old sign completely.
298 */
299 assert ( ( sign == msb ) || carry );
300 sign = ( msb ^ carry );
301 }
302
303 /* Add N to make result positive if necessary */
304 if ( sign )
305 bigint_add ( modulus, result );
306
307 /* Sanity check */
308 assert ( ! bigint_is_geq ( result, modulus ) );
309}
int carry
Definition bigint.h:68
#define max(x, y)
Definition ath.h:41
#define bigint_set_bit(value, bit)
Set bit in big integer.
Definition bigint.h:156
#define bigint_shl(value)
Shift big integer left.
Definition bigint.h:111
#define bigint_subtract(subtrahend, value)
Subtract big integers.
Definition bigint.h:99
#define bigint_max_set_bit(value)
Find highest bit set in big integer.
Definition bigint.h:199
#define bigint_is_geq(value, reference)
Compare big integers.
Definition bigint.h:145
#define bigint_add(addend, value)
Add big integers.
Definition bigint.h:87

References __attribute__, assert, bigint_add, bigint_is_geq, bigint_max_set_bit, bigint_set_bit, bigint_shl, bigint_subtract, bigint_t, carry, max, memset(), result, and size.

◆ bigint_mod_invert_raw()

void bigint_mod_invert_raw ( const bigint_element_t * invertend0,
bigint_element_t * inverse0,
unsigned int size )

Compute inverse of odd big integer modulo any power of two.

Parameters
invertend0Element 0 of odd big integer to be inverted
inverse0Element 0 of big integer to hold result
sizeNumber of elements in invertend and result

Definition at line 318 of file bigint.c.

319 {
320 const bigint_t ( size ) __attribute__ (( may_alias ))
321 *invertend = ( ( const void * ) invertend0 );
322 bigint_t ( size ) __attribute__ (( may_alias ))
323 *inverse = ( ( void * ) inverse0 );
324 bigint_element_t accum;
326 unsigned int i;
327
328 /* Sanity check */
329 assert ( bigint_bit_is_set ( invertend, 0 ) );
330
331 /* Initialise output */
332 memset ( inverse, 0xff, sizeof ( *inverse ) );
333
334 /* Compute inverse modulo 2^(width)
335 *
336 * This method is a lightly modified version of the pseudocode
337 * presented in "A New Algorithm for Inversion mod p^k (Koç,
338 * 2017)".
339 *
340 * Each inner loop iteration calculates one bit of the
341 * inverse. The residue value is the two's complement
342 * negation of the value "b" as used by Koç, to allow for
343 * division by two using a logical right shift (since we have
344 * no arithmetic right shift operation for big integers).
345 *
346 * The residue is stored in the as-yet uncalculated portion of
347 * the inverse. The size of the residue therefore decreases
348 * by one element for each outer loop iteration. Trivial
349 * inspection of the algorithm shows that any higher bits
350 * could not contribute to the eventual output value, and so
351 * we may safely reuse storage this way.
352 *
353 * Due to the suffix property of inverses mod 2^k, the result
354 * represents the least significant bits of the inverse modulo
355 * an arbitrarily large 2^k.
356 */
357 for ( i = size ; i > 0 ; i-- ) {
358 const bigint_t ( i ) __attribute__ (( may_alias ))
359 *addend = ( ( const void * ) invertend );
360 bigint_t ( i ) __attribute__ (( may_alias ))
361 *residue = ( ( void * ) inverse );
362
363 /* Calculate one element's worth of inverse bits */
364 for ( accum = 0, bit = 1 ; bit ; bit <<= 1 ) {
365 if ( bigint_bit_is_set ( residue, 0 ) ) {
366 accum |= bit;
367 bigint_add ( addend, residue );
368 }
369 bigint_shr ( residue );
370 }
371
372 /* Store in the element no longer required to hold residue */
373 inverse->element[ i - 1 ] = accum;
374 }
375
376 /* Correct order of inverse elements */
377 for ( i = 0 ; i < ( size / 2 ) ; i++ ) {
378 accum = inverse->element[i];
379 inverse->element[i] = inverse->element[ size - 1 - i ];
380 inverse->element[ size - 1 - i ] = accum;
381 }
382}
#define bigint_bit_is_set(value, bit)
Test if bit is set in big integer.
Definition bigint.h:179
static unsigned int unsigned int bit
Definition bigint.h:392
#define bigint_shr(value)
Shift big integer right.
Definition bigint.h:122

References __attribute__, assert, bigint_add, bigint_bit_is_set, bigint_shr, bigint_t, bit, memset(), and size.

◆ bigint_montgomery_relaxed_raw()

int bigint_montgomery_relaxed_raw ( const bigint_element_t * modulus0,
bigint_element_t * value0,
bigint_element_t * result0,
unsigned int size )

Perform relaxed Montgomery reduction (REDC) of a big integer.

Parameters
modulus0Element 0 of big integer odd modulus
value0Element 0 of big integer to be reduced
result0Element 0 of big integer to hold result
sizeNumber of elements in modulus and result
Return values
carryCarry out

The value to be reduced will be made divisible by the size of the modulus while retaining its residue class (i.e. multiples of the modulus will be added until the low half of the value is zero).

The result may be expressed as

tR = x + mN

where x is the input value, N is the modulus, R=2^n (where n is the number of bits in the representation of the modulus, including any leading zero bits), and m is the number of multiples of the modulus added to make the result tR divisible by R.

The maximum addend is mN <= (R-1)*N (and such an m can be proven to exist since N is limited to being odd and therefore coprime to R).

Since the result of this addition is one bit larger than the input value, a carry out bit is also returned. The caller may be able to prove that the carry out is always zero, in which case it may be safely ignored.

The upper half of the output value (i.e. t) will also be copied to the result pointer. It is permissible for the result pointer to overlap the lower half of the input value.

External knowledge of constraints on the modulus and the input value may be used to prove constraints on the result. The constraint on the modulus may be generally expressed as

R > kN

for some positive integer k. The value k=1 is allowed, and simply expresses that the modulus fits within the number of bits in its own representation.

For classic Montgomery reduction, we have k=1, i.e. R > N and a separate constraint that the input value is in the range x < RN. This gives the result constraint

tR < RN + (R-1)N < 2RN - N < 2RN t < 2N

A single subtraction of the modulus may therefore be required to bring it into the range t < N.

When the input value is known to be a product of two integers A and B, with A < aN and B < bN, we get the result constraint

tR < abN^2 + (R-1)N < (ab/k)RN + RN - N < (1 + ab/k)RN t < (1 + ab/k)N

If we have k=a=b=1, i.e. R > N with A < N and B < N, then the result is in the range t < 2N and may require a single subtraction of the modulus to bring it into the range t < N so that it may be used as an input on a subsequent iteration.

If we have k=4 and a=b=2, i.e. R > 4N with A < 2N and B < 2N, then the result is in the range t < 2N and may immediately be used as an input on a subsequent iteration, without requiring a subtraction.

Larger values of k may be used to allow for larger values of a and b, which can be useful to elide intermediate reductions in a calculation chain that involves additions and subtractions between multiplications (as used in elliptic curve point addition, for example). As a general rule: each intermediate addition or subtraction will require k to be doubled.

When the input value is known to be a single integer A, with A < aN (as used when converting out of Montgomery form), we get the result constraint

tR < aN + (R-1)N < RN + (a-1)N

If we have a=1, i.e. A < N, then the constraint becomes

tR < RN t < N

and so the result is immediately in the range t < N with no subtraction of the modulus required.

For any larger value of a, the result value t=N becomes possible. Additional external knowledge may potentially be used to prove that t=N cannot occur. For example: if the caller is performing modular exponentiation with a prime modulus (or, more generally, a modulus that is coprime to the base), then there is no way for a non-zero base value to end up producing an exact multiple of the modulus. If t=N cannot be disproved, then conversion out of Montgomery form may require an additional subtraction of the modulus.

Definition at line 488 of file bigint.c.

491 {
492 const bigint_t ( size ) __attribute__ (( may_alias ))
493 *modulus = ( ( const void * ) modulus0 );
494 union {
495 bigint_t ( size * 2 ) full;
496 struct {
497 bigint_t ( size ) low;
498 bigint_t ( size ) high;
499 } __attribute__ (( packed ));
500 } __attribute__ (( may_alias )) *value = ( ( void * ) value0 );
501 bigint_t ( size ) __attribute__ (( may_alias ))
502 *result = ( ( void * ) result0 );
503 static bigint_t ( 1 ) cached;
504 static bigint_t ( 1 ) negmodinv;
505 bigint_element_t multiple;
507 unsigned int i;
508 unsigned int j;
509 int overflow;
510
511 /* Sanity checks */
512 assert ( bigint_bit_is_set ( modulus, 0 ) );
513
514 /* Calculate inverse (or use cached version) */
515 if ( cached.element[0] != modulus->element[0] ) {
516 bigint_mod_invert ( modulus, &negmodinv );
517 negmodinv.element[0] = -negmodinv.element[0];
518 cached.element[0] = modulus->element[0];
519 }
520
521 /* Perform multiprecision Montgomery reduction */
522 for ( i = 0 ; i < size ; i++ ) {
523
524 /* Determine scalar multiple for this round */
525 multiple = ( value->low.element[i] * negmodinv.element[0] );
526
527 /* Multiply value to make it divisible by 2^(width*i) */
528 carry = 0;
529 for ( j = 0 ; j < size ; j++ ) {
530 bigint_multiply_one ( multiple, modulus->element[j],
531 &value->full.element[ i + j ],
532 &carry );
533 }
534
535 /* Since value is now divisible by 2^(width*i), we
536 * know that the current low element must have been
537 * zeroed.
538 */
539 assert ( value->low.element[i] == 0 );
540
541 /* Store the multiplication carry out in the result,
542 * avoiding the need to immediately propagate the
543 * carry through the remaining elements.
544 */
545 result->element[i] = carry;
546 }
547
548 /* Add the accumulated carries */
549 overflow = bigint_add ( result, &value->high );
550
551 /* Copy to result buffer */
552 bigint_copy ( &value->high, result );
553
554 return overflow;
555}
#define bigint_mod_invert(invertend, inverse)
Compute inverse of odd big integer modulo any power of two.
Definition bigint.h:286
#define bigint_copy(source, dest)
Copy big integer.
Definition bigint.h:235
uint32_t high
High 32 bits of address.
Definition myson.h:1
uint32_t low
Low 16 bits of address.
Definition myson.h:0
if(natsemi->flags &NATSEMI_64BIT) return 1

References __attribute__, assert, bigint_add, bigint_bit_is_set, bigint_copy, bigint_mod_invert, bigint_multiply_one(), bigint_t, carry, high, low, result, size, value, and value0.

◆ bigint_montgomery_raw()

void bigint_montgomery_raw ( const bigint_element_t * modulus0,
bigint_element_t * value0,
bigint_element_t * result0,
unsigned int size )

Perform classic Montgomery reduction (REDC) of a big integer.

Parameters
modulus0Element 0 of big integer odd modulus
value0Element 0 of big integer to be reduced
result0Element 0 of big integer to hold result
sizeNumber of elements in modulus and result

Definition at line 565 of file bigint.c.

568 {
569 const bigint_t ( size ) __attribute__ (( may_alias ))
570 *modulus = ( ( const void * ) modulus0 );
571 union {
572 bigint_t ( size * 2 ) full;
573 struct {
574 bigint_t ( size ) low;
575 bigint_t ( size ) high;
576 } __attribute__ (( packed ));
577 } __attribute__ (( may_alias )) *value = ( ( void * ) value0 );
578 bigint_t ( size ) __attribute__ (( may_alias ))
579 *result = ( ( void * ) result0 );
580 int overflow;
581 int underflow;
582
583 /* Sanity check */
584 assert ( ! bigint_is_geq ( &value->high, modulus ) );
585
586 /* Perform relaxed Montgomery reduction */
587 overflow = bigint_montgomery_relaxed ( modulus, &value->full, result );
588
589 /* Conditionally subtract the modulus once */
590 underflow = bigint_subtract ( modulus, result );
591 bigint_swap ( result, &value->high, ( underflow & ~overflow ) );
592
593 /* Sanity check */
594 assert ( ! bigint_is_geq ( result, modulus ) );
595}
#define bigint_montgomery_relaxed(modulus, value, result)
Perform relaxed Montgomery reduction (REDC) of a big integer.
Definition bigint.h:300
#define bigint_swap(first, second, swap)
Conditionally swap big integers (in constant time)
Definition bigint.h:247

References __attribute__, assert, bigint_is_geq, bigint_montgomery_relaxed, bigint_subtract, bigint_swap, bigint_t, high, low, result, size, value, and value0.

◆ bigint_ladder_raw()

void bigint_ladder_raw ( bigint_element_t * result0,
bigint_element_t * multiple0,
unsigned int size,
const bigint_element_t * exponent0,
unsigned int exponent_size,
bigint_ladder_op_t * op,
const void * ctx,
void * tmp )

Perform generalised exponentiation via a Montgomery ladder.

Parameters
result0Element 0 of result (initialised to identity element)
multiple0Element 0 of multiple (initialised to generator)
sizeNumber of elements in result and multiple
exponent0Element 0 of exponent
exponent_sizeNumber of elements in exponent
opMontgomery ladder commutative operation
ctxOperation context (if needed)
tmpTemporary working space (if needed)

The Montgomery ladder may be used to perform any operation that is isomorphic to exponentiation, i.e. to compute the result

r = g^e = g * g * g * g * .... * g

for an arbitrary commutative operation "*", generator "g" and exponent "e".

The result "r" is computed in constant time (assuming that the underlying operation is constant time) in k steps, where k is the number of bits in the big integer representation of the exponent.

The result "r" must be initialised to the operation's identity element, and the multiple must be initialised to the generator "g". On exit, the multiple will contain

m = r * g = g^(e+1)

Note that the terminology used here refers to exponentiation defined as repeated multiplication, but that the ladder may equally well be used to perform any isomorphic operation (such as multiplication defined as repeated addition).

Definition at line 632 of file bigint.c.

636 {
637 bigint_t ( size ) __attribute__ (( may_alias ))
638 *result = ( ( void * ) result0 );
639 bigint_t ( size ) __attribute__ (( may_alias ))
640 *multiple = ( ( void * ) multiple0 );
641 const bigint_t ( exponent_size ) __attribute__ (( may_alias ))
642 *exponent = ( ( const void * ) exponent0 );
643 const unsigned int width = ( 8 * sizeof ( bigint_element_t ) );
644 unsigned int bit = ( exponent_size * width );
645 int toggle = 0;
646 int previous;
647
648 /* We have two physical storage locations: Rres (the "result"
649 * register) and Rmul (the "multiple" register).
650 *
651 * On entry we have:
652 *
653 * Rres = g^0 = 1 (the identity element)
654 * Rmul = g (the generator)
655 *
656 * For calculation purposes, define two virtual registers R[0]
657 * and R[1], mapped to the underlying physical storage
658 * locations via a boolean toggle state "t":
659 *
660 * R[t] -> Rres
661 * R[~t] -> Rmul
662 *
663 * Define the initial toggle state to be t=0, so that we have:
664 *
665 * R[0] = g^0 = 1 (the identity element)
666 * R[1] = g (the generator)
667 *
668 * The Montgomery ladder then iterates over each bit "b" of
669 * the exponent "e" (from MSB down to LSB), computing:
670 *
671 * R[1] := R[0] * R[1], R[0] := R[0] * R[0] (if b=0)
672 * R[0] := R[1] * R[0], R[1] := R[1] * R[1] (if b=1)
673 *
674 * i.e.
675 *
676 * R[~b] := R[b] * R[~b], R[b] := R[b] * R[b]
677 *
678 * To avoid data-dependent memory access patterns, we
679 * implement this as:
680 *
681 * Rmul := Rres * Rmul
682 * Rres := Rres * Rres
683 *
684 * and update the toggle state "t" (via constant-time
685 * conditional swaps) as needed to ensure that R[b] always
686 * maps to Rres and R[~b] always maps to Rmul.
687 */
688 while ( bit-- ) {
689
690 /* Update toggle state t := b
691 *
692 * If the new toggle state is not equal to the old
693 * toggle state, then we must swap R[0] and R[1] (in
694 * constant time).
695 */
696 previous = toggle;
697 toggle = bigint_bit_is_set ( exponent, bit );
698 bigint_swap ( result, multiple, ( toggle ^ previous ) );
699
700 /* Calculate Rmul = R[~b] := R[b] * R[~b] = Rres * Rmul */
701 op ( result->element, multiple->element, size, ctx, tmp );
702
703 /* Calculate Rres = R[b] := R[b] * R[b] = Rres * Rres */
704 op ( result->element, result->element, size, ctx, tmp );
705 }
706
707 /* Reset toggle state to zero */
708 bigint_swap ( result, multiple, toggle );
709}
struct golan_eq_context ctx
Definition CIB_PRM.h:0
static uint16_t struct vmbus_xfer_pages_operations * op
Definition netvsc.h:327

References __attribute__, bigint_bit_is_set, bigint_swap, bigint_t, bit, ctx, op, result, size, and tmp.

◆ bigint_mod_exp_ladder()

void bigint_mod_exp_ladder ( const bigint_element_t * multiplier0,
bigint_element_t * result0,
unsigned int size,
const void * ctx,
void * tmp )

Perform modular multiplication as part of a Montgomery ladder.

Parameters
operandElement 0 of first input operand (may overlap result)
resultElement 0 of second input operand and result
sizeNumber of elements in operands and result
ctxOperation context (odd modulus, or NULL)
tmpTemporary working space

Definition at line 720 of file bigint.c.

722 {
723 const bigint_t ( size ) __attribute__ (( may_alias ))
724 *multiplier = ( ( const void * ) multiplier0 );
725 bigint_t ( size ) __attribute__ (( may_alias ))
726 *result = ( ( void * ) result0 );
727 const bigint_t ( size ) __attribute__ (( may_alias ))
728 *modulus = ( ( const void * ) ctx );
729 bigint_t ( size * 2 ) __attribute__ (( may_alias ))
730 *product = ( ( void * ) tmp );
731
732 /* Multiply and reduce */
734 if ( modulus ) {
735 bigint_montgomery ( modulus, product, result );
736 } else {
738 }
739}
#define bigint_montgomery(modulus, value, result)
Perform classic Montgomery reduction (REDC) of a big integer.
Definition bigint.h:314
#define bigint_shrink(source, dest)
Shrink big integer.
Definition bigint.h:222
#define bigint_multiply(multiplicand, multiplier, result)
Multiply big integers.
Definition bigint.h:260
uint8_t product
Product string.
Definition smbios.h:5

References __attribute__, bigint_montgomery, bigint_multiply, bigint_shrink, bigint_t, ctx, multiplier, product, result, size, and tmp.

Referenced by bigint_mod_exp_raw(), ecdsa_invert(), and weierstrass_done_raw().

◆ bigint_mod_exp_raw()

void bigint_mod_exp_raw ( const bigint_element_t * base0,
const bigint_element_t * modulus0,
const bigint_element_t * exponent0,
bigint_element_t * result0,
unsigned int size,
unsigned int exponent_size,
void * tmp )

Perform modular exponentiation of big integers.

Parameters
base0Element 0 of big integer base
modulus0Element 0 of big integer modulus
exponent0Element 0 of big integer exponent
result0Element 0 of big integer to hold result
sizeNumber of elements in base, modulus, and result
exponent_sizeNumber of elements in exponent
tmpTemporary working space

Definition at line 752 of file bigint.c.

757 {
758 const bigint_t ( size ) __attribute__ (( may_alias )) *base =
759 ( ( const void * ) base0 );
760 const bigint_t ( size ) __attribute__ (( may_alias )) *modulus =
761 ( ( const void * ) modulus0 );
762 const bigint_t ( exponent_size ) __attribute__ (( may_alias ))
763 *exponent = ( ( const void * ) exponent0 );
764 bigint_t ( size ) __attribute__ (( may_alias )) *result =
765 ( ( void * ) result0 );
766 const unsigned int width = ( 8 * sizeof ( bigint_element_t ) );
767 struct {
768 struct {
769 bigint_t ( size ) modulus;
770 bigint_t ( size ) stash;
771 };
772 union {
773 bigint_t ( 2 * size ) full;
774 bigint_t ( size ) low;
775 } product;
776 } *temp = tmp;
777 const uint8_t one[1] = { 1 };
778 bigint_element_t submask;
779 unsigned int subsize;
780 unsigned int scale;
781 unsigned int i;
782
783 /* Sanity check */
784 assert ( sizeof ( *temp ) == bigint_mod_exp_tmp_len ( modulus ) );
785
786 /* Handle degenerate case of zero modulus */
787 if ( ! bigint_max_set_bit ( modulus ) ) {
788 memset ( result, 0, sizeof ( *result ) );
789 return;
790 }
791
792 /* Factor modulus as (N * 2^scale) where N is odd */
793 bigint_copy ( modulus, &temp->modulus );
794 for ( scale = 0 ; ( ! bigint_bit_is_set ( &temp->modulus, 0 ) ) ;
795 scale++ ) {
796 bigint_shr ( &temp->modulus );
797 }
798 subsize = ( ( scale + width - 1 ) / width );
799 submask = ( ( 1UL << ( scale % width ) ) - 1 );
800 if ( ! submask )
801 submask = ~submask;
802
803 /* Calculate (R^2 mod N) */
804 bigint_reduce ( &temp->modulus, &temp->stash );
805
806 /* Initialise result = Montgomery(1, R^2 mod N) */
807 bigint_grow ( &temp->stash, &temp->product.full );
808 bigint_montgomery ( &temp->modulus, &temp->product.full, result );
809
810 /* Convert base into Montgomery form */
811 bigint_multiply ( base, &temp->stash, &temp->product.full );
812 bigint_montgomery ( &temp->modulus, &temp->product.full,
813 &temp->stash );
814
815 /* Calculate x1 = base^exponent modulo N */
816 bigint_ladder ( result, &temp->stash, exponent, bigint_mod_exp_ladder,
817 &temp->modulus, &temp->product );
818
819 /* Convert back out of Montgomery form */
820 bigint_grow ( result, &temp->product.full );
821 bigint_montgomery_relaxed ( &temp->modulus, &temp->product.full,
822 result );
823
824 /* Handle even moduli via Garner's algorithm */
825 if ( subsize ) {
826 const bigint_t ( subsize ) __attribute__ (( may_alias ))
827 *subbase = ( ( const void * ) base );
828 bigint_t ( subsize ) __attribute__ (( may_alias ))
829 *submodulus = ( ( void * ) &temp->modulus );
830 bigint_t ( subsize ) __attribute__ (( may_alias ))
831 *substash = ( ( void * ) &temp->stash );
832 bigint_t ( subsize ) __attribute__ (( may_alias ))
833 *subresult = ( ( void * ) result );
834 union {
835 bigint_t ( 2 * subsize ) full;
836 bigint_t ( subsize ) low;
837 } __attribute__ (( may_alias ))
838 *subproduct = ( ( void * ) &temp->product.full );
839
840 /* Calculate x2 = base^exponent modulo 2^k */
841 bigint_init ( substash, one, sizeof ( one ) );
842 bigint_copy ( subbase, submodulus );
843 bigint_ladder ( substash, submodulus, exponent,
844 bigint_mod_exp_ladder, NULL, subproduct );
845
846 /* Reconstruct N */
847 bigint_copy ( modulus, &temp->modulus );
848 for ( i = 0 ; i < scale ; i++ )
849 bigint_shr ( &temp->modulus );
850
851 /* Calculate N^-1 modulo 2^k */
852 bigint_mod_invert ( submodulus, &subproduct->low );
853 bigint_copy ( &subproduct->low, submodulus );
854
855 /* Calculate y = (x2 - x1) * N^-1 modulo 2^k */
856 bigint_subtract ( subresult, substash );
857 bigint_multiply ( substash, submodulus, &subproduct->full );
858 subproduct->low.element[ subsize - 1 ] &= submask;
859 bigint_grow ( &subproduct->low, &temp->stash );
860
861 /* Reconstruct N */
862 bigint_mod_invert ( submodulus, &subproduct->low );
863 bigint_copy ( &subproduct->low, submodulus );
864
865 /* Calculate x = x1 + N * y */
866 bigint_multiply ( &temp->modulus, &temp->stash,
867 &temp->product.full );
868 bigint_add ( &temp->product.low, result );
869 }
870}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
void bigint_mod_exp_ladder(const bigint_element_t *multiplier0, bigint_element_t *result0, unsigned int size, const void *ctx, void *tmp)
Perform modular multiplication as part of a Montgomery ladder.
Definition bigint.c:720
#define bigint_grow(source, dest)
Grow big integer.
Definition bigint.h:209
#define bigint_ladder(result, multiple, exponent, op, ctx, tmp)
Perform generalised exponentiation via a Montgomery ladder.
Definition bigint.h:330
#define bigint_mod_exp_tmp_len(modulus)
Calculate temporary working space required for moduluar exponentiation.
Definition bigint.h:361
#define bigint_reduce(modulus, result)
Reduce big integer R^2 modulo N.
Definition bigint.h:274
#define bigint_init(value, data, len)
Initialise big integer.
Definition bigint.h:62
uint32_t base
Base.
Definition librm.h:3

References __attribute__, assert, base, bigint_add, bigint_bit_is_set, bigint_copy, bigint_grow, bigint_init, bigint_ladder, bigint_max_set_bit, bigint_mod_exp_ladder(), bigint_mod_exp_tmp_len, bigint_mod_invert, bigint_montgomery, bigint_montgomery_relaxed, bigint_multiply, bigint_reduce, bigint_shr, bigint_subtract, bigint_t, low, memset(), NULL, product, result, size, and tmp.