xref: /freebsd/crypto/libecc/src/examples/sig/dsa/dsa.c (revision 4e62c3cafa4c4e41efd6f87b7fe559cf819cf3e4)
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 */
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