1*f0865ec9SKyle Evans /* 2*f0865ec9SKyle Evans * Copyright (C) 2017 - 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 * Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr> 8*f0865ec9SKyle Evans * 9*f0865ec9SKyle Evans * Contributors: 10*f0865ec9SKyle Evans * Nicolas VIVET <nicolas.vivet@ssi.gouv.fr> 11*f0865ec9SKyle Evans * Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr> 12*f0865ec9SKyle Evans * 13*f0865ec9SKyle Evans * This software is licensed under a dual BSD and GPL v2 license. 14*f0865ec9SKyle Evans * See LICENSE file at the root folder of the project. 15*f0865ec9SKyle Evans */ 16*f0865ec9SKyle Evans #include <libecc/sig/sig_algs.h> 17*f0865ec9SKyle Evans 18*f0865ec9SKyle Evans /* 19*f0865ec9SKyle Evans * Generic private key generation (generate a scalar in ]0,q[ 20*f0865ec9SKyle Evans * Common accross many schemes, but might diverge for some. 21*f0865ec9SKyle Evans */ 22*f0865ec9SKyle Evans int generic_gen_priv_key(ec_priv_key *priv_key) 23*f0865ec9SKyle Evans { 24*f0865ec9SKyle Evans nn_src_t q; 25*f0865ec9SKyle Evans int ret; 26*f0865ec9SKyle Evans 27*f0865ec9SKyle Evans ret = priv_key_check_initialized(priv_key); EG(ret, err); 28*f0865ec9SKyle Evans 29*f0865ec9SKyle Evans q = &(priv_key->params->ec_gen_order); 30*f0865ec9SKyle Evans 31*f0865ec9SKyle Evans /* Get a random value in ]0,q[ where q is the group generator order */ 32*f0865ec9SKyle Evans ret = nn_get_random_mod(&(priv_key->x), q); 33*f0865ec9SKyle Evans 34*f0865ec9SKyle Evans err: 35*f0865ec9SKyle Evans return ret; 36*f0865ec9SKyle Evans } 37*f0865ec9SKyle Evans 38*f0865ec9SKyle Evans /* Private key generation function per signature scheme */ 39*f0865ec9SKyle Evans int gen_priv_key(ec_priv_key *priv_key) 40*f0865ec9SKyle Evans { 41*f0865ec9SKyle Evans const ec_sig_mapping *sm; 42*f0865ec9SKyle Evans int ret; 43*f0865ec9SKyle Evans u8 i; 44*f0865ec9SKyle Evans 45*f0865ec9SKyle Evans ret = priv_key_check_initialized(priv_key); EG(ret, err); 46*f0865ec9SKyle Evans 47*f0865ec9SKyle Evans ret = -1; 48*f0865ec9SKyle Evans for (i = 0, sm = &ec_sig_maps[i]; 49*f0865ec9SKyle Evans sm->type != UNKNOWN_ALG; sm = &ec_sig_maps[++i]) { 50*f0865ec9SKyle Evans if (sm->type == priv_key->key_type) { 51*f0865ec9SKyle Evans /* NOTE: since sm is initalized with a structure 52*f0865ec9SKyle Evans * coming from a const source, we can safely call 53*f0865ec9SKyle Evans * the callback here, but better safe than sorry. 54*f0865ec9SKyle Evans */ 55*f0865ec9SKyle Evans MUST_HAVE((sm->gen_priv_key != NULL), ret, err); 56*f0865ec9SKyle Evans ret = sm->gen_priv_key(priv_key); 57*f0865ec9SKyle Evans break; 58*f0865ec9SKyle Evans } 59*f0865ec9SKyle Evans } 60*f0865ec9SKyle Evans 61*f0865ec9SKyle Evans err: 62*f0865ec9SKyle Evans return ret; 63*f0865ec9SKyle Evans } 64*f0865ec9SKyle Evans 65*f0865ec9SKyle Evans /* 66*f0865ec9SKyle Evans * Generic function to init a uninitialized public key from an initialized 67*f0865ec9SKyle Evans * private key. The function uses the expected logic to derive the key 68*f0865ec9SKyle Evans * (e.g. Y=xG, Y=(x^-1)G, etc). It returns -1 on error (i.e. if the signature 69*f0865ec9SKyle Evans * alg is unknown) in which case the public key has not been initialized. 70*f0865ec9SKyle Evans * It returns 0 on success. 71*f0865ec9SKyle Evans */ 72*f0865ec9SKyle Evans int init_pubkey_from_privkey(ec_pub_key *pub_key, ec_priv_key *priv_key) 73*f0865ec9SKyle Evans { 74*f0865ec9SKyle Evans const ec_sig_mapping *sm; 75*f0865ec9SKyle Evans int ret; 76*f0865ec9SKyle Evans u8 i; 77*f0865ec9SKyle Evans 78*f0865ec9SKyle Evans ret = priv_key_check_initialized(priv_key); EG(ret, err); 79*f0865ec9SKyle Evans 80*f0865ec9SKyle Evans ret = -1; 81*f0865ec9SKyle Evans for (i = 0, sm = &ec_sig_maps[i]; 82*f0865ec9SKyle Evans sm->type != UNKNOWN_ALG; sm = &ec_sig_maps[++i]) { 83*f0865ec9SKyle Evans if (sm->type == priv_key->key_type) { 84*f0865ec9SKyle Evans /* NOTE: since sm is initalized with a structure 85*f0865ec9SKyle Evans * coming from a const source, we can safely call 86*f0865ec9SKyle Evans * the callback here, but better safe than sorry. 87*f0865ec9SKyle Evans */ 88*f0865ec9SKyle Evans MUST_HAVE((sm->init_pub_key != NULL), ret, err); 89*f0865ec9SKyle Evans ret = sm->init_pub_key(pub_key, priv_key); 90*f0865ec9SKyle Evans break; 91*f0865ec9SKyle Evans } 92*f0865ec9SKyle Evans } 93*f0865ec9SKyle Evans 94*f0865ec9SKyle Evans err: 95*f0865ec9SKyle Evans return ret; 96*f0865ec9SKyle Evans } 97*f0865ec9SKyle Evans 98*f0865ec9SKyle Evans /* 99*f0865ec9SKyle Evans * On success, 0 is returned and out parameter 'sig_mapping' provides a 100*f0865ec9SKyle Evans * pointer to the ec_sig_mapping matching given input parameter 101*f0865ec9SKyle Evans * 'sig_name' (a null-terminated string, e.g. "ECDSA"). -1 is returned on error 102*f0865ec9SKyle Evans * in which case 'sig_mapping' is not meaningful. 103*f0865ec9SKyle Evans */ 104*f0865ec9SKyle Evans int get_sig_by_name(const char *ec_sig_name, const ec_sig_mapping **sig_mapping) 105*f0865ec9SKyle Evans { 106*f0865ec9SKyle Evans const ec_sig_mapping *sm; 107*f0865ec9SKyle Evans int ret, check; 108*f0865ec9SKyle Evans u8 i; 109*f0865ec9SKyle Evans 110*f0865ec9SKyle Evans MUST_HAVE((ec_sig_name != NULL), ret, err); 111*f0865ec9SKyle Evans MUST_HAVE((sig_mapping != NULL), ret, err); 112*f0865ec9SKyle Evans 113*f0865ec9SKyle Evans ret = -1; 114*f0865ec9SKyle Evans for (i = 0, sm = &ec_sig_maps[i]; 115*f0865ec9SKyle Evans sm->type != UNKNOWN_ALG; sm = &ec_sig_maps[++i]) { 116*f0865ec9SKyle Evans if((!are_str_equal(ec_sig_name, sm->name, &check)) && check){ 117*f0865ec9SKyle Evans (*sig_mapping) = sm; 118*f0865ec9SKyle Evans ret = 0; 119*f0865ec9SKyle Evans break; 120*f0865ec9SKyle Evans } 121*f0865ec9SKyle Evans } 122*f0865ec9SKyle Evans 123*f0865ec9SKyle Evans err: 124*f0865ec9SKyle Evans return ret; 125*f0865ec9SKyle Evans } 126*f0865ec9SKyle Evans 127*f0865ec9SKyle Evans /* 128*f0865ec9SKyle Evans * On success, 0 is returned and out parameter 'sig_mapping' provides a 129*f0865ec9SKyle Evans * pointer to the ec_sig_mapping matching given input parameter 130*f0865ec9SKyle Evans * 'sig_type' (e.g. ECDSA, ECSDA). -1 is returned on error in which 131*f0865ec9SKyle Evans * case 'sig_mapping' is not meaningful. 132*f0865ec9SKyle Evans */ 133*f0865ec9SKyle Evans int get_sig_by_type(ec_alg_type sig_type, const ec_sig_mapping **sig_mapping) 134*f0865ec9SKyle Evans { 135*f0865ec9SKyle Evans const ec_sig_mapping *sm; 136*f0865ec9SKyle Evans int ret; 137*f0865ec9SKyle Evans u8 i; 138*f0865ec9SKyle Evans 139*f0865ec9SKyle Evans MUST_HAVE((sig_mapping != NULL), ret, err); 140*f0865ec9SKyle Evans 141*f0865ec9SKyle Evans ret = -1; 142*f0865ec9SKyle Evans for (i = 0, sm = &ec_sig_maps[i]; 143*f0865ec9SKyle Evans sm->type != UNKNOWN_ALG; sm = &ec_sig_maps[++i]) { 144*f0865ec9SKyle Evans if (sm->type == sig_type) { 145*f0865ec9SKyle Evans (*sig_mapping) = sm; 146*f0865ec9SKyle Evans ret = 0; 147*f0865ec9SKyle Evans break; 148*f0865ec9SKyle Evans } 149*f0865ec9SKyle Evans } 150*f0865ec9SKyle Evans 151*f0865ec9SKyle Evans err: 152*f0865ec9SKyle Evans return ret; 153*f0865ec9SKyle Evans } 154*f0865ec9SKyle Evans 155*f0865ec9SKyle Evans /* 156*f0865ec9SKyle Evans * Here, we provide a helper that sanity checks the provided signature 157*f0865ec9SKyle Evans * mapping against the constant ones. 0 is returned on success, -1 on 158*f0865ec9SKyle Evans * error. 159*f0865ec9SKyle Evans */ 160*f0865ec9SKyle Evans int ec_sig_mapping_callbacks_sanity_check(const ec_sig_mapping *sig) 161*f0865ec9SKyle Evans { 162*f0865ec9SKyle Evans const ec_sig_mapping *sm; 163*f0865ec9SKyle Evans int ret = -1, check; 164*f0865ec9SKyle Evans u8 i; 165*f0865ec9SKyle Evans 166*f0865ec9SKyle Evans MUST_HAVE((sig != NULL), ret, err); 167*f0865ec9SKyle Evans 168*f0865ec9SKyle Evans /* We just check is our mapping is indeed 169*f0865ec9SKyle Evans * one of the registered mappings. 170*f0865ec9SKyle Evans */ 171*f0865ec9SKyle Evans for (i = 0, sm = &ec_sig_maps[i]; 172*f0865ec9SKyle Evans sm->type != UNKNOWN_ALG; sm = &ec_sig_maps[++i]) { 173*f0865ec9SKyle Evans if (sm->type == sig->type){ 174*f0865ec9SKyle Evans if ((!are_str_equal_nlen(sm->name, sig->name, MAX_SIG_ALG_NAME_LEN, &check)) && (!check)){ 175*f0865ec9SKyle Evans goto err; 176*f0865ec9SKyle Evans } else if (sm->siglen != sig->siglen){ 177*f0865ec9SKyle Evans goto err; 178*f0865ec9SKyle Evans } else if (sm->gen_priv_key != sig->gen_priv_key){ 179*f0865ec9SKyle Evans goto err; 180*f0865ec9SKyle Evans } else if (sm->init_pub_key != sig->init_pub_key){ 181*f0865ec9SKyle Evans goto err; 182*f0865ec9SKyle Evans } else if (sm->sign_init != sig->sign_init){ 183*f0865ec9SKyle Evans goto err; 184*f0865ec9SKyle Evans } else if (sm->sign_update != sig->sign_update){ 185*f0865ec9SKyle Evans goto err; 186*f0865ec9SKyle Evans } else if (sm->sign_finalize != sig->sign_finalize){ 187*f0865ec9SKyle Evans goto err; 188*f0865ec9SKyle Evans } else if (sm->sign != sig->sign){ 189*f0865ec9SKyle Evans goto err; 190*f0865ec9SKyle Evans } else if (sm->verify_init != sig->verify_init){ 191*f0865ec9SKyle Evans goto err; 192*f0865ec9SKyle Evans } else if (sm->verify_update != sig->verify_update){ 193*f0865ec9SKyle Evans goto err; 194*f0865ec9SKyle Evans } else if (sm->verify_finalize != sig->verify_finalize){ 195*f0865ec9SKyle Evans goto err; 196*f0865ec9SKyle Evans } else if (sm->verify != sig->verify){ 197*f0865ec9SKyle Evans goto err; 198*f0865ec9SKyle Evans } else{ 199*f0865ec9SKyle Evans ret = 0; 200*f0865ec9SKyle Evans } 201*f0865ec9SKyle Evans } 202*f0865ec9SKyle Evans } 203*f0865ec9SKyle Evans 204*f0865ec9SKyle Evans err: 205*f0865ec9SKyle Evans return ret; 206*f0865ec9SKyle Evans } 207*f0865ec9SKyle Evans 208*f0865ec9SKyle Evans /* 209*f0865ec9SKyle Evans * Sanity checks of a signature context to see if everything seems OK. 0 is 210*f0865ec9SKyle Evans * returned on cucces, -1 on error. 211*f0865ec9SKyle Evans */ 212*f0865ec9SKyle Evans int ec_sig_ctx_callbacks_sanity_check(const struct ec_sign_context *sig_ctx) 213*f0865ec9SKyle Evans { 214*f0865ec9SKyle Evans int ret; 215*f0865ec9SKyle Evans 216*f0865ec9SKyle Evans MUST_HAVE((sig_ctx != NULL) && (sig_ctx->ctx_magic == SIG_SIGN_MAGIC), ret, err); 217*f0865ec9SKyle Evans 218*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(sig_ctx->h); EG(ret, err); 219*f0865ec9SKyle Evans ret = ec_sig_mapping_callbacks_sanity_check(sig_ctx->sig); 220*f0865ec9SKyle Evans 221*f0865ec9SKyle Evans err: 222*f0865ec9SKyle Evans return ret; 223*f0865ec9SKyle Evans } 224*f0865ec9SKyle Evans 225*f0865ec9SKyle Evans /* 226*f0865ec9SKyle Evans * Sanity check of a verification context to see if everything seems 227*f0865ec9SKyle Evans * OK. 0 is returned on success, -1 on error. 228*f0865ec9SKyle Evans */ 229*f0865ec9SKyle Evans int ec_verify_ctx_callbacks_sanity_check(const struct ec_verify_context *verify_ctx) 230*f0865ec9SKyle Evans { 231*f0865ec9SKyle Evans int ret; 232*f0865ec9SKyle Evans 233*f0865ec9SKyle Evans MUST_HAVE((verify_ctx != NULL) && (verify_ctx->ctx_magic == SIG_VERIFY_MAGIC), ret, err); 234*f0865ec9SKyle Evans 235*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(verify_ctx->h); EG(ret, err); 236*f0865ec9SKyle Evans ret = ec_sig_mapping_callbacks_sanity_check(verify_ctx->sig); 237*f0865ec9SKyle Evans 238*f0865ec9SKyle Evans err: 239*f0865ec9SKyle Evans return ret; 240*f0865ec9SKyle Evans } 241*f0865ec9SKyle Evans 242*f0865ec9SKyle Evans 243*f0865ec9SKyle Evans /* 244*f0865ec9SKyle Evans * Compute generic effective signature length (in bytes) depending on the curve 245*f0865ec9SKyle Evans * parameters, the signature algorithm and the hash function. On success, 0 is 246*f0865ec9SKyle Evans * returned and The signature length is returned using 'siglen' parameter. -1 is 247*f0865ec9SKyle Evans * returned on error. 248*f0865ec9SKyle Evans */ 249*f0865ec9SKyle Evans int ec_get_sig_len(const ec_params *params, ec_alg_type sig_type, 250*f0865ec9SKyle Evans hash_alg_type hash_type, u8 *siglen) 251*f0865ec9SKyle Evans { 252*f0865ec9SKyle Evans const ec_sig_mapping *sm; 253*f0865ec9SKyle Evans u8 digest_size = 0; 254*f0865ec9SKyle Evans u8 block_size = 0; 255*f0865ec9SKyle Evans int ret; 256*f0865ec9SKyle Evans u8 i; 257*f0865ec9SKyle Evans 258*f0865ec9SKyle Evans MUST_HAVE(((params != NULL) && (siglen != NULL)), ret, err); 259*f0865ec9SKyle Evans 260*f0865ec9SKyle Evans ret = get_hash_sizes(hash_type, &digest_size, &block_size); EG(ret, err); 261*f0865ec9SKyle Evans 262*f0865ec9SKyle Evans ret = -1; 263*f0865ec9SKyle Evans for (i = 0, sm = &ec_sig_maps[i]; 264*f0865ec9SKyle Evans sm->type != UNKNOWN_ALG; sm = &ec_sig_maps[++i]) { 265*f0865ec9SKyle Evans if (sm->type == sig_type) { 266*f0865ec9SKyle Evans /* NOTE: since sm is initalized with a structure 267*f0865ec9SKyle Evans * coming from a const source, we can safely call 268*f0865ec9SKyle Evans * the callback here, but better safe than sorry. 269*f0865ec9SKyle Evans */ 270*f0865ec9SKyle Evans MUST_HAVE((sm->siglen != NULL), ret, err); 271*f0865ec9SKyle Evans ret = sm->siglen(params->ec_fp.p_bitlen, 272*f0865ec9SKyle Evans params->ec_gen_order_bitlen, 273*f0865ec9SKyle Evans digest_size, block_size, siglen); 274*f0865ec9SKyle Evans break; 275*f0865ec9SKyle Evans } 276*f0865ec9SKyle Evans } 277*f0865ec9SKyle Evans 278*f0865ec9SKyle Evans err: 279*f0865ec9SKyle Evans return ret; 280*f0865ec9SKyle Evans } 281*f0865ec9SKyle Evans 282*f0865ec9SKyle Evans /* Generic signature */ 283*f0865ec9SKyle Evans 284*f0865ec9SKyle Evans /* 285*f0865ec9SKyle Evans * Core version of generic signature initialization function. Its purpose 286*f0865ec9SKyle Evans * is to initialize given sign context structure 'ctx' based on given key pair, 287*f0865ec9SKyle Evans * nn random function, signature and hash types. This version allows passing 288*f0865ec9SKyle Evans * a specific nn random function. It returns 0 on success, -1 on error. 289*f0865ec9SKyle Evans * 290*f0865ec9SKyle Evans * The random function is expected to initialize a nn 'out' with a value taken 291*f0865ec9SKyle Evans * uniformly at random in [1, q-1]. It returns 0 on success and -1 on error. See 292*f0865ec9SKyle Evans * nn_get_random_mod() in nn_rand.c for a function that fits the dscription. 293*f0865ec9SKyle Evans */ 294*f0865ec9SKyle Evans int _ec_sign_init(struct ec_sign_context *ctx, 295*f0865ec9SKyle Evans const ec_key_pair *key_pair, 296*f0865ec9SKyle Evans int (*rand) (nn_t out, nn_src_t q), 297*f0865ec9SKyle Evans ec_alg_type sig_type, hash_alg_type hash_type, 298*f0865ec9SKyle Evans const u8 *adata, u16 adata_len) 299*f0865ec9SKyle Evans { 300*f0865ec9SKyle Evans const ec_sig_mapping *sm; 301*f0865ec9SKyle Evans const hash_mapping *hm; 302*f0865ec9SKyle Evans int ret; 303*f0865ec9SKyle Evans u8 i; 304*f0865ec9SKyle Evans 305*f0865ec9SKyle Evans MUST_HAVE((ctx != NULL), ret, err); 306*f0865ec9SKyle Evans 307*f0865ec9SKyle Evans ret = key_pair_check_initialized_and_type(key_pair, sig_type); EG(ret, err); 308*f0865ec9SKyle Evans 309*f0865ec9SKyle Evans /* We first need to get the specific hash structure */ 310*f0865ec9SKyle Evans ret = -1; 311*f0865ec9SKyle Evans for (i = 0, hm = &hash_maps[i]; 312*f0865ec9SKyle Evans hm->type != UNKNOWN_HASH_ALG; hm = &hash_maps[++i]) { 313*f0865ec9SKyle Evans if (hm->type == hash_type) { 314*f0865ec9SKyle Evans ret = 0; 315*f0865ec9SKyle Evans break; 316*f0865ec9SKyle Evans } 317*f0865ec9SKyle Evans } 318*f0865ec9SKyle Evans if (ret) { 319*f0865ec9SKyle Evans goto err; 320*f0865ec9SKyle Evans } 321*f0865ec9SKyle Evans 322*f0865ec9SKyle Evans /* Now, let's try and get the specific key alg which was requested */ 323*f0865ec9SKyle Evans ret = -1; 324*f0865ec9SKyle Evans for (i = 0, sm = &ec_sig_maps[i]; 325*f0865ec9SKyle Evans sm->type != UNKNOWN_ALG; sm = &ec_sig_maps[++i]) { 326*f0865ec9SKyle Evans if ((sm->type == sig_type) && (sm->sign_init != NULL)) { 327*f0865ec9SKyle Evans ret = 0; 328*f0865ec9SKyle Evans break; 329*f0865ec9SKyle Evans } 330*f0865ec9SKyle Evans } 331*f0865ec9SKyle Evans if (ret) { 332*f0865ec9SKyle Evans goto err; 333*f0865ec9SKyle Evans } 334*f0865ec9SKyle Evans 335*f0865ec9SKyle Evans #ifdef NO_KNOWN_VECTORS 336*f0865ec9SKyle Evans /* 337*f0865ec9SKyle Evans * NOTE: when we do not need self tests for known vectors, 338*f0865ec9SKyle Evans * we can be strict about random function handler! 339*f0865ec9SKyle Evans * We only use our internal method to provide random integers 340*f0865ec9SKyle Evans * (which avoids honest mistakes ...). 341*f0865ec9SKyle Evans * 342*f0865ec9SKyle Evans * This also allows us to avoid the corruption of such a pointer 343*f0865ec9SKyle Evans * in our signature contexts. 344*f0865ec9SKyle Evans */ 345*f0865ec9SKyle Evans if (rand) { 346*f0865ec9SKyle Evans MUST_HAVE((rand == nn_get_random_mod), ret, err); 347*f0865ec9SKyle Evans } 348*f0865ec9SKyle Evans rand = nn_get_random_mod; 349*f0865ec9SKyle Evans #else 350*f0865ec9SKyle Evans /* Use given random function if provided or fallback to ours */ 351*f0865ec9SKyle Evans if (!rand) { 352*f0865ec9SKyle Evans rand = nn_get_random_mod; 353*f0865ec9SKyle Evans } 354*f0865ec9SKyle Evans #endif 355*f0865ec9SKyle Evans /* Sanity checks on our mappings */ 356*f0865ec9SKyle Evans ret = hash_mapping_sanity_check(hm); EG(ret, err); 357*f0865ec9SKyle Evans ret = sig_mapping_sanity_check(sm); EG(ret, err); 358*f0865ec9SKyle Evans 359*f0865ec9SKyle Evans /* Initialize context for specific signature function */ 360*f0865ec9SKyle Evans ret = local_memset(ctx, 0, sizeof(struct ec_sign_context)); EG(ret, err); 361*f0865ec9SKyle Evans ctx->key_pair = key_pair; 362*f0865ec9SKyle Evans ctx->rand = rand; 363*f0865ec9SKyle Evans ctx->h = hm; 364*f0865ec9SKyle Evans ctx->sig = sm; 365*f0865ec9SKyle Evans ctx->adata = adata; 366*f0865ec9SKyle Evans ctx->adata_len = adata_len; 367*f0865ec9SKyle Evans ctx->ctx_magic = SIG_SIGN_MAGIC; 368*f0865ec9SKyle Evans 369*f0865ec9SKyle Evans /* 370*f0865ec9SKyle Evans * NOTE: since sm has been previously initalized with a structure 371*f0865ec9SKyle Evans * coming from a const source, we can safely call the callback here. 372*f0865ec9SKyle Evans */ 373*f0865ec9SKyle Evans ret = sm->sign_init(ctx); 374*f0865ec9SKyle Evans 375*f0865ec9SKyle Evans err: 376*f0865ec9SKyle Evans if (ret && (ctx != NULL)) { 377*f0865ec9SKyle Evans /* Clear the whole context to prevent future reuse */ 378*f0865ec9SKyle Evans IGNORE_RET_VAL(local_memset(ctx, 0, sizeof(struct ec_sign_context))); 379*f0865ec9SKyle Evans } 380*f0865ec9SKyle Evans 381*f0865ec9SKyle Evans return ret; 382*f0865ec9SKyle Evans } 383*f0865ec9SKyle Evans 384*f0865ec9SKyle Evans /* 385*f0865ec9SKyle Evans * Same as previous but for public use; it forces our internal nn random 386*f0865ec9SKyle Evans * function (nn_get_random_mod()). Returns 0 on success, -1 on error. 387*f0865ec9SKyle Evans */ 388*f0865ec9SKyle Evans int ec_sign_init(struct ec_sign_context *ctx, const ec_key_pair *key_pair, 389*f0865ec9SKyle Evans ec_alg_type sig_type, hash_alg_type hash_type, 390*f0865ec9SKyle Evans const u8 *adata, u16 adata_len) 391*f0865ec9SKyle Evans { 392*f0865ec9SKyle Evans return _ec_sign_init(ctx, key_pair, NULL, sig_type, hash_type, 393*f0865ec9SKyle Evans adata, adata_len); 394*f0865ec9SKyle Evans } 395*f0865ec9SKyle Evans 396*f0865ec9SKyle Evans /* 397*f0865ec9SKyle Evans * Signature update function. Returns 0 on success, -1 on error. On error, 398*f0865ec9SKyle Evans * signature context is zeroized and is no more usable. 399*f0865ec9SKyle Evans */ 400*f0865ec9SKyle Evans int ec_sign_update(struct ec_sign_context *ctx, const u8 *chunk, u32 chunklen) 401*f0865ec9SKyle Evans { 402*f0865ec9SKyle Evans int ret; 403*f0865ec9SKyle Evans 404*f0865ec9SKyle Evans /* Sanity checks */ 405*f0865ec9SKyle Evans ret = sig_sign_check_initialized(ctx); EG(ret, err); 406*f0865ec9SKyle Evans ret = sig_mapping_sanity_check(ctx->sig); EG(ret, err); 407*f0865ec9SKyle Evans ret = hash_mapping_sanity_check(ctx->h); EG(ret, err); 408*f0865ec9SKyle Evans ret = ec_sig_ctx_callbacks_sanity_check(ctx); EG(ret, err); 409*f0865ec9SKyle Evans ret = ctx->sig->sign_update(ctx, chunk, chunklen); 410*f0865ec9SKyle Evans 411*f0865ec9SKyle Evans err: 412*f0865ec9SKyle Evans if (ret && (ctx != NULL)) { 413*f0865ec9SKyle Evans /* Clear the whole context to prevent future reuse */ 414*f0865ec9SKyle Evans IGNORE_RET_VAL(local_memset(ctx, 0, sizeof(struct ec_sign_context))); 415*f0865ec9SKyle Evans } 416*f0865ec9SKyle Evans 417*f0865ec9SKyle Evans return ret; 418*f0865ec9SKyle Evans } 419*f0865ec9SKyle Evans 420*f0865ec9SKyle Evans /* 421*f0865ec9SKyle Evans * Signature finalization function. Returns 0 on success, -1 on error. 422*f0865ec9SKyle Evans * Upon call, the signature context is cleared to prevent future use. 423*f0865ec9SKyle Evans */ 424*f0865ec9SKyle Evans int ec_sign_finalize(struct ec_sign_context *ctx, u8 *sig, u8 siglen) 425*f0865ec9SKyle Evans { 426*f0865ec9SKyle Evans int ret; 427*f0865ec9SKyle Evans 428*f0865ec9SKyle Evans /* Sanity checks */ 429*f0865ec9SKyle Evans ret = sig_sign_check_initialized(ctx); EG(ret, err); 430*f0865ec9SKyle Evans ret = sig_mapping_sanity_check(ctx->sig); EG(ret, err); 431*f0865ec9SKyle Evans ret = hash_mapping_sanity_check(ctx->h); EG(ret, err); 432*f0865ec9SKyle Evans ret = ec_sig_ctx_callbacks_sanity_check(ctx); EG(ret, err); 433*f0865ec9SKyle Evans ret = ctx->sig->sign_finalize(ctx, sig, siglen); 434*f0865ec9SKyle Evans 435*f0865ec9SKyle Evans err: 436*f0865ec9SKyle Evans if (ctx != NULL) { 437*f0865ec9SKyle Evans /* Clear the whole context to prevent future reuse */ 438*f0865ec9SKyle Evans IGNORE_RET_VAL(local_memset(ctx, 0, sizeof(struct ec_sign_context))); 439*f0865ec9SKyle Evans } 440*f0865ec9SKyle Evans 441*f0865ec9SKyle Evans return ret; 442*f0865ec9SKyle Evans } 443*f0865ec9SKyle Evans 444*f0865ec9SKyle Evans /* 445*f0865ec9SKyle Evans * Single call version of signature function (init, update and finalize). It 446*f0865ec9SKyle Evans * returns 0 on success, -1 on error. This version allows passing a custom 447*f0865ec9SKyle Evans * random function. This is useful for test vectors but should be done with 448*f0865ec9SKyle Evans * care. 449*f0865ec9SKyle Evans * 450*f0865ec9SKyle Evans * The random function is expected to initialize a nn 'out' with a value taken 451*f0865ec9SKyle Evans * uniformly at random in [1, q-1]. It returns 0 on success and -1 on error. See 452*f0865ec9SKyle Evans * nn_get_random_mod() in nn_rand.c for a function that fits the dscription. 453*f0865ec9SKyle Evans */ 454*f0865ec9SKyle Evans int generic_ec_sign(u8 *sig, u8 siglen, const ec_key_pair *key_pair, 455*f0865ec9SKyle Evans const u8 *m, u32 mlen, 456*f0865ec9SKyle Evans int (*rand) (nn_t out, nn_src_t q), 457*f0865ec9SKyle Evans ec_alg_type sig_type, hash_alg_type hash_type, 458*f0865ec9SKyle Evans const u8 *adata, u16 adata_len) 459*f0865ec9SKyle Evans { 460*f0865ec9SKyle Evans struct ec_sign_context ctx; 461*f0865ec9SKyle Evans int ret; 462*f0865ec9SKyle Evans 463*f0865ec9SKyle Evans ret = _ec_sign_init(&ctx, key_pair, rand, sig_type, 464*f0865ec9SKyle Evans hash_type, adata, adata_len); EG(ret, err); 465*f0865ec9SKyle Evans ret = ec_sign_update(&ctx, m, mlen); EG(ret, err); 466*f0865ec9SKyle Evans ret = ec_sign_finalize(&ctx, sig, siglen); 467*f0865ec9SKyle Evans 468*f0865ec9SKyle Evans err: 469*f0865ec9SKyle Evans return ret; 470*f0865ec9SKyle Evans } 471*f0865ec9SKyle Evans 472*f0865ec9SKyle Evans 473*f0865ec9SKyle Evans int _ec_sign(u8 *sig, u8 siglen, const ec_key_pair *key_pair, 474*f0865ec9SKyle Evans const u8 *m, u32 mlen, 475*f0865ec9SKyle Evans int (*rand) (nn_t out, nn_src_t q), 476*f0865ec9SKyle Evans ec_alg_type sig_type, hash_alg_type hash_type, 477*f0865ec9SKyle Evans const u8 *adata, u16 adata_len) 478*f0865ec9SKyle Evans { 479*f0865ec9SKyle Evans const ec_sig_mapping *sm; 480*f0865ec9SKyle Evans int ret; 481*f0865ec9SKyle Evans 482*f0865ec9SKyle Evans ret = get_sig_by_type(sig_type, &sm); EG(ret, err); 483*f0865ec9SKyle Evans MUST_HAVE(((sm != NULL) && (sm->sign != NULL)), ret, err); 484*f0865ec9SKyle Evans 485*f0865ec9SKyle Evans ret = sm->sign(sig, siglen, key_pair, m, mlen, rand, 486*f0865ec9SKyle Evans sig_type, hash_type, adata, adata_len); 487*f0865ec9SKyle Evans 488*f0865ec9SKyle Evans err: 489*f0865ec9SKyle Evans return ret; 490*f0865ec9SKyle Evans } 491*f0865ec9SKyle Evans 492*f0865ec9SKyle Evans /* 493*f0865ec9SKyle Evans * Same as previous but for public use; it forces our internal nn random 494*f0865ec9SKyle Evans * function (nn_get_random_mod()) by pasing NULL for 'rand' argument 495*f0865ec9SKyle Evans * _ec_sign(). Returns 0 on success, -1 on error. 496*f0865ec9SKyle Evans */ 497*f0865ec9SKyle Evans int ec_sign(u8 *sig, u8 siglen, const ec_key_pair *key_pair, 498*f0865ec9SKyle Evans const u8 *m, u32 mlen, 499*f0865ec9SKyle Evans ec_alg_type sig_type, hash_alg_type hash_type, 500*f0865ec9SKyle Evans const u8 *adata, u16 adata_len) 501*f0865ec9SKyle Evans { 502*f0865ec9SKyle Evans return _ec_sign(sig, siglen, key_pair, m, mlen, 503*f0865ec9SKyle Evans NULL, sig_type, hash_type, adata, adata_len); 504*f0865ec9SKyle Evans } 505*f0865ec9SKyle Evans 506*f0865ec9SKyle Evans /* 507*f0865ec9SKyle Evans * Generic signature verification initialization function. Returns 0 on success, 508*f0865ec9SKyle Evans * -1 on error. On error, verification context is cleared to prevent further 509*f0865ec9SKyle Evans * reuse. 510*f0865ec9SKyle Evans */ 511*f0865ec9SKyle Evans int ec_verify_init(struct ec_verify_context *ctx, const ec_pub_key *pub_key, 512*f0865ec9SKyle Evans const u8 *sig, u8 siglen, 513*f0865ec9SKyle Evans ec_alg_type sig_type, hash_alg_type hash_type, 514*f0865ec9SKyle Evans const u8 *adata, u16 adata_len) 515*f0865ec9SKyle Evans { 516*f0865ec9SKyle Evans const ec_sig_mapping *sm; 517*f0865ec9SKyle Evans const hash_mapping *hm; 518*f0865ec9SKyle Evans u8 i; 519*f0865ec9SKyle Evans int ret; 520*f0865ec9SKyle Evans 521*f0865ec9SKyle Evans MUST_HAVE((ctx != NULL), ret, err); 522*f0865ec9SKyle Evans 523*f0865ec9SKyle Evans ret = pub_key_check_initialized_and_type(pub_key, sig_type); EG(ret, err); 524*f0865ec9SKyle Evans 525*f0865ec9SKyle Evans /* We first need to get the specific hash structure */ 526*f0865ec9SKyle Evans ret = -1; 527*f0865ec9SKyle Evans for (i = 0, hm = &hash_maps[i]; 528*f0865ec9SKyle Evans hm->type != UNKNOWN_HASH_ALG; hm = &hash_maps[++i]) { 529*f0865ec9SKyle Evans if (hm->type == hash_type) { 530*f0865ec9SKyle Evans ret = 0; 531*f0865ec9SKyle Evans break; 532*f0865ec9SKyle Evans } 533*f0865ec9SKyle Evans } 534*f0865ec9SKyle Evans if (ret) { 535*f0865ec9SKyle Evans goto err; 536*f0865ec9SKyle Evans } 537*f0865ec9SKyle Evans 538*f0865ec9SKyle Evans /* 539*f0865ec9SKyle Evans * Now, let's try and get the specific key algorithm which was 540*f0865ec9SKyle Evans * requested 541*f0865ec9SKyle Evans */ 542*f0865ec9SKyle Evans ret = -1; 543*f0865ec9SKyle Evans for (i = 0, sm = &ec_sig_maps[i]; 544*f0865ec9SKyle Evans sm->type != UNKNOWN_ALG; sm = &ec_sig_maps[++i]) { 545*f0865ec9SKyle Evans if ((sm->type == sig_type) && (sm->verify_init != NULL)) { 546*f0865ec9SKyle Evans ret = 0; 547*f0865ec9SKyle Evans break; 548*f0865ec9SKyle Evans } 549*f0865ec9SKyle Evans } 550*f0865ec9SKyle Evans if (ret) { 551*f0865ec9SKyle Evans goto err; 552*f0865ec9SKyle Evans } 553*f0865ec9SKyle Evans 554*f0865ec9SKyle Evans /* Sanity checks on our mappings */ 555*f0865ec9SKyle Evans ret = hash_mapping_sanity_check(hm); EG(ret, err); 556*f0865ec9SKyle Evans ret = sig_mapping_sanity_check(sm); EG(ret, err); 557*f0865ec9SKyle Evans 558*f0865ec9SKyle Evans /* Initialize context for specific signature function */ 559*f0865ec9SKyle Evans ret = local_memset(ctx, 0, sizeof(struct ec_verify_context)); EG(ret, err); 560*f0865ec9SKyle Evans ctx->pub_key = pub_key; 561*f0865ec9SKyle Evans ctx->h = hm; 562*f0865ec9SKyle Evans ctx->sig = sm; 563*f0865ec9SKyle Evans ctx->adata = adata; 564*f0865ec9SKyle Evans ctx->adata_len = adata_len; 565*f0865ec9SKyle Evans ctx->ctx_magic = SIG_VERIFY_MAGIC; 566*f0865ec9SKyle Evans 567*f0865ec9SKyle Evans /* 568*f0865ec9SKyle Evans * NOTE: since sm has been previously initalized with a structure 569*f0865ec9SKyle Evans * coming from a const source, we can safely call the callback 570*f0865ec9SKyle Evans * here. 571*f0865ec9SKyle Evans */ 572*f0865ec9SKyle Evans ret = sm->verify_init(ctx, sig, siglen); 573*f0865ec9SKyle Evans 574*f0865ec9SKyle Evans err: 575*f0865ec9SKyle Evans 576*f0865ec9SKyle Evans if (ret && (ctx != NULL)) { 577*f0865ec9SKyle Evans /* Clear the whole context to prevent future reuse */ 578*f0865ec9SKyle Evans IGNORE_RET_VAL(local_memset(ctx, 0, sizeof(struct ec_verify_context))); 579*f0865ec9SKyle Evans } 580*f0865ec9SKyle Evans 581*f0865ec9SKyle Evans return ret; 582*f0865ec9SKyle Evans } 583*f0865ec9SKyle Evans 584*f0865ec9SKyle Evans /* 585*f0865ec9SKyle Evans * Signature verification update function. Returns 0 on success, -1 on error. 586*f0865ec9SKyle Evans * On error, verification context is cleared to prevent further reuse. 587*f0865ec9SKyle Evans */ 588*f0865ec9SKyle Evans int ec_verify_update(struct ec_verify_context *ctx, 589*f0865ec9SKyle Evans const u8 *chunk, u32 chunklen) 590*f0865ec9SKyle Evans { 591*f0865ec9SKyle Evans int ret; 592*f0865ec9SKyle Evans 593*f0865ec9SKyle Evans ret = sig_verify_check_initialized(ctx); EG(ret, err); 594*f0865ec9SKyle Evans ret = sig_mapping_sanity_check(ctx->sig); EG(ret, err); 595*f0865ec9SKyle Evans ret = hash_mapping_sanity_check(ctx->h); EG(ret, err); 596*f0865ec9SKyle Evans 597*f0865ec9SKyle Evans /* Since we call a callback, sanity check our contexts */ 598*f0865ec9SKyle Evans ret = ec_verify_ctx_callbacks_sanity_check(ctx); EG(ret, err); 599*f0865ec9SKyle Evans ret = ctx->sig->verify_update(ctx, chunk, chunklen); 600*f0865ec9SKyle Evans 601*f0865ec9SKyle Evans err: 602*f0865ec9SKyle Evans if (ret && (ctx != NULL)) { 603*f0865ec9SKyle Evans /* Clear the whole context to prevent future reuse */ 604*f0865ec9SKyle Evans IGNORE_RET_VAL(local_memset(ctx, 0, sizeof(struct ec_verify_context))); 605*f0865ec9SKyle Evans } 606*f0865ec9SKyle Evans 607*f0865ec9SKyle Evans return ret; 608*f0865ec9SKyle Evans } 609*f0865ec9SKyle Evans 610*f0865ec9SKyle Evans /* 611*f0865ec9SKyle Evans * Signature verification finalize function. Returns 0 on success, -1 on error. 612*f0865ec9SKyle Evans * On error, verification context is cleared to prevent further reuse. 613*f0865ec9SKyle Evans */ 614*f0865ec9SKyle Evans int ec_verify_finalize(struct ec_verify_context *ctx) 615*f0865ec9SKyle Evans { 616*f0865ec9SKyle Evans int ret; 617*f0865ec9SKyle Evans 618*f0865ec9SKyle Evans ret = sig_verify_check_initialized(ctx); EG(ret, err); 619*f0865ec9SKyle Evans ret = sig_mapping_sanity_check(ctx->sig); EG(ret, err); 620*f0865ec9SKyle Evans ret = hash_mapping_sanity_check(ctx->h); EG(ret, err); 621*f0865ec9SKyle Evans 622*f0865ec9SKyle Evans /* Since we call a callback, sanity check our contexts */ 623*f0865ec9SKyle Evans ret = ec_verify_ctx_callbacks_sanity_check(ctx); EG(ret, err); 624*f0865ec9SKyle Evans ret = ctx->sig->verify_finalize(ctx); 625*f0865ec9SKyle Evans 626*f0865ec9SKyle Evans err: 627*f0865ec9SKyle Evans if (ret && (ctx != NULL)) { 628*f0865ec9SKyle Evans /* Clear the whole context to prevent future reuse */ 629*f0865ec9SKyle Evans IGNORE_RET_VAL(local_memset(ctx, 0, sizeof(struct ec_verify_context))); 630*f0865ec9SKyle Evans } 631*f0865ec9SKyle Evans return ret; 632*f0865ec9SKyle Evans } 633*f0865ec9SKyle Evans 634*f0865ec9SKyle Evans /* 635*f0865ec9SKyle Evans * Single call version of signature verification function (init, update and 636*f0865ec9SKyle Evans * finalize). It returns 0 on success, -1 on error. 637*f0865ec9SKyle Evans */ 638*f0865ec9SKyle Evans int generic_ec_verify(const u8 *sig, u8 siglen, const ec_pub_key *pub_key, 639*f0865ec9SKyle Evans const u8 *m, u32 mlen, 640*f0865ec9SKyle Evans ec_alg_type sig_type, hash_alg_type hash_type, 641*f0865ec9SKyle Evans const u8 *adata, u16 adata_len) 642*f0865ec9SKyle Evans { 643*f0865ec9SKyle Evans struct ec_verify_context ctx; 644*f0865ec9SKyle Evans int ret; 645*f0865ec9SKyle Evans 646*f0865ec9SKyle Evans ret = ec_verify_init(&ctx, pub_key, sig, siglen, sig_type, 647*f0865ec9SKyle Evans hash_type, adata, adata_len); EG(ret, err); 648*f0865ec9SKyle Evans ret = ec_verify_update(&ctx, m, mlen); EG(ret, err); 649*f0865ec9SKyle Evans ret = ec_verify_finalize(&ctx); 650*f0865ec9SKyle Evans 651*f0865ec9SKyle Evans err: 652*f0865ec9SKyle Evans return ret; 653*f0865ec9SKyle Evans } 654*f0865ec9SKyle Evans 655*f0865ec9SKyle Evans int ec_verify(const u8 *sig, u8 siglen, const ec_pub_key *pub_key, 656*f0865ec9SKyle Evans const u8 *m, u32 mlen, 657*f0865ec9SKyle Evans ec_alg_type sig_type, hash_alg_type hash_type, 658*f0865ec9SKyle Evans const u8 *adata, u16 adata_len) 659*f0865ec9SKyle Evans { 660*f0865ec9SKyle Evans 661*f0865ec9SKyle Evans const ec_sig_mapping *sm; 662*f0865ec9SKyle Evans int ret; 663*f0865ec9SKyle Evans 664*f0865ec9SKyle Evans ret = get_sig_by_type(sig_type, &sm); EG(ret, err); 665*f0865ec9SKyle Evans 666*f0865ec9SKyle Evans MUST_HAVE((sm != NULL) && (sm->verify != NULL), ret, err); 667*f0865ec9SKyle Evans 668*f0865ec9SKyle Evans ret = sm->verify(sig, siglen, pub_key, m, mlen, sig_type, 669*f0865ec9SKyle Evans hash_type, adata, adata_len); 670*f0865ec9SKyle Evans 671*f0865ec9SKyle Evans err: 672*f0865ec9SKyle Evans return ret; 673*f0865ec9SKyle Evans } 674*f0865ec9SKyle Evans 675*f0865ec9SKyle Evans int ec_verify_batch(const u8 **s, const u8 *s_len, const ec_pub_key **pub_keys, 676*f0865ec9SKyle Evans const u8 **m, const u32 *m_len, u32 num, ec_alg_type sig_type, 677*f0865ec9SKyle Evans hash_alg_type hash_type, const u8 **adata, const u16 *adata_len, 678*f0865ec9SKyle Evans verify_batch_scratch_pad *scratch_pad_area, u32 *scratch_pad_area_len) 679*f0865ec9SKyle Evans { 680*f0865ec9SKyle Evans 681*f0865ec9SKyle Evans const ec_sig_mapping *sm; 682*f0865ec9SKyle Evans int ret; 683*f0865ec9SKyle Evans 684*f0865ec9SKyle Evans ret = get_sig_by_type(sig_type, &sm); EG(ret, err); 685*f0865ec9SKyle Evans 686*f0865ec9SKyle Evans MUST_HAVE((sm != NULL) && (sm->verify_batch != NULL), ret, err); 687*f0865ec9SKyle Evans 688*f0865ec9SKyle Evans ret = sm->verify_batch(s, s_len, pub_keys, m, m_len, num, sig_type, 689*f0865ec9SKyle Evans hash_type, adata, adata_len, 690*f0865ec9SKyle Evans scratch_pad_area, scratch_pad_area_len); 691*f0865ec9SKyle Evans 692*f0865ec9SKyle Evans err: 693*f0865ec9SKyle Evans return ret; 694*f0865ec9SKyle Evans } 695*f0865ec9SKyle Evans 696*f0865ec9SKyle Evans /* 697*f0865ec9SKyle Evans * Import a signature with structured data containing information about the EC 698*f0865ec9SKyle Evans * algorithm type as well as the hash function used to produce the signature. 699*f0865ec9SKyle Evans * The function returns 0 on success, -1 on error. out parameters (sig_type, 700*f0865ec9SKyle Evans * hash_type, curve_name should only be considered on success. 701*f0865ec9SKyle Evans */ 702*f0865ec9SKyle Evans int ec_structured_sig_import_from_buf(u8 *sig, u32 siglen, 703*f0865ec9SKyle Evans const u8 *out_buf, u32 outlen, 704*f0865ec9SKyle Evans ec_alg_type * sig_type, 705*f0865ec9SKyle Evans hash_alg_type * hash_type, 706*f0865ec9SKyle Evans u8 curve_name[MAX_CURVE_NAME_LEN]) 707*f0865ec9SKyle Evans { 708*f0865ec9SKyle Evans u32 metadata_len = (3 * sizeof(u8)); 709*f0865ec9SKyle Evans int ret; 710*f0865ec9SKyle Evans 711*f0865ec9SKyle Evans MUST_HAVE((out_buf != NULL) && (sig_type != NULL) && 712*f0865ec9SKyle Evans (hash_type != NULL) && (curve_name != NULL), ret, err); 713*f0865ec9SKyle Evans /* We only deal with signatures of length < 256 */ 714*f0865ec9SKyle Evans MUST_HAVE((siglen <= EC_MAX_SIGLEN) && (sig != NULL), ret, err); 715*f0865ec9SKyle Evans 716*f0865ec9SKyle Evans /* We first import the metadata consisting of: 717*f0865ec9SKyle Evans * - One byte = the EC algorithm type 718*f0865ec9SKyle Evans * - One byte = the hash algorithm type 719*f0865ec9SKyle Evans * - One byte = the curve type (FRP256V1, ...) 720*f0865ec9SKyle Evans */ 721*f0865ec9SKyle Evans MUST_HAVE((outlen <= (siglen + metadata_len)), ret, err); 722*f0865ec9SKyle Evans 723*f0865ec9SKyle Evans *sig_type = (ec_alg_type)out_buf[0]; 724*f0865ec9SKyle Evans *hash_type = (hash_alg_type)out_buf[1]; 725*f0865ec9SKyle Evans ret = ec_get_curve_name_by_type((ec_curve_type) out_buf[2], 726*f0865ec9SKyle Evans curve_name, MAX_CURVE_NAME_LEN); EG(ret, err); 727*f0865ec9SKyle Evans 728*f0865ec9SKyle Evans /* Copy the raw signature */ 729*f0865ec9SKyle Evans ret = local_memcpy(sig, out_buf + metadata_len, siglen); 730*f0865ec9SKyle Evans 731*f0865ec9SKyle Evans err: 732*f0865ec9SKyle Evans return ret; 733*f0865ec9SKyle Evans } 734*f0865ec9SKyle Evans 735*f0865ec9SKyle Evans /* 736*f0865ec9SKyle Evans * Export a signature with structured data containing information about the 737*f0865ec9SKyle Evans * EC algorithm type as well as the hash function used to produce it. The 738*f0865ec9SKyle Evans * function returns 0 on success, -1 on error. 739*f0865ec9SKyle Evans */ 740*f0865ec9SKyle Evans int ec_structured_sig_export_to_buf(const u8 *sig, u32 siglen, 741*f0865ec9SKyle Evans u8 *out_buf, u32 outlen, 742*f0865ec9SKyle Evans ec_alg_type sig_type, 743*f0865ec9SKyle Evans hash_alg_type hash_type, 744*f0865ec9SKyle Evans const u8 745*f0865ec9SKyle Evans curve_name[MAX_CURVE_NAME_LEN]) 746*f0865ec9SKyle Evans { 747*f0865ec9SKyle Evans u32 metadata_len = (3 * sizeof(u8)); 748*f0865ec9SKyle Evans u32 len; 749*f0865ec9SKyle Evans u8 curve_name_len; 750*f0865ec9SKyle Evans ec_curve_type curve_type; 751*f0865ec9SKyle Evans int ret; 752*f0865ec9SKyle Evans 753*f0865ec9SKyle Evans MUST_HAVE((out_buf != NULL) && (curve_name != NULL), ret, err); 754*f0865ec9SKyle Evans /* We only deal with signatures of length < 256 */ 755*f0865ec9SKyle Evans MUST_HAVE((siglen <= EC_MAX_SIGLEN) && (sig != NULL), ret, err); 756*f0865ec9SKyle Evans 757*f0865ec9SKyle Evans /* We first export the metadata consisting of: 758*f0865ec9SKyle Evans * - One byte = the EC algorithm type 759*f0865ec9SKyle Evans * - One byte = the hash algorithm type 760*f0865ec9SKyle Evans * - One byte = the curve type (FRP256V1, ...) 761*f0865ec9SKyle Evans * 762*f0865ec9SKyle Evans */ 763*f0865ec9SKyle Evans MUST_HAVE(outlen >= (siglen + metadata_len), ret, err); 764*f0865ec9SKyle Evans 765*f0865ec9SKyle Evans out_buf[0] = (u8)sig_type; 766*f0865ec9SKyle Evans out_buf[1] = (u8)hash_type; 767*f0865ec9SKyle Evans ret = local_strlen((const char *)curve_name, &len); EG(ret, err); 768*f0865ec9SKyle Evans len += 1; 769*f0865ec9SKyle Evans MUST_HAVE((len < 256), ret, err); 770*f0865ec9SKyle Evans curve_name_len = (u8)len; 771*f0865ec9SKyle Evans ret = ec_get_curve_type_by_name(curve_name, curve_name_len, &curve_type); EG(ret, err); 772*f0865ec9SKyle Evans out_buf[2] = (u8)curve_type; 773*f0865ec9SKyle Evans MUST_HAVE((out_buf[2] != UNKNOWN_CURVE), ret, err); 774*f0865ec9SKyle Evans 775*f0865ec9SKyle Evans /* Copy the raw signature */ 776*f0865ec9SKyle Evans ret = local_memcpy(out_buf + metadata_len, sig, siglen); 777*f0865ec9SKyle Evans 778*f0865ec9SKyle Evans err: 779*f0865ec9SKyle Evans return ret; 780*f0865ec9SKyle Evans } 781*f0865ec9SKyle Evans 782*f0865ec9SKyle Evans 783*f0865ec9SKyle Evans /* Signature finalization function */ 784*f0865ec9SKyle Evans int unsupported_sign_init(struct ec_sign_context * ctx) 785*f0865ec9SKyle Evans { 786*f0865ec9SKyle Evans /* Quirk to avoid unused variables */ 787*f0865ec9SKyle Evans FORCE_USED_VAR(ctx); 788*f0865ec9SKyle Evans 789*f0865ec9SKyle Evans /* Return an error in any case here */ 790*f0865ec9SKyle Evans return -1; 791*f0865ec9SKyle Evans } 792*f0865ec9SKyle Evans 793*f0865ec9SKyle Evans int unsupported_sign_update(struct ec_sign_context * ctx, 794*f0865ec9SKyle Evans const u8 *chunk, u32 chunklen) 795*f0865ec9SKyle Evans { 796*f0865ec9SKyle Evans /* Quirk to avoid unused variables */ 797*f0865ec9SKyle Evans FORCE_USED_VAR(ctx); 798*f0865ec9SKyle Evans FORCE_USED_VAR(chunk); 799*f0865ec9SKyle Evans FORCE_USED_VAR(chunklen); 800*f0865ec9SKyle Evans 801*f0865ec9SKyle Evans /* Return an error in any case here */ 802*f0865ec9SKyle Evans return -1; 803*f0865ec9SKyle Evans } 804*f0865ec9SKyle Evans 805*f0865ec9SKyle Evans int unsupported_sign_finalize(struct ec_sign_context *ctx, u8 *sig, u8 siglen) 806*f0865ec9SKyle Evans { 807*f0865ec9SKyle Evans /* Quirk to avoid unused variables */ 808*f0865ec9SKyle Evans FORCE_USED_VAR(ctx); 809*f0865ec9SKyle Evans FORCE_USED_VAR(sig); 810*f0865ec9SKyle Evans FORCE_USED_VAR(siglen); 811*f0865ec9SKyle Evans 812*f0865ec9SKyle Evans /* Return an error in any case here */ 813*f0865ec9SKyle Evans return -1; 814*f0865ec9SKyle Evans } 815*f0865ec9SKyle Evans 816*f0865ec9SKyle Evans int unsupported_verify_init(struct ec_verify_context * ctx, 817*f0865ec9SKyle Evans const u8 *sig, u8 siglen) 818*f0865ec9SKyle Evans { 819*f0865ec9SKyle Evans /* Quirk to avoid unused variables */ 820*f0865ec9SKyle Evans FORCE_USED_VAR(ctx); 821*f0865ec9SKyle Evans FORCE_USED_VAR(sig); 822*f0865ec9SKyle Evans FORCE_USED_VAR(siglen); 823*f0865ec9SKyle Evans 824*f0865ec9SKyle Evans /* Return an error in any case here */ 825*f0865ec9SKyle Evans return -1; 826*f0865ec9SKyle Evans } 827*f0865ec9SKyle Evans 828*f0865ec9SKyle Evans int unsupported_verify_update(struct ec_verify_context * ctx, 829*f0865ec9SKyle Evans const u8 *chunk, u32 chunklen) 830*f0865ec9SKyle Evans { 831*f0865ec9SKyle Evans /* Quirk to avoid unused variables */ 832*f0865ec9SKyle Evans FORCE_USED_VAR(ctx); 833*f0865ec9SKyle Evans FORCE_USED_VAR(chunk); 834*f0865ec9SKyle Evans FORCE_USED_VAR(chunklen); 835*f0865ec9SKyle Evans 836*f0865ec9SKyle Evans /* Return an error in any case here */ 837*f0865ec9SKyle Evans return -1; 838*f0865ec9SKyle Evans } 839*f0865ec9SKyle Evans 840*f0865ec9SKyle Evans int unsupported_verify_finalize(struct ec_verify_context * ctx) 841*f0865ec9SKyle Evans { 842*f0865ec9SKyle Evans /* Quirk to avoid unused variables */ 843*f0865ec9SKyle Evans FORCE_USED_VAR(ctx); 844*f0865ec9SKyle Evans 845*f0865ec9SKyle Evans /* Return an error in any case here */ 846*f0865ec9SKyle Evans return -1; 847*f0865ec9SKyle Evans } 848*f0865ec9SKyle Evans 849*f0865ec9SKyle Evans /* Unsupported batch verification */ 850*f0865ec9SKyle Evans int unsupported_verify_batch(const u8 **s, const u8 *s_len, const ec_pub_key **pub_keys, 851*f0865ec9SKyle Evans const u8 **m, const u32 *m_len, u32 num, ec_alg_type sig_type, 852*f0865ec9SKyle Evans hash_alg_type hash_type, const u8 **adata, const u16 *adata_len, 853*f0865ec9SKyle Evans verify_batch_scratch_pad *scratch_pad_area, u32 *scratch_pad_area_len) 854*f0865ec9SKyle Evans { 855*f0865ec9SKyle Evans /* Quirk to avoid unused variables */ 856*f0865ec9SKyle Evans FORCE_USED_VAR(s); 857*f0865ec9SKyle Evans FORCE_USED_VAR(pub_keys); 858*f0865ec9SKyle Evans FORCE_USED_VAR(m); 859*f0865ec9SKyle Evans FORCE_USED_VAR(num); 860*f0865ec9SKyle Evans FORCE_USED_VAR(sig_type); 861*f0865ec9SKyle Evans FORCE_USED_VAR(hash_type); 862*f0865ec9SKyle Evans FORCE_USED_VAR(adata); 863*f0865ec9SKyle Evans FORCE_USED_VAR(s_len); 864*f0865ec9SKyle Evans FORCE_USED_VAR(m_len); 865*f0865ec9SKyle Evans FORCE_USED_VAR(adata_len); 866*f0865ec9SKyle Evans FORCE_USED_VAR(scratch_pad_area); 867*f0865ec9SKyle Evans FORCE_USED_VAR(scratch_pad_area_len); 868*f0865ec9SKyle Evans 869*f0865ec9SKyle Evans /* Return an error in any case here */ 870*f0865ec9SKyle Evans return -1; 871*f0865ec9SKyle Evans } 872*f0865ec9SKyle Evans 873*f0865ec9SKyle Evans /* This function returns 1 in 'check' if the init/update/finalize mode 874*f0865ec9SKyle Evans * is supported by the signature algorithm, 0 otherwise. 875*f0865ec9SKyle Evans * 876*f0865ec9SKyle Evans * Return value is 0 on success, -1 on error. 'check' is only meaningful on 877*f0865ec9SKyle Evans * success. 878*f0865ec9SKyle Evans */ 879*f0865ec9SKyle Evans int is_sign_streaming_mode_supported(ec_alg_type sig_type, int *check) 880*f0865ec9SKyle Evans { 881*f0865ec9SKyle Evans int ret; 882*f0865ec9SKyle Evans const ec_sig_mapping *sig; 883*f0865ec9SKyle Evans 884*f0865ec9SKyle Evans MUST_HAVE((check != NULL), ret, err); 885*f0865ec9SKyle Evans 886*f0865ec9SKyle Evans ret = get_sig_by_type(sig_type, &sig); EG(ret, err); 887*f0865ec9SKyle Evans MUST_HAVE((sig != NULL), ret, err); 888*f0865ec9SKyle Evans 889*f0865ec9SKyle Evans if ((sig->sign_init == unsupported_sign_init) || 890*f0865ec9SKyle Evans (sig->sign_update == unsupported_sign_update) || 891*f0865ec9SKyle Evans (sig->sign_finalize == unsupported_sign_finalize)) { 892*f0865ec9SKyle Evans (*check) = 0; 893*f0865ec9SKyle Evans } 894*f0865ec9SKyle Evans else{ 895*f0865ec9SKyle Evans (*check) = 1; 896*f0865ec9SKyle Evans } 897*f0865ec9SKyle Evans 898*f0865ec9SKyle Evans err: 899*f0865ec9SKyle Evans return ret; 900*f0865ec9SKyle Evans } 901*f0865ec9SKyle Evans 902*f0865ec9SKyle Evans /* This function returns 1 in 'check' if the init/update/finalize mode 903*f0865ec9SKyle Evans * is supported by the verification algorithm, 0 otherwise. 904*f0865ec9SKyle Evans * 905*f0865ec9SKyle Evans * Return value is 0 on success, -1 on error. 'check' is only meaningful on 906*f0865ec9SKyle Evans * success. 907*f0865ec9SKyle Evans */ 908*f0865ec9SKyle Evans int is_verify_streaming_mode_supported(ec_alg_type sig_type, int *check) 909*f0865ec9SKyle Evans { 910*f0865ec9SKyle Evans int ret; 911*f0865ec9SKyle Evans const ec_sig_mapping *sig; 912*f0865ec9SKyle Evans 913*f0865ec9SKyle Evans MUST_HAVE((check != NULL), ret, err); 914*f0865ec9SKyle Evans 915*f0865ec9SKyle Evans ret = get_sig_by_type(sig_type, &sig); EG(ret, err); 916*f0865ec9SKyle Evans MUST_HAVE((sig != NULL), ret, err); 917*f0865ec9SKyle Evans 918*f0865ec9SKyle Evans if ((sig->verify_init == unsupported_verify_init) || 919*f0865ec9SKyle Evans (sig->verify_update == unsupported_verify_update) || 920*f0865ec9SKyle Evans (sig->verify_finalize == unsupported_verify_finalize)) { 921*f0865ec9SKyle Evans (*check) = 0; 922*f0865ec9SKyle Evans } 923*f0865ec9SKyle Evans else{ 924*f0865ec9SKyle Evans (*check) = 1; 925*f0865ec9SKyle Evans } 926*f0865ec9SKyle Evans 927*f0865ec9SKyle Evans err: 928*f0865ec9SKyle Evans return ret; 929*f0865ec9SKyle Evans } 930*f0865ec9SKyle Evans 931*f0865ec9SKyle Evans /* This function returns 1 in 'check' if the batch verification mode 932*f0865ec9SKyle Evans * is supported by the verification algorithm, 0 otherwise. 933*f0865ec9SKyle Evans * 934*f0865ec9SKyle Evans * Return value is 0 on success, -1 on error. 'check' is only meaningful on 935*f0865ec9SKyle Evans * success. 936*f0865ec9SKyle Evans */ 937*f0865ec9SKyle Evans int is_verify_batch_mode_supported(ec_alg_type sig_type, int *check) 938*f0865ec9SKyle Evans { 939*f0865ec9SKyle Evans int ret; 940*f0865ec9SKyle Evans const ec_sig_mapping *sig; 941*f0865ec9SKyle Evans 942*f0865ec9SKyle Evans MUST_HAVE((check != NULL), ret, err); 943*f0865ec9SKyle Evans 944*f0865ec9SKyle Evans ret = get_sig_by_type(sig_type, &sig); EG(ret, err); 945*f0865ec9SKyle Evans MUST_HAVE((sig != NULL), ret, err); 946*f0865ec9SKyle Evans 947*f0865ec9SKyle Evans if (sig->verify_batch == unsupported_verify_batch) { 948*f0865ec9SKyle Evans (*check) = 0; 949*f0865ec9SKyle Evans } 950*f0865ec9SKyle Evans else{ 951*f0865ec9SKyle Evans (*check) = 1; 952*f0865ec9SKyle Evans } 953*f0865ec9SKyle Evans 954*f0865ec9SKyle Evans err: 955*f0865ec9SKyle Evans return ret; 956*f0865ec9SKyle Evans } 957*f0865ec9SKyle Evans 958*f0865ec9SKyle Evans /* Tells if the signature scheme is deterministic or not, 959*f0865ec9SKyle Evans * e.g. if random nonces are used to produce signatures. 960*f0865ec9SKyle Evans * 961*f0865ec9SKyle Evans * 'check' is set to 1 if deterministic, 0 otherwise. 962*f0865ec9SKyle Evans * 963*f0865ec9SKyle Evans * Return value is 0 on success, -1 on error. 'check' is only meaningful on 964*f0865ec9SKyle Evans * success. 965*f0865ec9SKyle Evans 966*f0865ec9SKyle Evans */ 967*f0865ec9SKyle Evans int is_sign_deterministic(ec_alg_type sig_type, int *check) 968*f0865ec9SKyle Evans { 969*f0865ec9SKyle Evans int ret; 970*f0865ec9SKyle Evans const ec_sig_mapping *sig; 971*f0865ec9SKyle Evans 972*f0865ec9SKyle Evans MUST_HAVE((check != NULL), ret, err); 973*f0865ec9SKyle Evans 974*f0865ec9SKyle Evans ret = get_sig_by_type(sig_type, &sig); EG(ret, err); 975*f0865ec9SKyle Evans MUST_HAVE((sig != NULL), ret, err); 976*f0865ec9SKyle Evans 977*f0865ec9SKyle Evans switch(sig_type) { 978*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519) 979*f0865ec9SKyle Evans case EDDSA25519: 980*f0865ec9SKyle Evans case EDDSA25519CTX: 981*f0865ec9SKyle Evans case EDDSA25519PH: 982*f0865ec9SKyle Evans (*check) = 1; 983*f0865ec9SKyle Evans break; 984*f0865ec9SKyle Evans #endif 985*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 986*f0865ec9SKyle Evans case EDDSA448: 987*f0865ec9SKyle Evans case EDDSA448PH: 988*f0865ec9SKyle Evans (*check) = 1; 989*f0865ec9SKyle Evans break; 990*f0865ec9SKyle Evans #endif 991*f0865ec9SKyle Evans #if defined(WITH_SIG_DECDSA) 992*f0865ec9SKyle Evans case DECDSA: 993*f0865ec9SKyle Evans (*check) = 1; 994*f0865ec9SKyle Evans break; 995*f0865ec9SKyle Evans #endif 996*f0865ec9SKyle Evans default: 997*f0865ec9SKyle Evans (*check) = 0; 998*f0865ec9SKyle Evans break; 999*f0865ec9SKyle Evans } 1000*f0865ec9SKyle Evans 1001*f0865ec9SKyle Evans err: 1002*f0865ec9SKyle Evans return ret; 1003*f0865ec9SKyle Evans } 1004*f0865ec9SKyle Evans 1005*f0865ec9SKyle Evans 1006*f0865ec9SKyle Evans /* 1007*f0865ec9SKyle Evans * Bubble sort the table of numbers and the table of projective points 1008*f0865ec9SKyle Evans * accordingly in ascending order. We only work on index numbers in the table 1009*f0865ec9SKyle Evans * to avoid useless copies. 1010*f0865ec9SKyle Evans */ 1011*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int _bubble_sort(verify_batch_scratch_pad *elements, u32 num) 1012*f0865ec9SKyle Evans { 1013*f0865ec9SKyle Evans u32 i, j; 1014*f0865ec9SKyle Evans int ret, swapped; 1015*f0865ec9SKyle Evans 1016*f0865ec9SKyle Evans MUST_HAVE((elements != NULL), ret, err); 1017*f0865ec9SKyle Evans MUST_HAVE((num >= 1), ret, err); 1018*f0865ec9SKyle Evans for(i = 0; i < (num - 1); i++){ 1019*f0865ec9SKyle Evans swapped = 0; 1020*f0865ec9SKyle Evans for(j = 0; j < (num - i - 1); j++){ 1021*f0865ec9SKyle Evans int check; 1022*f0865ec9SKyle Evans u32 indexj, indexj_next; 1023*f0865ec9SKyle Evans indexj = elements[j].index; 1024*f0865ec9SKyle Evans indexj_next = elements[j + 1].index; 1025*f0865ec9SKyle Evans ret = nn_cmp(&elements[indexj].number, &elements[indexj_next].number, &check); EG(ret, err); 1026*f0865ec9SKyle Evans if(check < 0){ 1027*f0865ec9SKyle Evans /* Swap the two elements */ 1028*f0865ec9SKyle Evans elements[j].index = indexj_next; 1029*f0865ec9SKyle Evans elements[j + 1].index = indexj; 1030*f0865ec9SKyle Evans swapped = 1; 1031*f0865ec9SKyle Evans } 1032*f0865ec9SKyle Evans } 1033*f0865ec9SKyle Evans /* If no swap occured in the inner loop, get out */ 1034*f0865ec9SKyle Evans if(!swapped){ 1035*f0865ec9SKyle Evans break; 1036*f0865ec9SKyle Evans } 1037*f0865ec9SKyle Evans } 1038*f0865ec9SKyle Evans 1039*f0865ec9SKyle Evans ret = 0; 1040*f0865ec9SKyle Evans err: 1041*f0865ec9SKyle Evans return ret; 1042*f0865ec9SKyle Evans } 1043*f0865ec9SKyle Evans 1044*f0865ec9SKyle Evans /* 1045*f0865ec9SKyle Evans * Bos-Coster algorithm, presented e.g. in https://ed25519.cr.yp.to/ed25519-20110705.pdf 1046*f0865ec9SKyle Evans * 1047*f0865ec9SKyle Evans * The Bos-Coster algorithm allows to optimize a sum of multi-scalar multiplications using 1048*f0865ec9SKyle Evans * addition chains. This is used for example in batch signature verification of schemes 1049*f0865ec9SKyle Evans * that support it. 1050*f0865ec9SKyle Evans * 1051*f0865ec9SKyle Evans */ 1052*f0865ec9SKyle Evans int ec_verify_bos_coster(verify_batch_scratch_pad *elements, u32 num, bitcnt_t bits) 1053*f0865ec9SKyle Evans { 1054*f0865ec9SKyle Evans int ret, check; 1055*f0865ec9SKyle Evans u32 i, index0, index1, max_bos_coster_iterations; 1056*f0865ec9SKyle Evans 1057*f0865ec9SKyle Evans MUST_HAVE((elements != NULL), ret, err); 1058*f0865ec9SKyle Evans MUST_HAVE((num > 1), ret, err); 1059*f0865ec9SKyle Evans 1060*f0865ec9SKyle Evans /* We fix our maximum attempts here. 1061*f0865ec9SKyle Evans * 1062*f0865ec9SKyle Evans * NOTE: this avoids "denial of service" when 1063*f0865ec9SKyle Evans * providing scalars with too big discrepancies, as 1064*f0865ec9SKyle Evans * the Bos-Coster algorithm supposes uniformly randomized 1065*f0865ec9SKyle Evans * numbers ... 1066*f0865ec9SKyle Evans * If we are provided with scalars with too big differences, 1067*f0865ec9SKyle Evans * we end up looping for a very long time. In this case, we 1068*f0865ec9SKyle Evans * rather quit with a specific error. 1069*f0865ec9SKyle Evans * 1070*f0865ec9SKyle Evans * The limit hereafter is fixed using the mean asymptotic complexity 1071*f0865ec9SKyle Evans * of the algorithm in the nominal case (multiplied by the bit size 1072*f0865ec9SKyle Evans * of num to be lax). 1073*f0865ec9SKyle Evans */ 1074*f0865ec9SKyle Evans MUST_HAVE((num * bits) >= num, ret, err); 1075*f0865ec9SKyle Evans MUST_HAVE((num * bits) >= bits, ret, err); 1076*f0865ec9SKyle Evans max_bos_coster_iterations = (num * bits); 1077*f0865ec9SKyle Evans 1078*f0865ec9SKyle Evans /********************************************/ 1079*f0865ec9SKyle Evans /****** Bos-Coster algorithm ****************/ 1080*f0865ec9SKyle Evans for(i = 0; i < num; i++){ 1081*f0865ec9SKyle Evans elements[i].index = i; 1082*f0865ec9SKyle Evans } 1083*f0865ec9SKyle Evans i = 0; 1084*f0865ec9SKyle Evans do { 1085*f0865ec9SKyle Evans /* Sort the elements in descending order */ 1086*f0865ec9SKyle Evans ret = _bubble_sort(elements, num); EG(ret, err); 1087*f0865ec9SKyle Evans /* Perform the addition */ 1088*f0865ec9SKyle Evans index0 = elements[0].index; 1089*f0865ec9SKyle Evans index1 = elements[1].index; 1090*f0865ec9SKyle Evans ret = prj_pt_add(&elements[index1].point, &elements[index0].point, 1091*f0865ec9SKyle Evans &elements[index1].point); EG(ret, err); 1092*f0865ec9SKyle Evans /* Check the two first integers */ 1093*f0865ec9SKyle Evans ret = nn_cmp(&elements[index0].number, &elements[index1].number, &check); 1094*f0865ec9SKyle Evans /* Subtract the two first numbers */ 1095*f0865ec9SKyle Evans ret = nn_sub(&elements[index0].number, &elements[index0].number, 1096*f0865ec9SKyle Evans &elements[index1].number); EG(ret, err); 1097*f0865ec9SKyle Evans i++; 1098*f0865ec9SKyle Evans if(i > max_bos_coster_iterations){ 1099*f0865ec9SKyle Evans /* Give up with specific error code */ 1100*f0865ec9SKyle Evans ret = -2; 1101*f0865ec9SKyle Evans goto err; 1102*f0865ec9SKyle Evans } 1103*f0865ec9SKyle Evans } while(check > 0); 1104*f0865ec9SKyle Evans 1105*f0865ec9SKyle Evans index0 = elements[0].index; 1106*f0865ec9SKyle Evans /* Proceed with the last scalar multiplication */ 1107*f0865ec9SKyle Evans ret = _prj_pt_unprotected_mult(&elements[index0].point, &elements[index0].number, &elements[index0].point); 1108*f0865ec9SKyle Evans 1109*f0865ec9SKyle Evans /* The result is in point [0] of elements */ 1110*f0865ec9SKyle Evans err: 1111*f0865ec9SKyle Evans return ret; 1112*f0865ec9SKyle Evans } 1113