Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/libecc/src/examples/sig/dsa/dsa.c
34928 views
1
/*
2
* Copyright (C) 2021 - This file is part of libecc project
3
*
4
* Authors:
5
* Ryad BENADJILA <[email protected]>
6
* Arnaud EBALARD <[email protected]>
7
*
8
* This software is licensed under a dual BSD and GPL v2 license.
9
* See LICENSE file at the root folder of the project.
10
*/
11
#include "dsa.h"
12
13
14
/* We include the rand external dependency because we have to generate
15
* some random data for the nonces.
16
*/
17
#include <libecc/external_deps/rand.h>
18
/* We include the printf external dependency for printf output */
19
#include <libecc/external_deps/print.h>
20
/* We include our common helpers */
21
#include "../common/common.h"
22
23
/*
24
* The purpose of this example is to implement the DSA
25
* related algorithms as per FIPS 186-4 based on libecc arithmetic
26
* primitives.
27
*
28
* XXX: Please be aware that libecc has been designed for Elliptic
29
* Curve cryptography, and as so the arithmetic primitives are
30
* not optimized for big numbers >= 1024 bits usually used for DSA.
31
* Additionnaly, a hard limit of our NN values makes it impossible
32
* to exceed ~5300 bits in the best case (words of size 64 bits).
33
*
34
* All in all, please see this as a proof of concept of implementing
35
* FIPS 186-4 rather than a production code. Use it at your own risk!
36
*
37
* !! DISCLAIMER !!
38
* ================
39
*
40
* Althoug some efforts have been made to secure this implementation
41
* of DSA (e.g. by protecting the private key and nonces using constant
42
* time and blinding WHEN activated with BLINDING=1), please consider this
43
* code as a proof of concept and use it at your own risk.
44
*
45
* All-in-all, this piece of code can be useful in some contexts, or risky to
46
* use in other sensitive ones where advanced side-channels or fault attacks
47
* have to be considered. Use this DSA code knowingly and at your own risk!
48
*
49
*/
50
51
52
/* Import a DSA private key from buffers */
53
int dsa_import_priv_key(dsa_priv_key *priv, const u8 *p, u16 plen,
54
const u8 *q, u16 qlen,
55
const u8 *g, u16 glen,
56
const u8 *x, u16 xlen)
57
{
58
int ret, cmp;
59
60
/* Sanity checks */
61
MUST_HAVE((priv != NULL), ret, err);
62
MUST_HAVE((p != NULL) && (q != NULL) && (g != NULL) && (x != NULL), ret, err);
63
64
/* Import our big numbers */
65
ret = _os2ip(&(priv->p), p, plen); EG(ret, err);
66
ret = _os2ip(&(priv->q), q, qlen); EG(ret, err);
67
ret = _os2ip(&(priv->g), g, glen); EG(ret, err);
68
ret = _os2ip(&(priv->x), x, xlen); EG(ret, err);
69
70
/* Sanity check that q < p */
71
ret = nn_cmp(&(priv->q), &(priv->p), &cmp); EG(ret, err);
72
MUST_HAVE((cmp < 0), ret, err);
73
/* Sanity check that g < p */
74
ret = nn_cmp(&(priv->g), &(priv->p), &cmp); EG(ret, err);
75
MUST_HAVE((cmp < 0), ret, err);
76
/* Sanity check that x < q */
77
ret = nn_cmp(&(priv->x), &(priv->q), &cmp); EG(ret, err);
78
MUST_HAVE((cmp < 0), ret, err);
79
80
err:
81
if(ret && (priv != NULL)){
82
IGNORE_RET_VAL(local_memset(priv, 0, sizeof(dsa_priv_key)));
83
}
84
85
return ret;
86
}
87
88
/* Import a DSA public key from buffers */
89
int dsa_import_pub_key(dsa_pub_key *pub, const u8 *p, u16 plen,
90
const u8 *q, u16 qlen,
91
const u8 *g, u16 glen,
92
const u8 *y, u16 ylen)
93
{
94
int ret, cmp;
95
96
/* Sanity checks */
97
MUST_HAVE((pub != NULL), ret, err);
98
MUST_HAVE((p != NULL) && (q != NULL) && (g != NULL) && (y != NULL), ret, err);
99
100
/* Import our big numbers */
101
ret = _os2ip(&(pub->p), p, plen); EG(ret, err);
102
ret = _os2ip(&(pub->q), q, qlen); EG(ret, err);
103
ret = _os2ip(&(pub->g), g, glen); EG(ret, err);
104
ret = _os2ip(&(pub->y), y, ylen); EG(ret, err);
105
106
/* Sanity check that q < p */
107
ret = nn_cmp(&(pub->q), &(pub->p), &cmp); EG(ret, err);
108
MUST_HAVE((cmp < 0), ret, err);
109
/* Sanity check that g < p */
110
ret = nn_cmp(&(pub->g), &(pub->p), &cmp); EG(ret, err);
111
MUST_HAVE((cmp < 0), ret, err);
112
/* Sanity check that y < p */
113
ret = nn_cmp(&(pub->y), &(pub->p), &cmp); EG(ret, err);
114
MUST_HAVE((cmp < 0), ret, err);
115
116
err:
117
if(ret && (pub != NULL)){
118
IGNORE_RET_VAL(local_memset(pub, 0, sizeof(dsa_pub_key)));
119
}
120
121
return ret;
122
}
123
124
125
126
/* Compute a DSA public key from a private key.
127
* The public key is computed using modular exponentiation of the generator
128
* with the private key.
129
*/
130
int dsa_compute_pub_from_priv(dsa_pub_key *pub, const dsa_priv_key *priv)
131
{
132
int ret, cmp;
133
nn_src_t p, q, g, x;
134
nn x_;
135
x_.magic = WORD(0);
136
137
MUST_HAVE((pub != NULL) && (priv != NULL), ret, err);
138
139
/* Make things more readable */
140
p = &(priv->p);
141
q = &(priv->q);
142
g = &(priv->g);
143
x = &(priv->x);
144
145
/* Sanity checks */
146
ret = nn_check_initialized(p); EG(ret, err);
147
ret = nn_check_initialized(q); EG(ret, err);
148
ret = nn_check_initialized(g); EG(ret, err);
149
ret = nn_check_initialized(x); EG(ret, err);
150
151
/* Sanity check that q < p */
152
ret = nn_cmp(&(priv->q), &(priv->p), &cmp); EG(ret, err);
153
MUST_HAVE((cmp < 0), ret, err);
154
/* Sanity check that g < p */
155
ret = nn_cmp(&(priv->g), &(priv->p), &cmp); EG(ret, err);
156
MUST_HAVE((cmp < 0), ret, err);
157
/* Sanity check that x < q */
158
ret = nn_cmp(&(priv->x), &(priv->q), &cmp); EG(ret, err);
159
MUST_HAVE((cmp < 0), ret, err);
160
161
ret = nn_init(&x_, 0); EG(ret, err);
162
/* Blind the private key in all cases as this is a
163
* sensitive value.
164
*/
165
ret = _blind_scalar(x, q, &x_); EG(ret, err);
166
ret = _fix_scalar_msb(&x_, q, &x_); EG(ret, err);
167
168
/* Perform the exponentiation y = g**x mod (p) */
169
ret = nn_mod_pow(&(pub->y), g, &x_, p); EG(ret, err);
170
171
/* Initialize the public key */
172
ret = nn_copy(&(pub->p), p); EG(ret, err);
173
ret = nn_copy(&(pub->q), q); EG(ret, err);
174
ret = nn_copy(&(pub->g), g);
175
176
err:
177
if(ret && (pub != NULL)){
178
IGNORE_RET_VAL(local_memset(pub, 0, sizeof(dsa_pub_key)));
179
}
180
181
nn_uninit(&x_);
182
183
PTR_NULLIFY(p);
184
PTR_NULLIFY(q);
185
PTR_NULLIFY(g);
186
PTR_NULLIFY(x);
187
188
return ret;
189
}
190
191
/* Generate a DSA signature
192
* This implements "DSA Signature Generation" in section 4.6 of FIPS 186-4.
193
*/
194
int dsa_sign(const dsa_priv_key *priv, const u8 *msg, u32 msglen,
195
const u8 *nonce, u16 noncelen,
196
u8 *sig, u16 siglen, gen_hash_alg_type dsa_hash)
197
{
198
int ret, iszero;
199
/* N is the bit length of q */
200
bitcnt_t N, rshift;
201
/* Length of the hash function */
202
u8 hlen, block_size;
203
nn_src_t p, q, g, x;
204
/* The nonce, it inverse and its protected version */
205
nn k, kinv, k_;
206
/* r, s and z */
207
nn r, s, z;
208
/* Hash */
209
u8 hash[MAX_DIGEST_SIZE];
210
#ifdef USE_SIG_BLINDING
211
/* b is the blinding mask */
212
nn b;
213
b.magic = WORD(0);
214
#endif /* USE_SIG_BLINDING */
215
k.magic = kinv.magic = k_.magic = r.magic = s.magic = z.magic = WORD(0);
216
217
/* Sanity checks */
218
MUST_HAVE((priv != NULL) && (msg != NULL) && (sig != NULL), ret, err);
219
220
ret = local_memset(hash, 0, sizeof(hash)); EG(ret, err);
221
222
/* Make things more readable */
223
p = &(priv->p);
224
q = &(priv->q);
225
g = &(priv->g);
226
x = &(priv->x);
227
228
/* Sanity checks */
229
ret = nn_check_initialized(p); EG(ret, err);
230
ret = nn_check_initialized(q); EG(ret, err);
231
ret = nn_check_initialized(g); EG(ret, err);
232
ret = nn_check_initialized(x); EG(ret, err);
233
234
/* Let N be the bit length of q. Let min(N, outlen) denote the minimum
235
* of the positive integers N and outlen, where outlen is the bit length
236
* of the hash function output block.
237
*/
238
ret = nn_bitlen(q, &N); EG(ret, err);
239
ret = gen_hash_get_hash_sizes(dsa_hash, &hlen, &block_size); EG(ret, err);
240
MUST_HAVE((hlen <= MAX_DIGEST_SIZE), ret, err);
241
242
/* Sanity check on the signature length */
243
MUST_HAVE((siglen == (2 * BYTECEIL(N))), ret, err);
244
245
restart:
246
/* If the nonce is imposed, use it. Else get a random modulo q */
247
if(nonce != NULL){
248
ret = _os2ip(&k, nonce, noncelen); EG(ret, err);
249
}
250
else{
251
ret = nn_get_random_mod(&k, q); EG(ret, err);
252
}
253
254
/* Fix the MSB of our scalar */
255
ret = nn_copy(&k_, &k); EG(ret, err);
256
#ifdef USE_SIG_BLINDING
257
/* Blind the scalar */
258
ret = _blind_scalar(&k_, q, &k_); EG(ret, err);
259
#endif /* USE_SIG_BLINDING */
260
ret = _fix_scalar_msb(&k_, q, &k_); EG(ret, err);
261
/* r = (g**k mod p) mod q */
262
ret = nn_init(&r, 0); EG(ret, err);
263
/* Exponentiation modulo p */
264
ret = nn_mod_pow(&r, g, &k_, p); EG(ret, err);
265
/* Modulo q */
266
ret = nn_mod(&r, &r, q); EG(ret, err);
267
268
/* If r is 0, restart the process */
269
ret = nn_iszero(&r, &iszero); EG(ret, err);
270
if (iszero) {
271
goto restart;
272
}
273
274
/* Export r */
275
ret = _i2osp(&r, sig, (siglen / 2)); EG(ret, err);
276
277
/* Compute the hash */
278
ret = gen_hash_hfunc(msg, msglen, hash, dsa_hash); EG(ret, err);
279
/* z = the leftmost min(N, outlen) bits of Hash(M) */
280
rshift = 0;
281
if ((hlen * 8) > N) {
282
rshift = (bitcnt_t)((hlen * 8) - N);
283
}
284
ret = _os2ip(&z, hash, hlen); EG(ret, err);
285
if (rshift) {
286
ret = nn_rshift_fixedlen(&z, &z, rshift); EG(ret, err);
287
}
288
ret = nn_mod(&z, &z, q); EG(ret, err);
289
290
#ifdef USE_SIG_BLINDING
291
/* Note: if we use blinding, r and e are multiplied by
292
* a random value b in ]0,q[ */
293
ret = nn_get_random_mod(&b, q); EG(ret, err);
294
/* Blind r with b */
295
ret = nn_mod_mul(&r, &r, &b, q); EG(ret, err);
296
/* Blind the message z */
297
ret = nn_mod_mul(&z, &z, &b, q); EG(ret, err);
298
/*
299
* In case of blinding, we compute (b*k)^-1, and b^-1 will
300
* automatically unblind (r*x) in the following.
301
*/
302
ret = nn_mod_mul(&k, &k, &b, q); EG(ret, err);
303
#endif /* USE_SIG_BLINDING */
304
305
/* Compute s = k^-1 * (xr + z) mod q */
306
/* Compute k^-1 mod q */
307
/* NOTE: we use Fermat's little theorem inversion for
308
* constant time here. This is possible since q is prime.
309
*/
310
ret = nn_modinv_fermat(&kinv, &k, q); EG(ret, err);
311
ret = nn_mod_mul(&s, &r, x, q); EG(ret, err);
312
ret = nn_mod_add(&s, &s, &z, q); EG(ret, err);
313
ret = nn_mod_mul(&s, &kinv, &s, q); EG(ret, err);
314
315
/* If s is 0, restart the process */
316
ret = nn_iszero(&s, &iszero); EG(ret, err);
317
if (iszero) {
318
goto restart;
319
}
320
321
/* Export s */
322
ret = _i2osp(&s, sig + (siglen / 2), (siglen / 2));
323
324
err:
325
if(ret && (sig != NULL)){
326
IGNORE_RET_VAL(local_memset(sig, 0, siglen));
327
}
328
329
nn_uninit(&k);
330
nn_uninit(&kinv);
331
nn_uninit(&k_);
332
#ifdef USE_SIG_BLINDING
333
nn_uninit(&b);
334
#endif
335
nn_uninit(&r);
336
nn_uninit(&s);
337
nn_uninit(&z);
338
339
PTR_NULLIFY(p);
340
PTR_NULLIFY(q);
341
PTR_NULLIFY(g);
342
PTR_NULLIFY(x);
343
344
return ret;
345
}
346
347
348
349
/* Verify a DSA signature
350
* This implements "DSA Signature Verification and Validation" in section 4.7 of FIPS 186-4.
351
*/
352
int dsa_verify(const dsa_pub_key *pub, const u8 *msg, u32 msglen,
353
const u8 *sig, u16 siglen, gen_hash_alg_type dsa_hash)
354
{
355
int ret, iszero, cmp;
356
/* N is the bit length of q */
357
bitcnt_t N, rshift;
358
/* Length of the hash function */
359
u8 hlen, block_size;
360
nn_src_t p, q, g, y;
361
/* r, s */
362
nn r, s, z;
363
/* u1, u2, and v */
364
nn u1, u2, v;
365
/* Hash */
366
u8 hash[MAX_DIGEST_SIZE];
367
r.magic = s.magic = z.magic = u1.magic = u2.magic = WORD(0);
368
369
/* Sanity checks */
370
MUST_HAVE((pub != NULL) && (msg != NULL) && (sig != NULL), ret, err);
371
372
ret = local_memset(hash, 0, sizeof(hash)); EG(ret, err);
373
374
/* Make things more readable */
375
p = &(pub->p);
376
q = &(pub->q);
377
g = &(pub->g);
378
y = &(pub->y);
379
380
/* Sanity checks */
381
ret = nn_check_initialized(p); EG(ret, err);
382
ret = nn_check_initialized(q); EG(ret, err);
383
ret = nn_check_initialized(g); EG(ret, err);
384
ret = nn_check_initialized(y); EG(ret, err);
385
386
/* Sanity check on the signature length */
387
ret = nn_bitlen(q, &N); EG(ret, err);
388
MUST_HAVE((siglen == (2 * BYTECEIL(N))), ret, err);
389
390
/* Extract r and s */
391
ret = _os2ip(&r, sig, (siglen / 2)); EG(ret, err);
392
ret = _os2ip(&s, sig + (siglen / 2), (siglen / 2)); EG(ret, err);
393
394
/* Return an error if r = 0 or s = 0 */
395
ret = nn_iszero(&r, &iszero); EG(ret, err);
396
MUST_HAVE((!iszero), ret, err);
397
ret = nn_iszero(&s, &iszero); EG(ret, err);
398
MUST_HAVE((!iszero), ret, err);
399
/* Check thatt 0 < r′ < q and 0 < s′ < q */
400
ret = nn_cmp(&r, q, &cmp); EG(ret, err);
401
MUST_HAVE((cmp < 0), ret, err);
402
ret = nn_cmp(&s, q, &cmp); EG(ret, err);
403
MUST_HAVE((cmp < 0), ret, err);
404
405
/* Compute the hash */
406
ret = gen_hash_get_hash_sizes(dsa_hash, &hlen, &block_size); EG(ret, err);
407
MUST_HAVE((hlen <= MAX_DIGEST_SIZE), ret, err);
408
ret = gen_hash_hfunc(msg, msglen, hash, dsa_hash); EG(ret, err);
409
/* z = the leftmost min(N, outlen) bits of Hash(M) */
410
rshift = 0;
411
if ((hlen * 8) > N) {
412
rshift = (bitcnt_t)((hlen * 8) - N);
413
}
414
ret = _os2ip(&z, hash, hlen); EG(ret, err);
415
if (rshift) {
416
ret = nn_rshift_fixedlen(&z, &z, rshift); EG(ret, err);
417
}
418
ret = nn_mod(&z, &z, q); EG(ret, err);
419
420
/* Compute w = s**-1 mod (q) in s */
421
ret = nn_modinv(&s, &s, q); EG(ret, err);
422
423
/* u1 = (zw) mod q */
424
ret = nn_mod_mul(&u1, &z, &s, q); EG(ret, err);
425
/* u2 = ((r′)w) mod q */
426
ret = nn_mod_mul(&u2, &r, &s, q); EG(ret, err);
427
/* Now compute v = = ((g**u1 y**u2) mod p) mod q */
428
/* NOTE: no need to use a secure exponentiation here as we only
429
* manipulate public data.
430
*/
431
ret = _nn_mod_pow_insecure(&v, g, &u1, p); EG(ret, err);
432
ret = _nn_mod_pow_insecure(&s, y, &u2, p); EG(ret, err);
433
ret = nn_mod_mul(&v, &v, &s, p); EG(ret, err);
434
ret = nn_mod(&v, &v, q); EG(ret, err);
435
436
/* Check that v = r */
437
ret = nn_cmp(&v, &r, &cmp); EG(ret, err);
438
ret = (cmp != 0) ? -1 : 0;
439
440
err:
441
nn_uninit(&r);
442
nn_uninit(&s);
443
nn_uninit(&z);
444
nn_uninit(&u1);
445
nn_uninit(&u2);
446
nn_uninit(&v);
447
448
PTR_NULLIFY(p);
449
PTR_NULLIFY(q);
450
PTR_NULLIFY(g);
451
PTR_NULLIFY(y);
452
453
return ret;
454
}
455
456
#ifdef DSA
457
#include <libecc/utils/print_buf.h>
458
int main(int argc, char *argv[])
459
{
460
int ret = 0;
461
462
const u8 p[] = {
463
0x90, 0x06, 0x64, 0x55, 0xB5, 0xCF, 0xC3, 0x8F, 0x9C, 0xAA, 0x4A, 0x48, 0xB4, 0x28, 0x1F, 0x29, 0x2C, 0x26, 0x0F, 0xEE, 0xF0, 0x1F, 0xD6, 0x10, 0x37, 0xE5, 0x62, 0x58,
464
0xA7, 0x79, 0x5A, 0x1C, 0x7A, 0xD4, 0x60, 0x76, 0x98, 0x2C, 0xE6, 0xBB, 0x95, 0x69, 0x36, 0xC6, 0xAB, 0x4D, 0xCF, 0xE0, 0x5E, 0x67, 0x84, 0x58, 0x69, 0x40, 0xCA, 0x54,
465
0x4B, 0x9B, 0x21, 0x40, 0xE1, 0xEB, 0x52, 0x3F, 0x00, 0x9D, 0x20, 0xA7, 0xE7, 0x88, 0x0E, 0x4E, 0x5B, 0xFA, 0x69, 0x0F, 0x1B, 0x90, 0x04, 0xA2, 0x78, 0x11, 0xCD, 0x99,
466
0x04, 0xAF, 0x70, 0x42, 0x0E, 0xEF, 0xD6, 0xEA, 0x11, 0xEF, 0x7D, 0xA1, 0x29, 0xF5, 0x88, 0x35, 0xFF, 0x56, 0xB8, 0x9F, 0xAA, 0x63, 0x7B, 0xC9, 0xAC, 0x2E, 0xFA, 0xAB,
467
0x90, 0x34, 0x02, 0x22, 0x9F, 0x49, 0x1D, 0x8D, 0x34, 0x85, 0x26, 0x1C, 0xD0, 0x68, 0x69, 0x9B, 0x6B, 0xA5, 0x8A, 0x1D, 0xDB, 0xBE, 0xF6, 0xDB, 0x51, 0xE8, 0xFE, 0x34,
468
0xE8, 0xA7, 0x8E, 0x54, 0x2D, 0x7B, 0xA3, 0x51, 0xC2, 0x1E, 0xA8, 0xD8, 0xF1, 0xD2, 0x9F, 0x5D, 0x5D, 0x15, 0x93, 0x94, 0x87, 0xE2, 0x7F, 0x44, 0x16, 0xB0, 0xCA, 0x63,
469
0x2C, 0x59, 0xEF, 0xD1, 0xB1, 0xEB, 0x66, 0x51, 0x1A, 0x5A, 0x0F, 0xBF, 0x61, 0x5B, 0x76, 0x6C, 0x58, 0x62, 0xD0, 0xBD, 0x8A, 0x3F, 0xE7, 0xA0, 0xE0, 0xDA, 0x0F, 0xB2,
470
0xFE, 0x1F, 0xCB, 0x19, 0xE8, 0xF9, 0x99, 0x6A, 0x8E, 0xA0, 0xFC, 0xCD, 0xE5, 0x38, 0x17, 0x52, 0x38, 0xFC, 0x8B, 0x0E, 0xE6, 0xF2, 0x9A, 0xF7, 0xF6, 0x42, 0x77, 0x3E,
471
0xBE, 0x8C, 0xD5, 0x40, 0x24, 0x15, 0xA0, 0x14, 0x51, 0xA8, 0x40, 0x47, 0x6B, 0x2F, 0xCE, 0xB0, 0xE3, 0x88, 0xD3, 0x0D, 0x4B, 0x37, 0x6C, 0x37, 0xFE, 0x40, 0x1C, 0x2A,
472
0x2C, 0x2F, 0x94, 0x1D, 0xAD, 0x17, 0x9C, 0x54, 0x0C, 0x1C, 0x8C, 0xE0, 0x30, 0xD4, 0x60, 0xC4, 0xD9, 0x83, 0xBE, 0x9A, 0xB0, 0xB2, 0x0F, 0x69, 0x14, 0x4C, 0x1A, 0xE1,
473
0x3F, 0x93, 0x83, 0xEA, 0x1C, 0x08, 0x50, 0x4F, 0xB0, 0xBF, 0x32, 0x15, 0x03, 0xEF, 0xE4, 0x34, 0x88, 0x31, 0x0D, 0xD8, 0xDC, 0x77, 0xEC, 0x5B, 0x83, 0x49, 0xB8, 0xBF,
474
0xE9, 0x7C, 0x2C, 0x56, 0x0E, 0xA8, 0x78, 0xDE, 0x87, 0xC1, 0x1E, 0x3D, 0x59, 0x7F, 0x1F, 0xEA, 0x74, 0x2D, 0x73, 0xEE, 0xC7, 0xF3, 0x7B, 0xE4, 0x39, 0x49, 0xEF, 0x1A,
475
0x0D, 0x15, 0xC3, 0xF3, 0xE3, 0xFC, 0x0A, 0x83, 0x35, 0x61, 0x70, 0x55, 0xAC, 0x91, 0x32, 0x8E, 0xC2, 0x2B, 0x50, 0xFC, 0x15, 0xB9, 0x41, 0xD3, 0xD1, 0x62, 0x4C, 0xD8,
476
0x8B, 0xC2, 0x5F, 0x3E, 0x94, 0x1F, 0xDD, 0xC6, 0x20, 0x06, 0x89, 0x58, 0x1B, 0xFE, 0xC4, 0x16, 0xB4, 0xB2, 0xCB, 0x73,
477
};
478
479
const u8 q[] = {
480
0xCF, 0xA0, 0x47, 0x8A, 0x54, 0x71, 0x7B, 0x08, 0xCE, 0x64, 0x80, 0x5B, 0x76, 0xE5, 0xB1, 0x42, 0x49, 0xA7, 0x7A, 0x48, 0x38, 0x46, 0x9D, 0xF7, 0xF7, 0xDC, 0x98, 0x7E,
481
0xFC, 0xCF, 0xB1, 0x1D,
482
};
483
484
const u8 g[] = {
485
0x5E, 0x5C, 0xBA, 0x99, 0x2E, 0x0A, 0x68, 0x0D, 0x88, 0x5E, 0xB9, 0x03, 0xAE, 0xA7, 0x8E, 0x4A, 0x45, 0xA4, 0x69, 0x10, 0x3D, 0x44, 0x8E, 0xDE, 0x3B, 0x7A, 0xCC, 0xC5,
486
0x4D, 0x52, 0x1E, 0x37, 0xF8, 0x4A, 0x4B, 0xDD, 0x5B, 0x06, 0xB0, 0x97, 0x0C, 0xC2, 0xD2, 0xBB, 0xB7, 0x15, 0xF7, 0xB8, 0x28, 0x46, 0xF9, 0xA0, 0xC3, 0x93, 0x91, 0x4C,
487
0x79, 0x2E, 0x6A, 0x92, 0x3E, 0x21, 0x17, 0xAB, 0x80, 0x52, 0x76, 0xA9, 0x75, 0xAA, 0xDB, 0x52, 0x61, 0xD9, 0x16, 0x73, 0xEA, 0x9A, 0xAF, 0xFE, 0xEC, 0xBF, 0xA6, 0x18,
488
0x3D, 0xFC, 0xB5, 0xD3, 0xB7, 0x33, 0x2A, 0xA1, 0x92, 0x75, 0xAF, 0xA1, 0xF8, 0xEC, 0x0B, 0x60, 0xFB, 0x6F, 0x66, 0xCC, 0x23, 0xAE, 0x48, 0x70, 0x79, 0x1D, 0x59, 0x82,
489
0xAA, 0xD1, 0xAA, 0x94, 0x85, 0xFD, 0x8F, 0x4A, 0x60, 0x12, 0x6F, 0xEB, 0x2C, 0xF0, 0x5D, 0xB8, 0xA7, 0xF0, 0xF0, 0x9B, 0x33, 0x97, 0xF3, 0x93, 0x7F, 0x2E, 0x90, 0xB9,
490
0xE5, 0xB9, 0xC9, 0xB6, 0xEF, 0xEF, 0x64, 0x2B, 0xC4, 0x83, 0x51, 0xC4, 0x6F, 0xB1, 0x71, 0xB9, 0xBF, 0xA9, 0xEF, 0x17, 0xA9, 0x61, 0xCE, 0x96, 0xC7, 0xE7, 0xA7, 0xCC,
491
0x3D, 0x3D, 0x03, 0xDF, 0xAD, 0x10, 0x78, 0xBA, 0x21, 0xDA, 0x42, 0x51, 0x98, 0xF0, 0x7D, 0x24, 0x81, 0x62, 0x2B, 0xCE, 0x45, 0x96, 0x9D, 0x9C, 0x4D, 0x60, 0x63, 0xD7,
492
0x2A, 0xB7, 0xA0, 0xF0, 0x8B, 0x2F, 0x49, 0xA7, 0xCC, 0x6A, 0xF3, 0x35, 0xE0, 0x8C, 0x47, 0x20, 0xE3, 0x14, 0x76, 0xB6, 0x72, 0x99, 0xE2, 0x31, 0xF8, 0xBD, 0x90, 0xB3,
493
0x9A, 0xC3, 0xAE, 0x3B, 0xE0, 0xC6, 0xB6, 0xCA, 0xCE, 0xF8, 0x28, 0x9A, 0x2E, 0x28, 0x73, 0xD5, 0x8E, 0x51, 0xE0, 0x29, 0xCA, 0xFB, 0xD5, 0x5E, 0x68, 0x41, 0x48, 0x9A,
494
0xB6, 0x6B, 0x5B, 0x4B, 0x9B, 0xA6, 0xE2, 0xF7, 0x84, 0x66, 0x08, 0x96, 0xAF, 0xF3, 0x87, 0xD9, 0x28, 0x44, 0xCC, 0xB8, 0xB6, 0x94, 0x75, 0x49, 0x6D, 0xE1, 0x9D, 0xA2,
495
0xE5, 0x82, 0x59, 0xB0, 0x90, 0x48, 0x9A, 0xC8, 0xE6, 0x23, 0x63, 0xCD, 0xF8, 0x2C, 0xFD, 0x8E, 0xF2, 0xA4, 0x27, 0xAB, 0xCD, 0x65, 0x75, 0x0B, 0x50, 0x6F, 0x56, 0xDD,
496
0xE3, 0xB9, 0x88, 0x56, 0x7A, 0x88, 0x12, 0x6B, 0x91, 0x4D, 0x78, 0x28, 0xE2, 0xB6, 0x3A, 0x6D, 0x7E, 0xD0, 0x74, 0x7E, 0xC5, 0x9E, 0x0E, 0x0A, 0x23, 0xCE, 0x7D, 0x8A,
497
0x74, 0xC1, 0xD2, 0xC2, 0xA7, 0xAF, 0xB6, 0xA2, 0x97, 0x99, 0x62, 0x0F, 0x00, 0xE1, 0x1C, 0x33, 0x78, 0x7F, 0x7D, 0xED, 0x3B, 0x30, 0xE1, 0xA2, 0x2D, 0x09, 0xF1, 0xFB,
498
0xDA, 0x1A, 0xBB, 0xBF, 0xBF, 0x25, 0xCA, 0xE0, 0x5A, 0x13, 0xF8, 0x12, 0xE3, 0x45, 0x63, 0xF9, 0x94, 0x10, 0xE7, 0x3B,
499
};
500
501
const u8 x[] = {
502
0x3A, 0xBC, 0x15, 0x87, 0x29, 0x7C, 0xE7, 0xB9, 0xEA, 0x1A, 0xD6, 0x65, 0x1C, 0xF2, 0xBC, 0x4D, 0x7F, 0x92, 0xED, 0x25, 0xCA, 0xBC, 0x85, 0x53, 0xF5, 0x67, 0xD1, 0xB4,
503
0x0E, 0xBB, 0x87, 0x64,
504
};
505
506
const u8 y[] = {
507
0x8b, 0x89, 0x1c, 0x86, 0x92, 0xd3, 0xde, 0x87, 0x58, 0x79, 0x39, 0x0f, 0x26, 0x98, 0xb2, 0x6f, 0xbe, 0xcc, 0xa6, 0xb0, 0x75, 0x53, 0x5d, 0xce, 0x6b, 0x0c, 0x86, 0x25, 0x77, 0xf9, 0xfa, 0x0d, 0xef, 0x60, 0x74, 0xe7, 0xa7, 0x62, 0x41, 0x21, 0x22, 0x4a, 0x59, 0x58, 0x96, 0xab, 0xd4, 0xcd, 0xa5, 0x6b, 0x2c, 0xef, 0xb9, 0x42, 0xe0, 0x25, 0xd2, 0xa4, 0x28, 0x2f, 0xfa, 0xa9, 0x8a, 0x48, 0xcd, 0xb4, 0x7e, 0x1a, 0x6f, 0xcb, 0x5c, 0xfb, 0x39, 0x3e, 0xf3, 0x5a, 0xf9, 0xdf, 0x91, 0x31, 0x02, 0xbb, 0x30, 0x3c, 0x2b, 0x5c, 0x36, 0xc3, 0xf8, 0xfc, 0x04, 0xed, 0x7b, 0x8b, 0x69, 0xfe, 0xfe, 0x0c, 0xf3, 0xe1, 0xfc, 0x05, 0xcf, 0xa7, 0x13, 0xb3, 0x43, 0x5b, 0x26, 0x56, 0xe9, 0x13, 0xba, 0x88, 0x74, 0xae, 0xa9, 0xf9, 0x36, 0x00, 0x6a, 0xeb, 0x44, 0x8b, 0xcd, 0x00, 0x5d, 0x18, 0xec, 0x35, 0x62, 0xa3, 0x3d, 0x04, 0xcf, 0x25, 0xc8, 0xd3, 0xd6, 0x98, 0x44, 0x34, 0x34, 0x42, 0xfa, 0x3d, 0xb7, 0xde, 0x61, 0x8c, 0x5e, 0x2d, 0xa0, 0x64, 0x57, 0x3e, 0x61, 0xe6, 0xd5, 0x58, 0x1b, 0xfb, 0x69, 0x4a, 0x23, 0xac, 0x87, 0xfd, 0x5b, 0x52, 0xd6, 0x2e, 0x95, 0x4e, 0x13, 0x76, 0xdb, 0x8d, 0xdb, 0x52, 0x4f, 0xfc, 0x0d, 0x46, 0x9d, 0xf9, 0x78, 0x79, 0x2e, 0xe4, 0x41, 0x73, 0x8e, 0x5d, 0xb0, 0x5a, 0x7d, 0xc4, 0x3e, 0x94, 0xc1, 0x1a, 0x2e, 0x7a, 0x4f, 0xbe, 0x38, 0x30, 0x71, 0xfa, 0x36, 0xd2, 0xa7, 0xec, 0x8a, 0x93, 0x88, 0xfe, 0x1c, 0x4f, 0x79, 0x88, 0x8a, 0x99, 0xd3, 0xb6, 0x10, 0x56, 0x97, 0xc2, 0x55, 0x6b, 0x79, 0xbb, 0x4d, 0x7e, 0x78, 0x1c, 0xeb, 0xb3, 0xd4, 0x86, 0x6a, 0xd8, 0x25, 0xa5, 0xe8, 0x30, 0x84, 0x60, 0x72, 0x28, 0x9f, 0xdb, 0xc9, 0x41, 0xfa, 0x67, 0x9c, 0xa8, 0x2f, 0x5f, 0x78, 0xb7, 0x46, 0x1b, 0x24, 0x04, 0xdb, 0x88, 0x3d, 0x21, 0x5f, 0x4e, 0x06, 0x76, 0xcf, 0x54, 0x93, 0x95, 0x0a, 0xc5, 0x59, 0x16, 0x97, 0xbf, 0xea, 0x8d, 0x1e, 0xe6, 0xec, 0x01, 0x6b, 0x89, 0xba, 0x51, 0xca, 0xfb, 0x5f, 0x9c, 0x84, 0xc9, 0x89, 0xfa, 0x11, 0x73, 0x75, 0xe9, 0x45, 0x78, 0xf2, 0x8b, 0xe0, 0xb3, 0x4c, 0xe0, 0x54, 0x5d, 0xa4, 0x62, 0x66, 0xfd, 0x77, 0xf6, 0x2d, 0x8f, 0x2c, 0xee, 0x92, 0xab, 0x77, 0x01, 0x2a, 0xfe, 0xbc, 0x11, 0x00, 0x89, 0x85, 0xa8, 0x21, 0xcd, 0x2d, 0x97, 0x8c, 0x7e, 0x6f, 0xe7, 0x49, 0x9d, 0x1a, 0xaf, 0x8d, 0xe6, 0x32, 0xc2, 0x1b, 0xb4, 0x8c, 0xa5, 0xcb, 0xf9, 0xf3, 0x10, 0x98, 0xfd, 0x3f, 0xd3, 0x85, 0x4c, 0x49, 0xa6, 0x5d, 0x92, 0x01, 0x74, 0x4a, 0xac, 0xe5, 0x40, 0x35, 0x49, 0x74, 0xf9,
508
};
509
510
const u8 msg[] = "abc";
511
512
const u8 nonce[] = {
513
0xA6, 0x90, 0x2C, 0x1E, 0x6E, 0x39, 0x43, 0xC5, 0x62, 0x80, 0x61, 0x58, 0x8A, 0x8B, 0x00, 0x7B, 0xCC, 0xEA, 0x91, 0xDB, 0xF1, 0x29, 0x15, 0x48, 0x3F, 0x04, 0xB2, 0x4A,
514
0xB0, 0x67, 0x8B, 0xEE,
515
};
516
517
dsa_priv_key priv;
518
dsa_pub_key pub;
519
dsa_pub_key pub2;
520
u8 sig[32*2] = { 0 };
521
522
FORCE_USED_VAR(argc);
523
FORCE_USED_VAR(argv);
524
525
/* Sanity check on size for DSA.
526
* NOTE: the double parentheses are here to handle -Wunreachable-code
527
*/
528
if((NN_USABLE_MAX_BIT_LEN) < (4096)){
529
ext_printf("Error: you seem to have compiled libecc with usable NN size < 4096, not suitable for DSA.\n");
530
ext_printf(" => Please recompile libecc with EXTRA_CFLAGS=\"-DUSER_NN_BIT_LEN=4096\"\n");
531
ext_printf(" This will increase usable NN for proper DSA up to 4096 bits.\n");
532
ext_printf(" Then recompile the current examples with the same EXTRA_CFLAGS=\"-DUSER_NN_BIT_LEN=4096\" flag and execute again!\n");
533
/* NOTE: ret = 0 here to pass self tests even if the library is not compatible */
534
ret = 0;
535
goto err;
536
}
537
538
539
ret = dsa_import_priv_key(&priv, p, sizeof(p), q, sizeof(q), g, sizeof(g), x, sizeof(x)); EG(ret, err);
540
ret = dsa_import_pub_key(&pub, p, sizeof(p), q, sizeof(q), g, sizeof(g), y, sizeof(y)); EG(ret, err);
541
ret = dsa_compute_pub_from_priv(&pub2, &priv); EG(ret, err);
542
543
nn_print("y", &(pub2.y));
544
545
ret = dsa_sign(&priv, msg, sizeof(msg)-1, nonce, sizeof(nonce), sig, sizeof(sig), HASH_SHA256); EG(ret, err);
546
547
buf_print("sig", sig, sizeof(sig));
548
549
ret = dsa_verify(&pub, msg, sizeof(msg)-1, sig, sizeof(sig), HASH_SHA256);
550
ext_printf("Signature result %d\n", ret);
551
552
err:
553
return ret;
554
}
555
#endif
556
557