1*f0865ec9SKyle Evans /* 2*f0865ec9SKyle Evans * Copyright (C) 2021 - This file is part of libecc project 3*f0865ec9SKyle Evans * 4*f0865ec9SKyle Evans * Authors: 5*f0865ec9SKyle Evans * Ryad BENADJILA <ryadbenadjila@gmail.com> 6*f0865ec9SKyle Evans * Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr> 7*f0865ec9SKyle Evans * 8*f0865ec9SKyle Evans * This software is licensed under a dual BSD and GPL v2 license. 9*f0865ec9SKyle Evans * See LICENSE file at the root folder of the project. 10*f0865ec9SKyle Evans */ 11*f0865ec9SKyle Evans #include <libecc/lib_ecc_config.h> 12*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519) || defined(WITH_SIG_EDDSA448) 13*f0865ec9SKyle Evans 14*f0865ec9SKyle Evans /* 15*f0865ec9SKyle Evans * XXX: EdDSA is incompatible with small stack devices for now ... 16*f0865ec9SKyle Evans */ 17*f0865ec9SKyle Evans #if defined(USE_SMALL_STACK) 18*f0865ec9SKyle Evans #error "Error: EDDSA25519 and EDDSA448 are incompatible with USE_SMALL_STACK (devices low on memory)" 19*f0865ec9SKyle Evans #endif 20*f0865ec9SKyle Evans 21*f0865ec9SKyle Evans /* 22*f0865ec9SKyle Evans * Sanity checks on the hash functions and curves depending on the EdDSA variant. 23*f0865ec9SKyle Evans */ 24*f0865ec9SKyle Evans /* EDDSA25519 used SHA-512 as a fixed hash function and WEI25519 as a fixed 25*f0865ec9SKyle Evans * curve. 26*f0865ec9SKyle Evans */ 27*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519) 28*f0865ec9SKyle Evans #if !defined(WITH_HASH_SHA512) || !defined(WITH_CURVE_WEI25519) 29*f0865ec9SKyle Evans #error "Error: EDDSA25519 needs SHA-512 and WEI25519 to be defined! Please define them in libecc config file" 30*f0865ec9SKyle Evans #endif 31*f0865ec9SKyle Evans #endif 32*f0865ec9SKyle Evans /* EDDSA448 used SHAKE256 as a fixed hash function and WEI448 as a fixed 33*f0865ec9SKyle Evans * curve. 34*f0865ec9SKyle Evans */ 35*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 36*f0865ec9SKyle Evans #if !defined(WITH_HASH_SHAKE256) || !defined(WITH_CURVE_WEI448) 37*f0865ec9SKyle Evans #error "Error: EDDSA25519 needs SHAKE256 and WEI448 to be defined! Please define them in libecc config file" 38*f0865ec9SKyle Evans #endif 39*f0865ec9SKyle Evans #endif 40*f0865ec9SKyle Evans 41*f0865ec9SKyle Evans #include <libecc/nn/nn_rand.h> 42*f0865ec9SKyle Evans #include <libecc/nn/nn_mul_public.h> 43*f0865ec9SKyle Evans #include <libecc/nn/nn_logical.h> 44*f0865ec9SKyle Evans #include <libecc/fp/fp.h> 45*f0865ec9SKyle Evans #include <libecc/fp/fp_sqrt.h> 46*f0865ec9SKyle Evans /* Include the "internal" header as we use non public API here */ 47*f0865ec9SKyle Evans #include "../nn/nn_div.h" 48*f0865ec9SKyle Evans 49*f0865ec9SKyle Evans 50*f0865ec9SKyle Evans #include <libecc/sig/sig_algs_internal.h> 51*f0865ec9SKyle Evans #include <libecc/sig/sig_algs.h> 52*f0865ec9SKyle Evans #include <libecc/sig/ec_key.h> 53*f0865ec9SKyle Evans #include <libecc/utils/utils.h> 54*f0865ec9SKyle Evans #ifdef VERBOSE_INNER_VALUES 55*f0865ec9SKyle Evans #define EC_SIG_ALG "EDDSA" 56*f0865ec9SKyle Evans #endif 57*f0865ec9SKyle Evans #include <libecc/utils/dbg_sig.h> 58*f0865ec9SKyle Evans 59*f0865ec9SKyle Evans 60*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static inline int dom(u16 x, const u8 *y, u16 olen_y, const hash_mapping *h, 61*f0865ec9SKyle Evans hash_context *h_ctx, u8 dom_type){ 62*f0865ec9SKyle Evans u8 tmp[2]; 63*f0865ec9SKyle Evans int ret; 64*f0865ec9SKyle Evans 65*f0865ec9SKyle Evans MUST_HAVE((h != NULL) && (h_ctx != NULL), ret, err); 66*f0865ec9SKyle Evans /* Sanity check on ancillary data len, its size must not exceed 255 bytes as per RFC8032 */ 67*f0865ec9SKyle Evans MUST_HAVE((x <= 255) && (olen_y <= 255), ret, err); 68*f0865ec9SKyle Evans 69*f0865ec9SKyle Evans if(dom_type == 2){ 70*f0865ec9SKyle Evans ret = h->hfunc_update(h_ctx, (const u8*)"SigEd25519 no Ed25519 collisions", 32); EG(ret, err); 71*f0865ec9SKyle Evans } 72*f0865ec9SKyle Evans else if(dom_type == 4){ 73*f0865ec9SKyle Evans ret = h->hfunc_update(h_ctx, (const u8*)"SigEd448", 8); EG(ret, err); 74*f0865ec9SKyle Evans } 75*f0865ec9SKyle Evans else{ 76*f0865ec9SKyle Evans ret = -1; 77*f0865ec9SKyle Evans goto err; 78*f0865ec9SKyle Evans } 79*f0865ec9SKyle Evans tmp[0] = (u8)x; 80*f0865ec9SKyle Evans tmp[1] = (u8)olen_y; 81*f0865ec9SKyle Evans ret = h->hfunc_update(h_ctx, tmp, 2); EG(ret, err); 82*f0865ec9SKyle Evans if(y != NULL){ 83*f0865ec9SKyle Evans ret = h->hfunc_update(h_ctx, y, olen_y); EG(ret, err); 84*f0865ec9SKyle Evans } 85*f0865ec9SKyle Evans 86*f0865ec9SKyle Evans err: 87*f0865ec9SKyle Evans return ret; 88*f0865ec9SKyle Evans } 89*f0865ec9SKyle Evans 90*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519) 91*f0865ec9SKyle Evans /* Helper for dom2(x, y). 92*f0865ec9SKyle Evans * 93*f0865ec9SKyle Evans * See RFC8032: 94*f0865ec9SKyle Evans * 95*f0865ec9SKyle Evans * dom2(x, y) The blank octet string when signing or verifying 96*f0865ec9SKyle Evans * Ed25519. Otherwise, the octet string: "SigEd25519 no 97*f0865ec9SKyle Evans * Ed25519 collisions" || octet(x) || octet(OLEN(y)) || 98*f0865ec9SKyle Evans * y, where x is in range 0-255 and y is an octet string 99*f0865ec9SKyle Evans * of at most 255 octets. "SigEd25519 no Ed25519 100*f0865ec9SKyle Evans * collisions" is in ASCII (32 octets). 101*f0865ec9SKyle Evans */ 102*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static inline int dom2(u16 x, const u8 *y, u16 olen_y, const hash_mapping *h, 103*f0865ec9SKyle Evans hash_context *h_ctx){ 104*f0865ec9SKyle Evans return dom(x, y, olen_y, h, h_ctx, 2); 105*f0865ec9SKyle Evans } 106*f0865ec9SKyle Evans #endif /* defined(WITH_SIG_EDDSA25519) */ 107*f0865ec9SKyle Evans 108*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 109*f0865ec9SKyle Evans /* Helper for dom4(x, y). 110*f0865ec9SKyle Evans * 111*f0865ec9SKyle Evans * See RFC8032: 112*f0865ec9SKyle Evans * 113*f0865ec9SKyle Evans * dom4(x, y) The octet string "SigEd448" || octet(x) || 114*f0865ec9SKyle Evans * octet(OLEN(y)) || y, where x is in range 0-255 and y 115*f0865ec9SKyle Evans * is an octet string of at most 255 octets. "SigEd448" 116*f0865ec9SKyle Evans * is in ASCII (8 octets). 117*f0865ec9SKyle Evans */ 118*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static inline int dom4(u16 x, const u8 *y, u16 olen_y, const hash_mapping *h, 119*f0865ec9SKyle Evans hash_context *h_ctx){ 120*f0865ec9SKyle Evans return dom(x, y, olen_y, h, h_ctx, 4); 121*f0865ec9SKyle Evans } 122*f0865ec9SKyle Evans #endif /* defined(WITH_SIG_EDDSA448) */ 123*f0865ec9SKyle Evans 124*f0865ec9SKyle Evans /* EdDSA sanity check on keys. 125*f0865ec9SKyle Evans * EDDSA25519 and variants only support WEI25519 as a curve, and SHA-512 as a hash function. 126*f0865ec9SKyle Evans * EDDSA448 and variants only support WEI448 as a curve, and SHAKE256 as a "hash function". 127*f0865ec9SKyle Evans */ 128*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static inline hash_alg_type get_eddsa_hash_type(ec_alg_type sig_type){ 129*f0865ec9SKyle Evans hash_alg_type hash_type = UNKNOWN_HASH_ALG; 130*f0865ec9SKyle Evans 131*f0865ec9SKyle Evans switch (sig_type) { 132*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519) 133*f0865ec9SKyle Evans case EDDSA25519: 134*f0865ec9SKyle Evans case EDDSA25519PH: 135*f0865ec9SKyle Evans case EDDSA25519CTX:{ 136*f0865ec9SKyle Evans hash_type = SHA512; 137*f0865ec9SKyle Evans break; 138*f0865ec9SKyle Evans } 139*f0865ec9SKyle Evans #endif 140*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 141*f0865ec9SKyle Evans case EDDSA448: 142*f0865ec9SKyle Evans case EDDSA448PH:{ 143*f0865ec9SKyle Evans hash_type = SHAKE256; 144*f0865ec9SKyle Evans break; 145*f0865ec9SKyle Evans } 146*f0865ec9SKyle Evans #endif 147*f0865ec9SKyle Evans default:{ 148*f0865ec9SKyle Evans hash_type = UNKNOWN_HASH_ALG; 149*f0865ec9SKyle Evans break; 150*f0865ec9SKyle Evans } 151*f0865ec9SKyle Evans } 152*f0865ec9SKyle Evans return hash_type; 153*f0865ec9SKyle Evans } 154*f0865ec9SKyle Evans 155*f0865ec9SKyle Evans /* 156*f0865ec9SKyle Evans * Check given EdDSA key type does match given curve type. Returns 0 on success, 157*f0865ec9SKyle Evans * and -1 on error. 158*f0865ec9SKyle Evans */ 159*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int eddsa_key_type_check_curve(ec_alg_type key_type, 160*f0865ec9SKyle Evans ec_curve_type curve_type) 161*f0865ec9SKyle Evans { 162*f0865ec9SKyle Evans int ret; 163*f0865ec9SKyle Evans 164*f0865ec9SKyle Evans switch (key_type) { 165*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519) 166*f0865ec9SKyle Evans case EDDSA25519: 167*f0865ec9SKyle Evans case EDDSA25519PH: 168*f0865ec9SKyle Evans case EDDSA25519CTX:{ 169*f0865ec9SKyle Evans /* Check curve */ 170*f0865ec9SKyle Evans ret = (curve_type == WEI25519) ? 0 : -1; 171*f0865ec9SKyle Evans break; 172*f0865ec9SKyle Evans } 173*f0865ec9SKyle Evans #endif 174*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 175*f0865ec9SKyle Evans case EDDSA448: 176*f0865ec9SKyle Evans case EDDSA448PH:{ 177*f0865ec9SKyle Evans /* Check curve */ 178*f0865ec9SKyle Evans ret = (curve_type == WEI448) ? 0 : -1; 179*f0865ec9SKyle Evans break; 180*f0865ec9SKyle Evans } 181*f0865ec9SKyle Evans #endif 182*f0865ec9SKyle Evans default:{ 183*f0865ec9SKyle Evans ret = -1; 184*f0865ec9SKyle Evans break; 185*f0865ec9SKyle Evans } 186*f0865ec9SKyle Evans } 187*f0865ec9SKyle Evans 188*f0865ec9SKyle Evans return ret; 189*f0865ec9SKyle Evans } 190*f0865ec9SKyle Evans 191*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int eddsa_priv_key_sanity_check(const ec_priv_key *in_priv) 192*f0865ec9SKyle Evans { 193*f0865ec9SKyle Evans int ret; 194*f0865ec9SKyle Evans 195*f0865ec9SKyle Evans ret = priv_key_check_initialized(in_priv); EG(ret, err); 196*f0865ec9SKyle Evans ret = eddsa_key_type_check_curve(in_priv->key_type, 197*f0865ec9SKyle Evans in_priv->params->curve_type); 198*f0865ec9SKyle Evans 199*f0865ec9SKyle Evans err: 200*f0865ec9SKyle Evans return ret; 201*f0865ec9SKyle Evans } 202*f0865ec9SKyle Evans 203*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int eddsa_pub_key_sanity_check(const ec_pub_key *in_pub) 204*f0865ec9SKyle Evans { 205*f0865ec9SKyle Evans int ret; 206*f0865ec9SKyle Evans 207*f0865ec9SKyle Evans 208*f0865ec9SKyle Evans ret = pub_key_check_initialized(in_pub); EG(ret, err); 209*f0865ec9SKyle Evans ret = eddsa_key_type_check_curve(in_pub->key_type, 210*f0865ec9SKyle Evans in_pub->params->curve_type); 211*f0865ec9SKyle Evans 212*f0865ec9SKyle Evans err: 213*f0865ec9SKyle Evans return ret; 214*f0865ec9SKyle Evans } 215*f0865ec9SKyle Evans 216*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int eddsa_key_pair_sanity_check(const ec_key_pair *key_pair) 217*f0865ec9SKyle Evans { 218*f0865ec9SKyle Evans int ret; 219*f0865ec9SKyle Evans 220*f0865ec9SKyle Evans MUST_HAVE((key_pair != NULL), ret, err); 221*f0865ec9SKyle Evans ret = eddsa_priv_key_sanity_check(&(key_pair->priv_key)); EG(ret, err); 222*f0865ec9SKyle Evans ret = eddsa_pub_key_sanity_check(&(key_pair->pub_key)); EG(ret, err); 223*f0865ec9SKyle Evans MUST_HAVE((key_pair->priv_key.key_type == key_pair->pub_key.key_type), ret, err); 224*f0865ec9SKyle Evans 225*f0865ec9SKyle Evans err: 226*f0865ec9SKyle Evans return ret; 227*f0865ec9SKyle Evans } 228*f0865ec9SKyle Evans 229*f0865ec9SKyle Evans /* 230*f0865ec9SKyle Evans * EdDSA decode an integer from a buffer using little endian format. 231*f0865ec9SKyle Evans */ 232*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int eddsa_decode_integer(nn_t nn_out, const u8 *buf, u16 buf_size) 233*f0865ec9SKyle Evans { 234*f0865ec9SKyle Evans u16 i; 235*f0865ec9SKyle Evans u8 buf_little_endian[MAX_DIGEST_SIZE]; 236*f0865ec9SKyle Evans int ret; 237*f0865ec9SKyle Evans 238*f0865ec9SKyle Evans MUST_HAVE((buf != NULL), ret, err); 239*f0865ec9SKyle Evans MUST_HAVE((sizeof(buf_little_endian) >= buf_size), ret, err); 240*f0865ec9SKyle Evans 241*f0865ec9SKyle Evans ret = nn_init(nn_out, 0); EG(ret, err); 242*f0865ec9SKyle Evans 243*f0865ec9SKyle Evans ret = local_memset(buf_little_endian, 0, sizeof(buf_little_endian)); EG(ret, err); 244*f0865ec9SKyle Evans if(buf_size > 1){ 245*f0865ec9SKyle Evans /* Inverse endianness of our input buffer */ 246*f0865ec9SKyle Evans for(i = 0; i < buf_size; i++){ 247*f0865ec9SKyle Evans buf_little_endian[i] = buf[buf_size - 1 - i]; 248*f0865ec9SKyle Evans } 249*f0865ec9SKyle Evans } 250*f0865ec9SKyle Evans 251*f0865ec9SKyle Evans /* Compute an integer from the buffer */ 252*f0865ec9SKyle Evans ret = nn_init_from_buf(nn_out, buf_little_endian, buf_size); 253*f0865ec9SKyle Evans 254*f0865ec9SKyle Evans err: 255*f0865ec9SKyle Evans return ret; 256*f0865ec9SKyle Evans } 257*f0865ec9SKyle Evans 258*f0865ec9SKyle Evans /* 259*f0865ec9SKyle Evans * EdDSA encode an integer to a buffer using little endian format. 260*f0865ec9SKyle Evans */ 261*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int eddsa_encode_integer(nn_src_t nn_in, u8 *buf, u16 buf_size) 262*f0865ec9SKyle Evans { 263*f0865ec9SKyle Evans u16 i; 264*f0865ec9SKyle Evans u8 tmp; 265*f0865ec9SKyle Evans int ret; 266*f0865ec9SKyle Evans bitcnt_t blen; 267*f0865ec9SKyle Evans 268*f0865ec9SKyle Evans MUST_HAVE((buf != NULL), ret, err); 269*f0865ec9SKyle Evans ret = nn_check_initialized(nn_in); EG(ret, err); 270*f0865ec9SKyle Evans 271*f0865ec9SKyle Evans /* Sanity check that we do not lose information */ 272*f0865ec9SKyle Evans ret = nn_bitlen(nn_in, &blen); EG(ret, err); 273*f0865ec9SKyle Evans MUST_HAVE((((u32)blen) <= (8 * (u32)buf_size)), ret, err); 274*f0865ec9SKyle Evans 275*f0865ec9SKyle Evans /* Export the number to our buffer */ 276*f0865ec9SKyle Evans ret = nn_export_to_buf(buf, buf_size, nn_in); EG(ret, err); 277*f0865ec9SKyle Evans 278*f0865ec9SKyle Evans /* Now reverse endianness in place */ 279*f0865ec9SKyle Evans if(buf_size > 1){ 280*f0865ec9SKyle Evans for(i = 0; i < (buf_size / 2); i++){ 281*f0865ec9SKyle Evans tmp = buf[i]; 282*f0865ec9SKyle Evans buf[i] = buf[buf_size - 1 - i]; 283*f0865ec9SKyle Evans buf[buf_size - 1 - i] = tmp; 284*f0865ec9SKyle Evans } 285*f0865ec9SKyle Evans } 286*f0865ec9SKyle Evans 287*f0865ec9SKyle Evans err: 288*f0865ec9SKyle Evans return ret; 289*f0865ec9SKyle Evans } 290*f0865ec9SKyle Evans 291*f0865ec9SKyle Evans /* 292*f0865ec9SKyle Evans * EdDSA encoding of scalar s. 293*f0865ec9SKyle Evans */ 294*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int eddsa_compute_s(nn_t s, const u8 *digest, u16 digest_size) 295*f0865ec9SKyle Evans { 296*f0865ec9SKyle Evans int ret; 297*f0865ec9SKyle Evans 298*f0865ec9SKyle Evans MUST_HAVE((digest != NULL), ret, err); 299*f0865ec9SKyle Evans MUST_HAVE(((digest_size % 2) == 0), ret, err); 300*f0865ec9SKyle Evans 301*f0865ec9SKyle Evans /* s is half of the digest size encoded in little endian format */ 302*f0865ec9SKyle Evans ret = eddsa_decode_integer(s, digest, (digest_size / 2)); EG(ret, err); 303*f0865ec9SKyle Evans 304*f0865ec9SKyle Evans err: 305*f0865ec9SKyle Evans return ret; 306*f0865ec9SKyle Evans } 307*f0865ec9SKyle Evans 308*f0865ec9SKyle Evans /* Extract the digest from the encoded private key */ 309*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int eddsa_get_digest_from_priv_key(u8 *digest, u8 *digest_size, const ec_priv_key *in_priv) 310*f0865ec9SKyle Evans { 311*f0865ec9SKyle Evans int ret; 312*f0865ec9SKyle Evans hash_alg_type hash_type; 313*f0865ec9SKyle Evans const hash_mapping *hash; 314*f0865ec9SKyle Evans 315*f0865ec9SKyle Evans MUST_HAVE(((digest != NULL) && (digest_size != NULL)), ret, err); 316*f0865ec9SKyle Evans ret = eddsa_priv_key_sanity_check(in_priv); EG(ret, err); 317*f0865ec9SKyle Evans 318*f0865ec9SKyle Evans MUST_HAVE(((hash_type = get_eddsa_hash_type(in_priv->key_type)) != UNKNOWN_HASH_ALG), ret, err); 319*f0865ec9SKyle Evans ret = get_hash_by_type(hash_type, &hash); EG(ret, err); 320*f0865ec9SKyle Evans MUST_HAVE((hash != NULL), ret, err); 321*f0865ec9SKyle Evans 322*f0865ec9SKyle Evans /* Check real digest size */ 323*f0865ec9SKyle Evans MUST_HAVE(((*digest_size) >= hash->digest_size), ret, err); 324*f0865ec9SKyle Evans 325*f0865ec9SKyle Evans (*digest_size) = hash->digest_size; 326*f0865ec9SKyle Evans ret = nn_export_to_buf(digest, *digest_size, &(in_priv->x)); 327*f0865ec9SKyle Evans 328*f0865ec9SKyle Evans err: 329*f0865ec9SKyle Evans return ret; 330*f0865ec9SKyle Evans } 331*f0865ec9SKyle Evans 332*f0865ec9SKyle Evans /* Encode an Edwards curve affine point in canonical form */ 333*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int eddsa_encode_point(aff_pt_edwards_src_t in, 334*f0865ec9SKyle Evans fp_src_t alpha_edwards, 335*f0865ec9SKyle Evans u8 *buf, u16 buflen, 336*f0865ec9SKyle Evans ec_alg_type sig_alg) 337*f0865ec9SKyle Evans { 338*f0865ec9SKyle Evans nn out_reduced; 339*f0865ec9SKyle Evans u8 lsb = 0; 340*f0865ec9SKyle Evans int ret; 341*f0865ec9SKyle Evans out_reduced.magic = WORD(0); 342*f0865ec9SKyle Evans 343*f0865ec9SKyle Evans /* Sanity checks */ 344*f0865ec9SKyle Evans MUST_HAVE((buf != NULL), ret, err); 345*f0865ec9SKyle Evans ret = aff_pt_edwards_check_initialized(in); EG(ret, err); 346*f0865ec9SKyle Evans ret = fp_check_initialized(alpha_edwards); EG(ret, err); 347*f0865ec9SKyle Evans 348*f0865ec9SKyle Evans /* Zeroize the buffer */ 349*f0865ec9SKyle Evans ret = local_memset(buf, 0, buflen); EG(ret, err); 350*f0865ec9SKyle Evans ret = nn_init(&out_reduced, 0); EG(ret, err); 351*f0865ec9SKyle Evans 352*f0865ec9SKyle Evans /* Note: we should be reduced modulo Fp for canonical encoding here as 353*f0865ec9SKyle Evans * coordinate elements are in Fp ... 354*f0865ec9SKyle Evans */ 355*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 356*f0865ec9SKyle Evans if((sig_alg == EDDSA448) || (sig_alg == EDDSA448PH)){ 357*f0865ec9SKyle Evans /* 358*f0865ec9SKyle Evans * In case of EDDSA448, we apply the 4-isogeny to transfer from 359*f0865ec9SKyle Evans * Ed448 to Edwards448. 360*f0865ec9SKyle Evans * The isogeny maps (x, y) on Ed448 to (x1, y1) on Edwards448 361*f0865ec9SKyle Evans * using: 362*f0865ec9SKyle Evans * x1 = (4*x*y/c) / (y^2-x^2) 363*f0865ec9SKyle Evans * y1 = (2-x^2-y^2) / (x^2+y^2) = (2 - (x^2+y^2)) / (x^2 + y^2) 364*f0865ec9SKyle Evans * and (0, 1) as well as (0, -1) are mapped to (0, 1) 365*f0865ec9SKyle Evans * We only need to encode our y1 here, but x1 computation is 366*f0865ec9SKyle Evans * unfortunately needed to get its LSB that is necessary for 367*f0865ec9SKyle Evans * the encoding. 368*f0865ec9SKyle Evans */ 369*f0865ec9SKyle Evans fp tmp_x, tmp_y, y1; 370*f0865ec9SKyle Evans tmp_x.magic = tmp_y.magic = y1.magic = WORD(0); 371*f0865ec9SKyle Evans /* Compute x1 to get our LSB */ 372*f0865ec9SKyle Evans ret = fp_init(&y1, in->y.ctx); EG(ret, err1); 373*f0865ec9SKyle Evans ret = fp_copy(&tmp_x, &(in->x)); EG(ret, err1); 374*f0865ec9SKyle Evans ret = fp_sqr(&tmp_x, &tmp_x); EG(ret, err1); 375*f0865ec9SKyle Evans ret = fp_copy(&tmp_y, &(in->y)); EG(ret, err1); 376*f0865ec9SKyle Evans ret = fp_sqr(&tmp_y, &tmp_y); EG(ret, err1); 377*f0865ec9SKyle Evans ret = fp_sub(&tmp_y, &tmp_y, &tmp_x); EG(ret, err1); 378*f0865ec9SKyle Evans /* NOTE: inversion by zero should be caught by lower layers */ 379*f0865ec9SKyle Evans ret = fp_inv(&tmp_y, &tmp_y); EG(ret, err1); 380*f0865ec9SKyle Evans ret = fp_set_word_value(&tmp_x, WORD(4)); EG(ret, err1); 381*f0865ec9SKyle Evans ret = fp_mul(&tmp_x, &tmp_x, &(in->x)); EG(ret, err1); 382*f0865ec9SKyle Evans ret = fp_mul(&tmp_x, &tmp_x, &(in->y)); EG(ret, err1); 383*f0865ec9SKyle Evans ret = fp_mul(&tmp_x, &tmp_x, &tmp_y); EG(ret, err1); 384*f0865ec9SKyle Evans ret = fp_inv(&tmp_y, alpha_edwards); EG(ret, err1); 385*f0865ec9SKyle Evans ret = fp_mul(&tmp_x, &tmp_x, &tmp_y); EG(ret, err1); 386*f0865ec9SKyle Evans ret = nn_getbit(&(tmp_x.fp_val), 0, &lsb); EG(ret, err1); 387*f0865ec9SKyle Evans /* Compute y1 */ 388*f0865ec9SKyle Evans ret = fp_copy(&tmp_x, &(in->x)); EG(ret, err1); 389*f0865ec9SKyle Evans ret = fp_sqr(&tmp_x, &tmp_x); EG(ret, err1); 390*f0865ec9SKyle Evans ret = fp_copy(&tmp_y, &(in->y)); EG(ret, err1); 391*f0865ec9SKyle Evans ret = fp_sqr(&tmp_y, &tmp_y); EG(ret, err1); 392*f0865ec9SKyle Evans ret = fp_set_word_value(&y1, WORD(2)); EG(ret, err1); 393*f0865ec9SKyle Evans ret = fp_sub(&y1, &y1, &tmp_x); EG(ret, err1); 394*f0865ec9SKyle Evans ret = fp_sub(&y1, &y1, &tmp_y); EG(ret, err1); 395*f0865ec9SKyle Evans ret = fp_add(&tmp_x, &tmp_x, &tmp_y); EG(ret, err1); 396*f0865ec9SKyle Evans /* NOTE: inversion by zero should be caught by lower layers */ 397*f0865ec9SKyle Evans ret = fp_inv(&tmp_x, &tmp_x); EG(ret, err1); 398*f0865ec9SKyle Evans ret = fp_mul(&y1, &y1, &tmp_x); EG(ret, err1); 399*f0865ec9SKyle Evans ret = eddsa_encode_integer(&(y1.fp_val), buf, buflen); 400*f0865ec9SKyle Evans err1: 401*f0865ec9SKyle Evans fp_uninit(&tmp_x); 402*f0865ec9SKyle Evans fp_uninit(&tmp_y); 403*f0865ec9SKyle Evans fp_uninit(&y1); 404*f0865ec9SKyle Evans EG(ret, err); 405*f0865ec9SKyle Evans } 406*f0865ec9SKyle Evans else 407*f0865ec9SKyle Evans #endif /* !defined(WITH_SIG_EDDSA448) */ 408*f0865ec9SKyle Evans { /* EDDSA25519 and other cases */ 409*f0865ec9SKyle Evans FORCE_USED_VAR(sig_alg); /* To avoid unused variable error */ 410*f0865ec9SKyle Evans ret = nn_getbit(&(in->x.fp_val), 0, &lsb); EG(ret, err); 411*f0865ec9SKyle Evans ret = eddsa_encode_integer(&(in->y.fp_val), buf, buflen); EG(ret, err); 412*f0865ec9SKyle Evans } 413*f0865ec9SKyle Evans /* 414*f0865ec9SKyle Evans * Now deal with the sign for the last bit: copy the least significant 415*f0865ec9SKyle Evans * bit of the x coordinate in the MSB of the last octet. 416*f0865ec9SKyle Evans */ 417*f0865ec9SKyle Evans MUST_HAVE((buflen > 1), ret, err); 418*f0865ec9SKyle Evans buf[buflen - 1] |= (u8)(lsb << 7); 419*f0865ec9SKyle Evans 420*f0865ec9SKyle Evans err: 421*f0865ec9SKyle Evans nn_uninit(&out_reduced); 422*f0865ec9SKyle Evans 423*f0865ec9SKyle Evans return ret; 424*f0865ec9SKyle Evans } 425*f0865ec9SKyle Evans 426*f0865ec9SKyle Evans /* Decode an Edwards curve affine point from canonical form */ 427*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int eddsa_decode_point(aff_pt_edwards_t out, ec_edwards_crv_src_t edwards_curve, 428*f0865ec9SKyle Evans fp_src_t alpha_edwards, const u8 *buf, u16 buflen, 429*f0865ec9SKyle Evans ec_alg_type sig_type) 430*f0865ec9SKyle Evans { 431*f0865ec9SKyle Evans fp x, y; 432*f0865ec9SKyle Evans fp sqrt1, sqrt2; 433*f0865ec9SKyle Evans u8 x_0, lsb; 434*f0865ec9SKyle Evans u8 buf_little_endian[MAX_DIGEST_SIZE]; 435*f0865ec9SKyle Evans u16 i; 436*f0865ec9SKyle Evans int ret, iszero; 437*f0865ec9SKyle Evans 438*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 439*f0865ec9SKyle Evans fp tmp; 440*f0865ec9SKyle Evans tmp.magic = WORD(0); 441*f0865ec9SKyle Evans #endif 442*f0865ec9SKyle Evans x.magic = y.magic = sqrt1.magic = sqrt2.magic = WORD(0); 443*f0865ec9SKyle Evans 444*f0865ec9SKyle Evans MUST_HAVE((buf != NULL), ret, err); 445*f0865ec9SKyle Evans 446*f0865ec9SKyle Evans ret = ec_edwards_crv_check_initialized(edwards_curve); EG(ret, err); 447*f0865ec9SKyle Evans 448*f0865ec9SKyle Evans ret = fp_check_initialized(alpha_edwards); EG(ret, err); 449*f0865ec9SKyle Evans 450*f0865ec9SKyle Evans /* Extract the sign */ 451*f0865ec9SKyle Evans x_0 = ((buf[buflen - 1] & 0x80) >> 7); 452*f0865ec9SKyle Evans /* Extract the value by reversing endianness */ 453*f0865ec9SKyle Evans MUST_HAVE((sizeof(buf_little_endian) >= buflen), ret, err); 454*f0865ec9SKyle Evans 455*f0865ec9SKyle Evans /* Inverse endianness of our input buffer and mask the sign bit */ 456*f0865ec9SKyle Evans MUST_HAVE((buflen > 1), ret, err); 457*f0865ec9SKyle Evans 458*f0865ec9SKyle Evans for(i = 0; i < buflen; i++){ 459*f0865ec9SKyle Evans buf_little_endian[i] = buf[buflen - 1 - i]; 460*f0865ec9SKyle Evans if(i == 0){ 461*f0865ec9SKyle Evans /* Mask the sign bit */ 462*f0865ec9SKyle Evans buf_little_endian[i] &= 0x7f; 463*f0865ec9SKyle Evans } 464*f0865ec9SKyle Evans } 465*f0865ec9SKyle Evans /* Try to decode the y coordinate */ 466*f0865ec9SKyle Evans ret = fp_init_from_buf(&y, edwards_curve->a.ctx, buf_little_endian, buflen); EG(ret, err); 467*f0865ec9SKyle Evans /* 468*f0865ec9SKyle Evans * If we suceed, try to find our x coordinate that is the square root of 469*f0865ec9SKyle Evans * (y^2 - 1) / (d y^2 + 1) or (y^2 - 1) / (d y^2 - 1) depending on the 470*f0865ec9SKyle Evans * algorithm (EDDSA25519 our EDDSA448). 471*f0865ec9SKyle Evans */ 472*f0865ec9SKyle Evans ret = fp_init(&sqrt1, edwards_curve->a.ctx); EG(ret, err); 473*f0865ec9SKyle Evans ret = fp_init(&sqrt2, edwards_curve->a.ctx); EG(ret, err); 474*f0865ec9SKyle Evans ret = fp_init(&x, edwards_curve->a.ctx); EG(ret, err); 475*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 476*f0865ec9SKyle Evans if((sig_type == EDDSA448) || (sig_type == EDDSA448PH)){ 477*f0865ec9SKyle Evans const u8 d_edwards448_buff[] = { 478*f0865ec9SKyle Evans 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 479*f0865ec9SKyle Evans 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 480*f0865ec9SKyle Evans 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 481*f0865ec9SKyle Evans 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 482*f0865ec9SKyle Evans 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 483*f0865ec9SKyle Evans 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 484*f0865ec9SKyle Evans 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x67, 0x56 485*f0865ec9SKyle Evans }; 486*f0865ec9SKyle Evans ec_edwards_crv edwards_curve_edwards448; 487*f0865ec9SKyle Evans 488*f0865ec9SKyle Evans ret = fp_init(&tmp, edwards_curve->a.ctx); EG(ret, err); 489*f0865ec9SKyle Evans /* 490*f0865ec9SKyle Evans * If we deal with EDDSA448 we must handle the point on 491*f0865ec9SKyle Evans * Edwards448 so we use the dedicated d. 492*f0865ec9SKyle Evans */ 493*f0865ec9SKyle Evans ret = fp_init_from_buf(&tmp, edwards_curve->a.ctx, 494*f0865ec9SKyle Evans (const u8*)d_edwards448_buff, sizeof(d_edwards448_buff)); EG(ret, err); 495*f0865ec9SKyle Evans ret = ec_edwards_crv_init(&edwards_curve_edwards448, &(edwards_curve->a), &tmp, &(edwards_curve->order)); EG(ret, err); 496*f0865ec9SKyle Evans /* Compute x from y using the dedicated primitive */ 497*f0865ec9SKyle Evans ret = aff_pt_edwards_x_from_y(&sqrt1, &sqrt2, &y, &edwards_curve_edwards448); EG(ret, err); /* Error or no square root found, this should not happen! */ 498*f0865ec9SKyle Evans ec_edwards_crv_uninit(&edwards_curve_edwards448); 499*f0865ec9SKyle Evans } 500*f0865ec9SKyle Evans else 501*f0865ec9SKyle Evans #endif 502*f0865ec9SKyle Evans { 503*f0865ec9SKyle Evans /* Compute x from y using the dedicated primitive */ 504*f0865ec9SKyle Evans ret = aff_pt_edwards_x_from_y(&sqrt1, &sqrt2, &y, edwards_curve); EG(ret, err); /* Error or no square root found, this should not happen! */ 505*f0865ec9SKyle Evans } 506*f0865ec9SKyle Evans /* Now select the square root of the proper sign */ 507*f0865ec9SKyle Evans ret = nn_getbit(&(sqrt1.fp_val), 0, &lsb); EG(ret, err); 508*f0865ec9SKyle Evans if(lsb == x_0){ 509*f0865ec9SKyle Evans ret = fp_copy(&x, &sqrt1); EG(ret, err); 510*f0865ec9SKyle Evans } 511*f0865ec9SKyle Evans else{ 512*f0865ec9SKyle Evans ret = fp_copy(&x, &sqrt2); EG(ret, err); 513*f0865ec9SKyle Evans } 514*f0865ec9SKyle Evans /* If x = 0 and the sign bit is 1, this is an error */ 515*f0865ec9SKyle Evans ret = fp_iszero(&x, &iszero); EG(ret, err); 516*f0865ec9SKyle Evans MUST_HAVE(!(iszero && (x_0 == 1)), ret, err); 517*f0865ec9SKyle Evans /* 518*f0865ec9SKyle Evans * In case of EDDSA448, we apply the 4-isogeny to transfer from 519*f0865ec9SKyle Evans * Edwards448 to Ed448. 520*f0865ec9SKyle Evans * The isogeny maps (x1, y1) on Edwards448 to (x, y) on Ed448 using: 521*f0865ec9SKyle Evans * x = alpha_edwards * (x1*y1) / (2-x1^2-y1^2) 522*f0865ec9SKyle Evans * y = (x1^2+y1^2) / (y1^2-x1^2) 523*f0865ec9SKyle Evans */ 524*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 525*f0865ec9SKyle Evans if((sig_type == EDDSA448) || (sig_type == EDDSA448PH)){ 526*f0865ec9SKyle Evans /* 527*f0865ec9SKyle Evans * Use sqrt1 and sqrt2 as temporary buffers for x and y, and 528*f0865ec9SKyle Evans * tmp as scratch pad buffer 529*f0865ec9SKyle Evans */ 530*f0865ec9SKyle Evans ret = fp_copy(&sqrt1, &x); EG(ret, err); 531*f0865ec9SKyle Evans ret = fp_copy(&sqrt2, &y); EG(ret, err); 532*f0865ec9SKyle Evans 533*f0865ec9SKyle Evans ret = fp_set_word_value(&x, WORD(2)); EG(ret, err); 534*f0865ec9SKyle Evans ret = fp_sqr(&tmp, &sqrt1); EG(ret, err); 535*f0865ec9SKyle Evans ret = fp_sub(&x, &x, &tmp); EG(ret, err); 536*f0865ec9SKyle Evans ret = fp_sqr(&tmp, &sqrt2); EG(ret, err); 537*f0865ec9SKyle Evans ret = fp_sub(&x, &x, &tmp); EG(ret, err); 538*f0865ec9SKyle Evans /* NOTE: inversion by zero should be caught by lower layers */ 539*f0865ec9SKyle Evans ret = fp_inv(&x, &x); EG(ret, err); 540*f0865ec9SKyle Evans ret = fp_mul(&x, &x, &sqrt1); EG(ret, err); 541*f0865ec9SKyle Evans ret = fp_mul(&x, &x, &sqrt2); EG(ret, err); 542*f0865ec9SKyle Evans ret = fp_mul(&x, &x, alpha_edwards); EG(ret, err); 543*f0865ec9SKyle Evans 544*f0865ec9SKyle Evans ret = fp_sqr(&sqrt1, &sqrt1); EG(ret, err); 545*f0865ec9SKyle Evans ret = fp_sqr(&sqrt2, &sqrt2); EG(ret, err); 546*f0865ec9SKyle Evans ret = fp_sub(&y, &sqrt2, &sqrt1); EG(ret, err); 547*f0865ec9SKyle Evans /* NOTE: inversion by zero should be caught by lower layers */ 548*f0865ec9SKyle Evans ret = fp_inv(&y, &y); EG(ret, err); 549*f0865ec9SKyle Evans ret = fp_add(&sqrt1, &sqrt1, &sqrt2); EG(ret, err); 550*f0865ec9SKyle Evans ret = fp_mul(&y, &y, &sqrt1); EG(ret, err); 551*f0865ec9SKyle Evans } 552*f0865ec9SKyle Evans #endif /* !defined(WITH_SIG_EDDSA448) */ 553*f0865ec9SKyle Evans 554*f0865ec9SKyle Evans /* Initialize our point */ 555*f0865ec9SKyle Evans ret = aff_pt_edwards_init_from_coords(out, edwards_curve, &x, &y); 556*f0865ec9SKyle Evans 557*f0865ec9SKyle Evans err: 558*f0865ec9SKyle Evans fp_uninit(&sqrt1); 559*f0865ec9SKyle Evans fp_uninit(&sqrt2); 560*f0865ec9SKyle Evans fp_uninit(&x); 561*f0865ec9SKyle Evans fp_uninit(&y); 562*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 563*f0865ec9SKyle Evans fp_uninit(&tmp); 564*f0865ec9SKyle Evans #endif 565*f0865ec9SKyle Evans 566*f0865ec9SKyle Evans return ret; 567*f0865ec9SKyle Evans } 568*f0865ec9SKyle Evans 569*f0865ec9SKyle Evans 570*f0865ec9SKyle Evans /* 571*f0865ec9SKyle Evans * Derive hash from private key. 572*f0865ec9SKyle Evans */ 573*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int eddsa_derive_priv_key_hash(const ec_priv_key *in_priv, 574*f0865ec9SKyle Evans u8 *buf, u16 buflen) 575*f0865ec9SKyle Evans { 576*f0865ec9SKyle Evans hash_alg_type hash_type = UNKNOWN_HASH_ALG; 577*f0865ec9SKyle Evans const hash_mapping *hash; 578*f0865ec9SKyle Evans u8 x_buf[EC_PRIV_KEY_MAX_SIZE]; 579*f0865ec9SKyle Evans int ret; 580*f0865ec9SKyle Evans const u8 *in[2]; 581*f0865ec9SKyle Evans u32 in_len[2]; 582*f0865ec9SKyle Evans 583*f0865ec9SKyle Evans MUST_HAVE((buf != NULL), ret, err); 584*f0865ec9SKyle Evans ret = eddsa_priv_key_sanity_check(in_priv); EG(ret, err); 585*f0865ec9SKyle Evans 586*f0865ec9SKyle Evans MUST_HAVE(((hash_type = get_eddsa_hash_type(in_priv->key_type)) != UNKNOWN_HASH_ALG), ret, err); 587*f0865ec9SKyle Evans ret = get_hash_by_type(hash_type, &hash); EG(ret, err); 588*f0865ec9SKyle Evans MUST_HAVE((hash != NULL), ret, err); 589*f0865ec9SKyle Evans 590*f0865ec9SKyle Evans /* Get the private key as a buffer and hash it */ 591*f0865ec9SKyle Evans ret = local_memset(x_buf, 0, sizeof(x_buf)); EG(ret, err); 592*f0865ec9SKyle Evans MUST_HAVE((sizeof(x_buf) >= (hash->digest_size / 2)), ret, err); 593*f0865ec9SKyle Evans 594*f0865ec9SKyle Evans ret = ec_priv_key_export_to_buf(in_priv, x_buf, (hash->digest_size / 2)); EG(ret, err); 595*f0865ec9SKyle Evans 596*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(hash); EG(ret, err); 597*f0865ec9SKyle Evans 598*f0865ec9SKyle Evans MUST_HAVE((buflen >= hash->digest_size), ret, err); 599*f0865ec9SKyle Evans 600*f0865ec9SKyle Evans in[0] = x_buf; in[1] = NULL; 601*f0865ec9SKyle Evans in_len[0] = (hash->digest_size / 2); in_len[1] = 0; 602*f0865ec9SKyle Evans ret = hash->hfunc_scattered(in, in_len, buf); 603*f0865ec9SKyle Evans 604*f0865ec9SKyle Evans err: 605*f0865ec9SKyle Evans PTR_NULLIFY(hash); 606*f0865ec9SKyle Evans 607*f0865ec9SKyle Evans return ret; 608*f0865ec9SKyle Evans } 609*f0865ec9SKyle Evans 610*f0865ec9SKyle Evans /* 611*f0865ec9SKyle Evans * Derive an EdDSA private key. 612*f0865ec9SKyle Evans * 613*f0865ec9SKyle Evans */ 614*f0865ec9SKyle Evans int eddsa_derive_priv_key(ec_priv_key *priv_key) 615*f0865ec9SKyle Evans { 616*f0865ec9SKyle Evans int ret, cmp; 617*f0865ec9SKyle Evans u8 digest_size; 618*f0865ec9SKyle Evans u8 digest[MAX_DIGEST_SIZE]; 619*f0865ec9SKyle Evans hash_alg_type hash_type = UNKNOWN_HASH_ALG; 620*f0865ec9SKyle Evans word_t cofactor = WORD(0); 621*f0865ec9SKyle Evans 622*f0865ec9SKyle Evans /* Check if private key is initialized. */ 623*f0865ec9SKyle Evans ret = eddsa_priv_key_sanity_check(priv_key); EG(ret, err); 624*f0865ec9SKyle Evans 625*f0865ec9SKyle Evans /* Check hash function compatibility: 626*f0865ec9SKyle Evans * We must have 2**(b-1) > p with (2*b) the size of the hash function. 627*f0865ec9SKyle Evans */ 628*f0865ec9SKyle Evans MUST_HAVE(((hash_type = get_eddsa_hash_type(priv_key->key_type)) != UNKNOWN_HASH_ALG), ret, err); 629*f0865ec9SKyle Evans 630*f0865ec9SKyle Evans digest_size = 0; 631*f0865ec9SKyle Evans ret = get_hash_sizes(hash_type, &digest_size, NULL); EG(ret, err); 632*f0865ec9SKyle Evans 633*f0865ec9SKyle Evans MUST_HAVE(((2 * priv_key->params->ec_fp.p_bitlen) < (8 * (bitcnt_t)digest_size)), ret, err); 634*f0865ec9SKyle Evans MUST_HAVE(((digest_size % 2) == 0), ret, err); 635*f0865ec9SKyle Evans MUST_HAVE((digest_size <= sizeof(digest)), ret, err); 636*f0865ec9SKyle Evans 637*f0865ec9SKyle Evans /* 638*f0865ec9SKyle Evans * Now that we have our private scalar, derive the hash value of secret 639*f0865ec9SKyle Evans * key 640*f0865ec9SKyle Evans */ 641*f0865ec9SKyle Evans /* Hash the private key */ 642*f0865ec9SKyle Evans ret = eddsa_derive_priv_key_hash(priv_key, digest, digest_size); EG(ret, err); 643*f0865ec9SKyle Evans 644*f0865ec9SKyle Evans /* Get the cofactor as an integer */ 645*f0865ec9SKyle Evans cofactor = priv_key->params->ec_gen_cofactor.val[0]; 646*f0865ec9SKyle Evans ret = nn_cmp_word(&(priv_key->params->ec_gen_cofactor), cofactor, &cmp); EG(ret, err); 647*f0865ec9SKyle Evans MUST_HAVE((cmp == 0), ret, err); 648*f0865ec9SKyle Evans /* Cofactor must be 2**2 or 2**3 as per RFC8032 standard */ 649*f0865ec9SKyle Evans MUST_HAVE((cofactor == (0x1 << 2)) || (cofactor == (0x1 << 3)), ret, err); 650*f0865ec9SKyle Evans 651*f0865ec9SKyle Evans /* Now clear the low bits related to cofactor */ 652*f0865ec9SKyle Evans digest[0] &= (u8)(~(cofactor - 1)); 653*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519) 654*f0865ec9SKyle Evans if ((priv_key->key_type == EDDSA25519) || 655*f0865ec9SKyle Evans (priv_key->key_type == EDDSA25519CTX) || 656*f0865ec9SKyle Evans (priv_key->key_type == EDDSA25519PH)){ 657*f0865ec9SKyle Evans /* 658*f0865ec9SKyle Evans * MSB of highest octet of half must be cleared, second MSB must 659*f0865ec9SKyle Evans * be set 660*f0865ec9SKyle Evans */ 661*f0865ec9SKyle Evans digest[(digest_size / 2) - 1] &= 0x7f; 662*f0865ec9SKyle Evans digest[(digest_size / 2) - 1] |= 0x40; 663*f0865ec9SKyle Evans } 664*f0865ec9SKyle Evans #endif 665*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 666*f0865ec9SKyle Evans if ((priv_key->key_type == EDDSA448) || (priv_key->key_type == EDDSA448PH)) { 667*f0865ec9SKyle Evans MUST_HAVE((digest_size / 2) >= 2, ret, err); 668*f0865ec9SKyle Evans /* 669*f0865ec9SKyle Evans * All eight bits of the last octet are cleared, highest bit 670*f0865ec9SKyle Evans * of the second to last octet is set. 671*f0865ec9SKyle Evans */ 672*f0865ec9SKyle Evans digest[(digest_size / 2) - 1] = 0; 673*f0865ec9SKyle Evans digest[(digest_size / 2) - 2] |= 0x80; 674*f0865ec9SKyle Evans } 675*f0865ec9SKyle Evans #endif 676*f0865ec9SKyle Evans #if !defined(WITH_SIG_EDDSA25519) && !defined(WITH_SIG_EDDSA448) 677*f0865ec9SKyle Evans ret = -1; 678*f0865ec9SKyle Evans goto err; 679*f0865ec9SKyle Evans #endif 680*f0865ec9SKyle Evans /* 681*f0865ec9SKyle Evans * Now that we have derived our hash, store it in place of our secret 682*f0865ec9SKyle Evans * value NOTE: we do not need the secret value anymore since only the 683*f0865ec9SKyle Evans * hash is needed. 684*f0865ec9SKyle Evans */ 685*f0865ec9SKyle Evans ret = nn_init_from_buf(&(priv_key->x), digest, digest_size); 686*f0865ec9SKyle Evans 687*f0865ec9SKyle Evans err: 688*f0865ec9SKyle Evans VAR_ZEROIFY(digest_size); 689*f0865ec9SKyle Evans 690*f0865ec9SKyle Evans return ret; 691*f0865ec9SKyle Evans } 692*f0865ec9SKyle Evans 693*f0865ec9SKyle Evans /* 694*f0865ec9SKyle Evans * Generate an EdDSA private key. 695*f0865ec9SKyle Evans * 696*f0865ec9SKyle Evans */ 697*f0865ec9SKyle Evans int eddsa_gen_priv_key(ec_priv_key *priv_key) 698*f0865ec9SKyle Evans { 699*f0865ec9SKyle Evans int ret; 700*f0865ec9SKyle Evans u8 digest_size; 701*f0865ec9SKyle Evans hash_alg_type hash_type = UNKNOWN_HASH_ALG; 702*f0865ec9SKyle Evans 703*f0865ec9SKyle Evans /* Check if private key is initialized. */ 704*f0865ec9SKyle Evans ret = eddsa_priv_key_sanity_check(priv_key); EG(ret, err); 705*f0865ec9SKyle Evans 706*f0865ec9SKyle Evans /* Check hash function compatibility: 707*f0865ec9SKyle Evans * We must have 2**(b-1) > p with (2*b) the size of the hash function. 708*f0865ec9SKyle Evans */ 709*f0865ec9SKyle Evans MUST_HAVE(((hash_type = get_eddsa_hash_type(priv_key->key_type)) != UNKNOWN_HASH_ALG), ret, err); 710*f0865ec9SKyle Evans 711*f0865ec9SKyle Evans digest_size = 0; 712*f0865ec9SKyle Evans ret = get_hash_sizes(hash_type, &digest_size, NULL); EG(ret, err); 713*f0865ec9SKyle Evans 714*f0865ec9SKyle Evans MUST_HAVE(((2 * priv_key->params->ec_fp.p_bitlen) < (8 * (bitcnt_t)digest_size)), ret, err); 715*f0865ec9SKyle Evans MUST_HAVE(((digest_size % 2) == 0), ret, err); 716*f0865ec9SKyle Evans 717*f0865ec9SKyle Evans /* Generate a random private key 718*f0865ec9SKyle Evans * An EdDSA secret scalar is a b bit string with (2*b) the size of the hash function 719*f0865ec9SKyle Evans */ 720*f0865ec9SKyle Evans ret = nn_get_random_len(&(priv_key->x), (digest_size / 2)); EG(ret, err); 721*f0865ec9SKyle Evans 722*f0865ec9SKyle Evans /* Derive the private key */ 723*f0865ec9SKyle Evans ret = eddsa_derive_priv_key(priv_key); 724*f0865ec9SKyle Evans 725*f0865ec9SKyle Evans err: 726*f0865ec9SKyle Evans VAR_ZEROIFY(digest_size); 727*f0865ec9SKyle Evans 728*f0865ec9SKyle Evans return ret; 729*f0865ec9SKyle Evans } 730*f0865ec9SKyle Evans 731*f0865ec9SKyle Evans 732*f0865ec9SKyle Evans /* Import an EdDSA private key from a raw buffer. 733*f0865ec9SKyle Evans * NOTE: the private key must be a big number associated to the curve that 734*f0865ec9SKyle Evans * depends on the flavor of EdDSA (Ed25519 or Ed448), and the result is a 735*f0865ec9SKyle Evans * derived private key that can be used by the internal EdDSA functions. 736*f0865ec9SKyle Evans * The derived key is a hash of the private key: we mainly perform this 737*f0865ec9SKyle Evans * derivation early to prevent side-channel attacks and other leaks on the 738*f0865ec9SKyle Evans * "root" private key. 739*f0865ec9SKyle Evans */ 740*f0865ec9SKyle Evans int eddsa_import_priv_key(ec_priv_key *priv_key, const u8 *buf, u16 buflen, 741*f0865ec9SKyle Evans const ec_params *shortw_curve_params, 742*f0865ec9SKyle Evans ec_alg_type sig_type) 743*f0865ec9SKyle Evans { 744*f0865ec9SKyle Evans int ret; 745*f0865ec9SKyle Evans hash_alg_type hash_type = UNKNOWN_HASH_ALG; 746*f0865ec9SKyle Evans u8 digest_size; 747*f0865ec9SKyle Evans bitcnt_t blen; 748*f0865ec9SKyle Evans 749*f0865ec9SKyle Evans /* Some sanity checks */ 750*f0865ec9SKyle Evans MUST_HAVE((priv_key != NULL) && (buf != NULL) && (shortw_curve_params != NULL), ret, err); 751*f0865ec9SKyle Evans 752*f0865ec9SKyle Evans /* Import the big number from our buffer */ 753*f0865ec9SKyle Evans ret = nn_init_from_buf(&(priv_key->x), buf, buflen); EG(ret, err); 754*f0865ec9SKyle Evans /* The bit length of our big number must be <= b, half the digest size */ 755*f0865ec9SKyle Evans hash_type = get_eddsa_hash_type(sig_type); 756*f0865ec9SKyle Evans MUST_HAVE((hash_type != UNKNOWN_HASH_ALG), ret, err); 757*f0865ec9SKyle Evans 758*f0865ec9SKyle Evans digest_size = 0; 759*f0865ec9SKyle Evans ret = get_hash_sizes(hash_type, &digest_size, NULL); EG(ret, err); 760*f0865ec9SKyle Evans 761*f0865ec9SKyle Evans ret = nn_bitlen(&(priv_key->x), &blen); EG(ret, err); 762*f0865ec9SKyle Evans MUST_HAVE((blen <= (8 * ((bitcnt_t)digest_size / 2))), ret, err); 763*f0865ec9SKyle Evans 764*f0865ec9SKyle Evans /* Initialize stuff */ 765*f0865ec9SKyle Evans priv_key->key_type = sig_type; 766*f0865ec9SKyle Evans priv_key->params = shortw_curve_params; 767*f0865ec9SKyle Evans priv_key->magic = PRIV_KEY_MAGIC; 768*f0865ec9SKyle Evans 769*f0865ec9SKyle Evans /* Now derive the private key. 770*f0865ec9SKyle Evans * NOTE: sanity check on the private key is performed during derivation. 771*f0865ec9SKyle Evans */ 772*f0865ec9SKyle Evans ret = eddsa_derive_priv_key(priv_key); 773*f0865ec9SKyle Evans 774*f0865ec9SKyle Evans err: 775*f0865ec9SKyle Evans if((priv_key != NULL) && ret){ 776*f0865ec9SKyle Evans IGNORE_RET_VAL(local_memset(priv_key, 0, sizeof(ec_priv_key))); 777*f0865ec9SKyle Evans } 778*f0865ec9SKyle Evans VAR_ZEROIFY(digest_size); 779*f0865ec9SKyle Evans VAR_ZEROIFY(blen); 780*f0865ec9SKyle Evans 781*f0865ec9SKyle Evans return ret; 782*f0865ec9SKyle Evans } 783*f0865ec9SKyle Evans 784*f0865ec9SKyle Evans /* NOTE: we perform EDDSA public key computation on the short Weierstrass 785*f0865ec9SKyle Evans * form of the curve thanks to the birational equivalence of curve 786*f0865ec9SKyle Evans * models (the isomorphism allows to perform the scalar multiplication 787*f0865ec9SKyle Evans * on the equivalent curve). 788*f0865ec9SKyle Evans */ 789*f0865ec9SKyle Evans int eddsa_init_pub_key(ec_pub_key *out_pub, const ec_priv_key *in_priv) 790*f0865ec9SKyle Evans { 791*f0865ec9SKyle Evans prj_pt_src_t G; 792*f0865ec9SKyle Evans u8 digest_size; 793*f0865ec9SKyle Evans u8 digest[MAX_DIGEST_SIZE]; 794*f0865ec9SKyle Evans /* Secret scalar used for public generation */ 795*f0865ec9SKyle Evans nn s; 796*f0865ec9SKyle Evans hash_alg_type hash_type; 797*f0865ec9SKyle Evans u8 digest_size_; 798*f0865ec9SKyle Evans int ret; 799*f0865ec9SKyle Evans s.magic = WORD(0); 800*f0865ec9SKyle Evans 801*f0865ec9SKyle Evans MUST_HAVE(out_pub != NULL, ret, err); 802*f0865ec9SKyle Evans ret = eddsa_priv_key_sanity_check(in_priv); EG(ret, err); 803*f0865ec9SKyle Evans 804*f0865ec9SKyle Evans ret = nn_init(&s, 0); EG(ret, err); 805*f0865ec9SKyle Evans 806*f0865ec9SKyle Evans /* Zero init public key to be generated */ 807*f0865ec9SKyle Evans ret = local_memset(out_pub, 0, sizeof(ec_pub_key)); EG(ret, err); 808*f0865ec9SKyle Evans 809*f0865ec9SKyle Evans /* Get the generator G */ 810*f0865ec9SKyle Evans G = &(in_priv->params->ec_gen); 811*f0865ec9SKyle Evans 812*f0865ec9SKyle Evans /* Get the digest in proper format */ 813*f0865ec9SKyle Evans MUST_HAVE(((hash_type = get_eddsa_hash_type(in_priv->key_type)) != UNKNOWN_HASH_ALG), ret, err); 814*f0865ec9SKyle Evans 815*f0865ec9SKyle Evans digest_size_ = 0; 816*f0865ec9SKyle Evans ret = get_hash_sizes(hash_type, &digest_size_, NULL); EG(ret, err); 817*f0865ec9SKyle Evans 818*f0865ec9SKyle Evans /* Extract the digest */ 819*f0865ec9SKyle Evans digest_size = sizeof(digest); 820*f0865ec9SKyle Evans ret = eddsa_get_digest_from_priv_key(digest, &digest_size, in_priv); EG(ret, err); 821*f0865ec9SKyle Evans 822*f0865ec9SKyle Evans /* Sanity check */ 823*f0865ec9SKyle Evans MUST_HAVE((digest_size == digest_size_), ret, err); 824*f0865ec9SKyle Evans 825*f0865ec9SKyle Evans /* Encode the scalar s from the digest */ 826*f0865ec9SKyle Evans ret = eddsa_compute_s(&s, digest, digest_size); EG(ret, err); 827*f0865ec9SKyle Evans 828*f0865ec9SKyle Evans /* Compute s x G where G is the base point */ 829*f0865ec9SKyle Evans /* 830*f0865ec9SKyle Evans * Use blinding when computing point scalar multiplication as we 831*f0865ec9SKyle Evans * manipulate a fixed secret. 832*f0865ec9SKyle Evans */ 833*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 834*f0865ec9SKyle Evans if((in_priv->key_type == EDDSA448) || (in_priv->key_type == EDDSA448PH)){ 835*f0865ec9SKyle Evans /* 836*f0865ec9SKyle Evans * NOTE: because of the 4-isogeny between Ed448 and Edwards448, 837*f0865ec9SKyle Evans * we actually multiply by (s/4) since the base point of 838*f0865ec9SKyle Evans * Edwards448 is four times the one of Ed448. 839*f0865ec9SKyle Evans * Here, s/4 can be simply computed by right shifting by 2 as 840*f0865ec9SKyle Evans * we are ensured that our scalar is a multiple of 4 by 841*f0865ec9SKyle Evans * construction. 842*f0865ec9SKyle Evans */ 843*f0865ec9SKyle Evans ret = nn_rshift(&s, &s, 2); EG(ret, err); 844*f0865ec9SKyle Evans } 845*f0865ec9SKyle Evans #endif 846*f0865ec9SKyle Evans ret = prj_pt_mul_blind(&(out_pub->y), &s, G); EG(ret, err); 847*f0865ec9SKyle Evans 848*f0865ec9SKyle Evans out_pub->key_type = in_priv->key_type; 849*f0865ec9SKyle Evans out_pub->params = in_priv->params; 850*f0865ec9SKyle Evans out_pub->magic = PUB_KEY_MAGIC; 851*f0865ec9SKyle Evans 852*f0865ec9SKyle Evans err: 853*f0865ec9SKyle Evans PTR_NULLIFY(G); 854*f0865ec9SKyle Evans VAR_ZEROIFY(digest_size); 855*f0865ec9SKyle Evans nn_uninit(&s); 856*f0865ec9SKyle Evans 857*f0865ec9SKyle Evans return ret; 858*f0865ec9SKyle Evans } 859*f0865ec9SKyle Evans 860*f0865ec9SKyle Evans /* 861*f0865ec9SKyle Evans * Import a public key in canonical form. 862*f0865ec9SKyle Evans * (imports a public key from a buffer and checks its canonical form.) 863*f0865ec9SKyle Evans * 864*f0865ec9SKyle Evans */ 865*f0865ec9SKyle Evans int eddsa_import_pub_key(ec_pub_key *pub_key, const u8 *buf, u16 buflen, 866*f0865ec9SKyle Evans const ec_params *shortw_curve_params, 867*f0865ec9SKyle Evans ec_alg_type sig_type) 868*f0865ec9SKyle Evans { 869*f0865ec9SKyle Evans aff_pt_edwards _Tmp; 870*f0865ec9SKyle Evans ec_edwards_crv edwards_curve; 871*f0865ec9SKyle Evans int ret; 872*f0865ec9SKyle Evans ec_shortw_crv_src_t shortw_curve; 873*f0865ec9SKyle Evans fp_src_t alpha_montgomery; 874*f0865ec9SKyle Evans fp_src_t gamma_montgomery; 875*f0865ec9SKyle Evans fp_src_t alpha_edwards; 876*f0865ec9SKyle Evans prj_pt_t pub_key_y; 877*f0865ec9SKyle Evans _Tmp.magic = edwards_curve.magic = WORD(0); 878*f0865ec9SKyle Evans 879*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519) && defined(WITH_SIG_EDDSA448) 880*f0865ec9SKyle Evans if((sig_type != EDDSA25519) && (sig_type != EDDSA25519CTX) && (sig_type != EDDSA25519PH) && \ 881*f0865ec9SKyle Evans (sig_type != EDDSA448) && (sig_type != EDDSA448PH)){ 882*f0865ec9SKyle Evans #endif 883*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519) && !defined(WITH_SIG_EDDSA448) 884*f0865ec9SKyle Evans if((sig_type != EDDSA25519) && (sig_type != EDDSA25519CTX) && (sig_type != EDDSA25519PH)){ 885*f0865ec9SKyle Evans #endif 886*f0865ec9SKyle Evans #if !defined(WITH_SIG_EDDSA25519) && defined(WITH_SIG_EDDSA448) 887*f0865ec9SKyle Evans if((sig_type != EDDSA448) && (sig_type != EDDSA448PH)){ 888*f0865ec9SKyle Evans #endif 889*f0865ec9SKyle Evans ret = -1; 890*f0865ec9SKyle Evans goto err; 891*f0865ec9SKyle Evans } 892*f0865ec9SKyle Evans 893*f0865ec9SKyle Evans MUST_HAVE((pub_key != NULL) && (shortw_curve_params != NULL) && (buf != NULL), ret, err); 894*f0865ec9SKyle Evans 895*f0865ec9SKyle Evans /* Check for sizes on the buffer for strict size depending on EdDSA types */ 896*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519) 897*f0865ec9SKyle Evans if((sig_type == EDDSA25519) || (sig_type == EDDSA25519CTX) || (sig_type == EDDSA25519PH)){ 898*f0865ec9SKyle Evans MUST_HAVE((buflen == EDDSA25519_PUB_KEY_ENCODED_LEN), ret, err); 899*f0865ec9SKyle Evans } 900*f0865ec9SKyle Evans #endif 901*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 902*f0865ec9SKyle Evans if((sig_type == EDDSA448) || (sig_type == EDDSA448PH)){ 903*f0865ec9SKyle Evans MUST_HAVE((buflen == EDDSA448_PUB_KEY_ENCODED_LEN), ret, err); 904*f0865ec9SKyle Evans } 905*f0865ec9SKyle Evans #endif 906*f0865ec9SKyle Evans 907*f0865ec9SKyle Evans /* Make things more readable */ 908*f0865ec9SKyle Evans shortw_curve = &(shortw_curve_params->ec_curve); 909*f0865ec9SKyle Evans alpha_montgomery = &(shortw_curve_params->ec_alpha_montgomery); 910*f0865ec9SKyle Evans gamma_montgomery = &(shortw_curve_params->ec_gamma_montgomery); 911*f0865ec9SKyle Evans alpha_edwards = &(shortw_curve_params->ec_alpha_edwards); 912*f0865ec9SKyle Evans pub_key_y = &(pub_key->y); 913*f0865ec9SKyle Evans 914*f0865ec9SKyle Evans /* Get the isogenic Edwards curve */ 915*f0865ec9SKyle Evans ret = curve_shortw_to_edwards(shortw_curve, &edwards_curve, alpha_montgomery, 916*f0865ec9SKyle Evans gamma_montgomery, alpha_edwards); EG(ret, err); 917*f0865ec9SKyle Evans 918*f0865ec9SKyle Evans /* Decode the point in Edwards */ 919*f0865ec9SKyle Evans ret = eddsa_decode_point(&_Tmp, &edwards_curve, alpha_edwards, buf, buflen, 920*f0865ec9SKyle Evans sig_type); EG(ret, err); 921*f0865ec9SKyle Evans /* Then transfer to short Weierstrass in our public key */ 922*f0865ec9SKyle Evans ret = aff_pt_edwards_to_prj_pt_shortw(&_Tmp, shortw_curve, pub_key_y, 923*f0865ec9SKyle Evans alpha_edwards); EG(ret, err); 924*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 925*f0865ec9SKyle Evans if((sig_type == EDDSA448) || (sig_type == EDDSA448PH)){ 926*f0865ec9SKyle Evans nn_src_t gen_order = &(shortw_curve_params->ec_gen_order); 927*f0865ec9SKyle Evans nn tmp; 928*f0865ec9SKyle Evans tmp.magic = WORD(0); 929*f0865ec9SKyle Evans 930*f0865ec9SKyle Evans /* 931*f0865ec9SKyle Evans * NOTE: because of the 4-isogeny between Ed448 and Edwards448, 932*f0865ec9SKyle Evans * we actually multiply by (s/4) since the base point of 933*f0865ec9SKyle Evans * Edwards448 is four times the one of Ed448. 934*f0865ec9SKyle Evans * Here, s/4 is computed by multiplying s by the modular 935*f0865ec9SKyle Evans * inverse of 4. 936*f0865ec9SKyle Evans */ 937*f0865ec9SKyle Evans ret = nn_init(&tmp, 0); EG(ret, err1); 938*f0865ec9SKyle Evans ret = nn_modinv_word(&tmp, WORD(4), gen_order); EG(ret, err1); 939*f0865ec9SKyle Evans ret = prj_pt_mul(&(pub_key->y), &tmp, pub_key_y); EG(ret, err1); 940*f0865ec9SKyle Evans err1: 941*f0865ec9SKyle Evans nn_uninit(&tmp); 942*f0865ec9SKyle Evans PTR_NULLIFY(gen_order); 943*f0865ec9SKyle Evans EG(ret, err); 944*f0865ec9SKyle Evans } 945*f0865ec9SKyle Evans #endif 946*f0865ec9SKyle Evans /* Mark the public key as initialized */ 947*f0865ec9SKyle Evans pub_key->key_type = sig_type; 948*f0865ec9SKyle Evans pub_key->params = shortw_curve_params; 949*f0865ec9SKyle Evans pub_key->magic = PUB_KEY_MAGIC; 950*f0865ec9SKyle Evans 951*f0865ec9SKyle Evans /* Now sanity check our public key before validating the import */ 952*f0865ec9SKyle Evans ret = eddsa_pub_key_sanity_check(pub_key); 953*f0865ec9SKyle Evans 954*f0865ec9SKyle Evans err: 955*f0865ec9SKyle Evans if((pub_key != NULL) && ret){ 956*f0865ec9SKyle Evans IGNORE_RET_VAL(local_memset(pub_key, 0, sizeof(ec_pub_key))); 957*f0865ec9SKyle Evans } 958*f0865ec9SKyle Evans PTR_NULLIFY(shortw_curve); 959*f0865ec9SKyle Evans PTR_NULLIFY(alpha_montgomery); 960*f0865ec9SKyle Evans PTR_NULLIFY(gamma_montgomery); 961*f0865ec9SKyle Evans PTR_NULLIFY(alpha_edwards); 962*f0865ec9SKyle Evans PTR_NULLIFY(pub_key_y); 963*f0865ec9SKyle Evans aff_pt_edwards_uninit(&_Tmp); 964*f0865ec9SKyle Evans ec_edwards_crv_uninit(&edwards_curve); 965*f0865ec9SKyle Evans 966*f0865ec9SKyle Evans return ret; 967*f0865ec9SKyle Evans } 968*f0865ec9SKyle Evans 969*f0865ec9SKyle Evans /* 970*f0865ec9SKyle Evans * Export a public key in canonical form. 971*f0865ec9SKyle Evans * (exports a public key to a buffer in canonical form.) 972*f0865ec9SKyle Evans */ 973*f0865ec9SKyle Evans int eddsa_export_pub_key(const ec_pub_key *in_pub, u8 *buf, u16 buflen) 974*f0865ec9SKyle Evans { 975*f0865ec9SKyle Evans aff_pt_edwards _Tmp; 976*f0865ec9SKyle Evans ec_edwards_crv edwards_curve; 977*f0865ec9SKyle Evans ec_alg_type sig_type; 978*f0865ec9SKyle Evans int ret; 979*f0865ec9SKyle Evans ec_shortw_crv_src_t shortw_curve; 980*f0865ec9SKyle Evans fp_src_t alpha_montgomery; 981*f0865ec9SKyle Evans fp_src_t gamma_montgomery; 982*f0865ec9SKyle Evans fp_src_t alpha_edwards; 983*f0865ec9SKyle Evans prj_pt_src_t pub_key_y; 984*f0865ec9SKyle Evans _Tmp.magic = edwards_curve.magic = WORD(0); 985*f0865ec9SKyle Evans 986*f0865ec9SKyle Evans ret = pub_key_check_initialized(in_pub); EG(ret, err); 987*f0865ec9SKyle Evans MUST_HAVE((buf != NULL), ret, err); 988*f0865ec9SKyle Evans 989*f0865ec9SKyle Evans /* Make things more readable */ 990*f0865ec9SKyle Evans shortw_curve = &(in_pub->params->ec_curve); 991*f0865ec9SKyle Evans alpha_montgomery = &(in_pub->params->ec_alpha_montgomery); 992*f0865ec9SKyle Evans gamma_montgomery = &(in_pub->params->ec_gamma_montgomery); 993*f0865ec9SKyle Evans alpha_edwards = &(in_pub->params->ec_alpha_edwards); 994*f0865ec9SKyle Evans pub_key_y = &(in_pub->y); 995*f0865ec9SKyle Evans sig_type = in_pub->key_type; 996*f0865ec9SKyle Evans 997*f0865ec9SKyle Evans /* Check for sizes on the buffer for strict size depending on EdDSA types */ 998*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519) 999*f0865ec9SKyle Evans if((sig_type == EDDSA25519) || (sig_type == EDDSA25519CTX) || (sig_type == EDDSA25519PH)){ 1000*f0865ec9SKyle Evans MUST_HAVE((buflen == EDDSA25519_PUB_KEY_ENCODED_LEN), ret, err); 1001*f0865ec9SKyle Evans } 1002*f0865ec9SKyle Evans #endif 1003*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 1004*f0865ec9SKyle Evans if((sig_type == EDDSA448) || (sig_type == EDDSA448PH)){ 1005*f0865ec9SKyle Evans MUST_HAVE((buflen == EDDSA448_PUB_KEY_ENCODED_LEN), ret, err); 1006*f0865ec9SKyle Evans } 1007*f0865ec9SKyle Evans #endif 1008*f0865ec9SKyle Evans 1009*f0865ec9SKyle Evans /* Transfer our short Weierstrass to Edwards representation */ 1010*f0865ec9SKyle Evans ret = curve_shortw_to_edwards(shortw_curve, &edwards_curve, alpha_montgomery, 1011*f0865ec9SKyle Evans gamma_montgomery, alpha_edwards); EG(ret, err); 1012*f0865ec9SKyle Evans ret = prj_pt_shortw_to_aff_pt_edwards(pub_key_y, &edwards_curve, &_Tmp, 1013*f0865ec9SKyle Evans alpha_edwards); EG(ret, err); 1014*f0865ec9SKyle Evans /* Export to buffer canonical form */ 1015*f0865ec9SKyle Evans ret = eddsa_encode_point(&_Tmp, alpha_edwards, buf, 1016*f0865ec9SKyle Evans buflen, in_pub->key_type); 1017*f0865ec9SKyle Evans 1018*f0865ec9SKyle Evans err: 1019*f0865ec9SKyle Evans PTR_NULLIFY(shortw_curve); 1020*f0865ec9SKyle Evans PTR_NULLIFY(alpha_montgomery); 1021*f0865ec9SKyle Evans PTR_NULLIFY(gamma_montgomery); 1022*f0865ec9SKyle Evans PTR_NULLIFY(alpha_edwards); 1023*f0865ec9SKyle Evans PTR_NULLIFY(pub_key_y); 1024*f0865ec9SKyle Evans aff_pt_edwards_uninit(&_Tmp); 1025*f0865ec9SKyle Evans ec_edwards_crv_uninit(&edwards_curve); 1026*f0865ec9SKyle Evans 1027*f0865ec9SKyle Evans return ret; 1028*f0865ec9SKyle Evans } 1029*f0865ec9SKyle Evans 1030*f0865ec9SKyle Evans /* Import an EdDSA key pair from a private key buffer */ 1031*f0865ec9SKyle Evans int eddsa_import_key_pair_from_priv_key_buf(ec_key_pair *kp, 1032*f0865ec9SKyle Evans const u8 *buf, u16 buflen, 1033*f0865ec9SKyle Evans const ec_params *shortw_curve_params, 1034*f0865ec9SKyle Evans ec_alg_type sig_type) 1035*f0865ec9SKyle Evans { 1036*f0865ec9SKyle Evans int ret; 1037*f0865ec9SKyle Evans 1038*f0865ec9SKyle Evans MUST_HAVE((kp != NULL), ret, err); 1039*f0865ec9SKyle Evans 1040*f0865ec9SKyle Evans /* Try to import the private key */ 1041*f0865ec9SKyle Evans ret = eddsa_import_priv_key(&(kp->priv_key), buf, buflen, 1042*f0865ec9SKyle Evans shortw_curve_params, sig_type); EG(ret, err); 1043*f0865ec9SKyle Evans 1044*f0865ec9SKyle Evans /* Now derive the public key */ 1045*f0865ec9SKyle Evans ret = eddsa_init_pub_key(&(kp->pub_key), &(kp->priv_key)); 1046*f0865ec9SKyle Evans 1047*f0865ec9SKyle Evans err: 1048*f0865ec9SKyle Evans return ret; 1049*f0865ec9SKyle Evans } 1050*f0865ec9SKyle Evans 1051*f0865ec9SKyle Evans /* Compute PH(M) with PH being the hash depending on the key type */ 1052*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int eddsa_compute_pre_hash(const u8 *message, u32 message_size, 1053*f0865ec9SKyle Evans u8 *digest, u8 *digest_size, 1054*f0865ec9SKyle Evans ec_alg_type sig_type) 1055*f0865ec9SKyle Evans { 1056*f0865ec9SKyle Evans hash_alg_type hash_type; 1057*f0865ec9SKyle Evans const hash_mapping *hash; 1058*f0865ec9SKyle Evans hash_context hash_ctx; 1059*f0865ec9SKyle Evans int ret; 1060*f0865ec9SKyle Evans 1061*f0865ec9SKyle Evans MUST_HAVE((message != NULL) && (digest != NULL) && (digest_size != NULL), ret, err); 1062*f0865ec9SKyle Evans 1063*f0865ec9SKyle Evans MUST_HAVE(((hash_type = get_eddsa_hash_type(sig_type)) != UNKNOWN_HASH_ALG), ret, err); 1064*f0865ec9SKyle Evans 1065*f0865ec9SKyle Evans ret = get_hash_by_type(hash_type, &hash); EG(ret, err); 1066*f0865ec9SKyle Evans MUST_HAVE((hash != NULL), ret, err); 1067*f0865ec9SKyle Evans 1068*f0865ec9SKyle Evans /* Sanity check on the size */ 1069*f0865ec9SKyle Evans MUST_HAVE(((*digest_size) >= hash->digest_size), ret, err); 1070*f0865ec9SKyle Evans 1071*f0865ec9SKyle Evans (*digest_size) = hash->digest_size; 1072*f0865ec9SKyle Evans /* Hash the message */ 1073*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(hash); EG(ret, err); 1074*f0865ec9SKyle Evans ret = hash->hfunc_init(&hash_ctx); EG(ret, err); 1075*f0865ec9SKyle Evans ret = hash->hfunc_update(&hash_ctx, message, message_size); EG(ret, err); 1076*f0865ec9SKyle Evans ret = hash->hfunc_finalize(&hash_ctx, digest); EG(ret, err); 1077*f0865ec9SKyle Evans 1078*f0865ec9SKyle Evans err: 1079*f0865ec9SKyle Evans return ret; 1080*f0865ec9SKyle Evans } 1081*f0865ec9SKyle Evans 1082*f0865ec9SKyle Evans /*****************/ 1083*f0865ec9SKyle Evans 1084*f0865ec9SKyle Evans /* EdDSA signature length */ 1085*f0865ec9SKyle Evans int eddsa_siglen(u16 p_bit_len, u16 q_bit_len, u8 hsize, u8 blocksize, u8 *siglen) 1086*f0865ec9SKyle Evans { 1087*f0865ec9SKyle Evans int ret; 1088*f0865ec9SKyle Evans 1089*f0865ec9SKyle Evans MUST_HAVE((siglen != NULL), ret, err); 1090*f0865ec9SKyle Evans MUST_HAVE((p_bit_len <= CURVES_MAX_P_BIT_LEN) && 1091*f0865ec9SKyle Evans (q_bit_len <= CURVES_MAX_Q_BIT_LEN) && 1092*f0865ec9SKyle Evans (hsize <= MAX_DIGEST_SIZE) && (blocksize <= MAX_BLOCK_SIZE), ret, err); 1093*f0865ec9SKyle Evans 1094*f0865ec9SKyle Evans (*siglen) = (u8)EDDSA_SIGLEN(hsize); 1095*f0865ec9SKyle Evans ret = 0; 1096*f0865ec9SKyle Evans err: 1097*f0865ec9SKyle Evans return ret; 1098*f0865ec9SKyle Evans } 1099*f0865ec9SKyle Evans 1100*f0865ec9SKyle Evans /* 1101*f0865ec9SKyle Evans * Generic *internal* EdDSA signature functions (init, update and finalize). 1102*f0865ec9SKyle Evans * 1103*f0865ec9SKyle Evans * Global EdDSA signature process is as follows (I,U,F provides 1104*f0865ec9SKyle Evans * information in which function(s) (init(), update() or finalize()) 1105*f0865ec9SKyle Evans * a specific step is performed): 1106*f0865ec9SKyle Evans * 1107*f0865ec9SKyle Evans */ 1108*f0865ec9SKyle Evans 1109*f0865ec9SKyle Evans #define EDDSA_SIGN_MAGIC ((word_t)(0x7632542bf630972bULL)) 1110*f0865ec9SKyle Evans #define EDDSA_SIGN_CHECK_INITIALIZED(A, ret, err) \ 1111*f0865ec9SKyle Evans MUST_HAVE((((void *)(A)) != NULL) && ((A)->magic == EDDSA_SIGN_MAGIC), ret, err) 1112*f0865ec9SKyle Evans 1113*f0865ec9SKyle Evans int _eddsa_sign_init_pre_hash(struct ec_sign_context *ctx) 1114*f0865ec9SKyle Evans { 1115*f0865ec9SKyle Evans int ret; 1116*f0865ec9SKyle Evans bitcnt_t blen; 1117*f0865ec9SKyle Evans u8 use_message_pre_hash = 0; 1118*f0865ec9SKyle Evans ec_alg_type key_type = UNKNOWN_ALG; 1119*f0865ec9SKyle Evans const ec_key_pair *key_pair; 1120*f0865ec9SKyle Evans const hash_mapping *h; 1121*f0865ec9SKyle Evans 1122*f0865ec9SKyle Evans /* First, verify context has been initialized */ 1123*f0865ec9SKyle Evans ret = sig_sign_check_initialized(ctx); EG(ret, err); 1124*f0865ec9SKyle Evans 1125*f0865ec9SKyle Evans /* Make things more readable */ 1126*f0865ec9SKyle Evans key_pair = ctx->key_pair; 1127*f0865ec9SKyle Evans h = ctx->h; 1128*f0865ec9SKyle Evans key_type = ctx->key_pair->priv_key.key_type; 1129*f0865ec9SKyle Evans 1130*f0865ec9SKyle Evans /* Sanity check: this function is only supported in PH mode */ 1131*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519) 1132*f0865ec9SKyle Evans if(key_type == EDDSA25519PH){ 1133*f0865ec9SKyle Evans use_message_pre_hash = 1; 1134*f0865ec9SKyle Evans } 1135*f0865ec9SKyle Evans #endif 1136*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 1137*f0865ec9SKyle Evans if(key_type == EDDSA448PH){ 1138*f0865ec9SKyle Evans use_message_pre_hash = 1; 1139*f0865ec9SKyle Evans } 1140*f0865ec9SKyle Evans #endif 1141*f0865ec9SKyle Evans MUST_HAVE((use_message_pre_hash == 1), ret, err); 1142*f0865ec9SKyle Evans 1143*f0865ec9SKyle Evans /* Additional sanity checks on input params from context */ 1144*f0865ec9SKyle Evans ret = eddsa_key_pair_sanity_check(key_pair); EG(ret, err); 1145*f0865ec9SKyle Evans 1146*f0865ec9SKyle Evans MUST_HAVE((h != NULL) && (h->digest_size <= MAX_DIGEST_SIZE) && (h->block_size <= MAX_BLOCK_SIZE), ret, err); 1147*f0865ec9SKyle Evans 1148*f0865ec9SKyle Evans /* Sanity check on hash types */ 1149*f0865ec9SKyle Evans MUST_HAVE((key_type == key_pair->pub_key.key_type) && (h->type == get_eddsa_hash_type(key_type)), ret, err); 1150*f0865ec9SKyle Evans 1151*f0865ec9SKyle Evans /* 1152*f0865ec9SKyle Evans * Sanity check on hash size versus private key size 1153*f0865ec9SKyle Evans */ 1154*f0865ec9SKyle Evans ret = nn_bitlen(&(key_pair->priv_key.x), &blen); EG(ret, err); 1155*f0865ec9SKyle Evans MUST_HAVE(blen <= (8 * h->digest_size), ret, err); 1156*f0865ec9SKyle Evans 1157*f0865ec9SKyle Evans /* 1158*f0865ec9SKyle Evans * Initialize hash context stored in our private part of context 1159*f0865ec9SKyle Evans * and record data init has been done 1160*f0865ec9SKyle Evans */ 1161*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 1162*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(h); EG(ret, err); 1163*f0865ec9SKyle Evans ret = h->hfunc_init(&(ctx->sign_data.eddsa.h_ctx)); EG(ret, err); 1164*f0865ec9SKyle Evans 1165*f0865ec9SKyle Evans /* Initialize other elements in the context */ 1166*f0865ec9SKyle Evans ctx->sign_data.eddsa.magic = EDDSA_SIGN_MAGIC; 1167*f0865ec9SKyle Evans 1168*f0865ec9SKyle Evans err: 1169*f0865ec9SKyle Evans PTR_NULLIFY(key_pair); 1170*f0865ec9SKyle Evans PTR_NULLIFY(h); 1171*f0865ec9SKyle Evans VAR_ZEROIFY(use_message_pre_hash); 1172*f0865ec9SKyle Evans 1173*f0865ec9SKyle Evans return ret; 1174*f0865ec9SKyle Evans } 1175*f0865ec9SKyle Evans 1176*f0865ec9SKyle Evans int _eddsa_sign_update_pre_hash(struct ec_sign_context *ctx, 1177*f0865ec9SKyle Evans const u8 *chunk, u32 chunklen) 1178*f0865ec9SKyle Evans { 1179*f0865ec9SKyle Evans int ret; 1180*f0865ec9SKyle Evans ec_alg_type key_type = UNKNOWN_ALG; 1181*f0865ec9SKyle Evans u8 use_message_pre_hash = 0; 1182*f0865ec9SKyle Evans 1183*f0865ec9SKyle Evans /* 1184*f0865ec9SKyle Evans * First, verify context has been initialized and public 1185*f0865ec9SKyle Evans * part too. This guarantees the context is an EDDSA 1186*f0865ec9SKyle Evans * verification one and we do not update() or finalize() 1187*f0865ec9SKyle Evans * before init(). 1188*f0865ec9SKyle Evans */ 1189*f0865ec9SKyle Evans ret = sig_sign_check_initialized(ctx); EG(ret, err); 1190*f0865ec9SKyle Evans EDDSA_SIGN_CHECK_INITIALIZED(&(ctx->sign_data.eddsa), ret, err); 1191*f0865ec9SKyle Evans MUST_HAVE((chunk != NULL), ret, err); 1192*f0865ec9SKyle Evans 1193*f0865ec9SKyle Evans key_type = ctx->key_pair->priv_key.key_type; 1194*f0865ec9SKyle Evans 1195*f0865ec9SKyle Evans /* Sanity check: this function is only supported in PH mode */ 1196*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519) 1197*f0865ec9SKyle Evans if(key_type == EDDSA25519PH){ 1198*f0865ec9SKyle Evans use_message_pre_hash = 1; 1199*f0865ec9SKyle Evans } 1200*f0865ec9SKyle Evans #endif 1201*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 1202*f0865ec9SKyle Evans if(key_type == EDDSA448PH){ 1203*f0865ec9SKyle Evans use_message_pre_hash = 1; 1204*f0865ec9SKyle Evans } 1205*f0865ec9SKyle Evans #endif 1206*f0865ec9SKyle Evans MUST_HAVE(use_message_pre_hash == 1, ret, err); 1207*f0865ec9SKyle Evans 1208*f0865ec9SKyle Evans /* Sanity check on hash types */ 1209*f0865ec9SKyle Evans MUST_HAVE((ctx->h->type == get_eddsa_hash_type(key_type)), ret, err); 1210*f0865ec9SKyle Evans 1211*f0865ec9SKyle Evans /* 2. Compute h = H(m) */ 1212*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 1213*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err); 1214*f0865ec9SKyle Evans 1215*f0865ec9SKyle Evans ret = ctx->h->hfunc_update(&(ctx->sign_data.eddsa.h_ctx), chunk, chunklen); 1216*f0865ec9SKyle Evans 1217*f0865ec9SKyle Evans err: 1218*f0865ec9SKyle Evans VAR_ZEROIFY(use_message_pre_hash); 1219*f0865ec9SKyle Evans 1220*f0865ec9SKyle Evans return ret; 1221*f0865ec9SKyle Evans 1222*f0865ec9SKyle Evans } 1223*f0865ec9SKyle Evans 1224*f0865ec9SKyle Evans int _eddsa_sign_finalize_pre_hash(struct ec_sign_context *ctx, u8 *sig, u8 siglen) 1225*f0865ec9SKyle Evans { 1226*f0865ec9SKyle Evans const ec_priv_key *priv_key; 1227*f0865ec9SKyle Evans const ec_pub_key *pub_key; 1228*f0865ec9SKyle Evans prj_pt_src_t G; 1229*f0865ec9SKyle Evans u8 hash[MAX_DIGEST_SIZE]; 1230*f0865ec9SKyle Evans u8 ph_hash[MAX_DIGEST_SIZE]; 1231*f0865ec9SKyle Evans prj_pt R; 1232*f0865ec9SKyle Evans ec_edwards_crv crv_edwards; 1233*f0865ec9SKyle Evans aff_pt_edwards Tmp_edwards; 1234*f0865ec9SKyle Evans nn_src_t q; 1235*f0865ec9SKyle Evans u8 hsize, hash_size; 1236*f0865ec9SKyle Evans int ret; 1237*f0865ec9SKyle Evans ec_shortw_crv_src_t shortw_curve; 1238*f0865ec9SKyle Evans fp_src_t alpha_montgomery; 1239*f0865ec9SKyle Evans fp_src_t gamma_montgomery; 1240*f0865ec9SKyle Evans fp_src_t alpha_edwards; 1241*f0865ec9SKyle Evans prj_pt_src_t pub_key_y; 1242*f0865ec9SKyle Evans u8 use_message_pre_hash = 0; 1243*f0865ec9SKyle Evans u16 use_message_pre_hash_hsize = 0; 1244*f0865ec9SKyle Evans ec_alg_type key_type = UNKNOWN_ALG; 1245*f0865ec9SKyle Evans u8 r_len, s_len; 1246*f0865ec9SKyle Evans const hash_mapping *h; 1247*f0865ec9SKyle Evans 1248*f0865ec9SKyle Evans nn r, s, S; 1249*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 1250*f0865ec9SKyle Evans /* b is the blinding mask */ 1251*f0865ec9SKyle Evans nn b, binv; 1252*f0865ec9SKyle Evans b.magic = binv.magic = WORD(0); 1253*f0865ec9SKyle Evans #endif /* !USE_SIG_BLINDING */ 1254*f0865ec9SKyle Evans r.magic = s.magic = S.magic = WORD(0); 1255*f0865ec9SKyle Evans R.magic = crv_edwards.magic = Tmp_edwards.magic = WORD(0); 1256*f0865ec9SKyle Evans 1257*f0865ec9SKyle Evans /* 1258*f0865ec9SKyle Evans * First, verify context has been initialized and private 1259*f0865ec9SKyle Evans * part too. This guarantees the context is an EDDSA 1260*f0865ec9SKyle Evans * signature one and we do not update() or finalize() 1261*f0865ec9SKyle Evans * before init(). 1262*f0865ec9SKyle Evans */ 1263*f0865ec9SKyle Evans ret = sig_sign_check_initialized(ctx); EG(ret, err); 1264*f0865ec9SKyle Evans EDDSA_SIGN_CHECK_INITIALIZED(&(ctx->sign_data.eddsa), ret, err); 1265*f0865ec9SKyle Evans MUST_HAVE((sig != NULL), ret, err); 1266*f0865ec9SKyle Evans 1267*f0865ec9SKyle Evans /* Zero init out points and data */ 1268*f0865ec9SKyle Evans ret = local_memset(&R, 0, sizeof(prj_pt)); EG(ret, err); 1269*f0865ec9SKyle Evans ret = local_memset(&Tmp_edwards, 0, sizeof(aff_pt_edwards)); EG(ret, err); 1270*f0865ec9SKyle Evans ret = local_memset(&crv_edwards, 0, sizeof(ec_edwards_crv)); EG(ret, err); 1271*f0865ec9SKyle Evans ret = local_memset(hash, 0, sizeof(hash)); EG(ret, err); 1272*f0865ec9SKyle Evans ret = local_memset(ph_hash, 0, sizeof(ph_hash)); EG(ret, err); 1273*f0865ec9SKyle Evans 1274*f0865ec9SKyle Evans /* Key type */ 1275*f0865ec9SKyle Evans key_type = ctx->key_pair->priv_key.key_type; 1276*f0865ec9SKyle Evans /* Sanity check on hash types */ 1277*f0865ec9SKyle Evans MUST_HAVE((key_type == ctx->key_pair->pub_key.key_type) && (ctx->h->type == get_eddsa_hash_type(key_type)), ret, err); 1278*f0865ec9SKyle Evans 1279*f0865ec9SKyle Evans /* Make things more readable */ 1280*f0865ec9SKyle Evans priv_key = &(ctx->key_pair->priv_key); 1281*f0865ec9SKyle Evans pub_key = &(ctx->key_pair->pub_key); 1282*f0865ec9SKyle Evans q = &(priv_key->params->ec_gen_order); 1283*f0865ec9SKyle Evans G = &(priv_key->params->ec_gen); 1284*f0865ec9SKyle Evans h = ctx->h; 1285*f0865ec9SKyle Evans hsize = h->digest_size; 1286*f0865ec9SKyle Evans r_len = EDDSA_R_LEN(hsize); 1287*f0865ec9SKyle Evans s_len = EDDSA_S_LEN(hsize); 1288*f0865ec9SKyle Evans 1289*f0865ec9SKyle Evans shortw_curve = &(priv_key->params->ec_curve); 1290*f0865ec9SKyle Evans alpha_montgomery = &(priv_key->params->ec_alpha_montgomery); 1291*f0865ec9SKyle Evans gamma_montgomery = &(priv_key->params->ec_gamma_montgomery); 1292*f0865ec9SKyle Evans alpha_edwards = &(priv_key->params->ec_alpha_edwards); 1293*f0865ec9SKyle Evans pub_key_y = &(pub_key->y); 1294*f0865ec9SKyle Evans 1295*f0865ec9SKyle Evans dbg_nn_print("p", &(priv_key->params->ec_fp.p)); 1296*f0865ec9SKyle Evans dbg_nn_print("q", &(priv_key->params->ec_gen_order)); 1297*f0865ec9SKyle Evans dbg_priv_key_print("x", priv_key); 1298*f0865ec9SKyle Evans dbg_ec_point_print("G", &(priv_key->params->ec_gen)); 1299*f0865ec9SKyle Evans dbg_pub_key_print("Y", &(ctx->key_pair->pub_key)); 1300*f0865ec9SKyle Evans 1301*f0865ec9SKyle Evans /* Check provided signature length */ 1302*f0865ec9SKyle Evans MUST_HAVE((siglen == EDDSA_SIGLEN(hsize)) && (siglen == (r_len + s_len)), ret, err); 1303*f0865ec9SKyle Evans 1304*f0865ec9SKyle Evans /* Is it indeed a PH version of the algorithm? */ 1305*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519) 1306*f0865ec9SKyle Evans if(key_type == EDDSA25519PH){ 1307*f0865ec9SKyle Evans use_message_pre_hash = 1; 1308*f0865ec9SKyle Evans use_message_pre_hash_hsize = hsize; 1309*f0865ec9SKyle Evans } 1310*f0865ec9SKyle Evans #endif 1311*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 1312*f0865ec9SKyle Evans if(key_type == EDDSA448PH){ 1313*f0865ec9SKyle Evans use_message_pre_hash = 1; 1314*f0865ec9SKyle Evans /* NOTE: as per RFC8032, EDDSA448PH uses 1315*f0865ec9SKyle Evans * SHAKE256 with 64 bytes output. 1316*f0865ec9SKyle Evans */ 1317*f0865ec9SKyle Evans use_message_pre_hash_hsize = 64; 1318*f0865ec9SKyle Evans } 1319*f0865ec9SKyle Evans #endif 1320*f0865ec9SKyle Evans /* Sanity check: this function is only supported in PH mode */ 1321*f0865ec9SKyle Evans MUST_HAVE((use_message_pre_hash == 1), ret, err); 1322*f0865ec9SKyle Evans 1323*f0865ec9SKyle Evans /* Finish the message hash session */ 1324*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 1325*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(h); EG(ret, err); 1326*f0865ec9SKyle Evans 1327*f0865ec9SKyle Evans ret = h->hfunc_finalize(&(ctx->sign_data.eddsa.h_ctx), ph_hash); EG(ret, err); 1328*f0865ec9SKyle Evans 1329*f0865ec9SKyle Evans /* 1. Finish computing the nonce r = H(h256 || ... || h511 || m) */ 1330*f0865ec9SKyle Evans /* Update our hash context with half of the secret key */ 1331*f0865ec9SKyle Evans hash_size = sizeof(hash); 1332*f0865ec9SKyle Evans ret = eddsa_get_digest_from_priv_key(hash, &hash_size, priv_key); EG(ret, err); 1333*f0865ec9SKyle Evans 1334*f0865ec9SKyle Evans /* Sanity check */ 1335*f0865ec9SKyle Evans MUST_HAVE((hash_size == hsize), ret, err); 1336*f0865ec9SKyle Evans 1337*f0865ec9SKyle Evans /* Hash half the digest */ 1338*f0865ec9SKyle Evans ret = h->hfunc_init(&(ctx->sign_data.eddsa.h_ctx)); EG(ret, err); 1339*f0865ec9SKyle Evans 1340*f0865ec9SKyle Evans /* At this point, we are ensured that we have PH versions of the algorithms */ 1341*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519) 1342*f0865ec9SKyle Evans if(key_type == EDDSA25519PH){ 1343*f0865ec9SKyle Evans ret = dom2(1, ctx->adata, ctx->adata_len, h, 1344*f0865ec9SKyle Evans &(ctx->sign_data.eddsa.h_ctx)); EG(ret, err); 1345*f0865ec9SKyle Evans } 1346*f0865ec9SKyle Evans #endif 1347*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 1348*f0865ec9SKyle Evans if(key_type == EDDSA448PH){ 1349*f0865ec9SKyle Evans ret = dom4(1, ctx->adata, ctx->adata_len, h, 1350*f0865ec9SKyle Evans &(ctx->sign_data.eddsa.h_ctx)); EG(ret, err); 1351*f0865ec9SKyle Evans } 1352*f0865ec9SKyle Evans #endif 1353*f0865ec9SKyle Evans ret = h->hfunc_update(&(ctx->sign_data.eddsa.h_ctx), &hash[hsize / 2], hsize / 2); EG(ret, err); 1354*f0865ec9SKyle Evans 1355*f0865ec9SKyle Evans /* Update hash h with message hash PH(m) */ 1356*f0865ec9SKyle Evans MUST_HAVE((use_message_pre_hash_hsize <= hsize), ret, err); 1357*f0865ec9SKyle Evans 1358*f0865ec9SKyle Evans ret = h->hfunc_update(&(ctx->sign_data.eddsa.h_ctx), ph_hash, 1359*f0865ec9SKyle Evans use_message_pre_hash_hsize); EG(ret, err); 1360*f0865ec9SKyle Evans 1361*f0865ec9SKyle Evans /* 1. Finish computing the nonce r = H(h256 || ... || h511 || PH(m)) */ 1362*f0865ec9SKyle Evans ret = h->hfunc_finalize(&(ctx->sign_data.eddsa.h_ctx), hash); EG(ret, err); 1363*f0865ec9SKyle Evans dbg_buf_print("h(h || m)", hash, hsize); 1364*f0865ec9SKyle Evans 1365*f0865ec9SKyle Evans /* Import r as the hash scalar */ 1366*f0865ec9SKyle Evans ret = eddsa_decode_integer(&r, hash, hsize); EG(ret, err); 1367*f0865ec9SKyle Evans 1368*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 1369*f0865ec9SKyle Evans /* Get a random b for blinding the r modular operations before the 1370*f0865ec9SKyle Evans * scalar multiplication as we do not want it to leak. 1371*f0865ec9SKyle Evans */ 1372*f0865ec9SKyle Evans ret = nn_get_random_mod(&b, q); EG(ret, err); 1373*f0865ec9SKyle Evans dbg_nn_print("b", &b); 1374*f0865ec9SKyle Evans /* NOTE: we use Fermat's little theorem inversion for 1375*f0865ec9SKyle Evans * constant time here. This is possible since q is prime. 1376*f0865ec9SKyle Evans */ 1377*f0865ec9SKyle Evans ret = nn_modinv_fermat(&binv, &b, q); EG(ret, err); 1378*f0865ec9SKyle Evans 1379*f0865ec9SKyle Evans /* Blind r */ 1380*f0865ec9SKyle Evans ret = nn_mul(&r, &r, &b); EG(ret, err); 1381*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */ 1382*f0865ec9SKyle Evans 1383*f0865ec9SKyle Evans /* Reduce r modulo q for the next computation. 1384*f0865ec9SKyle Evans * (this is a blind reduction if USE_SIG_BLINDING). 1385*f0865ec9SKyle Evans */ 1386*f0865ec9SKyle Evans ret = nn_mod_notrim(&r, &r, q); EG(ret, err); 1387*f0865ec9SKyle Evans 1388*f0865ec9SKyle Evans /* Now perform our scalar multiplication. 1389*f0865ec9SKyle Evans */ 1390*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 1391*f0865ec9SKyle Evans if(key_type == EDDSA448PH){ 1392*f0865ec9SKyle Evans /* 1393*f0865ec9SKyle Evans * NOTE: in case of EDDSA448, because of the 4-isogeny we must 1394*f0865ec9SKyle Evans * divide our scalar by 4. 1395*f0865ec9SKyle Evans */ 1396*f0865ec9SKyle Evans nn r_tmp; 1397*f0865ec9SKyle Evans r_tmp.magic = WORD(0); 1398*f0865ec9SKyle Evans 1399*f0865ec9SKyle Evans ret = nn_init(&r_tmp, 0); EG(ret, err1); 1400*f0865ec9SKyle Evans ret = nn_modinv_word(&r_tmp, WORD(4), q); EG(ret, err1); 1401*f0865ec9SKyle Evans ret = nn_mod_mul(&r_tmp, &r_tmp, &r, q); EG(ret, err1); 1402*f0865ec9SKyle Evans 1403*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 1404*f0865ec9SKyle Evans /* Unblind r_tmp */ 1405*f0865ec9SKyle Evans ret = nn_mod_mul(&r_tmp, &r_tmp, &binv, q); EG(ret, err1); 1406*f0865ec9SKyle Evans ret = prj_pt_mul_blind(&R, &r_tmp, G); 1407*f0865ec9SKyle Evans #else 1408*f0865ec9SKyle Evans ret = prj_pt_mul(&R, &r_tmp, G); 1409*f0865ec9SKyle Evans #endif /* !USE_SIG_BLINDING */ 1410*f0865ec9SKyle Evans err1: 1411*f0865ec9SKyle Evans nn_uninit(&r_tmp); 1412*f0865ec9SKyle Evans EG(ret, err); 1413*f0865ec9SKyle Evans } 1414*f0865ec9SKyle Evans else 1415*f0865ec9SKyle Evans #endif /* !defined(WITH_SIG_EDDSA448) */ 1416*f0865ec9SKyle Evans { 1417*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 1418*f0865ec9SKyle Evans nn r_tmp; 1419*f0865ec9SKyle Evans r_tmp.magic = WORD(0); 1420*f0865ec9SKyle Evans 1421*f0865ec9SKyle Evans ret = nn_init(&r_tmp, 0); EG(ret, err2); 1422*f0865ec9SKyle Evans ret = nn_copy(&r_tmp, &r); EG(ret, err2); 1423*f0865ec9SKyle Evans 1424*f0865ec9SKyle Evans /* Unblind r_tmp */ 1425*f0865ec9SKyle Evans ret = nn_mod_mul(&r_tmp, &r_tmp, &binv, q); EG(ret, err2); 1426*f0865ec9SKyle Evans ret = prj_pt_mul_blind(&R, &r_tmp, G); EG(ret, err2); 1427*f0865ec9SKyle Evans err2: 1428*f0865ec9SKyle Evans nn_uninit(&r_tmp); 1429*f0865ec9SKyle Evans EG(ret, err); 1430*f0865ec9SKyle Evans #else 1431*f0865ec9SKyle Evans ret = prj_pt_mul(&R, &r, G); EG(ret, err); 1432*f0865ec9SKyle Evans #endif /* !USE_SIG_BLINDING */ 1433*f0865ec9SKyle Evans } 1434*f0865ec9SKyle Evans 1435*f0865ec9SKyle Evans /* Now compute S = (r + H(R || PubKey || PH(m)) * secret) mod q */ 1436*f0865ec9SKyle Evans ret = h->hfunc_init(&(ctx->sign_data.eddsa.h_ctx)); EG(ret, err); 1437*f0865ec9SKyle Evans /* Transfer R to Edwards */ 1438*f0865ec9SKyle Evans ret = curve_shortw_to_edwards(shortw_curve, &crv_edwards, alpha_montgomery, 1439*f0865ec9SKyle Evans gamma_montgomery, alpha_edwards); EG(ret, err); 1440*f0865ec9SKyle Evans ret = prj_pt_shortw_to_aff_pt_edwards(&R, &crv_edwards, &Tmp_edwards, 1441*f0865ec9SKyle Evans alpha_edwards); EG(ret, err); 1442*f0865ec9SKyle Evans dbg_ec_edwards_point_print("R", &Tmp_edwards); 1443*f0865ec9SKyle Evans 1444*f0865ec9SKyle Evans MUST_HAVE((r_len <= siglen), ret, err); 1445*f0865ec9SKyle Evans /* Encode R and update */ 1446*f0865ec9SKyle Evans ret = eddsa_encode_point(&Tmp_edwards, alpha_edwards, &sig[0], 1447*f0865ec9SKyle Evans r_len, key_type); EG(ret, err); 1448*f0865ec9SKyle Evans /* At this point, we are ensured that we have PH versions of the algorithms */ 1449*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519) 1450*f0865ec9SKyle Evans if(key_type == EDDSA25519PH){ 1451*f0865ec9SKyle Evans ret = dom2(1, ctx->adata, ctx->adata_len, h, 1452*f0865ec9SKyle Evans &(ctx->sign_data.eddsa.h_ctx)); EG(ret, err); 1453*f0865ec9SKyle Evans } 1454*f0865ec9SKyle Evans #endif 1455*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 1456*f0865ec9SKyle Evans if(key_type == EDDSA448PH){ 1457*f0865ec9SKyle Evans ret = dom4(1, ctx->adata, ctx->adata_len, h, 1458*f0865ec9SKyle Evans &(ctx->sign_data.eddsa.h_ctx)); EG(ret, err); 1459*f0865ec9SKyle Evans } 1460*f0865ec9SKyle Evans #endif 1461*f0865ec9SKyle Evans /* Update the hash with the encoded R point */ 1462*f0865ec9SKyle Evans ret = h->hfunc_update(&(ctx->sign_data.eddsa.h_ctx), &sig[0], r_len); EG(ret, err); 1463*f0865ec9SKyle Evans /* Encode the public key */ 1464*f0865ec9SKyle Evans /* Transfer the public key to Edwards */ 1465*f0865ec9SKyle Evans ret = prj_pt_shortw_to_aff_pt_edwards(pub_key_y, &crv_edwards, 1466*f0865ec9SKyle Evans &Tmp_edwards, alpha_edwards); EG(ret, err); 1467*f0865ec9SKyle Evans dbg_ec_edwards_point_print("A", &Tmp_edwards); 1468*f0865ec9SKyle Evans MUST_HAVE(r_len <= sizeof(hash), ret, err); 1469*f0865ec9SKyle Evans 1470*f0865ec9SKyle Evans /* NOTE: we use the hash buffer as a temporary buffer */ 1471*f0865ec9SKyle Evans ret = eddsa_encode_point(&Tmp_edwards, alpha_edwards, hash, 1472*f0865ec9SKyle Evans r_len, key_type); EG(ret, err); 1473*f0865ec9SKyle Evans 1474*f0865ec9SKyle Evans /* Update the hash with the encoded public key point */ 1475*f0865ec9SKyle Evans ret = h->hfunc_update(&(ctx->sign_data.eddsa.h_ctx), hash, r_len); EG(ret, err); 1476*f0865ec9SKyle Evans /* Update the hash with PH(m) */ 1477*f0865ec9SKyle Evans ret = h->hfunc_update(&(ctx->sign_data.eddsa.h_ctx), ph_hash, 1478*f0865ec9SKyle Evans use_message_pre_hash_hsize); EG(ret, err); 1479*f0865ec9SKyle Evans /* Finalize the hash */ 1480*f0865ec9SKyle Evans ret = h->hfunc_finalize(&(ctx->sign_data.eddsa.h_ctx), hash); EG(ret, err); 1481*f0865ec9SKyle Evans dbg_buf_print("h(R || PubKey || PH(m))", hash, hsize); 1482*f0865ec9SKyle Evans /* Import our resulting hash as an integer in S */ 1483*f0865ec9SKyle Evans ret = eddsa_decode_integer(&S, hash, hsize); EG(ret, err); 1484*f0865ec9SKyle Evans ret = nn_mod(&S, &S, q); EG(ret, err); 1485*f0865ec9SKyle Evans /* Extract the digest */ 1486*f0865ec9SKyle Evans hsize = sizeof(hash); 1487*f0865ec9SKyle Evans ret = eddsa_get_digest_from_priv_key(hash, &hsize, priv_key); EG(ret, err); 1488*f0865ec9SKyle Evans /* Encode the scalar s from the digest */ 1489*f0865ec9SKyle Evans ret = eddsa_compute_s(&s, hash, hsize); EG(ret, err); 1490*f0865ec9SKyle Evans ret = nn_mod(&s, &s, q); EG(ret, err); 1491*f0865ec9SKyle Evans 1492*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 1493*f0865ec9SKyle Evans /* If we use blinding, multiply by b */ 1494*f0865ec9SKyle Evans ret = nn_mod_mul(&S, &S, &b, q); EG(ret, err); 1495*f0865ec9SKyle Evans #endif /* !USE_SIG_BLINDING */ 1496*f0865ec9SKyle Evans /* Multiply by the secret */ 1497*f0865ec9SKyle Evans ret = nn_mod_mul(&S, &S, &s, q); EG(ret, err); 1498*f0865ec9SKyle Evans /* The secret is not needed anymore */ 1499*f0865ec9SKyle Evans nn_uninit(&s); 1500*f0865ec9SKyle Evans /* Add to r */ 1501*f0865ec9SKyle Evans ret = nn_mod_add(&S, &S, &r, q); EG(ret, err); 1502*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 1503*f0865ec9SKyle Evans /* Unblind the result */ 1504*f0865ec9SKyle Evans ret = nn_mod_mul(&S, &S, &binv, q); EG(ret, err); 1505*f0865ec9SKyle Evans #endif /* !USE_SIG_BLINDING */ 1506*f0865ec9SKyle Evans /* Store our S in the context as an encoded buffer */ 1507*f0865ec9SKyle Evans MUST_HAVE((s_len <= (siglen - r_len)), ret, err); 1508*f0865ec9SKyle Evans ret = eddsa_encode_integer(&S, &sig[r_len], s_len); 1509*f0865ec9SKyle Evans 1510*f0865ec9SKyle Evans err: 1511*f0865ec9SKyle Evans /* Clean what remains on the stack */ 1512*f0865ec9SKyle Evans PTR_NULLIFY(h); 1513*f0865ec9SKyle Evans PTR_NULLIFY(priv_key); 1514*f0865ec9SKyle Evans PTR_NULLIFY(pub_key); 1515*f0865ec9SKyle Evans PTR_NULLIFY(G); 1516*f0865ec9SKyle Evans PTR_NULLIFY(q); 1517*f0865ec9SKyle Evans PTR_NULLIFY(shortw_curve); 1518*f0865ec9SKyle Evans PTR_NULLIFY(alpha_montgomery); 1519*f0865ec9SKyle Evans PTR_NULLIFY(gamma_montgomery); 1520*f0865ec9SKyle Evans PTR_NULLIFY(alpha_edwards); 1521*f0865ec9SKyle Evans PTR_NULLIFY(pub_key_y); 1522*f0865ec9SKyle Evans VAR_ZEROIFY(hsize); 1523*f0865ec9SKyle Evans VAR_ZEROIFY(hash_size); 1524*f0865ec9SKyle Evans VAR_ZEROIFY(use_message_pre_hash); 1525*f0865ec9SKyle Evans VAR_ZEROIFY(use_message_pre_hash_hsize); 1526*f0865ec9SKyle Evans VAR_ZEROIFY(r_len); 1527*f0865ec9SKyle Evans VAR_ZEROIFY(s_len); 1528*f0865ec9SKyle Evans 1529*f0865ec9SKyle Evans prj_pt_uninit(&R); 1530*f0865ec9SKyle Evans ec_edwards_crv_uninit(&crv_edwards); 1531*f0865ec9SKyle Evans aff_pt_edwards_uninit(&Tmp_edwards); 1532*f0865ec9SKyle Evans nn_uninit(&s); 1533*f0865ec9SKyle Evans nn_uninit(&r); 1534*f0865ec9SKyle Evans nn_uninit(&S); 1535*f0865ec9SKyle Evans 1536*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 1537*f0865ec9SKyle Evans nn_uninit(&b); 1538*f0865ec9SKyle Evans nn_uninit(&binv); 1539*f0865ec9SKyle Evans #endif /* !USE_SIG_BLINDING */ 1540*f0865ec9SKyle Evans 1541*f0865ec9SKyle Evans /* 1542*f0865ec9SKyle Evans * We can now clear data part of the context. This will clear 1543*f0865ec9SKyle Evans * magic and avoid further reuse of the whole context. 1544*f0865ec9SKyle Evans */ 1545*f0865ec9SKyle Evans if(ctx != NULL){ 1546*f0865ec9SKyle Evans IGNORE_RET_VAL(local_memset(&(ctx->sign_data.eddsa), 0, sizeof(eddsa_sign_data))); 1547*f0865ec9SKyle Evans } 1548*f0865ec9SKyle Evans IGNORE_RET_VAL(local_memset(ph_hash, 0, sizeof(ph_hash))); 1549*f0865ec9SKyle Evans 1550*f0865ec9SKyle Evans return ret; 1551*f0865ec9SKyle Evans } 1552*f0865ec9SKyle Evans 1553*f0865ec9SKyle Evans 1554*f0865ec9SKyle Evans /******** Signature function specific to pure EdDSA where the message 1555*f0865ec9SKyle Evans ********* streaming mode via init/update/finalize is not supported. 1556*f0865ec9SKyle Evans */ 1557*f0865ec9SKyle Evans int _eddsa_sign(u8 *sig, u8 siglen, const ec_key_pair *key_pair, 1558*f0865ec9SKyle Evans const u8 *m, u32 mlen, int (*rand) (nn_t out, nn_src_t q), 1559*f0865ec9SKyle Evans ec_alg_type sig_type, hash_alg_type hash_type, 1560*f0865ec9SKyle Evans const u8 *adata, u16 adata_len) 1561*f0865ec9SKyle Evans { 1562*f0865ec9SKyle Evans int ret; 1563*f0865ec9SKyle Evans ec_alg_type key_type = UNKNOWN_ALG; 1564*f0865ec9SKyle Evans ec_shortw_crv_src_t shortw_curve; 1565*f0865ec9SKyle Evans fp_src_t alpha_montgomery; 1566*f0865ec9SKyle Evans fp_src_t gamma_montgomery; 1567*f0865ec9SKyle Evans fp_src_t alpha_edwards; 1568*f0865ec9SKyle Evans prj_pt_src_t pub_key_y; 1569*f0865ec9SKyle Evans u8 use_message_pre_hash = 0; 1570*f0865ec9SKyle Evans u16 use_message_pre_hash_hsize = 0; 1571*f0865ec9SKyle Evans prj_pt_src_t G; 1572*f0865ec9SKyle Evans prj_pt R; 1573*f0865ec9SKyle Evans aff_pt_edwards Tmp_edwards; 1574*f0865ec9SKyle Evans ec_edwards_crv crv_edwards; 1575*f0865ec9SKyle Evans u8 hash[MAX_DIGEST_SIZE]; 1576*f0865ec9SKyle Evans u8 ph_hash[MAX_DIGEST_SIZE]; 1577*f0865ec9SKyle Evans const ec_priv_key *priv_key; 1578*f0865ec9SKyle Evans const ec_pub_key *pub_key; 1579*f0865ec9SKyle Evans nn_src_t q; 1580*f0865ec9SKyle Evans u8 hsize, hash_size; 1581*f0865ec9SKyle Evans hash_context h_ctx; 1582*f0865ec9SKyle Evans u8 r_len, s_len; 1583*f0865ec9SKyle Evans bitcnt_t blen; 1584*f0865ec9SKyle Evans const hash_mapping *h; 1585*f0865ec9SKyle Evans 1586*f0865ec9SKyle Evans nn r, s, S; 1587*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 1588*f0865ec9SKyle Evans /* b is the blinding mask */ 1589*f0865ec9SKyle Evans nn b, binv; 1590*f0865ec9SKyle Evans b.magic = binv.magic = WORD(0); 1591*f0865ec9SKyle Evans #endif 1592*f0865ec9SKyle Evans 1593*f0865ec9SKyle Evans r.magic = s.magic = S.magic = WORD(0); 1594*f0865ec9SKyle Evans R.magic = Tmp_edwards.magic = crv_edwards.magic = WORD(0); 1595*f0865ec9SKyle Evans 1596*f0865ec9SKyle Evans /* 1597*f0865ec9SKyle Evans * NOTE: EdDSA does not use any notion of random Nonce, so no need 1598*f0865ec9SKyle Evans * to use 'rand' here: we strictly check that NULL is provided. 1599*f0865ec9SKyle Evans */ 1600*f0865ec9SKyle Evans MUST_HAVE((rand == NULL), ret, err); 1601*f0865ec9SKyle Evans 1602*f0865ec9SKyle Evans /* Zero init out points and data */ 1603*f0865ec9SKyle Evans ret = local_memset(&R, 0, sizeof(prj_pt)); EG(ret, err); 1604*f0865ec9SKyle Evans ret = local_memset(&Tmp_edwards, 0, sizeof(aff_pt_edwards)); EG(ret, err); 1605*f0865ec9SKyle Evans ret = local_memset(&crv_edwards, 0, sizeof(ec_edwards_crv)); EG(ret, err); 1606*f0865ec9SKyle Evans ret = local_memset(hash, 0, sizeof(hash)); EG(ret, err); 1607*f0865ec9SKyle Evans ret = local_memset(ph_hash, 0, sizeof(ph_hash)); EG(ret, err); 1608*f0865ec9SKyle Evans 1609*f0865ec9SKyle Evans /* Sanity check on the key pair */ 1610*f0865ec9SKyle Evans ret = eddsa_key_pair_sanity_check(key_pair); EG(ret, err); 1611*f0865ec9SKyle Evans 1612*f0865ec9SKyle Evans /* Make things more readable */ 1613*f0865ec9SKyle Evans ret = get_hash_by_type(hash_type, &h); EG(ret, err); 1614*f0865ec9SKyle Evans key_type = key_pair->priv_key.key_type; 1615*f0865ec9SKyle Evans 1616*f0865ec9SKyle Evans /* Sanity check on the hash type */ 1617*f0865ec9SKyle Evans MUST_HAVE((h != NULL), ret, err); 1618*f0865ec9SKyle Evans MUST_HAVE((get_eddsa_hash_type(sig_type) == hash_type), ret, err); 1619*f0865ec9SKyle Evans /* Sanity check on the key type */ 1620*f0865ec9SKyle Evans MUST_HAVE(key_type == sig_type, ret, err); 1621*f0865ec9SKyle Evans MUST_HAVE((h != NULL) && (h->digest_size <= MAX_DIGEST_SIZE) && (h->block_size <= MAX_BLOCK_SIZE), ret, err); 1622*f0865ec9SKyle Evans /* 1623*f0865ec9SKyle Evans * Sanity check on hash size versus private key size 1624*f0865ec9SKyle Evans */ 1625*f0865ec9SKyle Evans ret = nn_bitlen(&(key_pair->priv_key.x), &blen); EG(ret, err); 1626*f0865ec9SKyle Evans MUST_HAVE((blen <= (8 * h->digest_size)), ret, err); 1627*f0865ec9SKyle Evans 1628*f0865ec9SKyle Evans /* Make things more readable */ 1629*f0865ec9SKyle Evans priv_key = &(key_pair->priv_key); 1630*f0865ec9SKyle Evans pub_key = &(key_pair->pub_key); 1631*f0865ec9SKyle Evans q = &(priv_key->params->ec_gen_order); 1632*f0865ec9SKyle Evans G = &(priv_key->params->ec_gen); 1633*f0865ec9SKyle Evans hsize = h->digest_size; 1634*f0865ec9SKyle Evans r_len = EDDSA_R_LEN(hsize); 1635*f0865ec9SKyle Evans s_len = EDDSA_S_LEN(hsize); 1636*f0865ec9SKyle Evans 1637*f0865ec9SKyle Evans shortw_curve = &(priv_key->params->ec_curve); 1638*f0865ec9SKyle Evans alpha_montgomery = &(priv_key->params->ec_alpha_montgomery); 1639*f0865ec9SKyle Evans gamma_montgomery = &(priv_key->params->ec_gamma_montgomery); 1640*f0865ec9SKyle Evans alpha_edwards = &(priv_key->params->ec_alpha_edwards); 1641*f0865ec9SKyle Evans pub_key_y = &(pub_key->y); 1642*f0865ec9SKyle Evans 1643*f0865ec9SKyle Evans dbg_nn_print("p", &(priv_key->params->ec_fp.p)); 1644*f0865ec9SKyle Evans dbg_nn_print("q", &(priv_key->params->ec_gen_order)); 1645*f0865ec9SKyle Evans dbg_priv_key_print("x", priv_key); 1646*f0865ec9SKyle Evans dbg_ec_point_print("G", &(priv_key->params->ec_gen)); 1647*f0865ec9SKyle Evans dbg_pub_key_print("Y", pub_key); 1648*f0865ec9SKyle Evans 1649*f0865ec9SKyle Evans /* Check provided signature length */ 1650*f0865ec9SKyle Evans MUST_HAVE((siglen == EDDSA_SIGLEN(hsize)) && (siglen == (r_len + s_len)), ret, err); 1651*f0865ec9SKyle Evans 1652*f0865ec9SKyle Evans /* Do we use the raw message or its PH(M) hashed version? */ 1653*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519) 1654*f0865ec9SKyle Evans if(key_type == EDDSA25519PH){ 1655*f0865ec9SKyle Evans use_message_pre_hash = 1; 1656*f0865ec9SKyle Evans use_message_pre_hash_hsize = hsize; 1657*f0865ec9SKyle Evans } 1658*f0865ec9SKyle Evans #endif 1659*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 1660*f0865ec9SKyle Evans if(key_type == EDDSA448PH){ 1661*f0865ec9SKyle Evans use_message_pre_hash = 1; 1662*f0865ec9SKyle Evans /* NOTE: as per RFC8032, EDDSA448PH uses 1663*f0865ec9SKyle Evans * SHAKE256 with 64 bytes output. 1664*f0865ec9SKyle Evans */ 1665*f0865ec9SKyle Evans use_message_pre_hash_hsize = 64; 1666*f0865ec9SKyle Evans } 1667*f0865ec9SKyle Evans #endif 1668*f0865ec9SKyle Evans /* First of all, compute the message hash if necessary */ 1669*f0865ec9SKyle Evans if(use_message_pre_hash){ 1670*f0865ec9SKyle Evans hash_size = sizeof(ph_hash); 1671*f0865ec9SKyle Evans ret = eddsa_compute_pre_hash(m, mlen, ph_hash, &hash_size, sig_type); EG(ret, err); 1672*f0865ec9SKyle Evans MUST_HAVE(use_message_pre_hash_hsize <= hash_size, ret, err); 1673*f0865ec9SKyle Evans } 1674*f0865ec9SKyle Evans /* Initialize our hash context */ 1675*f0865ec9SKyle Evans /* Compute half of the secret key */ 1676*f0865ec9SKyle Evans hash_size = sizeof(hash); 1677*f0865ec9SKyle Evans ret = eddsa_get_digest_from_priv_key(hash, &hash_size, &(key_pair->priv_key)); EG(ret, err); 1678*f0865ec9SKyle Evans /* Sanity check */ 1679*f0865ec9SKyle Evans MUST_HAVE((hash_size == hsize), ret, err); 1680*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 1681*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(h); EG(ret, err); 1682*f0865ec9SKyle Evans ret = h->hfunc_init(&h_ctx); EG(ret, err); 1683*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519) 1684*f0865ec9SKyle Evans if(key_type == EDDSA25519CTX){ 1685*f0865ec9SKyle Evans /* As per RFC8032, for EDDSA25519CTX the context SHOULD NOT be empty */ 1686*f0865ec9SKyle Evans MUST_HAVE(adata != NULL, ret, err); 1687*f0865ec9SKyle Evans ret = dom2(0, adata, adata_len, h, &h_ctx); EG(ret, err); 1688*f0865ec9SKyle Evans } 1689*f0865ec9SKyle Evans if(key_type == EDDSA25519PH){ 1690*f0865ec9SKyle Evans ret = dom2(1, adata, adata_len, h, &h_ctx); EG(ret, err); 1691*f0865ec9SKyle Evans } 1692*f0865ec9SKyle Evans #endif 1693*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 1694*f0865ec9SKyle Evans if(key_type == EDDSA448){ 1695*f0865ec9SKyle Evans ret = dom4(0, adata, adata_len, h, &h_ctx); EG(ret, err); 1696*f0865ec9SKyle Evans } 1697*f0865ec9SKyle Evans if(key_type == EDDSA448PH){ 1698*f0865ec9SKyle Evans ret = dom4(1, adata, adata_len, h, &h_ctx); EG(ret, err); 1699*f0865ec9SKyle Evans } 1700*f0865ec9SKyle Evans #endif 1701*f0865ec9SKyle Evans ret = h->hfunc_update(&h_ctx, &hash[hsize / 2], hsize / 2); EG(ret, err); 1702*f0865ec9SKyle Evans 1703*f0865ec9SKyle Evans /* Now finish computing the scalar r */ 1704*f0865ec9SKyle Evans if(use_message_pre_hash){ 1705*f0865ec9SKyle Evans ret = h->hfunc_update(&h_ctx, ph_hash, use_message_pre_hash_hsize); EG(ret, err); 1706*f0865ec9SKyle Evans } 1707*f0865ec9SKyle Evans else{ 1708*f0865ec9SKyle Evans ret = h->hfunc_update(&h_ctx, m, mlen); EG(ret, err); 1709*f0865ec9SKyle Evans } 1710*f0865ec9SKyle Evans ret = h->hfunc_finalize(&h_ctx, hash); EG(ret, err); 1711*f0865ec9SKyle Evans dbg_buf_print("h(h || PH(m))", hash, hsize); 1712*f0865ec9SKyle Evans 1713*f0865ec9SKyle Evans /* Import r as the hash scalar */ 1714*f0865ec9SKyle Evans ret = eddsa_decode_integer(&r, hash, hsize); EG(ret, err); 1715*f0865ec9SKyle Evans 1716*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 1717*f0865ec9SKyle Evans /* Get a random b for blinding the r modular operations before the 1718*f0865ec9SKyle Evans * scalar multiplication as we do not want it to leak. 1719*f0865ec9SKyle Evans */ 1720*f0865ec9SKyle Evans ret = nn_get_random_mod(&b, q); EG(ret, err); 1721*f0865ec9SKyle Evans dbg_nn_print("b", &b); 1722*f0865ec9SKyle Evans /* NOTE: we use Fermat's little theorem inversion for 1723*f0865ec9SKyle Evans * constant time here. This is possible since q is prime. 1724*f0865ec9SKyle Evans */ 1725*f0865ec9SKyle Evans ret = nn_modinv_fermat(&binv, &b, q); EG(ret, err); 1726*f0865ec9SKyle Evans 1727*f0865ec9SKyle Evans /* Blind r */ 1728*f0865ec9SKyle Evans ret = nn_mul(&r, &r, &b); EG(ret, err); 1729*f0865ec9SKyle Evans #endif /* !USE_SIG_BLINDING */ 1730*f0865ec9SKyle Evans 1731*f0865ec9SKyle Evans /* Reduce r modulo q for the next computation. 1732*f0865ec9SKyle Evans * (this is a blind reduction if USE_SIG_BLINDING). 1733*f0865ec9SKyle Evans */ 1734*f0865ec9SKyle Evans ret = nn_mod_notrim(&r, &r, q); EG(ret, err); 1735*f0865ec9SKyle Evans 1736*f0865ec9SKyle Evans /* Now perform our scalar multiplication. 1737*f0865ec9SKyle Evans */ 1738*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 1739*f0865ec9SKyle Evans if((key_type == EDDSA448) || (key_type == EDDSA448PH)){ 1740*f0865ec9SKyle Evans /* 1741*f0865ec9SKyle Evans * NOTE: in case of EDDSA448, because of the 4-isogeny we must 1742*f0865ec9SKyle Evans * divide our scalar by 4. 1743*f0865ec9SKyle Evans */ 1744*f0865ec9SKyle Evans nn r_tmp; 1745*f0865ec9SKyle Evans r_tmp.magic = WORD(0); 1746*f0865ec9SKyle Evans 1747*f0865ec9SKyle Evans ret = nn_init(&r_tmp, 0); EG(ret, err1); 1748*f0865ec9SKyle Evans ret = nn_modinv_word(&r_tmp, WORD(4), q); EG(ret, err1); 1749*f0865ec9SKyle Evans ret = nn_mod_mul(&r_tmp, &r_tmp, &r, q); EG(ret, err1); 1750*f0865ec9SKyle Evans 1751*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 1752*f0865ec9SKyle Evans /* Unblind r_tmp */ 1753*f0865ec9SKyle Evans ret = nn_mod_mul(&r_tmp, &r_tmp, &binv, q); EG(ret, err1); 1754*f0865ec9SKyle Evans ret = prj_pt_mul_blind(&R, &r_tmp, G); 1755*f0865ec9SKyle Evans #else 1756*f0865ec9SKyle Evans ret = prj_pt_mul(&R, &r_tmp, G); 1757*f0865ec9SKyle Evans #endif /* !USE_SIG_BLINDING */ 1758*f0865ec9SKyle Evans err1: 1759*f0865ec9SKyle Evans nn_uninit(&r_tmp); 1760*f0865ec9SKyle Evans EG(ret, err); 1761*f0865ec9SKyle Evans } 1762*f0865ec9SKyle Evans else 1763*f0865ec9SKyle Evans #endif /* !defined(WITH_SIG_EDDSA448) */ 1764*f0865ec9SKyle Evans { 1765*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 1766*f0865ec9SKyle Evans nn r_tmp; 1767*f0865ec9SKyle Evans r_tmp.magic = WORD(0); 1768*f0865ec9SKyle Evans 1769*f0865ec9SKyle Evans ret = nn_init(&r_tmp, 0); EG(ret, err2); 1770*f0865ec9SKyle Evans ret = nn_copy(&r_tmp, &r); EG(ret, err2); 1771*f0865ec9SKyle Evans 1772*f0865ec9SKyle Evans /* Unblind r_tmp */ 1773*f0865ec9SKyle Evans ret = nn_mod_mul(&r_tmp, &r_tmp, &binv, q); EG(ret, err2); 1774*f0865ec9SKyle Evans ret = prj_pt_mul_blind(&R, &r_tmp, G); EG(ret, err2); 1775*f0865ec9SKyle Evans err2: 1776*f0865ec9SKyle Evans nn_uninit(&r_tmp); 1777*f0865ec9SKyle Evans EG(ret, err); 1778*f0865ec9SKyle Evans #else 1779*f0865ec9SKyle Evans ret = prj_pt_mul(&R, &r, G); EG(ret, err); 1780*f0865ec9SKyle Evans #endif /* !USE_SIG_BLINDING */ 1781*f0865ec9SKyle Evans } 1782*f0865ec9SKyle Evans 1783*f0865ec9SKyle Evans /* Now compute S = (r + H(R || PubKey || PH(m)) * secret) mod q */ 1784*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(h); EG(ret, err); 1785*f0865ec9SKyle Evans ret = h->hfunc_init(&h_ctx); EG(ret, err); 1786*f0865ec9SKyle Evans /* Transfer R to Edwards */ 1787*f0865ec9SKyle Evans ret = curve_shortw_to_edwards(shortw_curve, &crv_edwards, alpha_montgomery, 1788*f0865ec9SKyle Evans gamma_montgomery, alpha_edwards); EG(ret, err); 1789*f0865ec9SKyle Evans ret = prj_pt_shortw_to_aff_pt_edwards(&R, &crv_edwards, &Tmp_edwards, 1790*f0865ec9SKyle Evans alpha_edwards); EG(ret, err); 1791*f0865ec9SKyle Evans dbg_ec_edwards_point_print("R", &Tmp_edwards); 1792*f0865ec9SKyle Evans MUST_HAVE((r_len <= siglen), ret, err); 1793*f0865ec9SKyle Evans /* Encode R and update */ 1794*f0865ec9SKyle Evans ret = eddsa_encode_point(&Tmp_edwards, alpha_edwards, &sig[0], 1795*f0865ec9SKyle Evans r_len, key_type); EG(ret, err); 1796*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519) 1797*f0865ec9SKyle Evans if(key_type == EDDSA25519CTX){ 1798*f0865ec9SKyle Evans /* 1799*f0865ec9SKyle Evans * As per RFC8032, for EDDSA25519CTX the context 1800*f0865ec9SKyle Evans * SHOULD NOT be empty 1801*f0865ec9SKyle Evans */ 1802*f0865ec9SKyle Evans MUST_HAVE((adata != NULL), ret, err); 1803*f0865ec9SKyle Evans ret = dom2(0, adata, adata_len, h, &h_ctx); EG(ret, err); 1804*f0865ec9SKyle Evans } 1805*f0865ec9SKyle Evans if(key_type == EDDSA25519PH){ 1806*f0865ec9SKyle Evans ret = dom2(1, adata, adata_len, h, &h_ctx); EG(ret, err); 1807*f0865ec9SKyle Evans } 1808*f0865ec9SKyle Evans #endif 1809*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 1810*f0865ec9SKyle Evans if(key_type == EDDSA448){ 1811*f0865ec9SKyle Evans ret = dom4(0, adata, adata_len, h, &h_ctx); EG(ret, err); 1812*f0865ec9SKyle Evans } 1813*f0865ec9SKyle Evans if(key_type == EDDSA448PH){ 1814*f0865ec9SKyle Evans ret = dom4(1, adata, adata_len, h, &h_ctx); EG(ret, err); 1815*f0865ec9SKyle Evans } 1816*f0865ec9SKyle Evans #endif 1817*f0865ec9SKyle Evans /* Update the hash with the encoded R point */ 1818*f0865ec9SKyle Evans ret = h->hfunc_update(&h_ctx, &sig[0], r_len); EG(ret, err); 1819*f0865ec9SKyle Evans /* Transfer the public key to Edwards */ 1820*f0865ec9SKyle Evans ret = prj_pt_shortw_to_aff_pt_edwards(pub_key_y, &crv_edwards, &Tmp_edwards, 1821*f0865ec9SKyle Evans alpha_edwards); EG(ret, err); 1822*f0865ec9SKyle Evans dbg_ec_edwards_point_print("A", &Tmp_edwards); 1823*f0865ec9SKyle Evans MUST_HAVE((r_len <= sizeof(hash)), ret, err); 1824*f0865ec9SKyle Evans /* Encode the public key */ 1825*f0865ec9SKyle Evans /* NOTE: we use the hash buffer as a temporary buffer */ 1826*f0865ec9SKyle Evans ret = eddsa_encode_point(&Tmp_edwards, alpha_edwards, 1827*f0865ec9SKyle Evans hash, r_len, key_type); EG(ret, err); 1828*f0865ec9SKyle Evans /* Update the hash with the encoded public key point */ 1829*f0865ec9SKyle Evans ret = h->hfunc_update(&h_ctx, hash, r_len); EG(ret, err); 1830*f0865ec9SKyle Evans /* Update the hash with the message or its hash for the PH versions */ 1831*f0865ec9SKyle Evans if(use_message_pre_hash){ 1832*f0865ec9SKyle Evans ret = h->hfunc_update(&h_ctx, ph_hash, use_message_pre_hash_hsize); EG(ret, err); 1833*f0865ec9SKyle Evans } 1834*f0865ec9SKyle Evans else{ 1835*f0865ec9SKyle Evans ret = h->hfunc_update(&h_ctx, m, mlen); EG(ret, err); 1836*f0865ec9SKyle Evans } 1837*f0865ec9SKyle Evans /* Finalize the hash */ 1838*f0865ec9SKyle Evans ret = h->hfunc_finalize(&h_ctx, hash); EG(ret, err); 1839*f0865ec9SKyle Evans dbg_buf_print("h(R || PubKey || PH(m))", hash, hsize); 1840*f0865ec9SKyle Evans /* Import our resulting hash as an integer in S */ 1841*f0865ec9SKyle Evans ret = eddsa_decode_integer(&S, hash, hsize); EG(ret, err); 1842*f0865ec9SKyle Evans ret = nn_mod(&S, &S, q); EG(ret, err); 1843*f0865ec9SKyle Evans /* Extract the digest */ 1844*f0865ec9SKyle Evans hsize = sizeof(hash); 1845*f0865ec9SKyle Evans ret = eddsa_get_digest_from_priv_key(hash, &hsize, priv_key); EG(ret, err); 1846*f0865ec9SKyle Evans ret = eddsa_compute_s(&s, hash, hsize); EG(ret, err); 1847*f0865ec9SKyle Evans ret = nn_mod(&s, &s, q); EG(ret, err); 1848*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 1849*f0865ec9SKyle Evans /* If we use blinding, multiply by b */ 1850*f0865ec9SKyle Evans ret = nn_mod_mul(&S, &S, &b, q); EG(ret, err); 1851*f0865ec9SKyle Evans #endif /* !USE_SIG_BLINDING */ 1852*f0865ec9SKyle Evans /* Multiply by the secret */ 1853*f0865ec9SKyle Evans ret = nn_mod_mul(&S, &S, &s, q); EG(ret, err); 1854*f0865ec9SKyle Evans /* The secret is not needed anymore */ 1855*f0865ec9SKyle Evans nn_uninit(&s); 1856*f0865ec9SKyle Evans /* Add to r */ 1857*f0865ec9SKyle Evans ret = nn_mod_add(&S, &S, &r, q); EG(ret, err); 1858*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 1859*f0865ec9SKyle Evans /* Unblind the result */ 1860*f0865ec9SKyle Evans ret = nn_mod_mul(&S, &S, &binv, q); EG(ret, err); 1861*f0865ec9SKyle Evans #endif /* !USE_SIG_BLINDING */ 1862*f0865ec9SKyle Evans /* Store our S in the context as an encoded buffer */ 1863*f0865ec9SKyle Evans MUST_HAVE((s_len <= (siglen - r_len)), ret, err); 1864*f0865ec9SKyle Evans /* Encode the scalar s from the digest */ 1865*f0865ec9SKyle Evans ret = eddsa_encode_integer(&S, &sig[r_len], s_len); 1866*f0865ec9SKyle Evans 1867*f0865ec9SKyle Evans err: 1868*f0865ec9SKyle Evans /* Clean what remains on the stack */ 1869*f0865ec9SKyle Evans PTR_NULLIFY(priv_key); 1870*f0865ec9SKyle Evans PTR_NULLIFY(pub_key); 1871*f0865ec9SKyle Evans PTR_NULLIFY(G); 1872*f0865ec9SKyle Evans PTR_NULLIFY(q); 1873*f0865ec9SKyle Evans PTR_NULLIFY(shortw_curve); 1874*f0865ec9SKyle Evans PTR_NULLIFY(alpha_montgomery); 1875*f0865ec9SKyle Evans PTR_NULLIFY(gamma_montgomery); 1876*f0865ec9SKyle Evans PTR_NULLIFY(alpha_edwards); 1877*f0865ec9SKyle Evans PTR_NULLIFY(pub_key_y); 1878*f0865ec9SKyle Evans PTR_NULLIFY(h); 1879*f0865ec9SKyle Evans VAR_ZEROIFY(hsize); 1880*f0865ec9SKyle Evans VAR_ZEROIFY(hash_size); 1881*f0865ec9SKyle Evans VAR_ZEROIFY(use_message_pre_hash); 1882*f0865ec9SKyle Evans VAR_ZEROIFY(use_message_pre_hash_hsize); 1883*f0865ec9SKyle Evans VAR_ZEROIFY(r_len); 1884*f0865ec9SKyle Evans VAR_ZEROIFY(s_len); 1885*f0865ec9SKyle Evans VAR_ZEROIFY(blen); 1886*f0865ec9SKyle Evans IGNORE_RET_VAL(local_memset(&h_ctx, 0, sizeof(h_ctx))); 1887*f0865ec9SKyle Evans IGNORE_RET_VAL(local_memset(hash, 0, sizeof(hash))); 1888*f0865ec9SKyle Evans IGNORE_RET_VAL(local_memset(ph_hash, 0, sizeof(ph_hash))); 1889*f0865ec9SKyle Evans 1890*f0865ec9SKyle Evans prj_pt_uninit(&R); 1891*f0865ec9SKyle Evans ec_edwards_crv_uninit(&crv_edwards); 1892*f0865ec9SKyle Evans aff_pt_edwards_uninit(&Tmp_edwards); 1893*f0865ec9SKyle Evans nn_uninit(&s); 1894*f0865ec9SKyle Evans nn_uninit(&r); 1895*f0865ec9SKyle Evans nn_uninit(&S); 1896*f0865ec9SKyle Evans 1897*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 1898*f0865ec9SKyle Evans nn_uninit(&b); 1899*f0865ec9SKyle Evans nn_uninit(&binv); 1900*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */ 1901*f0865ec9SKyle Evans 1902*f0865ec9SKyle Evans return ret; 1903*f0865ec9SKyle Evans } 1904*f0865ec9SKyle Evans 1905*f0865ec9SKyle Evans /******************************************************************************/ 1906*f0865ec9SKyle Evans /* 1907*f0865ec9SKyle Evans * Generic *internal* EDDSA verification functions (init, update and finalize). 1908*f0865ec9SKyle Evans * 1909*f0865ec9SKyle Evans */ 1910*f0865ec9SKyle Evans 1911*f0865ec9SKyle Evans #define EDDSA_VERIFY_MAGIC ((word_t)(0x3298fe87e77151beULL)) 1912*f0865ec9SKyle Evans #define EDDSA_VERIFY_CHECK_INITIALIZED(A, ret, err) \ 1913*f0865ec9SKyle Evans MUST_HAVE((((void *)(A)) != NULL) && ((A)->magic == EDDSA_VERIFY_MAGIC), ret, err) 1914*f0865ec9SKyle Evans 1915*f0865ec9SKyle Evans int _eddsa_verify_init(struct ec_verify_context *ctx, const u8 *sig, u8 siglen) 1916*f0865ec9SKyle Evans { 1917*f0865ec9SKyle Evans nn_src_t q; 1918*f0865ec9SKyle Evans ec_edwards_crv crv_edwards; 1919*f0865ec9SKyle Evans aff_pt_edwards R; 1920*f0865ec9SKyle Evans prj_pt _Tmp; 1921*f0865ec9SKyle Evans prj_pt_t _R; 1922*f0865ec9SKyle Evans aff_pt_edwards A; 1923*f0865ec9SKyle Evans nn *S; 1924*f0865ec9SKyle Evans u8 buff[MAX_DIGEST_SIZE]; 1925*f0865ec9SKyle Evans int ret, iszero, cmp; 1926*f0865ec9SKyle Evans u16 hsize; 1927*f0865ec9SKyle Evans const ec_pub_key *pub_key; 1928*f0865ec9SKyle Evans ec_shortw_crv_src_t shortw_curve; 1929*f0865ec9SKyle Evans fp_src_t alpha_montgomery; 1930*f0865ec9SKyle Evans fp_src_t gamma_montgomery; 1931*f0865ec9SKyle Evans fp_src_t alpha_edwards; 1932*f0865ec9SKyle Evans nn_src_t gen_cofactor; 1933*f0865ec9SKyle Evans prj_pt_src_t pub_key_y; 1934*f0865ec9SKyle Evans hash_context *h_ctx; 1935*f0865ec9SKyle Evans hash_context *h_ctx_pre_hash; 1936*f0865ec9SKyle Evans ec_alg_type key_type = UNKNOWN_ALG; 1937*f0865ec9SKyle Evans 1938*f0865ec9SKyle Evans R.magic = crv_edwards.magic = _Tmp.magic = A.magic = WORD(0); 1939*f0865ec9SKyle Evans 1940*f0865ec9SKyle Evans /* First, verify context has been initialized */ 1941*f0865ec9SKyle Evans ret = sig_verify_check_initialized(ctx); EG(ret, err); 1942*f0865ec9SKyle Evans MUST_HAVE((sig != NULL), ret, err); 1943*f0865ec9SKyle Evans 1944*f0865ec9SKyle Evans /* Zero init our local data */ 1945*f0865ec9SKyle Evans ret = local_memset(&A, 0, sizeof(aff_pt_edwards)); EG(ret, err); 1946*f0865ec9SKyle Evans ret = local_memset(&crv_edwards, 0, sizeof(ec_edwards_crv)); EG(ret, err); 1947*f0865ec9SKyle Evans ret = local_memset(buff, 0, sizeof(buff)); EG(ret, err); 1948*f0865ec9SKyle Evans ret = local_memset(&R, 0, sizeof(R)); EG(ret, err); 1949*f0865ec9SKyle Evans ret = local_memset(&_Tmp, 0, sizeof(_Tmp)); EG(ret, err); 1950*f0865ec9SKyle Evans 1951*f0865ec9SKyle Evans /* Do some sanity checks on input params */ 1952*f0865ec9SKyle Evans ret = eddsa_pub_key_sanity_check(ctx->pub_key); EG(ret, err); 1953*f0865ec9SKyle Evans MUST_HAVE((ctx->h != NULL) && (ctx->h->digest_size <= MAX_DIGEST_SIZE) && (ctx->h->block_size <= MAX_BLOCK_SIZE), ret, err); 1954*f0865ec9SKyle Evans 1955*f0865ec9SKyle Evans /* Make things more readable */ 1956*f0865ec9SKyle Evans q = &(ctx->pub_key->params->ec_gen_order); 1957*f0865ec9SKyle Evans _R = &(ctx->verify_data.eddsa._R); 1958*f0865ec9SKyle Evans S = &(ctx->verify_data.eddsa.S); 1959*f0865ec9SKyle Evans hsize = ctx->h->digest_size; 1960*f0865ec9SKyle Evans 1961*f0865ec9SKyle Evans pub_key = ctx->pub_key; 1962*f0865ec9SKyle Evans shortw_curve = &(pub_key->params->ec_curve); 1963*f0865ec9SKyle Evans alpha_montgomery = &(pub_key->params->ec_alpha_montgomery); 1964*f0865ec9SKyle Evans gamma_montgomery = &(pub_key->params->ec_gamma_montgomery); 1965*f0865ec9SKyle Evans alpha_edwards = &(pub_key->params->ec_alpha_edwards); 1966*f0865ec9SKyle Evans gen_cofactor = &(pub_key->params->ec_gen_cofactor); 1967*f0865ec9SKyle Evans pub_key_y = &(pub_key->y); 1968*f0865ec9SKyle Evans key_type = pub_key->key_type; 1969*f0865ec9SKyle Evans h_ctx = &(ctx->verify_data.eddsa.h_ctx); 1970*f0865ec9SKyle Evans h_ctx_pre_hash = &(ctx->verify_data.eddsa.h_ctx_pre_hash); 1971*f0865ec9SKyle Evans 1972*f0865ec9SKyle Evans /* Sanity check on hash types */ 1973*f0865ec9SKyle Evans MUST_HAVE((ctx->h->type == get_eddsa_hash_type(key_type)), ret, err); 1974*f0865ec9SKyle Evans 1975*f0865ec9SKyle Evans /* Check given signature length is the expected one */ 1976*f0865ec9SKyle Evans MUST_HAVE((siglen == EDDSA_SIGLEN(hsize)), ret, err); 1977*f0865ec9SKyle Evans MUST_HAVE((siglen == (EDDSA_R_LEN(hsize) + EDDSA_S_LEN(hsize))), ret, err); 1978*f0865ec9SKyle Evans 1979*f0865ec9SKyle Evans /* Initialize the hash context */ 1980*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 1981*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err); 1982*f0865ec9SKyle Evans ret = ctx->h->hfunc_init(h_ctx); EG(ret, err); 1983*f0865ec9SKyle Evans ret = ctx->h->hfunc_init(h_ctx_pre_hash); EG(ret, err); 1984*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519) 1985*f0865ec9SKyle Evans if(key_type == EDDSA25519CTX){ 1986*f0865ec9SKyle Evans /* As per RFC8032, for EDDSA25519CTX the context SHOULD NOT be empty */ 1987*f0865ec9SKyle Evans MUST_HAVE((ctx->adata != NULL), ret, err); 1988*f0865ec9SKyle Evans ret = dom2(0, ctx->adata, ctx->adata_len, ctx->h, h_ctx); EG(ret, err); 1989*f0865ec9SKyle Evans } 1990*f0865ec9SKyle Evans if(key_type == EDDSA25519PH){ 1991*f0865ec9SKyle Evans ret = dom2(1, ctx->adata, ctx->adata_len, ctx->h, h_ctx); EG(ret, err); 1992*f0865ec9SKyle Evans } 1993*f0865ec9SKyle Evans #endif 1994*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 1995*f0865ec9SKyle Evans if(key_type == EDDSA448){ 1996*f0865ec9SKyle Evans ret = dom4(0, ctx->adata, ctx->adata_len, ctx->h, h_ctx); EG(ret, err); 1997*f0865ec9SKyle Evans } 1998*f0865ec9SKyle Evans if(key_type == EDDSA448PH){ 1999*f0865ec9SKyle Evans ret = dom4(1, ctx->adata, ctx->adata_len, ctx->h, h_ctx); EG(ret, err); 2000*f0865ec9SKyle Evans } 2001*f0865ec9SKyle Evans #endif 2002*f0865ec9SKyle Evans /* Import R and S values from signature buffer */ 2003*f0865ec9SKyle Evans /*******************************/ 2004*f0865ec9SKyle Evans /* Import R as an Edwards point */ 2005*f0865ec9SKyle Evans ret = curve_shortw_to_edwards(shortw_curve, &crv_edwards, alpha_montgomery, 2006*f0865ec9SKyle Evans gamma_montgomery, alpha_edwards); EG(ret, err); 2007*f0865ec9SKyle Evans /* NOTE: non canonical R are checked and rejected here */ 2008*f0865ec9SKyle Evans ret = eddsa_decode_point(&R, &crv_edwards, alpha_edwards, &sig[0], 2009*f0865ec9SKyle Evans EDDSA_R_LEN(hsize), key_type); EG(ret, err); 2010*f0865ec9SKyle Evans dbg_ec_edwards_point_print("R", &R); 2011*f0865ec9SKyle Evans /* Transfer our public point R to Weierstrass */ 2012*f0865ec9SKyle Evans ret = aff_pt_edwards_to_prj_pt_shortw(&R, shortw_curve, _R, alpha_edwards); EG(ret, err); 2013*f0865ec9SKyle Evans /* Update the hash with the encoded R */ 2014*f0865ec9SKyle Evans ret = ctx->h->hfunc_update(h_ctx, &sig[0], EDDSA_R_LEN(hsize)); EG(ret, err); 2015*f0865ec9SKyle Evans 2016*f0865ec9SKyle Evans /*******************************/ 2017*f0865ec9SKyle Evans /* Import S as an integer */ 2018*f0865ec9SKyle Evans ret = eddsa_decode_integer(S, &sig[EDDSA_R_LEN(hsize)], EDDSA_S_LEN(hsize)); EG(ret, err); 2019*f0865ec9SKyle Evans /* Reject S if it is not reduced modulo q */ 2020*f0865ec9SKyle Evans ret = nn_cmp(S, q, &cmp); EG(ret, err); 2021*f0865ec9SKyle Evans MUST_HAVE((cmp < 0), ret, err); 2022*f0865ec9SKyle Evans dbg_nn_print("S", S); 2023*f0865ec9SKyle Evans 2024*f0865ec9SKyle Evans /*******************************/ 2025*f0865ec9SKyle Evans /* Encode the public key 2026*f0865ec9SKyle Evans * NOTE: since we deal with a public key transfered to Weierstrass, 2027*f0865ec9SKyle Evans * encoding checking has been handled elsewhere. 2028*f0865ec9SKyle Evans */ 2029*f0865ec9SKyle Evans /* Reject the signature if the public key is one of small order points. 2030*f0865ec9SKyle Evans * We multiply by the cofactor: since this is a public verification, 2031*f0865ec9SKyle Evans * we use a basic double and add algorithm. 2032*f0865ec9SKyle Evans */ 2033*f0865ec9SKyle Evans ret = _prj_pt_unprotected_mult(&_Tmp, gen_cofactor, pub_key_y); EG(ret, err); 2034*f0865ec9SKyle Evans /* Reject the signature if we have point at infinity here as this means 2035*f0865ec9SKyle Evans * that the public key is of small order. 2036*f0865ec9SKyle Evans */ 2037*f0865ec9SKyle Evans ret = prj_pt_iszero(&_Tmp, &iszero); EG(ret, err); 2038*f0865ec9SKyle Evans MUST_HAVE((!iszero), ret, err); 2039*f0865ec9SKyle Evans 2040*f0865ec9SKyle Evans /* Transfer the public key to Edwards */ 2041*f0865ec9SKyle Evans ret = prj_pt_shortw_to_aff_pt_edwards(pub_key_y, &crv_edwards, &A, alpha_edwards); EG(ret, err); 2042*f0865ec9SKyle Evans dbg_ec_edwards_point_print("A", &A); 2043*f0865ec9SKyle Evans MUST_HAVE((EDDSA_R_LEN(hsize) <= sizeof(buff)), ret, err); 2044*f0865ec9SKyle Evans /* NOTE: we use the hash buffer as a temporary buffer */ 2045*f0865ec9SKyle Evans ret = eddsa_encode_point(&A, alpha_edwards, buff, EDDSA_R_LEN(hsize), key_type); EG(ret, err); 2046*f0865ec9SKyle Evans 2047*f0865ec9SKyle Evans /* Update the hash with the encoded public key */ 2048*f0865ec9SKyle Evans ret = ctx->h->hfunc_update(h_ctx, buff, EDDSA_R_LEN(hsize)); EG(ret, err); 2049*f0865ec9SKyle Evans 2050*f0865ec9SKyle Evans /* Context magic set */ 2051*f0865ec9SKyle Evans ctx->verify_data.eddsa.magic = EDDSA_VERIFY_MAGIC; 2052*f0865ec9SKyle Evans 2053*f0865ec9SKyle Evans err: 2054*f0865ec9SKyle Evans PTR_NULLIFY(q); 2055*f0865ec9SKyle Evans PTR_NULLIFY(_R); 2056*f0865ec9SKyle Evans PTR_NULLIFY(S); 2057*f0865ec9SKyle Evans PTR_NULLIFY(pub_key); 2058*f0865ec9SKyle Evans PTR_NULLIFY(shortw_curve); 2059*f0865ec9SKyle Evans PTR_NULLIFY(alpha_montgomery); 2060*f0865ec9SKyle Evans PTR_NULLIFY(gamma_montgomery); 2061*f0865ec9SKyle Evans PTR_NULLIFY(alpha_edwards); 2062*f0865ec9SKyle Evans PTR_NULLIFY(gen_cofactor); 2063*f0865ec9SKyle Evans PTR_NULLIFY(pub_key_y); 2064*f0865ec9SKyle Evans 2065*f0865ec9SKyle Evans ec_edwards_crv_uninit(&crv_edwards); 2066*f0865ec9SKyle Evans aff_pt_edwards_uninit(&A); 2067*f0865ec9SKyle Evans aff_pt_edwards_uninit(&R); 2068*f0865ec9SKyle Evans prj_pt_uninit(&_Tmp); 2069*f0865ec9SKyle Evans 2070*f0865ec9SKyle Evans return ret; 2071*f0865ec9SKyle Evans } 2072*f0865ec9SKyle Evans 2073*f0865ec9SKyle Evans int _eddsa_verify_update(struct ec_verify_context *ctx, 2074*f0865ec9SKyle Evans const u8 *chunk, u32 chunklen) 2075*f0865ec9SKyle Evans { 2076*f0865ec9SKyle Evans int ret; 2077*f0865ec9SKyle Evans ec_alg_type key_type = UNKNOWN_ALG; 2078*f0865ec9SKyle Evans u8 use_message_pre_hash = 0; 2079*f0865ec9SKyle Evans hash_context *h_ctx; 2080*f0865ec9SKyle Evans hash_context *h_ctx_pre_hash; 2081*f0865ec9SKyle Evans 2082*f0865ec9SKyle Evans /* 2083*f0865ec9SKyle Evans * First, verify context has been initialized and public 2084*f0865ec9SKyle Evans * part too. This guarantees the context is an EDDSA 2085*f0865ec9SKyle Evans * verification one and we do not update() or finalize() 2086*f0865ec9SKyle Evans * before init(). 2087*f0865ec9SKyle Evans */ 2088*f0865ec9SKyle Evans ret = sig_verify_check_initialized(ctx); EG(ret, err); 2089*f0865ec9SKyle Evans EDDSA_VERIFY_CHECK_INITIALIZED(&(ctx->verify_data.eddsa), ret, err); 2090*f0865ec9SKyle Evans 2091*f0865ec9SKyle Evans key_type = ctx->pub_key->key_type; 2092*f0865ec9SKyle Evans h_ctx = &(ctx->verify_data.eddsa.h_ctx); 2093*f0865ec9SKyle Evans h_ctx_pre_hash = &(ctx->verify_data.eddsa.h_ctx_pre_hash); 2094*f0865ec9SKyle Evans 2095*f0865ec9SKyle Evans /* Sanity check on hash types */ 2096*f0865ec9SKyle Evans MUST_HAVE(ctx->h->type == get_eddsa_hash_type(key_type), ret, err); 2097*f0865ec9SKyle Evans 2098*f0865ec9SKyle Evans /* Do we use the raw message or its PH(M) hashed version? */ 2099*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519) 2100*f0865ec9SKyle Evans if(key_type == EDDSA25519PH){ 2101*f0865ec9SKyle Evans use_message_pre_hash = 1; 2102*f0865ec9SKyle Evans } 2103*f0865ec9SKyle Evans #endif 2104*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 2105*f0865ec9SKyle Evans if(key_type == EDDSA448PH){ 2106*f0865ec9SKyle Evans use_message_pre_hash = 1; 2107*f0865ec9SKyle Evans } 2108*f0865ec9SKyle Evans #endif 2109*f0865ec9SKyle Evans /* 2. Compute h = H(m) */ 2110*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 2111*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err); 2112*f0865ec9SKyle Evans if(use_message_pre_hash == 1){ 2113*f0865ec9SKyle Evans /* In PH mode, update the dedicated hash context */ 2114*f0865ec9SKyle Evans ret = ctx->h->hfunc_update(h_ctx_pre_hash, 2115*f0865ec9SKyle Evans chunk, chunklen); EG(ret, err); 2116*f0865ec9SKyle Evans } 2117*f0865ec9SKyle Evans else{ 2118*f0865ec9SKyle Evans /* In normal mode, update the nominal hash context */ 2119*f0865ec9SKyle Evans ret = ctx->h->hfunc_update(h_ctx, chunk, chunklen); EG(ret, err); 2120*f0865ec9SKyle Evans } 2121*f0865ec9SKyle Evans 2122*f0865ec9SKyle Evans err: 2123*f0865ec9SKyle Evans VAR_ZEROIFY(use_message_pre_hash); 2124*f0865ec9SKyle Evans 2125*f0865ec9SKyle Evans return ret; 2126*f0865ec9SKyle Evans } 2127*f0865ec9SKyle Evans 2128*f0865ec9SKyle Evans int _eddsa_verify_finalize(struct ec_verify_context *ctx) 2129*f0865ec9SKyle Evans { 2130*f0865ec9SKyle Evans prj_pt_src_t G, _R, A; 2131*f0865ec9SKyle Evans prj_pt _Tmp1, _Tmp2; 2132*f0865ec9SKyle Evans nn_src_t q, S; 2133*f0865ec9SKyle Evans nn h; 2134*f0865ec9SKyle Evans u16 hsize; 2135*f0865ec9SKyle Evans u8 hash[MAX_DIGEST_SIZE]; 2136*f0865ec9SKyle Evans nn_src_t gen_cofactor; 2137*f0865ec9SKyle Evans int ret, iszero, cmp; 2138*f0865ec9SKyle Evans ec_alg_type key_type = UNKNOWN_ALG; 2139*f0865ec9SKyle Evans u8 use_message_pre_hash = 0; 2140*f0865ec9SKyle Evans u16 use_message_pre_hash_hsize = 0; 2141*f0865ec9SKyle Evans hash_context *h_ctx; 2142*f0865ec9SKyle Evans hash_context *h_ctx_pre_hash; 2143*f0865ec9SKyle Evans 2144*f0865ec9SKyle Evans _Tmp1.magic = _Tmp2.magic = h.magic = WORD(0); 2145*f0865ec9SKyle Evans 2146*f0865ec9SKyle Evans /* 2147*f0865ec9SKyle Evans * First, verify context has been initialized and public 2148*f0865ec9SKyle Evans * part too. This guarantees the context is an EDDSA 2149*f0865ec9SKyle Evans * verification one and we do not finalize() before init(). 2150*f0865ec9SKyle Evans */ 2151*f0865ec9SKyle Evans ret = sig_verify_check_initialized(ctx); EG(ret, err); 2152*f0865ec9SKyle Evans EDDSA_VERIFY_CHECK_INITIALIZED(&(ctx->verify_data.eddsa), ret, err); 2153*f0865ec9SKyle Evans 2154*f0865ec9SKyle Evans /* Zero init points */ 2155*f0865ec9SKyle Evans ret = local_memset(&_Tmp1, 0, sizeof(prj_pt)); EG(ret, err); 2156*f0865ec9SKyle Evans ret = local_memset(&_Tmp2, 0, sizeof(prj_pt)); EG(ret, err); 2157*f0865ec9SKyle Evans ret = local_memset(hash, 0, sizeof(hash)); EG(ret, err); 2158*f0865ec9SKyle Evans 2159*f0865ec9SKyle Evans /* Make things more readable */ 2160*f0865ec9SKyle Evans G = &(ctx->pub_key->params->ec_gen); 2161*f0865ec9SKyle Evans A = &(ctx->pub_key->y); 2162*f0865ec9SKyle Evans q = &(ctx->pub_key->params->ec_gen_order); 2163*f0865ec9SKyle Evans hsize = ctx->h->digest_size; 2164*f0865ec9SKyle Evans S = &(ctx->verify_data.eddsa.S); 2165*f0865ec9SKyle Evans _R = &(ctx->verify_data.eddsa._R); 2166*f0865ec9SKyle Evans gen_cofactor = &(ctx->pub_key->params->ec_gen_cofactor); 2167*f0865ec9SKyle Evans key_type = ctx->pub_key->key_type; 2168*f0865ec9SKyle Evans h_ctx = &(ctx->verify_data.eddsa.h_ctx); 2169*f0865ec9SKyle Evans h_ctx_pre_hash = &(ctx->verify_data.eddsa.h_ctx_pre_hash); 2170*f0865ec9SKyle Evans 2171*f0865ec9SKyle Evans /* Sanity check on hash types */ 2172*f0865ec9SKyle Evans MUST_HAVE((ctx->h->type == get_eddsa_hash_type(key_type)), ret, err); 2173*f0865ec9SKyle Evans 2174*f0865ec9SKyle Evans /* Do we use the raw message or its PH(M) hashed version? */ 2175*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519) 2176*f0865ec9SKyle Evans if(key_type == EDDSA25519PH){ 2177*f0865ec9SKyle Evans use_message_pre_hash = 1; 2178*f0865ec9SKyle Evans use_message_pre_hash_hsize = hsize; 2179*f0865ec9SKyle Evans } 2180*f0865ec9SKyle Evans #endif 2181*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 2182*f0865ec9SKyle Evans if(key_type == EDDSA448PH){ 2183*f0865ec9SKyle Evans use_message_pre_hash = 1; 2184*f0865ec9SKyle Evans /* NOTE: as per RFC8032, EDDSA448PH uses 2185*f0865ec9SKyle Evans * SHAKE256 with 64 bytes output. 2186*f0865ec9SKyle Evans */ 2187*f0865ec9SKyle Evans use_message_pre_hash_hsize = 64; 2188*f0865ec9SKyle Evans } 2189*f0865ec9SKyle Evans #endif 2190*f0865ec9SKyle Evans 2191*f0865ec9SKyle Evans /* Reject S if it is not reduced modulo q */ 2192*f0865ec9SKyle Evans ret = nn_cmp(S, q, &cmp); EG(ret, err); 2193*f0865ec9SKyle Evans MUST_HAVE((cmp < 0), ret, err); 2194*f0865ec9SKyle Evans 2195*f0865ec9SKyle Evans MUST_HAVE((hsize <= sizeof(hash)), ret, err); 2196*f0865ec9SKyle Evans 2197*f0865ec9SKyle Evans /* 2. Finish our computation of h = H(R || A || M) */ 2198*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 2199*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err); 2200*f0865ec9SKyle Evans /* Update the hash with the message or its hash for the PH versions */ 2201*f0865ec9SKyle Evans if(use_message_pre_hash == 1){ 2202*f0865ec9SKyle Evans ret = ctx->h->hfunc_finalize(h_ctx_pre_hash, hash); EG(ret, err); 2203*f0865ec9SKyle Evans MUST_HAVE((use_message_pre_hash_hsize <= hsize), ret, err); 2204*f0865ec9SKyle Evans ret = ctx->h->hfunc_update(h_ctx, hash, use_message_pre_hash_hsize); EG(ret, err); 2205*f0865ec9SKyle Evans } 2206*f0865ec9SKyle Evans ret = ctx->h->hfunc_finalize(h_ctx, hash); EG(ret, err); 2207*f0865ec9SKyle Evans dbg_buf_print("hash = H(R || A || PH(M))", hash, hsize); 2208*f0865ec9SKyle Evans 2209*f0865ec9SKyle Evans /* 3. Import our hash as a NN and reduce it modulo q */ 2210*f0865ec9SKyle Evans ret = eddsa_decode_integer(&h, hash, hsize); EG(ret, err); 2211*f0865ec9SKyle Evans ret = nn_mod(&h, &h, q); EG(ret, err); 2212*f0865ec9SKyle Evans dbg_nn_print("h = ", &h); 2213*f0865ec9SKyle Evans 2214*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 2215*f0865ec9SKyle Evans if((key_type == EDDSA448) || (key_type == EDDSA448PH)){ 2216*f0865ec9SKyle Evans /* When dealing with EDDSA448, because of our 4-isogeny between Edwars448 and Ed448 2217*f0865ec9SKyle Evans * mapping base point to four times base point, we actually multiply our public key by 4 here 2218*f0865ec9SKyle Evans * to be inline with the other computations (the public key stored in Weierstrass ) 2219*f0865ec9SKyle Evans */ 2220*f0865ec9SKyle Evans ret = nn_lshift(&h, &h, 2); EG(ret, err); 2221*f0865ec9SKyle Evans ret = nn_mod(&h, &h, q); EG(ret, err); 2222*f0865ec9SKyle Evans } 2223*f0865ec9SKyle Evans #endif 2224*f0865ec9SKyle Evans /* 4. Compute (S * G) - R - (h * A) */ 2225*f0865ec9SKyle Evans ret = prj_pt_mul(&_Tmp1, S, G); EG(ret, err); 2226*f0865ec9SKyle Evans ret = prj_pt_neg(&_Tmp2, _R); EG(ret, err); 2227*f0865ec9SKyle Evans ret = prj_pt_add(&_Tmp1, &_Tmp1, &_Tmp2); EG(ret, err); 2228*f0865ec9SKyle Evans ret = prj_pt_mul(&_Tmp2, &h, A); EG(ret, err); 2229*f0865ec9SKyle Evans ret = prj_pt_neg(&_Tmp2, &_Tmp2); EG(ret, err); 2230*f0865ec9SKyle Evans ret = prj_pt_add(&_Tmp1, &_Tmp1, &_Tmp2); EG(ret, err); 2231*f0865ec9SKyle Evans 2232*f0865ec9SKyle Evans /* 5. We use cofactored multiplication, so multiply by the cofactor: 2233*f0865ec9SKyle Evans * since this is a public verification, we use a basic double and add 2234*f0865ec9SKyle Evans * algorithm. 2235*f0865ec9SKyle Evans */ 2236*f0865ec9SKyle Evans ret = _prj_pt_unprotected_mult(&_Tmp2, gen_cofactor, &_Tmp1); EG(ret, err); 2237*f0865ec9SKyle Evans 2238*f0865ec9SKyle Evans /* Reject the signature if we do not have point at infinity here */ 2239*f0865ec9SKyle Evans ret = prj_pt_iszero(&_Tmp2, &iszero); EG(ret, err); 2240*f0865ec9SKyle Evans ret = iszero ? 0 : -1; 2241*f0865ec9SKyle Evans 2242*f0865ec9SKyle Evans err: 2243*f0865ec9SKyle Evans /* 2244*f0865ec9SKyle Evans * We can now clear data part of the context. This will clear 2245*f0865ec9SKyle Evans * magic and avoid further reuse of the whole context. 2246*f0865ec9SKyle Evans */ 2247*f0865ec9SKyle Evans if(ctx != NULL){ 2248*f0865ec9SKyle Evans IGNORE_RET_VAL(local_memset(&(ctx->verify_data.eddsa), 0, sizeof(eddsa_verify_data))); 2249*f0865ec9SKyle Evans } 2250*f0865ec9SKyle Evans 2251*f0865ec9SKyle Evans /* Clean what remains on the stack */ 2252*f0865ec9SKyle Evans PTR_NULLIFY(G); 2253*f0865ec9SKyle Evans PTR_NULLIFY(A); 2254*f0865ec9SKyle Evans PTR_NULLIFY(q); 2255*f0865ec9SKyle Evans PTR_NULLIFY(S); 2256*f0865ec9SKyle Evans PTR_NULLIFY(_R); 2257*f0865ec9SKyle Evans PTR_NULLIFY(gen_cofactor); 2258*f0865ec9SKyle Evans VAR_ZEROIFY(hsize); 2259*f0865ec9SKyle Evans VAR_ZEROIFY(use_message_pre_hash); 2260*f0865ec9SKyle Evans VAR_ZEROIFY(use_message_pre_hash_hsize); 2261*f0865ec9SKyle Evans 2262*f0865ec9SKyle Evans nn_uninit(&h); 2263*f0865ec9SKyle Evans prj_pt_uninit(&_Tmp1); 2264*f0865ec9SKyle Evans prj_pt_uninit(&_Tmp2); 2265*f0865ec9SKyle Evans 2266*f0865ec9SKyle Evans return ret; 2267*f0865ec9SKyle Evans } 2268*f0865ec9SKyle Evans 2269*f0865ec9SKyle Evans /* Batch verification function: 2270*f0865ec9SKyle Evans * This function takes multiple signatures/messages/public keys, and 2271*f0865ec9SKyle Evans * checks all the signatures. 2272*f0865ec9SKyle Evans * 2273*f0865ec9SKyle Evans * This returns 0 if *all* the signatures are correct, and -1 if at least 2274*f0865ec9SKyle Evans * one signature is not correct. 2275*f0865ec9SKyle Evans * 2276*f0865ec9SKyle Evans * NOTE: the "no_memory" version is not optimized and straightforwardly 2277*f0865ec9SKyle Evans * checks for the signature using naive sums. See below for an optimized 2278*f0865ec9SKyle Evans * Bos-Coster version (but requiring additional memory to work). 2279*f0865ec9SKyle Evans * 2280*f0865ec9SKyle Evans */ 2281*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int _eddsa_verify_batch_no_memory(const u8 **s, const u8 *s_len, const ec_pub_key **pub_keys, 2282*f0865ec9SKyle Evans const u8 **m, const u32 *m_len, u32 num, ec_alg_type sig_type, 2283*f0865ec9SKyle Evans hash_alg_type hash_type, const u8 **adata, const u16 *adata_len) 2284*f0865ec9SKyle Evans { 2285*f0865ec9SKyle Evans nn_src_t q = NULL; 2286*f0865ec9SKyle Evans ec_edwards_crv crv_edwards; 2287*f0865ec9SKyle Evans aff_pt_edwards R, A; 2288*f0865ec9SKyle Evans prj_pt_src_t G = NULL; 2289*f0865ec9SKyle Evans prj_pt _Tmp, _R_sum, _A_sum; 2290*f0865ec9SKyle Evans nn S, S_sum, z, h; 2291*f0865ec9SKyle Evans u8 hash[MAX_DIGEST_SIZE]; 2292*f0865ec9SKyle Evans int ret, iszero, cmp; 2293*f0865ec9SKyle Evans u16 hsize; 2294*f0865ec9SKyle Evans const ec_pub_key *pub_key, *pub_key0; 2295*f0865ec9SKyle Evans ec_shortw_crv_src_t shortw_curve; 2296*f0865ec9SKyle Evans fp_src_t alpha_montgomery; 2297*f0865ec9SKyle Evans fp_src_t gamma_montgomery; 2298*f0865ec9SKyle Evans fp_src_t alpha_edwards; 2299*f0865ec9SKyle Evans nn_src_t gen_cofactor = NULL; 2300*f0865ec9SKyle Evans prj_pt_src_t pub_key_y; 2301*f0865ec9SKyle Evans hash_context h_ctx; 2302*f0865ec9SKyle Evans hash_context h_ctx_pre_hash; 2303*f0865ec9SKyle Evans u8 use_message_pre_hash = 0; 2304*f0865ec9SKyle Evans u16 use_message_pre_hash_hsize = 0; 2305*f0865ec9SKyle Evans const hash_mapping *hm; 2306*f0865ec9SKyle Evans ec_alg_type key_type = UNKNOWN_ALG; 2307*f0865ec9SKyle Evans u32 i; 2308*f0865ec9SKyle Evans 2309*f0865ec9SKyle Evans R.magic = S.magic = S_sum.magic = crv_edwards.magic = WORD(0); 2310*f0865ec9SKyle Evans _Tmp.magic = _R_sum.magic = _A_sum.magic = WORD(0); 2311*f0865ec9SKyle Evans z.magic = h.magic = WORD(0); 2312*f0865ec9SKyle Evans 2313*f0865ec9SKyle Evans /* First, some sanity checks */ 2314*f0865ec9SKyle Evans MUST_HAVE((s != NULL) && (pub_keys != NULL) && (m != NULL) && (adata != NULL), ret, err); 2315*f0865ec9SKyle Evans /* We need at least one element in our batch data bags */ 2316*f0865ec9SKyle Evans MUST_HAVE((num > 0), ret, err); 2317*f0865ec9SKyle Evans 2318*f0865ec9SKyle Evans 2319*f0865ec9SKyle Evans /* Zero init our local data */ 2320*f0865ec9SKyle Evans ret = local_memset(&crv_edwards, 0, sizeof(ec_edwards_crv)); EG(ret, err); 2321*f0865ec9SKyle Evans ret = local_memset(hash, 0, sizeof(hash)); EG(ret, err); 2322*f0865ec9SKyle Evans ret = local_memset(&A, 0, sizeof(aff_pt_edwards)); EG(ret, err); 2323*f0865ec9SKyle Evans ret = local_memset(&R, 0, sizeof(aff_pt_edwards)); EG(ret, err); 2324*f0865ec9SKyle Evans ret = local_memset(&_R_sum, 0, sizeof(prj_pt)); EG(ret, err); 2325*f0865ec9SKyle Evans ret = local_memset(&_A_sum, 0, sizeof(prj_pt)); EG(ret, err); 2326*f0865ec9SKyle Evans ret = local_memset(&_Tmp, 0, sizeof(prj_pt)); EG(ret, err); 2327*f0865ec9SKyle Evans 2328*f0865ec9SKyle Evans pub_key0 = pub_keys[0]; 2329*f0865ec9SKyle Evans MUST_HAVE((pub_key0 != NULL), ret, err); 2330*f0865ec9SKyle Evans 2331*f0865ec9SKyle Evans /* Get our hash mapping */ 2332*f0865ec9SKyle Evans ret = get_hash_by_type(hash_type, &hm); EG(ret, err); 2333*f0865ec9SKyle Evans hsize = hm->digest_size; 2334*f0865ec9SKyle Evans MUST_HAVE((hm != NULL), ret, err); 2335*f0865ec9SKyle Evans 2336*f0865ec9SKyle Evans /* Do we use the raw message or its PH(M) hashed version? */ 2337*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519) 2338*f0865ec9SKyle Evans if(sig_type == EDDSA25519PH){ 2339*f0865ec9SKyle Evans use_message_pre_hash = 1; 2340*f0865ec9SKyle Evans use_message_pre_hash_hsize = hsize; 2341*f0865ec9SKyle Evans } 2342*f0865ec9SKyle Evans #endif 2343*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 2344*f0865ec9SKyle Evans if(sig_type == EDDSA448PH){ 2345*f0865ec9SKyle Evans use_message_pre_hash = 1; 2346*f0865ec9SKyle Evans /* NOTE: as per RFC8032, EDDSA448PH uses 2347*f0865ec9SKyle Evans * SHAKE256 with 64 bytes output. 2348*f0865ec9SKyle Evans */ 2349*f0865ec9SKyle Evans use_message_pre_hash_hsize = 64; 2350*f0865ec9SKyle Evans } 2351*f0865ec9SKyle Evans #endif 2352*f0865ec9SKyle Evans 2353*f0865ec9SKyle Evans for(i = 0; i < num; i++){ 2354*f0865ec9SKyle Evans u8 siglen; 2355*f0865ec9SKyle Evans const u8 *sig = NULL; 2356*f0865ec9SKyle Evans 2357*f0865ec9SKyle Evans ret = eddsa_pub_key_sanity_check(pub_keys[i]); EG(ret, err); 2358*f0865ec9SKyle Evans 2359*f0865ec9SKyle Evans /* Make things more readable */ 2360*f0865ec9SKyle Evans pub_key = pub_keys[i]; 2361*f0865ec9SKyle Evans 2362*f0865ec9SKyle Evans /* Sanity check that all our public keys have the same parameters */ 2363*f0865ec9SKyle Evans MUST_HAVE((pub_key->params) == (pub_key0->params), ret, err); 2364*f0865ec9SKyle Evans 2365*f0865ec9SKyle Evans q = &(pub_key->params->ec_gen_order); 2366*f0865ec9SKyle Evans shortw_curve = &(pub_key->params->ec_curve); 2367*f0865ec9SKyle Evans alpha_montgomery = &(pub_key->params->ec_alpha_montgomery); 2368*f0865ec9SKyle Evans gamma_montgomery = &(pub_key->params->ec_gamma_montgomery); 2369*f0865ec9SKyle Evans alpha_edwards = &(pub_key->params->ec_alpha_edwards); 2370*f0865ec9SKyle Evans gen_cofactor = &(pub_key->params->ec_gen_cofactor); 2371*f0865ec9SKyle Evans pub_key_y = &(pub_key->y); 2372*f0865ec9SKyle Evans key_type = pub_key->key_type; 2373*f0865ec9SKyle Evans G = &(pub_key->params->ec_gen); 2374*f0865ec9SKyle Evans 2375*f0865ec9SKyle Evans /* Check the key type versus the algorithm */ 2376*f0865ec9SKyle Evans MUST_HAVE((key_type == sig_type), ret, err); 2377*f0865ec9SKyle Evans 2378*f0865ec9SKyle Evans if(i == 0){ 2379*f0865ec9SKyle Evans /* Initialize our sums to zero/point at infinity */ 2380*f0865ec9SKyle Evans ret = nn_init(&S_sum, 0); EG(ret, err); 2381*f0865ec9SKyle Evans ret = prj_pt_init(&_R_sum, shortw_curve); EG(ret, err); 2382*f0865ec9SKyle Evans ret = prj_pt_zero(&_R_sum); EG(ret, err); 2383*f0865ec9SKyle Evans ret = prj_pt_init(&_A_sum, shortw_curve); EG(ret, err); 2384*f0865ec9SKyle Evans ret = prj_pt_zero(&_A_sum); EG(ret, err); 2385*f0865ec9SKyle Evans ret = nn_init(&z, 0); EG(ret, err); 2386*f0865ec9SKyle Evans ret = nn_init(&h, 0); EG(ret, err); 2387*f0865ec9SKyle Evans } 2388*f0865ec9SKyle Evans 2389*f0865ec9SKyle Evans gen_z_again: 2390*f0865ec9SKyle Evans /* Get a random z for randomizing the linear combination */ 2391*f0865ec9SKyle Evans ret = nn_get_random_len(&z, (hsize / 4)); EG(ret, err); 2392*f0865ec9SKyle Evans ret = nn_iszero(&z, &iszero); EG(ret, err); 2393*f0865ec9SKyle Evans if(iszero){ 2394*f0865ec9SKyle Evans goto gen_z_again; 2395*f0865ec9SKyle Evans } 2396*f0865ec9SKyle Evans 2397*f0865ec9SKyle Evans /* Sanity check on hash types */ 2398*f0865ec9SKyle Evans MUST_HAVE((hash_type == get_eddsa_hash_type(key_type)), ret, err); 2399*f0865ec9SKyle Evans 2400*f0865ec9SKyle Evans /* Check given signature length is the expected one */ 2401*f0865ec9SKyle Evans siglen = s_len[i]; 2402*f0865ec9SKyle Evans sig = s[i]; 2403*f0865ec9SKyle Evans MUST_HAVE((siglen == EDDSA_SIGLEN(hsize)), ret, err); 2404*f0865ec9SKyle Evans MUST_HAVE((siglen == (EDDSA_R_LEN(hsize) + EDDSA_S_LEN(hsize))), ret, err); 2405*f0865ec9SKyle Evans 2406*f0865ec9SKyle Evans /* Initialize the hash context */ 2407*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 2408*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(hm); EG(ret, err); 2409*f0865ec9SKyle Evans ret = hm->hfunc_init(&h_ctx); EG(ret, err); 2410*f0865ec9SKyle Evans ret = hm->hfunc_init(&h_ctx_pre_hash); EG(ret, err); 2411*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519) 2412*f0865ec9SKyle Evans if(key_type == EDDSA25519CTX){ 2413*f0865ec9SKyle Evans /* As per RFC8032, for EDDSA25519CTX the context SHOULD NOT be empty */ 2414*f0865ec9SKyle Evans MUST_HAVE((adata[i] != NULL), ret, err); 2415*f0865ec9SKyle Evans ret = dom2(0, adata[i], adata_len[i], hm, &h_ctx); EG(ret, err); 2416*f0865ec9SKyle Evans } 2417*f0865ec9SKyle Evans if(key_type == EDDSA25519PH){ 2418*f0865ec9SKyle Evans ret = dom2(1, adata[i], adata_len[i], hm, &h_ctx); EG(ret, err); 2419*f0865ec9SKyle Evans } 2420*f0865ec9SKyle Evans #endif 2421*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 2422*f0865ec9SKyle Evans if(key_type == EDDSA448){ 2423*f0865ec9SKyle Evans ret = dom4(0, adata[i], adata_len[i], hm, &h_ctx); EG(ret, err); 2424*f0865ec9SKyle Evans } 2425*f0865ec9SKyle Evans if(key_type == EDDSA448PH){ 2426*f0865ec9SKyle Evans ret = dom4(1, adata[i], adata_len[i], hm, &h_ctx); EG(ret, err); 2427*f0865ec9SKyle Evans } 2428*f0865ec9SKyle Evans #endif 2429*f0865ec9SKyle Evans /* Import R and S values from signature buffer */ 2430*f0865ec9SKyle Evans /*******************************/ 2431*f0865ec9SKyle Evans /* Import R as an Edwards point */ 2432*f0865ec9SKyle Evans ret = curve_shortw_to_edwards(shortw_curve, &crv_edwards, alpha_montgomery, 2433*f0865ec9SKyle Evans gamma_montgomery, alpha_edwards); EG(ret, err); 2434*f0865ec9SKyle Evans /* NOTE: non canonical R are checked and rejected here */ 2435*f0865ec9SKyle Evans ret = eddsa_decode_point(&R, &crv_edwards, alpha_edwards, &sig[0], 2436*f0865ec9SKyle Evans EDDSA_R_LEN(hsize), key_type); EG(ret, err); 2437*f0865ec9SKyle Evans dbg_ec_edwards_point_print("R", &R); 2438*f0865ec9SKyle Evans /* Transfer our public point R to Weierstrass */ 2439*f0865ec9SKyle Evans ret = aff_pt_edwards_to_prj_pt_shortw(&R, shortw_curve, &_Tmp, alpha_edwards); EG(ret, err); 2440*f0865ec9SKyle Evans /* Update the hash with the encoded R */ 2441*f0865ec9SKyle Evans ret = hm->hfunc_update(&h_ctx, &sig[0], EDDSA_R_LEN(hsize)); EG(ret, err); 2442*f0865ec9SKyle Evans /* Multiply by z. 2443*f0865ec9SKyle Evans */ 2444*f0865ec9SKyle Evans ret = _prj_pt_unprotected_mult(&_Tmp, &z, &_Tmp); EG(ret, err); 2445*f0865ec9SKyle Evans /* Add to the sum */ 2446*f0865ec9SKyle Evans ret = prj_pt_add(&_R_sum, &_R_sum, &_Tmp); EG(ret, err); 2447*f0865ec9SKyle Evans 2448*f0865ec9SKyle Evans /*******************************/ 2449*f0865ec9SKyle Evans /* Import S as an integer */ 2450*f0865ec9SKyle Evans ret = eddsa_decode_integer(&S, &sig[EDDSA_R_LEN(hsize)], EDDSA_S_LEN(hsize)); EG(ret, err); 2451*f0865ec9SKyle Evans /* Reject S if it is not reduced modulo q */ 2452*f0865ec9SKyle Evans ret = nn_cmp(&S, q, &cmp); EG(ret, err); 2453*f0865ec9SKyle Evans MUST_HAVE((cmp < 0), ret, err); 2454*f0865ec9SKyle Evans dbg_nn_print("S", &S); 2455*f0865ec9SKyle Evans 2456*f0865ec9SKyle Evans /* Add z S to the sum */ 2457*f0865ec9SKyle Evans ret = nn_mul(&S, &S, &z); EG(ret, err); 2458*f0865ec9SKyle Evans ret = nn_mod(&S, &S, q); EG(ret, err); 2459*f0865ec9SKyle Evans ret = nn_mod_add(&S_sum, &S_sum, &S, q); EG(ret, err); 2460*f0865ec9SKyle Evans 2461*f0865ec9SKyle Evans /*******************************/ 2462*f0865ec9SKyle Evans /* Encode the public key 2463*f0865ec9SKyle Evans * NOTE: since we deal with a public key transfered to Weierstrass, 2464*f0865ec9SKyle Evans * encoding checking has been handled elsewhere. 2465*f0865ec9SKyle Evans */ 2466*f0865ec9SKyle Evans /* Reject the signature if the public key is one of small order points. 2467*f0865ec9SKyle Evans * We multiply by the cofactor: since this is a public verification, 2468*f0865ec9SKyle Evans * we use a basic double and add algorithm. 2469*f0865ec9SKyle Evans */ 2470*f0865ec9SKyle Evans ret = _prj_pt_unprotected_mult(&_Tmp, gen_cofactor, pub_key_y); EG(ret, err); 2471*f0865ec9SKyle Evans /* Reject the signature if we have point at infinity here as this means 2472*f0865ec9SKyle Evans * that the public key is of small order. 2473*f0865ec9SKyle Evans */ 2474*f0865ec9SKyle Evans ret = prj_pt_iszero(&_Tmp, &iszero); EG(ret, err); 2475*f0865ec9SKyle Evans MUST_HAVE((!iszero), ret, err); 2476*f0865ec9SKyle Evans 2477*f0865ec9SKyle Evans /* Transfer the public key to Edwards */ 2478*f0865ec9SKyle Evans ret = prj_pt_shortw_to_aff_pt_edwards(pub_key_y, &crv_edwards, &A, alpha_edwards); EG(ret, err); 2479*f0865ec9SKyle Evans dbg_ec_edwards_point_print("A", &A); 2480*f0865ec9SKyle Evans MUST_HAVE((EDDSA_R_LEN(hsize) <= sizeof(hash)), ret, err); 2481*f0865ec9SKyle Evans /* NOTE: we use the hash buffer as a temporary buffer */ 2482*f0865ec9SKyle Evans ret = eddsa_encode_point(&A, alpha_edwards, hash, EDDSA_R_LEN(hsize), key_type); EG(ret, err); 2483*f0865ec9SKyle Evans 2484*f0865ec9SKyle Evans /* Update the hash with the encoded public key */ 2485*f0865ec9SKyle Evans ret = hm->hfunc_update(&h_ctx, hash, EDDSA_R_LEN(hsize)); EG(ret, err); 2486*f0865ec9SKyle Evans /* Finish our computation of h = H(R || A || M) */ 2487*f0865ec9SKyle Evans /* Update the hash with the message or its hash for the PH versions */ 2488*f0865ec9SKyle Evans if(use_message_pre_hash == 1){ 2489*f0865ec9SKyle Evans ret = hm->hfunc_update(&h_ctx_pre_hash, m[i], m_len[i]); EG(ret, err); 2490*f0865ec9SKyle Evans ret = hm->hfunc_finalize(&h_ctx_pre_hash, hash); EG(ret, err); 2491*f0865ec9SKyle Evans MUST_HAVE((use_message_pre_hash_hsize <= hsize), ret, err); 2492*f0865ec9SKyle Evans ret = hm->hfunc_update(&h_ctx, hash, use_message_pre_hash_hsize); EG(ret, err); 2493*f0865ec9SKyle Evans } 2494*f0865ec9SKyle Evans else{ 2495*f0865ec9SKyle Evans ret = hm->hfunc_update(&h_ctx, m[i], m_len[i]); EG(ret, err); 2496*f0865ec9SKyle Evans } 2497*f0865ec9SKyle Evans ret = hm->hfunc_finalize(&h_ctx, hash); EG(ret, err); 2498*f0865ec9SKyle Evans dbg_buf_print("hash = H(R || A || PH(M))", hash, hsize); 2499*f0865ec9SKyle Evans 2500*f0865ec9SKyle Evans /* Import our hash as a NN and reduce it modulo q */ 2501*f0865ec9SKyle Evans ret = eddsa_decode_integer(&h, hash, hsize); EG(ret, err); 2502*f0865ec9SKyle Evans ret = nn_mod(&h, &h, q); EG(ret, err); 2503*f0865ec9SKyle Evans dbg_nn_print("h = ", &h); 2504*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 2505*f0865ec9SKyle Evans if((key_type == EDDSA448) || (key_type == EDDSA448PH)){ 2506*f0865ec9SKyle Evans /* When dealing with EDDSA448, because of our 4-isogeny between Edwars448 and Ed448 2507*f0865ec9SKyle Evans * mapping base point to four times base point, we actually multiply our public key by 4 here 2508*f0865ec9SKyle Evans * to be inline with the other computations (the public key stored in Weierstrass ) 2509*f0865ec9SKyle Evans */ 2510*f0865ec9SKyle Evans ret = nn_lshift(&h, &h, 2); EG(ret, err); 2511*f0865ec9SKyle Evans ret = nn_mod(&h, &h, q); EG(ret, err); 2512*f0865ec9SKyle Evans } 2513*f0865ec9SKyle Evans #endif 2514*f0865ec9SKyle Evans 2515*f0865ec9SKyle Evans /* Multiply by (z * h) mod q. 2516*f0865ec9SKyle Evans * NOTE: we use unprotected scalar multiplication since this is a 2517*f0865ec9SKyle Evans * public operation. 2518*f0865ec9SKyle Evans */ 2519*f0865ec9SKyle Evans ret = nn_mul(&z, &z, &h); EG(ret, err); 2520*f0865ec9SKyle Evans ret = nn_mod(&z, &z, q); EG(ret, err); 2521*f0865ec9SKyle Evans ret = _prj_pt_unprotected_mult(&_Tmp, &z, &_Tmp); EG(ret, err); 2522*f0865ec9SKyle Evans /* Add to the sum */ 2523*f0865ec9SKyle Evans ret = prj_pt_add(&_A_sum, &_A_sum, &_Tmp); EG(ret, err); 2524*f0865ec9SKyle Evans } 2525*f0865ec9SKyle Evans 2526*f0865ec9SKyle Evans /* Sanity check */ 2527*f0865ec9SKyle Evans MUST_HAVE((gen_cofactor != NULL) && (q != NULL) && (G != NULL), ret, err); 2528*f0865ec9SKyle Evans 2529*f0865ec9SKyle Evans /* Multiply the S sum by the cofactor */ 2530*f0865ec9SKyle Evans ret = nn_mul(&S_sum, &S_sum, gen_cofactor); EG(ret, err); 2531*f0865ec9SKyle Evans ret = nn_mod(&S_sum, &S_sum, q); EG(ret, err); 2532*f0865ec9SKyle Evans /* Negate it. NOTE: -x mod q is (q - x) mod q, i.e. (q - x) when x is reduced */ 2533*f0865ec9SKyle Evans ret = nn_mod_neg(&S_sum, &S_sum, q); EG(ret, err); 2534*f0865ec9SKyle Evans /* Multiply this by the generator */ 2535*f0865ec9SKyle Evans ret = _prj_pt_unprotected_mult(&_Tmp, &S_sum, G); EG(ret, err); 2536*f0865ec9SKyle Evans 2537*f0865ec9SKyle Evans /* Multiply the R sum by the cofactor */ 2538*f0865ec9SKyle Evans ret = _prj_pt_unprotected_mult(&_R_sum, gen_cofactor, &_R_sum); EG(ret, err); 2539*f0865ec9SKyle Evans 2540*f0865ec9SKyle Evans /* Now add the three sums */ 2541*f0865ec9SKyle Evans ret = prj_pt_add(&_Tmp, &_Tmp, &_A_sum); 2542*f0865ec9SKyle Evans ret = prj_pt_add(&_Tmp, &_Tmp, &_R_sum); 2543*f0865ec9SKyle Evans 2544*f0865ec9SKyle Evans /* Reject the signature if we do not have point at infinity here */ 2545*f0865ec9SKyle Evans ret = prj_pt_iszero(&_Tmp, &iszero); EG(ret, err); 2546*f0865ec9SKyle Evans ret = iszero ? 0 : -1; 2547*f0865ec9SKyle Evans 2548*f0865ec9SKyle Evans err: 2549*f0865ec9SKyle Evans PTR_NULLIFY(q); 2550*f0865ec9SKyle Evans PTR_NULLIFY(pub_key); 2551*f0865ec9SKyle Evans PTR_NULLIFY(pub_key0); 2552*f0865ec9SKyle Evans PTR_NULLIFY(shortw_curve); 2553*f0865ec9SKyle Evans PTR_NULLIFY(alpha_montgomery); 2554*f0865ec9SKyle Evans PTR_NULLIFY(gamma_montgomery); 2555*f0865ec9SKyle Evans PTR_NULLIFY(alpha_edwards); 2556*f0865ec9SKyle Evans PTR_NULLIFY(gen_cofactor); 2557*f0865ec9SKyle Evans PTR_NULLIFY(pub_key_y); 2558*f0865ec9SKyle Evans PTR_NULLIFY(G); 2559*f0865ec9SKyle Evans 2560*f0865ec9SKyle Evans ec_edwards_crv_uninit(&crv_edwards); 2561*f0865ec9SKyle Evans aff_pt_edwards_uninit(&A); 2562*f0865ec9SKyle Evans aff_pt_edwards_uninit(&R); 2563*f0865ec9SKyle Evans prj_pt_uninit(&_R_sum); 2564*f0865ec9SKyle Evans prj_pt_uninit(&_A_sum); 2565*f0865ec9SKyle Evans prj_pt_uninit(&_Tmp); 2566*f0865ec9SKyle Evans nn_uninit(&S); 2567*f0865ec9SKyle Evans nn_uninit(&S_sum); 2568*f0865ec9SKyle Evans nn_uninit(&z); 2569*f0865ec9SKyle Evans nn_uninit(&h); 2570*f0865ec9SKyle Evans 2571*f0865ec9SKyle Evans return ret; 2572*f0865ec9SKyle Evans 2573*f0865ec9SKyle Evans } 2574*f0865ec9SKyle Evans 2575*f0865ec9SKyle Evans /* 2576*f0865ec9SKyle Evans * The following batch verification uses the Bos-Coster algorithm, presented e.g. in 2577*f0865ec9SKyle Evans * https://ed25519.cr.yp.to/ed25519-20110705.pdf 2578*f0865ec9SKyle Evans * 2579*f0865ec9SKyle Evans * The Bos-Coster algorithm allows to optimize a sum of scalar multiplications using 2580*f0865ec9SKyle Evans * addition chains. 2581*f0865ec9SKyle Evans * 2582*f0865ec9SKyle Evans */ 2583*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int _eddsa_verify_batch(const u8 **s, const u8 *s_len, const ec_pub_key **pub_keys, 2584*f0865ec9SKyle Evans const u8 **m, const u32 *m_len, u32 num, ec_alg_type sig_type, 2585*f0865ec9SKyle Evans hash_alg_type hash_type, const u8 **adata, const u16 *adata_len, 2586*f0865ec9SKyle Evans verify_batch_scratch_pad *scratch_pad_area, u32 *scratch_pad_area_len) 2587*f0865ec9SKyle Evans { 2588*f0865ec9SKyle Evans nn_src_t q = NULL; 2589*f0865ec9SKyle Evans ec_edwards_crv crv_edwards; 2590*f0865ec9SKyle Evans aff_pt_edwards R, A; 2591*f0865ec9SKyle Evans prj_pt_src_t G = NULL; 2592*f0865ec9SKyle Evans nn S, z; 2593*f0865ec9SKyle Evans u8 hash[MAX_DIGEST_SIZE]; 2594*f0865ec9SKyle Evans int ret, iszero, cmp; 2595*f0865ec9SKyle Evans u16 hsize; 2596*f0865ec9SKyle Evans const ec_pub_key *pub_key, *pub_key0; 2597*f0865ec9SKyle Evans ec_shortw_crv_src_t shortw_curve; 2598*f0865ec9SKyle Evans fp_src_t alpha_montgomery; 2599*f0865ec9SKyle Evans fp_src_t gamma_montgomery; 2600*f0865ec9SKyle Evans fp_src_t alpha_edwards; 2601*f0865ec9SKyle Evans nn_src_t gen_cofactor = NULL; 2602*f0865ec9SKyle Evans prj_pt_src_t pub_key_y; 2603*f0865ec9SKyle Evans hash_context h_ctx; 2604*f0865ec9SKyle Evans hash_context h_ctx_pre_hash; 2605*f0865ec9SKyle Evans u8 use_message_pre_hash = 0; 2606*f0865ec9SKyle Evans u16 use_message_pre_hash_hsize = 0; 2607*f0865ec9SKyle Evans const hash_mapping *hm; 2608*f0865ec9SKyle Evans ec_alg_type key_type = UNKNOWN_ALG; 2609*f0865ec9SKyle Evans /* NN numbers and points pointers */ 2610*f0865ec9SKyle Evans verify_batch_scratch_pad *elements = scratch_pad_area; 2611*f0865ec9SKyle Evans u32 i; 2612*f0865ec9SKyle Evans u64 expected_len; 2613*f0865ec9SKyle Evans bitcnt_t q_bit_len = 0; 2614*f0865ec9SKyle Evans 2615*f0865ec9SKyle Evans S.magic = z.magic = crv_edwards.magic = WORD(0); 2616*f0865ec9SKyle Evans 2617*f0865ec9SKyle Evans /* First, some sanity checks */ 2618*f0865ec9SKyle Evans MUST_HAVE((s != NULL) && (pub_keys != NULL) && (m != NULL) && (adata != NULL), ret, err); 2619*f0865ec9SKyle Evans MUST_HAVE((scratch_pad_area_len != NULL), ret, err); 2620*f0865ec9SKyle Evans MUST_HAVE(((2 * num) >= num), ret, err); 2621*f0865ec9SKyle Evans MUST_HAVE(((2 * num) + 1) >= num, ret, err); 2622*f0865ec9SKyle Evans 2623*f0865ec9SKyle Evans /* In oder to apply the algorithm, we must have at least two 2624*f0865ec9SKyle Evans * elements to verify. If this is not the case, we fallback to 2625*f0865ec9SKyle Evans * the regular "no memory" version. 2626*f0865ec9SKyle Evans */ 2627*f0865ec9SKyle Evans if(num <= 1){ 2628*f0865ec9SKyle Evans if(scratch_pad_area == NULL){ 2629*f0865ec9SKyle Evans /* We do not require any memory in this case */ 2630*f0865ec9SKyle Evans (*scratch_pad_area_len) = 0; 2631*f0865ec9SKyle Evans ret = 0; 2632*f0865ec9SKyle Evans goto err; 2633*f0865ec9SKyle Evans } 2634*f0865ec9SKyle Evans else{ 2635*f0865ec9SKyle Evans ret = _eddsa_verify_batch_no_memory(s, s_len, pub_keys, m, m_len, num, sig_type, 2636*f0865ec9SKyle Evans hash_type, adata, adata_len); 2637*f0865ec9SKyle Evans goto err; 2638*f0865ec9SKyle Evans } 2639*f0865ec9SKyle Evans } 2640*f0865ec9SKyle Evans 2641*f0865ec9SKyle Evans expected_len = ((2 * num) + 1) * sizeof(verify_batch_scratch_pad); 2642*f0865ec9SKyle Evans MUST_HAVE((expected_len < 0xffffffff), ret, err); 2643*f0865ec9SKyle Evans 2644*f0865ec9SKyle Evans if(scratch_pad_area == NULL){ 2645*f0865ec9SKyle Evans /* Return the needed size: we need to keep track of (2 * num) + 1 NN numbers 2646*f0865ec9SKyle Evans * and (2 * num) + 1 projective points, plus (2 * num) + 1 indices 2647*f0865ec9SKyle Evans */ 2648*f0865ec9SKyle Evans (*scratch_pad_area_len) = (u32)expected_len; 2649*f0865ec9SKyle Evans ret = 0; 2650*f0865ec9SKyle Evans goto err; 2651*f0865ec9SKyle Evans } 2652*f0865ec9SKyle Evans else{ 2653*f0865ec9SKyle Evans MUST_HAVE((*scratch_pad_area_len) >= expected_len, ret, err); 2654*f0865ec9SKyle Evans } 2655*f0865ec9SKyle Evans 2656*f0865ec9SKyle Evans /********************************************/ 2657*f0865ec9SKyle Evans /****** Initialize elements *****************/ 2658*f0865ec9SKyle Evans /* Zero init our local data */ 2659*f0865ec9SKyle Evans ret = local_memset(&crv_edwards, 0, sizeof(ec_edwards_crv)); EG(ret, err); 2660*f0865ec9SKyle Evans ret = local_memset(hash, 0, sizeof(hash)); EG(ret, err); 2661*f0865ec9SKyle Evans ret = local_memset(&A, 0, sizeof(aff_pt_edwards)); EG(ret, err); 2662*f0865ec9SKyle Evans ret = local_memset(&R, 0, sizeof(aff_pt_edwards)); EG(ret, err); 2663*f0865ec9SKyle Evans 2664*f0865ec9SKyle Evans pub_key0 = pub_keys[0]; 2665*f0865ec9SKyle Evans MUST_HAVE((pub_key0 != NULL), ret, err); 2666*f0865ec9SKyle Evans 2667*f0865ec9SKyle Evans /* Get our hash mapping */ 2668*f0865ec9SKyle Evans ret = get_hash_by_type(hash_type, &hm); EG(ret, err); 2669*f0865ec9SKyle Evans hsize = hm->digest_size; 2670*f0865ec9SKyle Evans MUST_HAVE((hm != NULL), ret, err); 2671*f0865ec9SKyle Evans 2672*f0865ec9SKyle Evans /* Do we use the raw message or its PH(M) hashed version? */ 2673*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519) 2674*f0865ec9SKyle Evans if(sig_type == EDDSA25519PH){ 2675*f0865ec9SKyle Evans use_message_pre_hash = 1; 2676*f0865ec9SKyle Evans use_message_pre_hash_hsize = hsize; 2677*f0865ec9SKyle Evans } 2678*f0865ec9SKyle Evans #endif 2679*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 2680*f0865ec9SKyle Evans if(sig_type == EDDSA448PH){ 2681*f0865ec9SKyle Evans use_message_pre_hash = 1; 2682*f0865ec9SKyle Evans /* NOTE: as per RFC8032, EDDSA448PH uses 2683*f0865ec9SKyle Evans * SHAKE256 with 64 bytes output. 2684*f0865ec9SKyle Evans */ 2685*f0865ec9SKyle Evans use_message_pre_hash_hsize = 64; 2686*f0865ec9SKyle Evans } 2687*f0865ec9SKyle Evans #endif 2688*f0865ec9SKyle Evans 2689*f0865ec9SKyle Evans /* Compute our original numbers and points */ 2690*f0865ec9SKyle Evans MUST_HAVE((num >= 1), ret, err); 2691*f0865ec9SKyle Evans for(i = 0; i < num; i++){ 2692*f0865ec9SKyle Evans u8 siglen; 2693*f0865ec9SKyle Evans const u8 *sig = NULL; 2694*f0865ec9SKyle Evans 2695*f0865ec9SKyle Evans ret = eddsa_pub_key_sanity_check(pub_keys[i]); EG(ret, err); 2696*f0865ec9SKyle Evans 2697*f0865ec9SKyle Evans /* Make things more readable */ 2698*f0865ec9SKyle Evans pub_key = pub_keys[i]; 2699*f0865ec9SKyle Evans 2700*f0865ec9SKyle Evans /* Sanity check that all our public keys have the same parameters */ 2701*f0865ec9SKyle Evans MUST_HAVE((pub_key->params) == (pub_key0->params), ret, err); 2702*f0865ec9SKyle Evans 2703*f0865ec9SKyle Evans q = &(pub_key->params->ec_gen_order); 2704*f0865ec9SKyle Evans shortw_curve = &(pub_key->params->ec_curve); 2705*f0865ec9SKyle Evans alpha_montgomery = &(pub_key->params->ec_alpha_montgomery); 2706*f0865ec9SKyle Evans gamma_montgomery = &(pub_key->params->ec_gamma_montgomery); 2707*f0865ec9SKyle Evans alpha_edwards = &(pub_key->params->ec_alpha_edwards); 2708*f0865ec9SKyle Evans gen_cofactor = &(pub_key->params->ec_gen_cofactor); 2709*f0865ec9SKyle Evans pub_key_y = &(pub_key->y); 2710*f0865ec9SKyle Evans key_type = pub_key->key_type; 2711*f0865ec9SKyle Evans G = &(pub_key->params->ec_gen); 2712*f0865ec9SKyle Evans q_bit_len = pub_key->params->ec_gen_order_bitlen; 2713*f0865ec9SKyle Evans 2714*f0865ec9SKyle Evans /* Check the key type versus the algorithm */ 2715*f0865ec9SKyle Evans MUST_HAVE((key_type == sig_type), ret, err); 2716*f0865ec9SKyle Evans 2717*f0865ec9SKyle Evans if(i == 0){ 2718*f0865ec9SKyle Evans /* Initialize our numbers */ 2719*f0865ec9SKyle Evans ret = nn_init(&z, 0); EG(ret, err); 2720*f0865ec9SKyle Evans ret = nn_init(&S, 0); EG(ret, err); 2721*f0865ec9SKyle Evans ret = nn_init(&elements[(2 * num)].number, 0); EG(ret, err); 2722*f0865ec9SKyle Evans ret = _prj_pt_unprotected_mult(&elements[(2 * num)].point, gen_cofactor, G); EG(ret, err); 2723*f0865ec9SKyle Evans } 2724*f0865ec9SKyle Evans 2725*f0865ec9SKyle Evans gen_z_again: 2726*f0865ec9SKyle Evans /* Get a random z for randomizing the linear combination */ 2727*f0865ec9SKyle Evans ret = nn_get_random_len(&z, (hsize / 4)); EG(ret, err); 2728*f0865ec9SKyle Evans ret = nn_iszero(&z, &iszero); EG(ret, err); 2729*f0865ec9SKyle Evans if(iszero){ 2730*f0865ec9SKyle Evans goto gen_z_again; 2731*f0865ec9SKyle Evans } 2732*f0865ec9SKyle Evans 2733*f0865ec9SKyle Evans /* Sanity check on hash types */ 2734*f0865ec9SKyle Evans MUST_HAVE((hash_type == get_eddsa_hash_type(key_type)), ret, err); 2735*f0865ec9SKyle Evans 2736*f0865ec9SKyle Evans /* Check given signature length is the expected one */ 2737*f0865ec9SKyle Evans siglen = s_len[i]; 2738*f0865ec9SKyle Evans sig = s[i]; 2739*f0865ec9SKyle Evans MUST_HAVE((siglen == EDDSA_SIGLEN(hsize)), ret, err); 2740*f0865ec9SKyle Evans MUST_HAVE((siglen == (EDDSA_R_LEN(hsize) + EDDSA_S_LEN(hsize))), ret, err); 2741*f0865ec9SKyle Evans 2742*f0865ec9SKyle Evans /* Initialize the hash context */ 2743*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 2744*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(hm); EG(ret, err); 2745*f0865ec9SKyle Evans ret = hm->hfunc_init(&h_ctx); EG(ret, err); 2746*f0865ec9SKyle Evans ret = hm->hfunc_init(&h_ctx_pre_hash); EG(ret, err); 2747*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519) 2748*f0865ec9SKyle Evans if(key_type == EDDSA25519CTX){ 2749*f0865ec9SKyle Evans /* As per RFC8032, for EDDSA25519CTX the context SHOULD NOT be empty */ 2750*f0865ec9SKyle Evans MUST_HAVE((adata[i] != NULL), ret, err); 2751*f0865ec9SKyle Evans ret = dom2(0, adata[i], adata_len[i], hm, &h_ctx); EG(ret, err); 2752*f0865ec9SKyle Evans } 2753*f0865ec9SKyle Evans if(key_type == EDDSA25519PH){ 2754*f0865ec9SKyle Evans ret = dom2(1, adata[i], adata_len[i], hm, &h_ctx); EG(ret, err); 2755*f0865ec9SKyle Evans } 2756*f0865ec9SKyle Evans #endif 2757*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 2758*f0865ec9SKyle Evans if(key_type == EDDSA448){ 2759*f0865ec9SKyle Evans ret = dom4(0, adata[i], adata_len[i], hm, &h_ctx); EG(ret, err); 2760*f0865ec9SKyle Evans } 2761*f0865ec9SKyle Evans if(key_type == EDDSA448PH){ 2762*f0865ec9SKyle Evans ret = dom4(1, adata[i], adata_len[i], hm, &h_ctx); EG(ret, err); 2763*f0865ec9SKyle Evans } 2764*f0865ec9SKyle Evans #endif 2765*f0865ec9SKyle Evans /* Import R and S values from signature buffer */ 2766*f0865ec9SKyle Evans /*******************************/ 2767*f0865ec9SKyle Evans /* Import R as an Edwards point */ 2768*f0865ec9SKyle Evans ret = curve_shortw_to_edwards(shortw_curve, &crv_edwards, alpha_montgomery, 2769*f0865ec9SKyle Evans gamma_montgomery, alpha_edwards); EG(ret, err); 2770*f0865ec9SKyle Evans /* NOTE: non canonical R are checked and rejected here */ 2771*f0865ec9SKyle Evans ret = eddsa_decode_point(&R, &crv_edwards, alpha_edwards, &sig[0], 2772*f0865ec9SKyle Evans EDDSA_R_LEN(hsize), key_type); EG(ret, err); 2773*f0865ec9SKyle Evans dbg_ec_edwards_point_print("R", &R); 2774*f0865ec9SKyle Evans /* Transfer our public point R to Weierstrass */ 2775*f0865ec9SKyle Evans ret = aff_pt_edwards_to_prj_pt_shortw(&R, shortw_curve, &elements[i].point, alpha_edwards); EG(ret, err); 2776*f0865ec9SKyle Evans /* Update the hash with the encoded R */ 2777*f0865ec9SKyle Evans ret = hm->hfunc_update(&h_ctx, &sig[0], EDDSA_R_LEN(hsize)); EG(ret, err); 2778*f0865ec9SKyle Evans /* Store 8 * z in our number to be multiplied with R */ 2779*f0865ec9SKyle Evans ret = nn_init(&elements[i].number, 0); EG(ret, err); 2780*f0865ec9SKyle Evans ret = nn_mul(&elements[i].number, gen_cofactor, &z); EG(ret, err); 2781*f0865ec9SKyle Evans ret = nn_mod(&elements[i].number, &elements[i].number, q); EG(ret, err); 2782*f0865ec9SKyle Evans 2783*f0865ec9SKyle Evans /*******************************/ 2784*f0865ec9SKyle Evans /* Import S as an integer */ 2785*f0865ec9SKyle Evans ret = eddsa_decode_integer(&S, &sig[EDDSA_R_LEN(hsize)], EDDSA_S_LEN(hsize)); EG(ret, err); 2786*f0865ec9SKyle Evans /* Reject S if it is not reduced modulo q */ 2787*f0865ec9SKyle Evans ret = nn_cmp(&S, q, &cmp); EG(ret, err); 2788*f0865ec9SKyle Evans MUST_HAVE((cmp < 0), ret, err); 2789*f0865ec9SKyle Evans dbg_nn_print("S", &S); 2790*f0865ec9SKyle Evans 2791*f0865ec9SKyle Evans /* Add (- z S) to the sum */ 2792*f0865ec9SKyle Evans ret = nn_mul(&S, &S, &z); EG(ret, err); 2793*f0865ec9SKyle Evans ret = nn_mod(&S, &S, q); EG(ret, err); 2794*f0865ec9SKyle Evans ret = nn_mod_neg(&S, &S, q); EG(ret, err); /* Negate S */ 2795*f0865ec9SKyle Evans ret = nn_mod_add(&elements[(2 * num)].number, &elements[(2 * num)].number, &S, q); EG(ret, err); 2796*f0865ec9SKyle Evans 2797*f0865ec9SKyle Evans /*******************************/ 2798*f0865ec9SKyle Evans /* Encode the public key 2799*f0865ec9SKyle Evans * NOTE: since we deal with a public key transfered to Weierstrass, 2800*f0865ec9SKyle Evans * encoding checking has been handled elsewhere. 2801*f0865ec9SKyle Evans */ 2802*f0865ec9SKyle Evans /* Reject the signature if the public key is one of small order points. 2803*f0865ec9SKyle Evans * We multiply by the cofactor: since this is a public verification, 2804*f0865ec9SKyle Evans * we use a basic double and add algorithm. 2805*f0865ec9SKyle Evans */ 2806*f0865ec9SKyle Evans ret = _prj_pt_unprotected_mult(&elements[num + i].point, gen_cofactor, pub_key_y); EG(ret, err); 2807*f0865ec9SKyle Evans /* Reject the signature if we have point at infinity here as this means 2808*f0865ec9SKyle Evans * that the public key is of small order. 2809*f0865ec9SKyle Evans */ 2810*f0865ec9SKyle Evans ret = prj_pt_iszero(&elements[num + i].point, &iszero); EG(ret, err); 2811*f0865ec9SKyle Evans MUST_HAVE((!iszero), ret, err); 2812*f0865ec9SKyle Evans 2813*f0865ec9SKyle Evans /* Transfer the public key to Edwards */ 2814*f0865ec9SKyle Evans ret = prj_pt_shortw_to_aff_pt_edwards(pub_key_y, &crv_edwards, &A, alpha_edwards); EG(ret, err); 2815*f0865ec9SKyle Evans dbg_ec_edwards_point_print("A", &A); 2816*f0865ec9SKyle Evans MUST_HAVE((EDDSA_R_LEN(hsize) <= sizeof(hash)), ret, err); 2817*f0865ec9SKyle Evans /* NOTE: we use the hash buffer as a temporary buffer */ 2818*f0865ec9SKyle Evans ret = eddsa_encode_point(&A, alpha_edwards, hash, EDDSA_R_LEN(hsize), key_type); EG(ret, err); 2819*f0865ec9SKyle Evans 2820*f0865ec9SKyle Evans /* Update the hash with the encoded public key */ 2821*f0865ec9SKyle Evans ret = hm->hfunc_update(&h_ctx, hash, EDDSA_R_LEN(hsize)); EG(ret, err); 2822*f0865ec9SKyle Evans /* Finish our computation of h = H(R || A || M) */ 2823*f0865ec9SKyle Evans /* Update the hash with the message or its hash for the PH versions */ 2824*f0865ec9SKyle Evans if(use_message_pre_hash == 1){ 2825*f0865ec9SKyle Evans ret = hm->hfunc_update(&h_ctx_pre_hash, m[i], m_len[i]); EG(ret, err); 2826*f0865ec9SKyle Evans ret = hm->hfunc_finalize(&h_ctx_pre_hash, hash); EG(ret, err); 2827*f0865ec9SKyle Evans MUST_HAVE((use_message_pre_hash_hsize <= hsize), ret, err); 2828*f0865ec9SKyle Evans ret = hm->hfunc_update(&h_ctx, hash, use_message_pre_hash_hsize); EG(ret, err); 2829*f0865ec9SKyle Evans } 2830*f0865ec9SKyle Evans else{ 2831*f0865ec9SKyle Evans ret = hm->hfunc_update(&h_ctx, m[i], m_len[i]); EG(ret, err); 2832*f0865ec9SKyle Evans } 2833*f0865ec9SKyle Evans ret = hm->hfunc_finalize(&h_ctx, hash); EG(ret, err); 2834*f0865ec9SKyle Evans dbg_buf_print("hash = H(R || A || PH(M))", hash, hsize); 2835*f0865ec9SKyle Evans 2836*f0865ec9SKyle Evans /* Import our hash as a NN and reduce it modulo q */ 2837*f0865ec9SKyle Evans ret = eddsa_decode_integer(&elements[num + i].number, hash, hsize); EG(ret, err); 2838*f0865ec9SKyle Evans ret = nn_mod(&elements[num + i].number, &elements[num + i].number, q); EG(ret, err); 2839*f0865ec9SKyle Evans dbg_nn_print("h = ", &elements[num + i].number); 2840*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448) 2841*f0865ec9SKyle Evans if((key_type == EDDSA448) || (key_type == EDDSA448PH)){ 2842*f0865ec9SKyle Evans /* When dealing with EDDSA448, because of our 4-isogeny between Edwars448 and Ed448 2843*f0865ec9SKyle Evans * mapping base point to four times base point, we actually multiply our public key by 4 here 2844*f0865ec9SKyle Evans * to be inline with the other computations (the public key stored in Weierstrass ) 2845*f0865ec9SKyle Evans */ 2846*f0865ec9SKyle Evans ret = nn_lshift(&elements[num + i].number, &elements[num + i].number, 2); EG(ret, err); 2847*f0865ec9SKyle Evans ret = nn_mod(&elements[num + i].number, &elements[num + i].number, q); EG(ret, err); 2848*f0865ec9SKyle Evans } 2849*f0865ec9SKyle Evans #endif 2850*f0865ec9SKyle Evans /* Compute by (z * h) mod q. 2851*f0865ec9SKyle Evans */ 2852*f0865ec9SKyle Evans ret = nn_mul(&elements[num + i].number, &elements[num + i].number, &z); EG(ret, err); 2853*f0865ec9SKyle Evans ret = nn_mod(&elements[num + i].number, &elements[num + i].number, q); EG(ret, err); 2854*f0865ec9SKyle Evans } 2855*f0865ec9SKyle Evans 2856*f0865ec9SKyle Evans /* Sanity check */ 2857*f0865ec9SKyle Evans MUST_HAVE((gen_cofactor != NULL) && (q != NULL) && (G != NULL) && (q_bit_len != 0), ret, err); 2858*f0865ec9SKyle Evans 2859*f0865ec9SKyle Evans /********************************************/ 2860*f0865ec9SKyle Evans /****** Bos-Coster algorithm ****************/ 2861*f0865ec9SKyle Evans ret = ec_verify_bos_coster(elements, (2 * num) + 1, q_bit_len); 2862*f0865ec9SKyle Evans if(ret){ 2863*f0865ec9SKyle Evans if(ret == -2){ 2864*f0865ec9SKyle Evans /* In case of Bos-Coster time out, we fall back to the 2865*f0865ec9SKyle Evans * slower regular batch verification. 2866*f0865ec9SKyle Evans */ 2867*f0865ec9SKyle Evans ret = _eddsa_verify_batch_no_memory(s, s_len, pub_keys, m, m_len, num, sig_type, 2868*f0865ec9SKyle Evans hash_type, adata, adata_len); EG(ret, err); 2869*f0865ec9SKyle Evans } 2870*f0865ec9SKyle Evans goto err; 2871*f0865ec9SKyle Evans } 2872*f0865ec9SKyle Evans 2873*f0865ec9SKyle Evans /* The first element should contain the sum: it should 2874*f0865ec9SKyle Evans * be equal to zero. Reject the signature if this is not 2875*f0865ec9SKyle Evans * the case. 2876*f0865ec9SKyle Evans */ 2877*f0865ec9SKyle Evans ret = prj_pt_iszero(&elements[elements[0].index].point, &iszero); EG(ret, err); 2878*f0865ec9SKyle Evans ret = iszero ? 0 : -1; 2879*f0865ec9SKyle Evans 2880*f0865ec9SKyle Evans err: 2881*f0865ec9SKyle Evans PTR_NULLIFY(q); 2882*f0865ec9SKyle Evans PTR_NULLIFY(pub_key); 2883*f0865ec9SKyle Evans PTR_NULLIFY(pub_key0); 2884*f0865ec9SKyle Evans PTR_NULLIFY(shortw_curve); 2885*f0865ec9SKyle Evans PTR_NULLIFY(alpha_montgomery); 2886*f0865ec9SKyle Evans PTR_NULLIFY(gamma_montgomery); 2887*f0865ec9SKyle Evans PTR_NULLIFY(alpha_edwards); 2888*f0865ec9SKyle Evans PTR_NULLIFY(gen_cofactor); 2889*f0865ec9SKyle Evans PTR_NULLIFY(pub_key_y); 2890*f0865ec9SKyle Evans PTR_NULLIFY(G); 2891*f0865ec9SKyle Evans PTR_NULLIFY(elements); 2892*f0865ec9SKyle Evans 2893*f0865ec9SKyle Evans /* Unitialize all our scratch_pad_area */ 2894*f0865ec9SKyle Evans if((scratch_pad_area != NULL) && (scratch_pad_area_len != NULL)){ 2895*f0865ec9SKyle Evans IGNORE_RET_VAL(local_memset((u8*)scratch_pad_area, 0, (*scratch_pad_area_len))); 2896*f0865ec9SKyle Evans } 2897*f0865ec9SKyle Evans 2898*f0865ec9SKyle Evans ec_edwards_crv_uninit(&crv_edwards); 2899*f0865ec9SKyle Evans aff_pt_edwards_uninit(&A); 2900*f0865ec9SKyle Evans aff_pt_edwards_uninit(&R); 2901*f0865ec9SKyle Evans nn_uninit(&S); 2902*f0865ec9SKyle Evans nn_uninit(&z); 2903*f0865ec9SKyle Evans 2904*f0865ec9SKyle Evans return ret; 2905*f0865ec9SKyle Evans } 2906*f0865ec9SKyle Evans 2907*f0865ec9SKyle Evans int eddsa_verify_batch(const u8 **s, const u8 *s_len, const ec_pub_key **pub_keys, 2908*f0865ec9SKyle Evans const u8 **m, const u32 *m_len, u32 num, ec_alg_type sig_type, 2909*f0865ec9SKyle Evans hash_alg_type hash_type, const u8 **adata, const u16 *adata_len, 2910*f0865ec9SKyle Evans verify_batch_scratch_pad *scratch_pad_area, u32 *scratch_pad_area_len) 2911*f0865ec9SKyle Evans { 2912*f0865ec9SKyle Evans int ret; 2913*f0865ec9SKyle Evans 2914*f0865ec9SKyle Evans if(scratch_pad_area != NULL){ 2915*f0865ec9SKyle Evans MUST_HAVE((scratch_pad_area_len != NULL), ret, err); 2916*f0865ec9SKyle Evans ret = _eddsa_verify_batch(s, s_len, pub_keys, m, m_len, num, sig_type, 2917*f0865ec9SKyle Evans hash_type, adata, adata_len, 2918*f0865ec9SKyle Evans scratch_pad_area, scratch_pad_area_len); EG(ret, err); 2919*f0865ec9SKyle Evans } 2920*f0865ec9SKyle Evans else{ 2921*f0865ec9SKyle Evans ret = _eddsa_verify_batch_no_memory(s, s_len, pub_keys, m, m_len, num, sig_type, 2922*f0865ec9SKyle Evans hash_type, adata, adata_len); EG(ret, err); 2923*f0865ec9SKyle Evans } 2924*f0865ec9SKyle Evans 2925*f0865ec9SKyle Evans err: 2926*f0865ec9SKyle Evans return ret; 2927*f0865ec9SKyle Evans } 2928*f0865ec9SKyle Evans 2929*f0865ec9SKyle Evans #else /* !(defined(WITH_SIG_EDDSA25519) || defined(WITH_SIG_EDDSA448)) */ 2930*f0865ec9SKyle Evans 2931*f0865ec9SKyle Evans /* 2932*f0865ec9SKyle Evans * Dummy definition to avoid the empty translation unit ISO C warning 2933*f0865ec9SKyle Evans */ 2934*f0865ec9SKyle Evans typedef int dummy; 2935*f0865ec9SKyle Evans #endif /* defined(WITH_SIG_EDDSA25519) || defined(WITH_SIG_EDDSA448) */ 2936