From cc1f1ff75cdc535ff1997d7cc9aa48c11077c2df Mon Sep 17 00:00:00 2001 From: Sarah GLINER Date: Mon, 13 Nov 2023 17:08:01 +0100 Subject: [PATCH] some more error mgmt --- src/monero_api.h | 82 +++---- src/monero_blind.c | 65 ++++-- src/monero_clsag.c | 96 +++++++-- src/monero_crypto.c | 501 +++++++++++++++++++++++++++++-------------- src/monero_init.c | 36 +++- src/monero_key.c | 64 ++++-- src/monero_mlsag.c | 61 +++++- src/monero_open_tx.c | 14 +- src/monero_prehash.c | 25 ++- src/monero_proof.c | 31 ++- 10 files changed, 694 insertions(+), 281 deletions(-) diff --git a/src/monero_api.h b/src/monero_api.h index c8a22d5..1a8dfb1 100644 --- a/src/monero_api.h +++ b/src/monero_api.h @@ -142,14 +142,14 @@ extern const unsigned char C_FAKE_SEC_SPEND_KEY[32]; int is_fake_view_key(unsigned char *s); int is_fake_spend_key(unsigned char *s); -void monero_ge_fromfe_frombytes(unsigned char *ge, unsigned char *bytes, size_t ge_len, - size_t bytes_len); +int monero_ge_fromfe_frombytes(unsigned char *ge, unsigned char *bytes, size_t ge_len, + size_t bytes_len); void monero_sc_add(unsigned char *r, unsigned char *s1, unsigned char *s2); -void monero_hash_to_scalar(unsigned char *scalar, unsigned char *raw, size_t scalar_len, - unsigned int len); -void monero_hash_to_ec(unsigned char *ec, unsigned char *ec_pub, size_t ec_len); -void monero_generate_keypair(unsigned char *ec_pub, unsigned char *ec_priv, size_t ec_pub_len, - size_t ec_priv_len); +int monero_hash_to_scalar(unsigned char *scalar, unsigned char *raw, size_t scalar_len, + unsigned int len); +int monero_hash_to_ec(unsigned char *ec, unsigned char *ec_pub, size_t ec_len); +int monero_generate_keypair(unsigned char *ec_pub, unsigned char *ec_priv, size_t ec_pub_len, + size_t ec_priv_len); /* * compute s = 8 * (k*P) * @@ -182,22 +182,22 @@ int monero_derive_secret_key(unsigned char *x, unsigned char *drv_data, unsigned int monero_derive_public_key(unsigned char *x, unsigned char *drv_data, unsigned int out_idx, unsigned char *ec_pub, size_t x_len, size_t drv_data_len, size_t ec_pub_len); -void monero_secret_key_to_public_key(unsigned char *ec_pub, unsigned char *ec_priv, - size_t ec_pub_len, size_t ec_priv_len); -void monero_generate_key_image(unsigned char *img, unsigned char *P, unsigned char *x, - size_t img_len, size_t x_len); +int monero_secret_key_to_public_key(unsigned char *ec_pub, unsigned char *ec_priv, + size_t ec_pub_len, size_t ec_priv_len); +int monero_generate_key_image(unsigned char *img, unsigned char *P, unsigned char *x, + size_t img_len, size_t x_len); int monero_derive_view_tag(unsigned char *view_tag, const unsigned char drv_data[static 32], unsigned int out_idx); -void monero_derive_subaddress_public_key(unsigned char *x, unsigned char *pub, - unsigned char *drv_data, unsigned int index, size_t x_len, - size_t pub_len, size_t drv_data_len); -void monero_get_subaddress_spend_public_key(unsigned char *x, unsigned char *index, size_t x_len, - size_t index_len); -void monero_get_subaddress(unsigned char *C, unsigned char *D, unsigned char *index, size_t C_len, - size_t D_len, size_t index_len); -void monero_get_subaddress_secret_key(unsigned char *sub_s, unsigned char *s, unsigned char *index, - size_t sub_s_len, size_t s_len, size_t index_len); +int monero_derive_subaddress_public_key(unsigned char *x, unsigned char *pub, + unsigned char *drv_data, unsigned int index, size_t x_len, + size_t pub_len, size_t drv_data_len); +int monero_get_subaddress_spend_public_key(unsigned char *x, unsigned char *index, size_t x_len, + size_t index_len); +int monero_get_subaddress(unsigned char *C, unsigned char *D, unsigned char *index, size_t C_len, + size_t D_len, size_t index_len); +int monero_get_subaddress_secret_key(unsigned char *sub_s, unsigned char *s, unsigned char *index, + size_t sub_s_len, size_t s_len, size_t index_len); void monero_clear_words(void); /* ----------------------------------------------------------------------- */ @@ -295,28 +295,28 @@ int monero_derivation_to_scalar(unsigned char *scalar, unsigned char *drv_data, /* * W = k.P */ -void monero_ecmul_k(unsigned char *W, unsigned char *P, unsigned char *scalar32, size_t W_len, - size_t P_len, size_t scalar32_len); +int monero_ecmul_k(unsigned char *W, unsigned char *P, unsigned char *scalar32, size_t W_len, + size_t P_len, size_t scalar32_len); /* * W = 8k.P */ -void monero_ecmul_8k(unsigned char *W, unsigned char *P, unsigned char *scalar32, size_t W_len, - size_t P_len, size_t scalar32_len); +int monero_ecmul_8k(unsigned char *W, unsigned char *P, unsigned char *scalar32, size_t W_len, + size_t P_len, size_t scalar32_len); /* * W = 8.P */ -void monero_ecmul_8(unsigned char *W, unsigned char *P, size_t W_len, size_t P_len); +int monero_ecmul_8(unsigned char *W, unsigned char *P, size_t W_len, size_t P_len); /* * W = k.G */ -void monero_ecmul_G(unsigned char *W, unsigned char *scalar32, size_t W_len, size_t scalar32_len); +int monero_ecmul_G(unsigned char *W, unsigned char *scalar32, size_t W_len, size_t scalar32_len); /* * W = k.H */ -void monero_ecmul_H(unsigned char *W, unsigned char *scalar32, size_t W_len, size_t scalar32_len); +int monero_ecmul_H(unsigned char *W, unsigned char *scalar32, size_t W_len, size_t scalar32_len); /** * keccak("amount"|sk) @@ -326,38 +326,38 @@ void monero_ecdhHash(unsigned char *x, unsigned char *k, size_t k_len); /** * keccak("commitment_mask"|sk) %order */ -void monero_genCommitmentMask(unsigned char *c, unsigned char *sk, size_t c_len, size_t sk_len); +int monero_genCommitmentMask(unsigned char *c, unsigned char *sk, size_t c_len, size_t sk_len); /* * W = P+Q */ -void monero_ecadd(unsigned char *W, unsigned char *P, unsigned char *Q, size_t W_len, size_t P_len, - size_t Q_len); +int monero_ecadd(unsigned char *W, unsigned char *P, unsigned char *Q, size_t W_len, size_t P_len, + size_t Q_len); /* * W = P-Q */ -void monero_ecsub(unsigned char *W, unsigned char *P, unsigned char *Q, size_t W_len, size_t P_len, - size_t Q_len); +int monero_ecsub(unsigned char *W, unsigned char *P, unsigned char *Q, size_t W_len, size_t P_len, + size_t Q_len); /* r = (a+b) %order */ -void monero_addm(unsigned char *r, unsigned char *a, unsigned char *b, size_t r_len, size_t a_len, - size_t b_len); +int monero_addm(unsigned char *r, unsigned char *a, unsigned char *b, size_t r_len, size_t a_len, + size_t b_len); /* r = (a-b) %order */ -void monero_subm(unsigned char *r, unsigned char *a, unsigned char *b, size_t r_len, size_t a_len, - size_t b_len); +int monero_subm(unsigned char *r, unsigned char *a, unsigned char *b, size_t r_len, size_t a_len, + size_t b_len); /* r = (a*b) %order */ -void monero_multm(unsigned char *r, unsigned char *a, unsigned char *b, size_t r_len, size_t a_len, - size_t b_len); +int monero_multm(unsigned char *r, unsigned char *a, unsigned char *b, size_t r_len, size_t a_len, + size_t b_len); /* r = (a*8) %order */ -void monero_multm_8(unsigned char *r, unsigned char *a, size_t r_len, size_t a_len); +int monero_multm_8(unsigned char *r, unsigned char *a, size_t r_len, size_t a_len); /* */ -void monero_reduce(unsigned char *r, unsigned char *a, size_t r_len, size_t a_len); +int monero_reduce(unsigned char *r, unsigned char *a, size_t r_len, size_t a_len); -void monero_rng_mod_order(unsigned char *r, size_t r_len); +int monero_rng_mod_order(unsigned char *r, size_t r_len); /* ----------------------------------------------------------------------- */ /* --- IO ---- */ /* ----------------------------------------------------------------------- */ diff --git a/src/monero_blind.c b/src/monero_blind.c index cd8b56b..6d25255 100644 --- a/src/monero_blind.c +++ b/src/monero_blind.c @@ -48,11 +48,26 @@ int monero_apdu_blind() { } } else { // blind mask - monero_hash_to_scalar(AKout, AKout, sizeof(AKout), sizeof(AKout)); - monero_addm(k, k, AKout, sizeof(k), sizeof(k), sizeof(AKout)); + err = monero_hash_to_scalar(AKout, AKout, sizeof(AKout), sizeof(AKout)); + if (err) { + return err; + } + + err = monero_addm(k, k, AKout, sizeof(k), sizeof(k), sizeof(AKout)); + if (err) { + return err; + } + // blind value - monero_hash_to_scalar(AKout, AKout, sizeof(AKout), sizeof(AKout)); - monero_addm(v, v, AKout, sizeof(v), sizeof(v), sizeof(AKout)); + err = monero_hash_to_scalar(AKout, AKout, sizeof(AKout), sizeof(AKout)); + if (err) { + return err; + } + + err = monero_addm(v, v, AKout, sizeof(v), sizeof(v), sizeof(AKout)); + if (err) { + return err; + } } // ret all monero_io_insert(v, 32); @@ -66,19 +81,39 @@ int monero_apdu_blind() { /* ----------------------------------------------------------------------- */ int monero_unblind(unsigned char *v, unsigned char *k, unsigned char *AKout, unsigned int short_amount, size_t v_len, size_t k_len, size_t AKout_len) { + int error; if (short_amount == 2) { - monero_genCommitmentMask(k, AKout, k_len, AKout_len); + error = monero_genCommitmentMask(k, AKout, k_len, AKout_len); + if (error) { + return error; + } + monero_ecdhHash(AKout, AKout, AKout_len); for (int i = 0; i < 8; i++) { v[i] = v[i] ^ AKout[i]; } } else { // unblind mask - monero_hash_to_scalar(AKout, AKout, AKout_len, AKout_len); - monero_subm(k, k, AKout, k_len, k_len, AKout_len); + error = monero_hash_to_scalar(AKout, AKout, AKout_len, AKout_len); + if (error) { + return error; + } + + error = monero_subm(k, k, AKout, k_len, k_len, AKout_len); + if (error) { + return error; + } + // unblind value - monero_hash_to_scalar(AKout, AKout, AKout_len, AKout_len); - monero_subm(v, v, AKout, v_len, v_len, AKout_len); + error = monero_hash_to_scalar(AKout, AKout, AKout_len, AKout_len); + if (error) { + return error; + } + + error = monero_subm(v, v, AKout, v_len, v_len, AKout_len); + if (error) { + return error; + } } return 0; } @@ -101,8 +136,11 @@ int monero_apdu_unblind() { monero_io_discard(1); - monero_unblind(v, k, AKout, G_monero_vstate.options & 0x03, sizeof(v), sizeof(k), - sizeof(AKout)); + err = monero_unblind(v, k, AKout, G_monero_vstate.options & 0x03, sizeof(v), sizeof(k), + sizeof(AKout)); + if (err) { + return err; + } // ret all monero_io_insert(v, 32); @@ -125,7 +163,10 @@ int monero_apdu_gen_commitment_mask() { } monero_io_discard(1); - monero_genCommitmentMask(k, AKout, sizeof(k), sizeof(AKout)); + err = monero_genCommitmentMask(k, AKout, sizeof(k), sizeof(AKout)); + if (err) { + return err; + } // ret all monero_io_insert(k, 32); diff --git a/src/monero_clsag.c b/src/monero_clsag.c index e9bcb5f..1fe5e54 100644 --- a/src/monero_clsag.c +++ b/src/monero_clsag.c @@ -62,20 +62,38 @@ int monero_apdu_clsag_prepare() { monero_io_discard(1); // a - monero_rng_mod_order(a, sizeof(a)); + err = monero_rng_mod_order(a, sizeof(a)); + if (err) { + return err; + } + monero_io_insert_encrypt(a, 32, TYPE_ALPHA); // a.G - monero_ecmul_G(W, a, sizeof(W), sizeof(a)); + err = monero_ecmul_G(W, a, sizeof(W), sizeof(a)); + if (err) { + return err; + } + monero_io_insert(W, 32); // a.H - monero_ecmul_k(W, H, a, sizeof(W), sizeof(H), sizeof(a)); + err = monero_ecmul_k(W, H, a, sizeof(W), sizeof(H), sizeof(a)); + if (err) { + return err; + } + monero_io_insert(W, 32); // I = p.H - monero_ecmul_k(W, H, p, sizeof(W), sizeof(H), sizeof(p)); + err = monero_ecmul_k(W, H, p, sizeof(W), sizeof(H), sizeof(p)); + if (err) { + return err; + } monero_io_insert(W, 32); // D = z.H - monero_ecmul_k(W, H, z, sizeof(W), sizeof(H), sizeof(z)); + err = monero_ecmul_k(W, H, z, sizeof(W), sizeof(H), sizeof(z)); + if (err) { + return err; + } monero_io_insert(W, 32); return SW_OK; @@ -107,7 +125,10 @@ int monero_apdu_clsag_hash() { monero_keccak_update_H(msg, 32); if ((G_monero_vstate.options & 0x80) == 0) { monero_keccak_final_H(c); - monero_reduce(c, c, sizeof(c), sizeof(c)); + int err = monero_reduce(c, c, sizeof(c), sizeof(c)); + if (err) { + return err; + } monero_io_insert(c, 32); memcpy(G_monero_vstate.c, c, 32); } @@ -172,13 +193,36 @@ int monero_apdu_clsag_sign() { monero_check_scalar_not_null(p); monero_check_scalar_not_null(z); - monero_reduce(a, a, sizeof(a), sizeof(a)); - monero_reduce(p, p, sizeof(p), sizeof(p)); - monero_reduce(z, z, sizeof(z), sizeof(z)); - monero_reduce(mu_P, mu_P, sizeof(mu_P), sizeof(mu_P)); - monero_reduce(mu_C, mu_C, sizeof(mu_C), sizeof(mu_C)); - monero_reduce(G_monero_vstate.c, G_monero_vstate.c, sizeof(G_monero_vstate.c), - sizeof(G_monero_vstate.c)); + err = monero_reduce(a, a, sizeof(a), sizeof(a)); + if (err) { + return err; + } + + err = monero_reduce(p, p, sizeof(p), sizeof(p)); + if (err) { + return err; + } + + err = monero_reduce(z, z, sizeof(z), sizeof(z)); + if (err) { + return err; + } + + err = monero_reduce(mu_P, mu_P, sizeof(mu_P), sizeof(mu_P)); + if (err) { + return err; + } + + err = monero_reduce(mu_C, mu_C, sizeof(mu_C), sizeof(mu_C)); + if (err) { + return err; + } + + err = monero_reduce(G_monero_vstate.c, G_monero_vstate.c, sizeof(G_monero_vstate.c), + sizeof(G_monero_vstate.c)); + if (err) { + return err; + } // s0_p_mu_P = mu_P*p // s0_add_z_mu_C = mu_C*z + s0_p_mu_P @@ -187,15 +231,31 @@ int monero_apdu_clsag_sign() { // = a - c*(mu_C*z + mu_P*p) // s = p*mu_P - monero_multm(s, p, mu_P, sizeof(s), sizeof(p), sizeof(mu_P)); + err = monero_multm(s, p, mu_P, sizeof(s), sizeof(p), sizeof(mu_P)); + if (err) { + return err; + } // mu_P = mu_C*z - monero_multm(mu_P, mu_C, z, sizeof(mu_P), sizeof(mu_C), sizeof(z)); + err = monero_multm(mu_P, mu_C, z, sizeof(mu_P), sizeof(mu_C), sizeof(z)); + if (err) { + return err; + } // s = p*mu_P + mu_C*z - monero_addm(s, s, mu_P, sizeof(s), sizeof(s), sizeof(mu_P)); + err = monero_addm(s, s, mu_P, sizeof(s), sizeof(s), sizeof(mu_P)); + if (err) { + return err; + } // mu_P = c * (p*mu_P + mu_C*z) - monero_multm(mu_P, G_monero_vstate.c, s, sizeof(mu_P), sizeof(G_monero_vstate.c), sizeof(s)); + err = monero_multm(mu_P, G_monero_vstate.c, s, sizeof(mu_P), sizeof(G_monero_vstate.c), + sizeof(s)); + if (err) { + return err; + } // s = a - c*(p*mu_P + mu_C*z) - monero_subm(s, a, mu_P, sizeof(s), sizeof(a), sizeof(mu_P)); + err = monero_subm(s, a, mu_P, sizeof(s), sizeof(a), sizeof(mu_P)); + if (err) { + return err; + } monero_io_insert(s, 32); diff --git a/src/monero_crypto.c b/src/monero_crypto.c index 56faffe..a164db4 100644 --- a/src/monero_crypto.c +++ b/src/monero_crypto.c @@ -69,16 +69,11 @@ int monero_aes_derive(cx_aes_key_t *sk, unsigned char *seed32, unsigned char *a, monero_keccak_H(h1, 32, h1); - return cx_aes_init_key_no_throw(h1, 16, sk); -} - -/* ----------------------------------------------------------------------- */ -/* --- --- */ -/* ----------------------------------------------------------------------- */ -void monero_aes_generate(cx_aes_key_t *sk) { - unsigned char h1[16]; - cx_rng(h1, 16); - cx_aes_init_key_no_throw(h1, 16, sk); + int error = cx_aes_init_key_no_throw(h1, 16, sk); + if (error) { + return SW_SECURITY_INTERNAL; + } + return 0; } /* ----------------------------------------------------------------------- */ @@ -162,21 +157,33 @@ void monero_hash_init_sha256(cx_hash_t *hasher) { } int monero_hash_init_keccak(cx_hash_t *hasher) { - return cx_keccak_init_no_throw((cx_sha3_t *)hasher, 256); + int error = cx_keccak_init_no_throw((cx_sha3_t *)hasher, 256); + if (error) { + return SW_SECURITY_INTERNAL; + } + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ int monero_hash_update(cx_hash_t *hasher, const unsigned char *buf, unsigned int len) { - return cx_hash_no_throw(hasher, 0, buf, len, NULL, 0); + int error = cx_hash_no_throw(hasher, 0, buf, len, NULL, 0); + if (error) { + return SW_SECURITY_INTERNAL; + } + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ int monero_hash_final(cx_hash_t *hasher, unsigned char *out) { - return cx_hash_no_throw(hasher, CX_LAST, NULL, 0, out, 32); + int error = cx_hash_no_throw(hasher, CX_LAST, NULL, 0, out, 32); + if (error) { + return SW_SECURITY_INTERNAL; + } + return 0; } /* ----------------------------------------------------------------------- */ @@ -190,11 +197,14 @@ int monero_hash(unsigned int algo, cx_hash_t *hasher, const unsigned char *buf, } else { err = cx_keccak_init_no_throw((cx_sha3_t *)hasher, 256); if (err) { - return err; + return SW_SECURITY_INTERNAL; } } err = cx_hash_no_throw(hasher, CX_LAST, buf, len, out, 32); - return err; + if (err) { + return SW_SECURITY_INTERNAL; + } + return 0; } /* ----------------------------------------------------------------------- */ @@ -305,8 +315,9 @@ const unsigned char C_fe_qm5div8[] = { 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd}; -void monero_ge_fromfe_frombytes(unsigned char *ge, unsigned char *bytes, size_t ge_len, - size_t bytes_len) { +int monero_ge_fromfe_frombytes(unsigned char *ge, unsigned char *bytes, size_t ge_len, + size_t bytes_len) { + int error = 0; #define MOD (unsigned char *)C_ED25519_FIELD, 32 #define fe_isnegative(f) (f[31] & 1) #if 0 @@ -358,71 +369,72 @@ void monero_ge_fromfe_frombytes(unsigned char *ge, unsigned char *bytes, size_t unsigned char sign; if (!ge) { PRINTF("Buffer Error: %s:%d \n", __LINE__); - return; + return SW_WRONG_DATA; } if (ge_len < 32) { PRINTF("Buffer Error: %s:%d \n", __LINE__); - return; + return SW_WRONG_DATA_RANGE; } // cx works in BE monero_reverse32(u, bytes, 32, bytes_len); - cx_math_modm_no_throw(u, 32, (unsigned char *)C_ED25519_FIELD, 32); + error |= cx_math_modm_no_throw(u, 32, (unsigned char *)C_ED25519_FIELD, 32); // go on - cx_math_multm_no_throw(v, u, u, MOD); /* 2 * u^2 */ - cx_math_addm_no_throw(v, v, v, MOD); + error |= cx_math_multm_no_throw(v, u, u, MOD); /* 2 * u^2 */ + error |= cx_math_addm_no_throw(v, v, v, MOD); memset(w, 0, 32); - w[31] = 1; /* w = 1 */ - cx_math_addm_no_throw(w, v, w, MOD); /* w = 2 * u^2 + 1 */ - cx_math_multm_no_throw(x, w, w, MOD); /* w^2 */ - cx_math_multm_no_throw(y, (unsigned char *)C_fe_ma2, v, MOD); /* -2 * A^2 * u^2 */ - cx_math_addm_no_throw(x, x, y, MOD); /* x = w^2 - 2 * A^2 * u^2 */ + w[31] = 1; /* w = 1 */ + error |= cx_math_addm_no_throw(w, v, w, MOD); /* w = 2 * u^2 + 1 */ + error |= cx_math_multm_no_throw(x, w, w, MOD); /* w^2 */ + error |= cx_math_multm_no_throw(y, (unsigned char *)C_fe_ma2, v, MOD); /* -2 * A^2 * u^2 */ + error |= cx_math_addm_no_throw(x, x, y, MOD); /* x = w^2 - 2 * A^2 * u^2 */ // inline fe_divpowm1(r->X, w, x); // (w / x)^(m + 1) => fe_divpowm1(r,u,v) #define _u w #define _v x - cx_math_multm_no_throw(v3, _v, _v, MOD); - cx_math_multm_no_throw(v3, v3, _v, MOD); /* v3 = v^3 */ - cx_math_multm_no_throw(uv7, v3, v3, MOD); - cx_math_multm_no_throw(uv7, uv7, _v, MOD); - cx_math_multm_no_throw(uv7, uv7, _u, MOD); /* uv7 = uv^7 */ - cx_math_powm_no_throw(uv7, uv7, (unsigned char *)C_fe_qm5div8, 32, MOD); /* (uv^7)^((q-5)/8)*/ - cx_math_multm_no_throw(uv7, uv7, v3, MOD); - cx_math_multm_no_throw(rX, uv7, w, MOD); /* u^(m+1)v^(-(m+1)) */ + error |= cx_math_multm_no_throw(v3, _v, _v, MOD); + error |= cx_math_multm_no_throw(v3, v3, _v, MOD); /* v3 = v^3 */ + error |= cx_math_multm_no_throw(uv7, v3, v3, MOD); + error |= cx_math_multm_no_throw(uv7, uv7, _v, MOD); + error |= cx_math_multm_no_throw(uv7, uv7, _u, MOD); /* uv7 = uv^7 */ + error |= cx_math_powm_no_throw(uv7, uv7, (unsigned char *)C_fe_qm5div8, 32, + MOD); /* (uv^7)^((q-5)/8)*/ + error |= cx_math_multm_no_throw(uv7, uv7, v3, MOD); + error |= cx_math_multm_no_throw(rX, uv7, w, MOD); /* u^(m+1)v^(-(m+1)) */ #undef _u #undef _v - cx_math_multm_no_throw(y, rX, rX, MOD); - cx_math_multm_no_throw(x, y, x, MOD); - cx_math_subm_no_throw(y, w, x, MOD); + error |= cx_math_multm_no_throw(y, rX, rX, MOD); + error |= cx_math_multm_no_throw(x, y, x, MOD); + error |= cx_math_subm_no_throw(y, w, x, MOD); memcpy(z, C_fe_ma, 32); if (!cx_math_is_zero(y, 32)) { - cx_math_addm_no_throw(y, w, x, MOD); + error |= cx_math_addm_no_throw(y, w, x, MOD); if (!cx_math_is_zero(y, 32)) { goto negative; } else { - cx_math_multm_no_throw(rX, rX, (unsigned char *)C_fe_fffb1, MOD); + error |= cx_math_multm_no_throw(rX, rX, (unsigned char *)C_fe_fffb1, MOD); } } else { - cx_math_multm_no_throw(rX, rX, (unsigned char *)C_fe_fffb2, MOD); + error |= cx_math_multm_no_throw(rX, rX, (unsigned char *)C_fe_fffb2, MOD); } - cx_math_multm_no_throw(rX, rX, u, MOD); // u * sqrt(2 * A * (A + 2) * w / x) - cx_math_multm_no_throw(z, z, v, MOD); // -2 * A * u^2 + error |= cx_math_multm_no_throw(rX, rX, u, MOD); // u * sqrt(2 * A * (A + 2) * w / x) + error |= cx_math_multm_no_throw(z, z, v, MOD); // -2 * A * u^2 sign = 0; goto setsign; negative: - cx_math_multm_no_throw(x, x, (unsigned char *)C_fe_sqrtm1, MOD); - cx_math_subm_no_throw(y, w, x, MOD); + error |= cx_math_multm_no_throw(x, x, (unsigned char *)C_fe_sqrtm1, MOD); + error |= cx_math_subm_no_throw(y, w, x, MOD); if (!cx_math_is_zero(y, 32)) { - cx_math_addm_no_throw(y, w, x, MOD); - cx_math_multm_no_throw(rX, rX, (unsigned char *)C_fe_fffb3, MOD); + error |= cx_math_addm_no_throw(y, w, x, MOD); + error |= cx_math_multm_no_throw(rX, rX, (unsigned char *)C_fe_fffb3, MOD); } else { - cx_math_multm_no_throw(rX, rX, (unsigned char *)C_fe_fffb4, MOD); + error |= cx_math_multm_no_throw(rX, rX, (unsigned char *)C_fe_fffb4, MOD); } // r->X = sqrt(A * (A + 2) * w / x) // z = -A @@ -430,20 +442,25 @@ void monero_ge_fromfe_frombytes(unsigned char *ge, unsigned char *bytes, size_t setsign: if (fe_isnegative(rX) != sign) { - cx_math_sub(rX, (unsigned char *)C_ED25519_FIELD, rX, 32); + error |= cx_math_sub(rX, (unsigned char *)C_ED25519_FIELD, rX, 32); } - cx_math_addm_no_throw(rZ, z, w, MOD); - cx_math_subm_no_throw(rY, z, w, MOD); - cx_math_multm_no_throw(rX, rX, rZ, MOD); + error |= cx_math_addm_no_throw(rZ, z, w, MOD); + error |= cx_math_subm_no_throw(rY, z, w, MOD); + error |= cx_math_multm_no_throw(rX, rX, rZ, MOD); // back to monero y-affine - cx_math_invprimem_no_throw(u, rZ, MOD); + error |= cx_math_invprimem_no_throw(u, rZ, MOD); Pxy[0] = 0x04; - cx_math_multm_no_throw(&Pxy[1], rX, u, MOD); - cx_math_multm_no_throw(&Pxy[1 + 32], rY, u, MOD); - cx_edwards_compress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + error |= cx_math_multm_no_throw(&Pxy[1], rX, u, MOD); + error |= cx_math_multm_no_throw(&Pxy[1 + 32], rY, u, MOD); + error |= cx_edwards_compress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); memcpy(ge, &Pxy[1], 32); + if (error) { + return SW_SECURITY_INTERNAL; + } + return 0; + #undef u #undef v #undef w @@ -467,28 +484,51 @@ void monero_ge_fromfe_frombytes(unsigned char *ge, unsigned char *bytes, size_t /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_hash_to_scalar(unsigned char *scalar, unsigned char *raw, size_t scalar_len, - unsigned int raw_len) { +int monero_hash_to_scalar(unsigned char *scalar, unsigned char *raw, size_t scalar_len, + unsigned int raw_len) { monero_keccak_F(raw, raw_len, scalar); - monero_reduce(scalar, scalar, scalar_len, scalar_len); + int error = monero_reduce(scalar, scalar, scalar_len, scalar_len); + if (error) { + return error; + } + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_hash_to_ec(unsigned char *ec, unsigned char *ec_pub, size_t ec_len) { +int monero_hash_to_ec(unsigned char *ec, unsigned char *ec_pub, size_t ec_len) { + int error; monero_keccak_F(ec_pub, 32, ec); - monero_ge_fromfe_frombytes(ec, ec, ec_len, ec_len); - monero_ecmul_8(ec, ec, ec_len, ec_len); + + error = monero_ge_fromfe_frombytes(ec, ec, ec_len, ec_len); + if (error) { + return error; + } + + error = monero_ecmul_8(ec, ec, ec_len, ec_len); + if (error) { + return error; + } + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_generate_keypair(unsigned char *ec_pub, unsigned char *ec_priv, size_t ec_pub_len, - size_t ec_priv_len) { - monero_rng_mod_order(ec_priv, ec_priv_len); - monero_ecmul_G(ec_pub, ec_priv, ec_pub_len, ec_priv_len); +int monero_generate_keypair(unsigned char *ec_pub, unsigned char *ec_priv, size_t ec_pub_len, + size_t ec_priv_len) { + int error; + error = monero_rng_mod_order(ec_priv, ec_priv_len); + if (error) { + return error; + } + + error = monero_ecmul_G(ec_pub, ec_priv, ec_pub_len, ec_priv_len); + if (error) { + return error; + } + return 0; } /* ----------------------------------------------------------------------- */ @@ -521,7 +561,10 @@ int monero_derivation_to_scalar(unsigned char *scalar, unsigned char *drv_data, } len_varint += 32; monero_keccak_F(varint, len_varint, varint); - monero_reduce(scalar, varint, scalar_len, sizeof(varint)); + error = monero_reduce(scalar, varint, scalar_len, sizeof(varint)); + if (error) { + return error; + } return 0; } @@ -541,7 +584,10 @@ int monero_derive_secret_key(unsigned char *x, unsigned char *drv_data, unsigned } // generate - monero_addm(x, tmp, ec_priv, x_len, sizeof(tmp), ec_priv_len); + error = monero_addm(x, tmp, ec_priv, x_len, sizeof(tmp), ec_priv_len); + if (error) { + return error; + } return 0; } @@ -559,27 +605,43 @@ int monero_derive_public_key(unsigned char *x, unsigned char *drv_data, unsigned return error; } // generate - monero_ecmul_G(tmp, tmp, sizeof(tmp), sizeof(tmp)); - monero_ecadd(x, tmp, ec_pub, x_len, sizeof(tmp), ec_pub_len); + error = monero_ecmul_G(tmp, tmp, sizeof(tmp), sizeof(tmp)); + if (error) { + return error; + } + + error = monero_ecadd(x, tmp, ec_pub, x_len, sizeof(tmp), ec_pub_len); + if (error) { + return error; + } return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_secret_key_to_public_key(unsigned char *ec_pub, unsigned char *ec_priv, - size_t ec_pub_len, size_t ec_priv_len) { - monero_ecmul_G(ec_pub, ec_priv, ec_pub_len, ec_priv_len); +int monero_secret_key_to_public_key(unsigned char *ec_pub, unsigned char *ec_priv, + size_t ec_pub_len, size_t ec_priv_len) { + return monero_ecmul_G(ec_pub, ec_priv, ec_pub_len, ec_priv_len); } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_generate_key_image(unsigned char *img, unsigned char *P, unsigned char *x, - size_t img_len, size_t x_len) { +int monero_generate_key_image(unsigned char *img, unsigned char *P, unsigned char *x, + size_t img_len, size_t x_len) { unsigned char I[32]; - monero_hash_to_ec(I, P, sizeof(I)); - monero_ecmul_k(img, I, x, img_len, sizeof(I), x_len); + int error; + error = monero_hash_to_ec(I, P, sizeof(I)); + if (error) { + return error; + } + + error = monero_ecmul_k(img, I, x, img_len, sizeof(I), x_len); + if (error) { + return error; + } + return 0; } /* ----------------------------------------------------------------------- */ @@ -610,39 +672,67 @@ int monero_derive_view_tag(unsigned char *view_tag, const unsigned char drv_data /* ----------------------------------------------------------------------- */ /* --- ok --- */ /* ----------------------------------------------------------------------- */ -void monero_derive_subaddress_public_key(unsigned char *x, unsigned char *pub, - unsigned char *drv_data, unsigned int index, size_t x_len, - size_t pub_len, size_t drv_data_len) { +int monero_derive_subaddress_public_key(unsigned char *x, unsigned char *pub, + unsigned char *drv_data, unsigned int index, size_t x_len, + size_t pub_len, size_t drv_data_len) { unsigned char scalarG[32]; + int error; monero_derivation_to_scalar(scalarG, drv_data, index, sizeof(scalarG), drv_data_len); - monero_ecmul_G(scalarG, scalarG, sizeof(scalarG), sizeof(scalarG)); - monero_ecsub(x, pub, scalarG, x_len, pub_len, sizeof(scalarG)); + error = monero_ecmul_G(scalarG, scalarG, sizeof(scalarG), sizeof(scalarG)); + if (error) { + return error; + } + error = monero_ecsub(x, pub, scalarG, x_len, pub_len, sizeof(scalarG)); + if (error) { + return error; + } + return 0; } /* ----------------------------------------------------------------------- */ /* --- ok --- */ /* ----------------------------------------------------------------------- */ -void monero_get_subaddress_spend_public_key(unsigned char *x, unsigned char *index, size_t x_len, - size_t index_len) { +int monero_get_subaddress_spend_public_key(unsigned char *x, unsigned char *index, size_t x_len, + size_t index_len) { + int error; // m = Hs(a || index_major || index_minor) - monero_get_subaddress_secret_key(x, G_monero_vstate.a, index, x_len, sizeof(G_monero_vstate.a), - index_len); + error = monero_get_subaddress_secret_key(x, G_monero_vstate.a, index, x_len, + sizeof(G_monero_vstate.a), index_len); + if (error) { + return error; + } + // M = m*G - monero_secret_key_to_public_key(x, x, x_len, x_len); + error = monero_secret_key_to_public_key(x, x, x_len, x_len); + if (error) { + return error; + } + // D = B + M - monero_ecadd(x, x, G_monero_vstate.B, x_len, x_len, sizeof(G_monero_vstate.B)); + error = monero_ecadd(x, x, G_monero_vstate.B, x_len, x_len, sizeof(G_monero_vstate.B)); + if (error) { + return error; + } + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_get_subaddress(unsigned char *C, unsigned char *D, unsigned char *index, size_t C_len, - size_t D_len, size_t index_len) { +int monero_get_subaddress(unsigned char *C, unsigned char *D, unsigned char *index, size_t C_len, + size_t D_len, size_t index_len) { // retrieve D - monero_get_subaddress_spend_public_key(D, index, D_len, index_len); + int error = monero_get_subaddress_spend_public_key(D, index, D_len, index_len); + if (error) { + return error; + } // C = a*D - monero_ecmul_k(C, D, G_monero_vstate.a, C_len, D_len, sizeof(G_monero_vstate.a)); + error = monero_ecmul_k(C, D, G_monero_vstate.a, C_len, D_len, sizeof(G_monero_vstate.a)); + if (error) { + return error; + } + return 0; } /* ----------------------------------------------------------------------- */ @@ -650,18 +740,18 @@ void monero_get_subaddress(unsigned char *C, unsigned char *D, unsigned char *in /* ----------------------------------------------------------------------- */ static const char C_sub_address_prefix[] = {'S', 'u', 'b', 'A', 'd', 'd', 'r', 0}; -void monero_get_subaddress_secret_key(unsigned char *sub_s, unsigned char *s, unsigned char *index, - size_t sub_s_len, size_t s_len, size_t index_len) { +int monero_get_subaddress_secret_key(unsigned char *sub_s, unsigned char *s, unsigned char *index, + size_t sub_s_len, size_t s_len, size_t index_len) { unsigned char in[sizeof(C_sub_address_prefix) + 32 + 8]; if (!s || s_len < 32) { PRINTF("Buffer Error: %s:%d \n", __LINE__); - return; + return SW_WRONG_DATA_RANGE; } if (!index || index_len < 8) { PRINTF("Buffer Error: %s:%d \n", __LINE__); - return; + return SW_WRONG_DATA_RANGE; } memcpy(in, C_sub_address_prefix, sizeof(C_sub_address_prefix)); @@ -669,7 +759,11 @@ void monero_get_subaddress_secret_key(unsigned char *sub_s, unsigned char *s, un memcpy(in + sizeof(C_sub_address_prefix) + 32, index, 8); // hash_to_scalar with more that 32bytes: monero_keccak_F(in, sizeof(in), sub_s); - monero_reduce(sub_s, sub_s, sub_s_len, sub_s_len); + int error = monero_reduce(sub_s, sub_s, sub_s_len, sub_s_len); + if (error) { + return error; + } + return 0; } /* ======================================================================= */ @@ -683,7 +777,9 @@ unsigned int monero_check_scalar_range_1N(unsigned char *s, size_t s_len) { unsigned char x[32]; monero_reverse32(x, s, sizeof(x), s_len); int diff; - cx_math_cmp_no_throw(x, C_ED25519_ORDER, 32, &diff); + if (cx_math_cmp_no_throw(x, C_ED25519_ORDER, 32, &diff)) { + return SW_SECURITY_INTERNAL; + } if (cx_math_is_zero(x, 32) || diff >= 0) { return SW_WRONG_DATA_RANGE; } @@ -702,183 +798,230 @@ unsigned int monero_check_scalar_not_null(unsigned char *s) { /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_ecmul_G(unsigned char *W, unsigned char *scalar32, size_t W_len, size_t scalar32_len) { +int monero_ecmul_G(unsigned char *W, unsigned char *scalar32, size_t W_len, size_t scalar32_len) { unsigned char Pxy[PXY_SIZE]; unsigned char s[32]; + int error; if (!W || W_len < 32) { PRINTF("Buffer Error: %s:%d \n", __LINE__); - return; + return SW_WRONG_DATA_RANGE; } monero_reverse32(s, scalar32, sizeof(s), scalar32_len); memcpy(Pxy, C_ED25519_G, PXY_SIZE); - cx_ecfp_scalar_mult_no_throw(CX_CURVE_Ed25519, Pxy, s, 32); - cx_edwards_compress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + error = cx_ecfp_scalar_mult_no_throw(CX_CURVE_Ed25519, Pxy, s, 32); + if (error) { + return SW_SECURITY_INTERNAL; + } + error = cx_edwards_compress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + if (error) { + return SW_SECURITY_INTERNAL; + } memcpy(W, &Pxy[1], 32); + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_ecmul_H(unsigned char *W, unsigned char *scalar32, size_t W_len, size_t scalar32_len) { +int monero_ecmul_H(unsigned char *W, unsigned char *scalar32, size_t W_len, size_t scalar32_len) { unsigned char Pxy[PXY_SIZE]; unsigned char s[32]; + int error = 0; + if (!W || W_len < 32) { PRINTF("Buffer Error: %s:%d \n", __LINE__); - return; + return SW_WRONG_DATA_RANGE; } monero_reverse32(s, scalar32, sizeof(s), scalar32_len); Pxy[0] = 0x02; memcpy(&Pxy[1], C_ED25519_Hy, 32); - cx_edwards_decompress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + error |= cx_edwards_decompress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); - cx_ecfp_scalar_mult_no_throw(CX_CURVE_Ed25519, Pxy, s, 32); - cx_edwards_compress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + error |= cx_ecfp_scalar_mult_no_throw(CX_CURVE_Ed25519, Pxy, s, 32); + + error |= cx_edwards_compress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + + if (error) { + return SW_SECURITY_INTERNAL; + } memcpy(W, &Pxy[1], 32); + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_ecmul_k(unsigned char *W, unsigned char *P, unsigned char *scalar32, size_t W_len, - size_t P_len, size_t scalar32_len) { +int monero_ecmul_k(unsigned char *W, unsigned char *P, unsigned char *scalar32, size_t W_len, + size_t P_len, size_t scalar32_len) { unsigned char Pxy[PXY_SIZE]; unsigned char s[32]; + int error = 0; if (!W || W_len < 32) { PRINTF("Buffer Error: %s:%d \n", __LINE__); - return; + return SW_WRONG_DATA_RANGE; } if (!P || P_len < 32) { PRINTF("Buffer Error: %s:%d \n", __LINE__); - return; + return SW_WRONG_DATA_RANGE; } monero_reverse32(s, scalar32, sizeof(s), scalar32_len); Pxy[0] = 0x02; memcpy(&Pxy[1], P, 32); - cx_edwards_decompress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + error |= cx_edwards_decompress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); - cx_ecfp_scalar_mult_no_throw(CX_CURVE_Ed25519, Pxy, s, 32); - cx_edwards_compress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + error |= cx_ecfp_scalar_mult_no_throw(CX_CURVE_Ed25519, Pxy, s, 32); + error |= cx_edwards_compress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + if (error) { + return SW_SECURITY_INTERNAL; + } memcpy(W, &Pxy[1], 32); + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_ecmul_8k(unsigned char *W, unsigned char *P, unsigned char *scalar32, size_t W_len, - size_t P_len, size_t scalar32_len) { +int monero_ecmul_8k(unsigned char *W, unsigned char *P, unsigned char *scalar32, size_t W_len, + size_t P_len, size_t scalar32_len) { unsigned char s[32]; - monero_multm_8(s, scalar32, sizeof(s), scalar32_len); - monero_ecmul_k(W, P, s, W_len, P_len, sizeof(s)); + int error = 0; + error = monero_multm_8(s, scalar32, sizeof(s), scalar32_len); + if (error) { + return error; + } + + error = monero_ecmul_k(W, P, s, W_len, P_len, sizeof(s)); + if (error) { + return error; + } + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_ecmul_8(unsigned char *W, unsigned char *P, size_t W_len, size_t P_len) { +int monero_ecmul_8(unsigned char *W, unsigned char *P, size_t W_len, size_t P_len) { unsigned char Pxy[PXY_SIZE]; + int error = 0; if (!W || W_len < 32) { PRINTF("Buffer Error: %s:%d \n", __LINE__); - return; + return SW_WRONG_DATA_RANGE; } if (!P || P_len < 32) { PRINTF("Buffer Error: %s:%d \n", __LINE__); - return; + return SW_WRONG_DATA_RANGE; } Pxy[0] = 0x02; memcpy(&Pxy[1], P, 32); - cx_edwards_decompress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); - cx_ecfp_add_point_no_throw(CX_CURVE_Ed25519, Pxy, Pxy, Pxy); - cx_ecfp_add_point_no_throw(CX_CURVE_Ed25519, Pxy, Pxy, Pxy); - cx_ecfp_add_point_no_throw(CX_CURVE_Ed25519, Pxy, Pxy, Pxy); - cx_edwards_compress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + error |= cx_edwards_decompress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + error |= cx_ecfp_add_point_no_throw(CX_CURVE_Ed25519, Pxy, Pxy, Pxy); + error |= cx_ecfp_add_point_no_throw(CX_CURVE_Ed25519, Pxy, Pxy, Pxy); + error |= cx_ecfp_add_point_no_throw(CX_CURVE_Ed25519, Pxy, Pxy, Pxy); + error |= cx_edwards_compress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + if (error) { + return SW_SECURITY_INTERNAL; + } memcpy(W, &Pxy[1], 32); + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_ecadd(unsigned char *W, unsigned char *P, unsigned char *Q, size_t W_len, size_t P_len, - size_t Q_len) { +int monero_ecadd(unsigned char *W, unsigned char *P, unsigned char *Q, size_t W_len, size_t P_len, + size_t Q_len) { unsigned char Pxy[PXY_SIZE]; unsigned char Qxy[PXY_SIZE]; + int error = 0; if (!W || W_len < 32) { PRINTF("Buffer Error: %s:%d \n", __LINE__); - return; + return SW_WRONG_DATA_RANGE; } if (!P || P_len < 32) { PRINTF("Buffer Error: %s:%d \n", __LINE__); - return; + return SW_WRONG_DATA_RANGE; } if (!Q || Q_len < 32) { PRINTF("Buffer Error: %s:%d \n", __LINE__); - return; + return SW_WRONG_DATA_RANGE; } Pxy[0] = 0x02; memcpy(&Pxy[1], P, 32); - cx_edwards_decompress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + error |= cx_edwards_decompress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); Qxy[0] = 0x02; memcpy(&Qxy[1], Q, 32); - cx_edwards_decompress_point_no_throw(CX_CURVE_Ed25519, Qxy, sizeof(Qxy)); + error |= cx_edwards_decompress_point_no_throw(CX_CURVE_Ed25519, Qxy, sizeof(Qxy)); - cx_ecfp_add_point_no_throw(CX_CURVE_Ed25519, Pxy, Pxy, Qxy); + error |= cx_ecfp_add_point_no_throw(CX_CURVE_Ed25519, Pxy, Pxy, Qxy); - cx_edwards_compress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + error |= cx_edwards_compress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); memcpy(W, &Pxy[1], 32); + + if (error) { + return SW_SECURITY_INTERNAL; + } + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_ecsub(unsigned char *W, unsigned char *P, unsigned char *Q, size_t W_len, size_t P_len, - size_t Q_len) { +int monero_ecsub(unsigned char *W, unsigned char *P, unsigned char *Q, size_t W_len, size_t P_len, + size_t Q_len) { unsigned char Pxy[PXY_SIZE]; unsigned char Qxy[PXY_SIZE]; + int error = 0; if (!W || W_len < 32) { PRINTF("Buffer Error: %s:%d \n", __LINE__); - return; + return SW_WRONG_DATA_RANGE; } if (!P || P_len < 32) { PRINTF("Buffer Error: %s:%d \n", __LINE__); - return; + return SW_WRONG_DATA_RANGE; } if (!Q || Q_len < 32) { PRINTF("Buffer Error: %s:%d \n", __LINE__); - return; + return SW_WRONG_DATA_RANGE; } Pxy[0] = 0x02; memcpy(&Pxy[1], P, 32); - cx_edwards_decompress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + error |= cx_edwards_decompress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); Qxy[0] = 0x02; memcpy(&Qxy[1], Q, 32); - cx_edwards_decompress_point_no_throw(CX_CURVE_Ed25519, Qxy, sizeof(Qxy)); + error |= cx_edwards_decompress_point_no_throw(CX_CURVE_Ed25519, Qxy, sizeof(Qxy)); cx_math_sub(Qxy + 1, (unsigned char *)C_ED25519_FIELD, Qxy + 1, 32); - cx_ecfp_add_point_no_throw(CX_CURVE_Ed25519, Pxy, Pxy, Qxy); + error |= cx_ecfp_add_point_no_throw(CX_CURVE_Ed25519, Pxy, Pxy, Qxy); - cx_edwards_compress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + error |= cx_edwards_compress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); memcpy(W, &Pxy[1], 32); + + if (error) { + return SW_SECURITY_INTERNAL; + } + return 0; } /* ----------------------------------------------------------------------- */ @@ -922,93 +1065,127 @@ void monero_ecdhHash(unsigned char *x, unsigned char *k, size_t k_len) { return scalar; } */ -void monero_genCommitmentMask(unsigned char *c, unsigned char *sk, size_t c_len, size_t sk_len) { +int monero_genCommitmentMask(unsigned char *c, unsigned char *sk, size_t c_len, size_t sk_len) { unsigned char data[15 + 32]; + int error; if (!sk || sk_len < 32) { PRINTF("Buffer Error: %s:%d \n", __LINE__); - return; + return SW_WRONG_DATA_RANGE; } memcpy(data, "commitment_mask", 15); memcpy(data + 15, sk, 32); - monero_hash_to_scalar(c, data, c_len, 15 + 32); + error = monero_hash_to_scalar(c, data, c_len, 15 + 32); + if (error) { + return error; + } + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_addm(unsigned char *r, unsigned char *a, unsigned char *b, size_t r_len, size_t a_len, - size_t b_len) { +int monero_addm(unsigned char *r, unsigned char *a, unsigned char *b, size_t r_len, size_t a_len, + size_t b_len) { unsigned char ra[32]; unsigned char rb[32]; monero_reverse32(ra, a, sizeof(ra), a_len); monero_reverse32(rb, b, sizeof(rb), b_len); - cx_math_addm_no_throw(r, ra, rb, (unsigned char *)C_ED25519_ORDER, 32); + int error = cx_math_addm_no_throw(r, ra, rb, (unsigned char *)C_ED25519_ORDER, 32); + if (error) { + return SW_SECURITY_INTERNAL; + } + monero_reverse32(r, r, r_len, r_len); + + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_subm(unsigned char *r, unsigned char *a, unsigned char *b, size_t r_len, size_t a_len, - size_t b_len) { +int monero_subm(unsigned char *r, unsigned char *a, unsigned char *b, size_t r_len, size_t a_len, + size_t b_len) { unsigned char ra[32]; unsigned char rb[32]; monero_reverse32(ra, a, sizeof(ra), a_len); monero_reverse32(rb, b, sizeof(rb), b_len); - cx_math_subm_no_throw(r, ra, rb, (unsigned char *)C_ED25519_ORDER, 32); + int error = cx_math_subm_no_throw(r, ra, rb, (unsigned char *)C_ED25519_ORDER, 32); + if (error) { + return SW_SECURITY_INTERNAL; + } + monero_reverse32(r, r, r_len, r_len); + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_multm(unsigned char *r, unsigned char *a, unsigned char *b, size_t r_len, size_t a_len, - size_t b_len) { +int monero_multm(unsigned char *r, unsigned char *a, unsigned char *b, size_t r_len, size_t a_len, + size_t b_len) { unsigned char ra[32]; unsigned char rb[32]; + int error; monero_reverse32(ra, a, sizeof(ra), a_len); monero_reverse32(rb, b, sizeof(rb), b_len); - cx_math_multm_no_throw(r, ra, rb, (unsigned char *)C_ED25519_ORDER, 32); + error = cx_math_multm_no_throw(r, ra, rb, (unsigned char *)C_ED25519_ORDER, 32); + if (error) { + return SW_SECURITY_INTERNAL; + } + monero_reverse32(r, r, r_len, r_len); + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_multm_8(unsigned char *r, unsigned char *a, size_t r_len, size_t a_len) { +int monero_multm_8(unsigned char *r, unsigned char *a, size_t r_len, size_t a_len) { unsigned char ra[32]; unsigned char rb[32]; monero_reverse32(ra, a, sizeof(ra), a_len); memset(rb, 0, 32); rb[31] = 8; - cx_math_multm_no_throw(r, ra, rb, (unsigned char *)C_ED25519_ORDER, 32); + int error = cx_math_multm_no_throw(r, ra, rb, (unsigned char *)C_ED25519_ORDER, 32); + if (error) { + return SW_SECURITY_INTERNAL; + } monero_reverse32(r, r, r_len, r_len); + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_reduce(unsigned char *r, unsigned char *a, size_t r_len, size_t a_len) { +int monero_reduce(unsigned char *r, unsigned char *a, size_t r_len, size_t a_len) { unsigned char ra[32]; monero_reverse32(ra, a, sizeof(ra), a_len); - cx_math_modm_no_throw(ra, 32, (unsigned char *)C_ED25519_ORDER, 32); + int error = cx_math_modm_no_throw(ra, 32, (unsigned char *)C_ED25519_ORDER, 32); + if (error) { + return SW_SECURITY_INTERNAL; + } monero_reverse32(r, ra, r_len, sizeof(ra)); + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_rng_mod_order(unsigned char *r, size_t r_len) { +int monero_rng_mod_order(unsigned char *r, size_t r_len) { unsigned char rnd[32 + 8]; cx_rng(rnd, 32 + 8); - cx_math_modm_no_throw(rnd, 32 + 8, (unsigned char *)C_ED25519_ORDER, 32); + int error = cx_math_modm_no_throw(rnd, 32 + 8, (unsigned char *)C_ED25519_ORDER, 32); + if (error) { + return SW_SECURITY_INTERNAL; + } monero_reverse32(r, rnd + 8, r_len, 32); + return 0; } /* ----------------------------------------------------------------------- */ diff --git a/src/monero_init.c b/src/monero_init.c index 7d9abc3..edfc5c7 100644 --- a/src/monero_init.c +++ b/src/monero_init.c @@ -70,6 +70,7 @@ int monero_init_private_key(void) { unsigned int path[5]; unsigned char seed[64]; unsigned char chain[32]; + int error; // generate account keys @@ -88,11 +89,17 @@ int monero_init_private_key(void) { case KEY_MODE_SEED: monero_keccak_F(seed, 32, G_monero_vstate.b); - monero_reduce(G_monero_vstate.b, G_monero_vstate.b, sizeof(G_monero_vstate.b), - sizeof(G_monero_vstate.b)); + error = monero_reduce(G_monero_vstate.b, G_monero_vstate.b, sizeof(G_monero_vstate.b), + sizeof(G_monero_vstate.b)); + if (error) { + return error; + } monero_keccak_F(G_monero_vstate.b, 32, G_monero_vstate.a); - monero_reduce(G_monero_vstate.a, G_monero_vstate.a, sizeof(G_monero_vstate.a), - sizeof(G_monero_vstate.a)); + error = monero_reduce(G_monero_vstate.a, G_monero_vstate.a, sizeof(G_monero_vstate.a), + sizeof(G_monero_vstate.a)); + if (error) { + return error; + } break; case KEY_MODE_EXTERNAL: @@ -103,16 +110,25 @@ int monero_init_private_key(void) { default: return SW_SECURITY_LOAD_KEY; } - monero_ecmul_G(G_monero_vstate.A, G_monero_vstate.a, sizeof(G_monero_vstate.A), - sizeof(G_monero_vstate.a)); - monero_ecmul_G(G_monero_vstate.B, G_monero_vstate.b, sizeof(G_monero_vstate.B), - sizeof(G_monero_vstate.b)); + error = monero_ecmul_G(G_monero_vstate.A, G_monero_vstate.a, sizeof(G_monero_vstate.A), + sizeof(G_monero_vstate.a)); + if (error) { + return error; + } + error = monero_ecmul_G(G_monero_vstate.B, G_monero_vstate.b, sizeof(G_monero_vstate.B), + sizeof(G_monero_vstate.b)); + if (error) { + return error; + } // generate key protection - int err = monero_aes_derive(&G_monero_vstate.spk, chain, G_monero_vstate.a, G_monero_vstate.b); + error = monero_aes_derive(&G_monero_vstate.spk, chain, G_monero_vstate.a, G_monero_vstate.b); + if (error) { + return error; + } G_monero_vstate.key_set = 1; - return err; + return 0; } /* ----------------------------------------------------------------------- */ diff --git a/src/monero_key.c b/src/monero_key.c index 94b3aa4..99e3b09 100644 --- a/src/monero_key.c +++ b/src/monero_key.c @@ -261,6 +261,7 @@ int monero_apdu_put_key() { unsigned char raw[32]; unsigned char pub[32]; unsigned char sec[32]; + int err; // option + priv/pub view key + priv/pub spend key + base58 address if (G_monero_vstate.io_length != (1 + 32 * 2 + 32 * 2 + 95)) { @@ -270,7 +271,11 @@ int monero_apdu_put_key() { // view key monero_io_fetch(sec, 32); monero_io_fetch(pub, 32); - monero_ecmul_G(raw, sec, sizeof(raw), sizeof(sec)); + err = monero_ecmul_G(raw, sec, sizeof(raw), sizeof(sec)); + if (err) { + return err; + } + if (memcmp(pub, raw, 32) != 0) { return SW_WRONG_DATA; } @@ -279,7 +284,11 @@ int monero_apdu_put_key() { // spend key monero_io_fetch(sec, 32); monero_io_fetch(pub, 32); - monero_ecmul_G(raw, sec, sizeof(raw), sizeof(sec)); + err = monero_ecmul_G(raw, sec, sizeof(raw), sizeof(sec)); + if (err) { + return err; + } + if (memcmp(pub, raw, 32) != 0) { return SW_WRONG_DATA; } @@ -444,7 +453,10 @@ int monero_apdu_sc_add(/*unsigned char *r, unsigned char *s1, unsigned char *s2* return SW_WRONG_DATA; } } - monero_addm(r, s1, s2, sizeof(r), sizeof(s1), sizeof(s2)); + err = monero_addm(r, s1, s2, sizeof(r), sizeof(s1), sizeof(s2)); + if (err) { + return err; + } monero_io_insert_encrypt(r, 32, TYPE_SCALAR); return SW_OK; } @@ -485,7 +497,11 @@ int monero_apdu_scal_mul_base(/*const rct::key &sec, rct::key mulkey*/) { } monero_io_discard(0); - monero_ecmul_G(r, sec, sizeof(r), sizeof(sec)); + err = monero_ecmul_G(r, sec, sizeof(r), sizeof(sec)); + if (err) { + return err; + } + monero_io_insert(r, 32); return SW_OK; } @@ -498,7 +514,10 @@ int monero_apdu_generate_keypair(/*crypto::public_key &pub, crypto::secret_key & unsigned char pub[32]; monero_io_discard(0); - monero_generate_keypair(pub, sec, sizeof(pub), sizeof(sec)); + int error = monero_generate_keypair(pub, sec, sizeof(pub), sizeof(sec)); + if (error) { + return error; + } monero_io_insert(pub, 32); monero_io_insert_encrypt(sec, 32, TYPE_SCALAR); return SW_OK; @@ -518,7 +537,11 @@ int monero_apdu_secret_key_to_public_key( } monero_io_discard(0); // pub - monero_ecmul_G(pub, sec, sizeof(pub), sizeof(sec)); + err = monero_ecmul_G(pub, sec, sizeof(pub), sizeof(sec)); + if (err) { + return err; + } + // pub key monero_io_insert(pub, 32); return SW_OK; @@ -657,7 +680,10 @@ int monero_apdu_generate_key_image( monero_io_discard(0); // pub - monero_generate_key_image(image, pub, sec, sizeof(image), sizeof(sec)); + err = monero_generate_key_image(image, pub, sec, sizeof(image), sizeof(sec)); + if (err) { + return err; + } // pub key monero_io_insert(image, 32); @@ -732,7 +758,10 @@ int monero_apdu_get_subaddress( monero_io_discard(0); // pub - monero_get_subaddress(C, D, index, sizeof(C), sizeof(D), sizeof(index)); + int error = monero_get_subaddress(C, D, index, sizeof(C), sizeof(D), sizeof(index)); + if (error) { + return error; + } // pub key monero_io_insert(C, 32); @@ -753,7 +782,10 @@ int monero_apdu_get_subaddress_spend_public_key( monero_io_discard(1); // pub - monero_get_subaddress_spend_public_key(D, index, sizeof(D), sizeof(index)); + int error = monero_get_subaddress_spend_public_key(D, index, sizeof(D), sizeof(index)); + if (error) { + return error; + } // pub key monero_io_insert(D, 32); @@ -777,8 +809,11 @@ int monero_apdu_get_subaddress_secret_key(/*const crypto::secret_key& sec, const monero_io_fetch(index, 8); monero_io_discard(0); - monero_get_subaddress_secret_key(sub_sec, sec, index, sizeof(sub_sec), sizeof(sec), - sizeof(index)); + err = monero_get_subaddress_secret_key(sub_sec, sec, index, sizeof(sub_sec), sizeof(sec), + sizeof(index)); + if (err) { + return err; + } memcpy(G_monero_vstate.last_get_subaddress_secret_key, sub_sec, 32); monero_io_insert_encrypt(sub_sec, 32, TYPE_SCALAR); @@ -850,8 +885,11 @@ int monero_apu_generate_txout_keys(/*size_t tx_version, crypto::secret_key tx_se monero_ecmul_k(additional_txkey_pub, Bout, additional_txkey_sec, sizeof(additional_txkey_pub), 32, sizeof(additional_txkey_sec)); } else { - monero_ecmul_G(additional_txkey_pub, additional_txkey_sec, sizeof(additional_txkey_pub), - sizeof(additional_txkey_sec)); + err = monero_ecmul_G(additional_txkey_pub, additional_txkey_sec, + sizeof(additional_txkey_pub), sizeof(additional_txkey_sec)); + if (err) { + return err; + } } } else { memset(additional_txkey_pub, 0, 32); diff --git a/src/monero_mlsag.c b/src/monero_mlsag.c index 930c104..b6f7eb7 100644 --- a/src/monero_mlsag.c +++ b/src/monero_mlsag.c @@ -56,20 +56,38 @@ int monero_apdu_mlsag_prepare() { monero_io_discard(1); // ai - monero_rng_mod_order(alpha, sizeof(alpha)); - monero_reduce(alpha, alpha, sizeof(alpha), sizeof(alpha)); + err = monero_rng_mod_order(alpha, sizeof(alpha)); + if (err) { + return err; + } + + err = monero_reduce(alpha, alpha, sizeof(alpha), sizeof(alpha)); + if (err) { + return err; + } + monero_io_insert_encrypt(alpha, 32, TYPE_ALPHA); // ai.G - monero_ecmul_G(mul, alpha, sizeof(mul), sizeof(alpha)); + err = monero_ecmul_G(mul, alpha, sizeof(mul), sizeof(alpha)); + if (err) { + return err; + } + monero_io_insert(mul, 32); if (options) { // ai.Hi - monero_ecmul_k(mul, Hi, alpha, sizeof(mul), sizeof(Hi), sizeof(alpha)); + err = monero_ecmul_k(mul, Hi, alpha, sizeof(mul), sizeof(Hi), sizeof(alpha)); + if (err) { + return err; + } monero_io_insert(mul, 32); // IIi = xin.Hi - monero_ecmul_k(mul, Hi, xin, sizeof(mul), sizeof(Hi), sizeof(xin)); + err = monero_ecmul_k(mul, Hi, xin, sizeof(mul), sizeof(Hi), sizeof(xin)); + if (err) { + return err; + } monero_io_insert(mul, 32); } return SW_OK; @@ -81,6 +99,7 @@ int monero_apdu_mlsag_prepare() { int monero_apdu_mlsag_hash() { unsigned char msg[32]; unsigned char c[32]; + int err; if (G_monero_vstate.io_p2 == 1) { if (monero_keccak_init_H()) { return SW_WRONG_DATA; @@ -94,7 +113,10 @@ int monero_apdu_mlsag_hash() { monero_keccak_update_H(msg, 32); if ((G_monero_vstate.options & 0x80) == 0) { monero_keccak_final_H(c); - monero_reduce(c, c, sizeof(c), sizeof(c)); + err = monero_reduce(c, c, sizeof(c), sizeof(c)); + if (err) { + return err; + } monero_io_insert(c, 32); memcpy(G_monero_vstate.c, c, 32); } @@ -133,12 +155,29 @@ int monero_apdu_mlsag_sign() { return SW_SECURITY_RANGE_VALUE; } - monero_reduce(ss, G_monero_vstate.c, sizeof(ss), sizeof(G_monero_vstate.c)); - monero_reduce(xin, xin, sizeof(xin), sizeof(xin)); - monero_multm(ss, ss, xin, sizeof(ss), sizeof(ss), sizeof(xin)); + err = monero_reduce(ss, G_monero_vstate.c, sizeof(ss), sizeof(G_monero_vstate.c)); + if (err) { + return err; + } - monero_reduce(alpha, alpha, sizeof(alpha), sizeof(alpha)); - monero_subm(ss2, alpha, ss, sizeof(ss2), sizeof(alpha), sizeof(ss)); + err = monero_reduce(xin, xin, sizeof(xin), sizeof(xin)); + if (err) { + return err; + } + + err = monero_multm(ss, ss, xin, sizeof(ss), sizeof(ss), sizeof(xin)); + if (err) { + return err; + } + + err = monero_reduce(alpha, alpha, sizeof(alpha), sizeof(alpha)); + if (err) { + return err; + } + err = monero_subm(ss2, alpha, ss, sizeof(ss2), sizeof(alpha), sizeof(ss)); + if (err) { + return err; + } monero_io_insert(ss2, 32); monero_io_insert_u32(G_monero_vstate.tx_sig_mode); diff --git a/src/monero_open_tx.c b/src/monero_open_tx.c index a279623..02b2b25 100644 --- a/src/monero_open_tx.c +++ b/src/monero_open_tx.c @@ -58,6 +58,7 @@ int monero_apdu_open_tx() { } int monero_apdu_open_tx_cont() { + int error; G_monero_vstate.tx_in_progress = 1; #ifdef DEBUG_HWDEVICE @@ -66,9 +67,16 @@ int monero_apdu_open_tx_cont() { cx_rng(G_monero_vstate.hmac_key, 32); #endif - monero_rng_mod_order(G_monero_vstate.r, sizeof(G_monero_vstate.r)); - monero_ecmul_G(G_monero_vstate.R, G_monero_vstate.r, sizeof(G_monero_vstate.R), - sizeof(G_monero_vstate.r)); + error = monero_rng_mod_order(G_monero_vstate.r, sizeof(G_monero_vstate.r)); + if (error) { + return error; + } + + error = monero_ecmul_G(G_monero_vstate.R, G_monero_vstate.r, sizeof(G_monero_vstate.R), + sizeof(G_monero_vstate.r)); + if (error) { + return error; + } monero_io_insert(G_monero_vstate.R, 32); monero_io_insert_encrypt(G_monero_vstate.r, 32, TYPE_SCALAR); diff --git a/src/monero_prehash.c b/src/monero_prehash.c index ed7ebd1..29f31a5 100644 --- a/src/monero_prehash.c +++ b/src/monero_prehash.c @@ -117,12 +117,27 @@ int monero_apdu_mlsag_prehash_update() { } // check C = aH+kG - monero_unblind(v, k, AKout, G_monero_vstate.options & 0x03, sizeof(v), sizeof(k), - sizeof(AKout)); - monero_ecmul_G(kG, k, sizeof(kG), sizeof(k)); + err = monero_unblind(v, k, AKout, G_monero_vstate.options & 0x03, sizeof(v), sizeof(k), + sizeof(AKout)); + if (err) { + return err; + } + + err = monero_ecmul_G(kG, k, sizeof(kG), sizeof(k)); + if (err) { + return err; + } + if (!cx_math_is_zero(v, 32)) { - monero_ecmul_H(aH, v, sizeof(aH), sizeof(v)); - monero_ecadd(aH, kG, aH, sizeof(aH), sizeof(kG), sizeof(aH)); + err = monero_ecmul_H(aH, v, sizeof(aH), sizeof(v)); + if (err) { + return err; + } + + err = monero_ecadd(aH, kG, aH, sizeof(aH), sizeof(kG), sizeof(aH)); + if (err) { + return err; + } } else { memcpy(aH, kG, 32); } diff --git a/src/monero_proof.c b/src/monero_proof.c index 7f5587e..e00cd44 100644 --- a/src/monero_proof.c +++ b/src/monero_proof.c @@ -58,7 +58,11 @@ int monero_apdu_get_tx_proof() { monero_io_discard(0); // Generate random k - monero_rng_mod_order(k, k_len); + err = monero_rng_mod_order(k, k_len); + if (err) { + return err; + } + // tmp = msg memcpy(G_monero_vstate.tmp + 32 * 0, msg, 32); // tmp = msg || D @@ -66,16 +70,25 @@ int monero_apdu_get_tx_proof() { if (G_monero_vstate.options & 1) { // X = kB - monero_ecmul_k(XY, B, k, sizeof(XY), 32, k_len); + err = monero_ecmul_k(XY, B, k, sizeof(XY), 32, k_len); + if (err) { + return err; + } } else { // X = kG - monero_ecmul_G(XY, k, sizeof(XY), k_len); + err = monero_ecmul_G(XY, k, sizeof(XY), k_len); + if (err) { + return err; + } } // tmp = msg || D || X memcpy(G_monero_vstate.tmp + 32 * 2, XY, 32); // Y = kA - monero_ecmul_k(XY, A, k, sizeof(XY), 32, k_len); + err = monero_ecmul_k(XY, A, k, sizeof(XY), 32, k_len); + if (err) { + return err; + } // tmp = msg || D || X || Y memcpy(G_monero_vstate.tmp + 32 * 3, XY, 32); monero_keccak_H((unsigned char *)"TXPROOF_V2", 10, sep); @@ -89,12 +102,18 @@ int monero_apdu_get_tx_proof() { memcpy(G_monero_vstate.tmp + 32 * 7, B, 32); // sig_c = H_n(tmp) - monero_hash_to_scalar(sig_c, &G_monero_vstate.tmp[0], sizeof(sig_c), 32 * 8); + err = monero_hash_to_scalar(sig_c, &G_monero_vstate.tmp[0], sizeof(sig_c), 32 * 8); + if (err) { + return err; + } // sig_c*r monero_multm(XY, sig_c, r, sizeof(XY), sizeof(sig_c), sizeof(r)); // sig_r = k - sig_c*r - monero_subm(sig_r, k, XY, sizeof(sig_r), k_len, sizeof(r)); + err = monero_subm(sig_r, k, XY, sizeof(sig_r), k_len, sizeof(r)); + if (err) { + return err; + } monero_io_insert(sig_c, 32); monero_io_insert(sig_r, 32);