1 /* $OpenBSD: ed25519.c,v 1.3 2013/12/09 11:03:45 markus Exp $ */
2
3 /*
4 * Public Domain, Authors: Daniel J. Bernstein, Niels Duif, Tanja Lange,
5 * Peter Schwabe, Bo-Yin Yang.
6 * Copied from supercop-20130419/crypto_sign/ed25519/ref/ed25519.c
7 *
8 * Modified to use lws genhash by Andy Green <andy@warmcat.com>
9 */
10
11 #include <libwebsockets.h>
12 #include <lws-ssh.h>
13 #include "ge25519.h"
14
15 int
crypto_hash_sha512(uint8_t * hash64,const uint8_t * data,size_t len)16 crypto_hash_sha512(uint8_t *hash64, const uint8_t *data, size_t len)
17 {
18 struct lws_genhash_ctx ctx;
19 int ret;
20
21 if (lws_genhash_init(&ctx, LWS_GENHASH_TYPE_SHA512)) {
22 lwsl_notice("Failed to init SHA512\n");
23 return 0;
24 }
25
26 ret = lws_genhash_update(&ctx, data, len);
27
28 if (lws_genhash_destroy(&ctx, hash64))
29 lwsl_notice("genhash destroy failed\n");
30
31 return ret ? 0 : 64;
32 }
33
34
35 static void
get_hram(unsigned char * hram,const unsigned char * sm,const unsigned char * pk,unsigned char * playground,size_t smlen)36 get_hram(unsigned char *hram, const unsigned char *sm,
37 const unsigned char *pk, unsigned char *playground,
38 size_t smlen)
39 {
40 unsigned long long i;
41
42 for (i = 0; i < 32; ++i)
43 playground[i] = sm[i];
44 for (i = 32; i < 64; ++i)
45 playground[i] = pk[i-32];
46 for (i = 64; i < smlen; ++i)
47 playground[i] = sm[i];
48
49 crypto_hash_sha512(hram, playground, smlen);
50 }
51
52
crypto_sign_ed25519_keypair(struct lws_context * context,unsigned char * pk,unsigned char * sk)53 int crypto_sign_ed25519_keypair(
54 struct lws_context *context,
55 unsigned char *pk,
56 unsigned char *sk
57 )
58 {
59 sc25519 scsk;
60 ge25519 gepk;
61 unsigned char extsk[64];
62 int i;
63
64 lws_get_random(context, sk, 32);
65 crypto_hash_sha512(extsk, sk, 32);
66 extsk[0] &= 248;
67 extsk[31] &= 127;
68 extsk[31] |= 64;
69
70 sc25519_from32bytes(&scsk,extsk);
71
72 ge25519_scalarmult_base(&gepk, &scsk);
73 ge25519_pack(pk, &gepk);
74 for(i=0;i<32;i++)
75 sk[32 + i] = pk[i];
76 return 0;
77 }
78
crypto_sign_ed25519(unsigned char * sm,unsigned long long * smlen,const unsigned char * m,size_t mlen,const unsigned char * sk)79 int crypto_sign_ed25519(
80 unsigned char *sm,
81 unsigned long long *smlen,
82 const unsigned char *m, size_t mlen,
83 const unsigned char *sk
84 )
85 {
86 sc25519 sck, scs, scsk;
87 ge25519 ger;
88 unsigned char r[32];
89 unsigned char s[32];
90 unsigned char extsk[64];
91 unsigned long long i;
92 unsigned char hmg[crypto_hash_sha512_BYTES];
93 unsigned char hram[crypto_hash_sha512_BYTES];
94
95 crypto_hash_sha512(extsk, sk, 32);
96 extsk[0] &= 248;
97 extsk[31] &= 127;
98 extsk[31] |= 64;
99
100 *smlen = mlen+64;
101 for(i=0;i<mlen;i++)
102 sm[64 + i] = m[i];
103 for(i=0;i<32;i++)
104 sm[32 + i] = extsk[32+i];
105
106 crypto_hash_sha512(hmg, sm+32, mlen+32);
107 /* Generate k as h(extsk[32],...,extsk[63],m) */
108
109 /* Computation of R */
110 sc25519_from64bytes(&sck, hmg);
111 ge25519_scalarmult_base(&ger, &sck);
112 ge25519_pack(r, &ger);
113
114 /* Computation of s */
115 for (i = 0; i < 32; i++)
116 sm[i] = r[i];
117
118 get_hram(hram, sm, sk + 32, sm, (size_t)mlen + 64);
119
120 sc25519_from64bytes(&scs, hram);
121 sc25519_from32bytes(&scsk, extsk);
122 sc25519_mul(&scs, &scs, &scsk);
123
124 sc25519_add(&scs, &scs, &sck);
125
126 sc25519_to32bytes(s,&scs); /* cat s */
127 for (i = 0; i < 32; i++)
128 sm[32 + i] = s[i];
129
130 return 0;
131 }
132
crypto_verify_32(const unsigned char * x,const unsigned char * y)133 int crypto_verify_32(const unsigned char *x,const unsigned char *y)
134 {
135 unsigned int differentbits = 0;
136 #define F(i) differentbits |= x[i] ^ y[i];
137 F(0)
138 F(1)
139 F(2)
140 F(3)
141 F(4)
142 F(5)
143 F(6)
144 F(7)
145 F(8)
146 F(9)
147 F(10)
148 F(11)
149 F(12)
150 F(13)
151 F(14)
152 F(15)
153 F(16)
154 F(17)
155 F(18)
156 F(19)
157 F(20)
158 F(21)
159 F(22)
160 F(23)
161 F(24)
162 F(25)
163 F(26)
164 F(27)
165 F(28)
166 F(29)
167 F(30)
168 F(31)
169 return (1 & ((differentbits - 1) >> 8)) - 1;
170 }
171
crypto_sign_ed25519_open(unsigned char * m,unsigned long long * mlen,const unsigned char * sm,unsigned long long smlen,const unsigned char * pk)172 int crypto_sign_ed25519_open(
173 unsigned char *m,unsigned long long *mlen,
174 const unsigned char *sm,unsigned long long smlen,
175 const unsigned char *pk
176 )
177 {
178 unsigned int i;
179 int ret;
180 unsigned char t2[32];
181 ge25519 get1, get2;
182 sc25519 schram, scs;
183 unsigned char hram[crypto_hash_sha512_BYTES];
184
185 *mlen = (unsigned long long) -1;
186 if (smlen < 64) {
187 lwsl_notice("a\n");
188
189 return -1;
190 }
191
192 if (ge25519_unpackneg_vartime(&get1, pk)) {
193 lwsl_notice("b\n");
194 return -1;
195 }
196
197 get_hram(hram,sm,pk,m, (size_t)smlen);
198
199 sc25519_from64bytes(&schram, hram);
200
201 sc25519_from32bytes(&scs, sm+32);
202
203 ge25519_double_scalarmult_vartime(&get2, &get1, &schram, &ge25519_base, &scs);
204 ge25519_pack(t2, &get2);
205
206 ret = crypto_verify_32(sm, t2);
207 lwsl_notice("vf says %d\n", ret);
208
209 if (!ret)
210 {
211 for(i=0;i<smlen-64;i++)
212 m[i] = sm[i + 64];
213 *mlen = smlen-64;
214 }
215 else
216 {
217 for(i=0;i<smlen-64;i++)
218 m[i] = 0;
219 }
220 return ret;
221 }
222