/*1* Copyright (C) 2017 - This file is part of libecc project2*3* Authors:4* Ryad BENADJILA <[email protected]>5* Arnaud EBALARD <[email protected]>6* Jean-Pierre FLORI <[email protected]>7*8* Contributors:9* Nicolas VIVET <[email protected]>10* Karim KHALFALLAH <[email protected]>11*12* This software is licensed under a dual BSD and GPL v2 license.13* See LICENSE file at the root folder of the project.14*/15#include <libecc/lib_ecc_config.h>16#ifdef WITH_SIG_ECKCDSA1718#include <libecc/nn/nn_rand.h>19#include <libecc/nn/nn_mul_public.h>20#include <libecc/nn/nn_logical.h>2122#include <libecc/sig/sig_algs_internal.h>23#include <libecc/sig/ec_key.h>24#ifdef VERBOSE_INNER_VALUES25#define EC_SIG_ALG "ECKCDSA"26#endif27#include <libecc/utils/dbg_sig.h>2829/*30* Initialize public key 'out_pub' from input private key 'in_priv'. The31* function returns 0 on success, -1 on error.32*/33int eckcdsa_init_pub_key(ec_pub_key *out_pub, const ec_priv_key *in_priv)34{35prj_pt_src_t G;36int ret, cmp;37nn xinv;38nn_src_t q;39xinv.magic = WORD(0);4041MUST_HAVE((out_pub != NULL), ret, err);4243ret = priv_key_check_initialized_and_type(in_priv, ECKCDSA); EG(ret, err);4445/* For readability in the remaining of the function */46q = &(in_priv->params->ec_gen_order);4748/* Zero init public key to be generated */49ret = local_memset(out_pub, 0, sizeof(ec_pub_key)); EG(ret, err);5051/* Sanity check on key */52MUST_HAVE((!nn_cmp(&(in_priv->x), q, &cmp)) && (cmp < 0), ret, err);5354/* Y = (x^-1)G */55G = &(in_priv->params->ec_gen);56/* NOTE: we use Fermat's little theorem inversion for57* constant time here. This is possible since q is prime.58*/59ret = nn_modinv_fermat(&xinv, &(in_priv->x), q); EG(ret, err);6061/* Use blinding when computing point scalar multiplication */62ret = prj_pt_mul_blind(&(out_pub->y), &xinv, G); EG(ret, err);6364out_pub->key_type = ECKCDSA;65out_pub->params = in_priv->params;66out_pub->magic = PUB_KEY_MAGIC;6768err:69nn_uninit(&xinv);7071return ret;72}7374/*75* Helper providing ECKCDSA signature length when exported to a buffer based on76* hash algorithm digest and block size, generator point order bit length, and77* underlying prime field order bit length. The function returns 0 on success,78* -1 on error. On success, signature length is provided via 'siglen' out79* parameter.80*/81int eckcdsa_siglen(u16 p_bit_len, u16 q_bit_len, u8 hsize, u8 blocksize,82u8 *siglen)83{84int ret;8586MUST_HAVE((siglen != NULL), ret, err);87MUST_HAVE((p_bit_len <= CURVES_MAX_P_BIT_LEN) &&88(q_bit_len <= CURVES_MAX_Q_BIT_LEN) &&89(hsize <= MAX_DIGEST_SIZE) &&90(blocksize <= MAX_BLOCK_SIZE), ret, err);9192(*siglen) = (u8)ECKCDSA_SIGLEN(hsize, q_bit_len);93ret = 0;9495err:96return ret;97}9899/*100* ISO 14888-3:2016 has some insane specific case when the digest size101* (gamma) is larger than beta, the bit length of q (i.e. hsize >102* bitlen(q), i.e. gamma > beta). In that case, both the values of h103* (= H(z||m)) and r (= H(FE2OS(W_x))) must be post-processed/mangled104* in the following way:105*106* - h = I2BS(beta', (BS2I(gamma, h))) mod 2^beta'107* - r = I2BS(beta', (BS2I(gamma, r))) mod 2^beta'108*109* where beta' = 8 * ceil(beta / 8)110*111* There are two things to consider before implementing those steps112* using various conversions to/from nn, shifting and masking:113*114* - the expected post-processing work is simply clearing the first115* (gamma - beta') bits at the beginning of h and r to keep only116* last beta ones unmodified.117* - In the library, we do not work on bitstring but byte strings in118* all cases119* - In EC-KCDSA sig/verif, the result (h and then r) are then XORed120* together and then converted to an integer (the buffer being121* considered in big endian order)122*123* For that reason, this function simply takes a buffer 'buf' of124* 'buflen' bytes and shifts it 'shift' bytes to the left, clearing125* the trailing 'shift' bytes at the end of the buffer. The function126* is expected to be used with 'shift' parameter set to127* (gamma - beta') / 8.128*129* This is better presented on an example:130*131* shift = (gamma - beta') / 8 = 4132* before: buf = { 0xff, 0xff, 0xff, 0x12, 0x34, 0x56, 0x78}133* after : buf = { 0x34, 0x56, 0x78, 0x00, 0x00, 0x00, 0x00}134*/135ATTRIBUTE_WARN_UNUSED_RET static int buf_lshift(u8 *buf, u8 buflen, u8 shift)136{137u8 i;138int ret;139140MUST_HAVE((buf != NULL), ret, err);141142if (shift > buflen) {143shift = buflen;144}145146/* Start by shifting all trailing bytes to the left ... */147for (i = shift; i < buflen; i++) {148buf[i - shift] = buf[i];149}150151/* Let's now zeroize the end of the buffer ... */152for (i = 1; i <= shift; i++) {153buf[buflen - i] = 0;154}155156ret = 0;157158err:159return ret;160}161162/*163* Generic *internal* EC-KCDSA signature functions (init, update and finalize).164* Their purpose is to allow passing a specific hash function (along with165* its output size) and the random ephemeral key k, so that compliance166* tests against test vectors can be made without ugly hack in the code167* itself.168*169* Global EC-KCDSA signature process is as follows (I,U,F provides170* information in which function(s) (init(), update() or finalize())171* a specific step is performed):172*173*| IUF - EC-KCDSA signature174*|175*| IUF 1. Compute h = H(z||m)176*| F 2. If |H| > bitlen(q), set h to beta' rightmost bits of177*| bitstring h (w/ beta' = 8 * ceil(bitlen(q) / 8)), i.e.178*| set h to I2BS(beta', BS2I(|H|, h) mod 2^beta')179*| F 3. Get a random value k in ]0,q[180*| F 4. Compute W = (W_x,W_y) = kG181*| F 5. Compute r = H(FE2OS(W_x)).182*| F 6. If |H| > bitlen(q), set r to beta' rightmost bits of183*| bitstring r (w/ beta' = 8 * ceil(bitlen(q) / 8)), i.e.184*| set r to I2BS(beta', BS2I(|H|, r) mod 2^beta')185*| F 7. Compute e = OS2I(r XOR h) mod q186*| F 8. Compute s = x(k - e) mod q187*| F 9. if s == 0, restart at step 3.188*| F 10. return (r,s)189*190*/191192#define ECKCDSA_SIGN_MAGIC ((word_t)(0x45503fcf5114bf1eULL))193#define ECKCDSA_SIGN_CHECK_INITIALIZED(A, ret, err) \194MUST_HAVE((((void *)(A)) != NULL) && \195((A)->magic == ECKCDSA_SIGN_MAGIC), ret, err)196197/*198* ECKCDSA signature initialization function. Returns 0 on success, -1 on199* error.200*/201int _eckcdsa_sign_init(struct ec_sign_context *ctx)202{203u8 tmp_buf[LOCAL_MAX(2 * BYTECEIL(CURVES_MAX_P_BIT_LEN), MAX_BLOCK_SIZE)];204const ec_pub_key *pub_key;205aff_pt y_aff;206u8 p_len;207u16 z_len;208int ret;209y_aff.magic = WORD(0);210211/* First, verify context has been initialized */212ret = sig_sign_check_initialized(ctx); EG(ret, err);213214/* Additional sanity checks on input params from context */215ret = key_pair_check_initialized_and_type(ctx->key_pair, ECKCDSA); EG(ret, err);216MUST_HAVE((ctx->h != NULL) && (ctx->h->digest_size <= MAX_DIGEST_SIZE) &&217(ctx->h->block_size <= MAX_BLOCK_SIZE), ret, err);218219/* Make things more readable */220pub_key = &(ctx->key_pair->pub_key);221p_len = (u8)BYTECEIL(pub_key->params->ec_fp.p_bitlen);222z_len = ctx->h->block_size;223224/*225* 1. Compute h = H(z||m)226*227* We first need to compute z, the certificate data that will be228* prepended to the message m prior to hashing. In ISO-14888-3:2016,229* z is basically the concatenation of Yx and Yy (the affine coordinates230* of the public key Y) up to the block size of the hash function.231* If the concatenation of those coordinates is smaller than blocksize,232* 0 are appended.233*234* So, we convert the public key point to its affine representation and235* concatenate the two coordinates in a temporary (zeroized) buffer, of236* which the first z_len (i.e. blocksize) bytes are exported to z.237*238* Message m will be handled during following update() calls.239*/240ret = prj_pt_to_aff(&y_aff, &(pub_key->y)); EG(ret, err);241ret = local_memset(tmp_buf, 0, sizeof(tmp_buf)); EG(ret, err);242ret = fp_export_to_buf(tmp_buf, p_len, &(y_aff.x)); EG(ret, err);243ret = fp_export_to_buf(tmp_buf + p_len, p_len, &(y_aff.y)); EG(ret, err);244245dbg_pub_key_print("Y", pub_key);246247/* Since we call a callback, sanity check our mapping */248ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);249ret = ctx->h->hfunc_init(&(ctx->sign_data.eckcdsa.h_ctx)); EG(ret, err);250ret = ctx->h->hfunc_update(&(ctx->sign_data.eckcdsa.h_ctx), tmp_buf, z_len); EG(ret, err);251ret = local_memset(tmp_buf, 0, sizeof(tmp_buf)); EG(ret, err);252253/* Initialize data part of the context */254ctx->sign_data.eckcdsa.magic = ECKCDSA_SIGN_MAGIC;255256err:257aff_pt_uninit(&y_aff);258259VAR_ZEROIFY(p_len);260VAR_ZEROIFY(z_len);261PTR_NULLIFY(pub_key);262263return ret;264}265266/* ECKCDSA signature update function. Returns 0 on success, -1 on error. */267int _eckcdsa_sign_update(struct ec_sign_context *ctx,268const u8 *chunk, u32 chunklen)269{270int ret;271272/*273* First, verify context has been initialized and private274* part too. This guarantees the context is an EC-KCDSA275* signature one and we do not update() or finalize()276* before init().277*/278ret = sig_sign_check_initialized(ctx); EG(ret, err);279ECKCDSA_SIGN_CHECK_INITIALIZED(&(ctx->sign_data.eckcdsa), ret, err);280281/* 1. Compute h = H(z||m) */282/* Since we call a callback, sanity check our mapping */283ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);284ret = ctx->h->hfunc_update(&(ctx->sign_data.eckcdsa.h_ctx), chunk, chunklen);285286err:287return ret;288}289290/*291* ECKCDSA signature finalization function. Returns 0 on success, -1 on292* error.293*/294int _eckcdsa_sign_finalize(struct ec_sign_context *ctx, u8 *sig, u8 siglen)295{296prj_pt_src_t G;297nn_src_t q, x;298prj_pt kG;299unsigned int i;300nn e, tmp, s, k;301u8 hzm[MAX_DIGEST_SIZE];302u8 r[MAX_DIGEST_SIZE];303u8 tmp_buf[BYTECEIL(CURVES_MAX_P_BIT_LEN)];304hash_context r_ctx;305const ec_priv_key *priv_key;306u8 p_len, r_len, s_len, hsize, shift;307bitcnt_t q_bit_len;308int ret, iszero, cmp;309#ifdef USE_SIG_BLINDING310/* b is the blinding mask */311nn b, binv;312b.magic = binv.magic = WORD(0);313#endif /* USE_SIG_BLINDING */314315kG.magic = WORD(0);316e.magic = tmp.magic = s.magic = k.magic = WORD(0);317318/*319* First, verify context has been initialized and private320* part too. This guarantees the context is an EC-KCDSA321* signature one and we do not finalize() before init().322*/323ret = sig_sign_check_initialized(ctx); EG(ret, err);324ECKCDSA_SIGN_CHECK_INITIALIZED(&(ctx->sign_data.eckcdsa), ret, err);325MUST_HAVE((sig != NULL), ret, err);326327/* Zero init points */328ret = local_memset(&kG, 0, sizeof(prj_pt)); EG(ret, err);329330/* Make things more readable */331priv_key = &(ctx->key_pair->priv_key);332G = &(priv_key->params->ec_gen);333q = &(priv_key->params->ec_gen_order);334hsize = ctx->h->digest_size;335p_len = (u8)BYTECEIL(priv_key->params->ec_fp.p_bitlen);336q_bit_len = priv_key->params->ec_gen_order_bitlen;337r_len = (u8)ECKCDSA_R_LEN(hsize, q_bit_len);338s_len = (u8)ECKCDSA_S_LEN(q_bit_len);339x = &(priv_key->x);340341/* Sanity check */342ret = nn_cmp(x, q, &cmp); EG(ret, err);343/* This should not happen and means that our344* private key is not compliant!345*/346MUST_HAVE((cmp < 0), ret, err);347348MUST_HAVE((siglen == ECKCDSA_SIGLEN(hsize, q_bit_len)), ret, err);349350dbg_nn_print("p", &(priv_key->params->ec_fp.p));351dbg_nn_print("q", q);352dbg_priv_key_print("x", priv_key);353dbg_ec_point_print("G", G);354355/* 1. Compute h = H(z||m) */356/* Since we call a callback, sanity check our mapping */357ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);358ret = ctx->h->hfunc_finalize(&(ctx->sign_data.eckcdsa.h_ctx), hzm); EG(ret, err);359dbg_buf_print("h = H(z||m) pre-mask", hzm, hsize);360361/*362* 2. If |H| > bitlen(q), set h to beta' rightmost bits of363* bitstring h (w/ beta' = 8 * ceil(bitlen(q) / 8)), i.e.364* set h to I2BS(beta', BS2I(|H|, h) mod 2^beta')365*/366shift = (u8)((hsize > r_len) ? (hsize - r_len) : 0);367MUST_HAVE((hsize <= sizeof(hzm)), ret, err);368369ret = buf_lshift(hzm, hsize, shift); EG(ret, err);370dbg_buf_print("h = H(z||m) post-mask", hzm, r_len);371372restart:373/* 3. Get a random value k in ]0,q[ */374#ifdef NO_KNOWN_VECTORS375/* NOTE: when we do not need self tests for known vectors,376* we can be strict about random function handler!377* This allows us to avoid the corruption of such a pointer.378*/379/* Sanity check on the handler before calling it */380MUST_HAVE((ctx->rand == nn_get_random_mod), ret, err);381#endif382MUST_HAVE((ctx->rand != NULL), ret, err);383ret = ctx->rand(&k, q); EG(ret, err);384dbg_nn_print("k", &k);385386#ifdef USE_SIG_BLINDING387/* Note: if we use blinding, k and e are multiplied by388* a random value b in ]0,q[ */389ret = nn_get_random_mod(&b, q); EG(ret, err);390dbg_nn_print("b", &b);391#endif /* USE_SIG_BLINDING */392393/* 4. Compute W = (W_x,W_y) = kG */394#ifdef USE_SIG_BLINDING395/* We use blinding for the scalar multiplication */396ret = prj_pt_mul_blind(&kG, &k, G); EG(ret, err);397#else398ret = prj_pt_mul(&kG, &k, G); EG(ret, err);399#endif /* USE_SIG_BLINDING */400ret = prj_pt_unique(&kG, &kG); EG(ret, err);401dbg_nn_print("W_x", &(kG.X.fp_val));402dbg_nn_print("W_y", &(kG.Y.fp_val));403404/* 5 Compute r = h(FE2OS(W_x)). */405ret = local_memset(tmp_buf, 0, sizeof(tmp_buf)); EG(ret, err);406ret = fp_export_to_buf(tmp_buf, p_len, &(kG.X)); EG(ret, err);407/* Since we call a callback, sanity check our mapping */408ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);409ret = ctx->h->hfunc_init(&r_ctx); EG(ret, err);410ret = ctx->h->hfunc_update(&r_ctx, tmp_buf, p_len); EG(ret, err);411ret = ctx->h->hfunc_finalize(&r_ctx, r); EG(ret, err);412ret = local_memset(tmp_buf, 0, p_len); EG(ret, err);413ret = local_memset(&r_ctx, 0, sizeof(hash_context)); EG(ret, err);414415/*416* 6. If |H| > bitlen(q), set r to beta' rightmost bits of417* bitstring r (w/ beta' = 8 * ceil(bitlen(q) / 8)), i.e.418* set r to I2BS(beta', BS2I(|H|, r) mod 2^beta')419*/420dbg_buf_print("r pre-mask", r, hsize);421MUST_HAVE((hsize <= sizeof(r)), ret, err);422423ret = buf_lshift(r, hsize, shift); EG(ret, err);424dbg_buf_print("r post-mask", r, r_len);425426/* 7. Compute e = OS2I(r XOR h) mod q */427for (i = 0; i < r_len; i++) {428hzm[i] ^= r[i];429}430ret = nn_init_from_buf(&tmp, hzm, r_len); EG(ret, err);431ret = local_memset(hzm, 0, r_len); EG(ret, err);432ret = nn_mod(&e, &tmp, q); EG(ret, err);433dbg_nn_print("e", &e);434435#ifdef USE_SIG_BLINDING436/* In case of blinding, we compute (k*b - e*b) * x * b^-1 */437ret = nn_mod_mul(&k, &k, &b, q); EG(ret, err);438ret = nn_mod_mul(&e, &e, &b, q); EG(ret, err);439/* NOTE: we use Fermat's little theorem inversion for440* constant time here. This is possible since q is prime.441*/442ret = nn_modinv_fermat(&binv, &b, q); EG(ret, err);443#endif /* USE_SIG_BLINDING */444/*445* 8. Compute s = x(k - e) mod q446*447* This is equivalent to computing s = x(k + (q - e)) mod q.448* This second version avoids checking if k < e before the449* subtraction, because e has already been reduced mod q450*/451ret = nn_mod_neg(&tmp, &e, q); EG(ret, err);452ret = nn_mod_add(&tmp, &k, &tmp, q); EG(ret, err);453ret = nn_mod_mul(&s, x, &tmp, q); EG(ret, err);454#ifdef USE_SIG_BLINDING455/* Unblind s with b^-1 */456ret = nn_mod_mul(&s, &s, &binv, q); EG(ret, err);457#endif /* USE_SIG_BLINDING */458459/* 9. if s == 0, restart at step 3. */460ret = nn_iszero(&s, &iszero); EG(ret, err);461if (iszero) {462goto restart;463}464465dbg_nn_print("s", &s);466467/* 10. return (r,s) */468ret = local_memcpy(sig, r, r_len); EG(ret, err);469ret = local_memset(r, 0, r_len); EG(ret, err);470ret = nn_export_to_buf(sig + r_len, s_len, &s);471472err:473prj_pt_uninit(&kG);474nn_uninit(&e);475nn_uninit(&tmp);476nn_uninit(&s);477nn_uninit(&k);478#ifdef USE_SIG_BLINDING479nn_uninit(&b);480nn_uninit(&binv);481#endif /* USE_SIG_BLINDING */482483/*484* We can now clear data part of the context. This will clear485* magic and avoid further reuse of the whole context.486*/487if(ctx != NULL){488IGNORE_RET_VAL(local_memset(&(ctx->sign_data.eckcdsa), 0, sizeof(eckcdsa_sign_data)));489}490491PTR_NULLIFY(G);492PTR_NULLIFY(q);493PTR_NULLIFY(x);494VAR_ZEROIFY(i);495PTR_NULLIFY(priv_key);496VAR_ZEROIFY(p_len);497VAR_ZEROIFY(r_len);498VAR_ZEROIFY(s_len);499VAR_ZEROIFY(q_bit_len);500VAR_ZEROIFY(hsize);501502return ret;503}504505/*506* Generic *internal* EC-KCDSA verification functions (init, update and507* finalize). Their purpose is to allow passing a specific hash function508* (along with its output size) and the random ephemeral key k, so that509* compliance tests against test vectors can be made without ugly hack510* in the code itself.511*512* Global EC-CKDSA verification process is as follows (I,U,F provides513* information in which function(s) (init(), update() or finalize())514* a specific step is performed):515*516*| IUF - EC-KCDSA verification517*|518*| I 1. Check the length of r:519*| - if |H| > bitlen(q), r must be of length520*| beta' = 8 * ceil(bitlen(q) / 8)521*| - if |H| <= bitlen(q), r must be of length hsize522*| I 2. Check that s is in ]0,q[523*| IUF 3. Compute h = H(z||m)524*| F 4. If |H| > bitlen(q), set h to beta' rightmost bits of525*| bitstring h (w/ beta' = 8 * ceil(bitlen(q) / 8)), i.e.526*| set h to I2BS(beta', BS2I(|H|, h) mod 2^beta')527*| F 5. Compute e = OS2I(r XOR h) mod q528*| F 6. Compute W' = sY + eG, where Y is the public key529*| F 7. Compute r' = h(W'x)530*| F 8. If |H| > bitlen(q), set r' to beta' rightmost bits of531*| bitstring r' (w/ beta' = 8 * ceil(bitlen(q) / 8)), i.e.532*| set r' to I2BS(beta', BS2I(|H|, r') mod 2^beta')533*| F 9. Check if r == r'534*535*/536537#define ECKCDSA_VERIFY_MAGIC ((word_t)(0xa836a75de66643aaULL))538#define ECKCDSA_VERIFY_CHECK_INITIALIZED(A, ret, err) \539MUST_HAVE((((void *)(A)) != NULL) && \540((A)->magic == ECKCDSA_VERIFY_MAGIC), ret, err)541542/*543* ECKCDSA verification finalization function. Returns 0 on success, -1 on error.544*/545int _eckcdsa_verify_init(struct ec_verify_context *ctx,546const u8 *sig, u8 siglen)547{548u8 tmp_buf[LOCAL_MAX(2 * BYTECEIL(CURVES_MAX_P_BIT_LEN), MAX_BLOCK_SIZE)];549u8 p_len, r_len, s_len, z_len;550bitcnt_t q_bit_len;551const ec_pub_key *pub_key;552aff_pt y_aff;553nn_src_t q;554u8 hsize;555int ret, iszero, cmp;556nn s;557y_aff.magic = s.magic = WORD(0);558559/* First, verify context has been initialized */560ret = sig_verify_check_initialized(ctx); EG(ret, err);561MUST_HAVE((sig != NULL), ret, err);562563/* Do some sanity checks on input params */564ret = pub_key_check_initialized_and_type(ctx->pub_key, ECKCDSA); EG(ret, err);565MUST_HAVE((ctx->h != NULL) && (ctx->h->digest_size <= MAX_DIGEST_SIZE) &&566(ctx->h->block_size <= MAX_BLOCK_SIZE), ret, err);567MUST_HAVE((sig != NULL), ret, err);568569/* Make things more readable */570pub_key = ctx->pub_key;571p_len = (u8)BYTECEIL(pub_key->params->ec_fp.p_bitlen);572q_bit_len = pub_key->params->ec_gen_order_bitlen;573q = &(pub_key->params->ec_gen_order);574hsize = ctx->h->digest_size;575r_len = (u8)ECKCDSA_R_LEN(hsize, q_bit_len);576s_len = (u8)ECKCDSA_S_LEN(q_bit_len);577z_len = ctx->h->block_size;578579/*580* 1. Check the length of r:581* - if |H| > bitlen(q), r must be of length582* beta' = 8 * ceil(bitlen(q) / 8)583* - if |H| <= bitlen(q), r must be of length hsize584*585* As we expect the signature as the concatenation of r and s, the check586* is done by verifying the length of the signature is the expected one.587*/588MUST_HAVE((siglen == ECKCDSA_SIGLEN(hsize, q_bit_len)), ret, err);589590/* 2. Check that s is in ]0,q[ */591ret = nn_init_from_buf(&s, sig + r_len, s_len); EG(ret, err);592ret = nn_iszero(&s, &iszero); EG(ret, err);593ret = nn_cmp(&s, q, &cmp); EG(ret, err);594MUST_HAVE((!iszero) && (cmp < 0), ret, err);595dbg_nn_print("s", &s);596597/*598* 3. Compute h = H(z||m)599*600* We first need to compute z, the certificate data that will be601* prepended to the message m prior to hashing. In ISO-14888-3:2016,602* z is basically the concatenation of Yx and Yy (the affine coordinates603* of the public key Y) up to the block size of the hash function.604* If the concatenation of those coordinates is smaller than blocksize,605* 0 are appended.606*607* So, we convert the public key point to its affine representation and608* concatenate the two coordinates in a temporary (zeroized) buffer, of609* which the first z_len (i.e. blocksize) bytes are exported to z.610*611* Message m will be handled during following update() calls.612*/613ret = prj_pt_to_aff(&y_aff, &(pub_key->y)); EG(ret, err);614ret = local_memset(tmp_buf, 0, sizeof(tmp_buf)); EG(ret, err);615ret = fp_export_to_buf(tmp_buf, p_len, &(y_aff.x)); EG(ret, err);616ret = fp_export_to_buf(tmp_buf + p_len, p_len, &(y_aff.y)); EG(ret, err);617618dbg_pub_key_print("Y", pub_key);619620/* Since we call a callback, sanity check our mapping */621ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);622ret = ctx->h->hfunc_init(&(ctx->verify_data.eckcdsa.h_ctx)); EG(ret, err);623ret = ctx->h->hfunc_update(&(ctx->verify_data.eckcdsa.h_ctx), tmp_buf,624z_len); EG(ret, err);625ret = local_memset(tmp_buf, 0, sizeof(tmp_buf)); EG(ret, err);626627/*628* Initialize the verify context by storing r and s as imported629* from the signature630*/631ret = local_memcpy(ctx->verify_data.eckcdsa.r, sig, r_len); EG(ret, err);632ret = nn_copy(&(ctx->verify_data.eckcdsa.s), &s); EG(ret, err);633634ctx->verify_data.eckcdsa.magic = ECKCDSA_VERIFY_MAGIC;635636err:637aff_pt_uninit(&y_aff);638nn_uninit(&s);639640if (ret && (ctx != NULL)) {641/*642* Signature is invalid. Clear data part of the context.643* This will clear magic and avoid further reuse of the644* whole context.645*/646IGNORE_RET_VAL(local_memset(&(ctx->verify_data.eckcdsa), 0,647sizeof(eckcdsa_verify_data)));648}649650/* Let's also clear what remains on the stack */651PTR_NULLIFY(q);652PTR_NULLIFY(pub_key);653VAR_ZEROIFY(p_len);654VAR_ZEROIFY(r_len);655VAR_ZEROIFY(s_len);656VAR_ZEROIFY(z_len);657VAR_ZEROIFY(q_bit_len);658VAR_ZEROIFY(hsize);659660return ret;661}662663/* ECKCDSA verification update function. Returns 0 on success, -1 on error. */664int _eckcdsa_verify_update(struct ec_verify_context *ctx,665const u8 *chunk, u32 chunklen)666{667int ret;668669/*670* First, verify context has been initialized and public671* part too. This guarantees the context is an EC-KCDSA672* verification one and we do not update() or finalize()673* before init().674*/675ret = sig_verify_check_initialized(ctx); EG(ret, err);676ECKCDSA_VERIFY_CHECK_INITIALIZED(&(ctx->verify_data.eckcdsa), ret, err);677678/* 3. Compute h = H(z||m) */679/* Since we call a callback, sanity check our mapping */680ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);681ret = ctx->h->hfunc_update(&(ctx->verify_data.eckcdsa.h_ctx),682chunk, chunklen);683684err:685return ret;686}687688/*689* ECKCDSA verification finalization function. Returns 0 on success, -1 on error.690*/691int _eckcdsa_verify_finalize(struct ec_verify_context *ctx)692{693u8 tmp_buf[BYTECEIL(CURVES_MAX_P_BIT_LEN)];694bitcnt_t q_bit_len, p_bit_len;695u8 p_len, r_len;696prj_pt sY, eG;697prj_pt_t Wprime;698prj_pt_src_t G, Y;699u8 r_prime[MAX_DIGEST_SIZE];700const ec_pub_key *pub_key;701hash_context r_prime_ctx;702u8 hzm[MAX_DIGEST_SIZE];703unsigned int i;704nn_src_t q;705nn e, tmp;706u8 hsize, shift;707int ret, check;708u8 *r;709nn *s;710711sY.magic = eG.magic = WORD(0);712e.magic = tmp.magic = WORD(0);713714/* NOTE: we reuse eG for Wprime to optimize local variables */715Wprime = &eG;716717/*718* First, verify context has been initialized and public719* part too. This guarantees the context is an EC-KCDSA720* verification one and we do not finalize() before init().721*/722ret = sig_verify_check_initialized(ctx); EG(ret, err);723ECKCDSA_VERIFY_CHECK_INITIALIZED(&(ctx->verify_data.eckcdsa), ret, err);724725/* Zero init points */726ret = local_memset(&sY, 0, sizeof(prj_pt)); EG(ret, err);727ret = local_memset(&eG, 0, sizeof(prj_pt)); EG(ret, err);728729/* Make things more readable */730pub_key = ctx->pub_key;731G = &(pub_key->params->ec_gen);732Y = &(pub_key->y);733q = &(pub_key->params->ec_gen_order);734p_bit_len = pub_key->params->ec_fp.p_bitlen;735q_bit_len = pub_key->params->ec_gen_order_bitlen;736p_len = (u8)BYTECEIL(p_bit_len);737hsize = ctx->h->digest_size;738r_len = (u8)ECKCDSA_R_LEN(hsize, q_bit_len);739r = ctx->verify_data.eckcdsa.r;740s = &(ctx->verify_data.eckcdsa.s);741742/* 3. Compute h = H(z||m) */743/* Since we call a callback, sanity check our mapping */744ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);745ret = ctx->h->hfunc_finalize(&(ctx->verify_data.eckcdsa.h_ctx), hzm); EG(ret, err);746dbg_buf_print("h = H(z||m) pre-mask", hzm, hsize);747748/*749* 4. If |H| > bitlen(q), set h to beta' rightmost bits of750* bitstring h (w/ beta' = 8 * ceil(bitlen(q) / 8)), i.e.751* set h to I2BS(beta', BS2I(|H|, h) mod 2^beta')752*/753shift = (u8)((hsize > r_len) ? (hsize - r_len) : 0);754MUST_HAVE(hsize <= sizeof(hzm), ret, err);755ret = buf_lshift(hzm, hsize, shift); EG(ret, err);756dbg_buf_print("h = H(z||m) post-mask", hzm, r_len);757758/* 5. Compute e = OS2I(r XOR h) mod q */759for (i = 0; i < r_len; i++) {760hzm[i] ^= r[i];761}762ret = nn_init_from_buf(&tmp, hzm, r_len); EG(ret, err);763ret = local_memset(hzm, 0, hsize); EG(ret, err);764ret = nn_mod(&e, &tmp, q); EG(ret, err);765766dbg_nn_print("e", &e);767768/* 6. Compute W' = sY + eG, where Y is the public key */769ret = prj_pt_mul(&sY, s, Y); EG(ret, err);770ret = prj_pt_mul(&eG, &e, G); EG(ret, err);771ret = prj_pt_add(Wprime, &sY, &eG); EG(ret, err);772ret = prj_pt_unique(Wprime, Wprime); EG(ret, err);773dbg_nn_print("W'_x", &(Wprime->X.fp_val));774dbg_nn_print("W'_y", &(Wprime->Y.fp_val));775776/* 7. Compute r' = h(W'x) */777ret = local_memset(tmp_buf, 0, sizeof(tmp_buf)); EG(ret, err);778ret = fp_export_to_buf(tmp_buf, p_len, &(Wprime->X)); EG(ret, err);779/* Since we call a callback, sanity check our mapping */780ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);781ret = ctx->h->hfunc_init(&r_prime_ctx); EG(ret, err);782ret = ctx->h->hfunc_update(&r_prime_ctx, tmp_buf, p_len); EG(ret, err);783ret = ctx->h->hfunc_finalize(&r_prime_ctx, r_prime); EG(ret, err);784ret = local_memset(tmp_buf, 0, p_len); EG(ret, err);785ret = local_memset(&r_prime_ctx, 0, sizeof(hash_context)); EG(ret, err);786787/*788* 8. If |H| > bitlen(q), set r' to beta' rightmost bits of789* bitstring r' (w/ beta' = 8 * ceil(bitlen(q) / 8)), i.e.790* set r' to I2BS(beta', BS2I(|H|, r') mod 2^beta')791*/792dbg_buf_print("r' pre-mask", r_prime, hsize);793ret = buf_lshift(r_prime, hsize, shift); EG(ret, err);794dbg_buf_print("r' post-mask", r_prime, r_len);795dbg_buf_print("r", r, r_len);796797/* 9. Check if r == r' */798ret = are_equal(r, r_prime, r_len, &check); EG(ret, err);799ret = check ? 0 : -1;800801err:802prj_pt_uninit(&sY);803prj_pt_uninit(&eG);804nn_uninit(&e);805nn_uninit(&tmp);806807/*808* We can now clear data part of the context. This will clear809* magic and avoid further reuse of the whole context.810*/811if(ctx != NULL){812IGNORE_RET_VAL(local_memset(&(ctx->verify_data.eckcdsa), 0,813sizeof(eckcdsa_verify_data)));814}815816/* Let's also clear what remains on the stack */817VAR_ZEROIFY(i);818PTR_NULLIFY(Wprime);819PTR_NULLIFY(G);820PTR_NULLIFY(Y);821PTR_NULLIFY(q);822VAR_ZEROIFY(p_len);823VAR_ZEROIFY(r_len);824VAR_ZEROIFY(q_bit_len);825VAR_ZEROIFY(p_bit_len);826PTR_NULLIFY(pub_key);827VAR_ZEROIFY(hsize);828PTR_NULLIFY(r);829PTR_NULLIFY(s);830831return ret;832}833834#else /* WITH_SIG_ECKCDSA */835836/*837* Dummy definition to avoid the empty translation unit ISO C warning838*/839typedef int dummy;840#endif /* WITH_SIG_ECKCDSA */841842843