Imported Upstream version 3.2
[platform/upstream/libwebsockets.git] / plugins / ssh-base / crypto / ed25519.c
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
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
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
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
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
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
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 }