xref: /freebsd/crypto/libecc/src/examples/sig/dsa/dsa.c (revision f0865ec9906d5a18fa2a3b61381f22ce16e606ad)
1*f0865ec9SKyle Evans /*
2*f0865ec9SKyle Evans  *  Copyright (C) 2021 - This file is part of libecc project
3*f0865ec9SKyle Evans  *
4*f0865ec9SKyle Evans  *  Authors:
5*f0865ec9SKyle Evans  *      Ryad BENADJILA <ryadbenadjila@gmail.com>
6*f0865ec9SKyle Evans  *      Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr>
7*f0865ec9SKyle Evans  *
8*f0865ec9SKyle Evans  *  This software is licensed under a dual BSD and GPL v2 license.
9*f0865ec9SKyle Evans  *  See LICENSE file at the root folder of the project.
10*f0865ec9SKyle Evans  */
11*f0865ec9SKyle Evans #include "dsa.h"
12*f0865ec9SKyle Evans 
13*f0865ec9SKyle Evans 
14*f0865ec9SKyle Evans /* We include the rand external dependency because we have to generate
15*f0865ec9SKyle Evans  * some random data for the nonces.
16*f0865ec9SKyle Evans  */
17*f0865ec9SKyle Evans #include <libecc/external_deps/rand.h>
18*f0865ec9SKyle Evans /* We include the printf external dependency for printf output */
19*f0865ec9SKyle Evans #include <libecc/external_deps/print.h>
20*f0865ec9SKyle Evans /* We include our common helpers */
21*f0865ec9SKyle Evans #include "../common/common.h"
22*f0865ec9SKyle Evans 
23*f0865ec9SKyle Evans /*
24*f0865ec9SKyle Evans  * The purpose of this example is to implement the DSA
25*f0865ec9SKyle Evans  * related algorithms as per FIPS 186-4 based on libecc arithmetic
26*f0865ec9SKyle Evans  * primitives.
27*f0865ec9SKyle Evans  *
28*f0865ec9SKyle Evans  * XXX: Please be aware that libecc has been designed for Elliptic
29*f0865ec9SKyle Evans  * Curve cryptography, and as so the arithmetic primitives are
30*f0865ec9SKyle Evans  * not optimized for big numbers >= 1024 bits usually used for DSA.
31*f0865ec9SKyle Evans  * Additionnaly, a hard limit of our NN values makes it impossible
32*f0865ec9SKyle Evans  * to exceed ~5300 bits in the best case (words of size 64 bits).
33*f0865ec9SKyle Evans  *
34*f0865ec9SKyle Evans  * All in all, please see this as a proof of concept of implementing
35*f0865ec9SKyle Evans  * FIPS 186-4 rather than a production code. Use it at your own risk!
36*f0865ec9SKyle Evans  *
37*f0865ec9SKyle Evans  * !! DISCLAIMER !!
38*f0865ec9SKyle Evans  * ================
39*f0865ec9SKyle Evans  *
40*f0865ec9SKyle Evans  * Althoug some efforts have been made to secure this implementation
41*f0865ec9SKyle Evans  * of DSA (e.g. by protecting the private key and nonces using constant
42*f0865ec9SKyle Evans  * time and blinding WHEN activated with BLINDING=1), please consider this
43*f0865ec9SKyle Evans  * code as a proof of concept and use it at your own risk.
44*f0865ec9SKyle Evans  *
45*f0865ec9SKyle Evans  * All-in-all, this piece of code can be useful in some contexts, or risky to
46*f0865ec9SKyle Evans  * use in other sensitive ones where advanced side-channels or fault attacks
47*f0865ec9SKyle Evans  * have to be considered. Use this DSA code knowingly and at your own risk!
48*f0865ec9SKyle Evans  *
49*f0865ec9SKyle Evans  */
50*f0865ec9SKyle Evans 
51*f0865ec9SKyle Evans 
52*f0865ec9SKyle Evans /* 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*f0865ec9SKyle Evans int dsa_import_priv_key(dsa_priv_key *priv, const u8 *p, u16 plen,
54*f0865ec9SKyle Evans 			const u8 *q, u16 qlen,
55*f0865ec9SKyle Evans 			const u8 *g, u16 glen,
56*f0865ec9SKyle Evans 			const u8 *x, u16 xlen)
57*f0865ec9SKyle Evans {
58*f0865ec9SKyle Evans 	int ret, cmp;
59*f0865ec9SKyle Evans 
60*f0865ec9SKyle Evans 	/* Sanity checks */
61*f0865ec9SKyle Evans 	MUST_HAVE((priv != NULL), ret, err);
62*f0865ec9SKyle Evans 	MUST_HAVE((p != NULL) && (q != NULL) && (g != NULL) && (x != NULL), ret, err);
63*f0865ec9SKyle Evans 
64*f0865ec9SKyle Evans 	/* Import our big numbers */
65*f0865ec9SKyle Evans 	ret = _os2ip(&(priv->p), p, plen); EG(ret, err);
66*f0865ec9SKyle Evans 	ret = _os2ip(&(priv->q), q, qlen); EG(ret, err);
67*f0865ec9SKyle Evans 	ret = _os2ip(&(priv->g), g, glen); EG(ret, err);
68*f0865ec9SKyle Evans 	ret = _os2ip(&(priv->x), x, xlen); EG(ret, err);
69*f0865ec9SKyle Evans 
70*f0865ec9SKyle Evans 	/* Sanity check that q < p */
71*f0865ec9SKyle Evans 	ret = nn_cmp(&(priv->q), &(priv->p), &cmp); EG(ret, err);
72*f0865ec9SKyle Evans 	MUST_HAVE((cmp < 0), ret, err);
73*f0865ec9SKyle Evans 	/* Sanity check that g < p */
74*f0865ec9SKyle Evans 	ret = nn_cmp(&(priv->g), &(priv->p), &cmp); EG(ret, err);
75*f0865ec9SKyle Evans 	MUST_HAVE((cmp < 0), ret, err);
76*f0865ec9SKyle Evans 	/* Sanity check that x < q */
77*f0865ec9SKyle Evans 	ret = nn_cmp(&(priv->x), &(priv->q), &cmp); EG(ret, err);
78*f0865ec9SKyle Evans 	MUST_HAVE((cmp < 0), ret, err);
79*f0865ec9SKyle Evans 
80*f0865ec9SKyle Evans err:
81*f0865ec9SKyle Evans 	if(ret && (priv != NULL)){
82*f0865ec9SKyle Evans 		IGNORE_RET_VAL(local_memset(priv, 0, sizeof(dsa_priv_key)));
83*f0865ec9SKyle Evans 	}
84*f0865ec9SKyle Evans 
85*f0865ec9SKyle Evans 	return ret;
86*f0865ec9SKyle Evans }
87*f0865ec9SKyle Evans 
88*f0865ec9SKyle Evans /* 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*f0865ec9SKyle Evans int dsa_import_pub_key(dsa_pub_key *pub, const u8 *p, u16 plen,
90*f0865ec9SKyle Evans 			const u8 *q, u16 qlen,
91*f0865ec9SKyle Evans 			const u8 *g, u16 glen,
92*f0865ec9SKyle Evans 			const u8 *y, u16 ylen)
93*f0865ec9SKyle Evans {
94*f0865ec9SKyle Evans 	int ret, cmp;
95*f0865ec9SKyle Evans 
96*f0865ec9SKyle Evans 	/* Sanity checks */
97*f0865ec9SKyle Evans 	MUST_HAVE((pub != NULL), ret, err);
98*f0865ec9SKyle Evans 	MUST_HAVE((p != NULL) && (q != NULL) && (g != NULL) && (y != NULL), ret, err);
99*f0865ec9SKyle Evans 
100*f0865ec9SKyle Evans 	/* Import our big numbers */
101*f0865ec9SKyle Evans 	ret = _os2ip(&(pub->p), p, plen); EG(ret, err);
102*f0865ec9SKyle Evans 	ret = _os2ip(&(pub->q), q, qlen); EG(ret, err);
103*f0865ec9SKyle Evans 	ret = _os2ip(&(pub->g), g, glen); EG(ret, err);
104*f0865ec9SKyle Evans 	ret = _os2ip(&(pub->y), y, ylen); EG(ret, err);
105*f0865ec9SKyle Evans 
106*f0865ec9SKyle Evans 	/* Sanity check that q < p */
107*f0865ec9SKyle Evans 	ret = nn_cmp(&(pub->q), &(pub->p), &cmp); EG(ret, err);
108*f0865ec9SKyle Evans 	MUST_HAVE((cmp < 0), ret, err);
109*f0865ec9SKyle Evans 	/* Sanity check that g < p */
110*f0865ec9SKyle Evans 	ret = nn_cmp(&(pub->g), &(pub->p), &cmp); EG(ret, err);
111*f0865ec9SKyle Evans 	MUST_HAVE((cmp < 0), ret, err);
112*f0865ec9SKyle Evans 	/* Sanity check that y < p */
113*f0865ec9SKyle Evans 	ret = nn_cmp(&(pub->y), &(pub->p), &cmp); EG(ret, err);
114*f0865ec9SKyle Evans 	MUST_HAVE((cmp < 0), ret, err);
115*f0865ec9SKyle Evans 
116*f0865ec9SKyle Evans err:
117*f0865ec9SKyle Evans 	if(ret && (pub != NULL)){
118*f0865ec9SKyle Evans 		IGNORE_RET_VAL(local_memset(pub, 0, sizeof(dsa_pub_key)));
119*f0865ec9SKyle Evans 	}
120*f0865ec9SKyle Evans 
121*f0865ec9SKyle Evans 	return ret;
122*f0865ec9SKyle Evans }
123*f0865ec9SKyle Evans 
124*f0865ec9SKyle Evans 
125*f0865ec9SKyle Evans 
126*f0865ec9SKyle Evans /* Compute a DSA public key from a private key.
127*f0865ec9SKyle Evans  * The public key is computed using modular exponentiation of the generator
128*f0865ec9SKyle Evans  * with the private key.
129*f0865ec9SKyle Evans  */
dsa_compute_pub_from_priv(dsa_pub_key * pub,const dsa_priv_key * priv)130*f0865ec9SKyle Evans int dsa_compute_pub_from_priv(dsa_pub_key *pub, const dsa_priv_key *priv)
131*f0865ec9SKyle Evans {
132*f0865ec9SKyle Evans 	int ret, cmp;
133*f0865ec9SKyle Evans 	nn_src_t p, q, g, x;
134*f0865ec9SKyle Evans 	nn x_;
135*f0865ec9SKyle Evans 	x_.magic = WORD(0);
136*f0865ec9SKyle Evans 
137*f0865ec9SKyle Evans 	MUST_HAVE((pub != NULL) && (priv != NULL), ret, err);
138*f0865ec9SKyle Evans 
139*f0865ec9SKyle Evans 	/* Make things more readable */
140*f0865ec9SKyle Evans 	p = &(priv->p);
141*f0865ec9SKyle Evans 	q = &(priv->q);
142*f0865ec9SKyle Evans 	g = &(priv->g);
143*f0865ec9SKyle Evans 	x = &(priv->x);
144*f0865ec9SKyle Evans 
145*f0865ec9SKyle Evans 	/* Sanity checks */
146*f0865ec9SKyle Evans 	ret = nn_check_initialized(p); EG(ret, err);
147*f0865ec9SKyle Evans 	ret = nn_check_initialized(q); EG(ret, err);
148*f0865ec9SKyle Evans 	ret = nn_check_initialized(g); EG(ret, err);
149*f0865ec9SKyle Evans 	ret = nn_check_initialized(x); EG(ret, err);
150*f0865ec9SKyle Evans 
151*f0865ec9SKyle Evans 	/* Sanity check that q < p */
152*f0865ec9SKyle Evans 	ret = nn_cmp(&(priv->q), &(priv->p), &cmp); EG(ret, err);
153*f0865ec9SKyle Evans 	MUST_HAVE((cmp < 0), ret, err);
154*f0865ec9SKyle Evans 	/* Sanity check that g < p */
155*f0865ec9SKyle Evans 	ret = nn_cmp(&(priv->g), &(priv->p), &cmp); EG(ret, err);
156*f0865ec9SKyle Evans 	MUST_HAVE((cmp < 0), ret, err);
157*f0865ec9SKyle Evans 	/* Sanity check that x < q */
158*f0865ec9SKyle Evans 	ret = nn_cmp(&(priv->x), &(priv->q), &cmp); EG(ret, err);
159*f0865ec9SKyle Evans 	MUST_HAVE((cmp < 0), ret, err);
160*f0865ec9SKyle Evans 
161*f0865ec9SKyle Evans 	ret = nn_init(&x_, 0); EG(ret, err);
162*f0865ec9SKyle Evans 	/* Blind the private key in all cases as this is a
163*f0865ec9SKyle Evans 	 * sensitive value.
164*f0865ec9SKyle Evans 	 */
165*f0865ec9SKyle Evans 	ret = _blind_scalar(x, q, &x_); EG(ret, err);
166*f0865ec9SKyle Evans 	ret = _fix_scalar_msb(&x_, q, &x_); EG(ret, err);
167*f0865ec9SKyle Evans 
168*f0865ec9SKyle Evans 	/* Perform the exponentiation y = g**x mod (p) */
169*f0865ec9SKyle Evans 	ret = nn_mod_pow(&(pub->y), g, &x_, p); EG(ret, err);
170*f0865ec9SKyle Evans 
171*f0865ec9SKyle Evans 	/* Initialize the public key */
172*f0865ec9SKyle Evans 	ret = nn_copy(&(pub->p), p); EG(ret, err);
173*f0865ec9SKyle Evans 	ret = nn_copy(&(pub->q), q); EG(ret, err);
174*f0865ec9SKyle Evans 	ret = nn_copy(&(pub->g), g);
175*f0865ec9SKyle Evans 
176*f0865ec9SKyle Evans err:
177*f0865ec9SKyle Evans 	if(ret && (pub != NULL)){
178*f0865ec9SKyle Evans 		IGNORE_RET_VAL(local_memset(pub, 0, sizeof(dsa_pub_key)));
179*f0865ec9SKyle Evans 	}
180*f0865ec9SKyle Evans 
181*f0865ec9SKyle Evans 	nn_uninit(&x_);
182*f0865ec9SKyle Evans 
183*f0865ec9SKyle Evans 	PTR_NULLIFY(p);
184*f0865ec9SKyle Evans 	PTR_NULLIFY(q);
185*f0865ec9SKyle Evans 	PTR_NULLIFY(g);
186*f0865ec9SKyle Evans 	PTR_NULLIFY(x);
187*f0865ec9SKyle Evans 
188*f0865ec9SKyle Evans 	return ret;
189*f0865ec9SKyle Evans }
190*f0865ec9SKyle Evans 
191*f0865ec9SKyle Evans /* Generate a DSA signature
192*f0865ec9SKyle Evans  * This implements "DSA Signature Generation" in section 4.6 of FIPS 186-4.
193*f0865ec9SKyle Evans  */
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*f0865ec9SKyle Evans int dsa_sign(const dsa_priv_key *priv, const u8 *msg, u32 msglen,
195*f0865ec9SKyle Evans 	     const u8 *nonce, u16 noncelen,
196*f0865ec9SKyle Evans 	     u8 *sig, u16 siglen, gen_hash_alg_type dsa_hash)
197*f0865ec9SKyle Evans {
198*f0865ec9SKyle Evans 	int ret, iszero;
199*f0865ec9SKyle Evans 	/* N is the bit length of q */
200*f0865ec9SKyle Evans 	bitcnt_t N, rshift;
201*f0865ec9SKyle Evans 	/* Length of the hash function */
202*f0865ec9SKyle Evans 	u8 hlen, block_size;
203*f0865ec9SKyle Evans 	nn_src_t p, q, g, x;
204*f0865ec9SKyle Evans 	/* The nonce, it inverse and its protected version */
205*f0865ec9SKyle Evans 	nn k, kinv, k_;
206*f0865ec9SKyle Evans 	/* r, s and z */
207*f0865ec9SKyle Evans 	nn r, s, z;
208*f0865ec9SKyle Evans 	/* Hash */
209*f0865ec9SKyle Evans 	u8 hash[MAX_DIGEST_SIZE];
210*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING
211*f0865ec9SKyle Evans 	/* b is the blinding mask */
212*f0865ec9SKyle Evans 	nn b;
213*f0865ec9SKyle Evans 	b.magic = WORD(0);
214*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */
215*f0865ec9SKyle Evans 	k.magic = kinv.magic = k_.magic = r.magic = s.magic = z.magic = WORD(0);
216*f0865ec9SKyle Evans 
217*f0865ec9SKyle Evans 	/* Sanity checks */
218*f0865ec9SKyle Evans 	MUST_HAVE((priv != NULL) && (msg != NULL) && (sig != NULL), ret, err);
219*f0865ec9SKyle Evans 
220*f0865ec9SKyle Evans 	ret = local_memset(hash, 0, sizeof(hash)); EG(ret, err);
221*f0865ec9SKyle Evans 
222*f0865ec9SKyle Evans 	/* Make things more readable */
223*f0865ec9SKyle Evans 	p = &(priv->p);
224*f0865ec9SKyle Evans 	q = &(priv->q);
225*f0865ec9SKyle Evans 	g = &(priv->g);
226*f0865ec9SKyle Evans 	x = &(priv->x);
227*f0865ec9SKyle Evans 
228*f0865ec9SKyle Evans 	/* Sanity checks */
229*f0865ec9SKyle Evans 	ret = nn_check_initialized(p); EG(ret, err);
230*f0865ec9SKyle Evans 	ret = nn_check_initialized(q); EG(ret, err);
231*f0865ec9SKyle Evans 	ret = nn_check_initialized(g); EG(ret, err);
232*f0865ec9SKyle Evans 	ret = nn_check_initialized(x); EG(ret, err);
233*f0865ec9SKyle Evans 
234*f0865ec9SKyle Evans 	/* Let N be the bit length of q. Let min(N, outlen) denote the minimum
235*f0865ec9SKyle Evans 	 * of the positive integers N and outlen, where outlen is the bit length
236*f0865ec9SKyle Evans 	 * of the hash function output block.
237*f0865ec9SKyle Evans 	 */
238*f0865ec9SKyle Evans 	ret = nn_bitlen(q, &N); EG(ret, err);
239*f0865ec9SKyle Evans 	ret = gen_hash_get_hash_sizes(dsa_hash, &hlen, &block_size); EG(ret, err);
240*f0865ec9SKyle Evans 	MUST_HAVE((hlen <= MAX_DIGEST_SIZE), ret, err);
241*f0865ec9SKyle Evans 
242*f0865ec9SKyle Evans 	/* Sanity check on the signature length */
243*f0865ec9SKyle Evans 	MUST_HAVE((siglen == (2 * BYTECEIL(N))), ret, err);
244*f0865ec9SKyle Evans 
245*f0865ec9SKyle Evans restart:
246*f0865ec9SKyle Evans 	/* If the nonce is imposed, use it. Else get a random modulo q */
247*f0865ec9SKyle Evans 	if(nonce != NULL){
248*f0865ec9SKyle Evans 		ret = _os2ip(&k, nonce, noncelen); EG(ret, err);
249*f0865ec9SKyle Evans 	}
250*f0865ec9SKyle Evans 	else{
251*f0865ec9SKyle Evans 		ret = nn_get_random_mod(&k, q); EG(ret, err);
252*f0865ec9SKyle Evans 	}
253*f0865ec9SKyle Evans 
254*f0865ec9SKyle Evans 	/* Fix the MSB of our scalar */
255*f0865ec9SKyle Evans 	ret = nn_copy(&k_, &k); EG(ret, err);
256*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING
257*f0865ec9SKyle Evans 	/* Blind the scalar */
258*f0865ec9SKyle Evans 	ret = _blind_scalar(&k_, q, &k_); EG(ret, err);
259*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */
260*f0865ec9SKyle Evans 	ret = _fix_scalar_msb(&k_, q, &k_); EG(ret, err);
261*f0865ec9SKyle Evans 	/* r = (g**k mod p) mod q */
262*f0865ec9SKyle Evans 	ret = nn_init(&r, 0); EG(ret, err);
263*f0865ec9SKyle Evans 	/* Exponentiation modulo p */
264*f0865ec9SKyle Evans 	ret = nn_mod_pow(&r, g, &k_, p); EG(ret, err);
265*f0865ec9SKyle Evans 	/* Modulo q */
266*f0865ec9SKyle Evans 	ret = nn_mod(&r, &r, q); EG(ret, err);
267*f0865ec9SKyle Evans 
268*f0865ec9SKyle Evans 	/* If r is 0, restart the process */
269*f0865ec9SKyle Evans 	ret = nn_iszero(&r, &iszero); EG(ret, err);
270*f0865ec9SKyle Evans 	if (iszero) {
271*f0865ec9SKyle Evans 		goto restart;
272*f0865ec9SKyle Evans  	}
273*f0865ec9SKyle Evans 
274*f0865ec9SKyle Evans 	/* Export r */
275*f0865ec9SKyle Evans 	ret = _i2osp(&r, sig, (siglen / 2)); EG(ret, err);
276*f0865ec9SKyle Evans 
277*f0865ec9SKyle Evans 	/* Compute the hash */
278*f0865ec9SKyle Evans 	ret = gen_hash_hfunc(msg, msglen, hash, dsa_hash); EG(ret, err);
279*f0865ec9SKyle Evans 	/* z = the leftmost min(N, outlen) bits of Hash(M) */
280*f0865ec9SKyle Evans         rshift = 0;
281*f0865ec9SKyle Evans         if ((hlen * 8) > N) {
282*f0865ec9SKyle Evans                 rshift = (bitcnt_t)((hlen * 8) - N);
283*f0865ec9SKyle Evans         }
284*f0865ec9SKyle Evans 	ret = _os2ip(&z, hash, hlen); EG(ret, err);
285*f0865ec9SKyle Evans 	if (rshift) {
286*f0865ec9SKyle Evans 		ret = nn_rshift_fixedlen(&z, &z, rshift); EG(ret, err);
287*f0865ec9SKyle Evans 	}
288*f0865ec9SKyle Evans 	ret = nn_mod(&z, &z, q); EG(ret, err);
289*f0865ec9SKyle Evans 
290*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING
291*f0865ec9SKyle Evans 	/* Note: if we use blinding, r and e are multiplied by
292*f0865ec9SKyle Evans 	 * a random value b in ]0,q[ */
293*f0865ec9SKyle Evans 	ret = nn_get_random_mod(&b, q); EG(ret, err);
294*f0865ec9SKyle Evans         /* Blind r with b */
295*f0865ec9SKyle Evans         ret = nn_mod_mul(&r, &r, &b, q); EG(ret, err);
296*f0865ec9SKyle Evans         /* Blind the message z */
297*f0865ec9SKyle Evans         ret = nn_mod_mul(&z, &z, &b, q); EG(ret, err);
298*f0865ec9SKyle Evans         /*
299*f0865ec9SKyle Evans          * In case of blinding, we compute (b*k)^-1, and b^-1 will
300*f0865ec9SKyle Evans          * automatically unblind (r*x) in the following.
301*f0865ec9SKyle Evans          */
302*f0865ec9SKyle Evans         ret = nn_mod_mul(&k, &k, &b, q); EG(ret, err);
303*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */
304*f0865ec9SKyle Evans 
305*f0865ec9SKyle Evans 	/* Compute s = k^-1 * (xr + z) mod q  */
306*f0865ec9SKyle Evans         /* Compute k^-1 mod q */
307*f0865ec9SKyle Evans         /* NOTE: we use Fermat's little theorem inversion for
308*f0865ec9SKyle Evans          * constant time here. This is possible since q is prime.
309*f0865ec9SKyle Evans          */
310*f0865ec9SKyle Evans         ret = nn_modinv_fermat(&kinv, &k, q); EG(ret, err);
311*f0865ec9SKyle Evans 	ret = nn_mod_mul(&s, &r, x, q); EG(ret, err);
312*f0865ec9SKyle Evans 	ret = nn_mod_add(&s, &s, &z, q); EG(ret, err);
313*f0865ec9SKyle Evans 	ret = nn_mod_mul(&s, &kinv, &s, q); EG(ret, err);
314*f0865ec9SKyle Evans 
315*f0865ec9SKyle Evans 	/* If s is 0, restart the process */
316*f0865ec9SKyle Evans 	ret = nn_iszero(&s, &iszero); EG(ret, err);
317*f0865ec9SKyle Evans 	if (iszero) {
318*f0865ec9SKyle Evans 		goto restart;
319*f0865ec9SKyle Evans  	}
320*f0865ec9SKyle Evans 
321*f0865ec9SKyle Evans 	/* Export s */
322*f0865ec9SKyle Evans 	ret = _i2osp(&s, sig + (siglen / 2), (siglen / 2));
323*f0865ec9SKyle Evans 
324*f0865ec9SKyle Evans err:
325*f0865ec9SKyle Evans 	if(ret && (sig != NULL)){
326*f0865ec9SKyle Evans 		IGNORE_RET_VAL(local_memset(sig, 0, siglen));
327*f0865ec9SKyle Evans 	}
328*f0865ec9SKyle Evans 
329*f0865ec9SKyle Evans 	nn_uninit(&k);
330*f0865ec9SKyle Evans 	nn_uninit(&kinv);
331*f0865ec9SKyle Evans 	nn_uninit(&k_);
332*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING
333*f0865ec9SKyle Evans 	nn_uninit(&b);
334*f0865ec9SKyle Evans #endif
335*f0865ec9SKyle Evans 	nn_uninit(&r);
336*f0865ec9SKyle Evans 	nn_uninit(&s);
337*f0865ec9SKyle Evans 	nn_uninit(&z);
338*f0865ec9SKyle Evans 
339*f0865ec9SKyle Evans 	PTR_NULLIFY(p);
340*f0865ec9SKyle Evans 	PTR_NULLIFY(q);
341*f0865ec9SKyle Evans 	PTR_NULLIFY(g);
342*f0865ec9SKyle Evans 	PTR_NULLIFY(x);
343*f0865ec9SKyle Evans 
344*f0865ec9SKyle Evans 	return ret;
345*f0865ec9SKyle Evans }
346*f0865ec9SKyle Evans 
347*f0865ec9SKyle Evans 
348*f0865ec9SKyle Evans 
349*f0865ec9SKyle Evans /* Verify a DSA signature
350*f0865ec9SKyle Evans  * This implements "DSA Signature Verification and Validation" in section 4.7 of FIPS 186-4.
351*f0865ec9SKyle Evans  */
dsa_verify(const dsa_pub_key * pub,const u8 * msg,u32 msglen,const u8 * sig,u16 siglen,gen_hash_alg_type dsa_hash)352*f0865ec9SKyle Evans int dsa_verify(const dsa_pub_key *pub, const u8 *msg, u32 msglen,
353*f0865ec9SKyle Evans 	     const u8 *sig, u16 siglen, gen_hash_alg_type dsa_hash)
354*f0865ec9SKyle Evans {
355*f0865ec9SKyle Evans 	int ret, iszero, cmp;
356*f0865ec9SKyle Evans 	/* N is the bit length of q */
357*f0865ec9SKyle Evans 	bitcnt_t N, rshift;
358*f0865ec9SKyle Evans 	/* Length of the hash function */
359*f0865ec9SKyle Evans 	u8 hlen, block_size;
360*f0865ec9SKyle Evans 	nn_src_t p, q, g, y;
361*f0865ec9SKyle Evans 	/* r, s */
362*f0865ec9SKyle Evans 	nn r, s, z;
363*f0865ec9SKyle Evans 	/* u1, u2, and v */
364*f0865ec9SKyle Evans 	nn u1, u2, v;
365*f0865ec9SKyle Evans 	/* Hash */
366*f0865ec9SKyle Evans 	u8 hash[MAX_DIGEST_SIZE];
367*f0865ec9SKyle Evans 	r.magic = s.magic = z.magic = u1.magic = u2.magic = WORD(0);
368*f0865ec9SKyle Evans 
369*f0865ec9SKyle Evans 	/* Sanity checks */
370*f0865ec9SKyle Evans 	MUST_HAVE((pub != NULL) && (msg != NULL) && (sig != NULL), ret, err);
371*f0865ec9SKyle Evans 
372*f0865ec9SKyle Evans 	ret = local_memset(hash, 0, sizeof(hash)); EG(ret, err);
373*f0865ec9SKyle Evans 
374*f0865ec9SKyle Evans 	/* Make things more readable */
375*f0865ec9SKyle Evans 	p = &(pub->p);
376*f0865ec9SKyle Evans 	q = &(pub->q);
377*f0865ec9SKyle Evans 	g = &(pub->g);
378*f0865ec9SKyle Evans 	y = &(pub->y);
379*f0865ec9SKyle Evans 
380*f0865ec9SKyle Evans 	/* Sanity checks */
381*f0865ec9SKyle Evans 	ret = nn_check_initialized(p); EG(ret, err);
382*f0865ec9SKyle Evans 	ret = nn_check_initialized(q); EG(ret, err);
383*f0865ec9SKyle Evans 	ret = nn_check_initialized(g); EG(ret, err);
384*f0865ec9SKyle Evans 	ret = nn_check_initialized(y); EG(ret, err);
385*f0865ec9SKyle Evans 
386*f0865ec9SKyle Evans 	/* Sanity check on the signature length */
387*f0865ec9SKyle Evans 	ret = nn_bitlen(q, &N); EG(ret, err);
388*f0865ec9SKyle Evans 	MUST_HAVE((siglen == (2 * BYTECEIL(N))), ret, err);
389*f0865ec9SKyle Evans 
390*f0865ec9SKyle Evans 	/* Extract r and s */
391*f0865ec9SKyle Evans 	ret = _os2ip(&r, sig, (siglen / 2)); EG(ret, err);
392*f0865ec9SKyle Evans 	ret = _os2ip(&s, sig + (siglen / 2), (siglen / 2)); EG(ret, err);
393*f0865ec9SKyle Evans 
394*f0865ec9SKyle Evans 	/* Return an error if r = 0 or s = 0 */
395*f0865ec9SKyle Evans 	ret = nn_iszero(&r, &iszero); EG(ret, err);
396*f0865ec9SKyle Evans 	MUST_HAVE((!iszero), ret, err);
397*f0865ec9SKyle Evans 	ret = nn_iszero(&s, &iszero); EG(ret, err);
398*f0865ec9SKyle Evans 	MUST_HAVE((!iszero), ret, err);
399*f0865ec9SKyle Evans 	/* Check thatt 0 < r′ < q and 0 < s′ < q */
400*f0865ec9SKyle Evans 	ret = nn_cmp(&r, q, &cmp); EG(ret, err);
401*f0865ec9SKyle Evans 	MUST_HAVE((cmp < 0), ret, err);
402*f0865ec9SKyle Evans 	ret = nn_cmp(&s, q, &cmp); EG(ret, err);
403*f0865ec9SKyle Evans 	MUST_HAVE((cmp < 0), ret, err);
404*f0865ec9SKyle Evans 
405*f0865ec9SKyle Evans 	/* Compute the hash */
406*f0865ec9SKyle Evans 	ret = gen_hash_get_hash_sizes(dsa_hash, &hlen, &block_size); EG(ret, err);
407*f0865ec9SKyle Evans 	MUST_HAVE((hlen <= MAX_DIGEST_SIZE), ret, err);
408*f0865ec9SKyle Evans 	ret = gen_hash_hfunc(msg, msglen, hash, dsa_hash); EG(ret, err);
409*f0865ec9SKyle Evans 	/* z = the leftmost min(N, outlen) bits of Hash(M) */
410*f0865ec9SKyle Evans         rshift = 0;
411*f0865ec9SKyle Evans         if ((hlen * 8) > N) {
412*f0865ec9SKyle Evans                 rshift = (bitcnt_t)((hlen * 8) - N);
413*f0865ec9SKyle Evans         }
414*f0865ec9SKyle Evans 	ret = _os2ip(&z, hash, hlen); EG(ret, err);
415*f0865ec9SKyle Evans 	if (rshift) {
416*f0865ec9SKyle Evans 		ret = nn_rshift_fixedlen(&z, &z, rshift); EG(ret, err);
417*f0865ec9SKyle Evans 	}
418*f0865ec9SKyle Evans 	ret = nn_mod(&z, &z, q); EG(ret, err);
419*f0865ec9SKyle Evans 
420*f0865ec9SKyle Evans 	/* Compute w = s**-1 mod (q) in s */
421*f0865ec9SKyle Evans         ret = nn_modinv(&s, &s, q); EG(ret, err);
422*f0865ec9SKyle Evans 
423*f0865ec9SKyle Evans 	/* u1 = (zw) mod q */
424*f0865ec9SKyle Evans 	ret = nn_mod_mul(&u1, &z, &s, q); EG(ret, err);
425*f0865ec9SKyle Evans 	/* u2 = ((r′)w) mod q */
426*f0865ec9SKyle Evans 	ret = nn_mod_mul(&u2, &r, &s, q); EG(ret, err);
427*f0865ec9SKyle Evans 	/* Now compute v = = ((g**u1 y**u2) mod p) mod q */
428*f0865ec9SKyle Evans 	/* NOTE: no need to use a secure exponentiation here as we only
429*f0865ec9SKyle Evans 	 * manipulate public data.
430*f0865ec9SKyle Evans 	 */
431*f0865ec9SKyle Evans 	ret = _nn_mod_pow_insecure(&v, g, &u1, p); EG(ret, err);
432*f0865ec9SKyle Evans 	ret = _nn_mod_pow_insecure(&s, y, &u2, p); EG(ret, err);
433*f0865ec9SKyle Evans 	ret = nn_mod_mul(&v, &v, &s, p); EG(ret, err);
434*f0865ec9SKyle Evans 	ret = nn_mod(&v, &v, q); EG(ret, err);
435*f0865ec9SKyle Evans 
436*f0865ec9SKyle Evans 	/* Check that v = r */
437*f0865ec9SKyle Evans 	ret = nn_cmp(&v, &r, &cmp); EG(ret, err);
438*f0865ec9SKyle Evans 	ret = (cmp != 0) ? -1 : 0;
439*f0865ec9SKyle Evans 
440*f0865ec9SKyle Evans err:
441*f0865ec9SKyle Evans 	nn_uninit(&r);
442*f0865ec9SKyle Evans 	nn_uninit(&s);
443*f0865ec9SKyle Evans 	nn_uninit(&z);
444*f0865ec9SKyle Evans 	nn_uninit(&u1);
445*f0865ec9SKyle Evans 	nn_uninit(&u2);
446*f0865ec9SKyle Evans 	nn_uninit(&v);
447*f0865ec9SKyle Evans 
448*f0865ec9SKyle Evans 	PTR_NULLIFY(p);
449*f0865ec9SKyle Evans 	PTR_NULLIFY(q);
450*f0865ec9SKyle Evans 	PTR_NULLIFY(g);
451*f0865ec9SKyle Evans 	PTR_NULLIFY(y);
452*f0865ec9SKyle Evans 
453*f0865ec9SKyle Evans 	return ret;
454*f0865ec9SKyle Evans }
455*f0865ec9SKyle Evans 
456*f0865ec9SKyle Evans #ifdef DSA
457*f0865ec9SKyle Evans #include <libecc/utils/print_buf.h>
main(int argc,char * argv[])458*f0865ec9SKyle Evans int main(int argc, char *argv[])
459*f0865ec9SKyle Evans {
460*f0865ec9SKyle Evans  	int ret = 0;
461*f0865ec9SKyle Evans 
462*f0865ec9SKyle Evans 	const u8 p[] = {
463*f0865ec9SKyle Evans 		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*f0865ec9SKyle Evans 		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*f0865ec9SKyle Evans 		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*f0865ec9SKyle Evans 		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*f0865ec9SKyle Evans 		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*f0865ec9SKyle Evans 		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*f0865ec9SKyle Evans 		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*f0865ec9SKyle Evans 		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*f0865ec9SKyle Evans 		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*f0865ec9SKyle Evans 		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*f0865ec9SKyle Evans 		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*f0865ec9SKyle Evans 		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*f0865ec9SKyle Evans 		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*f0865ec9SKyle Evans 		0x8B, 0xC2, 0x5F, 0x3E, 0x94, 0x1F, 0xDD, 0xC6, 0x20, 0x06, 0x89, 0x58, 0x1B, 0xFE, 0xC4, 0x16, 0xB4, 0xB2, 0xCB, 0x73,
477*f0865ec9SKyle Evans 	};
478*f0865ec9SKyle Evans 
479*f0865ec9SKyle Evans 	const u8 q[] = {
480*f0865ec9SKyle Evans 		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*f0865ec9SKyle Evans 		0xFC, 0xCF, 0xB1, 0x1D,
482*f0865ec9SKyle Evans 	};
483*f0865ec9SKyle Evans 
484*f0865ec9SKyle Evans 	const u8 g[] = {
485*f0865ec9SKyle Evans 		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*f0865ec9SKyle Evans 		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*f0865ec9SKyle Evans 		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*f0865ec9SKyle Evans 		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*f0865ec9SKyle Evans 		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*f0865ec9SKyle Evans 		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*f0865ec9SKyle Evans 		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*f0865ec9SKyle Evans 		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*f0865ec9SKyle Evans 		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*f0865ec9SKyle Evans 		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*f0865ec9SKyle Evans 		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*f0865ec9SKyle Evans 		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*f0865ec9SKyle Evans 		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*f0865ec9SKyle Evans 		0xDA, 0x1A, 0xBB, 0xBF, 0xBF, 0x25, 0xCA, 0xE0, 0x5A, 0x13, 0xF8, 0x12, 0xE3, 0x45, 0x63, 0xF9, 0x94, 0x10, 0xE7, 0x3B,
499*f0865ec9SKyle Evans 	};
500*f0865ec9SKyle Evans 
501*f0865ec9SKyle Evans 	const u8 x[] = {
502*f0865ec9SKyle Evans 		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*f0865ec9SKyle Evans 		0x0E, 0xBB, 0x87, 0x64,
504*f0865ec9SKyle Evans 	};
505*f0865ec9SKyle Evans 
506*f0865ec9SKyle Evans 	const u8 y[] = {
507*f0865ec9SKyle Evans 		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*f0865ec9SKyle Evans 	};
509*f0865ec9SKyle Evans 
510*f0865ec9SKyle Evans 	const u8 msg[] = "abc";
511*f0865ec9SKyle Evans 
512*f0865ec9SKyle Evans 	const u8 nonce[] = {
513*f0865ec9SKyle Evans 		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*f0865ec9SKyle Evans 		0xB0, 0x67, 0x8B, 0xEE,
515*f0865ec9SKyle Evans 	};
516*f0865ec9SKyle Evans 
517*f0865ec9SKyle Evans 	dsa_priv_key priv;
518*f0865ec9SKyle Evans 	dsa_pub_key pub;
519*f0865ec9SKyle Evans 	dsa_pub_key pub2;
520*f0865ec9SKyle Evans 	u8 sig[32*2] = { 0 };
521*f0865ec9SKyle Evans 
522*f0865ec9SKyle Evans 	FORCE_USED_VAR(argc);
523*f0865ec9SKyle Evans 	FORCE_USED_VAR(argv);
524*f0865ec9SKyle Evans 
525*f0865ec9SKyle Evans 	/* Sanity check on size for DSA.
526*f0865ec9SKyle Evans 	 * NOTE: the double parentheses are here to handle -Wunreachable-code
527*f0865ec9SKyle Evans 	 */
528*f0865ec9SKyle Evans 	if((NN_USABLE_MAX_BIT_LEN) < (4096)){
529*f0865ec9SKyle Evans 		ext_printf("Error: you seem to have compiled libecc with usable NN size < 4096, not suitable for DSA.\n");
530*f0865ec9SKyle Evans 		ext_printf("  => Please recompile libecc with EXTRA_CFLAGS=\"-DUSER_NN_BIT_LEN=4096\"\n");
531*f0865ec9SKyle Evans 		ext_printf("     This will increase usable NN for proper DSA up to 4096 bits.\n");
532*f0865ec9SKyle Evans 		ext_printf("     Then recompile the current examples with the same EXTRA_CFLAGS=\"-DUSER_NN_BIT_LEN=4096\" flag and execute again!\n");
533*f0865ec9SKyle Evans 		/* NOTE: ret = 0 here to pass self tests even if the library is not compatible */
534*f0865ec9SKyle Evans 		ret = 0;
535*f0865ec9SKyle Evans 		goto err;
536*f0865ec9SKyle Evans 	}
537*f0865ec9SKyle Evans 
538*f0865ec9SKyle Evans 
539*f0865ec9SKyle Evans 	ret = dsa_import_priv_key(&priv, p, sizeof(p), q, sizeof(q), g, sizeof(g), x, sizeof(x)); EG(ret, err);
540*f0865ec9SKyle Evans 	ret = dsa_import_pub_key(&pub, p, sizeof(p), q, sizeof(q), g, sizeof(g), y, sizeof(y)); EG(ret, err);
541*f0865ec9SKyle Evans 	ret = dsa_compute_pub_from_priv(&pub2, &priv); EG(ret, err);
542*f0865ec9SKyle Evans 
543*f0865ec9SKyle Evans 	nn_print("y", &(pub2.y));
544*f0865ec9SKyle Evans 
545*f0865ec9SKyle Evans 	ret = dsa_sign(&priv, msg, sizeof(msg)-1, nonce, sizeof(nonce), sig, sizeof(sig), HASH_SHA256); EG(ret, err);
546*f0865ec9SKyle Evans 
547*f0865ec9SKyle Evans 	buf_print("sig", sig, sizeof(sig));
548*f0865ec9SKyle Evans 
549*f0865ec9SKyle Evans 	ret = dsa_verify(&pub, msg, sizeof(msg)-1, sig, sizeof(sig), HASH_SHA256);
550*f0865ec9SKyle Evans 	ext_printf("Signature result %d\n", ret);
551*f0865ec9SKyle Evans 
552*f0865ec9SKyle Evans err:
553*f0865ec9SKyle Evans 	return ret;
554*f0865ec9SKyle Evans }
555*f0865ec9SKyle Evans #endif
556