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