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
15int
16crypto_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
35static void
36get_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
53int 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
79int 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
133int 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 (int)((1 & ((differentbits - 1) >> 8)) - 1);
170}
171
172int 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