ArduinoLibs
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
Curve25519.cpp
1 /*
2  * Copyright (C) 2015 Southern Storm Software, Pty Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  */
22 
23 #include "Curve25519.h"
24 #include "Crypto.h"
25 #include "RNG.h"
26 #include "utility/ProgMemUtil.h"
27 #include <string.h>
28 
42 // Number of limbs in a value from the field modulo 2^255 - 19.
43 // We assume that sizeof(limb_t) is a power of 2: 1, 2, 4, etc.
44 #define NUM_LIMBS (32 / sizeof(limb_t))
45 
46 // Number of bits in limb_t.
47 #define LIMB_BITS (8 * sizeof(limb_t))
48 
49 // The overhead of clean() calls in mul(), reduceQuick(), etc can
50 // add up to a lot of processing time during eval(). Only do such
51 // cleanups if strict mode has been enabled. Other implementations
52 // like curve25519-donna don't do any cleaning at all so the value
53 // of cleaning up the stack is dubious at best anyway.
54 #if defined(CURVE25519_STRICT_CLEAN)
55 #define strict_clean(x) clean(x)
56 #else
57 #define strict_clean(x) do { ; } while (0)
58 #endif
59 
79 bool Curve25519::eval(uint8_t result[32], const uint8_t s[32], const uint8_t x[32])
80 {
81  limb_t x_1[NUM_LIMBS];
82  limb_t x_2[NUM_LIMBS];
83  limb_t x_3[NUM_LIMBS];
84  limb_t z_2[NUM_LIMBS];
85  limb_t z_3[NUM_LIMBS];
86  limb_t A[NUM_LIMBS];
87  limb_t B[NUM_LIMBS];
88  limb_t C[NUM_LIMBS];
89  limb_t D[NUM_LIMBS];
90  limb_t E[NUM_LIMBS];
91  limb_t AA[NUM_LIMBS];
92  limb_t BB[NUM_LIMBS];
93  limb_t DA[NUM_LIMBS];
94  limb_t CB[NUM_LIMBS];
95  uint8_t mask;
96  uint8_t sposn;
97  uint8_t select;
98  uint8_t swap;
99  bool retval;
100 
101  // Unpack the "x" argument into the limb representation
102  // which also masks off the high bit. NULL means 9.
103  if (x) {
104  // x1 = x
105  BigNumberUtil::unpackLE(x_1, NUM_LIMBS, x, 32);
106  x_1[NUM_LIMBS - 1] &= ((((limb_t)1) << (LIMB_BITS - 1)) - 1);
107  } else {
108  memset(x_1, 0, sizeof(x_1)); // x_1 = 9
109  x_1[0] = 9;
110  }
111 
112  // Check that "x" is within the range of the modulo field.
113  // We can do this with a reduction - if there was no borrow
114  // then the value of "x" was out of range. Timing is sensitive
115  // here so that we don't reveal anything about the value of "x".
116  // If there was a reduction, then continue executing the rest
117  // of this function with the (now) in-range "x" value and
118  // report the failure at the end.
119  retval = (bool)(reduceQuick(x_1) & 0x01);
120 
121  // Initialize the other temporary variables.
122  memset(x_2, 0, sizeof(x_2)); // x_2 = 1
123  x_2[0] = 1;
124  memset(z_2, 0, sizeof(z_2)); // z_2 = 0
125  memcpy(x_3, x_1, sizeof(x_1)); // x_3 = x
126  memcpy(z_3, x_2, sizeof(x_2)); // z_3 = 1
127 
128  // Iterate over all 255 bits of "s" from the highest to the lowest.
129  // We ignore the high bit of the 256-bit representation of "s".
130  mask = 0x40;
131  sposn = 31;
132  swap = 0;
133  for (uint8_t t = 255; t > 0; --t) {
134  // Conditional swaps on entry to this bit but only if we
135  // didn't swap on the previous bit.
136  select = s[sposn] & mask;
137  swap ^= select;
138  cswap(swap, x_2, x_3);
139  cswap(swap, z_2, z_3);
140 
141  // Evaluate the curve.
142  add(A, x_2, z_2); // A = x_2 + z_2
143  square(AA, A); // AA = A^2
144  sub(B, x_2, z_2); // B = x_2 - z_2
145  square(BB, B); // BB = B^2
146  sub(E, AA, BB); // E = AA - BB
147  add(C, x_3, z_3); // C = x_3 + z_3
148  sub(D, x_3, z_3); // D = x_3 - z_3
149  mul(DA, D, A); // DA = D * A
150  mul(CB, C, B); // CB = C * B
151  add(x_3, DA, CB); // x_3 = (DA + CB)^2
152  square(x_3, x_3);
153  sub(z_3, DA, CB); // z_3 = x_1 * (DA - CB)^2
154  square(z_3, z_3);
155  mul(z_3, z_3, x_1);
156  mul(x_2, AA, BB); // x_2 = AA * BB
157  mulA24(z_2, E); // z_2 = E * (AA + a24 * E)
158  add(z_2, z_2, AA);
159  mul(z_2, z_2, E);
160 
161  // Move onto the next lower bit of "s".
162  mask >>= 1;
163  if (!mask) {
164  --sposn;
165  mask = 0x80;
166  swap = select << 7;
167  } else {
168  swap = select >> 1;
169  }
170  }
171 
172  // Final conditional swaps.
173  cswap(swap, x_2, x_3);
174  cswap(swap, z_2, z_3);
175 
176  // Compute x_2 * (z_2 ^ (p - 2)) where p = 2^255 - 19.
177  recip(z_3, z_2);
178  mul(x_2, x_2, z_3);
179 
180  // Pack the result into the return array.
181  BigNumberUtil::packLE(result, 32, x_2, NUM_LIMBS);
182 
183  // Clean up and exit.
184  clean(x_1);
185  clean(x_2);
186  clean(x_3);
187  clean(z_2);
188  clean(z_3);
189  clean(A);
190  clean(B);
191  clean(C);
192  clean(D);
193  clean(E);
194  clean(AA);
195  clean(BB);
196  clean(DA);
197  clean(CB);
198  return retval;
199 }
200 
244 void Curve25519::dh1(uint8_t k[32], uint8_t f[32])
245 {
246  do {
247  // Generate a random "f" value and then adjust the value to make
248  // it valid as an "s" value for eval(). According to the specification
249  // we need to mask off the 3 right-most bits of f[0], mask off the
250  // left-most bit of f[31], and set the second to left-most bit of f[31].
251  RNG.rand(f, 32);
252  f[0] &= 0xF8;
253  f[31] = (f[31] & 0x7F) | 0x40;
254 
255  // Evaluate the curve function: k = Curve25519::eval(f, 9).
256  // We pass NULL to eval() to indicate the value 9. There is no
257  // need to check the return value from eval() because we know
258  // that 9 is a valid field element.
259  eval(k, f, 0);
260 
261  // If "k" is weak for contributory behaviour then reject it,
262  // generate another "f" value, and try again. This case is
263  // highly unlikely but we still perform the check just in case.
264  } while (isWeakPoint(k));
265 }
266 
282 bool Curve25519::dh2(uint8_t k[32], uint8_t f[32])
283 {
284  uint8_t weak;
285 
286  // Evaluate the curve function: k = Curve25519::eval(f, k).
287  // If "k" is weak for contributory behaviour before or after
288  // the curve evaluation, then fail the exchange. For safety
289  // we perform every phase of the weak checks even if we could
290  // bail out earlier so that the execution takes the same
291  // amount of time for weak and non-weak "k" values.
292  weak = isWeakPoint(k); // Is "k" weak before?
293  weak |= ((eval(k, f, k) ^ 0x01) & 0x01); // Is "k" weak during?
294  weak |= isWeakPoint(k); // Is "k" weak after?
295  clean(f, 32);
296  return (bool)((weak ^ 0x01) & 0x01);
297 }
298 
306 uint8_t Curve25519::isWeakPoint(const uint8_t k[32])
307 {
308  // List of weak points from http://cr.yp.to/ecdh.html
309  // That page lists some others but they are variants on these
310  // of the form "point + i * (2^255 - 19)" for i = 0, 1, 2.
311  // Here we mask off the high bit and eval() catches the rest.
312  static const uint8_t points[5][32] PROGMEM = {
313  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
314  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
315  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
316  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
317  {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
318  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
319  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
320  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
321  {0xE0, 0xEB, 0x7A, 0x7C, 0x3B, 0x41, 0xB8, 0xAE,
322  0x16, 0x56, 0xE3, 0xFA, 0xF1, 0x9F, 0xC4, 0x6A,
323  0xDA, 0x09, 0x8D, 0xEB, 0x9C, 0x32, 0xB1, 0xFD,
324  0x86, 0x62, 0x05, 0x16, 0x5F, 0x49, 0xB8, 0x00},
325  {0x5F, 0x9C, 0x95, 0xBC, 0xA3, 0x50, 0x8C, 0x24,
326  0xB1, 0xD0, 0xB1, 0x55, 0x9C, 0x83, 0xEF, 0x5B,
327  0x04, 0x44, 0x5C, 0xC4, 0x58, 0x1C, 0x8E, 0x86,
328  0xD8, 0x22, 0x4E, 0xDD, 0xD0, 0x9F, 0x11, 0x57},
329  {0xEC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
330  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
331  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
332  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F}
333  };
334 
335  // Check each of the weak points in turn. We perform the
336  // comparisons carefully so as not to reveal the value of "k"
337  // in the instruction timing. If "k" is indeed weak then
338  // we still check everything so as not to reveal which
339  // weak point it is.
340  uint8_t result = 0;
341  for (uint8_t posn = 0; posn < 5; ++posn) {
342  const uint8_t *point = points[posn];
343  uint8_t check = (pgm_read_byte(point + 31) ^ k[31]) & 0x7F;
344  for (uint8_t index = 31; index > 0; --index)
345  check |= (pgm_read_byte(point + index - 1) ^ k[index - 1]);
346  result |= (uint8_t)((((uint16_t)0x0100) - check) >> 8);
347  }
348 
349  // The "result" variable will be non-zero if there was a match.
350  return result;
351 }
352 
365 void Curve25519::reduce(limb_t *result, limb_t *x, uint8_t size)
366 {
367  /*
368  Note: This explaination is best viewed with a UTF-8 text viewer.
369 
370  To help explain what this function is doing, the following describes
371  how to efficiently compute reductions modulo a base of the form (2ⁿ - b)
372  where b is greater than zero and (b + 1)² <= 2ⁿ.
373 
374  Here we are interested in reducing the result of multiplying two
375  numbers that are less than or equal to (2ⁿ - b - 1). That is,
376  multiplying numbers that have already been reduced.
377 
378  Given some x less than or equal to (2ⁿ - b - 1)², we want to find a
379  y less than (2ⁿ - b) such that:
380 
381  y ≡ x mod (2ⁿ - b)
382 
383  We know that for all integer values of k >= 0:
384 
385  y ≡ x - k * (2ⁿ - b)
386  ≡ x - k * 2ⁿ + k * b
387 
388  In our case we choose k = ⌊x / 2ⁿ⌋ and then let:
389 
390  w = (x mod 2ⁿ) + ⌊x / 2ⁿ⌋ * b
391 
392  The value w will either be the answer y or y can be obtained by
393  repeatedly subtracting (2ⁿ - b) from w until it is less than (2ⁿ - b).
394  At most b subtractions will be required.
395 
396  In our case b is 19 which is more subtractions than we would like to do,
397  but we can handle that by performing the above reduction twice and then
398  performing a single trial subtraction:
399 
400  w = (x mod 2ⁿ) + ⌊x / 2ⁿ⌋ * b
401  y = (w mod 2ⁿ) + ⌊w / 2ⁿ⌋ * b
402  if y >= (2ⁿ - b)
403  y -= (2ⁿ - b)
404 
405  The value y is the answer we want for reducing x modulo (2ⁿ - b).
406  */
407 
408  dlimb_t carry;
409  uint8_t posn;
410 
411  // Calculate (x mod 2^255) + ((x / 2^255) * 19) which will
412  // either produce the answer we want or it will produce a
413  // value of the form "answer + j * (2^255 - 19)".
414  carry = ((dlimb_t)(x[NUM_LIMBS - 1] >> (LIMB_BITS - 1))) * 19U;
415  x[NUM_LIMBS - 1] &= ((((limb_t)1) << (LIMB_BITS - 1)) - 1);
416  for (posn = 0; posn < size; ++posn) {
417  carry += ((dlimb_t)(x[posn + NUM_LIMBS])) * 38U;
418  carry += x[posn];
419  x[posn] = (limb_t)carry;
420  carry >>= LIMB_BITS;
421  }
422  if (size < NUM_LIMBS) {
423  // The high order half of the number is short; e.g. for mulA24().
424  // Propagate the carry through the rest of the low order part.
425  for (posn = size; posn < NUM_LIMBS; ++posn) {
426  carry += x[posn];
427  x[posn] = (limb_t)carry;
428  carry >>= LIMB_BITS;
429  }
430  }
431 
432  // The "j" value may still be too large due to the final carry-out.
433  // We must repeat the reduction. If we already have the answer,
434  // then this won't do any harm but we must still do the calculation
435  // to preserve the overall timing.
436  carry *= 38U;
437  carry += ((dlimb_t)(x[NUM_LIMBS - 1] >> (LIMB_BITS - 1))) * 19U;
438  x[NUM_LIMBS - 1] &= ((((limb_t)1) << (LIMB_BITS - 1)) - 1);
439  for (posn = 0; posn < NUM_LIMBS; ++posn) {
440  carry += x[posn];
441  x[posn] = (limb_t)carry;
442  carry >>= LIMB_BITS;
443  }
444 
445  // At this point "x" will either be the answer or it will be the
446  // answer plus (2^255 - 19). Perform a trial subtraction which
447  // is equivalent to adding 19 and subtracting 2^255. We put the
448  // trial answer into the top-most limbs of the original "x" array.
449  // We add 19 here; the subtraction of 2^255 occurs in the next step.
450  carry = 19U;
451  for (posn = 0; posn < NUM_LIMBS; ++posn) {
452  carry += x[posn];
453  x[posn + NUM_LIMBS] = (limb_t)carry;
454  carry >>= LIMB_BITS;
455  }
456 
457  // If there was a borrow, then the bottom-most limbs of "x" are the
458  // correct answer. If there was no borrow, then the top-most limbs
459  // of "x" are the correct answer. Select the correct answer but do
460  // it in a way that instruction timing will not reveal which value
461  // was selected. Borrow will occur if the high bit of the previous
462  // result is 0: turn the high bit into a selection mask.
463  limb_t mask = (limb_t)(((slimb_t)(x[NUM_LIMBS * 2 - 1])) >> (LIMB_BITS - 1));
464  limb_t nmask = ~mask;
465  x[NUM_LIMBS * 2 - 1] &= ((((limb_t)1) << (LIMB_BITS - 1)) - 1);
466  for (posn = 0; posn < NUM_LIMBS; ++posn) {
467  result[posn] = (x[posn] & nmask) | (x[posn + NUM_LIMBS] & mask);
468  }
469 }
470 
484 limb_t Curve25519::reduceQuick(limb_t *x)
485 {
486  limb_t temp[NUM_LIMBS];
487  dlimb_t carry;
488  uint8_t posn;
489  limb_t *xx;
490  limb_t *tt;
491 
492  // Perform a trial subtraction of (2^255 - 19) from "x" which is
493  // equivalent to adding 19 and subtracting 2^255. We add 19 here;
494  // the subtraction of 2^255 occurs in the next step.
495  carry = 19U;
496  xx = x;
497  tt = temp;
498  for (posn = 0; posn < NUM_LIMBS; ++posn) {
499  carry += *xx++;
500  *tt++ = (limb_t)carry;
501  carry >>= LIMB_BITS;
502  }
503 
504  // If there was a borrow, then the original "x" is the correct answer.
505  // If there was no borrow, then "temp" is the correct answer. Select the
506  // correct answer but do it in a way that instruction timing will not
507  // reveal which value was selected. Borrow will occur if the high bit
508  // of "temp" is 0: turn the high bit into a selection mask.
509  limb_t mask = (limb_t)(((slimb_t)(temp[NUM_LIMBS - 1])) >> (LIMB_BITS - 1));
510  limb_t nmask = ~mask;
511  temp[NUM_LIMBS - 1] &= ((((limb_t)1) << (LIMB_BITS - 1)) - 1);
512  xx = x;
513  tt = temp;
514  for (posn = 0; posn < NUM_LIMBS; ++posn) {
515  *xx = ((*xx) & nmask) | ((*tt++) & mask);
516  ++xx;
517  }
518 
519  // Clean up "temp".
520  strict_clean(temp);
521 
522  // Return a zero value if we actually subtracted (2^255 - 19) from "x".
523  return nmask;
524 }
525 
536 void Curve25519::mul(limb_t *result, const limb_t *x, const limb_t *y)
537 {
538  limb_t temp[NUM_LIMBS * 2];
539  uint8_t i, j;
540  dlimb_t carry;
541  limb_t word;
542  const limb_t *yy;
543  limb_t *tt;
544 
545  // Multiply the lowest word of x by y.
546  carry = 0;
547  word = x[0];
548  yy = y;
549  tt = temp;
550  for (i = 0; i < NUM_LIMBS; ++i) {
551  carry += ((dlimb_t)(*yy++)) * word;
552  *tt++ = (limb_t)carry;
553  carry >>= LIMB_BITS;
554  }
555  *tt = (limb_t)carry;
556 
557  // Multiply and add the remaining words of x by y.
558  for (i = 1; i < NUM_LIMBS; ++i) {
559  word = x[i];
560  carry = 0;
561  yy = y;
562  tt = temp + i;
563  for (j = 0; j < NUM_LIMBS; ++j) {
564  carry += ((dlimb_t)(*yy++)) * word;
565  carry += *tt;
566  *tt++ = (limb_t)carry;
567  carry >>= LIMB_BITS;
568  }
569  *tt = (limb_t)carry;
570  }
571 
572  // Reduce the intermediate result modulo 2^255 - 19.
573  reduce(result, temp, NUM_LIMBS);
574  strict_clean(temp);
575 }
576 
596 void Curve25519::mulA24(limb_t *result, const limb_t *x)
597 {
598  // The constant a24 = 121665 (0x1DB41) as a limb array.
599 #if BIGNUMBER_LIMB_8BIT
600  static limb_t const a24[3] PROGMEM = {0x41, 0xDB, 0x01};
601  #define pgm_read_a24(index) (pgm_read_byte(&(a24[(index)])))
602 #elif BIGNUMBER_LIMB_16BIT
603  static limb_t const a24[2] PROGMEM = {0xDB41, 0x0001};
604  #define pgm_read_a24(index) (pgm_read_word(&(a24[(index)])))
605 #elif BIGNUMBER_LIMB_32BIT
606  static limb_t const a24[1] PROGMEM = {0x0001DB41};
607  #define pgm_read_a24(index) (pgm_read_dword(&(a24[(index)])))
608 #else
609  #error "limb_t must be 8, 16, or 32 bits in size"
610 #endif
611  #define NUM_A24_LIMBS (sizeof(a24) / sizeof(limb_t))
612 
613  // Multiply the lowest limb of a24 by x and zero-extend into the result.
614  limb_t temp[NUM_LIMBS * 2];
615  uint8_t i, j;
616  dlimb_t carry = 0;
617  limb_t word = pgm_read_a24(0);
618  const limb_t *xx = x;
619  limb_t *tt = temp;
620  for (i = 0; i < NUM_LIMBS; ++i) {
621  carry += ((dlimb_t)(*xx++)) * word;
622  *tt++ = (limb_t)carry;
623  carry >>= LIMB_BITS;
624  }
625  *tt = (limb_t)carry;
626 
627  // Multiply and add the remaining limbs of a24.
628  for (i = 1; i < NUM_A24_LIMBS; ++i) {
629  word = pgm_read_a24(i);
630  carry = 0;
631  xx = x;
632  tt = temp + i;
633  for (j = 0; j < NUM_LIMBS; ++j) {
634  carry += ((dlimb_t)(*xx++)) * word;
635  carry += *tt;
636  *tt++ = (limb_t)carry;
637  carry >>= LIMB_BITS;
638  }
639  *tt = (limb_t)carry;
640  }
641 
642  // Reduce the intermediate result modulo 2^255 - 19.
643  reduce(result, temp, NUM_A24_LIMBS);
644  strict_clean(temp);
645 }
646 
657 void Curve25519::add(limb_t *result, const limb_t *x, const limb_t *y)
658 {
659  dlimb_t carry = 0;
660  uint8_t posn;
661  limb_t *rr = result;
662 
663  // Add the two arrays to obtain the intermediate result.
664  for (posn = 0; posn < NUM_LIMBS; ++posn) {
665  carry += *x++;
666  carry += *y++;
667  *rr++ = (limb_t)carry;
668  carry >>= LIMB_BITS;
669  }
670 
671  // Reduce the result using the quick trial subtraction method.
672  reduceQuick(result);
673 }
674 
685 void Curve25519::sub(limb_t *result, const limb_t *x, const limb_t *y)
686 {
687  dlimb_t borrow;
688  uint8_t posn;
689  limb_t *rr = result;
690 
691  // Subtract y from x to generate the intermediate result.
692  borrow = 0;
693  for (posn = 0; posn < NUM_LIMBS; ++posn) {
694  borrow = ((dlimb_t)(*x++)) - (*y++) - ((borrow >> LIMB_BITS) & 0x01);
695  *rr++ = (limb_t)borrow;
696  }
697 
698  // If we had a borrow, then the result has gone negative and we
699  // have to add 2^255 - 19 to the result to make it positive again.
700  // The top bits of "borrow" will be all 1's if there is a borrow
701  // or it will be all 0's if there was no borrow. Easiest is to
702  // conditionally subtract 19 and then mask off the high bit.
703  rr = result;
704  borrow = (borrow >> LIMB_BITS) & 19U;
705  borrow = ((dlimb_t)(*rr)) - borrow;
706  *rr++ = (limb_t)borrow;
707  for (posn = 1; posn < NUM_LIMBS; ++posn) {
708  borrow = ((dlimb_t)(*rr)) - ((borrow >> LIMB_BITS) & 0x01);
709  *rr++ = (limb_t)borrow;
710  }
711  *(--rr) &= ((((limb_t)1) << (LIMB_BITS - 1)) - 1);
712 }
713 
724 void Curve25519::cswap(uint8_t select, limb_t *x, limb_t *y)
725 {
726  uint8_t posn;
727  limb_t dummy;
728  limb_t sel;
729 
730  // Turn "select" into an all-zeroes or all-ones mask. We don't care
731  // which bit or bits is set in the original "select" value.
732  sel = (limb_t)(((((dlimb_t)1) << LIMB_BITS) - select) >> LIMB_BITS);
733  --sel;
734 
735  // Swap the two values based on "select". Algorithm from:
736  // https://tools.ietf.org/html/draft-irtf-cfrg-curves-02
737  for (posn = 0; posn < NUM_LIMBS; ++posn) {
738  dummy = sel & (x[posn] ^ y[posn]);
739  x[posn] ^= dummy;
740  y[posn] ^= dummy;
741  }
742 }
743 
751 void Curve25519::recip(limb_t *result, const limb_t *x)
752 {
753  limb_t t1[NUM_LIMBS];
754  uint8_t i, j;
755 
756  // The reciprocal is the same as x ^ (p - 2) where p = 2^255 - 19.
757  // The big-endian hexadecimal expansion of (p - 2) is:
758  // 7FFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFEB
759  //
760  // The naive implementation needs to do 2 multiplications per 1 bit and
761  // 1 multiplication per 0 bit. We can improve upon this by creating a
762  // pattern 0000000001 ... 0000000001. If we square and multiply the
763  // pattern by itself we can turn the pattern into the partial results
764  // 0000000011 ... 0000000011, 0000000111 ... 0000000111, etc.
765  // This averages out to about 1.1 multiplications per 1 bit instead of 2.
766 
767  // Build a pattern of 250 bits in length of repeated copies of 0000000001.
768  #define RECIP_GROUP_SIZE 10
769  #define RECIP_GROUP_BITS 250 // Must be a multiple of RECIP_GROUP_SIZE.
770  square(t1, x);
771  for (j = 0; j < (RECIP_GROUP_SIZE - 1); ++j)
772  square(t1, t1);
773  mul(result, t1, x);
774  for (i = 0; i < ((RECIP_GROUP_BITS / RECIP_GROUP_SIZE) - 2); ++i) {
775  for (j = 0; j < RECIP_GROUP_SIZE; ++j)
776  square(t1, t1);
777  mul(result, result, t1);
778  }
779 
780  // Multiply bit-shifted versions of the 0000000001 pattern into
781  // the result to "fill in" the gaps in the pattern.
782  square(t1, result);
783  mul(result, result, t1);
784  for (j = 0; j < (RECIP_GROUP_SIZE - 2); ++j) {
785  square(t1, t1);
786  mul(result, result, t1);
787  }
788 
789  // Deal with the 5 lowest bits of (p - 2), 01011, from highest to lowest.
790  square(result, result);
791  square(result, result);
792  mul(result, result, x);
793  square(result, result);
794  square(result, result);
795  mul(result, result, x);
796  square(result, result);
797  mul(result, result, x);
798 
799  // Clean up and exit.
800  clean(t1);
801 }
void rand(uint8_t *data, size_t len)
Generates random bytes into a caller-supplied buffer.
Definition: RNG.cpp:298
static bool eval(uint8_t result[32], const uint8_t s[32], const uint8_t x[32])
Evaluates the raw Curve25519 function.
Definition: Curve25519.cpp:79
static void unpackLE(limb_t *limbs, size_t count, const uint8_t *bytes, size_t len)
Unpacks the little-endian byte representation of a big number into a limb array.
static void packLE(uint8_t *bytes, size_t len, const limb_t *limbs, size_t count)
Packs the little-endian byte representation of a big number into a byte array.
static void dh1(uint8_t k[32], uint8_t f[32])
Performs phase 1 of a Diffie-Hellman key exchange using Curve25519.
Definition: Curve25519.cpp:244
static bool dh2(uint8_t k[32], uint8_t f[32])
Performs phase 2 of a Diffie-Hellman key exchange using Curve25519.
Definition: Curve25519.cpp:282