iPXE
bigint.h
Go to the documentation of this file.
1 #ifndef _BITS_BIGINT_H
2 #define _BITS_BIGINT_H
3 
4 /** @file
5  *
6  * Big integer support
7  */
8 
9 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
10 
11 #include <stdint.h>
12 #include <string.h>
13 
14 /** Element of a big integer */
16 
17 /**
18  * Initialise big integer
19  *
20  * @v value0 Element 0 of big integer to initialise
21  * @v size Number of elements
22  * @v data Raw data
23  * @v len Length of raw data
24  */
25 static inline __attribute__ (( always_inline )) void
27  const void *data, size_t len ) {
28  bigint_t ( size ) __attribute__ (( may_alias )) *value =
29  ( ( void * ) value0 );
30  long pad_len = ( sizeof ( *value ) - len );
31  void *discard_D;
32  long discard_c;
33 
34  /* Copy raw data in reverse order, padding with zeros */
35  __asm__ __volatile__ ( "jecxz 2f\n\t"
36  "\n1:\n\t"
37  "movb -1(%3,%1), %%al\n\t"
38  "stosb\n\t"
39  "loop 1b\n\t"
40  "\n2:\n\t"
41  "xorl %%eax, %%eax\n\t"
42  "mov %4, %1\n\t"
43  "rep stosb\n\t"
44  : "=&D" ( discard_D ), "=&c" ( discard_c ),
45  "+m" ( *value )
46  : "r" ( data ), "g" ( pad_len ), "0" ( value0 ),
47  "1" ( len )
48  : "eax" );
49 }
50 
51 /**
52  * Add big integers
53  *
54  * @v addend0 Element 0 of big integer to add
55  * @v value0 Element 0 of big integer to be added to
56  * @v size Number of elements
57  * @ret carry Carry flag
58  */
59 static inline __attribute__ (( always_inline )) int
61  unsigned int size ) {
62  bigint_t ( size ) __attribute__ (( may_alias )) *value =
63  ( ( void * ) value0 );
64  long index;
65  void *discard_S;
66  long discard_c;
67  int carry;
68 
69  __asm__ __volatile__ ( "xor %0, %0\n\t" /* Zero %0 and clear CF */
70  "\n1:\n\t"
71  "lodsl\n\t"
72  "adcl %%eax, (%5,%0,4)\n\t"
73  "inc %0\n\t" /* Does not affect CF */
74  "loop 1b\n\t"
75  : "=&r" ( index ), "=&S" ( discard_S ),
76  "=&c" ( discard_c ), "=@ccc" ( carry ),
77  "+m" ( *value )
78  : "r" ( value0 ), "1" ( addend0 ), "2" ( size )
79  : "eax" );
80  return carry;
81 }
82 
83 /**
84  * Subtract big integers
85  *
86  * @v subtrahend0 Element 0 of big integer to subtract
87  * @v value0 Element 0 of big integer to be subtracted from
88  * @v size Number of elements
89  * @ret borrow Borrow flag
90  */
91 static inline __attribute__ (( always_inline )) int
92 bigint_subtract_raw ( const uint32_t *subtrahend0, uint32_t *value0,
93  unsigned int size ) {
94  bigint_t ( size ) __attribute__ (( may_alias )) *value =
95  ( ( void * ) value0 );
96  long index;
97  void *discard_S;
98  long discard_c;
99  int borrow;
100 
101  __asm__ __volatile__ ( "xor %0, %0\n\t" /* Zero %0 and clear CF */
102  "\n1:\n\t"
103  "lodsl\n\t"
104  "sbbl %%eax, (%5,%0,4)\n\t"
105  "inc %0\n\t" /* Does not affect CF */
106  "loop 1b\n\t"
107  : "=&r" ( index ), "=&S" ( discard_S ),
108  "=&c" ( discard_c ), "=@ccc" ( borrow ),
109  "+m" ( *value )
110  : "r" ( value0 ), "1" ( subtrahend0 ),
111  "2" ( size )
112  : "eax" );
113  return borrow;
114 }
115 
116 /**
117  * Shift big integer left
118  *
119  * @v value0 Element 0 of big integer
120  * @v size Number of elements
121  * @ret out Bit shifted out
122  */
123 static inline __attribute__ (( always_inline )) int
124 bigint_shl_raw ( uint32_t *value0, unsigned int size ) {
125  bigint_t ( size ) __attribute__ (( may_alias )) *value =
126  ( ( void * ) value0 );
127  long index;
128  long discard_c;
129  int out;
130 
131  __asm__ __volatile__ ( "xor %0, %0\n\t" /* Zero %0 and clear CF */
132  "\n1:\n\t"
133  "rcll $1, (%4,%0,4)\n\t"
134  "inc %0\n\t" /* Does not affect CF */
135  "loop 1b\n\t"
136  : "=&r" ( index ), "=&c" ( discard_c ),
137  "=@ccc" ( out ), "+m" ( *value )
138  : "r" ( value0 ), "1" ( size ) );
139  return out;
140 }
141 
142 /**
143  * Shift big integer right
144  *
145  * @v value0 Element 0 of big integer
146  * @v size Number of elements
147  * @ret out Bit shifted out
148  */
149 static inline __attribute__ (( always_inline )) int
150 bigint_shr_raw ( uint32_t *value0, unsigned int size ) {
151  bigint_t ( size ) __attribute__ (( may_alias )) *value =
152  ( ( void * ) value0 );
153  long discard_c;
154  int out;
155 
156  __asm__ __volatile__ ( "clc\n\t"
157  "\n1:\n\t"
158  "rcrl $1, -4(%3,%0,4)\n\t"
159  "loop 1b\n\t"
160  : "=&c" ( discard_c ), "=@ccc" ( out ),
161  "+m" ( *value )
162  : "r" ( value0 ), "0" ( size ) );
163  return out;
164 }
165 
166 /**
167  * Test if big integer is equal to zero
168  *
169  * @v value0 Element 0 of big integer
170  * @v size Number of elements
171  * @ret is_zero Big integer is equal to zero
172  */
173 static inline __attribute__ (( always_inline, pure )) int
174 bigint_is_zero_raw ( const uint32_t *value0, unsigned int size ) {
175  void *discard_D;
176  long discard_c;
177  int result;
178 
179  __asm__ __volatile__ ( "xor %0, %0\n\t" /* Set ZF */
180  "repe scasl\n\t"
181  "sete %b0\n\t"
182  : "=&a" ( result ), "=&D" ( discard_D ),
183  "=&c" ( discard_c )
184  : "1" ( value0 ), "2" ( size ) );
185  return result;
186 }
187 
188 /**
189  * Compare big integers
190  *
191  * @v value0 Element 0 of big integer
192  * @v reference0 Element 0 of reference big integer
193  * @v size Number of elements
194  * @ret geq Big integer is greater than or equal to the reference
195  */
196 static inline __attribute__ (( always_inline, pure )) int
198  unsigned int size ) {
199  long discard_c;
201  int result;
202 
203  __asm__ __volatile__ ( "\n1:\n\t"
204  "movl -4(%3, %1, 4), %k2\n\t"
205  "cmpl -4(%4, %1, 4), %k2\n\t"
206  "loope 1b\n\t"
207  "setae %b0\n\t"
208  : "=q" ( result ), "=&c" ( discard_c ),
209  "=&r" ( discard_tmp )
210  : "r" ( value0 ), "r" ( reference0 ),
211  "0" ( 0 ), "1" ( size ) );
212  return result;
213 }
214 
215 /**
216  * Find highest bit set in big integer
217  *
218  * @v value0 Element 0 of big integer
219  * @v size Number of elements
220  * @ret max_bit Highest bit set + 1 (or 0 if no bits set)
221  */
222 static inline __attribute__ (( always_inline )) int
223 bigint_max_set_bit_raw ( const uint32_t *value0, unsigned int size ) {
224  long discard_c;
225  int result;
226 
227  __asm__ __volatile__ ( "\n1:\n\t"
228  "bsrl -4(%2,%1,4), %0\n\t"
229  "loopz 1b\n\t"
230  "rol %1\n\t" /* Does not affect ZF */
231  "rol %1\n\t"
232  "leal 1(%k0,%k1,8), %k0\n\t"
233  "jnz 2f\n\t"
234  "xor %0, %0\n\t"
235  "\n2:\n\t"
236  : "=&r" ( result ), "=&c" ( discard_c )
237  : "r" ( value0 ), "1" ( size ) );
238  return result;
239 }
240 
241 /**
242  * Grow big integer
243  *
244  * @v source0 Element 0 of source big integer
245  * @v source_size Number of elements in source big integer
246  * @v dest0 Element 0 of destination big integer
247  * @v dest_size Number of elements in destination big integer
248  */
249 static inline __attribute__ (( always_inline )) void
250 bigint_grow_raw ( const uint32_t *source0, unsigned int source_size,
251  uint32_t *dest0, unsigned int dest_size ) {
252  bigint_t ( dest_size ) __attribute__ (( may_alias )) *dest =
253  ( ( void * ) dest0 );
255  void *discard_D;
256  void *discard_S;
257  long discard_c;
258 
259  __asm__ __volatile__ ( "rep movsl\n\t"
260  "xorl %%eax, %%eax\n\t"
261  "mov %4, %2\n\t"
262  "rep stosl\n\t"
263  : "=&D" ( discard_D ), "=&S" ( discard_S ),
264  "=&c" ( discard_c ), "+m" ( *dest )
265  : "g" ( pad_size ), "0" ( dest0 ),
266  "1" ( source0 ), "2" ( source_size )
267  : "eax" );
268 }
269 
270 /**
271  * Shrink big integer
272  *
273  * @v source0 Element 0 of source big integer
274  * @v source_size Number of elements in source big integer
275  * @v dest0 Element 0 of destination big integer
276  * @v dest_size Number of elements in destination big integer
277  */
278 static inline __attribute__ (( always_inline )) void
279 bigint_shrink_raw ( const uint32_t *source0, unsigned int source_size __unused,
280  uint32_t *dest0, unsigned int dest_size ) {
281  bigint_t ( dest_size ) __attribute__ (( may_alias )) *dest =
282  ( ( void * ) dest0 );
283  void *discard_D;
284  void *discard_S;
285  long discard_c;
286 
287  __asm__ __volatile__ ( "rep movsl\n\t"
288  : "=&D" ( discard_D ), "=&S" ( discard_S ),
289  "=&c" ( discard_c ), "+m" ( *dest )
290  : "0" ( dest0 ), "1" ( source0 ),
291  "2" ( dest_size )
292  : "eax" );
293 }
294 
295 /**
296  * Finalise big integer
297  *
298  * @v value0 Element 0 of big integer to finalise
299  * @v size Number of elements
300  * @v out Output buffer
301  * @v len Length of output buffer
302  */
303 static inline __attribute__ (( always_inline )) void
304 bigint_done_raw ( const uint32_t *value0, unsigned int size __unused,
305  void *out, size_t len ) {
306  struct {
307  uint8_t bytes[len];
308  } __attribute__ (( may_alias )) *out_bytes = out;
309  void *discard_D;
310  long discard_c;
311 
312  /* Copy raw data in reverse order */
313  __asm__ __volatile__ ( "jecxz 2f\n\t"
314  "\n1:\n\t"
315  "movb -1(%3,%1), %%al\n\t"
316  "stosb\n\t"
317  "loop 1b\n\t"
318  "\n2:\n\t"
319  : "=&D" ( discard_D ), "=&c" ( discard_c ),
320  "+m" ( *out_bytes )
321  : "r" ( value0 ), "0" ( out ), "1" ( len )
322  : "eax" );
323 }
324 
325 /**
326  * Multiply big integer elements
327  *
328  * @v multiplicand Multiplicand element
329  * @v multiplier Multiplier element
330  * @v result Result element
331  * @v carry Carry element
332  */
333 static inline __attribute__ (( always_inline )) void
334 bigint_multiply_one ( const uint32_t multiplicand, const uint32_t multiplier,
336  uint32_t discard_a;
337 
338  __asm__ __volatile__ ( /* Perform multiplication */
339  "mull %3\n\t"
340  /* Accumulate carry */
341  "addl %5, %0\n\t"
342  "adcl $0, %1\n\t"
343  /* Accumulate result */
344  "addl %0, %2\n\t"
345  "adcl $0, %1\n\t"
346  : "=&a" ( discard_a ),
347  "=&d" ( *carry ),
348  "+m" ( *result )
349  : "g" ( multiplicand ),
350  "0" ( multiplier ),
351  "r" ( *carry ) );
352 }
353 
354 #endif /* _BITS_BIGINT_H */
void bigint_grow_raw(const bigint_element_t *source0, unsigned int source_size, bigint_element_t *dest0, unsigned int dest_size)
static const uint32_t * reference0
Definition: bigint.h:197
int carry
Definition: bigint.h:67
void * discard_S
Definition: bigint.h:65
int bigint_max_set_bit_raw(const bigint_element_t *value0, unsigned int size)
long index
Definition: bigint.h:64
void bigint_multiply_one(const bigint_element_t multiplicand, const bigint_element_t multiplier, bigint_element_t *result, bigint_element_t *carry)
long pad_size
Definition: bigint.h:254
static uint32_t * value0
Definition: bigint.h:60
long discard_tmp
Definition: bigint.h:200
static unsigned int const void size_t len
Definition: bigint.h:27
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
static unsigned int const void * data
Definition: bigint.h:26
pseudo_bit_t value[0x00020]
Definition: arbel.h:13
int result
Definition: bigint.h:177
uint32_t bigint_element_t
Element of a big integer.
Definition: bigint.h:15
void bigint_init_raw(bigint_element_t *value0, unsigned int size, const void *data, size_t len)
static unsigned int uint32_t unsigned int dest_size
Definition: bigint.h:251
int borrow
Definition: bigint.h:99
static __attribute__((always_inline)) void bigint_init_raw(uint32_t *value0
Initialise big integer.
unsigned char uint8_t
Definition: stdint.h:10
void * discard_D
Definition: bigint.h:31
unsigned int uint32_t
Definition: stdint.h:12
int bigint_shl_raw(bigint_element_t *value0, unsigned int size)
static unsigned int source_size __unused
Definition: bigint.h:279
long pad_len
Definition: bigint.h:30
__asm__(".section \".rodata\", \"a\", " PROGBITS "\n\t" "\nprivate_key_data:\n\t" ".size private_key_data, ( . - private_key_data )\n\t" ".equ private_key_len, ( . - private_key_data )\n\t" ".previous\n\t")
static const uint32_t multiplier
Port multiplier number.
Definition: bigint.h:334
static unsigned int source_size
Definition: bigint.h:250
void bigint_shrink_raw(const bigint_element_t *source0, unsigned int source_size, bigint_element_t *dest0, unsigned int dest_size)
void bigint_done_raw(const bigint_element_t *value0, unsigned int size, void *out, size_t len)
int out
Definition: bigint.h:129
int bigint_add_raw(const bigint_element_t *addend0, bigint_element_t *value0, unsigned int size)
if(len >=6 *4) __asm__ __volatile__("movsl" if(len >=5 *4) __asm__ __volatile__("movsl" if(len >=4 *4) __asm__ __volatile__("movsl" if(len >=3 *4) __asm__ __volatile__("movsl" if(len >=2 *4) __asm__ __volatile__("movsl" if(len >=1 *4) __asm__ __volatile__("movsl" if((len % 4) >=2) __asm__ __volatile__("movsw" if((len % 2) >=1) __asm__ __volatile__("movsb" return dest
Definition: string.h:150
Optimised string operations.
long discard_c
Definition: bigint.h:32
int bigint_shr_raw(bigint_element_t *value0, unsigned int size)
int bigint_subtract_raw(const bigint_element_t *subtrahend0, bigint_element_t *value0, unsigned int size)
uint8_t bytes[64]
Definition: ib_mad.h:16
int bigint_is_zero_raw(const bigint_element_t *value0, unsigned int size)
static unsigned int uint32_t * dest0
Definition: bigint.h:250
static unsigned int size
Definition: bigint.h:26
int bigint_is_geq_raw(const bigint_element_t *value0, const bigint_element_t *reference0, unsigned int size)
typedef bigint_t(X25519_SIZE) x25519_t
An X25519 unsigned big integer used in internal calculations.
__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")