1 /*
2 	Public domain by Andrew M. <liquidsun@gmail.com>
3 
4 	Ed25519 reference implementation using Ed25519-donna
5 */
6 
7 
8 #define ED25519_FN(fn)         cryptonite_##fn
9 
10 #include "ed25519-donna.h"
11 #include "ed25519.h"
12 #include "ed25519-randombytes.h"
13 #include "ed25519-hash.h"
14 #include "ed25519-cryptonite-exts.h"
15 
16 /*
17 	Generates a (extsk[0..31]) and aExt (extsk[32..63])
18 */
19 
20 DONNA_INLINE static void
ed25519_extsk(hash_512bits extsk,const ed25519_secret_key sk)21 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 
28 static void
ed25519_hram(hash_512bits hram,const ed25519_signature RS,const ed25519_public_key pk,const unsigned char * m,size_t mlen)29 ed25519_hram(hash_512bits hram, const ed25519_signature RS, const ed25519_public_key pk, const unsigned char *m, size_t mlen) {
30 	ed25519_hash_context ctx;
31 	ed25519_hash_init(&ctx);
32 	ed25519_hash_update(&ctx, RS, 32);
33 	ed25519_hash_update(&ctx, pk, 32);
34 	ed25519_hash_update(&ctx, m, mlen);
35 	ed25519_hash_final(&ctx, hram);
36 }
37 
38 void
ED25519_FN(ed25519_publickey)39 ED25519_FN(ed25519_publickey) (const ed25519_secret_key sk, ed25519_public_key pk) {
40 	bignum256modm a;
41 	ge25519 ALIGN(16) A;
42 	hash_512bits extsk;
43 
44 	/* A = aB */
45 	ed25519_extsk(extsk, sk);
46 	expand256_modm(a, extsk, 32);
47 	ge25519_scalarmult_base_niels(&A, ge25519_niels_base_multiples, a);
48 	ge25519_pack(pk, &A);
49 }
50 
51 
52 void
ED25519_FN(ed25519_sign)53 ED25519_FN(ed25519_sign) (const unsigned char *m, size_t mlen, const ed25519_secret_key sk, const ed25519_public_key pk, ed25519_signature RS) {
54 	ed25519_hash_context ctx;
55 	bignum256modm r, S, a;
56 	ge25519 ALIGN(16) R;
57 	hash_512bits extsk, hashr, hram;
58 
59 	ed25519_extsk(extsk, sk);
60 
61 	/* r = H(aExt[32..64], m) */
62 	ed25519_hash_init(&ctx);
63 	ed25519_hash_update(&ctx, extsk + 32, 32);
64 	ed25519_hash_update(&ctx, m, mlen);
65 	ed25519_hash_final(&ctx, hashr);
66 	expand256_modm(r, hashr, 64);
67 
68 	/* R = rB */
69 	ge25519_scalarmult_base_niels(&R, ge25519_niels_base_multiples, r);
70 	ge25519_pack(RS, &R);
71 
72 	/* S = H(R,A,m).. */
73 	ed25519_hram(hram, RS, pk, m, mlen);
74 	expand256_modm(S, hram, 64);
75 
76 	/* S = H(R,A,m)a */
77 	expand256_modm(a, extsk, 32);
78 	mul256_modm(S, S, a);
79 
80 	/* S = (r + H(R,A,m)a) */
81 	add256_modm(S, S, r);
82 
83 	/* S = (r + H(R,A,m)a) mod L */
84 	contract256_modm(RS + 32, S);
85 }
86 
87 int
ED25519_FN(ed25519_sign_open)88 ED25519_FN(ed25519_sign_open) (const unsigned char *m, size_t mlen, const ed25519_public_key pk, const ed25519_signature RS) {
89 	ge25519 ALIGN(16) R, A;
90 	hash_512bits hash;
91 	bignum256modm hram, S;
92 	unsigned char checkR[32];
93 
94 	if ((RS[63] & 224) || !ge25519_unpack_negative_vartime(&A, pk))
95 		return -1;
96 
97 	/* hram = H(R,A,m) */
98 	ed25519_hram(hash, RS, pk, m, mlen);
99 	expand256_modm(hram, hash, 64);
100 
101 	/* S */
102 	expand256_modm(S, RS + 32, 32);
103 
104 	/* SB - H(R,A,m)A */
105 	ge25519_double_scalarmult_vartime(&R, &A, hram, S);
106 	ge25519_pack(checkR, &R);
107 
108 	/* check that R = SB - H(R,A,m)A */
109 	return ed25519_verify(RS, checkR, 32) ? 0 : -1;
110 }
111 
112 #include "ed25519-donna-batchverify.h"
113 
114 /*
115 	Fast Curve25519 basepoint scalar multiplication
116 */
117 
118 void
ED25519_FN(curved25519_scalarmult_basepoint)119 ED25519_FN(curved25519_scalarmult_basepoint) (curved25519_key pk, const curved25519_key e) {
120 	curved25519_key ec;
121 	bignum256modm s;
122 	bignum25519 ALIGN(16) yplusz, zminusy;
123 	ge25519 ALIGN(16) p;
124 	size_t i;
125 
126 	/* clamp */
127 	for (i = 0; i < 32; i++) ec[i] = e[i];
128 	ec[0] &= 248;
129 	ec[31] &= 127;
130 	ec[31] |= 64;
131 
132 	expand_raw256_modm(s, ec);
133 
134 	/* scalar * basepoint */
135 	ge25519_scalarmult_base_niels(&p, ge25519_niels_base_multiples, s);
136 
137 	/* u = (y + z) / (z - y) */
138 	curve25519_add(yplusz, p.y, p.z);
139 	curve25519_sub(zminusy, p.z, p.y);
140 	curve25519_recip(zminusy, zminusy);
141 	curve25519_mul(yplusz, yplusz, zminusy);
142 	curve25519_contract(pk, yplusz);
143 }
144 
145