CVE-2023-41325 (C, published 2023-09-15T20:15Z)
Description: value: OP-TEE is a Trusted Execution Environment (TEE) designed as companion to a non-secure Linux kernel running on Arm; Cortex-A cores using the TrustZone technology. Starting in version 3.20 and prior to version 3.22, `shdr_verify_signature` can make a double free. `shdr_verify_signature` used to verify a TA binary before it is loaded. To verify a signature of it, allocate a memory for RSA key. RSA key allocate function (`sw_crypto_acipher_alloc_rsa_public_key`) will try to allocate a memory (which is optee’s heap memory). RSA key is consist of exponent and modulus (represent as variable `e`, `n`) and it allocation is not atomic way, so it may succeed in `e` but fail in `n`. In this case sw_crypto_acipher_alloc_rsa_public_key` will free on `e` and return as it is failed but variable ‘e’ is remained as already freed memory address . `shdr_verify_signature` will free again that memory (which is `e`) even it is freed when it failed allocate RSA key. A patch is available in version 3.22. No known workarounds are available.
Severity: nan (CVSS v3 base score: 6.7)
Weakness: CWE-415 \u2014 Double Free
The product calls free() twice on the same memory address, potentially leading to modification of unexpected memory locations.
Repository: https://github.com/OP-TEE/optee_os
Files changed:
core/crypto/crypto.c
core/drivers/crypto/caam/acipher/caam_dh.c
core/drivers/crypto/caam/acipher/caam_dsa.c
core/drivers/crypto/caam/acipher/caam_ecc.c
core/drivers/crypto/caam/acipher/caam_rsa.c
core/drivers/crypto/se050/core/ecc.c
core/drivers/crypto/se050/core/rsa.c
core/drivers/crypto/versal/ecc.c
core/include/crypto/crypto.h
core/lib/libtomcrypt/dh.c
core/lib/libtomcrypt/dsa.c
core/lib/libtomcrypt/ecc.c
core/lib/libtomcrypt/mpi_desc.c
core/lib/libtomcrypt/rsa.c
core/tee/tee_svc_cryp.c
lib/libmbedtls/core/bignum.c
lib/libmbedtls/core/dh.c
lib/libmbedtls/core/ecc.c
lib/libmbedtls/core/rsa.c
Commit message: core: crypto_bignum_free(): add indirection and set pointer to NULL

To prevent human mistake, crypto_bignum_free() sets the location of the
bignum pointer to NULL after freeing it.

Signed-off-by: Jihwan Park <jihwp@amazon.com>
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
Reviewed-by: Jerome Forissier <jerome.forissier@linaro.org>
Reviewed-by: Joakim Bech <joakim.bech@linaro.org>
Reviewed-by: Etienne Carriere <etienne.carriere@foss.st.com>


Vulnerable code:
void crypto_bignum_free(struct bignum *a)
	if (a)
	crypto_bignum_free(key->g);
	crypto_bignum_free(key->p);
	crypto_bignum_free(key->x);
	crypto_bignum_free(key->y);
	crypto_bignum_free(key->g);
	crypto_bignum_free(key->p);
	crypto_bignum_free(key->q);
	crypto_bignum_free(key->x);
	crypto_bignum_free(key->g);
	crypto_bignum_free(key->p);
	crypto_bignum_free(key->q);
	crypto_bignum_free(key->d);
	crypto_bignum_free(key->x);
	crypto_bignum_free(key->x);
	crypto_bignum_free(key->x);
	crypto_bignum_free(key->y);
	crypto_bignum_free(key->e);
	crypto_bignum_free(key->d);
	crypto_bignum_free(key->n);
	crypto_bignum_free(key->p);
	crypto_bignum_free(key->q);
	crypto_bignum_free(key->qp);
	crypto_bignum_free(key->dp);
	crypto_bignum_free(key->dq);
	crypto_bignum_free(key->e);
	crypto_bignum_free(key->n);
	crypto_bignum_free(key->e);
	crypto_bignum_free(key->n);
	crypto_bignum_free(s->d);
	crypto_bignum_free(s->x);
	crypto_bignum_free(s->y);
	crypto_bignum_free(s->x);
	crypto_bignum_free(s->y);
	crypto_bignum_free(s->x);
	crypto_bignum_free(s->y);
	crypto_bignum_free(s->e);
	crypto_bignum_free(s->d);
	crypto_bignum_free(s->n);
	crypto_bignum_free(s->p);
	crypto_bignum_free(s->q);
	crypto_bignum_free(s->qp);
	crypto_bignum_free(s->dp);
	crypto_bignum_free(s->dq);
		crypto_bignum_free(s->e);
		crypto_bignum_free(s->n);
		crypto_bignum_free(s->e);
	crypto_bignum_free(s->e);
	crypto_bignum_free(s->d);
	crypto_bignum_free(s->n);
	crypto_bignum_free(s->p);
	crypto_bignum_free(s->q);
	crypto_bignum_free(s->qp);
	crypto_bignum_free(s->dp);
	crypto_bignum_free(s->dq);
	crypto_bignum_free(ephemeral.d);
	crypto_bignum_free(ephemeral.x);
	crypto_bignum_free(ephemeral.y);
void crypto_bignum_free(struct bignum *a);
	crypto_bignum_free(s->g);
	crypto_bignum_free(s->p);
	crypto_bignum_free(s->y);
	crypto_bignum_free(s->x);
	crypto_bignum_free(s->g);
	crypto_bignum_free(s->p);
	crypto_bignum_free(s->q);
	crypto_bignum_free(s->y);
	crypto_bignum_free(s->g);
	crypto_bignum_free(s->p);
	crypto_bignum_free(s->q);
	crypto_bignum_free(s->x);
	crypto_bignum_free(s->y);
	crypto_bignum_free(s->d);
	crypto_bignum_free(s->x);
	crypto_bignum_free(s->x);
void crypto_bignum_free(struct bignum *s)
	mbedtls_mpi_free((mbedtls_mpi *)s);
	free(s);
	crypto_bignum_free(s->e);
	crypto_bignum_free(s->n);
	crypto_bignum_free(s->e);
	crypto_bignum_free(s->e);
	crypto_bignum_free(s->d);
	crypto_bignum_free(s->n);
	crypto_bignum_free(s->p);
	crypto_bignum_free(s->q);
	crypto_bignum_free(s->qp);
	crypto_bignum_free(s->dp);
	crypto_bignum_free(s->dq);
	crypto_bignum_free(*bn);
	*bn = NULL;
		crypto_bignum_free(pub);
		crypto_bignum_free(ss);
void crypto_bignum_free(struct bignum *s)
	mbedtls_mpi_free((mbedtls_mpi *)s);
	free(s);
	crypto_bignum_free(s->g);
	crypto_bignum_free(s->p);
	crypto_bignum_free(s->y);
	crypto_bignum_free(s->x);
	crypto_bignum_free(s->x);
	crypto_bignum_free(s->y);
	crypto_bignum_free(s->d);
	crypto_bignum_free(s->x);
	crypto_bignum_free(s->x);
	crypto_bignum_free(s->e);
	crypto_bignum_free(s->n);
	crypto_bignum_free(s->e);
	crypto_bignum_free(s->e);
	crypto_bignum_free(s->d);
	crypto_bignum_free(s->n);
	crypto_bignum_free(s->p);
	crypto_bignum_free(s->q);
	crypto_bignum_free(s->qp);
	crypto_bignum_free(s->dp);
	crypto_bignum_free(s->dq);

Fixed code:
void crypto_bignum_free(struct bignum **a)
	if (a && *a)
	crypto_bignum_free(&key->g);
	crypto_bignum_free(&key->p);
	crypto_bignum_free(&key->x);
	crypto_bignum_free(&key->y);
	crypto_bignum_free(&key->g);
	crypto_bignum_free(&key->p);
	crypto_bignum_free(&key->q);
	crypto_bignum_free(&key->x);
	crypto_bignum_free(&key->g);
	crypto_bignum_free(&key->p);
	crypto_bignum_free(&key->q);
	crypto_bignum_free(&key->d);
	crypto_bignum_free(&key->x);
	crypto_bignum_free(&key->x);
	crypto_bignum_free(&key->x);
	crypto_bignum_free(&key->y);
	crypto_bignum_free(&key->e);
	crypto_bignum_free(&key->d);
	crypto_bignum_free(&key->n);
	crypto_bignum_free(&key->p);
	crypto_bignum_free(&key->q);
	crypto_bignum_free(&key->qp);
	crypto_bignum_free(&key->dp);
	crypto_bignum_free(&key->dq);
	crypto_bignum_free(&key->e);
	crypto_bignum_free(&key->n);
	crypto_bignum_free(&key->e);
	crypto_bignum_free(&key->n);
	crypto_bignum_free(&s->d);
	crypto_bignum_free(&s->x);
	crypto_bignum_free(&s->y);
	crypto_bignum_free(&s->x);
	crypto_bignum_free(&s->y);
	crypto_bignum_free(&s->x);
	crypto_bignum_free(&s->y);
	crypto_bignum_free(&s->e);
	crypto_bignum_free(&s->d);
	crypto_bignum_free(&s->n);
	crypto_bignum_free(&s->p);
	crypto_bignum_free(&s->q);
	crypto_bignum_free(&s->qp);
	crypto_bignum_free(&s->dp);
	crypto_bignum_free(&s->dq);
		crypto_bignum_free(&s->e);
		crypto_bignum_free(&s->n);
		crypto_bignum_free(&s->e);
	crypto_bignum_free(&s->e);
	crypto_bignum_free(&s->d);
	crypto_bignum_free(&s->n);
	crypto_bignum_free(&s->p);
	crypto_bignum_free(&s->q);
	crypto_bignum_free(&s->qp);
	crypto_bignum_free(&s->dp);
	crypto_bignum_free(&s->dq);
	crypto_bignum_free(&ephemeral.d);
	crypto_bignum_free(&ephemeral.x);
	crypto_bignum_free(&ephemeral.y);
void crypto_bignum_free(struct bignum **a);
	crypto_bignum_free(&s->g);
	crypto_bignum_free(&s->p);
	crypto_bignum_free(&s->y);
	crypto_bignum_free(&s->x);
	crypto_bignum_free(&s->g);
	crypto_bignum_free(&s->p);
	crypto_bignum_free(&s->q);
	crypto_bignum_free(&s->y);
	crypto_bignum_free(&s->g);
	crypto_bignum_free(&s->p);
	crypto_bignum_free(&s->q);
	crypto_bignum_free(&s->x);
	crypto_bignum_free(&s->y);
	crypto_bignum_free(&s->d);
	crypto_bignum_free(&s->x);
	crypto_bignum_free(&s->x);
void crypto_bignum_free(struct bignum **s)
	assert(s);

	mbedtls_mpi_free((mbedtls_mpi *)*s);
	free(*s);
	*s = NULL;
	crypto_bignum_free(&s->e);
	crypto_bignum_free(&s->n);
	crypto_bignum_free(&s->e);
	crypto_bignum_free(&s->e);
	crypto_bignum_free(&s->d);
	crypto_bignum_free(&s->n);
	crypto_bignum_free(&s->p);
	crypto_bignum_free(&s->q);
	crypto_bignum_free(&s->qp);
	crypto_bignum_free(&s->dp);
	crypto_bignum_free(&s->dq);
	crypto_bignum_free(bn);
		crypto_bignum_free(&pub);
		crypto_bignum_free(&ss);
void crypto_bignum_free(struct bignum **s)
	assert(s);

	mbedtls_mpi_free((mbedtls_mpi *)*s);
	free(*s);
	*s = NULL;
	crypto_bignum_free(&s->g);
	crypto_bignum_free(&s->p);
	crypto_bignum_free(&s->y);
	crypto_bignum_free(&s->x);
	crypto_bignum_free(&s->x);
	crypto_bignum_free(&s->y);
	crypto_bignum_free(&s->d);
	crypto_bignum_free(&s->x);
	crypto_bignum_free(&s->x);
	crypto_bignum_free(&s->e);
	crypto_bignum_free(&s->n);
	crypto_bignum_free(&s->e);
	crypto_bignum_free(&s->e);
	crypto_bignum_free(&s->d);
	crypto_bignum_free(&s->n);
	crypto_bignum_free(&s->p);
	crypto_bignum_free(&s->q);
	crypto_bignum_free(&s->qp);
	crypto_bignum_free(&s->dp);
	crypto_bignum_free(&s->dq);