CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/ext/libkirk/ec.c
Views: 1401
1
// Copyright 2007-2022 Segher Boessenkool <[email protected]>
2
// Licensed under the terms of the GNU GPL, either version 2 or version 3
3
// https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
4
// https://www.gnu.org/licenses/gpl-3.0.html
5
6
7
// Modified for Kirk engine by setting single curve and internal function
8
// to support Kirk elliptic curve options.- July 2011
9
10
#include <string.h>
11
#include <stdio.h>
12
13
// Include definitions from kirk header
14
#include "kirk_engine.h"
15
16
struct point {
17
u8 x[20];
18
u8 y[20];
19
};
20
// Simplified for use by Kirk Engine since it has only 1 curve
21
22
u8 ec_p[20];
23
u8 ec_a[20];
24
u8 ec_b[20];
25
u8 ec_N[21];
26
struct point ec_G; // mon
27
struct point ec_Q; // mon
28
u8 ec_k[21];
29
30
31
32
void hex_dump(char *str, u8 *buf, int size)
33
{
34
int i;
35
36
if(str)
37
printf("%s:", str);
38
39
for(i=0; i<size; i++){
40
if((i%32)==0){
41
printf("\n%4X:", i);
42
}
43
printf(" %02X", buf[i]);
44
}
45
printf("\n\n");
46
}
47
48
static void elt_copy(u8 *d, u8 *a)
49
{
50
memcpy(d, a, 20);
51
}
52
53
static void elt_zero(u8 *d)
54
{
55
memset(d, 0, 20);
56
}
57
58
static int elt_is_zero(u8 *d)
59
{
60
u32 i;
61
62
for (i = 0; i < 20; i++)
63
if (d[i] != 0)
64
return 0;
65
66
return 1;
67
}
68
69
static void elt_add(u8 *d, u8 *a, u8 *b)
70
{
71
bn_add(d, a, b, ec_p, 20);
72
}
73
74
static void elt_sub(u8 *d, u8 *a, u8 *b)
75
{
76
bn_sub(d, a, b, ec_p, 20);
77
}
78
79
static void elt_mul(u8 *d, u8 *a, u8 *b)
80
{
81
bn_mon_mul(d, a, b, ec_p, 20);
82
}
83
84
static void elt_square(u8 *d, u8 *a)
85
{
86
elt_mul(d, a, a);
87
}
88
89
static void elt_inv(u8 *d, u8 *a)
90
{
91
u8 s[20];
92
elt_copy(s, a);
93
bn_mon_inv(d, s, ec_p, 20);
94
}
95
96
static void point_to_mon(struct point *p)
97
{
98
bn_to_mon(p->x, ec_p, 20);
99
bn_to_mon(p->y, ec_p, 20);
100
}
101
102
static void point_from_mon(struct point *p)
103
{
104
bn_from_mon(p->x, ec_p, 20);
105
bn_from_mon(p->y, ec_p, 20);
106
}
107
108
#if 0
109
static int point_is_on_curve(u8 *p)
110
{
111
u8 s[20], t[20];
112
u8 *x, *y;
113
114
x = p;
115
y = p + 20;
116
117
elt_square(t, x);
118
elt_mul(s, t, x);
119
120
elt_mul(t, x, ec_a);
121
elt_add(s, s, t);
122
123
elt_add(s, s, ec_b);
124
125
elt_square(t, y);
126
elt_sub(s, s, t);
127
128
return elt_is_zero(s);
129
}
130
#endif
131
132
static void point_zero(struct point *p)
133
{
134
elt_zero(p->x);
135
elt_zero(p->y);
136
}
137
138
static int point_is_zero(struct point *p)
139
{
140
return elt_is_zero(p->x) && elt_is_zero(p->y);
141
}
142
143
static void point_double(struct point *r, struct point *p)
144
{
145
u8 s[20], t[20];
146
struct point pp;
147
u8 *px, *py, *rx, *ry;
148
149
pp = *p;
150
151
px = pp.x;
152
py = pp.y;
153
rx = r->x;
154
ry = r->y;
155
156
if (elt_is_zero(py)) {
157
point_zero(r);
158
return;
159
}
160
161
elt_square(t, px); // t = px*px
162
elt_add(s, t, t); // s = 2*px*px
163
elt_add(s, s, t); // s = 3*px*px
164
elt_add(s, s, ec_a); // s = 3*px*px + a
165
elt_add(t, py, py); // t = 2*py
166
elt_inv(t, t); // t = 1/(2*py)
167
elt_mul(s, s, t); // s = (3*px*px+a)/(2*py)
168
169
elt_square(rx, s); // rx = s*s
170
elt_add(t, px, px); // t = 2*px
171
elt_sub(rx, rx, t); // rx = s*s - 2*px
172
173
elt_sub(t, px, rx); // t = -(rx-px)
174
elt_mul(ry, s, t); // ry = -s*(rx-px)
175
elt_sub(ry, ry, py); // ry = -s*(rx-px) - py
176
}
177
178
static void point_add(struct point *r, struct point *p, struct point *q)
179
{
180
u8 s[20], t[20], u[20];
181
u8 *px, *py, *qx, *qy, *rx, *ry;
182
struct point pp, qq;
183
184
pp = *p;
185
qq = *q;
186
187
px = pp.x;
188
py = pp.y;
189
qx = qq.x;
190
qy = qq.y;
191
rx = r->x;
192
ry = r->y;
193
194
if (point_is_zero(&pp)) {
195
elt_copy(rx, qx);
196
elt_copy(ry, qy);
197
return;
198
}
199
200
if (point_is_zero(&qq)) {
201
elt_copy(rx, px);
202
elt_copy(ry, py);
203
return;
204
}
205
206
elt_sub(u, qx, px);
207
208
if (elt_is_zero(u)) {
209
elt_sub(u, qy, py);
210
if (elt_is_zero(u))
211
point_double(r, &pp);
212
else
213
point_zero(r);
214
215
return;
216
}
217
218
elt_inv(t, u); // t = 1/(qx-px)
219
elt_sub(u, qy, py); // u = qy-py
220
elt_mul(s, t, u); // s = (qy-py)/(qx-px)
221
222
elt_square(rx, s); // rx = s*s
223
elt_add(t, px, qx); // t = px+qx
224
elt_sub(rx, rx, t); // rx = s*s - (px+qx)
225
226
elt_sub(t, px, rx); // t = -(rx-px)
227
elt_mul(ry, s, t); // ry = -s*(rx-px)
228
elt_sub(ry, ry, py); // ry = -s*(rx-px) - py
229
}
230
231
static void point_mul(struct point *d, u8 *a, struct point *b) // a is bignum
232
{
233
u32 i;
234
u8 mask;
235
236
point_zero(d);
237
238
for (i = 0; i < 21; i++)
239
for (mask = 0x80; mask != 0; mask >>= 1) {
240
point_double(d, d);
241
if ((a[i] & mask) != 0)
242
point_add(d, d, b);
243
}
244
}
245
// Modified from original to support kirk engine use - July 2011
246
// Added call to Kirk Random number generator rather than /dev/random
247
248
static void generate_ecdsa(u8 *outR, u8 *outS, u8 *k, u8 *hash)
249
{
250
u8 e[21];
251
u8 kk[21];
252
u8 m[21];
253
u8 R[21];
254
u8 S[21];
255
u8 minv[21];
256
struct point mG;
257
258
e[0] = 0;R[0] = 0;S[0] = 0;
259
memcpy(e + 1, hash, 20);
260
bn_reduce(e, ec_N, 21);
261
262
// Original removed for portability
263
//try_again:
264
//fp = fopen("/dev/random", "rb");
265
//if (fread(m, sizeof m, 1, fp) != 1)
266
//fail("reading random");
267
//fclose(fp);
268
//m[0] = 0;
269
//if (bn_compare(m, ec_N, 21) >= 0)
270
//goto try_again;
271
272
// R = (mG).x
273
274
// Added call back to kirk PRNG - July 2011
275
kirk_CMD14(m+1, 20);
276
m[0] = 0;
277
278
point_mul(&mG, m, &ec_G);
279
point_from_mon(&mG);
280
R[0] = 0;
281
elt_copy(R+1, mG.x);
282
283
// S = m**-1*(e + Rk) (mod N)
284
285
bn_copy(kk, k, 21);
286
bn_reduce(kk, ec_N, 21);
287
bn_to_mon(m, ec_N, 21);
288
bn_to_mon(e, ec_N, 21);
289
bn_to_mon(R, ec_N, 21);
290
bn_to_mon(kk, ec_N, 21);
291
292
bn_mon_mul(S, R, kk, ec_N, 21);
293
bn_add(kk, S, e, ec_N, 21);
294
bn_mon_inv(minv, m, ec_N, 21);
295
bn_mon_mul(S, minv, kk, ec_N, 21);
296
297
bn_from_mon(R, ec_N, 21);
298
bn_from_mon(S, ec_N, 21);
299
memcpy(outR,R+1,20);
300
memcpy(outS,S+1,20);
301
}
302
303
// Signing =
304
// r = k *G;
305
// s = x*r+m / k
306
307
// Verify =
308
// r/s * P = m/s * G
309
310
// Slightly modified to support kirk compatible signature input - July 2011
311
static int check_ecdsa(struct point *Q, u8 *inR, u8 *inS, u8 *hash)
312
{
313
u8 Sinv[21];
314
u8 e[21], R[21], S[21];
315
u8 w1[21], w2[21];
316
struct point r1, r2;
317
u8 rr[21];
318
319
e[0] = 0;
320
memcpy(e + 1, hash, 20);
321
bn_reduce(e, ec_N, 21);
322
R[0] = 0;
323
memcpy(R + 1, inR, 20);
324
bn_reduce(R, ec_N, 21);
325
S[0] = 0;
326
memcpy(S + 1, inS, 20);
327
bn_reduce(S, ec_N, 21);
328
329
bn_to_mon(R, ec_N, 21);
330
bn_to_mon(S, ec_N, 21);
331
bn_to_mon(e, ec_N, 21);
332
// make Sinv = 1/S
333
bn_mon_inv(Sinv, S, ec_N, 21);
334
// w1 = m * Sinv
335
bn_mon_mul(w1, e, Sinv, ec_N, 21);
336
// w2 = r * Sinv
337
bn_mon_mul(w2, R, Sinv, ec_N, 21);
338
339
// mod N both
340
bn_from_mon(w1, ec_N, 21);
341
bn_from_mon(w2, ec_N, 21);
342
343
// r1 = m/s * G
344
point_mul(&r1, w1, &ec_G);
345
// r2 = r/s * P
346
point_mul(&r2, w2, Q);
347
348
//r1 = r1 + r2
349
point_add(&r1, &r1, &r2);
350
351
point_from_mon(&r1);
352
353
rr[0] = 0;
354
memcpy(rr + 1, r1.x, 20);
355
bn_reduce(rr, ec_N, 21);
356
357
bn_from_mon(R, ec_N, 21);
358
bn_from_mon(S, ec_N, 21);
359
360
return (bn_compare(rr, R, 21) == 0);
361
}
362
363
364
// Modified from original to support kirk engine use - July 2011
365
void ec_priv_to_pub(u8 *k, u8 *Q)
366
{
367
struct point ec_temp;
368
bn_to_mon(k, ec_N, 21);
369
point_mul(&ec_temp, k, &ec_G);
370
point_from_mon(&ec_temp);
371
//bn_from_mon(k, ec_N, 21);
372
memcpy(Q,ec_temp.x,20);
373
memcpy(Q+20,ec_temp.y,20);
374
}
375
376
// Modified from original to support kirk engine use - July 2011
377
void ec_pub_mult(u8 *k, u8 *Q)
378
{
379
struct point ec_temp;
380
//bn_to_mon(k, ec_N, 21);
381
point_mul(&ec_temp, k, &ec_Q);
382
point_from_mon(&ec_temp);
383
//bn_from_mon(k, ec_N, 21);
384
memcpy(Q,ec_temp.x,20);
385
memcpy(Q+20,ec_temp.y,20);
386
}
387
388
389
// Simplified for use by Kirk Engine - NO LONGER COMPATIABLE WITH ORIGINAL VERSION - July 2011
390
int ecdsa_set_curve(u8* p,u8* a,u8* b,u8* N,u8* Gx,u8* Gy)
391
{
392
memcpy(ec_p,p,20);
393
memcpy(ec_a,a,20);
394
memcpy(ec_b,b,20);
395
memcpy(ec_N,N,21);
396
397
bn_to_mon(ec_a, ec_p, 20);
398
bn_to_mon(ec_b, ec_p, 20);
399
400
memcpy(ec_G.x, Gx, 20);
401
memcpy(ec_G.y, Gy, 20);
402
point_to_mon(&ec_G);
403
404
return 0;
405
}
406
407
void ecdsa_set_pub(u8 *Q)
408
{
409
memcpy(ec_Q.x, Q, 20);
410
memcpy(ec_Q.y, Q+20, 20);
411
point_to_mon(&ec_Q);
412
}
413
414
void ecdsa_set_priv(u8 *ink)
415
{
416
u8 k[21];
417
k[0]=0;
418
memcpy(k+1,ink,20);
419
bn_reduce(k, ec_N, 21);
420
421
memcpy(ec_k, k, sizeof ec_k);
422
}
423
424
int ecdsa_verify(u8 *hash, u8 *R, u8 *S)
425
{
426
return check_ecdsa(&ec_Q, R, S, hash);
427
}
428
429
void ecdsa_sign(u8 *hash, u8 *R, u8 *S)
430
{
431
generate_ecdsa(R, S, ec_k, hash);
432
}
433
434
int point_is_on_curve(u8 *p)
435
{
436
u8 s[20], t[20];
437
u8 *x, *y;
438
439
x = p;
440
y = p + 20;
441
442
elt_square(t, x);
443
elt_mul(s, t, x);// s = x^3
444
445
elt_mul(t, x, ec_a);
446
elt_add(s, s, t); //s = x^3 + a *x
447
448
elt_add(s, s, ec_b);//s = x^3 + a *x + b
449
450
elt_square(t, y); //t = y^2
451
elt_sub(s, s, t); // is s - t = 0?
452
hex_dump("S", s, 20);
453
hex_dump("T", t,20);
454
return elt_is_zero(s);
455
}
456
457
void dump_ecc(void) {
458
hex_dump("P", ec_p, 20);
459
hex_dump("a", ec_a, 20);
460
hex_dump("b", ec_b, 20);
461
hex_dump("N", ec_N, 21);
462
hex_dump("Gx", ec_G.x, 20);
463
hex_dump("Gy", ec_G.y, 20);
464
}
465
466