You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

300 lines
8.7 KiB

  1. /* Copyright (c) 2014 Cryptography Research, Inc.
  2. * Released under the MIT License. See LICENSE.txt for license information.
  3. */
  4. #include <errno.h>
  5. #include "goldilocks.h"
  6. #include "ec_point.h"
  7. #include "scalarmul.h"
  8. #include "barrett_field.h"
  9. #include "crandom.h"
  10. #include "sha512.h"
  11. #ifndef GOLDILOCKS_RANDOM_INIT_FILE
  12. #define GOLDILOCKS_RANDOM_INIT_FILE "/dev/urandom"
  13. #endif
  14. #ifndef GOLDILOCKS_RANDOM_RESEED_INTERVAL
  15. #define GOLDILOCKS_RANDOM_RESEED_INTERVAL 10000
  16. #endif
  17. /* We'll check it ourselves */
  18. #ifndef GOLDILOCKS_RANDOM_RESEEDS_MANDATORY
  19. #define GOLDILOCKS_RANDOM_RESEEDS_MANDATORY 0
  20. #endif
  21. /* TODO: word size; precompute */
  22. const struct affine_t goldilocks_base_point = {
  23. {{ 0xf0de840aed939full, 0xc170033f4ba0c7ull, 0xf3932d94c63d96ull, 0x9cecfa96147eaaull,
  24. 0x5f065c3c59d070ull, 0x3a6a26adf73324ull, 0x1b4faff4609845ull, 0x297ea0ea2692ffull
  25. }},
  26. {{ 19, 0, 0, 0, 0, 0, 0, 0 }}
  27. };
  28. // /* TODO: direct */
  29. // void
  30. // transfer_and_serialize(struct p448_t *out, const struct tw_extensible_t *twext) {
  31. // struct extensible_t ext;
  32. // transfer_tw_to_un(&ext, twext);
  33. // serialize_extensible(out, &ext);
  34. // }
  35. // FIXME: threading
  36. // TODO: autogen instead of init
  37. struct {
  38. struct tw_niels_t combs[80];
  39. struct tw_niels_t wnafs[32];
  40. struct crandom_state_t rand;
  41. } goldilocks_global;
  42. int
  43. goldilocks_init () {
  44. struct extensible_t ext;
  45. struct tw_extensible_t text;
  46. /* Sanity check: the base point is on the curve. */
  47. assert(validate_affine(&goldilocks_base_point));
  48. /* Convert it to twisted Edwards. */
  49. convert_affine_to_extensible(&ext, &goldilocks_base_point);
  50. twist(&text, &ext);
  51. //p448_transfer_un_to_tw(&text, &ext);
  52. /* Precompute the tables. */
  53. precompute_for_combs(goldilocks_global.combs, &text, 5, 5, 18);
  54. precompute_for_wnaf(goldilocks_global.wnafs, &text, 5);
  55. return crandom_init_from_file(&goldilocks_global.rand,
  56. GOLDILOCKS_RANDOM_INIT_FILE,
  57. GOLDILOCKS_RANDOM_RESEED_INTERVAL,
  58. GOLDILOCKS_RANDOM_RESEEDS_MANDATORY);
  59. }
  60. static word_t
  61. q448_lo[4] = {
  62. 0xdc873d6d54a7bb0dull,
  63. 0xde933d8d723a70aaull,
  64. 0x3bb124b65129c96full,
  65. 0x000000008335dc16ull
  66. };
  67. static const struct p448_t
  68. sqrt_d_minus_1 = {{
  69. 0xd2e21836749f46ull,
  70. 0x888db42b4f0179ull,
  71. 0x5a189aabdeea38ull,
  72. 0x51e65ca6f14c06ull,
  73. 0xa49f7b424d9770ull,
  74. 0xdcac4628c5f656ull,
  75. 0x49443b8748734aull,
  76. 0x12fec0c0b25b7aull
  77. }};
  78. int
  79. goldilocks_keygen (
  80. struct goldilocks_private_key_t *privkey,
  81. struct goldilocks_public_key_t *pubkey
  82. ) {
  83. // TODO: check for init. Also maybe take CRANDOM object? API...
  84. word_t sk[448*2/WORD_BITS];
  85. struct tw_extensible_t exta;
  86. struct p448_t pk;
  87. int ret = crandom_generate(&goldilocks_global.rand, (unsigned char *)sk, sizeof(sk));
  88. barrett_reduce(sk,sizeof(sk)/sizeof(sk[0]),0,q448_lo,7,4,62); // TODO word size
  89. q448_serialize(privkey->opaque, sk);
  90. edwards_comb(&exta, sk, goldilocks_global.combs, 5, 5, 18);
  91. //transfer_and_serialize_qtor(&pk, &sqrt_d_minus_1, &exta);
  92. untwist_and_double_and_serialize(&pk, &exta);
  93. p448_serialize(pubkey->opaque, &pk);
  94. memcpy(&privkey->opaque[56], pubkey->opaque, 56);
  95. int ret2 = crandom_generate(&goldilocks_global.rand, &privkey->opaque[112], 32);
  96. if (!ret) ret = ret2;
  97. return ret ? GOLDI_ENODICE : GOLDI_EOK;
  98. }
  99. int
  100. goldilocks_shared_secret (
  101. uint8_t shared[64],
  102. const struct goldilocks_private_key_t *my_privkey,
  103. const struct goldilocks_public_key_t *your_pubkey
  104. ) {
  105. word_t sk[448/WORD_BITS];
  106. struct p448_t pk;
  107. mask_t succ = p448_deserialize(&pk,your_pubkey->opaque), msucc = -1;
  108. #ifdef EXPERIMENT_ECDH_STIR_IN_PUBKEYS
  109. struct p448_t sum, prod;
  110. msucc &= p448_deserialize(&sum,&my_privkey->opaque[56]);
  111. p448_mul(&prod,&pk,&sum);
  112. p448_add(&sum,&pk,&sum);
  113. #endif
  114. msucc &= q448_deserialize(sk,my_privkey->opaque);
  115. succ &= p448_montgomery_ladder(&pk,&pk,sk,446,2);
  116. p448_serialize(shared,&pk);
  117. /* obliterate records of our failure by adjusting with obliteration key */
  118. struct sha512_ctx_t ctx;
  119. sha512_init(&ctx);
  120. #ifdef EXPERIMENT_ECDH_OBLITERATE_CT
  121. uint8_t oblit[40];
  122. unsigned i;
  123. for (i=0; i<8; i++) {
  124. oblit[i] = "noshared"[i] & ~(succ&msucc);
  125. }
  126. for (i=0; i<32; i++) {
  127. oblit[8+i] = my_privkey->opaque[112+i] & ~(succ&msucc);
  128. }
  129. sha512_update(&ctx, oblit, 40);
  130. #endif
  131. #ifdef EXPERIMENT_ECDH_STIR_IN_PUBKEYS
  132. /* stir in the sum and product of the pubkeys. */
  133. uint8_t a_pk[56];
  134. p448_serialize(a_pk, &sum);
  135. sha512_update(&ctx, a_pk, 56);
  136. p448_serialize(a_pk, &prod);
  137. sha512_update(&ctx, a_pk, 56);
  138. #endif
  139. /* stir in the shared key and finish */
  140. sha512_update(&ctx, shared, 56);
  141. sha512_final(&ctx, shared);
  142. return (GOLDI_ECORRUPT & ~msucc)
  143. | (GOLDI_EINVAL & msucc &~ succ)
  144. | (GOLDI_EOK & msucc & succ);
  145. }
  146. int
  147. goldilocks_sign (
  148. uint8_t signature_out[56*2],
  149. const uint8_t *message,
  150. uint64_t message_len,
  151. const struct goldilocks_private_key_t *privkey
  152. ) {
  153. /* challenge = H(pk, [nonceG], message). FIXME: endian. */
  154. word_t skw[448/WORD_BITS];
  155. mask_t succ = q448_deserialize(skw,privkey->opaque);
  156. if (!succ) {
  157. memset(skw,0,sizeof(skw));
  158. return GOLDI_ECORRUPT;
  159. }
  160. /* Derive a nonce. TODO: use HMAC. FIXME: endian. FUTURE: factor. */
  161. word_t tk[512/WORD_BITS];
  162. struct sha512_ctx_t ctx;
  163. sha512_init(&ctx);
  164. sha512_update(&ctx, (const unsigned char *)"signonce", 8);
  165. sha512_update(&ctx, &privkey->opaque[112], 32);
  166. sha512_update(&ctx, message, message_len);
  167. sha512_update(&ctx, &privkey->opaque[112], 32);
  168. sha512_final(&ctx, (unsigned char *)tk);
  169. barrett_reduce(tk,512/WORD_BITS,0,q448_lo,7,4,62); // TODO word size
  170. /* 4[nonce]G */
  171. uint8_t signature_tmp[56];
  172. struct tw_extensible_t exta;
  173. struct p448_t gsk;
  174. edwards_comb(&exta, tk, goldilocks_global.combs, 5, 5, 18);
  175. double_tw_extensible(&exta);
  176. untwist_and_double_and_serialize(&gsk, &exta);
  177. p448_serialize(signature_tmp, &gsk);
  178. word_t challenge[512/WORD_BITS];
  179. sha512_update(&ctx, &privkey->opaque[56], 56);
  180. sha512_update(&ctx, signature_tmp, 56);
  181. sha512_update(&ctx, message, message_len);
  182. sha512_final(&ctx, (unsigned char *)challenge);
  183. // reduce challenge and sub.
  184. barrett_negate(challenge,512/WORD_BITS,q448_lo,7,4,62);
  185. barrett_mac(
  186. tk,512/WORD_BITS,
  187. challenge,512/WORD_BITS,
  188. skw,448/WORD_BITS,
  189. q448_lo,7,4,62
  190. );
  191. word_t carry = add_nr_ext_packed(tk,tk,512/WORD_BITS,tk,512/WORD_BITS,-1);
  192. barrett_reduce(tk,512/WORD_BITS,carry,q448_lo,7,4,62);
  193. memcpy(signature_out, signature_tmp, 56);
  194. q448_serialize(signature_out+56, tk);
  195. memset((unsigned char *)tk,0,sizeof(tk));
  196. memset((unsigned char *)skw,0,sizeof(skw));
  197. memset((unsigned char *)challenge,0,sizeof(challenge));
  198. /* response = 2(nonce_secret - sk*challenge)
  199. * Nonce = 8[nonce_secret]*G
  200. * PK = 2[sk]*G, except doubled (TODO)
  201. * so [2] ( [response]G + 2[challenge]PK ) = Nonce
  202. */
  203. return 0;
  204. }
  205. int
  206. goldilocks_verify (
  207. const uint8_t signature[56*2],
  208. const uint8_t *message,
  209. uint64_t message_len,
  210. const struct goldilocks_public_key_t *pubkey
  211. ) {
  212. struct p448_t pk;
  213. word_t s[448/WORD_BITS];
  214. mask_t succ = p448_deserialize(&pk,pubkey->opaque);
  215. if (!succ) return GOLDI_EINVAL;
  216. succ = q448_deserialize(s, &signature[56]);
  217. if (!succ) return GOLDI_EINVAL;
  218. /* challenge = H(pk, [nonceG], message). FIXME: endian. */
  219. word_t challenge[512/WORD_BITS];
  220. struct sha512_ctx_t ctx;
  221. sha512_init(&ctx);
  222. sha512_update(&ctx, pubkey->opaque, 56);
  223. sha512_update(&ctx, signature, 56);
  224. sha512_update(&ctx, message, message_len);
  225. sha512_final(&ctx, (unsigned char *)challenge);
  226. barrett_reduce(challenge,512/WORD_BITS,0,q448_lo,7,4,62);
  227. struct p448_t eph;
  228. struct tw_extensible_t pk_text;
  229. /* deserialize [nonce]G */
  230. succ = p448_deserialize(&eph, signature);
  231. if (!succ) return GOLDI_EINVAL;
  232. // succ = affine_deserialize(&pk_aff,&pk);
  233. // if (!succ) return EINVAL;
  234. //
  235. // convert_affine_to_extensible(&pk_ext,&pk_aff);
  236. // transfer_un_to_tw(&pk_text,&pk_ext);
  237. succ = deserialize_and_twist_approx(&pk_text, &sqrt_d_minus_1, &pk);
  238. if (!succ) return GOLDI_EINVAL;
  239. edwards_combo_var_fixed_vt( &pk_text, challenge, s, goldilocks_global.wnafs, 5 );
  240. untwist_and_double_and_serialize( &pk, &pk_text );
  241. p448_sub(&eph, &eph, &pk);
  242. p448_bias(&eph, 2);
  243. succ = p448_is_zero(&eph);
  244. return succ ? 0 : GOLDI_EINVAL;
  245. }