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