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 <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 */
174static 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 */
268static 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 */
367static 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 */
645static 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 */
676static 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 */
780static 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 */
858static 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 */
952int 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,
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 NULL
NULL pointer (VOID *)
Definition Base.h:322
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:16
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:720
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:573
#define DBGC2(...)
Definition compiler.h:522
#define DBGCP(...)
Definition compiler.h:539
#define DBGC(...)
Definition compiler.h:505
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:896
#define EINVAL
Invalid argument.
Definition errno.h:429
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
#define __attribute__(x)
Definition compiler.h:10
#define bigint_grow(source, dest)
Grow big integer.
Definition bigint.h:209
#define bigint_ladder(result, multiple, exponent, op, ctx, tmp)
Perform generalised exponentiation via a Montgomery ladder.
Definition bigint.h:330
#define bigint_montgomery_relaxed(modulus, value, result)
Perform relaxed Montgomery reduction (REDC) of a big integer.
Definition bigint.h:300
#define bigint_size(bigint)
Determine number of elements in big-integer type.
Definition bigint.h:41
#define bigint_reduce(modulus, result)
Reduce big integer R^2 modulo N.
Definition bigint.h:274
#define bigint_subtract(subtrahend, value)
Subtract big integers.
Definition bigint.h:99
#define bigint_montgomery(modulus, value, result)
Perform classic Montgomery reduction (REDC) of a big integer.
Definition bigint.h:314
#define bigint_copy(source, dest)
Copy big integer.
Definition bigint.h:235
#define bigint_is_zero(value)
Test if big integer is equal to zero.
Definition bigint.h:134
#define bigint_t(size)
Define a big-integer type.
Definition bigint.h:20
#define bigint_required_size(len)
Determine number of elements required for a big-integer type.
Definition bigint.h:31
#define bigint_multiply(multiplicand, multiplier, result)
Multiply big integers.
Definition bigint.h:260
#define bigint_done(value, out, len)
Finalise big integer.
Definition bigint.h:75
#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 bigint_init(value, data, len)
Initialise big integer.
Definition bigint.h:62
uint8_t product
Product string.
Definition smbios.h:5
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
A Weierstrass elliptic curve.
Definition weierstrass.h:92
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:98
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:94
const char * name
Curve name.
Definition weierstrass.h:96
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.
int weierstrass_is_infinity(struct weierstrass_curve *curve, const void *point)
Check if this is the point at infinity.
#define WEIERSTRASS_STOP
Define a stop operation.
#define WEIERSTRASS_DEST(op)
Extract destination big integer register.
#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.
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.
#define weierstrass_add(curve, augend, addend, result)
Add points on curve.
#define WEIERSTRASS_ADD3(dest, augend, addend)
Define a three-argument addition operation.
#define WEIERSTRASS_RIGHT(op)
Extract right source big integer register.
#define WEIERSTRASS_MUL2(multiplicand, multiplier)
Define a two-argument multiplication operation.
#define WEIERSTRASS_MOV(dest, source)
Define a move operation.
weierstrass_register
Big integer register names.
Definition weierstrass.c:52
@ WEIERSTRASS_Wt
Definition weierstrass.c:76
@ WEIERSTRASS_x3
Definition weierstrass.c:83
@ WEIERSTRASS_NUM_REGISTERS
Definition weierstrass.c:88
@ WEIERSTRASS_a
Definition weierstrass.c:59
@ WEIERSTRASS_y2
Definition weierstrass.c:68
@ WEIERSTRASS_3b
Definition weierstrass.c:61
@ WEIERSTRASS_Wp
Definition weierstrass.c:81
@ WEIERSTRASS_Wxy
Definition weierstrass.c:77
@ WEIERSTRASS_y3
Definition weierstrass.c:84
@ WEIERSTRASS_Wyz
Definition weierstrass.c:78
@ WEIERSTRASS_y1
Definition weierstrass.c:64
@ WEIERSTRASS_x2
Definition weierstrass.c:67
@ WEIERSTRASS_z3
Definition weierstrass.c:85
@ WEIERSTRASS_x1
Definition weierstrass.c:63
@ WEIERSTRASS_z2
Definition weierstrass.c:69
@ WEIERSTRASS_Wzx
Definition weierstrass.c:79
@ WEIERSTRASS_z1
Definition weierstrass.c:65
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:98
@ 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)
static int weierstrass_verify_raw(const struct weierstrass_curve *curve, const bigint_element_t *point0)
Verify freshly initialised point is on curve.
#define WEIERSTRASS_LEFT(op)
Extract left source big integer register.
#define WEIERSTRASS_OPCODE(op)
Extract bytecode operation code.
static void weierstrass_exec(const struct weierstrass_curve *curve, void **regs, unsigned int size, unsigned int op)
Execute bytecode instruction.
int weierstrass_multiply(struct weierstrass_curve *curve, const void *base, const void *scalar, void *result)
Multiply curve point by scalar.
#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_add_once(struct weierstrass_curve *curve, const void *addend, const void *augend, void *result)
Add curve points (as a one-off operation)
static void weierstrass_init_curve(struct weierstrass_curve *curve)
Initialise curve.
static void weierstrass_done_raw(struct weierstrass_curve *curve, bigint_element_t *point0, bigint_element_t *temp0, void *out)
Finalise curve point.
static int weierstrass_init_raw(struct weierstrass_curve *curve, bigint_element_t *point0, bigint_element_t *temp0, const void *data)
Initialise curve point.
#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:17
#define weierstrass_t(size)
Define a Weierstrass projective co-ordinate type.
Definition weierstrass.h:58
#define WEIERSTRASS_NUM_MONT
Number of cached in Montgomery form for each Weierstrass curve.
Definition weierstrass.h:79
@ WEIERSTRASS_2N
Definition weierstrass.h:73
@ WEIERSTRASS_4N
Definition weierstrass.h:74
@ WEIERSTRASS_NUM_MULTIPLES
Definition weierstrass.h:75