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.

150 lines
3.6 KiB

  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. #if !defined(ED25519_SUFFIX)
  7. #define ED25519_SUFFIX
  8. #endif
  9. #define ED25519_FN3(fn,suffix) fn##suffix
  10. #define ED25519_FN2(fn,suffix) ED25519_FN3(fn,suffix)
  11. #define ED25519_FN(fn) ED25519_FN2(fn,ED25519_SUFFIX)
  12. #include "ed25519-donna.h"
  13. #include "ed25519.h"
  14. #include "ed25519-randombytes.h"
  15. #include "ed25519-hash.h"
  16. /*
  17. Generates a (extsk[0..31]) and aExt (extsk[32..63])
  18. */
  19. DONNA_INLINE static void
  20. ed25519_extsk(hash_512bits extsk, const ed25519_secret_key sk) {
  21. ed25519_hash(extsk, sk, 32);
  22. extsk[0] &= 248;
  23. extsk[31] &= 127;
  24. extsk[31] |= 64;
  25. }
  26. static void
  27. ed25519_hram(hash_512bits hram, const ed25519_signature RS, const ed25519_public_key pk, const unsigned char *m, size_t mlen) {
  28. ed25519_hash_context ctx;
  29. ed25519_hash_init(&ctx);
  30. ed25519_hash_update(&ctx, RS, 32);
  31. ed25519_hash_update(&ctx, pk, 32);
  32. ed25519_hash_update(&ctx, m, mlen);
  33. ed25519_hash_final(&ctx, hram);
  34. }
  35. void
  36. ED25519_FN(ed25519_publickey) (const ed25519_secret_key sk, ed25519_public_key pk) {
  37. bignum256modm a;
  38. ge25519 ALIGN(16) A;
  39. hash_512bits extsk;
  40. /* A = aB */
  41. ed25519_extsk(extsk, sk);
  42. expand256_modm(a, extsk, 32);
  43. ge25519_scalarmult_base_niels(&A, ge25519_niels_base_multiples, a);
  44. ge25519_pack(pk, &A);
  45. }
  46. void
  47. ED25519_FN(ed25519_sign) (const unsigned char *m, size_t mlen, const ed25519_secret_key sk, const ed25519_public_key pk, ed25519_signature RS) {
  48. ed25519_hash_context ctx;
  49. bignum256modm r, S, a;
  50. ge25519 ALIGN(16) R;
  51. hash_512bits extsk, hashr, hram;
  52. ed25519_extsk(extsk, sk);
  53. /* r = H(aExt[32..64], m) */
  54. ed25519_hash_init(&ctx);
  55. ed25519_hash_update(&ctx, extsk + 32, 32);
  56. ed25519_hash_update(&ctx, m, mlen);
  57. ed25519_hash_final(&ctx, hashr);
  58. expand256_modm(r, hashr, 64);
  59. /* R = rB */
  60. ge25519_scalarmult_base_niels(&R, ge25519_niels_base_multiples, r);
  61. ge25519_pack(RS, &R);
  62. /* S = H(R,A,m).. */
  63. ed25519_hram(hram, RS, pk, m, mlen);
  64. expand256_modm(S, hram, 64);
  65. /* S = H(R,A,m)a */
  66. expand256_modm(a, extsk, 32);
  67. mul256_modm(S, S, a);
  68. /* S = (r + H(R,A,m)a) */
  69. add256_modm(S, S, r);
  70. /* S = (r + H(R,A,m)a) mod L */
  71. contract256_modm(RS + 32, S);
  72. }
  73. int
  74. ED25519_FN(ed25519_sign_open) (const unsigned char *m, size_t mlen, const ed25519_public_key pk, const ed25519_signature RS) {
  75. ge25519 ALIGN(16) R, A;
  76. hash_512bits hash;
  77. bignum256modm hram, S;
  78. unsigned char checkR[32];
  79. if ((RS[63] & 224) || !ge25519_unpack_negative_vartime(&A, pk))
  80. return -1;
  81. /* hram = H(R,A,m) */
  82. ed25519_hram(hash, RS, pk, m, mlen);
  83. expand256_modm(hram, hash, 64);
  84. /* S */
  85. expand256_modm(S, RS + 32, 32);
  86. /* SB - H(R,A,m)A */
  87. ge25519_double_scalarmult_vartime(&R, &A, hram, S);
  88. ge25519_pack(checkR, &R);
  89. /* check that R = SB - H(R,A,m)A */
  90. return ed25519_verify(RS, checkR, 32) ? 0 : -1;
  91. }
  92. #include "ed25519-donna-batchverify.h"
  93. /*
  94. Fast Curve25519 basepoint scalar multiplication
  95. */
  96. void
  97. ED25519_FN(curved25519_scalarmult_basepoint) (curved25519_key pk, const curved25519_key e) {
  98. curved25519_key ec;
  99. bignum256modm s;
  100. bignum25519 ALIGN(16) yplusz, zminusy;
  101. ge25519 ALIGN(16) p;
  102. size_t i;
  103. /* clamp */
  104. for (i = 0; i < 32; i++) ec[i] = e[i];
  105. ec[0] &= 248;
  106. ec[31] &= 127;
  107. ec[31] |= 64;
  108. expand_raw256_modm(s, ec);
  109. /* scalar * basepoint */
  110. ge25519_scalarmult_base_niels(&p, ge25519_niels_base_multiples, s);
  111. /* u = (y + z) / (z - y) */
  112. curve25519_add(yplusz, p.y, p.z);
  113. curve25519_sub(zminusy, p.z, p.y);
  114. curve25519_recip(zminusy, zminusy);
  115. curve25519_mul(yplusz, yplusz, zminusy);
  116. curve25519_contract(pk, yplusz);
  117. }