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 */ 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 */ 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 */ 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 */ 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 */ 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> 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