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