diff --git a/src/modules/bppp/bppp_norm_product_impl.h b/src/modules/bppp/bppp_norm_product_impl.h index 9d61b0d0..ecb758c3 100644 --- a/src/modules/bppp/bppp_norm_product_impl.h +++ b/src/modules/bppp/bppp_norm_product_impl.h @@ -238,9 +238,13 @@ static int secp256k1_bppp_rangeproof_norm_product_prove( ecmult_r_cb_data r_cb_data; size_t g_len = n_vec_len, h_len = l_vec_len; const size_t G_GENS_LEN = g_len; - size_t log_g_len = secp256k1_bppp_log2(g_len), log_h_len = secp256k1_bppp_log2(h_len); - size_t num_rounds = log_g_len > log_h_len ? log_g_len : log_h_len; + size_t log_g_len, log_h_len; + size_t num_rounds; + VERIFY_CHECK(g_len > 0 && h_len > 0); + log_g_len = secp256k1_bppp_log2(g_len); + log_h_len = secp256k1_bppp_log2(h_len); + num_rounds = log_g_len > log_h_len ? log_g_len : log_h_len; /* Check proof sizes.*/ VERIFY_CHECK(*proof_len >= 65 * num_rounds + 64); VERIFY_CHECK(g_vec_len == (n_vec_len + l_vec_len) && l_vec_len == c_vec_len); @@ -440,10 +444,17 @@ static int secp256k1_bppp_rangeproof_norm_product_verify( secp256k1_gej res1, res2; size_t i = 0, scratch_checkpoint; int overflow; - size_t log_g_len = secp256k1_bppp_log2(g_len), log_h_len = secp256k1_bppp_log2(c_vec_len); - size_t n_rounds = log_g_len > log_h_len ? log_g_len : log_h_len; + size_t log_g_len, log_h_len; + size_t n_rounds; size_t h_len = c_vec_len; + if (g_len == 0 || c_vec_len == 0) { + return 0; + } + log_g_len = secp256k1_bppp_log2(g_len); + log_h_len = secp256k1_bppp_log2(c_vec_len); + n_rounds = log_g_len > log_h_len ? log_g_len : log_h_len; + if (g_vec->n != (h_len + g_len) || (proof_len != 65 * n_rounds + 64)) { return 0; } diff --git a/src/modules/bppp/bppp_util.h b/src/modules/bppp/bppp_util.h index 10c58bb7..fd04ae69 100644 --- a/src/modules/bppp/bppp_util.h +++ b/src/modules/bppp/bppp_util.h @@ -45,9 +45,10 @@ static int secp256k1_is_power_of_two(size_t n) { return n > 0 && (n & (n - 1)) == 0; } -/* Compute the log2 of n. If n is not a power of two, it returns the largest - * `k` such that 2^k <= n. Assumes n < 2^64. In Bulletproofs, this is bounded - * by len of input vectors which can be safely assumed to be less than 2^64. +/* Compute the log2 of n. n must NOT be 0. If n is not a power of two, it + * returns the largest `k` such that 2^k <= n. Assumes 0 < n < 2^64. In + * Bulletproofs, this is bounded by len of input vectors which can be safely + * assumed to be less than 2^64. */ static size_t secp256k1_bppp_log2(size_t n) { return 64 - 1 - secp256k1_clz64_var((uint64_t)n); diff --git a/src/modules/bppp/tests_impl.h b/src/modules/bppp/tests_impl.h index ab101fac..e9231656 100644 --- a/src/modules/bppp/tests_impl.h +++ b/src/modules/bppp/tests_impl.h @@ -420,6 +420,24 @@ void norm_arg_zero(void) { secp256k1_bppp_generators_destroy(ctx, gs); } + /* Verify vectors of length 0 */ + { + unsigned int n_vec_len = 1; + unsigned int c_vec_len = 1; + secp256k1_bppp_generators *gs = secp256k1_bppp_generators_create(ctx, n_vec_len + c_vec_len); + size_t plen = sizeof(proof); + random_scalar_order(&n_vec[0]); + random_scalar_order(&c_vec[0]); + random_scalar_order(&l_vec[0]); + CHECK(secp256k1_bppp_commit(ctx, scratch, &commit, gs, n_vec, n_vec_len, l_vec, c_vec_len, c_vec, c_vec_len, &q)); + CHECK(secp256k1_norm_arg_prove(scratch, proof, &plen, &r, gs, n_vec, n_vec_len, l_vec, c_vec_len, c_vec, c_vec_len, &commit)); + CHECK(secp256k1_norm_arg_verify(scratch, proof, plen, &r, gs, n_vec_len, c_vec, c_vec_len, &commit)); + CHECK(!secp256k1_norm_arg_verify(scratch, proof, plen, &r, gs, 0, c_vec, c_vec_len, &commit)); + CHECK(!secp256k1_norm_arg_verify(scratch, proof, plen, &r, gs, n_vec_len, c_vec, 0, &commit)); + + secp256k1_bppp_generators_destroy(ctx, gs); + } + secp256k1_scratch_space_destroy(ctx, scratch); }