ed25519.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /*
  2. Public domain by Andrew M. <liquidsun@gmail.com>
  3. Ed25519 reference implementation using Ed25519-donna
  4. */
  5. /* define ED25519_SUFFIX to have it appended to the end of each public function */
  6. #ifdef ED25519_SUFFIX
  7. #define ED25519_FN3(fn, suffix) fn##suffix
  8. #define ED25519_FN2(fn, suffix) ED25519_FN3(fn, suffix)
  9. #define ED25519_FN(fn) ED25519_FN2(fn, ED25519_SUFFIX)
  10. #else
  11. #define ED25519_FN(fn) fn
  12. #endif
  13. #include "ed25519_donna.h"
  14. #include "ed25519.h"
  15. #include "ed25519_hash_custom.h"
  16. #include "../rand.h"
  17. #include "../memzero.h"
  18. /*
  19. Generates a (extsk[0..31]) and aExt (extsk[32..63])
  20. */
  21. DONNA_INLINE static void ed25519_extsk(hash_512bits extsk, const ed25519_secret_key sk) {
  22. ed25519_hash(extsk, sk, 32);
  23. extsk[0] &= 248;
  24. extsk[31] &= 127;
  25. extsk[31] |= 64;
  26. }
  27. static void ed25519_hram(
  28. hash_512bits hram,
  29. const ed25519_public_key R,
  30. const ed25519_public_key pk,
  31. const unsigned char* m,
  32. size_t mlen) {
  33. ed25519_hash_context ctx;
  34. ed25519_hash_init(&ctx);
  35. ed25519_hash_update(&ctx, R, 32);
  36. ed25519_hash_update(&ctx, pk, 32);
  37. ed25519_hash_update(&ctx, m, mlen);
  38. ed25519_hash_final(&ctx, hram);
  39. }
  40. void ED25519_FN(ed25519_publickey)(const ed25519_secret_key sk, ed25519_public_key pk) {
  41. hash_512bits extsk = {0};
  42. ed25519_extsk(extsk, sk);
  43. ed25519_publickey_ext(extsk, pk);
  44. memzero(&extsk, sizeof(extsk));
  45. }
  46. void ED25519_FN(ed25519_cosi_commit)(ed25519_secret_key nonce, ed25519_public_key commitment) {
  47. bignum256modm r = {0};
  48. ge25519 ALIGN(16) R;
  49. unsigned char extnonce[64] = {0};
  50. /* r = random512 mod L */
  51. random_buffer(extnonce, sizeof(extnonce));
  52. expand256_modm(r, extnonce, sizeof(extnonce));
  53. memzero(&extnonce, sizeof(extnonce));
  54. contract256_modm(nonce, r);
  55. /* R = rB */
  56. ge25519_scalarmult_base_niels(&R, ge25519_niels_base_multiples, r);
  57. memzero(&r, sizeof(r));
  58. ge25519_pack(commitment, &R);
  59. }
  60. int ED25519_FN(ed25519_cosi_sign)(
  61. const unsigned char* m,
  62. size_t mlen,
  63. const ed25519_secret_key sk,
  64. const ed25519_secret_key nonce,
  65. const ed25519_public_key R,
  66. const ed25519_public_key pk,
  67. ed25519_cosi_signature sig) {
  68. bignum256modm r = {0}, S = {0}, a = {0};
  69. hash_512bits extsk = {0}, hram = {0};
  70. ed25519_extsk(extsk, sk);
  71. /* r */
  72. expand_raw256_modm(r, nonce);
  73. if(!is_reduced256_modm(r)) return -1;
  74. /* S = H(R,A,m).. */
  75. ed25519_hram(hram, R, pk, m, mlen);
  76. expand256_modm(S, hram, 64);
  77. /* S = H(R,A,m)a */
  78. expand256_modm(a, extsk, 32);
  79. memzero(&extsk, sizeof(extsk));
  80. mul256_modm(S, S, a);
  81. memzero(&a, sizeof(a));
  82. /* S = (r + H(R,A,m)a) */
  83. add256_modm(S, S, r);
  84. memzero(&r, sizeof(r));
  85. /* S = (r + H(R,A,m)a) mod L */
  86. contract256_modm(sig, S);
  87. return 0;
  88. }
  89. void ED25519_FN(ed25519_sign_ext)(
  90. const unsigned char* m,
  91. size_t mlen,
  92. const ed25519_secret_key sk,
  93. const ed25519_secret_key skext,
  94. ed25519_signature RS) {
  95. ed25519_hash_context ctx;
  96. bignum256modm r = {0}, S = {0}, a = {0};
  97. ge25519 ALIGN(16) R = {0};
  98. ge25519 ALIGN(16) A = {0};
  99. ed25519_public_key pk = {0};
  100. hash_512bits extsk = {0}, hashr = {0}, hram = {0};
  101. /* we don't stretch the key through hashing first since its already 64 bytes */
  102. memcpy(extsk, sk, 32);
  103. memcpy(extsk + 32, skext, 32);
  104. /* r = H(aExt[32..64], m) */
  105. ed25519_hash_init(&ctx);
  106. ed25519_hash_update(&ctx, extsk + 32, 32);
  107. ed25519_hash_update(&ctx, m, mlen);
  108. ed25519_hash_final(&ctx, hashr);
  109. expand256_modm(r, hashr, 64);
  110. memzero(&hashr, sizeof(hashr));
  111. /* R = rB */
  112. ge25519_scalarmult_base_niels(&R, ge25519_niels_base_multiples, r);
  113. ge25519_pack(RS, &R);
  114. /* a = aExt[0..31] */
  115. expand256_modm(a, extsk, 32);
  116. memzero(&extsk, sizeof(extsk));
  117. /* A = aB */
  118. ge25519_scalarmult_base_niels(&A, ge25519_niels_base_multiples, a);
  119. ge25519_pack(pk, &A);
  120. /* S = H(R,A,m).. */
  121. ed25519_hram(hram, RS, pk, m, mlen);
  122. expand256_modm(S, hram, 64);
  123. /* S = H(R,A,m)a */
  124. mul256_modm(S, S, a);
  125. memzero(&a, sizeof(a));
  126. /* S = (r + H(R,A,m)a) */
  127. add256_modm(S, S, r);
  128. memzero(&r, sizeof(r));
  129. /* S = (r + H(R,A,m)a) mod L */
  130. contract256_modm(RS + 32, S);
  131. }
  132. void ED25519_FN(ed25519_sign)(
  133. const unsigned char* m,
  134. size_t mlen,
  135. const ed25519_secret_key sk,
  136. ed25519_signature RS) {
  137. hash_512bits extsk = {0};
  138. ed25519_extsk(extsk, sk);
  139. ED25519_FN(ed25519_sign_ext)(m, mlen, extsk, extsk + 32, RS);
  140. memzero(&extsk, sizeof(extsk));
  141. }
  142. int ED25519_FN(ed25519_sign_open)(
  143. const unsigned char* m,
  144. size_t mlen,
  145. const ed25519_public_key pk,
  146. const ed25519_signature RS) {
  147. ge25519 ALIGN(16) R = {0}, A = {0};
  148. hash_512bits hash = {0};
  149. bignum256modm hram = {0}, S = {0};
  150. unsigned char checkR[32] = {0};
  151. if((RS[63] & 224) || !ge25519_unpack_negative_vartime(&A, pk)) return -1;
  152. /* hram = H(R,A,m) */
  153. ed25519_hram(hash, RS, pk, m, mlen);
  154. expand256_modm(hram, hash, 64);
  155. /* S */
  156. expand_raw256_modm(S, RS + 32);
  157. if(!is_reduced256_modm(S)) return -1;
  158. /* SB - H(R,A,m)A */
  159. ge25519_double_scalarmult_vartime(&R, &A, hram, S);
  160. ge25519_pack(checkR, &R);
  161. /* check that R = SB - H(R,A,m)A */
  162. return ed25519_verify(RS, checkR, 32) ? 0 : -1;
  163. }
  164. int ED25519_FN(ed25519_scalarmult)(
  165. ed25519_public_key res,
  166. const ed25519_secret_key sk,
  167. const ed25519_public_key pk) {
  168. bignum256modm a = {0};
  169. ge25519 ALIGN(16) A = {0}, P = {0};
  170. hash_512bits extsk = {0};
  171. ed25519_extsk(extsk, sk);
  172. expand256_modm(a, extsk, 32);
  173. memzero(&extsk, sizeof(extsk));
  174. if(!ge25519_unpack_negative_vartime(&P, pk)) {
  175. return -1;
  176. }
  177. ge25519_scalarmult(&A, &P, a);
  178. memzero(&a, sizeof(a));
  179. curve25519_neg(A.x, A.x);
  180. ge25519_pack(res, &A);
  181. return 0;
  182. }
  183. #ifndef ED25519_SUFFIX
  184. #include "curve25519_donna_scalarmult_base.h"
  185. void ed25519_publickey_ext(const ed25519_secret_key extsk, ed25519_public_key pk) {
  186. bignum256modm a = {0};
  187. ge25519 ALIGN(16) A = {0};
  188. expand256_modm(a, extsk, 32);
  189. /* A = aB */
  190. ge25519_scalarmult_base_niels(&A, ge25519_niels_base_multiples, a);
  191. memzero(&a, sizeof(a));
  192. ge25519_pack(pk, &A);
  193. }
  194. int ed25519_cosi_combine_publickeys(
  195. ed25519_public_key res,
  196. CONST ed25519_public_key* pks,
  197. size_t n) {
  198. size_t i = 0;
  199. ge25519 P = {0};
  200. ge25519_pniels sump = {0};
  201. ge25519_p1p1 sump1 = {0};
  202. if(n == 1) {
  203. memcpy(res, pks, sizeof(ed25519_public_key));
  204. return 0;
  205. }
  206. if(!ge25519_unpack_negative_vartime(&P, pks[i++])) {
  207. return -1;
  208. }
  209. ge25519_full_to_pniels(&sump, &P);
  210. while(i < n - 1) {
  211. if(!ge25519_unpack_negative_vartime(&P, pks[i++])) {
  212. return -1;
  213. }
  214. ge25519_pnielsadd(&sump, &P, &sump);
  215. }
  216. if(!ge25519_unpack_negative_vartime(&P, pks[i++])) {
  217. return -1;
  218. }
  219. ge25519_pnielsadd_p1p1(&sump1, &P, &sump, 0);
  220. ge25519_p1p1_to_partial(&P, &sump1);
  221. curve25519_neg(P.x, P.x);
  222. ge25519_pack(res, &P);
  223. return 0;
  224. }
  225. void ed25519_cosi_combine_signatures(
  226. ed25519_signature res,
  227. const ed25519_public_key R,
  228. CONST ed25519_cosi_signature* sigs,
  229. size_t n) {
  230. bignum256modm s = {0}, t = {0};
  231. size_t i = 0;
  232. expand256_modm(s, sigs[i++], 32);
  233. while(i < n) {
  234. expand256_modm(t, sigs[i++], 32);
  235. add256_modm(s, s, t);
  236. }
  237. memcpy(res, R, 32);
  238. contract256_modm(res + 32, s);
  239. }
  240. /*
  241. Fast Curve25519 basepoint scalar multiplication
  242. */
  243. void curve25519_scalarmult_basepoint(curve25519_key pk, const curve25519_key e) {
  244. curve25519_key ec = {0};
  245. bignum256modm s = {0};
  246. bignum25519 ALIGN(16) yplusz = {0}, zminusy = {0};
  247. ge25519 ALIGN(16) p = {0};
  248. size_t i = 0;
  249. /* clamp */
  250. for(i = 0; i < 32; i++) ec[i] = e[i];
  251. ec[0] &= 248;
  252. ec[31] &= 127;
  253. ec[31] |= 64;
  254. expand_raw256_modm(s, ec);
  255. memzero(&ec, sizeof(ec));
  256. /* scalar * basepoint */
  257. ge25519_scalarmult_base_niels(&p, ge25519_niels_base_multiples, s);
  258. memzero(&s, sizeof(s));
  259. /* u = (y + z) / (z - y) */
  260. curve25519_add(yplusz, p.y, p.z);
  261. curve25519_sub(zminusy, p.z, p.y);
  262. curve25519_recip(zminusy, zminusy);
  263. curve25519_mul(yplusz, yplusz, zminusy);
  264. curve25519_contract(pk, yplusz);
  265. }
  266. void curve25519_scalarmult(
  267. curve25519_key mypublic,
  268. const curve25519_key secret,
  269. const curve25519_key basepoint) {
  270. curve25519_key e = {0};
  271. size_t i = 0;
  272. for(i = 0; i < 32; ++i) e[i] = secret[i];
  273. e[0] &= 0xf8;
  274. e[31] &= 0x7f;
  275. e[31] |= 0x40;
  276. curve25519_scalarmult_donna(mypublic, e, basepoint);
  277. memzero(&e, sizeof(e));
  278. }
  279. #endif // ED25519_SUFFIX