CVE-2023-41325: Double Free (CWE-415)
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.
CWE description: The product calls free() twice on the same memory address, potentially leading to modification of unexpected memory locations.
CVSS v3 base score: 6.7
Published: 2023-09-15T20:15Z
Repository: https://github.com/OP-TEE/optee_os
Language: C
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 date: 2023-07-04 16:28:43 +0200
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>

Diff: diff --git a/core/crypto/crypto.c b/core/crypto/crypto.c
index 3552887a7..73e27c008 100644
--- a/core/crypto/crypto.c
+++ b/core/crypto/crypto.c
@@ -526,13 +526,13 @@ void crypto_bignum_copy(struct bignum *to __unused,
 			const struct bignum *from __unused)
 {
 	bignum_cant_happen();
 }
 
-void crypto_bignum_free(struct bignum *a)
+void crypto_bignum_free(struct bignum **a)
 {
-	if (a)
+	if (a && *a)
 		panic();
 }
 
 void crypto_bignum_clear(struct bignum *a __unused)
 {
diff --git a/core/drivers/crypto/caam/acipher/caam_dh.c b/core/drivers/crypto/caam/acipher/caam_dh.c
index 6131ff0ef..35fc44541 100644
--- a/core/drivers/crypto/caam/acipher/caam_dh.c
+++ b/core/drivers/crypto/caam/acipher/caam_dh.c
@@ -193,14 +193,14 @@ static TEE_Result do_allocate_keypair(struct dh_keypair *key, size_t size_bits)
 	return TEE_SUCCESS;
 
 err:
 	DH_TRACE("Allocation error");
 
-	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->x);
+	crypto_bignum_free(&key->y);
 
 	return TEE_ERROR_OUT_OF_MEMORY;
 }
 
 /*
diff --git a/core/drivers/crypto/caam/acipher/caam_dsa.c b/core/drivers/crypto/caam/acipher/caam_dsa.c
index 2696f0b3c..d60bb8e89 100644
--- a/core/drivers/crypto/caam/acipher/caam_dsa.c
+++ b/core/drivers/crypto/caam/acipher/caam_dsa.c
@@ -307,14 +307,14 @@ static TEE_Result do_allocate_keypair(struct dsa_keypair *key, size_t l_bits,
 	return TEE_SUCCESS;
 
 err:
 	DSA_TRACE("Allocation error");
 
-	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->x);
 
 	return TEE_ERROR_OUT_OF_MEMORY;
 }
 
 /*
@@ -356,13 +356,13 @@ static TEE_Result do_allocate_publickey(struct dsa_public_key *key,
 	return TEE_SUCCESS;
 
 err:
 	DSA_TRACE("Allocation error");
 
-	crypto_bignum_free(key->g);
-	crypto_bignum_free(key->p);
-	crypto_bignum_free(key->q);
+	crypto_bignum_free(&key->g);
+	crypto_bignum_free(&key->p);
+	crypto_bignum_free(&key->q);
 
 	return TEE_ERROR_OUT_OF_MEMORY;
 }
 
 /*
diff --git a/core/drivers/crypto/caam/acipher/caam_ecc.c b/core/drivers/crypto/caam/acipher/caam_ecc.c
index db4c15ffd..62c113c40 100644
--- a/core/drivers/crypto/caam/acipher/caam_ecc.c
+++ b/core/drivers/crypto/caam/acipher/caam_ecc.c
@@ -169,12 +169,12 @@ static TEE_Result do_allocate_keypair(struct ecc_keypair *key,
 	return TEE_SUCCESS;
 
 err:
 	ECC_TRACE("Allocation error");
 
-	crypto_bignum_free(key->d);
-	crypto_bignum_free(key->x);
+	crypto_bignum_free(&key->d);
+	crypto_bignum_free(&key->x);
 
 	return TEE_ERROR_OUT_OF_MEMORY;
 }
 
 /*
@@ -205,11 +205,11 @@ static TEE_Result do_allocate_publickey(struct ecc_public_key *key,
 	return TEE_SUCCESS;
 
 err:
 	ECC_TRACE("Allocation error");
 
-	crypto_bignum_free(key->x);
+	crypto_bignum_free(&key->x);
 
 	return TEE_ERROR_OUT_OF_MEMORY;
 }
 
 /*
@@ -217,12 +217,12 @@ err:
  *
  * @key  Public Key
  */
 static void do_free_publickey(struct ecc_public_key *key)
 {
-	crypto_bignum_free(key->x);
-	crypto_bignum_free(key->y);
+	crypto_bignum_free(&key->x);
+	crypto_bignum_free(&key->y);
 }
 
 /*
  * Generate ECC keypair
  *
diff --git a/core/drivers/crypto/caam/acipher/caam_rsa.c b/core/drivers/crypto/caam/acipher/caam_rsa.c
index 055ce9d5e..580048b8e 100644
--- a/core/drivers/crypto/caam/acipher/caam_rsa.c
+++ b/core/drivers/crypto/caam/acipher/caam_rsa.c
@@ -84,18 +84,18 @@ static uint8_t caam_era;
  *
  * @key  RSA keypair
  */
 static void do_free_keypair(struct rsa_keypair *key)
 {
-	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->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);
 }
 
 /*
  * Free local caam RSA keypair
  *
@@ -433,12 +433,12 @@ static TEE_Result do_allocate_publickey(struct rsa_public_key *key,
 	return TEE_SUCCESS;
 
 err_alloc_publickey:
 	RSA_TRACE("Allocation error");
 
-	crypto_bignum_free(key->e);
-	crypto_bignum_free(key->n);
+	crypto_bignum_free(&key->e);
+	crypto_bignum_free(&key->n);
 
 	return TEE_ERROR_OUT_OF_MEMORY;
 }
 
 /*
@@ -446,12 +446,12 @@ err_alloc_publickey:
  *
  * @key        Public Key
  */
 static void do_free_publickey(struct rsa_public_key *key)
 {
-	crypto_bignum_free(key->e);
-	crypto_bignum_free(key->n);
+	crypto_bignum_free(&key->e);
+	crypto_bignum_free(&key->n);
 }
 
 /*
  * Output the RSA keypair format 3 additional fields in bignumber object
  *
diff --git a/core/drivers/crypto/se050/core/ecc.c b/core/drivers/crypto/se050/core/ecc.c
index 1d942df9b..c55ab8b2a 100644
--- a/core/drivers/crypto/se050/core/ecc.c
+++ b/core/drivers/crypto/se050/core/ecc.c
@@ -741,13 +741,13 @@ static TEE_Result do_alloc_keypair(struct ecc_keypair *s, uint32_t type,
 		goto err;
 	if (!bn_alloc_max(&s->y))
 		goto err;
 	return TEE_SUCCESS;
 err:
-	crypto_bignum_free(s->d);
-	crypto_bignum_free(s->x);
-	crypto_bignum_free(s->y);
+	crypto_bignum_free(&s->d);
+	crypto_bignum_free(&s->x);
+	crypto_bignum_free(&s->y);
 	return TEE_ERROR_OUT_OF_MEMORY;
 }
 
 static TEE_Result do_alloc_publickey(struct ecc_public_key *s, uint32_t type,
 				     size_t size_bits __unused)
@@ -762,22 +762,22 @@ static TEE_Result do_alloc_publickey(struct ecc_public_key *s, uint32_t type,
 		goto err;
 	if (!bn_alloc_max(&s->y))
 		goto err;
 	return TEE_SUCCESS;
 err:
-	crypto_bignum_free(s->x);
-	crypto_bignum_free(s->y);
+	crypto_bignum_free(&s->x);
+	crypto_bignum_free(&s->y);
 	return TEE_ERROR_OUT_OF_MEMORY;
 }
 
 static void do_free_publickey(struct ecc_public_key *s)
 {
 	if (!s)
 		return;
 
-	crypto_bignum_free(s->x);
-	crypto_bignum_free(s->y);
+	crypto_bignum_free(&s->x);
+	crypto_bignum_free(&s->y);
 }
 
 static struct drvcrypt_ecc driver_ecc = {
 	.alloc_keypair = do_alloc_keypair,
 	.alloc_publickey = do_alloc_publickey,
diff --git a/core/drivers/crypto/se050/core/rsa.c b/core/drivers/crypto/se050/core/rsa.c
index 815abb3cd..475d2b99a 100644
--- a/core/drivers/crypto/se050/core/rsa.c
+++ b/core/drivers/crypto/se050/core/rsa.c
@@ -535,18 +535,18 @@ static TEE_Result do_alloc_keypair(struct rsa_keypair *s,
 	if (!bn_alloc_max(&s->dq))
 		goto err;
 
 	return TEE_SUCCESS;
 err:
-	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->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);
 
 	return TEE_ERROR_OUT_OF_MEMORY;
 }
 
 static TEE_Result do_alloc_publickey(struct rsa_public_key *s,
@@ -554,22 +554,22 @@ static TEE_Result do_alloc_publickey(struct rsa_public_key *s,
 {
 	memset(s, 0, sizeof(*s));
 	if (!bn_alloc_max(&s->e))
 		return TEE_ERROR_OUT_OF_MEMORY;
 	if (!bn_alloc_max(&s->n)) {
-		crypto_bignum_free(s->e);
+		crypto_bignum_free(&s->e);
 		return TEE_ERROR_OUT_OF_MEMORY;
 	}
 
 	return TEE_SUCCESS;
 }
 
 static void do_free_publickey(struct rsa_public_key *s)
 {
 	if (s) {
-		crypto_bignum_free(s->n);
-		crypto_bignum_free(s->e);
+		crypto_bignum_free(&s->n);
+		crypto_bignum_free(&s->e);
 	}
 }
 
 static void do_free_keypair(struct rsa_keypair *s)
 {
@@ -585,18 +585,18 @@ static void do_free_keypair(struct rsa_keypair *s)
 		st = sss_se05x_key_object_get_handle(&k_object, key_id);
 		if (st == kStatus_SSS_Success)
 			sss_se05x_key_store_erase_key(se050_kstore, &k_object);
 	}
 
-	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->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);
 }
 
 static TEE_Result do_gen_keypair(struct rsa_keypair *key, size_t kb)
 {
 	sss_status_t st = kStatus_SSS_Fail;
diff --git a/core/drivers/crypto/versal/ecc.c b/core/drivers/crypto/versal/ecc.c
index ff8ea37e4..64a919e21 100644
--- a/core/drivers/crypto/versal/ecc.c
+++ b/core/drivers/crypto/versal/ecc.c
@@ -269,13 +269,13 @@ static TEE_Result sign(uint32_t algo, struct ecc_keypair *key,
 		return ret;
 	}
 
 	versal_mbox_alloc(bytes, NULL, &k);
 	crypto_bignum_bn2bin_eswap(key->curve, ephemeral.d, k.buf);
-	crypto_bignum_free(ephemeral.d);
-	crypto_bignum_free(ephemeral.x);
-	crypto_bignum_free(ephemeral.y);
+	crypto_bignum_free(&ephemeral.d);
+	crypto_bignum_free(&ephemeral.x);
+	crypto_bignum_free(&ephemeral.y);
 
 	/* Private key*/
 	versal_mbox_alloc(bytes, NULL, &d);
 	crypto_bignum_bn2bin_eswap(key->curve, key->d, d.buf);
 
diff --git a/core/include/crypto/crypto.h b/core/include/crypto/crypto.h
index e9c0eafe9..aa8debe55 100644
--- a/core/include/crypto/crypto.h
+++ b/core/include/crypto/crypto.h
@@ -96,11 +96,11 @@ TEE_Result crypto_bignum_bin2bn(const uint8_t *from, size_t fromsize,
 				struct bignum *to);
 size_t crypto_bignum_num_bytes(struct bignum *a);
 size_t crypto_bignum_num_bits(struct bignum *a);
 void crypto_bignum_bn2bin(const struct bignum *from, uint8_t *to);
 void crypto_bignum_copy(struct bignum *to, const struct bignum *from);
-void crypto_bignum_free(struct bignum *a);
+void crypto_bignum_free(struct bignum **a);
 void crypto_bignum_clear(struct bignum *a);
 
 /* return -1 if a<b, 0 if a==b, +1 if a>b */
 int32_t crypto_bignum_compare(struct bignum *a, struct bignum *b);
 
diff --git a/core/lib/libtomcrypt/dh.c b/core/lib/libtomcrypt/dh.c
index 4eb9916f2..b1d0a4d00 100644
--- a/core/lib/libtomcrypt/dh.c
+++ b/core/lib/libtomcrypt/dh.c
@@ -26,14 +26,14 @@ TEE_Result crypto_acipher_alloc_dh_keypair(struct dh_keypair *s,
 		goto err;
 	if (!bn_alloc_max(&s->q))
 		goto err;
 	return TEE_SUCCESS;
 err:
-	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->y);
+	crypto_bignum_free(&s->x);
 	return TEE_ERROR_OUT_OF_MEMORY;
 }
 
 TEE_Result crypto_acipher_gen_dh_key(struct dh_keypair *key, struct bignum *q,
 				     size_t xbits, size_t key_size)
diff --git a/core/lib/libtomcrypt/dsa.c b/core/lib/libtomcrypt/dsa.c
index a2dc720ed..d6243c469 100644
--- a/core/lib/libtomcrypt/dsa.c
+++ b/core/lib/libtomcrypt/dsa.c
@@ -28,14 +28,14 @@ TEE_Result crypto_acipher_alloc_dsa_keypair(struct dsa_keypair *s,
 		goto err;
 	if (!bn_alloc_max(&s->x))
 		goto err;
 	return TEE_SUCCESS;
 err:
-	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->y);
 	return TEE_ERROR_OUT_OF_MEMORY;
 }
 
 TEE_Result crypto_acipher_alloc_dsa_public_key(struct dsa_public_key *s,
 					       size_t key_size_bits __unused)
@@ -50,13 +50,13 @@ TEE_Result crypto_acipher_alloc_dsa_public_key(struct dsa_public_key *s,
 		goto err;
 	if (!bn_alloc_max(&s->y))
 		goto err;
 	return TEE_SUCCESS;
 err:
-	crypto_bignum_free(s->g);
-	crypto_bignum_free(s->p);
-	crypto_bignum_free(s->q);
+	crypto_bignum_free(&s->g);
+	crypto_bignum_free(&s->p);
+	crypto_bignum_free(&s->q);
 	return TEE_ERROR_OUT_OF_MEMORY;
 }
 
 TEE_Result crypto_acipher_gen_dsa_key(struct dsa_keypair *key, size_t key_size)
 {
diff --git a/core/lib/libtomcrypt/ecc.c b/core/lib/libtomcrypt/ecc.c
index 529b4770e..ac0521270 100644
--- a/core/lib/libtomcrypt/ecc.c
+++ b/core/lib/libtomcrypt/ecc.c
@@ -16,12 +16,12 @@
 static void _ltc_ecc_free_public_key(struct ecc_public_key *s)
 {
 	if (!s)
 		return;
 
-	crypto_bignum_free(s->x);
-	crypto_bignum_free(s->y);
+	crypto_bignum_free(&s->x);
+	crypto_bignum_free(&s->y);
 }
 
 /*
  * For a given TEE @curve, return key size and LTC curve name. Also check that
  * @algo is compatible with this curve.
@@ -458,12 +458,12 @@ TEE_Result crypto_asym_alloc_ecc_keypair(struct ecc_keypair *s,
 	return TEE_SUCCESS;
 
 err:
 	s->ops = NULL;
 
-	crypto_bignum_free(s->d);
-	crypto_bignum_free(s->x);
+	crypto_bignum_free(&s->d);
+	crypto_bignum_free(&s->x);
 
 	return TEE_ERROR_OUT_OF_MEMORY;
 }
 
 const struct crypto_ecc_public_ops*
@@ -534,9 +534,9 @@ TEE_Result crypto_asym_alloc_ecc_public_key(struct ecc_public_key *s,
 	return TEE_SUCCESS;
 
 err:
 	s->ops = NULL;
 
-	crypto_bignum_free(s->x);
+	crypto_bignum_free(&s->x);
 
 	return TEE_ERROR_OUT_OF_MEMORY;
 }
diff --git a/core/lib/libtomcrypt/mpi_desc.c b/core/lib/libtomcrypt/mpi_desc.c
index 235fbe630..ff8dd13c7 100644
--- a/core/lib/libtomcrypt/mpi_desc.c
+++ b/core/lib/libtomcrypt/mpi_desc.c
@@ -761,14 +761,17 @@ struct bignum *crypto_bignum_allocate(size_t size_bits)
 	}
 
 	return (struct bignum *)bn;
 }
 
-void crypto_bignum_free(struct bignum *s)
+void crypto_bignum_free(struct bignum **s)
 {
-	mbedtls_mpi_free((mbedtls_mpi *)s);
-	free(s);
+	assert(s);
+
+	mbedtls_mpi_free((mbedtls_mpi *)*s);
+	free(*s);
+	*s = NULL;
 }
 
 void crypto_bignum_clear(struct bignum *s)
 {
 	mbedtls_mpi *bn = (mbedtls_mpi *)s;
diff --git a/core/lib/libtomcrypt/rsa.c b/core/lib/libtomcrypt/rsa.c
index 22e6d47e0..56a67c4e0 100644
--- a/core/lib/libtomcrypt/rsa.c
+++ b/core/lib/libtomcrypt/rsa.c
@@ -131,11 +131,11 @@ TEE_Result sw_crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s,
 		return TEE_ERROR_OUT_OF_MEMORY;
 	if (!bn_alloc_max(&s->n))
 		goto err;
 	return TEE_SUCCESS;
 err:
-	crypto_bignum_free(s->e);
+	crypto_bignum_free(&s->e);
 	return TEE_ERROR_OUT_OF_MEMORY;
 }
 
 
 void crypto_acipher_free_rsa_public_key(struct rsa_public_key *s)
@@ -143,30 +143,30 @@ __weak __alias("sw_crypto_acipher_free_rsa_public_key");
 
 void sw_crypto_acipher_free_rsa_public_key(struct rsa_public_key *s)
 {
 	if (!s)
 		return;
-	crypto_bignum_free(s->n);
-	crypto_bignum_free(s->e);
+	crypto_bignum_free(&s->n);
+	crypto_bignum_free(&s->e);
 }
 
 
 void crypto_acipher_free_rsa_keypair(struct rsa_keypair *s)
 __weak __alias("sw_crypto_acipher_free_rsa_keypair");
 
 void sw_crypto_acipher_free_rsa_keypair(struct rsa_keypair *s)
 {
 	if (!s)
 		return;
-	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->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);
 }
 
 TEE_Result crypto_acipher_gen_rsa_key(struct rsa_keypair *key,
 				      size_t key_size)
 __weak __alias("sw_crypto_acipher_gen_rsa_key");
diff --git a/core/tee/tee_svc_cryp.c b/core/tee/tee_svc_cryp.c
index 85b095444..cded770cb 100644
--- a/core/tee/tee_svc_cryp.c
+++ b/core/tee/tee_svc_cryp.c
@@ -897,12 +897,11 @@ static void op_attr_bignum_clear(void *attr)
 
 static void op_attr_bignum_free(void *attr)
 {
 	struct bignum **bn = attr;
 
-	crypto_bignum_free(*bn);
-	*bn = NULL;
+	crypto_bignum_free(bn);
 }
 
 static TEE_Result op_attr_value_from_user(void *attr, const void *buffer,
 					  size_t size)
 {
@@ -3555,12 +3554,12 @@ TEE_Result syscall_cryp_derive_key(unsigned long state,
 					      TEE_ATTR_SECRET_VALUE);
 			}
 		} else {
 			res = TEE_ERROR_OUT_OF_MEMORY;
 		}
-		crypto_bignum_free(pub);
-		crypto_bignum_free(ss);
+		crypto_bignum_free(&pub);
+		crypto_bignum_free(&ss);
 	} else if (cs->algo == TEE_ALG_ECDH_DERIVE_SHARED_SECRET) {
 		uint32_t curve = ((struct ecc_keypair *)ko->attr)->curve;
 		struct ecc_public_key key_public = { };
 		uint8_t *pt_secret = NULL;
 		unsigned long pt_secret_len = 0;
diff --git a/lib/libmbedtls/core/bignum.c b/lib/libmbedtls/core/bignum.c
index 61f6c5c60..dea30f61a 100644
--- a/lib/libmbedtls/core/bignum.c
+++ b/lib/libmbedtls/core/bignum.c
@@ -85,14 +85,17 @@ struct bignum *crypto_bignum_allocate(size_t size_bits)
 	}
 
 	return (struct bignum *)bn;
 }
 
-void crypto_bignum_free(struct bignum *s)
+void crypto_bignum_free(struct bignum **s)
 {
-	mbedtls_mpi_free((mbedtls_mpi *)s);
-	free(s);
+	assert(s);
+
+	mbedtls_mpi_free((mbedtls_mpi *)*s);
+	free(*s);
+	*s = NULL;
 }
 
 void crypto_bignum_clear(struct bignum *s)
 {
 	mbedtls_mpi *bn = (mbedtls_mpi *)s;
diff --git a/lib/libmbedtls/core/dh.c b/lib/libmbedtls/core/dh.c
index b3415aaa7..e95aa1495 100644
--- a/lib/libmbedtls/core/dh.c
+++ b/lib/libmbedtls/core/dh.c
@@ -33,14 +33,14 @@ TEE_Result crypto_acipher_alloc_dh_keypair(struct dh_keypair *s,
 	s->q = crypto_bignum_allocate(key_size_bits);
 	if (!s->q)
 		goto err;
 	return TEE_SUCCESS;
 err:
-	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->y);
+	crypto_bignum_free(&s->x);
 	return TEE_ERROR_OUT_OF_MEMORY;
 }
 
 TEE_Result crypto_acipher_gen_dh_key(struct dh_keypair *key,
 				     struct bignum *q __unused,
diff --git a/lib/libmbedtls/core/ecc.c b/lib/libmbedtls/core/ecc.c
index 8ec9f16bc..e70588e92 100644
--- a/lib/libmbedtls/core/ecc.c
+++ b/lib/libmbedtls/core/ecc.c
@@ -38,12 +38,12 @@ static TEE_Result get_tee_result(int lmd_res)
 static void ecc_free_public_key(struct ecc_public_key *s)
 {
 	if (!s)
 		return;
 
-	crypto_bignum_free(s->x);
-	crypto_bignum_free(s->y);
+	crypto_bignum_free(&s->x);
+	crypto_bignum_free(&s->y);
 }
 
 static TEE_Result ecc_get_keysize(uint32_t curve, uint32_t algo,
 				  size_t *key_size_bytes, size_t *key_size_bits)
 {
@@ -459,12 +459,12 @@ TEE_Result crypto_asym_alloc_ecc_keypair(struct ecc_keypair *s,
 		goto err;
 
 	return TEE_SUCCESS;
 
 err:
-	crypto_bignum_free(s->d);
-	crypto_bignum_free(s->x);
+	crypto_bignum_free(&s->d);
+	crypto_bignum_free(&s->x);
 
 	return TEE_ERROR_OUT_OF_MEMORY;
 }
 
 static const struct crypto_ecc_public_ops ecc_public_key_ops = {
@@ -556,9 +556,9 @@ TEE_Result crypto_asym_alloc_ecc_public_key(struct ecc_public_key *s,
 		goto err;
 
 	return TEE_SUCCESS;
 
 err:
-	crypto_bignum_free(s->x);
+	crypto_bignum_free(&s->x);
 
 	return TEE_ERROR_OUT_OF_MEMORY;
 }
diff --git a/lib/libmbedtls/core/rsa.c b/lib/libmbedtls/core/rsa.c
index 99b0290cb..72cc42236 100644
--- a/lib/libmbedtls/core/rsa.c
+++ b/lib/libmbedtls/core/rsa.c
@@ -183,40 +183,40 @@ TEE_Result sw_crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s,
 	s->n = crypto_bignum_allocate(key_size_bits);
 	if (!s->n)
 		goto err;
 	return TEE_SUCCESS;
 err:
-	crypto_bignum_free(s->e);
+	crypto_bignum_free(&s->e);
 	return TEE_ERROR_OUT_OF_MEMORY;
 }
 
 void crypto_acipher_free_rsa_public_key(struct rsa_public_key *s)
 __weak __alias("sw_crypto_acipher_free_rsa_public_key");
 
 void sw_crypto_acipher_free_rsa_public_key(struct rsa_public_key *s)
 {
 	if (!s)
 		return;
-	crypto_bignum_free(s->n);
-	crypto_bignum_free(s->e);
+	crypto_bignum_free(&s->n);
+	crypto_bignum_free(&s->e);
 }
 
 void crypto_acipher_free_rsa_keypair(struct rsa_keypair *s)
 __weak __alias("sw_crypto_acipher_free_rsa_keypair");
 
 void sw_crypto_acipher_free_rsa_keypair(struct rsa_keypair *s)
 {
 	if (!s)
 		return;
-	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->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);
 }
 
 TEE_Result crypto_acipher_gen_rsa_key(struct rsa_keypair *key,
 				      size_t key_size)
 __weak __alias("sw_crypto_acipher_gen_rsa_key");

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);