Crypto: Fix difference between IPC and Library mode
This patch fixes the difference in empty buffer handling between
IPC mode and Library mode. In the IPC mode implementation for Crypto
partition, the function tfm_crypto_call_sfn() reduces the empty
buffers in IOVEC[] from `in_len` and `out_len`. In Library mode,
these empty buffers are still accounted for in `in_len` and
`out_len`. This meant that the generic sanity check within
each Crypto Service API was failing for IPC mode when empty
buffers were passed in by the client.
This patch introduces a macro which validates `in_len` and `out_len`
differently for IPC mode and Library mode. For IPC mode, the lengths
are compared against an expected range of values. For Library mode,
the lengths are validated against a fixed value as expected by the
API.
Signed-off-by: Soby Mathew <soby.mathew@arm.com>
Change-Id: I55e79a31fcf7d16329aa8166fc704455ca01ac20
diff --git a/secure_fw/partitions/crypto/crypto_aead.c b/secure_fw/partitions/crypto/crypto_aead.c
index f663ae6..ebb522f 100644
--- a/secure_fw/partitions/crypto/crypto_aead.c
+++ b/secure_fw/partitions/crypto/crypto_aead.c
@@ -17,6 +17,7 @@
#include "tfm_crypto_api.h"
#include "tfm_crypto_defs.h"
+#include "tfm_crypto_private.h"
/*!
* \defgroup public_psa Public functions, PSA
@@ -34,13 +35,12 @@
#else
psa_status_t status = PSA_SUCCESS;
- if ( !((in_len == 2) || (in_len == 3)) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 3, out_len, 0, 1);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
return PSA_ERROR_CONNECTION_REFUSED;
}
+
const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
const struct tfm_crypto_aead_pack_input *aead_pack_input = &iov->aead_in;
psa_key_handle_t key_handle = iov->key_handle;
@@ -51,16 +51,10 @@
size_t plaintext_length = in_vec[1].len;
uint8_t *ciphertext = out_vec[0].base;
size_t ciphertext_size = out_vec[0].len;
- const uint8_t *additional_data = NULL;
- size_t additional_data_length = 0;
+ const uint8_t *additional_data = in_vec[2].base;
+ size_t additional_data_length = in_vec[2].len;
- /* Check if additional data has been passed and initialise it */
- if (in_len == 3) {
- additional_data = in_vec[2].base;
- additional_data_length = in_vec[2].len;
- }
-
- /* Initialise ciphertext_length to zero */
+ /* Initialise ciphertext_length to zero. */
out_vec[0].len = 0;
status = tfm_crypto_check_handle_owner(key_handle, NULL);
@@ -86,13 +80,12 @@
#else
psa_status_t status = PSA_SUCCESS;
- if ( !((in_len == 2) || (in_len == 3)) || (out_len > 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 3, out_len, 0, 1);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
return PSA_ERROR_CONNECTION_REFUSED;
}
+
const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
const struct tfm_crypto_aead_pack_input *aead_pack_input = &iov->aead_in;
psa_key_handle_t key_handle = iov->key_handle;
@@ -103,16 +96,10 @@
size_t ciphertext_length = in_vec[1].len;
uint8_t *plaintext = out_vec[0].base;
size_t plaintext_size = out_vec[0].len;
- const uint8_t *additional_data = NULL;
- size_t additional_data_length = 0;
+ const uint8_t *additional_data = in_vec[2].base;
+ size_t additional_data_length = in_vec[2].len;
- /* Check if additional data has been passed and initialise it */
- if (in_len == 3) {
- additional_data = in_vec[2].base;
- additional_data_length = in_vec[2].len;
- }
-
- /* Initialise plaintext_length to zero */
+ /* Initialise plaintext_length to zero. */
out_vec[0].len = 0;
status = tfm_crypto_check_handle_owner(key_handle, NULL);
diff --git a/secure_fw/partitions/crypto/crypto_asymmetric.c b/secure_fw/partitions/crypto/crypto_asymmetric.c
index 24bdce0..b001746 100644
--- a/secure_fw/partitions/crypto/crypto_asymmetric.c
+++ b/secure_fw/partitions/crypto/crypto_asymmetric.c
@@ -17,6 +17,7 @@
#include "tfm_crypto_api.h"
#include "tfm_crypto_defs.h"
+#include "tfm_crypto_private.h"
/*!
* \defgroup public_psa Public functions, PSA
@@ -32,15 +33,13 @@
#ifdef TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED
return PSA_ERROR_NOT_SUPPORTED;
#else
- if ((in_len != 2) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 2, out_len, 0, 1);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
return PSA_ERROR_CONNECTION_REFUSED;
}
- const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
+ const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
psa_key_handle_t handle = iov->key_handle;
psa_algorithm_t alg = iov->alg;
const uint8_t *hash = in_vec[1].base;
@@ -66,13 +65,12 @@
#ifdef TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED
return PSA_ERROR_NOT_SUPPORTED;
#else
- if ((in_len != 3) || (out_len != 0)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 3, out_len, 0, 0);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
return PSA_ERROR_CONNECTION_REFUSED;
}
+
const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
psa_key_handle_t handle = iov->key_handle;
@@ -102,32 +100,25 @@
#else
psa_status_t status;
- if (!((in_len == 2) || (in_len == 3)) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 3, out_len, 0, 1);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
return PSA_ERROR_CONNECTION_REFUSED;
}
- const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
+ const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
psa_key_handle_t handle = iov->key_handle;
psa_algorithm_t alg = iov->alg;
const uint8_t *input = in_vec[1].base;
size_t input_length = in_vec[1].len;
- const uint8_t *salt = NULL;
- size_t salt_length = 0;
+ const uint8_t *salt = in_vec[2].base;
+ size_t salt_length = in_vec[2].len;
uint8_t *output = out_vec[0].base;
size_t output_size = out_vec[0].len;
psa_key_type_t type;
size_t key_bits;
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
- if (in_len == 3) {
- salt = in_vec[2].base;
- salt_length = in_vec[2].len;
- }
-
status = tfm_crypto_check_handle_owner(handle, NULL);
if (status != PSA_SUCCESS) {
return status;
@@ -162,9 +153,8 @@
#ifdef TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED
return PSA_ERROR_NOT_SUPPORTED;
#else
- if (!((in_len == 2) || (in_len == 3)) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 3, out_len, 0, 1);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
return PSA_ERROR_CONNECTION_REFUSED;
@@ -175,17 +165,12 @@
psa_algorithm_t alg = iov->alg;
const uint8_t *input = in_vec[1].base;
size_t input_length = in_vec[1].len;
- const uint8_t *salt = NULL;
- size_t salt_length = 0;
+ const uint8_t *salt = in_vec[2].base;
+ size_t salt_length = in_vec[2].len;
uint8_t *output = out_vec[0].base;
size_t output_size = out_vec[0].len;
psa_status_t status;
- if (in_len == 3) {
- salt = in_vec[2].base;
- salt_length = in_vec[2].len;
- }
-
status = tfm_crypto_check_handle_owner(handle, NULL);
if (status != PSA_SUCCESS) {
return status;
diff --git a/secure_fw/partitions/crypto/crypto_cipher.c b/secure_fw/partitions/crypto/crypto_cipher.c
index 85297a8..abaa259 100644
--- a/secure_fw/partitions/crypto/crypto_cipher.c
+++ b/secure_fw/partitions/crypto/crypto_cipher.c
@@ -17,6 +17,7 @@
#include "tfm_crypto_api.h"
#include "tfm_crypto_defs.h"
+#include "tfm_crypto_private.h"
/*!
* \defgroup public_psa Public functions, PSA
@@ -35,9 +36,7 @@
psa_status_t status = PSA_SUCCESS;
psa_cipher_operation_t *operation = NULL;
- if ((in_len != 1) || (out_len != 2)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 1, 2);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
(out_vec[0].len != sizeof(uint32_t))) {
@@ -85,9 +84,7 @@
psa_status_t status = PSA_SUCCESS;
psa_cipher_operation_t *operation = NULL;
- if ((in_len != 2) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 2, out_len, 1, 1);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
(out_vec[0].len != sizeof(uint32_t))) {
@@ -132,9 +129,7 @@
psa_status_t status = PSA_SUCCESS;
psa_cipher_operation_t *operation = NULL;
- if ((in_len != 1) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 1, 1);
if ((out_vec[0].len != sizeof(uint32_t)) ||
(in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
@@ -183,9 +178,7 @@
psa_status_t status = PSA_SUCCESS;
psa_cipher_operation_t *operation = NULL;
- if ((in_len != 1) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 1, 1);
if ((out_vec[0].len != sizeof(uint32_t)) ||
(in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
@@ -234,14 +227,13 @@
psa_status_t status = PSA_SUCCESS;
psa_cipher_operation_t *operation = NULL;
- if ((in_len != 2) || (out_len != 2)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 2, out_len, 1, 2);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
(out_vec[0].len != sizeof(uint32_t))) {
return PSA_ERROR_CONNECTION_REFUSED;
}
+
const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
uint32_t handle = iov->op_handle;
uint32_t *handle_out = out_vec[0].base;
@@ -287,9 +279,7 @@
psa_status_t status = PSA_SUCCESS;
psa_cipher_operation_t *operation = NULL;
- if ((in_len != 1) || (out_len != 2)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 1, 2);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
(out_vec[0].len != sizeof(uint32_t))) {
@@ -339,9 +329,7 @@
psa_status_t status = PSA_SUCCESS;
psa_cipher_operation_t *operation = NULL;
- if ((in_len != 1) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 1, 1);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
(out_vec[0].len != sizeof(uint32_t))) {
diff --git a/secure_fw/partitions/crypto/crypto_hash.c b/secure_fw/partitions/crypto/crypto_hash.c
index 9d5ae46..6a706e8 100644
--- a/secure_fw/partitions/crypto/crypto_hash.c
+++ b/secure_fw/partitions/crypto/crypto_hash.c
@@ -17,6 +17,7 @@
#include "tfm_crypto_api.h"
#include "tfm_crypto_defs.h"
+#include "tfm_crypto_private.h"
/*!
* \defgroup public_psa Public functions, PSA
@@ -35,9 +36,7 @@
psa_status_t status = PSA_SUCCESS;
psa_hash_operation_t *operation = NULL;
- if ((in_len != 1) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 1, 1);
if ((out_vec[0].len != sizeof(uint32_t)) ||
(in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
@@ -83,9 +82,7 @@
psa_status_t status = PSA_SUCCESS;
psa_hash_operation_t *operation = NULL;
- if ((in_len != 2) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 2, out_len, 1, 1);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
(out_vec[0].len != sizeof(uint32_t))) {
@@ -130,9 +127,7 @@
psa_status_t status = PSA_SUCCESS;
psa_hash_operation_t *operation = NULL;
- if ((in_len != 1) || (out_len != 2)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 1, 2);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
(out_vec[0].len != sizeof(uint32_t))) {
@@ -182,9 +177,7 @@
psa_status_t status = PSA_SUCCESS;
psa_hash_operation_t *operation = NULL;
- if ((in_len != 2) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 2, out_len, 1, 1);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
(out_vec[0].len != sizeof(uint32_t))) {
@@ -231,9 +224,7 @@
psa_status_t status = PSA_SUCCESS;
psa_hash_operation_t *operation = NULL;
- if ((in_len != 1) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 1, 1);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
(out_vec[0].len != sizeof(uint32_t))) {
@@ -280,9 +271,7 @@
psa_hash_operation_t *source_operation = NULL;
psa_hash_operation_t *target_operation = NULL;
- if ((in_len != 1) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 1, 1);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
(out_vec[0].len != sizeof(uint32_t))) {
@@ -327,9 +316,8 @@
#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED
return PSA_ERROR_NOT_SUPPORTED;
#else
- if ((in_len != 2) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 2, out_len, 0, 1);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
return PSA_ERROR_CONNECTION_REFUSED;
@@ -357,9 +345,8 @@
#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED
return PSA_ERROR_NOT_SUPPORTED;
#else
- if (in_len != 3) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 3, out_len, 0, 0);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
return PSA_ERROR_CONNECTION_REFUSED;
diff --git a/secure_fw/partitions/crypto/crypto_init.c b/secure_fw/partitions/crypto/crypto_init.c
index 75dfc00..2f90638 100644
--- a/secure_fw/partitions/crypto/crypto_init.c
+++ b/secure_fw/partitions/crypto/crypto_init.c
@@ -115,8 +115,8 @@
{
psa_status_t status = PSA_SUCCESS;
size_t in_len = PSA_MAX_IOVEC, out_len = PSA_MAX_IOVEC, i;
- psa_invec in_vec[PSA_MAX_IOVEC] = { {0} };
- psa_outvec out_vec[PSA_MAX_IOVEC] = { {0} };
+ psa_invec in_vec[PSA_MAX_IOVEC] = { {NULL, 0} };
+ psa_outvec out_vec[PSA_MAX_IOVEC] = { {NULL, 0} };
void *alloc_buf_ptr = NULL;
/* Check the number of in_vec filled */
diff --git a/secure_fw/partitions/crypto/crypto_key.c b/secure_fw/partitions/crypto/crypto_key.c
index ff062ac..caf5387 100644
--- a/secure_fw/partitions/crypto/crypto_key.c
+++ b/secure_fw/partitions/crypto/crypto_key.c
@@ -17,6 +17,7 @@
#include "tfm_crypto_api.h"
#include "tfm_crypto_defs.h"
+#include "tfm_crypto_private.h"
#include <stdbool.h>
#ifndef TFM_CRYPTO_MAX_KEY_HANDLES
@@ -194,9 +195,7 @@
return PSA_ERROR_NOT_SUPPORTED;
#else
- if ((in_len != 3) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 2, 3, out_len, 1, 1);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
(in_vec[1].len != sizeof(struct psa_client_key_attributes_s)) ||
@@ -256,9 +255,8 @@
#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED
return PSA_ERROR_NOT_SUPPORTED;
#else
- if ((in_len != 2) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 2, 2, out_len, 1, 1);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
(in_vec[1].len != sizeof(psa_app_key_id_t)) ||
@@ -313,9 +311,7 @@
#else
(void)out_vec;
- if ((in_len != 1) || (out_len != 0)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 0, 0);
if (in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) {
return PSA_ERROR_CONNECTION_REFUSED;
@@ -352,9 +348,7 @@
#else
(void)out_vec;
- if ((in_len != 1) || (out_len != 0)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 0, 0);
if (in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) {
return PSA_ERROR_CONNECTION_REFUSED;
@@ -389,9 +383,8 @@
#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED
return PSA_ERROR_NOT_SUPPORTED;
#else
- if ((in_len != 1) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 1, 1);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
(out_vec[0].len != sizeof(struct psa_client_key_attributes_s))) {
@@ -428,9 +421,8 @@
#if (TFM_CRYPTO_KEY_MODULE_DISABLED != 0)
return PSA_ERROR_NOT_SUPPORTED;
#else
- if ((in_len != 1) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 1, 1);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
(out_vec[0].len != sizeof(struct psa_client_key_attributes_s))) {
@@ -469,9 +461,8 @@
#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED
return PSA_ERROR_NOT_SUPPORTED;
#else
- if ((in_len != 1) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 0, 1);
if (in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) {
return PSA_ERROR_CONNECTION_REFUSED;
@@ -494,9 +485,8 @@
#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED
return PSA_ERROR_NOT_SUPPORTED;
#else
- if ((in_len != 1) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 0, 1);
if (in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) {
return PSA_ERROR_CONNECTION_REFUSED;
@@ -520,9 +510,7 @@
return PSA_ERROR_NOT_SUPPORTED;
#else
- if ((in_len != 2) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 2, 2, out_len, 1, 1);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
(out_vec[0].len != sizeof(psa_key_handle_t)) ||
@@ -583,9 +571,8 @@
#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED
return PSA_ERROR_NOT_SUPPORTED;
#else
- if ((in_len != 2) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 2, 2, out_len, 1, 1);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
(in_vec[1].len != sizeof(struct psa_client_key_attributes_s)) ||
diff --git a/secure_fw/partitions/crypto/crypto_key_derivation.c b/secure_fw/partitions/crypto/crypto_key_derivation.c
index a4cd862..baeab11 100644
--- a/secure_fw/partitions/crypto/crypto_key_derivation.c
+++ b/secure_fw/partitions/crypto/crypto_key_derivation.c
@@ -23,6 +23,7 @@
#include "tfm_memory_utils.h"
#include "tfm_plat_crypto_keys.h"
+#include "tfm_crypto_private.h"
#ifdef TFM_PARTITION_TEST_PS
#include "psa_manifest/pid.h"
@@ -142,9 +143,7 @@
psa_status_t status = PSA_SUCCESS;
psa_key_derivation_operation_t *operation = NULL;
- if ((in_len != 1) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 1, 1);
if ((out_vec[0].len != sizeof(uint32_t)) ||
(in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
@@ -189,9 +188,8 @@
return PSA_ERROR_NOT_SUPPORTED;
#else
psa_status_t status;
- if ((in_len != 1) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 1, 1);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
(out_vec[0].len != sizeof(size_t))) {
@@ -225,9 +223,8 @@
return PSA_ERROR_NOT_SUPPORTED;
#else
psa_status_t status;
- if ((in_len != 1) || (out_len != 0)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 0, 0);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
return PSA_ERROR_CONNECTION_REFUSED;
@@ -259,9 +256,8 @@
return PSA_ERROR_NOT_SUPPORTED;
#else
psa_status_t status;
- if ((in_len != 2) || (out_len != 0)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 2, out_len, 0, 0);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
return PSA_ERROR_CONNECTION_REFUSED;
@@ -301,9 +297,8 @@
return PSA_ERROR_NOT_SUPPORTED;
#else
psa_status_t status;
- if ((in_len != 1) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 0, 1);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
return PSA_ERROR_CONNECTION_REFUSED;
@@ -336,9 +331,8 @@
return PSA_ERROR_NOT_SUPPORTED;
#else
psa_status_t status;
- if ((in_len != 1) || (out_len != 0)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 0, 0);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
return PSA_ERROR_CONNECTION_REFUSED;
@@ -376,9 +370,8 @@
return PSA_ERROR_NOT_SUPPORTED;
#else
psa_status_t status;
- if ((in_len != 2) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 2, 2, out_len, 1, 1);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
(in_vec[1].len != sizeof(struct psa_client_key_attributes_s)) ||
@@ -444,9 +437,8 @@
return PSA_ERROR_NOT_SUPPORTED;
#else
psa_status_t status;
- if ((in_len != 1) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 1, 1);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
(out_vec[0].len != sizeof(uint32_t))) {
@@ -498,9 +490,8 @@
return PSA_ERROR_NOT_SUPPORTED;
#else
psa_status_t status;
- if ((in_len != 2) || (out_len != 0)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 2, out_len, 0, 0);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
return PSA_ERROR_CONNECTION_REFUSED;
@@ -542,9 +533,8 @@
#ifdef TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED
return PSA_ERROR_NOT_SUPPORTED;
#else
- if ((in_len != 1) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 0, 1);
if (in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) {
return PSA_ERROR_CONNECTION_REFUSED;
@@ -564,9 +554,8 @@
#ifdef TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED
return PSA_ERROR_NOT_SUPPORTED;
#else
- if ((in_len != 2) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 2, out_len, 0, 1);
if (in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) {
return PSA_ERROR_CONNECTION_REFUSED;
diff --git a/secure_fw/partitions/crypto/crypto_mac.c b/secure_fw/partitions/crypto/crypto_mac.c
index df42ac4..5ab9d46 100644
--- a/secure_fw/partitions/crypto/crypto_mac.c
+++ b/secure_fw/partitions/crypto/crypto_mac.c
@@ -17,6 +17,7 @@
#include "tfm_crypto_api.h"
#include "tfm_crypto_defs.h"
+#include "tfm_crypto_private.h"
/*!
* \defgroup public_psa Public functions, PSA
@@ -35,9 +36,7 @@
psa_status_t status = PSA_SUCCESS;
psa_mac_operation_t *operation = NULL;
- if ((in_len != 1) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 1, 1);
if ((out_vec[0].len != sizeof(uint32_t)) ||
(in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
@@ -89,9 +88,7 @@
psa_status_t status = PSA_SUCCESS;
psa_mac_operation_t *operation = NULL;
- if ((in_len != 1) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 1, 1);
if ((out_vec[0].len != sizeof(uint32_t)) ||
(in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
@@ -143,9 +140,7 @@
psa_status_t status = PSA_SUCCESS;
psa_mac_operation_t *operation = NULL;
- if ((in_len != 2) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 2, out_len, 1, 1);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
(out_vec[0].len != sizeof(uint32_t))) {
@@ -190,9 +185,7 @@
psa_status_t status = PSA_SUCCESS;
psa_mac_operation_t *operation = NULL;
- if ((in_len != 1) || (out_len != 2)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 1, 2);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
(out_vec[0].len != sizeof(uint32_t))) {
@@ -242,9 +235,7 @@
psa_status_t status = PSA_SUCCESS;
psa_mac_operation_t *operation = NULL;
- if ((in_len != 2) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 2, out_len, 1, 1);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
(out_vec[0].len != sizeof(uint32_t))) {
@@ -291,9 +282,7 @@
psa_status_t status = PSA_SUCCESS;
psa_mac_operation_t *operation = NULL;
- if ((in_len != 1) || (out_len != 1)) {
- return PSA_ERROR_CONNECTION_REFUSED;
- }
+ CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 1, 1);
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
(out_vec[0].len != sizeof(uint32_t))) {
diff --git a/secure_fw/partitions/crypto/tfm_crypto_private.h b/secure_fw/partitions/crypto/tfm_crypto_private.h
new file mode 100644
index 0000000..e3ec377
--- /dev/null
+++ b/secure_fw/partitions/crypto/tfm_crypto_private.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_CRYPTO_PRIVATE_H__
+#define __TFM_CRYPTO_PRIVATE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef TFM_PSA_API
+/*
+ * Validate the IOVEC[] lengths for IPC model. The tfm_crypto_call_sfn()
+ * reduces the entries in IOVEC[] which are empty from `in_len` and `out_len`.
+ * This means that Crypto service APIs need to ensure that the `in_len`
+ * and `out_len` are within the expected range.
+ *
+ * Also tfm_crypto_call_sfn() ensures that all entries in IOVEC[] are
+ * initialised. Hence all entries in IOVEC[] can be accessed to
+ * initialize internal variables even if they are outside `in_len`
+ * and `out_len`.
+ */
+#define CRYPTO_IN_OUT_LEN_VALIDATE(in_len, in_min, in_max, out_len, out_min, out_max) \
+ if (!(((in_len) >= (in_min)) && ((in_len) <= (in_max))) || \
+ !(((out_len) >= (out_min)) && ((out_len) <= (out_max)))) { \
+ return PSA_ERROR_PROGRAMMER_ERROR; \
+ }
+#else
+/*
+ * Validate the IOVEC[] lengths for Library model. Unlike the IPC model, the
+ * service APIs expects to receive the exact of `in_len` and `out_len`
+ * as expected by the API.
+ */
+#define CRYPTO_IN_OUT_LEN_VALIDATE(in_len, in_min, in_max, out_len, out_min, out_max) \
+ if (((in_len) != (in_max)) || ((out_len) != (out_max))) { \
+ return PSA_ERROR_PROGRAMMER_ERROR; \
+ }
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TFM_CRYPTO_PRIVATE_H__ */