blob: 2ad1efb765749a917b5f681e80d35845e10a70af [file] [log] [blame]
From 00b4f777b377c69f948f5a9d68cbfc8fa8c38a86 Mon Sep 17 00:00:00 2001
From: Julian Hall <julian.hall@arm.com>
Date: Fri, 11 Feb 2022 14:24:53 +0000
Subject: [PATCH] Integrate AEAD operation support
Resolves issues and integrates AEAD support into the crypto service
provider and clients.
Signed-off-by: Julian Hall <julian.hall@arm.com>
Change-Id: I5fbe78a2dd825f592e26fd665f60c18b576f9de9
Upstream-Status: Pending [Not submitted to upstream yet]
Signed-off-by: Emekcan Aras <Emekcan.Aras@arm.com>
---
.../caller/packed-c/crypto_caller_aead.h | 70 +++---
.../client/caller/stub/crypto_caller_aead.h | 12 +-
.../service/crypto/client/psa/psa_aead.c | 221 +++++++++++++++---
.../factory/full/crypto_provider_factory.c | 16 +-
.../component-test/component-test.cmake | 4 +-
deployments/crypto/opteesp/CMakeLists.txt | 4 +-
deployments/libts/linux-pc/CMakeLists.txt | 4 +-
deployments/se-proxy/opteesp/CMakeLists.txt | 4 +-
8 files changed, 263 insertions(+), 72 deletions(-)
diff --git a/components/service/crypto/client/caller/packed-c/crypto_caller_aead.h b/components/service/crypto/client/caller/packed-c/crypto_caller_aead.h
index 3d9947d5..c4ffb20c 100644
--- a/components/service/crypto/client/caller/packed-c/crypto_caller_aead.h
+++ b/components/service/crypto/client/caller/packed-c/crypto_caller_aead.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -20,38 +20,6 @@
extern "C" {
#endif
-static inline psa_status_t crypto_caller_aead_encrypt(struct service_client *context,
- psa_key_id_t key,
- psa_algorithm_t alg,
- const uint8_t *nonce,
- size_t nonce_length,
- const uint8_t *additional_data,
- size_t additional_data_length,
- const uint8_t *plaintext,
- size_t plaintext_length,
- uint8_t *aeadtext,
- size_t aeadtext_size,
- size_t *aeadtext_length)
-{
- return PSA_ERROR_NOT_SUPPORTED;
-}
-
-static inline psa_status_t crypto_caller_aead_decrypt(struct service_client *context,
- psa_key_id_t key,
- psa_algorithm_t alg,
- const uint8_t *nonce,
- size_t nonce_length,
- const uint8_t *additional_data,
- size_t additional_data_length,
- const uint8_t *aeadtext,
- size_t aeadtext_length,
- uint8_t *plaintext,
- size_t plaintext_size,
- size_t *plaintext_length)
-{
- return PSA_ERROR_NOT_SUPPORTED;
-}
-
static inline psa_status_t common_aead_setup(struct service_client *context,
uint32_t *op_handle,
psa_key_id_t key,
@@ -247,7 +215,7 @@ static inline psa_status_t crypto_caller_aead_set_lengths(struct service_client
{
psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
struct ts_crypto_aead_set_lengths_in req_msg;
- size_t req_fixed_len = sizeof(struct ts_crypto_aead_abort_in);
+ size_t req_fixed_len = sizeof(struct ts_crypto_aead_set_lengths_in);
size_t req_len = req_fixed_len;
req_msg.op_handle = op_handle;
@@ -611,6 +579,40 @@ static inline psa_status_t crypto_caller_aead_abort(struct service_client *conte
return psa_status;
}
+/**
+ * The maximum data length that may be carried in an update operation will be
+ * constrained by the maximum call payload capacity imposed by the end-to-end
+ * RPC call path. These functions return the maximum update size when serialization
+ * overheads are considered. This allows large paylaods to be processed in
+ * maximum size chunks.
+ */
+static inline size_t crypto_caller_aead_max_update_ad_size(const struct service_client *context)
+{
+ /* Returns the maximum number of bytes of additional data that may be
+ * carried as a parameter of the aead_update_ad operation
+ * using the packed-c encoding.
+ */
+ size_t payload_space = context->service_info.max_payload;
+ size_t overhead = sizeof(struct ts_crypto_aead_update_ad_in) + TLV_HDR_LEN;
+
+ return (payload_space > overhead) ? payload_space - overhead : 0;
+}
+
+static inline size_t crypto_caller_aead_max_update_size(const struct service_client *context)
+{
+ /* Returns the maximum number of bytes that may be
+ * carried as a parameter of the aead_update operation
+ * using the packed-c encoding.
+ */
+ size_t payload_space = context->service_info.max_payload;
+ size_t overhead = sizeof(struct ts_crypto_aead_update_in) + TLV_HDR_LEN;
+
+ /* Allow for output to be a whole number of blocks */
+ overhead += PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE;
+
+ return (payload_space > overhead) ? payload_space - overhead : 0;
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/components/service/crypto/client/caller/stub/crypto_caller_aead.h b/components/service/crypto/client/caller/stub/crypto_caller_aead.h
index 18aa8cec..455e7ac1 100644
--- a/components/service/crypto/client/caller/stub/crypto_caller_aead.h
+++ b/components/service/crypto/client/caller/stub/crypto_caller_aead.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -135,6 +135,16 @@ static inline psa_status_t crypto_caller_aead_abort(struct service_client *conte
return PSA_ERROR_NOT_SUPPORTED;
}
+static inline size_t crypto_caller_aead_max_update_ad_size(const struct service_client *context)
+{
+ return 0;
+}
+
+static inline size_t crypto_caller_aead_max_update_size(const struct service_client *context)
+{
+ return 0;
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/components/service/crypto/client/psa/psa_aead.c b/components/service/crypto/client/psa/psa_aead.c
index 22fd3da1..e4579e63 100644
--- a/components/service/crypto/client/psa/psa_aead.c
+++ b/components/service/crypto/client/psa/psa_aead.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -8,37 +8,6 @@
#include "psa_crypto_client.h"
#include "crypto_caller_selector.h"
-
-psa_status_t psa_aead_encrypt(psa_key_id_t key,
- psa_algorithm_t alg,
- const uint8_t *nonce,
- size_t nonce_length,
- const uint8_t *additional_data,
- size_t additional_data_length,
- const uint8_t *plaintext,
- size_t plaintext_length,
- uint8_t *aeadtext,
- size_t aeadtext_size,
- size_t *aeadtext_length)
-{
- return PSA_ERROR_NOT_SUPPORTED;
-}
-
-psa_status_t psa_aead_decrypt(psa_key_id_t key,
- psa_algorithm_t alg,
- const uint8_t *nonce,
- size_t nonce_length,
- const uint8_t *additional_data,
- size_t additional_data_length,
- const uint8_t *aeadtext,
- size_t aeadtext_length,
- uint8_t *plaintext,
- size_t plaintext_size,
- size_t *plaintext_length)
-{
- return PSA_ERROR_NOT_SUPPORTED;
-}
-
psa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation,
psa_key_id_t key,
psa_algorithm_t alg)
@@ -143,3 +112,191 @@ psa_status_t psa_aead_abort(psa_aead_operation_t *operation)
return crypto_caller_aead_abort(&psa_crypto_client_instance.base,
operation->handle);
}
+
+static psa_status_t multi_aead_update_ad(psa_aead_operation_t *operation,
+ const uint8_t *input,
+ size_t input_length)
+{
+ psa_status_t psa_status = PSA_SUCCESS;
+ size_t max_update_size =
+ crypto_caller_aead_max_update_ad_size(&psa_crypto_client_instance.base);
+ size_t bytes_input = 0;
+
+ if (!max_update_size) {
+
+ /* Don't know the max update size so assume that the entire
+ * input and output can be handled in a single update. If
+ * this isn't true, the first aead update operation will fail
+ * safely.
+ */
+ max_update_size = input_length;
+ }
+
+ while (bytes_input < input_length) {
+
+ size_t bytes_remaining = input_length - bytes_input;
+ size_t update_len = (bytes_remaining < max_update_size) ?
+ bytes_remaining :
+ max_update_size;
+
+ psa_status = psa_aead_update_ad(operation,
+ &input[bytes_input], update_len);
+
+ if (psa_status != PSA_SUCCESS) break;
+
+ bytes_input += update_len;
+ }
+
+ return psa_status;
+}
+
+static psa_status_t multi_aead_update(psa_aead_operation_t *operation,
+ const uint8_t *input,
+ size_t input_length,
+ uint8_t *output,
+ size_t output_size,
+ size_t *output_length)
+{
+ psa_status_t psa_status = PSA_SUCCESS;
+ size_t max_update_size =
+ crypto_caller_aead_max_update_size(&psa_crypto_client_instance.base);
+ size_t bytes_input = 0;
+ size_t bytes_output = 0;
+
+ *output_length = 0;
+
+ if (!max_update_size) {
+
+ /* Don't know the max update size so assume that the entire
+ * input and output can be handled in a single update. If
+ * this isn't true, the first aead update operation will fail
+ * safely.
+ */
+ max_update_size = input_length;
+ }
+
+ while ((bytes_input < input_length) && (bytes_output < output_size)) {
+
+ size_t update_output_len = 0;
+ size_t bytes_remaining = input_length - bytes_input;
+ size_t update_len = (bytes_remaining < max_update_size) ?
+ bytes_remaining :
+ max_update_size;
+
+ psa_status = psa_aead_update(operation,
+ &input[bytes_input], update_len,
+ &output[bytes_output], output_size - bytes_output, &update_output_len);
+
+ if (psa_status != PSA_SUCCESS) break;
+
+ bytes_input += update_len;
+ bytes_output += update_output_len;
+ }
+
+ if (psa_status == PSA_SUCCESS) {
+
+ *output_length = bytes_output;
+ }
+
+ return psa_status;
+}
+
+psa_status_t psa_aead_encrypt(psa_key_id_t key,
+ psa_algorithm_t alg,
+ const uint8_t *nonce,
+ size_t nonce_length,
+ const uint8_t *additional_data,
+ size_t additional_data_length,
+ const uint8_t *plaintext,
+ size_t plaintext_length,
+ uint8_t *aeadtext,
+ size_t aeadtext_size,
+ size_t *aeadtext_length)
+{
+ psa_aead_operation_t operation = psa_aead_operation_init();
+ size_t bytes_output = 0;
+ *aeadtext_length = 0;
+
+ psa_status_t psa_status = psa_aead_encrypt_setup(&operation, key, alg);
+ if (psa_status != PSA_SUCCESS) return psa_status;
+
+ if ((psa_status = psa_aead_set_lengths(&operation, additional_data_length, plaintext_length),
+ psa_status == PSA_SUCCESS) &&
+ (psa_status = psa_aead_set_nonce(&operation, nonce, nonce_length),
+ psa_status == PSA_SUCCESS) &&
+ (psa_status = multi_aead_update_ad(&operation, additional_data, additional_data_length),
+ psa_status == PSA_SUCCESS) &&
+ (psa_status = multi_aead_update(&operation, plaintext, plaintext_length,
+ aeadtext, aeadtext_size, &bytes_output),
+ psa_status == PSA_SUCCESS))
+ {
+ size_t remaining_aead_len = 0;
+ size_t tag_len = 0;
+
+ psa_status = psa_aead_finish(&operation,
+ NULL, 0, &remaining_aead_len,
+ &aeadtext[bytes_output], aeadtext_size - bytes_output, &tag_len);
+
+ if (psa_status == PSA_SUCCESS) {
+
+ *aeadtext_length = bytes_output + remaining_aead_len + tag_len;
+ }
+ }
+ else {
+
+ psa_aead_abort(&operation);
+ }
+
+ return psa_status;
+}
+
+psa_status_t psa_aead_decrypt(psa_key_id_t key,
+ psa_algorithm_t alg,
+ const uint8_t *nonce,
+ size_t nonce_length,
+ const uint8_t *additional_data,
+ size_t additional_data_length,
+ const uint8_t *aeadtext,
+ size_t aeadtext_length,
+ uint8_t *plaintext,
+ size_t plaintext_size,
+ size_t *plaintext_length)
+{
+ psa_aead_operation_t operation = psa_aead_operation_init();
+ size_t bytes_output = 0;
+ *plaintext_length = 0;
+
+ psa_status_t psa_status = psa_aead_decrypt_setup(&operation, key, alg);
+ if (psa_status != PSA_SUCCESS) return psa_status;
+
+ size_t tag_len = PSA_ALG_AEAD_GET_TAG_LENGTH(alg);
+ size_t ciphertext_len = (aeadtext_length > tag_len) ? aeadtext_length - tag_len : 0;
+
+ if ((psa_status = psa_aead_set_lengths(&operation, additional_data_length, ciphertext_len),
+ psa_status == PSA_SUCCESS) &&
+ (psa_status = psa_aead_set_nonce(&operation, nonce, nonce_length),
+ psa_status == PSA_SUCCESS) &&
+ (psa_status = multi_aead_update_ad(&operation, additional_data, additional_data_length),
+ psa_status == PSA_SUCCESS) &&
+ (psa_status = multi_aead_update(&operation, aeadtext, ciphertext_len,
+ plaintext, plaintext_size, &bytes_output),
+ psa_status == PSA_SUCCESS))
+ {
+ size_t remaining_plaintext_len = 0;
+
+ psa_status = psa_aead_verify(&operation,
+ NULL, 0, &remaining_plaintext_len,
+ &aeadtext[bytes_output], aeadtext_length - bytes_output);
+
+ if (psa_status == PSA_SUCCESS) {
+
+ *plaintext_length = bytes_output + remaining_plaintext_len;
+ }
+ }
+ else {
+
+ psa_aead_abort(&operation);
+ }
+
+ return psa_status;
+}
diff --git a/components/service/crypto/factory/full/crypto_provider_factory.c b/components/service/crypto/factory/full/crypto_provider_factory.c
index 2d926eb6..ee2b4473 100644
--- a/components/service/crypto/factory/full/crypto_provider_factory.c
+++ b/components/service/crypto/factory/full/crypto_provider_factory.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -17,6 +17,8 @@
#include <service/crypto/provider/extension/key_derivation/serializer/packed-c/packedc_key_derivation_provider_serializer.h>
#include <service/crypto/provider/extension/mac/mac_provider.h>
#include <service/crypto/provider/extension/mac/serializer/packed-c/packedc_mac_provider_serializer.h>
+#include <service/crypto/provider/extension/aead/aead_provider.h>
+#include <service/crypto/provider/extension/aead/serializer/packed-c/packedc_aead_provider_serializer.h>
#include <service/discovery/provider/discovery_provider.h>
#include <service/discovery/provider/serializer/packed-c/packedc_discovery_provider_serializer.h>
@@ -34,6 +36,7 @@ static struct full_crypto_provider
struct cipher_provider cipher_provider;
struct key_derivation_provider key_derivation_provider;
struct mac_provider mac_provider;
+ struct aead_provider aead_provider;
} instance;
@@ -98,6 +101,17 @@ struct crypto_provider *crypto_provider_factory_create(void)
crypto_provider_extend(&instance.crypto_provider,
&instance.mac_provider.base_provider);
+ /**
+ * Extend with aead operations
+ */
+ aead_provider_init(&instance.aead_provider);
+
+ aead_provider_register_serializer(&instance.aead_provider,
+ TS_RPC_ENCODING_PACKED_C, packedc_aead_provider_serializer_instance());
+
+ crypto_provider_extend(&instance.crypto_provider,
+ &instance.aead_provider.base_provider);
+
return &instance.crypto_provider;
}
diff --git a/deployments/component-test/component-test.cmake b/deployments/component-test/component-test.cmake
index a0233c34..c3b015ab 100644
--- a/deployments/component-test/component-test.cmake
+++ b/deployments/component-test/component-test.cmake
@@ -1,5 +1,5 @@
#-------------------------------------------------------------------------------
-# Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -85,6 +85,8 @@ add_components(
"components/service/crypto/provider/extension/key_derivation/serializer/packed-c"
"components/service/crypto/provider/extension/mac"
"components/service/crypto/provider/extension/mac/serializer/packed-c"
+ "components/service/crypto/provider/extension/aead"
+ "components/service/crypto/provider/extension/aead/serializer/packed-c"
"components/service/crypto/provider/test"
"components/service/crypto/backend/mbedcrypto"
"components/service/crypto/factory/full"
diff --git a/deployments/crypto/opteesp/CMakeLists.txt b/deployments/crypto/opteesp/CMakeLists.txt
index 8ada74e9..eb5d0847 100644
--- a/deployments/crypto/opteesp/CMakeLists.txt
+++ b/deployments/crypto/opteesp/CMakeLists.txt
@@ -1,5 +1,5 @@
#-------------------------------------------------------------------------------
-# Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -62,6 +62,8 @@ add_components(TARGET "crypto-sp"
"components/service/crypto/provider/extension/key_derivation/serializer/packed-c"
"components/service/crypto/provider/extension/mac"
"components/service/crypto/provider/extension/mac/serializer/packed-c"
+ "components/service/crypto/provider/extension/aead"
+ "components/service/crypto/provider/extension/aead/serializer/packed-c"
"components/service/crypto/factory/full"
"components/service/crypto/backend/mbedcrypto"
"components/service/crypto/backend/mbedcrypto/trng_adapter/platform"
diff --git a/deployments/libts/linux-pc/CMakeLists.txt b/deployments/libts/linux-pc/CMakeLists.txt
index fc98407c..97eaaa73 100644
--- a/deployments/libts/linux-pc/CMakeLists.txt
+++ b/deployments/libts/linux-pc/CMakeLists.txt
@@ -1,5 +1,5 @@
#-------------------------------------------------------------------------------
-# Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -71,6 +71,8 @@ add_components(
"components/service/crypto/provider/extension/key_derivation/serializer/packed-c"
"components/service/crypto/provider/extension/mac"
"components/service/crypto/provider/extension/mac/serializer/packed-c"
+ "components/service/crypto/provider/extension/aead"
+ "components/service/crypto/provider/extension/aead/serializer/packed-c"
"components/service/crypto/factory/full"
"components/service/crypto/backend/mbedcrypto"
"components/service/crypto/backend/mbedcrypto/trng_adapter/linux"
diff --git a/deployments/se-proxy/opteesp/CMakeLists.txt b/deployments/se-proxy/opteesp/CMakeLists.txt
index 953bb716..24a8ca65 100644
--- a/deployments/se-proxy/opteesp/CMakeLists.txt
+++ b/deployments/se-proxy/opteesp/CMakeLists.txt
@@ -1,5 +1,5 @@
#-------------------------------------------------------------------------------
-# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -70,6 +70,8 @@ add_components(TARGET "se-proxy"
"components/service/crypto/provider/extension/key_derivation/serializer/packed-c"
"components/service/crypto/provider/extension/mac"
"components/service/crypto/provider/extension/mac/serializer/packed-c"
+ "components/service/crypto/provider/extension/aead"
+ "components/service/crypto/provider/extension/aead/serializer/packed-c"
"components/service/crypto/factory/full"
"components/service/secure_storage/include"
"components/service/secure_storage/frontend/secure_storage_provider"