diff --git a/api-tests/dev_apis/crypto/test_c081/test.cmake b/api-tests/dev_apis/crypto/test_c081/test.cmake new file mode 100644 index 00000000..e055551d --- /dev/null +++ b/api-tests/dev_apis/crypto/test_c081/test.cmake @@ -0,0 +1,24 @@ +#/** @file +# * Copyright (c) 2026, Arm Limited or its affiliates. All rights reserved. +# * SPDX-License-Identifier : Apache-2.0 +# * +# * Licensed under the Apache License, Version 2.0 (the "License"); +# * you may not use this file except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.apache.org/licenses/LICENSE-2.0 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +#**/ + +list(APPEND CC_SOURCE + test_entry_c081.c + test_c081.c +) +list(APPEND CC_OPTIONS ) +list(APPEND AS_SOURCE ) +list(APPEND AS_OPTIONS ) diff --git a/api-tests/dev_apis/crypto/test_c081/test_c081.c b/api-tests/dev_apis/crypto/test_c081/test_c081.c new file mode 100644 index 00000000..d0aadd90 --- /dev/null +++ b/api-tests/dev_apis/crypto/test_c081/test_c081.c @@ -0,0 +1,102 @@ +/** @file + * Copyright (c) 2026, Arm Limited or its affiliates. All rights reserved. + * SPDX-License-Identifier : Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +**/ + +#include "val_interfaces.h" +#include "test_c081.h" +#include "test_data.h" + +const client_test_t test_c081_crypto_list[] = { + NULL, + psa_hash_parallel_capacity_test, + NULL, +}; + +static uint32_t g_test_count = 1; + +int32_t psa_hash_parallel_capacity_test(caller_security_t caller __UNUSED) +{ +#if defined(ARCH_TEST_SHA256) && defined(ARCH_TEST_MAX_PARALLEL_HASH_OPS) && \ + defined(ARCH_TEST_PARALLEL_HASH_OPS_FAILURE_STATUS) + int32_t status; + int32_t i; + size_t op_index; + int32_t num_checks = sizeof(check1) / sizeof(check1[0]); + psa_hash_operation_t operations[ARCH_TEST_MAX_PARALLEL_HASH_OPS]; + psa_hash_operation_t extra_operation = PSA_HASH_OPERATION_INIT; + + if (num_checks == 0) + { + val->print(TEST, "No test available for the selected crypto configuration\n", 0); + return RESULT_SKIP(VAL_STATUS_NO_TESTS); + } + + status = val->crypto_function(VAL_CRYPTO_INIT); + TEST_ASSERT_EQUAL(status, PSA_SUCCESS, TEST_CHECKPOINT_NUM(1)); + + for (i = 0; i < num_checks; i++) + { + val->print(TEST, "Check %d: ", g_test_count++); + val->print(TEST, check1[i].test_desc, check1[i].max_parallel_ops); + + status = val->wd_reprogram_timer(WD_CRYPTO_TIMEOUT); + TEST_ASSERT_EQUAL(status, VAL_STATUS_SUCCESS, TEST_CHECKPOINT_NUM(2)); + + for (op_index = 0; op_index < check1[i].max_parallel_ops; op_index++) + { + val->crypto_function(VAL_CRYPTO_HASH_OPERATION_INIT, + &operations[op_index]); + status = val->crypto_function(VAL_CRYPTO_HASH_SETUP, + &operations[op_index], + check1[i].alg); + TEST_ASSERT_EQUAL(status, PSA_SUCCESS, TEST_CHECKPOINT_NUM(3)); + } + + val->crypto_function(VAL_CRYPTO_HASH_OPERATION_INIT, + &extra_operation); + status = val->crypto_function(VAL_CRYPTO_HASH_SETUP, + &extra_operation, + check1[i].alg); + TEST_ASSERT_EQUAL(status, check1[i].expected_failure_status, + TEST_CHECKPOINT_NUM(4)); + + status = val->crypto_function(VAL_CRYPTO_HASH_ABORT, + &extra_operation); + TEST_ASSERT_EQUAL(status, PSA_SUCCESS, TEST_CHECKPOINT_NUM(5)); + + for (op_index = 0; op_index < check1[i].max_parallel_ops; op_index++) + { + status = val->crypto_function(VAL_CRYPTO_HASH_ABORT, + &operations[op_index]); + TEST_ASSERT_EQUAL(status, PSA_SUCCESS, TEST_CHECKPOINT_NUM(6)); + } + + status = val->crypto_function(VAL_CRYPTO_HASH_SETUP, + &extra_operation, + check1[i].alg); + TEST_ASSERT_EQUAL(status, PSA_SUCCESS, TEST_CHECKPOINT_NUM(7)); + + status = val->crypto_function(VAL_CRYPTO_HASH_ABORT, + &extra_operation); + TEST_ASSERT_EQUAL(status, PSA_SUCCESS, TEST_CHECKPOINT_NUM(8)); + } + + return VAL_STATUS_SUCCESS; +#else + val->print(TEST, "No test available for the selected crypto configuration\n", 0); + return RESULT_SKIP(VAL_STATUS_NO_TESTS); +#endif +} diff --git a/api-tests/dev_apis/crypto/test_c081/test_c081.h b/api-tests/dev_apis/crypto/test_c081/test_c081.h new file mode 100644 index 00000000..0d64bc6a --- /dev/null +++ b/api-tests/dev_apis/crypto/test_c081/test_c081.h @@ -0,0 +1,32 @@ +/** @file + * Copyright (c) 2026, Arm Limited or its affiliates. All rights reserved. + * SPDX-License-Identifier : Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +**/ +#ifndef _TEST_C081_CLIENT_TESTS_H_ +#define _TEST_C081_CLIENT_TESTS_H_ + +#include "val_crypto.h" +#define test_entry CONCAT(test_entry_, c081) +#define val CONCAT(val, test_entry) +#define psa CONCAT(psa, test_entry) + +extern val_api_t *val; +extern psa_api_t *psa; +extern const client_test_t test_c081_crypto_list[]; + +int32_t psa_hash_parallel_capacity_test(caller_security_t caller); +extern void crypto_common_exit_action(void); + +#endif /* _TEST_C081_CLIENT_TESTS_H_ */ diff --git a/api-tests/dev_apis/crypto/test_c081/test_data.h b/api-tests/dev_apis/crypto/test_c081/test_data.h new file mode 100644 index 00000000..952b9467 --- /dev/null +++ b/api-tests/dev_apis/crypto/test_c081/test_data.h @@ -0,0 +1,38 @@ +/** @file + * Copyright (c) 2026, Arm Limited or its affiliates. All rights reserved. + * SPDX-License-Identifier : Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +**/ + +#include "test_crypto_common.h" + +typedef struct { + const char *test_desc; + psa_algorithm_t alg; + size_t max_parallel_ops; + psa_status_t expected_failure_status; +} test_data; + +static const test_data check1[] = { +#if defined(ARCH_TEST_SHA256) && defined(ARCH_TEST_MAX_PARALLEL_HASH_OPS) && \ + defined(ARCH_TEST_PARALLEL_HASH_OPS_FAILURE_STATUS) +{ + .test_desc = "Test configured parallel hash operation limit with SHA256 - " + "expect %d sessions to open, next to fail\n", + .alg = PSA_ALG_SHA_256, + .max_parallel_ops = ARCH_TEST_MAX_PARALLEL_HASH_OPS, + .expected_failure_status = ARCH_TEST_PARALLEL_HASH_OPS_FAILURE_STATUS, +}, +#endif +}; diff --git a/api-tests/dev_apis/crypto/test_c081/test_entry_c081.c b/api-tests/dev_apis/crypto/test_c081/test_entry_c081.c new file mode 100644 index 00000000..59c22bc3 --- /dev/null +++ b/api-tests/dev_apis/crypto/test_c081/test_entry_c081.c @@ -0,0 +1,52 @@ +/** @file + * Copyright (c) 2026, Arm Limited or its affiliates. All rights reserved. + * SPDX-License-Identifier : Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +**/ + +#include "val_interfaces.h" +#include "test_c081.h" + +#define TEST_NUM VAL_CREATE_TEST_ID(VAL_CRYPTO_BASE, 81) +#define TEST_DESC "psa_hash_setup : Desc=parallel hash operation capacity : " + +TEST_PUBLISH(TEST_NUM, test_entry); +val_api_t *val = NULL; +psa_api_t *psa = NULL; + +void test_entry(val_api_t *val_api, psa_api_t *psa_api) +{ + int32_t status = VAL_STATUS_SUCCESS; + + val = val_api; + psa = psa_api; + + val->test_init(TEST_NUM, VAL_CRYPTO_BASE, TEST_DESC, + TEST_FIELD(TEST_ISOLATION_L1, WD_HIGH_TIMEOUT)); + if (!IS_TEST_START(val->get_status())) + { + goto test_exit; + } + + status = val->execute_non_secure_tests(TEST_NUM, test_c081_crypto_list, FALSE); + if (VAL_ERROR(status)) + { + goto test_exit; + } + +test_exit: + crypto_common_exit_action(); + val->crypto_function(VAL_CRYPTO_FREE); + val->test_exit(); +} diff --git a/api-tests/dev_apis/crypto/testsuite.db b/api-tests/dev_apis/crypto/testsuite.db index 810b1275..8c6ddca6 100644 --- a/api-tests/dev_apis/crypto/testsuite.db +++ b/api-tests/dev_apis/crypto/testsuite.db @@ -100,5 +100,6 @@ test_c077 test_c078 test_c079 test_c080 +test_c081 (END) diff --git a/api-tests/platform/targets/common/nspe/crypto/pal_crypto_config_check.h b/api-tests/platform/targets/common/nspe/crypto/pal_crypto_config_check.h index b6fdd112..1243c5b5 100644 --- a/api-tests/platform/targets/common/nspe/crypto/pal_crypto_config_check.h +++ b/api-tests/platform/targets/common/nspe/crypto/pal_crypto_config_check.h @@ -192,6 +192,20 @@ #error "ARCH_TEST_HKDF defined, but not all prerequisites" #endif +#if defined(ARCH_TEST_MAX_PARALLEL_HASH_OPS) && !defined(ARCH_TEST_HASH) +#error "ARCH_TEST_MAX_PARALLEL_HASH_OPS defined, but not all prerequisites" +#endif + +#if defined(ARCH_TEST_MAX_PARALLEL_HASH_OPS) && \ + !defined(ARCH_TEST_PARALLEL_HASH_OPS_FAILURE_STATUS) +#error "ARCH_TEST_MAX_PARALLEL_HASH_OPS defined, but failure status is missing" +#endif + +#if defined(ARCH_TEST_PARALLEL_HASH_OPS_FAILURE_STATUS) && \ + !defined(ARCH_TEST_MAX_PARALLEL_HASH_OPS) +#error "ARCH_TEST_PARALLEL_HASH_OPS_FAILURE_STATUS defined, but max parallel ops is missing" +#endif + #if defined(ARCH_TEST_CMAC) && !defined(ARCH_TEST_AES) #error "ARCH_TEST_CMAC defined, but not all prerequisites" #endif diff --git a/api-tests/platform/targets/tgt_dev_apis_linux/nspe/pal_crypto_config.h b/api-tests/platform/targets/tgt_dev_apis_linux/nspe/pal_crypto_config.h index 4575b64d..cce02a75 100644 --- a/api-tests/platform/targets/tgt_dev_apis_linux/nspe/pal_crypto_config.h +++ b/api-tests/platform/targets/tgt_dev_apis_linux/nspe/pal_crypto_config.h @@ -275,6 +275,31 @@ #define ARCH_TEST_HKDF #define ARCH_TEST_HKDF_EXTRACT #define ARCH_TEST_HKDF_EXPAND + +/** + * \def ARCH_TEST_MAX_PARALLEL_HASH_OPS + * + * Maximum number of parallel multipart hash operations supported by + * the target for the hash capacity test. + * + * Uncomment and set to enable test_c081. + * + * Requires: ARCH_TEST_HASH and at least one enabled hash algorithm. + */ +#define ARCH_TEST_MAX_PARALLEL_HASH_OPS 8 + +/** + * \def ARCH_TEST_PARALLEL_HASH_OPS_FAILURE_STATUS + * + * Error expected when the target refuses one more multipart hash + * operation beyond ARCH_TEST_MAX_PARALLEL_HASH_OPS. + * + * Uncomment to enable test_c081. + * + * Requires: ARCH_TEST_MAX_PARALLEL_HASH_OPS + */ +#define ARCH_TEST_PARALLEL_HASH_OPS_FAILURE_STATUS PSA_ERROR_INSUFFICIENT_MEMORY + /** * \def ARCH_TEST_TLS12_PRF *