Path: blob/main/crypto/libecc/src/sig/ecsdsa_common.c
39534 views
/*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#if (defined(WITH_SIG_ECSDSA) || defined(WITH_SIG_ECOSDSA))1718#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/ecsdsa_common.h>23#include <libecc/sig/sig_algs_internal.h>24#include <libecc/sig/ec_key.h>25#ifdef VERBOSE_INNER_VALUES26#define EC_SIG_ALG "EC[O]SDSA"27#endif28#include <libecc/utils/dbg_sig.h>2930/*31* Generic *internal* helper for EC-{,O}SDSA public key initialization32* functions. The function returns 0 on success, -1 on error.33*/34int __ecsdsa_init_pub_key(ec_pub_key *out_pub, const ec_priv_key *in_priv,35ec_alg_type key_type)36{37prj_pt_src_t G;38int ret;3940MUST_HAVE((out_pub != NULL), ret, err);4142/* Zero init public key to be generated */43ret = local_memset(out_pub, 0, sizeof(ec_pub_key)); EG(ret, err);4445ret = priv_key_check_initialized_and_type(in_priv, key_type); EG(ret, err);4647/* Y = xG */48G = &(in_priv->params->ec_gen);49/* Use blinding when computing point scalar multiplication */50ret = prj_pt_mul_blind(&(out_pub->y), &(in_priv->x), G); EG(ret, err);5152out_pub->key_type = key_type;53out_pub->params = in_priv->params;54out_pub->magic = PUB_KEY_MAGIC;5556err:57return ret;58}5960/*61* Generic *internal* helper for EC{,O}SDSA signature length functions.62* It provides signature length when exported to a buffer based on hash63* algorithm digest and block size, generator point order bit length, and64* uderlying prime field order bit length. The function returns 0 on success,65* -1 on error. On success, signature length is provided via 'siglen' out66* parameter. The function returns 0 on success, -1 on error. On success,67* 'siglen' out parameter provides the length of signature fonction. It is68* not meaningful on error.69*/70int __ecsdsa_siglen(u16 p_bit_len, u16 q_bit_len, u8 hsize, u8 blocksize,71u8 *siglen)72{73int ret;7475MUST_HAVE((siglen != NULL), ret, err);76MUST_HAVE(((p_bit_len <= CURVES_MAX_P_BIT_LEN) &&77(q_bit_len <= CURVES_MAX_Q_BIT_LEN) &&78(hsize <= MAX_DIGEST_SIZE) && (blocksize <= MAX_BLOCK_SIZE)),79ret, err);8081(*siglen) = (u8)ECSDSA_SIGLEN(hsize, q_bit_len);82ret = 0;8384err:85return ret;86}8788/*89* Generic *internal* EC-{,O}SDSA signature functions. There purpose is to90* allow passing specific hash functions and the random ephemeral91* key k, so that compliance tests against test vector be made92* without ugly hack in the code itself.93*94* The 'optimized' parameter tells the function if the r value of95* the signature is computed using only the x ccordinate of the96* the user's public key (normal version uses both coordinates).97*98* Normal: r = h(Wx || Wy || m)99* Optimized : r = h(Wx || m)100*101*| IUF - ECSDSA/ECOSDSA signature102*|103*| I 1. Get a random value k in ]0, q[104*| I 2. Compute W = kG = (Wx, Wy)105*| IUF 3. Compute r = H(Wx [|| Wy] || m)106*| - In the normal version (ECSDSA), r = H(Wx || Wy || m).107*| - In the optimized version (ECOSDSA), r = H(Wx || m).108*| F 4. Compute e = OS2I(r) mod q109*| F 5. if e == 0, restart at step 1.110*| F 6. Compute s = (k + ex) mod q.111*| F 7. if s == 0, restart at step 1.112*| F 8. Return (r, s)113*114* In the project, the normal mode is named ECSDSA, the optimized115* one is ECOSDSA.116*117* Implementation note:118*119* In ISO-14888-3, the option is provided to the developer to check120* whether r = 0 and restart the process in that case. Even if121* unlikely to trigger, that check makes a lot of sense because the122* verifier expects a non-zero value for r. In the specification, r123* is a string (r = H(Wx [|| Wy] || m)). But r is used in practice124* - both on the signer and the verifier - after conversion to an125* integer and reduction mod q. The value resulting from that step126* is named e (e = OS2I(r) mod q). The check for the case when r = 0127* should be replaced by a check for e = 0. This is more conservative128* and what is described above and done below in the implementation.129*/130131#define ECSDSA_SIGN_MAGIC ((word_t)(0x743c03ae409d15c4ULL))132#define ECSDSA_SIGN_CHECK_INITIALIZED(A, ret, err) \133MUST_HAVE((((void *)(A)) != NULL) && \134((A)->magic == ECSDSA_SIGN_MAGIC), ret, err)135136/*137* Generic *internal* helper for EC-{,O}SDSA signature initialization functions.138* The function returns 0 on success, -1 on error.139*/140int __ecsdsa_sign_init(struct ec_sign_context *ctx,141ec_alg_type key_type, int optimized)142{143u8 Wx[BYTECEIL(CURVES_MAX_P_BIT_LEN)];144u8 Wy[BYTECEIL(CURVES_MAX_P_BIT_LEN)];145const ec_priv_key *priv_key;146prj_pt_src_t G;147bitcnt_t p_bit_len;148u8 p_len;149prj_pt kG;150nn_src_t q;151int ret;152nn k;153kG.magic = k.magic = WORD(0);154155/* First, verify context has been initialized */156ret = sig_sign_check_initialized(ctx); EG(ret, err);157158/* Zero init points */159ret = local_memset(&kG, 0, sizeof(prj_pt)); EG(ret, err);160161/* Additional sanity checks on input params from context */162ret = key_pair_check_initialized_and_type(ctx->key_pair, key_type); EG(ret, err);163MUST_HAVE((ctx->h != NULL) && (ctx->h->digest_size <= MAX_DIGEST_SIZE) &&164(ctx->h->block_size <= MAX_BLOCK_SIZE), ret, err);165166/* Make things more readable */167priv_key = &(ctx->key_pair->priv_key);168G = &(priv_key->params->ec_gen);169q = &(priv_key->params->ec_gen_order);170p_bit_len = priv_key->params->ec_fp.p_bitlen;171p_len = (u8)BYTECEIL(p_bit_len);172173dbg_nn_print("p", &(priv_key->params->ec_fp.p));174dbg_nn_print("q", q);175dbg_priv_key_print("x", priv_key);176dbg_ec_point_print("G", G);177dbg_pub_key_print("Y", &(ctx->key_pair->pub_key));178179/* 1. Get a random value k in ]0, q[ */180#ifdef NO_KNOWN_VECTORS181/* NOTE: when we do not need self tests for known vectors,182* we can be strict about random function handler!183* This allows us to avoid the corruption of such a pointer.184*/185/* Sanity check on the handler before calling it */186MUST_HAVE((ctx->rand == nn_get_random_mod), ret, err);187#endif188MUST_HAVE((ctx->rand != NULL), ret, err);189ret = ctx->rand(&k, q); EG(ret, err);190dbg_nn_print("k", &k);191192/* 2. Compute W = kG = (Wx, Wy). */193#ifdef USE_SIG_BLINDING194ret = prj_pt_mul_blind(&kG, &k, G); EG(ret, err);195#else196ret = prj_pt_mul(&kG, &k, G); EG(ret, err);197#endif198ret = prj_pt_unique(&kG, &kG); EG(ret, err);199dbg_nn_print("W_x", &(kG.X.fp_val));200dbg_nn_print("W_y", &(kG.Y.fp_val));201202/*203* 3. Compute r = H(Wx [|| Wy] || m)204*205* - In the normal version (ECSDSA), r = h(Wx || Wy || m).206* - In the optimized version (ECOSDSA), r = h(Wx || m).207*/208/* Since we call a callback, sanity check our mapping */209ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);210ret = ctx->h->hfunc_init(&(ctx->sign_data.ecsdsa.h_ctx)); EG(ret, err);211ret = fp_export_to_buf(Wx, p_len, &(kG.X)); EG(ret, err);212ret = ctx->h->hfunc_update(&(ctx->sign_data.ecsdsa.h_ctx), Wx, p_len); EG(ret, err);213if (!optimized) {214ret = fp_export_to_buf(Wy, p_len, &(kG.Y)); EG(ret, err);215ret = ctx->h->hfunc_update(&(ctx->sign_data.ecsdsa.h_ctx), Wy,216p_len); EG(ret, err);217}218ret = local_memset(Wx, 0, p_len); EG(ret, err);219ret = local_memset(Wy, 0, p_len); EG(ret, err);220221/* Initialize the remaining of sign context. */222ret = nn_copy(&(ctx->sign_data.ecsdsa.k), &k); EG(ret, err);223ctx->sign_data.ecsdsa.magic = ECSDSA_SIGN_MAGIC;224225err:226prj_pt_uninit(&kG);227nn_uninit(&k);228229PTR_NULLIFY(priv_key);230PTR_NULLIFY(G);231PTR_NULLIFY(q);232VAR_ZEROIFY(p_len);233VAR_ZEROIFY(p_bit_len);234235return ret;236}237238/*239* Generic *internal* helper for EC-{,O}SDSA signature update functions.240* The function returns 0 on success, -1 on error.241*/242int __ecsdsa_sign_update(struct ec_sign_context *ctx,243const u8 *chunk, u32 chunklen)244{245int ret;246247/*248* First, verify context has been initialized and private249* part too. This guarantees the context is an ECSDSA250* signature one and we do not update() or finalize()251* before init().252*/253ret = sig_sign_check_initialized(ctx); EG(ret, err);254ECSDSA_SIGN_CHECK_INITIALIZED(&(ctx->sign_data.ecsdsa), ret, err);255256/* 3. Compute r = H(Wx [|| Wy] || m) */257/* Since we call a callback, sanity check our mapping */258ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);259ret = ctx->h->hfunc_update(&(ctx->sign_data.ecsdsa.h_ctx), chunk, chunklen); EG(ret, err);260261err:262return ret;263}264265/*266* Generic *internal* helper for EC-{,O}SDSA signature finalization functions.267* The function returns 0 on success, -1 on error.268*/269int __ecsdsa_sign_finalize(struct ec_sign_context *ctx, u8 *sig, u8 siglen)270{271nn_src_t q, x;272nn s, e, ex;273u8 r[MAX_DIGEST_SIZE];274const ec_priv_key *priv_key;275bitcnt_t q_bit_len;276u8 r_len, s_len;277u8 hsize;278int ret;279int iszero;280#ifdef USE_SIG_BLINDING281/* b is the blinding mask */282nn b, binv;283b.magic = binv.magic = WORD(0);284#endif /* USE_SIG_BLINDING */285286s.magic = e.magic = ex.magic = WORD(0);287288/*289* First, verify context has been initialized and private290* part too. This guarantees the context is an ECSDSA291* signature one and we do not finalize() before init().292*/293ret = sig_sign_check_initialized(ctx); EG(ret, err);294ECSDSA_SIGN_CHECK_INITIALIZED(&(ctx->sign_data.ecsdsa), ret, err);295MUST_HAVE((sig != NULL), ret, err);296297/* Make things more readable */298priv_key = &(ctx->key_pair->priv_key);299q = &(priv_key->params->ec_gen_order);300x = &(priv_key->x);301q_bit_len = priv_key->params->ec_gen_order_bitlen;302hsize = ctx->h->digest_size;303r_len = (u8)ECSDSA_R_LEN(hsize);304s_len = (u8)ECSDSA_S_LEN(q_bit_len);305306MUST_HAVE((siglen == ECSDSA_SIGLEN(hsize, q_bit_len)), ret, err);307308#ifdef USE_SIG_BLINDING309ret = nn_get_random_mod(&b, q); EG(ret, err);310dbg_nn_print("b", &b);311#endif /* USE_SIG_BLINDING */312313/* 3. Compute r = H(Wx [|| Wy] || m) */314ret = local_memset(r, 0, hsize); EG(ret, err);315/* Since we call a callback, sanity check our mapping */316ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);317ret = ctx->h->hfunc_finalize(&(ctx->sign_data.ecsdsa.h_ctx), r); EG(ret, err);318319dbg_buf_print("r", r, r_len);320321/* 4. Compute e = OS2I(r) mod q */322ret = nn_init_from_buf(&e, r, r_len); EG(ret, err);323ret = nn_mod(&e, &e, q); EG(ret, err);324dbg_nn_print("e", &e);325326/*327* 5. if e == 0, restart at step 1.328*329* As we cannot restart at that point (step 1. is in init()),330* we just stop and return an error.331*/332MUST_HAVE(!nn_iszero(&e, &iszero) && !iszero, ret, err);333334#ifdef USE_SIG_BLINDING335/* Blind e with b */336ret = nn_mod_mul(&e, &e, &b, q); EG(ret, err);337#endif /* USE_SIG_BLINDING */338339/* 6. Compute s = (k + ex) mod q. */340ret = nn_mod_mul(&ex, x, &e, q); EG(ret, err);341#ifdef USE_SIG_BLINDING342/* Blind k with b */343ret = nn_mod_mul(&s, &(ctx->sign_data.ecsdsa.k), &b, q); EG(ret, err);344ret = nn_mod_add(&s, &s, &ex, q); EG(ret, err);345#else346ret = nn_mod_add(&s, &(ctx->sign_data.ecsdsa.k), &ex, q); EG(ret, err);347#endif /* USE_SIG_BLINDING */348349#ifdef USE_SIG_BLINDING350/* Unblind s */351/* NOTE: we use Fermat's little theorem inversion for352* constant time here. This is possible since q is prime.353*/354ret = nn_modinv_fermat(&binv, &b, q); EG(ret, err);355ret = nn_mod_mul(&s, &s, &binv, q); EG(ret, err);356#endif /* USE_SIG_BLINDING */357dbg_nn_print("s", &s);358359/*360* 7. if s == 0, restart at step 1.361*362* As we cannot restart at that point (step 1. is in init()),363* we just stop and return an error.364*/365MUST_HAVE((!nn_iszero(&s, &iszero)) && (!iszero), ret, err);366367/* 8. Return (r, s) */368ret = local_memcpy(sig, r, r_len); EG(ret, err);369ret = local_memset(r, 0, r_len); EG(ret, err);370ret = nn_export_to_buf(sig + r_len, s_len, &s);371372err:373nn_uninit(&s);374nn_uninit(&e);375nn_uninit(&ex);376#ifdef USE_SIG_BLINDING377nn_uninit(&b);378nn_uninit(&binv);379#endif /* USE_SIG_BLINDING */380381/*382* We can now clear data part of the context. This will clear383* magic and avoid further reuse of the whole context.384*/385if(ctx != NULL){386IGNORE_RET_VAL(local_memset(&(ctx->sign_data.ecsdsa), 0, sizeof(ecsdsa_sign_data)));387}388389/* Clean what remains on the stack */390PTR_NULLIFY(q);391PTR_NULLIFY(x);392PTR_NULLIFY(priv_key);393VAR_ZEROIFY(q_bit_len);394VAR_ZEROIFY(r_len);395VAR_ZEROIFY(s_len);396VAR_ZEROIFY(hsize);397398return ret;399}400401/* local helper for context sanity checks. Returns 0 on success, -1 on error. */402#define ECSDSA_VERIFY_MAGIC ((word_t)(0x8eac1ff89995bb0aULL))403#define ECSDSA_VERIFY_CHECK_INITIALIZED(A, ret, err) \404MUST_HAVE((((const void *)(A)) != NULL) && \405((A)->magic == ECSDSA_VERIFY_MAGIC), ret, err)406407/*408*| IUF - ECSDSA/ECOSDSA verification409*|410*| I 1. if s is not in ]0,q[, reject the signature.411*| I 2. Compute e = -r mod q412*| I 3. If e == 0, reject the signature.413*| I 4. Compute W' = sG + eY414*| IUF 5. Compute r' = H(W'x [|| W'y] || m)415*| - In the normal version (ECSDSA), r' = H(W'x || W'y || m).416*| - In the optimized version (ECOSDSA), r' = H(W'x || m).417*| F 6. Accept the signature if and only if r and r' are the same418*/419420/*421* Generic *internal* helper for EC-{,O}SDSA verification initialization functions.422* The function returns 0 on success, -1 on error.423*/424int __ecsdsa_verify_init(struct ec_verify_context *ctx,425const u8 *sig, u8 siglen,426ec_alg_type key_type, int optimized)427{428prj_pt_src_t G, Y;429const ec_pub_key *pub_key;430nn_src_t q;431nn rmodq, e, r, s;432prj_pt sG, eY;433prj_pt_t Wprime;434u8 Wprimex[BYTECEIL(CURVES_MAX_P_BIT_LEN)];435u8 Wprimey[BYTECEIL(CURVES_MAX_P_BIT_LEN)];436u8 p_len, r_len, s_len;437bitcnt_t q_bit_len;438u8 hsize;439int ret, iszero, cmp;440441rmodq.magic = e.magic = r.magic = s.magic = WORD(0);442sG.magic = eY.magic = WORD(0);443444/* NOTE: we reuse sG for Wprime to optimize local variables */445Wprime = &sG;446447/* First, verify context has been initialized */448ret = sig_verify_check_initialized(ctx); EG(ret, err);449450/* Zero init points */451ret = local_memset(&sG, 0, sizeof(prj_pt)); EG(ret, err);452ret = local_memset(&eY, 0, sizeof(prj_pt)); EG(ret, err);453454/* Do some sanity checks on input params */455ret = pub_key_check_initialized_and_type(ctx->pub_key, key_type); EG(ret, err);456MUST_HAVE((ctx->h != NULL) && (ctx->h->digest_size <= MAX_DIGEST_SIZE) &&457(ctx->h->block_size <= MAX_BLOCK_SIZE), ret, err);458MUST_HAVE((sig != NULL), ret, err);459460/* Make things more readable */461pub_key = ctx->pub_key;462G = &(pub_key->params->ec_gen);463Y = &(pub_key->y);464q = &(pub_key->params->ec_gen_order);465p_len = (u8)BYTECEIL(pub_key->params->ec_fp.p_bitlen);466q_bit_len = pub_key->params->ec_gen_order_bitlen;467hsize = ctx->h->digest_size;468r_len = (u8)ECSDSA_R_LEN(hsize);469s_len = (u8)ECSDSA_S_LEN(q_bit_len);470471MUST_HAVE((siglen == ECSDSA_SIGLEN(hsize, q_bit_len)), ret, err);472473/* 1. if s is not in ]0,q[, reject the signature. */474ret = nn_init_from_buf(&s, sig + r_len, s_len); EG(ret, err);475ret = nn_iszero(&s, &iszero); EG(ret, err);476ret = nn_cmp(&s, q, &cmp); EG(ret, err);477MUST_HAVE((!iszero) && (cmp < 0), ret, err);478479/*480* 2. Compute e = -r mod q481*482* To avoid dealing w/ negative numbers, we simply compute483* e = -r mod q = q - (r mod q) (except when r is 0).484*/485ret = nn_init_from_buf(&r, sig, r_len); EG(ret, err);486ret = nn_mod(&rmodq, &r, q); EG(ret, err);487ret = nn_mod_neg(&e, &rmodq, q); EG(ret, err);488489/* 3. If e == 0, reject the signature. */490ret = nn_iszero(&e, &iszero); EG(ret, err);491MUST_HAVE((!iszero), ret, err);492493/* 4. Compute W' = sG + eY */494ret = prj_pt_mul(&sG, &s, G); EG(ret, err);495ret = prj_pt_mul(&eY, &e, Y); EG(ret, err);496ret = prj_pt_add(Wprime, &sG, &eY); EG(ret, err);497ret = prj_pt_unique(Wprime, Wprime); EG(ret, err);498499/*500* 5. Compute r' = H(W'x [|| W'y] || m)501*502* - In the normal version (ECSDSA), r = h(W'x || W'y || m).503* - In the optimized version (ECOSDSA), r = h(W'x || m).504*/505/* Since we call a callback, sanity check our mapping */506ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);507ret = ctx->h->hfunc_init(&(ctx->verify_data.ecsdsa.h_ctx)); EG(ret, err);508ret = fp_export_to_buf(Wprimex, p_len, &(Wprime->X)); EG(ret, err);509/* Since we call a callback, sanity check our mapping */510ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);511ret = ctx->h->hfunc_update(&(ctx->verify_data.ecsdsa.h_ctx), Wprimex, p_len); EG(ret, err);512if (!optimized) {513ret = fp_export_to_buf(Wprimey, p_len, &(Wprime->Y)); EG(ret, err);514/* Since we call a callback, sanity check our mapping */515ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);516ret = ctx->h->hfunc_update(&(ctx->verify_data.ecsdsa.h_ctx),517Wprimey, p_len); EG(ret, err);518}519ret = local_memset(Wprimex, 0, p_len); EG(ret, err);520ret = local_memset(Wprimey, 0, p_len); EG(ret, err);521522/* Initialize the remaining of verify context. */523ret = local_memcpy(ctx->verify_data.ecsdsa.r, sig, r_len); EG(ret, err);524ret = nn_copy(&(ctx->verify_data.ecsdsa.s), &s); EG(ret, err);525526ctx->verify_data.ecsdsa.magic = ECSDSA_VERIFY_MAGIC;527528err:529nn_uninit(&rmodq);530nn_uninit(&e);531nn_uninit(&r);532nn_uninit(&s);533prj_pt_uninit(&sG);534prj_pt_uninit(&eY);535536/* Clean what remains on the stack */537PTR_NULLIFY(Wprime);538PTR_NULLIFY(G);539PTR_NULLIFY(Y);540PTR_NULLIFY(pub_key);541PTR_NULLIFY(q);542VAR_ZEROIFY(p_len);543VAR_ZEROIFY(r_len);544VAR_ZEROIFY(s_len);545VAR_ZEROIFY(q_bit_len);546VAR_ZEROIFY(hsize);547548return ret;549}550551/*552* Generic *internal* helper for EC-{,O}SDSA verification update functions.553* The function returns 0 on success, -1 on error.554*/555int __ecsdsa_verify_update(struct ec_verify_context *ctx,556const u8 *chunk, u32 chunklen)557{558int ret;559560/*561* First, verify context has been initialized and public562* part too. This guarantees the context is an ECSDSA563* verification one and we do not update() or finalize()564* before init().565*/566ret = sig_verify_check_initialized(ctx); EG(ret, err);567ECSDSA_VERIFY_CHECK_INITIALIZED(&(ctx->verify_data.ecsdsa), ret, err);568569/* 5. Compute r' = H(W'x [|| W'y] || m) */570/* Since we call a callback, sanity check our mapping */571ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);572ret = ctx->h->hfunc_update(&(ctx->verify_data.ecsdsa.h_ctx), chunk,573chunklen);574575err:576return ret;577}578579/*580* Generic *internal* helper for EC-{,O}SDSA verification finalization581* functions. The function returns 0 on success, -1 on error.582*/583int __ecsdsa_verify_finalize(struct ec_verify_context *ctx)584{585u8 r_prime[MAX_DIGEST_SIZE];586u32 r_len;587int ret, check;588589/*590* First, verify context has been initialized and public591* part too. This guarantees the context is an ECSDSA592* verification one and we do not finalize() before init().593*/594ret = sig_verify_check_initialized(ctx); EG(ret, err);595ECSDSA_VERIFY_CHECK_INITIALIZED(&(ctx->verify_data.ecsdsa), ret, err);596597r_len = ECSDSA_R_LEN(ctx->h->digest_size);598599/* 5. Compute r' = H(W'x [|| W'y] || m) */600/* Since we call a callback, sanity check our mapping */601ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);602ret = ctx->h->hfunc_finalize(&(ctx->verify_data.ecsdsa.h_ctx), r_prime); EG(ret, err);603604/* 6. Accept the signature if and only if r and r' are the same */605ret = are_equal(ctx->verify_data.ecsdsa.r, r_prime, r_len, &check); EG(ret, err);606ret = check ? 0 : -1;607608err:609IGNORE_RET_VAL(local_memset(r_prime, 0, sizeof(r_prime)));610/*611* We can now clear data part of the context. This will clear612* magic and avoid further reuse of the whole context.613*/614if(ctx != NULL){615IGNORE_RET_VAL(local_memset(&(ctx->verify_data.ecsdsa), 0,616sizeof(ecsdsa_verify_data)));617}618619/* Clean what remains on the stack */620VAR_ZEROIFY(r_len);621622return ret;623}624625#else /* (defined(WITH_SIG_ECSDSA) || defined(WITH_SIG_ECOSDSA)) */626627/*628* Dummy definition to avoid the empty translation unit ISO C warning629*/630typedef int dummy;631#endif /* (defined(WITH_SIG_ECSDSA) || defined(WITH_SIG_ECOSDSA)) */632633634