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 
68 bool Curve25519::eval(uint8_t result[32], const uint8_t s[32], const uint8_t x[32])
69 {
70  limb_t x_1[NUM_LIMBS];
71  limb_t x_2[NUM_LIMBS];
72  limb_t x_3[NUM_LIMBS];
73  limb_t z_2[NUM_LIMBS];
74  limb_t z_3[NUM_LIMBS];
75  limb_t A[NUM_LIMBS];
76  limb_t B[NUM_LIMBS];
77  limb_t C[NUM_LIMBS];
78  limb_t D[NUM_LIMBS];
79  limb_t E[NUM_LIMBS];
80  limb_t AA[NUM_LIMBS];
81  limb_t BB[NUM_LIMBS];
82  limb_t DA[NUM_LIMBS];
83  limb_t CB[NUM_LIMBS];
84  uint8_t mask;
85  uint8_t sposn;
86  uint8_t select;
87  uint8_t swap;
88  bool retval;
89 
90  // Unpack the "x" argument into the limb representation
91  // which also masks off the high bit. NULL means 9.
92  if (x) {
93  unpack(x_1, x); // x_1 = x
94  } else {
95  memset(x_1, 0, sizeof(x_1)); // x_1 = 9
96  x_1[0] = 9;
97  }
98 
99  // Check that "x" is within the range of the modulo field.
100  // We can do this with a reduction - if there was no borrow
101  // then the value of "x" was out of range. Timing is sensitive
102  // here so that we don't reveal anything about the value of "x".
103  // If there was a reduction, then continue executing the rest
104  // of this function with the (now) in-range "x" value and
105  // report the failure at the end.
106  retval = (bool)(reduceQuick(x_1) & 0x01);
107 
108  // Initialize the other temporary variables.
109  memset(x_2, 0, sizeof(x_2)); // x_2 = 1
110  x_2[0] = 1;
111  memset(z_2, 0, sizeof(z_2)); // z_2 = 0
112  memcpy(x_3, x_1, sizeof(x_1)); // x_3 = x
113  memcpy(z_3, x_2, sizeof(x_2)); // z_3 = 1
114 
115  // Iterate over all 255 bits of "s" from the highest to the lowest.
116  // We ignore the high bit of the 256-bit representation of "s".
117  mask = 0x40;
118  sposn = 31;
119  swap = 0;
120  for (uint8_t t = 255; t > 0; --t) {
121  // Conditional swaps on entry to this bit but only if we
122  // didn't swap on the previous bit.
123  select = s[sposn] & mask;
124  swap ^= select;
125  cswap(swap, x_2, x_3);
126  cswap(swap, z_2, z_3);
127 
128  // Evaluate the curve.
129  add(A, x_2, z_2); // A = x_2 + z_2
130  square(AA, A); // AA = A^2
131  sub(B, x_2, z_2); // B = x_2 - z_2
132  square(BB, B); // BB = B^2
133  sub(E, AA, BB); // E = AA - BB
134  add(C, x_3, z_3); // C = x_3 + z_3
135  sub(D, x_3, z_3); // D = x_3 - z_3
136  mul(DA, D, A); // DA = D * A
137  mul(CB, C, B); // CB = C * B
138  add(x_3, DA, CB); // x_3 = (DA + CB)^2
139  square(x_3, x_3);
140  sub(z_3, DA, CB); // z_3 = x_1 * (DA - CB)^2
141  square(z_3, z_3);
142  mul(z_3, z_3, x_1);
143  mul(x_2, AA, BB); // x_2 = AA * BB
144  mulA24(z_2, E); // z_2 = E * (AA + a24 * E)
145  add(z_2, z_2, AA);
146  mul(z_2, z_2, E);
147 
148  // Move onto the next lower bit of "s".
149  mask >>= 1;
150  if (!mask) {
151  --sposn;
152  mask = 0x80;
153  swap = select << 7;
154  } else {
155  swap = select >> 1;
156  }
157  }
158 
159  // Final conditional swaps.
160  cswap(swap, x_2, x_3);
161  cswap(swap, z_2, z_3);
162 
163  // Compute x_2 * (z_2 ^ (p - 2)) where p = 2^255 - 19.
164  recip(z_3, z_2);
165  mul(x_2, x_2, z_3);
166 
167  // Pack the result into the return array.
168  pack(result, x_2);
169 
170  // Clean up and exit.
171  clean(x_1);
172  clean(x_2);
173  clean(x_3);
174  clean(z_2);
175  clean(z_3);
176  clean(A);
177  clean(B);
178  clean(C);
179  clean(D);
180  clean(E);
181  clean(AA);
182  clean(BB);
183  clean(DA);
184  clean(CB);
185  return retval;
186 }
187 
231 void Curve25519::dh1(uint8_t k[32], uint8_t f[32])
232 {
233  do {
234  // Generate a random "f" value and then adjust the value to make
235  // it valid as an "s" value for eval(). According to the specification
236  // we need to mask off the 3 right-most bits of f[0], mask off the
237  // left-most bit of f[31], and set the second to left-most bit of f[31].
238  RNG.rand(f, 32);
239  f[0] &= 0xF8;
240  f[31] = (f[31] & 0x7F) | 0x40;
241 
242  // Evaluate the curve function: k = Curve25519::eval(f, 9).
243  // We pass NULL to eval() to indicate the value 9. There is no
244  // need to check the return value from eval() because we know
245  // that 9 is a valid field element.
246  eval(k, f, 0);
247 
248  // If "k" is weak for contributory behaviour then reject it,
249  // generate another "f" value, and try again. This case is
250  // highly unlikely but we still perform the check just in case.
251  } while (isWeakPoint(k));
252 }
253 
269 bool Curve25519::dh2(uint8_t k[32], uint8_t f[32])
270 {
271  uint8_t weak;
272 
273  // Evaluate the curve function: k = Curve25519::eval(f, k).
274  // If "k" is weak for contributory behaviour before or after
275  // the curve evaluation, then fail the exchange. For safety
276  // we perform every phase of the weak checks even if we could
277  // bail out earlier so that the execution takes the same
278  // amount of time for weak and non-weak "k" values.
279  weak = isWeakPoint(k); // Is "k" weak before?
280  weak |= ((eval(k, f, k) ^ 0x01) & 0x01); // Is "k" weak during?
281  weak |= isWeakPoint(k); // Is "k" weak after?
282  clean(f, 32);
283  return (bool)((weak ^ 0x01) & 0x01);
284 }
285 
293 uint8_t Curve25519::isWeakPoint(const uint8_t k[32])
294 {
295  // List of weak points from http://cr.yp.to/ecdh.html
296  // That page lists some others but they are variants on these
297  // of the form "point + i * (2^255 - 19)" for i = 0, 1, 2.
298  // Here we mask off the high bit and eval() catches the rest.
299  static const uint8_t points[5][32] PROGMEM = {
300  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
301  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
302  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
303  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
304  {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
305  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
306  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
307  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
308  {0xE0, 0xEB, 0x7A, 0x7C, 0x3B, 0x41, 0xB8, 0xAE,
309  0x16, 0x56, 0xE3, 0xFA, 0xF1, 0x9F, 0xC4, 0x6A,
310  0xDA, 0x09, 0x8D, 0xEB, 0x9C, 0x32, 0xB1, 0xFD,
311  0x86, 0x62, 0x05, 0x16, 0x5F, 0x49, 0xB8, 0x00},
312  {0x5F, 0x9C, 0x95, 0xBC, 0xA3, 0x50, 0x8C, 0x24,
313  0xB1, 0xD0, 0xB1, 0x55, 0x9C, 0x83, 0xEF, 0x5B,
314  0x04, 0x44, 0x5C, 0xC4, 0x58, 0x1C, 0x8E, 0x86,
315  0xD8, 0x22, 0x4E, 0xDD, 0xD0, 0x9F, 0x11, 0x57},
316  {0xEC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
317  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
318  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
319  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F}
320  };
321 
322  // Check each of the weak points in turn. We perform the
323  // comparisons carefully so as not to reveal the value of "k"
324  // in the instruction timing. If "k" is indeed weak then
325  // we still check everything so as not to reveal which
326  // weak point it is.
327  uint8_t result = 0;
328  for (uint8_t posn = 0; posn < 5; ++posn) {
329  const uint8_t *point = points[posn];
330  uint8_t check = (pgm_read_byte(point + 31) ^ k[31]) & 0x7F;
331  for (uint8_t index = 31; index > 0; --index)
332  check |= (pgm_read_byte(point + index - 1) ^ k[index - 1]);
333  result |= (uint8_t)((((uint16_t)0x0100) - check) >> 8);
334  }
335 
336  // The "result" variable will be non-zero if there was a match.
337  return result;
338 }
339 
352 void Curve25519::reduce(limb_t *result, limb_t *x, uint8_t size)
353 {
354  /*
355  Note: This explaination is best viewed with a UTF-8 text viewer.
356 
357  To help explain what this function is doing, the following describes
358  how to efficiently compute reductions modulo a base of the form (2ⁿ - b)
359  where b is greater than zero and (b + 1)² <= 2ⁿ.
360 
361  Here we are interested in reducing the result of multiplying two
362  numbers that are less than or equal to (2ⁿ - b - 1). That is,
363  multiplying numbers that have already been reduced.
364 
365  Given some x less than or equal to (2ⁿ - b - 1)², we want to find a
366  y less than (2ⁿ - b) such that:
367 
368  y ≡ x mod (2ⁿ - b)
369 
370  We know that for all integer values of k >= 0:
371 
372  y ≡ x - k * (2ⁿ - b)
373  ≡ x - k * 2ⁿ + k * b
374 
375  In our case we choose k = ⌊x / 2ⁿ⌋ and then let:
376 
377  w = (x mod 2ⁿ) + ⌊x / 2ⁿ⌋ * b
378 
379  The value w will either be the answer y or y can be obtained by
380  repeatedly subtracting (2ⁿ - b) from w until it is less than (2ⁿ - b).
381  At most b subtractions will be required.
382 
383  In our case b is 19 which is more subtractions than we would like to do,
384  but we can handle that by performing the above reduction twice and then
385  performing a single trial subtraction:
386 
387  w = (x mod 2ⁿ) + ⌊x / 2ⁿ⌋ * b
388  y = (w mod 2ⁿ) + ⌊w / 2ⁿ⌋ * b
389  if y >= (2ⁿ - b)
390  y -= (2ⁿ - b)
391 
392  The value y is the answer we want for reducing x modulo (2ⁿ - b).
393  */
394 
395  dlimb_t carry;
396  uint8_t posn;
397 
398  // Calculate (x mod 2^255) + ((x / 2^255) * 19) which will
399  // either produce the answer we want or it will produce a
400  // value of the form "answer + j * (2^255 - 19)".
401  carry = ((dlimb_t)(x[NUM_LIMBS - 1] >> (LIMB_BITS - 1))) * 19U;
402  x[NUM_LIMBS - 1] &= ((((limb_t)1) << (LIMB_BITS - 1)) - 1);
403  for (posn = 0; posn < size; ++posn) {
404  carry += ((dlimb_t)(x[posn + NUM_LIMBS])) * 38U;
405  carry += x[posn];
406  x[posn] = (limb_t)carry;
407  carry >>= LIMB_BITS;
408  }
409  if (size < NUM_LIMBS) {
410  // The high order half of the number is short; e.g. for mulA24().
411  // Propagate the carry through the rest of the low order part.
412  for (posn = size; posn < NUM_LIMBS; ++posn) {
413  carry += x[posn];
414  x[posn] = (limb_t)carry;
415  carry >>= LIMB_BITS;
416  }
417  }
418 
419  // The "j" value may still be too large due to the final carry-out.
420  // We must repeat the reduction. If we already have the answer,
421  // then this won't do any harm but we must still do the calculation
422  // to preserve the overall timing.
423  carry *= 38U;
424  carry += ((dlimb_t)(x[NUM_LIMBS - 1] >> (LIMB_BITS - 1))) * 19U;
425  x[NUM_LIMBS - 1] &= ((((limb_t)1) << (LIMB_BITS - 1)) - 1);
426  for (posn = 0; posn < NUM_LIMBS; ++posn) {
427  carry += x[posn];
428  x[posn] = (limb_t)carry;
429  carry >>= LIMB_BITS;
430  }
431 
432  // At this point "x" will either be the answer or it will be the
433  // answer plus (2^255 - 19). Perform a trial subtraction which
434  // is equivalent to adding 19 and subtracting 2^255. We put the
435  // trial answer into the top-most limbs of the original "x" array.
436  // We add 19 here; the subtraction of 2^255 occurs in the next step.
437  carry = 19U;
438  for (posn = 0; posn < NUM_LIMBS; ++posn) {
439  carry += x[posn];
440  x[posn + NUM_LIMBS] = (limb_t)carry;
441  carry >>= LIMB_BITS;
442  }
443 
444  // If there was a borrow, then the bottom-most limbs of "x" are the
445  // correct answer. If there was no borrow, then the top-most limbs
446  // of "x" are the correct answer. Select the correct answer but do
447  // it in a way that instruction timing will not reveal which value
448  // was selected. Borrow will occur if the high bit of the previous
449  // result is 0: turn the high bit into a selection mask.
450  limb_t mask = (limb_t)(((slimb_t)(x[NUM_LIMBS * 2 - 1])) >> (LIMB_BITS - 1));
451  limb_t nmask = ~mask;
452  x[NUM_LIMBS * 2 - 1] &= ((((limb_t)1) << (LIMB_BITS - 1)) - 1);
453  for (posn = 0; posn < NUM_LIMBS; ++posn) {
454  result[posn] = (x[posn] & nmask) | (x[posn + NUM_LIMBS] & mask);
455  }
456 }
457 
471 limb_t Curve25519::reduceQuick(limb_t *x)
472 {
473  limb_t temp[NUM_LIMBS];
474  dlimb_t carry;
475  uint8_t posn;
476 
477  // Perform a trial subtraction of (2^255 - 19) from "x" which is
478  // equivalent to adding 19 and subtracting 2^255. We add 19 here;
479  // the subtraction of 2^255 occurs in the next step.
480  carry = 19U;
481  for (posn = 0; posn < NUM_LIMBS; ++posn) {
482  carry += x[posn];
483  temp[posn] = (limb_t)carry;
484  carry >>= LIMB_BITS;
485  }
486 
487  // If there was a borrow, then the original "x" is the correct answer.
488  // If there was no borrow, then "temp" is the correct answer. Select the
489  // correct answer but do it in a way that instruction timing will not
490  // reveal which value was selected. Borrow will occur if the high bit
491  // of "temp" is 0: turn the high bit into a selection mask.
492  limb_t mask = (limb_t)(((slimb_t)(temp[NUM_LIMBS - 1])) >> (LIMB_BITS - 1));
493  limb_t nmask = ~mask;
494  temp[NUM_LIMBS - 1] &= ((((limb_t)1) << (LIMB_BITS - 1)) - 1);
495  for (posn = 0; posn < NUM_LIMBS; ++posn) {
496  x[posn] = (x[posn] & nmask) | (temp[posn] & mask);
497  }
498 
499  // Clean up "temp".
500  clean(temp);
501 
502  // Return a zero value if we actually subtracted (2^255 - 19) from "x".
503  return nmask;
504 }
505 
516 void Curve25519::mul(limb_t *result, const limb_t *x, const limb_t *y)
517 {
518  limb_t temp[NUM_LIMBS * 2];
519  uint8_t i, j;
520  dlimb_t carry;
521  limb_t word;
522 
523  // Multiply the lowest word of x by y.
524  carry = 0;
525  word = x[0];
526  for (i = 0; i < NUM_LIMBS; ++i) {
527  carry += ((dlimb_t)(y[i])) * word;
528  temp[i] = (limb_t)carry;
529  carry >>= LIMB_BITS;
530  }
531  temp[NUM_LIMBS] = (limb_t)carry;
532 
533  // Multiply and add the remaining words of x by y.
534  for (i = 1; i < NUM_LIMBS; ++i) {
535  word = x[i];
536  carry = 0;
537  for (j = 0; j < NUM_LIMBS; ++j) {
538  carry += ((dlimb_t)(y[j])) * word;
539  carry += temp[i + j];
540  temp[i + j] = (limb_t)carry;
541  carry >>= LIMB_BITS;
542  }
543  temp[i + NUM_LIMBS] = (limb_t)carry;
544  }
545 
546  // Reduce the intermediate result modulo 2^255 - 19.
547  reduce(result, temp, NUM_LIMBS);
548  clean(temp);
549 }
550 
570 void Curve25519::mulA24(limb_t *result, const limb_t *x)
571 {
572  // The constant a24 = 121665 (0x1DB41) as a limb array.
573 #if BIGNUMBER_LIMB_8BIT
574  static limb_t const a24[3] PROGMEM = {0x41, 0xDB, 0x01};
575  #define pgm_read_a24(index) (pgm_read_byte(&(a24[(index)])))
576 #elif BIGNUMBER_LIMB_16BIT
577  static limb_t const a24[2] PROGMEM = {0xDB41, 0x0001};
578  #define pgm_read_a24(index) (pgm_read_word(&(a24[(index)])))
579 #elif BIGNUMBER_LIMB_32BIT
580  static limb_t const a24[1] PROGMEM = {0x0001DB41};
581  #define pgm_read_a24(index) (pgm_read_dword(&(a24[(index)])))
582 #else
583  #error "limb_t must be 8, 16, or 32 bits in size"
584 #endif
585  #define NUM_A24_LIMBS (sizeof(a24) / sizeof(limb_t))
586 
587  // Multiply the lowest limb of a24 by x and zero-extend into the result.
588  limb_t temp[NUM_LIMBS * 2];
589  uint8_t i, j;
590  dlimb_t carry = 0;
591  limb_t word = pgm_read_a24(0);
592  for (i = 0; i < NUM_LIMBS; ++i) {
593  carry += ((dlimb_t)(x[i])) * word;
594  temp[i] = (limb_t)carry;
595  carry >>= LIMB_BITS;
596  }
597  temp[NUM_LIMBS] = (limb_t)carry;
598 
599  // Multiply and add the remaining limbs of a24.
600  for (i = 1; i < NUM_A24_LIMBS; ++i) {
601  word = pgm_read_a24(i);
602  carry = 0;
603  for (j = 0; j < NUM_LIMBS; ++j) {
604  carry += ((dlimb_t)(x[j])) * word;
605  carry += temp[i + j];
606  temp[i + j] = (limb_t)carry;
607  carry >>= LIMB_BITS;
608  }
609  temp[i + NUM_LIMBS] = (limb_t)carry;
610  }
611 
612  // Reduce the intermediate result modulo 2^255 - 19.
613  reduce(result, temp, NUM_A24_LIMBS);
614  clean(temp);
615 }
616 
627 void Curve25519::add(limb_t *result, const limb_t *x, const limb_t *y)
628 {
629  dlimb_t carry = 0;
630  uint8_t posn;
631 
632  // Add the two arrays to obtain the intermediate result.
633  for (posn = 0; posn < NUM_LIMBS; ++posn) {
634  carry += x[posn];
635  carry += y[posn];
636  result[posn] = (limb_t)carry;
637  carry >>= LIMB_BITS;
638  }
639 
640  // Reduce the result using the quick trial subtraction method.
641  reduceQuick(result);
642 }
643 
654 void Curve25519::sub(limb_t *result, const limb_t *x, const limb_t *y)
655 {
656  dlimb_t borrow;
657  uint8_t posn;
658 
659  // Subtract y from x to generate the intermediate result.
660  borrow = 0;
661  for (posn = 0; posn < NUM_LIMBS; ++posn) {
662  borrow = ((dlimb_t)x[posn]) - y[posn] - ((borrow >> LIMB_BITS) & 0x01);
663  result[posn] = (limb_t)borrow;
664  }
665 
666  // If we had a borrow, then the result has gone negative and we
667  // have to add 2^255 - 19 to the result to make it positive again.
668  // The top bits of "borrow" will be all 1's if there is a borrow
669  // or it will be all 0's if there was no borrow. Easiest is to
670  // conditionally subtract 19 and then mask off the high bit.
671  borrow = (borrow >> LIMB_BITS) & 19U;
672  borrow = ((dlimb_t)result[0]) - borrow;
673  result[0] = (limb_t)borrow;
674  for (posn = 1; posn < NUM_LIMBS; ++posn) {
675  borrow = ((dlimb_t)result[posn]) - ((borrow >> LIMB_BITS) & 0x01);
676  result[posn] = (limb_t)borrow;
677  }
678  result[NUM_LIMBS - 1] &= ((((limb_t)1) << (LIMB_BITS - 1)) - 1);
679 }
680 
691 void Curve25519::cswap(uint8_t select, limb_t *x, limb_t *y)
692 {
693  uint8_t posn;
694  limb_t dummy;
695  limb_t sel;
696 
697  // Turn "select" into an all-zeroes or all-ones mask. We don't care
698  // which bit or bits is set in the original "select" value.
699  sel = (limb_t)(((((dlimb_t)1) << LIMB_BITS) - select) >> LIMB_BITS);
700  --sel;
701 
702  // Swap the two values based on "select". Algorithm from:
703  // https://tools.ietf.org/html/draft-irtf-cfrg-curves-02
704  for (posn = 0; posn < NUM_LIMBS; ++posn) {
705  dummy = sel & (x[posn] ^ y[posn]);
706  x[posn] ^= dummy;
707  y[posn] ^= dummy;
708  }
709 }
710 
718 void Curve25519::recip(limb_t *result, const limb_t *x)
719 {
720  limb_t t1[NUM_LIMBS];
721  uint8_t i, j;
722 
723  // The reciprocal is the same as x ^ (p - 2) where p = 2^255 - 19.
724  // The big-endian hexadecimal expansion of (p - 2) is:
725  // 7FFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFEB
726  //
727  // The naive implementation needs to do 2 multiplications per 1 bit and
728  // 1 multiplication per 0 bit. We can improve upon this by creating a
729  // pattern 0000000001 ... 0000000001. If we square and multiply the
730  // pattern by itself we can turn the pattern into the partial results
731  // 0000000011 ... 0000000011, 0000000111 ... 0000000111, etc.
732  // This averages out to about 1.1 multiplications per 1 bit instead of 2.
733 
734  // Build a pattern of 250 bits in length of repeated copies of 0000000001.
735  #define RECIP_GROUP_SIZE 10
736  #define RECIP_GROUP_BITS 250 // Must be a multiple of RECIP_GROUP_SIZE.
737  square(t1, x);
738  for (j = 0; j < (RECIP_GROUP_SIZE - 1); ++j)
739  square(t1, t1);
740  mul(result, t1, x);
741  for (i = 0; i < ((RECIP_GROUP_BITS / RECIP_GROUP_SIZE) - 2); ++i) {
742  for (j = 0; j < RECIP_GROUP_SIZE; ++j)
743  square(t1, t1);
744  mul(result, result, t1);
745  }
746 
747  // Multiply bit-shifted versions of the 0000000001 pattern into
748  // the result to "fill in" the gaps in the pattern.
749  square(t1, result);
750  mul(result, result, t1);
751  for (j = 0; j < (RECIP_GROUP_SIZE - 2); ++j) {
752  square(t1, t1);
753  mul(result, result, t1);
754  }
755 
756  // Deal with the 5 lowest bits of (p - 2), 01011, from highest to lowest.
757  square(result, result);
758  square(result, result);
759  mul(result, result, x);
760  square(result, result);
761  square(result, result);
762  mul(result, result, x);
763  square(result, result);
764  mul(result, result, x);
765 
766  // Clean up and exit.
767  clean(t1);
768 }
769 
782 void Curve25519::unpack(limb_t *result, const uint8_t *x)
783 {
784 #if BIGNUMBER_LIMB_8BIT
785  memcpy(result, x, 32);
786  result[31] &= 0x7F;
787 #elif BIGNUMBER_LIMB_16BIT
788  for (uint8_t posn = 0; posn < 16; ++posn) {
789  result[posn] = ((limb_t)x[posn * 2]) | (((limb_t)x[posn * 2 + 1]) << 8);
790  }
791  result[15] &= 0x7FFF;
792 #elif BIGNUMBER_LIMB_32BIT
793  for (uint8_t posn = 0; posn < 8; ++posn) {
794  result[posn] = ((limb_t)x[posn * 4]) |
795  (((limb_t)x[posn * 4 + 1]) << 8) |
796  (((limb_t)x[posn * 4 + 2]) << 16) |
797  (((limb_t)x[posn * 4 + 3]) << 24);
798  }
799  result[7] &= 0x7FFFFFFF;
800 #endif
801 }
802 
812 void Curve25519::pack(uint8_t *result, const limb_t *x)
813 {
814 #if BIGNUMBER_LIMB_8BIT
815  memcpy(result, x, 32);
816 #elif BIGNUMBER_LIMB_16BIT
817  for (uint8_t posn = 0; posn < 16; ++posn) {
818  limb_t value = x[posn];
819  result[posn * 2] = (uint8_t)value;
820  result[posn * 2 + 1] = (uint8_t)(value >> 8);
821  }
822 #elif BIGNUMBER_LIMB_32BIT
823  for (uint8_t posn = 0; posn < 8; ++posn) {
824  limb_t value = x[posn];
825  result[posn * 4] = (uint8_t)value;
826  result[posn * 4 + 1] = (uint8_t)(value >> 8);
827  result[posn * 4 + 2] = (uint8_t)(value >> 16);
828  result[posn * 4 + 3] = (uint8_t)(value >> 24);
829  }
830 #endif
831 }
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:68
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:231
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:269