1 /* 2 * Copyright (C) 2021 - This file is part of libecc project 3 * 4 * Authors: 5 * Ryad BENADJILA <ryadbenadjila@gmail.com> 6 * Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr> 7 * 8 * This software is licensed under a dual BSD and GPL v2 license. 9 * See LICENSE file at the root folder of the project. 10 */ 11 #include "dsa.h" 12 13 14 /* We include the rand external dependency because we have to generate 15 * some random data for the nonces. 16 */ 17 #include <libecc/external_deps/rand.h> 18 /* We include the printf external dependency for printf output */ 19 #include <libecc/external_deps/print.h> 20 /* We include our common helpers */ 21 #include "../common/common.h" 22 23 /* 24 * The purpose of this example is to implement the DSA 25 * related algorithms as per FIPS 186-4 based on libecc arithmetic 26 * primitives. 27 * 28 * XXX: Please be aware that libecc has been designed for Elliptic 29 * Curve cryptography, and as so the arithmetic primitives are 30 * not optimized for big numbers >= 1024 bits usually used for DSA. 31 * Additionnaly, a hard limit of our NN values makes it impossible 32 * to exceed ~5300 bits in the best case (words of size 64 bits). 33 * 34 * All in all, please see this as a proof of concept of implementing 35 * FIPS 186-4 rather than a production code. Use it at your own risk! 36 * 37 * !! DISCLAIMER !! 38 * ================ 39 * 40 * Althoug some efforts have been made to secure this implementation 41 * of DSA (e.g. by protecting the private key and nonces using constant 42 * time and blinding WHEN activated with BLINDING=1), please consider this 43 * code as a proof of concept and use it at your own risk. 44 * 45 * All-in-all, this piece of code can be useful in some contexts, or risky to 46 * use in other sensitive ones where advanced side-channels or fault attacks 47 * have to be considered. Use this DSA code knowingly and at your own risk! 48 * 49 */ 50 51 52 /* Import a DSA private key from buffers */ 53 int dsa_import_priv_key(dsa_priv_key *priv, const u8 *p, u16 plen, 54 const u8 *q, u16 qlen, 55 const u8 *g, u16 glen, 56 const u8 *x, u16 xlen) 57 { 58 int ret, cmp; 59 60 /* Sanity checks */ 61 MUST_HAVE((priv != NULL), ret, err); 62 MUST_HAVE((p != NULL) && (q != NULL) && (g != NULL) && (x != NULL), ret, err); 63 64 /* Import our big numbers */ 65 ret = _os2ip(&(priv->p), p, plen); EG(ret, err); 66 ret = _os2ip(&(priv->q), q, qlen); EG(ret, err); 67 ret = _os2ip(&(priv->g), g, glen); EG(ret, err); 68 ret = _os2ip(&(priv->x), x, xlen); EG(ret, err); 69 70 /* Sanity check that q < p */ 71 ret = nn_cmp(&(priv->q), &(priv->p), &cmp); EG(ret, err); 72 MUST_HAVE((cmp < 0), ret, err); 73 /* Sanity check that g < p */ 74 ret = nn_cmp(&(priv->g), &(priv->p), &cmp); EG(ret, err); 75 MUST_HAVE((cmp < 0), ret, err); 76 /* Sanity check that x < q */ 77 ret = nn_cmp(&(priv->x), &(priv->q), &cmp); EG(ret, err); 78 MUST_HAVE((cmp < 0), ret, err); 79 80 err: 81 if(ret && (priv != NULL)){ 82 IGNORE_RET_VAL(local_memset(priv, 0, sizeof(dsa_priv_key))); 83 } 84 85 return ret; 86 } 87 88 /* Import a DSA public key from buffers */ 89 int dsa_import_pub_key(dsa_pub_key *pub, const u8 *p, u16 plen, 90 const u8 *q, u16 qlen, 91 const u8 *g, u16 glen, 92 const u8 *y, u16 ylen) 93 { 94 int ret, cmp; 95 96 /* Sanity checks */ 97 MUST_HAVE((pub != NULL), ret, err); 98 MUST_HAVE((p != NULL) && (q != NULL) && (g != NULL) && (y != NULL), ret, err); 99 100 /* Import our big numbers */ 101 ret = _os2ip(&(pub->p), p, plen); EG(ret, err); 102 ret = _os2ip(&(pub->q), q, qlen); EG(ret, err); 103 ret = _os2ip(&(pub->g), g, glen); EG(ret, err); 104 ret = _os2ip(&(pub->y), y, ylen); EG(ret, err); 105 106 /* Sanity check that q < p */ 107 ret = nn_cmp(&(pub->q), &(pub->p), &cmp); EG(ret, err); 108 MUST_HAVE((cmp < 0), ret, err); 109 /* Sanity check that g < p */ 110 ret = nn_cmp(&(pub->g), &(pub->p), &cmp); EG(ret, err); 111 MUST_HAVE((cmp < 0), ret, err); 112 /* Sanity check that y < p */ 113 ret = nn_cmp(&(pub->y), &(pub->p), &cmp); EG(ret, err); 114 MUST_HAVE((cmp < 0), ret, err); 115 116 err: 117 if(ret && (pub != NULL)){ 118 IGNORE_RET_VAL(local_memset(pub, 0, sizeof(dsa_pub_key))); 119 } 120 121 return ret; 122 } 123 124 125 126 /* Compute a DSA public key from a private key. 127 * The public key is computed using modular exponentiation of the generator 128 * with the private key. 129 */ 130 int dsa_compute_pub_from_priv(dsa_pub_key *pub, const dsa_priv_key *priv) 131 { 132 int ret, cmp; 133 nn_src_t p, q, g, x; 134 nn x_; 135 x_.magic = WORD(0); 136 137 MUST_HAVE((pub != NULL) && (priv != NULL), ret, err); 138 139 /* Make things more readable */ 140 p = &(priv->p); 141 q = &(priv->q); 142 g = &(priv->g); 143 x = &(priv->x); 144 145 /* Sanity checks */ 146 ret = nn_check_initialized(p); EG(ret, err); 147 ret = nn_check_initialized(q); EG(ret, err); 148 ret = nn_check_initialized(g); EG(ret, err); 149 ret = nn_check_initialized(x); EG(ret, err); 150 151 /* Sanity check that q < p */ 152 ret = nn_cmp(&(priv->q), &(priv->p), &cmp); EG(ret, err); 153 MUST_HAVE((cmp < 0), ret, err); 154 /* Sanity check that g < p */ 155 ret = nn_cmp(&(priv->g), &(priv->p), &cmp); EG(ret, err); 156 MUST_HAVE((cmp < 0), ret, err); 157 /* Sanity check that x < q */ 158 ret = nn_cmp(&(priv->x), &(priv->q), &cmp); EG(ret, err); 159 MUST_HAVE((cmp < 0), ret, err); 160 161 ret = nn_init(&x_, 0); EG(ret, err); 162 /* Blind the private key in all cases as this is a 163 * sensitive value. 164 */ 165 ret = _blind_scalar(x, q, &x_); EG(ret, err); 166 ret = _fix_scalar_msb(&x_, q, &x_); EG(ret, err); 167 168 /* Perform the exponentiation y = g**x mod (p) */ 169 ret = nn_mod_pow(&(pub->y), g, &x_, p); EG(ret, err); 170 171 /* Initialize the public key */ 172 ret = nn_copy(&(pub->p), p); EG(ret, err); 173 ret = nn_copy(&(pub->q), q); EG(ret, err); 174 ret = nn_copy(&(pub->g), g); 175 176 err: 177 if(ret && (pub != NULL)){ 178 IGNORE_RET_VAL(local_memset(pub, 0, sizeof(dsa_pub_key))); 179 } 180 181 nn_uninit(&x_); 182 183 PTR_NULLIFY(p); 184 PTR_NULLIFY(q); 185 PTR_NULLIFY(g); 186 PTR_NULLIFY(x); 187 188 return ret; 189 } 190 191 /* Generate a DSA signature 192 * This implements "DSA Signature Generation" in section 4.6 of FIPS 186-4. 193 */ 194 int dsa_sign(const dsa_priv_key *priv, const u8 *msg, u32 msglen, 195 const u8 *nonce, u16 noncelen, 196 u8 *sig, u16 siglen, gen_hash_alg_type dsa_hash) 197 { 198 int ret, iszero; 199 /* N is the bit length of q */ 200 bitcnt_t N, rshift; 201 /* Length of the hash function */ 202 u8 hlen, block_size; 203 nn_src_t p, q, g, x; 204 /* The nonce, it inverse and its protected version */ 205 nn k, kinv, k_; 206 /* r, s and z */ 207 nn r, s, z; 208 /* Hash */ 209 u8 hash[MAX_DIGEST_SIZE]; 210 #ifdef USE_SIG_BLINDING 211 /* b is the blinding mask */ 212 nn b; 213 b.magic = WORD(0); 214 #endif /* USE_SIG_BLINDING */ 215 k.magic = kinv.magic = k_.magic = r.magic = s.magic = z.magic = WORD(0); 216 217 /* Sanity checks */ 218 MUST_HAVE((priv != NULL) && (msg != NULL) && (sig != NULL), ret, err); 219 220 ret = local_memset(hash, 0, sizeof(hash)); EG(ret, err); 221 222 /* Make things more readable */ 223 p = &(priv->p); 224 q = &(priv->q); 225 g = &(priv->g); 226 x = &(priv->x); 227 228 /* Sanity checks */ 229 ret = nn_check_initialized(p); EG(ret, err); 230 ret = nn_check_initialized(q); EG(ret, err); 231 ret = nn_check_initialized(g); EG(ret, err); 232 ret = nn_check_initialized(x); EG(ret, err); 233 234 /* Let N be the bit length of q. Let min(N, outlen) denote the minimum 235 * of the positive integers N and outlen, where outlen is the bit length 236 * of the hash function output block. 237 */ 238 ret = nn_bitlen(q, &N); EG(ret, err); 239 ret = gen_hash_get_hash_sizes(dsa_hash, &hlen, &block_size); EG(ret, err); 240 MUST_HAVE((hlen <= MAX_DIGEST_SIZE), ret, err); 241 242 /* Sanity check on the signature length */ 243 MUST_HAVE((siglen == (2 * BYTECEIL(N))), ret, err); 244 245 restart: 246 /* If the nonce is imposed, use it. Else get a random modulo q */ 247 if(nonce != NULL){ 248 ret = _os2ip(&k, nonce, noncelen); EG(ret, err); 249 } 250 else{ 251 ret = nn_get_random_mod(&k, q); EG(ret, err); 252 } 253 254 /* Fix the MSB of our scalar */ 255 ret = nn_copy(&k_, &k); EG(ret, err); 256 #ifdef USE_SIG_BLINDING 257 /* Blind the scalar */ 258 ret = _blind_scalar(&k_, q, &k_); EG(ret, err); 259 #endif /* USE_SIG_BLINDING */ 260 ret = _fix_scalar_msb(&k_, q, &k_); EG(ret, err); 261 /* r = (g**k mod p) mod q */ 262 ret = nn_init(&r, 0); EG(ret, err); 263 /* Exponentiation modulo p */ 264 ret = nn_mod_pow(&r, g, &k_, p); EG(ret, err); 265 /* Modulo q */ 266 ret = nn_mod(&r, &r, q); EG(ret, err); 267 268 /* If r is 0, restart the process */ 269 ret = nn_iszero(&r, &iszero); EG(ret, err); 270 if (iszero) { 271 goto restart; 272 } 273 274 /* Export r */ 275 ret = _i2osp(&r, sig, (siglen / 2)); EG(ret, err); 276 277 /* Compute the hash */ 278 ret = gen_hash_hfunc(msg, msglen, hash, dsa_hash); EG(ret, err); 279 /* z = the leftmost min(N, outlen) bits of Hash(M) */ 280 rshift = 0; 281 if ((hlen * 8) > N) { 282 rshift = (bitcnt_t)((hlen * 8) - N); 283 } 284 ret = _os2ip(&z, hash, hlen); EG(ret, err); 285 if (rshift) { 286 ret = nn_rshift_fixedlen(&z, &z, rshift); EG(ret, err); 287 } 288 ret = nn_mod(&z, &z, q); EG(ret, err); 289 290 #ifdef USE_SIG_BLINDING 291 /* Note: if we use blinding, r and e are multiplied by 292 * a random value b in ]0,q[ */ 293 ret = nn_get_random_mod(&b, q); EG(ret, err); 294 /* Blind r with b */ 295 ret = nn_mod_mul(&r, &r, &b, q); EG(ret, err); 296 /* Blind the message z */ 297 ret = nn_mod_mul(&z, &z, &b, q); EG(ret, err); 298 /* 299 * In case of blinding, we compute (b*k)^-1, and b^-1 will 300 * automatically unblind (r*x) in the following. 301 */ 302 ret = nn_mod_mul(&k, &k, &b, q); EG(ret, err); 303 #endif /* USE_SIG_BLINDING */ 304 305 /* Compute s = k^-1 * (xr + z) mod q */ 306 /* Compute k^-1 mod q */ 307 /* NOTE: we use Fermat's little theorem inversion for 308 * constant time here. This is possible since q is prime. 309 */ 310 ret = nn_modinv_fermat(&kinv, &k, q); EG(ret, err); 311 ret = nn_mod_mul(&s, &r, x, q); EG(ret, err); 312 ret = nn_mod_add(&s, &s, &z, q); EG(ret, err); 313 ret = nn_mod_mul(&s, &kinv, &s, q); EG(ret, err); 314 315 /* If s is 0, restart the process */ 316 ret = nn_iszero(&s, &iszero); EG(ret, err); 317 if (iszero) { 318 goto restart; 319 } 320 321 /* Export s */ 322 ret = _i2osp(&s, sig + (siglen / 2), (siglen / 2)); 323 324 err: 325 if(ret && (sig != NULL)){ 326 IGNORE_RET_VAL(local_memset(sig, 0, siglen)); 327 } 328 329 nn_uninit(&k); 330 nn_uninit(&kinv); 331 nn_uninit(&k_); 332 #ifdef USE_SIG_BLINDING 333 nn_uninit(&b); 334 #endif 335 nn_uninit(&r); 336 nn_uninit(&s); 337 nn_uninit(&z); 338 339 PTR_NULLIFY(p); 340 PTR_NULLIFY(q); 341 PTR_NULLIFY(g); 342 PTR_NULLIFY(x); 343 344 return ret; 345 } 346 347 348 349 /* Verify a DSA signature 350 * This implements "DSA Signature Verification and Validation" in section 4.7 of FIPS 186-4. 351 */ 352 int dsa_verify(const dsa_pub_key *pub, const u8 *msg, u32 msglen, 353 const u8 *sig, u16 siglen, gen_hash_alg_type dsa_hash) 354 { 355 int ret, iszero, cmp; 356 /* N is the bit length of q */ 357 bitcnt_t N, rshift; 358 /* Length of the hash function */ 359 u8 hlen, block_size; 360 nn_src_t p, q, g, y; 361 /* r, s */ 362 nn r, s, z; 363 /* u1, u2, and v */ 364 nn u1, u2, v; 365 /* Hash */ 366 u8 hash[MAX_DIGEST_SIZE]; 367 r.magic = s.magic = z.magic = u1.magic = u2.magic = WORD(0); 368 369 /* Sanity checks */ 370 MUST_HAVE((pub != NULL) && (msg != NULL) && (sig != NULL), ret, err); 371 372 ret = local_memset(hash, 0, sizeof(hash)); EG(ret, err); 373 374 /* Make things more readable */ 375 p = &(pub->p); 376 q = &(pub->q); 377 g = &(pub->g); 378 y = &(pub->y); 379 380 /* Sanity checks */ 381 ret = nn_check_initialized(p); EG(ret, err); 382 ret = nn_check_initialized(q); EG(ret, err); 383 ret = nn_check_initialized(g); EG(ret, err); 384 ret = nn_check_initialized(y); EG(ret, err); 385 386 /* Sanity check on the signature length */ 387 ret = nn_bitlen(q, &N); EG(ret, err); 388 MUST_HAVE((siglen == (2 * BYTECEIL(N))), ret, err); 389 390 /* Extract r and s */ 391 ret = _os2ip(&r, sig, (siglen / 2)); EG(ret, err); 392 ret = _os2ip(&s, sig + (siglen / 2), (siglen / 2)); EG(ret, err); 393 394 /* Return an error if r = 0 or s = 0 */ 395 ret = nn_iszero(&r, &iszero); EG(ret, err); 396 MUST_HAVE((!iszero), ret, err); 397 ret = nn_iszero(&s, &iszero); EG(ret, err); 398 MUST_HAVE((!iszero), ret, err); 399 /* Check thatt 0 < r′ < q and 0 < s′ < q */ 400 ret = nn_cmp(&r, q, &cmp); EG(ret, err); 401 MUST_HAVE((cmp < 0), ret, err); 402 ret = nn_cmp(&s, q, &cmp); EG(ret, err); 403 MUST_HAVE((cmp < 0), ret, err); 404 405 /* Compute the hash */ 406 ret = gen_hash_get_hash_sizes(dsa_hash, &hlen, &block_size); EG(ret, err); 407 MUST_HAVE((hlen <= MAX_DIGEST_SIZE), ret, err); 408 ret = gen_hash_hfunc(msg, msglen, hash, dsa_hash); EG(ret, err); 409 /* z = the leftmost min(N, outlen) bits of Hash(M) */ 410 rshift = 0; 411 if ((hlen * 8) > N) { 412 rshift = (bitcnt_t)((hlen * 8) - N); 413 } 414 ret = _os2ip(&z, hash, hlen); EG(ret, err); 415 if (rshift) { 416 ret = nn_rshift_fixedlen(&z, &z, rshift); EG(ret, err); 417 } 418 ret = nn_mod(&z, &z, q); EG(ret, err); 419 420 /* Compute w = s**-1 mod (q) in s */ 421 ret = nn_modinv(&s, &s, q); EG(ret, err); 422 423 /* u1 = (zw) mod q */ 424 ret = nn_mod_mul(&u1, &z, &s, q); EG(ret, err); 425 /* u2 = ((r′)w) mod q */ 426 ret = nn_mod_mul(&u2, &r, &s, q); EG(ret, err); 427 /* Now compute v = = ((g**u1 y**u2) mod p) mod q */ 428 /* NOTE: no need to use a secure exponentiation here as we only 429 * manipulate public data. 430 */ 431 ret = _nn_mod_pow_insecure(&v, g, &u1, p); EG(ret, err); 432 ret = _nn_mod_pow_insecure(&s, y, &u2, p); EG(ret, err); 433 ret = nn_mod_mul(&v, &v, &s, p); EG(ret, err); 434 ret = nn_mod(&v, &v, q); EG(ret, err); 435 436 /* Check that v = r */ 437 ret = nn_cmp(&v, &r, &cmp); EG(ret, err); 438 ret = (cmp != 0) ? -1 : 0; 439 440 err: 441 nn_uninit(&r); 442 nn_uninit(&s); 443 nn_uninit(&z); 444 nn_uninit(&u1); 445 nn_uninit(&u2); 446 nn_uninit(&v); 447 448 PTR_NULLIFY(p); 449 PTR_NULLIFY(q); 450 PTR_NULLIFY(g); 451 PTR_NULLIFY(y); 452 453 return ret; 454 } 455 456 #ifdef DSA 457 #include <libecc/utils/print_buf.h> 458 int main(int argc, char *argv[]) 459 { 460 int ret = 0; 461 462 const u8 p[] = { 463 0x90, 0x06, 0x64, 0x55, 0xB5, 0xCF, 0xC3, 0x8F, 0x9C, 0xAA, 0x4A, 0x48, 0xB4, 0x28, 0x1F, 0x29, 0x2C, 0x26, 0x0F, 0xEE, 0xF0, 0x1F, 0xD6, 0x10, 0x37, 0xE5, 0x62, 0x58, 464 0xA7, 0x79, 0x5A, 0x1C, 0x7A, 0xD4, 0x60, 0x76, 0x98, 0x2C, 0xE6, 0xBB, 0x95, 0x69, 0x36, 0xC6, 0xAB, 0x4D, 0xCF, 0xE0, 0x5E, 0x67, 0x84, 0x58, 0x69, 0x40, 0xCA, 0x54, 465 0x4B, 0x9B, 0x21, 0x40, 0xE1, 0xEB, 0x52, 0x3F, 0x00, 0x9D, 0x20, 0xA7, 0xE7, 0x88, 0x0E, 0x4E, 0x5B, 0xFA, 0x69, 0x0F, 0x1B, 0x90, 0x04, 0xA2, 0x78, 0x11, 0xCD, 0x99, 466 0x04, 0xAF, 0x70, 0x42, 0x0E, 0xEF, 0xD6, 0xEA, 0x11, 0xEF, 0x7D, 0xA1, 0x29, 0xF5, 0x88, 0x35, 0xFF, 0x56, 0xB8, 0x9F, 0xAA, 0x63, 0x7B, 0xC9, 0xAC, 0x2E, 0xFA, 0xAB, 467 0x90, 0x34, 0x02, 0x22, 0x9F, 0x49, 0x1D, 0x8D, 0x34, 0x85, 0x26, 0x1C, 0xD0, 0x68, 0x69, 0x9B, 0x6B, 0xA5, 0x8A, 0x1D, 0xDB, 0xBE, 0xF6, 0xDB, 0x51, 0xE8, 0xFE, 0x34, 468 0xE8, 0xA7, 0x8E, 0x54, 0x2D, 0x7B, 0xA3, 0x51, 0xC2, 0x1E, 0xA8, 0xD8, 0xF1, 0xD2, 0x9F, 0x5D, 0x5D, 0x15, 0x93, 0x94, 0x87, 0xE2, 0x7F, 0x44, 0x16, 0xB0, 0xCA, 0x63, 469 0x2C, 0x59, 0xEF, 0xD1, 0xB1, 0xEB, 0x66, 0x51, 0x1A, 0x5A, 0x0F, 0xBF, 0x61, 0x5B, 0x76, 0x6C, 0x58, 0x62, 0xD0, 0xBD, 0x8A, 0x3F, 0xE7, 0xA0, 0xE0, 0xDA, 0x0F, 0xB2, 470 0xFE, 0x1F, 0xCB, 0x19, 0xE8, 0xF9, 0x99, 0x6A, 0x8E, 0xA0, 0xFC, 0xCD, 0xE5, 0x38, 0x17, 0x52, 0x38, 0xFC, 0x8B, 0x0E, 0xE6, 0xF2, 0x9A, 0xF7, 0xF6, 0x42, 0x77, 0x3E, 471 0xBE, 0x8C, 0xD5, 0x40, 0x24, 0x15, 0xA0, 0x14, 0x51, 0xA8, 0x40, 0x47, 0x6B, 0x2F, 0xCE, 0xB0, 0xE3, 0x88, 0xD3, 0x0D, 0x4B, 0x37, 0x6C, 0x37, 0xFE, 0x40, 0x1C, 0x2A, 472 0x2C, 0x2F, 0x94, 0x1D, 0xAD, 0x17, 0x9C, 0x54, 0x0C, 0x1C, 0x8C, 0xE0, 0x30, 0xD4, 0x60, 0xC4, 0xD9, 0x83, 0xBE, 0x9A, 0xB0, 0xB2, 0x0F, 0x69, 0x14, 0x4C, 0x1A, 0xE1, 473 0x3F, 0x93, 0x83, 0xEA, 0x1C, 0x08, 0x50, 0x4F, 0xB0, 0xBF, 0x32, 0x15, 0x03, 0xEF, 0xE4, 0x34, 0x88, 0x31, 0x0D, 0xD8, 0xDC, 0x77, 0xEC, 0x5B, 0x83, 0x49, 0xB8, 0xBF, 474 0xE9, 0x7C, 0x2C, 0x56, 0x0E, 0xA8, 0x78, 0xDE, 0x87, 0xC1, 0x1E, 0x3D, 0x59, 0x7F, 0x1F, 0xEA, 0x74, 0x2D, 0x73, 0xEE, 0xC7, 0xF3, 0x7B, 0xE4, 0x39, 0x49, 0xEF, 0x1A, 475 0x0D, 0x15, 0xC3, 0xF3, 0xE3, 0xFC, 0x0A, 0x83, 0x35, 0x61, 0x70, 0x55, 0xAC, 0x91, 0x32, 0x8E, 0xC2, 0x2B, 0x50, 0xFC, 0x15, 0xB9, 0x41, 0xD3, 0xD1, 0x62, 0x4C, 0xD8, 476 0x8B, 0xC2, 0x5F, 0x3E, 0x94, 0x1F, 0xDD, 0xC6, 0x20, 0x06, 0x89, 0x58, 0x1B, 0xFE, 0xC4, 0x16, 0xB4, 0xB2, 0xCB, 0x73, 477 }; 478 479 const u8 q[] = { 480 0xCF, 0xA0, 0x47, 0x8A, 0x54, 0x71, 0x7B, 0x08, 0xCE, 0x64, 0x80, 0x5B, 0x76, 0xE5, 0xB1, 0x42, 0x49, 0xA7, 0x7A, 0x48, 0x38, 0x46, 0x9D, 0xF7, 0xF7, 0xDC, 0x98, 0x7E, 481 0xFC, 0xCF, 0xB1, 0x1D, 482 }; 483 484 const u8 g[] = { 485 0x5E, 0x5C, 0xBA, 0x99, 0x2E, 0x0A, 0x68, 0x0D, 0x88, 0x5E, 0xB9, 0x03, 0xAE, 0xA7, 0x8E, 0x4A, 0x45, 0xA4, 0x69, 0x10, 0x3D, 0x44, 0x8E, 0xDE, 0x3B, 0x7A, 0xCC, 0xC5, 486 0x4D, 0x52, 0x1E, 0x37, 0xF8, 0x4A, 0x4B, 0xDD, 0x5B, 0x06, 0xB0, 0x97, 0x0C, 0xC2, 0xD2, 0xBB, 0xB7, 0x15, 0xF7, 0xB8, 0x28, 0x46, 0xF9, 0xA0, 0xC3, 0x93, 0x91, 0x4C, 487 0x79, 0x2E, 0x6A, 0x92, 0x3E, 0x21, 0x17, 0xAB, 0x80, 0x52, 0x76, 0xA9, 0x75, 0xAA, 0xDB, 0x52, 0x61, 0xD9, 0x16, 0x73, 0xEA, 0x9A, 0xAF, 0xFE, 0xEC, 0xBF, 0xA6, 0x18, 488 0x3D, 0xFC, 0xB5, 0xD3, 0xB7, 0x33, 0x2A, 0xA1, 0x92, 0x75, 0xAF, 0xA1, 0xF8, 0xEC, 0x0B, 0x60, 0xFB, 0x6F, 0x66, 0xCC, 0x23, 0xAE, 0x48, 0x70, 0x79, 0x1D, 0x59, 0x82, 489 0xAA, 0xD1, 0xAA, 0x94, 0x85, 0xFD, 0x8F, 0x4A, 0x60, 0x12, 0x6F, 0xEB, 0x2C, 0xF0, 0x5D, 0xB8, 0xA7, 0xF0, 0xF0, 0x9B, 0x33, 0x97, 0xF3, 0x93, 0x7F, 0x2E, 0x90, 0xB9, 490 0xE5, 0xB9, 0xC9, 0xB6, 0xEF, 0xEF, 0x64, 0x2B, 0xC4, 0x83, 0x51, 0xC4, 0x6F, 0xB1, 0x71, 0xB9, 0xBF, 0xA9, 0xEF, 0x17, 0xA9, 0x61, 0xCE, 0x96, 0xC7, 0xE7, 0xA7, 0xCC, 491 0x3D, 0x3D, 0x03, 0xDF, 0xAD, 0x10, 0x78, 0xBA, 0x21, 0xDA, 0x42, 0x51, 0x98, 0xF0, 0x7D, 0x24, 0x81, 0x62, 0x2B, 0xCE, 0x45, 0x96, 0x9D, 0x9C, 0x4D, 0x60, 0x63, 0xD7, 492 0x2A, 0xB7, 0xA0, 0xF0, 0x8B, 0x2F, 0x49, 0xA7, 0xCC, 0x6A, 0xF3, 0x35, 0xE0, 0x8C, 0x47, 0x20, 0xE3, 0x14, 0x76, 0xB6, 0x72, 0x99, 0xE2, 0x31, 0xF8, 0xBD, 0x90, 0xB3, 493 0x9A, 0xC3, 0xAE, 0x3B, 0xE0, 0xC6, 0xB6, 0xCA, 0xCE, 0xF8, 0x28, 0x9A, 0x2E, 0x28, 0x73, 0xD5, 0x8E, 0x51, 0xE0, 0x29, 0xCA, 0xFB, 0xD5, 0x5E, 0x68, 0x41, 0x48, 0x9A, 494 0xB6, 0x6B, 0x5B, 0x4B, 0x9B, 0xA6, 0xE2, 0xF7, 0x84, 0x66, 0x08, 0x96, 0xAF, 0xF3, 0x87, 0xD9, 0x28, 0x44, 0xCC, 0xB8, 0xB6, 0x94, 0x75, 0x49, 0x6D, 0xE1, 0x9D, 0xA2, 495 0xE5, 0x82, 0x59, 0xB0, 0x90, 0x48, 0x9A, 0xC8, 0xE6, 0x23, 0x63, 0xCD, 0xF8, 0x2C, 0xFD, 0x8E, 0xF2, 0xA4, 0x27, 0xAB, 0xCD, 0x65, 0x75, 0x0B, 0x50, 0x6F, 0x56, 0xDD, 496 0xE3, 0xB9, 0x88, 0x56, 0x7A, 0x88, 0x12, 0x6B, 0x91, 0x4D, 0x78, 0x28, 0xE2, 0xB6, 0x3A, 0x6D, 0x7E, 0xD0, 0x74, 0x7E, 0xC5, 0x9E, 0x0E, 0x0A, 0x23, 0xCE, 0x7D, 0x8A, 497 0x74, 0xC1, 0xD2, 0xC2, 0xA7, 0xAF, 0xB6, 0xA2, 0x97, 0x99, 0x62, 0x0F, 0x00, 0xE1, 0x1C, 0x33, 0x78, 0x7F, 0x7D, 0xED, 0x3B, 0x30, 0xE1, 0xA2, 0x2D, 0x09, 0xF1, 0xFB, 498 0xDA, 0x1A, 0xBB, 0xBF, 0xBF, 0x25, 0xCA, 0xE0, 0x5A, 0x13, 0xF8, 0x12, 0xE3, 0x45, 0x63, 0xF9, 0x94, 0x10, 0xE7, 0x3B, 499 }; 500 501 const u8 x[] = { 502 0x3A, 0xBC, 0x15, 0x87, 0x29, 0x7C, 0xE7, 0xB9, 0xEA, 0x1A, 0xD6, 0x65, 0x1C, 0xF2, 0xBC, 0x4D, 0x7F, 0x92, 0xED, 0x25, 0xCA, 0xBC, 0x85, 0x53, 0xF5, 0x67, 0xD1, 0xB4, 503 0x0E, 0xBB, 0x87, 0x64, 504 }; 505 506 const u8 y[] = { 507 0x8b, 0x89, 0x1c, 0x86, 0x92, 0xd3, 0xde, 0x87, 0x58, 0x79, 0x39, 0x0f, 0x26, 0x98, 0xb2, 0x6f, 0xbe, 0xcc, 0xa6, 0xb0, 0x75, 0x53, 0x5d, 0xce, 0x6b, 0x0c, 0x86, 0x25, 0x77, 0xf9, 0xfa, 0x0d, 0xef, 0x60, 0x74, 0xe7, 0xa7, 0x62, 0x41, 0x21, 0x22, 0x4a, 0x59, 0x58, 0x96, 0xab, 0xd4, 0xcd, 0xa5, 0x6b, 0x2c, 0xef, 0xb9, 0x42, 0xe0, 0x25, 0xd2, 0xa4, 0x28, 0x2f, 0xfa, 0xa9, 0x8a, 0x48, 0xcd, 0xb4, 0x7e, 0x1a, 0x6f, 0xcb, 0x5c, 0xfb, 0x39, 0x3e, 0xf3, 0x5a, 0xf9, 0xdf, 0x91, 0x31, 0x02, 0xbb, 0x30, 0x3c, 0x2b, 0x5c, 0x36, 0xc3, 0xf8, 0xfc, 0x04, 0xed, 0x7b, 0x8b, 0x69, 0xfe, 0xfe, 0x0c, 0xf3, 0xe1, 0xfc, 0x05, 0xcf, 0xa7, 0x13, 0xb3, 0x43, 0x5b, 0x26, 0x56, 0xe9, 0x13, 0xba, 0x88, 0x74, 0xae, 0xa9, 0xf9, 0x36, 0x00, 0x6a, 0xeb, 0x44, 0x8b, 0xcd, 0x00, 0x5d, 0x18, 0xec, 0x35, 0x62, 0xa3, 0x3d, 0x04, 0xcf, 0x25, 0xc8, 0xd3, 0xd6, 0x98, 0x44, 0x34, 0x34, 0x42, 0xfa, 0x3d, 0xb7, 0xde, 0x61, 0x8c, 0x5e, 0x2d, 0xa0, 0x64, 0x57, 0x3e, 0x61, 0xe6, 0xd5, 0x58, 0x1b, 0xfb, 0x69, 0x4a, 0x23, 0xac, 0x87, 0xfd, 0x5b, 0x52, 0xd6, 0x2e, 0x95, 0x4e, 0x13, 0x76, 0xdb, 0x8d, 0xdb, 0x52, 0x4f, 0xfc, 0x0d, 0x46, 0x9d, 0xf9, 0x78, 0x79, 0x2e, 0xe4, 0x41, 0x73, 0x8e, 0x5d, 0xb0, 0x5a, 0x7d, 0xc4, 0x3e, 0x94, 0xc1, 0x1a, 0x2e, 0x7a, 0x4f, 0xbe, 0x38, 0x30, 0x71, 0xfa, 0x36, 0xd2, 0xa7, 0xec, 0x8a, 0x93, 0x88, 0xfe, 0x1c, 0x4f, 0x79, 0x88, 0x8a, 0x99, 0xd3, 0xb6, 0x10, 0x56, 0x97, 0xc2, 0x55, 0x6b, 0x79, 0xbb, 0x4d, 0x7e, 0x78, 0x1c, 0xeb, 0xb3, 0xd4, 0x86, 0x6a, 0xd8, 0x25, 0xa5, 0xe8, 0x30, 0x84, 0x60, 0x72, 0x28, 0x9f, 0xdb, 0xc9, 0x41, 0xfa, 0x67, 0x9c, 0xa8, 0x2f, 0x5f, 0x78, 0xb7, 0x46, 0x1b, 0x24, 0x04, 0xdb, 0x88, 0x3d, 0x21, 0x5f, 0x4e, 0x06, 0x76, 0xcf, 0x54, 0x93, 0x95, 0x0a, 0xc5, 0x59, 0x16, 0x97, 0xbf, 0xea, 0x8d, 0x1e, 0xe6, 0xec, 0x01, 0x6b, 0x89, 0xba, 0x51, 0xca, 0xfb, 0x5f, 0x9c, 0x84, 0xc9, 0x89, 0xfa, 0x11, 0x73, 0x75, 0xe9, 0x45, 0x78, 0xf2, 0x8b, 0xe0, 0xb3, 0x4c, 0xe0, 0x54, 0x5d, 0xa4, 0x62, 0x66, 0xfd, 0x77, 0xf6, 0x2d, 0x8f, 0x2c, 0xee, 0x92, 0xab, 0x77, 0x01, 0x2a, 0xfe, 0xbc, 0x11, 0x00, 0x89, 0x85, 0xa8, 0x21, 0xcd, 0x2d, 0x97, 0x8c, 0x7e, 0x6f, 0xe7, 0x49, 0x9d, 0x1a, 0xaf, 0x8d, 0xe6, 0x32, 0xc2, 0x1b, 0xb4, 0x8c, 0xa5, 0xcb, 0xf9, 0xf3, 0x10, 0x98, 0xfd, 0x3f, 0xd3, 0x85, 0x4c, 0x49, 0xa6, 0x5d, 0x92, 0x01, 0x74, 0x4a, 0xac, 0xe5, 0x40, 0x35, 0x49, 0x74, 0xf9, 508 }; 509 510 const u8 msg[] = "abc"; 511 512 const u8 nonce[] = { 513 0xA6, 0x90, 0x2C, 0x1E, 0x6E, 0x39, 0x43, 0xC5, 0x62, 0x80, 0x61, 0x58, 0x8A, 0x8B, 0x00, 0x7B, 0xCC, 0xEA, 0x91, 0xDB, 0xF1, 0x29, 0x15, 0x48, 0x3F, 0x04, 0xB2, 0x4A, 514 0xB0, 0x67, 0x8B, 0xEE, 515 }; 516 517 dsa_priv_key priv; 518 dsa_pub_key pub; 519 dsa_pub_key pub2; 520 u8 sig[32*2] = { 0 }; 521 522 FORCE_USED_VAR(argc); 523 FORCE_USED_VAR(argv); 524 525 /* Sanity check on size for DSA. 526 * NOTE: the double parentheses are here to handle -Wunreachable-code 527 */ 528 if((NN_USABLE_MAX_BIT_LEN) < (4096)){ 529 ext_printf("Error: you seem to have compiled libecc with usable NN size < 4096, not suitable for DSA.\n"); 530 ext_printf(" => Please recompile libecc with EXTRA_CFLAGS=\"-DUSER_NN_BIT_LEN=4096\"\n"); 531 ext_printf(" This will increase usable NN for proper DSA up to 4096 bits.\n"); 532 ext_printf(" Then recompile the current examples with the same EXTRA_CFLAGS=\"-DUSER_NN_BIT_LEN=4096\" flag and execute again!\n"); 533 /* NOTE: ret = 0 here to pass self tests even if the library is not compatible */ 534 ret = 0; 535 goto err; 536 } 537 538 539 ret = dsa_import_priv_key(&priv, p, sizeof(p), q, sizeof(q), g, sizeof(g), x, sizeof(x)); EG(ret, err); 540 ret = dsa_import_pub_key(&pub, p, sizeof(p), q, sizeof(q), g, sizeof(g), y, sizeof(y)); EG(ret, err); 541 ret = dsa_compute_pub_from_priv(&pub2, &priv); EG(ret, err); 542 543 nn_print("y", &(pub2.y)); 544 545 ret = dsa_sign(&priv, msg, sizeof(msg)-1, nonce, sizeof(nonce), sig, sizeof(sig), HASH_SHA256); EG(ret, err); 546 547 buf_print("sig", sig, sizeof(sig)); 548 549 ret = dsa_verify(&pub, msg, sizeof(msg)-1, sig, sizeof(sig), HASH_SHA256); 550 ext_printf("Signature result %d\n", ret); 551 552 err: 553 return ret; 554 } 555 #endif 556