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