ed25519_tor.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /*
  2. Public domain by Andrew M. <liquidsun@gmail.com>
  3. Ed25519 reference implementation using Ed25519-donna
  4. */
  5. /*
  6. Tor specific notes:
  7. This file is used by Tor instead of `ed25519.c` as the number of
  8. changes/additions is non-trivial.
  9. Tor modifications to `ed25519.c`:
  10. * 'Tab` -> ' '.
  11. * Include `ed25519_donna_tor.h` instead of `ed25519.h`.
  12. * The external interface has been reworked to match that provided
  13. by Tor's copy of the SUPERCOP `ref10` code.
  14. * The secret (aka private) key is now stored/used in expanded form.
  15. * The internal math tests from `test-internals.c` have been wrapped
  16. in a function and the entire file is included to allow for
  17. runtime validation.
  18. */
  19. /* define ED25519_SUFFIX to have it appended to the end of each public function */
  20. #if !defined(ED25519_SUFFIX)
  21. #define ED25519_SUFFIX
  22. #endif
  23. #define ED25519_FN3(fn,suffix) fn##suffix
  24. #define ED25519_FN2(fn,suffix) ED25519_FN3(fn,suffix)
  25. #define ED25519_FN(fn) ED25519_FN2(fn,ED25519_SUFFIX)
  26. #include "ed25519-donna.h"
  27. #include "ed25519_donna_tor.h"
  28. #include "ed25519-randombytes.h"
  29. #include "ed25519-hash.h"
  30. typedef unsigned char ed25519_signature[64];
  31. typedef unsigned char ed25519_public_key[32];
  32. typedef unsigned char ed25519_secret_key[32];
  33. static int ED25519_FN(ed25519_sign_open) (const unsigned char *m, size_t mlen,
  34. const ed25519_public_key pk, const ed25519_signature RS);
  35. /*
  36. Generates a (extsk[0..31]) and aExt (extsk[32..63])
  37. */
  38. DONNA_INLINE static void
  39. ed25519_extsk(hash_512bits extsk, const ed25519_secret_key sk) {
  40. ed25519_hash(extsk, sk, 32);
  41. extsk[0] &= 248;
  42. extsk[31] &= 127;
  43. extsk[31] |= 64;
  44. }
  45. static void
  46. ed25519_hram(hash_512bits hram, const ed25519_signature RS, const ed25519_public_key pk, const unsigned char *m, size_t mlen) {
  47. ed25519_hash_context ctx;
  48. ed25519_hash_init(&ctx);
  49. ed25519_hash_update(&ctx, RS, 32);
  50. ed25519_hash_update(&ctx, pk, 32);
  51. ed25519_hash_update(&ctx, m, mlen);
  52. ed25519_hash_final(&ctx, hram);
  53. }
  54. static int
  55. ED25519_FN(ed25519_sign_open) (const unsigned char *m, size_t mlen, const ed25519_public_key pk, const ed25519_signature RS) {
  56. ge25519 ALIGN(16) R, A;
  57. hash_512bits hash;
  58. bignum256modm hram, S;
  59. unsigned char checkR[32];
  60. if ((RS[63] & 224) || !ge25519_unpack_negative_vartime(&A, pk))
  61. return -1;
  62. /* hram = H(R,A,m) */
  63. ed25519_hram(hash, RS, pk, m, mlen);
  64. expand256_modm(hram, hash, 64);
  65. /* S */
  66. expand256_modm(S, RS + 32, 32);
  67. /* SB - H(R,A,m)A */
  68. ge25519_double_scalarmult_vartime(&R, &A, hram, S);
  69. ge25519_pack(checkR, &R);
  70. /* check that R = SB - H(R,A,m)A */
  71. return ed25519_verify(RS, checkR, 32) ? 0 : -1;
  72. }
  73. #include "ed25519-donna-batchverify.h"
  74. /*
  75. Fast Curve25519 basepoint scalar multiplication
  76. */
  77. void
  78. ED25519_FN(curved25519_scalarmult_basepoint) (curved25519_key pk, const curved25519_key e) {
  79. curved25519_key ec;
  80. bignum256modm s;
  81. bignum25519 ALIGN(16) yplusz, zminusy;
  82. ge25519 ALIGN(16) p;
  83. size_t i;
  84. /* clamp */
  85. for (i = 0; i < 32; i++) ec[i] = e[i];
  86. ec[0] &= 248;
  87. ec[31] &= 127;
  88. ec[31] |= 64;
  89. expand_raw256_modm(s, ec);
  90. /* scalar * basepoint */
  91. ge25519_scalarmult_base_niels(&p, ge25519_niels_base_multiples, s);
  92. /* u = (y + z) / (z - y) */
  93. curve25519_add(yplusz, p.y, p.z);
  94. curve25519_sub(zminusy, p.z, p.y);
  95. curve25519_recip(zminusy, zminusy);
  96. curve25519_mul(yplusz, yplusz, zminusy);
  97. curve25519_contract(pk, yplusz);
  98. }
  99. /*
  100. Tor has a specific idea of how an Ed25519 implementaion should behave.
  101. Implement such a beast using the ed25519-donna primitives/internals.
  102. * Private key generation using Tor's CSPRNG.
  103. * Routines that deal with the private key now use the expanded form.
  104. */
  105. int
  106. ed25519_donna_seckey(unsigned char *sk)
  107. {
  108. ed25519_secret_key seed;
  109. if (crypto_strongest_rand(seed, 32))
  110. return -1;
  111. ed25519_extsk(sk, seed);
  112. memwipe(seed, 0, sizeof(seed));
  113. return 0;
  114. }
  115. int
  116. ed25519_donna_seckey_expand(unsigned char *sk, const unsigned char *skseed)
  117. {
  118. ed25519_extsk(sk, skseed);
  119. return 0;
  120. }
  121. int
  122. ed25519_donna_pubkey(unsigned char *pk, const unsigned char *sk)
  123. {
  124. bignum256modm a;
  125. ge25519 ALIGN(16) A;
  126. /* A = aB */
  127. expand256_modm(a, sk, 32);
  128. ge25519_scalarmult_base_niels(&A, ge25519_niels_base_multiples, a);
  129. ge25519_pack(pk, &A);
  130. return 0;
  131. }
  132. int
  133. ed25519_donna_keygen(unsigned char *pk, unsigned char *sk)
  134. {
  135. int ok;
  136. ok = ed25519_donna_seckey(sk);
  137. ed25519_donna_pubkey(pk, sk);
  138. return ok;
  139. }
  140. int
  141. ed25519_donna_open(const unsigned char *signature, const unsigned char *m,
  142. size_t mlen, const unsigned char *pk)
  143. {
  144. /* Wrap the ed25519-donna routine, since it is also used by the batch
  145. * verification code.
  146. */
  147. return ED25519_FN(ed25519_sign_open)(m, mlen, pk, signature);
  148. }
  149. int
  150. ed25519_donna_sign(unsigned char *sig, const unsigned char *m, size_t mlen,
  151. const unsigned char *sk, const unsigned char *pk)
  152. {
  153. ed25519_hash_context ctx;
  154. bignum256modm r, S, a;
  155. ge25519 ALIGN(16) R;
  156. hash_512bits hashr, hram;
  157. /* This is equivalent to the removed `ED25519_FN(ed25519_sign)` routine,
  158. * except that the key expansion step is omitted as sk already is in expanded
  159. * form.
  160. */
  161. /* r = H(aExt[32..64], m) */
  162. ed25519_hash_init(&ctx);
  163. ed25519_hash_update(&ctx, sk + 32, 32);
  164. ed25519_hash_update(&ctx, m, mlen);
  165. ed25519_hash_final(&ctx, hashr);
  166. expand256_modm(r, hashr, 64);
  167. /* R = rB */
  168. ge25519_scalarmult_base_niels(&R, ge25519_niels_base_multiples, r);
  169. ge25519_pack(sig, &R);
  170. /* S = H(R,A,m).. */
  171. ed25519_hram(hram, sig, pk, m, mlen);
  172. expand256_modm(S, hram, 64);
  173. /* S = H(R,A,m)a */
  174. expand256_modm(a, sk, 32);
  175. mul256_modm(S, S, a);
  176. /* S = (r + H(R,A,m)a) */
  177. add256_modm(S, S, r);
  178. /* S = (r + H(R,A,m)a) mod L */
  179. contract256_modm(sig + 32, S);
  180. return 0;
  181. }
  182. #include "test-internals.c"