1 /*
2 * Copyright (C) 2021 - This file is part of libecc project
3 *
4 * Authors:
5 * Ryad BENADJILA <ryadbenadjila@gmail.com>
6 * Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr>
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 */
dsa_import_priv_key(dsa_priv_key * priv,const u8 * p,u16 plen,const u8 * q,u16 qlen,const u8 * g,u16 glen,const u8 * x,u16 xlen)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 */
dsa_import_pub_key(dsa_pub_key * pub,const u8 * p,u16 plen,const u8 * q,u16 qlen,const u8 * g,u16 glen,const u8 * y,u16 ylen)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 */
dsa_compute_pub_from_priv(dsa_pub_key * pub,const dsa_priv_key * priv)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 */
dsa_sign(const dsa_priv_key * priv,const u8 * msg,u32 msglen,const u8 * nonce,u16 noncelen,u8 * sig,u16 siglen,gen_hash_alg_type dsa_hash)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 */
dsa_verify(const dsa_pub_key * pub,const u8 * msg,u32 msglen,const u8 * sig,u16 siglen,gen_hash_alg_type dsa_hash)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>
main(int argc,char * argv[])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