No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 
 
 

184 líneas
5.9 KiB

  1. /* Copyright (c) 2016, Google Inc.
  2. *
  3. * Permission to use, copy, modify, and/or distribute this software for any
  4. * purpose with or without fee is hereby granted, provided that the above
  5. * copyright notice and this permission notice appear in all copies.
  6. *
  7. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  8. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  9. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  10. * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  11. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  12. * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  13. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
  14. #include <assert.h>
  15. #include <string.h>
  16. #include <openssl/aes.h>
  17. #include <openssl/rand.h>
  18. #include "internal.h"
  19. extern uint16_t newhope_omegas_montgomery[];
  20. extern uint16_t newhope_omegas_inv_montgomery[];
  21. extern uint16_t newhope_psis_bitrev_montgomery[];
  22. extern uint16_t newhope_psis_inv_montgomery[];
  23. void NEWHOPE_POLY_frombytes(NEWHOPE_POLY* r, const uint8_t* a) {
  24. for (int i = 0; i < PARAM_N / 4; i++) {
  25. r->coeffs[4 * i + 0] =
  26. a[7 * i + 0] | (((uint16_t)a[7 * i + 1] & 0x3f) << 8);
  27. r->coeffs[4 * i + 1] = (a[7 * i + 1] >> 6) |
  28. (((uint16_t)a[7 * i + 2]) << 2) |
  29. (((uint16_t)a[7 * i + 3] & 0x0f) << 10);
  30. r->coeffs[4 * i + 2] = (a[7 * i + 3] >> 4) |
  31. (((uint16_t)a[7 * i + 4]) << 4) |
  32. (((uint16_t)a[7 * i + 5] & 0x03) << 12);
  33. r->coeffs[4 * i + 3] =
  34. (a[7 * i + 5] >> 2) | (((uint16_t)a[7 * i + 6]) << 6);
  35. }
  36. }
  37. void NEWHOPE_POLY_tobytes(uint8_t* r, const NEWHOPE_POLY* p) {
  38. uint16_t t0, t1, t2, t3, m;
  39. int16_t c;
  40. for (int i = 0; i < PARAM_N / 4; i++) {
  41. t0 = newhope_barrett_reduce(
  42. p->coeffs[4 * i + 0]); /* Make sure that coefficients
  43. have only 14 bits */
  44. t1 = newhope_barrett_reduce(p->coeffs[4 * i + 1]);
  45. t2 = newhope_barrett_reduce(p->coeffs[4 * i + 2]);
  46. t3 = newhope_barrett_reduce(p->coeffs[4 * i + 3]);
  47. m = t0 - PARAM_Q;
  48. c = m;
  49. c >>= 15;
  50. t0 = m ^ ((t0 ^ m) & c); /* Make sure that coefficients are in [0,q] */
  51. m = t1 - PARAM_Q;
  52. c = m;
  53. c >>= 15;
  54. t1 = m ^ ((t1 ^ m) & c); /* <Make sure that coefficients are in [0,q] */
  55. m = t2 - PARAM_Q;
  56. c = m;
  57. c >>= 15;
  58. t2 = m ^ ((t2 ^ m) & c); /* <Make sure that coefficients are in [0,q] */
  59. m = t3 - PARAM_Q;
  60. c = m;
  61. c >>= 15;
  62. t3 = m ^ ((t3 ^ m) & c); /* Make sure that coefficients are in [0,q] */
  63. r[7 * i + 0] = t0 & 0xff;
  64. r[7 * i + 1] = (t0 >> 8) | (t1 << 6);
  65. r[7 * i + 2] = (t1 >> 2);
  66. r[7 * i + 3] = (t1 >> 10) | (t2 << 4);
  67. r[7 * i + 4] = (t2 >> 4);
  68. r[7 * i + 5] = (t2 >> 12) | (t3 << 2);
  69. r[7 * i + 6] = (t3 >> 6);
  70. }
  71. }
  72. void newhope_poly_uniform(NEWHOPE_POLY* a, const uint8_t* seed) {
  73. /* The reference implementation uses SHAKE-128 here; this implementation uses
  74. * AES-CTR. Use half the seed for the initialization vector and half for the
  75. * key. */
  76. #if SEED_LENGTH != 2 * AES_BLOCK_SIZE
  77. #error "2 * seed length != AES_BLOCK_SIZE"
  78. #endif
  79. uint8_t ivec[AES_BLOCK_SIZE];
  80. memcpy(ivec, &seed[SEED_LENGTH / 2], SEED_LENGTH / 2);
  81. AES_KEY key;
  82. AES_set_encrypt_key(seed, 8 * SEED_LENGTH / 2, &key);
  83. /* AES state. */
  84. uint8_t ecount[AES_BLOCK_SIZE];
  85. memset(ecount, 0, AES_BLOCK_SIZE);
  86. /* Encrypt a block of zeros just to get the random bytes. With luck, 2688
  87. * bytes is enough. */
  88. uint8_t buf[AES_BLOCK_SIZE * 168];
  89. memset(buf, 0, sizeof(buf));
  90. unsigned int block_num = 0;
  91. AES_ctr128_encrypt(buf, buf, sizeof(buf), &key, ivec, ecount, &block_num);
  92. size_t pos = 0, coeff_num = 0;
  93. while (coeff_num < PARAM_N) {
  94. /* Specialized for q = 12889 */
  95. uint16_t val = (buf[pos] | ((uint16_t)buf[pos + 1] << 8)) & 0x3fff;
  96. if (val < PARAM_Q) {
  97. a->coeffs[coeff_num++] = val;
  98. }
  99. pos += 2;
  100. if (pos > sizeof(buf) - 2) {
  101. memset(buf, 0, sizeof(buf));
  102. AES_ctr128_encrypt(buf, buf, sizeof(buf), &key, ivec, ecount, &block_num);
  103. pos = 0;
  104. }
  105. }
  106. }
  107. void NEWHOPE_POLY_noise(NEWHOPE_POLY* r) {
  108. #if PARAM_K != 16
  109. #error "poly_getnoise in poly.c only supports k=16"
  110. #endif
  111. uint32_t tp[PARAM_N];
  112. /* The reference implementation calls ChaCha20 here. */
  113. RAND_bytes((uint8_t *) tp, sizeof(tp));
  114. for (size_t i = 0; i < PARAM_N; i++) {
  115. const uint32_t t = tp[i];
  116. uint32_t d = 0;
  117. for (size_t j = 0; j < 8; j++) {
  118. d += (t >> j) & 0x01010101;
  119. }
  120. const uint32_t a = ((d >> 8) & 0xff) + (d & 0xff);
  121. const uint32_t b = (d >> 24) + ((d >> 16) & 0xff);
  122. r->coeffs[i] = a + PARAM_Q - b;
  123. }
  124. }
  125. void newhope_poly_pointwise(NEWHOPE_POLY* r, const NEWHOPE_POLY* a,
  126. const NEWHOPE_POLY* b) {
  127. for (size_t i = 0; i < PARAM_N; i++) {
  128. uint16_t t = newhope_montgomery_reduce(3186 * b->coeffs[i]);
  129. /* t is now in Montgomery domain */
  130. r->coeffs[i] = newhope_montgomery_reduce(a->coeffs[i] * t);
  131. /* r->coeffs[i] is back in normal domain */
  132. }
  133. }
  134. void newhope_poly_add(NEWHOPE_POLY* r, const NEWHOPE_POLY* a,
  135. const NEWHOPE_POLY* b) {
  136. for (size_t i = 0; i < PARAM_N; i++) {
  137. r->coeffs[i] = newhope_barrett_reduce(a->coeffs[i] + b->coeffs[i]);
  138. }
  139. }
  140. void NEWHOPE_POLY_noise_ntt(NEWHOPE_POLY* r) {
  141. NEWHOPE_POLY_noise(r);
  142. /* Forward NTT transformation. Because we're operating on a noise polynomial,
  143. * we can regard the bits as already reversed and skip the bit-reversal
  144. * step:
  145. *
  146. * newhope_bitrev_vector(r->coeffs); */
  147. newhope_mul_coefficients(r->coeffs, newhope_psis_bitrev_montgomery);
  148. newhope_ntt((uint16_t *) r->coeffs, newhope_omegas_montgomery);
  149. }
  150. void newhope_poly_invntt(NEWHOPE_POLY* r) {
  151. newhope_bitrev_vector(r->coeffs);
  152. newhope_ntt((uint16_t *) r->coeffs, newhope_omegas_inv_montgomery);
  153. newhope_mul_coefficients(r->coeffs, newhope_psis_inv_montgomery);
  154. }