CVE-2023-36327 (C, published 2023-09-01T16:15Z)
Description: value: Integer Overflow vulnerability in RELIC before commit 421f2e91cf2ba42473d4d54daf24e295679e290e, allows attackers to execute arbitrary code and cause a denial of service in pos argument in bn_get_prime function.
Severity: nan (CVSS v3 base score: 9.8)
Weakness: CWE-190 \u2014 Integer Overflow or Wraparound
The product performs a calculation that can
         produce an integer overflow or wraparound when the logic
         assumes that the resulting value will always be larger than
         the original value. This occurs when an integer value is
         incremented to a value that is too large to store in the
         associated representation. When this occurs, the value may
         become a very small or negative number.
Repository: https://github.com/relic-toolkit/relic
Files changed:
include/relic_bn.h
include/relic_label.h
src/bn/relic_bn_prime.c
test/test_cp.c
Commit message: Remove dangerous API for returning small primes from an internal table.


Vulnerable code:
/**
 * Returns a small precomputed prime from a given position in the list of prime
 * numbers.
 *
 * @param[in] pos			- the position in the prime sequence.
 * @return a prime if the position is lower than 512, 0 otherwise.
 */
dig_t bn_get_prime(int pos);

#undef bn_get_prime
#define bn_get_prime 	RLC_PREFIX(bn_get_prime)
dig_t bn_get_prime(int pos) {
	if (pos >= BASIC_TESTS) {
		return 0;
	}
	return primes[pos];
}

		result = cp_bdpe_gen(pub, prv, bn_get_prime(47), RLC_BN_BITS);
			in = buf[0] % bn_get_prime(47);
			in = buf[0] % bn_get_prime(47);
			out = (buf[0] % bn_get_prime(47));
			in = (in + out) % bn_get_prime(47);
		TEST_CASE("pairing-based laconic private set intersection is correct") {
			pc_get_ord(q);
			for (int j = 0; j < M; j++) {
				bn_rand_mod(x[j], q);
			}
			for (int j = 0; j < N; j++) {
				bn_rand_mod(y[j], q);
			}
			TEST_ASSERT(cp_pbpsi_gen(q, ss, s, M) == RLC_OK, end);
			TEST_ASSERT(cp_pbpsi_ask(d, r, x, s, M) == RLC_OK, end);
			for (int k = 0; k <= N; k++) {
				for (int j = 0; j < k; j++) {
					bn_copy(y[j], x[j]);
				TEST_ASSERT(cp_pbpsi_ans(t, u, ss, d[0], y, N) == RLC_OK, end);
				TEST_ASSERT(cp_pbpsi_int(z, &l, d, x, M, t, u, N) == RLC_OK,
					end);
				TEST_ASSERT(l == k, end);
			}
		} TEST_END;
	#if defined(WITH_BN) && defined(WITH_PC)
		util_banner("Protocols based on accumulators:\n", 0);
		if (pc_param_set_any() == RLC_OK) {
			if (psi() != RLC_OK) {
				core_clean();
				return 1;
			}
		}
	#endif


Fixed code:
	dig_t prime = 0xFB;
		result = cp_bdpe_gen(pub, prv, prime, RLC_BN_BITS);
			in = buf[0] % prime;
			in = buf[0] % prime;
			out = (buf[0] % prime);
			in = (in + out) % prime;
		if (pc_param_set_any() == RLC_OK) {
			TEST_CASE("pairing-based laconic private set intersection is correct") {
				pc_get_ord(q);
				for (int j = 0; j < M; j++) {
					bn_rand_mod(x[j], q);
				for (int j = 0; j < N; j++) {
					bn_rand_mod(y[j], q);
				}
				TEST_ASSERT(cp_pbpsi_gen(q, ss, s, M) == RLC_OK, end);
				TEST_ASSERT(cp_pbpsi_ask(d, r, x, s, M) == RLC_OK, end);
				for (int k = 0; k <= N; k++) {
					for (int j = 0; j < k; j++) {
						bn_copy(y[j], x[j]);
					}
					TEST_ASSERT(cp_pbpsi_ans(t, u, ss, d[0], y, N) == RLC_OK, end);
					TEST_ASSERT(cp_pbpsi_int(z, &l, d, x, M, t, u, N) == RLC_OK,
						end);
					TEST_ASSERT(l == k, end);
				}
			} TEST_END;
		}
#if defined(WITH_BN) && defined(WITH_PC)
	util_banner("Protocols based on accumulators:\n", 0);
	if (psi() != RLC_OK) {
		core_clean();
		return 1;
	}
#endif