ed25519_tor.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  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 "orconfig.h"
  27. #include "ed25519-donna.h"
  28. #include "ed25519_donna_tor.h"
  29. #include "ed25519-randombytes.h"
  30. #include "ed25519-hash.h"
  31. #include "lib/crypt_ops/crypto_util.h"
  32. typedef unsigned char ed25519_signature[64];
  33. typedef unsigned char ed25519_public_key[32];
  34. typedef unsigned char ed25519_secret_key[32];
  35. static void ed25519_donna_gettweak(unsigned char *out,
  36. const unsigned char *param);
  37. static int ED25519_FN(ed25519_sign_open) (const unsigned char *m, size_t mlen,
  38. const ed25519_public_key pk, const ed25519_signature RS);
  39. /*
  40. Generates a (extsk[0..31]) and aExt (extsk[32..63])
  41. */
  42. DONNA_INLINE static void
  43. ed25519_extsk(hash_512bits extsk, const ed25519_secret_key sk) {
  44. ed25519_hash(extsk, sk, 32);
  45. extsk[0] &= 248;
  46. extsk[31] &= 127;
  47. extsk[31] |= 64;
  48. }
  49. static void
  50. ed25519_hram(hash_512bits hram, const ed25519_signature RS, const ed25519_public_key pk, const unsigned char *m, size_t mlen) {
  51. ed25519_hash_context ctx;
  52. ed25519_hash_init(&ctx);
  53. ed25519_hash_update(&ctx, RS, 32);
  54. ed25519_hash_update(&ctx, pk, 32);
  55. ed25519_hash_update(&ctx, m, mlen);
  56. ed25519_hash_final(&ctx, hram);
  57. }
  58. static int
  59. ED25519_FN(ed25519_sign_open) (const unsigned char *m, size_t mlen, const ed25519_public_key pk, const ed25519_signature RS) {
  60. ge25519 ALIGN(16) R, A;
  61. hash_512bits hash;
  62. bignum256modm hram, S;
  63. unsigned char checkR[32];
  64. if ((RS[63] & 224) || !ge25519_unpack_negative_vartime(&A, pk))
  65. return -1;
  66. /* hram = H(R,A,m) */
  67. ed25519_hram(hash, RS, pk, m, mlen);
  68. expand256_modm(hram, hash, 64);
  69. /* S */
  70. expand256_modm(S, RS + 32, 32);
  71. /* SB - H(R,A,m)A */
  72. ge25519_double_scalarmult_vartime(&R, &A, hram, S);
  73. ge25519_pack(checkR, &R);
  74. /* check that R = SB - H(R,A,m)A */
  75. return ed25519_verify(RS, checkR, 32) ? 0 : -1;
  76. }
  77. #include "ed25519-donna-batchverify.h"
  78. /*
  79. Fast Curve25519 basepoint scalar multiplication
  80. */
  81. void
  82. ED25519_FN(curved25519_scalarmult_basepoint) (curved25519_key pk, const curved25519_key e) {
  83. curved25519_key ec;
  84. bignum256modm s;
  85. bignum25519 ALIGN(16) yplusz, zminusy;
  86. ge25519 ALIGN(16) p;
  87. size_t i;
  88. /* clamp */
  89. for (i = 0; i < 32; i++) ec[i] = e[i];
  90. ec[0] &= 248;
  91. ec[31] &= 127;
  92. ec[31] |= 64;
  93. expand_raw256_modm(s, ec);
  94. /* scalar * basepoint */
  95. ge25519_scalarmult_base_niels(&p, ge25519_niels_base_multiples, s);
  96. /* u = (y + z) / (z - y) */
  97. curve25519_add(yplusz, p.y, p.z);
  98. curve25519_sub(zminusy, p.z, p.y);
  99. curve25519_recip(zminusy, zminusy);
  100. curve25519_mul(yplusz, yplusz, zminusy);
  101. curve25519_contract(pk, yplusz);
  102. }
  103. /*
  104. Tor has a specific idea of how an Ed25519 implementation should behave.
  105. Implement such a beast using the ed25519-donna primitives/internals.
  106. * Private key generation using Tor's CSPRNG.
  107. * Routines that deal with the private key now use the expanded form.
  108. * Support for multiplicative key blinding has been added.
  109. * Support for converting a Curve25519 key to an Ed25519 key has been added.
  110. */
  111. int
  112. ed25519_donna_seckey(unsigned char *sk)
  113. {
  114. ed25519_secret_key seed;
  115. crypto_strongest_rand(seed, 32);
  116. ed25519_extsk(sk, seed);
  117. memwipe(seed, 0, sizeof(seed));
  118. return 0;
  119. }
  120. int
  121. ed25519_donna_seckey_expand(unsigned char *sk, const unsigned char *skseed)
  122. {
  123. ed25519_extsk(sk, skseed);
  124. return 0;
  125. }
  126. int
  127. ed25519_donna_pubkey(unsigned char *pk, const unsigned char *sk)
  128. {
  129. bignum256modm a = {0};
  130. ge25519 ALIGN(16) A = {{0}, {0}, {0}, {0}};
  131. /* A = aB */
  132. expand256_modm(a, sk, 32);
  133. ge25519_scalarmult_base_niels(&A, ge25519_niels_base_multiples, a);
  134. ge25519_pack(pk, &A);
  135. return 0;
  136. }
  137. int
  138. ed25519_donna_keygen(unsigned char *pk, unsigned char *sk)
  139. {
  140. int ok;
  141. ok = ed25519_donna_seckey(sk);
  142. ed25519_donna_pubkey(pk, sk);
  143. return ok;
  144. }
  145. int
  146. ed25519_donna_open(const unsigned char *signature, const unsigned char *m,
  147. size_t mlen, const unsigned char *pk)
  148. {
  149. /* Wrap the ed25519-donna routine, since it is also used by the batch
  150. * verification code.
  151. */
  152. return ED25519_FN(ed25519_sign_open)(m, mlen, pk, signature);
  153. }
  154. int
  155. ed25519_donna_sign(unsigned char *sig, const unsigned char *m, size_t mlen,
  156. const unsigned char *sk, const unsigned char *pk)
  157. {
  158. ed25519_hash_context ctx;
  159. bignum256modm r = {0}, S, a;
  160. ge25519 ALIGN(16) R = {{0}, {0}, {0}, {0}};
  161. hash_512bits hashr, hram;
  162. /* This is equivalent to the removed `ED25519_FN(ed25519_sign)` routine,
  163. * except that the key expansion step is omitted as sk already is in expanded
  164. * form.
  165. */
  166. /* r = H(aExt[32..64], m) */
  167. ed25519_hash_init(&ctx);
  168. ed25519_hash_update(&ctx, sk + 32, 32);
  169. ed25519_hash_update(&ctx, m, mlen);
  170. ed25519_hash_final(&ctx, hashr);
  171. expand256_modm(r, hashr, 64);
  172. /* R = rB */
  173. ge25519_scalarmult_base_niels(&R, ge25519_niels_base_multiples, r);
  174. ge25519_pack(sig, &R);
  175. /* S = H(R,A,m).. */
  176. ed25519_hram(hram, sig, pk, m, mlen);
  177. expand256_modm(S, hram, 64);
  178. /* S = H(R,A,m)a */
  179. expand256_modm(a, sk, 32);
  180. mul256_modm(S, S, a);
  181. /* S = (r + H(R,A,m)a) */
  182. add256_modm(S, S, r);
  183. /* S = (r + H(R,A,m)a) mod L */
  184. contract256_modm(sig + 32, S);
  185. return 0;
  186. }
  187. static void
  188. ed25519_donna_gettweak(unsigned char *out, const unsigned char *param)
  189. {
  190. memcpy(out, param, 32);
  191. out[0] &= 248; /* Is this necessary ? */
  192. out[31] &= 63;
  193. out[31] |= 64;
  194. }
  195. int
  196. ed25519_donna_blind_secret_key(unsigned char *out, const unsigned char *inp,
  197. const unsigned char *param)
  198. {
  199. static const char str[] = "Derive temporary signing key hash input";
  200. unsigned char tweak[64];
  201. ed25519_hash_context ctx;
  202. bignum256modm ALIGN(16) sk, t;
  203. ed25519_donna_gettweak(tweak, param);
  204. expand256_modm(t, tweak, 32);
  205. expand256_modm(sk, inp, 32);
  206. mul256_modm(sk, sk, t);
  207. contract256_modm(out, sk);
  208. ed25519_hash_init(&ctx);
  209. ed25519_hash_update(&ctx, (const unsigned char*)str, strlen(str));
  210. ed25519_hash_update(&ctx, inp + 32, 32);
  211. ed25519_hash_final(&ctx, tweak);
  212. memcpy(out + 32, tweak, 32);
  213. memwipe(sk, 0, sizeof(sk));
  214. memwipe(t, 0, sizeof(t));
  215. memwipe(tweak, 0, sizeof(tweak));
  216. return 0;
  217. }
  218. int
  219. ed25519_donna_blind_public_key(unsigned char *out, const unsigned char *inp,
  220. const unsigned char *param)
  221. {
  222. static const bignum256modm zero = { 0 };
  223. unsigned char tweak[64];
  224. unsigned char pkcopy[32];
  225. ge25519 ALIGN(16) A, Aprime;
  226. bignum256modm ALIGN(16) t;
  227. ed25519_donna_gettweak(tweak, param);
  228. expand256_modm(t, tweak, 32);
  229. /* No "ge25519_unpack", negate the public key. */
  230. memcpy(pkcopy, inp, 32);
  231. pkcopy[31] ^= (1<<7);
  232. if (!ge25519_unpack_negative_vartime(&A, pkcopy)) {
  233. return -1;
  234. }
  235. /* A' = [tweak] * A + [0] * basepoint. */
  236. ge25519_double_scalarmult_vartime(&Aprime, &A, t, zero);
  237. ge25519_pack(out, &Aprime);
  238. memwipe(tweak, 0, sizeof(tweak));
  239. memwipe(pkcopy, 0, sizeof(pkcopy));
  240. memwipe(&A, 0, sizeof(A));
  241. memwipe(&Aprime, 0, sizeof(Aprime));
  242. memwipe(t, 0, sizeof(t));
  243. return 0;
  244. }
  245. int
  246. ed25519_donna_pubkey_from_curve25519_pubkey(unsigned char *out,
  247. const unsigned char *inp, int signbit)
  248. {
  249. static const bignum25519 ALIGN(16) one = { 1 };
  250. bignum25519 ALIGN(16) u, uminus1, uplus1, inv_uplus1, y;
  251. /* Prop228: y = (u-1)/(u+1) */
  252. curve25519_expand(u, inp);
  253. curve25519_sub(uminus1, u, one);
  254. curve25519_add(uplus1, u, one);
  255. curve25519_recip(inv_uplus1, uplus1);
  256. curve25519_mul(y, uminus1, inv_uplus1);
  257. curve25519_contract(out, y);
  258. /* Propagate sign. */
  259. out[31] |= (!!signbit) << 7;
  260. return 0;
  261. }
  262. /* Do the scalar multiplication of <b>pubkey</b> with the group order
  263. * <b>modm_m</b>. Place the result in <b>out</b> which must be at least 32
  264. * bytes long. */
  265. int
  266. ed25519_donna_scalarmult_with_group_order(unsigned char *out,
  267. const unsigned char *pubkey)
  268. {
  269. static const bignum256modm ALIGN(16) zero = { 0 };
  270. unsigned char pkcopy[32];
  271. ge25519 ALIGN(16) Point, Result;
  272. /* No "ge25519_unpack", negate the public key and unpack it back.
  273. * See ed25519_donna_blind_public_key() */
  274. memcpy(pkcopy, pubkey, 32);
  275. pkcopy[31] ^= (1<<7);
  276. if (!ge25519_unpack_negative_vartime(&Point, pkcopy)) {
  277. return -1; /* error: bail out */
  278. }
  279. /* There is no regular scalarmult function so we have to do:
  280. * Result = l*P + 0*B */
  281. ge25519_double_scalarmult_vartime(&Result, &Point, modm_m, zero);
  282. ge25519_pack(out, &Result);
  283. return 0;
  284. }
  285. #include "test-internals.c"