| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336 |
- /*
- Public domain by Andrew M. <liquidsun@gmail.com>
- Ed25519 reference implementation using Ed25519-donna
- */
- /* define ED25519_SUFFIX to have it appended to the end of each public function */
- #ifdef ED25519_SUFFIX
- #define ED25519_FN3(fn, suffix) fn##suffix
- #define ED25519_FN2(fn, suffix) ED25519_FN3(fn, suffix)
- #define ED25519_FN(fn) ED25519_FN2(fn, ED25519_SUFFIX)
- #else
- #define ED25519_FN(fn) fn
- #endif
- #include "ed25519_donna.h"
- #include "ed25519.h"
- #include "ed25519_hash_custom.h"
- #include "../rand.h"
- #include "../memzero.h"
- /*
- Generates a (extsk[0..31]) and aExt (extsk[32..63])
- */
- DONNA_INLINE static void ed25519_extsk(hash_512bits extsk, const ed25519_secret_key sk) {
- ed25519_hash(extsk, sk, 32);
- extsk[0] &= 248;
- extsk[31] &= 127;
- extsk[31] |= 64;
- }
- static void ed25519_hram(
- hash_512bits hram,
- const ed25519_public_key R,
- const ed25519_public_key pk,
- const unsigned char* m,
- size_t mlen) {
- ed25519_hash_context ctx;
- ed25519_hash_init(&ctx);
- ed25519_hash_update(&ctx, R, 32);
- ed25519_hash_update(&ctx, pk, 32);
- ed25519_hash_update(&ctx, m, mlen);
- ed25519_hash_final(&ctx, hram);
- }
- void ED25519_FN(ed25519_publickey)(const ed25519_secret_key sk, ed25519_public_key pk) {
- hash_512bits extsk = {0};
- ed25519_extsk(extsk, sk);
- ed25519_publickey_ext(extsk, pk);
- memzero(&extsk, sizeof(extsk));
- }
- void ED25519_FN(ed25519_cosi_commit)(ed25519_secret_key nonce, ed25519_public_key commitment) {
- bignum256modm r = {0};
- ge25519 ALIGN(16) R;
- unsigned char extnonce[64] = {0};
- /* r = random512 mod L */
- random_buffer(extnonce, sizeof(extnonce));
- expand256_modm(r, extnonce, sizeof(extnonce));
- memzero(&extnonce, sizeof(extnonce));
- contract256_modm(nonce, r);
- /* R = rB */
- ge25519_scalarmult_base_niels(&R, ge25519_niels_base_multiples, r);
- memzero(&r, sizeof(r));
- ge25519_pack(commitment, &R);
- }
- int ED25519_FN(ed25519_cosi_sign)(
- const unsigned char* m,
- size_t mlen,
- const ed25519_secret_key sk,
- const ed25519_secret_key nonce,
- const ed25519_public_key R,
- const ed25519_public_key pk,
- ed25519_cosi_signature sig) {
- bignum256modm r = {0}, S = {0}, a = {0};
- hash_512bits extsk = {0}, hram = {0};
- ed25519_extsk(extsk, sk);
- /* r */
- expand_raw256_modm(r, nonce);
- if(!is_reduced256_modm(r)) return -1;
- /* S = H(R,A,m).. */
- ed25519_hram(hram, R, pk, m, mlen);
- expand256_modm(S, hram, 64);
- /* S = H(R,A,m)a */
- expand256_modm(a, extsk, 32);
- memzero(&extsk, sizeof(extsk));
- mul256_modm(S, S, a);
- memzero(&a, sizeof(a));
- /* S = (r + H(R,A,m)a) */
- add256_modm(S, S, r);
- memzero(&r, sizeof(r));
- /* S = (r + H(R,A,m)a) mod L */
- contract256_modm(sig, S);
- return 0;
- }
- void ED25519_FN(ed25519_sign_ext)(
- const unsigned char* m,
- size_t mlen,
- const ed25519_secret_key sk,
- const ed25519_secret_key skext,
- ed25519_signature RS) {
- ed25519_hash_context ctx;
- bignum256modm r = {0}, S = {0}, a = {0};
- ge25519 ALIGN(16) R = {0};
- ge25519 ALIGN(16) A = {0};
- ed25519_public_key pk = {0};
- hash_512bits extsk = {0}, hashr = {0}, hram = {0};
- /* we don't stretch the key through hashing first since its already 64 bytes */
- memcpy(extsk, sk, 32);
- memcpy(extsk + 32, skext, 32);
- /* r = H(aExt[32..64], m) */
- ed25519_hash_init(&ctx);
- ed25519_hash_update(&ctx, extsk + 32, 32);
- ed25519_hash_update(&ctx, m, mlen);
- ed25519_hash_final(&ctx, hashr);
- expand256_modm(r, hashr, 64);
- memzero(&hashr, sizeof(hashr));
- /* R = rB */
- ge25519_scalarmult_base_niels(&R, ge25519_niels_base_multiples, r);
- ge25519_pack(RS, &R);
- /* a = aExt[0..31] */
- expand256_modm(a, extsk, 32);
- memzero(&extsk, sizeof(extsk));
- /* A = aB */
- ge25519_scalarmult_base_niels(&A, ge25519_niels_base_multiples, a);
- ge25519_pack(pk, &A);
- /* S = H(R,A,m).. */
- ed25519_hram(hram, RS, pk, m, mlen);
- expand256_modm(S, hram, 64);
- /* S = H(R,A,m)a */
- mul256_modm(S, S, a);
- memzero(&a, sizeof(a));
- /* S = (r + H(R,A,m)a) */
- add256_modm(S, S, r);
- memzero(&r, sizeof(r));
- /* S = (r + H(R,A,m)a) mod L */
- contract256_modm(RS + 32, S);
- }
- void ED25519_FN(ed25519_sign)(
- const unsigned char* m,
- size_t mlen,
- const ed25519_secret_key sk,
- ed25519_signature RS) {
- hash_512bits extsk = {0};
- ed25519_extsk(extsk, sk);
- ED25519_FN(ed25519_sign_ext)(m, mlen, extsk, extsk + 32, RS);
- memzero(&extsk, sizeof(extsk));
- }
- int ED25519_FN(ed25519_sign_open)(
- const unsigned char* m,
- size_t mlen,
- const ed25519_public_key pk,
- const ed25519_signature RS) {
- ge25519 ALIGN(16) R = {0}, A = {0};
- hash_512bits hash = {0};
- bignum256modm hram = {0}, S = {0};
- unsigned char checkR[32] = {0};
- if((RS[63] & 224) || !ge25519_unpack_negative_vartime(&A, pk)) return -1;
- /* hram = H(R,A,m) */
- ed25519_hram(hash, RS, pk, m, mlen);
- expand256_modm(hram, hash, 64);
- /* S */
- expand_raw256_modm(S, RS + 32);
- if(!is_reduced256_modm(S)) return -1;
- /* SB - H(R,A,m)A */
- ge25519_double_scalarmult_vartime(&R, &A, hram, S);
- ge25519_pack(checkR, &R);
- /* check that R = SB - H(R,A,m)A */
- return ed25519_verify(RS, checkR, 32) ? 0 : -1;
- }
- int ED25519_FN(ed25519_scalarmult)(
- ed25519_public_key res,
- const ed25519_secret_key sk,
- const ed25519_public_key pk) {
- bignum256modm a = {0};
- ge25519 ALIGN(16) A = {0}, P = {0};
- hash_512bits extsk = {0};
- ed25519_extsk(extsk, sk);
- expand256_modm(a, extsk, 32);
- memzero(&extsk, sizeof(extsk));
- if(!ge25519_unpack_negative_vartime(&P, pk)) {
- return -1;
- }
- ge25519_scalarmult(&A, &P, a);
- memzero(&a, sizeof(a));
- curve25519_neg(A.x, A.x);
- ge25519_pack(res, &A);
- return 0;
- }
- #ifndef ED25519_SUFFIX
- #include "curve25519_donna_scalarmult_base.h"
- void ed25519_publickey_ext(const ed25519_secret_key extsk, ed25519_public_key pk) {
- bignum256modm a = {0};
- ge25519 ALIGN(16) A = {0};
- expand256_modm(a, extsk, 32);
- /* A = aB */
- ge25519_scalarmult_base_niels(&A, ge25519_niels_base_multiples, a);
- memzero(&a, sizeof(a));
- ge25519_pack(pk, &A);
- }
- int ed25519_cosi_combine_publickeys(
- ed25519_public_key res,
- CONST ed25519_public_key* pks,
- size_t n) {
- size_t i = 0;
- ge25519 P = {0};
- ge25519_pniels sump = {0};
- ge25519_p1p1 sump1 = {0};
- if(n == 1) {
- memcpy(res, pks, sizeof(ed25519_public_key));
- return 0;
- }
- if(!ge25519_unpack_negative_vartime(&P, pks[i++])) {
- return -1;
- }
- ge25519_full_to_pniels(&sump, &P);
- while(i < n - 1) {
- if(!ge25519_unpack_negative_vartime(&P, pks[i++])) {
- return -1;
- }
- ge25519_pnielsadd(&sump, &P, &sump);
- }
- if(!ge25519_unpack_negative_vartime(&P, pks[i++])) {
- return -1;
- }
- ge25519_pnielsadd_p1p1(&sump1, &P, &sump, 0);
- ge25519_p1p1_to_partial(&P, &sump1);
- curve25519_neg(P.x, P.x);
- ge25519_pack(res, &P);
- return 0;
- }
- void ed25519_cosi_combine_signatures(
- ed25519_signature res,
- const ed25519_public_key R,
- CONST ed25519_cosi_signature* sigs,
- size_t n) {
- bignum256modm s = {0}, t = {0};
- size_t i = 0;
- expand256_modm(s, sigs[i++], 32);
- while(i < n) {
- expand256_modm(t, sigs[i++], 32);
- add256_modm(s, s, t);
- }
- memcpy(res, R, 32);
- contract256_modm(res + 32, s);
- }
- /*
- Fast Curve25519 basepoint scalar multiplication
- */
- void curve25519_scalarmult_basepoint(curve25519_key pk, const curve25519_key e) {
- curve25519_key ec = {0};
- bignum256modm s = {0};
- bignum25519 ALIGN(16) yplusz = {0}, zminusy = {0};
- ge25519 ALIGN(16) p = {0};
- size_t i = 0;
- /* clamp */
- for(i = 0; i < 32; i++) ec[i] = e[i];
- ec[0] &= 248;
- ec[31] &= 127;
- ec[31] |= 64;
- expand_raw256_modm(s, ec);
- memzero(&ec, sizeof(ec));
- /* scalar * basepoint */
- ge25519_scalarmult_base_niels(&p, ge25519_niels_base_multiples, s);
- memzero(&s, sizeof(s));
- /* u = (y + z) / (z - y) */
- curve25519_add(yplusz, p.y, p.z);
- curve25519_sub(zminusy, p.z, p.y);
- curve25519_recip(zminusy, zminusy);
- curve25519_mul(yplusz, yplusz, zminusy);
- curve25519_contract(pk, yplusz);
- }
- void curve25519_scalarmult(
- curve25519_key mypublic,
- const curve25519_key secret,
- const curve25519_key basepoint) {
- curve25519_key e = {0};
- size_t i = 0;
- for(i = 0; i < 32; ++i) e[i] = secret[i];
- e[0] &= 0xf8;
- e[31] &= 0x7f;
- e[31] |= 0x40;
- curve25519_scalarmult_donna(mypublic, e, basepoint);
- memzero(&e, sizeof(e));
- }
- #endif // ED25519_SUFFIX
|