From c3d0c35040c07574093438771713578c0f39831c Mon Sep 17 00:00:00 2001 From: "Diego F. Aranha" Date: Thu, 8 Aug 2024 12:18:59 +0200 Subject: [PATCH] Add tests for GLV-SAC recoding. --- include/relic_bn.h | 12 ++++++++++++ src/bn/relic_bn_rec.c | 31 +++++++++++++++++++++++-------- src/bn/relic_bn_smb.c | 9 ++++++--- test/test_bn.c | 23 +++++++++++++++++++++++ 4 files changed, 64 insertions(+), 11 deletions(-) diff --git a/include/relic_bn.h b/include/relic_bn.h index 39046483c..bbfa6e740 100644 --- a/include/relic_bn.h +++ b/include/relic_bn.h @@ -1541,6 +1541,18 @@ void bn_rec_glv(bn_t k0, bn_t k1, const bn_t k, const bn_t n, const bn_t v1[], void bn_rec_frb(bn_t *ki, int sub, const bn_t k, const bn_t x, const bn_t n, int cof); +/** + * Recodes subscalars in the signed aligned column representation.. + * + * @param[out] b - the recoded subscalars. + * @param[in] len - the length in bytes of the recoding. + * @param[in] k - the subscalars to recode. + * @param[in] m - the number of subscallars to recode. + * @param[in] n - the elliptic curve group order. + * @throw ERR_NO_BUFFER - if the buffer capacity is insufficient. + */ +void bn_rec_sac(int8_t *b, size_t *len, bn_t *k, size_t m, bn_t n); + /** * Computes the coefficients of the polynomial representing the Lagrange * interpolation for a modulus and a given set of roots. diff --git a/src/bn/relic_bn_rec.c b/src/bn/relic_bn_rec.c index d48b63660..2f8b2c210 100644 --- a/src/bn/relic_bn_rec.c +++ b/src/bn/relic_bn_rec.c @@ -876,16 +876,24 @@ void bn_rec_glv(bn_t k0, bn_t k1, const bn_t k, const bn_t n, const bn_t *v1, } } -void bn_rec_sac(bn_t *b, bn_t *k, size_t m, bn_t n) { +void bn_rec_sac(int8_t *b, size_t *len, bn_t *k, size_t m, bn_t n) { /* Assume k0 is the sign-aligner. */ bn_t *t = RLC_ALLOCA(bn_t, m); size_t l = RLC_CEIL(bn_bits(n), m) + 1; + int8_t bji; if (t == NULL) { RLC_THROW(ERR_NO_MEMORY); return; } + if (*len <= l) { + *len = 0; + RLC_FREE(t); + RLC_THROW(ERR_NO_BUFFER); + return; + } + RLC_TRY { for (size_t i = 0; i < m; i++) { bn_null(t[i]); @@ -893,25 +901,32 @@ void bn_rec_sac(bn_t *b, bn_t *k, size_t m, bn_t n) { bn_copy(t[i], k[i]); } - bn_set_bit(b[0], l - 1, 0); + /* The current basis for BN curves might be one bit longer. */ + for (size_t i = 0; i < m; i++) { + l = RLC_MAX(l, bn_bits(k[i]) + 1); + } + + b[l - 1] = 0; for (size_t i = 0; i < l - 1; i++) { - bn_set_bit(b[0], i, 1 - bn_get_bit(k[0], i + 1)); + b[i] = 1 - bn_get_bit(k[0], i + 1); } for (size_t j = 1; j < m; j++) { - for (size_t i = 0; i < l; i++) { - uint8_t bji = bn_get_bit(t[j], 0); - bn_set_bit(b[j], i, bji); + for (size_t i = 0; i < l - 1; i++) { + bji = bn_get_bit(t[j], 0); + b[j * l + i] = bji; bn_hlv(t[j], t[j]); - bn_add_dig(t[j], t[j], bji & bn_get_bit(b[0], i)); + bn_add_dig(t[j], t[j], bji & b[i]); } + b[j * l + l - 1] = bn_get_bit(t[j], 0); } + *len = l; } RLC_CATCH_ANY { RLC_THROW(ERR_CAUGHT); } RLC_FINALLY { for (size_t i = 0; i < m; i++) { bn_free(t[i]); - RLC_FREE(t); } + RLC_FREE(t); } } diff --git a/src/bn/relic_bn_smb.c b/src/bn/relic_bn_smb.c index 27b4b3698..d1446ae0e 100644 --- a/src/bn/relic_bn_smb.c +++ b/src/bn/relic_bn_smb.c @@ -81,6 +81,7 @@ int bn_smb_jac(const bn_t a, const bn_t b) { dig_t n, d, t; bn_t t0, t1, t2, t3; uint_t z, i, s = (RLC_DIG >> 1) - 2; + int r; bn_null(t0); bn_null(t1); @@ -130,7 +131,8 @@ int bn_smb_jac(const bn_t a, const bn_t b) { n >>= z; } } - return (d == 1 ? 1 - (t & 2) : 0); + r = (d == 1 ? 1 - (t & 2) : 0); + break; } z = RLC_MIN(arch_lzcnt(t0->dp[i - 1]), arch_lzcnt(t1->dp[i - 1])); @@ -200,7 +202,8 @@ int bn_smb_jac(const bn_t a, const bn_t b) { bn_rsh(t0, t3, s); if (bn_is_zero(t0)) { - return (bn_cmp_dig(t1, 1) == RLC_EQ ? 1 - (t & 2) : 0); + r = (bn_cmp_dig(t1, 1) == RLC_EQ ? 1 - (t & 2) : 0); + break; } if (bn_sign(t0) == RLC_NEG) { @@ -222,5 +225,5 @@ int bn_smb_jac(const bn_t a, const bn_t b) { bn_free(t3); } - return t; + return r; } diff --git a/test/test_bn.c b/test/test_bn.c index 4e2f7f574..5ac90f83b 100644 --- a/test/test_bn.c +++ b/test/test_bn.c @@ -2281,6 +2281,29 @@ static int recoding(void) { bn_cmp(a, v2[2]) == RLC_EQ, end); } } TEST_END; + + TEST_CASE("glv-sac recoding is correct") { + size_t l = RLC_BN_BITS; + int8_t ptr[2 * RLC_BN_BITS] = { 0 }; + if (ep_param_set_any_endom() == RLC_OK) { + ep_curve_get_v1(v1); + ep_curve_get_v2(v2); + ep_curve_get_ord(b); + bn_rand_mod(a, b); + bn_rec_glv(b, c, a, b, (const bn_t *)v1, (const bn_t *)v2); + ep_curve_get_ord(v2[0]); + bn_rec_sac(ptr, &l, v1, 2, v2[0]); + if (bn_is_even(b)) { + bn_add_dig(b, b, 1); + } + bn_copy(v1[0], b); + bn_copy(v1[1], c); + for (size_t i = 0; i < l; i++) { + TEST_ASSERT(ptr[i] == 0 || ptr[i] == 1, end); + TEST_ASSERT(ptr[l + i] == 0 || ptr[l + i] == 1, end); + } + } + } TEST_END; #endif /* WITH_EP && EP_ENDOM */ } RLC_CATCH_ANY {