iPXE
x25519.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 * X25519 key exchange
30 *
31 * This implementation is inspired by and partially based upon the
32 * paper "Implementing Curve25519/X25519: A Tutorial on Elliptic Curve
33 * Cryptography" by Martin Kleppmann, available for download from
34 * https://www.cl.cam.ac.uk/teaching/2122/Crypto/curve25519.pdf
35 *
36 * The underlying modular addition, subtraction, and multiplication
37 * operations are completely redesigned for substantially improved
38 * efficiency compared to the TweetNaCl implementation studied in that
39 * paper.
40 *
41 * TweetNaCl iPXE
42 * --------- ----
43 *
44 * Storage size of each big integer 128 40
45 * (in bytes)
46 *
47 * Stack usage for key exchange 1144 360
48 * (in bytes, large objects only)
49 *
50 * Cost of big integer addition 16 5
51 * (in number of 64-bit additions)
52 *
53 * Cost of big integer multiplication 273 31
54 * (in number of 64-bit multiplications)
55 *
56 * The implementation is constant-time (provided that the underlying
57 * big integer operations are also constant-time).
58 */
59
60#include <stdint.h>
61#include <string.h>
62#include <assert.h>
63#include <errno.h>
64#include <ipxe/init.h>
65#include <ipxe/crypto.h>
66#include <ipxe/x25519.h>
67
68/** X25519 reduction constant
69 *
70 * The X25519 field prime is p=2^255-19. This gives us:
71 *
72 * p = 2^255 - 19
73 * 2^255 = p + 19
74 * 2^255 = 19 (mod p)
75 * k * 2^255 = k * 19 (mod p)
76 *
77 * We can therefore reduce a value modulo p by taking the high-order
78 * bits of the value from bit 255 and above, multiplying by 19, and
79 * adding this to the low-order 255 bits of the value.
80 *
81 * This would be cumbersome to do in practice since it would require
82 * partitioning the value at a 255-bit boundary (and hence would
83 * require some shifting and masking operations). However, we can
84 * note that:
85 *
86 * k * 2^255 = k * 19 (mod p)
87 * k * 2 * 2^255 = k * 2 * 19 (mod p)
88 * k * 2^256 = k * 38 (mod p)
89 *
90 * We can therefore simplify the reduction to taking the high order
91 * bits of the value from bit 256 and above, multiplying by 38, and
92 * adding this to the low-order 256 bits of the value.
93 *
94 * Since 256 will inevitably be a multiple of the big integer element
95 * size (typically 32 or 64 bits), this avoids the need to perform any
96 * shifting or masking operations.
97 */
98#define X25519_REDUCE_256 38
99
100/** X25519 multiplication step 1 result
101 *
102 * Step 1 of X25519 multiplication is to compute the product of two
103 * X25519 unsigned 258-bit integers.
104 *
105 * Both multiplication inputs are limited to 258 bits, and so the
106 * product will have at most 516 bits.
107 */
109 /** Raw product
110 *
111 * Big integer multiplication produces a result with a number
112 * of elements equal to the sum of the number of elements in
113 * each input.
114 */
116 /** Partition into low-order and high-order bits
117 *
118 * Reduction modulo p requires separating the low-order 256
119 * bits from the remaining high-order bits.
120 *
121 * Since the value will never exceed 516 bits (see above),
122 * there will be at most 260 high-order bits.
123 */
124 struct {
125 /** Low-order 256 bits */
126 bigint_t ( bigint_required_size ( ( 256 /* bits */ + 7 ) / 8 ) )
127 low_256bit;
128 /** High-order 260 bits */
129 bigint_t ( bigint_required_size ( ( 260 /* bits */ + 7 ) / 8 ) )
130 high_260bit;
131 } __attribute__ (( packed )) parts;
132};
133
134/** X25519 multiplication step 2 result
135 *
136 * Step 2 of X25519 multiplication is to multiply the high-order 260
137 * bits from step 1 with the 6-bit reduction constant 38, and to add
138 * this to the low-order 256 bits from step 1.
139 *
140 * The multiplication inputs are limited to 260 and 6 bits
141 * respectively, and so the product will have at most 266 bits. After
142 * adding the low-order 256 bits from step 1, the result will have at
143 * most 267 bits.
144 */
146 /** Raw product
147 *
148 * Big integer multiplication produces a result with a number
149 * of elements equal to the sum of the number of elements in
150 * each input.
151 */
152 bigint_t ( bigint_required_size ( ( 260 /* bits */ + 7 ) / 8 ) +
153 bigint_required_size ( ( 6 /* bits */ + 7 ) / 8 ) ) product;
154 /** Big integer value
155 *
156 * The value will never exceed 267 bits (see above), and so
157 * may be consumed as a normal X25519 big integer.
158 */
159 x25519_t value;
160 /** Partition into low-order and high-order bits
161 *
162 * Reduction modulo p requires separating the low-order 256
163 * bits from the remaining high-order bits.
164 *
165 * Since the value will never exceed 267 bits (see above),
166 * there will be at most 11 high-order bits.
167 */
168 struct {
169 /** Low-order 256 bits */
170 bigint_t ( bigint_required_size ( ( 256 /* bits */ + 7 ) / 8 ) )
171 low_256bit;
172 /** High-order 11 bits */
173 bigint_t ( bigint_required_size ( ( 11 /* bits */ + 7 ) / 8 ) )
174 high_11bit;
175 } __attribute__ (( packed )) parts;
176};
177
178/** X25519 multiplication step 3 result
179 *
180 * Step 3 of X25519 multiplication is to multiply the high-order 11
181 * bits from step 2 with the 6-bit reduction constant 38, and to add
182 * this to the low-order 256 bits from step 2.
183 *
184 * The multiplication inputs are limited to 11 and 6 bits
185 * respectively, and so the product will have at most 17 bits. After
186 * adding the low-order 256 bits from step 2, the result will have at
187 * most 257 bits.
188 */
190 /** Raw product
191 *
192 * Big integer multiplication produces a result with a number
193 * of elements equal to the sum of the number of elements in
194 * each input.
195 */
196 bigint_t ( bigint_required_size ( ( 11 /* bits */ + 7 ) / 8 ) +
197 bigint_required_size ( ( 6 /* bits */ + 7 ) / 8 ) ) product;
198 /** Big integer value
199 *
200 * The value will never exceed 267 bits (see above), and so
201 * may be consumed as a normal X25519 big integer.
202 */
203 x25519_t value;
204};
205
206/** X25519 multiplication temporary working space
207 *
208 * We overlap the buffers used by each step of the multiplication
209 * calculation to reduce the total stack space required:
210 *
211 * |--------------------------------------------------------|
212 * | <- pad -> | <------------ step 1 result -------------> |
213 * | | <- low 256 bits -> | <-- high 260 bits --> |
214 * | <------- step 2 result ------> | <-- step 3 result --> |
215 * |--------------------------------------------------------|
216 */
218 /** Step 1 result */
219 struct {
220 /** Padding to avoid collision between steps 1 and 2
221 *
222 * The step 2 multiplication consumes the high 260
223 * bits of step 1, and so the step 2 multiplication
224 * result must not overlap this portion of the step 1
225 * result.
226 */
229 parts.high_260bit ) ];
230 /** Step 1 result */
232 } __attribute__ (( packed ));
233 /** Steps 2 and 3 results */
234 struct {
235 /** Step 2 result */
237 /** Step 3 result */
239 } __attribute__ (( packed ));
240};
241
242/** An X25519 elliptic curve point in projective coordinates
243 *
244 * A point (x,y) on the Montgomery curve used in X25519 is represented
245 * using projective coordinates (X/Z,Y/Z) so that intermediate
246 * calculations may be performed on both numerator and denominator
247 * separately, with the division step performed only once at the end
248 * of the calculation.
249 *
250 * The group operation calculation is performed using a Montgomery
251 * ladder as:
252 *
253 * X[2i] = ( X[i]^2 - Z[i]^2 )^2
254 * X[2i+1] = ( X[i] * X[i+1] - Z[i] * Z[i+1] )^2
255 * Z[2i] = 4 * X[i] * Z[i] * ( X[i]^2 + A * X[i] * Z[i] + Z[i]^2 )
256 * Z[2i+1] = X[0] * ( X[i] * Z[i+1] - X[i+1] * Z[i] ) ^ 2
257 *
258 * It is therefore not necessary to store (or use) the value of Y.
259 */
261 /** X coordinate */
263 /** Z coordinate */
265};
266
267/** An X25519 Montgomery ladder step */
269 /** X[n]/Z[n] */
271 /** X[n+1]/Z[n+1] */
273};
274
275/** Constant p=2^255-19 (the finite field prime) */
276static const uint8_t x25519_p_raw[] = {
277 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
278 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
279 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
280 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xed
281};
282
283/** Constant p=2^255-19 (the finite field prime) */
284static x25519_t x25519_p;
285
286/** Constant 2p=2^256-38 */
287static x25519_t x25519_2p;
288
289/** Constant 4p=2^257-76 */
290static x25519_t x25519_4p;
291
292/** Reduction constant (used during multiplication) */
294
295/** Reduction constant (used during multiplication) */
297 x25519_reduce_256;
298
299/** Constant 121665 (used in the Montgomery ladder) */
300static const uint8_t x25519_121665_raw[] = { 0x01, 0xdb, 0x41 };
301
302/** Constant 121665 (used in the Montgomery ladder) */
304
305/** Constant g=9 (the group generator) */
307 .raw = { 9, }
308};
309
310/**
311 * Initialise constants
312 *
313 */
314static void x25519_init_constants ( void ) {
315
316 /* Construct constant p */
318
319 /* Construct constant 2p */
322
323 /* Construct constant 4p */
326
327 /* Construct reduction constant */
328 bigint_init ( &x25519_reduce_256, x25519_reduce_256_raw,
329 sizeof ( x25519_reduce_256_raw ) );
330
331 /* Construct constant 121665 */
332 bigint_init ( &x25519_121665.value, x25519_121665_raw,
333 sizeof ( x25519_121665_raw ) );
334}
335
336/** Initialisation function */
337struct init_fn x25519_init_fn __init_fn ( INIT_NORMAL ) = {
338 .name = "x25519",
339 .initialise = x25519_init_constants,
340};
341
342/**
343 * Add big integers modulo field prime
344 *
345 * @v augend Big integer to add
346 * @v addend Big integer to add
347 * @v result Big integer to hold result (may overlap augend)
348 */
349static inline __attribute__ (( always_inline )) void
350x25519_add ( const union x25519_quad257 *augend,
351 const union x25519_quad257 *addend,
352 union x25519_oct258 *result ) {
353 int copy;
354
355 /* Copy augend if necessary */
356 copy = ( result != &augend->oct258 );
357 build_assert ( __builtin_constant_p ( copy ) );
358 if ( copy ) {
359 build_assert ( result != &addend->oct258 );
360 bigint_copy ( &augend->oct258.value, &result->value );
361 }
362
363 /* Perform addition
364 *
365 * Both inputs are in the range [0,4p-1] and the resulting
366 * sum is therefore in the range [0,8p-2].
367 *
368 * This range lies within the range [0,8p-1] and the result is
369 * therefore a valid X25519 unsigned 258-bit integer, as
370 * required.
371 */
372 bigint_add ( &addend->value, &result->value );
373}
374
375/**
376 * Subtract big integers modulo field prime
377 *
378 * @v minuend Big integer from which to subtract
379 * @v subtrahend Big integer to subtract
380 * @v result Big integer to hold result (may overlap minuend)
381 */
382static inline __attribute__ (( always_inline )) void
383x25519_subtract ( const union x25519_quad257 *minuend,
384 const union x25519_quad257 *subtrahend,
385 union x25519_oct258 *result ) {
386 int copy;
387
388 /* Copy minuend if necessary */
389 copy = ( result != &minuend->oct258 );
390 build_assert ( __builtin_constant_p ( copy ) );
391 if ( copy ) {
392 build_assert ( result != &subtrahend->oct258 );
393 bigint_copy ( &minuend->oct258.value, &result->value );
394 }
395
396 /* Perform subtraction
397 *
398 * Both inputs are in the range [0,4p-1] and the resulting
399 * difference is therefore in the range [1-4p,4p-1].
400 *
401 * This range lies partially outside the range [0,8p-1] and
402 * the result is therefore not yet a valid X25519 unsigned
403 * 258-bit integer.
404 */
405 bigint_subtract ( &subtrahend->value, &result->value );
406
407 /* Add constant multiple of field prime p
408 *
409 * Add the constant 4p to the result. This brings the result
410 * within the range [1,8p-1] (without changing the value
411 * modulo p).
412 *
413 * This range lies within the range [0,8p-1] and the result is
414 * therefore now a valid X25519 unsigned 258-bit integer, as
415 * required.
416 */
417 bigint_add ( &x25519_4p, &result->value );
418}
419
420/**
421 * Multiply big integers modulo field prime
422 *
423 * @v multiplicand Big integer to be multiplied
424 * @v multiplier Big integer to be multiplied
425 * @v result Big integer to hold result (may overlap either input)
426 */
427void x25519_multiply ( const union x25519_oct258 *multiplicand,
428 const union x25519_oct258 *multiplier,
429 union x25519_quad257 *result ) {
431 union x25519_multiply_step1 *step1 = &tmp.step1;
432 union x25519_multiply_step2 *step2 = &tmp.step2;
433 union x25519_multiply_step3 *step3 = &tmp.step3;
434
435 /* Step 1: perform raw multiplication
436 *
437 * step1 = multiplicand * multiplier
438 *
439 * Both inputs are 258-bit numbers and the step 1 result is
440 * therefore 258+258=516 bits.
441 */
442 static_assert ( sizeof ( step1->product ) >= sizeof ( step1->parts ) );
443 bigint_multiply ( &multiplicand->value, &multiplier->value,
444 &step1->product );
445
446 /* Step 2: reduce high-order 516-256=260 bits of step 1 result
447 *
448 * Use the identity 2^256=38 (mod p) to reduce the high-order
449 * bits of the step 1 result. We split the 516-bit result
450 * from step 1 into its low-order 256 bits and high-order 260
451 * bits:
452 *
453 * step1 = step1(low 256 bits) + step1(high 260 bits) * 2^256
454 *
455 * and then perform the calculation:
456 *
457 * step2 = step1 (mod p)
458 * = step1(low 256 bits) + step1(high 260 bits) * 2^256 (mod p)
459 * = step1(low 256 bits) + step1(high 260 bits) * 38 (mod p)
460 *
461 * There are 6 bits in the constant value 38. The step 2
462 * multiplication product will therefore have 260+6=266 bits,
463 * and the step 2 result (after the addition) will therefore
464 * have 267 bits.
465 */
466 static_assert ( sizeof ( step2->product ) >= sizeof ( step2->value ) );
467 static_assert ( sizeof ( step2->product ) >= sizeof ( step2->parts ) );
468 bigint_grow ( &step1->parts.low_256bit, &result->value );
469 bigint_multiply ( &step1->parts.high_260bit, &x25519_reduce_256,
470 &step2->product );
471 bigint_add ( &result->value, &step2->value );
472
473 /* Step 3: reduce high-order 267-256=11 bits of step 2 result
474 *
475 * Use the identity 2^256=38 (mod p) again to reduce the
476 * high-order bits of the step 2 result. As before, we split
477 * the 267-bit result from step 2 into its low-order 256 bits
478 * and high-order 11 bits:
479 *
480 * step2 = step2(low 256 bits) + step2(high 11 bits) * 2^256
481 *
482 * and then perform the calculation:
483 *
484 * step3 = step2 (mod p)
485 * = step2(low 256 bits) + step2(high 11 bits) * 2^256 (mod p)
486 * = step2(low 256 bits) + step2(high 11 bits) * 38 (mod p)
487 *
488 * There are 6 bits in the constant value 38. The step 3
489 * multiplication product will therefore have 11+6=19 bits,
490 * and the step 3 result (after the addition) will therefore
491 * have 257 bits.
492 *
493 * A loose upper bound for the step 3 result (after the
494 * addition) is given by:
495 *
496 * step3 < ( 2^256 - 1 ) + ( 2^19 - 1 )
497 * < ( 2^257 - 2^256 - 1 ) + ( 2^19 - 1 )
498 * < ( 2^257 - 76 ) - 2^256 + 2^19 + 74
499 * < 4 * ( 2^255 - 19 ) - 2^256 + 2^19 + 74
500 * < 4p - 2^256 + 2^19 + 74
501 *
502 * and so the step 3 result is strictly less than 4p, and
503 * therefore lies within the range [0,4p-1].
504 */
505 memset ( &step3->value, 0, sizeof ( step3->value ) );
506 bigint_grow ( &step2->parts.low_256bit, &result->value );
507 bigint_multiply ( &step2->parts.high_11bit, &x25519_reduce_256,
508 &step3->product );
509 bigint_add ( &step3->value, &result->value );
510
511 /* Step 1 calculates the product of the input operands, and
512 * each subsequent step reduces the number of bits in the
513 * result while preserving this value (modulo p). The final
514 * result is therefore equal to the product of the input
515 * operands (modulo p), as required.
516 *
517 * The step 3 result lies within the range [0,4p-1] and the
518 * final result is therefore a valid X25519 unsigned 257-bit
519 * integer, as required.
520 */
521}
522
523/**
524 * Compute multiplicative inverse
525 *
526 * @v invertend Big integer to be inverted
527 * @v result Big integer to hold result (may not overlap input)
528 */
529void x25519_invert ( const union x25519_oct258 *invertend,
530 union x25519_quad257 *result ) {
531 int i;
532
533 /* Sanity check */
534 assert ( invertend != &result->oct258 );
535
536 /* Calculate inverse as x^(-1)=x^(p-2) where p is the field prime
537 *
538 * The field prime is p=2^255-19 and so:
539 *
540 * p - 2 = 2^255 - 21
541 * = (2^255 - 1) - 2^4 - 2^2
542 *
543 * i.e. p-2 is a 254-bit number in which all bits are set
544 * apart from bit 2 and bit 4.
545 *
546 * We use the square-and-multiply method to compute x^(p-2).
547 */
548 bigint_copy ( &invertend->value, &result->value );
549 for ( i = 253 ; i >= 0 ; i-- ) {
550
551 /* Square running total */
552 x25519_multiply ( &result->oct258, &result->oct258, result );
553
554 /* For each set bit in the exponent, multiply by invertend */
555 if ( ( i != 2 ) && ( i != 4 ) ) {
556 x25519_multiply ( invertend, &result->oct258, result );
557 }
558 }
559}
560
561/**
562 * Reduce big integer via conditional subtraction
563 *
564 * @v subtrahend Big integer to subtract
565 * @v value Big integer to be subtracted from, if possible
566 */
567static void x25519_reduce_by ( const x25519_t *subtrahend, x25519_t *value ) {
568 x25519_t tmp;
569 int underflow;
570
571 /* Conditionally subtract subtrahend
572 *
573 * Subtract the subtrahend, discarding the result (in constant
574 * time) if the subtraction underflows.
575 */
576 bigint_copy ( value, &tmp );
577 underflow = bigint_subtract ( subtrahend, value );
578 bigint_swap ( value, &tmp, underflow );
579}
580
581/**
582 * Reduce big integer to canonical range
583 *
584 * @v value Big integer to be reduced
585 */
587
588 /* Conditionally subtract 2p
589 *
590 * Subtract twice the field prime, discarding the result (in
591 * constant time) if the subtraction underflows.
592 *
593 * The input value is in the range [0,4p-1]. After this
594 * conditional subtraction, the value is in the range
595 * [0,2p-1].
596 */
597 x25519_reduce_by ( &x25519_2p, &value->value );
598
599 /* Conditionally subtract p
600 *
601 * Subtract the field prime, discarding the result (in
602 * constant time) if the subtraction underflows.
603 *
604 * The value is already in the range [0,2p-1]. After this
605 * conditional subtraction, the value is in the range [0,p-1]
606 * and is therefore the canonical representation.
607 */
608 x25519_reduce_by ( &x25519_p, &value->value );
609}
610
611/**
612 * Compute next step of the Montgomery ladder
613 *
614 * @v base Base point
615 * @v bit Bit value
616 * @v step Ladder step
617 */
618static void x25519_step ( const union x25519_quad257 *base, int bit,
619 struct x25519_step *step ) {
620 union x25519_quad257 *a = &step->x_n.X;
621 union x25519_quad257 *b = &step->x_n1.X;
622 union x25519_quad257 *c = &step->x_n.Z;
623 union x25519_quad257 *d = &step->x_n1.Z;
624 union x25519_oct258 e;
625 union x25519_quad257 f;
626 union x25519_oct258 *v1_e;
627 union x25519_oct258 *v2_a;
628 union x25519_oct258 *v3_c;
629 union x25519_oct258 *v4_b;
630 union x25519_quad257 *v5_d;
631 union x25519_quad257 *v6_f;
632 union x25519_quad257 *v7_a;
633 union x25519_quad257 *v8_c;
634 union x25519_oct258 *v9_e;
635 union x25519_oct258 *v10_a;
636 union x25519_quad257 *v11_b;
637 union x25519_oct258 *v12_c;
638 union x25519_quad257 *v13_a;
639 union x25519_oct258 *v14_a;
640 union x25519_quad257 *v15_c;
641 union x25519_quad257 *v16_a;
642 union x25519_quad257 *v17_d;
643 union x25519_quad257 *v18_b;
644
645 /* See the referenced paper "Implementing Curve25519/X25519: A
646 * Tutorial on Elliptic Curve Cryptography" for the reasoning
647 * behind this calculation.
648 */
649
650 /* Reuse storage locations for intermediate results where possible */
651 v1_e = &e;
652 v2_a = container_of ( &a->value, union x25519_oct258, value );
653 v3_c = container_of ( &c->value, union x25519_oct258, value );
654 v4_b = container_of ( &b->value, union x25519_oct258, value );
655 v5_d = d;
656 v6_f = &f;
657 v7_a = a;
658 v8_c = c;
659 v9_e = &e;
660 v10_a = container_of ( &a->value, union x25519_oct258, value );
661 v11_b = b;
662 v12_c = container_of ( &c->value, union x25519_oct258, value );
663 v13_a = a;
664 v14_a = container_of ( &a->value, union x25519_oct258, value );
665 v15_c = c;
666 v16_a = a;
667 v17_d = d;
668 v18_b = b;
669
670 /* Select inputs */
671 bigint_swap ( &a->value, &b->value, bit );
672 bigint_swap ( &c->value, &d->value, bit );
673
674 /* v1 = a + c */
675 x25519_add ( a, c, v1_e );
676
677 /* v2 = a - c */
678 x25519_subtract ( a, c, v2_a );
679
680 /* v3 = b + d */
681 x25519_add ( b, d, v3_c );
682
683 /* v4 = b - d */
684 x25519_subtract ( b, d, v4_b );
685
686 /* v5 = v1^2 = (a + c)^2 = a^2 + 2ac + c^2 */
687 x25519_multiply ( v1_e, v1_e, v5_d );
688
689 /* v6 = v2^2 = (a - c)^2 = a^2 - 2ac + c^2 */
690 x25519_multiply ( v2_a, v2_a, v6_f );
691
692 /* v7 = v3 * v2 = (b + d) * (a - c) = ab - bc + ad - cd */
693 x25519_multiply ( v3_c, v2_a, v7_a );
694
695 /* v8 = v4 * v1 = (b - d) * (a + c) = ab + bc - ad - cd */
696 x25519_multiply ( v4_b, v1_e, v8_c );
697
698 /* v9 = v7 + v8 = 2 * (ab - cd) */
699 x25519_add ( v7_a, v8_c, v9_e );
700
701 /* v10 = v7 - v8 = 2 * (ad - bc) */
702 x25519_subtract ( v7_a, v8_c, v10_a );
703
704 /* v11 = v10^2 = 4 * (ad - bc)^2 */
705 x25519_multiply ( v10_a, v10_a, v11_b );
706
707 /* v12 = v5 - v6 = (a + c)^2 - (a - c)^2 = 4ac */
708 x25519_subtract ( v5_d, v6_f, v12_c );
709
710 /* v13 = v12 * 121665 = 486660ac = (A-2) * ac */
711 x25519_multiply ( v12_c, &x25519_121665, v13_a );
712
713 /* v14 = v13 + v5 = (A-2) * ac + a^2 + 2ac + c^2 = a^2 + A * ac + c^2 */
714 x25519_add ( v13_a, v5_d, v14_a );
715
716 /* v15 = v12 * v14 = 4ac * (a^2 + A * ac + c^2) */
717 x25519_multiply ( v12_c, v14_a, v15_c );
718
719 /* v16 = v5 * v6 = (a + c)^2 * (a - c)^2 = (a^2 - c^2)^2 */
720 x25519_multiply ( &v5_d->oct258, &v6_f->oct258, v16_a );
721
722 /* v17 = v11 * base = 4 * base * (ad - bc)^2 */
723 x25519_multiply ( &v11_b->oct258, &base->oct258, v17_d );
724
725 /* v18 = v9^2 = 4 * (ab - cd)^2 */
726 x25519_multiply ( v9_e, v9_e, v18_b );
727
728 /* Select outputs */
729 bigint_swap ( &a->value, &b->value, bit );
730 bigint_swap ( &c->value, &d->value, bit );
731}
732
733/**
734 * Multiply X25519 elliptic curve point
735 *
736 * @v base Base point
737 * @v scalar Scalar multiple
738 * @v result Point to hold result (may overlap base point)
739 */
740static void x25519_ladder ( const union x25519_quad257 *base,
741 struct x25519_value *scalar,
742 union x25519_quad257 *result ) {
743 static const uint8_t zero[] = { 0 };
744 static const uint8_t one[] = { 1 };
745 struct x25519_step step;
746 union x25519_quad257 *tmp;
747 int bit;
748 int i;
749
750 /* Initialise ladder */
751 bigint_init ( &step.x_n.X.value, one, sizeof ( one ) );
752 bigint_init ( &step.x_n.Z.value, zero, sizeof ( zero ) );
753 bigint_copy ( &base->value, &step.x_n1.X.value );
754 bigint_init ( &step.x_n1.Z.value, one, sizeof ( one ) );
755
756 /* Use ladder */
757 for ( i = 254 ; i >= 0 ; i-- ) {
758 bit = ( ( scalar->raw[ i / 8 ] >> ( i % 8 ) ) & 1 );
759 x25519_step ( base, bit, &step );
760 }
761
762 /* Convert back to affine coordinate */
763 tmp = &step.x_n1.X;
764 x25519_invert ( &step.x_n.Z.oct258, tmp );
765 x25519_multiply ( &step.x_n.X.oct258, &tmp->oct258, result );
767}
768
769/**
770 * Reverse X25519 value endianness
771 *
772 * @v value Value to reverse
773 */
774static void x25519_reverse ( struct x25519_value *value ) {
775 uint8_t *low = value->raw;
776 uint8_t *high = &value->raw[ sizeof ( value->raw ) - 1 ];
777 uint8_t tmp;
778
779 /* Reverse bytes */
780 do {
781 tmp = *low;
782 *low = *high;
783 *high = tmp;
784 } while ( ++low < --high );
785}
786
787/**
788 * Check if X25519 value is zero
789 *
790 * @v value Value to check
791 * @ret is_zero Value is zero
792 */
793int x25519_is_zero ( const struct x25519_value *value ) {
794 x25519_t point;
795
796 /* Check if value is zero */
797 bigint_init ( &point, value->raw, sizeof ( value->raw ) );
798 return bigint_is_zero ( &point );
799}
800
801/**
802 * Calculate X25519 key
803 *
804 * @v base Base point
805 * @v scalar Scalar multiple
806 * @v result Point to hold result (may overlap base point)
807 */
808void x25519_key ( const struct x25519_value *base,
809 const struct x25519_value *scalar,
810 struct x25519_value *result ) {
811 struct x25519_value *tmp = result;
812 union x25519_quad257 point;
813
814 /* Reverse base point and clear high bit as required by RFC7748 */
815 memcpy ( tmp, base, sizeof ( *tmp ) );
817 tmp->raw[0] &= 0x7f;
818 bigint_init ( &point.value, tmp->raw, sizeof ( tmp->raw ) );
819
820 /* Clamp scalar as required by RFC7748 */
821 memcpy ( tmp, scalar, sizeof ( *tmp ) );
822 tmp->raw[0] &= 0xf8;
823 tmp->raw[31] |= 0x40;
824
825 /* Multiply elliptic curve point */
826 x25519_ladder ( &point, tmp, &point );
827
828 /* Reverse result */
829 bigint_done ( &point.value, result->raw, sizeof ( result->raw ) );
831}
832
833/**
834 * Check if this is the point at infinity
835 *
836 * @v point Curve point
837 * @ret is_infinity This is the point at infinity
838 */
839static int x25519_curve_is_infinity ( const void *point ) {
840
841 /* We use all zeroes for the point at infinity (as per RFC8422) */
842 return x25519_is_zero ( point );
843}
844
845/**
846 * Multiply scalar by curve point
847 *
848 * @v base Base point
849 * @v scalar Scalar multiple
850 * @v result Result point to fill in
851 * @ret rc Return status code
852 */
853static int x25519_curve_multiply ( const void *base, const void *scalar,
854 void *result ) {
855
856 x25519_key ( base, scalar, result );
857 return 0;
858}
859
860/**
861 * Add curve points (as a one-off operation)
862 *
863 * @v addend Curve point to add
864 * @v augend Curve point to add
865 * @v result Curve point to hold result
866 * @ret rc Return status code
867 */
868static int x25519_curve_add ( const void *addend __unused,
869 const void *augend __unused,
870 void *result __unused ) {
871
872 return -ENOTTY;
873}
874
875/** X25519 elliptic curve */
877 .name = "x25519",
878 .pointsize = sizeof ( struct x25519_value ),
879 .keysize = sizeof ( struct x25519_value ),
880 .base = x25519_generator.raw,
881 .is_infinity = x25519_curve_is_infinity,
882 .multiply = x25519_curve_multiply,
883 .add = x25519_curve_add,
884};
pseudo_bit_t value[0x00020]
Definition arbel.h:2
uint16_t result
Definition hyperv.h:33
unsigned char uint8_t
Definition stdint.h:10
static const uint32_t multiplier
Port multiplier number.
Definition bigint.h:335
Assertions.
#define build_assert(condition)
Assert a condition at build time (after dead code elimination)
Definition assert.h:77
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
Error codes.
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:573
#define INIT_NORMAL
Normal initialisation.
Definition init.h:32
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define ENOTTY
Inappropriate I/O control operation.
Definition errno.h:595
#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_subtract(subtrahend, value)
Subtract big integers.
Definition bigint.h:99
static unsigned int unsigned int bit
Definition bigint.h:392
#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_swap(first, second, swap)
Conditionally swap big integers (in constant time)
Definition bigint.h:247
#define bigint_init(value, data, len)
Initialise big integer.
Definition bigint.h:62
Cryptographic API.
uint8_t product
Product string.
Definition smbios.h:5
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
#define __init_fn(init_order)
Declare an initialisation functon.
Definition init.h:24
uint32_t base
Base.
Definition librm.h:3
unsigned long tmp
Definition linux_pci.h:65
uint32_t high
High 32 bits of address.
Definition myson.h:1
uint32_t low
Low 16 bits of address.
Definition myson.h:0
void step(void)
Single-step a single process.
Definition process.c:99
#define offsetof(type, field)
Get offset of a field within a structure.
Definition stddef.h:25
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
An elliptic curve.
Definition crypto.h:178
An initialisation function.
Definition init.h:15
An X25519 elliptic curve point in projective coordinates.
Definition x25519.c:260
union x25519_quad257 X
X coordinate.
Definition x25519.c:262
union x25519_quad257 Z
Z coordinate.
Definition x25519.c:264
An X25519 Montgomery ladder step.
Definition x25519.c:268
struct x25519_projective x_n
X[n]/Z[n].
Definition x25519.c:270
struct x25519_projective x_n1
X[n+1]/Z[n+1].
Definition x25519.c:272
An X25519 32-byte value.
Definition x25519.h:78
uint8_t raw[32]
Raw value.
Definition x25519.h:80
X25519 multiplication step 1 result.
Definition x25519.c:108
bigint_t(X25519_SIZE+X25519_SIZE) product
Raw product.
struct x25519_multiply_step1::@143326331223017073312237123340004167004022061343 parts
Partition into low-order and high-order bits.
X25519 multiplication step 2 result.
Definition x25519.c:145
bigint_t(bigint_required_size((260+7)/8)+bigint_required_size((6+7)/8))
Raw product.
Definition x25519.c:152
X25519 multiplication step 3 result.
Definition x25519.c:189
X25519 multiplication temporary working space.
Definition x25519.c:217
union x25519_multiply_step1 step1
Step 1 result.
Definition x25519.c:231
uint8_t pad[sizeof(union x25519_multiply_step2) - offsetof(union x25519_multiply_step1, parts.high_260bit)]
Padding to avoid collision between steps 1 and 2.
Definition x25519.c:229
union x25519_multiply_step2 step2
Step 2 result.
Definition x25519.c:236
union x25519_multiply_step3 step3
Step 3 result.
Definition x25519.c:238
An X25519 unsigned 258-bit integer.
Definition x25519.h:46
x25519_t value
Big integer value.
Definition x25519.h:48
An X25519 unsigned 257-bit integer.
Definition x25519.h:65
x25519_t value
Big integer value.
Definition x25519.h:67
const union x25519_oct258 oct258
X25519 unsigned 258-bit integer.
Definition x25519.h:74
u16 keysize
Length of encryption key to be used, network byte order.
Definition wpa.h:10
int x25519_is_zero(const struct x25519_value *value)
Check if X25519 value is zero.
Definition x25519.c:793
void x25519_multiply(const union x25519_oct258 *multiplicand, const union x25519_oct258 *multiplier, union x25519_quad257 *result)
Multiply big integers modulo field prime.
Definition x25519.c:427
#define X25519_REDUCE_256
X25519 reduction constant.
Definition x25519.c:98
static void x25519_step(const union x25519_quad257 *base, int bit, struct x25519_step *step)
Compute next step of the Montgomery ladder.
Definition x25519.c:618
struct elliptic_curve x25519_curve
X25519 elliptic curve.
Definition x25519.c:876
static void x25519_reduce_by(const x25519_t *subtrahend, x25519_t *value)
Reduce big integer via conditional subtraction.
Definition x25519.c:567
void x25519_reduce(union x25519_quad257 *value)
Reduce big integer to canonical range.
Definition x25519.c:586
static const uint8_t x25519_p_raw[]
Constant p=2^255-19 (the finite field prime)
Definition x25519.c:276
static x25519_t x25519_2p
Constant 2p=2^256-38.
Definition x25519.c:287
static x25519_t x25519_4p
Constant 4p=2^257-76.
Definition x25519.c:290
static struct x25519_value x25519_generator
Constant g=9 (the group generator)
Definition x25519.c:306
static void x25519_reverse(struct x25519_value *value)
Reverse X25519 value endianness.
Definition x25519.c:774
void x25519_key(const struct x25519_value *base, const struct x25519_value *scalar, struct x25519_value *result)
Calculate X25519 key.
Definition x25519.c:808
static int x25519_curve_is_infinity(const void *point)
Check if this is the point at infinity.
Definition x25519.c:839
static union x25519_oct258 x25519_121665
Constant 121665 (used in the Montgomery ladder)
Definition x25519.c:303
static void x25519_ladder(const union x25519_quad257 *base, struct x25519_value *scalar, union x25519_quad257 *result)
Multiply X25519 elliptic curve point.
Definition x25519.c:740
static const uint8_t x25519_reduce_256_raw[]
Reduction constant (used during multiplication)
Definition x25519.c:293
static void x25519_add(const union x25519_quad257 *augend, const union x25519_quad257 *addend, union x25519_oct258 *result)
Add big integers modulo field prime.
Definition x25519.c:350
void x25519_invert(const union x25519_oct258 *invertend, union x25519_quad257 *result)
Compute multiplicative inverse.
Definition x25519.c:529
static int x25519_curve_multiply(const void *base, const void *scalar, void *result)
Multiply scalar by curve point.
Definition x25519.c:853
static void x25519_init_constants(void)
Initialise constants.
Definition x25519.c:314
static void x25519_subtract(const union x25519_quad257 *minuend, const union x25519_quad257 *subtrahend, union x25519_oct258 *result)
Subtract big integers modulo field prime.
Definition x25519.c:383
static int x25519_curve_add(const void *addend __unused, const void *augend __unused, void *result __unused)
Add curve points (as a one-off operation)
Definition x25519.c:868
static x25519_t x25519_p
Constant p=2^255-19 (the finite field prime)
Definition x25519.c:284
X25519 key exchange.
#define X25519_SIZE
X25519 unsigned big integer size.
Definition x25519.h:27