iPXE
weierstrass.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2024 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 FILE_SECBOOT ( PERMITTED );
26 
27 /** @file
28  *
29  * Weierstrass elliptic curves
30  *
31  * The implementation is based upon Algorithm 1 from "Complete
32  * addition formulas for prime order elliptic curves" (Joost Renes,
33  * Craig Costello, and Lejla Batina), available from
34  *
35  * https://www.microsoft.com/en-us/research/wp-content/uploads/2016/06/complete-2.pdf
36  *
37  * The steps within the algorithm have been reordered and temporary
38  * variables shuffled to reduce stack usage, and calculations are
39  * carried out modulo small multiples of the field prime in order to
40  * elide reductions after intermediate addition and subtraction
41  * operations.
42  *
43  * The algorithm is encoded using a bytecode representation, since
44  * this substantially reduces the code size compared to direct
45  * implementation of the big integer operations.
46  */
47 
48 #include <errno.h>
49 #include <ipxe/weierstrass.h>
50 
51 /** Big integer register names */
53 
54  /*
55  * Read-only registers
56  */
57 
58  /* Curve constant "a" (for multiply), zero (for add/subtract) */
60  /* Curve constant "3b" */
62  /* Augend (x,y,z) co-ordinates */
66  /* Addend (x,y,z) co-ordinates */
70 
71  /*
72  * Read-write registers
73  */
74 
75  /* Temporary working registers */
80  /* Low half of multiplication product */
82  /* Result (x,y,z) co-ordinates */
86 
87  /* Number of registers */
89 };
90 
91 /** Zero register (for add/subtract operations */
92 #define WEIERSTRASS_zero WEIERSTRASS_a
93 
94 /** Construct big integer register index */
95 #define WEIERSTRASS_REGISTER( name ) _C2 ( WEIERSTRASS_, name )
96 
97 /** Bytecode operation codes */
99  /** Subtract big integers (and add nothing)*/
101  /** Subtract big integers (and add 2N) */
103  /** Subtract big integers (and add 4N) */
105  /** Add big integers */
107  /** Multiply big integers (and perform Montgomery reduction) */
109 };
110 
111 /**
112  * Define a bytecode operation
113  *
114  * @v opcode Operation code
115  * @v dest Destination big integer register name
116  * @v left Left source big integer register name
117  * @v right Right source big integer register name
118  */
119 #define WEIERSTRASS_OP( opcode, dest, left, right ) \
120  ( ( (opcode) << 12 ) | \
121  ( WEIERSTRASS_REGISTER ( dest ) << 8 ) | \
122  ( WEIERSTRASS_REGISTER ( left ) << 4 ) | \
123  ( WEIERSTRASS_REGISTER ( right ) << 0 ) )
124 
125 /** Extract bytecode operation code */
126 #define WEIERSTRASS_OPCODE( op ) ( ( (op) >> 12 ) & 0xf )
127 
128 /** Extract destination big integer register */
129 #define WEIERSTRASS_DEST( op ) ( ( (op) >> 8 ) & 0xf )
130 
131 /** Extract left source big integer register */
132 #define WEIERSTRASS_LEFT( op ) ( ( (op) >> 4 ) & 0xf )
133 
134 /** Extract right source big integer register */
135 #define WEIERSTRASS_RIGHT( op ) ( ( (op) >> 0 ) & 0xf )
136 
137 /** Define a three-argument addition operation */
138 #define WEIERSTRASS_ADD3( dest, augend, addend ) \
139  WEIERSTRASS_OP ( WEIERSTRASS_OP_ADD, dest, augend, addend )
140 
141 /** Define a two-argument addition operation */
142 #define WEIERSTRASS_ADD2( augend, addend ) \
143  WEIERSTRASS_ADD3 ( augend, augend, addend )
144 
145 /** Define a move operation */
146 #define WEIERSTRASS_MOV( dest, source ) \
147  WEIERSTRASS_ADD3( dest, source, zero )
148 
149 /** Define a three-argument subtraction operation */
150 #define WEIERSTRASS_SUB3( dest, minuend, subtrahend, multiple ) \
151  WEIERSTRASS_OP ( _C2 ( WEIERSTRASS_OP_SUB_, multiple ), \
152  dest, minuend, subtrahend )
153 
154 /** Define a two-argument subtraction operation */
155 #define WEIERSTRASS_SUB2( minuend, subtrahend, multiple ) \
156  WEIERSTRASS_SUB3 ( minuend, minuend, subtrahend, multiple )
157 
158 /** Define a stop operation */
159 #define WEIERSTRASS_STOP WEIERSTRASS_SUB2 ( zero, zero, 0N )
160 
161 /** Define a three-argument multiplication operation */
162 #define WEIERSTRASS_MUL3( dest, multiplicand, multiplier ) \
163  WEIERSTRASS_OP ( WEIERSTRASS_OP_MUL, dest, multiplicand, multiplier )
164 
165 /** Define a two-argument multiplication operation */
166 #define WEIERSTRASS_MUL2( multiplicand, multiplier ) \
167  WEIERSTRASS_MUL3 ( multiplicand, multiplicand, multiplier )
168 
169 /**
170  * Initialise curve
171  *
172  * @v curve Weierstrass curve
173  */
174 static void weierstrass_init_curve ( struct weierstrass_curve *curve ) {
175  unsigned int size = curve->size;
176  bigint_t ( size ) __attribute__ (( may_alias )) *prime =
177  ( ( void * ) curve->prime[0] );
178  bigint_t ( size ) __attribute__ (( may_alias )) *fermat =
179  ( ( void * ) curve->fermat );
180  bigint_t ( size ) __attribute__ (( may_alias )) *square =
181  ( ( void * ) curve->square );
182  bigint_t ( size ) __attribute__ (( may_alias )) *one =
183  ( ( void * ) curve->one );
184  bigint_t ( size ) __attribute__ (( may_alias )) *a =
185  ( ( void * ) curve->a );
186  bigint_t ( size ) __attribute__ (( may_alias )) *b3 =
187  ( ( void * ) curve->b3 );
188  bigint_t ( size ) __attribute__ (( may_alias )) *mont =
189  ( ( void * ) curve->mont[0] );
190  bigint_t ( size ) __attribute__ (( may_alias )) *temp =
191  ( ( void * ) curve->prime[1] );
192  bigint_t ( size * 2 ) __attribute__ (( may_alias )) *product =
193  ( ( void * ) temp );
194  bigint_t ( size ) __attribute__ (( may_alias )) *two =
195  ( ( void * ) temp );
196  static const uint8_t one_raw[] = { 1 };
197  static const uint8_t two_raw[] = { 2 };
198  size_t len = curve->len;
199  unsigned int i;
200 
201  /* Initialise field prime */
202  bigint_init ( prime, curve->prime_raw, len );
203  DBGC ( curve, "WEIERSTRASS %s N = %s\n",
204  curve->name, bigint_ntoa ( prime ) );
205 
206  /* Calculate Montgomery constant R^2 mod N */
207  bigint_reduce ( prime, square );
208  DBGC ( curve, "WEIERSTRASS %s R^2 = %s mod N\n",
209  curve->name, bigint_ntoa ( square ) );
210 
211  /* Calculate constant "3b" */
212  bigint_init ( b3, curve->b_raw, len );
213  DBGC ( curve, "WEIERSTRASS %s b = %s\n",
214  curve->name, bigint_ntoa ( b3 ) );
215  bigint_copy ( b3, a );
216  bigint_add ( b3, b3 );
217  bigint_add ( a, b3 );
218 
219  /* Initialise "a" */
220  bigint_init ( a, curve->a_raw, len );
221  DBGC ( curve, "WEIERSTRASS %s a = %s\n",
222  curve->name, bigint_ntoa ( a ) );
223 
224  /* Initialise "1" */
225  bigint_init ( one, one_raw, sizeof ( one_raw ) );
226 
227  /* Convert relevant constants to Montgomery form
228  *
229  * We rely on the fact that the prime multiples have not yet
230  * been calculated, and so can be used as a temporary buffer.
231  */
232  for ( i = 0 ; i < WEIERSTRASS_NUM_MONT ; i++ ) {
233  static const char *names[] = { " ", " a", "3b" };
234  bigint_multiply ( &mont[i], square, product );
235  bigint_montgomery ( prime, product, &mont[i] );
236  DBGC ( curve, "WEIERSTRASS %s %sR = %s mod N\n",
237  curve->name, names[i], bigint_ntoa ( &mont[i] ) );
238  }
239 
240  /* Calculate constant "N-2"
241  *
242  * We rely on the fact that the prime multiples have not yet
243  * been calculated, and so can be used as a temporary buffer.
244  */
245  bigint_copy ( prime, fermat );
246  bigint_init ( two, two_raw, sizeof ( two_raw ) );
247  bigint_subtract ( two, fermat );
248  DBGC ( curve, "WEIERSTRASS %s N-2 = %s\n",
249  curve->name, bigint_ntoa ( fermat ) );
250 
251  /* Calculate multiples of field prime */
252  for ( i = 1 ; i < WEIERSTRASS_NUM_MULTIPLES ; i++ ) {
253  bigint_copy ( &prime[ i - 1 ], &prime[i] );
254  bigint_add ( &prime[i], &prime[i] );
255  DBGC ( curve, "WEIERSTRASS %s %dN = %s\n",
256  curve->name, ( 1 << i ), bigint_ntoa ( &prime[i] ) );
257  }
258 }
259 
260 /**
261  * Execute bytecode instruction
262  *
263  * @v curve Weierstrass curve
264  * @v regs Registers
265  * @v size Big integer size
266  * @v op Operation
267  */
268 static void weierstrass_exec ( const struct weierstrass_curve *curve,
269  void **regs, unsigned int size,
270  unsigned int op ) {
271  const bigint_t ( size ) __attribute__ (( may_alias ))
272  *prime = ( ( const void * ) curve->prime[0] );
273  bigint_t ( size * 2 ) __attribute__ (( may_alias ))
275  bigint_t ( size ) __attribute__ (( may_alias )) *dest;
276  const bigint_t ( size ) __attribute__ (( may_alias )) *left;
277  const bigint_t ( size ) __attribute__ (( may_alias )) *right;
278  const bigint_t ( size ) __attribute__ (( may_alias )) *addend;
279  const bigint_t ( size ) __attribute__ (( may_alias )) *subtrahend;
280  unsigned int op_code;
281  unsigned int op_dest;
282  unsigned int op_left;
283  unsigned int op_right;
284 
285  /* Decode instruction */
286  op_code = WEIERSTRASS_OPCODE ( op );
287  op_dest = WEIERSTRASS_DEST ( op );
288  op_left = WEIERSTRASS_LEFT ( op );
289  op_right = WEIERSTRASS_RIGHT ( op );
290  dest = regs[op_dest];
291  left = regs[op_left];
292  right = regs[op_right];
293 
294  /* Check destination is a writable register */
295  assert ( op_dest >= WEIERSTRASS_Wt );
296 
297  /* Handle multiplications */
298  if ( op_code == WEIERSTRASS_OP_MUL ) {
299  assert ( op_left != WEIERSTRASS_Wp );
300  assert ( op_right != WEIERSTRASS_Wp );
301  bigint_multiply ( left, right, product );
303  DBGCP ( curve, "WEIERSTRASS %s R%d := R%d x R%d = %s\n",
304  curve->name, op_dest, op_left, op_right,
305  bigint_ntoa ( dest ) );
306  return;
307  }
308 
309  /* Copy left source, if required */
310  if ( op_dest != op_left )
311  bigint_copy ( left, dest );
312 
313  /* Do nothing more if addend/subtrahend is zero */
314  if ( ! op_right ) {
315  DBGCP ( curve, "WEIERSTRASS %s R%d := R%d = %s\n",
316  curve->name, op_dest, op_left, bigint_ntoa ( dest ) );
317  return;
318  }
319 
320  /* Determine addend and subtrahend */
321  addend = NULL;
322  subtrahend = NULL;
323  if ( op_code == WEIERSTRASS_OP_ADD ) {
324  DBGCP ( curve, "WEIERSTRASS %s R%d := R%d + R%d = ",
325  curve->name, op_dest, op_left, op_right );
326  addend = ( ( const void * ) right );
327  } else {
328  subtrahend = ( ( const void * ) right );
329  if ( op_code > WEIERSTRASS_OP_SUB_0N ) {
330  DBGCP ( curve, "WEIERSTRASS %s R%d := R%d - R%d + "
331  "%dN = ", curve->name, op_dest, op_left,
332  op_right, ( 1 << op_code ) );
333  addend = ( ( const void * ) curve->prime[op_code] );
334  } else {
335  DBGCP ( curve, "WEIERSTRASS %s R%d := R%d - R%d = ",
336  curve->name, op_dest, op_left, op_right );
337  }
338  }
339 
340  /* Perform addition and subtraction */
341  if ( addend )
342  bigint_add ( addend, dest );
343  if ( subtrahend )
344  bigint_subtract ( subtrahend, dest );
345  DBGCP ( curve, "%s\n", bigint_ntoa ( dest ) );
346 }
347 
348 /**
349  * Add points on curve
350  *
351  * @v curve Weierstrass curve
352  * @v augend0 Element 0 of point (x1,y1,z1) to be added
353  * @v addend0 Element 0 of point (x2,y2,z2) to be added
354  * @v result0 Element 0 of point (x3,y3,z3) to hold result
355  *
356  * Points are represented in projective coordinates, with all values
357  * in Montgomery form and in the range [0,4N) where N is the field
358  * prime.
359  *
360  * The augend may have the same value as the addend (i.e. this routine
361  * may be used to perform point doubling as well as point addition),
362  * and either or both may be the point at infinity.
363  *
364  * The result may overlap either input, since the inputs are fully
365  * consumed before the result is written.
366  */
367 static void weierstrass_add_raw ( const struct weierstrass_curve *curve,
368  const bigint_element_t *augend0,
369  const bigint_element_t *addend0,
370  bigint_element_t *result0 ) {
371  unsigned int size = curve->size;
372  const bigint_t ( size ) __attribute__ (( may_alias ))
373  *prime = ( ( const void * ) curve->prime[0] );
374  const bigint_t ( size ) __attribute__ (( may_alias ))
375  *a = ( ( const void * ) curve->a );
376  const bigint_t ( size ) __attribute__ (( may_alias ))
377  *b3 = ( ( const void * ) curve->b3 );
378  const weierstrass_t ( size ) __attribute__ (( may_alias ))
379  *augend = ( ( const void * ) augend0 );
380  const weierstrass_t ( size ) __attribute__ (( may_alias ))
381  *addend = ( ( const void * ) addend0 );
382  weierstrass_t ( size ) __attribute__ (( may_alias ))
383  *result = ( ( void * ) result0 );
384  struct {
385  bigint_t ( size ) Wt;
386  bigint_t ( size ) Wxy;
387  bigint_t ( size ) Wyz;
388  bigint_t ( size ) Wzx;
389  bigint_t ( size * 2 ) Wp;
390  } temp;
392  unsigned int schedule;
393  const uint16_t *op;
394  unsigned int i;
395 
396  /* On entry, we assume that x1, x2, y1, y2, z1, z2 are all in
397  * the range [0,4N). Additions will extend the range.
398  * Subtractions will extend the range (and require an addition
399  * of a suitable multiple of the modulus to ensure that the
400  * result is a positive value). Relaxed Montgomery
401  * multiplications will reduce the range to [0,2N). The
402  * outputs x3, y3, z3 will be in the range [0,4N) and
403  * therefore usable as subsequent inputs.
404  */
405  static const uint16_t ops[] = {
406  /* [Wxy] Qxy = (x1+y1)*(x2+y2) (mod 2N) */
407  WEIERSTRASS_ADD3 ( Wt, x1, y1 ),
408  WEIERSTRASS_ADD3 ( Wxy, x2, y2 ),
409  WEIERSTRASS_MUL2 ( Wxy, Wt ),
410  /* [Wyz] Qyz = (y1+z1)*(y2+z2) (mod 2N) */
411  WEIERSTRASS_ADD3 ( Wt, y1, z1 ),
412  WEIERSTRASS_ADD3 ( Wyz, y2, z2 ),
413  WEIERSTRASS_MUL2 ( Wyz, Wt ),
414  /* [Wzx] Qzx = (z1+x1)*(z2+x2) (mod 2N) */
415  WEIERSTRASS_ADD3 ( Wt, z1, x1 ),
416  WEIERSTRASS_ADD3 ( Wzx, z2, x2 ),
417  WEIERSTRASS_MUL2 ( Wzx, Wt ),
418  /* [x3] Px = x1*x2 (mod 2N) */
419  WEIERSTRASS_MUL3 ( x3, x1, x2 ),
420  /* [y3] Py = y1*y2 (mod 2N) */
421  WEIERSTRASS_MUL3 ( y3, y1, y2 ),
422  /* [z3] Pz = z1*z2 (mod 2N) */
423  WEIERSTRASS_MUL3 ( z3, z1, z2 ),
424  /* [Wxy] Rxy = Qxy - Px - Py (mod 6N)
425  * = (x1+y1)*(x2+y2) - x1*x2 - y1*y2 (mod 6N)
426  * = x1*y2 + x2*y1 (mod 6N)
427  */
428  WEIERSTRASS_SUB2 ( Wxy, x3, 0N ),
429  WEIERSTRASS_SUB2 ( Wxy, y3, 4N ),
430  /* [Wyz] Ryz = Qyz - Py - Pz (mod 6N)
431  * = (y1+z1)*(y2+z2) - y1*y2 - z1*z2 (mod 6N)
432  * = y1*z2 + y2*z1 (mod 6N)
433  */
434  WEIERSTRASS_SUB2 ( Wyz, y3, 0N ),
435  WEIERSTRASS_SUB2 ( Wyz, z3, 4N ),
436  /* [Wzx] Rzx = Qzx - Pz - Px (mod 6N)
437  * = (z1+x1)*(z2+x2) - z1*z2 - x1*x2 (mod 6N)
438  * = x1*z2 + x2*z1 (mod 6N)
439  */
440  WEIERSTRASS_SUB2 ( Wzx, z3, 0N ),
441  WEIERSTRASS_SUB2 ( Wzx, x3, 4N ),
442  /* [Wt] aRzx = a * Rzx (mod 2N)
443  * = a * (x1*z2 + x2*z1) (mod 2N)
444  */
445  WEIERSTRASS_MUL3 ( Wt, a, Wzx ),
446  /* [Wp] 3bPz = 3b * Pz (mod 2N)
447  * = 3b*z1*z2 (mod 2N)
448  */
449  WEIERSTRASS_MUL3 ( Wp, 3b, z3 ),
450  /* [Wp] Sy = aRzx + 3bPz (mod 4N)
451  * = a*(x1*z2 + x2*z1) + 3b*z1*z2 (mod 4N)
452  */
453  WEIERSTRASS_ADD2 ( Wp, Wt ),
454  /* [Wt] Syz = Py + Sy (mod 6N)
455  * = y1*y2 + a*(x1*z2 + x2*z1) + 3b*z1*z2 (mod 6N)
456  */
457  WEIERSTRASS_ADD3 ( Wt, y3, Wp ),
458  /* [y3] Sxy = Py - Sy (mod 6N)
459  * = y1*y2 - a*(x1*z2 + x2*z1) - 3b*z1*z2 (mod 6N)
460  */
461  WEIERSTRASS_SUB2 ( y3, Wp, 4N ),
462  /* [z3] aPz = a * Pz (mod 2N)
463  * = a * z1*z2 (mod 2N)
464  */
465  WEIERSTRASS_MUL2 ( z3, a ),
466  /* [Wzx] 3bRzx = 3b * Rzx (mod 2N)
467  * = 3b * (x1*z2 + x2*z1) (mod 2N)
468  */
469  WEIERSTRASS_MUL2 ( Wzx, 3b ),
470  /* [x3] aPzx' = Px - aPz (mod 4N)
471  * = x1*x2 - a*z1*z2 (mod 4N)
472  */
473  WEIERSTRASS_SUB2 ( x3, z3, 2N ),
474  /* [Wp] Szx = a * aPzx' (mod 2N)
475  * = a * (x1*x2 - a*z1*z2) (mod 2N)
476  * = a*x1*x2 - (a^2)*z1*z2 (mod 2N)
477  */
478  WEIERSTRASS_MUL3 ( Wp, a, x3 ),
479  /* [x3] Px = aPzx' + aPz (mod 6N)
480  * = x1*x2 - a*z1*z2 + a*z1*z2 (mod 6N)
481  * = x1*x2 (mod 6N)
482  */
483  WEIERSTRASS_ADD2 ( x3, z3 ),
484  /* [Wzx] Tzx = 3bRzx + Szx (mod 4N)
485  * = a*x1*x2 + 3b*(x1*z2 + x2*z1) -
486  * (a^2)*z1*z2 (mod 4N)
487  */
488  WEIERSTRASS_ADD2 ( Wzx, Wp ),
489  /* [z3] aPzx = Px + aPz (mod 8N)
490  * = x1*x2 + a*z1*z2 (mod 8N)
491  */
492  WEIERSTRASS_ADD2 ( z3, x3 ),
493  /* [x3] 2Px = Px + Px (mod 12N)
494  * = 2*x1*x2 (mod 12N)
495  */
496  WEIERSTRASS_ADD2 ( x3, x3 ),
497  /* [x3] Tyz = 2Px + aPzx (mod 20N)
498  * = 2*x1*x2 + x1*x2 + a*z1*z2 (mod 20N)
499  * = 3*x1*x2 + a*z1*z2 (mod 20N)
500  */
501  WEIERSTRASS_ADD2 ( x3, z3 ),
502  /* [z3] Syz = Syz (mod 6N)
503  * = y1*y2 + a*(x1*z2 + x2*z1) + 3b*z1*z2 (mod 6N)
504  */
505  WEIERSTRASS_MOV ( z3, Wt ),
506  /* [Wt] Tyz = Tyz (mod 20N)
507  * = 3*x1*x2 + a*z1*z2 (mod 20N)
508  */
509  WEIERSTRASS_MOV ( Wt, x3 ),
510  /* [x3] Ux = Rxy * Sxy (mod 2N)
511  * = (x1*y2 + x2*y1) *
512  * (y1*y2 - a*(x1*z2 + x2*z1) - 3b*z1*z2) (mod 2N)
513  */
514  WEIERSTRASS_MUL3 ( x3, Wxy, y3 ),
515  /* [y3] Uy = Syz * Sxy (mod 2N)
516  * = (y1*y2 + a*(x1*z2 + x2*z1) + 3b*z1*z2) *
517  * (y1*y2 - a*(x1*z2 + x2*z1) - 3b*z1*z2) (mod 2N)
518  */
519  WEIERSTRASS_MUL2 ( y3, z3 ),
520  /* [z3] Uz = Ryz * Syz (mod 2N)
521  * = (y1*z2 + y2*z1) *
522  * (y1*y2 + a*(x1*z2 + x2*z1) + 3b*z1*z2) (mod 2N)
523  */
524  WEIERSTRASS_MUL2 ( z3, Wyz ),
525  /* [Wp] Vx = Ryz * Tzx (mod 2N)
526  * = (y1*z2 + y2*z1) *
527  * (a*x1*x2 + 3b*(x1*z2 + x2*z1) - (a^2)*z1*z2)
528  * (mod 2N)
529  */
530  WEIERSTRASS_MUL3 ( Wp, Wyz, Wzx ),
531  /* [x3] x3 = Ux - Vx (mod 4N)
532  * = ((x1*y2 + x2*y1) *
533  * (y1*y2 - a*(x1*z2 + x2*z1) - 3b*z1*z2)) -
534  * ((y1*z2 + y2*z1) *
535  * (a*x1*x2 + 3b*(x1*z2 + x2*z1) - (a^2)*z1*z2))
536  * (mod 4N)
537  */
538  WEIERSTRASS_SUB2 ( x3, Wp, 2N ),
539  /* [Wp] Vy = Tyz * Tzx (mod 2N)
540  * = (3*x1*x2 + a*z1*z2) *
541  * (a*x1*x2 + 3b*(x1*z2 + x2*z1) - (a^2)*z1*z2)
542  * (mod 2N)
543  */
544  WEIERSTRASS_MUL3 ( Wp, Wt, Wzx ),
545  /* [y3] y3 = Vy + Uy (mod 4N)
546  * = ((3*x1*x2 + a*z1*z2) *
547  * (a*x1*x2 + 3b*(x1*z2 + x2*z1) - (a^2)*z1*z2)) +
548  * ((y1*y2 + a*(x1*z2 + x2*z1) + 3b*z1*z2) *
549  * (y1*y2 - a*(x1*z2 + x2*z1) - 3b*z1*z2))
550  * (mod 4N)
551  */
552  WEIERSTRASS_ADD2 ( y3, Wp ),
553  /* [Wp] Vz = Rxy * Tyz (mod 2N)
554  * = (x1*y2 + x2*y1) * (3*x1*x2 + a*z1*z2) (mod 2N)
555  */
556  WEIERSTRASS_MUL3 ( Wp, Wxy, Wt ),
557  /* [z3] z3 = Uz + Vz (mod 4N)
558  * = ((y1*z2 + y2*z1) *
559  * (y1*y2 + a*(x1*z2 + x2*z1) + 3b*z1*z2)) +
560  * ((x1*y2 + x2*y1) * (3*x1*x2 + a*z1*z2))
561  * (mod 4N)
562  */
563  WEIERSTRASS_ADD2 ( z3, Wp ),
564  /* Stop */
566  };
567 
568  /* Initialise register list */
569  regs[WEIERSTRASS_a] = ( ( void * ) a );
570  regs[WEIERSTRASS_3b] = ( ( void * ) b3 );
571  regs[WEIERSTRASS_x1] = ( ( void * ) &augend->x );
572  regs[WEIERSTRASS_x2] = ( ( void * ) &addend->x );
573  regs[WEIERSTRASS_x3] = ( ( void * ) &result->x );
574  regs[WEIERSTRASS_Wt] = &temp;
575  schedule = ( ( ( 1 << WEIERSTRASS_NUM_REGISTERS ) - 1 )
576  - ( 1 << WEIERSTRASS_a )
577  - ( 1 << WEIERSTRASS_3b )
578  - ( 1 << WEIERSTRASS_x1 )
579  - ( 1 << WEIERSTRASS_x2 )
580  - ( 1 << WEIERSTRASS_x3 )
581  - ( 1 << WEIERSTRASS_Wt ) );
582  for ( i = 0 ; schedule ; i++, schedule >>= 1 ) {
583  if ( schedule & 1 )
584  regs[i] = ( regs[ i - 1 ] + sizeof ( *prime ) );
585  }
586  DBGC2 ( curve, "WEIERSTRASS %s augend (%s,",
587  curve->name, bigint_ntoa ( &augend->x ) );
588  DBGC2 ( curve, "%s,", bigint_ntoa ( &augend->y ) );
589  DBGC2 ( curve, "%s)\n", bigint_ntoa ( &augend->z ) );
590  DBGC2 ( curve, "WEIERSTRASS %s addend (%s,",
591  curve->name, bigint_ntoa ( &addend->x ) );
592  DBGC2 ( curve, "%s,", bigint_ntoa ( &addend->y ) );
593  DBGC2 ( curve, "%s)\n", bigint_ntoa ( &addend->z ) );
594 
595  /* Sanity checks */
596  assert ( regs[WEIERSTRASS_a] == a );
597  assert ( regs[WEIERSTRASS_3b] == b3 );
598  assert ( regs[WEIERSTRASS_x1] == &augend->x );
599  assert ( regs[WEIERSTRASS_y1] == &augend->y );
600  assert ( regs[WEIERSTRASS_z1] == &augend->z );
601  assert ( regs[WEIERSTRASS_x2] == &addend->x );
602  assert ( regs[WEIERSTRASS_y2] == &addend->y );
603  assert ( regs[WEIERSTRASS_z2] == &addend->z );
604  assert ( regs[WEIERSTRASS_x3] == &result->x );
605  assert ( regs[WEIERSTRASS_y3] == &result->y );
606  assert ( regs[WEIERSTRASS_z3] == &result->z );
607  assert ( regs[WEIERSTRASS_Wt] == &temp.Wt );
608  assert ( regs[WEIERSTRASS_Wxy] == &temp.Wxy );
609  assert ( regs[WEIERSTRASS_Wyz] == &temp.Wyz );
610  assert ( regs[WEIERSTRASS_Wzx] == &temp.Wzx );
611  assert ( regs[WEIERSTRASS_Wp] == &temp.Wp );
612 
613  /* Execute bytecode instruction sequence */
614  for ( op = ops ; *op != WEIERSTRASS_STOP ; op++ )
615  weierstrass_exec ( curve, regs, size, *op );
616  DBGC2 ( curve, "WEIERSTRASS %s result (%s,",
617  curve->name, bigint_ntoa ( &result->x ) );
618  DBGC2 ( curve, "%s,", bigint_ntoa ( &result->y ) );
619  DBGC2 ( curve, "%s)\n", bigint_ntoa ( &result->z ) );
620 }
621 
622 /**
623  * Add points on curve
624  *
625  * @v curve Weierstrass curve
626  * @v augend Point (x1,y1,z1) to be added
627  * @v addend Point (x2,y2,z2) to be added
628  * @v result0 Point (x3,y3,z3) to hold result
629  */
630 #define weierstrass_add( curve, augend, addend, result ) do { \
631  weierstrass_add_raw ( (curve), (augend)->all.element, \
632  (addend)->all.element, \
633  (result)->all.element ); \
634  } while ( 0 )
635 
636 /**
637  * Add points on curve as part of a Montgomery ladder
638  *
639  * @v operand Element 0 of first input operand (may overlap result)
640  * @v result Element 0 of second input operand and result
641  * @v size Number of elements in operands and result
642  * @v ctx Operation context
643  * @v tmp Temporary working space (not used)
644  */
645 static void weierstrass_add_ladder ( const bigint_element_t *operand0,
646  bigint_element_t *result0,
647  unsigned int size, const void *ctx,
648  void *tmp __unused ) {
649  const struct weierstrass_curve *curve = ctx;
650  const weierstrass_t ( curve->size ) __attribute__ (( may_alias ))
651  *operand = ( ( const void * ) operand0 );
652  weierstrass_t ( curve->size ) __attribute__ (( may_alias ))
653  *result = ( ( void * ) result0 );
654 
655  /* Add curve points */
656  assert ( size == bigint_size ( &operand->all ) );
657  assert ( size == bigint_size ( &result->all ) );
658  weierstrass_add ( curve, operand, result, result );
659 }
660 
661 /**
662  * Verify freshly initialised point is on curve
663  *
664  * @v curve Weierstrass curve
665  * @v point0 Element 0 of point (x,y,z) to be verified
666  * @ret rc Return status code
667  *
668  * As with point addition, points are represented in projective
669  * coordinates, with all values in Montgomery form and in the range
670  * [0,4N) where N is the field prime.
671  *
672  * This verification logic is valid only for points that have been
673  * freshly constructed via weierstrass_init() (i.e. must either have
674  * z=1 or be the point at infinity (0,1,0)).
675  */
676 static int weierstrass_verify_raw ( const struct weierstrass_curve *curve,
677  const bigint_element_t *point0 ) {
678  unsigned int size = curve->size;
679  const bigint_t ( size ) __attribute__ (( may_alias ))
680  *prime = ( ( const void * ) curve->prime[0] );
681  const bigint_t ( size ) __attribute__ (( may_alias ))
682  *a = ( ( const void * ) curve->a );
683  const bigint_t ( size ) __attribute__ (( may_alias ))
684  *b3 = ( ( const void * ) curve->b3 );
685  const weierstrass_t ( size ) __attribute__ (( may_alias ))
686  *point = ( ( const void * ) point0 );
687  struct {
688  bigint_t ( size ) Wt;
689  bigint_t ( size * 2 ) Wp;
690  } temp;
692  const uint16_t *op;
693 
694  /* Calculate 3*(x^3 + a*x + b - y^2) */
695  static const uint16_t ops[] = {
696  /* [Wt] Tx = x^2 (mod 2N) */
697  WEIERSTRASS_MUL3 ( Wt, x1, x1 ),
698  /* [Wt] Txa = Tx + a (mod 3N)
699  * = x^2 + a (mod 3N)
700  */
701  WEIERSTRASS_MOV ( Wp, a ),
702  WEIERSTRASS_ADD2 ( Wt, Wp ),
703  /* [Wt] Txax = Txa * x (mod 2N)
704  * = (x^2 + a)*x (mod 2N)
705  * = x^3 + a*x (mod 2N)
706  */
707  WEIERSTRASS_MUL2 ( Wt, x1 ),
708  /* [Wp] Ty = y^2 (mod 2N) */
709  WEIERSTRASS_MUL3 ( Wp, y1, y1 ),
710  /* [Wt] Txaxy = Txax - Ty (mod 4N)
711  * = x^3 + a*x - y^2 (mod 4N)
712  */
713  WEIERSTRASS_SUB2 ( Wt, Wp, 2N ),
714  /* [Wp] 2Txaxy = Txaxy + Txaxy (mod 8N)
715  * = 2*(x^3 + a*x - y^2) (mod 8N)
716  */
717  WEIERSTRASS_ADD3 ( Wp, Wt, Wt ),
718  /* [Wt] 3Txaxy = 2Txaxy + Txaxy (mod 12N)
719  * = 3*(x^3 + a*x - y^2) (mod 12N)
720  */
721  WEIERSTRASS_ADD2 ( Wt, Wp ),
722  /* [Wt] 3Txaxyb = 3Txaxy + 3b (mod 13N)
723  * = 3*(x^3 + a*x - y^2) + 3b (mod 13N)
724  * = 3*(x^3 + a*x + b - y^2) (mod 13N)
725  */
726  WEIERSTRASS_ADD2 ( Wt, 3b ),
727  /* [Wt] check = 3Txaxyb * z (mod 2N)
728  * = 3*(x^3 + a*x + b - y^2) * z (mod 2N)
729  */
730  WEIERSTRASS_MUL2 ( Wt, z1 ),
731  /* Stop */
733  };
734 
735  /* Initialise register list */
736  regs[WEIERSTRASS_a] = ( ( void * ) a );
737  regs[WEIERSTRASS_3b] = ( ( void * ) b3 );
738  regs[WEIERSTRASS_x1] = ( ( void * ) &point->x );
739  regs[WEIERSTRASS_y1] = ( ( void * ) &point->y );
740  regs[WEIERSTRASS_z1] = ( ( void * ) &point->z );
741  regs[WEIERSTRASS_Wt] = &temp.Wt;
742  regs[WEIERSTRASS_Wp] = &temp.Wp;
743 
744  /* Execute bytecode instruction sequence */
745  for ( op = ops ; *op != WEIERSTRASS_STOP ; op++ )
746  weierstrass_exec ( curve, regs, size, *op );
747 
748  /* Check that result is zero (modulo the field prime) */
749  bigint_grow ( &temp.Wt, &temp.Wp );
750  bigint_montgomery ( prime, &temp.Wp, &temp.Wt );
751  if ( ! bigint_is_zero ( &temp.Wt ) ) {
752  DBGC ( curve, "WEIERSTRASS %s base point is not on curve\n",
753  curve->name );
754  return -EINVAL;
755  }
756 
757  return 0;
758 }
759 
760 /**
761  * Verify freshly initialised point is on curve
762  *
763  * @v curve Weierstrass curve
764  * @v point Point (x,y,z) to be verified
765  * @ret rc Return status code
766  */
767 #define weierstrass_verify( curve, point ) ( { \
768  weierstrass_verify_raw ( (curve), (point)->all.element ); \
769  } )
770 
771 /**
772  * Initialise curve point
773  *
774  * @v curve Weierstrass curve
775  * @v point0 Element 0 of point (x,y,z) to be filled in
776  * @v temp0 Element 0 of temporary point buffer
777  * @v data Raw curve point
778  * @ret rc Return status code
779  */
780 static int weierstrass_init_raw ( struct weierstrass_curve *curve,
781  bigint_element_t *point0,
782  bigint_element_t *temp0, const void *data ) {
783  unsigned int size = curve->size;
784  size_t len = curve->len;
785  const bigint_t ( size ) __attribute__ (( may_alias )) *prime =
786  ( ( const void * ) curve->prime[0] );
787  const bigint_t ( size ) __attribute__ (( may_alias )) *prime2 =
788  ( ( const void * ) curve->prime[WEIERSTRASS_2N] );
789  const bigint_t ( size ) __attribute__ (( may_alias )) *square =
790  ( ( const void * ) curve->square );
791  const bigint_t ( size ) __attribute__ (( may_alias )) *one =
792  ( ( const void * ) curve->one );
793  weierstrass_t ( size ) __attribute__ (( may_alias ))
794  *point = ( ( void * ) point0 );
795  union {
796  bigint_t ( size * 2 ) product;
797  weierstrass_t ( size ) point;
798  } __attribute__ (( may_alias )) *temp = ( ( void * ) temp0 );
799  size_t offset;
800  int is_infinite;
801  unsigned int i;
802  int rc;
803 
804  /* Initialise curve, if not already done
805  *
806  * The least significant element of the field prime must be
807  * odd, and so the least significant element of the
808  * (initialised) first multiple of the field prime must be
809  * non-zero.
810  */
811  if ( ! prime2->element[0] )
812  weierstrass_init_curve ( curve );
813 
814  /* Convert input to projective coordinates in Montgomery form */
815  DBGC ( curve, "WEIERSTRASS %s point (", curve->name );
816  for ( i = 0, offset = 0 ; i < WEIERSTRASS_AXES ; i++, offset += len ) {
817  bigint_init ( &point->axis[i], ( data + offset ), len );
818  DBGC ( curve, "%s%s", ( i ? "," : "" ),
819  bigint_ntoa ( &point->axis[i] ) );
820  bigint_multiply ( &point->axis[i], square, &temp->product );
821  bigint_montgomery_relaxed ( prime, &temp->product,
822  &point->axis[i] );
823  }
824  memset ( &point->z, 0, sizeof ( point->z ) );
825  is_infinite = bigint_is_zero ( &point->xy );
826  bigint_copy ( one, &point->axis[ is_infinite ? 1 : 2 ] );
827  DBGC ( curve, ")\n" );
828 
829  /* Verify point is on curve */
830  if ( ( rc = weierstrass_verify ( curve, point ) ) != 0 )
831  return rc;
832 
833  return 0;
834 }
835 
836 /**
837  * Initialise curve point
838  *
839  * @v curve Weierstrass curve
840  * @v point Point (x,y,z) to be filled in
841  * @v temp Temporary point buffer
842  * @v data Raw curve point
843  * @ret rc Return status code
844  */
845 #define weierstrass_init( curve, point, temp, data ) ( { \
846  weierstrass_init_raw ( (curve), (point)->all.element, \
847  (temp)->all.element, (data) ); \
848  } )
849 
850 /**
851  * Finalise curve point
852  *
853  * @v curve Weierstrass curve
854  * @v point0 Element 0 of point (x,y,z)
855  * @v temp0 Element 0 of temporary point buffer
856  * @v out Output buffer
857  */
858 static void weierstrass_done_raw ( struct weierstrass_curve *curve,
859  bigint_element_t *point0,
860  bigint_element_t *temp0, void *out ) {
861  unsigned int size = curve->size;
862  size_t len = curve->len;
863  const bigint_t ( size ) __attribute__ (( may_alias )) *prime =
864  ( ( const void * ) curve->prime[0] );
865  const bigint_t ( size ) __attribute__ (( may_alias )) *fermat =
866  ( ( const void * ) curve->fermat );
867  const bigint_t ( size ) __attribute__ (( may_alias )) *one =
868  ( ( const void * ) curve->one );
869  weierstrass_t ( size ) __attribute__ (( may_alias ))
870  *point = ( ( void * ) point0 );
871  union {
872  bigint_t ( size * 2 ) product;
873  weierstrass_t ( size ) point;
874  } __attribute__ (( may_alias )) *temp = ( ( void * ) temp0 );
875  size_t offset;
876  unsigned int i;
877 
878  /* Invert result Z co-ordinate (via Fermat's little theorem) */
879  bigint_copy ( one, &temp->point.z );
880  bigint_ladder ( &temp->point.z, &point->z, fermat,
881  bigint_mod_exp_ladder, prime, &temp->product );
882 
883  /* Convert result back to affine co-ordinates */
884  DBGC ( curve, "WEIERSTRASS %s result (", curve->name );
885  for ( i = 0, offset = 0 ; i < WEIERSTRASS_AXES ; i++, offset += len ) {
886  bigint_multiply ( &point->axis[i], &temp->point.z,
887  &temp->product );
888  bigint_montgomery_relaxed ( prime, &temp->product,
889  &point->axis[i] );
890  bigint_grow ( &point->axis[i], &temp->product );
891  bigint_montgomery ( prime, &temp->product, &point->axis[i] );
892  DBGC ( curve, "%s%s", ( i ? "," : "" ),
893  bigint_ntoa ( &point->axis[i] ) );
894  bigint_done ( &point->axis[i], ( out + offset ), len );
895  }
896  DBGC ( curve, ")\n" );
897 }
898 
899 /**
900  * Finalise curve point
901  *
902  * @v curve Weierstrass curve
903  * @v point Point (x,y,z)
904  * @v temp Temporary point buffer
905  * @v out Output buffer
906  * @ret rc Return status code
907  */
908 #define weierstrass_done( curve, point, temp, out ) ( { \
909  weierstrass_done_raw ( (curve), (point)->all.element, \
910  (temp)->all.element, (out) ); \
911  } )
912 
913 /**
914  * Check if this is the point at infinity
915  *
916  * @v point Curve point
917  * @ret is_infinity This is the point at infinity
918  */
920  const void *point ) {
921  unsigned int size = curve->size;
922  size_t len = curve->len;
923  struct {
924  bigint_t ( size ) axis;
925  } temp;
926  size_t offset;
927  int is_finite = 0;
928  unsigned int i;
929 
930  /* We use all zeroes to represent the point at infinity */
931  DBGC ( curve, "WEIERSTRASS %s point (", curve->name );
932  for ( i = 0, offset = 0 ; i < WEIERSTRASS_AXES ; i++, offset += len ) {
933  bigint_init ( &temp.axis, ( point + offset ), len );
934  DBGC ( curve, "%s%s", ( i ? "," : "" ),
935  bigint_ntoa ( &temp.axis ) );
936  is_finite |= ( ! bigint_is_zero ( &temp.axis ) );
937  }
938  DBGC ( curve, ") is%s infinity\n", ( is_finite ? " not" : "" ) );
939 
940  return ( ! is_finite );
941 }
942 
943 /**
944  * Multiply curve point by scalar
945  *
946  * @v curve Weierstrass curve
947  * @v base Base point
948  * @v scalar Scalar multiple
949  * @v result Result point to fill in
950  * @ret rc Return status code
951  */
952 int weierstrass_multiply ( struct weierstrass_curve *curve, const void *base,
953  const void *scalar, void *result ) {
954  unsigned int size = curve->size;
955  size_t len = curve->len;
956  const bigint_t ( size ) __attribute__ (( may_alias )) *one =
957  ( ( const void * ) curve->one );
958  struct {
960  weierstrass_t ( size ) multiple;
961  bigint_t ( bigint_required_size ( len ) ) scalar;
962  } temp;
963  int rc;
964 
965  /* Convert input to projective coordinates in Montgomery form */
966  if ( ( rc = weierstrass_init ( curve, &temp.multiple, &temp.result,
967  base ) ) != 0 ) {
968  return rc;
969  }
970 
971  /* Construct identity element (the point at infinity) */
972  memset ( &temp.result, 0, sizeof ( temp.result ) );
973  bigint_copy ( one, &temp.result.y );
974 
975  /* Initialise scalar */
976  bigint_init ( &temp.scalar, scalar, len );
977  DBGC ( curve, "WEIERSTRASS %s scalar %s\n",
978  curve->name, bigint_ntoa ( &temp.scalar ) );
979 
980  /* Perform multiplication via Montgomery ladder */
981  bigint_ladder ( &temp.result.all, &temp.multiple.all, &temp.scalar,
982  weierstrass_add_ladder, curve, NULL );
983 
984  /* Convert result back to affine co-ordinates */
985  weierstrass_done ( curve, &temp.result, &temp.multiple, result );
986 
987  return 0;
988 }
989 
990 /**
991  * Add curve points (as a one-off operation)
992  *
993  * @v curve Weierstrass curve
994  * @v addend Curve point to add
995  * @v augend Curve point to add
996  * @v result Curve point to hold result
997  * @ret rc Return status code
998  */
1000  const void *addend, const void *augend,
1001  void *result ) {
1002  unsigned int size = curve->size;
1003  struct {
1004  weierstrass_t ( size ) addend;
1005  weierstrass_t ( size ) augend;
1007  } temp;
1008  int rc;
1009 
1010  /* Convert inputs to projective coordinates in Montgomery form */
1011  if ( ( rc = weierstrass_init ( curve, &temp.addend, &temp.result,
1012  addend ) ) != 0 ) {
1013  return rc;
1014  }
1015  if ( ( rc = weierstrass_init ( curve, &temp.augend, &temp.result,
1016  augend ) ) != 0 ) {
1017  return rc;
1018  }
1019 
1020  /* Add curve points */
1021  weierstrass_add ( curve, &temp.augend, &temp.addend, &temp.result );
1022 
1023  /* Convert result back to affine co-ordinates */
1024  weierstrass_done ( curve, &temp.result, &temp.addend, result );
1025 
1026  return 0;
1027 }
#define weierstrass_init(curve, point, temp, data)
Initialise curve point.
Definition: weierstrass.c:845
#define __attribute__(x)
Definition: compiler.h:10
uint32_t base
Base.
Definition: librm.h:138
#define EINVAL
Invalid argument.
Definition: errno.h:429
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
unsigned short uint16_t
Definition: stdint.h:11
bigint_element_t * square
Cached Montgomery constant (R^2 mod N)
Definition: weierstrass.h:113
#define WEIERSTRASS_RIGHT(op)
Extract right source big integer register.
Definition: weierstrass.c:135
#define WEIERSTRASS_STOP
Define a stop operation.
Definition: weierstrass.c:159
weierstrass_register
Big integer register names.
Definition: weierstrass.c:52
bigint_element_t * prime[WEIERSTRASS_NUM_CACHED]
Cached field prime "N" (and multiples thereof)
Definition: weierstrass.h:109
Error codes.
static void weierstrass_exec(const struct weierstrass_curve *curve, void **regs, unsigned int size, unsigned int op)
Execute bytecode instruction.
Definition: weierstrass.c:268
uint16_t size
Buffer size.
Definition: dwmac.h:14
#define WEIERSTRASS_AXES
Number of axes in Weierstrass curve point representation.
Definition: weierstrass.h:17
bigint_element_t * mont[WEIERSTRASS_NUM_MONT]
Definition: weierstrass.h:124
#define WEIERSTRASS_OPCODE(op)
Extract bytecode operation code.
Definition: weierstrass.c:126
Weierstrass elliptic curves.
#define DBGC(...)
Definition: compiler.h:505
#define bigint_grow(source, dest)
Grow big integer.
Definition: bigint.h:209
#define bigint_init(value, data, len)
Initialise big integer.
Definition: bigint.h:62
#define weierstrass_verify(curve, point)
Verify freshly initialised point is on curve.
Definition: weierstrass.c:767
struct golan_eq_context ctx
Definition: CIB_PRM.h:28
#define bigint_is_zero(value)
Test if big integer is equal to zero.
Definition: bigint.h:134
#define bigint_montgomery_relaxed(modulus, value, result)
Perform relaxed Montgomery reduction (REDC) of a big integer.
Definition: bigint.h:300
__be32 out[4]
Definition: CIB_PRM.h:36
bigint_element_t * b3
Cached constant "3b", in Montgomery form.
Definition: weierstrass.h:122
static void weierstrass_done_raw(struct weierstrass_curve *curve, bigint_element_t *point0, bigint_element_t *temp0, void *out)
Finalise curve point.
Definition: weierstrass.c:858
static void weierstrass_init_curve(struct weierstrass_curve *curve)
Initialise curve.
Definition: weierstrass.c:174
unsigned long tmp
Definition: linux_pci.h:65
Add big integers.
Definition: weierstrass.c:106
#define WEIERSTRASS_MOV(dest, source)
Define a move operation.
Definition: weierstrass.c:146
static void weierstrass_add_ladder(const bigint_element_t *operand0, bigint_element_t *result0, unsigned int size, const void *ctx, void *tmp __unused)
Add points on curve as part of a Montgomery ladder.
Definition: weierstrass.c:645
#define weierstrass_add(curve, augend, addend, result)
Add points on curve.
Definition: weierstrass.c:630
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define weierstrass_t(size)
Define a Weierstrass projective co-ordinate type.
Definition: weierstrass.h:58
#define weierstrass_done(curve, point, temp, out)
Finalise curve point.
Definition: weierstrass.c:908
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
#define bigint_copy(source, dest)
Copy big integer.
Definition: bigint.h:235
uint32_t bigint_element_t
Element of a big integer.
Definition: bigint.h:16
ring len
Length.
Definition: dwmac.h:231
#define WEIERSTRASS_MUL3(dest, multiplicand, multiplier)
Define a three-argument multiplication operation.
Definition: weierstrass.c:162
static void weierstrass_add_raw(const struct weierstrass_curve *curve, const bigint_element_t *augend0, const bigint_element_t *addend0, bigint_element_t *result0)
Add points on curve.
Definition: weierstrass.c:367
bigint_element_t * fermat
Cached constant "N-2" (for Fermat's little theorem)
Definition: weierstrass.h:111
const uint8_t * b_raw
Constant "b".
Definition: weierstrass.h:104
int weierstrass_add_once(struct weierstrass_curve *curve, const void *addend, const void *augend, void *result)
Add curve points (as a one-off operation)
Definition: weierstrass.c:999
#define bigint_done(value, out, len)
Finalise big integer.
Definition: bigint.h:75
Subtract big integers (and add 2N)
Definition: weierstrass.c:102
bigint_element_t * a
Cached constant "a", in Montgomery form.
Definition: weierstrass.h:120
#define bigint_required_size(len)
Determine number of elements required for a big-integer type.
Definition: bigint.h:31
#define WEIERSTRASS_NUM_MONT
Number of cached in Montgomery form for each Weierstrass curve.
Definition: weierstrass.h:79
const char * name
Curve name.
Definition: weierstrass.h:96
FILE_SECBOOT(PERMITTED)
unsigned char uint8_t
Definition: stdint.h:10
#define WEIERSTRASS_SUB2(minuend, subtrahend, multiple)
Define a two-argument subtraction operation.
Definition: weierstrass.c:155
size_t len
Length of raw scalar values.
Definition: weierstrass.h:98
struct i386_regs regs
Definition: registers.h:15
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
bigint_element_t * one
Cached constant "1", in Montgomery form.
Definition: weierstrass.h:118
int weierstrass_is_infinity(struct weierstrass_curve *curve, const void *point)
Check if this is the point at infinity.
Definition: weierstrass.c:919
uint16_t result
Definition: hyperv.h:33
Subtract big integers (and add nothing)
Definition: weierstrass.c:100
static uint16_t struct vmbus_xfer_pages_operations * op
Definition: netvsc.h:327
static int weierstrass_init_raw(struct weierstrass_curve *curve, bigint_element_t *point0, bigint_element_t *temp0, const void *data)
Initialise curve point.
Definition: weierstrass.c:780
#define bigint_montgomery(modulus, value, result)
Perform classic Montgomery reduction (REDC) of a big integer.
Definition: bigint.h:314
#define DBGC2(...)
Definition: compiler.h:522
#define bigint_size(bigint)
Determine number of elements in big-integer type.
Definition: bigint.h:41
#define bigint_multiply(multiplicand, multiplier, result)
Multiply big integers.
Definition: bigint.h:260
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:151
uint8_t data[48]
Additional event data.
Definition: ena.h:22
#define DBGCP(...)
Definition: compiler.h:539
#define bigint_reduce(modulus, result)
Reduce big integer R^2 modulo N.
Definition: bigint.h:274
uint8_t product
Product string.
Definition: smbios.h:17
#define WEIERSTRASS_MUL2(multiplicand, multiplier)
Define a two-argument multiplication operation.
Definition: weierstrass.c:166
#define WEIERSTRASS_LEFT(op)
Extract left source big integer register.
Definition: weierstrass.c:132
#define bigint_ladder(result, multiple, exponent, op, ctx, tmp)
Perform generalised exponentiation via a Montgomery ladder.
Definition: bigint.h:330
const unsigned int size
Number of elements in scalar values.
Definition: weierstrass.h:94
#define WEIERSTRASS_DEST(op)
Extract destination big integer register.
Definition: weierstrass.c:129
Multiply big integers (and perform Montgomery reduction)
Definition: weierstrass.c:108
static int weierstrass_verify_raw(const struct weierstrass_curve *curve, const bigint_element_t *point0)
Verify freshly initialised point is on curve.
Definition: weierstrass.c:676
weierstrass_opcode
Bytecode operation codes.
Definition: weierstrass.c:98
Subtract big integers (and add 4N)
Definition: weierstrass.c:104
uint16_t offset
Offset to command line.
Definition: bzimage.h:8
#define WEIERSTRASS_ADD3(dest, augend, addend)
Define a three-argument addition operation.
Definition: weierstrass.c:138
#define bigint_subtract(subtrahend, value)
Subtract big integers.
Definition: bigint.h:99
int weierstrass_multiply(struct weierstrass_curve *curve, const void *base, const void *scalar, void *result)
Multiply curve point by scalar.
Definition: weierstrass.c:952
#define bigint_add(addend, value)
Add big integers.
Definition: bigint.h:87
#define bigint_ntoa(value)
Transcribe big integer (for debugging)
Definition: bigint.h:50
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322
const uint8_t * prime_raw
Field prime.
Definition: weierstrass.h:100
#define WEIERSTRASS_ADD2(augend, addend)
Define a two-argument addition operation.
Definition: weierstrass.c:142
typedef bigint_t(X25519_SIZE) x25519_t
An X25519 unsigned big integer used in internal calculations.
const uint8_t * a_raw
Constant "a".
Definition: weierstrass.h:102
void * memset(void *dest, int character, size_t len) __nonnull
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
A Weierstrass elliptic curve.
Definition: weierstrass.h:92