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 "sdsa.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 Schnorr signature 25 * scheme (aka SDSA for Schnorr DSA) based on libecc arithmetic primitives. 26 * Many "variants" of Schnorr signature schemes exist, we implement here the 27 * one corresponding to SDSA as described in the ISO14888-3 standard. 28 * 29 * XXX: Please be aware that libecc has been designed for Elliptic 30 * Curve cryptography, and as so the arithmetic primitives are 31 * not optimized for big numbers >= 1024 bits usually used for SDSA. 32 * Additionnaly, a hard limit of our NN values makes it impossible 33 * to exceed ~5300 bits in the best case (words of size 64 bits). 34 * 35 * All in all, please see this as a proof of concept. 36 * Use it at your own risk! 37 * 38 * !! DISCLAIMER !! 39 * ================ 40 * 41 * Althoug some efforts have been made to secure this implementation 42 * of Schnorr DSA (e.g. by protecting the private key and nonces using constant 43 * time and blinding WHEN activated with BLINDING=1), please consider this 44 * code as a proof of concept and use it at your own risk. 45 * 46 * All-in-all, this piece of code can be useful in some contexts, or risky to 47 * use in other sensitive ones where advanced side-channels or fault attacks 48 * have to be considered. Use this SDSA code knowingly and at your own risk! 49 * 50 */ 51 52 /* NOTE: since SDSA is very similar to DSA, we reuse some of our DSA 53 * primitives to factorize some code. Also, SDSA private and public keys 54 * have the exact same type as DSA keys. 55 */ 56 57 /* Import a SDSA private key from buffers */ 58 int sdsa_import_priv_key(sdsa_priv_key *priv, const u8 *p, u16 plen, 59 const u8 *q, u16 qlen, 60 const u8 *g, u16 glen, 61 const u8 *x, u16 xlen) 62 { 63 return dsa_import_priv_key(priv, p, plen, q, qlen, g, glen, x, xlen); 64 } 65 66 /* Import a SDSA public key from buffers */ 67 int sdsa_import_pub_key(sdsa_pub_key *pub, const u8 *p, u16 plen, 68 const u8 *q, u16 qlen, 69 const u8 *g, u16 glen, 70 const u8 *y, u16 ylen) 71 { 72 return dsa_import_pub_key(pub, p, plen, q, qlen, g, glen, y, ylen); 73 } 74 75 76 77 /* Compute a SDSA public key from a private key. 78 * The public key is computed using modular exponentiation of the generator 79 * with the private key. 80 */ 81 int sdsa_compute_pub_from_priv(sdsa_pub_key *pub, const sdsa_priv_key *priv) 82 { 83 return dsa_compute_pub_from_priv(pub, priv); 84 } 85 86 /* Generate a SDSA signature 87 */ 88 int sdsa_sign(const sdsa_priv_key *priv, const u8 *msg, u32 msglen, 89 const u8 *nonce, u16 noncelen, 90 u8 *sig, u16 siglen, gen_hash_alg_type sdsa_hash) 91 { 92 int ret, iszero; 93 /* alpha is the bit length of p, beta is the bit length of q */ 94 bitcnt_t alpha, beta; 95 /* Length of the hash function (hlen is "gamma") */ 96 u8 hlen, block_size; 97 nn_src_t p, q, g, x; 98 /* The nonce and its protected version */ 99 nn k, k_; 100 /* r, s, pi */ 101 nn r, s; 102 nn_t pi; 103 /* This is a bit too much for stack space, but we need it for 104 * the computation of "pi" I2BS representation ... 105 */ 106 u8 pi_buf[NN_USABLE_MAX_BYTE_LEN]; 107 /* hash context */ 108 gen_hash_context hash_ctx; 109 #ifdef USE_SIG_BLINDING 110 /* b is the blinding mask */ 111 nn b; 112 b.magic = WORD(0); 113 #endif /* USE_SIG_BLINDING */ 114 k.magic = k_.magic = r.magic = s.magic = WORD(0); 115 116 /* Sanity checks */ 117 MUST_HAVE((priv != NULL) && (msg != NULL) && (sig != NULL), ret, err); 118 119 ret = local_memset(pi_buf, 0, sizeof(pi_buf)); EG(ret, err); 120 121 /* Make things more readable */ 122 p = &(priv->p); 123 q = &(priv->q); 124 g = &(priv->g); 125 x = &(priv->x); 126 127 /* Sanity checks */ 128 ret = nn_check_initialized(p); EG(ret, err); 129 ret = nn_check_initialized(q); EG(ret, err); 130 ret = nn_check_initialized(g); EG(ret, err); 131 ret = nn_check_initialized(x); EG(ret, err); 132 133 /* Let alpha be the bit length of p */ 134 ret = nn_bitlen(p, &alpha); EG(ret, err); 135 /* Let beta be the bit length of q */ 136 ret = nn_bitlen(q, &beta); EG(ret, err); 137 /* Get the hash sizes (8*"gamma") */ 138 ret = gen_hash_get_hash_sizes(sdsa_hash, &hlen, &block_size); EG(ret, err); 139 MUST_HAVE((hlen <= MAX_DIGEST_SIZE), ret, err); 140 141 /* Sanity check on the signature length: 142 * the signature is of size hash function plus an integer modulo q 143 * "gamma" + beta 144 */ 145 MUST_HAVE((siglen == (hlen + BYTECEIL(beta))), ret, err); 146 147 restart: 148 /* If the nonce is imposed, use it. Else get a random modulo q */ 149 if(nonce != NULL){ 150 ret = _os2ip(&k, nonce, noncelen); EG(ret, err); 151 } 152 else{ 153 ret = nn_get_random_mod(&k, q); EG(ret, err); 154 } 155 156 /* Fix the MSB of our scalar */ 157 ret = nn_copy(&k_, &k); EG(ret, err); 158 #ifdef USE_SIG_BLINDING 159 /* Blind the scalar */ 160 ret = _blind_scalar(&k_, q, &k_); EG(ret, err); 161 #endif /* USE_SIG_BLINDING */ 162 ret = _fix_scalar_msb(&k_, q, &k_); EG(ret, err); 163 /* Use r as aliasing for pi to save some space */ 164 pi = &r; 165 /* pi = (g**k mod p) */ 166 ret = nn_init(pi, 0); EG(ret, err); 167 /* Exponentiation modulo p */ 168 ret = nn_mod_pow(pi, g, &k_, p); EG(ret, err); 169 170 /* Compute I2BS(alpha, pi) 171 */ 172 ret = _i2osp(pi, pi_buf, (u16)BYTECEIL(alpha)); EG(ret, err); 173 174 /* r = h(I2BS(alpha, pi) || M) */ 175 ret = gen_hash_init(&hash_ctx, sdsa_hash); EG(ret, err); 176 ret = gen_hash_update(&hash_ctx, pi_buf, (u16)BYTECEIL(alpha), sdsa_hash); EG(ret, err); 177 ret = gen_hash_update(&hash_ctx, msg, msglen, sdsa_hash); EG(ret, err); 178 /* Export r result of the hash function in sig */ 179 ret = gen_hash_final(&hash_ctx, sig, sdsa_hash); EG(ret, err); 180 181 /* Import r as an integer modulo q */ 182 ret = _os2ip(&r, sig, hlen); EG(ret, err); 183 ret = nn_mod(&r, &r, q); EG(ret, err); 184 185 /* If r is 0, restart the process */ 186 ret = nn_iszero(&r, &iszero); EG(ret, err); 187 if (iszero) { 188 IGNORE_RET_VAL(local_memset(sig, 0, hlen)); 189 goto restart; 190 } 191 192 #ifdef USE_SIG_BLINDING 193 /* Note: if we use blinding, r and k are multiplied by 194 * a random value b in ]0,q[ */ 195 ret = nn_get_random_mod(&b, q); EG(ret, err); 196 /* Blind r with b */ 197 ret = nn_mod_mul(&r, &r, &b, q); EG(ret, err); 198 /* Blind k with b */ 199 ret = nn_mod_mul(&k, &k, &b, q); EG(ret, err); 200 /* 201 * In case of blinding, we compute b^-1 with 202 * little Fermat theorem. This will be used to 203 * unblind s. 204 */ 205 ret = nn_modinv_fermat(&b, &b, q); EG(ret, err); 206 #endif /* USE_SIG_BLINDING */ 207 208 /* Compute s = (k + r x) mod q */ 209 ret = nn_mod_mul(&s, &r, x, q); EG(ret, err); 210 ret = nn_mod_add(&s, &s, &k, q); EG(ret, err); 211 212 #ifdef USE_SIG_BLINDING 213 /* In case of blinding, unblind s */ 214 ret = nn_mod_mul(&s, &s, &b, q); EG(ret, err); 215 #endif /* USE_SIG_BLINDING */ 216 /* If s is 0, restart the process */ 217 ret = nn_iszero(&s, &iszero); EG(ret, err); 218 if (iszero) { 219 goto restart; 220 } 221 222 /* Export s */ 223 ret = _i2osp(&s, sig + hlen, (u16)(siglen - hlen)); EG(ret, err); 224 225 err: 226 if(ret && (sig != NULL)){ 227 IGNORE_RET_VAL(local_memset(sig, 0, siglen)); 228 } 229 230 nn_uninit(&k); 231 nn_uninit(&k_); 232 #ifdef USE_SIG_BLINDING 233 nn_uninit(&b); 234 #endif 235 nn_uninit(&r); 236 nn_uninit(&s); 237 238 PTR_NULLIFY(pi); 239 240 PTR_NULLIFY(p); 241 PTR_NULLIFY(q); 242 PTR_NULLIFY(g); 243 PTR_NULLIFY(x); 244 245 return ret; 246 } 247 248 249 250 /* Verify a SDSA signature 251 */ 252 int sdsa_verify(const sdsa_pub_key *pub, const u8 *msg, u32 msglen, 253 const u8 *sig, u16 siglen, gen_hash_alg_type sdsa_hash) 254 { 255 int ret, iszero, cmp; 256 /* alpha is the bit length of p, beta is the bit length of q */ 257 bitcnt_t alpha, beta; 258 /* Length of the hash function */ 259 u8 hlen, block_size; 260 nn_src_t p, q, g, y; 261 /* r, s */ 262 nn r, s; 263 /* u, and pi */ 264 nn u, pi; 265 /* This is a bit too much for stack space, but we need it for 266 * the computation of "pi" I2BS representation ... 267 */ 268 u8 pi_buf[NN_USABLE_MAX_BYTE_LEN]; 269 /* Hash */ 270 u8 hash[MAX_DIGEST_SIZE]; 271 /* hash context */ 272 gen_hash_context hash_ctx; 273 r.magic = s.magic = u.magic = pi.magic = WORD(0); 274 275 /* Sanity checks */ 276 MUST_HAVE((pub != NULL) && (msg != NULL) && (sig != NULL), ret, err); 277 278 ret = local_memset(pi_buf, 0, sizeof(pi_buf)); EG(ret, err); 279 ret = local_memset(hash, 0, sizeof(hash)); EG(ret, err); 280 281 /* Make things more readable */ 282 p = &(pub->p); 283 q = &(pub->q); 284 g = &(pub->g); 285 y = &(pub->y); 286 287 /* Sanity checks */ 288 ret = nn_check_initialized(p); EG(ret, err); 289 ret = nn_check_initialized(q); EG(ret, err); 290 ret = nn_check_initialized(g); EG(ret, err); 291 ret = nn_check_initialized(y); EG(ret, err); 292 293 /* Let alpha be the bit length of p */ 294 ret = nn_bitlen(p, &alpha); EG(ret, err); 295 /* Let beta be the bit length of q */ 296 ret = nn_bitlen(q, &beta); EG(ret, err); 297 /* Get the hash sizes (8*"gamma") */ 298 ret = gen_hash_get_hash_sizes(sdsa_hash, &hlen, &block_size); EG(ret, err); 299 MUST_HAVE((hlen <= MAX_DIGEST_SIZE), ret, err); 300 301 /* Sanity check on the signature length */ 302 MUST_HAVE((siglen == (hlen + BYTECEIL(beta))), ret, err); 303 304 /* Extract r and s */ 305 ret = _os2ip(&r, sig, hlen); EG(ret, err); 306 ret = _os2ip(&s, sig + hlen, (u16)(siglen - hlen)); EG(ret, err); 307 308 /* Return an error if r = 0 or s = 0 */ 309 ret = nn_iszero(&r, &iszero); EG(ret, err); 310 MUST_HAVE((!iszero), ret, err); 311 ret = nn_iszero(&s, &iszero); EG(ret, err); 312 MUST_HAVE((!iszero), ret, err); 313 /* Check that 0 < s < q */ 314 ret = nn_cmp(&s, q, &cmp); EG(ret, err); 315 MUST_HAVE((cmp < 0), ret, err); 316 317 /* Take r modulo q */ 318 ret = nn_mod(&r, &r, q); EG(ret, err); 319 320 /* Initialize internal variables */ 321 ret = nn_init(&u, 0); EG(ret, err); 322 ret = nn_init(&pi, 0); EG(ret, err); 323 324 /* NOTE: no need to use a secure exponentiation here as we only 325 * manipulate public data. 326 */ 327 /* Compute (y ** -r) mod (p) */ 328 ret = nn_sub(&r, q, &r); EG(ret, err); /* compute -r = (q - r) mod q */ 329 ret = _nn_mod_pow_insecure(&u, y, &r, p); EG(ret, err); 330 /* Compute (g ** s) mod (p) */ 331 ret = _nn_mod_pow_insecure(&pi, g, &s, p); EG(ret, err); 332 /* Compute (y ** -r) * (g ** s) mod (p) */ 333 ret = nn_mod_mul(&pi, &pi, &u, p); EG(ret, err); 334 335 /* Compute r' */ 336 /* I2BS(alpha, pi) 337 */ 338 ret = _i2osp(&pi, pi_buf, (u16)BYTECEIL(alpha)); EG(ret, err); 339 /* r' = h(I2BS(alpha, pi) || M) */ 340 ret = gen_hash_init(&hash_ctx, sdsa_hash); EG(ret, err); 341 ret = gen_hash_update(&hash_ctx, pi_buf, (u16)BYTECEIL(alpha), sdsa_hash); EG(ret, err); 342 ret = gen_hash_update(&hash_ctx, msg, msglen, sdsa_hash); EG(ret, err); 343 ret = gen_hash_final(&hash_ctx, hash, sdsa_hash); EG(ret, err); 344 345 /* Check that hash values r' == r */ 346 ret = are_equal(sig, hash, hlen, &cmp); EG(ret, err); 347 ret = (cmp != 1) ? -1 : 0; 348 349 err: 350 nn_uninit(&r); 351 nn_uninit(&s); 352 nn_uninit(&u); 353 nn_uninit(&pi); 354 355 PTR_NULLIFY(p); 356 PTR_NULLIFY(q); 357 PTR_NULLIFY(g); 358 PTR_NULLIFY(y); 359 360 return ret; 361 } 362 363 #ifdef SDSA 364 #include <libecc/utils/print_buf.h> 365 int main(int argc, char *argv[]) 366 { 367 int ret = 0; 368 369 /* This example is taken from ISO14888-3 SDSA (Appendix F "Numerical examples" */ 370 const u8 p[] = { 371 0x87, 0xA8, 0xE6, 0x1D, 0xB4, 0xB6, 0x66, 0x3C, 0xFF, 0xBB, 0xD1, 0x9C, 0x65, 0x19, 0x59, 0x99, 0x8C, 0xEE, 0xF6, 0x08, 0x66, 0x0D, 0xD0, 0xF2, 372 0x5D, 0x2C, 0xEE, 0xD4, 0x43, 0x5E, 0x3B, 0x00, 0xE0, 0x0D, 0xF8, 0xF1, 0xD6, 0x19, 0x57, 0xD4, 0xFA, 0xF7, 0xDF, 0x45, 0x61, 0xB2, 0xAA, 0x30, 373 0x16, 0xC3, 0xD9, 0x11, 0x34, 0x09, 0x6F, 0xAA, 0x3B, 0xF4, 0x29, 0x6D, 0x83, 0x0E, 0x9A, 0x7C, 0x20, 0x9E, 0x0C, 0x64, 0x97, 0x51, 0x7A, 0xBD, 374 0x5A, 0x8A, 0x9D, 0x30, 0x6B, 0xCF, 0x67, 0xED, 0x91, 0xF9, 0xE6, 0x72, 0x5B, 0x47, 0x58, 0xC0, 0x22, 0xE0, 0xB1, 0xEF, 0x42, 0x75, 0xBF, 0x7B, 375 0x6C, 0x5B, 0xFC, 0x11, 0xD4, 0x5F, 0x90, 0x88, 0xB9, 0x41, 0xF5, 0x4E, 0xB1, 0xE5, 0x9B, 0xB8, 0xBC, 0x39, 0xA0, 0xBF, 0x12, 0x30, 0x7F, 0x5C, 376 0x4F, 0xDB, 0x70, 0xC5, 0x81, 0xB2, 0x3F, 0x76, 0xB6, 0x3A, 0xCA, 0xE1, 0xCA, 0xA6, 0xB7, 0x90, 0x2D, 0x52, 0x52, 0x67, 0x35, 0x48, 0x8A, 0x0E, 377 0xF1, 0x3C, 0x6D, 0x9A, 0x51, 0xBF, 0xA4, 0xAB, 0x3A, 0xD8, 0x34, 0x77, 0x96, 0x52, 0x4D, 0x8E, 0xF6, 0xA1, 0x67, 0xB5, 0xA4, 0x18, 0x25, 0xD9, 378 0x67, 0xE1, 0x44, 0xE5, 0x14, 0x05, 0x64, 0x25, 0x1C, 0xCA, 0xCB, 0x83, 0xE6, 0xB4, 0x86, 0xF6, 0xB3, 0xCA, 0x3F, 0x79, 0x71, 0x50, 0x60, 0x26, 379 0xC0, 0xB8, 0x57, 0xF6, 0x89, 0x96, 0x28, 0x56, 0xDE, 0xD4, 0x01, 0x0A, 0xBD, 0x0B, 0xE6, 0x21, 0xC3, 0xA3, 0x96, 0x0A, 0x54, 0xE7, 0x10, 0xC3, 380 0x75, 0xF2, 0x63, 0x75, 0xD7, 0x01, 0x41, 0x03, 0xA4, 0xB5, 0x43, 0x30, 0xC1, 0x98, 0xAF, 0x12, 0x61, 0x16, 0xD2, 0x27, 0x6E, 0x11, 0x71, 0x5F, 381 0x69, 0x38, 0x77, 0xFA, 0xD7, 0xEF, 0x09, 0xCA, 0xDB, 0x09, 0x4A, 0xE9, 0x1E, 0x1A, 0x15, 0x97, 382 }; 383 384 const u8 q[] = { 385 0x8C, 0xF8, 0x36, 0x42, 0xA7, 0x09, 0xA0, 0x97, 0xB4, 0x47, 0x99, 0x76, 0x40, 0x12, 0x9D, 0xA2, 0x99, 0xB1, 0xA4, 0x7D, 0x1E, 0xB3, 0x75, 0x0B, 386 0xA3, 0x08, 0xB0, 0xFE, 0x64, 0xF5, 0xFB, 0xD3, 387 }; 388 389 const u8 g[] = { 390 0x3F, 0xB3, 0x2C, 0x9B, 0x73, 0x13, 0x4D, 0x0B, 0x2E, 0x77, 0x50, 0x66, 0x60, 0xED, 0xBD, 0x48, 0x4C, 0xA7, 0xB1, 0x8F, 0x21, 0xEF, 0x20, 0x54, 391 0x07, 0xF4, 0x79, 0x3A, 0x1A, 0x0B, 0xA1, 0x25, 0x10, 0xDB, 0xC1, 0x50, 0x77, 0xBE, 0x46, 0x3F, 0xFF, 0x4F, 0xED, 0x4A, 0xAC, 0x0B, 0xB5, 0x55, 392 0xBE, 0x3A, 0x6C, 0x1B, 0x0C, 0x6B, 0x47, 0xB1, 0xBC, 0x37, 0x73, 0xBF, 0x7E, 0x8C, 0x6F, 0x62, 0x90, 0x12, 0x28, 0xF8, 0xC2, 0x8C, 0xBB, 0x18, 393 0xA5, 0x5A, 0xE3, 0x13, 0x41, 0x00, 0x0A, 0x65, 0x01, 0x96, 0xF9, 0x31, 0xC7, 0x7A, 0x57, 0xF2, 0xDD, 0xF4, 0x63, 0xE5, 0xE9, 0xEC, 0x14, 0x4B, 394 0x77, 0x7D, 0xE6, 0x2A, 0xAA, 0xB8, 0xA8, 0x62, 0x8A, 0xC3, 0x76, 0xD2, 0x82, 0xD6, 0xED, 0x38, 0x64, 0xE6, 0x79, 0x82, 0x42, 0x8E, 0xBC, 0x83, 395 0x1D, 0x14, 0x34, 0x8F, 0x6F, 0x2F, 0x91, 0x93, 0xB5, 0x04, 0x5A, 0xF2, 0x76, 0x71, 0x64, 0xE1, 0xDF, 0xC9, 0x67, 0xC1, 0xFB, 0x3F, 0x2E, 0x55, 396 0xA4, 0xBD, 0x1B, 0xFF, 0xE8, 0x3B, 0x9C, 0x80, 0xD0, 0x52, 0xB9, 0x85, 0xD1, 0x82, 0xEA, 0x0A, 0xDB, 0x2A, 0x3B, 0x73, 0x13, 0xD3, 0xFE, 0x14, 397 0xC8, 0x48, 0x4B, 0x1E, 0x05, 0x25, 0x88, 0xB9, 0xB7, 0xD2, 0xBB, 0xD2, 0xDF, 0x01, 0x61, 0x99, 0xEC, 0xD0, 0x6E, 0x15, 0x57, 0xCD, 0x09, 0x15, 398 0xB3, 0x35, 0x3B, 0xBB, 0x64, 0xE0, 0xEC, 0x37, 0x7F, 0xD0, 0x28, 0x37, 0x0D, 0xF9, 0x2B, 0x52, 0xC7, 0x89, 0x14, 0x28, 0xCD, 0xC6, 0x7E, 0xB6, 399 0x18, 0x4B, 0x52, 0x3D, 0x1D, 0xB2, 0x46, 0xC3, 0x2F, 0x63, 0x07, 0x84, 0x90, 0xF0, 0x0E, 0xF8, 0xD6, 0x47, 0xD1, 0x48, 0xD4, 0x79, 0x54, 0x51, 400 0x5E, 0x23, 0x27, 0xCF, 0xEF, 0x98, 0xC5, 0x82, 0x66, 0x4B, 0x4C, 0x0F, 0x6C, 0xC4, 0x16, 0x59, 401 }; 402 403 const u8 x[] = { 404 0x73, 0x01, 0x88, 0x95, 0x20, 0xD4, 0x7A, 0xA0, 0x55, 0x99, 0x5B, 0xA1, 0xD8, 0xFC, 0xD7, 0x01, 0x6E, 0xA6, 0x2E, 0x09, 0x18, 0x89, 0x2E, 0x07, 405 0xB7, 0xDC, 0x23, 0xAF, 0x69, 0x00, 0x6B, 0x88, 406 }; 407 408 const u8 y[] = { 409 0x57, 0xA1, 0x72, 0x58, 0xD4, 0xA3, 0xF4, 0x7C, 0x45, 0x45, 0xAD, 0x51, 0xF3, 0x10, 0x9C, 0x5D, 0xB4, 0x1B, 0x78, 0x78, 0x79, 0xFC, 0xFE, 0x53, 410 0x8D, 0xC1, 0xDD, 0x5D, 0x35, 0xCE, 0x42, 0xFF, 0x3A, 0x9F, 0x22, 0x5E, 0xDE, 0x65, 0x02, 0x12, 0x64, 0x08, 0xFC, 0xB1, 0x3A, 0xEA, 0x22, 0x31, 411 0x80, 0xB1, 0x49, 0xC4, 0x64, 0xE1, 0x76, 0xEB, 0xF0, 0x3B, 0xA6, 0x51, 0x0D, 0x82, 0x06, 0xC9, 0x20, 0xF6, 0xB1, 0xE0, 0x93, 0x92, 0xE6, 0xC8, 412 0x40, 0xA0, 0x5B, 0xDB, 0x9D, 0x68, 0x75, 0xAB, 0x3F, 0x48, 0x17, 0xEC, 0x3A, 0x65, 0xA6, 0x65, 0xB7, 0x88, 0xEC, 0xBB, 0x44, 0x71, 0x88, 0xC7, 413 0xDF, 0x2E, 0xB4, 0xD3, 0xD9, 0x42, 0x4E, 0x57, 0xD9, 0x64, 0x39, 0x8D, 0xBE, 0x1C, 0x63, 0x62, 0x65, 0x9C, 0x6B, 0xD8, 0x55, 0xC1, 0xD3, 0xE5, 414 0x1D, 0x64, 0x79, 0x6C, 0xA5, 0x98, 0x48, 0x0D, 0xFD, 0xD9, 0x58, 0x0E, 0x55, 0x08, 0x53, 0x45, 0xC1, 0x5E, 0x34, 0xD6, 0xA3, 0x3A, 0x2F, 0x43, 415 0xE2, 0x22, 0x40, 0x7A, 0xCE, 0x05, 0x89, 0x72, 0xD3, 0x49, 0x52, 0xAE, 0x2B, 0x70, 0x5C, 0x53, 0x22, 0x43, 0xBE, 0x39, 0x4B, 0x22, 0x23, 0x29, 416 0x61, 0x61, 0x14, 0x5E, 0xF2, 0x92, 0x7C, 0xDB, 0xC5, 0x5B, 0xBD, 0x56, 0x4A, 0xAE, 0x8D, 0xE4, 0xBA, 0x45, 0x00, 0xA7, 0xFA, 0x43, 0x2F, 0xE7, 417 0x8B, 0x0F, 0x06, 0x89, 0x1E, 0x40, 0x80, 0x83, 0x7E, 0x76, 0x10, 0x57, 0xBC, 0x6C, 0xB8, 0xAC, 0x18, 0xFD, 0x43, 0x20, 0x75, 0x82, 0x03, 0x2A, 418 0xFB, 0x63, 0xC6, 0x24, 0xF3, 0x2E, 0x66, 0xB0, 0x5F, 0xC3, 0x1C, 0x5D, 0xFF, 0xB2, 0x5F, 0xA9, 0x2D, 0x4D, 0x00, 0xE2, 0xB0, 0xD4, 0xF7, 0x21, 419 0xE8, 0x8C, 0x41, 0x7D, 0x2E, 0x57, 0x79, 0x7B, 0x8F, 0x55, 0xA2, 0xFF, 0xC6, 0xEE, 0x4D, 0xDB, 420 }; 421 422 const u8 msg[] = "abc"; 423 424 const u8 nonce[] = { 425 0x2B, 0x73, 0xE8, 0xFF, 0x3A, 0x7C, 0x01, 0x68, 0x6C, 0xA5, 0x56, 0xE0, 0xFA, 0xBF, 0xD7, 0x4A, 0xC8, 0xD1, 0xFD, 0xA4, 0xAD, 0x3D, 0x50, 0x3F, 426 0x23, 0xB8, 0xEB, 0x8A, 0xEE, 0xC6, 0x33, 0x05, 427 }; 428 429 sdsa_priv_key priv; 430 sdsa_pub_key pub; 431 sdsa_pub_key pub2; 432 u8 sig[32*2] = { 0 }; 433 434 FORCE_USED_VAR(argc); 435 FORCE_USED_VAR(argv); 436 437 /* Sanity check on size for DSA. 438 * NOTE: the double parentheses are here to handle -Wunreachable-code 439 */ 440 if((NN_USABLE_MAX_BIT_LEN) < (4096)){ 441 ext_printf("Error: you seem to have compiled libecc with usable NN size < 4096, not suitable for DSA.\n"); 442 ext_printf(" => Please recompile libecc with EXTRA_CFLAGS=\"-DUSER_NN_BIT_LEN=4096\"\n"); 443 ext_printf(" This will increase usable NN for proper DSA up to 4096 bits.\n"); 444 ext_printf(" Then recompile the current examples with the same EXTRA_CFLAGS=\"-DUSER_NN_BIT_LEN=4096\" flag and execute again!\n"); 445 /* NOTE: ret = 0 here to pass self tests even if the library is not compatible */ 446 ret = 0; 447 goto err; 448 } 449 450 451 ret = sdsa_import_priv_key(&priv, p, sizeof(p), q, sizeof(q), g, sizeof(g), x, sizeof(x)); EG(ret, err); 452 ret = sdsa_import_pub_key(&pub, p, sizeof(p), q, sizeof(q), g, sizeof(g), y, sizeof(y)); EG(ret, err); 453 ret = sdsa_compute_pub_from_priv(&pub2, &priv); EG(ret, err); 454 455 nn_print("y", &(pub2.y)); 456 457 ret = sdsa_sign(&priv, msg, sizeof(msg)-1, nonce, sizeof(nonce), sig, sizeof(sig), HASH_SHA256); EG(ret, err); 458 459 buf_print("sig", sig, sizeof(sig)); 460 461 ret = sdsa_verify(&pub, msg, sizeof(msg)-1, sig, sizeof(sig), HASH_SHA256); 462 ext_printf("Signature result %d\n", ret); 463 464 err: 465 return ret; 466 } 467 #endif 468