diff --git a/.codecheckignore b/.codecheckignore index bf97857..c55a298 100644 --- a/.codecheckignore +++ b/.codecheckignore @@ -7,8 +7,6 @@ ^connectivity/drivers/emac ^connectivity/drivers/mbedtls ^connectivity/mbedtls -^features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV -^features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM ^features/frameworks ^connectivity/lwipstack/lwip ^connectivity/lwipstack/lwip-sys @@ -20,6 +18,8 @@ ^features/unsupported/ ^hal/storage_abstraction ^platform/cxxsupport +^platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV +^platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM ^platform/tests/UNITTESTS ^events/tests/UNITTESTS ^rtos/source/TARGET_CORTEX/rtx4 diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/attestation/main.cpp b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/attestation/main.cpp deleted file mode 100755 index 866123c..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/attestation/main.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/* -* Copyright (c) 2019-2020 ARM Limited. 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. -*/ - -#if !defined(MBED_CONF_RTOS_PRESENT) -#error [NOT_SUPPORTED] PSA attestation test cases require RTOS to run. -#else - -#include "psa/crypto.h" - -#if ((!defined(TARGET_PSA)) || (!defined(MBEDTLS_PSA_CRYPTO_C))) -#error [NOT_SUPPORTED] Mbed Crypto is OFF - skipping. -#else - -#include "greentea-client/test_env.h" -#include "unity/unity.h" -#include "utest/utest.h" -#include "psa/lifecycle.h" -#include "psa_initial_attestation_api.h" -#include "psa_attest_inject_key.h" -#include -#include - -#include "entropy.h" -#include "entropy_poll.h" - -/* MAX value support macro */ -#if !defined(MAX) -#define MAX(a,b) (((a)>(b))?(a):(b)) -#endif - -#define MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE \ -MAX(MBEDTLS_ENTROPY_MIN_PLATFORM, MBEDTLS_ENTROPY_BLOCK_SIZE) - -using namespace utest::v1; - -utest::v1::status_t greentea_test_setup(const size_t number_of_cases) -{ - GREENTEA_SETUP(60, "default_auto"); - return greentea_test_setup_handler(number_of_cases); -} - -#define PSA_ATTESTATION_PRIVATE_KEY_ID 17 - -static const uint8_t private_key_data[] = { - 0x49, 0xc9, 0xa8, 0xc1, 0x8c, 0x4b, 0x88, 0x56, - 0x38, 0xc4, 0x31, 0xcf, 0x1d, 0xf1, 0xc9, 0x94, - 0x13, 0x16, 0x09, 0xb5, 0x80, 0xd4, 0xfd, 0x43, - 0xa0, 0xca, 0xb1, 0x7d, 0xb2, 0xf1, 0x3e, 0xee -}; - -static const uint8_t public_key_data[] = { - 0x04, 0x77, 0x72, 0x65, 0x6f, 0x81, 0x4b, 0x39, - 0x92, 0x79, 0xd5, 0xe1, 0xf1, 0x78, 0x1f, 0xac, - 0x6f, 0x09, 0x9a, 0x3c, 0x5c, 0xa1, 0xb0, 0xe3, - 0x53, 0x51, 0x83, 0x4b, 0x08, 0xb6, 0x5e, 0x0b, - 0x57, 0x25, 0x90, 0xcd, 0xaf, 0x8f, 0x76, 0x93, - 0x61, 0xbc, 0xf3, 0x4a, 0xcf, 0xc1, 0x1e, 0x5e, - 0x07, 0x4e, 0x84, 0x26, 0xbd, 0xde, 0x04, 0xbe, - 0x6e, 0x65, 0x39, 0x45, 0x44, 0x96, 0x17, 0xde, - 0x45 -}; - -#define TEST_TOKEN_SIZE (0x200) -#define TEST_CHALLENGE_OBJ_SIZE (32u) - -#define CHALLENGE_FOR_TEST 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, \ - 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, \ - 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, \ - 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF - -static uint8_t token_buffer[TEST_TOKEN_SIZE]; -static uint8_t challenge_buffer[TEST_CHALLENGE_OBJ_SIZE] = {CHALLENGE_FOR_TEST}; - -static void check_initial_attestation_get_token() -{ - psa_status_t status = PSA_SUCCESS; - size_t exported_length; - uint8_t exported[sizeof(public_key_data)]; - enum psa_attest_err_t attest_err = PSA_ATTEST_ERR_SUCCESS; - uint32_t token_size; - - status = psa_crypto_init(); - TEST_ASSERT_EQUAL(PSA_SUCCESS, status); - status = psa_attestation_inject_key(private_key_data, - sizeof(private_key_data), - PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1), - exported, - sizeof(exported), - &exported_length); - - TEST_ASSERT_EQUAL(PSA_SUCCESS, status); - TEST_ASSERT_EQUAL(sizeof(public_key_data), exported_length); - TEST_ASSERT_EQUAL(0, memcmp(public_key_data, exported, exported_length)); - - attest_err = psa_initial_attest_get_token_size(TEST_CHALLENGE_OBJ_SIZE, - &token_size); - - TEST_ASSERT_EQUAL(PSA_ATTEST_ERR_SUCCESS, attest_err); - - attest_err = psa_initial_attest_get_token(challenge_buffer, - TEST_CHALLENGE_OBJ_SIZE, - token_buffer, - &token_size); - - TEST_ASSERT_EQUAL(PSA_ATTEST_ERR_SUCCESS, attest_err); -} -/***************************************************************************************/ - -utest::v1::status_t case_teardown_handler(const Case *const source, const size_t passed, const size_t failed, const failure_t reason) -{ - psa_key_handle_t handle; - psa_open_key(PSA_ATTESTATION_PRIVATE_KEY_ID, &handle); - psa_destroy_key(handle); - mbedtls_psa_crypto_free(); - return greentea_case_teardown_handler(source, passed, failed, reason); -} - -utest::v1::status_t case_setup_handler(const Case *const source, const size_t index_of_case) -{ - psa_status_t status; - status = mbed_psa_reboot_and_request_new_security_state(PSA_LIFECYCLE_ASSEMBLY_AND_TEST); - TEST_ASSERT_EQUAL(PSA_SUCCESS, status); -#if defined(MBEDTLS_ENTROPY_NV_SEED) - uint8_t seed[MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE] = {0}; - /* inject some seed for test*/ - for (int i = 0; i < MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE; ++i) { - seed[i] = i; - } - - /* don't really care if this succeeds this is just to make crypto init pass*/ - mbedtls_psa_inject_entropy(seed, MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE); -#endif - return greentea_case_setup_handler(source, index_of_case); -} - - -Case cases[] = { - Case("PSA attestation get token", case_setup_handler, check_initial_attestation_get_token, case_teardown_handler), -}; - -Specification specification(greentea_test_setup, cases); - -int main() -{ - return !Harness::run(specification); -} - -#endif // ((!defined(TARGET_PSA)) || (!defined(MBEDTLS_PSA_CRYPTO_C))) -#endif // !defined(MBED_CONF_RTOS_PRESENT) diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/psa_attestation_testlist.md b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/psa_attestation_testlist.md deleted file mode 100644 index d8d7f10..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/psa_attestation_testlist.md +++ /dev/null @@ -1,22 +0,0 @@ -# PSA Initial Attestation Testcase checklist - -| Test | Return value | API | Test Algorithm | Test Cases | -|-----------|--------------------------------------|-------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| test_a001 | PSA_ATTEST_ERR_SUCCESS | psa_initial_attest_get_token()
psa_initial_attest_get_token_size() | 1. Provide correct inputs to API with described challenge sizes
2. Expect API to return this define as return value each time
3. Verify the token | 1. Challenge_size = 32
2. Challenge_size = 48
3. Challenge_size = 64 | -| | PSA_ATTEST_ERR_INVALID_INPUT | psa_initial_attest_get_token()
psa_initial_attest_get_token_size() | 1. Provide described challenge sizes to the API along with other valid parameters
2. Expect API to return this define as return value each time | 1. Challenge_size is zero
2. Invalid challenge size between 0 and 32
3. Invalid challenge size between 32 and 64
4. Challenge_size is greater than MAX_CHALLENGE_SIZE | -| | PSA_ATTEST_ERR_TOKEN_BUFFER_OVERFLOW | psa_initial_attest_get_token() | 1. Provide described taken size to the API along with other valid parameters
2. Expect API to return this define as return value each time | Pass the token_size which less than actual/required token size | -| | PSA_ATTEST_ERR_INIT_FAILED | psa_initial_attest_get_token()
psa_initial_attest_get_token_size() | Can't simulate. Test can't generate stimulus where attestation initialisation fails | | -| | PSA_ATTEST_ERR_CLAIM_UNAVAILABLE | psa_initial_attest_get_token() | Can't simulate. Test can't generate stimulus where claim can unavailable | | -| | PSA_ATTEST_ERR_GENERAL | psa_initial_attest_get_token()
psa_initial_attest_get_token_size() | Can't simulate. Test can't generate stimulus where unexpected error happened during API operation | | - -## Note - -1. In verifying the token, only the data type of claims and presence of the mandatory claims are checked and the values of the claims are not checked. -2. Checks related to token signature validation will be part of future release - -# License -Arm PSA test suite is distributed under Apache v2.0 License. - --------------- - -*Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.* diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/test_a001/main.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/test_a001/main.c deleted file mode 100644 index 2bdbffd..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/test_a001/main.c +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited and affiliates. - * 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 "pal_mbed_os_intf.h" - -#if !defined(MBED_CONF_RTOS_PRESENT) -#error [NOT_SUPPORTED] PSA compliance attestation test cases require RTOS to run. -#else -void test_entry_a001(val_api_t *val_api, psa_api_t *psa_api); - -int main(void) -{ - test_start(test_entry_a001, COMPLIANCE_TEST_ATTESTATION); -} -#endif diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/test_a001/test_a001.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/test_a001/test_a001.c deleted file mode 100644 index edb8e59..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/test_a001/test_a001.c +++ /dev/null @@ -1,105 +0,0 @@ -/** @file - * Copyright (c) 2019, 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 "val_target.h" -#include "test_a001.h" -#include "test_data.h" - -client_test_t test_a001_attestation_list[] = { - NULL, - psa_initial_attestation_get_token_test, - psa_initial_attestation_get_token_size_test, - NULL, -}; - -static int g_test_count = 1; - -int32_t psa_initial_attestation_get_token_test(caller_security_t caller) -{ - int num_checks = sizeof(check1)/sizeof(check1[0]); - uint32_t i, status, token_size; - uint8_t challenge[PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64+1]; - uint8_t token_buffer[TOKEN_SIZE]; - - for (i = 0; i < num_checks; i++) - { - val->print(PRINT_TEST, "[Check %d] ", g_test_count++); - val->print(PRINT_TEST, check1[i].test_desc, 0); - - memset(challenge, 0x2a, sizeof(challenge)); - memset(token_buffer, 0, sizeof(token_buffer)); - - status = val->attestation_function(VAL_INITIAL_ATTEST_GET_TOKEN_SIZE, - check1[i].challenge_size, &token_size); - if (status != PSA_SUCCESS) - { - if (check1[i].challenge_size != PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32 || - check1[i].challenge_size != PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48 || - check1[i].challenge_size != PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64) - { - token_size = check1[i].token_size; - check1[i].challenge_size = check1[i].actual_challenge_size; - } - else - return status; - } - - status = val->attestation_function(VAL_INITIAL_ATTEST_GET_TOKEN, challenge, - check1[i].challenge_size, token_buffer, &token_size); - TEST_ASSERT_EQUAL(status, check1[i].expected_status, TEST_CHECKPOINT_NUM(1)); - - if (check1[i].expected_status != PSA_SUCCESS) - continue; - - /* Validate the token */ - status = val->attestation_function(VAL_INITIAL_ATTEST_VERIFY_TOKEN, challenge, - check1[i].challenge_size, token_buffer, token_size); - TEST_ASSERT_EQUAL(status, PSA_SUCCESS, TEST_CHECKPOINT_NUM(2)); - } - - return VAL_STATUS_SUCCESS; -} - -int32_t psa_initial_attestation_get_token_size_test(caller_security_t caller) -{ - int num_checks = sizeof(check2)/sizeof(check2[0]); - uint32_t i, status, token_size; - - for (i = 0; i < num_checks; i++) - { - val->print(PRINT_TEST, "[Check %d] ", g_test_count++); - val->print(PRINT_TEST, check2[i].test_desc, 0); - - status = val->attestation_function(VAL_INITIAL_ATTEST_GET_TOKEN_SIZE, - check2[i].challenge_size, &token_size); - - TEST_ASSERT_EQUAL(status, check2[i].expected_status, TEST_CHECKPOINT_NUM(1)); - - if (check2[i].expected_status != PSA_SUCCESS) - continue; - - if (token_size < check2[i].challenge_size) - { - val->print(PRINT_ERROR, "Token size less than challenge size\n", 0); - return VAL_STATUS_INSUFFICIENT_SIZE; - } - } - - return VAL_STATUS_SUCCESS; -} - diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/test_a001/test_a001.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/test_a001/test_a001.h deleted file mode 100644 index e066ee8..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/test_a001/test_a001.h +++ /dev/null @@ -1,33 +0,0 @@ -/** @file - * Copyright (c) 2019, 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_A001_CLIENT_TESTS_H_ -#define _TEST_A001_CLIENT_TESTS_H_ - -#include "val_attestation.h" -#define test_entry CONCAT(test_entry_, a001) -#define val CONCAT(val,test_entry) -#define psa CONCAT(psa,test_entry) - -#define TOKEN_SIZE 512 - -extern val_api_t *val; -extern psa_api_t *psa; -extern client_test_t test_a001_attestation_list[]; - -int32_t psa_initial_attestation_get_token_test(caller_security_t caller); -int32_t psa_initial_attestation_get_token_size_test(caller_security_t caller); -#endif /* _TEST_A001_CLIENT_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/test_a001/test_data.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/test_a001/test_data.h deleted file mode 100644 index bfeba55..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/test_a001/test_data.h +++ /dev/null @@ -1,103 +0,0 @@ -/** @file - * Copyright (c) 2019, 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_attestation.h" - -typedef struct { - char test_desc[100]; - uint32_t challenge_size; - uint32_t actual_challenge_size; - uint32_t token_size; - psa_status_t expected_status; -} test_data; - - -static test_data check1[] = { -{"Test psa_initial_attestation_get_token with Challenge 32\n", - PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32, TOKEN_SIZE, PSA_SUCCESS -}, - -{"Test psa_initial_attestation_get_token with Challenge 48\n", - PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48, TOKEN_SIZE, PSA_SUCCESS -}, - -{"Test psa_initial_attestation_get_token with Challenge 64\n", - PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64, TOKEN_SIZE, PSA_SUCCESS -}, - -{"Test psa_initial_attestation_get_token with zero challenge size\n", - 0, 0, TOKEN_SIZE, PSA_ATTEST_ERR_INVALID_INPUT -}, - -{"Test psa_initial_attestation_get_token with small challenge size\n", - PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32-1, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32-1, - TOKEN_SIZE, PSA_ATTEST_ERR_INVALID_INPUT -}, - -{"Test psa_initial_attestation_get_token with invalid challenge size\n", - PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32+1, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32+1, - TOKEN_SIZE, PSA_ATTEST_ERR_INVALID_INPUT -}, - -{"Test psa_initial_attestation_get_token with large challenge size\n", - MAX_CHALLENGE_SIZE+1, MAX_CHALLENGE_SIZE+1, TOKEN_SIZE, PSA_ATTEST_ERR_INVALID_INPUT -}, - -{"Test psa_initial_attestation_get_token with zero as token size\n", - PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32-1, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32, - 0, PSA_ATTEST_ERR_INVALID_INPUT -}, - -{"Test psa_initial_attestation_get_token with small token size\n", - PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32-1, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32, - PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32-1, PSA_ATTEST_ERR_TOKEN_BUFFER_OVERFLOW -}, -}; - -static test_data check2[] = { -{"Test psa_initial_attestation_get_token_size with Challenge 32\n", - PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32, TOKEN_SIZE, PSA_SUCCESS -}, - -{"Test psa_initial_attestation_get_token_size with Challenge 48\n", - PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48, TOKEN_SIZE, PSA_SUCCESS -}, - -{"Test psa_initial_attestation_get_token_size with Challenge 64\n", - PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64, TOKEN_SIZE, PSA_SUCCESS -}, - -{"Test psa_initial_attestation_get_token_size with zero challenge size\n", - 0, 0, - TOKEN_SIZE, PSA_ATTEST_ERR_INVALID_INPUT -}, - -{"Test psa_initial_attestation_get_token_size with small challenge size\n", - PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32-1, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32-1, - TOKEN_SIZE, PSA_ATTEST_ERR_INVALID_INPUT -}, - -{"Test psa_initial_attestation_get_token_size with invalid challenge size\n", - PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32+1, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32+1, - TOKEN_SIZE, PSA_ATTEST_ERR_INVALID_INPUT -}, - -{"Test psa_initial_attestation_get_token_size with large challenge size\n", - MAX_CHALLENGE_SIZE+1, MAX_CHALLENGE_SIZE+1, - TOKEN_SIZE, PSA_ATTEST_ERR_INVALID_INPUT -}, -}; diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/test_a001/test_entry.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/test_a001/test_entry.c deleted file mode 100644 index db253b8..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/test_a001/test_entry.c +++ /dev/null @@ -1,52 +0,0 @@ -/** @file - * Copyright (c) 2019, 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 "val_target.h" -#include "test_a001.h" - -#define TEST_NUM VAL_CREATE_TEST_ID(VAL_INITIAL_ATTESTATION_BASE, 1) -#define TEST_DESC "Testing initial attestation APIs\n" -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; - - /* test init */ - val->test_init(TEST_NUM, TEST_DESC, TEST_FIELD(TEST_ISOLATION_L1, WD_HIGH_TIMEOUT)); - if (!IS_TEST_START(val->get_status())) - { - goto test_exit; - } - - /* Execute list of tests available in test[num]_attestation_list from Non-secure side*/ - status = val->execute_non_secure_tests(TEST_NUM, test_a001_attestation_list, FALSE); - - if (VAL_ERROR(status)) - { - goto test_exit; - } - -test_exit: - val->test_exit(); -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/psa_its_testlist.md b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/psa_its_testlist.md deleted file mode 100644 index b466a7e..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/psa_its_testlist.md +++ /dev/null @@ -1,30 +0,0 @@ -# PSA Internal Trusted Storage Testcase checklist - -## Requirements for Storage Test Suite - -Following are the requirements of the Storage Test Suite.
- -1. Unless described in this document, any behaviour that is defined as IMPLEMENTATION_DEFINED in PSA Storage API document is not verified in this document.
-2. Storage Test Cases use UID value starting from 1 onwards. These UID needs to be free for successfull test execution.
-3. UID values 1 and 2 are reserved as WRITE_ONCE UID.These UID can't be free from testcase. Make sure these are free.
- - -| Test | Return Value | API Verified | Test Algorithm | UID Usage | -|-----------|--------------------------------------|------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| test_s001 | PSA_ITS_ERROR_UID_NOT_FOUND | psa_its_get
psa_its_get_info
psa_its_remove
| 1. Call get API with UID for which no UID/Data pair is created
2. Call get_info API for which no UID/Data pair is created
3. Call remove API for which no UID/Data pair is created
4. Set valid UID/Data pair with uid1
5. Set one more set of UID/Data pair, with different uid, than previous
6. Remove the uid of step 4.
7. Call get API for removed UID/data pair
8. Call get_info API for removed UID/Data pair
9. Call remove API for removed UID/Data pair
10. Set valid UID/Data pair
11. Call get API for different uid , then created
12. Call get_info API for different uid, then created
13. Call remove API for different uid, then created
14. Remove the created UID/Data pair.
15. Remove the stray uid.
| UID value used are 5,6,7 | -| test_s002 | PSA_ITS_ERROR_WRITE_ONCE | psa_its_set
psa_its_remove
| 1. Set valid UID/data value pair , with create flag value none.2. Call get and get_info API to validate the data, attributes associated with data
3. Call set API again with same uid and create flag PSA_PS_WRITE_ONCE_FLAG
4. Call get and get_info API to validate the data, attributes associated with data is not changed after second set operation
5. try to remove the UID/data pair.
6. Create new UID/data value pair, with create flag PSA_PS_WRITE_ONCE_FLAG
7. Try to remove the created UID.
8. Call get and get_info API to validate the data, attributes associated with data
9. Again call SET with same UID , create flag PSA_PS_WRITE_ONCE_FLAG but different data length
10. Try to remove the UID, PSA_ITS_ERROR_WRITE_ONCE error should be returned
11. Call get and get_info API to validate the data, attributes associated with data
| UID value used are 1 and 2 | -| test_s003 | PSA_ITS_ERROR_INSUFFICIENT_SPACE | psa_its_set
| 1. Create UID/data pairs, with data_len 256 bytes. Do this with incrementing uid values till we have INSUFFICENT_SPACE.
2. Remove all the UID/data pairs created.
3. Repeat the steps once more, to check all previous uid are removed successfully
| UID value starts from 5 and keep on incrementing till all space is exhausted | -| test_s004 | PSA_ITS_SUCCESS | psa_its_set
psa_its_get
psa_its_get_info
psa_its_remove
| 1. Set a valid uid/data pair
2. Validate the data using get api
3. Change the data length to half of previous.
4. Call GET api with original data length , error should be returned and also the return buffer should be empty
5. Call GET api with correct data_len and validate the data received.
6. Check old data cannot be accessed.
7. Call REMOVE api to delete the UID/data pair
| UID value used is 5 | -| test_s005 | PSA_ITS_SUCCESS | psa_its_set
psa_its_get
psa_its_get_info
psa_its_remove
| 1. Set valid UID/data pair with varying uid and data_len
2. Call GET api and validate the set data
3. Call GET info api and validate the data attributes
4. Call REMOVE api to delete the UID/data pair
| UID value used are 4 | -| test_s006 | PSA_ITS_ERROR_FLAGS_NOT_SUPPORTED | psa_its_set
| 1. Call the SET_INFO with minimum flag value to max flag value
2. Call GET_INFO api and validate the flag value
3. Remove the uid/data pair
| UID value used is 5 | -| test_s007 | PSA_ITS_ERROR_INCORRECT_SIZE | psa_its_set
| 1. Create valid uid/data pair.
2. Increase the length of storage.
3. Try to access the old length using get api.
4. Try to access with valid length less than stored size.
5. Decrease the length of storage.
6. Try to access the old length.
7. Remove the uid
| UID value used is 5 | -| test_s008 | PSA_ITS_ERROR_OFFSET_INVALID | psa_its_get
| 1. Set valid UID/data pair
2. Call GET api with valid offset and offset + data_len equal to stored data size.
3. Call GET api with valid offset and offset + data_len less than stored data size.
4. Call get api with invalid offset.
5. Call get api with zero offset , but data len greater than data size.
6. Remove the uid.
| UID value used is 5 | -| test_s009 | PSA_ITS_SUCCESS | psa_its_get
psa_its_set
psa_its_get_info
| 1. Call the SET API with NULL pointer and data_len zero
2. Validate using get_info api storage should be present.
3. Call get API with NULL pointer.
4. Remove the UID.
5. Call get_info API to validate storage is removed.
6. Set storage entity with valid write_buffer , but length zero.
7. Call get_info API to validate storage attributes.
8. Call get_info api with NULL pointer and valid uid.
9. Remove the uid
| UID value used is 5
| -| test_s010 | PSA_ITS_ERROR_STORAGE_FAILURE
| psa_its_set
| 1. Call the SET API with UID value 0.
2. Check that storage creation fails.
| UID value used is 0
| - -## License -Arm PSA test suite is distributed under Apache v2.0 License. - --------------- - -*Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.* diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/main.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/main.c deleted file mode 100644 index 2ab8343..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/main.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited and affiliates. - * 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 "pal_mbed_os_intf.h" - -#if !defined(MBED_CONF_RTOS_PRESENT) -#error [NOT_SUPPORTED] PSA compliance its test cases require RTOS to run -#else - -#ifdef ITS_TEST -void test_entry_s001(val_api_t *val_api, psa_api_t *psa_api); -#elif PS_TEST -void test_entry_p001(val_api_t *val_api, psa_api_t *psa_api); -#endif - -int main(void) -{ -#ifdef ITS_TEST - test_start(test_entry_s001, COMPLIANCE_TEST_STORAGE); -#elif PS_TEST - test_start(test_entry_p001, COMPLIANCE_TEST_STORAGE); -#endif -} -#endif // !defined(MBED_CONF_RTOS_PRESENT) diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/test_entry.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/test_entry.c deleted file mode 100644 index 8b8aed9..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/test_entry.c +++ /dev/null @@ -1,53 +0,0 @@ -/** @file - * Copyright (c) 2019, 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 "val_target.h" -#include "test_s001.h" - -#define TEST_NUM VAL_CREATE_TEST_ID(VAL_STORAGE_BASE, 1) -#define TEST_DESC "UID not found check\n" - -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; - - /* test init */ - val->test_init(TEST_NUM, TEST_DESC, TEST_FIELD(TEST_ISOLATION_L1, WD_HIGH_TIMEOUT)); - if (!IS_TEST_START(val->get_status())) - { - goto test_exit; - } - - /* Execute list of tests available in test[num]_secure_storage_list from Non-secure side*/ - status = val->execute_non_secure_tests(TEST_NUM, test_s001_sst_list, FALSE); - - if (VAL_ERROR(status)) - { - goto test_exit; - } - -test_exit: - val->test_exit(); -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/test_its_data.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/test_its_data.h deleted file mode 100644 index af95d04..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/test_its_data.h +++ /dev/null @@ -1,81 +0,0 @@ -/** @file - * Copyright (c) 2019, 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_S001_ITS_DATA_TESTS_H_ -#define _TEST_S001_ITS_DATA_TESTS_H_ - -#include "val_internal_trusted_storage.h" - -#define SST_FUNCTION val->its_function -#define psa_sst_uid_t psa_its_uid_t - -typedef struct { - enum its_function_code api; - psa_its_status_t status; -} test_data; - -static struct psa_its_info_t info; -static const test_data s001_data[] = { -{ - 0, 0 /* Unused Index0 */ -}, -{ - VAL_ITS_GET, PSA_ITS_ERROR_UID_NOT_FOUND /* Call the get API when no UID is set */ -}, -{ - VAL_ITS_GET_INFO, PSA_ITS_ERROR_UID_NOT_FOUND /* Call the get_info API when no UID is set */ -}, -{ - VAL_ITS_REMOVE, PSA_ITS_ERROR_UID_NOT_FOUND /* Call the remove API when no UID is set */ -}, -{ - VAL_ITS_SET, PSA_ITS_SUCCESS /* Create a valid storage entity with UID1 */ -}, -{ - VAL_ITS_SET, PSA_ITS_SUCCESS /* Create a valid storage entity with UID2 */ -}, -{ - VAL_ITS_REMOVE, PSA_ITS_SUCCESS /* Remove UID1 */ -}, -{ - VAL_ITS_GET, PSA_ITS_ERROR_UID_NOT_FOUND /* Call get API for UID1 */ -}, -{ - VAL_ITS_GET_INFO, PSA_ITS_ERROR_UID_NOT_FOUND /* Call get_info API for UID1 */ -}, -{ - VAL_ITS_REMOVE, PSA_ITS_ERROR_UID_NOT_FOUND /* Call remove API for UID1 */ -}, -{ - VAL_ITS_SET, PSA_ITS_SUCCESS /* Create a valid storage entity again with UID1 */ -}, -{ - VAL_ITS_GET, PSA_ITS_ERROR_UID_NOT_FOUND /* Call get API for UID not same as UID1 or UID2 */ -}, -{ - VAL_ITS_GET_INFO, PSA_ITS_ERROR_UID_NOT_FOUND /* Call get_info for UID not same as UID1 or UID2 */ -}, -{ - VAL_ITS_REMOVE, PSA_ITS_ERROR_UID_NOT_FOUND /* Call remove API for UID not same as UID1 or UID2 */ -}, -{ - VAL_ITS_REMOVE, PSA_ITS_SUCCESS /* Remove UID1 */ -}, -{ - VAL_ITS_REMOVE, PSA_ITS_SUCCESS /* Remove UID2 */ -}, -}; -#endif /* _TEST_S001_ITS_DATA_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/test_ps_data.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/test_ps_data.h deleted file mode 100644 index 2013058..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/test_ps_data.h +++ /dev/null @@ -1,81 +0,0 @@ -/** @file - * Copyright (c) 2019, Arm Limited or ps 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_S001_PS_DATA_TESTS_H_ -#define _TEST_S001_PS_DATA_TESTS_H_ - -#include "val_protected_storage.h" - -#define SST_FUNCTION val->ps_function -#define psa_sst_uid_t psa_ps_uid_t - -typedef struct { - enum ps_function_code api; - psa_ps_status_t status; -} test_data; - -static struct psa_ps_info_t info; -static const test_data s001_data[] = { -{ - 0, 0 /* This is dummy for index0 */ -}, -{ - VAL_PS_GET, PSA_PS_ERROR_UID_NOT_FOUND /* Call the get API when no UID is set */ -}, -{ - VAL_PS_GET_INFO, PSA_PS_ERROR_UID_NOT_FOUND /* Call the get_info API when no UID is set */ -}, -{ - VAL_PS_REMOVE, PSA_PS_ERROR_UID_NOT_FOUND /* Call the remove API when no UID is set */ -}, -{ - VAL_PS_SET, PSA_PS_SUCCESS /* Create a valid storage entity with UID1 */ -}, -{ - VAL_PS_SET, PSA_PS_SUCCESS /* Create a valid storage entity with UID2 */ -}, -{ - VAL_PS_REMOVE, PSA_PS_SUCCESS /* Remove UID1 */ -}, -{ - VAL_PS_GET, PSA_PS_ERROR_UID_NOT_FOUND /* Call get API for UID1 */ -}, -{ - VAL_PS_GET_INFO, PSA_PS_ERROR_UID_NOT_FOUND /* Call get_info API for UID1 */ -}, -{ - VAL_PS_REMOVE, PSA_PS_ERROR_UID_NOT_FOUND /* Call remove API for UID1 */ -}, -{ - VAL_PS_SET, PSA_PS_SUCCESS /* Create a valid storage entity again with UID1 */ -}, -{ - VAL_PS_GET, PSA_PS_ERROR_UID_NOT_FOUND /* Call get API for UID not same as UID1 or UID2 */ -}, -{ - VAL_PS_GET_INFO, PSA_PS_ERROR_UID_NOT_FOUND /* Call get_info for UID not same as UID1 or UID2 */ -}, -{ - VAL_PS_REMOVE, PSA_PS_ERROR_UID_NOT_FOUND /* Call remove API for UID not same as UID1 or UID2 */ -}, -{ - VAL_PS_REMOVE, PSA_PS_SUCCESS /* Remove UID1 */ -}, -{ - VAL_PS_REMOVE, PSA_PS_SUCCESS /* Remove UID2 */ -}, -}; -#endif /* _TEST_S001_PS_DATA_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/test_s001.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/test_s001.c deleted file mode 100644 index 5e9c26f..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/test_s001.c +++ /dev/null @@ -1,170 +0,0 @@ -/** @file - * Copyright (c) 2019, 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 "val_target.h" -#include "test_s001.h" -#ifdef ITS_TEST -#include "test_its_data.h" -#elif PS_TEST -#include "test_ps_data.h" -#endif - -#define TEST_BUFF_SIZE 16 - -client_test_t test_s001_sst_list[] = { - NULL, - psa_sst_uid_not_found, - NULL, -}; - -static uint8_t write_buff[TEST_BUFF_SIZE] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}; -static uint8_t read_buff[TEST_BUFF_SIZE] = {0}; - -static int32_t sst_calls_without_set_call(psa_sst_uid_t p_uid) -{ - uint32_t status; - - /* get() without using set() before */ - val->print(PRINT_TEST, "[Check 1] Call get API for UID %d which is not set\n", p_uid); - status = SST_FUNCTION(s001_data[1].api, p_uid, 0, TEST_BUFF_SIZE, read_buff); - TEST_ASSERT_EQUAL(status,s001_data[1].status,TEST_CHECKPOINT_NUM(1)); - - /* get_info() without using set() before */ - val->print(PRINT_TEST, "[Check 2] Call get_info API for UID %d which is not set\n", p_uid); - status = SST_FUNCTION(s001_data[2].api, p_uid, &info); - TEST_ASSERT_EQUAL(status, s001_data[2].status, TEST_CHECKPOINT_NUM(2)); - - /* remove() without using set() before */ - val->print(PRINT_TEST, "[Check 3] Call remove API for UID %d which is not set\n", p_uid); - status = SST_FUNCTION(s001_data[3].api, p_uid); - TEST_ASSERT_EQUAL(status, s001_data[3].status, TEST_CHECKPOINT_NUM(3)); - - return VAL_STATUS_SUCCESS; -} - -static int32_t sst_set_and_remove(psa_sst_uid_t p_uid) -{ - uint32_t status; - - /* set() a UID1 */ - status = SST_FUNCTION(s001_data[4].api, p_uid, TEST_BUFF_SIZE, write_buff, 0); - TEST_ASSERT_EQUAL(status, s001_data[4].status, TEST_CHECKPOINT_NUM(4)); - - /* Also set() with a different UID */ - status = SST_FUNCTION(s001_data[5].api, p_uid + 1, TEST_BUFF_SIZE, write_buff, 0); - TEST_ASSERT_EQUAL(status, s001_data[5].status, TEST_CHECKPOINT_NUM(5)); - - /* remove() UID1 */ - status = SST_FUNCTION(s001_data[6].api, p_uid); - TEST_ASSERT_EQUAL(status, s001_data[6].status, TEST_CHECKPOINT_NUM(6)); - - return VAL_STATUS_SUCCESS; -} - -static int32_t sst_calls_after_uid_remove(psa_sst_uid_t p_uid) -{ - uint32_t status; - - /* get() for UID which is removed */ - val->print(PRINT_TEST, "[Check 4] Call get API for UID %d which is removed\n", p_uid); - status = SST_FUNCTION(s001_data[7].api, p_uid, 0, TEST_BUFF_SIZE, read_buff); - TEST_ASSERT_EQUAL(status, s001_data[7].status, TEST_CHECKPOINT_NUM(7)); - - /* get_info() for UID which is removed */ - val->print(PRINT_TEST, "[Check 5] Call get_info API for UID %d which is removed\n", p_uid); - status = SST_FUNCTION(s001_data[8].api, p_uid, &info); - TEST_ASSERT_EQUAL(status, s001_data[8].status, TEST_CHECKPOINT_NUM(8)); - - /* remove() for UID which is removed */ - val->print(PRINT_TEST, "[Check 6] Call remove API for UID %d which is removed\n", p_uid); - status = SST_FUNCTION(s001_data[9].api, p_uid); - TEST_ASSERT_EQUAL(status, s001_data[9].status, TEST_CHECKPOINT_NUM(9)); - - return VAL_STATUS_SUCCESS; -} - -static int32_t sst_calls_with_different_uid(psa_sst_uid_t p_uid) -{ - uint32_t status; - - /* set() a UID */ - val->print(PRINT_TEST, "Set storage for UID %d\n", p_uid); - status = SST_FUNCTION(s001_data[10].api, p_uid, TEST_BUFF_SIZE, write_buff, 0); - TEST_ASSERT_EQUAL(status, s001_data[10].status, TEST_CHECKPOINT_NUM(10)); - - /* get() for different UID then set UID */ - val->print(PRINT_TEST, "[Check 7] Call get API for different UID %d\n", p_uid); - status = SST_FUNCTION(s001_data[11].api, p_uid-1, 0, TEST_BUFF_SIZE - 1, read_buff); - TEST_ASSERT_EQUAL(status, s001_data[11].status, TEST_CHECKPOINT_NUM(11)); - - /* get_info() for different UID then set UID */ - val->print(PRINT_TEST, "[Check 8] Call get_info API for different UID %d\n", p_uid); - status = SST_FUNCTION(s001_data[12].api, p_uid-1, &info); - TEST_ASSERT_EQUAL(status, s001_data[12].status, TEST_CHECKPOINT_NUM(12)); - - /* remove() for different UID then set UID */ - val->print(PRINT_TEST, "[Check 9] Call remove API for different UID %d\n", p_uid); - status = SST_FUNCTION(s001_data[13].api, p_uid-1); - TEST_ASSERT_EQUAL(status, s001_data[13].status, TEST_CHECKPOINT_NUM(13)); - - /* remove() the set UID */ - status = SST_FUNCTION(s001_data[14].api, p_uid); - TEST_ASSERT_EQUAL(status, s001_data[14].status, TEST_CHECKPOINT_NUM(14)); - - return VAL_STATUS_SUCCESS; -} - -static int32_t sst_remove_stray_uid(psa_sst_uid_t p_uid) -{ - uint32_t status; - - /* Remove UID + 1 */ - status = SST_FUNCTION(s001_data[15].api, p_uid); - TEST_ASSERT_EQUAL(status, s001_data[15].status, TEST_CHECKPOINT_NUM(15)); - - return VAL_STATUS_SUCCESS; -} - -int32_t psa_sst_uid_not_found(caller_security_t caller) -{ - int32_t test_status; - psa_sst_uid_t uid = UID_BASE_VALUE + 6; - - test_status = sst_calls_without_set_call(uid); - if (test_status != VAL_STATUS_SUCCESS) - return test_status; - - test_status = sst_set_and_remove(uid); - if (test_status != VAL_STATUS_SUCCESS) - return test_status; - - test_status = sst_calls_after_uid_remove(uid); - if (test_status != VAL_STATUS_SUCCESS) - return test_status; - - test_status = sst_calls_with_different_uid(uid); - if (test_status != VAL_STATUS_SUCCESS) - return test_status; - - test_status = sst_remove_stray_uid(uid + 1); - if (test_status != VAL_STATUS_SUCCESS) - return test_status; - - return VAL_STATUS_SUCCESS; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/test_s001.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/test_s001.h deleted file mode 100644 index 08e5691..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/test_s001.h +++ /dev/null @@ -1,35 +0,0 @@ -/** @file - * Copyright (c) 2019, 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_S001_CLIENT_TESTS_H_ -#define _TEST_S001_CLIENT_TESTS_H_ - -#ifdef ITS_TEST -#define VAL_STORAGE_BASE VAL_INTERNAL_TRUSTED_STORAGE_BASE -#define test_entry CONCAT(test_entry_, s001) -#elif PS_TEST -#define VAL_STORAGE_BASE VAL_PROTECTED_STORAGE_BASE -#define test_entry CONCAT(test_entry_, p001) -#endif -#define val CONCAT(val,test_entry) -#define psa CONCAT(psa,test_entry) - -extern val_api_t *val; -extern psa_api_t *psa; -extern client_test_t test_s001_sst_list[]; - -int32_t psa_sst_uid_not_found(caller_security_t caller); -#endif /* _TEST_S001_CLIENT_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/main.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/main.c deleted file mode 100644 index 46729ac..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/main.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited and affiliates. - * 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 "pal_mbed_os_intf.h" -#include "lifecycle.h" -#if !defined(MBED_CONF_RTOS_PRESENT) -#error [NOT_SUPPORTED] PSA compliance its test cases require RTOS to run -#else - -#ifdef ITS_TEST -void test_entry_s002(val_api_t *val_api, psa_api_t *psa_api); -#elif PS_TEST -void test_entry_p002(val_api_t *val_api, psa_api_t *psa_api); -#endif - -int main(void) -{ -#ifdef ITS_TEST - test_start(test_entry_s002, COMPLIANCE_TEST_STORAGE); -#elif PS_TEST - test_start(test_entry_p002, COMPLIANCE_TEST_STORAGE); -#endif -} -#endif // !defined(MBED_CONF_RTOS_PRESENT) diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/test_entry.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/test_entry.c deleted file mode 100644 index 538a41f..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/test_entry.c +++ /dev/null @@ -1,53 +0,0 @@ -/** @file - * Copyright (c) 2019, 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 "val_target.h" -#include "test_s002.h" - -#define TEST_NUM VAL_CREATE_TEST_ID(VAL_STORAGE_BASE, 2) -#define TEST_DESC "Write once error check\n" - -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; - - /* test init */ - val->test_init(TEST_NUM, TEST_DESC, TEST_FIELD(TEST_ISOLATION_L1, WD_HIGH_TIMEOUT)); - if (!IS_TEST_START(val->get_status())) - { - goto test_exit; - } - - /* Execute list of tests available in test[num]_secure_storage_list from Non-secure side*/ - status = val->execute_non_secure_tests(TEST_NUM, test_s002_sst_list, FALSE); - - if (VAL_ERROR(status)) - { - goto test_exit; - } - -test_exit: - val->test_exit(); -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/test_its_data.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/test_its_data.h deleted file mode 100644 index 303b25f..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/test_its_data.h +++ /dev/null @@ -1,134 +0,0 @@ -/** @file - * Copyright (c) 2019, 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_S002_ITS_DATA_TESTS_H_ -#define _TEST_S002_ITS_DATA_TESTS_H_ - -#include "val_internal_trusted_storage.h" - -#define SST_FUNCTION val->its_function -#define PSA_SST_FLAG_WRITE_ONCE PSA_ITS_FLAG_WRITE_ONCE -#define psa_sst_uid_t psa_its_uid_t - -typedef struct { - enum its_function_code api; - psa_its_status_t status; -} test_data; - -static struct psa_its_info_t orig_info; -static struct psa_its_info_t new_info; -static const test_data s002_data[] = { -{ - 0, 0 /* This is dummy for index0 */ -}, -{ - VAL_ITS_SET, PSA_ITS_SUCCESS /* Create a valid storage with create flag value 0 */ -}, -{ - VAL_ITS_GET_INFO, PSA_ITS_SUCCESS /* Call the get_info API to validate the attributes */ -}, -{ - 0, 0 /* Index not used as check for get info size */ -}, -{ - 0, 0 /* Index not used as check for get info flag */ -}, -{ - VAL_ITS_GET, PSA_ITS_SUCCESS /* Validate the data using get API */ -}, -{ - 0, 0 /* Index not used */ -}, -{ - VAL_ITS_SET, PSA_ITS_SUCCESS /* Change the flag to WRITE_ONCE using set API */ -}, -{ - VAL_ITS_GET_INFO, PSA_ITS_SUCCESS /* Call the get_info API to validate the flag change */ -}, -{ - 0, 0 /* Index not used as check for get info size */ -}, -{ - 0, 0 /* Index not used as check for get info flag */ -}, -{ - VAL_ITS_GET, PSA_ITS_SUCCESS /* Validate the data using get API after flag change */ -}, -{ - 0, 0 /* Index not used */ -}, -{ - VAL_ITS_REMOVE, PSA_ITS_ERROR_WRITE_ONCE /* Storage should not be removed after WRITE_ONCE flag */ -}, -{ - VAL_ITS_SET, PSA_ITS_SUCCESS /* Create a storage with different UID and flag value WRITE_ONCE */ -}, -{ - VAL_ITS_REMOVE, PSA_ITS_ERROR_WRITE_ONCE /* Storage should not be removed */ -}, -{ - VAL_ITS_GET, PSA_ITS_SUCCESS /* Validate the data using get API after flag change */ -}, -{ - 0, 0 /* Index not used */ -}, -{ - VAL_ITS_GET_INFO, PSA_ITS_SUCCESS /* Call the get_info API to validate the flag change */ -}, -{ - 0, 0 /* Index not used as check for get info size */ -}, -{ - 0, 0 /* Index not used as check for get info flag */ -}, -{ - VAL_ITS_SET, PSA_ITS_ERROR_WRITE_ONCE /* Try to set different size for same UID and flag value */ -}, -{ - VAL_ITS_REMOVE, PSA_ITS_ERROR_WRITE_ONCE /* Storage should not be removed */ -}, -{ - VAL_ITS_GET_INFO, PSA_ITS_SUCCESS /* Call the get_info API to validate the flag change */ -}, -{ - 0, 0 /* Index not used as check for get info size */ -}, -{ - 0, 0 /* Index not used as check for get info flag */ -}, -{ - VAL_ITS_GET, PSA_ITS_SUCCESS /* Validate the data using get API after flag change */ -}, -{ - 0, 0 /* Index not used */ -}, -{ - VAL_ITS_SET, PSA_ITS_ERROR_WRITE_ONCE /* Setting flag to zero for UID should fail */ -}, -{ - VAL_ITS_REMOVE, PSA_ITS_ERROR_WRITE_ONCE /* Storage should not be removed */ -}, -{ - VAL_ITS_GET_INFO, PSA_ITS_SUCCESS /* Check that the WRITE_ONCE flag is preserved */ -}, -{ - 0, 0 /* Index not used as check for get info size */ -}, -{ - 0, 0 /* Index not used as check for get info flag */ -}, -}; -#endif /* _TEST_S002_ITS_DATA_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/test_ps_data.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/test_ps_data.h deleted file mode 100644 index 19e88b7..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/test_ps_data.h +++ /dev/null @@ -1,134 +0,0 @@ -/** @file - * Copyright (c) 2019, Arm Limited or ps 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_S002_PS_DATA_TESTS_H_ -#define _TEST_S002_PS_DATA_TESTS_H_ - -#include "val_protected_storage.h" - -#define SST_FUNCTION val->ps_function -#define PSA_SST_FLAG_WRITE_ONCE PSA_PS_FLAG_WRITE_ONCE -#define psa_sst_uid_t psa_ps_uid_t - -typedef struct { - enum ps_function_code api; - psa_ps_status_t status; -} test_data; - -static struct psa_ps_info_t orig_info; -static struct psa_ps_info_t new_info; -static const test_data s002_data[] = { -{ - 0, 0 /* This is dummy for index0 */ -}, -{ - VAL_PS_SET, PSA_PS_SUCCESS /* Create a valid storage with create flag value 0 */ -}, -{ - VAL_PS_GET_INFO, PSA_PS_SUCCESS /* Call the get_info API to validate the attributes */ -}, -{ - 0, 0 /* Index not used as check for get info size */ -}, -{ - 0, 0 /* Index not used as check for get info flag */ -}, -{ - VAL_PS_GET, PSA_PS_SUCCESS /* Validate the data using get API */ -}, -{ - 0, 0 /* Index not used */ -}, -{ - VAL_PS_SET, PSA_PS_SUCCESS /* Change the flag to WRITE_ONCE using set API */ -}, -{ - VAL_PS_GET_INFO, PSA_PS_SUCCESS /* Call the get_info API to validate the flag change */ -}, -{ - 0, 0 /* Index not used as check for get info size */ -}, -{ - 0, 0 /* Index not used as check for get info flag */ -}, -{ - VAL_PS_GET, PSA_PS_SUCCESS /* Validate the data using get API after flag change */ -}, -{ - 0, 0 /* Index not used */ -}, -{ - VAL_PS_REMOVE, PSA_PS_ERROR_WRITE_ONCE /* Storage should not be removed after WRITE_ONCE flag */ -}, -{ - VAL_PS_SET, PSA_PS_SUCCESS /* Create storage with different UID and flag value WRITE_ONCE */ -}, -{ - VAL_PS_REMOVE, PSA_PS_ERROR_WRITE_ONCE /* Storage should not be removed */ -}, -{ - VAL_PS_GET, PSA_PS_SUCCESS /* Validate the data using get API after flag change */ -}, -{ - 0, 0 /* Index not used */ -}, -{ - VAL_PS_GET_INFO, PSA_PS_SUCCESS /* Call the get_info API to validate the flag change */ -}, -{ - 0, 0 /* Index not used as check for get info size */ -}, -{ - 0, 0 /* Index not used as check for get info flag */ -}, -{ - VAL_PS_SET, PSA_PS_ERROR_WRITE_ONCE /* Try to set different size for same UID and flag value */ -}, -{ - VAL_PS_REMOVE, PSA_PS_ERROR_WRITE_ONCE /* Storage should not be removed */ -}, -{ - VAL_PS_GET_INFO, PSA_PS_SUCCESS /* Call the get_info API to validate the flag change */ -}, -{ - 0, 0 /* Index not used as check for get info size */ -}, -{ - 0, 0 /* Index not used as check for get info flag */ -}, -{ - VAL_PS_GET, PSA_PS_SUCCESS /* Validate the data using get API after flag change */ -}, -{ - 0, 0 /* Index not used */ -}, -{ - VAL_PS_SET, PSA_PS_ERROR_WRITE_ONCE /* Setting flag to zero for UID should fail */ -}, -{ - VAL_PS_REMOVE, PSA_PS_ERROR_WRITE_ONCE /* Storage should not be removed */ -}, -{ - VAL_PS_GET_INFO, PSA_PS_SUCCESS /* Check that the WRITE_ONCE flag is preserved */ -}, -{ - 0, 0 /* Index not used as check for get info size */ -}, -{ - 0, 0 /* Index not used as check for get info flag */ -}, -}; -#endif /* _TEST_S002_PS_DATA_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/test_s002.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/test_s002.c deleted file mode 100644 index d46ace1..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/test_s002.c +++ /dev/null @@ -1,161 +0,0 @@ -/** @file - * Copyright (c) 2019, Arm Limited or sst 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 "val_target.h" -#include "test_s002.h" -#ifdef ITS_TEST -#include "test_its_data.h" -#elif PS_TEST -#include "test_ps_data.h" -#endif - -#define UID_WRITE_ONCE_1 UID_BASE_VALUE + 1 -#define UID_WRITE_ONCE_2 UID_BASE_VALUE + 2 -#define TEST_BUFF_SIZE 16 - -client_test_t test_s002_sst_list[] = { - NULL, - psa_sst_update_write_once_flag_after_create, - psa_sst_create_with_write_once_flag, - NULL, -}; - -int32_t psa_sst_update_write_once_flag_after_create(caller_security_t caller) -{ - uint32_t status; - psa_sst_uid_t uid = UID_WRITE_ONCE_1; - uint8_t write_buff[TEST_BUFF_SIZE/2] = {0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE, 0xBA, 0xBE}; - uint8_t read_buff[TEST_BUFF_SIZE/2] = {0}; - uint8_t write_buff_new[TEST_BUFF_SIZE/4] = {0xFF, 0xFF, 0xFF, 0xFF}; - - /* set() data without a WRITE_ONCE flag */ - status = SST_FUNCTION(s002_data[1].api, uid, TEST_BUFF_SIZE/2, write_buff, 0); - TEST_ASSERT_EQUAL(status, s002_data[1].status, TEST_CHECKPOINT_NUM(1)); - - /* Check that get_info() returns correct attributes; also store for reference for later */ - status = SST_FUNCTION(s002_data[2].api, uid, &orig_info); - TEST_ASSERT_EQUAL(status, s002_data[2].status, TEST_CHECKPOINT_NUM(2)); - TEST_ASSERT_EQUAL(orig_info.size, TEST_BUFF_SIZE/2, TEST_CHECKPOINT_NUM(3)); - TEST_ASSERT_EQUAL(orig_info.flags, 0, TEST_CHECKPOINT_NUM(4)); - - /* Check for data consistency using get() */ - status = SST_FUNCTION(s002_data[5].api, uid, 0, TEST_BUFF_SIZE/2, read_buff); - TEST_ASSERT_EQUAL(status, s002_data[5].status, TEST_CHECKPOINT_NUM(5)); - TEST_ASSERT_MEMCMP(write_buff, read_buff, TEST_BUFF_SIZE/2, TEST_CHECKPOINT_NUM(6)); - - /* set() with WRITE_ONCE_FLAG */ - val->print(PRINT_TEST, "[Check 1] Update the flag of UID %d with WRITE_ONCE flag\n", uid); - status = SST_FUNCTION(s002_data[7].api, uid, TEST_BUFF_SIZE/4, write_buff_new, - PSA_SST_FLAG_WRITE_ONCE); - TEST_ASSERT_EQUAL(status, s002_data[7].status, TEST_CHECKPOINT_NUM(7)); - - /* Check that info is updated, after new set */ - status = SST_FUNCTION(s002_data[8].api, uid, &new_info); - TEST_ASSERT_EQUAL(status, s002_data[8].status, TEST_CHECKPOINT_NUM(8)); - TEST_ASSERT_EQUAL(new_info.size, new_info.size, TEST_CHECKPOINT_NUM(9)); - TEST_ASSERT_EQUAL(new_info.flags, new_info.flags, TEST_CHECKPOINT_NUM(10)); - - /* Check that data contents are preserved which were written with WRITE_ONCE_FLAG originally */ - status = SST_FUNCTION(s002_data[11].api, uid, 0, TEST_BUFF_SIZE/4, read_buff); - TEST_ASSERT_EQUAL(status, s002_data[11].status, TEST_CHECKPOINT_NUM(11)); - TEST_ASSERT_MEMCMP(write_buff_new, read_buff, TEST_BUFF_SIZE/4, TEST_CHECKPOINT_NUM(12)); - - /* remove() the UID */ - val->print(PRINT_TEST, "[Check 2] Try to remove the UID %d having WRITE_ONCE flag\n", uid); - status = SST_FUNCTION(s002_data[13].api, uid); - TEST_ASSERT_EQUAL(status, s002_data[13].status, TEST_CHECKPOINT_NUM(13)); - - return VAL_STATUS_SUCCESS; -} - - -int32_t psa_sst_create_with_write_once_flag(caller_security_t caller) -{ - uint32_t status; - psa_sst_uid_t uid = UID_WRITE_ONCE_2; - uint8_t write_buff[TEST_BUFF_SIZE] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}; - uint8_t read_buff[TEST_BUFF_SIZE] = {0}; - uint8_t write_buff_new[TEST_BUFF_SIZE + 1] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF}; - - /* Set data for a UID using WRITE_ONCE flag */ - val->print(PRINT_TEST, "[Check 3] Create a new UID %d with WRITE_ONCE flag\n", uid); - status = SST_FUNCTION(s002_data[14].api, uid, TEST_BUFF_SIZE, write_buff, - PSA_SST_FLAG_WRITE_ONCE); - TEST_ASSERT_EQUAL(status, s002_data[14].status, TEST_CHECKPOINT_NUM(14)); - - /* Check that remove() fails with PSA_SST_ERROR_WRITE_ONCE */ - val->print(PRINT_TEST, "[Check 4] Try to remove the UID %d having WRITE_ONCE flag\n", uid); - status = SST_FUNCTION(s002_data[15].api, uid); - TEST_ASSERT_EQUAL(status, s002_data[15].status, TEST_CHECKPOINT_NUM(15)); - - /* Check data consistency using get()*/ - status = SST_FUNCTION(s002_data[16].api, uid, 0, TEST_BUFF_SIZE, read_buff); - TEST_ASSERT_EQUAL(status, s002_data[16].status, TEST_CHECKPOINT_NUM(16)); - TEST_ASSERT_MEMCMP(write_buff, read_buff, TEST_BUFF_SIZE, TEST_CHECKPOINT_NUM(17)); - - /* Check that info values is as expected */ - status = SST_FUNCTION(s002_data[18].api, uid, &orig_info); - TEST_ASSERT_EQUAL(status, s002_data[18].status, TEST_CHECKPOINT_NUM(18)); - TEST_ASSERT_EQUAL(orig_info.size, TEST_BUFF_SIZE, TEST_CHECKPOINT_NUM(19)); - TEST_ASSERT_EQUAL(orig_info.flags, PSA_SST_FLAG_WRITE_ONCE, TEST_CHECKPOINT_NUM(20)); - - /* Try to overwrite using set() with same UID as used before with WRITE_ONCE_FLAG */ - val->print(PRINT_TEST, "[Check 5] Try to change the length of write_once UID %d\n", uid); - status = SST_FUNCTION(s002_data[21].api, uid, (TEST_BUFF_SIZE + 1), write_buff_new, - PSA_SST_FLAG_WRITE_ONCE); - TEST_ASSERT_EQUAL(status, s002_data[21].status, TEST_CHECKPOINT_NUM(21)); - - /* Check that remove() still fails with PSA_SST_ERROR_WRITE_ONCE */ - val->print(PRINT_TEST, "[Check 6] Check UID removal still fails\n", 0); - status = SST_FUNCTION(s002_data[22].api, uid); - TEST_ASSERT_EQUAL(status, s002_data[22].status, TEST_CHECKPOINT_NUM(22)); - - /* Check that info is preserved */ - status = SST_FUNCTION(s002_data[23].api, uid, &new_info); - TEST_ASSERT_EQUAL(status, s002_data[23].status, TEST_CHECKPOINT_NUM(23)); - TEST_ASSERT_EQUAL(new_info.size, orig_info.size, TEST_CHECKPOINT_NUM(24)); - TEST_ASSERT_EQUAL(new_info.flags, orig_info.flags, TEST_CHECKPOINT_NUM(25)); - - /* Check that data contents are preserved which were written with WRITE_ONCE_FLAG originally */ - status = SST_FUNCTION(s002_data[26].api, uid, 0, TEST_BUFF_SIZE, read_buff); - TEST_ASSERT_EQUAL(status, s002_data[26].status, TEST_CHECKPOINT_NUM(26)); - TEST_ASSERT_MEMCMP(write_buff, read_buff, TEST_BUFF_SIZE, TEST_CHECKPOINT_NUM(27)); - - /* Try to overwrite using set() with same UID as used before without WRITE_ONCE_FLAG */ - val->print(PRINT_TEST, "[Check 7] Try to change the WRITE_ONCE flag to None for UID %d\n", uid); - new_info.size = 0; - new_info.flags = 0; - status = SST_FUNCTION(s002_data[28].api, uid, (TEST_BUFF_SIZE - 1), write_buff_new, 0); - TEST_ASSERT_EQUAL(status, s002_data[28].status, TEST_CHECKPOINT_NUM(28)); - - /* Check that remove() still fails with PSA_SST_ERROR_WRITE_ONCE */ - val->print(PRINT_TEST, "[Check 8] Check UID removal still fails\n", 0); - status = SST_FUNCTION(s002_data[29].api, uid); - TEST_ASSERT_EQUAL(status, s002_data[29].status, TEST_CHECKPOINT_NUM(29)); - - /* Check that info is preserved */ - status = SST_FUNCTION(s002_data[30].api, uid, &new_info); - TEST_ASSERT_EQUAL(status, s002_data[30].status, TEST_CHECKPOINT_NUM(30)); - TEST_ASSERT_EQUAL(new_info.size, orig_info.size, TEST_CHECKPOINT_NUM(31)); - TEST_ASSERT_EQUAL(new_info.flags, orig_info.flags, TEST_CHECKPOINT_NUM(32)); - - return VAL_STATUS_SUCCESS; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/test_s002.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/test_s002.h deleted file mode 100644 index 3a06eb9..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/test_s002.h +++ /dev/null @@ -1,36 +0,0 @@ -/** @file - * Copyright (c) 2019, 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_S002_CLIENT_TESTS_H_ -#define _TEST_S002_CLIENT_TESTS_H_ - -#ifdef ITS_TEST -#define VAL_STORAGE_BASE VAL_INTERNAL_TRUSTED_STORAGE_BASE -#define test_entry CONCAT(test_entry_, s002) -#elif PS_TEST -#define VAL_STORAGE_BASE VAL_PROTECTED_STORAGE_BASE -#define test_entry CONCAT(test_entry_, p002) -#endif -#define val CONCAT(val,test_entry) -#define psa CONCAT(psa,test_entry) - -extern val_api_t *val; -extern psa_api_t *psa; -extern client_test_t test_s002_sst_list[]; - -int32_t psa_sst_update_write_once_flag_after_create(caller_security_t caller); -int32_t psa_sst_create_with_write_once_flag(caller_security_t caller); -#endif /* _TEST_S002_CLIENT_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/main.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/main.c deleted file mode 100644 index fc7328c..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/main.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited and affiliates. - * 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 "pal_mbed_os_intf.h" -#include "lifecycle.h" - -#ifndef PS_ALLOW_ENTIRE_STORAGE_FILL -#error [NOT_SUPPORTED] Test is too long for CI, thus always fails on timeout. -#endif - -#ifdef ITS_TEST -void test_entry_s003(val_api_t *val_api, psa_api_t *psa_api); -#elif PS_TEST -void test_entry_p003(val_api_t *val_api, psa_api_t *psa_api); -#endif - -int main(void) -{ -#ifdef ITS_TEST - test_start(test_entry_s003, COMPLIANCE_TEST_STORAGE); -#elif PS_TEST - test_start(test_entry_p003, COMPLIANCE_TEST_STORAGE); -#endif - -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/test_entry.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/test_entry.c deleted file mode 100644 index 30dcbde..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/test_entry.c +++ /dev/null @@ -1,53 +0,0 @@ -/** @file - * Copyright (c) 2019, 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 "val_target.h" -#include "test_s003.h" - -#define TEST_NUM VAL_CREATE_TEST_ID(VAL_STORAGE_BASE, 3) -#define TEST_DESC "Insufficient space check\n" - -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; - - /* test init */ - val->test_init(TEST_NUM, TEST_DESC, TEST_FIELD(TEST_ISOLATION_L1, WD_HIGH_TIMEOUT)); - if (!IS_TEST_START(val->get_status())) - { - goto test_exit; - } - - /* Execute list of tests available in test[num]_secure_storage_list from Non-secure side*/ - status = val->execute_non_secure_tests(TEST_NUM, test_s003_sst_list, FALSE); - - if (VAL_ERROR(status)) - { - goto test_exit; - } - -test_exit: - val->test_exit(); -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/test_its_data.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/test_its_data.h deleted file mode 100644 index 511e418..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/test_its_data.h +++ /dev/null @@ -1,42 +0,0 @@ -/** @file - * Copyright (c) 2019, 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_S003_ITS_DATA_TESTS_H_ -#define _TEST_S003_ITS_DATA_TESTS_H_ - -#include "val_internal_trusted_storage.h" - -#define SST_FUNCTION val->its_function -#define PSA_SST_SUCCESS PSA_ITS_SUCCESS -#define psa_sst_uid_t psa_its_uid_t - -typedef struct { - enum its_function_code api; - psa_its_status_t status; -} test_data; - -static const test_data s003_data[] = { -{ - 0, 0 /* This is dummy for index0 */ -}, -{ - VAL_ITS_SET, PSA_ITS_ERROR_INSUFFICIENT_SPACE /* Call set API till insufficent space */ -}, -{ - VAL_ITS_REMOVE, PSA_ITS_SUCCESS /* Remove the UID created */ -}, -}; -#endif /* _TEST_S003_ITS_DATA_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/test_ps_data.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/test_ps_data.h deleted file mode 100644 index db48c35..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/test_ps_data.h +++ /dev/null @@ -1,42 +0,0 @@ -/** @file - * Copyright (c) 2019, Arm Limited or ps 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_S003_PS_DATA_TESTS_H_ -#define _TEST_S003_PS_DATA_TESTS_H_ - -#include "val_protected_storage.h" - -#define SST_FUNCTION val->ps_function -#define PSA_SST_SUCCESS PSA_PS_SUCCESS -#define psa_sst_uid_t psa_ps_uid_t - -typedef struct { - enum ps_function_code api; - psa_ps_status_t status; -} test_data; - -static const test_data s003_data[] = { -{ - 0, 0 /* This is dummy for index0 */ -}, -{ - VAL_PS_SET, PSA_PS_ERROR_INSUFFICIENT_SPACE /* Call set API till insufficent space */ -}, -{ - VAL_PS_REMOVE, PSA_PS_SUCCESS /* Remove the UID created */ -}, -}; -#endif /* _TEST_S003_PS_DATA_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/test_s003.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/test_s003.c deleted file mode 100644 index 3475075..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/test_s003.c +++ /dev/null @@ -1,96 +0,0 @@ -/** @file - * Copyright (c) 2019, 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 "val_target.h" -#include "test_s003.h" -#if ITS_TEST -#include "test_its_data.h" -#elif PS_TEST -#include "test_ps_data.h" -#endif - -#define TEST_BUFF_SIZE 1024 -#define NUM_ITERATIONS 2 -#define TEST_BASE_UID_VALUE UID_BASE_VALUE + 5 - -client_test_t test_s003_sst_list[] = { - NULL, - psa_sst_insufficient_space, - NULL, -}; - -static uint8_t write_buff[TEST_BUFF_SIZE]; -static char test_desc[2][80] = { - "Overload storage space\n", - "Overload storage again to verify all previous UID removed\n"}; - -int32_t psa_sst_insufficient_space(caller_security_t caller) -{ - uint32_t status = PSA_SST_SUCCESS; - psa_sst_uid_t uid; - uint32_t count = 0, results[NUM_ITERATIONS] = {0}; - int i = 0; - - /* Saturate the storage for NUM_ITERATION times, and remove them after */ - for (i = 0 ; i < NUM_ITERATIONS; i++) - { - val->print(PRINT_TEST, "[Check %d] ", i + 1); - val->print(PRINT_TEST, &test_desc[i][0], 0); - for (uid = TEST_BASE_UID_VALUE; status == PSA_SST_SUCCESS; uid++) - { - val->print(PRINT_INFO, "Setting 0x%x bytes for ", TEST_BUFF_SIZE); - val->print(PRINT_INFO, "UID %d\n", uid); - status = SST_FUNCTION(s003_data[1].api, uid, TEST_BUFF_SIZE, write_buff, 0); - if (status != PSA_SST_SUCCESS) - { - val->print(PRINT_INFO, "UID %d set failed due to insufficient space\n", uid); - break; - } - } - TEST_ASSERT_EQUAL(status, s003_data[1].status, TEST_CHECKPOINT_NUM(1)); - - /* Store number of set()s it took to saturate the storage */ - count = uid - (TEST_BASE_UID_VALUE); - results[i] = uid - (TEST_BASE_UID_VALUE); - - if (count) - val->print(PRINT_TEST, "Remove all registered UIDs\n", 0); - for (uid = TEST_BASE_UID_VALUE; uid < (count + TEST_BASE_UID_VALUE); uid++) - { - val->print(PRINT_INFO, "Removing UID %d\n", uid); - status = SST_FUNCTION(s003_data[2].api, uid); - if (status != PSA_SST_SUCCESS) - break; - } - if (count) - TEST_ASSERT_EQUAL(status, s003_data[2].status, TEST_CHECKPOINT_NUM(2)); - } - - /* Check that it takes equal number of UIDs to fill up the storage each time */ - for (i = 0; i < (NUM_ITERATIONS -1); i++) - { - if (results[i] != results[i+1]) - { - val->print(PRINT_ERROR, "\tERROR : Mismatch between number of UIDs required to\n", 0); - val->print(PRINT_ERROR, "\t fill up the storage between iteration %d", i); - val->print(PRINT_ERROR, " and iteration %d\n", i+1); - return VAL_STATUS_ERROR; - } - } - return VAL_STATUS_SUCCESS; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/test_s003.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/test_s003.h deleted file mode 100644 index 9fb4755..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/test_s003.h +++ /dev/null @@ -1,35 +0,0 @@ -/** @file - * Copyright (c) 2019, 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_S003_CLIENT_TESTS_H_ -#define _TEST_S003_CLIENT_TESTS_H_ - -#ifdef ITS_TEST -#define VAL_STORAGE_BASE VAL_INTERNAL_TRUSTED_STORAGE_BASE -#define test_entry CONCAT(test_entry_, s003) -#elif PS_TEST -#define VAL_STORAGE_BASE VAL_PROTECTED_STORAGE_BASE -#define test_entry CONCAT(test_entry_, p003) -#endif -#define val CONCAT(val,test_entry) -#define psa CONCAT(psa,test_entry) - -extern val_api_t *val; -extern psa_api_t *psa; -extern client_test_t test_s003_sst_list[]; - -int32_t psa_sst_insufficient_space(caller_security_t caller); -#endif /* _TEST_S003_CLIENT_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/main.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/main.c deleted file mode 100644 index 20a623e..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/main.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited and affiliates. - * 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 "pal_mbed_os_intf.h" -#if !defined(MBED_CONF_RTOS_PRESENT) -#error [NOT_SUPPORTED] PSA compliance its test cases require RTOS to run -#else - -#ifdef ITS_TEST -void test_entry_s004(val_api_t *val_api, psa_api_t *psa_api); -#elif PS_TEST -void test_entry_p004(val_api_t *val_api, psa_api_t *psa_api); -#endif - -int main(void) -{ -#ifdef ITS_TEST - test_start(test_entry_s004, COMPLIANCE_TEST_STORAGE); -#elif PS_TEST - test_start(test_entry_p004, COMPLIANCE_TEST_STORAGE); -#endif -} -#endif // !defined(MBED_CONF_RTOS_PRESENT) diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/test_entry.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/test_entry.c deleted file mode 100644 index a6afc24..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/test_entry.c +++ /dev/null @@ -1,53 +0,0 @@ -/** @file - * Copyright (c) 2019, 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 "val_target.h" -#include "test_s004.h" - -#define TEST_NUM VAL_CREATE_TEST_ID(VAL_STORAGE_BASE, 4) -#define TEST_DESC "Data Consistency check\n" - -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; - - /* test init */ - val->test_init(TEST_NUM, TEST_DESC, TEST_FIELD(TEST_ISOLATION_L1, WD_HIGH_TIMEOUT)); - if (!IS_TEST_START(val->get_status())) - { - goto test_exit; - } - - /* Execute list of tests available in test[num]_secure_storage_list from Non-secure side*/ - status = val->execute_non_secure_tests(TEST_NUM, test_s004_sst_list, FALSE); - - if (VAL_ERROR(status)) - { - goto test_exit; - } - -test_exit: - val->test_exit(); -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/test_its_data.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/test_its_data.h deleted file mode 100644 index b41dc1b..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/test_its_data.h +++ /dev/null @@ -1,65 +0,0 @@ -/** @file - * Copyright (c) 2019, 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_S004_ITS_DATA_TESTS_H_ -#define _TEST_S004_ITS_DATA_TESTS_H_ - -#include "val_internal_trusted_storage.h" - -#define SST_FUNCTION val->its_function -#define psa_sst_uid_t psa_its_uid_t - -typedef struct { - enum its_function_code api; - psa_its_status_t status; -} test_data; - -static const test_data s004_data[] = { -{ - 0, 0 /* This is dummy for index0 */ -}, -{ - VAL_ITS_SET, PSA_ITS_SUCCESS /* Create a valid storage entity */ -}, -{ - VAL_ITS_GET, PSA_ITS_SUCCESS /* Validate the data using get API after set API failure */ -}, -{ - 0, 0 /* Index not used */ -}, -{ - VAL_ITS_SET, PSA_ITS_SUCCESS /* For same UID set the length as half of previous */ -}, -{ - VAL_ITS_GET, PSA_ITS_ERROR_INCORRECT_SIZE /* Call get with incorrect length */ -}, -{ - 0, 0 /* No data should be returned */ -}, -{ - VAL_ITS_GET, PSA_ITS_SUCCESS /* Call get API with correct length */ -}, -{ - 0, 0 /* No data should be returned */ -}, -{ - 0, 0 /* Check that we should not be able to access the old data */ -}, -{ - VAL_ITS_REMOVE, PSA_ITS_SUCCESS /* Remove the valid storage entity */ -}, -}; -#endif /* _TEST_S004_ITS_DATA_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/test_ps_data.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/test_ps_data.h deleted file mode 100644 index baaf194..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/test_ps_data.h +++ /dev/null @@ -1,65 +0,0 @@ -/** @file - * Copyright (c) 2019, Arm Limited or ps 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_S004_PS_DATA_TESTS_H_ -#define _TEST_S004_PS_DATA_TESTS_H_ - -#include "val_protected_storage.h" - -#define SST_FUNCTION val->ps_function -#define psa_sst_uid_t psa_ps_uid_t - -typedef struct { - enum ps_function_code api; - psa_ps_status_t status; -} test_data; - -static const test_data s004_data[] = { -{ - 0, 0 /* This is dummy for index0 */ -}, -{ - VAL_PS_SET, PSA_PS_SUCCESS /* Create a valid storage entity */ -}, -{ - VAL_PS_GET, PSA_PS_SUCCESS /* Validate the data using get API after set API failure */ -}, -{ - 0, 0 /* Index not used */ -}, -{ - VAL_PS_SET, PSA_PS_SUCCESS /* For same UID set the length as half of previous */ -}, -{ - VAL_PS_GET, PSA_PS_ERROR_INCORRECT_SIZE /* Call get with incorrect length */ -}, -{ - 0, 0 /* No data should be returned */ -}, -{ - VAL_PS_GET, PSA_PS_SUCCESS /* Call get API with correct length */ -}, -{ - 0, 0 /* No data should be returned */ -}, -{ - 0, 0 /* Check that we should not be able to access the old data */ -}, -{ - VAL_PS_REMOVE, PSA_PS_SUCCESS /* Remove the valid storage entity */ -}, -}; -#endif /* _TEST_S004_PS_DATA_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/test_s004.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/test_s004.c deleted file mode 100644 index 004ee2f..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/test_s004.c +++ /dev/null @@ -1,84 +0,0 @@ -/** @file - * Copyright (c) 2019, 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 "val_target.h" -#include "test_s004.h" -#ifdef ITS_TEST -#include "test_its_data.h" -#elif PS_TEST -#include "test_ps_data.h" -#endif - -#define TEST_BUFF_SIZE 20 - -client_test_t test_s004_sst_list[] = { - NULL, - psa_sst_get_data_check, - NULL, -}; - -static psa_sst_uid_t uid = UID_BASE_VALUE + 5; -static uint8_t read_buff[TEST_BUFF_SIZE] = {0}; -static uint8_t write_buff[TEST_BUFF_SIZE] = {0x99, 0x01, 0x30, 0x50, 0x04, 0x23, 0xF6, 0x07, 0x08, \ - 0x0D, 0x70, 0xA1, 0xFF, 0xFF, 0x14, 0x73, 0x46, 0x97, 0xE8, 0xDD}; - -int32_t psa_sst_get_data_check(caller_security_t caller) -{ - uint32_t status,j; - - /* Set data for UID */ - status = SST_FUNCTION(s004_data[1].api, uid, TEST_BUFF_SIZE, write_buff,0); - TEST_ASSERT_EQUAL(status, s004_data[1].status, TEST_CHECKPOINT_NUM(1)); - - /* Call get function and check the data consistency */ - status = SST_FUNCTION(s004_data[2].api, uid, 0, TEST_BUFF_SIZE, read_buff); - TEST_ASSERT_EQUAL(status, s004_data[2].status, TEST_CHECKPOINT_NUM(2)); - TEST_ASSERT_MEMCMP(read_buff, write_buff, TEST_BUFF_SIZE, TEST_CHECKPOINT_NUM(3)); - - /* Call the set again for same uid and set the length as half */ - status = SST_FUNCTION(s004_data[4].api, uid, TEST_BUFF_SIZE/2, write_buff, 0); - TEST_ASSERT_EQUAL(status, s004_data[4].status, TEST_CHECKPOINT_NUM(4)); - - /* Call get function with incorrect buffer length */ - val->print(PRINT_TEST, "[Check 1] Call get API with incorrect length\n", 0); - memset(read_buff, 0, TEST_BUFF_SIZE); - status = SST_FUNCTION(s004_data[5].api, uid, 0, TEST_BUFF_SIZE, read_buff); - TEST_ASSERT_EQUAL(status, s004_data[5].status, TEST_CHECKPOINT_NUM(5)); - for (j = 0; j < TEST_BUFF_SIZE; j++) - { - TEST_ASSERT_EQUAL(read_buff[j], 0, TEST_CHECKPOINT_NUM(6)); - } - - /* Call get function with CORRECT buffer length */ - status = SST_FUNCTION(s004_data[7].api, uid, 0, TEST_BUFF_SIZE/2, read_buff); - TEST_ASSERT_EQUAL(status, s004_data[7].status, TEST_CHECKPOINT_NUM(7)); - TEST_ASSERT_MEMCMP(read_buff, write_buff, TEST_BUFF_SIZE/2, TEST_CHECKPOINT_NUM(8)); - - /* Check we should not be able to access old set data */ - val->print(PRINT_TEST, "[Check 2] Old buffer invalid after length change\n", 0); - for (j = TEST_BUFF_SIZE/2; j < TEST_BUFF_SIZE; j++) - { - TEST_ASSERT_EQUAL(read_buff[j], 0, TEST_CHECKPOINT_NUM(9)); - } - - /* Remove the UID */ - status = SST_FUNCTION(s004_data[10].api, uid); - TEST_ASSERT_EQUAL(status, s004_data[10].status, TEST_CHECKPOINT_NUM(10)); - - return VAL_STATUS_SUCCESS; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/test_s004.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/test_s004.h deleted file mode 100644 index 03c6ad1..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/test_s004.h +++ /dev/null @@ -1,35 +0,0 @@ -/** @file - * Copyright (c) 2019, 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_S004_CLIENT_TESTS_H_ -#define _TEST_S004_CLIENT_TESTS_H_ - -#ifdef ITS_TEST -#define VAL_STORAGE_BASE VAL_INTERNAL_TRUSTED_STORAGE_BASE -#define test_entry CONCAT(test_entry_, s004) -#elif PS_TEST -#define VAL_STORAGE_BASE VAL_PROTECTED_STORAGE_BASE -#define test_entry CONCAT(test_entry_, p004) -#endif -#define val CONCAT(val,test_entry) -#define psa CONCAT(psa,test_entry) - -extern val_api_t *val; -extern psa_api_t *psa; -extern client_test_t test_s004_sst_list[]; - -int32_t psa_sst_get_data_check(caller_security_t caller); -#endif /* _TEST_S004_CLIENT_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/main.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/main.c deleted file mode 100644 index b15f531..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/main.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited and affiliates. - * 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 "pal_mbed_os_intf.h" - -#if !defined(MBED_CONF_RTOS_PRESENT) -#error [NOT_SUPPORTED] PSA compliance its test cases require RTOS to run -#else - -#ifdef ITS_TEST -void test_entry_s005(val_api_t *val_api, psa_api_t *psa_api); -#elif PS_TEST -void test_entry_p005(val_api_t *val_api, psa_api_t *psa_api); -#endif - -int main(void) -{ -#ifdef ITS_TEST - test_start(test_entry_s005, COMPLIANCE_TEST_STORAGE); -#elif PS_TEST - test_start(test_entry_p005, COMPLIANCE_TEST_STORAGE); -#endif -} -#endif // !defined(MBED_CONF_RTOS_PRESENT) diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/test_entry.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/test_entry.c deleted file mode 100644 index 36dcbaa..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/test_entry.c +++ /dev/null @@ -1,52 +0,0 @@ -/** @file - * Copyright (c) 2019, 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 "val_target.h" -#include "test_s005.h" - -#define TEST_NUM VAL_CREATE_TEST_ID(VAL_STORAGE_BASE, 5) -#define TEST_DESC "Success scenarios check\n" - -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; - - /* test init */ - val->test_init(TEST_NUM, TEST_DESC, TEST_FIELD(TEST_ISOLATION_L1, WD_HIGH_TIMEOUT)); - if (!IS_TEST_START(val->get_status())) - { - goto test_exit; - } - - /* Execute list of tests available in test[num]_secure_storage_list from Non-secure side*/ - status = val->execute_non_secure_tests(TEST_NUM, test_s005_sst_list, FALSE); - if (VAL_ERROR(status)) - { - goto test_exit; - } - -test_exit: - val->test_exit(); -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/test_its_data.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/test_its_data.h deleted file mode 100644 index 653f7cc..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/test_its_data.h +++ /dev/null @@ -1,58 +0,0 @@ -/** @file - * Copyright (c) 2019, 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_S005_ITS_DATA_TESTS_H_ -#define _TEST_S005_ITS_DATA_TESTS_H_ - -#include "val_internal_trusted_storage.h" - -#define SST_FUNCTION val->its_function -#define psa_sst_uid_t psa_its_uid_t -#define psa_sst_create_flags_t psa_its_create_flags_t - -typedef struct { - enum its_function_code api; - psa_its_status_t status; -} test_data; - -static struct psa_its_info_t info; -static const test_data s005_data[] = { -{ - 0, 0 /* This is dummy for index0 */ -}, -{ - VAL_ITS_SET, PSA_ITS_SUCCESS /* Create a valid storage entity */ -}, -{ - VAL_ITS_GET, PSA_ITS_SUCCESS /* Validate the data using get API */ -}, -{ - 0, 0 /* Index not used */ -}, -{ - VAL_ITS_GET_INFO, PSA_ITS_SUCCESS /* Validate the data attributes get_info API */ -}, -{ - 0, 0 /* Index not used */ -}, -{ - 0, 0 /* Index not used */ -}, -{ - VAL_ITS_REMOVE, PSA_ITS_SUCCESS /* Remove the valid storage entity */ -}, -}; -#endif /* _TEST_S005_ITS_DATA_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/test_ps_data.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/test_ps_data.h deleted file mode 100644 index a961269..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/test_ps_data.h +++ /dev/null @@ -1,58 +0,0 @@ -/** @file - * Copyright (c) 2019, Arm Limited or ps 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_S005_PS_DATA_TESTS_H_ -#define _TEST_S005_PS_DATA_TESTS_H_ - -#include "val_protected_storage.h" - -#define SST_FUNCTION val->ps_function -#define psa_sst_uid_t psa_ps_uid_t -#define psa_sst_create_flags_t psa_ps_create_flags_t - -typedef struct { - enum ps_function_code api; - psa_ps_status_t status; -} test_data; - -static struct psa_ps_info_t info; -static const test_data s005_data[] = { -{ - 0, 0 /* This is dummy for index0 */ -}, -{ - VAL_PS_SET, PSA_PS_SUCCESS /* Create a valid storage entity */ -}, -{ - VAL_PS_GET, PSA_PS_SUCCESS /* Validate the data using get API */ -}, -{ - 0, 0 /* Index not used */ -}, -{ - VAL_PS_GET_INFO, PSA_PS_SUCCESS /* Validate the data attributes get_info API */ -}, -{ - 0, 0 /* Index not used */ -}, -{ - 0, 0 /* Index not used */ -}, -{ - VAL_PS_REMOVE, PSA_PS_SUCCESS /* Remove the valid storage entity */ -}, -}; -#endif /* _TEST_S005_PS_DATA_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/test_s005.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/test_s005.c deleted file mode 100644 index c974d04..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/test_s005.c +++ /dev/null @@ -1,89 +0,0 @@ -/** @file - * Copyright (c) 2019, 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 "val_target.h" -#include "test_s005.h" -#ifdef ITS_TEST -#include "test_its_data.h" -#elif PS_TEST -#include "test_ps_data.h" -#endif - -#define TEST_BUFF_SIZE 30 - -client_test_t test_s005_sst_list[] = { - NULL, - psa_sst_apis_check_success_case, - NULL, -}; - -static uint8_t read_buff[TEST_BUFF_SIZE]; -static uint8_t write_buff[TEST_BUFF_SIZE] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x23, 0xF6, 0x07, 0x08, 0x0D, 0x0A, 0x1B, 0x0C, 0x5D, 0x0E,\ - 0x70, 0xA1, 0xFF, 0xFF, 0x14, 0x73, 0x46, 0x97, 0xE8, 0xDD, 0xCA, 0x0B, 0x3C, 0x0D, 0x2E}; - -static int32_t psa_sst_apis_check(psa_sst_uid_t uid, uint32_t data_len, - uint8_t *data_buff, psa_sst_create_flags_t create_flag) -{ - uint32_t status; - - /* Set the UID with the data_len and data_buff */ - status = SST_FUNCTION(s005_data[1].api, uid, data_len, data_buff, create_flag); - TEST_ASSERT_EQUAL(status, s005_data[1].status, TEST_CHECKPOINT_NUM(1)); - - /* Call the get function to get the data buffer and match the buffer */ - status = SST_FUNCTION(s005_data[2].api, uid, 0, data_len, read_buff); - TEST_ASSERT_EQUAL(status, s005_data[2].status, TEST_CHECKPOINT_NUM(2)); - TEST_ASSERT_MEMCMP(read_buff, data_buff, data_len, TEST_CHECKPOINT_NUM(3)); - - /* Call the get_info function and match the attributes */ - status = SST_FUNCTION(s005_data[4].api, uid, &info); - TEST_ASSERT_EQUAL(status, s005_data[4].status, TEST_CHECKPOINT_NUM(4)); - TEST_ASSERT_EQUAL(info.size, data_len, TEST_CHECKPOINT_NUM(5)); - TEST_ASSERT_EQUAL(info.flags, create_flag, TEST_CHECKPOINT_NUM(6)); - - /* Remove the UID */ - status = SST_FUNCTION(s005_data[7].api, uid); - TEST_ASSERT_EQUAL(status, s005_data[7].status, TEST_CHECKPOINT_NUM(7)); - - return VAL_STATUS_SUCCESS; -} - -int32_t psa_sst_apis_check_success_case(caller_security_t caller) -{ - psa_sst_uid_t uid = UID_BASE_VALUE + 4; - uint32_t data_len = 0, status = VAL_STATUS_SUCCESS; - - /* Calling set function with data_len 1 and valid data pointer */ - val->print(PRINT_TEST, "[Check 1] Set UID with data length zero and call storage APIs\n", 0); - if (psa_sst_apis_check(uid, data_len, write_buff, 0)) - { - val->print(PRINT_ERROR, "Data Len = %d\n", data_len); - return VAL_STATUS_ERROR; - } - - data_len = TEST_BUFF_SIZE/2; - val->print(PRINT_TEST, "[Check 2] Resetting the length check\n", 0); - if (psa_sst_apis_check(uid, data_len, write_buff, 0)) - { - val->print(PRINT_ERROR, "Data Len = %d\n", data_len); - return VAL_STATUS_ERROR; - } - - return status; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/test_s005.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/test_s005.h deleted file mode 100644 index 9451737..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/test_s005.h +++ /dev/null @@ -1,36 +0,0 @@ -/** @file - * Copyright (c) 2019, 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_S005_CLIENT_TESTS_H_ -#define _TEST_S005_CLIENT_TESTS_H_ - -#ifdef ITS_TEST -#define VAL_STORAGE_BASE VAL_INTERNAL_TRUSTED_STORAGE_BASE -#define test_entry CONCAT(test_entry_, s005) -#elif PS_TEST -#define VAL_STORAGE_BASE VAL_PROTECTED_STORAGE_BASE -#define test_entry CONCAT(test_entry_, p005) -#endif -#define val CONCAT(val,test_entry) -#define psa CONCAT(psa,test_entry) - -extern val_api_t *val; -extern psa_api_t *psa; -extern client_test_t test_s005_sst_list[]; - -int32_t psa_sst_apis_check_success_case(caller_security_t caller); - -#endif /* _TEST_S005_CLIENT_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/main.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/main.c deleted file mode 100644 index 1a24de7..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/main.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited and affiliates. - * 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 "pal_mbed_os_intf.h" - -#if !defined(MBED_CONF_RTOS_PRESENT) -#error [NOT_SUPPORTED] PSA compliance its test cases require RTOS to run -#else - -#ifdef ITS_TEST -void test_entry_s006(val_api_t *val_api, psa_api_t *psa_api); -#elif PS_TEST -void test_entry_p006(val_api_t *val_api, psa_api_t *psa_api); -#endif - -int main(void) -{ -#ifdef ITS_TEST - test_start(test_entry_s006, COMPLIANCE_TEST_STORAGE); -#elif PS_TEST - test_start(test_entry_p006, COMPLIANCE_TEST_STORAGE); -#endif -} -#endif // !defined(MBED_CONF_RTOS_PRESENT) diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/test_entry.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/test_entry.c deleted file mode 100644 index dda491b..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/test_entry.c +++ /dev/null @@ -1,52 +0,0 @@ -/** @file - * Copyright (c) 2019, 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 "val_target.h" -#include "test_s006.h" - -#define TEST_NUM VAL_CREATE_TEST_ID(VAL_STORAGE_BASE, 6) -#define TEST_DESC "Flags not supported check\n" - -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; - - /* test init */ - val->test_init(TEST_NUM, TEST_DESC, TEST_FIELD(TEST_ISOLATION_L1, WD_HIGH_TIMEOUT)); - if (!IS_TEST_START(val->get_status())) - { - goto test_exit; - } - - /* Execute list of tests available in test[num]_secure_storage_list from Non-secure side*/ - status = val->execute_non_secure_tests(TEST_NUM, test_s006_sst_list, FALSE); - if (VAL_ERROR(status)) - { - goto test_exit; - } - -test_exit: - val->test_exit(); -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/test_its_data.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/test_its_data.h deleted file mode 100644 index 4426f2c..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/test_its_data.h +++ /dev/null @@ -1,53 +0,0 @@ -/** @file - * Copyright (c) 2019, 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_S006_ITS_DATA_TESTS_H_ -#define _TEST_S006_ITS_DATA_TESTS_H_ - -#include "val_internal_trusted_storage.h" - -#define SST_FUNCTION val->its_function -#define PSA_SST_FLAG_WRITE_ONCE PSA_ITS_FLAG_WRITE_ONCE -#define psa_sst_uid_t psa_its_uid_t -#define psa_sst_create_flags_t psa_its_create_flags_t - -typedef struct { - enum its_function_code api; - psa_its_status_t status; -} test_data; - -static struct psa_its_info_t info; -static const test_data s006_data[] = { -{ - 0, PSA_ITS_ERROR_FLAGS_NOT_SUPPORTED /* This is dummy for index0 */ -}, -{ - VAL_ITS_SET, PSA_ITS_SUCCESS /* Create a valid storage entity with different flag values */ -}, -{ - VAL_ITS_GET_INFO, PSA_ITS_SUCCESS /* Validate the flag value get_info API */ -}, -{ - 0, 0 /* Index not used */ -}, -{ - VAL_ITS_REMOVE, PSA_ITS_SUCCESS /* Remove the storage entity */ -}, -{ - VAL_ITS_REMOVE, PSA_ITS_ERROR_UID_NOT_FOUND /* Storage entity remove fails */ -}, -}; -#endif /* _TEST_S006_ITS_DATA_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/test_ps_data.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/test_ps_data.h deleted file mode 100644 index 86e1e30..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/test_ps_data.h +++ /dev/null @@ -1,53 +0,0 @@ -/** @file - * Copyright (c) 2019, Arm Limited or ps 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_S006_PS_DATA_TESTS_H_ -#define _TEST_S006_PS_DATA_TESTS_H_ - -#include "val_protected_storage.h" - -#define SST_FUNCTION val->ps_function -#define PSA_SST_FLAG_WRITE_ONCE PSA_PS_FLAG_WRITE_ONCE -#define psa_sst_uid_t psa_ps_uid_t -#define psa_sst_create_flags_t psa_ps_create_flags_t - -typedef struct { - enum ps_function_code api; - psa_ps_status_t status; -} test_data; - -static struct psa_ps_info_t info; -static const test_data s006_data[] = { -{ - 0, PSA_PS_ERROR_FLAGS_NOT_SUPPORTED /* This is dummy for index0 */ -}, -{ - VAL_PS_SET, PSA_PS_SUCCESS /* Create a valid storage entity with different flag values */ -}, -{ - VAL_PS_GET_INFO, PSA_PS_SUCCESS /* Validate the flag value get_info API */ -}, -{ - 0, 0 /* Index not used */ -}, -{ - VAL_PS_REMOVE, PSA_PS_SUCCESS /* Remove the storage entity */ -}, -{ - VAL_PS_REMOVE, PSA_PS_ERROR_UID_NOT_FOUND /* Remove the storage entity */ -} -}; -#endif /* _TEST_S006_PS_DATA_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/test_s006.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/test_s006.c deleted file mode 100644 index 26b8984..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/test_s006.c +++ /dev/null @@ -1,90 +0,0 @@ -/** @file - * Copyright (c) 2019, 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 "val_target.h" -#include "test_s006.h" -#ifdef ITS_TEST -#include "test_its_data.h" -#elif PS_TEST -#include "test_ps_data.h" -#endif - -#define TEST_BUFF_SIZE 30 - -client_test_t test_s006_sst_list[] = { - NULL, - psa_sst_flags_not_supported, - NULL, -}; - -static uint8_t write_buff[TEST_BUFF_SIZE] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x23, 0xF6, 0x07, 0x08, 0x0D, 0x0A, 0x1B, 0x0C, 0x5D, 0x0E,\ - 0x70, 0xA1, 0xFF, 0xFF, 0x14, 0x73, 0x46, 0x97, 0xE8, 0xDD, 0xCA, 0x0B, 0x3C, 0x0D, 0x2E}; - -static int32_t psa_sst_remove_api(psa_sst_uid_t uid, uint32_t data_len, - uint8_t *data_buff, psa_sst_create_flags_t create_flag) -{ - uint32_t status; - - /* Call the get_info function and match the attributes */ - status = SST_FUNCTION(s006_data[2].api, uid, &info); - TEST_ASSERT_EQUAL(status, s006_data[2].status, TEST_CHECKPOINT_NUM(2)); - TEST_ASSERT_EQUAL(info.flags, create_flag, TEST_CHECKPOINT_NUM(3)); - - /* Remove the UID */ - status = SST_FUNCTION(s006_data[4].api, uid); - TEST_ASSERT_EQUAL(status, s006_data[4].status, TEST_CHECKPOINT_NUM(4)); - - return VAL_STATUS_SUCCESS; -} - -int32_t psa_sst_flags_not_supported(caller_security_t caller) -{ - psa_sst_create_flags_t flag = 0x80000000; - uint32_t status = VAL_STATUS_SUCCESS; - psa_sst_uid_t uid = UID_BASE_VALUE + 5; - int32_t test_status; - - /* Calling set function with different create flag value */ - - val->print(PRINT_TEST, "[Check 1] Call set API with valid flag values\n", 0); - while (flag) - { - /* Create storage with flag value */ - status = SST_FUNCTION(s006_data[1].api, uid, TEST_BUFF_SIZE, write_buff, - (flag & (~PSA_SST_FLAG_WRITE_ONCE))); - - if (status == s006_data[1].status) - { - test_status = psa_sst_remove_api(uid, TEST_BUFF_SIZE, write_buff, - (flag & (~PSA_SST_FLAG_WRITE_ONCE))); - if (test_status != VAL_STATUS_SUCCESS) - return test_status; - } - else if (status == s006_data[0].status) - { - /* Remove UID should fail */ - status = SST_FUNCTION(s006_data[5].api, uid); - TEST_ASSERT_EQUAL(status, s006_data[5].status, TEST_CHECKPOINT_NUM(5)); - } - - flag = flag >> 1; - }; - - return status; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/test_s006.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/test_s006.h deleted file mode 100644 index 9e79324..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/test_s006.h +++ /dev/null @@ -1,36 +0,0 @@ -/** @file - * Copyright (c) 2019, 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_S006_CLIENT_TESTS_H_ -#define _TEST_S006_CLIENT_TESTS_H_ - -#ifdef ITS_TEST -#define VAL_STORAGE_BASE VAL_INTERNAL_TRUSTED_STORAGE_BASE -#define test_entry CONCAT(test_entry_, s006) -#elif PS_TEST -#define VAL_STORAGE_BASE VAL_PROTECTED_STORAGE_BASE -#define test_entry CONCAT(test_entry_, p006) -#endif -#define val CONCAT(val,test_entry) -#define psa CONCAT(psa,test_entry) - -extern val_api_t *val; -extern psa_api_t *psa; -extern client_test_t test_s006_sst_list[]; - -int32_t psa_sst_flags_not_supported(caller_security_t caller); - -#endif /* _TEST_S006_CLIENT_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/main.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/main.c deleted file mode 100644 index a63001e..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/main.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited and affiliates. - * 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 "pal_mbed_os_intf.h" - -#if !defined(MBED_CONF_RTOS_PRESENT) -#error [NOT_SUPPORTED] PSA compliance its test cases require RTOS to run -#else - -#ifdef ITS_TEST -void test_entry_s007(val_api_t *val_api, psa_api_t *psa_api); -#elif PS_TEST -void test_entry_p007(val_api_t *val_api, psa_api_t *psa_api); -#endif - -int main(void) -{ -#ifdef ITS_TEST - test_start(test_entry_s007, COMPLIANCE_TEST_STORAGE); -#elif PS_TEST - test_start(test_entry_p007, COMPLIANCE_TEST_STORAGE); -#endif -} -#endif // !defined(MBED_CONF_RTOS_PRESENT) diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/test_entry.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/test_entry.c deleted file mode 100644 index f6005a1..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/test_entry.c +++ /dev/null @@ -1,52 +0,0 @@ -/** @file - * Copyright (c) 2019, 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 "val_target.h" -#include "test_s007.h" - -#define TEST_NUM VAL_CREATE_TEST_ID(VAL_STORAGE_BASE, 7) -#define TEST_DESC "Incorrect Size check\n" - -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; - - /* test init */ - val->test_init(TEST_NUM, TEST_DESC, TEST_FIELD(TEST_ISOLATION_L1, WD_HIGH_TIMEOUT)); - if (!IS_TEST_START(val->get_status())) - { - goto test_exit; - } - - /* Execute list of tests available in test[num]_secure_storage_list from Non-secure side*/ - status = val->execute_non_secure_tests(TEST_NUM, test_s007_sst_list, FALSE); - if (VAL_ERROR(status)) - { - goto test_exit; - } - -test_exit: - val->test_exit(); -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/test_its_data.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/test_its_data.h deleted file mode 100644 index 550dffb..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/test_its_data.h +++ /dev/null @@ -1,65 +0,0 @@ -/** @file - * Copyright (c) 2019, 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_S007_ITS_DATA_TESTS_H_ -#define _TEST_S007_ITS_DATA_TESTS_H_ - -#include "val_internal_trusted_storage.h" - -#define SST_FUNCTION val->its_function -#define psa_sst_uid_t psa_its_uid_t - -typedef struct { - enum its_function_code api; - psa_its_status_t status; -} test_data; - -static const test_data s007_data[] = { -{ - 0, 0 /* This is dummy for index0 */ -}, -{ - VAL_ITS_SET, PSA_ITS_SUCCESS /* Create a valid storage entity */ -}, -{ - VAL_ITS_SET, PSA_ITS_SUCCESS /* Increase the length of storage */ -}, -{ - VAL_ITS_GET, PSA_ITS_SUCCESS /* Try to access old length */ -}, -{ - VAL_ITS_GET, PSA_ITS_SUCCESS /* Try to access valid length less than set length */ -}, -{ - 0, 0 /* This is dummy for index5 */ -}, -{ - VAL_ITS_SET, PSA_ITS_SUCCESS /* Decrease the length of storage */ -}, -{ - VAL_ITS_GET, PSA_ITS_ERROR_INCORRECT_SIZE /* Try to access old length */ -}, -{ - VAL_ITS_GET, PSA_ITS_ERROR_INCORRECT_SIZE /* Try to access old length */ -}, -{ - VAL_ITS_GET, PSA_ITS_SUCCESS /* Try to access data with correct length */ -}, -{ - VAL_ITS_REMOVE, PSA_ITS_SUCCESS /* Remove the storage entity */ -}, -}; -#endif /* _TEST_S007_ITS_DATA_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/test_ps_data.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/test_ps_data.h deleted file mode 100644 index fa032c1..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/test_ps_data.h +++ /dev/null @@ -1,65 +0,0 @@ -/** @file - * Copyright (c) 2019, Arm Limited or ps 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_S007_PS_DATA_TESTS_H_ -#define _TEST_S007_PS_DATA_TESTS_H_ - -#include "val_protected_storage.h" - -#define SST_FUNCTION val->ps_function -#define psa_sst_uid_t psa_ps_uid_t - -typedef struct { - enum ps_function_code api; - psa_ps_status_t status; -} test_data; - -static const test_data s007_data[] = { -{ - 0, 0 /* This is dummy for index0 */ -}, -{ - VAL_PS_SET, PSA_PS_SUCCESS /* Create a valid storage entity */ -}, -{ - VAL_PS_SET, PSA_PS_SUCCESS /* Increase the length of storage */ -}, -{ - VAL_PS_GET, PSA_PS_SUCCESS /* Try to access old length */ -}, -{ - VAL_PS_GET, PSA_PS_SUCCESS /* Try to access valid length less than set length */ -}, -{ - 0, 0 /* This is dummy for index5 */ -}, -{ - VAL_PS_SET, PSA_PS_SUCCESS /* Decrease the length of storage */ -}, -{ - VAL_PS_GET, PSA_PS_ERROR_INCORRECT_SIZE /* Try to access old length */ -}, -{ - VAL_PS_GET, PSA_PS_ERROR_INCORRECT_SIZE /* Try to access old length */ -}, -{ - VAL_PS_GET, PSA_PS_SUCCESS /* Try to access data with correct length */ -}, -{ - VAL_PS_REMOVE, PSA_PS_SUCCESS /* Remove the storage entity */ -}, -}; -#endif /* _TEST_S007_PS_DATA_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/test_s007.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/test_s007.c deleted file mode 100644 index b17143c..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/test_s007.c +++ /dev/null @@ -1,89 +0,0 @@ -/** @file - * Copyright (c) 2019, 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 "val_target.h" -#include "test_s007.h" -#ifdef ITS_TEST -#include "test_its_data.h" -#elif PS_TEST -#include "test_ps_data.h" -#endif - -#define TEST_BUFF_SIZE 30 - -client_test_t test_s007_sst_list[] = { - NULL, - psa_sst_get_incorrect_size, - NULL, -}; - -static uint8_t write_buff[TEST_BUFF_SIZE] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x23, 0xF6, 0x07, 0x08, 0x0D, 0x0A, 0x1B, 0x0C, 0x5D, 0x0E,\ - 0x70, 0xA1, 0xFF, 0xFF, 0x14, 0x73, 0x46, 0x97, 0xE8, 0xDD, 0xCA, 0x0B, 0x3C, 0x0D, 0x2E}; -static uint8_t read_buff[TEST_BUFF_SIZE]; - -int32_t psa_sst_get_incorrect_size(caller_security_t caller) -{ - psa_sst_uid_t uid = UID_BASE_VALUE + 5; - uint32_t status = VAL_STATUS_SUCCESS; - - /* Set the UID with the data_len and data_buff */ - val->print(PRINT_TEST, "Create a valid Storage\n", 0); - status = SST_FUNCTION(s007_data[1].api, uid, TEST_BUFF_SIZE/2, write_buff, 0); - TEST_ASSERT_EQUAL(status, s007_data[1].status, TEST_CHECKPOINT_NUM(1)); - - /* Call set for same UID and increase the length */ - val->print(PRINT_TEST, "Increase the length of storage\n", 0); - status = SST_FUNCTION(s007_data[2].api, uid, TEST_BUFF_SIZE, write_buff, 0); - TEST_ASSERT_EQUAL(status, s007_data[2].status, TEST_CHECKPOINT_NUM(2)); - - /* Access data using get API and old length */ - val->print(PRINT_TEST, "[Check 1] Call get API with old length\n", 0); - status = SST_FUNCTION(s007_data[3].api, uid, 0, TEST_BUFF_SIZE/2, read_buff); - TEST_ASSERT_EQUAL(status, s007_data[3].status, TEST_CHECKPOINT_NUM(3)); - - /* Access data using get API and valid length */ - status = SST_FUNCTION(s007_data[4].api, uid, 0, TEST_BUFF_SIZE/4, read_buff); - TEST_ASSERT_EQUAL(status, s007_data[4].status, TEST_CHECKPOINT_NUM(4)); - TEST_ASSERT_MEMCMP(read_buff, write_buff, TEST_BUFF_SIZE/4, TEST_CHECKPOINT_NUM(5)); - - /* Decrease the length again */ - val->print(PRINT_TEST, "Decrease the length of storage\n", 0); - status = SST_FUNCTION(s007_data[6].api, uid, TEST_BUFF_SIZE/4, write_buff, 0); - TEST_ASSERT_EQUAL(status, s007_data[6].status, TEST_CHECKPOINT_NUM(6)); - - /* Access data using get API and old length */ - status = SST_FUNCTION(s007_data[7].api, uid, 0, TEST_BUFF_SIZE/2, read_buff); - TEST_ASSERT_EQUAL(status, s007_data[7].status, TEST_CHECKPOINT_NUM(7)); - - /* Access data using get API and old length */ - val->print(PRINT_TEST, "[Check 2] Call get API with old length\n", 0); - status = SST_FUNCTION(s007_data[8].api, uid, 0, TEST_BUFF_SIZE, read_buff); - TEST_ASSERT_EQUAL(status, s007_data[8].status, TEST_CHECKPOINT_NUM(8)); - - /* Access data using correct length */ - val->print(PRINT_TEST, "[Check 3] Call get API with valid length\n", 0); - status = SST_FUNCTION(s007_data[9].api, uid, 0, TEST_BUFF_SIZE/4, read_buff); - TEST_ASSERT_EQUAL(status, s007_data[9].status, TEST_CHECKPOINT_NUM(9)); - - /* Remove the UID */ - status = SST_FUNCTION(s007_data[10].api, uid); - TEST_ASSERT_EQUAL(status, s007_data[10].status, TEST_CHECKPOINT_NUM(10)); - - return status; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/test_s007.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/test_s007.h deleted file mode 100644 index b663980..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/test_s007.h +++ /dev/null @@ -1,36 +0,0 @@ -/** @file - * Copyright (c) 2019, 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_S007_CLIENT_TESTS_H_ -#define _TEST_S007_CLIENT_TESTS_H_ - -#ifdef ITS_TEST -#define VAL_STORAGE_BASE VAL_INTERNAL_TRUSTED_STORAGE_BASE -#define test_entry CONCAT(test_entry_, s007) -#elif PS_TEST -#define VAL_STORAGE_BASE VAL_PROTECTED_STORAGE_BASE -#define test_entry CONCAT(test_entry_, p007) -#endif -#define val CONCAT(val,test_entry) -#define psa CONCAT(psa,test_entry) - -extern val_api_t *val; -extern psa_api_t *psa; -extern client_test_t test_s007_sst_list[]; - -int32_t psa_sst_get_incorrect_size(caller_security_t caller); - -#endif /* _TEST_S007_CLIENT_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/main.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/main.c deleted file mode 100644 index b17f6cf..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/main.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited and affiliates. - * 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 "pal_mbed_os_intf.h" - -#if !defined(MBED_CONF_RTOS_PRESENT) -#error [NOT_SUPPORTED] PSA compliance its test cases require RTOS to run -#else - -#ifdef ITS_TEST -void test_entry_s008(val_api_t *val_api, psa_api_t *psa_api); -#elif PS_TEST -void test_entry_p008(val_api_t *val_api, psa_api_t *psa_api); -#endif - -int main(void) -{ -#ifdef ITS_TEST - test_start(test_entry_s008, COMPLIANCE_TEST_STORAGE); -#elif PS_TEST - test_start(test_entry_p008, COMPLIANCE_TEST_STORAGE); -#endif -} -#endif // !defined(MBED_CONF_RTOS_PRESENT) diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/test_entry.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/test_entry.c deleted file mode 100644 index f531881..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/test_entry.c +++ /dev/null @@ -1,53 +0,0 @@ -/** @file - * Copyright (c) 2019, 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 "val_target.h" -#include "test_s008.h" - -#define TEST_NUM VAL_CREATE_TEST_ID(VAL_STORAGE_BASE, 8) -#define TEST_DESC "Invalid offset check\n" - -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; - - /* test init */ - val->test_init(TEST_NUM, TEST_DESC, TEST_FIELD(TEST_ISOLATION_L1, WD_HIGH_TIMEOUT)); - if (!IS_TEST_START(val->get_status())) - { - goto test_exit; - } - - /* Execute list of tests available in test[num]_secure_storage_list from Non-secure side*/ - status = val->execute_non_secure_tests(TEST_NUM, test_s008_sst_list, FALSE); - - if (VAL_ERROR(status)) - { - goto test_exit; - } - -test_exit: - val->test_exit(); -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/test_its_data.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/test_its_data.h deleted file mode 100644 index 89093d4..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/test_its_data.h +++ /dev/null @@ -1,74 +0,0 @@ -/** @file - * Copyright (c) 2019, 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_S008_ITS_DATA_TESTS_H_ -#define _TEST_S008_ITS_DATA_TESTS_H_ - -#include "val_internal_trusted_storage.h" - -#define SST_FUNCTION val->its_function -#define psa_sst_uid_t psa_its_uid_t - -typedef struct { - enum its_function_code api; - psa_its_status_t status; -} test_data; - -static const test_data s008_data[] = { -{ - 0, 0 /* This is dummy for index0 */ -}, -{ - VAL_ITS_SET, PSA_ITS_SUCCESS /* Create a valid storage entity with zero flag value */ -}, -{ - VAL_ITS_GET, PSA_ITS_SUCCESS /* Call get API with offset + data_len = total_size */ -}, -{ - 0, 0 /* This is dummy for index3 */ -}, -{ - VAL_ITS_GET, PSA_ITS_SUCCESS /* Call get API with offset + data_len < total_size */ -}, -{ - 0, 0 /* This is dummy for index5 */ -}, -{ - VAL_ITS_GET, PSA_ITS_SUCCESS /* Call get API with offset = total data_size + 1 */ -}, -{ - 0, 0 /* This is dummy for index7 */ -}, -{ - VAL_ITS_GET, PSA_ITS_ERROR_INCORRECT_SIZE /* get API with offset + data_len > total data_size */ -}, -{ - 0, 0 /* This is dummy for index9 */ -}, -{ - VAL_ITS_GET, PSA_ITS_ERROR_INCORRECT_SIZE /* Call get API with invalid data len and offset zero */ -}, -{ - 0, 0 /* This is dummy for index11 */ -}, -{ - VAL_ITS_GET, PSA_ITS_SUCCESS /* Call get API with offset = MAX_UINT32 */ -}, -{ - VAL_ITS_REMOVE, PSA_ITS_SUCCESS /* Remove the storage entity */ -}, -}; -#endif /* _TEST_S008_ITS_DATA_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/test_ps_data.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/test_ps_data.h deleted file mode 100644 index 2b15d35..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/test_ps_data.h +++ /dev/null @@ -1,74 +0,0 @@ -/** @file - * Copyright (c) 2019, Arm Limited or ps 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_S008_PS_DATA_TESTS_H_ -#define _TEST_S008_PS_DATA_TESTS_H_ - -#include "val_protected_storage.h" - -#define SST_FUNCTION val->ps_function -#define psa_sst_uid_t psa_ps_uid_t - -typedef struct { - enum ps_function_code api; - psa_ps_status_t status; -} test_data; - -static const test_data s008_data[] = { -{ - 0, 0 /* This is dummy for index0 */ -}, -{ - VAL_PS_SET, PSA_PS_SUCCESS /* Create a valid storage entity with zero flag value */ -}, -{ - VAL_PS_GET, PSA_PS_SUCCESS /* Call get API with offset + data_len = total_size */ -}, -{ - 0, 0 /* This is dummy for index3 */ -}, -{ - VAL_PS_GET, PSA_PS_SUCCESS /* Call get API with offset + data_len < total_size */ -}, -{ - 0, 0 /* This is dummy for index5 */ -}, -{ - VAL_PS_GET, PSA_PS_SUCCESS/* Call get API with offset = total data_size + 1 */ -}, -{ - 0, 0 /* This is dummy for index7 */ -}, -{ - VAL_PS_GET, PSA_PS_ERROR_INCORRECT_SIZE /* Call get API with offset + data_len > total data_size */ -}, -{ - 0, 0 /* This is dummy for index9 */ -}, -{ - VAL_PS_GET, PSA_PS_ERROR_INCORRECT_SIZE /* Call get API with invalid data len and offset zero */ -}, -{ - 0, 0 /* This is dummy for index11 */ -}, -{ - VAL_PS_GET, PSA_PS_SUCCESS /* Call get API with offset = MAX_UINT32 */ -}, -{ - VAL_PS_REMOVE, PSA_PS_SUCCESS /* Remove the storage entity */ -}, -}; -#endif /* _TEST_S008_PS_DATA_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/test_s008.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/test_s008.c deleted file mode 100644 index 7a2536e..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/test_s008.c +++ /dev/null @@ -1,116 +0,0 @@ -/** @file - * Copyright (c) 2019, 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 "val_target.h" -#include "test_s008.h" -#ifdef ITS_TEST -#include "test_its_data.h" -#elif PS_TEST -#include "test_ps_data.h" -#endif - -#define TEST_BUFF_SIZE 20 -#define TEST_MAX_UINT32 0xFFFFFFFF - -client_test_t test_s008_sst_list[] = { - NULL, - psa_sst_valid_offset_success, - psa_sst_invalid_offset_failure, - NULL, -}; - -static psa_sst_uid_t uid = UID_BASE_VALUE + 5; -static uint8_t read_buff[TEST_BUFF_SIZE]; -static uint8_t write_buff[TEST_BUFF_SIZE] = {0x99, 0x01, 0x02, 0x03, 0x04, 0x23, 0xF6, 0x07, 0x08, \ - 0x0D, 0x70, 0xA1, 0xFF, 0xFF, 0x14, 0x73, 0x46, 0x97, 0xE8, 0xDD}; - -int32_t psa_sst_invalid_offset_failure(caller_security_t caller) -{ - uint32_t status, j; - - /* Case where offset = data_size +1 , data_len 0. Also check nothing is returned in read buff*/ - val->print(PRINT_TEST, "[Check 2] Try to access data with varying invalid offset\n", 0); - memset(read_buff, 0, TEST_BUFF_SIZE); - status = SST_FUNCTION(s008_data[6].api, uid, TEST_BUFF_SIZE+1, 0, read_buff); - TEST_ASSERT_NOT_EQUAL(status, s008_data[6].status, TEST_CHECKPOINT_NUM(6)); - for (j = 0; j < TEST_BUFF_SIZE; j++) - { - TEST_ASSERT_EQUAL(read_buff[j], 0x00, TEST_CHECKPOINT_NUM(7)); - } - - /* Case where offset = data_size , data_len= 1 Also check nothing is returned in read buff*/ - status = SST_FUNCTION(s008_data[8].api, uid, TEST_BUFF_SIZE, 1, read_buff); - TEST_ASSERT_EQUAL(status, s008_data[8].status, TEST_CHECKPOINT_NUM(8)); - for (j = 0; j < TEST_BUFF_SIZE; j++) - { - TEST_ASSERT_EQUAL(read_buff[j], 0x00, TEST_CHECKPOINT_NUM(9)); - } - - /* Case where offset = 0 , data_len > data_size Also check nothing is returned in read buff*/ - status = SST_FUNCTION(s008_data[10].api, uid, 0, TEST_BUFF_SIZE+1, read_buff); - TEST_ASSERT_EQUAL(status, s008_data[10].status, TEST_CHECKPOINT_NUM(10)); - for (j = 0; j < TEST_BUFF_SIZE; j++) - { - TEST_ASSERT_EQUAL(read_buff[j], 0x00, TEST_CHECKPOINT_NUM(11)); - } - - /* Try to access data with offset as MAX_UINT32 and length less than buffer size */ - status = SST_FUNCTION(s008_data[12].api, uid, TEST_MAX_UINT32, TEST_BUFF_SIZE/2, read_buff); - TEST_ASSERT_NOT_EQUAL(status, s008_data[12].status, TEST_CHECKPOINT_NUM(12)); - - /* Remove the UID */ - status = SST_FUNCTION(s008_data[13].api, uid); - TEST_ASSERT_EQUAL(status, s008_data[13].status, TEST_CHECKPOINT_NUM(13)); - - return VAL_STATUS_SUCCESS; -} - -int32_t psa_sst_valid_offset_success(caller_security_t caller) -{ - uint32_t status, data_len, offset = TEST_BUFF_SIZE; - - /* Set data for UID */ - status = SST_FUNCTION(s008_data[1].api, uid, TEST_BUFF_SIZE, write_buff, 0); - TEST_ASSERT_EQUAL(status, s008_data[1].status, TEST_CHECKPOINT_NUM(1)); - - /* Case where offset + datalen = data_size */ - val->print(PRINT_TEST, "[Check 1] Try to access data with varying valid offset\n", 0); - while (offset > 0) - { - data_len = TEST_BUFF_SIZE - offset; - memset(read_buff, 0, TEST_BUFF_SIZE); - status = SST_FUNCTION(s008_data[2].api, uid, offset, data_len, read_buff); - TEST_ASSERT_EQUAL(status, s008_data[2].status, TEST_CHECKPOINT_NUM(2)); - TEST_ASSERT_MEMCMP(read_buff, write_buff + offset, data_len, TEST_CHECKPOINT_NUM(3)); - offset >>= 1; - } - - offset = TEST_BUFF_SIZE - 2; - data_len = 1; - /* Case where offset + datalen < data_size */ - while (offset > 0) - { - status = SST_FUNCTION(s008_data[4].api, uid, offset, data_len, read_buff); - TEST_ASSERT_EQUAL(status, s008_data[4].status, TEST_CHECKPOINT_NUM(4)); - TEST_ASSERT_MEMCMP(read_buff, write_buff + offset, data_len, TEST_CHECKPOINT_NUM(5)); - offset >>= 1; - data_len <<= 1; - } - - return VAL_STATUS_SUCCESS; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/test_s008.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/test_s008.h deleted file mode 100644 index d036b4a..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/test_s008.h +++ /dev/null @@ -1,37 +0,0 @@ -/** @file - * Copyright (c) 2019, 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_S008_CLIENT_TESTS_H_ -#define _TEST_S008_CLIENT_TESTS_H_ - -#ifdef ITS_TEST -#define VAL_STORAGE_BASE VAL_INTERNAL_TRUSTED_STORAGE_BASE -#define test_entry CONCAT(test_entry_, s008) -#elif PS_TEST -#define VAL_STORAGE_BASE VAL_PROTECTED_STORAGE_BASE -#define test_entry CONCAT(test_entry_, p008) -#endif -#define val CONCAT(val,test_entry) -#define psa CONCAT(psa,test_entry) - -extern val_api_t *val; -extern psa_api_t *psa; -extern client_test_t test_s008_sst_list[]; - -int32_t psa_sst_valid_offset_success(caller_security_t caller); -int32_t psa_sst_invalid_offset_failure(caller_security_t caller); - -#endif /* _TEST_S008_CLIENT_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/main.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/main.c deleted file mode 100644 index 74a6ddb..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/main.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited and affiliates. - * 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 "pal_mbed_os_intf.h" - -#if !defined(MBED_CONF_RTOS_PRESENT) -#error [NOT_SUPPORTED] PSA compliance its test cases require RTOS to run -#else - -#ifdef ITS_TEST -void test_entry_s009(val_api_t *val_api, psa_api_t *psa_api); -#elif PS_TEST -void test_entry_p009(val_api_t *val_api, psa_api_t *psa_api); -#endif - -int main(void) -{ -#ifdef ITS_TEST - test_start(test_entry_s009, COMPLIANCE_TEST_STORAGE); -#elif PS_TEST - test_start(test_entry_p009, COMPLIANCE_TEST_STORAGE); -#endif -} -#endif // !defined(MBED_CONF_RTOS_PRESENT) diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/test_entry.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/test_entry.c deleted file mode 100644 index 37883fb..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/test_entry.c +++ /dev/null @@ -1,53 +0,0 @@ -/** @file - * Copyright (c) 2019, 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 "val_target.h" -#include "test_s009.h" - -#define TEST_NUM VAL_CREATE_TEST_ID(VAL_STORAGE_BASE, 9) -#define TEST_DESC "Invalid Arguments check\n" - -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; - - /* test init */ - val->test_init(TEST_NUM, TEST_DESC, TEST_FIELD(TEST_ISOLATION_L1, WD_HIGH_TIMEOUT)); - if (!IS_TEST_START(val->get_status())) - { - goto test_exit; - } - - /* Execute list of tests available in test[num]_secure_storage_list from Non-secure side*/ - status = val->execute_non_secure_tests(TEST_NUM, test_s009_sst_list, FALSE); - - if (VAL_ERROR(status)) - { - goto test_exit; - } - -test_exit: - val->test_exit(); -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/test_its_data.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/test_its_data.h deleted file mode 100644 index 80e7fb1..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/test_its_data.h +++ /dev/null @@ -1,69 +0,0 @@ -/** @file - * Copyright (c) 2019, 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_S009_ITS_DATA_TESTS_H_ -#define _TEST_S009_ITS_DATA_TESTS_H_ - -#include "val_internal_trusted_storage.h" - -#define SST_FUNCTION val->its_function -#define psa_sst_uid_t psa_its_uid_t - -typedef struct { - enum its_function_code api; - psa_its_status_t status; -} test_data; - -static struct psa_its_info_t info; -static const test_data s009_data[] = { -{ - 0, 0 /* This is dummy for index0 */ -}, -{ - VAL_ITS_SET, PSA_ITS_SUCCESS /* Call set API with NULL write buffer and 0 length */ -}, -{ - VAL_ITS_GET_INFO, PSA_ITS_SUCCESS /* Verify UID is created */ -}, -{ - VAL_ITS_GET, PSA_ITS_SUCCESS /* Call get API with NULL write buffer and 0 length */ -}, -{ - VAL_ITS_REMOVE, PSA_ITS_SUCCESS /* Remove the storage entity */ -}, -{ - VAL_ITS_GET_INFO, PSA_ITS_ERROR_UID_NOT_FOUND /* Verify UID is removed */ -}, -{ - VAL_ITS_SET, PSA_ITS_SUCCESS /* Create storage of zero size and valid write buffer */ -}, -{ - VAL_ITS_GET_INFO, PSA_ITS_SUCCESS /* Call get_info API to check data size */ -}, -{ - 0, 0 /* This is dummy for index8 */ -}, -{ - VAL_ITS_GET, PSA_ITS_SUCCESS /* Call get API with 0 length and NULL read buffer */ -}, -{ - VAL_ITS_SET, PSA_ITS_SUCCESS /* Increase the asset size */ -}, -{ - VAL_ITS_REMOVE, PSA_ITS_SUCCESS /* Remove the storage entity */ -}, -}; -#endif /* _TEST_S009_ITS_DATA_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/test_ps_data.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/test_ps_data.h deleted file mode 100644 index 129bca0..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/test_ps_data.h +++ /dev/null @@ -1,69 +0,0 @@ -/** @file - * Copyright (c) 2019, Arm Limited or ps 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_S009_PS_DATA_TESTS_H_ -#define _TEST_S009_PS_DATA_TESTS_H_ - -#include "val_protected_storage.h" - -#define SST_FUNCTION val->ps_function -#define psa_sst_uid_t psa_ps_uid_t - -typedef struct { - enum ps_function_code api; - psa_ps_status_t status; -} test_data; - -static struct psa_ps_info_t info; -static const test_data s009_data[] = { -{ - 0, 0 /* This is dummy for index0 */ -}, -{ - VAL_PS_SET, PSA_PS_SUCCESS /* Call set API with NULL write buffer and 0 length */ -}, -{ - VAL_PS_GET_INFO, PSA_PS_SUCCESS /* Verify UID is created */ -}, -{ - VAL_PS_GET, PSA_PS_SUCCESS /* Call get API with NULL write buffer and 0 length */ -}, -{ - VAL_PS_REMOVE, PSA_PS_SUCCESS /* Remove the storage entity */ -}, -{ - VAL_PS_GET_INFO, PSA_PS_ERROR_UID_NOT_FOUND /* Verify UID is removed */ -}, -{ - VAL_PS_SET, PSA_PS_SUCCESS /* Create storage of zero size and valid write buffer */ -}, -{ - VAL_PS_GET_INFO, PSA_PS_SUCCESS /* Call get_info API to check data size */ -}, -{ - 0, 0 /* This is dummy for index8 */ -}, -{ - VAL_PS_GET, PSA_PS_SUCCESS /* Call get API with 0 length and NULL read buffer */ -}, -{ - VAL_PS_SET, PSA_PS_SUCCESS /* Increase the asset size */ -}, -{ - VAL_PS_REMOVE, PSA_PS_SUCCESS /* Remove the storage entity */ -}, -}; -#endif /* _TEST_S009_PS_DATA_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/test_s009.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/test_s009.c deleted file mode 100644 index c54fa02..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/test_s009.c +++ /dev/null @@ -1,92 +0,0 @@ -/** @file - * Copyright (c) 2019, 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 "val_target.h" -#include "test_s009.h" -#ifdef ITS_TEST -#include "test_its_data.h" -#elif PS_TEST -#include "test_ps_data.h" -#endif - -#define TEST_BUFF_SIZE 20 - -client_test_t test_s009_sst_list[] = { - NULL, - psa_sst_zero_length_check, - NULL, -}; - -static psa_sst_uid_t uid = UID_BASE_VALUE + 5; -static uint8_t write_buff[TEST_BUFF_SIZE] = {0x99, 0x01, 0x02, 0x03, 0x04, 0x23, 0xF6, 0x07, 0x08, \ - 0x0D, 0x70, 0xA1, 0xFF, 0xFF, 0x14, 0x73, 0x46, 0x97, 0xE8, 0xDD}; - -int32_t psa_sst_zero_length_check(caller_security_t caller) -{ - uint32_t status; - - /* Set data for UID with length 0 and NULL pointer */ - val->print(PRINT_TEST, "[Check 1] Call set API with NULL pointer and data length 0\n", 0); - status = SST_FUNCTION(s009_data[1].api, uid, 0, NULL, 0); - TEST_ASSERT_EQUAL(status, s009_data[1].status, TEST_CHECKPOINT_NUM(1)); - - /* Call the get_info function to verify UID created */ - status = SST_FUNCTION(s009_data[2].api, uid, &info); - TEST_ASSERT_EQUAL(status, s009_data[2].status, TEST_CHECKPOINT_NUM(2)); - - /* Call get API with NULL read buffer */ - val->print(PRINT_TEST, "[Check 2] Call get API with NULL read buffer and data length 0\n", 0); - status = SST_FUNCTION(s009_data[3].api, uid, 0, 0, NULL); - TEST_ASSERT_EQUAL(status, s009_data[3].status, TEST_CHECKPOINT_NUM(3)); - - /* Remove the UID */ - val->print(PRINT_TEST, "[Check 3] Remove the UID\n", 0); - status = SST_FUNCTION(s009_data[4].api, uid); - TEST_ASSERT_EQUAL(status, s009_data[4].status, TEST_CHECKPOINT_NUM(4)); - - /* Call the get_info function to verify UID is removed */ - val->print(PRINT_TEST, "[Check 4] Call get_info API to verify UID removed\n", 0); - status = SST_FUNCTION(s009_data[5].api, uid, &info); - TEST_ASSERT_EQUAL(status, s009_data[5].status, TEST_CHECKPOINT_NUM(5)); - - /* Create UID with length 0 and valid write buffer */ - val->print(PRINT_TEST, "[Check 5] Create UID with zero data_len and valid write buffer\n", 0); - status = SST_FUNCTION(s009_data[6].api, uid, 0, write_buff, 0); - TEST_ASSERT_EQUAL(status, s009_data[6].status, TEST_CHECKPOINT_NUM(6)); - - /* Call the get_info function and match the attributes */ - status = SST_FUNCTION(s009_data[7].api, uid, &info); - TEST_ASSERT_EQUAL(status, s009_data[7].status, TEST_CHECKPOINT_NUM(7)); - TEST_ASSERT_EQUAL(info.size, 0, TEST_CHECKPOINT_NUM(8)); - - /* Call get API with NULL read buffer and valid UID */ - val->print(PRINT_TEST, "[Check 8] Call get API with NULL read buffer and data length 0\n", 0); - status = SST_FUNCTION(s009_data[9].api, uid, 0, 0, NULL); - TEST_ASSERT_EQUAL(status, s009_data[9].status, TEST_CHECKPOINT_NUM(9)); - - /* Change the length to test_buff_size */ - val->print(PRINT_TEST, "[Check 9] Increase the length\n", 0); - status = SST_FUNCTION(s009_data[10].api, uid, TEST_BUFF_SIZE, write_buff, 0); - TEST_ASSERT_EQUAL(status, s009_data[10].status, TEST_CHECKPOINT_NUM(10)); - - /* Remove the UID */ - status = SST_FUNCTION(s009_data[11].api, uid); - TEST_ASSERT_EQUAL(status, s009_data[11].status, TEST_CHECKPOINT_NUM(11)); - - return VAL_STATUS_SUCCESS; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/test_s009.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/test_s009.h deleted file mode 100644 index 49a5de0..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/test_s009.h +++ /dev/null @@ -1,36 +0,0 @@ -/** @file - * Copyright (c) 2019, 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_S009_CLIENT_TESTS_H_ -#define _TEST_S009_CLIENT_TESTS_H_ - -#ifdef ITS_TEST -#define VAL_STORAGE_BASE VAL_INTERNAL_TRUSTED_STORAGE_BASE -#define test_entry CONCAT(test_entry_, s009) -#elif PS_TEST -#define VAL_STORAGE_BASE VAL_PROTECTED_STORAGE_BASE -#define test_entry CONCAT(test_entry_, p009) -#endif -#define val CONCAT(val,test_entry) -#define psa CONCAT(psa,test_entry) - -extern val_api_t *val; -extern psa_api_t *psa; -extern client_test_t test_s009_sst_list[]; - -int32_t psa_sst_zero_length_check(caller_security_t caller); - -#endif /* _TEST_S009_CLIENT_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/main.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/main.c deleted file mode 100644 index c9f0728..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/main.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited and affiliates. - * 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 "pal_mbed_os_intf.h" - -#if !defined(MBED_CONF_RTOS_PRESENT) -#error [NOT_SUPPORTED] PSA compliance its test cases require RTOS to run -#else - -#ifdef ITS_TEST -void test_entry_s010(val_api_t *val_api, psa_api_t *psa_api); -#elif PS_TEST -void test_entry_p010(val_api_t *val_api, psa_api_t *psa_api); -#endif - -int main(void) -{ -#ifdef ITS_TEST - test_start(test_entry_s010, COMPLIANCE_TEST_STORAGE); -#elif PS_TEST - test_start(test_entry_p010, COMPLIANCE_TEST_STORAGE); -#endif -} -#endif // !defined(MBED_CONF_RTOS_PRESENT) diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/test_entry.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/test_entry.c deleted file mode 100644 index 82623c6..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/test_entry.c +++ /dev/null @@ -1,53 +0,0 @@ -/** @file - * Copyright (c) 2019, 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 "val_target.h" -#include "test_s010.h" - -#define TEST_NUM VAL_CREATE_TEST_ID(VAL_STORAGE_BASE, 10) -#define TEST_DESC "UID value zero check\n" - -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; - - /* test init */ - val->test_init(TEST_NUM, TEST_DESC, TEST_FIELD(TEST_ISOLATION_L1, WD_HIGH_TIMEOUT)); - if (!IS_TEST_START(val->get_status())) - { - goto test_exit; - } - - /* Execute list of tests available in test[num]_secure_storage_list from Non-secure side*/ - status = val->execute_non_secure_tests(TEST_NUM, test_s010_sst_list, FALSE); - - if (VAL_ERROR(status)) - { - goto test_exit; - } - -test_exit: - val->test_exit(); -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/test_its_data.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/test_its_data.h deleted file mode 100644 index 7b1b6d3..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/test_its_data.h +++ /dev/null @@ -1,35 +0,0 @@ -/** @file - * Copyright (c) 2019, 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_S010_ITS_DATA_TESTS_H_ -#define _TEST_S010_ITS_DATA_TESTS_H_ - -#include "val_internal_trusted_storage.h" - -#define SST_FUNCTION val->its_function -#define psa_sst_uid_t psa_its_uid_t - -typedef struct { - enum its_function_code api; - psa_its_status_t status; -} test_data; - -static const test_data s010_data[] = { -{ - VAL_ITS_SET, PSA_ITS_SUCCESS /* Create with UID value zero should fail */ -}, -}; -#endif /* _TEST_S010_ITS_DATA_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/test_ps_data.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/test_ps_data.h deleted file mode 100644 index e88ed9b..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/test_ps_data.h +++ /dev/null @@ -1,35 +0,0 @@ -/** @file - * Copyright (c) 2019, Arm Limited or ps 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_S010_PS_DATA_TESTS_H_ -#define _TEST_S010_PS_DATA_TESTS_H_ - -#include "val_protected_storage.h" - -#define SST_FUNCTION val->ps_function -#define psa_sst_uid_t psa_ps_uid_t - -typedef struct { - enum ps_function_code api; - psa_ps_status_t status; -} test_data; - -static const test_data s010_data[] = { -{ - VAL_PS_SET, PSA_PS_SUCCESS /* Create with UID value zero should fail */ -}, -}; -#endif /* _TEST_S010_PS_DATA_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/test_s010.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/test_s010.c deleted file mode 100644 index 380c069..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/test_s010.c +++ /dev/null @@ -1,49 +0,0 @@ -/** @file - * Copyright (c) 2019, 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 "val_target.h" -#include "test_s010.h" -#ifdef ITS_TEST -#include "test_its_data.h" -#elif PS_TEST -#include "test_ps_data.h" -#endif - -#define TEST_BUFF_SIZE 1 - -client_test_t test_s010_sst_list[] = { - NULL, - psa_sst_uid_value_zero_check, - NULL, -}; - -static uint8_t write_buff[TEST_BUFF_SIZE] = {0xFF}; - -int32_t psa_sst_uid_value_zero_check(caller_security_t caller) -{ - int32_t status; - psa_sst_uid_t uid = 0; - - /* Set with UID value zero should fail */ - val->print(PRINT_TEST, "[Check 1] Creating storage with UID 0 should fail\n", 0 ); - status = SST_FUNCTION(s010_data[0].api, uid, TEST_BUFF_SIZE, write_buff, 0); - TEST_ASSERT_NOT_EQUAL(status, s010_data[0].status, TEST_CHECKPOINT_NUM(1)); - - return VAL_STATUS_SUCCESS; -} - diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/test_s010.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/test_s010.h deleted file mode 100644 index 35dfb7c..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/test_s010.h +++ /dev/null @@ -1,35 +0,0 @@ -/** @file - * Copyright (c) 2019, 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_S010_CLIENT_TESTS_H_ -#define _TEST_S010_CLIENT_TESTS_H_ - -#ifdef ITS_TEST -#define VAL_STORAGE_BASE VAL_INTERNAL_TRUSTED_STORAGE_BASE -#define test_entry CONCAT(test_entry_, s010) -#elif PS_TEST -#define VAL_STORAGE_BASE VAL_PROTECTED_STORAGE_BASE -#define test_entry CONCAT(test_entry_, p010) -#endif -#define val CONCAT(val,test_entry) -#define psa CONCAT(psa,test_entry) - -extern val_api_t *val; -extern psa_api_t *psa; -extern client_test_t test_s010_sst_list[]; - -int32_t psa_sst_uid_value_zero_check(caller_security_t caller); -#endif /* _TEST_S010_CLIENT_TESTS_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/crypto_init/main.cpp b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/crypto_init/main.cpp deleted file mode 100644 index 778b0fb..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/crypto_init/main.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* -* Copyright (c) 2018-2020 ARM Limited. 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 "psa/crypto.h" - -#if ((!defined(TARGET_PSA)) || (!defined(MBEDTLS_PSA_CRYPTO_C))) -#error [NOT_SUPPORTED] Mbed Crypto is OFF - skipping. -#else - -#include "greentea-client/test_env.h" -#include "unity/unity.h" -#include "utest/utest.h" -#include "entropy.h" -#include "entropy_poll.h" - -#define TEST_RANDOM_SIZE 64 - -#if !defined(MAX) -#define MAX(a,b) (((a)>(b))?(a):(b)) -#endif - -/* Calculating the minimum allowed entropy size in bytes */ -#define MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE \ - MAX(MBEDTLS_ENTROPY_MIN_PLATFORM, MBEDTLS_ENTROPY_BLOCK_SIZE) - -using namespace utest::v1; - -utest::v1::status_t greentea_test_setup(const size_t number_of_cases) -{ - GREENTEA_SETUP(60, "default_auto"); - return greentea_test_setup_handler(number_of_cases); -} - -static void check_crypto_init_deinit() -{ - psa_status_t status; - uint8_t output[TEST_RANDOM_SIZE] = {0}; - - // Should fail as init is required first - status = psa_generate_random(output, sizeof(output)); - TEST_ASSERT_EQUAL(PSA_ERROR_BAD_STATE, status); - - status = psa_crypto_init(); - TEST_ASSERT_EQUAL(PSA_SUCCESS, status); - - status = psa_generate_random(output, sizeof(output)); - TEST_ASSERT_NOT_EQUAL(PSA_ERROR_BAD_STATE, status); - - mbedtls_psa_crypto_free(); - status = psa_generate_random(output, sizeof(output)); - TEST_ASSERT_EQUAL(PSA_ERROR_BAD_STATE, status); -} - -Case cases[] = { - Case("PSA crypto-init De-init", check_crypto_init_deinit), -}; - -Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); - -int main() -{ -#if defined(MBEDTLS_ENTROPY_NV_SEED) - uint8_t seed[MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE] = {0}; - /* inject some a seed for test*/ - for (int i = 0; i < MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE; ++i) { - seed[i] = i; - } - - /* don't really care if this succeed this is just to make crypto init pass*/ - mbedtls_psa_inject_entropy(seed, MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE); -#endif - return !Harness::run(specification); -} - -#endif // ((!defined(TARGET_PSA)) || (!defined(MBEDTLS_PSA_CRYPTO_C))) diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/entropy_inject/main.cpp b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/entropy_inject/main.cpp deleted file mode 100644 index 0098e8e..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/entropy_inject/main.cpp +++ /dev/null @@ -1,187 +0,0 @@ -/* -* Copyright (c) 2018 ARM Limited. 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. -*/ - -#if ((!defined(TARGET_PSA) || (!defined(COMPONENT_PSA_SRV_IPC)) && !defined(MBEDTLS_ENTROPY_NV_SEED))) -#error [NOT_SUPPORTED] PSA entropy injection tests can run only on PSA-enabled targets. -#else - -#include "greentea-client/test_env.h" -#include "unity/unity.h" -#include "utest/utest.h" -#include "psa/internal_trusted_storage.h" -#include "psa/lifecycle.h" -#include "entropy.h" -#include "entropy_poll.h" -#include "psa/crypto.h" -#include - -/* MAX value support macro */ -#if !defined(MAX) -#define MAX(a,b) (((a)>(b))?(a):(b)) -#endif - -/* Calculating the minimum allowed entropy size in bytes */ -#define MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE \ - MAX(MBEDTLS_ENTROPY_MIN_PLATFORM, MBEDTLS_ENTROPY_BLOCK_SIZE) - -using namespace utest::v1; - -uint8_t seed[MBEDTLS_ENTROPY_MAX_SEED_SIZE + 2] = {0}; -bool skip_tests = false; - -void validate_entropy_seed_injection(int seed_length_a, - int expected_status_a, - int seed_length_b, - int expected_status_b) -{ - psa_status_t status; - uint8_t output[32] = { 0 }; - uint8_t zeros[32] = { 0 }; - int memcmp_res = 0; - status = mbedtls_psa_inject_entropy(seed, seed_length_a); - TEST_ASSERT_EQUAL_INT(expected_status_a, status); - - status = mbedtls_psa_inject_entropy(seed, seed_length_b); - TEST_ASSERT_EQUAL_INT(expected_status_b, status); - - status = psa_crypto_init(); - TEST_ASSERT_EQUAL_INT(PSA_SUCCESS, status); - - status = psa_generate_random(output, sizeof(output)); - TEST_ASSERT_EQUAL_INT(PSA_SUCCESS, status); - - memcmp_res = memcmp(output, zeros, sizeof(output)); - TEST_ASSERT_NOT_EQUAL(0, memcmp_res); -} - -void run_entropy_inject_with_crypto_init() -{ - psa_status_t status; - status = psa_crypto_init(); - TEST_ASSERT_EQUAL_INT(PSA_ERROR_INSUFFICIENT_ENTROPY, status); - - status = mbedtls_psa_inject_entropy(seed, MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE); - TEST_ASSERT_EQUAL_INT(PSA_SUCCESS, status); - - status = psa_crypto_init(); - TEST_ASSERT_EQUAL_INT(PSA_SUCCESS, status); - - status = mbedtls_psa_inject_entropy(seed, MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE); - TEST_ASSERT_EQUAL_INT(PSA_ERROR_NOT_PERMITTED, status); - - mbedtls_psa_crypto_free(); - /* The seed is written by nv_seed callback functions therefore the injection will fail */ - status = mbedtls_psa_inject_entropy(seed, MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE); - TEST_ASSERT_EQUAL_INT(PSA_ERROR_NOT_PERMITTED, status); -} - - -utest::v1::status_t greentea_test_setup(const size_t number_of_cases) -{ - GREENTEA_SETUP(60, "default_auto"); - - /* fill seed in some data */ - for (size_t i = 0; i < sizeof(seed); ++i) { - seed[i] = i; - } - - psa_status_t status = mbed_psa_reboot_and_request_new_security_state(PSA_LIFECYCLE_ASSEMBLY_AND_TEST); - TEST_ASSERT_EQUAL(PSA_SUCCESS, status); - - if (mbedtls_psa_inject_entropy(seed, MBEDTLS_ENTROPY_MAX_SEED_SIZE) == PSA_ERROR_NOT_SUPPORTED) { - skip_tests = true; - } - - return greentea_test_setup_handler(number_of_cases); -} - -static void injection_small_good() -{ - TEST_SKIP_UNLESS(!skip_tests); - validate_entropy_seed_injection( - MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE, PSA_SUCCESS, - MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE, PSA_ERROR_NOT_PERMITTED); -} - -static void injection_big_good() -{ - TEST_SKIP_UNLESS(!skip_tests); - validate_entropy_seed_injection( - MBEDTLS_ENTROPY_MAX_SEED_SIZE, PSA_SUCCESS, - MBEDTLS_ENTROPY_MAX_SEED_SIZE, PSA_ERROR_NOT_PERMITTED); -} - -static void injection_too_small() -{ - TEST_SKIP_UNLESS(!skip_tests); - validate_entropy_seed_injection( - (MBEDTLS_ENTROPY_MIN_PLATFORM - 1), PSA_ERROR_INVALID_ARGUMENT, - MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE, PSA_SUCCESS); -} - -static void injection_too_big() -{ - TEST_SKIP_UNLESS(!skip_tests); - validate_entropy_seed_injection( - (MBEDTLS_ENTROPY_MAX_SEED_SIZE + 1), PSA_ERROR_INVALID_ARGUMENT, - MBEDTLS_ENTROPY_MAX_SEED_SIZE, PSA_SUCCESS); -} - -static void injection_and_init_deinit() -{ - TEST_SKIP_UNLESS(!skip_tests); - run_entropy_inject_with_crypto_init(); -} - - - -/***************************************************************************************/ - -utest::v1::status_t case_teardown_handler(const Case *const source, const size_t passed, const size_t failed, const failure_t reason) -{ - psa_status_t status; - status = mbed_psa_reboot_and_request_new_security_state(PSA_LIFECYCLE_ASSEMBLY_AND_TEST); - TEST_ASSERT_EQUAL(PSA_SUCCESS, status); - mbedtls_psa_crypto_free(); - return greentea_case_teardown_handler(source, passed, failed, reason); -} - -utest::v1::status_t case_setup_handler(const Case *const source, const size_t index_of_case) -{ - psa_status_t status; - status = mbed_psa_reboot_and_request_new_security_state(PSA_LIFECYCLE_ASSEMBLY_AND_TEST); - TEST_ASSERT_EQUAL(PSA_SUCCESS, status); - return greentea_case_setup_handler(source, index_of_case); -} - -Case cases[] = { - Case("PSA entropy injection small good", case_setup_handler, injection_small_good, case_teardown_handler), - Case("PSA entropy injection big good", case_setup_handler, injection_big_good, case_teardown_handler), - Case("PSA entropy injection too big", case_setup_handler, injection_too_big, case_teardown_handler), - Case("PSA entropy injection too small", case_setup_handler, injection_too_small, case_teardown_handler), - Case("PSA entropy injection before and after init", case_setup_handler, injection_and_init_deinit, case_teardown_handler), -}; - -Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); - -int main() -{ - return !Harness::run(specification); -} - -#endif // ((!defined(TARGET_PSA) || (!defined(COMPONENT_PSA_SRV_IPC)) && !defined(MBEDTLS_ENTROPY_NV_SEED))) diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/its_ps/main.cpp b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/its_ps/main.cpp deleted file mode 100644 index ee2c510..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/its_ps/main.cpp +++ /dev/null @@ -1,251 +0,0 @@ -/* -* Copyright (c) 2019 ARM Limited. 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. -*/ - -#if !defined(MBED_CONF_RTOS_PRESENT) -#error [NOT_SUPPORTED] ITS/PS test cases require RTOS to run. -#else - -#ifndef TARGET_PSA -#error [NOT_SUPPORTED] ITS/PS tests can run only on PSA-enabled targets. -#else - -#include "greentea-client/test_env.h" -#include "unity/unity.h" -#include "utest/utest.h" -#include "psa/error.h" -#include "psa/storage_common.h" -#include "psa/internal_trusted_storage.h" -#include "psa/protected_storage.h" -#include "psa/lifecycle.h" -#include "KVMap.h" -#include "KVStore.h" -#include "kv_config.h" -#include "psa_storage_common_impl.h" -#include "DeviceKey.h" - -using namespace utest::v1; -using namespace mbed; - -#define TEST_BUFF_SIZE 16 -#define STR_EXPAND(tok) #tok - -typedef enum { - its, - ps -} storage_type_t; - -extern "C" psa_status_t psa_ps_reset(); - -static psa_status_t set_func(storage_type_t stype, psa_storage_uid_t uid, size_t data_length, - const void *p_data, psa_storage_create_flags_t create_flags) -{ - return (stype == its) ? - psa_its_set(uid, data_length, p_data, create_flags) : - psa_ps_set(uid, data_length, p_data, create_flags); -} - -static psa_status_t get_func(storage_type_t stype, psa_storage_uid_t uid, size_t data_offset, - size_t data_length, void *p_data, size_t *actual_length) -{ - return (stype == its) ? - psa_its_get(uid, data_offset, data_length, p_data, actual_length) : - psa_ps_get(uid, data_offset, data_length, p_data, actual_length); -} - -static psa_status_t get_info_func(storage_type_t stype, psa_storage_uid_t uid, - struct psa_storage_info_t *p_info) -{ - return (stype == its) ? - psa_its_get_info(uid, p_info) : - psa_ps_get_info(uid, p_info); -} - -static psa_status_t remove_func(storage_type_t stype, psa_storage_uid_t uid) -{ - return (stype == its) ? - psa_its_remove(uid) : - psa_ps_remove(uid); -} - - -template -void pits_ps_test() -{ - psa_status_t status = PSA_SUCCESS; - uint8_t write_buff[TEST_BUFF_SIZE] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}; - uint8_t read_buff[TEST_BUFF_SIZE] = {0}; - size_t actual_size; - psa_storage_create_flags_t flags; - struct psa_storage_info_t info = {0, PSA_STORAGE_FLAG_WRITE_ONCE}; - memset(read_buff, 0, TEST_BUFF_SIZE); - - status = get_info_func(stype, 5, &info); - TEST_ASSERT_EQUAL(PSA_ERROR_DOES_NOT_EXIST, status); - - status = set_func(stype, 5, TEST_BUFF_SIZE, write_buff, 0); - TEST_ASSERT_EQUAL(PSA_SUCCESS, status); - - status = get_info_func(stype, 5, &info); - TEST_ASSERT_EQUAL(PSA_SUCCESS, status); - TEST_ASSERT_EQUAL(TEST_BUFF_SIZE, info.size); - TEST_ASSERT_EQUAL(0, info.flags); - - status = get_func(stype, 5, 0, TEST_BUFF_SIZE, read_buff, &actual_size); - TEST_ASSERT_EQUAL(PSA_SUCCESS, status); - TEST_ASSERT_EQUAL_MEMORY(write_buff, read_buff, TEST_BUFF_SIZE); - - memset(read_buff, 0, TEST_BUFF_SIZE); - status = get_func(stype, 5, 1, TEST_BUFF_SIZE, read_buff, &actual_size); - TEST_ASSERT_NOT_EQUAL(PSA_SUCCESS, status); - - status = get_func(stype, 5, 1, TEST_BUFF_SIZE - 1, read_buff, &actual_size); - TEST_ASSERT_EQUAL(PSA_SUCCESS, status); - TEST_ASSERT_EQUAL_MEMORY(write_buff + 1, read_buff, TEST_BUFF_SIZE - 1); - - status = remove_func(stype, 5); - TEST_ASSERT_EQUAL(PSA_SUCCESS, status); - - status = get_info_func(stype, 5, &info); - TEST_ASSERT_EQUAL(PSA_ERROR_DOES_NOT_EXIST, status); - - if (stype == its) { - return; - } - - mbed::KVMap &kv_map = mbed::KVMap::get_instance(); - mbed::KVStore *kvstore = kv_map.get_main_kv_instance(STR_EXPAND(MBED_CONF_STORAGE_DEFAULT_KV)); - uint32_t kv_get_flags; - - flags = PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION; - status = set_func(stype, 6, TEST_BUFF_SIZE, write_buff, flags); - TEST_ASSERT_EQUAL(PSA_SUCCESS, status); - - status = get_info_func(stype, 6, &info); - TEST_ASSERT_EQUAL(PSA_SUCCESS, status); - TEST_ASSERT_EQUAL(flags, info.flags); - - status = psa_storage_get_info_impl(kvstore, 1, 6, &info, &kv_get_flags); - TEST_ASSERT_EQUAL(PSA_SUCCESS, status); - TEST_ASSERT_EQUAL(kv_get_flags, mbed::KVStore::REQUIRE_CONFIDENTIALITY_FLAG); - - flags = PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION | PSA_STORAGE_FLAG_NO_CONFIDENTIALITY | PSA_STORAGE_FLAG_WRITE_ONCE; - status = set_func(stype, 6, TEST_BUFF_SIZE, write_buff, flags); - TEST_ASSERT_EQUAL(PSA_SUCCESS, status); - - status = get_info_func(stype, 6, &info); - TEST_ASSERT_EQUAL(PSA_SUCCESS, status); - TEST_ASSERT_EQUAL(flags, info.flags); - - status = psa_storage_get_info_impl(kvstore, 1, 6, &info, &kv_get_flags); - TEST_ASSERT_EQUAL(PSA_SUCCESS, status); - TEST_ASSERT_EQUAL(kv_get_flags, mbed::KVStore::WRITE_ONCE_FLAG); -} - -template -void pits_ps_write_once_test() -{ - psa_status_t status = PSA_SUCCESS; - uint8_t write_buff[TEST_BUFF_SIZE] = {0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00}; - uint8_t read_buff[TEST_BUFF_SIZE] = {0}; - size_t actual_size; - struct psa_storage_info_t info = {0, 0}; - - status = get_info_func(stype, 5, &info); - TEST_ASSERT_EQUAL(PSA_ERROR_DOES_NOT_EXIST, status); - - status = set_func(stype, 5, TEST_BUFF_SIZE, write_buff, PSA_STORAGE_FLAG_WRITE_ONCE); - TEST_ASSERT_EQUAL(PSA_SUCCESS, status); - - info.size = 0; - info.flags = PSA_STORAGE_FLAG_WRITE_ONCE; - status = get_info_func(stype, 5, &info); - TEST_ASSERT_EQUAL(PSA_SUCCESS, status); - TEST_ASSERT_EQUAL(TEST_BUFF_SIZE, info.size); - TEST_ASSERT_EQUAL(PSA_STORAGE_FLAG_WRITE_ONCE, info.flags); - - status = get_func(stype, 5, 0, TEST_BUFF_SIZE, read_buff, &actual_size); - TEST_ASSERT_EQUAL(PSA_SUCCESS, status); - TEST_ASSERT_EQUAL(TEST_BUFF_SIZE, actual_size); - TEST_ASSERT_EQUAL_MEMORY(write_buff, read_buff, TEST_BUFF_SIZE); - - status = set_func(stype, 5, TEST_BUFF_SIZE, write_buff, PSA_STORAGE_FLAG_WRITE_ONCE); - TEST_ASSERT_EQUAL(PSA_ERROR_NOT_PERMITTED, status); - - status = set_func(stype, 5, TEST_BUFF_SIZE, write_buff, 0); - TEST_ASSERT_EQUAL(PSA_ERROR_NOT_PERMITTED, status); - - status = remove_func(stype, 5); - TEST_ASSERT_EQUAL(PSA_ERROR_NOT_PERMITTED, status); - - info.size = 0; - info.flags = PSA_STORAGE_FLAG_WRITE_ONCE; - status = get_info_func(stype, 5, &info); - TEST_ASSERT_EQUAL(PSA_SUCCESS, status); - TEST_ASSERT_EQUAL(TEST_BUFF_SIZE, info.size); - TEST_ASSERT_EQUAL(PSA_STORAGE_FLAG_WRITE_ONCE, info.flags); -} - -utest::v1::status_t case_its_teardown_handler(const Case *const source, const size_t passed, const size_t failed, const failure_t reason) -{ - psa_status_t status; - status = mbed_psa_reboot_and_request_new_security_state(PSA_LIFECYCLE_ASSEMBLY_AND_TEST); - TEST_ASSERT_EQUAL(PSA_SUCCESS, status); - return greentea_case_teardown_handler(source, passed, failed, reason); -} - -template -utest::v1::status_t case_its_setup_handler(const Case *const source, const size_t index_of_case) -{ - psa_status_t status; - if (stype == its) { - status = mbed_psa_reboot_and_request_new_security_state(PSA_LIFECYCLE_ASSEMBLY_AND_TEST); - TEST_ASSERT_EQUAL(PSA_SUCCESS, status); - } else { - status = psa_ps_reset(); - TEST_ASSERT_EQUAL(PSA_SUCCESS, status); - } -#if DEVICEKEY_ENABLED - DeviceKey::get_instance().generate_root_of_trust(); -#endif - return greentea_case_setup_handler(source, index_of_case); -} - -Case cases[] = { - Case("PSA prot internal storage - Basic", case_its_setup_handler, pits_ps_test, case_its_teardown_handler), - Case("PSA prot internal storage - Write-once", case_its_setup_handler, pits_ps_write_once_test, case_its_teardown_handler), -#if COMPONENT_FLASHIAP - Case("PSA protected storage - Basic", case_its_setup_handler, pits_ps_test), - Case("PSA protected storage - Write-once", case_its_setup_handler, pits_ps_write_once_test) -#endif -}; - -utest::v1::status_t greentea_test_setup(const size_t number_of_cases) -{ - GREENTEA_SETUP(60, "default_auto"); - return greentea_test_setup_handler(number_of_cases); -} - -Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); - -int main() -{ - return !Harness::run(specification); -} - -#endif // TARGET_PSA -#endif // !defined(MBED_CONF_RTOS_PRESENT) diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/client.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/client.h deleted file mode 100644 index de1c520..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/client.h +++ /dev/null @@ -1,155 +0,0 @@ -/* Copyright (c) 2017-2020 ARM Limited - * - * 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. - */ - -#if defined(FEATURE_TFM) -#include "interface/include/psa_client.h" -#else - -#ifndef __MBED_OS_DEFAULT_PSA_CLIENT_API_H__ -#define __MBED_OS_DEFAULT_PSA_CLIENT_API_H__ - -#include -#include "psa/error.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if !defined(UINT32_MAX) -#define UINT32_MAX ((uint32_t)-1) -#endif - -#if !defined(INT32_MIN) -#define INT32_MIN (-0x7fffffff - 1) -#endif - -#define PSA_FRAMEWORK_VERSION (0x0100) /**< Version of the PSA Framework API. */ -#define PSA_VERSION_NONE (0L) /**< Identifier for an unimplemented Root of Trust (RoT) Service. */ -#define PSA_CONNECTION_REFUSED (INT32_MIN + 1) /**< The return value from psa_connect() if the RoT Service or SPM was unable to establish a connection.*/ -#define PSA_CONNECTION_BUSY (INT32_MIN + 2) /**< The return value from psa_connect() if the RoT Service rejects the connection for a transient reason.*/ -#define PSA_DROP_CONNECTION (INT32_MIN) /**< The result code in a call to psa_reply() to indicate a nonrecoverable error in the client.*/ -#define PSA_NULL_HANDLE ((psa_handle_t)0) /**< Denotes an invalid handle.*/ - -typedef int32_t psa_handle_t; - -typedef struct psa_invec { - const void *base; /**< Starting address of the buffer.*/ - size_t len; /**< Length in bytes of the buffer.*/ -} psa_invec; - - -typedef struct psa_outvec { - void *base; /**< Starting address of the buffer.*/ - size_t len; /**< Length in bytes of the buffer.*/ -} psa_outvec; - -/** - * \brief Retrieve the version of the PSA Framework API that is implemented. - * - * \return version The version of the PSA Framework implementation - * that is providing the runtime services to the - * caller. The major and minor version are encoded - * as follows: - * \arg version[15:8] -- major version number. - * \arg version[7:0] -- minor version number. - */ -uint32_t psa_framework_version(void); - -/** - * \brief Retrieve the version of an RoT Service or indicate that it is not - * present on this system. - * - * \param[in] sid ID of the RoT Service to query. - * - * \retval PSA_VERSION_NONE The RoT Service is not implemented, or the - * caller is not permitted to access the service. - * \retval > 0 The version of the implemented RoT Service. - */ -uint32_t psa_version(uint32_t sid); - -/** - * \brief Connect to an RoT Service by its SID. - * - * \param[in] sid ID of the RoT Service to connect to. - * \param[in] version Requested version of the RoT Service. - * - * \retval > 0 A handle for the connection. - * \retval PSA_ERROR_CONNECTION_REFUSED The SPM or RoT Service has refused the - * connection. - * \retval PSA_ERROR_CONNECTION_BUSY The SPM or RoT Service cannot make the - * connection at the moment. - * \retval "PROGRAMMER ERROR" The call is a PROGRAMMER ERROR if one or more - * of the following are true: - * \arg The RoT Service ID is not present. - * \arg The RoT Service version is not supported. - * \arg The caller is not allowed to access the RoT - * service. - */ -psa_handle_t psa_connect(uint32_t sid, uint32_t version); - -/** - * \brief Call an RoT Service on an established connection. - * - * \param[in] handle A handle to an established connection. - * \param[in] type The reuqest type. - * Must be zero( \ref PSA_IPC_CALL) or positive. - * \param[in] in_vec Array of input \ref psa_invec structures. - * \param[in] in_len Number of input \ref psa_invec structures. - * \param[in/out] out_vec Array of output \ref psa_outvec structures. - * \param[in] out_len Number of output \ref psa_outvec structures. - * - * \retval >=0 RoT Service-specific status value. - * \retval <0 RoT Service-specific error code. - * \retval PSA_ERROR_PROGRAMMER_ERROR The connection has been terminated by the - * RoT Service. The call is a PROGRAMMER ERROR if - * one or more of the following are true: - * \arg An invalid handle was passed. - * \arg The connection is already handling a request. - * \arg type < 0. - * \arg An invalid memory reference was provided. - * \arg in_len + out_len > PSA_MAX_IOVEC. - * \arg The message is unrecognized by the RoT - * Service or incorrectly formatted. - */ -psa_status_t psa_call(psa_handle_t handle, int32_t type, - const psa_invec *in_vec, - size_t in_len, - psa_outvec *out_vec, - size_t out_len); - -/** - * \brief Close a connection to an RoT Service. - * - * \param[in] handle A handle to an established connection, or the - * null handle. - * - * \retval void Success. - * \retval "PROGRAMMER ERROR" The call is a PROGRAMMER ERROR if one or more - * of the following are true: - * \arg An invalid handle was provided that is not - * the null handle. - * \arg The connection is currently handling a - * request. - */ -void psa_close(psa_handle_t handle); - -#ifdef __cplusplus -} -#endif - -#endif // __MBED_OS_DEFAULT_PSA_CLIENT_API_H__ -#endif diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto.h deleted file mode 100644 index 2b07b74..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto.h +++ /dev/null @@ -1,3780 +0,0 @@ -/** - * \file psa/crypto.h - * \brief Platform Security Architecture cryptography module - */ -/* - * Copyright (C) 2018, ARM Limited, 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 PSA_CRYPTO_H -#define PSA_CRYPTO_H - -#include "crypto_platform.h" - -#include - -#ifdef __DOXYGEN_ONLY__ -/* This __DOXYGEN_ONLY__ block contains mock definitions for things that - * must be defined in the crypto_platform.h header. These mock definitions - * are present in this file as a convenience to generate pretty-printed - * documentation that includes those definitions. */ - -/** \defgroup platform Implementation-specific definitions - * @{ - */ - -/** \brief Key handle. - * - * This type represents open handles to keys. It must be an unsigned integral - * type. The choice of type is implementation-dependent. - * - * 0 is not a valid key handle. How other handle values are assigned is - * implementation-dependent. - */ -typedef _unsigned_integral_type_ psa_key_handle_t; - -/**@}*/ -#endif /* __DOXYGEN_ONLY__ */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* The file "crypto_types.h" declares types that encode errors, - * algorithms, key types, policies, etc. */ -#include "crypto_types.h" - -/** \defgroup version API version - * @{ - */ - -/** - * The major version of this implementation of the PSA Crypto API - */ -#define PSA_CRYPTO_API_VERSION_MAJOR 1 - -/** - * The minor version of this implementation of the PSA Crypto API - */ -#define PSA_CRYPTO_API_VERSION_MINOR 0 - -/**@}*/ - -/* The file "crypto_values.h" declares macros to build and analyze values - * of integral types defined in "crypto_types.h". */ -#include "crypto_values.h" - -/** \defgroup initialization Library initialization - * @{ - */ - -/** - * \brief Library initialization. - * - * Applications must call this function before calling any other - * function in this module. - * - * Applications may call this function more than once. Once a call - * succeeds, subsequent calls are guaranteed to succeed. - * - * If the application calls other functions before calling psa_crypto_init(), - * the behavior is undefined. Implementations are encouraged to either perform - * the operation as if the library had been initialized or to return - * #PSA_ERROR_BAD_STATE or some other applicable error. In particular, - * implementations should not return a success status if the lack of - * initialization may have security implications, for example due to improper - * seeding of the random number generator. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY - */ -psa_status_t psa_crypto_init(void); - -/**@}*/ - -/** \addtogroup attributes - * @{ - */ - -/** \def PSA_KEY_ATTRIBUTES_INIT - * - * This macro returns a suitable initializer for a key attribute structure - * of type #psa_key_attributes_t. - */ -#ifdef __DOXYGEN_ONLY__ -/* This is an example definition for documentation purposes. - * Implementations should define a suitable value in `crypto_struct.h`. - */ -#define PSA_KEY_ATTRIBUTES_INIT {0} -#endif - -/** Return an initial value for a key attributes structure. - */ -static psa_key_attributes_t psa_key_attributes_init(void); - -/** Declare a key as persistent and set its key identifier. - * - * If the attribute structure currently declares the key as volatile (which - * is the default content of an attribute structure), this function sets - * the lifetime attribute to #PSA_KEY_LIFETIME_PERSISTENT. - * - * This function does not access storage, it merely stores the given - * value in the structure. - * The persistent key will be written to storage when the attribute - * structure is passed to a key creation function such as - * psa_import_key(), psa_generate_key(), - * psa_key_derivation_output_key() or psa_copy_key(). - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate each of its arguments exactly once. - * - * \param[out] attributes The attribute structure to write to. - * \param id The persistent identifier for the key. - */ -static void psa_set_key_id(psa_key_attributes_t *attributes, - psa_key_id_t id); - -/** Set the location of a persistent key. - * - * To make a key persistent, you must give it a persistent key identifier - * with psa_set_key_id(). By default, a key that has a persistent identifier - * is stored in the default storage area identifier by - * #PSA_KEY_LIFETIME_PERSISTENT. Call this function to choose a storage - * area, or to explicitly declare the key as volatile. - * - * This function does not access storage, it merely stores the given - * value in the structure. - * The persistent key will be written to storage when the attribute - * structure is passed to a key creation function such as - * psa_import_key(), psa_generate_key(), - * psa_key_derivation_output_key() or psa_copy_key(). - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate each of its arguments exactly once. - * - * \param[out] attributes The attribute structure to write to. - * \param lifetime The lifetime for the key. - * If this is #PSA_KEY_LIFETIME_VOLATILE, the - * key will be volatile, and the key identifier - * attribute is reset to 0. - */ -static void psa_set_key_lifetime(psa_key_attributes_t *attributes, - psa_key_lifetime_t lifetime); - -/** Retrieve the key identifier from key attributes. - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate its argument exactly once. - * - * \param[in] attributes The key attribute structure to query. - * - * \return The persistent identifier stored in the attribute structure. - * This value is unspecified if the attribute structure declares - * the key as volatile. - */ -static psa_key_id_t psa_get_key_id(const psa_key_attributes_t *attributes); - -/** Retrieve the lifetime from key attributes. - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate its argument exactly once. - * - * \param[in] attributes The key attribute structure to query. - * - * \return The lifetime value stored in the attribute structure. - */ -static psa_key_lifetime_t psa_get_key_lifetime( - const psa_key_attributes_t *attributes); - -/** Declare usage flags for a key. - * - * Usage flags are part of a key's usage policy. They encode what - * kind of operations are permitted on the key. For more details, - * refer to the documentation of the type #psa_key_usage_t. - * - * This function overwrites any usage flags - * previously set in \p attributes. - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate each of its arguments exactly once. - * - * \param[out] attributes The attribute structure to write to. - * \param usage_flags The usage flags to write. - */ -static void psa_set_key_usage_flags(psa_key_attributes_t *attributes, - psa_key_usage_t usage_flags); - -/** Retrieve the usage flags from key attributes. - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate its argument exactly once. - * - * \param[in] attributes The key attribute structure to query. - * - * \return The usage flags stored in the attribute structure. - */ -static psa_key_usage_t psa_get_key_usage_flags( - const psa_key_attributes_t *attributes); - -/** Declare the permitted algorithm policy for a key. - * - * The permitted algorithm policy of a key encodes which algorithm or - * algorithms are permitted to be used with this key. The following - * algorithm policies are supported: - * - 0 does not allow any cryptographic operation with the key. The key - * may be used for non-cryptographic actions such as exporting (if - * permitted by the usage flags). - * - An algorithm value permits this particular algorithm. - * - An algorithm wildcard built from #PSA_ALG_ANY_HASH allows the specified - * signature scheme with any hash algorithm. - * - * This function overwrites any algorithm policy - * previously set in \p attributes. - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate each of its arguments exactly once. - * - * \param[out] attributes The attribute structure to write to. - * \param alg The permitted algorithm policy to write. - */ -static void psa_set_key_algorithm(psa_key_attributes_t *attributes, - psa_algorithm_t alg); - - -/** Retrieve the algorithm policy from key attributes. - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate its argument exactly once. - * - * \param[in] attributes The key attribute structure to query. - * - * \return The algorithm stored in the attribute structure. - */ -static psa_algorithm_t psa_get_key_algorithm( - const psa_key_attributes_t *attributes); - -/** Declare the type of a key. - * - * This function overwrites any key type - * previously set in \p attributes. - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate each of its arguments exactly once. - * - * \param[out] attributes The attribute structure to write to. - * \param type The key type to write. - * If this is 0, the key type in \p attributes - * becomes unspecified. - */ -static void psa_set_key_type(psa_key_attributes_t *attributes, - psa_key_type_t type); - - -/** Declare the size of a key. - * - * This function overwrites any key size previously set in \p attributes. - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate each of its arguments exactly once. - * - * \param[out] attributes The attribute structure to write to. - * \param bits The key size in bits. - * If this is 0, the key size in \p attributes - * becomes unspecified. Keys of size 0 are - * not supported. - */ -static void psa_set_key_bits(psa_key_attributes_t *attributes, - size_t bits); - -/** Retrieve the key type from key attributes. - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate its argument exactly once. - * - * \param[in] attributes The key attribute structure to query. - * - * \return The key type stored in the attribute structure. - */ -static psa_key_type_t psa_get_key_type(const psa_key_attributes_t *attributes); - -/** Retrieve the key size from key attributes. - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate its argument exactly once. - * - * \param[in] attributes The key attribute structure to query. - * - * \return The key size stored in the attribute structure, in bits. - */ -static size_t psa_get_key_bits(const psa_key_attributes_t *attributes); - -/** Retrieve the attributes of a key. - * - * This function first resets the attribute structure as with - * psa_reset_key_attributes(). It then copies the attributes of - * the given key into the given attribute structure. - * - * \note This function may allocate memory or other resources. - * Once you have called this function on an attribute structure, - * you must call psa_reset_key_attributes() to free these resources. - * - * \param[in] handle Handle to the key to query. - * \param[in,out] attributes On success, the attributes of the key. - * On failure, equivalent to a - * freshly-initialized structure. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_get_key_attributes(psa_key_handle_t handle, - psa_key_attributes_t *attributes); - -/** Reset a key attribute structure to a freshly initialized state. - * - * You must initialize the attribute structure as described in the - * documentation of the type #psa_key_attributes_t before calling this - * function. Once the structure has been initialized, you may call this - * function at any time. - * - * This function frees any auxiliary resources that the structure - * may contain. - * - * \param[in,out] attributes The attribute structure to reset. - */ -void psa_reset_key_attributes(psa_key_attributes_t *attributes); - -/**@}*/ - -/** \defgroup key_management Key management - * @{ - */ - -/** Open a handle to an existing persistent key. - * - * Open a handle to a persistent key. A key is persistent if it was created - * with a lifetime other than #PSA_KEY_LIFETIME_VOLATILE. A persistent key - * always has a nonzero key identifier, set with psa_set_key_id() when - * creating the key. Implementations may provide additional pre-provisioned - * keys that can be opened with psa_open_key(). Such keys have a key identifier - * in the vendor range, as documented in the description of #psa_key_id_t. - * - * The application must eventually close the handle with psa_close_key() or - * psa_destroy_key() to release associated resources. If the application dies - * without calling one of these functions, the implementation should perform - * the equivalent of a call to psa_close_key(). - * - * Some implementations permit an application to open the same key multiple - * times. If this is successful, each call to psa_open_key() will return a - * different key handle. - * - * \note Applications that rely on opening a key multiple times will not be - * portable to implementations that only permit a single key handle to be - * opened. See also :ref:\`key-handles\`. - * - * \param id The persistent identifier of the key. - * \param[out] handle On success, a handle to the key. - * - * \retval #PSA_SUCCESS - * Success. The application can now use the value of `*handle` - * to access the key. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * The implementation does not have sufficient resources to open the - * key. This can be due to reaching an implementation limit on the - * number of open keys, the number of open key handles, or available - * memory. - * \retval #PSA_ERROR_DOES_NOT_EXIST - * There is no persistent key with key identifier \p id. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p id is not a valid persistent key identifier. - * \retval #PSA_ERROR_NOT_PERMITTED - * The specified key exists, but the application does not have the - * permission to access it. Note that this specification does not - * define any way to create such a key, but it may be possible - * through implementation-specific means. - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_open_key(psa_key_id_t id, - psa_key_handle_t *handle); - - -/** Close a key handle. - * - * If the handle designates a volatile key, this will destroy the key material - * and free all associated resources, just like psa_destroy_key(). - * - * If this is the last open handle to a persistent key, then closing the handle - * will free all resources associated with the key in volatile memory. The key - * data in persistent storage is not affected and can be opened again later - * with a call to psa_open_key(). - * - * Closing the key handle makes the handle invalid, and the key handle - * must not be used again by the application. - * - * \note If the key handle was used to set up an active - * :ref:\`multipart operation \`, then closing the - * key handle can cause the multipart operation to fail. Applications should - * maintain the key handle until after the multipart operation has finished. - * - * \param handle The key handle to close. - * If this is \c 0, do nothing and return \c PSA_SUCCESS. - * - * \retval #PSA_SUCCESS - * \p handle was a valid handle or \c 0. It is now closed. - * \retval #PSA_ERROR_INVALID_HANDLE - * \p handle is not a valid handle nor \c 0. - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_close_key(psa_key_handle_t handle); - -/** Make a copy of a key. - * - * Copy key material from one location to another. - * - * This function is primarily useful to copy a key from one location - * to another, since it populates a key using the material from - * another key which may have a different lifetime. - * - * This function may be used to share a key with a different party, - * subject to implementation-defined restrictions on key sharing. - * - * The policy on the source key must have the usage flag - * #PSA_KEY_USAGE_COPY set. - * This flag is sufficient to permit the copy if the key has the lifetime - * #PSA_KEY_LIFETIME_VOLATILE or #PSA_KEY_LIFETIME_PERSISTENT. - * Some secure elements do not provide a way to copy a key without - * making it extractable from the secure element. If a key is located - * in such a secure element, then the key must have both usage flags - * #PSA_KEY_USAGE_COPY and #PSA_KEY_USAGE_EXPORT in order to make - * a copy of the key outside the secure element. - * - * The resulting key may only be used in a way that conforms to - * both the policy of the original key and the policy specified in - * the \p attributes parameter: - * - The usage flags on the resulting key are the bitwise-and of the - * usage flags on the source policy and the usage flags in \p attributes. - * - If both allow the same algorithm or wildcard-based - * algorithm policy, the resulting key has the same algorithm policy. - * - If either of the policies allows an algorithm and the other policy - * allows a wildcard-based algorithm policy that includes this algorithm, - * the resulting key allows the same algorithm. - * - If the policies do not allow any algorithm in common, this function - * fails with the status #PSA_ERROR_INVALID_ARGUMENT. - * - * The effect of this function on implementation-defined attributes is - * implementation-defined. - * - * \param source_handle The key to copy. It must be a valid key handle. - * \param[in] attributes The attributes for the new key. - * They are used as follows: - * - The key type and size may be 0. If either is - * nonzero, it must match the corresponding - * attribute of the source key. - * - The key location (the lifetime and, for - * persistent keys, the key identifier) is - * used directly. - * - The policy constraints (usage flags and - * algorithm policy) are combined from - * the source key and \p attributes so that - * both sets of restrictions apply, as - * described in the documentation of this function. - * \param[out] target_handle On success, a handle to the newly created key. - * \c 0 on failure. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_HANDLE - * \p source_handle is invalid. - * \retval #PSA_ERROR_ALREADY_EXISTS - * This is an attempt to create a persistent key, and there is - * already a persistent key with the given identifier. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The lifetime or identifier in \p attributes are invalid. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The policy constraints on the source and specified in - * \p attributes are incompatible. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p attributes specifies a key type or key size - * which does not match the attributes of the source key. - * \retval #PSA_ERROR_NOT_PERMITTED - * The source key does not have the #PSA_KEY_USAGE_COPY usage flag. - * \retval #PSA_ERROR_NOT_PERMITTED - * The source key is not exportable and its lifetime does not - * allow copying it to the target's lifetime. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_INSUFFICIENT_STORAGE - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_copy_key(psa_key_handle_t source_handle, - const psa_key_attributes_t *attributes, - psa_key_handle_t *target_handle); - - -/** - * \brief Destroy a key. - * - * This function destroys a key from both volatile - * memory and, if applicable, non-volatile storage. Implementations shall - * make a best effort to ensure that that the key material cannot be recovered. - * - * This function also erases any metadata such as policies and frees - * resources associated with the key. To free all resources associated with - * the key, all handles to the key must be closed or destroyed. - * - * Destroying the key makes the handle invalid, and the key handle - * must not be used again by the application. Using other open handles to the - * destroyed key in a cryptographic operation will result in an error. - * - * If a key is currently in use in a multipart operation, then destroying the - * key will cause the multipart operation to fail. - * - * \param handle Handle to the key to erase. - * If this is \c 0, do nothing and return \c PSA_SUCCESS. - * - * \retval #PSA_SUCCESS - * \p handle was a valid handle and the key material that it - * referred to has been erased. - * Alternatively, \p handle is \c 0. - * \retval #PSA_ERROR_NOT_PERMITTED - * The key cannot be erased because it is - * read-only, either due to a policy or due to physical restrictions. - * \retval #PSA_ERROR_INVALID_HANDLE - * \p handle is not a valid handle nor \c 0. - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * There was an failure in communication with the cryptoprocessor. - * The key material may still be present in the cryptoprocessor. - * \retval #PSA_ERROR_STORAGE_FAILURE - * The storage is corrupted. Implementations shall make a best effort - * to erase key material even in this stage, however applications - * should be aware that it may be impossible to guarantee that the - * key material is not recoverable in such cases. - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * An unexpected condition which is not a storage corruption or - * a communication failure occurred. The cryptoprocessor may have - * been compromised. - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_destroy_key(psa_key_handle_t handle); - -/**@}*/ - -/** \defgroup import_export Key import and export - * @{ - */ - -/** - * \brief Import a key in binary format. - * - * This function supports any output from psa_export_key(). Refer to the - * documentation of psa_export_public_key() for the format of public keys - * and to the documentation of psa_export_key() for the format for - * other key types. - * - * The key data determines the key size. The attributes may optionally - * specify a key size; in this case it must match the size determined - * from the key data. A key size of 0 in \p attributes indicates that - * the key size is solely determined by the key data. - * - * Implementations must reject an attempt to import a key of size 0. - * - * This specification supports a single format for each key type. - * Implementations may support other formats as long as the standard - * format is supported. Implementations that support other formats - * should ensure that the formats are clearly unambiguous so as to - * minimize the risk that an invalid input is accidentally interpreted - * according to a different format. - * - * \param[in] attributes The attributes for the new key. - * The key size is always determined from the - * \p data buffer. - * If the key size in \p attributes is nonzero, - * it must be equal to the size from \p data. - * \param[out] handle On success, a handle to the newly created key. - * \c 0 on failure. - * \param[in] data Buffer containing the key data. The content of this - * buffer is interpreted according to the type declared - * in \p attributes. - * All implementations must support at least the format - * described in the documentation - * of psa_export_key() or psa_export_public_key() for - * the chosen type. Implementations may allow other - * formats, but should be conservative: implementations - * should err on the side of rejecting content if it - * may be erroneous (e.g. wrong type or truncated data). - * \param data_length Size of the \p data buffer in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * If the key is persistent, the key material and the key's metadata - * have been saved to persistent storage. - * \retval #PSA_ERROR_ALREADY_EXISTS - * This is an attempt to create a persistent key, and there is - * already a persistent key with the given identifier. - * \retval #PSA_ERROR_NOT_SUPPORTED - * The key type or key size is not supported, either by the - * implementation in general or in this particular persistent location. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The key attributes, as a whole, are invalid. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The key data is not correctly formatted. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The size in \p attributes is nonzero and does not match the size - * of the key data. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_INSUFFICIENT_STORAGE - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_import_key(const psa_key_attributes_t *attributes, - const uint8_t *data, - size_t data_length, - psa_key_handle_t *handle); - - - -/** - * \brief Export a key in binary format. - * - * The output of this function can be passed to psa_import_key() to - * create an equivalent object. - * - * If the implementation of psa_import_key() supports other formats - * beyond the format specified here, the output from psa_export_key() - * must use the representation specified here, not the original - * representation. - * - * For standard key types, the output format is as follows: - * - * - For symmetric keys (including MAC keys), the format is the - * raw bytes of the key. - * - For DES, the key data consists of 8 bytes. The parity bits must be - * correct. - * - For Triple-DES, the format is the concatenation of the - * two or three DES keys. - * - For RSA key pairs (#PSA_KEY_TYPE_RSA_KEY_PAIR), the format - * is the non-encrypted DER encoding of the representation defined by - * PKCS\#1 (RFC 8017) as `RSAPrivateKey`, version 0. - * ``` - * RSAPrivateKey ::= SEQUENCE { - * version INTEGER, -- must be 0 - * modulus INTEGER, -- n - * publicExponent INTEGER, -- e - * privateExponent INTEGER, -- d - * prime1 INTEGER, -- p - * prime2 INTEGER, -- q - * exponent1 INTEGER, -- d mod (p-1) - * exponent2 INTEGER, -- d mod (q-1) - * coefficient INTEGER, -- (inverse of q) mod p - * } - * ``` - * - For elliptic curve key pairs (key types for which - * #PSA_KEY_TYPE_IS_ECC_KEY_PAIR is true), the format is - * a representation of the private value as a `ceiling(m/8)`-byte string - * where `m` is the bit size associated with the curve, i.e. the bit size - * of the order of the curve's coordinate field. This byte string is - * in little-endian order for Montgomery curves (curve types - * `PSA_ECC_CURVE_CURVEXXX`), and in big-endian order for Weierstrass - * curves (curve types `PSA_ECC_CURVE_SECTXXX`, `PSA_ECC_CURVE_SECPXXX` - * and `PSA_ECC_CURVE_BRAINPOOL_PXXX`). - * This is the content of the `privateKey` field of the `ECPrivateKey` - * format defined by RFC 5915. - * - For Diffie-Hellman key exchange key pairs (key types for which - * #PSA_KEY_TYPE_IS_DH_KEY_PAIR is true), the - * format is the representation of the private key `x` as a big-endian byte - * string. The length of the byte string is the private key size in bytes - * (leading zeroes are not stripped). - * - For public keys (key types for which #PSA_KEY_TYPE_IS_PUBLIC_KEY is - * true), the format is the same as for psa_export_public_key(). - * - * The policy on the key must have the usage flag #PSA_KEY_USAGE_EXPORT set. - * - * \param handle Handle to the key to export. - * \param[out] data Buffer where the key data is to be written. - * \param data_size Size of the \p data buffer in bytes. - * \param[out] data_length On success, the number of bytes - * that make up the key data. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * The key does not have the #PSA_KEY_USAGE_EXPORT flag. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p data buffer is too small. You can determine a - * sufficient buffer size by calling - * #PSA_KEY_EXPORT_MAX_SIZE(\c type, \c bits) - * where \c type is the key type - * and \c bits is the key size in bits. - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_export_key(psa_key_handle_t handle, - uint8_t *data, - size_t data_size, - size_t *data_length); - -/** - * \brief Export a public key or the public part of a key pair in binary format. - * - * The output of this function can be passed to psa_import_key() to - * create an object that is equivalent to the public key. - * - * This specification supports a single format for each key type. - * Implementations may support other formats as long as the standard - * format is supported. Implementations that support other formats - * should ensure that the formats are clearly unambiguous so as to - * minimize the risk that an invalid input is accidentally interpreted - * according to a different format. - * - * For standard key types, the output format is as follows: - * - For RSA public keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY), the DER encoding of - * the representation defined by RFC 3279 §2.3.1 as `RSAPublicKey`. - * ``` - * RSAPublicKey ::= SEQUENCE { - * modulus INTEGER, -- n - * publicExponent INTEGER } -- e - * ``` - * - For elliptic curve public keys (key types for which - * #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true), the format is the uncompressed - * representation defined by SEC1 §2.3.3 as the content of an ECPoint. - * Let `m` be the bit size associated with the curve, i.e. the bit size of - * `q` for a curve over `F_q`. The representation consists of: - * - The byte 0x04; - * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; - * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. - * - For Diffie-Hellman key exchange public keys (key types for which - * #PSA_KEY_TYPE_IS_DH_PUBLIC_KEY is true), - * the format is the representation of the public key `y = g^x mod p` as a - * big-endian byte string. The length of the byte string is the length of the - * base prime `p` in bytes. - * - * Exporting a public key object or the public part of a key pair is - * always permitted, regardless of the key's usage flags. - * - * \param handle Handle to the key to export. - * \param[out] data Buffer where the key data is to be written. - * \param data_size Size of the \p data buffer in bytes. - * \param[out] data_length On success, the number of bytes - * that make up the key data. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The key is neither a public key nor a key pair. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p data buffer is too small. You can determine a - * sufficient buffer size by calling - * #PSA_KEY_EXPORT_MAX_SIZE(#PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(\c type), \c bits) - * where \c type is the key type - * and \c bits is the key size in bits. - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_export_public_key(psa_key_handle_t handle, - uint8_t *data, - size_t data_size, - size_t *data_length); - - - -/**@}*/ - -/** \defgroup hash Message digests - * @{ - */ - -/** Calculate the hash (digest) of a message. - * - * \note To verify the hash of a message against an - * expected value, use psa_hash_compare() instead. - * - * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value - * such that #PSA_ALG_IS_HASH(\p alg) is true). - * \param[in] input Buffer containing the message to hash. - * \param input_length Size of the \p input buffer in bytes. - * \param[out] hash Buffer where the hash is to be written. - * \param hash_size Size of the \p hash buffer in bytes. - * \param[out] hash_length On success, the number of bytes - * that make up the hash value. This is always - * #PSA_HASH_SIZE(\p alg). - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not a hash algorithm. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * \p hash_size is too small - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_hash_compute(psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - uint8_t *hash, - size_t hash_size, - size_t *hash_length); - -/** Calculate the hash (digest) of a message and compare it with a - * reference value. - * - * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value - * such that #PSA_ALG_IS_HASH(\p alg) is true). - * \param[in] input Buffer containing the message to hash. - * \param input_length Size of the \p input buffer in bytes. - * \param[out] hash Buffer containing the expected hash value. - * \param hash_length Size of the \p hash buffer in bytes. - * - * \retval #PSA_SUCCESS - * The expected hash is identical to the actual hash of the input. - * \retval #PSA_ERROR_INVALID_SIGNATURE - * The hash of the message was calculated successfully, but it - * differs from the expected hash. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not a hash algorithm. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p input_length or \p hash_length do not match the hash size for \p alg - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_hash_compare(psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - const uint8_t *hash, - size_t hash_length); - -/** The type of the state data structure for multipart hash operations. - * - * Before calling any function on a hash operation object, the application must - * initialize it by any of the following means: - * - Set the structure to all-bits-zero, for example: - * \code - * psa_hash_operation_t operation; - * memset(&operation, 0, sizeof(operation)); - * \endcode - * - Initialize the structure to logical zero values, for example: - * \code - * psa_hash_operation_t operation = {0}; - * \endcode - * - Initialize the structure to the initializer #PSA_HASH_OPERATION_INIT, - * for example: - * \code - * psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; - * \endcode - * - Assign the result of the function psa_hash_operation_init() - * to the structure, for example: - * \code - * psa_hash_operation_t operation; - * operation = psa_hash_operation_init(); - * \endcode - * - * This is an implementation-defined \c struct. Applications should not - * make any assumptions about the content of this structure except - * as directed by the documentation of a specific implementation. */ -typedef struct psa_hash_operation_s psa_hash_operation_t; - -/** \def PSA_HASH_OPERATION_INIT - * - * This macro returns a suitable initializer for a hash operation object - * of type #psa_hash_operation_t. - */ -#ifdef __DOXYGEN_ONLY__ -/* This is an example definition for documentation purposes. - * Implementations should define a suitable value in `crypto_struct.h`. - */ -#define PSA_HASH_OPERATION_INIT {0} -#endif - -/** Return an initial value for a hash operation object. - */ -static psa_hash_operation_t psa_hash_operation_init(void); - -/** Set up a multipart hash operation. - * - * The sequence of operations to calculate a hash (message digest) - * is as follows: - * -# Allocate an operation object which will be passed to all the functions - * listed here. - * -# Initialize the operation object with one of the methods described in the - * documentation for #psa_hash_operation_t, e.g. #PSA_HASH_OPERATION_INIT. - * -# Call psa_hash_setup() to specify the algorithm. - * -# Call psa_hash_update() zero, one or more times, passing a fragment - * of the message each time. The hash that is calculated is the hash - * of the concatenation of these messages in order. - * -# To calculate the hash, call psa_hash_finish(). - * To compare the hash with an expected value, call psa_hash_verify(). - * - * If an error occurs at any step after a call to psa_hash_setup(), the - * operation will need to be reset by a call to psa_hash_abort(). The - * application may call psa_hash_abort() at any time after the operation - * has been initialized. - * - * After a successful call to psa_hash_setup(), the application must - * eventually terminate the operation. The following events terminate an - * operation: - * - A successful call to psa_hash_finish() or psa_hash_verify(). - * - A call to psa_hash_abort(). - * - * \param[in,out] operation The operation object to set up. It must have - * been initialized as per the documentation for - * #psa_hash_operation_t and not yet in use. - * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value - * such that #PSA_ALG_IS_HASH(\p alg) is true). - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not a supported hash algorithm. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p alg is not a hash algorithm. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be inactive). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_hash_setup(psa_hash_operation_t *operation, - psa_algorithm_t alg); - -/** Add a message fragment to a multipart hash operation. - * - * The application must call psa_hash_setup() before calling this function. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_hash_abort(). - * - * \param[in,out] operation Active hash operation. - * \param[in] input Buffer containing the message fragment to hash. - * \param input_length Size of the \p input buffer in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it muct be active). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_hash_update(psa_hash_operation_t *operation, - const uint8_t *input, - size_t input_length); - -/** Finish the calculation of the hash of a message. - * - * The application must call psa_hash_setup() before calling this function. - * This function calculates the hash of the message formed by concatenating - * the inputs passed to preceding calls to psa_hash_update(). - * - * When this function returns successfuly, the operation becomes inactive. - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_hash_abort(). - * - * \warning Applications should not call this function if they expect - * a specific value for the hash. Call psa_hash_verify() instead. - * Beware that comparing integrity or authenticity data such as - * hash values with a function such as \c memcmp is risky - * because the time taken by the comparison may leak information - * about the hashed data which could allow an attacker to guess - * a valid hash and thereby bypass security controls. - * - * \param[in,out] operation Active hash operation. - * \param[out] hash Buffer where the hash is to be written. - * \param hash_size Size of the \p hash buffer in bytes. - * \param[out] hash_length On success, the number of bytes - * that make up the hash value. This is always - * #PSA_HASH_SIZE(\c alg) where \c alg is the - * hash algorithm that is calculated. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active). - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p hash buffer is too small. You can determine a - * sufficient buffer size by calling #PSA_HASH_SIZE(\c alg) - * where \c alg is the hash algorithm that is calculated. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_hash_finish(psa_hash_operation_t *operation, - uint8_t *hash, - size_t hash_size, - size_t *hash_length); - -/** Finish the calculation of the hash of a message and compare it with - * an expected value. - * - * The application must call psa_hash_setup() before calling this function. - * This function calculates the hash of the message formed by concatenating - * the inputs passed to preceding calls to psa_hash_update(). It then - * compares the calculated hash with the expected hash passed as a - * parameter to this function. - * - * When this function returns successfuly, the operation becomes inactive. - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_hash_abort(). - * - * \note Implementations shall make the best effort to ensure that the - * comparison between the actual hash and the expected hash is performed - * in constant time. - * - * \param[in,out] operation Active hash operation. - * \param[in] hash Buffer containing the expected hash value. - * \param hash_length Size of the \p hash buffer in bytes. - * - * \retval #PSA_SUCCESS - * The expected hash is identical to the actual hash of the message. - * \retval #PSA_ERROR_INVALID_SIGNATURE - * The hash of the message was calculated successfully, but it - * differs from the expected hash. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_hash_verify(psa_hash_operation_t *operation, - const uint8_t *hash, - size_t hash_length); - -/** Abort a hash operation. - * - * Aborting an operation frees all associated resources except for the - * \p operation structure itself. Once aborted, the operation object - * can be reused for another operation by calling - * psa_hash_setup() again. - * - * You may call this function any time after the operation object has - * been initialized by one of the methods described in #psa_hash_operation_t. - * - * In particular, calling psa_hash_abort() after the operation has been - * terminated by a call to psa_hash_abort(), psa_hash_finish() or - * psa_hash_verify() is safe and has no effect. - * - * \param[in,out] operation Initialized hash operation. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_hash_abort(psa_hash_operation_t *operation); - -/** Clone a hash operation. - * - * This function copies the state of an ongoing hash operation to - * a new operation object. In other words, this function is equivalent - * to calling psa_hash_setup() on \p target_operation with the same - * algorithm that \p source_operation was set up for, then - * psa_hash_update() on \p target_operation with the same input that - * that was passed to \p source_operation. After this function returns, the - * two objects are independent, i.e. subsequent calls involving one of - * the objects do not affect the other object. - * - * \param[in] source_operation The active hash operation to clone. - * \param[in,out] target_operation The operation object to set up. - * It must be initialized but not active. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_BAD_STATE - * The \p source_operation state is not valid (it must be active). - * \retval #PSA_ERROR_BAD_STATE - * The \p target_operation state is not valid (it must be inactive). - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation, - psa_hash_operation_t *target_operation); - -/**@}*/ - -/** \defgroup MAC Message authentication codes - * @{ - */ - -/** Calculate the MAC (message authentication code) of a message. - * - * \note To verify the MAC of a message against an - * expected value, use psa_mac_verify() instead. - * Beware that comparing integrity or authenticity data such as - * MAC values with a function such as \c memcmp is risky - * because the time taken by the comparison may leak information - * about the MAC value which could allow an attacker to guess - * a valid MAC and thereby bypass security controls. - * - * \param handle Handle to the key to use for the operation. - * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value - * such that #PSA_ALG_IS_MAC(\p alg) is true). - * \param[in] input Buffer containing the input message. - * \param input_length Size of the \p input buffer in bytes. - * \param[out] mac Buffer where the MAC value is to be written. - * \param mac_size Size of the \p mac buffer in bytes. - * \param[out] mac_length On success, the number of bytes - * that make up the MAC value. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not a MAC algorithm. - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * \p mac_size is too small - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * The key could not be retrieved from storage. - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_mac_compute(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - uint8_t *mac, - size_t mac_size, - size_t *mac_length); - -/** Calculate the MAC of a message and compare it with a reference value. - * - * \param handle Handle to the key to use for the operation. - * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value - * such that #PSA_ALG_IS_MAC(\p alg) is true). - * \param[in] input Buffer containing the input message. - * \param input_length Size of the \p input buffer in bytes. - * \param[out] mac Buffer containing the expected MAC value. - * \param mac_length Size of the \p mac buffer in bytes. - * - * \retval #PSA_SUCCESS - * The expected MAC is identical to the actual MAC of the input. - * \retval #PSA_ERROR_INVALID_SIGNATURE - * The MAC of the message was calculated successfully, but it - * differs from the expected value. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not a MAC algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * The key could not be retrieved from storage. - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_mac_verify(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - const uint8_t *mac, - size_t mac_length); - -/** The type of the state data structure for multipart MAC operations. - * - * Before calling any function on a MAC operation object, the application must - * initialize it by any of the following means: - * - Set the structure to all-bits-zero, for example: - * \code - * psa_mac_operation_t operation; - * memset(&operation, 0, sizeof(operation)); - * \endcode - * - Initialize the structure to logical zero values, for example: - * \code - * psa_mac_operation_t operation = {0}; - * \endcode - * - Initialize the structure to the initializer #PSA_MAC_OPERATION_INIT, - * for example: - * \code - * psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; - * \endcode - * - Assign the result of the function psa_mac_operation_init() - * to the structure, for example: - * \code - * psa_mac_operation_t operation; - * operation = psa_mac_operation_init(); - * \endcode - * - * This is an implementation-defined \c struct. Applications should not - * make any assumptions about the content of this structure except - * as directed by the documentation of a specific implementation. */ -typedef struct psa_mac_operation_s psa_mac_operation_t; - -/** \def PSA_MAC_OPERATION_INIT - * - * This macro returns a suitable initializer for a MAC operation object of type - * #psa_mac_operation_t. - */ -#ifdef __DOXYGEN_ONLY__ -/* This is an example definition for documentation purposes. - * Implementations should define a suitable value in `crypto_struct.h`. - */ -#define PSA_MAC_OPERATION_INIT {0} -#endif - -/** Return an initial value for a MAC operation object. - */ -static psa_mac_operation_t psa_mac_operation_init(void); - -/** Set up a multipart MAC calculation operation. - * - * This function sets up the calculation of the MAC - * (message authentication code) of a byte string. - * To verify the MAC of a message against an - * expected value, use psa_mac_verify_setup() instead. - * - * The sequence of operations to calculate a MAC is as follows: - * -# Allocate an operation object which will be passed to all the functions - * listed here. - * -# Initialize the operation object with one of the methods described in the - * documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT. - * -# Call psa_mac_sign_setup() to specify the algorithm and key. - * -# Call psa_mac_update() zero, one or more times, passing a fragment - * of the message each time. The MAC that is calculated is the MAC - * of the concatenation of these messages in order. - * -# At the end of the message, call psa_mac_sign_finish() to finish - * calculating the MAC value and retrieve it. - * - * If an error occurs at any step after a call to psa_mac_sign_setup(), the - * operation will need to be reset by a call to psa_mac_abort(). The - * application may call psa_mac_abort() at any time after the operation - * has been initialized. - * - * After a successful call to psa_mac_sign_setup(), the application must - * eventually terminate the operation through one of the following methods: - * - A successful call to psa_mac_sign_finish(). - * - A call to psa_mac_abort(). - * - * \param[in,out] operation The operation object to set up. It must have - * been initialized as per the documentation for - * #psa_mac_operation_t and not yet in use. - * \param handle Handle to the key to use for the operation. - * It must remain valid until the operation - * terminates. - * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value - * such that #PSA_ALG_IS_MAC(\p alg) is true). - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not a MAC algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * The key could not be retrieved from storage. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be inactive). - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg); - -/** Set up a multipart MAC verification operation. - * - * This function sets up the verification of the MAC - * (message authentication code) of a byte string against an expected value. - * - * The sequence of operations to verify a MAC is as follows: - * -# Allocate an operation object which will be passed to all the functions - * listed here. - * -# Initialize the operation object with one of the methods described in the - * documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT. - * -# Call psa_mac_verify_setup() to specify the algorithm and key. - * -# Call psa_mac_update() zero, one or more times, passing a fragment - * of the message each time. The MAC that is calculated is the MAC - * of the concatenation of these messages in order. - * -# At the end of the message, call psa_mac_verify_finish() to finish - * calculating the actual MAC of the message and verify it against - * the expected value. - * - * If an error occurs at any step after a call to psa_mac_verify_setup(), the - * operation will need to be reset by a call to psa_mac_abort(). The - * application may call psa_mac_abort() at any time after the operation - * has been initialized. - * - * After a successful call to psa_mac_verify_setup(), the application must - * eventually terminate the operation through one of the following methods: - * - A successful call to psa_mac_verify_finish(). - * - A call to psa_mac_abort(). - * - * \param[in,out] operation The operation object to set up. It must have - * been initialized as per the documentation for - * #psa_mac_operation_t and not yet in use. - * \param handle Handle to the key to use for the operation. - * It must remain valid until the operation - * terminates. - * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value - * such that #PSA_ALG_IS_MAC(\p alg) is true). - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \c key is not compatible with \c alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \c alg is not supported or is not a MAC algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * The key could not be retrieved from storage - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be inactive). - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg); - -/** Add a message fragment to a multipart MAC operation. - * - * The application must call psa_mac_sign_setup() or psa_mac_verify_setup() - * before calling this function. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_mac_abort(). - * - * \param[in,out] operation Active MAC operation. - * \param[in] input Buffer containing the message fragment to add to - * the MAC calculation. - * \param input_length Size of the \p input buffer in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_mac_update(psa_mac_operation_t *operation, - const uint8_t *input, - size_t input_length); - -/** Finish the calculation of the MAC of a message. - * - * The application must call psa_mac_sign_setup() before calling this function. - * This function calculates the MAC of the message formed by concatenating - * the inputs passed to preceding calls to psa_mac_update(). - * - * When this function returns successfuly, the operation becomes inactive. - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_mac_abort(). - * - * \warning Applications should not call this function if they expect - * a specific value for the MAC. Call psa_mac_verify_finish() instead. - * Beware that comparing integrity or authenticity data such as - * MAC values with a function such as \c memcmp is risky - * because the time taken by the comparison may leak information - * about the MAC value which could allow an attacker to guess - * a valid MAC and thereby bypass security controls. - * - * \param[in,out] operation Active MAC operation. - * \param[out] mac Buffer where the MAC value is to be written. - * \param mac_size Size of the \p mac buffer in bytes. - * \param[out] mac_length On success, the number of bytes - * that make up the MAC value. This is always - * #PSA_MAC_FINAL_SIZE(\c key_type, \c key_bits, \c alg) - * where \c key_type and \c key_bits are the type and - * bit-size respectively of the key and \c alg is the - * MAC algorithm that is calculated. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be an active mac sign - * operation). - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p mac buffer is too small. You can determine a - * sufficient buffer size by calling PSA_MAC_FINAL_SIZE(). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, - uint8_t *mac, - size_t mac_size, - size_t *mac_length); - -/** Finish the calculation of the MAC of a message and compare it with - * an expected value. - * - * The application must call psa_mac_verify_setup() before calling this function. - * This function calculates the MAC of the message formed by concatenating - * the inputs passed to preceding calls to psa_mac_update(). It then - * compares the calculated MAC with the expected MAC passed as a - * parameter to this function. - * - * When this function returns successfuly, the operation becomes inactive. - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_mac_abort(). - * - * \note Implementations shall make the best effort to ensure that the - * comparison between the actual MAC and the expected MAC is performed - * in constant time. - * - * \param[in,out] operation Active MAC operation. - * \param[in] mac Buffer containing the expected MAC value. - * \param mac_length Size of the \p mac buffer in bytes. - * - * \retval #PSA_SUCCESS - * The expected MAC is identical to the actual MAC of the message. - * \retval #PSA_ERROR_INVALID_SIGNATURE - * The MAC of the message was calculated successfully, but it - * differs from the expected MAC. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be an active mac verify - * operation). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation, - const uint8_t *mac, - size_t mac_length); - -/** Abort a MAC operation. - * - * Aborting an operation frees all associated resources except for the - * \p operation structure itself. Once aborted, the operation object - * can be reused for another operation by calling - * psa_mac_sign_setup() or psa_mac_verify_setup() again. - * - * You may call this function any time after the operation object has - * been initialized by one of the methods described in #psa_mac_operation_t. - * - * In particular, calling psa_mac_abort() after the operation has been - * terminated by a call to psa_mac_abort(), psa_mac_sign_finish() or - * psa_mac_verify_finish() is safe and has no effect. - * - * \param[in,out] operation Initialized MAC operation. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_mac_abort(psa_mac_operation_t *operation); - -/**@}*/ - -/** \defgroup cipher Symmetric ciphers - * @{ - */ - -/** Encrypt a message using a symmetric cipher. - * - * This function encrypts a message with a random IV (initialization - * vector). Use the multipart operation interface with a - * #psa_cipher_operation_t object to provide other forms of IV. - * - * \param handle Handle to the key to use for the operation. - * It must remain valid until the operation - * terminates. - * \param alg The cipher algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_CIPHER(\p alg) is true). - * \param[in] input Buffer containing the message to encrypt. - * \param input_length Size of the \p input buffer in bytes. - * \param[out] output Buffer where the output is to be written. - * The output contains the IV followed by - * the ciphertext proper. - * \param output_size Size of the \p output buffer in bytes. - * \param[out] output_length On success, the number of bytes - * that make up the output. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not a cipher algorithm. - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_cipher_encrypt(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - uint8_t *output, - size_t output_size, - size_t *output_length); - -/** Decrypt a message using a symmetric cipher. - * - * This function decrypts a message encrypted with a symmetric cipher. - * - * \param handle Handle to the key to use for the operation. - * It must remain valid until the operation - * terminates. - * \param alg The cipher algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_CIPHER(\p alg) is true). - * \param[in] input Buffer containing the message to decrypt. - * This consists of the IV followed by the - * ciphertext proper. - * \param input_length Size of the \p input buffer in bytes. - * \param[out] output Buffer where the plaintext is to be written. - * \param output_size Size of the \p output buffer in bytes. - * \param[out] output_length On success, the number of bytes - * that make up the output. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not a cipher algorithm. - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_cipher_decrypt(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - uint8_t *output, - size_t output_size, - size_t *output_length); - -/** The type of the state data structure for multipart cipher operations. - * - * Before calling any function on a cipher operation object, the application - * must initialize it by any of the following means: - * - Set the structure to all-bits-zero, for example: - * \code - * psa_cipher_operation_t operation; - * memset(&operation, 0, sizeof(operation)); - * \endcode - * - Initialize the structure to logical zero values, for example: - * \code - * psa_cipher_operation_t operation = {0}; - * \endcode - * - Initialize the structure to the initializer #PSA_CIPHER_OPERATION_INIT, - * for example: - * \code - * psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; - * \endcode - * - Assign the result of the function psa_cipher_operation_init() - * to the structure, for example: - * \code - * psa_cipher_operation_t operation; - * operation = psa_cipher_operation_init(); - * \endcode - * - * This is an implementation-defined \c struct. Applications should not - * make any assumptions about the content of this structure except - * as directed by the documentation of a specific implementation. */ -typedef struct psa_cipher_operation_s psa_cipher_operation_t; - -/** \def PSA_CIPHER_OPERATION_INIT - * - * This macro returns a suitable initializer for a cipher operation object of - * type #psa_cipher_operation_t. - */ -#ifdef __DOXYGEN_ONLY__ -/* This is an example definition for documentation purposes. - * Implementations should define a suitable value in `crypto_struct.h`. - */ -#define PSA_CIPHER_OPERATION_INIT {0} -#endif - -/** Return an initial value for a cipher operation object. - */ -static psa_cipher_operation_t psa_cipher_operation_init(void); - -/** Set the key for a multipart symmetric encryption operation. - * - * The sequence of operations to encrypt a message with a symmetric cipher - * is as follows: - * -# Allocate an operation object which will be passed to all the functions - * listed here. - * -# Initialize the operation object with one of the methods described in the - * documentation for #psa_cipher_operation_t, e.g. - * #PSA_CIPHER_OPERATION_INIT. - * -# Call psa_cipher_encrypt_setup() to specify the algorithm and key. - * -# Call either psa_cipher_generate_iv() or psa_cipher_set_iv() to - * generate or set the IV (initialization vector). You should use - * psa_cipher_generate_iv() unless the protocol you are implementing - * requires a specific IV value. - * -# Call psa_cipher_update() zero, one or more times, passing a fragment - * of the message each time. - * -# Call psa_cipher_finish(). - * - * If an error occurs at any step after a call to psa_cipher_encrypt_setup(), - * the operation will need to be reset by a call to psa_cipher_abort(). The - * application may call psa_cipher_abort() at any time after the operation - * has been initialized. - * - * After a successful call to psa_cipher_encrypt_setup(), the application must - * eventually terminate the operation. The following events terminate an - * operation: - * - A successful call to psa_cipher_finish(). - * - A call to psa_cipher_abort(). - * - * \param[in,out] operation The operation object to set up. It must have - * been initialized as per the documentation for - * #psa_cipher_operation_t and not yet in use. - * \param handle Handle to the key to use for the operation. - * It must remain valid until the operation - * terminates. - * \param alg The cipher algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_CIPHER(\p alg) is true). - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not a cipher algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be inactive). - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg); - -/** Set the key for a multipart symmetric decryption operation. - * - * The sequence of operations to decrypt a message with a symmetric cipher - * is as follows: - * -# Allocate an operation object which will be passed to all the functions - * listed here. - * -# Initialize the operation object with one of the methods described in the - * documentation for #psa_cipher_operation_t, e.g. - * #PSA_CIPHER_OPERATION_INIT. - * -# Call psa_cipher_decrypt_setup() to specify the algorithm and key. - * -# Call psa_cipher_set_iv() with the IV (initialization vector) for the - * decryption. If the IV is prepended to the ciphertext, you can call - * psa_cipher_update() on a buffer containing the IV followed by the - * beginning of the message. - * -# Call psa_cipher_update() zero, one or more times, passing a fragment - * of the message each time. - * -# Call psa_cipher_finish(). - * - * If an error occurs at any step after a call to psa_cipher_decrypt_setup(), - * the operation will need to be reset by a call to psa_cipher_abort(). The - * application may call psa_cipher_abort() at any time after the operation - * has been initialized. - * - * After a successful call to psa_cipher_decrypt_setup(), the application must - * eventually terminate the operation. The following events terminate an - * operation: - * - A successful call to psa_cipher_finish(). - * - A call to psa_cipher_abort(). - * - * \param[in,out] operation The operation object to set up. It must have - * been initialized as per the documentation for - * #psa_cipher_operation_t and not yet in use. - * \param handle Handle to the key to use for the operation. - * It must remain valid until the operation - * terminates. - * \param alg The cipher algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_CIPHER(\p alg) is true). - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not a cipher algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be inactive). - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg); - -/** Generate an IV for a symmetric encryption operation. - * - * This function generates a random IV (initialization vector), nonce - * or initial counter value for the encryption operation as appropriate - * for the chosen algorithm, key type and key size. - * - * The application must call psa_cipher_encrypt_setup() before - * calling this function. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_cipher_abort(). - * - * \param[in,out] operation Active cipher operation. - * \param[out] iv Buffer where the generated IV is to be written. - * \param iv_size Size of the \p iv buffer in bytes. - * \param[out] iv_length On success, the number of bytes of the - * generated IV. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active, with no IV set). - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p iv buffer is too small. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation, - uint8_t *iv, - size_t iv_size, - size_t *iv_length); - -/** Set the IV for a symmetric encryption or decryption operation. - * - * This function sets the IV (initialization vector), nonce - * or initial counter value for the encryption or decryption operation. - * - * The application must call psa_cipher_encrypt_setup() before - * calling this function. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_cipher_abort(). - * - * \note When encrypting, applications should use psa_cipher_generate_iv() - * instead of this function, unless implementing a protocol that requires - * a non-random IV. - * - * \param[in,out] operation Active cipher operation. - * \param[in] iv Buffer containing the IV to use. - * \param iv_length Size of the IV in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be an active cipher - * encrypt operation, with no IV set). - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The size of \p iv is not acceptable for the chosen algorithm, - * or the chosen algorithm does not use an IV. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, - const uint8_t *iv, - size_t iv_length); - -/** Encrypt or decrypt a message fragment in an active cipher operation. - * - * Before calling this function, you must: - * 1. Call either psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup(). - * The choice of setup function determines whether this function - * encrypts or decrypts its input. - * 2. If the algorithm requires an IV, call psa_cipher_generate_iv() - * (recommended when encrypting) or psa_cipher_set_iv(). - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_cipher_abort(). - * - * \param[in,out] operation Active cipher operation. - * \param[in] input Buffer containing the message fragment to - * encrypt or decrypt. - * \param input_length Size of the \p input buffer in bytes. - * \param[out] output Buffer where the output is to be written. - * \param output_size Size of the \p output buffer in bytes. - * \param[out] output_length On success, the number of bytes - * that make up the returned output. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active, with an IV set - * if required for the algorithm). - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p output buffer is too small. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, - const uint8_t *input, - size_t input_length, - uint8_t *output, - size_t output_size, - size_t *output_length); - -/** Finish encrypting or decrypting a message in a cipher operation. - * - * The application must call psa_cipher_encrypt_setup() or - * psa_cipher_decrypt_setup() before calling this function. The choice - * of setup function determines whether this function encrypts or - * decrypts its input. - * - * This function finishes the encryption or decryption of the message - * formed by concatenating the inputs passed to preceding calls to - * psa_cipher_update(). - * - * When this function returns successfuly, the operation becomes inactive. - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_cipher_abort(). - * - * \param[in,out] operation Active cipher operation. - * \param[out] output Buffer where the output is to be written. - * \param output_size Size of the \p output buffer in bytes. - * \param[out] output_length On success, the number of bytes - * that make up the returned output. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The total input size passed to this operation is not valid for - * this particular algorithm. For example, the algorithm is a based - * on block cipher and requires a whole number of blocks, but the - * total input size is not a multiple of the block size. - * \retval #PSA_ERROR_INVALID_PADDING - * This is a decryption operation for an algorithm that includes - * padding, and the ciphertext does not contain valid padding. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active, with an IV set - * if required for the algorithm). - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p output buffer is too small. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, - uint8_t *output, - size_t output_size, - size_t *output_length); - -/** Abort a cipher operation. - * - * Aborting an operation frees all associated resources except for the - * \p operation structure itself. Once aborted, the operation object - * can be reused for another operation by calling - * psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup() again. - * - * You may call this function any time after the operation object has - * been initialized as described in #psa_cipher_operation_t. - * - * In particular, calling psa_cipher_abort() after the operation has been - * terminated by a call to psa_cipher_abort() or psa_cipher_finish() - * is safe and has no effect. - * - * \param[in,out] operation Initialized cipher operation. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation); - -/**@}*/ - -/** \defgroup aead Authenticated encryption with associated data (AEAD) - * @{ - */ - -/** Process an authenticated encryption operation. - * - * \param handle Handle to the key to use for the operation. - * \param alg The AEAD algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * \param[in] nonce Nonce or IV to use. - * \param nonce_length Size of the \p nonce buffer in bytes. - * \param[in] additional_data Additional data that will be authenticated - * but not encrypted. - * \param additional_data_length Size of \p additional_data in bytes. - * \param[in] plaintext Data that will be authenticated and - * encrypted. - * \param plaintext_length Size of \p plaintext in bytes. - * \param[out] ciphertext Output buffer for the authenticated and - * encrypted data. The additional data is not - * part of this output. For algorithms where the - * encrypted data and the authentication tag - * are defined as separate outputs, the - * authentication tag is appended to the - * encrypted data. - * \param ciphertext_size Size of the \p ciphertext buffer in bytes. - * This must be at least - * #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\p alg, - * \p plaintext_length). - * \param[out] ciphertext_length On success, the size of the output - * in the \p ciphertext buffer. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not an AEAD algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * \p ciphertext_size is too small - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_encrypt(psa_key_handle_t handle, - 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 *ciphertext, - size_t ciphertext_size, - size_t *ciphertext_length); - -/** Process an authenticated decryption operation. - * - * \param handle Handle to the key to use for the operation. - * \param alg The AEAD algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * \param[in] nonce Nonce or IV to use. - * \param nonce_length Size of the \p nonce buffer in bytes. - * \param[in] additional_data Additional data that has been authenticated - * but not encrypted. - * \param additional_data_length Size of \p additional_data in bytes. - * \param[in] ciphertext Data that has been authenticated and - * encrypted. For algorithms where the - * encrypted data and the authentication tag - * are defined as separate inputs, the buffer - * must contain the encrypted data followed - * by the authentication tag. - * \param ciphertext_length Size of \p ciphertext in bytes. - * \param[out] plaintext Output buffer for the decrypted data. - * \param plaintext_size Size of the \p plaintext buffer in bytes. - * This must be at least - * #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\p alg, - * \p ciphertext_length). - * \param[out] plaintext_length On success, the size of the output - * in the \p plaintext buffer. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_INVALID_SIGNATURE - * The ciphertext is not authentic. - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not an AEAD algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * \p plaintext_size or \p nonce_length is too small - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_decrypt(psa_key_handle_t handle, - 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 *ciphertext, - size_t ciphertext_length, - uint8_t *plaintext, - size_t plaintext_size, - size_t *plaintext_length); - -/** The type of the state data structure for multipart AEAD operations. - * - * Before calling any function on an AEAD operation object, the application - * must initialize it by any of the following means: - * - Set the structure to all-bits-zero, for example: - * \code - * psa_aead_operation_t operation; - * memset(&operation, 0, sizeof(operation)); - * \endcode - * - Initialize the structure to logical zero values, for example: - * \code - * psa_aead_operation_t operation = {0}; - * \endcode - * - Initialize the structure to the initializer #PSA_AEAD_OPERATION_INIT, - * for example: - * \code - * psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT; - * \endcode - * - Assign the result of the function psa_aead_operation_init() - * to the structure, for example: - * \code - * psa_aead_operation_t operation; - * operation = psa_aead_operation_init(); - * \endcode - * - * This is an implementation-defined \c struct. Applications should not - * make any assumptions about the content of this structure except - * as directed by the documentation of a specific implementation. */ -typedef struct psa_aead_operation_s psa_aead_operation_t; - -/** \def PSA_AEAD_OPERATION_INIT - * - * This macro returns a suitable initializer for an AEAD operation object of - * type #psa_aead_operation_t. - */ -#ifdef __DOXYGEN_ONLY__ -/* This is an example definition for documentation purposes. - * Implementations should define a suitable value in `crypto_struct.h`. - */ -#define PSA_AEAD_OPERATION_INIT {0} -#endif - -/** Return an initial value for an AEAD operation object. - */ -static psa_aead_operation_t psa_aead_operation_init(void); - -/** Set the key for a multipart authenticated encryption operation. - * - * The sequence of operations to encrypt a message with authentication - * is as follows: - * -# Allocate an operation object which will be passed to all the functions - * listed here. - * -# Initialize the operation object with one of the methods described in the - * documentation for #psa_aead_operation_t, e.g. - * #PSA_AEAD_OPERATION_INIT. - * -# Call psa_aead_encrypt_setup() to specify the algorithm and key. - * -# If needed, call psa_aead_set_lengths() to specify the length of the - * inputs to the subsequent calls to psa_aead_update_ad() and - * psa_aead_update(). See the documentation of psa_aead_set_lengths() - * for details. - * -# Call either psa_aead_generate_nonce() or psa_aead_set_nonce() to - * generate or set the nonce. You should use - * psa_aead_generate_nonce() unless the protocol you are implementing - * requires a specific nonce value. - * -# Call psa_aead_update_ad() zero, one or more times, passing a fragment - * of the non-encrypted additional authenticated data each time. - * -# Call psa_aead_update() zero, one or more times, passing a fragment - * of the message to encrypt each time. - * -# Call psa_aead_finish(). - * - * If an error occurs at any step after a call to psa_aead_encrypt_setup(), - * the operation will need to be reset by a call to psa_aead_abort(). The - * application may call psa_aead_abort() at any time after the operation - * has been initialized. - * - * After a successful call to psa_aead_encrypt_setup(), the application must - * eventually terminate the operation. The following events terminate an - * operation: - * - A successful call to psa_aead_finish(). - * - A call to psa_aead_abort(). - * - * \param[in,out] operation The operation object to set up. It must have - * been initialized as per the documentation for - * #psa_aead_operation_t and not yet in use. - * \param handle Handle to the key to use for the operation. - * It must remain valid until the operation - * terminates. - * \param alg The AEAD algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be inactive). - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not an AEAD algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg); - -/** Set the key for a multipart authenticated decryption operation. - * - * The sequence of operations to decrypt a message with authentication - * is as follows: - * -# Allocate an operation object which will be passed to all the functions - * listed here. - * -# Initialize the operation object with one of the methods described in the - * documentation for #psa_aead_operation_t, e.g. - * #PSA_AEAD_OPERATION_INIT. - * -# Call psa_aead_decrypt_setup() to specify the algorithm and key. - * -# If needed, call psa_aead_set_lengths() to specify the length of the - * inputs to the subsequent calls to psa_aead_update_ad() and - * psa_aead_update(). See the documentation of psa_aead_set_lengths() - * for details. - * -# Call psa_aead_set_nonce() with the nonce for the decryption. - * -# Call psa_aead_update_ad() zero, one or more times, passing a fragment - * of the non-encrypted additional authenticated data each time. - * -# Call psa_aead_update() zero, one or more times, passing a fragment - * of the ciphertext to decrypt each time. - * -# Call psa_aead_verify(). - * - * If an error occurs at any step after a call to psa_aead_decrypt_setup(), - * the operation will need to be reset by a call to psa_aead_abort(). The - * application may call psa_aead_abort() at any time after the operation - * has been initialized. - * - * After a successful call to psa_aead_decrypt_setup(), the application must - * eventually terminate the operation. The following events terminate an - * operation: - * - A successful call to psa_aead_verify(). - * - A call to psa_aead_abort(). - * - * \param[in,out] operation The operation object to set up. It must have - * been initialized as per the documentation for - * #psa_aead_operation_t and not yet in use. - * \param handle Handle to the key to use for the operation. - * It must remain valid until the operation - * terminates. - * \param alg The AEAD algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be inactive). - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not an AEAD algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg); - -/** Generate a random nonce for an authenticated encryption operation. - * - * This function generates a random nonce for the authenticated encryption - * operation with an appropriate size for the chosen algorithm, key type - * and key size. - * - * The application must call psa_aead_encrypt_setup() before - * calling this function. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_aead_abort(). - * - * \param[in,out] operation Active AEAD operation. - * \param[out] nonce Buffer where the generated nonce is to be - * written. - * \param nonce_size Size of the \p nonce buffer in bytes. - * \param[out] nonce_length On success, the number of bytes of the - * generated nonce. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be an active aead encrypt - operation, with no nonce set). - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p nonce buffer is too small. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation, - uint8_t *nonce, - size_t nonce_size, - size_t *nonce_length); - -/** Set the nonce for an authenticated encryption or decryption operation. - * - * This function sets the nonce for the authenticated - * encryption or decryption operation. - * - * The application must call psa_aead_encrypt_setup() or - * psa_aead_decrypt_setup() before calling this function. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_aead_abort(). - * - * \note When encrypting, applications should use psa_aead_generate_nonce() - * instead of this function, unless implementing a protocol that requires - * a non-random IV. - * - * \param[in,out] operation Active AEAD operation. - * \param[in] nonce Buffer containing the nonce to use. - * \param nonce_length Size of the nonce in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active, with no nonce - * set). - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The size of \p nonce is not acceptable for the chosen algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation, - const uint8_t *nonce, - size_t nonce_length); - -/** Declare the lengths of the message and additional data for AEAD. - * - * The application must call this function before calling - * psa_aead_update_ad() or psa_aead_update() if the algorithm for - * the operation requires it. If the algorithm does not require it, - * calling this function is optional, but if this function is called - * then the implementation must enforce the lengths. - * - * You may call this function before or after setting the nonce with - * psa_aead_set_nonce() or psa_aead_generate_nonce(). - * - * - For #PSA_ALG_CCM, calling this function is required. - * - For the other AEAD algorithms defined in this specification, calling - * this function is not required. - * - For vendor-defined algorithm, refer to the vendor documentation. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_aead_abort(). - * - * \param[in,out] operation Active AEAD operation. - * \param ad_length Size of the non-encrypted additional - * authenticated data in bytes. - * \param plaintext_length Size of the plaintext to encrypt in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active, and - * psa_aead_update_ad() and psa_aead_update() must not have been - * called yet). - * \retval #PSA_ERROR_INVALID_ARGUMENT - * At least one of the lengths is not acceptable for the chosen - * algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation, - size_t ad_length, - size_t plaintext_length); - -/** Pass additional data to an active AEAD operation. - * - * Additional data is authenticated, but not encrypted. - * - * You may call this function multiple times to pass successive fragments - * of the additional data. You may not call this function after passing - * data to encrypt or decrypt with psa_aead_update(). - * - * Before calling this function, you must: - * 1. Call either psa_aead_encrypt_setup() or psa_aead_decrypt_setup(). - * 2. Set the nonce with psa_aead_generate_nonce() or psa_aead_set_nonce(). - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_aead_abort(). - * - * \warning When decrypting, until psa_aead_verify() has returned #PSA_SUCCESS, - * there is no guarantee that the input is valid. Therefore, until - * you have called psa_aead_verify() and it has returned #PSA_SUCCESS, - * treat the input as untrusted and prepare to undo any action that - * depends on the input if psa_aead_verify() returns an error status. - * - * \param[in,out] operation Active AEAD operation. - * \param[in] input Buffer containing the fragment of - * additional data. - * \param input_length Size of the \p input buffer in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active, have a nonce - * set, have lengths set if required by the algorithm, and - * psa_aead_update() must not have been called yet). - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The total input length overflows the additional data length that - * was previously specified with psa_aead_set_lengths(). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation, - const uint8_t *input, - size_t input_length); - -/** Encrypt or decrypt a message fragment in an active AEAD operation. - * - * Before calling this function, you must: - * 1. Call either psa_aead_encrypt_setup() or psa_aead_decrypt_setup(). - * The choice of setup function determines whether this function - * encrypts or decrypts its input. - * 2. Set the nonce with psa_aead_generate_nonce() or psa_aead_set_nonce(). - * 3. Call psa_aead_update_ad() to pass all the additional data. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_aead_abort(). - * - * \warning When decrypting, until psa_aead_verify() has returned #PSA_SUCCESS, - * there is no guarantee that the input is valid. Therefore, until - * you have called psa_aead_verify() and it has returned #PSA_SUCCESS: - * - Do not use the output in any way other than storing it in a - * confidential location. If you take any action that depends - * on the tentative decrypted data, this action will need to be - * undone if the input turns out not to be valid. Furthermore, - * if an adversary can observe that this action took place - * (for example through timing), they may be able to use this - * fact as an oracle to decrypt any message encrypted with the - * same key. - * - In particular, do not copy the output anywhere but to a - * memory or storage space that you have exclusive access to. - * - * This function does not require the input to be aligned to any - * particular block boundary. If the implementation can only process - * a whole block at a time, it must consume all the input provided, but - * it may delay the end of the corresponding output until a subsequent - * call to psa_aead_update(), psa_aead_finish() or psa_aead_verify() - * provides sufficient input. The amount of data that can be delayed - * in this way is bounded by #PSA_AEAD_UPDATE_OUTPUT_SIZE. - * - * \param[in,out] operation Active AEAD operation. - * \param[in] input Buffer containing the message fragment to - * encrypt or decrypt. - * \param input_length Size of the \p input buffer in bytes. - * \param[out] output Buffer where the output is to be written. - * \param output_size Size of the \p output buffer in bytes. - * This must be at least - * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c alg, - * \p input_length) where \c alg is the - * algorithm that is being calculated. - * \param[out] output_length On success, the number of bytes - * that make up the returned output. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active, have a nonce - * set, and have lengths set if required by the algorithm). - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p output buffer is too small. - * You can determine a sufficient buffer size by calling - * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c alg, \p input_length) - * where \c alg is the algorithm that is being calculated. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The total length of input to psa_aead_update_ad() so far is - * less than the additional data length that was previously - * specified with psa_aead_set_lengths(). - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The total input length overflows the plaintext length that - * was previously specified with psa_aead_set_lengths(). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_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); - -/** Finish encrypting a message in an AEAD operation. - * - * The operation must have been set up with psa_aead_encrypt_setup(). - * - * This function finishes the authentication of the additional data - * formed by concatenating the inputs passed to preceding calls to - * psa_aead_update_ad() with the plaintext formed by concatenating the - * inputs passed to preceding calls to psa_aead_update(). - * - * This function has two output buffers: - * - \p ciphertext contains trailing ciphertext that was buffered from - * preceding calls to psa_aead_update(). - * - \p tag contains the authentication tag. Its length is always - * #PSA_AEAD_TAG_LENGTH(\c alg) where \c alg is the AEAD algorithm - * that the operation performs. - * - * When this function returns successfuly, the operation becomes inactive. - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_aead_abort(). - * - * \param[in,out] operation Active AEAD operation. - * \param[out] ciphertext Buffer where the last part of the ciphertext - * is to be written. - * \param ciphertext_size Size of the \p ciphertext buffer in bytes. - * This must be at least - * #PSA_AEAD_FINISH_OUTPUT_SIZE(\c alg) where - * \c alg is the algorithm that is being - * calculated. - * \param[out] ciphertext_length On success, the number of bytes of - * returned ciphertext. - * \param[out] tag Buffer where the authentication tag is - * to be written. - * \param tag_size Size of the \p tag buffer in bytes. - * This must be at least - * #PSA_AEAD_TAG_LENGTH(\c alg) where \c alg is - * the algorithm that is being calculated. - * \param[out] tag_length On success, the number of bytes - * that make up the returned tag. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be an active encryption - * operation with a nonce set). - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p ciphertext or \p tag buffer is too small. - * You can determine a sufficient buffer size for \p ciphertext by - * calling #PSA_AEAD_FINISH_OUTPUT_SIZE(\c alg) - * where \c alg is the algorithm that is being calculated. - * You can determine a sufficient buffer size for \p tag by - * calling #PSA_AEAD_TAG_LENGTH(\c alg). - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The total length of input to psa_aead_update_ad() so far is - * less than the additional data length that was previously - * specified with psa_aead_set_lengths(). - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The total length of input to psa_aead_update() so far is - * less than the plaintext length that was previously - * specified with psa_aead_set_lengths(). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_finish(psa_aead_operation_t *operation, - uint8_t *ciphertext, - size_t ciphertext_size, - size_t *ciphertext_length, - uint8_t *tag, - size_t tag_size, - size_t *tag_length); - -/** Finish authenticating and decrypting a message in an AEAD operation. - * - * The operation must have been set up with psa_aead_decrypt_setup(). - * - * This function finishes the authenticated decryption of the message - * components: - * - * - The additional data consisting of the concatenation of the inputs - * passed to preceding calls to psa_aead_update_ad(). - * - The ciphertext consisting of the concatenation of the inputs passed to - * preceding calls to psa_aead_update(). - * - The tag passed to this function call. - * - * If the authentication tag is correct, this function outputs any remaining - * plaintext and reports success. If the authentication tag is not correct, - * this function returns #PSA_ERROR_INVALID_SIGNATURE. - * - * When this function returns successfuly, the operation becomes inactive. - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_aead_abort(). - * - * \note Implementations shall make the best effort to ensure that the - * comparison between the actual tag and the expected tag is performed - * in constant time. - * - * \param[in,out] operation Active AEAD operation. - * \param[out] plaintext Buffer where the last part of the plaintext - * is to be written. This is the remaining data - * from previous calls to psa_aead_update() - * that could not be processed until the end - * of the input. - * \param plaintext_size Size of the \p plaintext buffer in bytes. - * This must be at least - * #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c alg) where - * \c alg is the algorithm that is being - * calculated. - * \param[out] plaintext_length On success, the number of bytes of - * returned plaintext. - * \param[in] tag Buffer containing the authentication tag. - * \param tag_length Size of the \p tag buffer in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_SIGNATURE - * The calculations were successful, but the authentication tag is - * not correct. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be an active decryption - * operation with a nonce set). - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p plaintext buffer is too small. - * You can determine a sufficient buffer size for \p plaintext by - * calling #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c alg) - * where \c alg is the algorithm that is being calculated. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The total length of input to psa_aead_update_ad() so far is - * less than the additional data length that was previously - * specified with psa_aead_set_lengths(). - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The total length of input to psa_aead_update() so far is - * less than the plaintext length that was previously - * specified with psa_aead_set_lengths(). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_verify(psa_aead_operation_t *operation, - uint8_t *plaintext, - size_t plaintext_size, - size_t *plaintext_length, - const uint8_t *tag, - size_t tag_length); - -/** Abort an AEAD operation. - * - * Aborting an operation frees all associated resources except for the - * \p operation structure itself. Once aborted, the operation object - * can be reused for another operation by calling - * psa_aead_encrypt_setup() or psa_aead_decrypt_setup() again. - * - * You may call this function any time after the operation object has - * been initialized as described in #psa_aead_operation_t. - * - * In particular, calling psa_aead_abort() after the operation has been - * terminated by a call to psa_aead_abort(), psa_aead_finish() or - * psa_aead_verify() is safe and has no effect. - * - * \param[in,out] operation Initialized AEAD operation. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_abort(psa_aead_operation_t *operation); - -/**@}*/ - -/** \defgroup asymmetric Asymmetric cryptography - * @{ - */ - -/** - * \brief Sign a hash or short message with a private key. - * - * Note that to perform a hash-and-sign signature algorithm, you must - * first calculate the hash by calling psa_hash_setup(), psa_hash_update() - * and psa_hash_finish(). Then pass the resulting hash as the \p hash - * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) - * to determine the hash algorithm to use. - * - * \param handle Handle to the key to use for the operation. - * It must be an asymmetric key pair. - * \param alg A signature algorithm that is compatible with - * the type of \p handle. - * \param[in] hash The hash or message to sign. - * \param hash_length Size of the \p hash buffer in bytes. - * \param[out] signature Buffer where the signature is to be written. - * \param signature_size Size of the \p signature buffer in bytes. - * \param[out] signature_length On success, the number of bytes - * that make up the returned signature value. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p signature buffer is too small. You can - * determine a sufficient buffer size by calling - * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) - * where \c key_type and \c key_bits are the type and bit-size - * respectively of \p handle. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_sign_hash(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *hash, - size_t hash_length, - uint8_t *signature, - size_t signature_size, - size_t *signature_length); - -/** - * \brief Verify the signature a hash or short message using a public key. - * - * Note that to perform a hash-and-sign signature algorithm, you must - * first calculate the hash by calling psa_hash_setup(), psa_hash_update() - * and psa_hash_finish(). Then pass the resulting hash as the \p hash - * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) - * to determine the hash algorithm to use. - * - * \param handle Handle to the key to use for the operation. - * It must be a public key or an asymmetric key pair. - * \param alg A signature algorithm that is compatible with - * the type of \p handle. - * \param[in] hash The hash or message whose signature is to be - * verified. - * \param hash_length Size of the \p hash buffer in bytes. - * \param[in] signature Buffer containing the signature to verify. - * \param signature_length Size of the \p signature buffer in bytes. - * - * \retval #PSA_SUCCESS - * The signature is valid. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_SIGNATURE - * The calculation was perfomed successfully, but the passed - * signature is not a valid signature. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_verify_hash(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *hash, - size_t hash_length, - const uint8_t *signature, - size_t signature_length); - -/** - * \brief Encrypt a short message with a public key. - * - * \param handle Handle to the key to use for the operation. - * It must be a public key or an asymmetric - * key pair. - * \param alg An asymmetric encryption algorithm that is - * compatible with the type of \p handle. - * \param[in] input The message to encrypt. - * \param input_length Size of the \p input buffer in bytes. - * \param[in] salt A salt or label, if supported by the - * encryption algorithm. - * If the algorithm does not support a - * salt, pass \c NULL. - * If the algorithm supports an optional - * salt and you do not want to pass a salt, - * pass \c NULL. - * - * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is - * supported. - * \param salt_length Size of the \p salt buffer in bytes. - * If \p salt is \c NULL, pass 0. - * \param[out] output Buffer where the encrypted message is to - * be written. - * \param output_size Size of the \p output buffer in bytes. - * \param[out] output_length On success, the number of bytes - * that make up the returned output. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p output buffer is too small. You can - * determine a sufficient buffer size by calling - * #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) - * where \c key_type and \c key_bits are the type and bit-size - * respectively of \p handle. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_asymmetric_encrypt(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - const uint8_t *salt, - size_t salt_length, - uint8_t *output, - size_t output_size, - size_t *output_length); - -/** - * \brief Decrypt a short message with a private key. - * - * \param handle Handle to the key to use for the operation. - * It must be an asymmetric key pair. - * \param alg An asymmetric encryption algorithm that is - * compatible with the type of \p handle. - * \param[in] input The message to decrypt. - * \param input_length Size of the \p input buffer in bytes. - * \param[in] salt A salt or label, if supported by the - * encryption algorithm. - * If the algorithm does not support a - * salt, pass \c NULL. - * If the algorithm supports an optional - * salt and you do not want to pass a salt, - * pass \c NULL. - * - * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is - * supported. - * \param salt_length Size of the \p salt buffer in bytes. - * If \p salt is \c NULL, pass 0. - * \param[out] output Buffer where the decrypted message is to - * be written. - * \param output_size Size of the \c output buffer in bytes. - * \param[out] output_length On success, the number of bytes - * that make up the returned output. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p output buffer is too small. You can - * determine a sufficient buffer size by calling - * #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) - * where \c key_type and \c key_bits are the type and bit-size - * respectively of \p handle. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY - * \retval #PSA_ERROR_INVALID_PADDING - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_asymmetric_decrypt(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - const uint8_t *salt, - size_t salt_length, - uint8_t *output, - size_t output_size, - size_t *output_length); - -/**@}*/ - -/** \defgroup key_derivation Key derivation and pseudorandom generation - * @{ - */ - -/** The type of the state data structure for key derivation operations. - * - * Before calling any function on a key derivation operation object, the - * application must initialize it by any of the following means: - * - Set the structure to all-bits-zero, for example: - * \code - * psa_key_derivation_operation_t operation; - * memset(&operation, 0, sizeof(operation)); - * \endcode - * - Initialize the structure to logical zero values, for example: - * \code - * psa_key_derivation_operation_t operation = {0}; - * \endcode - * - Initialize the structure to the initializer #PSA_KEY_DERIVATION_OPERATION_INIT, - * for example: - * \code - * psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT; - * \endcode - * - Assign the result of the function psa_key_derivation_operation_init() - * to the structure, for example: - * \code - * psa_key_derivation_operation_t operation; - * operation = psa_key_derivation_operation_init(); - * \endcode - * - * This is an implementation-defined \c struct. Applications should not - * make any assumptions about the content of this structure except - * as directed by the documentation of a specific implementation. - */ -typedef struct psa_key_derivation_s psa_key_derivation_operation_t; - -/** \def PSA_KEY_DERIVATION_OPERATION_INIT - * - * This macro returns a suitable initializer for a key derivation operation - * object of type #psa_key_derivation_operation_t. - */ -#ifdef __DOXYGEN_ONLY__ -/* This is an example definition for documentation purposes. - * Implementations should define a suitable value in `crypto_struct.h`. - */ -#define PSA_KEY_DERIVATION_OPERATION_INIT {0} -#endif - -/** Return an initial value for a key derivation operation object. - */ -static psa_key_derivation_operation_t psa_key_derivation_operation_init(void); - -/** Set up a key derivation operation. - * - * A key derivation algorithm takes some inputs and uses them to generate - * a byte stream in a deterministic way. - * This byte stream can be used to produce keys and other - * cryptographic material. - * - * To derive a key: - * -# Start with an initialized object of type #psa_key_derivation_operation_t. - * -# Call psa_key_derivation_setup() to select the algorithm. - * -# Provide the inputs for the key derivation by calling - * psa_key_derivation_input_bytes() or psa_key_derivation_input_key() - * as appropriate. Which inputs are needed, in what order, and whether - * they may be keys and if so of what type depends on the algorithm. - * -# Optionally set the operation's maximum capacity with - * psa_key_derivation_set_capacity(). You may do this before, in the middle - * of or after providing inputs. For some algorithms, this step is mandatory - * because the output depends on the maximum capacity. - * -# To derive a key, call psa_key_derivation_output_key(). - * To derive a byte string for a different purpose, call - * psa_key_derivation_output_bytes(). - * Successive calls to these functions use successive output bytes - * calculated by the key derivation algorithm. - * -# Clean up the key derivation operation object with - * psa_key_derivation_abort(). - * - * If this function returns an error, the key derivation operation object is - * not changed. - * - * If an error occurs at any step after a call to psa_key_derivation_setup(), - * the operation will need to be reset by a call to psa_key_derivation_abort(). - * - * Implementations must reject an attempt to derive a key of size 0. - * - * \param[in,out] operation The key derivation operation object - * to set up. It must - * have been initialized but not set up yet. - * \param alg The key derivation algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_KEY_DERIVATION(\p alg) is true). - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \c alg is not a key derivation algorithm. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \c alg is not supported or is not a key derivation algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be inactive). - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_key_derivation_setup( - psa_key_derivation_operation_t *operation, - psa_algorithm_t alg); - -/** Retrieve the current capacity of a key derivation operation. - * - * The capacity of a key derivation is the maximum number of bytes that it can - * return. When you get *N* bytes of output from a key derivation operation, - * this reduces its capacity by *N*. - * - * \param[in] operation The operation to query. - * \param[out] capacity On success, the capacity of the operation. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active). - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_key_derivation_get_capacity( - const psa_key_derivation_operation_t *operation, - size_t *capacity); - -/** Set the maximum capacity of a key derivation operation. - * - * The capacity of a key derivation operation is the maximum number of bytes - * that the key derivation operation can return from this point onwards. - * - * \param[in,out] operation The key derivation operation object to modify. - * \param capacity The new capacity of the operation. - * It must be less or equal to the operation's - * current capacity. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p capacity is larger than the operation's current capacity. - * In this case, the operation object remains valid and its capacity - * remains unchanged. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active). - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_key_derivation_set_capacity( - psa_key_derivation_operation_t *operation, - size_t capacity); - -/** Use the maximum possible capacity for a key derivation operation. - * - * Use this value as the capacity argument when setting up a key derivation - * to indicate that the operation should have the maximum possible capacity. - * The value of the maximum possible capacity depends on the key derivation - * algorithm. - */ -#define PSA_KEY_DERIVATION_UNLIMITED_CAPACITY ((size_t)(-1)) - -/** Provide an input for key derivation or key agreement. - * - * Which inputs are required and in what order depends on the algorithm. - * Refer to the documentation of each key derivation or key agreement - * algorithm for information. - * - * This function passes direct inputs, which is usually correct for - * non-secret inputs. To pass a secret input, which should be in a key - * object, call psa_key_derivation_input_key() instead of this function. - * Refer to the documentation of individual step types - * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t) - * for more information. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_key_derivation_abort(). - * - * \param[in,out] operation The key derivation operation object to use. - * It must have been set up with - * psa_key_derivation_setup() and must not - * have produced any output yet. - * \param step Which step the input data is for. - * \param[in] data Input data to use. - * \param data_length Size of the \p data buffer in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \c step is not compatible with the operation's algorithm. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \c step does not allow direct inputs. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid for this input \p step. - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_key_derivation_input_bytes( - psa_key_derivation_operation_t *operation, - psa_key_derivation_step_t step, - const uint8_t *data, - size_t data_length); - -/** Provide an input for key derivation in the form of a key. - * - * Which inputs are required and in what order depends on the algorithm. - * Refer to the documentation of each key derivation or key agreement - * algorithm for information. - * - * This function obtains input from a key object, which is usually correct for - * secret inputs or for non-secret personalization strings kept in the key - * store. To pass a non-secret parameter which is not in the key store, - * call psa_key_derivation_input_bytes() instead of this function. - * Refer to the documentation of individual step types - * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t) - * for more information. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_key_derivation_abort(). - * - * \param[in,out] operation The key derivation operation object to use. - * It must have been set up with - * psa_key_derivation_setup() and must not - * have produced any output yet. - * \param step Which step the input data is for. - * \param handle Handle to the key. It must have an - * appropriate type for \p step and must - * allow the usage #PSA_KEY_USAGE_DERIVE. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \c step is not compatible with the operation's algorithm. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \c step does not allow key inputs of the given type - * or does not allow key inputs at all. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid for this input \p step. - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_key_derivation_input_key( - psa_key_derivation_operation_t *operation, - psa_key_derivation_step_t step, - psa_key_handle_t handle); - -/** Perform a key agreement and use the shared secret as input to a key - * derivation. - * - * A key agreement algorithm takes two inputs: a private key \p private_key - * a public key \p peer_key. - * The result of this function is passed as input to a key derivation. - * The output of this key derivation can be extracted by reading from the - * resulting operation to produce keys and other cryptographic material. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_key_derivation_abort(). - * - * \param[in,out] operation The key derivation operation object to use. - * It must have been set up with - * psa_key_derivation_setup() with a - * key agreement and derivation algorithm - * \c alg (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_KEY_AGREEMENT(\c alg) is true - * and #PSA_ALG_IS_RAW_KEY_AGREEMENT(\c alg) - * is false). - * The operation must be ready for an - * input of the type given by \p step. - * \param step Which step the input data is for. - * \param private_key Handle to the private key to use. - * \param[in] peer_key Public key of the peer. The peer key must be in the - * same format that psa_import_key() accepts for the - * public key type corresponding to the type of - * private_key. That is, this function performs the - * equivalent of - * #psa_import_key(..., - * `peer_key`, `peer_key_length`) where - * with key attributes indicating the public key - * type corresponding to the type of `private_key`. - * For example, for EC keys, this means that peer_key - * is interpreted as a point on the curve that the - * private key is on. The standard formats for public - * keys are documented in the documentation of - * psa_export_public_key(). - * \param peer_key_length Size of \p peer_key in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid for this key agreement \p step. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \c private_key is not compatible with \c alg, - * or \p peer_key is not valid for \c alg or not compatible with - * \c private_key. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \c alg is not supported or is not a key derivation algorithm. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \c step does not allow an input resulting from a key agreement. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_key_derivation_key_agreement( - psa_key_derivation_operation_t *operation, - psa_key_derivation_step_t step, - psa_key_handle_t private_key, - const uint8_t *peer_key, - size_t peer_key_length); - -/** Read some data from a key derivation operation. - * - * This function calculates output bytes from a key derivation algorithm and - * return those bytes. - * If you view the key derivation's output as a stream of bytes, this - * function destructively reads the requested number of bytes from the - * stream. - * The operation's capacity decreases by the number of bytes read. - * - * If this function returns an error status other than - * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error - * state and must be aborted by calling psa_key_derivation_abort(). - * - * \param[in,out] operation The key derivation operation object to read from. - * \param[out] output Buffer where the output will be written. - * \param output_length Number of bytes to output. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INSUFFICIENT_DATA - * The operation's capacity was less than - * \p output_length bytes. Note that in this case, - * no output is written to the output buffer. - * The operation's capacity is set to 0, thus - * subsequent calls to this function will not - * succeed, even with a smaller output buffer. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active and completed - * all required input steps). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_key_derivation_output_bytes( - psa_key_derivation_operation_t *operation, - uint8_t *output, - size_t output_length); - -/** Derive a key from an ongoing key derivation operation. - * - * This function calculates output bytes from a key derivation algorithm - * and uses those bytes to generate a key deterministically. - * The key's location, usage policy, type and size are taken from - * \p attributes. - * - * If you view the key derivation's output as a stream of bytes, this - * function destructively reads as many bytes as required from the - * stream. - * The operation's capacity decreases by the number of bytes read. - * - * If this function returns an error status other than - * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error - * state and must be aborted by calling psa_key_derivation_abort(). - * - * How much output is produced and consumed from the operation, and how - * the key is derived, depends on the key type: - * - * - For key types for which the key is an arbitrary sequence of bytes - * of a given size, this function is functionally equivalent to - * calling #psa_key_derivation_output_bytes - * and passing the resulting output to #psa_import_key. - * However, this function has a security benefit: - * if the implementation provides an isolation boundary then - * the key material is not exposed outside the isolation boundary. - * As a consequence, for these key types, this function always consumes - * exactly (\p bits / 8) bytes from the operation. - * The following key types defined in this specification follow this scheme: - * - * - #PSA_KEY_TYPE_AES; - * - #PSA_KEY_TYPE_ARC4; - * - #PSA_KEY_TYPE_CAMELLIA; - * - #PSA_KEY_TYPE_DERIVE; - * - #PSA_KEY_TYPE_HMAC. - * - * - For ECC keys on a Montgomery elliptic curve - * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a - * Montgomery curve), this function always draws a byte string whose - * length is determined by the curve, and sets the mandatory bits - * accordingly. That is: - * - * - Curve25519 (#PSA_ECC_CURVE_MONTGOMERY, 255 bits): draw a 32-byte - * string and process it as specified in RFC 7748 §5. - * - Curve448 (#PSA_ECC_CURVE_MONTGOMERY, 448 bits): draw a 56-byte - * string and process it as specified in RFC 7748 §5. - * - * - For key types for which the key is represented by a single sequence of - * \p bits bits with constraints as to which bit sequences are acceptable, - * this function draws a byte string of length (\p bits / 8) bytes rounded - * up to the nearest whole number of bytes. If the resulting byte string - * is acceptable, it becomes the key, otherwise the drawn bytes are discarded. - * This process is repeated until an acceptable byte string is drawn. - * The byte string drawn from the operation is interpreted as specified - * for the output produced by psa_export_key(). - * The following key types defined in this specification follow this scheme: - * - * - #PSA_KEY_TYPE_DES. - * Force-set the parity bits, but discard forbidden weak keys. - * For 2-key and 3-key triple-DES, the three keys are generated - * successively (for example, for 3-key triple-DES, - * if the first 8 bytes specify a weak key and the next 8 bytes do not, - * discard the first 8 bytes, use the next 8 bytes as the first key, - * and continue reading output from the operation to derive the other - * two keys). - * - Finite-field Diffie-Hellman keys (#PSA_KEY_TYPE_DH_KEY_PAIR(\c group) - * where \c group designates any Diffie-Hellman group) and - * ECC keys on a Weierstrass elliptic curve - * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a - * Weierstrass curve). - * For these key types, interpret the byte string as integer - * in big-endian order. Discard it if it is not in the range - * [0, *N* - 2] where *N* is the boundary of the private key domain - * (the prime *p* for Diffie-Hellman, the subprime *q* for DSA, - * or the order of the curve's base point for ECC). - * Add 1 to the resulting integer and use this as the private key *x*. - * This method allows compliance to NIST standards, specifically - * the methods titled "key-pair generation by testing candidates" - * in NIST SP 800-56A §5.6.1.1.4 for Diffie-Hellman, - * in FIPS 186-4 §B.1.2 for DSA, and - * in NIST SP 800-56A §5.6.1.2.2 or - * FIPS 186-4 §B.4.2 for elliptic curve keys. - * - * - For other key types, including #PSA_KEY_TYPE_RSA_KEY_PAIR, - * the way in which the operation output is consumed is - * implementation-defined. - * - * In all cases, the data that is read is discarded from the operation. - * The operation's capacity is decreased by the number of bytes read. - * - * For algorithms that take an input step #PSA_KEY_DERIVATION_INPUT_SECRET, - * the input to that step must be provided with psa_key_derivation_input_key(). - * Future versions of this specification may include additional restrictions - * on the derived key based on the attributes and strength of the secret key. - * - * \param[in] attributes The attributes for the new key. - * \param[in,out] operation The key derivation operation object to read from. - * \param[out] handle On success, a handle to the newly created key. - * \c 0 on failure. - * - * \retval #PSA_SUCCESS - * Success. - * If the key is persistent, the key material and the key's metadata - * have been saved to persistent storage. - * \retval #PSA_ERROR_ALREADY_EXISTS - * This is an attempt to create a persistent key, and there is - * already a persistent key with the given identifier. - * \retval #PSA_ERROR_INSUFFICIENT_DATA - * There was not enough data to create the desired key. - * Note that in this case, no output is written to the output buffer. - * The operation's capacity is set to 0, thus subsequent calls to - * this function will not succeed, even with a smaller output buffer. - * \retval #PSA_ERROR_NOT_SUPPORTED - * The key type or key size is not supported, either by the - * implementation in general or in this particular location. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The provided key attributes are not valid for the operation. - * \retval #PSA_ERROR_NOT_PERMITTED - * The #PSA_KEY_DERIVATION_INPUT_SECRET input was not provided through - * a key. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active and completed - * all required input steps). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_INSUFFICIENT_STORAGE - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_key_derivation_output_key( - const psa_key_attributes_t *attributes, - psa_key_derivation_operation_t *operation, - psa_key_handle_t *handle); - -/** Abort a key derivation operation. - * - * Aborting an operation frees all associated resources except for the \c - * operation structure itself. Once aborted, the operation object can be reused - * for another operation by calling psa_key_derivation_setup() again. - * - * This function may be called at any time after the operation - * object has been initialized as described in #psa_key_derivation_operation_t. - * - * In particular, it is valid to call psa_key_derivation_abort() twice, or to - * call psa_key_derivation_abort() on an operation that has not been set up. - * - * \param[in,out] operation The operation to abort. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_key_derivation_abort( - psa_key_derivation_operation_t *operation); - -/** Perform a key agreement and return the raw shared secret. - * - * \warning The raw result of a key agreement algorithm such as finite-field - * Diffie-Hellman or elliptic curve Diffie-Hellman has biases and should - * not be used directly as key material. It should instead be passed as - * input to a key derivation algorithm. To chain a key agreement with - * a key derivation, use psa_key_derivation_key_agreement() and other - * functions from the key derivation interface. - * - * \param alg The key agreement algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_RAW_KEY_AGREEMENT(\p alg) - * is true). - * \param private_key Handle to the private key to use. - * \param[in] peer_key Public key of the peer. It must be - * in the same format that psa_import_key() - * accepts. The standard formats for public - * keys are documented in the documentation - * of psa_export_public_key(). - * \param peer_key_length Size of \p peer_key in bytes. - * \param[out] output Buffer where the decrypted message is to - * be written. - * \param output_size Size of the \c output buffer in bytes. - * \param[out] output_length On success, the number of bytes - * that make up the returned output. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p alg is not a key agreement algorithm - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p private_key is not compatible with \p alg, - * or \p peer_key is not valid for \p alg or not compatible with - * \p private_key. - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * \p output_size is too small - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not a supported key agreement algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, - psa_key_handle_t private_key, - const uint8_t *peer_key, - size_t peer_key_length, - uint8_t *output, - size_t output_size, - size_t *output_length); - -/**@}*/ - -/** \defgroup random Random generation - * @{ - */ - -/** - * \brief Generate random bytes. - * - * \warning This function **can** fail! Callers MUST check the return status - * and MUST NOT use the content of the output buffer if the return - * status is not #PSA_SUCCESS. - * - * \note To generate a key, use psa_generate_key() instead. - * - * \param[out] output Output buffer for the generated data. - * \param output_size Number of bytes to generate and output. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_generate_random(uint8_t *output, - size_t output_size); - -/** - * \brief Generate a key or key pair. - * - * The key is generated randomly. - * Its location, usage policy, type and size are taken from \p attributes. - * - * Implementations must reject an attempt to generate a key of size 0. - * - * The following type-specific considerations apply: - * - For RSA keys (#PSA_KEY_TYPE_RSA_KEY_PAIR), - * the public exponent is 65537. - * The modulus is a product of two probabilistic primes - * between 2^{n-1} and 2^n where n is the bit size specified in the - * attributes. - * - * \param[in] attributes The attributes for the new key. - * \param[out] handle On success, a handle to the newly created key. - * \c 0 on failure. - * - * \retval #PSA_SUCCESS - * Success. - * If the key is persistent, the key material and the key's metadata - * have been saved to persistent storage. - * \retval #PSA_ERROR_ALREADY_EXISTS - * This is an attempt to create a persistent key, and there is - * already a persistent key with the given identifier. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_INSUFFICIENT_STORAGE - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, - psa_key_handle_t *handle); - -/**@}*/ - -#ifdef __cplusplus -} -#endif - -/* The file "crypto_sizes.h" contains definitions for size calculation - * macros whose definitions are implementation-specific. */ -#include "crypto_sizes.h" - -/* The file "crypto_struct.h" contains definitions for - * implementation-specific structs that are declared above. */ -#include "crypto_struct.h" - -/* The file "crypto_extra.h" contains vendor-specific definitions. This - * can include vendor-defined algorithms, extra functions, etc. */ -#include "crypto_extra.h" - -#endif /* PSA_CRYPTO_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_accel_driver.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_accel_driver.h deleted file mode 100644 index 4a540f0..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_accel_driver.h +++ /dev/null @@ -1,823 +0,0 @@ -/** - * \file psa/crypto_accel_driver.h - * \brief PSA cryptography accelerator driver module - * - * This header declares types and function signatures for cryptography - * drivers that access key material directly. This is meant for - * on-chip cryptography accelerators. - * - * This file is part of the PSA Crypto Driver Model, containing functions for - * driver developers to implement to enable hardware to be called in a - * standardized way by a PSA Cryptographic API implementation. The functions - * comprising the driver model, which driver authors implement, are not - * intended to be called by application developers. - */ - -/* - * Copyright (C) 2018, ARM Limited, 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 PSA_CRYPTO_ACCEL_DRIVER_H -#define PSA_CRYPTO_ACCEL_DRIVER_H - -#include "crypto_driver_common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** \defgroup driver_digest Hardware-Accelerated Message Digests - * - * Generation and authentication of Message Digests (aka hashes) must be done - * in parts using the following sequence: - * - `psa_drv_hash_setup_t` - * - `psa_drv_hash_update_t` - * - `psa_drv_hash_update_t` - * - ... - * - `psa_drv_hash_finish_t` - * - * If a previously started Message Digest operation needs to be terminated - * before the `psa_drv_hash_finish_t` operation is complete, it should be aborted - * by the `psa_drv_hash_abort_t`. Failure to do so may result in allocated - * resources not being freed or in other undefined behavior. - */ -/**@{*/ - -/** \brief The hardware-specific hash context structure - * - * The contents of this structure are implementation dependent and are - * therefore not described here - */ -typedef struct psa_drv_hash_context_s psa_drv_hash_context_t; - -/** \brief The function prototype for the start operation of a hash (message - * digest) operation - * - * Functions that implement this prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_hash__setup - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the underlying hash function - * - * \param[in,out] p_context A structure that will contain the - * hardware-specific hash context - * - * \retval PSA_SUCCESS Success. - */ -typedef psa_status_t (*psa_drv_hash_setup_t)(psa_drv_hash_context_t *p_context); - -/** \brief The function prototype for the update operation of a hash (message - * digest) operation - * - * Functions that implement this prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_hash__update - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the underlying algorithm - * - * \param[in,out] p_context A hardware-specific structure for the - * previously-established hash operation to be - * continued - * \param[in] p_input A buffer containing the message to be appended - * to the hash operation - * \param[in] input_length The size in bytes of the input message buffer - */ -typedef psa_status_t (*psa_drv_hash_update_t)(psa_drv_hash_context_t *p_context, - const uint8_t *p_input, - size_t input_length); - -/** \brief The function prototype for the finish operation of a hash (message - * digest) operation - * - * Functions that implement this prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_hash__finish - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the underlying algorithm - * - * \param[in,out] p_context A hardware-specific structure for the - * previously started hash operation to be - * fiinished - * \param[out] p_output A buffer where the generated digest will be - * placed - * \param[in] output_size The size in bytes of the buffer that has been - * allocated for the `p_output` buffer - * \param[out] p_output_length The number of bytes placed in `p_output` after - * success - * - * \retval PSA_SUCCESS - * Success. - */ -typedef psa_status_t (*psa_drv_hash_finish_t)(psa_drv_hash_context_t *p_context, - uint8_t *p_output, - size_t output_size, - size_t *p_output_length); - -/** \brief The function prototype for the abort operation of a hash (message - * digest) operation - * - * Functions that implement this prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_hash__abort - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the underlying algorithm - * - * \param[in,out] p_context A hardware-specific structure for the previously - * started hash operation to be aborted - */ -typedef void (*psa_drv_hash_abort_t)(psa_drv_hash_context_t *p_context); - -/**@}*/ - -/** \defgroup accel_mac Hardware-Accelerated Message Authentication Code - * Generation and authentication of Message Authentication Codes (MACs) using - * cryptographic accelerators can be done either as a single function call (via the - * `psa_drv_accel_mac_generate_t` or `psa_drv_accel_mac_verify_t` - * functions), or in parts using the following sequence: - * - `psa_drv_accel_mac_setup_t` - * - `psa_drv_accel_mac_update_t` - * - `psa_drv_accel_mac_update_t` - * - ... - * - `psa_drv_accel_mac_finish_t` or `psa_drv_accel_mac_finish_verify_t` - * - * If a previously started MAC operation needs to be terminated, it - * should be done so by the `psa_drv_accel_mac_abort_t`. Failure to do so may - * result in allocated resources not being freed or in other undefined - * behavior. - * - */ -/**@{*/ - -/** \brief The hardware-accelerator-specific MAC context structure - * - * The contents of this structure are implementation dependent and are - * therefore not described here. - */ -typedef struct psa_drv_accel_mac_context_s psa_drv_accel_mac_context_t; - -/** \brief The function prototype for the setup operation of a - * hardware-accelerated MAC operation - * - * Functions that implement this prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_accel_mac___setup - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the underlying primitive, and `MAC_VARIANT` - * is the specific variant of a MAC operation (such as HMAC or CMAC) - * - * \param[in,out] p_context A structure that will contain the - * hardware-specific MAC context - * \param[in] p_key A buffer containing the cleartext key material - * to be used in the operation - * \param[in] key_length The size in bytes of the key material - * - * \retval PSA_SUCCESS - * Success. - */ -typedef psa_status_t (*psa_drv_accel_mac_setup_t)(psa_drv_accel_mac_context_t *p_context, - const uint8_t *p_key, - size_t key_length); - -/** \brief The function prototype for the update operation of a - * hardware-accelerated MAC operation - * - * Functions that implement this prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_accel_mac___update - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` - * is the specific variant of a MAC operation (such as HMAC or CMAC) - * - * \param[in,out] p_context A hardware-specific structure for the - * previously-established MAC operation to be - * continued - * \param[in] p_input A buffer containing the message to be appended - * to the MAC operation - * \param[in] input_length The size in bytes of the input message buffer - */ -typedef psa_status_t (*psa_drv_accel_mac_update_t)(psa_drv_accel_mac_context_t *p_context, - const uint8_t *p_input, - size_t input_length); - -/** \brief The function prototype for the finish operation of a - * hardware-accelerated MAC operation - * - * Functions that implement this prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_accel_mac___finish - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` is - * the specific variant of a MAC operation (such as HMAC or CMAC) - * - * \param[in,out] p_context A hardware-specific structure for the - * previously started MAC operation to be - * finished - * \param[out] p_mac A buffer where the generated MAC will be placed - * \param[in] mac_length The size in bytes of the buffer that has been - * allocated for the `p_mac` buffer - * - * \retval PSA_SUCCESS - * Success. - */ -typedef psa_status_t (*psa_drv_accel_mac_finish_t)(psa_drv_accel_mac_context_t *p_context, - uint8_t *p_mac, - size_t mac_length); - -/** \brief The function prototype for the finish and verify operation of a - * hardware-accelerated MAC operation - * - * Functions that implement this prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_accel_mac___finish_verify - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` is - * the specific variant of a MAC operation (such as HMAC or CMAC) - * - * \param[in,out] p_context A hardware-specific structure for the - * previously started MAC operation to be - * verified and finished - * \param[in] p_mac A buffer containing the MAC that will be used - * for verification - * \param[in] mac_length The size in bytes of the data in the `p_mac` - * buffer - * - * \retval PSA_SUCCESS - * The operation completed successfully and the comparison matched - */ -typedef psa_status_t (*psa_drv_accel_mac_finish_verify_t)(psa_drv_accel_mac_context_t *p_context, - const uint8_t *p_mac, - size_t mac_length); - -/** \brief The function prototype for the abort operation for a previously - * started hardware-accelerated MAC operation - * - * Functions that implement this prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_accel_mac___abort - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` is - * the specific variant of a MAC operation (such as HMAC or CMAC) - * - * \param[in,out] p_context A hardware-specific structure for the - * previously started MAC operation to be - * aborted - * - */ -typedef psa_status_t (*psa_drv_accel_mac_abort_t)(psa_drv_accel_mac_context_t *p_context); - -/** \brief The function prototype for the one-shot operation of a - * hardware-accelerated MAC operation - * - * Functions that implement this prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_accel_mac__ - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` is - * the specific variant of a MAC operation (such as HMAC or CMAC) - * - * \param[in] p_input A buffer containing the data to be MACed - * \param[in] input_length The length in bytes of the `p_input` data - * \param[in] p_key A buffer containing the key material to be used - * for the MAC operation - * \param[in] key_length The length in bytes of the `p_key` data - * \param[in] alg The algorithm to be performed - * \param[out] p_mac The buffer where the resulting MAC will be placed - * upon success - * \param[in] mac_length The length in bytes of the `p_mac` buffer - */ -typedef psa_status_t (*psa_drv_accel_mac_t)(const uint8_t *p_input, - size_t input_length, - const uint8_t *p_key, - size_t key_length, - psa_algorithm_t alg, - uint8_t *p_mac, - size_t mac_length); - -/** \brief The function prototype for the one-shot hardware-accelerated MAC - * Verify operation - * - * Functions that implement this prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_accel_mac___verify - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` is - * the specific variant of a MAC operation (such as HMAC or CMAC) - * - * \param[in] p_input A buffer containing the data to be MACed - * \param[in] input_length The length in bytes of the `p_input` data - * \param[in] p_key A buffer containing the key material to be used - * for the MAC operation - * \param[in] key_length The length in bytes of the `p_key` data - * \param[in] alg The algorithm to be performed - * \param[in] p_mac The MAC data to be compared - * \param[in] mac_length The length in bytes of the `p_mac` buffer - * - * \retval PSA_SUCCESS - * The operation completed successfully and the comparison matched - */ -typedef psa_status_t (*psa_drv_accel_mac_verify_t)(const uint8_t *p_input, - size_t input_length, - const uint8_t *p_key, - size_t key_length, - psa_algorithm_t alg, - const uint8_t *p_mac, - size_t mac_length); -/**@}*/ - -/** \defgroup accel_cipher Hardware-Accelerated Block Ciphers - * Encryption and Decryption using hardware-acceleration in block modes other - * than ECB must be done in multiple parts, using the following flow: - * - `psa_drv_accel_ciphersetup_t` - * - `psa_drv_accel_cipher_set_iv_t` (optional depending upon block mode) - * - `psa_drv_accel_cipher_update_t` - * - `psa_drv_accel_cipher_update_t` - * - ... - * - `psa_drv_accel_cipher_finish_t` - * - * If a previously started hardware-accelerated Cipher operation needs to be - * terminated, it should be done so by the `psa_drv_accel_cipher_abort_t`. - * Failure to do so may result in allocated resources not being freed or in - * other undefined behavior. - */ -/**@{*/ - -/** \brief The hardware-accelerator-specific cipher context structure - * - * The contents of this structure are implementation dependent and are - * therefore not described here. - */ -typedef struct psa_drv_accel_cipher_context_s psa_drv_accel_cipher_context_t; - -/** \brief The function prototype for the setup operation of - * hardware-accelerated block cipher operations. - * Functions that implement this prototype should be named in the following - * conventions: - * ~~~~~~~~~~~~~{.c} - * psa_drv_accel_cipher_setup__ - * ~~~~~~~~~~~~~ - * Where - * - `CIPHER_NAME` is the name of the underlying block cipher (i.e. AES or DES) - * - `MODE` is the block mode of the cipher operation (i.e. CBC or CTR) - * - * For stream ciphers: - * ~~~~~~~~~~~~~{.c} - * psa_drv_accel_cipher_setup_ - * ~~~~~~~~~~~~~ - * Where `CIPHER_NAME` is the name of a stream cipher (i.e. RC4) - * - * \param[in,out] p_context A structure that will contain the - * hardware-specific cipher context - * \param[in] direction Indicates if the operation is an encrypt or a - * decrypt - * \param[in] p_key_data A buffer containing the cleartext key material - * to be used in the operation - * \param[in] key_data_size The size in bytes of the key material - * - * \retval PSA_SUCCESS - */ -typedef psa_status_t (*psa_drv_accel_cipher_setup_t)(psa_drv_accel_cipher_context_t *p_context, - psa_encrypt_or_decrypt_t direction, - const uint8_t *p_key_data, - size_t key_data_size); - -/** \brief The function prototype for the set initialization vector operation - * of hardware-accelerated block cipher operations - * Functions that implement this prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_accel_cipher_set_iv__ - * ~~~~~~~~~~~~~ - * Where - * - `CIPHER_NAME` is the name of the underlying block cipher (i.e. AES or DES) - * - `MODE` is the block mode of the cipher operation (i.e. CBC or CTR) - * - * \param[in,out] p_context A structure that contains the previously setup - * hardware-specific cipher context - * \param[in] p_iv A buffer containing the initialization vecotr - * \param[in] iv_length The size in bytes of the contents of `p_iv` - * - * \retval PSA_SUCCESS - */ -typedef psa_status_t (*psa_drv_accel_cipher_set_iv_t)(psa_drv_accel_cipher_context_t *p_context, - const uint8_t *p_iv, - size_t iv_length); - -/** \brief The function prototype for the update operation of - * hardware-accelerated block cipher operations. - * - * Functions that implement this prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_accel_cipher_update__ - * ~~~~~~~~~~~~~ - * Where - * - `CIPHER_NAME` is the name of the underlying block cipher (i.e. AES or DES) - * - `MODE` is the block mode of the cipher operation (i.e. CBC or CTR) - * - * \param[in,out] p_context A hardware-specific structure for the - * previously started cipher operation - * \param[in] p_input A buffer containing the data to be - * encrypted or decrypted - * \param[in] input_size The size in bytes of the `p_input` buffer - * \param[out] p_output A caller-allocated buffer where the - * generated output will be placed - * \param[in] output_size The size in bytes of the `p_output` buffer - * \param[out] p_output_length After completion, will contain the number - * of bytes placed in the `p_output` buffer - * - * \retval PSA_SUCCESS - */ -typedef psa_status_t (*psa_drv_accel_cipher_update_t)(psa_drv_accel_cipher_context_t *p_context, - const uint8_t *p_input, - size_t input_size, - uint8_t *p_output, - size_t output_size, - size_t *p_output_length); - -/** \brief The function prototype for the finish operation of - * hardware-accelerated block cipher operations. - * - * Functions that implement this prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_accel_cipher_finish__ - * ~~~~~~~~~~~~~ - * Where - * - `CIPHER_NAME` is the name of the underlying block cipher (i.e. AES or DES) - * - `MODE` is the block mode of the cipher operation (i.e. CBC or CTR) - * - * \param[in,out] p_context A hardware-specific structure for the - * previously started cipher operation - * \param[out] p_output A caller-allocated buffer where the generated - * output will be placed - * \param[in] output_size The size in bytes of the `p_output` buffer - * \param[out] p_output_length After completion, will contain the number of - * bytes placed in the `p_output` buffer - * - * \retval PSA_SUCCESS - */ -typedef psa_status_t (*psa_drv_accel_cipher_finish_t)(psa_drv_accel_cipher_context_t *p_context, - uint8_t *p_output, - size_t output_size, - size_t *p_output_length); - -/** \brief The function prototype for the abort operation of - * hardware-accelerated block cipher operations. - * - * Functions that implement the following prototype should be named in the - * following convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_accel_cipher_abort__ - * ~~~~~~~~~~~~~ - * Where - * - `CIPHER_NAME` is the name of the underlying block cipher (i.e. AES or DES) - * - `MODE` is the block mode of the cipher operation (i.e. CBC or CTR) - * - * \param[in,out] p_context A hardware-specific structure for the - * previously started cipher operation - * - * \retval PSA_SUCCESS - */ -typedef psa_status_t (*psa_drv_accel_cipher_abort_t)(psa_drv_accel_cipher_context_t *p_context); - -/**@}*/ - -/** \defgroup accel_aead Hardware-Accelerated Authenticated Encryption with Additional Data - * - * Hardware-accelerated Authenticated Encryption with Additional Data (AEAD) - * operations must be done in one function call. While this creates a burden - * for implementers as there must be sufficient space in memory for the entire - * message, it prevents decrypted data from being made available before the - * authentication operation is complete and the data is known to be authentic. - */ -/**@{*/ - -/** \brief The function prototype for the hardware-accelerated authenticated - * encryption operation. - * - * Functions that implement this prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_accel_aead__encrypt - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the AEAD algorithm - * - * \param[in] p_key A pointer to the key material - * \param[in] key_length The size in bytes of the key material - * \param[in] alg The AEAD algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(`alg`) is true) - * \param[in] nonce Nonce or IV to use - * \param[in] nonce_length Size of the `nonce` buffer in bytes - * \param[in] additional_data Additional data that will be MACed - * but not encrypted. - * \param[in] additional_data_length Size of `additional_data` in bytes - * \param[in] plaintext Data that will be MACed and - * encrypted. - * \param[in] plaintext_length Size of `plaintext` in bytes - * \param[out] ciphertext Output buffer for the authenticated and - * encrypted data. The additional data is - * not part of this output. For algorithms - * where the encrypted data and the - * authentication tag are defined as - * separate outputs, the authentication - * tag is appended to the encrypted data. - * \param[in] ciphertext_size Size of the `ciphertext` buffer in - * bytes - * This must be at least - * #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(`alg`, - * `plaintext_length`). - * \param[out] ciphertext_length On success, the size of the output in - * the `ciphertext` buffer - * - * \retval #PSA_SUCCESS - * - */ -typedef psa_status_t (*psa_drv_accel_aead_encrypt_t)(const uint8_t *p_key, - size_t key_length, - 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 *ciphertext, - size_t ciphertext_size, - size_t *ciphertext_length); - -/** \brief The function prototype for the hardware-accelerated authenticated - * decryption operation. - * - * Functions that implement this prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_accel_aead__decrypt - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the AEAD algorithm - * \param[in] p_key A pointer to the key material - * \param[in] key_length The size in bytes of the key material - * \param[in] alg The AEAD algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(`alg`) is true) - * \param[in] nonce Nonce or IV to use - * \param[in] nonce_length Size of the `nonce` buffer in bytes - * \param[in] additional_data Additional data that has been MACed - * but not encrypted - * \param[in] additional_data_length Size of `additional_data` in bytes - * \param[in] ciphertext Data that has been MACed and - * encrypted - * For algorithms where the encrypted data - * and the authentication tag are defined - * as separate inputs, the buffer must - * contain the encrypted data followed by - * the authentication tag. - * \param[in] ciphertext_length Size of `ciphertext` in bytes - * \param[out] plaintext Output buffer for the decrypted data - * \param[in] plaintext_size Size of the `plaintext` buffer in - * bytes - * This must be at least - * #PSA_AEAD_DECRYPT_OUTPUT_SIZE(`alg`, - * `ciphertext_length`). - * \param[out] plaintext_length On success, the size of the output - * in the \b plaintext buffer - * - * \retval #PSA_SUCCESS - * Success. - */ -typedef psa_status_t (*psa_drv_accel_aead_decrypt_t)(const uint8_t *p_key, - size_t key_length, - 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 *ciphertext, - size_t ciphertext_length, - uint8_t *plaintext, - size_t plaintext_size, - size_t *plaintext_length); - -/**@}*/ - -/** \defgroup accel_asymmetric Hardware-Accelerated Asymmetric Cryptography - * - * Since the amount of data that can (or should) be encrypted or signed using - * asymmetric keys is limited by the key size, hardware-accelerated asymmetric - * key operations must be done in single function calls. - */ -/**@{*/ - - -/** - * \brief The function prototype for the hardware-accelerated asymmetric sign - * operation. - * - * Functions that implement this prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_accel_asymmetric__sign - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the signing algorithm - * - * This function supports any asymmetric-key output from psa_export_key() as - * the buffer in \p p_key. Refer to the documentation of \ref - * psa_export_key() for the formats. - * - * \param[in] p_key A buffer containing the private key - * material - * \param[in] key_size The size in bytes of the `p_key` data - * \param[in] alg A signature algorithm that is compatible - * with the type of `p_key` - * \param[in] p_hash The hash or message to sign - * \param[in] hash_length Size of the `p_hash` buffer in bytes - * \param[out] p_signature Buffer where the signature is to be written - * \param[in] signature_size Size of the `p_signature` buffer in bytes - * \param[out] p_signature_length On success, the number of bytes - * that make up the returned signature value - * - * \retval PSA_SUCCESS - */ -typedef psa_status_t (*psa_drv_accel_asymmetric_sign_t)(const uint8_t *p_key, - size_t key_size, - psa_algorithm_t alg, - psa_key_type_t key_type, - const uint8_t *p_hash, - size_t hash_length, - uint8_t *p_signature, - size_t signature_size, - size_t *p_signature_length); - -/** - * \brief The function prototype for the hardware-accelerated signature verify - * operation - * - * Functions that implement this prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_accel_asymmetric__verify - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the signing algorithm - * - * This function supports any output from \ref psa_export_public_key() as the - * buffer in \p p_key. Refer to the documentation of \ref - * psa_export_public_key() for the format of public keys and to the - * documentation of \ref psa_export_key() for the format for other key types. - * - * \param[in] p_key A buffer containing the public key material - * \param[in] key_size The size in bytes of the `p_key` data - * \param[in] alg A signature algorithm that is compatible with - * the type of `key` - * \param[in] p_hash The hash or message whose signature is to be - * verified - * \param[in] hash_length Size of the `p_hash` buffer in bytes - * \param[in] p_signature Buffer containing the signature to verify - * \param[in] signature_length Size of the `p_signature` buffer in bytes - * - * \retval PSA_SUCCESS - * The signature is valid. - */ -typedef psa_status_t (*psa_drv_accel_asymmetric_verify_t)(const uint8_t *p_key, - size_t key_size, - psa_algorithm_t alg, - psa_key_type_t key_type, - const uint8_t *p_hash, - size_t hash_length, - const uint8_t *p_signature, - size_t signature_length); - -/** - * \brief The function prototype for the hardware-accelerated asymmetric - * encrypt operation - * - * Functions that implement this prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_accel_asymmetric__encrypt - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the encryption algorithm - * - * This function supports any output from \ref psa_export_public_key() as the - * buffer in \p p_key. Refer to the documentation of \ref - * psa_export_public_key() for the format of public keys and to the - * documentation of \ref psa_export_key() for the format for other key types. - * - * \param[in] p_key A buffer containing the public key material - * \param[in] key_size The size in bytes of the `p_key` data - * \param[in] alg An asymmetric encryption algorithm that is - * compatible with the type of `key` - * \param[in] p_input The message to encrypt - * \param[in] input_length Size of the `p_input` buffer in bytes - * \param[in] p_salt A salt or label, if supported by the - * encryption algorithm - * If the algorithm does not support a - * salt, pass `NULL` - * If the algorithm supports an optional - * salt and you do not want to pass a salt, - * pass `NULL`. - * For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is - * supported. - * \param[in] salt_length Size of the `p_salt` buffer in bytes - * If `p_salt` is `NULL`, pass 0. - * \param[out] p_output Buffer where the encrypted message is to - * be written - * \param[in] output_size Size of the `p_output` buffer in bytes - * \param[out] p_output_length On success, the number of bytes - * that make up the returned output - * - * \retval PSA_SUCCESS - */ -typedef psa_status_t (*psa_drv_accel_asymmetric_encrypt_t)(const uint8_t *p_key, - size_t key_size, - psa_algorithm_t alg, - psa_key_type_t key_type, - const uint8_t *p_input, - size_t input_length, - const uint8_t *p_salt, - size_t salt_length, - uint8_t *p_output, - size_t output_size, - size_t *p_output_length); - -/** - * \brief The function prototype for the hardware=acce;erated asymmetric - * decrypt operation - * - * Functions that implement this prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_accel_asymmetric__decrypt - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the encryption algorithm - * - * This function supports any asymmetric-key output from psa_export_key() as - * the buffer in \p p_key. Refer to the documentation of \ref - * psa_export_key() for the formats. - * - * \param[in] p_key A buffer containing the private key material - * \param[in] key_size The size in bytes of the `p_key` data - * \param[in] alg An asymmetric encryption algorithm that is - * compatible with the type of `key` - * \param[in] p_input The message to decrypt - * \param[in] input_length Size of the `p_input` buffer in bytes - * \param[in] p_salt A salt or label, if supported by the - * encryption algorithm - * If the algorithm does not support a - * salt, pass `NULL`. - * If the algorithm supports an optional - * salt and you do not want to pass a salt, - * pass `NULL`. - * For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is - * supported - * \param[in] salt_length Size of the `p_salt` buffer in bytes - * If `p_salt` is `NULL`, pass 0 - * \param[out] p_output Buffer where the decrypted message is to - * be written - * \param[in] output_size Size of the `p_output` buffer in bytes - * \param[out] p_output_length On success, the number of bytes - * that make up the returned output - * - * \retval PSA_SUCCESS - */ -typedef psa_status_t (*psa_drv_accel_asymmetric_decrypt_t)(const uint8_t *p_key, - size_t key_size, - psa_algorithm_t alg, - psa_key_type_t key_type, - const uint8_t *p_input, - size_t input_length, - const uint8_t *p_salt, - size_t salt_length, - uint8_t *p_output, - size_t output_size, - size_t *p_output_length); - -/**@}*/ - -#ifdef __cplusplus -} -#endif - -#endif /* PSA_CRYPTO_ACCEL_DRIVER_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_compat.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_compat.h deleted file mode 100644 index 1ed5f05..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_compat.h +++ /dev/null @@ -1,196 +0,0 @@ -/** - * \file psa/crypto_compat.h - * - * \brief PSA cryptography module: Backward compatibility aliases - * - * This header declares alternative names for macro and functions. - * New application code should not use these names. - * These names may be removed in a future version of Mbed Crypto. - * - * \note This file may not be included directly. Applications must - * include psa/crypto.h. - */ -/* - * Copyright (C) 2019, ARM Limited, 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. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#ifndef PSA_CRYPTO_COMPAT_H -#define PSA_CRYPTO_COMPAT_H - -#ifdef __cplusplus -extern "C" { -#endif - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) - -/* - * Mechanism for declaring deprecated values - */ -#if defined(MBEDTLS_DEPRECATED_WARNING) && !defined(MBEDTLS_PSA_DEPRECATED) -#define MBEDTLS_PSA_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_PSA_DEPRECATED -#endif - -typedef MBEDTLS_PSA_DEPRECATED size_t mbedtls_deprecated_size_t; -typedef MBEDTLS_PSA_DEPRECATED psa_status_t mbedtls_deprecated_psa_status_t; -typedef MBEDTLS_PSA_DEPRECATED psa_key_usage_t mbedtls_deprecated_psa_key_usage_t; -typedef MBEDTLS_PSA_DEPRECATED psa_ecc_curve_t mbedtls_deprecated_psa_ecc_curve_t; -typedef MBEDTLS_PSA_DEPRECATED psa_dh_group_t mbedtls_deprecated_psa_dh_group_t; - -#define MBEDTLS_DEPRECATED_CONSTANT( type, value ) \ - ( (mbedtls_deprecated_##type) ( value ) ) - -/* - * Deprecated PSA Crypto error code definitions (PSA Crypto API <= 1.0 beta2) - */ -#define PSA_ERROR_UNKNOWN_ERROR \ - MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_GENERIC_ERROR ) -#define PSA_ERROR_OCCUPIED_SLOT \ - MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_ALREADY_EXISTS ) -#define PSA_ERROR_EMPTY_SLOT \ - MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_DOES_NOT_EXIST ) -#define PSA_ERROR_INSUFFICIENT_CAPACITY \ - MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_INSUFFICIENT_DATA ) -#define PSA_ERROR_TAMPERING_DETECTED \ - MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_CORRUPTION_DETECTED ) - -/* - * Deprecated PSA Crypto numerical encodings (PSA Crypto API <= 1.0 beta3) - */ -#define PSA_KEY_USAGE_SIGN \ - MBEDTLS_DEPRECATED_CONSTANT( psa_key_usage_t, PSA_KEY_USAGE_SIGN_HASH ) -#define PSA_KEY_USAGE_VERIFY \ - MBEDTLS_DEPRECATED_CONSTANT( psa_key_usage_t, PSA_KEY_USAGE_VERIFY_HASH ) - -/* - * Deprecated PSA Crypto size calculation macros (PSA Crypto API <= 1.0 beta3) - */ -#define PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE \ - MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_SIGNATURE_MAX_SIZE ) -#define PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE( key_type, key_bits, alg ) \ - MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_SIGN_OUTPUT_SIZE( key_type, key_bits, alg ) ) - -/* - * Deprecated PSA Crypto function names (PSA Crypto API <= 1.0 beta3) - */ -MBEDTLS_PSA_DEPRECATED static inline psa_status_t psa_asymmetric_sign( psa_key_handle_t key, - psa_algorithm_t alg, - const uint8_t *hash, - size_t hash_length, - uint8_t *signature, - size_t signature_size, - size_t *signature_length ) -{ - return psa_sign_hash( key, alg, hash, hash_length, signature, signature_size, signature_length ); -} - -MBEDTLS_PSA_DEPRECATED static inline psa_status_t psa_asymmetric_verify( psa_key_handle_t key, - psa_algorithm_t alg, - const uint8_t *hash, - size_t hash_length, - const uint8_t *signature, - size_t signature_length ) -{ - return psa_verify_hash( key, alg, hash, hash_length, signature, signature_length ); -} - - - -#endif /* MBEDTLS_DEPRECATED_REMOVED */ - -/* - * Size-specific elliptic curve and Diffie-Hellman group names - */ -#define PSA_ECC_CURVE_SECP160K1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_K1 ) -#define PSA_ECC_CURVE_SECP192K1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_K1 ) -#define PSA_ECC_CURVE_SECP224K1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_K1 ) -#define PSA_ECC_CURVE_SECP256K1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_K1 ) -#define PSA_ECC_CURVE_SECP160R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_R1 ) -#define PSA_ECC_CURVE_SECP192R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_R1 ) -#define PSA_ECC_CURVE_SECP224R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_R1 ) -#define PSA_ECC_CURVE_SECP256R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_R1 ) -#define PSA_ECC_CURVE_SECP384R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_R1 ) -#define PSA_ECC_CURVE_SECP521R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_R1 ) -#define PSA_ECC_CURVE_SECP160R2 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_R2 ) -#define PSA_ECC_CURVE_SECT163K1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_K1 ) -#define PSA_ECC_CURVE_SECT233K1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_K1 ) -#define PSA_ECC_CURVE_SECT239K1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_K1 ) -#define PSA_ECC_CURVE_SECT283K1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_K1 ) -#define PSA_ECC_CURVE_SECT409K1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_K1 ) -#define PSA_ECC_CURVE_SECT571K1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_K1 ) -#define PSA_ECC_CURVE_SECT163R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R1 ) -#define PSA_ECC_CURVE_SECT193R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R1 ) -#define PSA_ECC_CURVE_SECT233R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R1 ) -#define PSA_ECC_CURVE_SECT283R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R1 ) -#define PSA_ECC_CURVE_SECT409R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R1 ) -#define PSA_ECC_CURVE_SECT571R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R1 ) -#define PSA_ECC_CURVE_SECT163R2 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R2 ) -#define PSA_ECC_CURVE_SECT193R2 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R2 ) -#define PSA_ECC_CURVE_BRAINPOOL_P256R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_BRAINPOOL_P_R1 ) -#define PSA_ECC_CURVE_BRAINPOOL_P384R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_BRAINPOOL_P_R1 ) -#define PSA_ECC_CURVE_BRAINPOOL_P512R1 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_BRAINPOOL_P_R1 ) -#define PSA_ECC_CURVE_CURVE25519 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_MONTGOMERY ) -#define PSA_ECC_CURVE_CURVE448 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_MONTGOMERY ) - -#define PSA_DH_GROUP_FFDHE2048 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_dh_group_t, PSA_DH_GROUP_RFC7919 ) -#define PSA_DH_GROUP_FFDHE3072 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_dh_group_t, PSA_DH_GROUP_RFC7919 ) -#define PSA_DH_GROUP_FFDHE4096 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_dh_group_t, PSA_DH_GROUP_RFC7919 ) -#define PSA_DH_GROUP_FFDHE6144 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_dh_group_t, PSA_DH_GROUP_RFC7919 ) -#define PSA_DH_GROUP_FFDHE8192 \ - MBEDTLS_DEPRECATED_CONSTANT( psa_dh_group_t, PSA_DH_GROUP_RFC7919 ) - -#ifdef __cplusplus -} -#endif - -#endif /* PSA_CRYPTO_COMPAT_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_driver_common.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_driver_common.h deleted file mode 100644 index 6f1a5d5..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_driver_common.h +++ /dev/null @@ -1,54 +0,0 @@ -/** - * \file psa/crypto_driver_common.h - * \brief Definitions for all PSA crypto drivers - * - * This file contains common definitions shared by all PSA crypto drivers. - * Do not include it directly: instead, include the header file(s) for - * the type(s) of driver that you are implementing. For example, if - * you are writing a driver for a chip that provides both a hardware - * random generator and an accelerator for some cryptographic algorithms, - * include `psa/crypto_entropy_driver.h` and `psa/crypto_accel_driver.h`. - * - * This file is part of the PSA Crypto Driver Model, containing functions for - * driver developers to implement to enable hardware to be called in a - * standardized way by a PSA Cryptographic API implementation. The functions - * comprising the driver model, which driver authors implement, are not - * intended to be called by application developers. - */ - -/* - * Copyright (C) 2018, ARM Limited, 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 PSA_CRYPTO_DRIVER_COMMON_H -#define PSA_CRYPTO_DRIVER_COMMON_H - -#include -#include - -/* Include type definitions (psa_status_t, psa_algorithm_t, - * psa_key_type_t, etc.) and macros to build and analyze values - * of these types. */ -#include "crypto_types.h" -#include "crypto_values.h" - -/** For encrypt-decrypt functions, whether the operation is an encryption - * or a decryption. */ -typedef enum { - PSA_CRYPTO_DRIVER_DECRYPT, - PSA_CRYPTO_DRIVER_ENCRYPT -} psa_encrypt_or_decrypt_t; - -#endif /* PSA_CRYPTO_DRIVER_COMMON_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_entropy_driver.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_entropy_driver.h deleted file mode 100644 index f596b6b..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_entropy_driver.h +++ /dev/null @@ -1,108 +0,0 @@ -/** - * \file psa/crypto_entropy_driver.h - * \brief PSA entropy source driver module - * - * This header declares types and function signatures for entropy sources. - * - * This file is part of the PSA Crypto Driver Model, containing functions for - * driver developers to implement to enable hardware to be called in a - * standardized way by a PSA Cryptographic API implementation. The functions - * comprising the driver model, which driver authors implement, are not - * intended to be called by application developers. - */ - -/* - * Copyright (C) 2018, ARM Limited, 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 PSA_CRYPTO_ENTROPY_DRIVER_H -#define PSA_CRYPTO_ENTROPY_DRIVER_H - -#include "crypto_driver_common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** \defgroup driver_rng Entropy Generation - */ -/**@{*/ - -/** \brief Initialize an entropy driver - * - * - * \param[in,out] p_context A hardware-specific structure - * containing any context information for - * the implementation - * - * \retval PSA_SUCCESS - */ -typedef psa_status_t (*psa_drv_entropy_init_t)(void *p_context); - -/** \brief Get a specified number of bits from the entropy source - * - * It retrives `buffer_size` bytes of data from the entropy source. The entropy - * source will always fill the provided buffer to its full size, however, most - * entropy sources have biases, and the actual amount of entropy contained in - * the buffer will be less than the number of bytes. - * The driver will return the actual number of bytes of entropy placed in the - * buffer in `p_received_entropy_bytes`. - * A PSA Crypto API implementation will likely feed the output of this function - * into a Digital Random Bit Generator (DRBG), and typically has a minimum - * amount of entropy that it needs. - * To accomplish this, the PSA Crypto implementation should be designed to call - * this function multiple times until it has received the required amount of - * entropy from the entropy source. - * - * \param[in,out] p_context A hardware-specific structure - * containing any context information - * for the implementation - * \param[out] p_buffer A caller-allocated buffer for the - * retrieved entropy to be placed in - * \param[in] buffer_size The allocated size of `p_buffer` - * \param[out] p_received_entropy_bits The amount of entropy (in bits) - * actually provided in `p_buffer` - * - * \retval PSA_SUCCESS - */ -typedef psa_status_t (*psa_drv_entropy_get_bits_t)(void *p_context, - uint8_t *p_buffer, - uint32_t buffer_size, - uint32_t *p_received_entropy_bits); - -/** - * \brief A struct containing all of the function pointers needed to interface - * to an entropy source - * - * PSA Crypto API implementations should populate instances of the table as - * appropriate upon startup. - * - * If one of the functions is not implemented, it should be set to NULL. - */ -typedef struct { - /** The driver-specific size of the entropy context */ - const size_t context_size; - /** Function that performs initialization for the entropy source */ - psa_drv_entropy_init_t p_init; - /** Function that performs the get_bits operation for the entropy source */ - psa_drv_entropy_get_bits_t p_get_bits; -} psa_drv_entropy_t; -/**@}*/ - -#ifdef __cplusplus -} -#endif - -#endif /* PSA_CRYPTO_ENTROPY_DRIVER_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_extra.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_extra.h deleted file mode 100644 index 64ab1bf..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_extra.h +++ /dev/null @@ -1,655 +0,0 @@ -/** - * \file psa/crypto_extra.h - * - * \brief PSA cryptography module: Mbed TLS vendor extensions - * - * \note This file may not be included directly. Applications must - * include psa/crypto.h. - * - * This file is reserved for vendor-specific definitions. - */ -/* - * Copyright (C) 2018, ARM Limited, 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. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#ifndef PSA_CRYPTO_EXTRA_H -#define PSA_CRYPTO_EXTRA_H - -#include "mbedtls/platform_util.h" - -#include "crypto_compat.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* UID for secure storage seed */ -#define PSA_CRYPTO_ITS_RANDOM_SEED_UID 0xFFFFFF52 - - -/** \addtogroup attributes - * @{ - */ - -/** \brief Declare the enrollment algorithm for a key. - * - * An operation on a key may indifferently use the algorithm set with - * psa_set_key_algorithm() or with this function. - * - * \param[out] attributes The attribute structure to write to. - * \param alg2 A second algorithm that the key may be used - * for, in addition to the algorithm set with - * psa_set_key_algorithm(). - * - * \warning Setting an enrollment algorithm is not recommended, because - * using the same key with different algorithms can allow some - * attacks based on arithmetic relations between different - * computations made with the same key, or can escalate harmless - * side channels into exploitable ones. Use this function only - * if it is necessary to support a protocol for which it has been - * verified that the usage of the key with multiple algorithms - * is safe. - */ -static inline void psa_set_key_enrollment_algorithm( - psa_key_attributes_t *attributes, - psa_algorithm_t alg2) -{ - attributes->core.policy.alg2 = alg2; -} - -/** Retrieve the enrollment algorithm policy from key attributes. - * - * \param[in] attributes The key attribute structure to query. - * - * \return The enrollment algorithm stored in the attribute structure. - */ -static inline psa_algorithm_t psa_get_key_enrollment_algorithm( - const psa_key_attributes_t *attributes) -{ - return( attributes->core.policy.alg2 ); -} - -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - -/** Retrieve the slot number where a key is stored. - * - * A slot number is only defined for keys that are stored in a secure - * element. - * - * This information is only useful if the secure element is not entirely - * managed through the PSA Cryptography API. It is up to the secure - * element driver to decide how PSA slot numbers map to any other interface - * that the secure element may have. - * - * \param[in] attributes The key attribute structure to query. - * \param[out] slot_number On success, the slot number containing the key. - * - * \retval #PSA_SUCCESS - * The key is located in a secure element, and \p *slot_number - * indicates the slot number that contains it. - * \retval #PSA_ERROR_NOT_PERMITTED - * The caller is not permitted to query the slot number. - * Mbed Crypto currently does not return this error. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The key is not located in a secure element. - */ -psa_status_t psa_get_key_slot_number( - const psa_key_attributes_t *attributes, - psa_key_slot_number_t *slot_number ); - -/** Choose the slot number where a key is stored. - * - * This function declares a slot number in the specified attribute - * structure. - * - * A slot number is only meaningful for keys that are stored in a secure - * element. It is up to the secure element driver to decide how PSA slot - * numbers map to any other interface that the secure element may have. - * - * \note Setting a slot number in key attributes for a key creation can - * cause the following errors when creating the key: - * - #PSA_ERROR_NOT_SUPPORTED if the selected secure element does - * not support choosing a specific slot number. - * - #PSA_ERROR_NOT_PERMITTED if the caller is not permitted to - * choose slot numbers in general or to choose this specific slot. - * - #PSA_ERROR_INVALID_ARGUMENT if the chosen slot number is not - * valid in general or not valid for this specific key. - * - #PSA_ERROR_ALREADY_EXISTS if there is already a key in the - * selected slot. - * - * \param[out] attributes The attribute structure to write to. - * \param slot_number The slot number to set. - */ -static inline void psa_set_key_slot_number( - psa_key_attributes_t *attributes, - psa_key_slot_number_t slot_number ) -{ - attributes->core.flags |= MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER; - attributes->slot_number = slot_number; -} - -/** Remove the slot number attribute from a key attribute structure. - * - * This function undoes the action of psa_set_key_slot_number(). - * - * \param[out] attributes The attribute structure to write to. - */ -static inline void psa_clear_key_slot_number( - psa_key_attributes_t *attributes ) -{ - attributes->core.flags &= ~MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER; -} - -/** Register a key that is already present in a secure element. - * - * The key must be located in a secure element designated by the - * lifetime field in \p attributes, in the slot set with - * psa_set_key_slot_number() in the attribute structure. - * This function makes the key available through the key identifier - * specified in \p attributes. - * - * \param[in] attributes The attributes of the existing key. - * - * \retval #PSA_SUCCESS - * The key was successfully registered. - * Note that depending on the design of the driver, this may or may - * not guarantee that a key actually exists in the designated slot - * and is compatible with the specified attributes. - * \retval #PSA_ERROR_ALREADY_EXISTS - * There is already a key with the identifier specified in - * \p attributes. - * \retval #PSA_ERROR_NOT_SUPPORTED - * The secure element driver for the specified lifetime does not - * support registering a key. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p attributes specifies a lifetime which is not located - * in a secure element. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * No slot number is specified in \p attributes, - * or the specified slot number is not valid. - * \retval #PSA_ERROR_NOT_PERMITTED - * The caller is not authorized to register the specified key slot. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t mbedtls_psa_register_se_key( - const psa_key_attributes_t *attributes); - -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - -/**@}*/ - -/** - * \brief Library deinitialization. - * - * This function clears all data associated with the PSA layer, - * including the whole key store. - * - * This is an Mbed TLS extension. - */ -void mbedtls_psa_crypto_free( void ); - -/** \brief Statistics about - * resource consumption related to the PSA keystore. - * - * \note The content of this structure is not part of the stable API and ABI - * of Mbed Crypto and may change arbitrarily from version to version. - */ -typedef struct mbedtls_psa_stats_s -{ - /** Number of slots containing key material for a volatile key. */ - size_t volatile_slots; - /** Number of slots containing key material for a key which is in - * internal persistent storage. */ - size_t persistent_slots; - /** Number of slots containing a reference to a key in a - * secure element. */ - size_t external_slots; - /** Number of slots which are occupied, but do not contain - * key material yet. */ - size_t half_filled_slots; - /** Number of slots that contain cache data. */ - size_t cache_slots; - /** Number of slots that are not used for anything. */ - size_t empty_slots; - /** Largest key id value among open keys in internal persistent storage. */ - psa_app_key_id_t max_open_internal_key_id; - /** Largest key id value among open keys in secure elements. */ - psa_app_key_id_t max_open_external_key_id; -} mbedtls_psa_stats_t; - -/** \brief Get statistics about - * resource consumption related to the PSA keystore. - * - * \note When Mbed Crypto is built as part of a service, with isolation - * between the application and the keystore, the service may or - * may not expose this function. - */ -void mbedtls_psa_get_stats( mbedtls_psa_stats_t *stats ); - -/** - * \brief Inject an initial entropy seed for the random generator into - * secure storage. - * - * This function injects data to be used as a seed for the random generator - * used by the PSA Crypto implementation. On devices that lack a trusted - * entropy source (preferably a hardware random number generator), - * the Mbed PSA Crypto implementation uses this value to seed its - * random generator. - * - * On devices without a trusted entropy source, this function must be - * called exactly once in the lifetime of the device. On devices with - * a trusted entropy source, calling this function is optional. - * In all cases, this function may only be called before calling any - * other function in the PSA Crypto API, including psa_crypto_init(). - * - * When this function returns successfully, it populates a file in - * persistent storage. Once the file has been created, this function - * can no longer succeed. - * - * If any error occurs, this function does not change the system state. - * You can call this function again after correcting the reason for the - * error if possible. - * - * \warning This function **can** fail! Callers MUST check the return status. - * - * \warning If you use this function, you should use it as part of a - * factory provisioning process. The value of the injected seed - * is critical to the security of the device. It must be - * *secret*, *unpredictable* and (statistically) *unique per device*. - * You should be generate it randomly using a cryptographically - * secure random generator seeded from trusted entropy sources. - * You should transmit it securely to the device and ensure - * that its value is not leaked or stored anywhere beyond the - * needs of transmitting it from the point of generation to - * the call of this function, and erase all copies of the value - * once this function returns. - * - * This is an Mbed TLS extension. - * - * \note This function is only available on the following platforms: - * * If the compile-time option MBEDTLS_PSA_INJECT_ENTROPY is enabled. - * Note that you must provide compatible implementations of - * mbedtls_nv_seed_read and mbedtls_nv_seed_write. - * * In a client-server integration of PSA Cryptography, on the client side, - * if the server supports this feature. - * \param[in] seed Buffer containing the seed value to inject. - * \param[in] seed_size Size of the \p seed buffer. - * The size of the seed in bytes must be greater - * or equal to both #MBEDTLS_ENTROPY_MIN_PLATFORM - * and #MBEDTLS_ENTROPY_BLOCK_SIZE. - * It must be less or equal to - * #MBEDTLS_ENTROPY_MAX_SEED_SIZE. - * - * \retval #PSA_SUCCESS - * The seed value was injected successfully. The random generator - * of the PSA Crypto implementation is now ready for use. - * You may now call psa_crypto_init() and use the PSA Crypto - * implementation. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p seed_size is out of range. - * \retval #PSA_ERROR_STORAGE_FAILURE - * There was a failure reading or writing from storage. - * \retval #PSA_ERROR_NOT_PERMITTED - * The library has already been initialized. It is no longer - * possible to call this function. - */ -psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed, - size_t seed_size); - -/** \addtogroup crypto_types - * @{ - */ - -/** DSA public key. - * - * The import and export format is the - * representation of the public key `y = g^x mod p` as a big-endian byte - * string. The length of the byte string is the length of the base prime `p` - * in bytes. - */ -#define PSA_KEY_TYPE_DSA_PUBLIC_KEY ((psa_key_type_t)0x4002) - -/** DSA key pair (private and public key). - * - * The import and export format is the - * representation of the private key `x` as a big-endian byte string. The - * length of the byte string is the private key size in bytes (leading zeroes - * are not stripped). - * - * Determinstic DSA key derivation with psa_generate_derived_key follows - * FIPS 186-4 §B.1.2: interpret the byte string as integer - * in big-endian order. Discard it if it is not in the range - * [0, *N* - 2] where *N* is the boundary of the private key domain - * (the prime *p* for Diffie-Hellman, the subprime *q* for DSA, - * or the order of the curve's base point for ECC). - * Add 1 to the resulting integer and use this as the private key *x*. - * - */ -#define PSA_KEY_TYPE_DSA_KEY_PAIR ((psa_key_type_t)0x7002) - -/** Whether a key type is an DSA key (pair or public-only). */ -#define PSA_KEY_TYPE_IS_DSA(type) \ - (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY) - -#define PSA_ALG_DSA_BASE ((psa_algorithm_t)0x10040000) -/** DSA signature with hashing. - * - * This is the signature scheme defined by FIPS 186-4, - * with a random per-message secret number (*k*). - * - * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true). - * This includes #PSA_ALG_ANY_HASH - * when specifying the algorithm in a usage policy. - * - * \return The corresponding DSA signature algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_DSA(hash_alg) \ - (PSA_ALG_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) -#define PSA_ALG_DETERMINISTIC_DSA_BASE ((psa_algorithm_t)0x10050000) -#define PSA_ALG_DSA_DETERMINISTIC_FLAG PSA_ALG_ECDSA_DETERMINISTIC_FLAG -/** Deterministic DSA signature with hashing. - * - * This is the deterministic variant defined by RFC 6979 of - * the signature scheme defined by FIPS 186-4. - * - * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true). - * This includes #PSA_ALG_ANY_HASH - * when specifying the algorithm in a usage policy. - * - * \return The corresponding DSA signature algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_DETERMINISTIC_DSA(hash_alg) \ - (PSA_ALG_DETERMINISTIC_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) -#define PSA_ALG_IS_DSA(alg) \ - (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_DSA_DETERMINISTIC_FLAG) == \ - PSA_ALG_DSA_BASE) -#define PSA_ALG_DSA_IS_DETERMINISTIC(alg) \ - (((alg) & PSA_ALG_DSA_DETERMINISTIC_FLAG) != 0) -#define PSA_ALG_IS_DETERMINISTIC_DSA(alg) \ - (PSA_ALG_IS_DSA(alg) && PSA_ALG_DSA_IS_DETERMINISTIC(alg)) -#define PSA_ALG_IS_RANDOMIZED_DSA(alg) \ - (PSA_ALG_IS_DSA(alg) && !PSA_ALG_DSA_IS_DETERMINISTIC(alg)) - - -/* We need to expand the sample definition of this macro from - * the API definition. */ -#undef PSA_ALG_IS_HASH_AND_SIGN -#define PSA_ALG_IS_HASH_AND_SIGN(alg) \ - (PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || \ - PSA_ALG_IS_DSA(alg) || PSA_ALG_IS_ECDSA(alg)) - -/**@}*/ - -/** \addtogroup attributes - * @{ - */ - -/** Custom Diffie-Hellman group. - * - * For keys of type #PSA_KEY_TYPE_DH_PUBLIC_KEY(#PSA_DH_GROUP_CUSTOM) or - * #PSA_KEY_TYPE_DH_KEY_PAIR(#PSA_DH_GROUP_CUSTOM), the group data comes - * from domain parameters set by psa_set_key_domain_parameters(). - */ -#define PSA_DH_GROUP_CUSTOM ((psa_dh_group_t) 0x7e) - - -/** - * \brief Set domain parameters for a key. - * - * Some key types require additional domain parameters in addition to - * the key type identifier and the key size. Use this function instead - * of psa_set_key_type() when you need to specify domain parameters. - * - * The format for the required domain parameters varies based on the key type. - * - * - For RSA keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY or #PSA_KEY_TYPE_RSA_KEY_PAIR), - * the domain parameter data consists of the public exponent, - * represented as a big-endian integer with no leading zeros. - * This information is used when generating an RSA key pair. - * When importing a key, the public exponent is read from the imported - * key data and the exponent recorded in the attribute structure is ignored. - * As an exception, the public exponent 65537 is represented by an empty - * byte string. - * - For DSA keys (#PSA_KEY_TYPE_DSA_PUBLIC_KEY or #PSA_KEY_TYPE_DSA_KEY_PAIR), - * the `Dss-Parms` format as defined by RFC 3279 §2.3.2. - * ``` - * Dss-Parms ::= SEQUENCE { - * p INTEGER, - * q INTEGER, - * g INTEGER - * } - * ``` - * - For Diffie-Hellman key exchange keys - * (#PSA_KEY_TYPE_DH_PUBLIC_KEY(#PSA_DH_GROUP_CUSTOM) or - * #PSA_KEY_TYPE_DH_KEY_PAIR(#PSA_DH_GROUP_CUSTOM)), the - * `DomainParameters` format as defined by RFC 3279 §2.3.3. - * ``` - * DomainParameters ::= SEQUENCE { - * p INTEGER, -- odd prime, p=jq +1 - * g INTEGER, -- generator, g - * q INTEGER, -- factor of p-1 - * j INTEGER OPTIONAL, -- subgroup factor - * validationParms ValidationParms OPTIONAL - * } - * ValidationParms ::= SEQUENCE { - * seed BIT STRING, - * pgenCounter INTEGER - * } - * ``` - * - * \note This function may allocate memory or other resources. - * Once you have called this function on an attribute structure, - * you must call psa_reset_key_attributes() to free these resources. - * - * \note This is an experimental extension to the interface. It may change - * in future versions of the library. - * - * \param[in,out] attributes Attribute structure where the specified domain - * parameters will be stored. - * If this function fails, the content of - * \p attributes is not modified. - * \param type Key type (a \c PSA_KEY_TYPE_XXX value). - * \param[in] data Buffer containing the key domain parameters. - * The content of this buffer is interpreted - * according to \p type as described above. - * \param data_length Size of the \p data buffer in bytes. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - */ -psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes, - psa_key_type_t type, - const uint8_t *data, - size_t data_length); - -/** - * \brief Get domain parameters for a key. - * - * Get the domain parameters for a key with this function, if any. The format - * of the domain parameters written to \p data is specified in the - * documentation for psa_set_key_domain_parameters(). - * - * \note This is an experimental extension to the interface. It may change - * in future versions of the library. - * - * \param[in] attributes The key attribute structure to query. - * \param[out] data On success, the key domain parameters. - * \param data_size Size of the \p data buffer in bytes. - * The buffer is guaranteed to be large - * enough if its size in bytes is at least - * the value given by - * PSA_KEY_DOMAIN_PARAMETERS_SIZE(). - * \param[out] data_length On success, the number of bytes - * that make up the key domain parameters data. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - */ -psa_status_t psa_get_key_domain_parameters( - const psa_key_attributes_t *attributes, - uint8_t *data, - size_t data_size, - size_t *data_length); - -/** Safe output buffer size for psa_get_key_domain_parameters(). - * - * This macro returns a compile-time constant if its arguments are - * compile-time constants. - * - * \warning This function may call its arguments multiple times or - * zero times, so you should not pass arguments that contain - * side effects. - * - * \note This is an experimental extension to the interface. It may change - * in future versions of the library. - * - * \param key_type A supported key type. - * \param key_bits The size of the key in bits. - * - * \return If the parameters are valid and supported, return - * a buffer size in bytes that guarantees that - * psa_get_key_domain_parameters() will not fail with - * #PSA_ERROR_BUFFER_TOO_SMALL. - * If the parameters are a valid combination that is not supported - * by the implementation, this macro shall return either a - * sensible size or 0. - * If the parameters are not valid, the - * return value is unspecified. - */ -#define PSA_KEY_DOMAIN_PARAMETERS_SIZE(key_type, key_bits) \ - (PSA_KEY_TYPE_IS_RSA(key_type) ? sizeof(int) : \ - PSA_KEY_TYPE_IS_DH(key_type) ? PSA_DH_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) : \ - PSA_KEY_TYPE_IS_DSA(key_type) ? PSA_DSA_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) : \ - 0) -#define PSA_DH_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) \ - (4 + (PSA_BITS_TO_BYTES(key_bits) + 5) * 3 /*without optional parts*/) -#define PSA_DSA_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) \ - (4 + (PSA_BITS_TO_BYTES(key_bits) + 5) * 2 /*p, g*/ + 34 /*q*/) - -/**@}*/ - -/** \defgroup psa_tls_helpers TLS helper functions - * @{ - */ - -#if defined(MBEDTLS_ECP_C) -#include - -/** Convert an ECC curve identifier from the Mbed TLS encoding to PSA. - * - * \note This function is provided solely for the convenience of - * Mbed TLS and may be removed at any time without notice. - * - * \param grpid An Mbed TLS elliptic curve identifier - * (`MBEDTLS_ECP_DP_xxx`). - * \param[out] bits On success, the bit size of the curve. - * - * \return The corresponding PSA elliptic curve identifier - * (`PSA_ECC_CURVE_xxx`). - * \return \c 0 on failure (\p grpid is not recognized). - */ -static inline psa_ecc_curve_t mbedtls_ecc_group_to_psa( mbedtls_ecp_group_id grpid, - size_t *bits ) -{ - switch( grpid ) - { - case MBEDTLS_ECP_DP_SECP192R1: - *bits = 192; - return( PSA_ECC_CURVE_SECP_R1 ); - case MBEDTLS_ECP_DP_SECP224R1: - *bits = 224; - return( PSA_ECC_CURVE_SECP_R1 ); - case MBEDTLS_ECP_DP_SECP256R1: - *bits = 256; - return( PSA_ECC_CURVE_SECP_R1 ); - case MBEDTLS_ECP_DP_SECP384R1: - *bits = 384; - return( PSA_ECC_CURVE_SECP_R1 ); - case MBEDTLS_ECP_DP_SECP521R1: - *bits = 521; - return( PSA_ECC_CURVE_SECP_R1 ); - case MBEDTLS_ECP_DP_BP256R1: - *bits = 256; - return( PSA_ECC_CURVE_BRAINPOOL_P_R1 ); - case MBEDTLS_ECP_DP_BP384R1: - *bits = 384; - return( PSA_ECC_CURVE_BRAINPOOL_P_R1 ); - case MBEDTLS_ECP_DP_BP512R1: - *bits = 512; - return( PSA_ECC_CURVE_BRAINPOOL_P_R1 ); - case MBEDTLS_ECP_DP_CURVE25519: - *bits = 255; - return( PSA_ECC_CURVE_MONTGOMERY ); - case MBEDTLS_ECP_DP_SECP192K1: - *bits = 192; - return( PSA_ECC_CURVE_SECP_K1 ); - case MBEDTLS_ECP_DP_SECP224K1: - *bits = 224; - return( PSA_ECC_CURVE_SECP_K1 ); - case MBEDTLS_ECP_DP_SECP256K1: - *bits = 256; - return( PSA_ECC_CURVE_SECP_K1 ); - case MBEDTLS_ECP_DP_CURVE448: - *bits = 448; - return( PSA_ECC_CURVE_MONTGOMERY ); - default: - return( 0 ); - } -} - -/** Convert an ECC curve identifier from the PSA encoding to Mbed TLS. - * - * \note This function is provided solely for the convenience of - * Mbed TLS and may be removed at any time without notice. - * - * \param curve A PSA elliptic curve identifier - * (`PSA_ECC_CURVE_xxx`). - * \param byte_length The byte-length of a private key on \p curve. - * - * \return The corresponding Mbed TLS elliptic curve identifier - * (`MBEDTLS_ECP_DP_xxx`). - * \return #MBEDTLS_ECP_DP_NONE if \c curve is not recognized. - * \return #MBEDTLS_ECP_DP_NONE if \p byte_length is not - * correct for \p curve. - */ -mbedtls_ecp_group_id mbedtls_ecc_group_of_psa( psa_ecc_curve_t curve, - size_t byte_length ); -#endif /* MBEDTLS_ECP_C */ - -/**@}*/ - -#ifdef __cplusplus -} -#endif - -#endif /* PSA_CRYPTO_EXTRA_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_platform.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_platform.h deleted file mode 100644 index d85a719..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_platform.h +++ /dev/null @@ -1,102 +0,0 @@ -/** - * \file psa/crypto_platform.h - * - * \brief PSA cryptography module: Mbed TLS platform definitions - * - * \note This file may not be included directly. Applications must - * include psa/crypto.h. - * - * This file contains platform-dependent type definitions. - * - * In implementations with isolation between the application and the - * cryptography module, implementers should take care to ensure that - * the definitions that are exposed to applications match what the - * module implements. - */ -/* - * Copyright (C) 2018, ARM Limited, 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. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#ifndef PSA_CRYPTO_PLATFORM_H -#define PSA_CRYPTO_PLATFORM_H - -/* Include the Mbed TLS configuration file, the way Mbed TLS does it - * in each of its header files. */ -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -/* PSA requires several types which C99 provides in stdint.h. */ -#include - -/* Integral type representing a key handle. */ -typedef uint16_t psa_key_handle_t; - -/* This implementation distinguishes *application key identifiers*, which - * are the key identifiers specified by the application, from - * *key file identifiers*, which are the key identifiers that the library - * sees internally. The two types can be different if there is a remote - * call layer between the application and the library which supports - * multiple client applications that do not have access to each others' - * keys. The point of having different types is that the key file - * identifier may encode not only the key identifier specified by the - * application, but also the the identity of the application. - * - * Note that this is an internal concept of the library and the remote - * call layer. The application itself never sees anything other than - * #psa_app_key_id_t with its standard definition. - */ - -/* The application key identifier is always what the application sees as - * #psa_key_id_t. */ -typedef uint32_t psa_app_key_id_t; - -#if defined(MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER) - -#if defined(PSA_CRYPTO_SECURE) -/* Building for the PSA Crypto service on a PSA platform. */ -/* A key owner is a PSA partition identifier. */ -typedef int32_t psa_key_owner_id_t; -#endif - -typedef struct -{ - uint32_t key_id; - psa_key_owner_id_t owner; -} psa_key_file_id_t; -#define PSA_KEY_FILE_GET_KEY_ID( file_id ) ( ( file_id ).key_id ) - -/* Since crypto.h is used as part of the PSA Cryptography API specification, - * it must use standard types for things like the argument of psa_open_key(). - * If it wasn't for that constraint, psa_open_key() would take a - * `psa_key_file_id_t` argument. As a workaround, make `psa_key_id_t` an - * alias for `psa_key_file_id_t` when building for a multi-client service. */ -typedef psa_key_file_id_t psa_key_id_t; -#define PSA_KEY_ID_INIT {0, 0} - -#else /* !MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER */ - -/* By default, a key file identifier is just the application key identifier. */ -typedef psa_app_key_id_t psa_key_file_id_t; -#define PSA_KEY_FILE_GET_KEY_ID( id ) ( id ) - -#endif /* !MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER */ - -#endif /* PSA_CRYPTO_PLATFORM_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_se_driver.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_se_driver.h deleted file mode 100644 index 7ac1ed1..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_se_driver.h +++ /dev/null @@ -1,1388 +0,0 @@ -/** - * \file psa/crypto_se_driver.h - * \brief PSA external cryptoprocessor driver module - * - * This header declares types and function signatures for cryptography - * drivers that access key material via opaque references. - * This is meant for cryptoprocessors that have a separate key storage from the - * space in which the PSA Crypto implementation runs, typically secure - * elements (SEs). - * - * This file is part of the PSA Crypto Driver HAL (hardware abstraction layer), - * containing functions for driver developers to implement to enable hardware - * to be called in a standardized way by a PSA Cryptography API - * implementation. The functions comprising the driver HAL, which driver - * authors implement, are not intended to be called by application developers. - */ - -/* - * Copyright (C) 2018, ARM Limited, 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 PSA_CRYPTO_SE_DRIVER_H -#define PSA_CRYPTO_SE_DRIVER_H - -#include "crypto_driver_common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** \defgroup se_init Secure element driver initialization - */ -/**@{*/ - -/** \brief Driver context structure - * - * Driver functions receive a pointer to this structure. - * Each registered driver has one instance of this structure. - * - * Implementations must include the fields specified here and - * may include other fields. - */ -typedef struct { - /** A read-only pointer to the driver's persistent data. - * - * Drivers typically use this persistent data to keep track of - * which slot numbers are available. This is only a guideline: - * drivers may use the persistent data for any purpose, keeping - * in mind the restrictions on when the persistent data is saved - * to storage: the persistent data is only saved after calling - * certain functions that receive a writable pointer to the - * persistent data. - * - * The core allocates a memory buffer for the persistent data. - * The pointer is guaranteed to be suitably aligned for any data type, - * like a pointer returned by `malloc` (but the core can use any - * method to allocate the buffer, not necessarily `malloc`). - * - * The size of this buffer is in the \c persistent_data_size field of - * this structure. - * - * Before the driver is initialized for the first time, the content of - * the persistent data is all-bits-zero. After a driver upgrade, if the - * size of the persistent data has increased, the original data is padded - * on the right with zeros; if the size has decreased, the original data - * is truncated to the new size. - * - * This pointer is to read-only data. Only a few driver functions are - * allowed to modify the persistent data. These functions receive a - * writable pointer. These functions are: - * - psa_drv_se_t::p_init - * - psa_drv_se_key_management_t::p_allocate - * - psa_drv_se_key_management_t::p_destroy - * - * The PSA Cryptography core saves the persistent data from one - * session to the next. It does this before returning from API functions - * that call a driver method that is allowed to modify the persistent - * data, specifically: - * - psa_crypto_init() causes a call to psa_drv_se_t::p_init, and may call - * psa_drv_se_key_management_t::p_destroy to complete an action - * that was interrupted by a power failure. - * - Key creation functions cause a call to - * psa_drv_se_key_management_t::p_allocate, and may cause a call to - * psa_drv_se_key_management_t::p_destroy in case an error occurs. - * - psa_destroy_key() causes a call to - * psa_drv_se_key_management_t::p_destroy. - */ - const void *const persistent_data; - - /** The size of \c persistent_data in bytes. - * - * This is always equal to the value of the `persistent_data_size` field - * of the ::psa_drv_se_t structure when the driver is registered. - */ - const size_t persistent_data_size; - - /** Driver transient data. - * - * The core initializes this value to 0 and does not read or modify it - * afterwards. The driver may store whatever it wants in this field. - */ - uintptr_t transient_data; -} psa_drv_se_context_t; - -/** \brief A driver initialization function. - * - * \param[in,out] drv_context The driver context structure. - * \param[in,out] persistent_data A pointer to the persistent data - * that allows writing. - * \param lifetime The lifetime value for which this driver - * is registered. - * - * \retval #PSA_SUCCESS - * The driver is operational. - * The core will update the persistent data in storage. - * \return - * Any other return value prevents the driver from being used in - * this session. - * The core will NOT update the persistent data in storage. - */ -typedef psa_status_t (*psa_drv_se_init_t)(psa_drv_se_context_t *drv_context, - void *persistent_data, - psa_key_lifetime_t lifetime); - -#if defined(__DOXYGEN_ONLY__) || !defined(MBEDTLS_PSA_CRYPTO_SE_C) -/* Mbed Crypto with secure element support enabled defines this type in - * crypto_types.h because it is also visible to applications through an - * implementation-specific extension. - * For the PSA Cryptography specification, this type is only visible - * via crypto_se_driver.h. */ -/** An internal designation of a key slot between the core part of the - * PSA Crypto implementation and the driver. The meaning of this value - * is driver-dependent. */ -typedef uint64_t psa_key_slot_number_t; -#endif /* __DOXYGEN_ONLY__ || !MBEDTLS_PSA_CRYPTO_SE_C */ - -/**@}*/ - -/** \defgroup se_mac Secure Element Message Authentication Codes - * Generation and authentication of Message Authentication Codes (MACs) using - * a secure element can be done either as a single function call (via the - * `psa_drv_se_mac_generate_t` or `psa_drv_se_mac_verify_t` functions), or in - * parts using the following sequence: - * - `psa_drv_se_mac_setup_t` - * - `psa_drv_se_mac_update_t` - * - `psa_drv_se_mac_update_t` - * - ... - * - `psa_drv_se_mac_finish_t` or `psa_drv_se_mac_finish_verify_t` - * - * If a previously started secure element MAC operation needs to be terminated, - * it should be done so by the `psa_drv_se_mac_abort_t`. Failure to do so may - * result in allocated resources not being freed or in other undefined - * behavior. - */ -/**@{*/ -/** \brief A function that starts a secure element MAC operation for a PSA - * Crypto Driver implementation - * - * \param[in,out] drv_context The driver context structure. - * \param[in,out] op_context A structure that will contain the - * hardware-specific MAC context - * \param[in] key_slot The slot of the key to be used for the - * operation - * \param[in] algorithm The algorithm to be used to underly the MAC - * operation - * - * \retval PSA_SUCCESS - * Success. - */ -typedef psa_status_t (*psa_drv_se_mac_setup_t)(psa_drv_se_context_t *drv_context, - void *op_context, - psa_key_slot_number_t key_slot, - psa_algorithm_t algorithm); - -/** \brief A function that continues a previously started secure element MAC - * operation - * - * \param[in,out] op_context A hardware-specific structure for the - * previously-established MAC operation to be - * updated - * \param[in] p_input A buffer containing the message to be appended - * to the MAC operation - * \param[in] input_length The size in bytes of the input message buffer - */ -typedef psa_status_t (*psa_drv_se_mac_update_t)(void *op_context, - const uint8_t *p_input, - size_t input_length); - -/** \brief a function that completes a previously started secure element MAC - * operation by returning the resulting MAC. - * - * \param[in,out] op_context A hardware-specific structure for the - * previously started MAC operation to be - * finished - * \param[out] p_mac A buffer where the generated MAC will be - * placed - * \param[in] mac_size The size in bytes of the buffer that has been - * allocated for the `output` buffer - * \param[out] p_mac_length After completion, will contain the number of - * bytes placed in the `p_mac` buffer - * - * \retval PSA_SUCCESS - * Success. - */ -typedef psa_status_t (*psa_drv_se_mac_finish_t)(void *op_context, - uint8_t *p_mac, - size_t mac_size, - size_t *p_mac_length); - -/** \brief A function that completes a previously started secure element MAC - * operation by comparing the resulting MAC against a provided value - * - * \param[in,out] op_context A hardware-specific structure for the previously - * started MAC operation to be fiinished - * \param[in] p_mac The MAC value against which the resulting MAC - * will be compared against - * \param[in] mac_length The size in bytes of the value stored in `p_mac` - * - * \retval PSA_SUCCESS - * The operation completed successfully and the MACs matched each - * other - * \retval PSA_ERROR_INVALID_SIGNATURE - * The operation completed successfully, but the calculated MAC did - * not match the provided MAC - */ -typedef psa_status_t (*psa_drv_se_mac_finish_verify_t)(void *op_context, - const uint8_t *p_mac, - size_t mac_length); - -/** \brief A function that aborts a previous started secure element MAC - * operation - * - * \param[in,out] op_context A hardware-specific structure for the previously - * started MAC operation to be aborted - */ -typedef psa_status_t (*psa_drv_se_mac_abort_t)(void *op_context); - -/** \brief A function that performs a secure element MAC operation in one - * command and returns the calculated MAC - * - * \param[in,out] drv_context The driver context structure. - * \param[in] p_input A buffer containing the message to be MACed - * \param[in] input_length The size in bytes of `p_input` - * \param[in] key_slot The slot of the key to be used - * \param[in] alg The algorithm to be used to underlie the MAC - * operation - * \param[out] p_mac A buffer where the generated MAC will be - * placed - * \param[in] mac_size The size in bytes of the `p_mac` buffer - * \param[out] p_mac_length After completion, will contain the number of - * bytes placed in the `output` buffer - * - * \retval PSA_SUCCESS - * Success. - */ -typedef psa_status_t (*psa_drv_se_mac_generate_t)(psa_drv_se_context_t *drv_context, - const uint8_t *p_input, - size_t input_length, - psa_key_slot_number_t key_slot, - psa_algorithm_t alg, - uint8_t *p_mac, - size_t mac_size, - size_t *p_mac_length); - -/** \brief A function that performs a secure element MAC operation in one - * command and compares the resulting MAC against a provided value - * - * \param[in,out] drv_context The driver context structure. - * \param[in] p_input A buffer containing the message to be MACed - * \param[in] input_length The size in bytes of `input` - * \param[in] key_slot The slot of the key to be used - * \param[in] alg The algorithm to be used to underlie the MAC - * operation - * \param[in] p_mac The MAC value against which the resulting MAC will - * be compared against - * \param[in] mac_length The size in bytes of `mac` - * - * \retval PSA_SUCCESS - * The operation completed successfully and the MACs matched each - * other - * \retval PSA_ERROR_INVALID_SIGNATURE - * The operation completed successfully, but the calculated MAC did - * not match the provided MAC - */ -typedef psa_status_t (*psa_drv_se_mac_verify_t)(psa_drv_se_context_t *drv_context, - const uint8_t *p_input, - size_t input_length, - psa_key_slot_number_t key_slot, - psa_algorithm_t alg, - const uint8_t *p_mac, - size_t mac_length); - -/** \brief A struct containing all of the function pointers needed to - * perform secure element MAC operations - * - * PSA Crypto API implementations should populate the table as appropriate - * upon startup. - * - * If one of the functions is not implemented (such as - * `psa_drv_se_mac_generate_t`), it should be set to NULL. - * - * Driver implementers should ensure that they implement all of the functions - * that make sense for their hardware, and that they provide a full solution - * (for example, if they support `p_setup`, they should also support - * `p_update` and at least one of `p_finish` or `p_finish_verify`). - * - */ -typedef struct { - /**The size in bytes of the hardware-specific secure element MAC context - * structure - */ - size_t context_size; - /** Function that performs a MAC setup operation - */ - psa_drv_se_mac_setup_t p_setup; - /** Function that performs a MAC update operation - */ - psa_drv_se_mac_update_t p_update; - /** Function that completes a MAC operation - */ - psa_drv_se_mac_finish_t p_finish; - /** Function that completes a MAC operation with a verify check - */ - psa_drv_se_mac_finish_verify_t p_finish_verify; - /** Function that aborts a previoustly started MAC operation - */ - psa_drv_se_mac_abort_t p_abort; - /** Function that performs a MAC operation in one call - */ - psa_drv_se_mac_generate_t p_mac; - /** Function that performs a MAC and verify operation in one call - */ - psa_drv_se_mac_verify_t p_mac_verify; -} psa_drv_se_mac_t; -/**@}*/ - -/** \defgroup se_cipher Secure Element Symmetric Ciphers - * - * Encryption and Decryption using secure element keys in block modes other - * than ECB must be done in multiple parts, using the following flow: - * - `psa_drv_se_cipher_setup_t` - * - `psa_drv_se_cipher_set_iv_t` (optional depending upon block mode) - * - `psa_drv_se_cipher_update_t` - * - `psa_drv_se_cipher_update_t` - * - ... - * - `psa_drv_se_cipher_finish_t` - * - * If a previously started secure element Cipher operation needs to be - * terminated, it should be done so by the `psa_drv_se_cipher_abort_t`. Failure - * to do so may result in allocated resources not being freed or in other - * undefined behavior. - * - * In situations where a PSA Cryptographic API implementation is using a block - * mode not-supported by the underlying hardware or driver, it can construct - * the block mode itself, while calling the `psa_drv_se_cipher_ecb_t` function - * for the cipher operations. - */ -/**@{*/ - -/** \brief A function that provides the cipher setup function for a - * secure element driver - * - * \param[in,out] drv_context The driver context structure. - * \param[in,out] op_context A structure that will contain the - * hardware-specific cipher context. - * \param[in] key_slot The slot of the key to be used for the - * operation - * \param[in] algorithm The algorithm to be used in the cipher - * operation - * \param[in] direction Indicates whether the operation is an encrypt - * or decrypt - * - * \retval PSA_SUCCESS - * \retval PSA_ERROR_NOT_SUPPORTED - */ -typedef psa_status_t (*psa_drv_se_cipher_setup_t)(psa_drv_se_context_t *drv_context, - void *op_context, - psa_key_slot_number_t key_slot, - psa_algorithm_t algorithm, - psa_encrypt_or_decrypt_t direction); - -/** \brief A function that sets the initialization vector (if - * necessary) for an secure element cipher operation - * - * Rationale: The `psa_se_cipher_*` operation in the PSA Cryptographic API has - * two IV functions: one to set the IV, and one to generate it internally. The - * generate function is not necessary for the drivers to implement as the PSA - * Crypto implementation can do the generation using its RNG features. - * - * \param[in,out] op_context A structure that contains the previously set up - * hardware-specific cipher context - * \param[in] p_iv A buffer containing the initialization vector - * \param[in] iv_length The size (in bytes) of the `p_iv` buffer - * - * \retval PSA_SUCCESS - */ -typedef psa_status_t (*psa_drv_se_cipher_set_iv_t)(void *op_context, - const uint8_t *p_iv, - size_t iv_length); - -/** \brief A function that continues a previously started secure element cipher - * operation - * - * \param[in,out] op_context A hardware-specific structure for the - * previously started cipher operation - * \param[in] p_input A buffer containing the data to be - * encrypted/decrypted - * \param[in] input_size The size in bytes of the buffer pointed to - * by `p_input` - * \param[out] p_output The caller-allocated buffer where the - * output will be placed - * \param[in] output_size The allocated size in bytes of the - * `p_output` buffer - * \param[out] p_output_length After completion, will contain the number - * of bytes placed in the `p_output` buffer - * - * \retval PSA_SUCCESS - */ -typedef psa_status_t (*psa_drv_se_cipher_update_t)(void *op_context, - const uint8_t *p_input, - size_t input_size, - uint8_t *p_output, - size_t output_size, - size_t *p_output_length); - -/** \brief A function that completes a previously started secure element cipher - * operation - * - * \param[in,out] op_context A hardware-specific structure for the - * previously started cipher operation - * \param[out] p_output The caller-allocated buffer where the output - * will be placed - * \param[in] output_size The allocated size in bytes of the `p_output` - * buffer - * \param[out] p_output_length After completion, will contain the number of - * bytes placed in the `p_output` buffer - * - * \retval PSA_SUCCESS - */ -typedef psa_status_t (*psa_drv_se_cipher_finish_t)(void *op_context, - uint8_t *p_output, - size_t output_size, - size_t *p_output_length); - -/** \brief A function that aborts a previously started secure element cipher - * operation - * - * \param[in,out] op_context A hardware-specific structure for the - * previously started cipher operation - */ -typedef psa_status_t (*psa_drv_se_cipher_abort_t)(void *op_context); - -/** \brief A function that performs the ECB block mode for secure element - * cipher operations - * - * Note: this function should only be used with implementations that do not - * provide a needed higher-level operation. - * - * \param[in,out] drv_context The driver context structure. - * \param[in] key_slot The slot of the key to be used for the operation - * \param[in] algorithm The algorithm to be used in the cipher operation - * \param[in] direction Indicates whether the operation is an encrypt or - * decrypt - * \param[in] p_input A buffer containing the data to be - * encrypted/decrypted - * \param[in] input_size The size in bytes of the buffer pointed to by - * `p_input` - * \param[out] p_output The caller-allocated buffer where the output - * will be placed - * \param[in] output_size The allocated size in bytes of the `p_output` - * buffer - * - * \retval PSA_SUCCESS - * \retval PSA_ERROR_NOT_SUPPORTED - */ -typedef psa_status_t (*psa_drv_se_cipher_ecb_t)(psa_drv_se_context_t *drv_context, - psa_key_slot_number_t key_slot, - psa_algorithm_t algorithm, - psa_encrypt_or_decrypt_t direction, - const uint8_t *p_input, - size_t input_size, - uint8_t *p_output, - size_t output_size); - -/** - * \brief A struct containing all of the function pointers needed to implement - * cipher operations using secure elements. - * - * PSA Crypto API implementations should populate instances of the table as - * appropriate upon startup or at build time. - * - * If one of the functions is not implemented (such as - * `psa_drv_se_cipher_ecb_t`), it should be set to NULL. - */ -typedef struct { - /** The size in bytes of the hardware-specific secure element cipher - * context structure - */ - size_t context_size; - /** Function that performs a cipher setup operation */ - psa_drv_se_cipher_setup_t p_setup; - /** Function that sets a cipher IV (if necessary) */ - psa_drv_se_cipher_set_iv_t p_set_iv; - /** Function that performs a cipher update operation */ - psa_drv_se_cipher_update_t p_update; - /** Function that completes a cipher operation */ - psa_drv_se_cipher_finish_t p_finish; - /** Function that aborts a cipher operation */ - psa_drv_se_cipher_abort_t p_abort; - /** Function that performs ECB mode for a cipher operation - * (Danger: ECB mode should not be used directly by clients of the PSA - * Crypto Client API) - */ - psa_drv_se_cipher_ecb_t p_ecb; -} psa_drv_se_cipher_t; - -/**@}*/ - -/** \defgroup se_asymmetric Secure Element Asymmetric Cryptography - * - * Since the amount of data that can (or should) be encrypted or signed using - * asymmetric keys is limited by the key size, asymmetric key operations using - * keys in a secure element must be done in single function calls. - */ -/**@{*/ - -/** - * \brief A function that signs a hash or short message with a private key in - * a secure element - * - * \param[in,out] drv_context The driver context structure. - * \param[in] key_slot Key slot of an asymmetric key pair - * \param[in] alg A signature algorithm that is compatible - * with the type of `key` - * \param[in] p_hash The hash to sign - * \param[in] hash_length Size of the `p_hash` buffer in bytes - * \param[out] p_signature Buffer where the signature is to be written - * \param[in] signature_size Size of the `p_signature` buffer in bytes - * \param[out] p_signature_length On success, the number of bytes - * that make up the returned signature value - * - * \retval PSA_SUCCESS - */ -typedef psa_status_t (*psa_drv_se_asymmetric_sign_t)(psa_drv_se_context_t *drv_context, - psa_key_slot_number_t key_slot, - psa_algorithm_t alg, - const uint8_t *p_hash, - size_t hash_length, - uint8_t *p_signature, - size_t signature_size, - size_t *p_signature_length); - -/** - * \brief A function that verifies the signature a hash or short message using - * an asymmetric public key in a secure element - * - * \param[in,out] drv_context The driver context structure. - * \param[in] key_slot Key slot of a public key or an asymmetric key - * pair - * \param[in] alg A signature algorithm that is compatible with - * the type of `key` - * \param[in] p_hash The hash whose signature is to be verified - * \param[in] hash_length Size of the `p_hash` buffer in bytes - * \param[in] p_signature Buffer containing the signature to verify - * \param[in] signature_length Size of the `p_signature` buffer in bytes - * - * \retval PSA_SUCCESS - * The signature is valid. - */ -typedef psa_status_t (*psa_drv_se_asymmetric_verify_t)(psa_drv_se_context_t *drv_context, - psa_key_slot_number_t key_slot, - psa_algorithm_t alg, - const uint8_t *p_hash, - size_t hash_length, - const uint8_t *p_signature, - size_t signature_length); - -/** - * \brief A function that encrypts a short message with an asymmetric public - * key in a secure element - * - * \param[in,out] drv_context The driver context structure. - * \param[in] key_slot Key slot of a public key or an asymmetric key - * pair - * \param[in] alg An asymmetric encryption algorithm that is - * compatible with the type of `key` - * \param[in] p_input The message to encrypt - * \param[in] input_length Size of the `p_input` buffer in bytes - * \param[in] p_salt A salt or label, if supported by the - * encryption algorithm - * If the algorithm does not support a - * salt, pass `NULL`. - * If the algorithm supports an optional - * salt and you do not want to pass a salt, - * pass `NULL`. - * For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is - * supported. - * \param[in] salt_length Size of the `p_salt` buffer in bytes - * If `p_salt` is `NULL`, pass 0. - * \param[out] p_output Buffer where the encrypted message is to - * be written - * \param[in] output_size Size of the `p_output` buffer in bytes - * \param[out] p_output_length On success, the number of bytes that make up - * the returned output - * - * \retval PSA_SUCCESS - */ -typedef psa_status_t (*psa_drv_se_asymmetric_encrypt_t)(psa_drv_se_context_t *drv_context, - psa_key_slot_number_t key_slot, - psa_algorithm_t alg, - const uint8_t *p_input, - size_t input_length, - const uint8_t *p_salt, - size_t salt_length, - uint8_t *p_output, - size_t output_size, - size_t *p_output_length); - -/** - * \brief A function that decrypts a short message with an asymmetric private - * key in a secure element. - * - * \param[in,out] drv_context The driver context structure. - * \param[in] key_slot Key slot of an asymmetric key pair - * \param[in] alg An asymmetric encryption algorithm that is - * compatible with the type of `key` - * \param[in] p_input The message to decrypt - * \param[in] input_length Size of the `p_input` buffer in bytes - * \param[in] p_salt A salt or label, if supported by the - * encryption algorithm - * If the algorithm does not support a - * salt, pass `NULL`. - * If the algorithm supports an optional - * salt and you do not want to pass a salt, - * pass `NULL`. - * For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is - * supported. - * \param[in] salt_length Size of the `p_salt` buffer in bytes - * If `p_salt` is `NULL`, pass 0. - * \param[out] p_output Buffer where the decrypted message is to - * be written - * \param[in] output_size Size of the `p_output` buffer in bytes - * \param[out] p_output_length On success, the number of bytes - * that make up the returned output - * - * \retval PSA_SUCCESS - */ -typedef psa_status_t (*psa_drv_se_asymmetric_decrypt_t)(psa_drv_se_context_t *drv_context, - psa_key_slot_number_t key_slot, - psa_algorithm_t alg, - const uint8_t *p_input, - size_t input_length, - const uint8_t *p_salt, - size_t salt_length, - uint8_t *p_output, - size_t output_size, - size_t *p_output_length); - -/** - * \brief A struct containing all of the function pointers needed to implement - * asymmetric cryptographic operations using secure elements. - * - * PSA Crypto API implementations should populate instances of the table as - * appropriate upon startup or at build time. - * - * If one of the functions is not implemented, it should be set to NULL. - */ -typedef struct { - /** Function that performs an asymmetric sign operation */ - psa_drv_se_asymmetric_sign_t p_sign; - /** Function that performs an asymmetric verify operation */ - psa_drv_se_asymmetric_verify_t p_verify; - /** Function that performs an asymmetric encrypt operation */ - psa_drv_se_asymmetric_encrypt_t p_encrypt; - /** Function that performs an asymmetric decrypt operation */ - psa_drv_se_asymmetric_decrypt_t p_decrypt; -} psa_drv_se_asymmetric_t; - -/**@}*/ - -/** \defgroup se_aead Secure Element Authenticated Encryption with Additional Data - * Authenticated Encryption with Additional Data (AEAD) operations with secure - * elements must be done in one function call. While this creates a burden for - * implementers as there must be sufficient space in memory for the entire - * message, it prevents decrypted data from being made available before the - * authentication operation is complete and the data is known to be authentic. - */ -/**@{*/ - -/** \brief A function that performs a secure element authenticated encryption - * operation - * - * \param[in,out] drv_context The driver context structure. - * \param[in] key_slot Slot containing the key to use. - * \param[in] algorithm The AEAD algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(`alg`) is true) - * \param[in] p_nonce Nonce or IV to use - * \param[in] nonce_length Size of the `p_nonce` buffer in bytes - * \param[in] p_additional_data Additional data that will be - * authenticated but not encrypted - * \param[in] additional_data_length Size of `p_additional_data` in bytes - * \param[in] p_plaintext Data that will be authenticated and - * encrypted - * \param[in] plaintext_length Size of `p_plaintext` in bytes - * \param[out] p_ciphertext Output buffer for the authenticated and - * encrypted data. The additional data is - * not part of this output. For algorithms - * where the encrypted data and the - * authentication tag are defined as - * separate outputs, the authentication - * tag is appended to the encrypted data. - * \param[in] ciphertext_size Size of the `p_ciphertext` buffer in - * bytes - * \param[out] p_ciphertext_length On success, the size of the output in - * the `p_ciphertext` buffer - * - * \retval #PSA_SUCCESS - * Success. - */ -typedef psa_status_t (*psa_drv_se_aead_encrypt_t)(psa_drv_se_context_t *drv_context, - psa_key_slot_number_t key_slot, - psa_algorithm_t algorithm, - const uint8_t *p_nonce, - size_t nonce_length, - const uint8_t *p_additional_data, - size_t additional_data_length, - const uint8_t *p_plaintext, - size_t plaintext_length, - uint8_t *p_ciphertext, - size_t ciphertext_size, - size_t *p_ciphertext_length); - -/** A function that peforms a secure element authenticated decryption operation - * - * \param[in,out] drv_context The driver context structure. - * \param[in] key_slot Slot containing the key to use - * \param[in] algorithm The AEAD algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(`alg`) is true) - * \param[in] p_nonce Nonce or IV to use - * \param[in] nonce_length Size of the `p_nonce` buffer in bytes - * \param[in] p_additional_data Additional data that has been - * authenticated but not encrypted - * \param[in] additional_data_length Size of `p_additional_data` in bytes - * \param[in] p_ciphertext Data that has been authenticated and - * encrypted. - * For algorithms where the encrypted data - * and the authentication tag are defined - * as separate inputs, the buffer must - * contain the encrypted data followed by - * the authentication tag. - * \param[in] ciphertext_length Size of `p_ciphertext` in bytes - * \param[out] p_plaintext Output buffer for the decrypted data - * \param[in] plaintext_size Size of the `p_plaintext` buffer in - * bytes - * \param[out] p_plaintext_length On success, the size of the output in - * the `p_plaintext` buffer - * - * \retval #PSA_SUCCESS - * Success. - */ -typedef psa_status_t (*psa_drv_se_aead_decrypt_t)(psa_drv_se_context_t *drv_context, - psa_key_slot_number_t key_slot, - psa_algorithm_t algorithm, - const uint8_t *p_nonce, - size_t nonce_length, - const uint8_t *p_additional_data, - size_t additional_data_length, - const uint8_t *p_ciphertext, - size_t ciphertext_length, - uint8_t *p_plaintext, - size_t plaintext_size, - size_t *p_plaintext_length); - -/** - * \brief A struct containing all of the function pointers needed to implement - * secure element Authenticated Encryption with Additional Data operations - * - * PSA Crypto API implementations should populate instances of the table as - * appropriate upon startup. - * - * If one of the functions is not implemented, it should be set to NULL. - */ -typedef struct { - /** Function that performs the AEAD encrypt operation */ - psa_drv_se_aead_encrypt_t p_encrypt; - /** Function that performs the AEAD decrypt operation */ - psa_drv_se_aead_decrypt_t p_decrypt; -} psa_drv_se_aead_t; -/**@}*/ - -/** \defgroup se_key_management Secure Element Key Management - * Currently, key management is limited to importing keys in the clear, - * destroying keys, and exporting keys in the clear. - * Whether a key may be exported is determined by the key policies in place - * on the key slot. - */ -/**@{*/ - -/** An enumeration indicating how a key is created. - */ -typedef enum -{ - PSA_KEY_CREATION_IMPORT, /**< During psa_import_key() */ - PSA_KEY_CREATION_GENERATE, /**< During psa_generate_key() */ - PSA_KEY_CREATION_DERIVE, /**< During psa_key_derivation_output_key() */ - PSA_KEY_CREATION_COPY, /**< During psa_copy_key() */ - -#ifndef __DOXYGEN_ONLY__ - /** A key is being registered with mbedtls_psa_register_se_key(). - * - * The core only passes this value to - * psa_drv_se_key_management_t::p_validate_slot_number, not to - * psa_drv_se_key_management_t::p_allocate. The call to - * `p_validate_slot_number` is not followed by any other call to the - * driver: the key is considered successfully registered if the call to - * `p_validate_slot_number` succeeds, or if `p_validate_slot_number` is - * null. - * - * With this creation method, the driver must return #PSA_SUCCESS if - * the given attributes are compatible with the existing key in the slot, - * and #PSA_ERROR_DOES_NOT_EXIST if the driver can determine that there - * is no key with the specified slot number. - * - * This is an Mbed Crypto extension. - */ - PSA_KEY_CREATION_REGISTER, -#endif -} psa_key_creation_method_t; - -/** \brief A function that allocates a slot for a key. - * - * To create a key in a specific slot in a secure element, the core - * first calls this function to determine a valid slot number, - * then calls a function to create the key material in that slot. - * In nominal conditions (that is, if no error occurs), - * the effect of a call to a key creation function in the PSA Cryptography - * API with a lifetime that places the key in a secure element is the - * following: - * -# The core calls psa_drv_se_key_management_t::p_allocate - * (or in some implementations - * psa_drv_se_key_management_t::p_validate_slot_number). The driver - * selects (or validates) a suitable slot number given the key attributes - * and the state of the secure element. - * -# The core calls a key creation function in the driver. - * - * The key creation functions in the PSA Cryptography API are: - * - psa_import_key(), which causes - * a call to `p_allocate` with \p method = #PSA_KEY_CREATION_IMPORT - * then a call to psa_drv_se_key_management_t::p_import. - * - psa_generate_key(), which causes - * a call to `p_allocate` with \p method = #PSA_KEY_CREATION_GENERATE - * then a call to psa_drv_se_key_management_t::p_import. - * - psa_key_derivation_output_key(), which causes - * a call to `p_allocate` with \p method = #PSA_KEY_CREATION_DERIVE - * then a call to psa_drv_se_key_derivation_t::p_derive. - * - psa_copy_key(), which causes - * a call to `p_allocate` with \p method = #PSA_KEY_CREATION_COPY - * then a call to psa_drv_se_key_management_t::p_export. - * - * In case of errors, other behaviors are possible. - * - If the PSA Cryptography subsystem dies after the first step, - * for example because the device has lost power abruptly, - * the second step may never happen, or may happen after a reset - * and re-initialization. Alternatively, after a reset and - * re-initialization, the core may call - * psa_drv_se_key_management_t::p_destroy on the slot number that - * was allocated (or validated) instead of calling a key creation function. - * - If an error occurs, the core may call - * psa_drv_se_key_management_t::p_destroy on the slot number that - * was allocated (or validated) instead of calling a key creation function. - * - * Errors and system resets also have an impact on the driver's persistent - * data. If a reset happens before the overall key creation process is - * completed (before or after the second step above), it is unspecified - * whether the persistent data after the reset is identical to what it - * was before or after the call to `p_allocate` (or `p_validate_slot_number`). - * - * \param[in,out] drv_context The driver context structure. - * \param[in,out] persistent_data A pointer to the persistent data - * that allows writing. - * \param[in] attributes Attributes of the key. - * \param method The way in which the key is being created. - * \param[out] key_slot Slot where the key will be stored. - * This must be a valid slot for a key of the - * chosen type. It must be unoccupied. - * - * \retval #PSA_SUCCESS - * Success. - * The core will record \c *key_slot as the key slot where the key - * is stored and will update the persistent data in storage. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_INSUFFICIENT_STORAGE - */ -typedef psa_status_t (*psa_drv_se_allocate_key_t)( - psa_drv_se_context_t *drv_context, - void *persistent_data, - const psa_key_attributes_t *attributes, - psa_key_creation_method_t method, - psa_key_slot_number_t *key_slot); - -/** \brief A function that determines whether a slot number is valid - * for a key. - * - * To create a key in a specific slot in a secure element, the core - * first calls this function to validate the choice of slot number, - * then calls a function to create the key material in that slot. - * See the documentation of #psa_drv_se_allocate_key_t for more details. - * - * As of the PSA Cryptography API specification version 1.0, there is no way - * for applications to trigger a call to this function. However some - * implementations offer the capability to create or declare a key in - * a specific slot via implementation-specific means, generally for the - * sake of initial device provisioning or onboarding. Such a mechanism may - * be added to a future version of the PSA Cryptography API specification. - * - * This function may update the driver's persistent data through - * \p persistent_data. The core will save the updated persistent data at the - * end of the key creation process. See the description of - * ::psa_drv_se_allocate_key_t for more information. - * - * \param[in,out] drv_context The driver context structure. - * \param[in,out] persistent_data A pointer to the persistent data - * that allows writing. - * \param[in] attributes Attributes of the key. - * \param method The way in which the key is being created. - * \param[in] key_slot Slot where the key is to be stored. - * - * \retval #PSA_SUCCESS - * The given slot number is valid for a key with the given - * attributes. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The given slot number is not valid for a key with the - * given attributes. This includes the case where the slot - * number is not valid at all. - * \retval #PSA_ERROR_ALREADY_EXISTS - * There is already a key with the specified slot number. - * Drivers may choose to return this error from the key - * creation function instead. - */ -typedef psa_status_t (*psa_drv_se_validate_slot_number_t)( - psa_drv_se_context_t *drv_context, - void *persistent_data, - const psa_key_attributes_t *attributes, - psa_key_creation_method_t method, - psa_key_slot_number_t key_slot); - -/** \brief A function that imports a key into a secure element in binary format - * - * This function can support any output from psa_export_key(). Refer to the - * documentation of psa_export_key() for the format for each key type. - * - * \param[in,out] drv_context The driver context structure. - * \param key_slot Slot where the key will be stored. - * This must be a valid slot for a key of the - * chosen type. It must be unoccupied. - * \param[in] attributes The key attributes, including the lifetime, - * the key type and the usage policy. - * Drivers should not access the key size stored - * in the attributes: it may not match the - * data passed in \p data. - * Drivers can call psa_get_key_lifetime(), - * psa_get_key_type(), - * psa_get_key_usage_flags() and - * psa_get_key_algorithm() to access this - * information. - * \param[in] data Buffer containing the key data. - * \param[in] data_length Size of the \p data buffer in bytes. - * \param[out] bits On success, the key size in bits. The driver - * must determine this value after parsing the - * key according to the key type. - * This value is not used if the function fails. - * - * \retval #PSA_SUCCESS - * Success. - */ -typedef psa_status_t (*psa_drv_se_import_key_t)( - psa_drv_se_context_t *drv_context, - psa_key_slot_number_t key_slot, - const psa_key_attributes_t *attributes, - const uint8_t *data, - size_t data_length, - size_t *bits); - -/** - * \brief A function that destroys a secure element key and restore the slot to - * its default state - * - * This function destroys the content of the key from a secure element. - * Implementations shall make a best effort to ensure that any previous content - * of the slot is unrecoverable. - * - * This function returns the specified slot to its default state. - * - * \param[in,out] drv_context The driver context structure. - * \param[in,out] persistent_data A pointer to the persistent data - * that allows writing. - * \param key_slot The key slot to erase. - * - * \retval #PSA_SUCCESS - * The slot's content, if any, has been erased. - */ -typedef psa_status_t (*psa_drv_se_destroy_key_t)( - psa_drv_se_context_t *drv_context, - void *persistent_data, - psa_key_slot_number_t key_slot); - -/** - * \brief A function that exports a secure element key in binary format - * - * The output of this function can be passed to psa_import_key() to - * create an equivalent object. - * - * If a key is created with `psa_import_key()` and then exported with - * this function, it is not guaranteed that the resulting data is - * identical: the implementation may choose a different representation - * of the same key if the format permits it. - * - * This function should generate output in the same format that - * `psa_export_key()` does. Refer to the - * documentation of `psa_export_key()` for the format for each key type. - * - * \param[in,out] drv_context The driver context structure. - * \param[in] key Slot whose content is to be exported. This must - * be an occupied key slot. - * \param[out] p_data Buffer where the key data is to be written. - * \param[in] data_size Size of the `p_data` buffer in bytes. - * \param[out] p_data_length On success, the number of bytes - * that make up the key data. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_DOES_NOT_EXIST - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - */ -typedef psa_status_t (*psa_drv_se_export_key_t)(psa_drv_se_context_t *drv_context, - psa_key_slot_number_t key, - uint8_t *p_data, - size_t data_size, - size_t *p_data_length); - -/** - * \brief A function that generates a symmetric or asymmetric key on a secure - * element - * - * If \p type is asymmetric (#PSA_KEY_TYPE_IS_ASYMMETRIC(\p type) = 1), - * the driver may export the public key at the time of generation, - * in the format documented for psa_export_public_key() by writing it - * to the \p pubkey buffer. - * This is optional, intended for secure elements that output the - * public key at generation time and that cannot export the public key - * later. Drivers that do not need this feature should leave - * \p *pubkey_length set to 0 and should - * implement the psa_drv_key_management_t::p_export_public function. - * Some implementations do not support this feature, in which case - * \p pubkey is \c NULL and \p pubkey_size is 0. - * - * \param[in,out] drv_context The driver context structure. - * \param key_slot Slot where the key will be stored. - * This must be a valid slot for a key of the - * chosen type. It must be unoccupied. - * \param[in] attributes The key attributes, including the lifetime, - * the key type and size, and the usage policy. - * Drivers can call psa_get_key_lifetime(), - * psa_get_key_type(), psa_get_key_bits(), - * psa_get_key_usage_flags() and - * psa_get_key_algorithm() to access this - * information. - * \param[out] pubkey A buffer where the driver can write the - * public key, when generating an asymmetric - * key pair. - * This is \c NULL when generating a symmetric - * key or if the core does not support - * exporting the public key at generation time. - * \param pubkey_size The size of the `pubkey` buffer in bytes. - * This is 0 when generating a symmetric - * key or if the core does not support - * exporting the public key at generation time. - * \param[out] pubkey_length On entry, this is always 0. - * On success, the number of bytes written to - * \p pubkey. If this is 0 or unchanged on return, - * the core will not read the \p pubkey buffer, - * and will instead call the driver's - * psa_drv_key_management_t::p_export_public - * function to export the public key when needed. - */ -typedef psa_status_t (*psa_drv_se_generate_key_t)( - psa_drv_se_context_t *drv_context, - psa_key_slot_number_t key_slot, - const psa_key_attributes_t *attributes, - uint8_t *pubkey, size_t pubkey_size, size_t *pubkey_length); - -/** - * \brief A struct containing all of the function pointers needed to for secure - * element key management - * - * PSA Crypto API implementations should populate instances of the table as - * appropriate upon startup or at build time. - * - * If one of the functions is not implemented, it should be set to NULL. - */ -typedef struct { - /** Function that allocates a slot for a key. */ - psa_drv_se_allocate_key_t p_allocate; - /** Function that checks the validity of a slot for a key. */ - psa_drv_se_validate_slot_number_t p_validate_slot_number; - /** Function that performs a key import operation */ - psa_drv_se_import_key_t p_import; - /** Function that performs a generation */ - psa_drv_se_generate_key_t p_generate; - /** Function that performs a key destroy operation */ - psa_drv_se_destroy_key_t p_destroy; - /** Function that performs a key export operation */ - psa_drv_se_export_key_t p_export; - /** Function that performs a public key export operation */ - psa_drv_se_export_key_t p_export_public; -} psa_drv_se_key_management_t; - -/**@}*/ - -/** \defgroup driver_derivation Secure Element Key Derivation and Agreement - * Key derivation is the process of generating new key material using an - * existing key and additional parameters, iterating through a basic - * cryptographic function, such as a hash. - * Key agreement is a part of cryptographic protocols that allows two parties - * to agree on the same key value, but starting from different original key - * material. - * The flows are similar, and the PSA Crypto Driver Model uses the same functions - * for both of the flows. - * - * There are two different final functions for the flows, - * `psa_drv_se_key_derivation_derive` and `psa_drv_se_key_derivation_export`. - * `psa_drv_se_key_derivation_derive` is used when the key material should be - * placed in a slot on the hardware and not exposed to the caller. - * `psa_drv_se_key_derivation_export` is used when the key material should be - * returned to the PSA Cryptographic API implementation. - * - * Different key derivation algorithms require a different number of inputs. - * Instead of having an API that takes as input variable length arrays, which - * can be problemmatic to manage on embedded platforms, the inputs are passed - * to the driver via a function, `psa_drv_se_key_derivation_collateral`, that - * is called multiple times with different `collateral_id`s. Thus, for a key - * derivation algorithm that required 3 paramter inputs, the flow would look - * something like: - * ~~~~~~~~~~~~~{.c} - * psa_drv_se_key_derivation_setup(kdf_algorithm, source_key, dest_key_size_bytes); - * psa_drv_se_key_derivation_collateral(kdf_algorithm_collateral_id_0, - * p_collateral_0, - * collateral_0_size); - * psa_drv_se_key_derivation_collateral(kdf_algorithm_collateral_id_1, - * p_collateral_1, - * collateral_1_size); - * psa_drv_se_key_derivation_collateral(kdf_algorithm_collateral_id_2, - * p_collateral_2, - * collateral_2_size); - * psa_drv_se_key_derivation_derive(); - * ~~~~~~~~~~~~~ - * - * key agreement example: - * ~~~~~~~~~~~~~{.c} - * psa_drv_se_key_derivation_setup(alg, source_key. dest_key_size_bytes); - * psa_drv_se_key_derivation_collateral(DHE_PUBKEY, p_pubkey, pubkey_size); - * psa_drv_se_key_derivation_export(p_session_key, - * session_key_size, - * &session_key_length); - * ~~~~~~~~~~~~~ - */ -/**@{*/ - -/** \brief A function that Sets up a secure element key derivation operation by - * specifying the algorithm and the source key sot - * - * \param[in,out] drv_context The driver context structure. - * \param[in,out] op_context A hardware-specific structure containing any - * context information for the implementation - * \param[in] kdf_alg The algorithm to be used for the key derivation - * \param[in] source_key The key to be used as the source material for - * the key derivation - * - * \retval PSA_SUCCESS - */ -typedef psa_status_t (*psa_drv_se_key_derivation_setup_t)(psa_drv_se_context_t *drv_context, - void *op_context, - psa_algorithm_t kdf_alg, - psa_key_slot_number_t source_key); - -/** \brief A function that provides collateral (parameters) needed for a secure - * element key derivation or key agreement operation - * - * Since many key derivation algorithms require multiple parameters, it is - * expeced that this function may be called multiple times for the same - * operation, each with a different algorithm-specific `collateral_id` - * - * \param[in,out] op_context A hardware-specific structure containing any - * context information for the implementation - * \param[in] collateral_id An ID for the collateral being provided - * \param[in] p_collateral A buffer containing the collateral data - * \param[in] collateral_size The size in bytes of the collateral - * - * \retval PSA_SUCCESS - */ -typedef psa_status_t (*psa_drv_se_key_derivation_collateral_t)(void *op_context, - uint32_t collateral_id, - const uint8_t *p_collateral, - size_t collateral_size); - -/** \brief A function that performs the final secure element key derivation - * step and place the generated key material in a slot - * - * \param[in,out] op_context A hardware-specific structure containing any - * context information for the implementation - * \param[in] dest_key The slot where the generated key material - * should be placed - * - * \retval PSA_SUCCESS - */ -typedef psa_status_t (*psa_drv_se_key_derivation_derive_t)(void *op_context, - psa_key_slot_number_t dest_key); - -/** \brief A function that performs the final step of a secure element key - * agreement and place the generated key material in a buffer - * - * \param[out] p_output Buffer in which to place the generated key - * material - * \param[in] output_size The size in bytes of `p_output` - * \param[out] p_output_length Upon success, contains the number of bytes of - * key material placed in `p_output` - * - * \retval PSA_SUCCESS - */ -typedef psa_status_t (*psa_drv_se_key_derivation_export_t)(void *op_context, - uint8_t *p_output, - size_t output_size, - size_t *p_output_length); - -/** - * \brief A struct containing all of the function pointers needed to for secure - * element key derivation and agreement - * - * PSA Crypto API implementations should populate instances of the table as - * appropriate upon startup. - * - * If one of the functions is not implemented, it should be set to NULL. - */ -typedef struct { - /** The driver-specific size of the key derivation context */ - size_t context_size; - /** Function that performs a key derivation setup */ - psa_drv_se_key_derivation_setup_t p_setup; - /** Function that sets key derivation collateral */ - psa_drv_se_key_derivation_collateral_t p_collateral; - /** Function that performs a final key derivation step */ - psa_drv_se_key_derivation_derive_t p_derive; - /** Function that perforsm a final key derivation or agreement and - * exports the key */ - psa_drv_se_key_derivation_export_t p_export; -} psa_drv_se_key_derivation_t; - -/**@}*/ - -/** \defgroup se_registration Secure element driver registration - */ -/**@{*/ - -/** A structure containing pointers to all the entry points of a - * secure element driver. - * - * Future versions of this specification may add extra substructures at - * the end of this structure. - */ -typedef struct { - /** The version of the driver HAL that this driver implements. - * This is a protection against loading driver binaries built against - * a different version of this specification. - * Use #PSA_DRV_SE_HAL_VERSION. - */ - uint32_t hal_version; - - /** The size of the driver's persistent data in bytes. - * - * This can be 0 if the driver does not need persistent data. - * - * See the documentation of psa_drv_se_context_t::persistent_data - * for more information about why and how a driver can use - * persistent data. - */ - size_t persistent_data_size; - - /** The driver initialization function. - * - * This function is called once during the initialization of the - * PSA Cryptography subsystem, before any other function of the - * driver is called. If this function returns a failure status, - * the driver will be unusable, at least until the next system reset. - * - * If this field is \c NULL, it is equivalent to a function that does - * nothing and returns #PSA_SUCCESS. - */ - psa_drv_se_init_t p_init; - - const psa_drv_se_key_management_t *key_management; - const psa_drv_se_mac_t *mac; - const psa_drv_se_cipher_t *cipher; - const psa_drv_se_aead_t *aead; - const psa_drv_se_asymmetric_t *asymmetric; - const psa_drv_se_key_derivation_t *derivation; -} psa_drv_se_t; - -/** The current version of the secure element driver HAL. - */ -/* 0.0.0 patchlevel 5 */ -#define PSA_DRV_SE_HAL_VERSION 0x00000005 - -/** Register an external cryptoprocessor (secure element) driver. - * - * This function is only intended to be used by driver code, not by - * application code. In implementations with separation between the - * PSA cryptography module and applications, this function should - * only be available to callers that run in the same memory space as - * the cryptography module, and should not be exposed to applications - * running in a different memory space. - * - * This function may be called before psa_crypto_init(). It is - * implementation-defined whether this function may be called - * after psa_crypto_init(). - * - * \note Implementations store metadata about keys including the lifetime - * value. Therefore, from one instantiation of the PSA Cryptography - * library to the next one, if there is a key in storage with a certain - * lifetime value, you must always register the same driver (or an - * updated version that communicates with the same secure element) - * with the same lifetime value. - * - * \param lifetime The lifetime value through which this driver will - * be exposed to applications. - * The values #PSA_KEY_LIFETIME_VOLATILE and - * #PSA_KEY_LIFETIME_PERSISTENT are reserved and - * may not be used for drivers. Implementations - * may reserve other values. - * \param[in] methods The method table of the driver. This structure must - * remain valid for as long as the cryptography - * module keeps running. It is typically a global - * constant. - * - * \return PSA_SUCCESS - * The driver was successfully registered. Applications can now - * use \p lifetime to access keys through the methods passed to - * this function. - * \return PSA_ERROR_BAD_STATE - * This function was called after the initialization of the - * cryptography module, and this implementation does not support - * driver registration at this stage. - * \return PSA_ERROR_ALREADY_EXISTS - * There is already a registered driver for this value of \p lifetime. - * \return PSA_ERROR_INVALID_ARGUMENT - * \p lifetime is a reserved value. - * \return PSA_ERROR_NOT_SUPPORTED - * `methods->hal_version` is not supported by this implementation. - * \return PSA_ERROR_INSUFFICIENT_MEMORY - * \return PSA_ERROR_NOT_PERMITTED - */ -psa_status_t psa_register_se_driver( - psa_key_lifetime_t lifetime, - const psa_drv_se_t *methods); - -/**@}*/ - -#ifdef __cplusplus -} -#endif - -#endif /* PSA_CRYPTO_SE_DRIVER_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_sizes.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_sizes.h deleted file mode 100644 index 1f04222..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_sizes.h +++ /dev/null @@ -1,662 +0,0 @@ -/** - * \file psa/crypto_sizes.h - * - * \brief PSA cryptography module: Mbed TLS buffer size macros - * - * \note This file may not be included directly. Applications must - * include psa/crypto.h. - * - * This file contains the definitions of macros that are useful to - * compute buffer sizes. The signatures and semantics of these macros - * are standardized, but the definitions are not, because they depend on - * the available algorithms and, in some cases, on permitted tolerances - * on buffer sizes. - * - * In implementations with isolation between the application and the - * cryptography module, implementers should take care to ensure that - * the definitions that are exposed to applications match what the - * module implements. - * - * Macros that compute sizes whose values do not depend on the - * implementation are in crypto.h. - */ -/* - * Copyright (C) 2018, ARM Limited, 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. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#ifndef PSA_CRYPTO_SIZES_H -#define PSA_CRYPTO_SIZES_H - -/* Include the Mbed TLS configuration file, the way Mbed TLS does it - * in each of its header files. */ -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#define PSA_BITS_TO_BYTES(bits) (((bits) + 7) / 8) -#define PSA_BYTES_TO_BITS(bytes) ((bytes) * 8) - -#define PSA_ROUND_UP_TO_MULTIPLE(block_size, length) \ - (((length) + (block_size) - 1) / (block_size) * (block_size)) - -/** The size of the output of psa_hash_finish(), in bytes. - * - * This is also the hash size that psa_hash_verify() expects. - * - * \param alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p alg) is true), or an HMAC algorithm - * (#PSA_ALG_HMAC(\c hash_alg) where \c hash_alg is a - * hash algorithm). - * - * \return The hash size for the specified hash algorithm. - * If the hash algorithm is not recognized, return 0. - * An implementation may return either 0 or the correct size - * for a hash algorithm that it recognizes, but does not support. - */ -#define PSA_HASH_SIZE(alg) \ - ( \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD2 ? 16 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD4 ? 16 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 16 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 20 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 20 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_224 ? 28 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_256 ? 32 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_384 ? 48 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512 ? 64 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 28 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 32 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 28 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 32 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 48 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 64 : \ - 0) - -/** \def PSA_HASH_MAX_SIZE - * - * Maximum size of a hash. - * - * This macro must expand to a compile-time constant integer. This value - * should be the maximum size of a hash supported by the implementation, - * in bytes, and must be no smaller than this maximum. - */ -/* Note: for HMAC-SHA-3, the block size is 144 bytes for HMAC-SHA3-226, - * 136 bytes for HMAC-SHA3-256, 104 bytes for SHA3-384, 72 bytes for - * HMAC-SHA3-512. */ -#if defined(MBEDTLS_SHA512_C) -#define PSA_HASH_MAX_SIZE 64 -#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 128 -#else -#define PSA_HASH_MAX_SIZE 32 -#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 64 -#endif - -/** \def PSA_MAC_MAX_SIZE - * - * Maximum size of a MAC. - * - * This macro must expand to a compile-time constant integer. This value - * should be the maximum size of a MAC supported by the implementation, - * in bytes, and must be no smaller than this maximum. - */ -/* All non-HMAC MACs have a maximum size that's smaller than the - * minimum possible value of PSA_HASH_MAX_SIZE in this implementation. */ -/* Note that the encoding of truncated MAC algorithms limits this value - * to 64 bytes. - */ -#define PSA_MAC_MAX_SIZE PSA_HASH_MAX_SIZE - -/** The tag size for an AEAD algorithm, in bytes. - * - * \param alg An AEAD algorithm - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * - * \return The tag size for the specified algorithm. - * If the AEAD algorithm does not have an identified - * tag that can be distinguished from the rest of - * the ciphertext, return 0. - * If the AEAD algorithm is not recognized, return 0. - * An implementation may return either 0 or a - * correct size for an AEAD algorithm that it - * recognizes, but does not support. - */ -#define PSA_AEAD_TAG_LENGTH(alg) \ - (PSA_ALG_IS_AEAD(alg) ? \ - (((alg) & PSA_ALG_AEAD_TAG_LENGTH_MASK) >> PSA_AEAD_TAG_LENGTH_OFFSET) : \ - 0) - -/* The maximum size of an RSA key on this implementation, in bits. - * This is a vendor-specific macro. - * - * Mbed TLS does not set a hard limit on the size of RSA keys: any key - * whose parameters fit in a bignum is accepted. However large keys can - * induce a large memory usage and long computation times. Unlike other - * auxiliary macros in this file and in crypto.h, which reflect how the - * library is configured, this macro defines how the library is - * configured. This implementation refuses to import or generate an - * RSA key whose size is larger than the value defined here. - * - * Note that an implementation may set different size limits for different - * operations, and does not need to accept all key sizes up to the limit. */ -#define PSA_VENDOR_RSA_MAX_KEY_BITS 4096 - -/* The maximum size of an ECC key on this implementation, in bits. - * This is a vendor-specific macro. */ -#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) -#define PSA_VENDOR_ECC_MAX_CURVE_BITS 521 -#elif defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) -#define PSA_VENDOR_ECC_MAX_CURVE_BITS 512 -#elif defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) -#define PSA_VENDOR_ECC_MAX_CURVE_BITS 448 -#elif defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) -#define PSA_VENDOR_ECC_MAX_CURVE_BITS 384 -#elif defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) -#define PSA_VENDOR_ECC_MAX_CURVE_BITS 384 -#elif defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) -#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256 -#elif defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) -#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256 -#elif defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) -#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256 -#elif defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) -#define PSA_VENDOR_ECC_MAX_CURVE_BITS 255 -#elif defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) -#define PSA_VENDOR_ECC_MAX_CURVE_BITS 224 -#elif defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) -#define PSA_VENDOR_ECC_MAX_CURVE_BITS 224 -#elif defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) -#define PSA_VENDOR_ECC_MAX_CURVE_BITS 192 -#elif defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) -#define PSA_VENDOR_ECC_MAX_CURVE_BITS 192 -#else -#define PSA_VENDOR_ECC_MAX_CURVE_BITS 0 -#endif - -/** \def PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN - * - * This macro returns the maximum length of the PSK supported - * by the TLS-1.2 PSK-to-MS key derivation. - * - * Quoting RFC 4279, Sect 5.3: - * TLS implementations supporting these ciphersuites MUST support - * arbitrary PSK identities up to 128 octets in length, and arbitrary - * PSKs up to 64 octets in length. Supporting longer identities and - * keys is RECOMMENDED. - * - * Therefore, no implementation should define a value smaller than 64 - * for #PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN. - */ -#define PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN 128 - -/** The maximum size of a block cipher supported by the implementation. */ -#define PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE 16 - -/** The size of the output of psa_mac_sign_finish(), in bytes. - * - * This is also the MAC size that psa_mac_verify_finish() expects. - * - * \param key_type The type of the MAC key. - * \param key_bits The size of the MAC key in bits. - * \param alg A MAC algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_MAC(\p alg) is true). - * - * \return The MAC size for the specified algorithm with - * the specified key parameters. - * \return 0 if the MAC algorithm is not recognized. - * \return Either 0 or the correct size for a MAC algorithm that - * the implementation recognizes, but does not support. - * \return Unspecified if the key parameters are not consistent - * with the algorithm. - */ -#define PSA_MAC_FINAL_SIZE(key_type, key_bits, alg) \ - ((alg) & PSA_ALG_MAC_TRUNCATION_MASK ? PSA_MAC_TRUNCATED_LENGTH(alg) : \ - PSA_ALG_IS_HMAC(alg) ? PSA_HASH_SIZE(PSA_ALG_HMAC_GET_HASH(alg)) : \ - PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) ? PSA_BLOCK_CIPHER_BLOCK_SIZE(key_type) : \ - ((void)(key_type), (void)(key_bits), 0)) - -/** The maximum size of the output of psa_aead_encrypt(), in bytes. - * - * If the size of the ciphertext buffer is at least this large, it is - * guaranteed that psa_aead_encrypt() will not fail due to an - * insufficient buffer size. Depending on the algorithm, the actual size of - * the ciphertext may be smaller. - * - * \param alg An AEAD algorithm - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * \param plaintext_length Size of the plaintext in bytes. - * - * \return The AEAD ciphertext size for the specified - * algorithm. - * If the AEAD algorithm is not recognized, return 0. - * An implementation may return either 0 or a - * correct size for an AEAD algorithm that it - * recognizes, but does not support. - */ -#define PSA_AEAD_ENCRYPT_OUTPUT_SIZE(alg, plaintext_length) \ - (PSA_AEAD_TAG_LENGTH(alg) != 0 ? \ - (plaintext_length) + PSA_AEAD_TAG_LENGTH(alg) : \ - 0) - -/** The maximum size of the output of psa_aead_decrypt(), in bytes. - * - * If the size of the plaintext buffer is at least this large, it is - * guaranteed that psa_aead_decrypt() will not fail due to an - * insufficient buffer size. Depending on the algorithm, the actual size of - * the plaintext may be smaller. - * - * \param alg An AEAD algorithm - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * \param ciphertext_length Size of the plaintext in bytes. - * - * \return The AEAD ciphertext size for the specified - * algorithm. - * If the AEAD algorithm is not recognized, return 0. - * An implementation may return either 0 or a - * correct size for an AEAD algorithm that it - * recognizes, but does not support. - */ -#define PSA_AEAD_DECRYPT_OUTPUT_SIZE(alg, ciphertext_length) \ - (PSA_AEAD_TAG_LENGTH(alg) != 0 ? \ - (ciphertext_length) - PSA_AEAD_TAG_LENGTH(alg) : \ - 0) - -/** A sufficient output buffer size for psa_aead_update(). - * - * If the size of the output buffer is at least this large, it is - * guaranteed that psa_aead_update() will not fail due to an - * insufficient buffer size. The actual size of the output may be smaller - * in any given call. - * - * \param alg An AEAD algorithm - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * \param input_length Size of the input in bytes. - * - * \return A sufficient output buffer size for the specified - * algorithm. - * If the AEAD algorithm is not recognized, return 0. - * An implementation may return either 0 or a - * correct size for an AEAD algorithm that it - * recognizes, but does not support. - */ -/* For all the AEAD modes defined in this specification, it is possible - * to emit output without delay. However, hardware may not always be - * capable of this. So for modes based on a block cipher, allow the - * implementation to delay the output until it has a full block. */ -#define PSA_AEAD_UPDATE_OUTPUT_SIZE(alg, input_length) \ - (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ - PSA_ROUND_UP_TO_MULTIPLE(PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE, (input_length)) : \ - (input_length)) - -/** A sufficient ciphertext buffer size for psa_aead_finish(). - * - * If the size of the ciphertext buffer is at least this large, it is - * guaranteed that psa_aead_finish() will not fail due to an - * insufficient ciphertext buffer size. The actual size of the output may - * be smaller in any given call. - * - * \param alg An AEAD algorithm - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * - * \return A sufficient ciphertext buffer size for the - * specified algorithm. - * If the AEAD algorithm is not recognized, return 0. - * An implementation may return either 0 or a - * correct size for an AEAD algorithm that it - * recognizes, but does not support. - */ -#define PSA_AEAD_FINISH_OUTPUT_SIZE(alg) \ - (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ - PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE : \ - 0) - -/** A sufficient plaintext buffer size for psa_aead_verify(). - * - * If the size of the plaintext buffer is at least this large, it is - * guaranteed that psa_aead_verify() will not fail due to an - * insufficient plaintext buffer size. The actual size of the output may - * be smaller in any given call. - * - * \param alg An AEAD algorithm - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * - * \return A sufficient plaintext buffer size for the - * specified algorithm. - * If the AEAD algorithm is not recognized, return 0. - * An implementation may return either 0 or a - * correct size for an AEAD algorithm that it - * recognizes, but does not support. - */ -#define PSA_AEAD_VERIFY_OUTPUT_SIZE(alg) \ - (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ - PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE : \ - 0) - -#define PSA_RSA_MINIMUM_PADDING_SIZE(alg) \ - (PSA_ALG_IS_RSA_OAEP(alg) ? \ - 2 * PSA_HASH_SIZE(PSA_ALG_RSA_OAEP_GET_HASH(alg)) + 1 : \ - 11 /*PKCS#1v1.5*/) - -/** - * \brief ECDSA signature size for a given curve bit size - * - * \param curve_bits Curve size in bits. - * \return Signature size in bytes. - * - * \note This macro returns a compile-time constant if its argument is one. - */ -#define PSA_ECDSA_SIGNATURE_SIZE(curve_bits) \ - (PSA_BITS_TO_BYTES(curve_bits) * 2) - -/** Sufficient signature buffer size for psa_sign_hash(). - * - * This macro returns a sufficient buffer size for a signature using a key - * of the specified type and size, with the specified algorithm. - * Note that the actual size of the signature may be smaller - * (some algorithms produce a variable-size signature). - * - * \warning This function may call its arguments multiple times or - * zero times, so you should not pass arguments that contain - * side effects. - * - * \param key_type An asymmetric key type (this may indifferently be a - * key pair type or a public key type). - * \param key_bits The size of the key in bits. - * \param alg The signature algorithm. - * - * \return If the parameters are valid and supported, return - * a buffer size in bytes that guarantees that - * psa_sign_hash() will not fail with - * #PSA_ERROR_BUFFER_TOO_SMALL. - * If the parameters are a valid combination that is not supported - * by the implementation, this macro shall return either a - * sensible size or 0. - * If the parameters are not valid, the - * return value is unspecified. - */ -#define PSA_SIGN_OUTPUT_SIZE(key_type, key_bits, alg) \ - (PSA_KEY_TYPE_IS_RSA(key_type) ? ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \ - PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_ECDSA_SIGNATURE_SIZE(key_bits) : \ - ((void)alg, 0)) - -#define PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE \ - PSA_ECDSA_SIGNATURE_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) - -/** \def PSA_SIGNATURE_MAX_SIZE - * - * Maximum size of an asymmetric signature. - * - * This macro must expand to a compile-time constant integer. This value - * should be the maximum size of a signature supported by the implementation, - * in bytes, and must be no smaller than this maximum. - */ -#define PSA_SIGNATURE_MAX_SIZE \ - (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) > PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE ? \ - PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) : \ - PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE) - -/** Sufficient output buffer size for psa_asymmetric_encrypt(). - * - * This macro returns a sufficient buffer size for a ciphertext produced using - * a key of the specified type and size, with the specified algorithm. - * Note that the actual size of the ciphertext may be smaller, depending - * on the algorithm. - * - * \warning This function may call its arguments multiple times or - * zero times, so you should not pass arguments that contain - * side effects. - * - * \param key_type An asymmetric key type (this may indifferently be a - * key pair type or a public key type). - * \param key_bits The size of the key in bits. - * \param alg The signature algorithm. - * - * \return If the parameters are valid and supported, return - * a buffer size in bytes that guarantees that - * psa_asymmetric_encrypt() will not fail with - * #PSA_ERROR_BUFFER_TOO_SMALL. - * If the parameters are a valid combination that is not supported - * by the implementation, this macro shall return either a - * sensible size or 0. - * If the parameters are not valid, the - * return value is unspecified. - */ -#define PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \ - (PSA_KEY_TYPE_IS_RSA(key_type) ? \ - ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \ - 0) - -/** Sufficient output buffer size for psa_asymmetric_decrypt(). - * - * This macro returns a sufficient buffer size for a ciphertext produced using - * a key of the specified type and size, with the specified algorithm. - * Note that the actual size of the ciphertext may be smaller, depending - * on the algorithm. - * - * \warning This function may call its arguments multiple times or - * zero times, so you should not pass arguments that contain - * side effects. - * - * \param key_type An asymmetric key type (this may indifferently be a - * key pair type or a public key type). - * \param key_bits The size of the key in bits. - * \param alg The signature algorithm. - * - * \return If the parameters are valid and supported, return - * a buffer size in bytes that guarantees that - * psa_asymmetric_decrypt() will not fail with - * #PSA_ERROR_BUFFER_TOO_SMALL. - * If the parameters are a valid combination that is not supported - * by the implementation, this macro shall return either a - * sensible size or 0. - * If the parameters are not valid, the - * return value is unspecified. - */ -#define PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \ - (PSA_KEY_TYPE_IS_RSA(key_type) ? \ - PSA_BITS_TO_BYTES(key_bits) - PSA_RSA_MINIMUM_PADDING_SIZE(alg) : \ - 0) - -/* Maximum size of the ASN.1 encoding of an INTEGER with the specified - * number of bits. - * - * This definition assumes that bits <= 2^19 - 9 so that the length field - * is at most 3 bytes. The length of the encoding is the length of the - * bit string padded to a whole number of bytes plus: - * - 1 type byte; - * - 1 to 3 length bytes; - * - 0 to 1 bytes of leading 0 due to the sign bit. - */ -#define PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(bits) \ - ((bits) / 8 + 5) - -/* Maximum size of the export encoding of an RSA public key. - * Assumes that the public exponent is less than 2^32. - * - * RSAPublicKey ::= SEQUENCE { - * modulus INTEGER, -- n - * publicExponent INTEGER } -- e - * - * - 4 bytes of SEQUENCE overhead; - * - n : INTEGER; - * - 7 bytes for the public exponent. - */ -#define PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) \ - (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) + 11) - -/* Maximum size of the export encoding of an RSA key pair. - * Assumes thatthe public exponent is less than 2^32 and that the size - * difference between the two primes is at most 1 bit. - * - * RSAPrivateKey ::= SEQUENCE { - * version Version, -- 0 - * modulus INTEGER, -- N-bit - * publicExponent INTEGER, -- 32-bit - * privateExponent INTEGER, -- N-bit - * prime1 INTEGER, -- N/2-bit - * prime2 INTEGER, -- N/2-bit - * exponent1 INTEGER, -- N/2-bit - * exponent2 INTEGER, -- N/2-bit - * coefficient INTEGER, -- N/2-bit - * } - * - * - 4 bytes of SEQUENCE overhead; - * - 3 bytes of version; - * - 7 half-size INTEGERs plus 2 full-size INTEGERs, - * overapproximated as 9 half-size INTEGERS; - * - 7 bytes for the public exponent. - */ -#define PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits) \ - (9 * PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE((key_bits) / 2 + 1) + 14) - -/* Maximum size of the export encoding of a DSA public key. - * - * SubjectPublicKeyInfo ::= SEQUENCE { - * algorithm AlgorithmIdentifier, - * subjectPublicKey BIT STRING } -- contains DSAPublicKey - * AlgorithmIdentifier ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters Dss-Parms } -- SEQUENCE of 3 INTEGERs - * DSAPublicKey ::= INTEGER -- public key, Y - * - * - 3 * 4 bytes of SEQUENCE overhead; - * - 1 + 1 + 7 bytes of algorithm (DSA OID); - * - 4 bytes of BIT STRING overhead; - * - 3 full-size INTEGERs (p, g, y); - * - 1 + 1 + 32 bytes for 1 sub-size INTEGER (q <= 256 bits). - */ -#define PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) \ - (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3 + 59) - -/* Maximum size of the export encoding of a DSA key pair. - * - * DSAPrivateKey ::= SEQUENCE { - * version Version, -- 0 - * prime INTEGER, -- p - * subprime INTEGER, -- q - * generator INTEGER, -- g - * public INTEGER, -- y - * private INTEGER, -- x - * } - * - * - 4 bytes of SEQUENCE overhead; - * - 3 bytes of version; - * - 3 full-size INTEGERs (p, g, y); - * - 2 * (1 + 1 + 32) bytes for 2 sub-size INTEGERs (q, x <= 256 bits). - */ -#define PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits) \ - (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3 + 75) - -/* Maximum size of the export encoding of an ECC public key. - * - * The representation of an ECC public key is: - * - The byte 0x04; - * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; - * - `y_P` as a `ceiling(m/8)`-byte string, big-endian; - * - where m is the bit size associated with the curve. - * - * - 1 byte + 2 * point size. - */ -#define PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) \ - (2 * PSA_BITS_TO_BYTES(key_bits) + 1) - -/* Maximum size of the export encoding of an ECC key pair. - * - * An ECC key pair is represented by the secret value. - */ -#define PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) \ - (PSA_BITS_TO_BYTES(key_bits)) - -/** Sufficient output buffer size for psa_export_key() or psa_export_public_key(). - * - * This macro returns a compile-time constant if its arguments are - * compile-time constants. - * - * \warning This function may call its arguments multiple times or - * zero times, so you should not pass arguments that contain - * side effects. - * - * The following code illustrates how to allocate enough memory to export - * a key by querying the key type and size at runtime. - * \code{c} - * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - * psa_status_t status; - * status = psa_get_key_attributes(key, &attributes); - * if (status != PSA_SUCCESS) handle_error(...); - * psa_key_type_t key_type = psa_get_key_type(&attributes); - * size_t key_bits = psa_get_key_bits(&attributes); - * size_t buffer_size = PSA_KEY_EXPORT_MAX_SIZE(key_type, key_bits); - * psa_reset_key_attributes(&attributes); - * uint8_t *buffer = malloc(buffer_size); - * if (buffer == NULL) handle_error(...); - * size_t buffer_length; - * status = psa_export_key(key, buffer, buffer_size, &buffer_length); - * if (status != PSA_SUCCESS) handle_error(...); - * \endcode - * - * For psa_export_public_key(), calculate the buffer size from the - * public key type. You can use the macro #PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR - * to convert a key pair type to the corresponding public key type. - * \code{c} - * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - * psa_status_t status; - * status = psa_get_key_attributes(key, &attributes); - * if (status != PSA_SUCCESS) handle_error(...); - * psa_key_type_t key_type = psa_get_key_type(&attributes); - * psa_key_type_t public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(key_type); - * size_t key_bits = psa_get_key_bits(&attributes); - * size_t buffer_size = PSA_KEY_EXPORT_MAX_SIZE(public_key_type, key_bits); - * psa_reset_key_attributes(&attributes); - * uint8_t *buffer = malloc(buffer_size); - * if (buffer == NULL) handle_error(...); - * size_t buffer_length; - * status = psa_export_public_key(key, buffer, buffer_size, &buffer_length); - * if (status != PSA_SUCCESS) handle_error(...); - * \endcode - * - * \param key_type A supported key type. - * \param key_bits The size of the key in bits. - * - * \return If the parameters are valid and supported, return - * a buffer size in bytes that guarantees that - * psa_sign_hash() will not fail with - * #PSA_ERROR_BUFFER_TOO_SMALL. - * If the parameters are a valid combination that is not supported - * by the implementation, this macro shall return either a - * sensible size or 0. - * If the parameters are not valid, the - * return value is unspecified. - */ -#define PSA_KEY_EXPORT_MAX_SIZE(key_type, key_bits) \ - (PSA_KEY_TYPE_IS_UNSTRUCTURED(key_type) ? PSA_BITS_TO_BYTES(key_bits) : \ - (key_type) == PSA_KEY_TYPE_RSA_KEY_PAIR ? PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits) : \ - (key_type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY ? PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ - (key_type) == PSA_KEY_TYPE_DSA_KEY_PAIR ? PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits) : \ - (key_type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY ? PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ - PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) ? PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) : \ - PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type) ? PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) : \ - 0) - -#endif /* PSA_CRYPTO_SIZES_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_types.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_types.h deleted file mode 100644 index d96c66e..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_types.h +++ /dev/null @@ -1,287 +0,0 @@ -/** - * \file psa/crypto_types.h - * - * \brief PSA cryptography module: type aliases. - * - * \note This file may not be included directly. Applications must - * include psa/crypto.h. Drivers must include the appropriate driver - * header file. - * - * This file contains portable definitions of integral types for properties - * of cryptographic keys, designations of cryptographic algorithms, and - * error codes returned by the library. - * - * This header file does not declare any function. - */ -/* - * Copyright (C) 2018, ARM Limited, 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. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#ifndef PSA_CRYPTO_TYPES_H -#define PSA_CRYPTO_TYPES_H - -#include - -/** \defgroup error Error codes - * @{ - */ - -/** - * \brief Function return status. - * - * This is either #PSA_SUCCESS (which is zero), indicating success, - * or a small negative value indicating that an error occurred. Errors are - * encoded as one of the \c PSA_ERROR_xxx values defined here. */ -/* If #PSA_SUCCESS is already defined, it means that #psa_status_t - * is also defined in an external header, so prevent its multiple - * definition. - */ -#ifndef PSA_SUCCESS -typedef int32_t psa_status_t; -#endif - -/**@}*/ - -/** \defgroup crypto_types Key and algorithm types - * @{ - */ - -/** \brief Encoding of a key type. - */ -typedef uint16_t psa_key_type_t; - -/** The type of PSA elliptic curve family identifiers. - * - * The curve identifier is required to create an ECC key using the - * PSA_KEY_TYPE_ECC_KEY_PAIR() or PSA_KEY_TYPE_ECC_PUBLIC_KEY() - * macros. - * - * Values defined by this standard will never be in the range 0x80-0xff. - * Vendors who define additional families must use an encoding in this range. - */ -typedef uint8_t psa_ecc_curve_t; - -/** The type of PSA Diffie-Hellman group family identifiers. - * - * The group identifier is required to create an Diffie-Hellman key using the - * PSA_KEY_TYPE_DH_KEY_PAIR() or PSA_KEY_TYPE_DH_PUBLIC_KEY() - * macros. - * - * Values defined by this standard will never be in the range 0x80-0xff. - * Vendors who define additional families must use an encoding in this range. - */ -typedef uint8_t psa_dh_group_t; - -/** \brief Encoding of a cryptographic algorithm. - * - * For algorithms that can be applied to multiple key types, this type - * does not encode the key type. For example, for symmetric ciphers - * based on a block cipher, #psa_algorithm_t encodes the block cipher - * mode and the padding mode while the block cipher itself is encoded - * via #psa_key_type_t. - */ -typedef uint32_t psa_algorithm_t; - -/**@}*/ - -/** \defgroup key_lifetimes Key lifetimes - * @{ - */ - -/** Encoding of key lifetimes. - * - * The lifetime of a key indicates where it is stored and what system actions - * may create and destroy it. - * - * Keys with the lifetime #PSA_KEY_LIFETIME_VOLATILE are automatically - * destroyed when the application terminates or on a power reset. - * - * Keys with a lifetime other than #PSA_KEY_LIFETIME_VOLATILE are said - * to be _persistent_. - * Persistent keys are preserved if the application or the system restarts. - * Persistent keys have a key identifier of type #psa_key_id_t. - * The application can call psa_open_key() to open a persistent key that - * it created previously. - */ -typedef uint32_t psa_key_lifetime_t; - -/** Encoding of identifiers of persistent keys. - * - * - Applications may freely choose key identifiers in the range - * #PSA_KEY_ID_USER_MIN to #PSA_KEY_ID_USER_MAX. - * - Implementations may define additional key identifiers in the range - * #PSA_KEY_ID_VENDOR_MIN to #PSA_KEY_ID_VENDOR_MAX. - * - 0 is reserved as an invalid key identifier. - * - Key identifiers outside these ranges are reserved for future use. - */ -/* Implementation-specific quirk: The Mbed Crypto library can be built as - * part of a multi-client service that exposes the PSA Crypto API in each - * client and encodes the client identity in the key id argument of functions - * such as psa_open_key(). In this build configuration, we define - * psa_key_id_t in crypto_platform.h instead of here. */ -#if !defined(MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER) -typedef uint32_t psa_key_id_t; -#define PSA_KEY_ID_INIT 0 -#endif - -/**@}*/ - -/** \defgroup policy Key policies - * @{ - */ - -/** \brief Encoding of permitted usage on a key. */ -typedef uint32_t psa_key_usage_t; - -/**@}*/ - -/** \defgroup attributes Key attributes - * @{ - */ - -/** The type of a structure containing key attributes. - * - * This is an opaque structure that can represent the metadata of a key - * object. Metadata that can be stored in attributes includes: - * - The location of the key in storage, indicated by its key identifier - * and its lifetime. - * - The key's policy, comprising usage flags and a specification of - * the permitted algorithm(s). - * - Information about the key itself: the key type and its size. - * - Implementations may define additional attributes. - * - * The actual key material is not considered an attribute of a key. - * Key attributes do not contain information that is generally considered - * highly confidential. - * - * An attribute structure can be a simple data structure where each function - * `psa_set_key_xxx` sets a field and the corresponding function - * `psa_get_key_xxx` retrieves the value of the corresponding field. - * However, implementations may report values that are equivalent to the - * original one, but have a different encoding. For example, an - * implementation may use a more compact representation for types where - * many bit-patterns are invalid or not supported, and store all values - * that it does not support as a special marker value. In such an - * implementation, after setting an invalid value, the corresponding - * get function returns an invalid value which may not be the one that - * was originally stored. - * - * An attribute structure may contain references to auxiliary resources, - * for example pointers to allocated memory or indirect references to - * pre-calculated values. In order to free such resources, the application - * must call psa_reset_key_attributes(). As an exception, calling - * psa_reset_key_attributes() on an attribute structure is optional if - * the structure has only been modified by the following functions - * since it was initialized or last reset with psa_reset_key_attributes(): - * - psa_set_key_id() - * - psa_set_key_lifetime() - * - psa_set_key_type() - * - psa_set_key_bits() - * - psa_set_key_usage_flags() - * - psa_set_key_algorithm() - * - * Before calling any function on a key attribute structure, the application - * must initialize it by any of the following means: - * - Set the structure to all-bits-zero, for example: - * \code - * psa_key_attributes_t attributes; - * memset(&attributes, 0, sizeof(attributes)); - * \endcode - * - Initialize the structure to logical zero values, for example: - * \code - * psa_key_attributes_t attributes = {0}; - * \endcode - * - Initialize the structure to the initializer #PSA_KEY_ATTRIBUTES_INIT, - * for example: - * \code - * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - * \endcode - * - Assign the result of the function psa_key_attributes_init() - * to the structure, for example: - * \code - * psa_key_attributes_t attributes; - * attributes = psa_key_attributes_init(); - * \endcode - * - * A freshly initialized attribute structure contains the following - * values: - * - * - lifetime: #PSA_KEY_LIFETIME_VOLATILE. - * - key identifier: 0 (which is not a valid key identifier). - * - type: \c 0 (meaning that the type is unspecified). - * - key size: \c 0 (meaning that the size is unspecified). - * - usage flags: \c 0 (which allows no usage except exporting a public key). - * - algorithm: \c 0 (which allows no cryptographic usage, but allows - * exporting). - * - * A typical sequence to create a key is as follows: - * -# Create and initialize an attribute structure. - * -# If the key is persistent, call psa_set_key_id(). - * Also call psa_set_key_lifetime() to place the key in a non-default - * location. - * -# Set the key policy with psa_set_key_usage_flags() and - * psa_set_key_algorithm(). - * -# Set the key type with psa_set_key_type(). - * Skip this step if copying an existing key with psa_copy_key(). - * -# When generating a random key with psa_generate_key() or deriving a key - * with psa_key_derivation_output_key(), set the desired key size with - * psa_set_key_bits(). - * -# Call a key creation function: psa_import_key(), psa_generate_key(), - * psa_key_derivation_output_key() or psa_copy_key(). This function reads - * the attribute structure, creates a key with these attributes, and - * outputs a handle to the newly created key. - * -# The attribute structure is now no longer necessary. - * You may call psa_reset_key_attributes(), although this is optional - * with the workflow presented here because the attributes currently - * defined in this specification do not require any additional resources - * beyond the structure itself. - * - * A typical sequence to query a key's attributes is as follows: - * -# Call psa_get_key_attributes(). - * -# Call `psa_get_key_xxx` functions to retrieve the attribute(s) that - * you are interested in. - * -# Call psa_reset_key_attributes() to free any resources that may be - * used by the attribute structure. - * - * Once a key has been created, it is impossible to change its attributes. - */ -typedef struct psa_key_attributes_s psa_key_attributes_t; - - -#ifndef __DOXYGEN_ONLY__ -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) -/* Mbed Crypto defines this type in crypto_types.h because it is also - * visible to applications through an implementation-specific extension. - * For the PSA Cryptography specification, this type is only visible - * via crypto_se_driver.h. */ -typedef uint64_t psa_key_slot_number_t; -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ -#endif /* !__DOXYGEN_ONLY__ */ - -/**@}*/ - -/** \defgroup derivation Key derivation - * @{ - */ - -/** \brief Encoding of the step of a key derivation. */ -typedef uint16_t psa_key_derivation_step_t; - -/**@}*/ - -#endif /* PSA_CRYPTO_TYPES_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_values.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_values.h deleted file mode 100644 index baaabff..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_values.h +++ /dev/null @@ -1,1705 +0,0 @@ -/** - * \file psa/crypto_values.h - * - * \brief PSA cryptography module: macros to build and analyze integer values. - * - * \note This file may not be included directly. Applications must - * include psa/crypto.h. Drivers must include the appropriate driver - * header file. - * - * This file contains portable definitions of macros to build and analyze - * values of integral types that encode properties of cryptographic keys, - * designations of cryptographic algorithms, and error codes returned by - * the library. - * - * This header file only defines preprocessor macros. - */ -/* - * Copyright (C) 2018, ARM Limited, 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. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#ifndef PSA_CRYPTO_VALUES_H -#define PSA_CRYPTO_VALUES_H - -/** \defgroup error Error codes - * @{ - */ - -/* PSA error codes */ - -/** The action was completed successfully. */ -#define PSA_SUCCESS ((psa_status_t)0) - -/** An error occurred that does not correspond to any defined - * failure cause. - * - * Implementations may use this error code if none of the other standard - * error codes are applicable. */ -#define PSA_ERROR_GENERIC_ERROR ((psa_status_t)-132) - -/** The requested operation or a parameter is not supported - * by this implementation. - * - * Implementations should return this error code when an enumeration - * parameter such as a key type, algorithm, etc. is not recognized. - * If a combination of parameters is recognized and identified as - * not valid, return #PSA_ERROR_INVALID_ARGUMENT instead. */ -#define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)-134) - -/** The requested action is denied by a policy. - * - * Implementations should return this error code when the parameters - * are recognized as valid and supported, and a policy explicitly - * denies the requested operation. - * - * If a subset of the parameters of a function call identify a - * forbidden operation, and another subset of the parameters are - * not valid or not supported, it is unspecified whether the function - * returns #PSA_ERROR_NOT_PERMITTED, #PSA_ERROR_NOT_SUPPORTED or - * #PSA_ERROR_INVALID_ARGUMENT. */ -#define PSA_ERROR_NOT_PERMITTED ((psa_status_t)-133) - -/** An output buffer is too small. - * - * Applications can call the \c PSA_xxx_SIZE macro listed in the function - * description to determine a sufficient buffer size. - * - * Implementations should preferably return this error code only - * in cases when performing the operation with a larger output - * buffer would succeed. However implementations may return this - * error if a function has invalid or unsupported parameters in addition - * to the parameters that determine the necessary output buffer size. */ -#define PSA_ERROR_BUFFER_TOO_SMALL ((psa_status_t)-138) - -/** Asking for an item that already exists - * - * Implementations should return this error, when attempting - * to write an item (like a key) that already exists. */ -#define PSA_ERROR_ALREADY_EXISTS ((psa_status_t)-139) - -/** Asking for an item that doesn't exist - * - * Implementations should return this error, if a requested item (like - * a key) does not exist. */ -#define PSA_ERROR_DOES_NOT_EXIST ((psa_status_t)-140) - -/** The requested action cannot be performed in the current state. - * - * Multipart operations return this error when one of the - * functions is called out of sequence. Refer to the function - * descriptions for permitted sequencing of functions. - * - * Implementations shall not return this error code to indicate - * that a key either exists or not, - * but shall instead return #PSA_ERROR_ALREADY_EXISTS or #PSA_ERROR_DOES_NOT_EXIST - * as applicable. - * - * Implementations shall not return this error code to indicate that a - * key handle is invalid, but shall return #PSA_ERROR_INVALID_HANDLE - * instead. */ -#define PSA_ERROR_BAD_STATE ((psa_status_t)-137) - -/** The parameters passed to the function are invalid. - * - * Implementations may return this error any time a parameter or - * combination of parameters are recognized as invalid. - * - * Implementations shall not return this error code to indicate that a - * key handle is invalid, but shall return #PSA_ERROR_INVALID_HANDLE - * instead. - */ -#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)-135) - -/** There is not enough runtime memory. - * - * If the action is carried out across multiple security realms, this - * error can refer to available memory in any of the security realms. */ -#define PSA_ERROR_INSUFFICIENT_MEMORY ((psa_status_t)-141) - -/** There is not enough persistent storage. - * - * Functions that modify the key storage return this error code if - * there is insufficient storage space on the host media. In addition, - * many functions that do not otherwise access storage may return this - * error code if the implementation requires a mandatory log entry for - * the requested action and the log storage space is full. */ -#define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)-142) - -/** There was a communication failure inside the implementation. - * - * This can indicate a communication failure between the application - * and an external cryptoprocessor or between the cryptoprocessor and - * an external volatile or persistent memory. A communication failure - * may be transient or permanent depending on the cause. - * - * \warning If a function returns this error, it is undetermined - * whether the requested action has completed or not. Implementations - * should return #PSA_SUCCESS on successful completion whenever - * possible, however functions may return #PSA_ERROR_COMMUNICATION_FAILURE - * if the requested action was completed successfully in an external - * cryptoprocessor but there was a breakdown of communication before - * the cryptoprocessor could report the status to the application. - */ -#define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t)-145) - -/** There was a storage failure that may have led to data loss. - * - * This error indicates that some persistent storage is corrupted. - * It should not be used for a corruption of volatile memory - * (use #PSA_ERROR_CORRUPTION_DETECTED), for a communication error - * between the cryptoprocessor and its external storage (use - * #PSA_ERROR_COMMUNICATION_FAILURE), or when the storage is - * in a valid state but is full (use #PSA_ERROR_INSUFFICIENT_STORAGE). - * - * Note that a storage failure does not indicate that any data that was - * previously read is invalid. However this previously read data may no - * longer be readable from storage. - * - * When a storage failure occurs, it is no longer possible to ensure - * the global integrity of the keystore. Depending on the global - * integrity guarantees offered by the implementation, access to other - * data may or may not fail even if the data is still readable but - * its integrity cannot be guaranteed. - * - * Implementations should only use this error code to report a - * permanent storage corruption. However application writers should - * keep in mind that transient errors while reading the storage may be - * reported using this error code. */ -#define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)-146) - -/** A hardware failure was detected. - * - * A hardware failure may be transient or permanent depending on the - * cause. */ -#define PSA_ERROR_HARDWARE_FAILURE ((psa_status_t)-147) - -/** A tampering attempt was detected. - * - * If an application receives this error code, there is no guarantee - * that previously accessed or computed data was correct and remains - * confidential. Applications should not perform any security function - * and should enter a safe failure state. - * - * Implementations may return this error code if they detect an invalid - * state that cannot happen during normal operation and that indicates - * that the implementation's security guarantees no longer hold. Depending - * on the implementation architecture and on its security and safety goals, - * the implementation may forcibly terminate the application. - * - * This error code is intended as a last resort when a security breach - * is detected and it is unsure whether the keystore data is still - * protected. Implementations shall only return this error code - * to report an alarm from a tampering detector, to indicate that - * the confidentiality of stored data can no longer be guaranteed, - * or to indicate that the integrity of previously returned data is now - * considered compromised. Implementations shall not use this error code - * to indicate a hardware failure that merely makes it impossible to - * perform the requested operation (use #PSA_ERROR_COMMUNICATION_FAILURE, - * #PSA_ERROR_STORAGE_FAILURE, #PSA_ERROR_HARDWARE_FAILURE, - * #PSA_ERROR_INSUFFICIENT_ENTROPY or other applicable error code - * instead). - * - * This error indicates an attack against the application. Implementations - * shall not return this error code as a consequence of the behavior of - * the application itself. */ -#define PSA_ERROR_CORRUPTION_DETECTED ((psa_status_t)-151) - -/** There is not enough entropy to generate random data needed - * for the requested action. - * - * This error indicates a failure of a hardware random generator. - * Application writers should note that this error can be returned not - * only by functions whose purpose is to generate random data, such - * as key, IV or nonce generation, but also by functions that execute - * an algorithm with a randomized result, as well as functions that - * use randomization of intermediate computations as a countermeasure - * to certain attacks. - * - * Implementations should avoid returning this error after psa_crypto_init() - * has succeeded. Implementations should generate sufficient - * entropy during initialization and subsequently use a cryptographically - * secure pseudorandom generator (PRNG). However implementations may return - * this error at any time if a policy requires the PRNG to be reseeded - * during normal operation. */ -#define PSA_ERROR_INSUFFICIENT_ENTROPY ((psa_status_t)-148) - -/** The signature, MAC or hash is incorrect. - * - * Verification functions return this error if the verification - * calculations completed successfully, and the value to be verified - * was determined to be incorrect. - * - * If the value to verify has an invalid size, implementations may return - * either #PSA_ERROR_INVALID_ARGUMENT or #PSA_ERROR_INVALID_SIGNATURE. */ -#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) - -/** The decrypted padding is incorrect. - * - * \warning In some protocols, when decrypting data, it is essential that - * the behavior of the application does not depend on whether the padding - * is correct, down to precise timing. Applications should prefer - * protocols that use authenticated encryption rather than plain - * encryption. If the application must perform a decryption of - * unauthenticated data, the application writer should take care not - * to reveal whether the padding is invalid. - * - * Implementations should strive to make valid and invalid padding - * as close as possible to indistinguishable to an external observer. - * In particular, the timing of a decryption operation should not - * depend on the validity of the padding. */ -#define PSA_ERROR_INVALID_PADDING ((psa_status_t)-150) - -/** Return this error when there's insufficient data when attempting - * to read from a resource. */ -#define PSA_ERROR_INSUFFICIENT_DATA ((psa_status_t)-143) - -/** The key handle is not valid. See also :ref:\`key-handles\`. - */ -#define PSA_ERROR_INVALID_HANDLE ((psa_status_t)-136) - -/**@}*/ - -/** \defgroup crypto_types Key and algorithm types - * @{ - */ - -/** An invalid key type value. - * - * Zero is not the encoding of any key type. - */ -#define PSA_KEY_TYPE_NONE ((psa_key_type_t)0x0000) - -/** Vendor-defined key type flag. - * - * Key types defined by this standard will never have the - * #PSA_KEY_TYPE_VENDOR_FLAG bit set. Vendors who define additional key types - * must use an encoding with the #PSA_KEY_TYPE_VENDOR_FLAG bit set and should - * respect the bitwise structure used by standard encodings whenever practical. - */ -#define PSA_KEY_TYPE_VENDOR_FLAG ((psa_key_type_t)0x8000) - -#define PSA_KEY_TYPE_CATEGORY_MASK ((psa_key_type_t)0x7000) -#define PSA_KEY_TYPE_CATEGORY_RAW ((psa_key_type_t)0x1000) -#define PSA_KEY_TYPE_CATEGORY_SYMMETRIC ((psa_key_type_t)0x2000) -#define PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY ((psa_key_type_t)0x4000) -#define PSA_KEY_TYPE_CATEGORY_KEY_PAIR ((psa_key_type_t)0x7000) - -#define PSA_KEY_TYPE_CATEGORY_FLAG_PAIR ((psa_key_type_t)0x3000) - -/** Whether a key type is vendor-defined. - * - * See also #PSA_KEY_TYPE_VENDOR_FLAG. - */ -#define PSA_KEY_TYPE_IS_VENDOR_DEFINED(type) \ - (((type) & PSA_KEY_TYPE_VENDOR_FLAG) != 0) - -/** Whether a key type is an unstructured array of bytes. - * - * This encompasses both symmetric keys and non-key data. - */ -#define PSA_KEY_TYPE_IS_UNSTRUCTURED(type) \ - (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_RAW || \ - ((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_SYMMETRIC) - -/** Whether a key type is asymmetric: either a key pair or a public key. */ -#define PSA_KEY_TYPE_IS_ASYMMETRIC(type) \ - (((type) & PSA_KEY_TYPE_CATEGORY_MASK \ - & ~PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) == \ - PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY) -/** Whether a key type is the public part of a key pair. */ -#define PSA_KEY_TYPE_IS_PUBLIC_KEY(type) \ - (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY) -/** Whether a key type is a key pair containing a private part and a public - * part. */ -#define PSA_KEY_TYPE_IS_KEY_PAIR(type) \ - (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_KEY_PAIR) -/** The key pair type corresponding to a public key type. - * - * You may also pass a key pair type as \p type, it will be left unchanged. - * - * \param type A public key type or key pair type. - * - * \return The corresponding key pair type. - * If \p type is not a public key or a key pair, - * the return value is undefined. - */ -#define PSA_KEY_TYPE_KEY_PAIR_OF_PUBLIC_KEY(type) \ - ((type) | PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) -/** The public key type corresponding to a key pair type. - * - * You may also pass a key pair type as \p type, it will be left unchanged. - * - * \param type A public key type or key pair type. - * - * \return The corresponding public key type. - * If \p type is not a public key or a key pair, - * the return value is undefined. - */ -#define PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) \ - ((type) & ~PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) - -/** Raw data. - * - * A "key" of this type cannot be used for any cryptographic operation. - * Applications may use this type to store arbitrary data in the keystore. */ -#define PSA_KEY_TYPE_RAW_DATA ((psa_key_type_t)0x1001) - -/** HMAC key. - * - * The key policy determines which underlying hash algorithm the key can be - * used for. - * - * HMAC keys should generally have the same size as the underlying hash. - * This size can be calculated with #PSA_HASH_SIZE(\c alg) where - * \c alg is the HMAC algorithm or the underlying hash algorithm. */ -#define PSA_KEY_TYPE_HMAC ((psa_key_type_t)0x1100) - -/** A secret for key derivation. - * - * The key policy determines which key derivation algorithm the key - * can be used for. - */ -#define PSA_KEY_TYPE_DERIVE ((psa_key_type_t)0x1200) - -/** Key for a cipher, AEAD or MAC algorithm based on the AES block cipher. - * - * The size of the key can be 16 bytes (AES-128), 24 bytes (AES-192) or - * 32 bytes (AES-256). - */ -#define PSA_KEY_TYPE_AES ((psa_key_type_t)0x2400) - -/** Key for a cipher or MAC algorithm based on DES or 3DES (Triple-DES). - * - * The size of the key can be 8 bytes (single DES), 16 bytes (2-key 3DES) or - * 24 bytes (3-key 3DES). - * - * Note that single DES and 2-key 3DES are weak and strongly - * deprecated and should only be used to decrypt legacy data. 3-key 3DES - * is weak and deprecated and should only be used in legacy protocols. - */ -#define PSA_KEY_TYPE_DES ((psa_key_type_t)0x2301) - -/** Key for a cipher, AEAD or MAC algorithm based on the - * Camellia block cipher. */ -#define PSA_KEY_TYPE_CAMELLIA ((psa_key_type_t)0x2403) - -/** Key for the RC4 stream cipher. - * - * Note that RC4 is weak and deprecated and should only be used in - * legacy protocols. */ -#define PSA_KEY_TYPE_ARC4 ((psa_key_type_t)0x2002) - -/** Key for the ChaCha20 stream cipher or the Chacha20-Poly1305 AEAD algorithm. - * - * ChaCha20 and the ChaCha20_Poly1305 construction are defined in RFC 7539. - * - * Implementations must support 12-byte nonces, may support 8-byte nonces, - * and should reject other sizes. - */ -#define PSA_KEY_TYPE_CHACHA20 ((psa_key_type_t)0x2004) - -/** RSA public key. */ -#define PSA_KEY_TYPE_RSA_PUBLIC_KEY ((psa_key_type_t)0x4001) -/** RSA key pair (private and public key). */ -#define PSA_KEY_TYPE_RSA_KEY_PAIR ((psa_key_type_t)0x7001) -/** Whether a key type is an RSA key (pair or public-only). */ -#define PSA_KEY_TYPE_IS_RSA(type) \ - (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY) - -#define PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE ((psa_key_type_t)0x4100) -#define PSA_KEY_TYPE_ECC_KEY_PAIR_BASE ((psa_key_type_t)0x7100) -#define PSA_KEY_TYPE_ECC_CURVE_MASK ((psa_key_type_t)0x00ff) -/** Elliptic curve key pair. - * - * \param curve A value of type ::psa_ecc_curve_t that identifies the - * ECC curve to be used. - */ -#define PSA_KEY_TYPE_ECC_KEY_PAIR(curve) \ - (PSA_KEY_TYPE_ECC_KEY_PAIR_BASE | (curve)) -/** Elliptic curve public key. - * - * \param curve A value of type ::psa_ecc_curve_t that identifies the - * ECC curve to be used. - */ -#define PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve) \ - (PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE | (curve)) - -/** Whether a key type is an elliptic curve key (pair or public-only). */ -#define PSA_KEY_TYPE_IS_ECC(type) \ - ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) & \ - ~PSA_KEY_TYPE_ECC_CURVE_MASK) == PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE) -/** Whether a key type is an elliptic curve key pair. */ -#define PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type) \ - (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \ - PSA_KEY_TYPE_ECC_KEY_PAIR_BASE) -/** Whether a key type is an elliptic curve public key. */ -#define PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(type) \ - (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \ - PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE) - -/** Extract the curve from an elliptic curve key type. */ -#define PSA_KEY_TYPE_GET_CURVE(type) \ - ((psa_ecc_curve_t) (PSA_KEY_TYPE_IS_ECC(type) ? \ - ((type) & PSA_KEY_TYPE_ECC_CURVE_MASK) : \ - 0)) - -/** SEC Koblitz curves over prime fields. - * - * This family comprises the following curves: - * secp192k1, secp224k1, secp256k1. - * They are defined in _Standards for Efficient Cryptography_, - * _SEC 2: Recommended Elliptic Curve Domain Parameters_. - * https://www.secg.org/sec2-v2.pdf - */ -#define PSA_ECC_CURVE_SECP_K1 ((psa_ecc_curve_t) 0x17) - -/** SEC random curves over prime fields. - * - * This family comprises the following curves: - * secp192k1, secp224r1, secp256r1, secp384r1, secp521r1. - * They are defined in _Standards for Efficient Cryptography_, - * _SEC 2: Recommended Elliptic Curve Domain Parameters_. - * https://www.secg.org/sec2-v2.pdf - */ -#define PSA_ECC_CURVE_SECP_R1 ((psa_ecc_curve_t) 0x12) -/* SECP160R2 (SEC2 v1, obsolete) */ -#define PSA_ECC_CURVE_SECP_R2 ((psa_ecc_curve_t) 0x1b) - -/** SEC Koblitz curves over binary fields. - * - * This family comprises the following curves: - * sect163k1, sect233k1, sect239k1, sect283k1, sect409k1, sect571k1. - * They are defined in _Standards for Efficient Cryptography_, - * _SEC 2: Recommended Elliptic Curve Domain Parameters_. - * https://www.secg.org/sec2-v2.pdf - */ -#define PSA_ECC_CURVE_SECT_K1 ((psa_ecc_curve_t) 0x27) - -/** SEC random curves over binary fields. - * - * This family comprises the following curves: - * sect163r1, sect233r1, sect283r1, sect409r1, sect571r1. - * They are defined in _Standards for Efficient Cryptography_, - * _SEC 2: Recommended Elliptic Curve Domain Parameters_. - * https://www.secg.org/sec2-v2.pdf - */ -#define PSA_ECC_CURVE_SECT_R1 ((psa_ecc_curve_t) 0x22) - -/** SEC additional random curves over binary fields. - * - * This family comprises the following curve: - * sect163r2. - * It is defined in _Standards for Efficient Cryptography_, - * _SEC 2: Recommended Elliptic Curve Domain Parameters_. - * https://www.secg.org/sec2-v2.pdf - */ -#define PSA_ECC_CURVE_SECT_R2 ((psa_ecc_curve_t) 0x2b) - -/** Brainpool P random curves. - * - * This family comprises the following curves: - * brainpoolP160r1, brainpoolP192r1, brainpoolP224r1, brainpoolP256r1, - * brainpoolP320r1, brainpoolP384r1, brainpoolP512r1. - * It is defined in RFC 5639. - */ -#define PSA_ECC_CURVE_BRAINPOOL_P_R1 ((psa_ecc_curve_t) 0x30) - -/** Curve25519 and Curve448. - * - * This family comprises the following Montgomery curves: - * - 255-bit: Bernstein et al., - * _Curve25519: new Diffie-Hellman speed records_, LNCS 3958, 2006. - * The algorithm #PSA_ALG_ECDH performs X25519 when used with this curve. - * - 448-bit: Hamburg, - * _Ed448-Goldilocks, a new elliptic curve_, NIST ECC Workshop, 2015. - * The algorithm #PSA_ALG_ECDH performs X448 when used with this curve. - */ -#define PSA_ECC_CURVE_MONTGOMERY ((psa_ecc_curve_t) 0x41) - -#define PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE ((psa_key_type_t)0x4200) -#define PSA_KEY_TYPE_DH_KEY_PAIR_BASE ((psa_key_type_t)0x7200) -#define PSA_KEY_TYPE_DH_GROUP_MASK ((psa_key_type_t)0x00ff) -/** Diffie-Hellman key pair. - * - * \param group A value of type ::psa_dh_group_t that identifies the - * Diffie-Hellman group to be used. - */ -#define PSA_KEY_TYPE_DH_KEY_PAIR(group) \ - (PSA_KEY_TYPE_DH_KEY_PAIR_BASE | (group)) -/** Diffie-Hellman public key. - * - * \param group A value of type ::psa_dh_group_t that identifies the - * Diffie-Hellman group to be used. - */ -#define PSA_KEY_TYPE_DH_PUBLIC_KEY(group) \ - (PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE | (group)) - -/** Whether a key type is a Diffie-Hellman key (pair or public-only). */ -#define PSA_KEY_TYPE_IS_DH(type) \ - ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) & \ - ~PSA_KEY_TYPE_DH_GROUP_MASK) == PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE) -/** Whether a key type is a Diffie-Hellman key pair. */ -#define PSA_KEY_TYPE_IS_DH_KEY_PAIR(type) \ - (((type) & ~PSA_KEY_TYPE_DH_GROUP_MASK) == \ - PSA_KEY_TYPE_DH_KEY_PAIR_BASE) -/** Whether a key type is a Diffie-Hellman public key. */ -#define PSA_KEY_TYPE_IS_DH_PUBLIC_KEY(type) \ - (((type) & ~PSA_KEY_TYPE_DH_GROUP_MASK) == \ - PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE) - -/** Extract the group from a Diffie-Hellman key type. */ -#define PSA_KEY_TYPE_GET_GROUP(type) \ - ((psa_dh_group_t) (PSA_KEY_TYPE_IS_DH(type) ? \ - ((type) & PSA_KEY_TYPE_DH_GROUP_MASK) : \ - 0)) - -/** Diffie-Hellman groups defined in RFC 7919 Appendix A. - * - * This family includes groups with the following key sizes (in bits): - * 2048, 3072, 4096, 6144, 8192. A given implementation may support - * all of these sizes or only a subset. - */ -#define PSA_DH_GROUP_RFC7919 ((psa_dh_group_t) 0x03) - -#define PSA_GET_KEY_TYPE_BLOCK_SIZE_EXPONENT(type) \ - (((type) >> 8) & 7) -/** The block size of a block cipher. - * - * \param type A cipher key type (value of type #psa_key_type_t). - * - * \return The block size for a block cipher, or 1 for a stream cipher. - * The return value is undefined if \p type is not a supported - * cipher key type. - * - * \note It is possible to build stream cipher algorithms on top of a block - * cipher, for example CTR mode (#PSA_ALG_CTR). - * This macro only takes the key type into account, so it cannot be - * used to determine the size of the data that #psa_cipher_update() - * might buffer for future processing in general. - * - * \note This macro returns a compile-time constant if its argument is one. - * - * \warning This macro may evaluate its argument multiple times. - */ -#define PSA_BLOCK_CIPHER_BLOCK_SIZE(type) \ - (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_SYMMETRIC ? \ - 1u << PSA_GET_KEY_TYPE_BLOCK_SIZE_EXPONENT(type) : \ - 0u) - -/** Vendor-defined algorithm flag. - * - * Algorithms defined by this standard will never have the #PSA_ALG_VENDOR_FLAG - * bit set. Vendors who define additional algorithms must use an encoding with - * the #PSA_ALG_VENDOR_FLAG bit set and should respect the bitwise structure - * used by standard encodings whenever practical. - */ -#define PSA_ALG_VENDOR_FLAG ((psa_algorithm_t)0x80000000) - -#define PSA_ALG_CATEGORY_MASK ((psa_algorithm_t)0x7f000000) -#define PSA_ALG_CATEGORY_HASH ((psa_algorithm_t)0x01000000) -#define PSA_ALG_CATEGORY_MAC ((psa_algorithm_t)0x02000000) -#define PSA_ALG_CATEGORY_CIPHER ((psa_algorithm_t)0x04000000) -#define PSA_ALG_CATEGORY_AEAD ((psa_algorithm_t)0x06000000) -#define PSA_ALG_CATEGORY_SIGN ((psa_algorithm_t)0x10000000) -#define PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION ((psa_algorithm_t)0x12000000) -#define PSA_ALG_CATEGORY_KEY_DERIVATION ((psa_algorithm_t)0x20000000) -#define PSA_ALG_CATEGORY_KEY_AGREEMENT ((psa_algorithm_t)0x30000000) - -/** Whether an algorithm is vendor-defined. - * - * See also #PSA_ALG_VENDOR_FLAG. - */ -#define PSA_ALG_IS_VENDOR_DEFINED(alg) \ - (((alg) & PSA_ALG_VENDOR_FLAG) != 0) - -/** Whether the specified algorithm is a hash algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a hash algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_HASH(alg) \ - (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_HASH) - -/** Whether the specified algorithm is a MAC algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a MAC algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_MAC(alg) \ - (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_MAC) - -/** Whether the specified algorithm is a symmetric cipher algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a symmetric cipher algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_CIPHER(alg) \ - (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_CIPHER) - -/** Whether the specified algorithm is an authenticated encryption - * with associated data (AEAD) algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is an AEAD algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_AEAD(alg) \ - (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_AEAD) - -/** Whether the specified algorithm is a public-key signature algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a public-key signature algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_SIGN(alg) \ - (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_SIGN) - -/** Whether the specified algorithm is a public-key encryption algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a public-key encryption algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg) \ - (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION) - -/** Whether the specified algorithm is a key agreement algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a key agreement algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_KEY_AGREEMENT(alg) \ - (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_AGREEMENT) - -/** Whether the specified algorithm is a key derivation algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a key derivation algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_KEY_DERIVATION(alg) \ - (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_DERIVATION) - -#define PSA_ALG_HASH_MASK ((psa_algorithm_t)0x000000ff) -/** MD2 */ -#define PSA_ALG_MD2 ((psa_algorithm_t)0x01000001) -/** MD4 */ -#define PSA_ALG_MD4 ((psa_algorithm_t)0x01000002) -/** MD5 */ -#define PSA_ALG_MD5 ((psa_algorithm_t)0x01000003) -/** PSA_ALG_RIPEMD160 */ -#define PSA_ALG_RIPEMD160 ((psa_algorithm_t)0x01000004) -/** SHA1 */ -#define PSA_ALG_SHA_1 ((psa_algorithm_t)0x01000005) -/** SHA2-224 */ -#define PSA_ALG_SHA_224 ((psa_algorithm_t)0x01000008) -/** SHA2-256 */ -#define PSA_ALG_SHA_256 ((psa_algorithm_t)0x01000009) -/** SHA2-384 */ -#define PSA_ALG_SHA_384 ((psa_algorithm_t)0x0100000a) -/** SHA2-512 */ -#define PSA_ALG_SHA_512 ((psa_algorithm_t)0x0100000b) -/** SHA2-512/224 */ -#define PSA_ALG_SHA_512_224 ((psa_algorithm_t)0x0100000c) -/** SHA2-512/256 */ -#define PSA_ALG_SHA_512_256 ((psa_algorithm_t)0x0100000d) -/** SHA3-224 */ -#define PSA_ALG_SHA3_224 ((psa_algorithm_t)0x01000010) -/** SHA3-256 */ -#define PSA_ALG_SHA3_256 ((psa_algorithm_t)0x01000011) -/** SHA3-384 */ -#define PSA_ALG_SHA3_384 ((psa_algorithm_t)0x01000012) -/** SHA3-512 */ -#define PSA_ALG_SHA3_512 ((psa_algorithm_t)0x01000013) - -/** In a hash-and-sign algorithm policy, allow any hash algorithm. - * - * This value may be used to form the algorithm usage field of a policy - * for a signature algorithm that is parametrized by a hash. The key - * may then be used to perform operations using the same signature - * algorithm parametrized with any supported hash. - * - * That is, suppose that `PSA_xxx_SIGNATURE` is one of the following macros: - * - #PSA_ALG_RSA_PKCS1V15_SIGN, #PSA_ALG_RSA_PSS, - * - #PSA_ALG_ECDSA, #PSA_ALG_DETERMINISTIC_ECDSA. - * Then you may create and use a key as follows: - * - Set the key usage field using #PSA_ALG_ANY_HASH, for example: - * ``` - * psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); // or VERIFY - * psa_set_key_algorithm(&attributes, PSA_xxx_SIGNATURE(PSA_ALG_ANY_HASH)); - * ``` - * - Import or generate key material. - * - Call psa_sign_hash() or psa_verify_hash(), passing - * an algorithm built from `PSA_xxx_SIGNATURE` and a specific hash. Each - * call to sign or verify a message may use a different hash. - * ``` - * psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA_256), ...); - * psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA_512), ...); - * psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA3_256), ...); - * ``` - * - * This value may not be used to build other algorithms that are - * parametrized over a hash. For any valid use of this macro to build - * an algorithm \c alg, #PSA_ALG_IS_HASH_AND_SIGN(\c alg) is true. - * - * This value may not be used to build an algorithm specification to - * perform an operation. It is only valid to build policies. - */ -#define PSA_ALG_ANY_HASH ((psa_algorithm_t)0x010000ff) - -#define PSA_ALG_MAC_SUBCATEGORY_MASK ((psa_algorithm_t)0x00c00000) -#define PSA_ALG_HMAC_BASE ((psa_algorithm_t)0x02800000) -/** Macro to build an HMAC algorithm. - * - * For example, #PSA_ALG_HMAC(#PSA_ALG_SHA_256) is HMAC-SHA-256. - * - * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true). - * - * \return The corresponding HMAC algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_HMAC(hash_alg) \ - (PSA_ALG_HMAC_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) - -#define PSA_ALG_HMAC_GET_HASH(hmac_alg) \ - (PSA_ALG_CATEGORY_HASH | ((hmac_alg) & PSA_ALG_HASH_MASK)) - -/** Whether the specified algorithm is an HMAC algorithm. - * - * HMAC is a family of MAC algorithms that are based on a hash function. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is an HMAC algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_HMAC(alg) \ - (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \ - PSA_ALG_HMAC_BASE) - -/* In the encoding of a MAC algorithm, the bits corresponding to - * PSA_ALG_MAC_TRUNCATION_MASK encode the length to which the MAC is - * truncated. As an exception, the value 0 means the untruncated algorithm, - * whatever its length is. The length is encoded in 6 bits, so it can - * reach up to 63; the largest MAC is 64 bytes so its trivial truncation - * to full length is correctly encoded as 0 and any non-trivial truncation - * is correctly encoded as a value between 1 and 63. */ -#define PSA_ALG_MAC_TRUNCATION_MASK ((psa_algorithm_t)0x00003f00) -#define PSA_MAC_TRUNCATION_OFFSET 8 - -/** Macro to build a truncated MAC algorithm. - * - * A truncated MAC algorithm is identical to the corresponding MAC - * algorithm except that the MAC value for the truncated algorithm - * consists of only the first \p mac_length bytes of the MAC value - * for the untruncated algorithm. - * - * \note This macro may allow constructing algorithm identifiers that - * are not valid, either because the specified length is larger - * than the untruncated MAC or because the specified length is - * smaller than permitted by the implementation. - * - * \note It is implementation-defined whether a truncated MAC that - * is truncated to the same length as the MAC of the untruncated - * algorithm is considered identical to the untruncated algorithm - * for policy comparison purposes. - * - * \param mac_alg A MAC algorithm identifier (value of type - * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg) - * is true). This may be a truncated or untruncated - * MAC algorithm. - * \param mac_length Desired length of the truncated MAC in bytes. - * This must be at most the full length of the MAC - * and must be at least an implementation-specified - * minimum. The implementation-specified minimum - * shall not be zero. - * - * \return The corresponding MAC algorithm with the specified - * length. - * \return Unspecified if \p alg is not a supported - * MAC algorithm or if \p mac_length is too small or - * too large for the specified MAC algorithm. - */ -#define PSA_ALG_TRUNCATED_MAC(mac_alg, mac_length) \ - (((mac_alg) & ~PSA_ALG_MAC_TRUNCATION_MASK) | \ - ((mac_length) << PSA_MAC_TRUNCATION_OFFSET & PSA_ALG_MAC_TRUNCATION_MASK)) - -/** Macro to build the base MAC algorithm corresponding to a truncated - * MAC algorithm. - * - * \param mac_alg A MAC algorithm identifier (value of type - * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg) - * is true). This may be a truncated or untruncated - * MAC algorithm. - * - * \return The corresponding base MAC algorithm. - * \return Unspecified if \p alg is not a supported - * MAC algorithm. - */ -#define PSA_ALG_FULL_LENGTH_MAC(mac_alg) \ - ((mac_alg) & ~PSA_ALG_MAC_TRUNCATION_MASK) - -/** Length to which a MAC algorithm is truncated. - * - * \param mac_alg A MAC algorithm identifier (value of type - * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg) - * is true). - * - * \return Length of the truncated MAC in bytes. - * \return 0 if \p alg is a non-truncated MAC algorithm. - * \return Unspecified if \p alg is not a supported - * MAC algorithm. - */ -#define PSA_MAC_TRUNCATED_LENGTH(mac_alg) \ - (((mac_alg) & PSA_ALG_MAC_TRUNCATION_MASK) >> PSA_MAC_TRUNCATION_OFFSET) - -#define PSA_ALG_CIPHER_MAC_BASE ((psa_algorithm_t)0x02c00000) -/** The CBC-MAC construction over a block cipher - * - * \warning CBC-MAC is insecure in many cases. - * A more secure mode, such as #PSA_ALG_CMAC, is recommended. - */ -#define PSA_ALG_CBC_MAC ((psa_algorithm_t)0x02c00001) -/** The CMAC construction over a block cipher */ -#define PSA_ALG_CMAC ((psa_algorithm_t)0x02c00002) - -/** Whether the specified algorithm is a MAC algorithm based on a block cipher. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a MAC algorithm based on a block cipher, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) \ - (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \ - PSA_ALG_CIPHER_MAC_BASE) - -#define PSA_ALG_CIPHER_STREAM_FLAG ((psa_algorithm_t)0x00800000) -#define PSA_ALG_CIPHER_FROM_BLOCK_FLAG ((psa_algorithm_t)0x00400000) - -/** Whether the specified algorithm is a stream cipher. - * - * A stream cipher is a symmetric cipher that encrypts or decrypts messages - * by applying a bitwise-xor with a stream of bytes that is generated - * from a key. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a stream cipher algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier or if it is not a symmetric cipher algorithm. - */ -#define PSA_ALG_IS_STREAM_CIPHER(alg) \ - (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_CIPHER_STREAM_FLAG)) == \ - (PSA_ALG_CATEGORY_CIPHER | PSA_ALG_CIPHER_STREAM_FLAG)) - -/** The ARC4 stream cipher algorithm. - */ -#define PSA_ALG_ARC4 ((psa_algorithm_t)0x04800001) - -/** The ChaCha20 stream cipher. - * - * ChaCha20 is defined in RFC 7539. - * - * The nonce size for psa_cipher_set_iv() or psa_cipher_generate_iv() - * must be 12. - * - * The initial block counter is always 0. - * - */ -#define PSA_ALG_CHACHA20 ((psa_algorithm_t)0x04800005) - -/** The CTR stream cipher mode. - * - * CTR is a stream cipher which is built from a block cipher. - * The underlying block cipher is determined by the key type. - * For example, to use AES-128-CTR, use this algorithm with - * a key of type #PSA_KEY_TYPE_AES and a length of 128 bits (16 bytes). - */ -#define PSA_ALG_CTR ((psa_algorithm_t)0x04c00001) - -/** The CFB stream cipher mode. - * - * The underlying block cipher is determined by the key type. - */ -#define PSA_ALG_CFB ((psa_algorithm_t)0x04c00002) - -/** The OFB stream cipher mode. - * - * The underlying block cipher is determined by the key type. - */ -#define PSA_ALG_OFB ((psa_algorithm_t)0x04c00003) - -/** The XTS cipher mode. - * - * XTS is a cipher mode which is built from a block cipher. It requires at - * least one full block of input, but beyond this minimum the input - * does not need to be a whole number of blocks. - */ -#define PSA_ALG_XTS ((psa_algorithm_t)0x044000ff) - -/** The CBC block cipher chaining mode, with no padding. - * - * The underlying block cipher is determined by the key type. - * - * This symmetric cipher mode can only be used with messages whose lengths - * are whole number of blocks for the chosen block cipher. - */ -#define PSA_ALG_CBC_NO_PADDING ((psa_algorithm_t)0x04600100) - -/** The CBC block cipher chaining mode with PKCS#7 padding. - * - * The underlying block cipher is determined by the key type. - * - * This is the padding method defined by PKCS#7 (RFC 2315) §10.3. - */ -#define PSA_ALG_CBC_PKCS7 ((psa_algorithm_t)0x04600101) - -#define PSA_ALG_AEAD_FROM_BLOCK_FLAG ((psa_algorithm_t)0x00400000) - -/** Whether the specified algorithm is an AEAD mode on a block cipher. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is an AEAD algorithm which is an AEAD mode based on - * a block cipher, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) \ - (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_AEAD_FROM_BLOCK_FLAG)) == \ - (PSA_ALG_CATEGORY_AEAD | PSA_ALG_AEAD_FROM_BLOCK_FLAG)) - -/** The CCM authenticated encryption algorithm. - * - * The underlying block cipher is determined by the key type. - */ -#define PSA_ALG_CCM ((psa_algorithm_t)0x06401001) - -/** The GCM authenticated encryption algorithm. - * - * The underlying block cipher is determined by the key type. - */ -#define PSA_ALG_GCM ((psa_algorithm_t)0x06401002) - -/** The Chacha20-Poly1305 AEAD algorithm. - * - * The ChaCha20_Poly1305 construction is defined in RFC 7539. - * - * Implementations must support 12-byte nonces, may support 8-byte nonces, - * and should reject other sizes. - * - * Implementations must support 16-byte tags and should reject other sizes. - */ -#define PSA_ALG_CHACHA20_POLY1305 ((psa_algorithm_t)0x06001005) - -/* In the encoding of a AEAD algorithm, the bits corresponding to - * PSA_ALG_AEAD_TAG_LENGTH_MASK encode the length of the AEAD tag. - * The constants for default lengths follow this encoding. - */ -#define PSA_ALG_AEAD_TAG_LENGTH_MASK ((psa_algorithm_t)0x00003f00) -#define PSA_AEAD_TAG_LENGTH_OFFSET 8 - -/** Macro to build a shortened AEAD algorithm. - * - * A shortened AEAD algorithm is similar to the corresponding AEAD - * algorithm, but has an authentication tag that consists of fewer bytes. - * Depending on the algorithm, the tag length may affect the calculation - * of the ciphertext. - * - * \param aead_alg An AEAD algorithm identifier (value of type - * #psa_algorithm_t such that #PSA_ALG_IS_AEAD(\p alg) - * is true). - * \param tag_length Desired length of the authentication tag in bytes. - * - * \return The corresponding AEAD algorithm with the specified - * length. - * \return Unspecified if \p alg is not a supported - * AEAD algorithm or if \p tag_length is not valid - * for the specified AEAD algorithm. - */ -#define PSA_ALG_AEAD_WITH_TAG_LENGTH(aead_alg, tag_length) \ - (((aead_alg) & ~PSA_ALG_AEAD_TAG_LENGTH_MASK) | \ - ((tag_length) << PSA_AEAD_TAG_LENGTH_OFFSET & \ - PSA_ALG_AEAD_TAG_LENGTH_MASK)) - -/** Calculate the corresponding AEAD algorithm with the default tag length. - * - * \param aead_alg An AEAD algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * - * \return The corresponding AEAD algorithm with the default - * tag length for that algorithm. - */ -#define PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH(aead_alg) \ - ( \ - PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, PSA_ALG_CCM) \ - PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, PSA_ALG_GCM) \ - PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, PSA_ALG_CHACHA20_POLY1305) \ - 0) -#define PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, ref) \ - PSA_ALG_AEAD_WITH_TAG_LENGTH(aead_alg, 0) == \ - PSA_ALG_AEAD_WITH_TAG_LENGTH(ref, 0) ? \ - ref : - -#define PSA_ALG_RSA_PKCS1V15_SIGN_BASE ((psa_algorithm_t)0x10020000) -/** RSA PKCS#1 v1.5 signature with hashing. - * - * This is the signature scheme defined by RFC 8017 - * (PKCS#1: RSA Cryptography Specifications) under the name - * RSASSA-PKCS1-v1_5. - * - * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true). - * This includes #PSA_ALG_ANY_HASH - * when specifying the algorithm in a usage policy. - * - * \return The corresponding RSA PKCS#1 v1.5 signature algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_RSA_PKCS1V15_SIGN(hash_alg) \ - (PSA_ALG_RSA_PKCS1V15_SIGN_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) -/** Raw PKCS#1 v1.5 signature. - * - * The input to this algorithm is the DigestInfo structure used by - * RFC 8017 (PKCS#1: RSA Cryptography Specifications), §9.2 - * steps 3–6. - */ -#define PSA_ALG_RSA_PKCS1V15_SIGN_RAW PSA_ALG_RSA_PKCS1V15_SIGN_BASE -#define PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) \ - (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PKCS1V15_SIGN_BASE) - -#define PSA_ALG_RSA_PSS_BASE ((psa_algorithm_t)0x10030000) -/** RSA PSS signature with hashing. - * - * This is the signature scheme defined by RFC 8017 - * (PKCS#1: RSA Cryptography Specifications) under the name - * RSASSA-PSS, with the message generation function MGF1, and with - * a salt length equal to the length of the hash. The specified - * hash algorithm is used to hash the input message, to create the - * salted hash, and for the mask generation. - * - * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true). - * This includes #PSA_ALG_ANY_HASH - * when specifying the algorithm in a usage policy. - * - * \return The corresponding RSA PSS signature algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_RSA_PSS(hash_alg) \ - (PSA_ALG_RSA_PSS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) -#define PSA_ALG_IS_RSA_PSS(alg) \ - (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PSS_BASE) - -#define PSA_ALG_ECDSA_BASE ((psa_algorithm_t)0x10060000) -/** ECDSA signature with hashing. - * - * This is the ECDSA signature scheme defined by ANSI X9.62, - * with a random per-message secret number (*k*). - * - * The representation of the signature as a byte string consists of - * the concatentation of the signature values *r* and *s*. Each of - * *r* and *s* is encoded as an *N*-octet string, where *N* is the length - * of the base point of the curve in octets. Each value is represented - * in big-endian order (most significant octet first). - * - * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true). - * This includes #PSA_ALG_ANY_HASH - * when specifying the algorithm in a usage policy. - * - * \return The corresponding ECDSA signature algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_ECDSA(hash_alg) \ - (PSA_ALG_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) -/** ECDSA signature without hashing. - * - * This is the same signature scheme as #PSA_ALG_ECDSA(), but - * without specifying a hash algorithm. This algorithm may only be - * used to sign or verify a sequence of bytes that should be an - * already-calculated hash. Note that the input is padded with - * zeros on the left or truncated on the left as required to fit - * the curve size. - */ -#define PSA_ALG_ECDSA_ANY PSA_ALG_ECDSA_BASE -#define PSA_ALG_DETERMINISTIC_ECDSA_BASE ((psa_algorithm_t)0x10070000) -/** Deterministic ECDSA signature with hashing. - * - * This is the deterministic ECDSA signature scheme defined by RFC 6979. - * - * The representation of a signature is the same as with #PSA_ALG_ECDSA(). - * - * Note that when this algorithm is used for verification, signatures - * made with randomized ECDSA (#PSA_ALG_ECDSA(\p hash_alg)) with the - * same private key are accepted. In other words, - * #PSA_ALG_DETERMINISTIC_ECDSA(\p hash_alg) differs from - * #PSA_ALG_ECDSA(\p hash_alg) only for signature, not for verification. - * - * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true). - * This includes #PSA_ALG_ANY_HASH - * when specifying the algorithm in a usage policy. - * - * \return The corresponding deterministic ECDSA signature - * algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_DETERMINISTIC_ECDSA(hash_alg) \ - (PSA_ALG_DETERMINISTIC_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) -#define PSA_ALG_ECDSA_DETERMINISTIC_FLAG ((psa_algorithm_t)0x00010000) -#define PSA_ALG_IS_ECDSA(alg) \ - (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_ECDSA_DETERMINISTIC_FLAG) == \ - PSA_ALG_ECDSA_BASE) -#define PSA_ALG_ECDSA_IS_DETERMINISTIC(alg) \ - (((alg) & PSA_ALG_ECDSA_DETERMINISTIC_FLAG) != 0) -#define PSA_ALG_IS_DETERMINISTIC_ECDSA(alg) \ - (PSA_ALG_IS_ECDSA(alg) && PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) -#define PSA_ALG_IS_RANDOMIZED_ECDSA(alg) \ - (PSA_ALG_IS_ECDSA(alg) && !PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) - -/** Whether the specified algorithm is a hash-and-sign algorithm. - * - * Hash-and-sign algorithms are public-key signature algorithms structured - * in two parts: first the calculation of a hash in a way that does not - * depend on the key, then the calculation of a signature from the - * hash value and the key. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a hash-and-sign algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_HASH_AND_SIGN(alg) \ - (PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || \ - PSA_ALG_IS_ECDSA(alg)) - -/** Get the hash used by a hash-and-sign signature algorithm. - * - * A hash-and-sign algorithm is a signature algorithm which is - * composed of two phases: first a hashing phase which does not use - * the key and produces a hash of the input message, then a signing - * phase which only uses the hash and the key and not the message - * itself. - * - * \param alg A signature algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_SIGN(\p alg) is true). - * - * \return The underlying hash algorithm if \p alg is a hash-and-sign - * algorithm. - * \return 0 if \p alg is a signature algorithm that does not - * follow the hash-and-sign structure. - * \return Unspecified if \p alg is not a signature algorithm or - * if it is not supported by the implementation. - */ -#define PSA_ALG_SIGN_GET_HASH(alg) \ - (PSA_ALG_IS_HASH_AND_SIGN(alg) ? \ - ((alg) & PSA_ALG_HASH_MASK) == 0 ? /*"raw" algorithm*/ 0 : \ - ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ - 0) - -/** RSA PKCS#1 v1.5 encryption. - */ -#define PSA_ALG_RSA_PKCS1V15_CRYPT ((psa_algorithm_t)0x12020000) - -#define PSA_ALG_RSA_OAEP_BASE ((psa_algorithm_t)0x12030000) -/** RSA OAEP encryption. - * - * This is the encryption scheme defined by RFC 8017 - * (PKCS#1: RSA Cryptography Specifications) under the name - * RSAES-OAEP, with the message generation function MGF1. - * - * \param hash_alg The hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true) to use - * for MGF1. - * - * \return The corresponding RSA OAEP signature algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_RSA_OAEP(hash_alg) \ - (PSA_ALG_RSA_OAEP_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) -#define PSA_ALG_IS_RSA_OAEP(alg) \ - (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_OAEP_BASE) -#define PSA_ALG_RSA_OAEP_GET_HASH(alg) \ - (PSA_ALG_IS_RSA_OAEP(alg) ? \ - ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ - 0) - -#define PSA_ALG_HKDF_BASE ((psa_algorithm_t)0x20000100) -/** Macro to build an HKDF algorithm. - * - * For example, `PSA_ALG_HKDF(PSA_ALG_SHA256)` is HKDF using HMAC-SHA-256. - * - * This key derivation algorithm uses the following inputs: - * - #PSA_KEY_DERIVATION_INPUT_SALT is the salt used in the "extract" step. - * It is optional; if omitted, the derivation uses an empty salt. - * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key used in the "extract" step. - * - #PSA_KEY_DERIVATION_INPUT_INFO is the info string used in the "expand" step. - * You must pass #PSA_KEY_DERIVATION_INPUT_SALT before #PSA_KEY_DERIVATION_INPUT_SECRET. - * You may pass #PSA_KEY_DERIVATION_INPUT_INFO at any time after steup and before - * starting to generate output. - * - * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true). - * - * \return The corresponding HKDF algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_HKDF(hash_alg) \ - (PSA_ALG_HKDF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) -/** Whether the specified algorithm is an HKDF algorithm. - * - * HKDF is a family of key derivation algorithms that are based on a hash - * function and the HMAC construction. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \c alg is an HKDF algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \c alg is not a supported - * key derivation algorithm identifier. - */ -#define PSA_ALG_IS_HKDF(alg) \ - (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_BASE) -#define PSA_ALG_HKDF_GET_HASH(hkdf_alg) \ - (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) - -#define PSA_ALG_TLS12_PRF_BASE ((psa_algorithm_t)0x20000200) -/** Macro to build a TLS-1.2 PRF algorithm. - * - * TLS 1.2 uses a custom pseudorandom function (PRF) for key schedule, - * specified in Section 5 of RFC 5246. It is based on HMAC and can be - * used with either SHA-256 or SHA-384. - * - * This key derivation algorithm uses the following inputs, which must be - * passed in the order given here: - * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed. - * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key. - * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label. - * - * For the application to TLS-1.2 key expansion, the seed is the - * concatenation of ServerHello.Random + ClientHello.Random, - * and the label is "key expansion". - * - * For example, `PSA_ALG_TLS12_PRF(PSA_ALG_SHA256)` represents the - * TLS 1.2 PRF using HMAC-SHA-256. - * - * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true). - * - * \return The corresponding TLS-1.2 PRF algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_TLS12_PRF(hash_alg) \ - (PSA_ALG_TLS12_PRF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) - -/** Whether the specified algorithm is a TLS-1.2 PRF algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \c alg is a TLS-1.2 PRF algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \c alg is not a supported - * key derivation algorithm identifier. - */ -#define PSA_ALG_IS_TLS12_PRF(alg) \ - (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_TLS12_PRF_BASE) -#define PSA_ALG_TLS12_PRF_GET_HASH(hkdf_alg) \ - (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) - -#define PSA_ALG_TLS12_PSK_TO_MS_BASE ((psa_algorithm_t)0x20000300) -/** Macro to build a TLS-1.2 PSK-to-MasterSecret algorithm. - * - * In a pure-PSK handshake in TLS 1.2, the master secret is derived - * from the PreSharedKey (PSK) through the application of padding - * (RFC 4279, Section 2) and the TLS-1.2 PRF (RFC 5246, Section 5). - * The latter is based on HMAC and can be used with either SHA-256 - * or SHA-384. - * - * This key derivation algorithm uses the following inputs, which must be - * passed in the order given here: - * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed. - * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key. - * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label. - * - * For the application to TLS-1.2, the seed (which is - * forwarded to the TLS-1.2 PRF) is the concatenation of the - * ClientHello.Random + ServerHello.Random, - * and the label is "master secret" or "extended master secret". - * - * For example, `PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA256)` represents the - * TLS-1.2 PSK to MasterSecret derivation PRF using HMAC-SHA-256. - * - * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true). - * - * \return The corresponding TLS-1.2 PSK to MS algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_TLS12_PSK_TO_MS(hash_alg) \ - (PSA_ALG_TLS12_PSK_TO_MS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) - -/** Whether the specified algorithm is a TLS-1.2 PSK to MS algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \c alg is a TLS-1.2 PSK to MS algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \c alg is not a supported - * key derivation algorithm identifier. - */ -#define PSA_ALG_IS_TLS12_PSK_TO_MS(alg) \ - (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_TLS12_PSK_TO_MS_BASE) -#define PSA_ALG_TLS12_PSK_TO_MS_GET_HASH(hkdf_alg) \ - (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) - -#define PSA_ALG_KEY_DERIVATION_MASK ((psa_algorithm_t)0x0803ffff) -#define PSA_ALG_KEY_AGREEMENT_MASK ((psa_algorithm_t)0x10fc0000) - -/** Macro to build a combined algorithm that chains a key agreement with - * a key derivation. - * - * \param ka_alg A key agreement algorithm (\c PSA_ALG_XXX value such - * that #PSA_ALG_IS_KEY_AGREEMENT(\p ka_alg) is true). - * \param kdf_alg A key derivation algorithm (\c PSA_ALG_XXX value such - * that #PSA_ALG_IS_KEY_DERIVATION(\p kdf_alg) is true). - * - * \return The corresponding key agreement and derivation - * algorithm. - * \return Unspecified if \p ka_alg is not a supported - * key agreement algorithm or \p kdf_alg is not a - * supported key derivation algorithm. - */ -#define PSA_ALG_KEY_AGREEMENT(ka_alg, kdf_alg) \ - ((ka_alg) | (kdf_alg)) - -#define PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) \ - (((alg) & PSA_ALG_KEY_DERIVATION_MASK) | PSA_ALG_CATEGORY_KEY_DERIVATION) - -#define PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) \ - (((alg) & PSA_ALG_KEY_AGREEMENT_MASK) | PSA_ALG_CATEGORY_KEY_AGREEMENT) - -/** Whether the specified algorithm is a raw key agreement algorithm. - * - * A raw key agreement algorithm is one that does not specify - * a key derivation function. - * Usually, raw key agreement algorithms are constructed directly with - * a \c PSA_ALG_xxx macro while non-raw key agreement algorithms are - * constructed with PSA_ALG_KEY_AGREEMENT(). - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a raw key agreement algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_RAW_KEY_AGREEMENT(alg) \ - (PSA_ALG_IS_KEY_AGREEMENT(alg) && \ - PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) == PSA_ALG_CATEGORY_KEY_DERIVATION) - -#define PSA_ALG_IS_KEY_DERIVATION_OR_AGREEMENT(alg) \ - ((PSA_ALG_IS_KEY_DERIVATION(alg) || PSA_ALG_IS_KEY_AGREEMENT(alg))) - -/** The finite-field Diffie-Hellman (DH) key agreement algorithm. - * - * The shared secret produced by key agreement is - * `g^{ab}` in big-endian format. - * It is `ceiling(m / 8)` bytes long where `m` is the size of the prime `p` - * in bits. - */ -#define PSA_ALG_FFDH ((psa_algorithm_t)0x30100000) - -/** Whether the specified algorithm is a finite field Diffie-Hellman algorithm. - * - * This includes the raw finite field Diffie-Hellman algorithm as well as - * finite-field Diffie-Hellman followed by any supporter key derivation - * algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \c alg is a finite field Diffie-Hellman algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \c alg is not a supported - * key agreement algorithm identifier. - */ -#define PSA_ALG_IS_FFDH(alg) \ - (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_FFDH) - -/** The elliptic curve Diffie-Hellman (ECDH) key agreement algorithm. - * - * The shared secret produced by key agreement is the x-coordinate of - * the shared secret point. It is always `ceiling(m / 8)` bytes long where - * `m` is the bit size associated with the curve, i.e. the bit size of the - * order of the curve's coordinate field. When `m` is not a multiple of 8, - * the byte containing the most significant bit of the shared secret - * is padded with zero bits. The byte order is either little-endian - * or big-endian depending on the curve type. - * - * - For Montgomery curves (curve types `PSA_ECC_CURVE_CURVEXXX`), - * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` - * in little-endian byte order. - * The bit size is 448 for Curve448 and 255 for Curve25519. - * - For Weierstrass curves over prime fields (curve types - * `PSA_ECC_CURVE_SECPXXX` and `PSA_ECC_CURVE_BRAINPOOL_PXXX`), - * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` - * in big-endian byte order. - * The bit size is `m = ceiling(log_2(p))` for the field `F_p`. - * - For Weierstrass curves over binary fields (curve types - * `PSA_ECC_CURVE_SECTXXX`), - * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` - * in big-endian byte order. - * The bit size is `m` for the field `F_{2^m}`. - */ -#define PSA_ALG_ECDH ((psa_algorithm_t)0x30200000) - -/** Whether the specified algorithm is an elliptic curve Diffie-Hellman - * algorithm. - * - * This includes the raw elliptic curve Diffie-Hellman algorithm as well as - * elliptic curve Diffie-Hellman followed by any supporter key derivation - * algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \c alg is an elliptic curve Diffie-Hellman algorithm, - * 0 otherwise. - * This macro may return either 0 or 1 if \c alg is not a supported - * key agreement algorithm identifier. - */ -#define PSA_ALG_IS_ECDH(alg) \ - (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_ECDH) - -/** Whether the specified algorithm encoding is a wildcard. - * - * Wildcard values may only be used to set the usage algorithm field in - * a policy, not to perform an operation. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \c alg is a wildcard algorithm encoding. - * \return 0 if \c alg is a non-wildcard algorithm encoding (suitable for - * an operation). - * \return This macro may return either 0 or 1 if \c alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_WILDCARD(alg) \ - (PSA_ALG_IS_HASH_AND_SIGN(alg) ? \ - PSA_ALG_SIGN_GET_HASH(alg) == PSA_ALG_ANY_HASH : \ - (alg) == PSA_ALG_ANY_HASH) - -/**@}*/ - -/** \defgroup key_lifetimes Key lifetimes - * @{ - */ - -/** A volatile key only exists as long as the handle to it is not closed. - * The key material is guaranteed to be erased on a power reset. - */ -#define PSA_KEY_LIFETIME_VOLATILE ((psa_key_lifetime_t)0x00000000) - -/** The default storage area for persistent keys. - * - * A persistent key remains in storage until it is explicitly destroyed or - * until the corresponding storage area is wiped. This specification does - * not define any mechanism to wipe a storage area, but implementations may - * provide their own mechanism (for example to perform a factory reset, - * to prepare for device refurbishment, or to uninstall an application). - * - * This lifetime value is the default storage area for the calling - * application. Implementations may offer other storage areas designated - * by other lifetime values as implementation-specific extensions. - */ -#define PSA_KEY_LIFETIME_PERSISTENT ((psa_key_lifetime_t)0x00000001) - -/** The minimum value for a key identifier chosen by the application. - */ -#define PSA_KEY_ID_USER_MIN ((psa_app_key_id_t)0x00000001) -/** The maximum value for a key identifier chosen by the application. - */ -#define PSA_KEY_ID_USER_MAX ((psa_app_key_id_t)0x3fffffff) -/** The minimum value for a key identifier chosen by the implementation. - */ -#define PSA_KEY_ID_VENDOR_MIN ((psa_app_key_id_t)0x40000000) -/** The maximum value for a key identifier chosen by the implementation. - */ -#define PSA_KEY_ID_VENDOR_MAX ((psa_app_key_id_t)0x7fffffff) - -/**@}*/ - -/** \defgroup policy Key policies - * @{ - */ - -/** Whether the key may be exported. - * - * A public key or the public part of a key pair may always be exported - * regardless of the value of this permission flag. - * - * If a key does not have export permission, implementations shall not - * allow the key to be exported in plain form from the cryptoprocessor, - * whether through psa_export_key() or through a proprietary interface. - * The key may however be exportable in a wrapped form, i.e. in a form - * where it is encrypted by another key. - */ -#define PSA_KEY_USAGE_EXPORT ((psa_key_usage_t)0x00000001) - -/** Whether the key may be copied. - * - * This flag allows the use of psa_copy_key() to make a copy of the key - * with the same policy or a more restrictive policy. - * - * For lifetimes for which the key is located in a secure element which - * enforce the non-exportability of keys, copying a key outside the secure - * element also requires the usage flag #PSA_KEY_USAGE_EXPORT. - * Copying the key inside the secure element is permitted with just - * #PSA_KEY_USAGE_COPY if the secure element supports it. - * For keys with the lifetime #PSA_KEY_LIFETIME_VOLATILE or - * #PSA_KEY_LIFETIME_PERSISTENT, the usage flag #PSA_KEY_USAGE_COPY - * is sufficient to permit the copy. - */ -#define PSA_KEY_USAGE_COPY ((psa_key_usage_t)0x00000002) - -/** Whether the key may be used to encrypt a message. - * - * This flag allows the key to be used for a symmetric encryption operation, - * for an AEAD encryption-and-authentication operation, - * or for an asymmetric encryption operation, - * if otherwise permitted by the key's type and policy. - * - * For a key pair, this concerns the public key. - */ -#define PSA_KEY_USAGE_ENCRYPT ((psa_key_usage_t)0x00000100) - -/** Whether the key may be used to decrypt a message. - * - * This flag allows the key to be used for a symmetric decryption operation, - * for an AEAD decryption-and-verification operation, - * or for an asymmetric decryption operation, - * if otherwise permitted by the key's type and policy. - * - * For a key pair, this concerns the private key. - */ -#define PSA_KEY_USAGE_DECRYPT ((psa_key_usage_t)0x00000200) - -/** Whether the key may be used to sign a message. - * - * This flag allows the key to be used for a MAC calculation operation - * or for an asymmetric signature operation, - * if otherwise permitted by the key's type and policy. - * - * For a key pair, this concerns the private key. - */ -#define PSA_KEY_USAGE_SIGN_HASH ((psa_key_usage_t)0x00000400) - -/** Whether the key may be used to verify a message signature. - * - * This flag allows the key to be used for a MAC verification operation - * or for an asymmetric signature verification operation, - * if otherwise permitted by by the key's type and policy. - * - * For a key pair, this concerns the public key. - */ -#define PSA_KEY_USAGE_VERIFY_HASH ((psa_key_usage_t)0x00000800) - -/** Whether the key may be used to derive other keys. - */ -#define PSA_KEY_USAGE_DERIVE ((psa_key_usage_t)0x00001000) - -/**@}*/ - -/** \defgroup derivation Key derivation - * @{ - */ - -/** A secret input for key derivation. - * - * This should be a key of type #PSA_KEY_TYPE_DERIVE - * (passed to psa_key_derivation_input_key()) - * or the shared secret resulting from a key agreement - * (obtained via psa_key_derivation_key_agreement()). - * - * The secret can also be a direct input (passed to - * key_derivation_input_bytes()). In this case, the derivation operation - * may not be used to derive keys: the operation will only allow - * psa_key_derivation_output_bytes(), not psa_key_derivation_output_key(). - */ -#define PSA_KEY_DERIVATION_INPUT_SECRET ((psa_key_derivation_step_t)0x0101) - -/** A label for key derivation. - * - * This should be a direct input. - * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. - */ -#define PSA_KEY_DERIVATION_INPUT_LABEL ((psa_key_derivation_step_t)0x0201) - -/** A salt for key derivation. - * - * This should be a direct input. - * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. - */ -#define PSA_KEY_DERIVATION_INPUT_SALT ((psa_key_derivation_step_t)0x0202) - -/** An information string for key derivation. - * - * This should be a direct input. - * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. - */ -#define PSA_KEY_DERIVATION_INPUT_INFO ((psa_key_derivation_step_t)0x0203) - -/** A seed for key derivation. - * - * This should be a direct input. - * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. - */ -#define PSA_KEY_DERIVATION_INPUT_SEED ((psa_key_derivation_step_t)0x0204) - -/**@}*/ - -#endif /* PSA_CRYPTO_VALUES_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/error.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/error.h deleted file mode 100644 index ba0e0e3..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/error.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -* Copyright (c) 2019 ARM Limited. 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. -*/ - -/* psa/error.h -Standard error codes for the SPM and RoT Services -As defined in PSA Firmware Framework v1.0 -*/ - -#ifndef __PSA_ERROR__ -#define __PSA_ERROR__ - -#include -#include - -typedef int32_t psa_status_t; - -#define PSA_SUCCESS ((psa_status_t)0) - -#define PSA_ERROR_PROGRAMMER_ERROR ((psa_status_t)-129) -#define PSA_ERROR_CONNECTION_REFUSED ((psa_status_t)-130) -#define PSA_ERROR_CONNECTION_BUSY ((psa_status_t)-131) -#define PSA_ERROR_GENERIC_ERROR ((psa_status_t)-132) -#define PSA_ERROR_NOT_PERMITTED ((psa_status_t)-133) -#define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)-134) -#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)-135) -#define PSA_ERROR_INVALID_HANDLE ((psa_status_t)-136) -#define PSA_ERROR_BAD_STATE ((psa_status_t)-137) -#define PSA_ERROR_BUFFER_TOO_SMALL ((psa_status_t)-138) -#define PSA_ERROR_ALREADY_EXISTS ((psa_status_t)-139) -#define PSA_ERROR_DOES_NOT_EXIST ((psa_status_t)-140) -#define PSA_ERROR_INSUFFICIENT_MEMORY ((psa_status_t)-141) -#define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)-142) -#define PSA_ERROR_INSUFFICIENT_DATA ((psa_status_t)-143) -#define PSA_ERROR_SERVICE_FAILURE ((psa_status_t)-144) -#define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t)-145) -#define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)-146) -#define PSA_ERROR_HARDWARE_FAILURE ((psa_status_t)-147) -#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) -#define PSA_ERROR_DATA_CORRUPT ((psa_status_t)-152) - -#endif // __PSA_ERROR__ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/internal_trusted_storage.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/internal_trusted_storage.h deleted file mode 100644 index 7b3b6a9..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/internal_trusted_storage.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright (c) 2017-2018 ARM Limited - * - * 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 __MBED_INTERNAL_TRUSTED_STORAGE_H__ -#define __MBED_INTERNAL_TRUSTED_STORAGE_H__ - -#include "psa_prot_internal_storage.h" - -#endif // __MBED_INTERNAL_TRUSTED_STORAGE_H__ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/lifecycle.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/lifecycle.h deleted file mode 100644 index 1afa44f..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/lifecycle.h +++ /dev/null @@ -1,79 +0,0 @@ -/* Copyright (c) 2018 ARM Limited - * - * 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 __LIFECYCLE_H__ -#define __LIFECYCLE_H__ - -/** @file -@brief This file describes the PSA RoT Lifecycle API -*/ - -#include -#include -#include "mbed_toolchain.h" -#include "psa/error.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -#define PSA_LIFECYCLE_STATE_MASK (0xff00u) /**< A mask value that extracts the main lifecycle state */ -#define PSA_LIFECYCLE_SUBSTATE_MASK (0x00ffu) /**< A mask value that extracts the IMPLEMENTATION DEFINED lifecycle sub-state */ - -#define PSA_LIFECYCLE_UNKNOWN (0x0000u) /**< State is unknown */ -#define PSA_LIFECYCLE_ASSEMBLY_AND_TEST (0x1000u) /**< Assembly and Test state */ -#define PSA_LIFECYCLE_PSA_ROT_PROVISIONING (0x2000u) /**< PSA RoT Provisioning state */ -#define PSA_LIFECYCLE_SECURED (0x3000u) /**< Secured state */ -#define PSA_LIFECYCLE_NON_PSA_ROT_DEBUG (0x4000u) /**< Non PSA RoT debug state */ -#define PSA_LIFECYCLE_RECOVERABLE_PSA_ROT_DEBUG (0x5000u) /**< Recoverable PSA RoT Debug state */ -#define PSA_LIFECYCLE_DECOMMISSIONED (0x6000u) /**< Decommissioned state */ - -/** \brief Get PSA RoT lifecycle state - * - * \retval The main state and sub-state are encoded as follows:@n - @a version[15:8] – main lifecycle state - @a version[7:0] – IMPLEMENTATION DEFINED sub-state - */ -uint32_t psa_security_lifecycle_state(void); - -/** \brief Request state change - * - * State change requested and the reset the system. - * \note System reset will not be performed when switching from PSA_LIFECYCLE_ASSEMBLY_AND_TEST - * to PSA_LIFECYCLE_ASSEMBLY_AND_TEST. - * - * \note state change to follwing states will delete PSA internal storage: - * - PSA_LIFECYCLE_ASSEMBLY_AND_TEST - * - PSA_LIFECYCLE_PSA_ROT_PROVISIONING - * - PSA_LIFECYCLE_DECOMMISSIONED - */ -psa_status_t mbed_psa_reboot_and_request_new_security_state(uint32_t new_state); - - -/** \brief Resets the system - * - * PSA targets do not allow NSPE to access system power domain. - * This API requests system reset to be carried out by SPE once all critical secure tasks are finished. - */ -MBED_NORETURN void mbed_psa_system_reset(); - -#ifdef __cplusplus -} -#endif - -#endif // __LIFECYCLE_H__ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/protected_storage.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/protected_storage.h deleted file mode 100644 index 6b299a3..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/protected_storage.h +++ /dev/null @@ -1,202 +0,0 @@ -/* Copyright (C) 2019, ARM Limited, 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. - */ - -/** @file -@brief This file describes the PSA Protected Storage API -*/ - -#ifndef __PSA_PROTECTED_STORAGE_H__ -#define __PSA_PROTECTED_STORAGE_H__ - -#include -#include - -#include "psa/error.h" -#include "psa/storage_common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define PSA_PS_API_VERSION_MAJOR 1 /**< The major version number of the PSA PS API. It will be incremented on significant updates that may include breaking changes */ -#define PSA_PS_API_VERSION_MINOR 1 /**< The minor version number of the PSA PS API. It will be incremented in small updates that are unlikely to include breaking changes */ - - -/** - * \brief create a new or modify an existing key/value pair - * - * \param[in] uid the identifier for the data - * \param[in] data_length The size in bytes of the data in `p_data` - * \param[in] p_data A buffer containing the data - * \param[in] create_flags The flags indicating the properties of the data - * - * \return A status indicating the success/failure of the operation - - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the provided uid value was already created with PSA_STORAGE_WRITE_ONCE_FLAG - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more of the given arguments were invalid. - * \retval PSA_ERROR_NOT_SUPPORTED The operation failed because one or more of the flags provided in `create_flags` is not supported or is not valid - * \retval PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because there was insufficient space on the storage medium - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) - * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an unspecified internal failure - */ -psa_status_t psa_ps_set(psa_storage_uid_t uid, - size_t data_length, - const void *p_data, - psa_storage_create_flags_t create_flags); - -/** - * \brief Retrieve the value for a provided uid - * - * \param[in] uid The identifier for the data - * \param[in] data_offset The offset within the data associated with the `uid` to start retrieving data - * \param[in] data_length The amount of data to read (and the minimum allocated size of the `p_data` buffer) - * \param[out] p_data The buffer where the data will be placed upon successful completion - * \param[out] p_data_length The actual amount of data returned - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more of the given arguments were invalid (null pointer, wrong flags etc.) - * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided uid value was not found in the storage - * \retval PSA_ERROR_BUFFER_TOO_SMALL The operation failed because the data associated with provided uid does not fit `data_size` - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) - * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an unspecified internal failure - * \retval PSA_ERROR_DATA_CORRUPT The operation failed because of an authentication failure when attempting to get the key - * \retval PSA_ERROR_INVALID_SIGNATURE The operation failed because the data associated with the UID failed authentication - */ -psa_status_t psa_ps_get(psa_storage_uid_t uid, - size_t data_offset, - size_t data_length, - void *p_data, - size_t *p_data_length); - -/** - * \brief Retrieve the metadata about the provided uid - * - * \param[in] uid The identifier for the data - * \param[out] p_info A pointer to the `psa_storage_info_t` struct that will be populated with the metadata - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more of the given arguments were invalid (null pointer, wrong flags etc.) - * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided uid value was not found in the storage - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) - * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an unspecified internal failure - * \retval PSA_ERROR_DATA_CORRUPT The operation failed because of an authentication failure when attempting to get the key - * \retval PSA_ERROR_INVALID_SIGNATURE The operation failed because the data associated with the UID failed authentication - */ -psa_status_t psa_ps_get_info(psa_storage_uid_t uid, struct psa_storage_info_t *p_info); - -/** - * \brief Remove the provided uid and its associated data from the storage - * - * \param[in] uid The identifier for the data to be removed - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more of the given arguments were invalid (null pointer, wrong flags etc.) - * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided uid value was not found in the storage - * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the provided uid value was created with psa_eps_WRITE_ONCE_FLAG - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) - * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an unspecified internal failure - */ -psa_status_t psa_ps_remove(psa_storage_uid_t uid); - -/** - * Creates an asset based on the given identifier, the maximum size and - * creation flags. This create allocates the space in the secure storage - * area without setting any data in the asset. - * - * It is only necessary to call this function for items that will be written - * with the \ref psa_ps_set_extended function. If only the \ref psa_ps_set function - * is needed, calls to this function are redundant. - * - * If the \ref PSA_STORAGE_FLAG_WRITE_ONCE flag is passed, implementations should - * return \ref PSA_ERROR_NOT_SUPPORTED. - * - * This function is optional. Not all PSA Protected Storage Implementations - * will implement this function. Consult the documentation of your chosen - * platform to determine if it is present. - * - * \param[in] uid A unique identifier for the asset. - * \param[in] size The maximum size in bytes of the asset. - * \param[in] create_flags Create flags \ref psa_storage_create_flags_t. - * - * \retval PSA_SUCCESS The assest does not exist and the input parameters are correct or - * the asset already exists, the input parameters are the same that - * have been used to create the asset and the owner is the same and the current asset content is kept - * TDB: "Owner is the same" doesn't really make sense from a PSA perspective, as each partition - * has its own UID space, making other partitions' data unadressable - * \retval PSA_ERROR_STORAGE_FAILURE The create action has a physical storage error - * \retval PSA_ERROR_INSUFFICIENT_STORAGE The maximum size is bigger of the current available space - * \retval PSA_ERROR_NOT_SUPPORTED One or more create_flags are not valid or supported - * \retval PSA_ERROR_INVALID_ARGUMENT The asset exists and the input paramters are not the same as the existing asset - * \retval PSA_ERROR_NOT_SUPPORTED The implementation of the API does not support this function - * \retval PSA_ERROR_GENERIC_ERROR The operation has failed due to an unspecified error - */ -psa_status_t psa_ps_create(psa_storage_uid_t uid, - size_t size, - psa_storage_create_flags_t create_flags); - -/** - * Sets partial data into an asset based on the given identifier, data_offset, - * data length and p_data. - * - * Before calling this function, the asset must have been created with a call - * to \ref psa_ps_create. - * - * This function is optional. Not all PSA Protected Storage Implementations - * will implement this function. Consult the documentation of your chosen - * platform to determine if it is present. - * - * \param[in] uid The unique identifier for the asset. - * \param[in] data_offset Offset within the asset to start the write. - * \param[in] data_length The size in bytes of the data in p_data to write. - * \param[in] p_data Pointer to a buffer which contains the data to write. - * - * \retval PSA_SUCCESS If the asset exists, the input parameters are correct and the data - * is correctly written in the physical storage - * \retval PSA_ERROR_STORAGE_FAILURE If the data is not written correctly in the physical storage - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more of the given arguments were invalid (null pointer, wrong flags, etc) - * \retval PSA_ERROR_DOES_NOT_EXIST The specified UID was not found - * \retval PSA_ERROR_NOT_SUPPORTED The implementation of the API does not support this function - * \retval PSA_ERROR_GENERIC_ERROR The operation failed due to an unspecified error - * \retval PSA_ERROR_DATA_CORRUPT The operation failed because the existing data has been corrupted - * \retval PSA_ERROR_INVALID_SIGNATURE The operation failed because the existing data failed authentication (MAC check failed) - */ -psa_status_t psa_ps_set_extended(psa_storage_uid_t uid, - size_t data_offset, - size_t data_length, - const void *p_data); - -/** - * Returns a bitmask with flags set for all of the optional features supported - * by the implementation. - * - * Currently defined flags are limited to: - * - \ref PSA_STORAGE_SUPPORT_SET_EXTENDED - */ -uint32_t psa_ps_get_support(void); - -#ifdef __cplusplus -} -#endif - - -#endif // __PSA_PROTECTED_STORAGE_H__ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/service.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/service.h deleted file mode 100644 index ff54f1c..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/service.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright (c) 2017-2020 ARM Limited - * - * 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. - */ - -#if defined(FEATURE_TFM) - -#include "interface/include/psa_service.h" -#include "secure_fw/core/ipc/include/tfm_utils.h" -#define SPM_PANIC(format, ...) tfm_panic() - -#else - -#error "Compiling psa service header on non-secure target is not allowed" - -#endif diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/storage_common.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/storage_common.h deleted file mode 100644 index 1747f14..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/storage_common.h +++ /dev/null @@ -1,64 +0,0 @@ -/* Copyright (C) 2019, ARM Limited, 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. - */ - -/** @file -@brief This file includes common definitions for PSA storage -*/ - -#ifndef __PSA_STORAGE_COMMON_H__ -#define __PSA_STORAGE_COMMON_H__ - -#include -#include -#include "psa/error.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** \brief Flags used when creating a data entry - */ -typedef uint32_t psa_storage_create_flags_t; - -#define PSA_STORAGE_FLAG_NONE 0 /**< No flags to pass */ -#define PSA_STORAGE_FLAG_WRITE_ONCE (1 << 0) /**< The data associated with the uid will not be able to be modified or deleted. Intended to be used to set bits in `psa_storage_create_flags_t`*/ -#define PSA_STORAGE_FLAG_NO_CONFIDENTIALITY (1 << 1) /**< The data associated with the uid is public and therefore does not require confidentiality. It therefore only needs to be integrity protected */ -#define PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION (1 << 2) /**< The data associated with the uid does not require replay protection. This may permit faster storage - but it permits an attecker with physical access to revert to an earlier version of the data. */ - -/** \brief A type for UIDs used for identifying data - */ -typedef uint64_t psa_storage_uid_t; - -/** - * \brief A container for metadata associated with a specific uid - */ -struct psa_storage_info_t { - size_t capacity; /**< The allocated capacity of the storage associated with a UID **/ - size_t size; /**< The size of the data associated with a uid **/ - psa_storage_create_flags_t flags; /**< The flags set when the uid was created **/ -}; - -/** \brief Flag indicating that \ref psa_storage_create and \ref psa_storage_set_extended are supported */ -#define PSA_STORAGE_SUPPORT_SET_EXTENDED (1 << 0) - -/** \brief PSA storage specific error codes */ -#define PSA_ERROR_DATA_CORRUPT ((psa_status_t)-152) - -#ifdef __cplusplus -} -#endif - -#endif // __PSA_STORAGE_COMMON_H__ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbed_lib.json b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbed_lib.json deleted file mode 100644 index e8e5047..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbed_lib.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "psa-services", - "requires": [ - "drivers", - "platform", - "mbedtls", - "storage", - "flashiap-block-device", - "kv-global-api", - "storage_tdb_internal" - ] -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/crypto_struct.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/crypto_struct.h deleted file mode 100644 index 938abd0..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/crypto_struct.h +++ /dev/null @@ -1,473 +0,0 @@ -/** - * \file psa/crypto_struct.h - * - * \brief PSA cryptography module: Mbed TLS structured type implementations - * - * \note This file may not be included directly. Applications must - * include psa/crypto.h. - * - * This file contains the definitions of some data structures with - * implementation-specific definitions. - * - * In implementations with isolation between the application and the - * cryptography module, it is expected that the front-end and the back-end - * would have different versions of this file. - * - *

Design notes about multipart operation structures

- * - * Each multipart operation structure contains a `psa_algorithm_t alg` - * field which indicates which specific algorithm the structure is for. - * When the structure is not in use, `alg` is 0. Most of the structure - * consists of a union which is discriminated by `alg`. - * - * Note that when `alg` is 0, the content of other fields is undefined. - * In particular, it is not guaranteed that a freshly-initialized structure - * is all-zero: we initialize structures to something like `{0, 0}`, which - * is only guaranteed to initializes the first member of the union; - * GCC and Clang initialize the whole structure to 0 (at the time of writing), - * but MSVC and CompCert don't. - * - * In Mbed Crypto, multipart operation structures live independently from - * the key. This allows Mbed Crypto to free the key objects when destroying - * a key slot. If a multipart operation needs to remember the key after - * the setup function returns, the operation structure needs to contain a - * copy of the key. - */ -/* - * Copyright (C) 2018, ARM Limited, 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. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#ifndef PSA_CRYPTO_STRUCT_H -#define PSA_CRYPTO_STRUCT_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Include the Mbed TLS configuration file, the way Mbed TLS does it - * in each of its header files. */ -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "mbedtls/cipher.h" -#include "mbedtls/cmac.h" -#include "mbedtls/gcm.h" -#include "mbedtls/md.h" -#include "mbedtls/md2.h" -#include "mbedtls/md4.h" -#include "mbedtls/md5.h" -#include "mbedtls/ripemd160.h" -#include "mbedtls/sha1.h" -#include "mbedtls/sha256.h" -#include "mbedtls/sha512.h" - -struct psa_hash_operation_s -{ - psa_algorithm_t alg; - union - { - unsigned dummy; /* Make the union non-empty even with no supported algorithms. */ -#if defined(MBEDTLS_MD2_C) - mbedtls_md2_context md2; -#endif -#if defined(MBEDTLS_MD4_C) - mbedtls_md4_context md4; -#endif -#if defined(MBEDTLS_MD5_C) - mbedtls_md5_context md5; -#endif -#if defined(MBEDTLS_RIPEMD160_C) - mbedtls_ripemd160_context ripemd160; -#endif -#if defined(MBEDTLS_SHA1_C) - mbedtls_sha1_context sha1; -#endif -#if defined(MBEDTLS_SHA256_C) - mbedtls_sha256_context sha256; -#endif -#if defined(MBEDTLS_SHA512_C) - mbedtls_sha512_context sha512; -#endif - } ctx; -}; - -#define PSA_HASH_OPERATION_INIT {0, {0}} -static inline struct psa_hash_operation_s psa_hash_operation_init( void ) -{ - const struct psa_hash_operation_s v = PSA_HASH_OPERATION_INIT; - return( v ); -} - -#if defined(MBEDTLS_MD_C) -typedef struct -{ - /** The hash context. */ - struct psa_hash_operation_s hash_ctx; - /** The HMAC part of the context. */ - uint8_t opad[PSA_HMAC_MAX_HASH_BLOCK_SIZE]; -} psa_hmac_internal_data; -#endif /* MBEDTLS_MD_C */ - -struct psa_mac_operation_s -{ - psa_algorithm_t alg; - unsigned int key_set : 1; - unsigned int iv_required : 1; - unsigned int iv_set : 1; - unsigned int has_input : 1; - unsigned int is_sign : 1; - uint8_t mac_size; - union - { - unsigned dummy; /* Make the union non-empty even with no supported algorithms. */ -#if defined(MBEDTLS_MD_C) - psa_hmac_internal_data hmac; -#endif -#if defined(MBEDTLS_CMAC_C) - mbedtls_cipher_context_t cmac; -#endif - } ctx; -}; - -#define PSA_MAC_OPERATION_INIT {0, 0, 0, 0, 0, 0, 0, {0}} -static inline struct psa_mac_operation_s psa_mac_operation_init( void ) -{ - const struct psa_mac_operation_s v = PSA_MAC_OPERATION_INIT; - return( v ); -} - -struct psa_cipher_operation_s -{ - psa_algorithm_t alg; - unsigned int key_set : 1; - unsigned int iv_required : 1; - unsigned int iv_set : 1; - uint8_t iv_size; - uint8_t block_size; - union - { - unsigned dummy; /* Enable easier initializing of the union. */ - mbedtls_cipher_context_t cipher; - } ctx; -}; - -#define PSA_CIPHER_OPERATION_INIT {0, 0, 0, 0, 0, 0, {0}} -static inline struct psa_cipher_operation_s psa_cipher_operation_init( void ) -{ - const struct psa_cipher_operation_s v = PSA_CIPHER_OPERATION_INIT; - return( v ); -} - -struct psa_aead_operation_s -{ - psa_algorithm_t alg; - unsigned int key_set : 1; - unsigned int iv_set : 1; - uint8_t iv_size; - uint8_t block_size; - union - { - unsigned dummy; /* Enable easier initializing of the union. */ - mbedtls_cipher_context_t cipher; - } ctx; -}; - -#define PSA_AEAD_OPERATION_INIT {0, 0, 0, 0, 0, {0}} -static inline struct psa_aead_operation_s psa_aead_operation_init( void ) -{ - const struct psa_aead_operation_s v = PSA_AEAD_OPERATION_INIT; - return( v ); -} - -#if defined(MBEDTLS_MD_C) -typedef struct -{ - uint8_t *info; - size_t info_length; - psa_hmac_internal_data hmac; - uint8_t prk[PSA_HASH_MAX_SIZE]; - uint8_t output_block[PSA_HASH_MAX_SIZE]; -#if PSA_HASH_MAX_SIZE > 0xff -#error "PSA_HASH_MAX_SIZE does not fit in uint8_t" -#endif - uint8_t offset_in_block; - uint8_t block_number; - unsigned int state : 2; - unsigned int info_set : 1; -} psa_hkdf_key_derivation_t; -#endif /* MBEDTLS_MD_C */ - -#if defined(MBEDTLS_MD_C) -typedef enum -{ - TLS12_PRF_STATE_INIT, /* no input provided */ - TLS12_PRF_STATE_SEED_SET, /* seed has been set */ - TLS12_PRF_STATE_KEY_SET, /* key has been set */ - TLS12_PRF_STATE_LABEL_SET, /* label has been set */ - TLS12_PRF_STATE_OUTPUT /* output has been started */ -} psa_tls12_prf_key_derivation_state_t; - -typedef struct psa_tls12_prf_key_derivation_s -{ -#if PSA_HASH_MAX_SIZE > 0xff -#error "PSA_HASH_MAX_SIZE does not fit in uint8_t" -#endif - - /* Indicates how many bytes in the current HMAC block have - * not yet been read by the user. */ - uint8_t left_in_block; - - /* The 1-based number of the block. */ - uint8_t block_number; - - psa_tls12_prf_key_derivation_state_t state; - - uint8_t *seed; - size_t seed_length; - uint8_t *label; - size_t label_length; - psa_hmac_internal_data hmac; - uint8_t Ai[PSA_HASH_MAX_SIZE]; - - /* `HMAC_hash( prk, A(i) + seed )` in the notation of RFC 5246, Sect. 5. */ - uint8_t output_block[PSA_HASH_MAX_SIZE]; -} psa_tls12_prf_key_derivation_t; -#endif /* MBEDTLS_MD_C */ - -struct psa_key_derivation_s -{ - psa_algorithm_t alg; - unsigned int can_output_key : 1; - size_t capacity; - union - { - /* Make the union non-empty even with no supported algorithms. */ - uint8_t dummy; -#if defined(MBEDTLS_MD_C) - psa_hkdf_key_derivation_t hkdf; - psa_tls12_prf_key_derivation_t tls12_prf; -#endif - } ctx; -}; - -/* This only zeroes out the first byte in the union, the rest is unspecified. */ -#define PSA_KEY_DERIVATION_OPERATION_INIT {0, 0, 0, {0}} -static inline struct psa_key_derivation_s psa_key_derivation_operation_init( void ) -{ - const struct psa_key_derivation_s v = PSA_KEY_DERIVATION_OPERATION_INIT; - return( v ); -} - -struct psa_key_policy_s -{ - psa_key_usage_t usage; - psa_algorithm_t alg; - psa_algorithm_t alg2; -}; -typedef struct psa_key_policy_s psa_key_policy_t; - -#define PSA_KEY_POLICY_INIT {0, 0, 0} -static inline struct psa_key_policy_s psa_key_policy_init( void ) -{ - const struct psa_key_policy_s v = PSA_KEY_POLICY_INIT; - return( v ); -} - -/* The type used internally for key sizes. - * Public interfaces use size_t, but internally we use a smaller type. */ -typedef uint16_t psa_key_bits_t; -/* The maximum value of the type used to represent bit-sizes. - * This is used to mark an invalid key size. */ -#define PSA_KEY_BITS_TOO_LARGE ( (psa_key_bits_t) ( -1 ) ) -/* The maximum size of a key in bits. - * Currently defined as the maximum that can be represented, rounded down - * to a whole number of bytes. - * This is an uncast value so that it can be used in preprocessor - * conditionals. */ -#define PSA_MAX_KEY_BITS 0xfff8 - -/** A mask of flags that can be stored in key attributes. - * - * This type is also used internally to store flags in slots. Internal - * flags are defined in library/psa_crypto_core.h. Internal flags may have - * the same value as external flags if they are properly handled during - * key creation and in psa_get_key_attributes. - */ -typedef uint16_t psa_key_attributes_flag_t; - -#define MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER \ - ( (psa_key_attributes_flag_t) 0x0001 ) - -/* A mask of key attribute flags used externally only. - * Only meant for internal checks inside the library. */ -#define MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY ( \ - MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER | \ - 0 ) - -/* A mask of key attribute flags used both internally and externally. - * Currently there aren't any. */ -#define MBEDTLS_PSA_KA_MASK_DUAL_USE ( \ - 0 ) - -typedef struct -{ - psa_key_type_t type; - psa_key_bits_t bits; - psa_key_lifetime_t lifetime; - psa_key_id_t id; - psa_key_policy_t policy; - psa_key_attributes_flag_t flags; -} psa_core_key_attributes_t; - -#define PSA_CORE_KEY_ATTRIBUTES_INIT {PSA_KEY_TYPE_NONE, 0, PSA_KEY_LIFETIME_VOLATILE, PSA_KEY_ID_INIT, PSA_KEY_POLICY_INIT, 0} - -struct psa_key_attributes_s -{ - psa_core_key_attributes_t core; -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - psa_key_slot_number_t slot_number; -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - void *domain_parameters; - size_t domain_parameters_size; -}; - -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) -#define PSA_KEY_ATTRIBUTES_INIT {PSA_CORE_KEY_ATTRIBUTES_INIT, 0, NULL, 0} -#else -#define PSA_KEY_ATTRIBUTES_INIT {PSA_CORE_KEY_ATTRIBUTES_INIT, NULL, 0} -#endif - -static inline struct psa_key_attributes_s psa_key_attributes_init( void ) -{ - const struct psa_key_attributes_s v = PSA_KEY_ATTRIBUTES_INIT; - return( v ); -} - -static inline void psa_set_key_id(psa_key_attributes_t *attributes, - psa_key_id_t id) -{ - attributes->core.id = id; - if( attributes->core.lifetime == PSA_KEY_LIFETIME_VOLATILE ) - attributes->core.lifetime = PSA_KEY_LIFETIME_PERSISTENT; -} - -static inline psa_key_id_t psa_get_key_id( - const psa_key_attributes_t *attributes) -{ - return( attributes->core.id ); -} - -static inline void psa_set_key_lifetime(psa_key_attributes_t *attributes, - psa_key_lifetime_t lifetime) -{ - attributes->core.lifetime = lifetime; - if( lifetime == PSA_KEY_LIFETIME_VOLATILE ) - { -#ifdef MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER - attributes->core.id.key_id = 0; - attributes->core.id.owner = 0; -#else - attributes->core.id = 0; -#endif - } -} - -static inline psa_key_lifetime_t psa_get_key_lifetime( - const psa_key_attributes_t *attributes) -{ - return( attributes->core.lifetime ); -} - -static inline void psa_set_key_usage_flags(psa_key_attributes_t *attributes, - psa_key_usage_t usage_flags) -{ - attributes->core.policy.usage = usage_flags; -} - -static inline psa_key_usage_t psa_get_key_usage_flags( - const psa_key_attributes_t *attributes) -{ - return( attributes->core.policy.usage ); -} - -static inline void psa_set_key_algorithm(psa_key_attributes_t *attributes, - psa_algorithm_t alg) -{ - attributes->core.policy.alg = alg; -} - -static inline psa_algorithm_t psa_get_key_algorithm( - const psa_key_attributes_t *attributes) -{ - return( attributes->core.policy.alg ); -} - -/* This function is declared in crypto_extra.h, which comes after this - * header file, but we need the function here, so repeat the declaration. */ -psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes, - psa_key_type_t type, - const uint8_t *data, - size_t data_length); - -static inline void psa_set_key_type(psa_key_attributes_t *attributes, - psa_key_type_t type) -{ - if( attributes->domain_parameters == NULL ) - { - /* Common case: quick path */ - attributes->core.type = type; - } - else - { - /* Call the bigger function to free the old domain paramteres. - * Ignore any errors which may arise due to type requiring - * non-default domain parameters, since this function can't - * report errors. */ - (void) psa_set_key_domain_parameters( attributes, type, NULL, 0 ); - } -} - -static inline psa_key_type_t psa_get_key_type( - const psa_key_attributes_t *attributes) -{ - return( attributes->core.type ); -} - -static inline void psa_set_key_bits(psa_key_attributes_t *attributes, - size_t bits) -{ - if( bits > PSA_MAX_KEY_BITS ) - attributes->core.bits = PSA_KEY_BITS_TOO_LARGE; - else - attributes->core.bits = (psa_key_bits_t) bits; -} - -static inline size_t psa_get_key_bits( - const psa_key_attributes_t *attributes) -{ - return( attributes->core.bits ); -} - -#ifdef __cplusplus -} -#endif - -#endif /* PSA_CRYPTO_STRUCT_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto.c deleted file mode 100644 index 6932318..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto.c +++ /dev/null @@ -1,5805 +0,0 @@ -/* - * PSA crypto layer on top of Mbed TLS crypto - */ -/* Copyright (C) 2018, ARM Limited, 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. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_PSA_CRYPTO_C) - -#include "psa_crypto_service_integration.h" -#include "psa/crypto.h" - -#include "psa_crypto_core.h" -#include "psa_crypto_invasive.h" -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) -#include "psa_crypto_se.h" -#endif -#include "psa_crypto_slot_management.h" -/* Include internal declarations that are useful for implementing persistently - * stored keys. */ -#include "psa_crypto_storage.h" - -#include -#include -#include -#include "mbedtls/platform.h" -#if !defined(MBEDTLS_PLATFORM_C) -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#include "mbedtls/arc4.h" -#include "mbedtls/asn1.h" -#include "mbedtls/asn1write.h" -#include "mbedtls/bignum.h" -#include "mbedtls/blowfish.h" -#include "mbedtls/camellia.h" -#include "mbedtls/chacha20.h" -#include "mbedtls/chachapoly.h" -#include "mbedtls/cipher.h" -#include "mbedtls/ccm.h" -#include "mbedtls/cmac.h" -#include "mbedtls/ctr_drbg.h" -#include "mbedtls/des.h" -#include "mbedtls/ecdh.h" -#include "mbedtls/ecp.h" -#include "mbedtls/entropy.h" -#include "mbedtls/error.h" -#include "mbedtls/gcm.h" -#include "mbedtls/md2.h" -#include "mbedtls/md4.h" -#include "mbedtls/md5.h" -#include "mbedtls/md.h" -#include "mbedtls/md_internal.h" -#include "mbedtls/pk.h" -#include "mbedtls/pk_internal.h" -#include "mbedtls/platform_util.h" -#include "mbedtls/error.h" -#include "mbedtls/ripemd160.h" -#include "mbedtls/rsa.h" -#include "mbedtls/sha1.h" -#include "mbedtls/sha256.h" -#include "mbedtls/sha512.h" -#include "mbedtls/xtea.h" - -#define ARRAY_LENGTH( array ) ( sizeof( array ) / sizeof( *( array ) ) ) - -/* constant-time buffer comparison */ -static inline int safer_memcmp( const uint8_t *a, const uint8_t *b, size_t n ) -{ - size_t i; - unsigned char diff = 0; - - for( i = 0; i < n; i++ ) - diff |= a[i] ^ b[i]; - - return( diff ); -} - - - -/****************************************************************/ -/* Global data, support functions and library management */ -/****************************************************************/ - -static int key_type_is_raw_bytes( psa_key_type_t type ) -{ - return( PSA_KEY_TYPE_IS_UNSTRUCTURED( type ) ); -} - -/* Values for psa_global_data_t::rng_state */ -#define RNG_NOT_INITIALIZED 0 -#define RNG_INITIALIZED 1 -#define RNG_SEEDED 2 - -typedef struct -{ - void (* entropy_init )( mbedtls_entropy_context *ctx ); - void (* entropy_free )( mbedtls_entropy_context *ctx ); - mbedtls_entropy_context entropy; - mbedtls_ctr_drbg_context ctr_drbg; - unsigned initialized : 1; - unsigned rng_state : 2; -} psa_global_data_t; - -static psa_global_data_t global_data; - -#define GUARD_MODULE_INITIALIZED \ - if( global_data.initialized == 0 ) \ - return( PSA_ERROR_BAD_STATE ); - -static psa_status_t mbedtls_to_psa_error( int ret ) -{ - /* If there's both a high-level code and low-level code, dispatch on - * the high-level code. */ - switch( ret < -0x7f ? - ( -ret & 0x7f80 ) : ret ) - { - case 0: - return( PSA_SUCCESS ); - - case MBEDTLS_ERR_AES_INVALID_KEY_LENGTH: - case MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH: - case MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE: - return( PSA_ERROR_NOT_SUPPORTED ); - case MBEDTLS_ERR_AES_HW_ACCEL_FAILED: - return( PSA_ERROR_HARDWARE_FAILURE ); - - case MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED: - return( PSA_ERROR_HARDWARE_FAILURE ); - - case MBEDTLS_ERR_ASN1_OUT_OF_DATA: - case MBEDTLS_ERR_ASN1_UNEXPECTED_TAG: - case MBEDTLS_ERR_ASN1_INVALID_LENGTH: - case MBEDTLS_ERR_ASN1_LENGTH_MISMATCH: - case MBEDTLS_ERR_ASN1_INVALID_DATA: - return( PSA_ERROR_INVALID_ARGUMENT ); - case MBEDTLS_ERR_ASN1_ALLOC_FAILED: - return( PSA_ERROR_INSUFFICIENT_MEMORY ); - case MBEDTLS_ERR_ASN1_BUF_TOO_SMALL: - return( PSA_ERROR_BUFFER_TOO_SMALL ); - -#if defined(MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA) - case MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA: -#elif defined(MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH) - case MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH: -#endif - case MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH: - return( PSA_ERROR_NOT_SUPPORTED ); - case MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED: - return( PSA_ERROR_HARDWARE_FAILURE ); - -#if defined(MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA) - case MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA: -#elif defined(MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH) - case MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH: -#endif - case MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH: - return( PSA_ERROR_NOT_SUPPORTED ); - case MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED: - return( PSA_ERROR_HARDWARE_FAILURE ); - - case MBEDTLS_ERR_CCM_BAD_INPUT: - return( PSA_ERROR_INVALID_ARGUMENT ); - case MBEDTLS_ERR_CCM_AUTH_FAILED: - return( PSA_ERROR_INVALID_SIGNATURE ); - case MBEDTLS_ERR_CCM_HW_ACCEL_FAILED: - return( PSA_ERROR_HARDWARE_FAILURE ); - - case MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA: - return( PSA_ERROR_INVALID_ARGUMENT ); - - case MBEDTLS_ERR_CHACHAPOLY_BAD_STATE: - return( PSA_ERROR_BAD_STATE ); - case MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED: - return( PSA_ERROR_INVALID_SIGNATURE ); - - case MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE: - return( PSA_ERROR_NOT_SUPPORTED ); - case MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA: - return( PSA_ERROR_INVALID_ARGUMENT ); - case MBEDTLS_ERR_CIPHER_ALLOC_FAILED: - return( PSA_ERROR_INSUFFICIENT_MEMORY ); - case MBEDTLS_ERR_CIPHER_INVALID_PADDING: - return( PSA_ERROR_INVALID_PADDING ); - case MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED: - return( PSA_ERROR_BAD_STATE ); - case MBEDTLS_ERR_CIPHER_AUTH_FAILED: - return( PSA_ERROR_INVALID_SIGNATURE ); - case MBEDTLS_ERR_CIPHER_INVALID_CONTEXT: - return( PSA_ERROR_CORRUPTION_DETECTED ); - case MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED: - return( PSA_ERROR_HARDWARE_FAILURE ); - - case MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED: - return( PSA_ERROR_HARDWARE_FAILURE ); - - case MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED: - return( PSA_ERROR_INSUFFICIENT_ENTROPY ); - case MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG: - case MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG: - return( PSA_ERROR_NOT_SUPPORTED ); - case MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR: - return( PSA_ERROR_INSUFFICIENT_ENTROPY ); - - case MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH: - return( PSA_ERROR_NOT_SUPPORTED ); - case MBEDTLS_ERR_DES_HW_ACCEL_FAILED: - return( PSA_ERROR_HARDWARE_FAILURE ); - - case MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED: - case MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE: - case MBEDTLS_ERR_ENTROPY_SOURCE_FAILED: - return( PSA_ERROR_INSUFFICIENT_ENTROPY ); - - case MBEDTLS_ERR_GCM_AUTH_FAILED: - return( PSA_ERROR_INVALID_SIGNATURE ); - case MBEDTLS_ERR_GCM_BAD_INPUT: - return( PSA_ERROR_INVALID_ARGUMENT ); - case MBEDTLS_ERR_GCM_HW_ACCEL_FAILED: - return( PSA_ERROR_HARDWARE_FAILURE ); - - case MBEDTLS_ERR_MD2_HW_ACCEL_FAILED: - case MBEDTLS_ERR_MD4_HW_ACCEL_FAILED: - case MBEDTLS_ERR_MD5_HW_ACCEL_FAILED: - return( PSA_ERROR_HARDWARE_FAILURE ); - - case MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE: - return( PSA_ERROR_NOT_SUPPORTED ); - case MBEDTLS_ERR_MD_BAD_INPUT_DATA: - return( PSA_ERROR_INVALID_ARGUMENT ); - case MBEDTLS_ERR_MD_ALLOC_FAILED: - return( PSA_ERROR_INSUFFICIENT_MEMORY ); - case MBEDTLS_ERR_MD_FILE_IO_ERROR: - return( PSA_ERROR_STORAGE_FAILURE ); - case MBEDTLS_ERR_MD_HW_ACCEL_FAILED: - return( PSA_ERROR_HARDWARE_FAILURE ); - - case MBEDTLS_ERR_MPI_FILE_IO_ERROR: - return( PSA_ERROR_STORAGE_FAILURE ); - case MBEDTLS_ERR_MPI_BAD_INPUT_DATA: - return( PSA_ERROR_INVALID_ARGUMENT ); - case MBEDTLS_ERR_MPI_INVALID_CHARACTER: - return( PSA_ERROR_INVALID_ARGUMENT ); - case MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL: - return( PSA_ERROR_BUFFER_TOO_SMALL ); - case MBEDTLS_ERR_MPI_NEGATIVE_VALUE: - return( PSA_ERROR_INVALID_ARGUMENT ); - case MBEDTLS_ERR_MPI_DIVISION_BY_ZERO: - return( PSA_ERROR_INVALID_ARGUMENT ); - case MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: - return( PSA_ERROR_INVALID_ARGUMENT ); - case MBEDTLS_ERR_MPI_ALLOC_FAILED: - return( PSA_ERROR_INSUFFICIENT_MEMORY ); - - case MBEDTLS_ERR_PK_ALLOC_FAILED: - return( PSA_ERROR_INSUFFICIENT_MEMORY ); - case MBEDTLS_ERR_PK_TYPE_MISMATCH: - case MBEDTLS_ERR_PK_BAD_INPUT_DATA: - return( PSA_ERROR_INVALID_ARGUMENT ); - case MBEDTLS_ERR_PK_FILE_IO_ERROR: - return( PSA_ERROR_STORAGE_FAILURE ); - case MBEDTLS_ERR_PK_KEY_INVALID_VERSION: - case MBEDTLS_ERR_PK_KEY_INVALID_FORMAT: - return( PSA_ERROR_INVALID_ARGUMENT ); - case MBEDTLS_ERR_PK_UNKNOWN_PK_ALG: - return( PSA_ERROR_NOT_SUPPORTED ); - case MBEDTLS_ERR_PK_PASSWORD_REQUIRED: - case MBEDTLS_ERR_PK_PASSWORD_MISMATCH: - return( PSA_ERROR_NOT_PERMITTED ); - case MBEDTLS_ERR_PK_INVALID_PUBKEY: - return( PSA_ERROR_INVALID_ARGUMENT ); - case MBEDTLS_ERR_PK_INVALID_ALG: - case MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE: - case MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE: - return( PSA_ERROR_NOT_SUPPORTED ); - case MBEDTLS_ERR_PK_SIG_LEN_MISMATCH: - return( PSA_ERROR_INVALID_SIGNATURE ); - case MBEDTLS_ERR_PK_HW_ACCEL_FAILED: - return( PSA_ERROR_HARDWARE_FAILURE ); - - case MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED: - return( PSA_ERROR_HARDWARE_FAILURE ); - case MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED: - return( PSA_ERROR_NOT_SUPPORTED ); - - case MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED: - return( PSA_ERROR_HARDWARE_FAILURE ); - - case MBEDTLS_ERR_RSA_BAD_INPUT_DATA: - return( PSA_ERROR_INVALID_ARGUMENT ); - case MBEDTLS_ERR_RSA_INVALID_PADDING: - return( PSA_ERROR_INVALID_PADDING ); - case MBEDTLS_ERR_RSA_KEY_GEN_FAILED: - return( PSA_ERROR_HARDWARE_FAILURE ); - case MBEDTLS_ERR_RSA_KEY_CHECK_FAILED: - return( PSA_ERROR_INVALID_ARGUMENT ); - case MBEDTLS_ERR_RSA_PUBLIC_FAILED: - case MBEDTLS_ERR_RSA_PRIVATE_FAILED: - return( PSA_ERROR_CORRUPTION_DETECTED ); - case MBEDTLS_ERR_RSA_VERIFY_FAILED: - return( PSA_ERROR_INVALID_SIGNATURE ); - case MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE: - return( PSA_ERROR_BUFFER_TOO_SMALL ); - case MBEDTLS_ERR_RSA_RNG_FAILED: - return( PSA_ERROR_INSUFFICIENT_MEMORY ); - case MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION: - return( PSA_ERROR_NOT_SUPPORTED ); - case MBEDTLS_ERR_RSA_HW_ACCEL_FAILED: - return( PSA_ERROR_HARDWARE_FAILURE ); - - case MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED: - case MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED: - case MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED: - return( PSA_ERROR_HARDWARE_FAILURE ); - - case MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH: - return( PSA_ERROR_INVALID_ARGUMENT ); - case MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED: - return( PSA_ERROR_HARDWARE_FAILURE ); - - case MBEDTLS_ERR_ECP_BAD_INPUT_DATA: - case MBEDTLS_ERR_ECP_INVALID_KEY: - return( PSA_ERROR_INVALID_ARGUMENT ); - case MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL: - return( PSA_ERROR_BUFFER_TOO_SMALL ); - case MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE: - return( PSA_ERROR_NOT_SUPPORTED ); - case MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH: - case MBEDTLS_ERR_ECP_VERIFY_FAILED: - return( PSA_ERROR_INVALID_SIGNATURE ); - case MBEDTLS_ERR_ECP_ALLOC_FAILED: - return( PSA_ERROR_INSUFFICIENT_MEMORY ); - case MBEDTLS_ERR_ECP_HW_ACCEL_FAILED: - return( PSA_ERROR_HARDWARE_FAILURE ); - case MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED: - return( PSA_ERROR_CORRUPTION_DETECTED ); - - default: - return( PSA_ERROR_GENERIC_ERROR ); - } -} - - - - -/****************************************************************/ -/* Key management */ -/****************************************************************/ - -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) -static inline int psa_key_slot_is_external( const psa_key_slot_t *slot ) -{ - return( psa_key_lifetime_is_external( slot->attr.lifetime ) ); -} -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - -#if defined(MBEDTLS_ECP_C) -mbedtls_ecp_group_id mbedtls_ecc_group_of_psa( psa_ecc_curve_t curve, - size_t byte_length ) -{ - switch( curve ) - { - case PSA_ECC_CURVE_SECP_R1: - switch( byte_length ) - { - case PSA_BITS_TO_BYTES( 192 ): - return( MBEDTLS_ECP_DP_SECP192R1 ); - case PSA_BITS_TO_BYTES( 224 ): - return( MBEDTLS_ECP_DP_SECP224R1 ); - case PSA_BITS_TO_BYTES( 256 ): - return( MBEDTLS_ECP_DP_SECP256R1 ); - case PSA_BITS_TO_BYTES( 384 ): - return( MBEDTLS_ECP_DP_SECP384R1 ); - case PSA_BITS_TO_BYTES( 521 ): - return( MBEDTLS_ECP_DP_SECP521R1 ); - default: - return( MBEDTLS_ECP_DP_NONE ); - } - break; - - case PSA_ECC_CURVE_BRAINPOOL_P_R1: - switch( byte_length ) - { - case PSA_BITS_TO_BYTES( 256 ): - return( MBEDTLS_ECP_DP_BP256R1 ); - case PSA_BITS_TO_BYTES( 384 ): - return( MBEDTLS_ECP_DP_BP384R1 ); - case PSA_BITS_TO_BYTES( 512 ): - return( MBEDTLS_ECP_DP_BP512R1 ); - default: - return( MBEDTLS_ECP_DP_NONE ); - } - break; - - case PSA_ECC_CURVE_MONTGOMERY: - switch( byte_length ) - { - case PSA_BITS_TO_BYTES( 255 ): - return( MBEDTLS_ECP_DP_CURVE25519 ); - case PSA_BITS_TO_BYTES( 448 ): - return( MBEDTLS_ECP_DP_CURVE448 ); - default: - return( MBEDTLS_ECP_DP_NONE ); - } - break; - - case PSA_ECC_CURVE_SECP_K1: - switch( byte_length ) - { - case PSA_BITS_TO_BYTES( 192 ): - return( MBEDTLS_ECP_DP_SECP192K1 ); - case PSA_BITS_TO_BYTES( 224 ): - return( MBEDTLS_ECP_DP_SECP224K1 ); - case PSA_BITS_TO_BYTES( 256 ): - return( MBEDTLS_ECP_DP_SECP256K1 ); - default: - return( MBEDTLS_ECP_DP_NONE ); - } - break; - - default: - return( MBEDTLS_ECP_DP_NONE ); - } -} -#endif /* defined(MBEDTLS_ECP_C) */ - -static psa_status_t prepare_raw_data_slot( psa_key_type_t type, - size_t bits, - struct raw_data *raw ) -{ - /* Check that the bit size is acceptable for the key type */ - switch( type ) - { - case PSA_KEY_TYPE_RAW_DATA: -#if defined(MBEDTLS_MD_C) - case PSA_KEY_TYPE_HMAC: -#endif - case PSA_KEY_TYPE_DERIVE: - break; -#if defined(MBEDTLS_AES_C) - case PSA_KEY_TYPE_AES: - if( bits != 128 && bits != 192 && bits != 256 ) - return( PSA_ERROR_INVALID_ARGUMENT ); - break; -#endif -#if defined(MBEDTLS_CAMELLIA_C) - case PSA_KEY_TYPE_CAMELLIA: - if( bits != 128 && bits != 192 && bits != 256 ) - return( PSA_ERROR_INVALID_ARGUMENT ); - break; -#endif -#if defined(MBEDTLS_DES_C) - case PSA_KEY_TYPE_DES: - if( bits != 64 && bits != 128 && bits != 192 ) - return( PSA_ERROR_INVALID_ARGUMENT ); - break; -#endif -#if defined(MBEDTLS_ARC4_C) - case PSA_KEY_TYPE_ARC4: - if( bits < 8 || bits > 2048 ) - return( PSA_ERROR_INVALID_ARGUMENT ); - break; -#endif -#if defined(MBEDTLS_CHACHA20_C) - case PSA_KEY_TYPE_CHACHA20: - if( bits != 256 ) - return( PSA_ERROR_INVALID_ARGUMENT ); - break; -#endif - default: - return( PSA_ERROR_NOT_SUPPORTED ); - } - if( bits % 8 != 0 ) - return( PSA_ERROR_INVALID_ARGUMENT ); - - /* Allocate memory for the key */ - raw->bytes = PSA_BITS_TO_BYTES( bits ); - raw->data = mbedtls_calloc( 1, raw->bytes ); - if( raw->data == NULL ) - { - raw->bytes = 0; - return( PSA_ERROR_INSUFFICIENT_MEMORY ); - } - return( PSA_SUCCESS ); -} - -#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_PARSE_C) -/* Mbed TLS doesn't support non-byte-aligned key sizes (i.e. key sizes - * that are not a multiple of 8) well. For example, there is only - * mbedtls_rsa_get_len(), which returns a number of bytes, and no - * way to return the exact bit size of a key. - * To keep things simple, reject non-byte-aligned key sizes. */ -static psa_status_t psa_check_rsa_key_byte_aligned( - const mbedtls_rsa_context *rsa ) -{ - mbedtls_mpi n; - psa_status_t status; - mbedtls_mpi_init( &n ); - status = mbedtls_to_psa_error( - mbedtls_rsa_export( rsa, &n, NULL, NULL, NULL, NULL ) ); - if( status == PSA_SUCCESS ) - { - if( mbedtls_mpi_bitlen( &n ) % 8 != 0 ) - status = PSA_ERROR_NOT_SUPPORTED; - } - mbedtls_mpi_free( &n ); - return( status ); -} - -static psa_status_t psa_import_rsa_key( psa_key_type_t type, - const uint8_t *data, - size_t data_length, - mbedtls_rsa_context **p_rsa ) -{ - psa_status_t status; - mbedtls_pk_context pk; - mbedtls_rsa_context *rsa; - size_t bits; - - mbedtls_pk_init( &pk ); - - /* Parse the data. */ - if( PSA_KEY_TYPE_IS_KEY_PAIR( type ) ) - status = mbedtls_to_psa_error( - mbedtls_pk_parse_key( &pk, data, data_length, NULL, 0 ) ); - else - status = mbedtls_to_psa_error( - mbedtls_pk_parse_public_key( &pk, data, data_length ) ); - if( status != PSA_SUCCESS ) - goto exit; - - /* We have something that the pkparse module recognizes. If it is a - * valid RSA key, store it. */ - if( mbedtls_pk_get_type( &pk ) != MBEDTLS_PK_RSA ) - { - status = PSA_ERROR_INVALID_ARGUMENT; - goto exit; - } - - rsa = mbedtls_pk_rsa( pk ); - /* The size of an RSA key doesn't have to be a multiple of 8. Mbed TLS - * supports non-byte-aligned key sizes, but not well. For example, - * mbedtls_rsa_get_len() returns the key size in bytes, not in bits. */ - bits = PSA_BYTES_TO_BITS( mbedtls_rsa_get_len( rsa ) ); - if( bits > PSA_VENDOR_RSA_MAX_KEY_BITS ) - { - status = PSA_ERROR_NOT_SUPPORTED; - goto exit; - } - status = psa_check_rsa_key_byte_aligned( rsa ); - -exit: - /* Free the content of the pk object only on error. */ - if( status != PSA_SUCCESS ) - { - mbedtls_pk_free( &pk ); - return( status ); - } - - /* On success, store the content of the object in the RSA context. */ - *p_rsa = rsa; - - return( PSA_SUCCESS ); -} -#endif /* defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_PARSE_C) */ - -#if defined(MBEDTLS_ECP_C) -static psa_status_t psa_prepare_import_ec_key( psa_ecc_curve_t curve, - size_t data_length, - int is_public, - mbedtls_ecp_keypair **p_ecp ) -{ - mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE; - *p_ecp = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) ); - if( *p_ecp == NULL ) - return( PSA_ERROR_INSUFFICIENT_MEMORY ); - mbedtls_ecp_keypair_init( *p_ecp ); - - if( is_public ) - { - /* A public key is represented as: - * - The byte 0x04; - * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; - * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. - * So its data length is 2m+1 where n is the key size in bits. - */ - if( ( data_length & 1 ) == 0 ) - return( PSA_ERROR_INVALID_ARGUMENT ); - data_length = data_length / 2; - } - - /* Load the group. */ - grp_id = mbedtls_ecc_group_of_psa( curve, data_length ); - if( grp_id == MBEDTLS_ECP_DP_NONE ) - return( PSA_ERROR_INVALID_ARGUMENT ); - return( mbedtls_to_psa_error( - mbedtls_ecp_group_load( &( *p_ecp )->grp, grp_id ) ) ); -} - -/* Import a public key given as the uncompressed representation defined by SEC1 - * 2.3.3 as the content of an ECPoint. */ -static psa_status_t psa_import_ec_public_key( psa_ecc_curve_t curve, - const uint8_t *data, - size_t data_length, - mbedtls_ecp_keypair **p_ecp ) -{ - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - mbedtls_ecp_keypair *ecp = NULL; - - status = psa_prepare_import_ec_key( curve, data_length, 1, &ecp ); - if( status != PSA_SUCCESS ) - goto exit; - - /* Load the public value. */ - status = mbedtls_to_psa_error( - mbedtls_ecp_point_read_binary( &ecp->grp, &ecp->Q, - data, data_length ) ); - if( status != PSA_SUCCESS ) - goto exit; - - /* Check that the point is on the curve. */ - status = mbedtls_to_psa_error( - mbedtls_ecp_check_pubkey( &ecp->grp, &ecp->Q ) ); - if( status != PSA_SUCCESS ) - goto exit; - - *p_ecp = ecp; - return( PSA_SUCCESS ); - -exit: - if( ecp != NULL ) - { - mbedtls_ecp_keypair_free( ecp ); - mbedtls_free( ecp ); - } - return( status ); -} - -/* Import a private key given as a byte string which is the private value - * in big-endian order. */ -static psa_status_t psa_import_ec_private_key( psa_ecc_curve_t curve, - const uint8_t *data, - size_t data_length, - mbedtls_ecp_keypair **p_ecp ) -{ - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - mbedtls_ecp_keypair *ecp = NULL; - - status = psa_prepare_import_ec_key( curve, data_length, 0, &ecp ); - if( status != PSA_SUCCESS ) - goto exit; - - /* Load the secret value. */ - status = mbedtls_to_psa_error( - mbedtls_mpi_read_binary( &ecp->d, data, data_length ) ); - if( status != PSA_SUCCESS ) - goto exit; - /* Validate the private key. */ - status = mbedtls_to_psa_error( - mbedtls_ecp_check_privkey( &ecp->grp, &ecp->d ) ); - if( status != PSA_SUCCESS ) - goto exit; - /* Calculate the public key from the private key. */ - status = mbedtls_to_psa_error( - mbedtls_ecp_mul( &ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G, - mbedtls_ctr_drbg_random, &global_data.ctr_drbg ) ); - if( status != PSA_SUCCESS ) - goto exit; - - *p_ecp = ecp; - return( PSA_SUCCESS ); - -exit: - if( ecp != NULL ) - { - mbedtls_ecp_keypair_free( ecp ); - mbedtls_free( ecp ); - } - return( status ); -} -#endif /* defined(MBEDTLS_ECP_C) */ - - -/** Return the size of the key in the given slot, in bits. - * - * \param[in] slot A key slot. - * - * \return The key size in bits, read from the metadata in the slot. - */ -static inline size_t psa_get_key_slot_bits( const psa_key_slot_t *slot ) -{ - return( slot->attr.bits ); -} - -/** Calculate the size of the key in the given slot, in bits. - * - * \param[in] slot A key slot containing a transparent key. - * - * \return The key size in bits, calculated from the key data. - */ -static psa_key_bits_t psa_calculate_key_bits( const psa_key_slot_t *slot ) -{ - size_t bits = 0; /* return 0 on an empty slot */ - - if( key_type_is_raw_bytes( slot->attr.type ) ) - bits = PSA_BYTES_TO_BITS( slot->data.raw.bytes ); -#if defined(MBEDTLS_RSA_C) - else if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) - bits = PSA_BYTES_TO_BITS( mbedtls_rsa_get_len( slot->data.rsa ) ); -#endif /* defined(MBEDTLS_RSA_C) */ -#if defined(MBEDTLS_ECP_C) - else if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) - bits = slot->data.ecp->grp.pbits; -#endif /* defined(MBEDTLS_ECP_C) */ - - /* We know that the size fits in psa_key_bits_t thanks to checks - * when the key was created. */ - return( (psa_key_bits_t) bits ); -} - -/** Import key data into a slot. `slot->attr.type` must have been set - * previously. This function assumes that the slot does not contain - * any key material yet. On failure, the slot content is unchanged. */ -psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, - const uint8_t *data, - size_t data_length ) -{ - psa_status_t status = PSA_SUCCESS; - - if( key_type_is_raw_bytes( slot->attr.type ) ) - { - size_t bit_size = PSA_BYTES_TO_BITS( data_length ); - /* Ensure that the bytes-to-bit conversion didn't overflow. */ - if( data_length > SIZE_MAX / 8 ) - return( PSA_ERROR_NOT_SUPPORTED ); - /* Enforce a size limit, and in particular ensure that the bit - * size fits in its representation type. */ - if( bit_size > PSA_MAX_KEY_BITS ) - return( PSA_ERROR_NOT_SUPPORTED ); - status = prepare_raw_data_slot( slot->attr.type, bit_size, - &slot->data.raw ); - if( status != PSA_SUCCESS ) - return( status ); - if( data_length != 0 ) - memcpy( slot->data.raw.data, data, data_length ); - } - else -#if defined(MBEDTLS_ECP_C) - if( PSA_KEY_TYPE_IS_ECC_KEY_PAIR( slot->attr.type ) ) - { - status = psa_import_ec_private_key( PSA_KEY_TYPE_GET_CURVE( slot->attr.type ), - data, data_length, - &slot->data.ecp ); - } - else if( PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY( slot->attr.type ) ) - { - status = psa_import_ec_public_key( - PSA_KEY_TYPE_GET_CURVE( slot->attr.type ), - data, data_length, - &slot->data.ecp ); - } - else -#endif /* MBEDTLS_ECP_C */ -#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_PARSE_C) - if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) - { - status = psa_import_rsa_key( slot->attr.type, - data, data_length, - &slot->data.rsa ); - } - else -#endif /* defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_PARSE_C) */ - { - return( PSA_ERROR_NOT_SUPPORTED ); - } - - if( status == PSA_SUCCESS ) - { - /* Write the actual key size to the slot. - * psa_start_key_creation() wrote the size declared by the - * caller, which may be 0 (meaning unspecified) or wrong. */ - slot->attr.bits = psa_calculate_key_bits( slot ); - } - return( status ); -} - -/** Calculate the intersection of two algorithm usage policies. - * - * Return 0 (which allows no operation) on incompatibility. - */ -static psa_algorithm_t psa_key_policy_algorithm_intersection( - psa_algorithm_t alg1, - psa_algorithm_t alg2 ) -{ - /* Common case: both sides actually specify the same policy. */ - if( alg1 == alg2 ) - return( alg1 ); - /* If the policies are from the same hash-and-sign family, check - * if one is a wildcard. If so the other has the specific algorithm. */ - if( PSA_ALG_IS_HASH_AND_SIGN( alg1 ) && - PSA_ALG_IS_HASH_AND_SIGN( alg2 ) && - ( alg1 & ~PSA_ALG_HASH_MASK ) == ( alg2 & ~PSA_ALG_HASH_MASK ) ) - { - if( PSA_ALG_SIGN_GET_HASH( alg1 ) == PSA_ALG_ANY_HASH ) - return( alg2 ); - if( PSA_ALG_SIGN_GET_HASH( alg2 ) == PSA_ALG_ANY_HASH ) - return( alg1 ); - } - /* If the policies are incompatible, allow nothing. */ - return( 0 ); -} - -static int psa_key_algorithm_permits( psa_algorithm_t policy_alg, - psa_algorithm_t requested_alg ) -{ - /* Common case: the policy only allows requested_alg. */ - if( requested_alg == policy_alg ) - return( 1 ); - /* If policy_alg is a hash-and-sign with a wildcard for the hash, - * and requested_alg is the same hash-and-sign family with any hash, - * then requested_alg is compliant with policy_alg. */ - if( PSA_ALG_IS_HASH_AND_SIGN( requested_alg ) && - PSA_ALG_SIGN_GET_HASH( policy_alg ) == PSA_ALG_ANY_HASH ) - { - return( ( policy_alg & ~PSA_ALG_HASH_MASK ) == - ( requested_alg & ~PSA_ALG_HASH_MASK ) ); - } - /* If it isn't permitted, it's forbidden. */ - return( 0 ); -} - -/** Test whether a policy permits an algorithm. - * - * The caller must test usage flags separately. - */ -static int psa_key_policy_permits( const psa_key_policy_t *policy, - psa_algorithm_t alg ) -{ - return( psa_key_algorithm_permits( policy->alg, alg ) || - psa_key_algorithm_permits( policy->alg2, alg ) ); -} - -/** Restrict a key policy based on a constraint. - * - * \param[in,out] policy The policy to restrict. - * \param[in] constraint The policy constraint to apply. - * - * \retval #PSA_SUCCESS - * \c *policy contains the intersection of the original value of - * \c *policy and \c *constraint. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \c *policy and \c *constraint are incompatible. - * \c *policy is unchanged. - */ -static psa_status_t psa_restrict_key_policy( - psa_key_policy_t *policy, - const psa_key_policy_t *constraint ) -{ - psa_algorithm_t intersection_alg = - psa_key_policy_algorithm_intersection( policy->alg, constraint->alg ); - psa_algorithm_t intersection_alg2 = - psa_key_policy_algorithm_intersection( policy->alg2, constraint->alg2 ); - if( intersection_alg == 0 && policy->alg != 0 && constraint->alg != 0 ) - return( PSA_ERROR_INVALID_ARGUMENT ); - if( intersection_alg2 == 0 && policy->alg2 != 0 && constraint->alg2 != 0 ) - return( PSA_ERROR_INVALID_ARGUMENT ); - policy->usage &= constraint->usage; - policy->alg = intersection_alg; - policy->alg2 = intersection_alg2; - return( PSA_SUCCESS ); -} - -/** Retrieve a slot which must contain a key. The key must have allow all the - * usage flags set in \p usage. If \p alg is nonzero, the key must allow - * operations with this algorithm. */ -static psa_status_t psa_get_key_from_slot( psa_key_handle_t handle, - psa_key_slot_t **p_slot, - psa_key_usage_t usage, - psa_algorithm_t alg ) -{ - psa_status_t status; - psa_key_slot_t *slot = NULL; - - *p_slot = NULL; - - status = psa_get_key_slot( handle, &slot ); - if( status != PSA_SUCCESS ) - return( status ); - - /* Enforce that usage policy for the key slot contains all the flags - * required by the usage parameter. There is one exception: public - * keys can always be exported, so we treat public key objects as - * if they had the export flag. */ - if( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->attr.type ) ) - usage &= ~PSA_KEY_USAGE_EXPORT; - if( ( slot->attr.policy.usage & usage ) != usage ) - return( PSA_ERROR_NOT_PERMITTED ); - - /* Enforce that the usage policy permits the requested algortihm. */ - if( alg != 0 && ! psa_key_policy_permits( &slot->attr.policy, alg ) ) - return( PSA_ERROR_NOT_PERMITTED ); - - *p_slot = slot; - return( PSA_SUCCESS ); -} - -/** Retrieve a slot which must contain a transparent key. - * - * A transparent key is a key for which the key material is directly - * available, as opposed to a key in a secure element. - * - * This is a temporary function to use instead of psa_get_key_from_slot() - * until secure element support is fully implemented. - */ -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) -static psa_status_t psa_get_transparent_key( psa_key_handle_t handle, - psa_key_slot_t **p_slot, - psa_key_usage_t usage, - psa_algorithm_t alg ) -{ - psa_status_t status = psa_get_key_from_slot( handle, p_slot, usage, alg ); - if( status != PSA_SUCCESS ) - return( status ); - if( psa_key_slot_is_external( *p_slot ) ) - { - *p_slot = NULL; - return( PSA_ERROR_NOT_SUPPORTED ); - } - return( PSA_SUCCESS ); -} -#else /* MBEDTLS_PSA_CRYPTO_SE_C */ -/* With no secure element support, all keys are transparent. */ -#define psa_get_transparent_key( handle, p_slot, usage, alg ) \ - psa_get_key_from_slot( handle, p_slot, usage, alg ) -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - -/** Wipe key data from a slot. Preserve metadata such as the policy. */ -static psa_status_t psa_remove_key_data_from_memory( psa_key_slot_t *slot ) -{ -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - if( psa_key_slot_is_external( slot ) ) - { - /* No key material to clean. */ - } - else -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - if( slot->attr.type == PSA_KEY_TYPE_NONE ) - { - /* No key material to clean. */ - } - else if( key_type_is_raw_bytes( slot->attr.type ) ) - { - mbedtls_free( slot->data.raw.data ); - } - else -#if defined(MBEDTLS_RSA_C) - if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) - { - mbedtls_rsa_free( slot->data.rsa ); - mbedtls_free( slot->data.rsa ); - } - else -#endif /* defined(MBEDTLS_RSA_C) */ -#if defined(MBEDTLS_ECP_C) - if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) - { - mbedtls_ecp_keypair_free( slot->data.ecp ); - mbedtls_free( slot->data.ecp ); - } - else -#endif /* defined(MBEDTLS_ECP_C) */ - { - /* Shouldn't happen: the key type is not any type that we - * put in. */ - return( PSA_ERROR_CORRUPTION_DETECTED ); - } - - return( PSA_SUCCESS ); -} - -/** Completely wipe a slot in memory, including its policy. - * Persistent storage is not affected. */ -psa_status_t psa_wipe_key_slot( psa_key_slot_t *slot ) -{ - psa_status_t status = psa_remove_key_data_from_memory( slot ); - /* Multipart operations may still be using the key. This is safe - * because all multipart operation objects are independent from - * the key slot: if they need to access the key after the setup - * phase, they have a copy of the key. Note that this means that - * key material can linger until all operations are completed. */ - /* At this point, key material and other type-specific content has - * been wiped. Clear remaining metadata. We can call memset and not - * zeroize because the metadata is not particularly sensitive. */ - memset( slot, 0, sizeof( *slot ) ); - return( status ); -} - -psa_status_t psa_destroy_key( psa_key_handle_t handle ) -{ - psa_key_slot_t *slot; - psa_status_t status; /* status of the last operation */ - psa_status_t overall_status = PSA_SUCCESS; -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - psa_se_drv_table_entry_t *driver; -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - - if( handle == 0 ) - return( PSA_SUCCESS ); - - status = psa_get_key_slot( handle, &slot ); - if( status != PSA_SUCCESS ) - return( status ); - -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - driver = psa_get_se_driver_entry( slot->attr.lifetime ); - if( driver != NULL ) - { - /* For a key in a secure element, we need to do three things: - * remove the key file in internal storage, destroy the - * key inside the secure element, and update the driver's - * persistent data. Start a transaction that will encompass these - * three actions. */ - psa_crypto_prepare_transaction( PSA_CRYPTO_TRANSACTION_DESTROY_KEY ); - psa_crypto_transaction.key.lifetime = slot->attr.lifetime; - psa_crypto_transaction.key.slot = slot->data.se.slot_number; - psa_crypto_transaction.key.id = slot->attr.id; - status = psa_crypto_save_transaction( ); - if( status != PSA_SUCCESS ) - { - (void) psa_crypto_stop_transaction( ); - /* We should still try to destroy the key in the secure - * element and the key metadata in storage. This is especially - * important if the error is that the storage is full. - * But how to do it exactly without risking an inconsistent - * state after a reset? - * https://github.com/ARMmbed/mbed-crypto/issues/215 - */ - overall_status = status; - goto exit; - } - - status = psa_destroy_se_key( driver, slot->data.se.slot_number ); - if( overall_status == PSA_SUCCESS ) - overall_status = status; - } -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - -#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) - if( slot->attr.lifetime != PSA_KEY_LIFETIME_VOLATILE ) - { - status = psa_destroy_persistent_key( slot->attr.id ); - if( overall_status == PSA_SUCCESS ) - overall_status = status; - - /* TODO: other slots may have a copy of the same key. We should - * invalidate them. - * https://github.com/ARMmbed/mbed-crypto/issues/214 - */ - } -#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ - -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - if( driver != NULL ) - { - status = psa_save_se_persistent_data( driver ); - if( overall_status == PSA_SUCCESS ) - overall_status = status; - status = psa_crypto_stop_transaction( ); - if( overall_status == PSA_SUCCESS ) - overall_status = status; - } -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) -exit: -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - status = psa_wipe_key_slot( slot ); - /* Prioritize CORRUPTION_DETECTED from wiping over a storage error */ - if( overall_status == PSA_SUCCESS ) - overall_status = status; - return( overall_status ); -} - -void psa_reset_key_attributes( psa_key_attributes_t *attributes ) -{ - mbedtls_free( attributes->domain_parameters ); - memset( attributes, 0, sizeof( *attributes ) ); -} - -psa_status_t psa_set_key_domain_parameters( psa_key_attributes_t *attributes, - psa_key_type_t type, - const uint8_t *data, - size_t data_length ) -{ - uint8_t *copy = NULL; - - if( data_length != 0 ) - { - copy = mbedtls_calloc( 1, data_length ); - if( copy == NULL ) - return( PSA_ERROR_INSUFFICIENT_MEMORY ); - memcpy( copy, data, data_length ); - } - /* After this point, this function is guaranteed to succeed, so it - * can start modifying `*attributes`. */ - - if( attributes->domain_parameters != NULL ) - { - mbedtls_free( attributes->domain_parameters ); - attributes->domain_parameters = NULL; - attributes->domain_parameters_size = 0; - } - - attributes->domain_parameters = copy; - attributes->domain_parameters_size = data_length; - attributes->core.type = type; - return( PSA_SUCCESS ); -} - -psa_status_t psa_get_key_domain_parameters( - const psa_key_attributes_t *attributes, - uint8_t *data, size_t data_size, size_t *data_length ) -{ - if( attributes->domain_parameters_size > data_size ) - return( PSA_ERROR_BUFFER_TOO_SMALL ); - *data_length = attributes->domain_parameters_size; - if( attributes->domain_parameters_size != 0 ) - memcpy( data, attributes->domain_parameters, - attributes->domain_parameters_size ); - return( PSA_SUCCESS ); -} - -#if defined(MBEDTLS_RSA_C) -static psa_status_t psa_get_rsa_public_exponent( - const mbedtls_rsa_context *rsa, - psa_key_attributes_t *attributes ) -{ - mbedtls_mpi mpi; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - uint8_t *buffer = NULL; - size_t buflen; - mbedtls_mpi_init( &mpi ); - - ret = mbedtls_rsa_export( rsa, NULL, NULL, NULL, NULL, &mpi ); - if( ret != 0 ) - goto exit; - if( mbedtls_mpi_cmp_int( &mpi, 65537 ) == 0 ) - { - /* It's the default value, which is reported as an empty string, - * so there's nothing to do. */ - goto exit; - } - - buflen = mbedtls_mpi_size( &mpi ); - buffer = mbedtls_calloc( 1, buflen ); - if( buffer == NULL ) - { - ret = MBEDTLS_ERR_MPI_ALLOC_FAILED; - goto exit; - } - ret = mbedtls_mpi_write_binary( &mpi, buffer, buflen ); - if( ret != 0 ) - goto exit; - attributes->domain_parameters = buffer; - attributes->domain_parameters_size = buflen; - -exit: - mbedtls_mpi_free( &mpi ); - if( ret != 0 ) - mbedtls_free( buffer ); - return( mbedtls_to_psa_error( ret ) ); -} -#endif /* MBEDTLS_RSA_C */ - -/** Retrieve all the publicly-accessible attributes of a key. - */ -psa_status_t psa_get_key_attributes( psa_key_handle_t handle, - psa_key_attributes_t *attributes ) -{ - psa_key_slot_t *slot; - psa_status_t status; - - psa_reset_key_attributes( attributes ); - - status = psa_get_key_from_slot( handle, &slot, 0, 0 ); - if( status != PSA_SUCCESS ) - return( status ); - - attributes->core = slot->attr; - attributes->core.flags &= ( MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY | - MBEDTLS_PSA_KA_MASK_DUAL_USE ); - -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - if( psa_key_slot_is_external( slot ) ) - psa_set_key_slot_number( attributes, slot->data.se.slot_number ); -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - - switch( slot->attr.type ) - { -#if defined(MBEDTLS_RSA_C) - case PSA_KEY_TYPE_RSA_KEY_PAIR: - case PSA_KEY_TYPE_RSA_PUBLIC_KEY: -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - /* TODO: reporting the public exponent for opaque keys - * is not yet implemented. - * https://github.com/ARMmbed/mbed-crypto/issues/216 - */ - if( psa_key_slot_is_external( slot ) ) - break; -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - status = psa_get_rsa_public_exponent( slot->data.rsa, attributes ); - break; -#endif /* MBEDTLS_RSA_C */ - default: - /* Nothing else to do. */ - break; - } - - if( status != PSA_SUCCESS ) - psa_reset_key_attributes( attributes ); - return( status ); -} - -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) -psa_status_t psa_get_key_slot_number( - const psa_key_attributes_t *attributes, - psa_key_slot_number_t *slot_number ) -{ - if( attributes->core.flags & MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER ) - { - *slot_number = attributes->slot_number; - return( PSA_SUCCESS ); - } - else - return( PSA_ERROR_INVALID_ARGUMENT ); -} -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - -#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECP_C) -static int pk_write_pubkey_simple( mbedtls_pk_context *key, - unsigned char *buf, size_t size ) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char *c; - size_t len = 0; - - c = buf + size; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, key ) ); - - return( (int) len ); -} -#endif /* defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECP_C) */ - -static psa_status_t psa_internal_export_key( const psa_key_slot_t *slot, - uint8_t *data, - size_t data_size, - size_t *data_length, - int export_public_key ) -{ -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - const psa_drv_se_t *drv; - psa_drv_se_context_t *drv_context; -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - - *data_length = 0; - - if( export_public_key && ! PSA_KEY_TYPE_IS_ASYMMETRIC( slot->attr.type ) ) - return( PSA_ERROR_INVALID_ARGUMENT ); - - /* Reject a zero-length output buffer now, since this can never be a - * valid key representation. This way we know that data must be a valid - * pointer and we can do things like memset(data, ..., data_size). */ - if( data_size == 0 ) - return( PSA_ERROR_BUFFER_TOO_SMALL ); - -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) ) - { - psa_drv_se_export_key_t method; - if( drv->key_management == NULL ) - return( PSA_ERROR_NOT_SUPPORTED ); - method = ( export_public_key ? - drv->key_management->p_export_public : - drv->key_management->p_export ); - if( method == NULL ) - return( PSA_ERROR_NOT_SUPPORTED ); - return( method( drv_context, - slot->data.se.slot_number, - data, data_size, data_length ) ); - } -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - - if( key_type_is_raw_bytes( slot->attr.type ) ) - { - if( slot->data.raw.bytes > data_size ) - return( PSA_ERROR_BUFFER_TOO_SMALL ); - memcpy( data, slot->data.raw.data, slot->data.raw.bytes ); - memset( data + slot->data.raw.bytes, 0, - data_size - slot->data.raw.bytes ); - *data_length = slot->data.raw.bytes; - return( PSA_SUCCESS ); - } -#if defined(MBEDTLS_ECP_C) - if( PSA_KEY_TYPE_IS_ECC_KEY_PAIR( slot->attr.type ) && !export_public_key ) - { - psa_status_t status; - - size_t bytes = PSA_BITS_TO_BYTES( slot->attr.bits ); - if( bytes > data_size ) - return( PSA_ERROR_BUFFER_TOO_SMALL ); - status = mbedtls_to_psa_error( - mbedtls_mpi_write_binary( &slot->data.ecp->d, data, bytes ) ); - if( status != PSA_SUCCESS ) - return( status ); - memset( data + bytes, 0, data_size - bytes ); - *data_length = bytes; - return( PSA_SUCCESS ); - } -#endif - else - { -#if defined(MBEDTLS_PK_WRITE_C) - if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) || - PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) - { - mbedtls_pk_context pk; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) - { -#if defined(MBEDTLS_RSA_C) - mbedtls_pk_init( &pk ); - pk.pk_info = &mbedtls_rsa_info; - pk.pk_ctx = slot->data.rsa; -#else - return( PSA_ERROR_NOT_SUPPORTED ); -#endif - } - else - { -#if defined(MBEDTLS_ECP_C) - mbedtls_pk_init( &pk ); - pk.pk_info = &mbedtls_eckey_info; - pk.pk_ctx = slot->data.ecp; -#else - return( PSA_ERROR_NOT_SUPPORTED ); -#endif - } - if( export_public_key || PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->attr.type ) ) - { - ret = pk_write_pubkey_simple( &pk, data, data_size ); - } - else - { - ret = mbedtls_pk_write_key_der( &pk, data, data_size ); - } - if( ret < 0 ) - { - memset( data, 0, data_size ); - return( mbedtls_to_psa_error( ret ) ); - } - /* The mbedtls_pk_xxx functions write to the end of the buffer. - * Move the data to the beginning and erase remaining data - * at the original location. */ - if( 2 * (size_t) ret <= data_size ) - { - memcpy( data, data + data_size - ret, ret ); - memset( data + data_size - ret, 0, ret ); - } - else if( (size_t) ret < data_size ) - { - memmove( data, data + data_size - ret, ret ); - memset( data + ret, 0, data_size - ret ); - } - *data_length = ret; - return( PSA_SUCCESS ); - } - else -#endif /* defined(MBEDTLS_PK_WRITE_C) */ - { - /* This shouldn't happen in the reference implementation, but - it is valid for a special-purpose implementation to omit - support for exporting certain key types. */ - return( PSA_ERROR_NOT_SUPPORTED ); - } - } -} - -psa_status_t psa_export_key( psa_key_handle_t handle, - uint8_t *data, - size_t data_size, - size_t *data_length ) -{ - psa_key_slot_t *slot; - psa_status_t status; - - /* Set the key to empty now, so that even when there are errors, we always - * set data_length to a value between 0 and data_size. On error, setting - * the key to empty is a good choice because an empty key representation is - * unlikely to be accepted anywhere. */ - *data_length = 0; - - /* Export requires the EXPORT flag. There is an exception for public keys, - * which don't require any flag, but psa_get_key_from_slot takes - * care of this. */ - status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_EXPORT, 0 ); - if( status != PSA_SUCCESS ) - return( status ); - return( psa_internal_export_key( slot, data, data_size, - data_length, 0 ) ); -} - -psa_status_t psa_export_public_key( psa_key_handle_t handle, - uint8_t *data, - size_t data_size, - size_t *data_length ) -{ - psa_key_slot_t *slot; - psa_status_t status; - - /* Set the key to empty now, so that even when there are errors, we always - * set data_length to a value between 0 and data_size. On error, setting - * the key to empty is a good choice because an empty key representation is - * unlikely to be accepted anywhere. */ - *data_length = 0; - - /* Exporting a public key doesn't require a usage flag. */ - status = psa_get_key_from_slot( handle, &slot, 0, 0 ); - if( status != PSA_SUCCESS ) - return( status ); - return( psa_internal_export_key( slot, data, data_size, - data_length, 1 ) ); -} - -#if defined(static_assert) -static_assert( ( MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_DUAL_USE ) == 0, - "One or more key attribute flag is listed as both external-only and dual-use" ); -static_assert( ( PSA_KA_MASK_INTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_DUAL_USE ) == 0, - "One or more key attribute flag is listed as both internal-only and dual-use" ); -static_assert( ( PSA_KA_MASK_INTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY ) == 0, - "One or more key attribute flag is listed as both internal-only and external-only" ); -#endif - -/** Validate that a key policy is internally well-formed. - * - * This function only rejects invalid policies. It does not validate the - * consistency of the policy with respect to other attributes of the key - * such as the key type. - */ -static psa_status_t psa_validate_key_policy( const psa_key_policy_t *policy ) -{ - if( ( policy->usage & ~( PSA_KEY_USAGE_EXPORT | - PSA_KEY_USAGE_COPY | - PSA_KEY_USAGE_ENCRYPT | - PSA_KEY_USAGE_DECRYPT | - PSA_KEY_USAGE_SIGN_HASH | - PSA_KEY_USAGE_VERIFY_HASH | - PSA_KEY_USAGE_DERIVE ) ) != 0 ) - return( PSA_ERROR_INVALID_ARGUMENT ); - - return( PSA_SUCCESS ); -} - -/** Validate the internal consistency of key attributes. - * - * This function only rejects invalid attribute values. If does not - * validate the consistency of the attributes with any key data that may - * be involved in the creation of the key. - * - * Call this function early in the key creation process. - * - * \param[in] attributes Key attributes for the new key. - * \param[out] p_drv On any return, the driver for the key, if any. - * NULL for a transparent key. - * - */ -static psa_status_t psa_validate_key_attributes( - const psa_key_attributes_t *attributes, - psa_se_drv_table_entry_t **p_drv ) -{ - psa_status_t status; - - if( attributes->core.lifetime != PSA_KEY_LIFETIME_VOLATILE ) - { - status = psa_validate_persistent_key_parameters( - attributes->core.lifetime, attributes->core.id, - p_drv, 1 ); - if( status != PSA_SUCCESS ) - return( status ); - } - - status = psa_validate_key_policy( &attributes->core.policy ); - if( status != PSA_SUCCESS ) - return( status ); - - /* Refuse to create overly large keys. - * Note that this doesn't trigger on import if the attributes don't - * explicitly specify a size (so psa_get_key_bits returns 0), so - * psa_import_key() needs its own checks. */ - if( psa_get_key_bits( attributes ) > PSA_MAX_KEY_BITS ) - return( PSA_ERROR_NOT_SUPPORTED ); - - /* Reject invalid flags. These should not be reachable through the API. */ - if( attributes->core.flags & ~ ( MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY | - MBEDTLS_PSA_KA_MASK_DUAL_USE ) ) - return( PSA_ERROR_INVALID_ARGUMENT ); - - return( PSA_SUCCESS ); -} - -/** Prepare a key slot to receive key material. - * - * This function allocates a key slot and sets its metadata. - * - * If this function fails, call psa_fail_key_creation(). - * - * This function is intended to be used as follows: - * -# Call psa_start_key_creation() to allocate a key slot, prepare - * it with the specified attributes, and assign it a handle. - * -# Populate the slot with the key material. - * -# Call psa_finish_key_creation() to finalize the creation of the slot. - * In case of failure at any step, stop the sequence and call - * psa_fail_key_creation(). - * - * \param method An identification of the calling function. - * \param[in] attributes Key attributes for the new key. - * \param[out] handle On success, a handle for the allocated slot. - * \param[out] p_slot On success, a pointer to the prepared slot. - * \param[out] p_drv On any return, the driver for the key, if any. - * NULL for a transparent key. - * - * \retval #PSA_SUCCESS - * The key slot is ready to receive key material. - * \return If this function fails, the key slot is an invalid state. - * You must call psa_fail_key_creation() to wipe and free the slot. - */ -static psa_status_t psa_start_key_creation( - psa_key_creation_method_t method, - const psa_key_attributes_t *attributes, - psa_key_handle_t *handle, - psa_key_slot_t **p_slot, - psa_se_drv_table_entry_t **p_drv ) -{ - psa_status_t status; - psa_key_slot_t *slot; - - (void) method; - *p_drv = NULL; - - status = psa_validate_key_attributes( attributes, p_drv ); - if( status != PSA_SUCCESS ) - return( status ); - - status = psa_get_empty_key_slot( handle, p_slot ); - if( status != PSA_SUCCESS ) - return( status ); - slot = *p_slot; - - /* We're storing the declared bit-size of the key. It's up to each - * creation mechanism to verify that this information is correct. - * It's automatically correct for mechanisms that use the bit-size as - * an input (generate, device) but not for those where the bit-size - * is optional (import, copy). */ - - slot->attr = attributes->core; - - /* Erase external-only flags from the internal copy. To access - * external-only flags, query `attributes`. Thanks to the check - * in psa_validate_key_attributes(), this leaves the dual-use - * flags and any internal flag that psa_get_empty_key_slot() - * may have set. */ - slot->attr.flags &= ~MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY; - -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - /* For a key in a secure element, we need to do three things - * when creating or registering a key: - * create the key file in internal storage, create the - * key inside the secure element, and update the driver's - * persistent data. Start a transaction that will encompass these - * three actions. */ - /* The first thing to do is to find a slot number for the new key. - * We save the slot number in persistent storage as part of the - * transaction data. It will be needed to recover if the power - * fails during the key creation process, to clean up on the secure - * element side after restarting. Obtaining a slot number from the - * secure element driver updates its persistent state, but we do not yet - * save the driver's persistent state, so that if the power fails, - * we can roll back to a state where the key doesn't exist. */ - if( *p_drv != NULL ) - { - status = psa_find_se_slot_for_key( attributes, method, *p_drv, - &slot->data.se.slot_number ); - if( status != PSA_SUCCESS ) - return( status ); - psa_crypto_prepare_transaction( PSA_CRYPTO_TRANSACTION_CREATE_KEY ); - psa_crypto_transaction.key.lifetime = slot->attr.lifetime; - psa_crypto_transaction.key.slot = slot->data.se.slot_number; - psa_crypto_transaction.key.id = slot->attr.id; - status = psa_crypto_save_transaction( ); - if( status != PSA_SUCCESS ) - { - (void) psa_crypto_stop_transaction( ); - return( status ); - } - } - - if( *p_drv == NULL && method == PSA_KEY_CREATION_REGISTER ) - { - /* Key registration only makes sense with a secure element. */ - return( PSA_ERROR_INVALID_ARGUMENT ); - } -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - - return( status ); -} - -/** Finalize the creation of a key once its key material has been set. - * - * This entails writing the key to persistent storage. - * - * If this function fails, call psa_fail_key_creation(). - * See the documentation of psa_start_key_creation() for the intended use - * of this function. - * - * \param[in,out] slot Pointer to the slot with key material. - * \param[in] driver The secure element driver for the key, - * or NULL for a transparent key. - * - * \retval #PSA_SUCCESS - * The key was successfully created. The handle is now valid. - * \return If this function fails, the key slot is an invalid state. - * You must call psa_fail_key_creation() to wipe and free the slot. - */ -static psa_status_t psa_finish_key_creation( - psa_key_slot_t *slot, - psa_se_drv_table_entry_t *driver ) -{ - psa_status_t status = PSA_SUCCESS; - (void) slot; - (void) driver; - -#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) - if( slot->attr.lifetime != PSA_KEY_LIFETIME_VOLATILE ) - { -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - if( driver != NULL ) - { - psa_se_key_data_storage_t data; -#if defined(static_assert) - static_assert( sizeof( slot->data.se.slot_number ) == - sizeof( data.slot_number ), - "Slot number size does not match psa_se_key_data_storage_t" ); - static_assert( sizeof( slot->attr.bits ) == sizeof( data.bits ), - "Bit-size size does not match psa_se_key_data_storage_t" ); -#endif - memcpy( &data.slot_number, &slot->data.se.slot_number, - sizeof( slot->data.se.slot_number ) ); - memcpy( &data.bits, &slot->attr.bits, - sizeof( slot->attr.bits ) ); - status = psa_save_persistent_key( &slot->attr, - (uint8_t*) &data, - sizeof( data ) ); - } - else -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - { - size_t buffer_size = - PSA_KEY_EXPORT_MAX_SIZE( slot->attr.type, - slot->attr.bits ); - uint8_t *buffer = mbedtls_calloc( 1, buffer_size ); - size_t length = 0; - if( buffer == NULL ) - return( PSA_ERROR_INSUFFICIENT_MEMORY ); - status = psa_internal_export_key( slot, - buffer, buffer_size, &length, - 0 ); - if( status == PSA_SUCCESS ) - status = psa_save_persistent_key( &slot->attr, - buffer, length ); - - mbedtls_platform_zeroize( buffer, buffer_size ); - mbedtls_free( buffer ); - } - } -#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ - -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - /* Finish the transaction for a key creation. This does not - * happen when registering an existing key. Detect this case - * by checking whether a transaction is in progress (actual - * creation of a key in a secure element requires a transaction, - * but registration doesn't use one). */ - if( driver != NULL && - psa_crypto_transaction.unknown.type == PSA_CRYPTO_TRANSACTION_CREATE_KEY ) - { - status = psa_save_se_persistent_data( driver ); - if( status != PSA_SUCCESS ) - { - psa_destroy_persistent_key( slot->attr.id ); - return( status ); - } - status = psa_crypto_stop_transaction( ); - if( status != PSA_SUCCESS ) - return( status ); - } -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - - return( status ); -} - -/** Abort the creation of a key. - * - * You may call this function after calling psa_start_key_creation(), - * or after psa_finish_key_creation() fails. In other circumstances, this - * function may not clean up persistent storage. - * See the documentation of psa_start_key_creation() for the intended use - * of this function. - * - * \param[in,out] slot Pointer to the slot with key material. - * \param[in] driver The secure element driver for the key, - * or NULL for a transparent key. - */ -static void psa_fail_key_creation( psa_key_slot_t *slot, - psa_se_drv_table_entry_t *driver ) -{ - (void) driver; - - if( slot == NULL ) - return; - -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - /* TODO: If the key has already been created in the secure - * element, and the failure happened later (when saving metadata - * to internal storage), we need to destroy the key in the secure - * element. - * https://github.com/ARMmbed/mbed-crypto/issues/217 - */ - - /* Abort the ongoing transaction if any (there may not be one if - * the creation process failed before starting one, or if the - * key creation is a registration of a key in a secure element). - * Earlier functions must already have done what it takes to undo any - * partial creation. All that's left is to update the transaction data - * itself. */ - (void) psa_crypto_stop_transaction( ); -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - - psa_wipe_key_slot( slot ); -} - -/** Validate optional attributes during key creation. - * - * Some key attributes are optional during key creation. If they are - * specified in the attributes structure, check that they are consistent - * with the data in the slot. - * - * This function should be called near the end of key creation, after - * the slot in memory is fully populated but before saving persistent data. - */ -static psa_status_t psa_validate_optional_attributes( - const psa_key_slot_t *slot, - const psa_key_attributes_t *attributes ) -{ - if( attributes->core.type != 0 ) - { - if( attributes->core.type != slot->attr.type ) - return( PSA_ERROR_INVALID_ARGUMENT ); - } - - if( attributes->domain_parameters_size != 0 ) - { -#if defined(MBEDTLS_RSA_C) - if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) - { - mbedtls_mpi actual, required; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_mpi_init( &actual ); - mbedtls_mpi_init( &required ); - ret = mbedtls_rsa_export( slot->data.rsa, - NULL, NULL, NULL, NULL, &actual ); - if( ret != 0 ) - goto rsa_exit; - ret = mbedtls_mpi_read_binary( &required, - attributes->domain_parameters, - attributes->domain_parameters_size ); - if( ret != 0 ) - goto rsa_exit; - if( mbedtls_mpi_cmp_mpi( &actual, &required ) != 0 ) - ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; - rsa_exit: - mbedtls_mpi_free( &actual ); - mbedtls_mpi_free( &required ); - if( ret != 0) - return( mbedtls_to_psa_error( ret ) ); - } - else -#endif - { - return( PSA_ERROR_INVALID_ARGUMENT ); - } - } - - if( attributes->core.bits != 0 ) - { - if( attributes->core.bits != slot->attr.bits ) - return( PSA_ERROR_INVALID_ARGUMENT ); - } - - return( PSA_SUCCESS ); -} - -psa_status_t psa_import_key( const psa_key_attributes_t *attributes, - const uint8_t *data, - size_t data_length, - psa_key_handle_t *handle ) -{ - psa_status_t status; - psa_key_slot_t *slot = NULL; - psa_se_drv_table_entry_t *driver = NULL; - - /* Reject zero-length symmetric keys (including raw data key objects). - * This also rejects any key which might be encoded as an empty string, - * which is never valid. */ - if( data_length == 0 ) - return( PSA_ERROR_INVALID_ARGUMENT ); - - status = psa_start_key_creation( PSA_KEY_CREATION_IMPORT, attributes, - handle, &slot, &driver ); - if( status != PSA_SUCCESS ) - goto exit; - -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - if( driver != NULL ) - { - const psa_drv_se_t *drv = psa_get_se_driver_methods( driver ); - /* The driver should set the number of key bits, however in - * case it doesn't, we initialize bits to an invalid value. */ - size_t bits = PSA_MAX_KEY_BITS + 1; - if( drv->key_management == NULL || - drv->key_management->p_import == NULL ) - { - status = PSA_ERROR_NOT_SUPPORTED; - goto exit; - } - status = drv->key_management->p_import( - psa_get_se_driver_context( driver ), - slot->data.se.slot_number, attributes, data, data_length, - &bits ); - if( status != PSA_SUCCESS ) - goto exit; - if( bits > PSA_MAX_KEY_BITS ) - { - status = PSA_ERROR_NOT_SUPPORTED; - goto exit; - } - slot->attr.bits = (psa_key_bits_t) bits; - } - else -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - { - status = psa_import_key_into_slot( slot, data, data_length ); - if( status != PSA_SUCCESS ) - goto exit; - } - status = psa_validate_optional_attributes( slot, attributes ); - if( status != PSA_SUCCESS ) - goto exit; - - status = psa_finish_key_creation( slot, driver ); -exit: - if( status != PSA_SUCCESS ) - { - psa_fail_key_creation( slot, driver ); - *handle = 0; - } - return( status ); -} - -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) -psa_status_t mbedtls_psa_register_se_key( - const psa_key_attributes_t *attributes ) -{ - psa_status_t status; - psa_key_slot_t *slot = NULL; - psa_se_drv_table_entry_t *driver = NULL; - psa_key_handle_t handle = 0; - - /* Leaving attributes unspecified is not currently supported. - * It could make sense to query the key type and size from the - * secure element, but not all secure elements support this - * and the driver HAL doesn't currently support it. */ - if( psa_get_key_type( attributes ) == PSA_KEY_TYPE_NONE ) - return( PSA_ERROR_NOT_SUPPORTED ); - if( psa_get_key_bits( attributes ) == 0 ) - return( PSA_ERROR_NOT_SUPPORTED ); - - status = psa_start_key_creation( PSA_KEY_CREATION_REGISTER, attributes, - &handle, &slot, &driver ); - if( status != PSA_SUCCESS ) - goto exit; - - status = psa_finish_key_creation( slot, driver ); - -exit: - if( status != PSA_SUCCESS ) - { - psa_fail_key_creation( slot, driver ); - } - /* Registration doesn't keep the key in RAM. */ - psa_close_key( handle ); - return( status ); -} -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - -static psa_status_t psa_copy_key_material( const psa_key_slot_t *source, - psa_key_slot_t *target ) -{ - psa_status_t status; - uint8_t *buffer = NULL; - size_t buffer_size = 0; - size_t length; - - buffer_size = PSA_KEY_EXPORT_MAX_SIZE( source->attr.type, - psa_get_key_slot_bits( source ) ); - buffer = mbedtls_calloc( 1, buffer_size ); - if( buffer == NULL ) - return( PSA_ERROR_INSUFFICIENT_MEMORY ); - status = psa_internal_export_key( source, buffer, buffer_size, &length, 0 ); - if( status != PSA_SUCCESS ) - goto exit; - target->attr.type = source->attr.type; - status = psa_import_key_into_slot( target, buffer, length ); - -exit: - mbedtls_platform_zeroize( buffer, buffer_size ); - mbedtls_free( buffer ); - return( status ); -} - -psa_status_t psa_copy_key( psa_key_handle_t source_handle, - const psa_key_attributes_t *specified_attributes, - psa_key_handle_t *target_handle ) -{ - psa_status_t status; - psa_key_slot_t *source_slot = NULL; - psa_key_slot_t *target_slot = NULL; - psa_key_attributes_t actual_attributes = *specified_attributes; - psa_se_drv_table_entry_t *driver = NULL; - - status = psa_get_transparent_key( source_handle, &source_slot, - PSA_KEY_USAGE_COPY, 0 ); - if( status != PSA_SUCCESS ) - goto exit; - - status = psa_validate_optional_attributes( source_slot, - specified_attributes ); - if( status != PSA_SUCCESS ) - goto exit; - - status = psa_restrict_key_policy( &actual_attributes.core.policy, - &source_slot->attr.policy ); - if( status != PSA_SUCCESS ) - goto exit; - - status = psa_start_key_creation( PSA_KEY_CREATION_COPY, - &actual_attributes, - target_handle, &target_slot, &driver ); - if( status != PSA_SUCCESS ) - goto exit; - -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - if( driver != NULL ) - { - /* Copying to a secure element is not implemented yet. */ - status = PSA_ERROR_NOT_SUPPORTED; - goto exit; - } -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - - status = psa_copy_key_material( source_slot, target_slot ); - if( status != PSA_SUCCESS ) - goto exit; - - status = psa_finish_key_creation( target_slot, driver ); -exit: - if( status != PSA_SUCCESS ) - { - psa_fail_key_creation( target_slot, driver ); - *target_handle = 0; - } - return( status ); -} - - - -/****************************************************************/ -/* Message digests */ -/****************************************************************/ - -#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_DETERMINISTIC) -static const mbedtls_md_info_t *mbedtls_md_info_from_psa( psa_algorithm_t alg ) -{ - switch( alg ) - { -#if defined(MBEDTLS_MD2_C) - case PSA_ALG_MD2: - return( &mbedtls_md2_info ); -#endif -#if defined(MBEDTLS_MD4_C) - case PSA_ALG_MD4: - return( &mbedtls_md4_info ); -#endif -#if defined(MBEDTLS_MD5_C) - case PSA_ALG_MD5: - return( &mbedtls_md5_info ); -#endif -#if defined(MBEDTLS_RIPEMD160_C) - case PSA_ALG_RIPEMD160: - return( &mbedtls_ripemd160_info ); -#endif -#if defined(MBEDTLS_SHA1_C) - case PSA_ALG_SHA_1: - return( &mbedtls_sha1_info ); -#endif -#if defined(MBEDTLS_SHA256_C) - case PSA_ALG_SHA_224: - return( &mbedtls_sha224_info ); - case PSA_ALG_SHA_256: - return( &mbedtls_sha256_info ); -#endif -#if defined(MBEDTLS_SHA512_C) -#if !defined(MBEDTLS_SHA512_NO_SHA384) - case PSA_ALG_SHA_384: - return( &mbedtls_sha384_info ); -#endif - case PSA_ALG_SHA_512: - return( &mbedtls_sha512_info ); -#endif - default: - return( NULL ); - } -} -#endif - -psa_status_t psa_hash_abort( psa_hash_operation_t *operation ) -{ - switch( operation->alg ) - { - case 0: - /* The object has (apparently) been initialized but it is not - * in use. It's ok to call abort on such an object, and there's - * nothing to do. */ - break; -#if defined(MBEDTLS_MD2_C) - case PSA_ALG_MD2: - mbedtls_md2_free( &operation->ctx.md2 ); - break; -#endif -#if defined(MBEDTLS_MD4_C) - case PSA_ALG_MD4: - mbedtls_md4_free( &operation->ctx.md4 ); - break; -#endif -#if defined(MBEDTLS_MD5_C) - case PSA_ALG_MD5: - mbedtls_md5_free( &operation->ctx.md5 ); - break; -#endif -#if defined(MBEDTLS_RIPEMD160_C) - case PSA_ALG_RIPEMD160: - mbedtls_ripemd160_free( &operation->ctx.ripemd160 ); - break; -#endif -#if defined(MBEDTLS_SHA1_C) - case PSA_ALG_SHA_1: - mbedtls_sha1_free( &operation->ctx.sha1 ); - break; -#endif -#if defined(MBEDTLS_SHA256_C) - case PSA_ALG_SHA_224: - case PSA_ALG_SHA_256: - mbedtls_sha256_free( &operation->ctx.sha256 ); - break; -#endif -#if defined(MBEDTLS_SHA512_C) -#if !defined(MBEDTLS_SHA512_NO_SHA384) - case PSA_ALG_SHA_384: -#endif - case PSA_ALG_SHA_512: - mbedtls_sha512_free( &operation->ctx.sha512 ); - break; -#endif - default: - return( PSA_ERROR_BAD_STATE ); - } - operation->alg = 0; - return( PSA_SUCCESS ); -} - -psa_status_t psa_hash_setup( psa_hash_operation_t *operation, - psa_algorithm_t alg ) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - /* A context must be freshly initialized before it can be set up. */ - if( operation->alg != 0 ) - { - return( PSA_ERROR_BAD_STATE ); - } - - switch( alg ) - { -#if defined(MBEDTLS_MD2_C) - case PSA_ALG_MD2: - mbedtls_md2_init( &operation->ctx.md2 ); - ret = mbedtls_md2_starts_ret( &operation->ctx.md2 ); - break; -#endif -#if defined(MBEDTLS_MD4_C) - case PSA_ALG_MD4: - mbedtls_md4_init( &operation->ctx.md4 ); - ret = mbedtls_md4_starts_ret( &operation->ctx.md4 ); - break; -#endif -#if defined(MBEDTLS_MD5_C) - case PSA_ALG_MD5: - mbedtls_md5_init( &operation->ctx.md5 ); - ret = mbedtls_md5_starts_ret( &operation->ctx.md5 ); - break; -#endif -#if defined(MBEDTLS_RIPEMD160_C) - case PSA_ALG_RIPEMD160: - mbedtls_ripemd160_init( &operation->ctx.ripemd160 ); - ret = mbedtls_ripemd160_starts_ret( &operation->ctx.ripemd160 ); - break; -#endif -#if defined(MBEDTLS_SHA1_C) - case PSA_ALG_SHA_1: - mbedtls_sha1_init( &operation->ctx.sha1 ); - ret = mbedtls_sha1_starts_ret( &operation->ctx.sha1 ); - break; -#endif -#if defined(MBEDTLS_SHA256_C) - case PSA_ALG_SHA_224: - mbedtls_sha256_init( &operation->ctx.sha256 ); - ret = mbedtls_sha256_starts_ret( &operation->ctx.sha256, 1 ); - break; - case PSA_ALG_SHA_256: - mbedtls_sha256_init( &operation->ctx.sha256 ); - ret = mbedtls_sha256_starts_ret( &operation->ctx.sha256, 0 ); - break; -#endif -#if defined(MBEDTLS_SHA512_C) -#if !defined(MBEDTLS_SHA512_NO_SHA384) - case PSA_ALG_SHA_384: - mbedtls_sha512_init( &operation->ctx.sha512 ); - ret = mbedtls_sha512_starts_ret( &operation->ctx.sha512, 1 ); - break; -#endif - case PSA_ALG_SHA_512: - mbedtls_sha512_init( &operation->ctx.sha512 ); - ret = mbedtls_sha512_starts_ret( &operation->ctx.sha512, 0 ); - break; -#endif - default: - return( PSA_ALG_IS_HASH( alg ) ? - PSA_ERROR_NOT_SUPPORTED : - PSA_ERROR_INVALID_ARGUMENT ); - } - if( ret == 0 ) - operation->alg = alg; - else - psa_hash_abort( operation ); - return( mbedtls_to_psa_error( ret ) ); -} - -psa_status_t psa_hash_update( psa_hash_operation_t *operation, - const uint8_t *input, - size_t input_length ) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - /* Don't require hash implementations to behave correctly on a - * zero-length input, which may have an invalid pointer. */ - if( input_length == 0 ) - return( PSA_SUCCESS ); - - switch( operation->alg ) - { -#if defined(MBEDTLS_MD2_C) - case PSA_ALG_MD2: - ret = mbedtls_md2_update_ret( &operation->ctx.md2, - input, input_length ); - break; -#endif -#if defined(MBEDTLS_MD4_C) - case PSA_ALG_MD4: - ret = mbedtls_md4_update_ret( &operation->ctx.md4, - input, input_length ); - break; -#endif -#if defined(MBEDTLS_MD5_C) - case PSA_ALG_MD5: - ret = mbedtls_md5_update_ret( &operation->ctx.md5, - input, input_length ); - break; -#endif -#if defined(MBEDTLS_RIPEMD160_C) - case PSA_ALG_RIPEMD160: - ret = mbedtls_ripemd160_update_ret( &operation->ctx.ripemd160, - input, input_length ); - break; -#endif -#if defined(MBEDTLS_SHA1_C) - case PSA_ALG_SHA_1: - ret = mbedtls_sha1_update_ret( &operation->ctx.sha1, - input, input_length ); - break; -#endif -#if defined(MBEDTLS_SHA256_C) - case PSA_ALG_SHA_224: - case PSA_ALG_SHA_256: - ret = mbedtls_sha256_update_ret( &operation->ctx.sha256, - input, input_length ); - break; -#endif -#if defined(MBEDTLS_SHA512_C) -#if !defined(MBEDTLS_SHA512_NO_SHA384) - case PSA_ALG_SHA_384: -#endif - case PSA_ALG_SHA_512: - ret = mbedtls_sha512_update_ret( &operation->ctx.sha512, - input, input_length ); - break; -#endif - default: - return( PSA_ERROR_BAD_STATE ); - } - - if( ret != 0 ) - psa_hash_abort( operation ); - return( mbedtls_to_psa_error( ret ) ); -} - -psa_status_t psa_hash_finish( psa_hash_operation_t *operation, - uint8_t *hash, - size_t hash_size, - size_t *hash_length ) -{ - psa_status_t status; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t actual_hash_length = PSA_HASH_SIZE( operation->alg ); - - /* Fill the output buffer with something that isn't a valid hash - * (barring an attack on the hash and deliberately-crafted input), - * in case the caller doesn't check the return status properly. */ - *hash_length = hash_size; - /* If hash_size is 0 then hash may be NULL and then the - * call to memset would have undefined behavior. */ - if( hash_size != 0 ) - memset( hash, '!', hash_size ); - - if( hash_size < actual_hash_length ) - { - status = PSA_ERROR_BUFFER_TOO_SMALL; - goto exit; - } - - switch( operation->alg ) - { -#if defined(MBEDTLS_MD2_C) - case PSA_ALG_MD2: - ret = mbedtls_md2_finish_ret( &operation->ctx.md2, hash ); - break; -#endif -#if defined(MBEDTLS_MD4_C) - case PSA_ALG_MD4: - ret = mbedtls_md4_finish_ret( &operation->ctx.md4, hash ); - break; -#endif -#if defined(MBEDTLS_MD5_C) - case PSA_ALG_MD5: - ret = mbedtls_md5_finish_ret( &operation->ctx.md5, hash ); - break; -#endif -#if defined(MBEDTLS_RIPEMD160_C) - case PSA_ALG_RIPEMD160: - ret = mbedtls_ripemd160_finish_ret( &operation->ctx.ripemd160, hash ); - break; -#endif -#if defined(MBEDTLS_SHA1_C) - case PSA_ALG_SHA_1: - ret = mbedtls_sha1_finish_ret( &operation->ctx.sha1, hash ); - break; -#endif -#if defined(MBEDTLS_SHA256_C) - case PSA_ALG_SHA_224: - case PSA_ALG_SHA_256: - ret = mbedtls_sha256_finish_ret( &operation->ctx.sha256, hash ); - break; -#endif -#if defined(MBEDTLS_SHA512_C) -#if !defined(MBEDTLS_SHA512_NO_SHA384) - case PSA_ALG_SHA_384: -#endif - case PSA_ALG_SHA_512: - ret = mbedtls_sha512_finish_ret( &operation->ctx.sha512, hash ); - break; -#endif - default: - return( PSA_ERROR_BAD_STATE ); - } - status = mbedtls_to_psa_error( ret ); - -exit: - if( status == PSA_SUCCESS ) - { - *hash_length = actual_hash_length; - return( psa_hash_abort( operation ) ); - } - else - { - psa_hash_abort( operation ); - return( status ); - } -} - -psa_status_t psa_hash_verify( psa_hash_operation_t *operation, - const uint8_t *hash, - size_t hash_length ) -{ - uint8_t actual_hash[MBEDTLS_MD_MAX_SIZE]; - size_t actual_hash_length; - psa_status_t status = psa_hash_finish( operation, - actual_hash, sizeof( actual_hash ), - &actual_hash_length ); - if( status != PSA_SUCCESS ) - return( status ); - if( actual_hash_length != hash_length ) - return( PSA_ERROR_INVALID_SIGNATURE ); - if( safer_memcmp( hash, actual_hash, actual_hash_length ) != 0 ) - return( PSA_ERROR_INVALID_SIGNATURE ); - return( PSA_SUCCESS ); -} - -psa_status_t psa_hash_compute( psa_algorithm_t alg, - const uint8_t *input, size_t input_length, - uint8_t *hash, size_t hash_size, - size_t *hash_length ) -{ - psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - - *hash_length = hash_size; - status = psa_hash_setup( &operation, alg ); - if( status != PSA_SUCCESS ) - goto exit; - status = psa_hash_update( &operation, input, input_length ); - if( status != PSA_SUCCESS ) - goto exit; - status = psa_hash_finish( &operation, hash, hash_size, hash_length ); - if( status != PSA_SUCCESS ) - goto exit; - -exit: - if( status == PSA_SUCCESS ) - status = psa_hash_abort( &operation ); - else - psa_hash_abort( &operation ); - return( status ); -} - -psa_status_t psa_hash_compare( psa_algorithm_t alg, - const uint8_t *input, size_t input_length, - const uint8_t *hash, size_t hash_length ) -{ - psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - - status = psa_hash_setup( &operation, alg ); - if( status != PSA_SUCCESS ) - goto exit; - status = psa_hash_update( &operation, input, input_length ); - if( status != PSA_SUCCESS ) - goto exit; - status = psa_hash_verify( &operation, hash, hash_length ); - if( status != PSA_SUCCESS ) - goto exit; - -exit: - if( status == PSA_SUCCESS ) - status = psa_hash_abort( &operation ); - else - psa_hash_abort( &operation ); - return( status ); -} - -psa_status_t psa_hash_clone( const psa_hash_operation_t *source_operation, - psa_hash_operation_t *target_operation ) -{ - if( target_operation->alg != 0 ) - return( PSA_ERROR_BAD_STATE ); - - switch( source_operation->alg ) - { - case 0: - return( PSA_ERROR_BAD_STATE ); -#if defined(MBEDTLS_MD2_C) - case PSA_ALG_MD2: - mbedtls_md2_clone( &target_operation->ctx.md2, - &source_operation->ctx.md2 ); - break; -#endif -#if defined(MBEDTLS_MD4_C) - case PSA_ALG_MD4: - mbedtls_md4_clone( &target_operation->ctx.md4, - &source_operation->ctx.md4 ); - break; -#endif -#if defined(MBEDTLS_MD5_C) - case PSA_ALG_MD5: - mbedtls_md5_clone( &target_operation->ctx.md5, - &source_operation->ctx.md5 ); - break; -#endif -#if defined(MBEDTLS_RIPEMD160_C) - case PSA_ALG_RIPEMD160: - mbedtls_ripemd160_clone( &target_operation->ctx.ripemd160, - &source_operation->ctx.ripemd160 ); - break; -#endif -#if defined(MBEDTLS_SHA1_C) - case PSA_ALG_SHA_1: - mbedtls_sha1_clone( &target_operation->ctx.sha1, - &source_operation->ctx.sha1 ); - break; -#endif -#if defined(MBEDTLS_SHA256_C) - case PSA_ALG_SHA_224: - case PSA_ALG_SHA_256: - mbedtls_sha256_clone( &target_operation->ctx.sha256, - &source_operation->ctx.sha256 ); - break; -#endif -#if defined(MBEDTLS_SHA512_C) -#if !defined(MBEDTLS_SHA512_NO_SHA384) - case PSA_ALG_SHA_384: -#endif - case PSA_ALG_SHA_512: - mbedtls_sha512_clone( &target_operation->ctx.sha512, - &source_operation->ctx.sha512 ); - break; -#endif - default: - return( PSA_ERROR_NOT_SUPPORTED ); - } - - target_operation->alg = source_operation->alg; - return( PSA_SUCCESS ); -} - - -/****************************************************************/ -/* MAC */ -/****************************************************************/ - -static const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa( - psa_algorithm_t alg, - psa_key_type_t key_type, - size_t key_bits, - mbedtls_cipher_id_t* cipher_id ) -{ - mbedtls_cipher_mode_t mode; - mbedtls_cipher_id_t cipher_id_tmp; - - if( PSA_ALG_IS_AEAD( alg ) ) - alg = PSA_ALG_AEAD_WITH_TAG_LENGTH( alg, 0 ); - - if( PSA_ALG_IS_CIPHER( alg ) || PSA_ALG_IS_AEAD( alg ) ) - { - switch( alg ) - { - case PSA_ALG_ARC4: - case PSA_ALG_CHACHA20: - mode = MBEDTLS_MODE_STREAM; - break; - case PSA_ALG_CTR: - mode = MBEDTLS_MODE_CTR; - break; - case PSA_ALG_CFB: - mode = MBEDTLS_MODE_CFB; - break; - case PSA_ALG_OFB: - mode = MBEDTLS_MODE_OFB; - break; - case PSA_ALG_CBC_NO_PADDING: - mode = MBEDTLS_MODE_CBC; - break; - case PSA_ALG_CBC_PKCS7: - mode = MBEDTLS_MODE_CBC; - break; - case PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, 0 ): - mode = MBEDTLS_MODE_CCM; - break; - case PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_GCM, 0 ): - mode = MBEDTLS_MODE_GCM; - break; - case PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CHACHA20_POLY1305, 0 ): - mode = MBEDTLS_MODE_CHACHAPOLY; - break; - default: - return( NULL ); - } - } - else if( alg == PSA_ALG_CMAC ) - mode = MBEDTLS_MODE_ECB; - else - return( NULL ); - - switch( key_type ) - { - case PSA_KEY_TYPE_AES: - cipher_id_tmp = MBEDTLS_CIPHER_ID_AES; - break; - case PSA_KEY_TYPE_DES: - /* key_bits is 64 for Single-DES, 128 for two-key Triple-DES, - * and 192 for three-key Triple-DES. */ - if( key_bits == 64 ) - cipher_id_tmp = MBEDTLS_CIPHER_ID_DES; - else - cipher_id_tmp = MBEDTLS_CIPHER_ID_3DES; - /* mbedtls doesn't recognize two-key Triple-DES as an algorithm, - * but two-key Triple-DES is functionally three-key Triple-DES - * with K1=K3, so that's how we present it to mbedtls. */ - if( key_bits == 128 ) - key_bits = 192; - break; - case PSA_KEY_TYPE_CAMELLIA: - cipher_id_tmp = MBEDTLS_CIPHER_ID_CAMELLIA; - break; - case PSA_KEY_TYPE_ARC4: - cipher_id_tmp = MBEDTLS_CIPHER_ID_ARC4; - break; - case PSA_KEY_TYPE_CHACHA20: - cipher_id_tmp = MBEDTLS_CIPHER_ID_CHACHA20; - break; - default: - return( NULL ); - } - if( cipher_id != NULL ) - *cipher_id = cipher_id_tmp; - - return( mbedtls_cipher_info_from_values( cipher_id_tmp, - (int) key_bits, mode ) ); -} - -#if defined(MBEDTLS_MD_C) -static size_t psa_get_hash_block_size( psa_algorithm_t alg ) -{ - switch( alg ) - { - case PSA_ALG_MD2: - return( 16 ); - case PSA_ALG_MD4: - return( 64 ); - case PSA_ALG_MD5: - return( 64 ); - case PSA_ALG_RIPEMD160: - return( 64 ); - case PSA_ALG_SHA_1: - return( 64 ); - case PSA_ALG_SHA_224: - return( 64 ); - case PSA_ALG_SHA_256: - return( 64 ); - case PSA_ALG_SHA_384: - return( 128 ); - case PSA_ALG_SHA_512: - return( 128 ); - default: - return( 0 ); - } -} -#endif /* MBEDTLS_MD_C */ - -/* Initialize the MAC operation structure. Once this function has been - * called, psa_mac_abort can run and will do the right thing. */ -static psa_status_t psa_mac_init( psa_mac_operation_t *operation, - psa_algorithm_t alg ) -{ - psa_status_t status = PSA_ERROR_NOT_SUPPORTED; - - operation->alg = alg; - operation->key_set = 0; - operation->iv_set = 0; - operation->iv_required = 0; - operation->has_input = 0; - operation->is_sign = 0; - -#if defined(MBEDTLS_CMAC_C) - if( alg == PSA_ALG_CMAC ) - { - operation->iv_required = 0; - mbedtls_cipher_init( &operation->ctx.cmac ); - status = PSA_SUCCESS; - } - else -#endif /* MBEDTLS_CMAC_C */ -#if defined(MBEDTLS_MD_C) - if( PSA_ALG_IS_HMAC( operation->alg ) ) - { - /* We'll set up the hash operation later in psa_hmac_setup_internal. */ - operation->ctx.hmac.hash_ctx.alg = 0; - status = PSA_SUCCESS; - } - else -#endif /* MBEDTLS_MD_C */ - { - if( ! PSA_ALG_IS_MAC( alg ) ) - status = PSA_ERROR_INVALID_ARGUMENT; - } - - if( status != PSA_SUCCESS ) - memset( operation, 0, sizeof( *operation ) ); - return( status ); -} - -#if defined(MBEDTLS_MD_C) -static psa_status_t psa_hmac_abort_internal( psa_hmac_internal_data *hmac ) -{ - mbedtls_platform_zeroize( hmac->opad, sizeof( hmac->opad ) ); - return( psa_hash_abort( &hmac->hash_ctx ) ); -} -#endif /* MBEDTLS_MD_C */ - -psa_status_t psa_mac_abort( psa_mac_operation_t *operation ) -{ - if( operation->alg == 0 ) - { - /* The object has (apparently) been initialized but it is not - * in use. It's ok to call abort on such an object, and there's - * nothing to do. */ - return( PSA_SUCCESS ); - } - else -#if defined(MBEDTLS_CMAC_C) - if( operation->alg == PSA_ALG_CMAC ) - { - mbedtls_cipher_free( &operation->ctx.cmac ); - } - else -#endif /* MBEDTLS_CMAC_C */ -#if defined(MBEDTLS_MD_C) - if( PSA_ALG_IS_HMAC( operation->alg ) ) - { - psa_hmac_abort_internal( &operation->ctx.hmac ); - } - else -#endif /* MBEDTLS_MD_C */ - { - /* Sanity check (shouldn't happen: operation->alg should - * always have been initialized to a valid value). */ - goto bad_state; - } - - operation->alg = 0; - operation->key_set = 0; - operation->iv_set = 0; - operation->iv_required = 0; - operation->has_input = 0; - operation->is_sign = 0; - - return( PSA_SUCCESS ); - -bad_state: - /* If abort is called on an uninitialized object, we can't trust - * anything. Wipe the object in case it contains confidential data. - * This may result in a memory leak if a pointer gets overwritten, - * but it's too late to do anything about this. */ - memset( operation, 0, sizeof( *operation ) ); - return( PSA_ERROR_BAD_STATE ); -} - -#if defined(MBEDTLS_CMAC_C) -static int psa_cmac_setup( psa_mac_operation_t *operation, - size_t key_bits, - psa_key_slot_t *slot, - const mbedtls_cipher_info_t *cipher_info ) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - operation->mac_size = cipher_info->block_size; - - ret = mbedtls_cipher_setup( &operation->ctx.cmac, cipher_info ); - if( ret != 0 ) - return( ret ); - - ret = mbedtls_cipher_cmac_starts( &operation->ctx.cmac, - slot->data.raw.data, - key_bits ); - return( ret ); -} -#endif /* MBEDTLS_CMAC_C */ - -#if defined(MBEDTLS_MD_C) -static psa_status_t psa_hmac_setup_internal( psa_hmac_internal_data *hmac, - const uint8_t *key, - size_t key_length, - psa_algorithm_t hash_alg ) -{ - uint8_t ipad[PSA_HMAC_MAX_HASH_BLOCK_SIZE]; - size_t i; - size_t hash_size = PSA_HASH_SIZE( hash_alg ); - size_t block_size = psa_get_hash_block_size( hash_alg ); - psa_status_t status; - - /* Sanity checks on block_size, to guarantee that there won't be a buffer - * overflow below. This should never trigger if the hash algorithm - * is implemented correctly. */ - /* The size checks against the ipad and opad buffers cannot be written - * `block_size > sizeof( ipad ) || block_size > sizeof( hmac->opad )` - * because that triggers -Wlogical-op on GCC 7.3. */ - if( block_size > sizeof( ipad ) ) - return( PSA_ERROR_NOT_SUPPORTED ); - if( block_size > sizeof( hmac->opad ) ) - return( PSA_ERROR_NOT_SUPPORTED ); - if( block_size < hash_size ) - return( PSA_ERROR_NOT_SUPPORTED ); - - if( key_length > block_size ) - { - status = psa_hash_compute( hash_alg, key, key_length, - ipad, sizeof( ipad ), &key_length ); - if( status != PSA_SUCCESS ) - goto cleanup; - } - /* A 0-length key is not commonly used in HMAC when used as a MAC, - * but it is permitted. It is common when HMAC is used in HKDF, for - * example. Don't call `memcpy` in the 0-length because `key` could be - * an invalid pointer which would make the behavior undefined. */ - else if( key_length != 0 ) - memcpy( ipad, key, key_length ); - - /* ipad contains the key followed by garbage. Xor and fill with 0x36 - * to create the ipad value. */ - for( i = 0; i < key_length; i++ ) - ipad[i] ^= 0x36; - memset( ipad + key_length, 0x36, block_size - key_length ); - - /* Copy the key material from ipad to opad, flipping the requisite bits, - * and filling the rest of opad with the requisite constant. */ - for( i = 0; i < key_length; i++ ) - hmac->opad[i] = ipad[i] ^ 0x36 ^ 0x5C; - memset( hmac->opad + key_length, 0x5C, block_size - key_length ); - - status = psa_hash_setup( &hmac->hash_ctx, hash_alg ); - if( status != PSA_SUCCESS ) - goto cleanup; - - status = psa_hash_update( &hmac->hash_ctx, ipad, block_size ); - -cleanup: - mbedtls_platform_zeroize( ipad, sizeof(ipad) ); - - return( status ); -} -#endif /* MBEDTLS_MD_C */ - -static psa_status_t psa_mac_setup( psa_mac_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg, - int is_sign ) -{ - psa_status_t status; - psa_key_slot_t *slot; - size_t key_bits; - psa_key_usage_t usage = - is_sign ? PSA_KEY_USAGE_SIGN_HASH : PSA_KEY_USAGE_VERIFY_HASH; - uint8_t truncated = PSA_MAC_TRUNCATED_LENGTH( alg ); - psa_algorithm_t full_length_alg = PSA_ALG_FULL_LENGTH_MAC( alg ); - - /* A context must be freshly initialized before it can be set up. */ - if( operation->alg != 0 ) - { - return( PSA_ERROR_BAD_STATE ); - } - - status = psa_mac_init( operation, full_length_alg ); - if( status != PSA_SUCCESS ) - return( status ); - if( is_sign ) - operation->is_sign = 1; - - status = psa_get_transparent_key( handle, &slot, usage, alg ); - if( status != PSA_SUCCESS ) - goto exit; - key_bits = psa_get_key_slot_bits( slot ); - -#if defined(MBEDTLS_CMAC_C) - if( full_length_alg == PSA_ALG_CMAC ) - { - const mbedtls_cipher_info_t *cipher_info = - mbedtls_cipher_info_from_psa( full_length_alg, - slot->attr.type, key_bits, NULL ); - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - if( cipher_info == NULL ) - { - status = PSA_ERROR_NOT_SUPPORTED; - goto exit; - } - operation->mac_size = cipher_info->block_size; - ret = psa_cmac_setup( operation, key_bits, slot, cipher_info ); - status = mbedtls_to_psa_error( ret ); - } - else -#endif /* MBEDTLS_CMAC_C */ -#if defined(MBEDTLS_MD_C) - if( PSA_ALG_IS_HMAC( full_length_alg ) ) - { - psa_algorithm_t hash_alg = PSA_ALG_HMAC_GET_HASH( alg ); - if( hash_alg == 0 ) - { - status = PSA_ERROR_NOT_SUPPORTED; - goto exit; - } - - operation->mac_size = PSA_HASH_SIZE( hash_alg ); - /* Sanity check. This shouldn't fail on a valid configuration. */ - if( operation->mac_size == 0 || - operation->mac_size > sizeof( operation->ctx.hmac.opad ) ) - { - status = PSA_ERROR_NOT_SUPPORTED; - goto exit; - } - - if( slot->attr.type != PSA_KEY_TYPE_HMAC ) - { - status = PSA_ERROR_INVALID_ARGUMENT; - goto exit; - } - - status = psa_hmac_setup_internal( &operation->ctx.hmac, - slot->data.raw.data, - slot->data.raw.bytes, - hash_alg ); - } - else -#endif /* MBEDTLS_MD_C */ - { - (void) key_bits; - status = PSA_ERROR_NOT_SUPPORTED; - } - - if( truncated == 0 ) - { - /* The "normal" case: untruncated algorithm. Nothing to do. */ - } - else if( truncated < 4 ) - { - /* A very short MAC is too short for security since it can be - * brute-forced. Ancient protocols with 32-bit MACs do exist, - * so we make this our minimum, even though 32 bits is still - * too small for security. */ - status = PSA_ERROR_NOT_SUPPORTED; - } - else if( truncated > operation->mac_size ) - { - /* It's impossible to "truncate" to a larger length. */ - status = PSA_ERROR_INVALID_ARGUMENT; - } - else - operation->mac_size = truncated; - -exit: - if( status != PSA_SUCCESS ) - { - psa_mac_abort( operation ); - } - else - { - operation->key_set = 1; - } - return( status ); -} - -psa_status_t psa_mac_sign_setup( psa_mac_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg ) -{ - return( psa_mac_setup( operation, handle, alg, 1 ) ); -} - -psa_status_t psa_mac_verify_setup( psa_mac_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg ) -{ - return( psa_mac_setup( operation, handle, alg, 0 ) ); -} - -psa_status_t psa_mac_update( psa_mac_operation_t *operation, - const uint8_t *input, - size_t input_length ) -{ - psa_status_t status = PSA_ERROR_BAD_STATE; - if( ! operation->key_set ) - return( PSA_ERROR_BAD_STATE ); - if( operation->iv_required && ! operation->iv_set ) - return( PSA_ERROR_BAD_STATE ); - operation->has_input = 1; - -#if defined(MBEDTLS_CMAC_C) - if( operation->alg == PSA_ALG_CMAC ) - { - int ret = mbedtls_cipher_cmac_update( &operation->ctx.cmac, - input, input_length ); - status = mbedtls_to_psa_error( ret ); - } - else -#endif /* MBEDTLS_CMAC_C */ -#if defined(MBEDTLS_MD_C) - if( PSA_ALG_IS_HMAC( operation->alg ) ) - { - status = psa_hash_update( &operation->ctx.hmac.hash_ctx, input, - input_length ); - } - else -#endif /* MBEDTLS_MD_C */ - { - /* This shouldn't happen if `operation` was initialized by - * a setup function. */ - return( PSA_ERROR_BAD_STATE ); - } - - if( status != PSA_SUCCESS ) - psa_mac_abort( operation ); - return( status ); -} - -#if defined(MBEDTLS_MD_C) -static psa_status_t psa_hmac_finish_internal( psa_hmac_internal_data *hmac, - uint8_t *mac, - size_t mac_size ) -{ - uint8_t tmp[MBEDTLS_MD_MAX_SIZE]; - psa_algorithm_t hash_alg = hmac->hash_ctx.alg; - size_t hash_size = 0; - size_t block_size = psa_get_hash_block_size( hash_alg ); - psa_status_t status; - - status = psa_hash_finish( &hmac->hash_ctx, tmp, sizeof( tmp ), &hash_size ); - if( status != PSA_SUCCESS ) - return( status ); - /* From here on, tmp needs to be wiped. */ - - status = psa_hash_setup( &hmac->hash_ctx, hash_alg ); - if( status != PSA_SUCCESS ) - goto exit; - - status = psa_hash_update( &hmac->hash_ctx, hmac->opad, block_size ); - if( status != PSA_SUCCESS ) - goto exit; - - status = psa_hash_update( &hmac->hash_ctx, tmp, hash_size ); - if( status != PSA_SUCCESS ) - goto exit; - - status = psa_hash_finish( &hmac->hash_ctx, tmp, sizeof( tmp ), &hash_size ); - if( status != PSA_SUCCESS ) - goto exit; - - memcpy( mac, tmp, mac_size ); - -exit: - mbedtls_platform_zeroize( tmp, hash_size ); - return( status ); -} -#endif /* MBEDTLS_MD_C */ - -static psa_status_t psa_mac_finish_internal( psa_mac_operation_t *operation, - uint8_t *mac, - size_t mac_size ) -{ - if( ! operation->key_set ) - return( PSA_ERROR_BAD_STATE ); - if( operation->iv_required && ! operation->iv_set ) - return( PSA_ERROR_BAD_STATE ); - - if( mac_size < operation->mac_size ) - return( PSA_ERROR_BUFFER_TOO_SMALL ); - -#if defined(MBEDTLS_CMAC_C) - if( operation->alg == PSA_ALG_CMAC ) - { - uint8_t tmp[PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE]; - int ret = mbedtls_cipher_cmac_finish( &operation->ctx.cmac, tmp ); - if( ret == 0 ) - memcpy( mac, tmp, operation->mac_size ); - mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); - return( mbedtls_to_psa_error( ret ) ); - } - else -#endif /* MBEDTLS_CMAC_C */ -#if defined(MBEDTLS_MD_C) - if( PSA_ALG_IS_HMAC( operation->alg ) ) - { - return( psa_hmac_finish_internal( &operation->ctx.hmac, - mac, operation->mac_size ) ); - } - else -#endif /* MBEDTLS_MD_C */ - { - /* This shouldn't happen if `operation` was initialized by - * a setup function. */ - return( PSA_ERROR_BAD_STATE ); - } -} - -psa_status_t psa_mac_sign_finish( psa_mac_operation_t *operation, - uint8_t *mac, - size_t mac_size, - size_t *mac_length ) -{ - psa_status_t status; - - if( operation->alg == 0 ) - { - return( PSA_ERROR_BAD_STATE ); - } - - /* Fill the output buffer with something that isn't a valid mac - * (barring an attack on the mac and deliberately-crafted input), - * in case the caller doesn't check the return status properly. */ - *mac_length = mac_size; - /* If mac_size is 0 then mac may be NULL and then the - * call to memset would have undefined behavior. */ - if( mac_size != 0 ) - memset( mac, '!', mac_size ); - - if( ! operation->is_sign ) - { - return( PSA_ERROR_BAD_STATE ); - } - - status = psa_mac_finish_internal( operation, mac, mac_size ); - - if( status == PSA_SUCCESS ) - { - status = psa_mac_abort( operation ); - if( status == PSA_SUCCESS ) - *mac_length = operation->mac_size; - else - memset( mac, '!', mac_size ); - } - else - psa_mac_abort( operation ); - return( status ); -} - -psa_status_t psa_mac_verify_finish( psa_mac_operation_t *operation, - const uint8_t *mac, - size_t mac_length ) -{ - uint8_t actual_mac[PSA_MAC_MAX_SIZE]; - psa_status_t status; - - if( operation->alg == 0 ) - { - return( PSA_ERROR_BAD_STATE ); - } - - if( operation->is_sign ) - { - return( PSA_ERROR_BAD_STATE ); - } - if( operation->mac_size != mac_length ) - { - status = PSA_ERROR_INVALID_SIGNATURE; - goto cleanup; - } - - status = psa_mac_finish_internal( operation, - actual_mac, sizeof( actual_mac ) ); - if( status != PSA_SUCCESS ) - goto cleanup; - - if( safer_memcmp( mac, actual_mac, mac_length ) != 0 ) - status = PSA_ERROR_INVALID_SIGNATURE; - -cleanup: - if( status == PSA_SUCCESS ) - status = psa_mac_abort( operation ); - else - psa_mac_abort( operation ); - - mbedtls_platform_zeroize( actual_mac, sizeof( actual_mac ) ); - - return( status ); -} - - - -/****************************************************************/ -/* Asymmetric cryptography */ -/****************************************************************/ - -#if defined(MBEDTLS_RSA_C) -/* Decode the hash algorithm from alg and store the mbedtls encoding in - * md_alg. Verify that the hash length is acceptable. */ -static psa_status_t psa_rsa_decode_md_type( psa_algorithm_t alg, - size_t hash_length, - mbedtls_md_type_t *md_alg ) -{ - psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg ); - const mbedtls_md_info_t *md_info = mbedtls_md_info_from_psa( hash_alg ); - *md_alg = mbedtls_md_get_type( md_info ); - - /* The Mbed TLS RSA module uses an unsigned int for hash length - * parameters. Validate that it fits so that we don't risk an - * overflow later. */ -#if SIZE_MAX > UINT_MAX - if( hash_length > UINT_MAX ) - return( PSA_ERROR_INVALID_ARGUMENT ); -#endif - -#if defined(MBEDTLS_PKCS1_V15) - /* For PKCS#1 v1.5 signature, if using a hash, the hash length - * must be correct. */ - if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) && - alg != PSA_ALG_RSA_PKCS1V15_SIGN_RAW ) - { - if( md_info == NULL ) - return( PSA_ERROR_NOT_SUPPORTED ); - if( mbedtls_md_get_size( md_info ) != hash_length ) - return( PSA_ERROR_INVALID_ARGUMENT ); - } -#endif /* MBEDTLS_PKCS1_V15 */ - -#if defined(MBEDTLS_PKCS1_V21) - /* PSS requires a hash internally. */ - if( PSA_ALG_IS_RSA_PSS( alg ) ) - { - if( md_info == NULL ) - return( PSA_ERROR_NOT_SUPPORTED ); - } -#endif /* MBEDTLS_PKCS1_V21 */ - - return( PSA_SUCCESS ); -} - -static psa_status_t psa_rsa_sign( mbedtls_rsa_context *rsa, - psa_algorithm_t alg, - const uint8_t *hash, - size_t hash_length, - uint8_t *signature, - size_t signature_size, - size_t *signature_length ) -{ - psa_status_t status; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_md_type_t md_alg; - - status = psa_rsa_decode_md_type( alg, hash_length, &md_alg ); - if( status != PSA_SUCCESS ) - return( status ); - - if( signature_size < mbedtls_rsa_get_len( rsa ) ) - return( PSA_ERROR_BUFFER_TOO_SMALL ); - -#if defined(MBEDTLS_PKCS1_V15) - if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) ) - { - mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V15, - MBEDTLS_MD_NONE ); - ret = mbedtls_rsa_pkcs1_sign( rsa, - mbedtls_ctr_drbg_random, - &global_data.ctr_drbg, - MBEDTLS_RSA_PRIVATE, - md_alg, - (unsigned int) hash_length, - hash, - signature ); - } - else -#endif /* MBEDTLS_PKCS1_V15 */ -#if defined(MBEDTLS_PKCS1_V21) - if( PSA_ALG_IS_RSA_PSS( alg ) ) - { - mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V21, md_alg ); - ret = mbedtls_rsa_rsassa_pss_sign( rsa, - mbedtls_ctr_drbg_random, - &global_data.ctr_drbg, - MBEDTLS_RSA_PRIVATE, - MBEDTLS_MD_NONE, - (unsigned int) hash_length, - hash, - signature ); - } - else -#endif /* MBEDTLS_PKCS1_V21 */ - { - return( PSA_ERROR_INVALID_ARGUMENT ); - } - - if( ret == 0 ) - *signature_length = mbedtls_rsa_get_len( rsa ); - return( mbedtls_to_psa_error( ret ) ); -} - -static psa_status_t psa_rsa_verify( mbedtls_rsa_context *rsa, - psa_algorithm_t alg, - const uint8_t *hash, - size_t hash_length, - const uint8_t *signature, - size_t signature_length ) -{ - psa_status_t status; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_md_type_t md_alg; - - status = psa_rsa_decode_md_type( alg, hash_length, &md_alg ); - if( status != PSA_SUCCESS ) - return( status ); - - if( signature_length != mbedtls_rsa_get_len( rsa ) ) - return( PSA_ERROR_INVALID_SIGNATURE ); - -#if defined(MBEDTLS_PKCS1_V15) - if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) ) - { - mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V15, - MBEDTLS_MD_NONE ); - ret = mbedtls_rsa_pkcs1_verify( rsa, - mbedtls_ctr_drbg_random, - &global_data.ctr_drbg, - MBEDTLS_RSA_PUBLIC, - md_alg, - (unsigned int) hash_length, - hash, - signature ); - } - else -#endif /* MBEDTLS_PKCS1_V15 */ -#if defined(MBEDTLS_PKCS1_V21) - if( PSA_ALG_IS_RSA_PSS( alg ) ) - { - mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V21, md_alg ); - ret = mbedtls_rsa_rsassa_pss_verify( rsa, - mbedtls_ctr_drbg_random, - &global_data.ctr_drbg, - MBEDTLS_RSA_PUBLIC, - MBEDTLS_MD_NONE, - (unsigned int) hash_length, - hash, - signature ); - } - else -#endif /* MBEDTLS_PKCS1_V21 */ - { - return( PSA_ERROR_INVALID_ARGUMENT ); - } - - /* Mbed TLS distinguishes "invalid padding" from "valid padding but - * the rest of the signature is invalid". This has little use in - * practice and PSA doesn't report this distinction. */ - if( ret == MBEDTLS_ERR_RSA_INVALID_PADDING ) - return( PSA_ERROR_INVALID_SIGNATURE ); - return( mbedtls_to_psa_error( ret ) ); -} -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_ECDSA_C) -/* `ecp` cannot be const because `ecp->grp` needs to be non-const - * for mbedtls_ecdsa_sign() and mbedtls_ecdsa_sign_det() - * (even though these functions don't modify it). */ -static psa_status_t psa_ecdsa_sign( mbedtls_ecp_keypair *ecp, - psa_algorithm_t alg, - const uint8_t *hash, - size_t hash_length, - uint8_t *signature, - size_t signature_size, - size_t *signature_length ) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_mpi r, s; - size_t curve_bytes = PSA_BITS_TO_BYTES( ecp->grp.pbits ); - mbedtls_mpi_init( &r ); - mbedtls_mpi_init( &s ); - - if( signature_size < 2 * curve_bytes ) - { - ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; - goto cleanup; - } - -#if defined(MBEDTLS_ECDSA_DETERMINISTIC) - if( PSA_ALG_DSA_IS_DETERMINISTIC( alg ) ) - { - psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg ); - const mbedtls_md_info_t *md_info = mbedtls_md_info_from_psa( hash_alg ); - mbedtls_md_type_t md_alg = mbedtls_md_get_type( md_info ); - MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det_ext( &ecp->grp, &r, &s, - &ecp->d, hash, - hash_length, md_alg, - mbedtls_ctr_drbg_random, - &global_data.ctr_drbg ) ); - } - else -#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ - { - (void) alg; - MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ecp->grp, &r, &s, &ecp->d, - hash, hash_length, - mbedtls_ctr_drbg_random, - &global_data.ctr_drbg ) ); - } - - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &r, - signature, - curve_bytes ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &s, - signature + curve_bytes, - curve_bytes ) ); - -cleanup: - mbedtls_mpi_free( &r ); - mbedtls_mpi_free( &s ); - if( ret == 0 ) - *signature_length = 2 * curve_bytes; - return( mbedtls_to_psa_error( ret ) ); -} - -static psa_status_t psa_ecdsa_verify( mbedtls_ecp_keypair *ecp, - const uint8_t *hash, - size_t hash_length, - const uint8_t *signature, - size_t signature_length ) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_mpi r, s; - size_t curve_bytes = PSA_BITS_TO_BYTES( ecp->grp.pbits ); - mbedtls_mpi_init( &r ); - mbedtls_mpi_init( &s ); - - if( signature_length != 2 * curve_bytes ) - return( PSA_ERROR_INVALID_SIGNATURE ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, - signature, - curve_bytes ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &s, - signature + curve_bytes, - curve_bytes ) ); - - ret = mbedtls_ecdsa_verify( &ecp->grp, hash, hash_length, - &ecp->Q, &r, &s ); - -cleanup: - mbedtls_mpi_free( &r ); - mbedtls_mpi_free( &s ); - return( mbedtls_to_psa_error( ret ) ); -} -#endif /* MBEDTLS_ECDSA_C */ - -psa_status_t psa_sign_hash( psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *hash, - size_t hash_length, - uint8_t *signature, - size_t signature_size, - size_t *signature_length ) -{ - psa_key_slot_t *slot; - psa_status_t status; -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - const psa_drv_se_t *drv; - psa_drv_se_context_t *drv_context; -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - - *signature_length = signature_size; - /* Immediately reject a zero-length signature buffer. This guarantees - * that signature must be a valid pointer. (On the other hand, the hash - * buffer can in principle be empty since it doesn't actually have - * to be a hash.) */ - if( signature_size == 0 ) - return( PSA_ERROR_BUFFER_TOO_SMALL ); - - status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_SIGN_HASH, alg ); - if( status != PSA_SUCCESS ) - goto exit; - if( ! PSA_KEY_TYPE_IS_KEY_PAIR( slot->attr.type ) ) - { - status = PSA_ERROR_INVALID_ARGUMENT; - goto exit; - } - -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) ) - { - if( drv->asymmetric == NULL || - drv->asymmetric->p_sign == NULL ) - { - status = PSA_ERROR_NOT_SUPPORTED; - goto exit; - } - status = drv->asymmetric->p_sign( drv_context, - slot->data.se.slot_number, - alg, - hash, hash_length, - signature, signature_size, - signature_length ); - } - else -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ -#if defined(MBEDTLS_RSA_C) - if( slot->attr.type == PSA_KEY_TYPE_RSA_KEY_PAIR ) - { - status = psa_rsa_sign( slot->data.rsa, - alg, - hash, hash_length, - signature, signature_size, - signature_length ); - } - else -#endif /* defined(MBEDTLS_RSA_C) */ -#if defined(MBEDTLS_ECP_C) - if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) - { -#if defined(MBEDTLS_ECDSA_C) - if( -#if defined(MBEDTLS_ECDSA_DETERMINISTIC) - PSA_ALG_IS_ECDSA( alg ) -#else - PSA_ALG_IS_RANDOMIZED_ECDSA( alg ) -#endif - ) - status = psa_ecdsa_sign( slot->data.ecp, - alg, - hash, hash_length, - signature, signature_size, - signature_length ); - else -#endif /* defined(MBEDTLS_ECDSA_C) */ - { - status = PSA_ERROR_INVALID_ARGUMENT; - } - } - else -#endif /* defined(MBEDTLS_ECP_C) */ - { - status = PSA_ERROR_NOT_SUPPORTED; - } - -exit: - /* Fill the unused part of the output buffer (the whole buffer on error, - * the trailing part on success) with something that isn't a valid mac - * (barring an attack on the mac and deliberately-crafted input), - * in case the caller doesn't check the return status properly. */ - if( status == PSA_SUCCESS ) - memset( signature + *signature_length, '!', - signature_size - *signature_length ); - else - memset( signature, '!', signature_size ); - /* If signature_size is 0 then we have nothing to do. We must not call - * memset because signature may be NULL in this case. */ - return( status ); -} - -psa_status_t psa_verify_hash( psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *hash, - size_t hash_length, - const uint8_t *signature, - size_t signature_length ) -{ - psa_key_slot_t *slot; - psa_status_t status; -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - const psa_drv_se_t *drv; - psa_drv_se_context_t *drv_context; -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - - status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_VERIFY_HASH, alg ); - if( status != PSA_SUCCESS ) - return( status ); - -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) ) - { - if( drv->asymmetric == NULL || - drv->asymmetric->p_verify == NULL ) - return( PSA_ERROR_NOT_SUPPORTED ); - return( drv->asymmetric->p_verify( drv_context, - slot->data.se.slot_number, - alg, - hash, hash_length, - signature, signature_length ) ); - } - else -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ -#if defined(MBEDTLS_RSA_C) - if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) - { - return( psa_rsa_verify( slot->data.rsa, - alg, - hash, hash_length, - signature, signature_length ) ); - } - else -#endif /* defined(MBEDTLS_RSA_C) */ -#if defined(MBEDTLS_ECP_C) - if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) - { -#if defined(MBEDTLS_ECDSA_C) - if( PSA_ALG_IS_ECDSA( alg ) ) - return( psa_ecdsa_verify( slot->data.ecp, - hash, hash_length, - signature, signature_length ) ); - else -#endif /* defined(MBEDTLS_ECDSA_C) */ - { - return( PSA_ERROR_INVALID_ARGUMENT ); - } - } - else -#endif /* defined(MBEDTLS_ECP_C) */ - { - return( PSA_ERROR_NOT_SUPPORTED ); - } -} - -#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) -static void psa_rsa_oaep_set_padding_mode( psa_algorithm_t alg, - mbedtls_rsa_context *rsa ) -{ - psa_algorithm_t hash_alg = PSA_ALG_RSA_OAEP_GET_HASH( alg ); - const mbedtls_md_info_t *md_info = mbedtls_md_info_from_psa( hash_alg ); - mbedtls_md_type_t md_alg = mbedtls_md_get_type( md_info ); - mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V21, md_alg ); -} -#endif /* defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) */ - -psa_status_t psa_asymmetric_encrypt( psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - const uint8_t *salt, - size_t salt_length, - uint8_t *output, - size_t output_size, - size_t *output_length ) -{ - psa_key_slot_t *slot; - psa_status_t status; - - (void) input; - (void) input_length; - (void) salt; - (void) output; - (void) output_size; - - *output_length = 0; - - if( ! PSA_ALG_IS_RSA_OAEP( alg ) && salt_length != 0 ) - return( PSA_ERROR_INVALID_ARGUMENT ); - - status = psa_get_transparent_key( handle, &slot, PSA_KEY_USAGE_ENCRYPT, alg ); - if( status != PSA_SUCCESS ) - return( status ); - if( ! ( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->attr.type ) || - PSA_KEY_TYPE_IS_KEY_PAIR( slot->attr.type ) ) ) - return( PSA_ERROR_INVALID_ARGUMENT ); - -#if defined(MBEDTLS_RSA_C) - if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) - { - mbedtls_rsa_context *rsa = slot->data.rsa; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - if( output_size < mbedtls_rsa_get_len( rsa ) ) - return( PSA_ERROR_BUFFER_TOO_SMALL ); -#if defined(MBEDTLS_PKCS1_V15) - if( alg == PSA_ALG_RSA_PKCS1V15_CRYPT ) - { - ret = mbedtls_rsa_pkcs1_encrypt( rsa, - mbedtls_ctr_drbg_random, - &global_data.ctr_drbg, - MBEDTLS_RSA_PUBLIC, - input_length, - input, - output ); - } - else -#endif /* MBEDTLS_PKCS1_V15 */ -#if defined(MBEDTLS_PKCS1_V21) - if( PSA_ALG_IS_RSA_OAEP( alg ) ) - { - psa_rsa_oaep_set_padding_mode( alg, rsa ); - ret = mbedtls_rsa_rsaes_oaep_encrypt( rsa, - mbedtls_ctr_drbg_random, - &global_data.ctr_drbg, - MBEDTLS_RSA_PUBLIC, - salt, salt_length, - input_length, - input, - output ); - } - else -#endif /* MBEDTLS_PKCS1_V21 */ - { - return( PSA_ERROR_INVALID_ARGUMENT ); - } - if( ret == 0 ) - *output_length = mbedtls_rsa_get_len( rsa ); - return( mbedtls_to_psa_error( ret ) ); - } - else -#endif /* defined(MBEDTLS_RSA_C) */ - { - return( PSA_ERROR_NOT_SUPPORTED ); - } -} - -psa_status_t psa_asymmetric_decrypt( psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - const uint8_t *salt, - size_t salt_length, - uint8_t *output, - size_t output_size, - size_t *output_length ) -{ - psa_key_slot_t *slot; - psa_status_t status; - - (void) input; - (void) input_length; - (void) salt; - (void) output; - (void) output_size; - - *output_length = 0; - - if( ! PSA_ALG_IS_RSA_OAEP( alg ) && salt_length != 0 ) - return( PSA_ERROR_INVALID_ARGUMENT ); - - status = psa_get_transparent_key( handle, &slot, PSA_KEY_USAGE_DECRYPT, alg ); - if( status != PSA_SUCCESS ) - return( status ); - if( ! PSA_KEY_TYPE_IS_KEY_PAIR( slot->attr.type ) ) - return( PSA_ERROR_INVALID_ARGUMENT ); - -#if defined(MBEDTLS_RSA_C) - if( slot->attr.type == PSA_KEY_TYPE_RSA_KEY_PAIR ) - { - mbedtls_rsa_context *rsa = slot->data.rsa; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if( input_length != mbedtls_rsa_get_len( rsa ) ) - return( PSA_ERROR_INVALID_ARGUMENT ); - -#if defined(MBEDTLS_PKCS1_V15) - if( alg == PSA_ALG_RSA_PKCS1V15_CRYPT ) - { - ret = mbedtls_rsa_pkcs1_decrypt( rsa, - mbedtls_ctr_drbg_random, - &global_data.ctr_drbg, - MBEDTLS_RSA_PRIVATE, - output_length, - input, - output, - output_size ); - } - else -#endif /* MBEDTLS_PKCS1_V15 */ -#if defined(MBEDTLS_PKCS1_V21) - if( PSA_ALG_IS_RSA_OAEP( alg ) ) - { - psa_rsa_oaep_set_padding_mode( alg, rsa ); - ret = mbedtls_rsa_rsaes_oaep_decrypt( rsa, - mbedtls_ctr_drbg_random, - &global_data.ctr_drbg, - MBEDTLS_RSA_PRIVATE, - salt, salt_length, - output_length, - input, - output, - output_size ); - } - else -#endif /* MBEDTLS_PKCS1_V21 */ - { - return( PSA_ERROR_INVALID_ARGUMENT ); - } - - return( mbedtls_to_psa_error( ret ) ); - } - else -#endif /* defined(MBEDTLS_RSA_C) */ - { - return( PSA_ERROR_NOT_SUPPORTED ); - } -} - - - -/****************************************************************/ -/* Symmetric cryptography */ -/****************************************************************/ - -/* Initialize the cipher operation structure. Once this function has been - * called, psa_cipher_abort can run and will do the right thing. */ -static psa_status_t psa_cipher_init( psa_cipher_operation_t *operation, - psa_algorithm_t alg ) -{ - if( ! PSA_ALG_IS_CIPHER( alg ) ) - { - memset( operation, 0, sizeof( *operation ) ); - return( PSA_ERROR_INVALID_ARGUMENT ); - } - - operation->alg = alg; - operation->key_set = 0; - operation->iv_set = 0; - operation->iv_required = 1; - operation->iv_size = 0; - operation->block_size = 0; - mbedtls_cipher_init( &operation->ctx.cipher ); - return( PSA_SUCCESS ); -} - -static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg, - mbedtls_operation_t cipher_operation ) -{ - int ret = 0; - psa_status_t status = PSA_ERROR_GENERIC_ERROR; - psa_key_slot_t *slot; - size_t key_bits; - const mbedtls_cipher_info_t *cipher_info = NULL; - psa_key_usage_t usage = ( cipher_operation == MBEDTLS_ENCRYPT ? - PSA_KEY_USAGE_ENCRYPT : - PSA_KEY_USAGE_DECRYPT ); - - /* A context must be freshly initialized before it can be set up. */ - if( operation->alg != 0 ) - { - return( PSA_ERROR_BAD_STATE ); - } - - status = psa_cipher_init( operation, alg ); - if( status != PSA_SUCCESS ) - return( status ); - - status = psa_get_transparent_key( handle, &slot, usage, alg); - if( status != PSA_SUCCESS ) - goto exit; - key_bits = psa_get_key_slot_bits( slot ); - - cipher_info = mbedtls_cipher_info_from_psa( alg, slot->attr.type, key_bits, NULL ); - if( cipher_info == NULL ) - { - status = PSA_ERROR_NOT_SUPPORTED; - goto exit; - } - - ret = mbedtls_cipher_setup( &operation->ctx.cipher, cipher_info ); - if( ret != 0 ) - goto exit; - -#if defined(MBEDTLS_DES_C) - if( slot->attr.type == PSA_KEY_TYPE_DES && key_bits == 128 ) - { - /* Two-key Triple-DES is 3-key Triple-DES with K1=K3 */ - uint8_t keys[24]; - memcpy( keys, slot->data.raw.data, 16 ); - memcpy( keys + 16, slot->data.raw.data, 8 ); - ret = mbedtls_cipher_setkey( &operation->ctx.cipher, - keys, - 192, cipher_operation ); - } - else -#endif - { - ret = mbedtls_cipher_setkey( &operation->ctx.cipher, - slot->data.raw.data, - (int) key_bits, cipher_operation ); - } - if( ret != 0 ) - goto exit; - -#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) - switch( alg ) - { - case PSA_ALG_CBC_NO_PADDING: - ret = mbedtls_cipher_set_padding_mode( &operation->ctx.cipher, - MBEDTLS_PADDING_NONE ); - break; - case PSA_ALG_CBC_PKCS7: - ret = mbedtls_cipher_set_padding_mode( &operation->ctx.cipher, - MBEDTLS_PADDING_PKCS7 ); - break; - default: - /* The algorithm doesn't involve padding. */ - ret = 0; - break; - } - if( ret != 0 ) - goto exit; -#endif //MBEDTLS_CIPHER_MODE_WITH_PADDING - - operation->key_set = 1; - operation->block_size = ( PSA_ALG_IS_STREAM_CIPHER( alg ) ? 1 : - PSA_BLOCK_CIPHER_BLOCK_SIZE( slot->attr.type ) ); - if( alg & PSA_ALG_CIPHER_FROM_BLOCK_FLAG ) - { - operation->iv_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( slot->attr.type ); - } -#if defined(MBEDTLS_CHACHA20_C) - else - if( alg == PSA_ALG_CHACHA20 ) - operation->iv_size = 12; -#endif - -exit: - if( status == 0 ) - status = mbedtls_to_psa_error( ret ); - if( status != 0 ) - psa_cipher_abort( operation ); - return( status ); -} - -psa_status_t psa_cipher_encrypt_setup( psa_cipher_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg ) -{ - return( psa_cipher_setup( operation, handle, alg, MBEDTLS_ENCRYPT ) ); -} - -psa_status_t psa_cipher_decrypt_setup( psa_cipher_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg ) -{ - return( psa_cipher_setup( operation, handle, alg, MBEDTLS_DECRYPT ) ); -} - -psa_status_t psa_cipher_generate_iv( psa_cipher_operation_t *operation, - uint8_t *iv, - size_t iv_size, - size_t *iv_length ) -{ - psa_status_t status; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - if( operation->iv_set || ! operation->iv_required ) - { - return( PSA_ERROR_BAD_STATE ); - } - if( iv_size < operation->iv_size ) - { - status = PSA_ERROR_BUFFER_TOO_SMALL; - goto exit; - } - ret = mbedtls_ctr_drbg_random( &global_data.ctr_drbg, - iv, operation->iv_size ); - if( ret != 0 ) - { - status = mbedtls_to_psa_error( ret ); - goto exit; - } - - *iv_length = operation->iv_size; - status = psa_cipher_set_iv( operation, iv, *iv_length ); - -exit: - if( status != PSA_SUCCESS ) - psa_cipher_abort( operation ); - return( status ); -} - -psa_status_t psa_cipher_set_iv( psa_cipher_operation_t *operation, - const uint8_t *iv, - size_t iv_length ) -{ - psa_status_t status; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - if( operation->iv_set || ! operation->iv_required ) - { - return( PSA_ERROR_BAD_STATE ); - } - if( iv_length != operation->iv_size ) - { - status = PSA_ERROR_INVALID_ARGUMENT; - goto exit; - } - ret = mbedtls_cipher_set_iv( &operation->ctx.cipher, iv, iv_length ); - status = mbedtls_to_psa_error( ret ); -exit: - if( status == PSA_SUCCESS ) - operation->iv_set = 1; - else - psa_cipher_abort( operation ); - return( status ); -} - -psa_status_t psa_cipher_update( psa_cipher_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 status; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t expected_output_size; - - if( operation->alg == 0 ) - { - return( PSA_ERROR_BAD_STATE ); - } - - if( ! PSA_ALG_IS_STREAM_CIPHER( operation->alg ) ) - { - /* Take the unprocessed partial block left over from previous - * update calls, if any, plus the input to this call. Remove - * the last partial block, if any. You get the data that will be - * output in this call. */ - expected_output_size = - ( operation->ctx.cipher.unprocessed_len + input_length ) - / operation->block_size * operation->block_size; - } - else - { - expected_output_size = input_length; - } - - if( output_size < expected_output_size ) - { - status = PSA_ERROR_BUFFER_TOO_SMALL; - goto exit; - } - - ret = mbedtls_cipher_update( &operation->ctx.cipher, input, - input_length, output, output_length ); - status = mbedtls_to_psa_error( ret ); -exit: - if( status != PSA_SUCCESS ) - psa_cipher_abort( operation ); - return( status ); -} - -psa_status_t psa_cipher_finish( psa_cipher_operation_t *operation, - uint8_t *output, - size_t output_size, - size_t *output_length ) -{ - psa_status_t status = PSA_ERROR_GENERIC_ERROR; - int cipher_ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; - uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH]; - - if( ! operation->key_set ) - { - return( PSA_ERROR_BAD_STATE ); - } - if( operation->iv_required && ! operation->iv_set ) - { - return( PSA_ERROR_BAD_STATE ); - } - - if( operation->ctx.cipher.operation == MBEDTLS_ENCRYPT && - operation->alg == PSA_ALG_CBC_NO_PADDING && - operation->ctx.cipher.unprocessed_len != 0 ) - { - status = PSA_ERROR_INVALID_ARGUMENT; - goto error; - } - - cipher_ret = mbedtls_cipher_finish( &operation->ctx.cipher, - temp_output_buffer, - output_length ); - if( cipher_ret != 0 ) - { - status = mbedtls_to_psa_error( cipher_ret ); - goto error; - } - - if( *output_length == 0 ) - ; /* Nothing to copy. Note that output may be NULL in this case. */ - else if( output_size >= *output_length ) - memcpy( output, temp_output_buffer, *output_length ); - else - { - status = PSA_ERROR_BUFFER_TOO_SMALL; - goto error; - } - - mbedtls_platform_zeroize( temp_output_buffer, sizeof( temp_output_buffer ) ); - status = psa_cipher_abort( operation ); - - return( status ); - -error: - - *output_length = 0; - - mbedtls_platform_zeroize( temp_output_buffer, sizeof( temp_output_buffer ) ); - (void) psa_cipher_abort( operation ); - - return( status ); -} - -psa_status_t psa_cipher_abort( psa_cipher_operation_t *operation ) -{ - if( operation->alg == 0 ) - { - /* The object has (apparently) been initialized but it is not - * in use. It's ok to call abort on such an object, and there's - * nothing to do. */ - return( PSA_SUCCESS ); - } - - /* Sanity check (shouldn't happen: operation->alg should - * always have been initialized to a valid value). */ - if( ! PSA_ALG_IS_CIPHER( operation->alg ) ) - return( PSA_ERROR_BAD_STATE ); - - mbedtls_cipher_free( &operation->ctx.cipher ); - - operation->alg = 0; - operation->key_set = 0; - operation->iv_set = 0; - operation->iv_size = 0; - operation->block_size = 0; - operation->iv_required = 0; - - return( PSA_SUCCESS ); -} - - - - -/****************************************************************/ -/* AEAD */ -/****************************************************************/ - -typedef struct -{ - psa_key_slot_t *slot; - const mbedtls_cipher_info_t *cipher_info; - union - { -#if defined(MBEDTLS_CCM_C) - mbedtls_ccm_context ccm; -#endif /* MBEDTLS_CCM_C */ -#if defined(MBEDTLS_GCM_C) - mbedtls_gcm_context gcm; -#endif /* MBEDTLS_GCM_C */ -#if defined(MBEDTLS_CHACHAPOLY_C) - mbedtls_chachapoly_context chachapoly; -#endif /* MBEDTLS_CHACHAPOLY_C */ - } ctx; - psa_algorithm_t core_alg; - uint8_t full_tag_length; - uint8_t tag_length; -} aead_operation_t; - -static void psa_aead_abort_internal( aead_operation_t *operation ) -{ - switch( operation->core_alg ) - { -#if defined(MBEDTLS_CCM_C) - case PSA_ALG_CCM: - mbedtls_ccm_free( &operation->ctx.ccm ); - break; -#endif /* MBEDTLS_CCM_C */ -#if defined(MBEDTLS_GCM_C) - case PSA_ALG_GCM: - mbedtls_gcm_free( &operation->ctx.gcm ); - break; -#endif /* MBEDTLS_GCM_C */ - } -} - -static psa_status_t psa_aead_setup( aead_operation_t *operation, - psa_key_handle_t handle, - psa_key_usage_t usage, - psa_algorithm_t alg ) -{ - psa_status_t status; - size_t key_bits; - mbedtls_cipher_id_t cipher_id; - - status = psa_get_transparent_key( handle, &operation->slot, usage, alg ); - if( status != PSA_SUCCESS ) - return( status ); - - key_bits = psa_get_key_slot_bits( operation->slot ); - - operation->cipher_info = - mbedtls_cipher_info_from_psa( alg, operation->slot->attr.type, key_bits, - &cipher_id ); - if( operation->cipher_info == NULL ) - return( PSA_ERROR_NOT_SUPPORTED ); - - switch( PSA_ALG_AEAD_WITH_TAG_LENGTH( alg, 0 ) ) - { -#if defined(MBEDTLS_CCM_C) - case PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, 0 ): - operation->core_alg = PSA_ALG_CCM; - operation->full_tag_length = 16; - /* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16. - * The call to mbedtls_ccm_encrypt_and_tag or - * mbedtls_ccm_auth_decrypt will validate the tag length. */ - if( PSA_BLOCK_CIPHER_BLOCK_SIZE( operation->slot->attr.type ) != 16 ) - return( PSA_ERROR_INVALID_ARGUMENT ); - mbedtls_ccm_init( &operation->ctx.ccm ); - status = mbedtls_to_psa_error( - mbedtls_ccm_setkey( &operation->ctx.ccm, cipher_id, - operation->slot->data.raw.data, - (unsigned int) key_bits ) ); - if( status != 0 ) - goto cleanup; - break; -#endif /* MBEDTLS_CCM_C */ - -#if defined(MBEDTLS_GCM_C) - case PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_GCM, 0 ): - operation->core_alg = PSA_ALG_GCM; - operation->full_tag_length = 16; - /* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16. - * The call to mbedtls_gcm_crypt_and_tag or - * mbedtls_gcm_auth_decrypt will validate the tag length. */ - if( PSA_BLOCK_CIPHER_BLOCK_SIZE( operation->slot->attr.type ) != 16 ) - return( PSA_ERROR_INVALID_ARGUMENT ); - mbedtls_gcm_init( &operation->ctx.gcm ); - status = mbedtls_to_psa_error( - mbedtls_gcm_setkey( &operation->ctx.gcm, cipher_id, - operation->slot->data.raw.data, - (unsigned int) key_bits ) ); - if( status != 0 ) - goto cleanup; - break; -#endif /* MBEDTLS_GCM_C */ - -#if defined(MBEDTLS_CHACHAPOLY_C) - case PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CHACHA20_POLY1305, 0 ): - operation->core_alg = PSA_ALG_CHACHA20_POLY1305; - operation->full_tag_length = 16; - /* We only support the default tag length. */ - if( alg != PSA_ALG_CHACHA20_POLY1305 ) - return( PSA_ERROR_NOT_SUPPORTED ); - mbedtls_chachapoly_init( &operation->ctx.chachapoly ); - status = mbedtls_to_psa_error( - mbedtls_chachapoly_setkey( &operation->ctx.chachapoly, - operation->slot->data.raw.data ) ); - if( status != 0 ) - goto cleanup; - break; -#endif /* MBEDTLS_CHACHAPOLY_C */ - - default: - return( PSA_ERROR_NOT_SUPPORTED ); - } - - if( PSA_AEAD_TAG_LENGTH( alg ) > operation->full_tag_length ) - { - status = PSA_ERROR_INVALID_ARGUMENT; - goto cleanup; - } - operation->tag_length = PSA_AEAD_TAG_LENGTH( alg ); - - return( PSA_SUCCESS ); - -cleanup: - psa_aead_abort_internal( operation ); - return( status ); -} - -psa_status_t psa_aead_encrypt( psa_key_handle_t handle, - 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 *ciphertext, - size_t ciphertext_size, - size_t *ciphertext_length ) -{ - psa_status_t status; - aead_operation_t operation; - uint8_t *tag; - - *ciphertext_length = 0; - - status = psa_aead_setup( &operation, handle, PSA_KEY_USAGE_ENCRYPT, alg ); - if( status != PSA_SUCCESS ) - return( status ); - - /* For all currently supported modes, the tag is at the end of the - * ciphertext. */ - if( ciphertext_size < ( plaintext_length + operation.tag_length ) ) - { - status = PSA_ERROR_BUFFER_TOO_SMALL; - goto exit; - } - tag = ciphertext + plaintext_length; - -#if defined(MBEDTLS_GCM_C) - if( operation.core_alg == PSA_ALG_GCM ) - { - status = mbedtls_to_psa_error( - mbedtls_gcm_crypt_and_tag( &operation.ctx.gcm, - MBEDTLS_GCM_ENCRYPT, - plaintext_length, - nonce, nonce_length, - additional_data, additional_data_length, - plaintext, ciphertext, - operation.tag_length, tag ) ); - } - else -#endif /* MBEDTLS_GCM_C */ -#if defined(MBEDTLS_CCM_C) - if( operation.core_alg == PSA_ALG_CCM ) - { - status = mbedtls_to_psa_error( - mbedtls_ccm_encrypt_and_tag( &operation.ctx.ccm, - plaintext_length, - nonce, nonce_length, - additional_data, - additional_data_length, - plaintext, ciphertext, - tag, operation.tag_length ) ); - } - else -#endif /* MBEDTLS_CCM_C */ -#if defined(MBEDTLS_CHACHAPOLY_C) - if( operation.core_alg == PSA_ALG_CHACHA20_POLY1305 ) - { - if( nonce_length != 12 || operation.tag_length != 16 ) - { - status = PSA_ERROR_NOT_SUPPORTED; - goto exit; - } - status = mbedtls_to_psa_error( - mbedtls_chachapoly_encrypt_and_tag( &operation.ctx.chachapoly, - plaintext_length, - nonce, - additional_data, - additional_data_length, - plaintext, - ciphertext, - tag ) ); - } - else -#endif /* MBEDTLS_CHACHAPOLY_C */ - { - return( PSA_ERROR_NOT_SUPPORTED ); - } - - if( status != PSA_SUCCESS && ciphertext_size != 0 ) - memset( ciphertext, 0, ciphertext_size ); - -exit: - psa_aead_abort_internal( &operation ); - if( status == PSA_SUCCESS ) - *ciphertext_length = plaintext_length + operation.tag_length; - return( status ); -} - -/* Locate the tag in a ciphertext buffer containing the encrypted data - * followed by the tag. Return the length of the part preceding the tag in - * *plaintext_length. This is the size of the plaintext in modes where - * the encrypted data has the same size as the plaintext, such as - * CCM and GCM. */ -static psa_status_t psa_aead_unpadded_locate_tag( size_t tag_length, - const uint8_t *ciphertext, - size_t ciphertext_length, - size_t plaintext_size, - const uint8_t **p_tag ) -{ - size_t payload_length; - if( tag_length > ciphertext_length ) - return( PSA_ERROR_INVALID_ARGUMENT ); - payload_length = ciphertext_length - tag_length; - if( payload_length > plaintext_size ) - return( PSA_ERROR_BUFFER_TOO_SMALL ); - *p_tag = ciphertext + payload_length; - return( PSA_SUCCESS ); -} - -psa_status_t psa_aead_decrypt( psa_key_handle_t handle, - 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 *ciphertext, - size_t ciphertext_length, - uint8_t *plaintext, - size_t plaintext_size, - size_t *plaintext_length ) -{ - psa_status_t status; - aead_operation_t operation; - const uint8_t *tag = NULL; - - *plaintext_length = 0; - - status = psa_aead_setup( &operation, handle, PSA_KEY_USAGE_DECRYPT, alg ); - if( status != PSA_SUCCESS ) - return( status ); - - status = psa_aead_unpadded_locate_tag( operation.tag_length, - ciphertext, ciphertext_length, - plaintext_size, &tag ); - if( status != PSA_SUCCESS ) - goto exit; - -#if defined(MBEDTLS_GCM_C) - if( operation.core_alg == PSA_ALG_GCM ) - { - status = mbedtls_to_psa_error( - mbedtls_gcm_auth_decrypt( &operation.ctx.gcm, - ciphertext_length - operation.tag_length, - nonce, nonce_length, - additional_data, - additional_data_length, - tag, operation.tag_length, - ciphertext, plaintext ) ); - } - else -#endif /* MBEDTLS_GCM_C */ -#if defined(MBEDTLS_CCM_C) - if( operation.core_alg == PSA_ALG_CCM ) - { - status = mbedtls_to_psa_error( - mbedtls_ccm_auth_decrypt( &operation.ctx.ccm, - ciphertext_length - operation.tag_length, - nonce, nonce_length, - additional_data, - additional_data_length, - ciphertext, plaintext, - tag, operation.tag_length ) ); - } - else -#endif /* MBEDTLS_CCM_C */ -#if defined(MBEDTLS_CHACHAPOLY_C) - if( operation.core_alg == PSA_ALG_CHACHA20_POLY1305 ) - { - if( nonce_length != 12 || operation.tag_length != 16 ) - { - status = PSA_ERROR_NOT_SUPPORTED; - goto exit; - } - status = mbedtls_to_psa_error( - mbedtls_chachapoly_auth_decrypt( &operation.ctx.chachapoly, - ciphertext_length - operation.tag_length, - nonce, - additional_data, - additional_data_length, - tag, - ciphertext, - plaintext ) ); - } - else -#endif /* MBEDTLS_CHACHAPOLY_C */ - { - return( PSA_ERROR_NOT_SUPPORTED ); - } - - if( status != PSA_SUCCESS && plaintext_size != 0 ) - memset( plaintext, 0, plaintext_size ); - -exit: - psa_aead_abort_internal( &operation ); - if( status == PSA_SUCCESS ) - *plaintext_length = ciphertext_length - operation.tag_length; - return( status ); -} - - - -/****************************************************************/ -/* Generators */ -/****************************************************************/ - -#define HKDF_STATE_INIT 0 /* no input yet */ -#define HKDF_STATE_STARTED 1 /* got salt */ -#define HKDF_STATE_KEYED 2 /* got key */ -#define HKDF_STATE_OUTPUT 3 /* output started */ - -static psa_algorithm_t psa_key_derivation_get_kdf_alg( - const psa_key_derivation_operation_t *operation ) -{ - if ( PSA_ALG_IS_KEY_AGREEMENT( operation->alg ) ) - return( PSA_ALG_KEY_AGREEMENT_GET_KDF( operation->alg ) ); - else - return( operation->alg ); -} - - -psa_status_t psa_key_derivation_abort( psa_key_derivation_operation_t *operation ) -{ - psa_status_t status = PSA_SUCCESS; - psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg( operation ); - if( kdf_alg == 0 ) - { - /* The object has (apparently) been initialized but it is not - * in use. It's ok to call abort on such an object, and there's - * nothing to do. */ - } - else -#if defined(MBEDTLS_MD_C) - if( PSA_ALG_IS_HKDF( kdf_alg ) ) - { - mbedtls_free( operation->ctx.hkdf.info ); - status = psa_hmac_abort_internal( &operation->ctx.hkdf.hmac ); - } - else if( PSA_ALG_IS_TLS12_PRF( kdf_alg ) || - /* TLS-1.2 PSK-to-MS KDF uses the same core as TLS-1.2 PRF */ - PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) ) - { - if( operation->ctx.tls12_prf.seed != NULL ) - { - mbedtls_platform_zeroize( operation->ctx.tls12_prf.seed, - operation->ctx.tls12_prf.seed_length ); - mbedtls_free( operation->ctx.tls12_prf.seed ); - } - - if( operation->ctx.tls12_prf.label != NULL ) - { - mbedtls_platform_zeroize( operation->ctx.tls12_prf.label, - operation->ctx.tls12_prf.label_length ); - mbedtls_free( operation->ctx.tls12_prf.label ); - } - - status = psa_hmac_abort_internal( &operation->ctx.tls12_prf.hmac ); - - /* We leave the fields Ai and output_block to be erased safely by the - * mbedtls_platform_zeroize() in the end of this function. */ - } - else -#endif /* MBEDTLS_MD_C */ - { - status = PSA_ERROR_BAD_STATE; - } - mbedtls_platform_zeroize( operation, sizeof( *operation ) ); - return( status ); -} - -psa_status_t psa_key_derivation_get_capacity(const psa_key_derivation_operation_t *operation, - size_t *capacity) -{ - if( operation->alg == 0 ) - { - /* This is a blank key derivation operation. */ - return PSA_ERROR_BAD_STATE; - } - - *capacity = operation->capacity; - return( PSA_SUCCESS ); -} - -psa_status_t psa_key_derivation_set_capacity( psa_key_derivation_operation_t *operation, - size_t capacity ) -{ - if( operation->alg == 0 ) - return( PSA_ERROR_BAD_STATE ); - if( capacity > operation->capacity ) - return( PSA_ERROR_INVALID_ARGUMENT ); - operation->capacity = capacity; - return( PSA_SUCCESS ); -} - -#if defined(MBEDTLS_MD_C) -/* Read some bytes from an HKDF-based operation. This performs a chunk - * of the expand phase of the HKDF algorithm. */ -static psa_status_t psa_key_derivation_hkdf_read( psa_hkdf_key_derivation_t *hkdf, - psa_algorithm_t hash_alg, - uint8_t *output, - size_t output_length ) -{ - uint8_t hash_length = PSA_HASH_SIZE( hash_alg ); - psa_status_t status; - - if( hkdf->state < HKDF_STATE_KEYED || ! hkdf->info_set ) - return( PSA_ERROR_BAD_STATE ); - hkdf->state = HKDF_STATE_OUTPUT; - - while( output_length != 0 ) - { - /* Copy what remains of the current block */ - uint8_t n = hash_length - hkdf->offset_in_block; - if( n > output_length ) - n = (uint8_t) output_length; - memcpy( output, hkdf->output_block + hkdf->offset_in_block, n ); - output += n; - output_length -= n; - hkdf->offset_in_block += n; - if( output_length == 0 ) - break; - /* We can't be wanting more output after block 0xff, otherwise - * the capacity check in psa_key_derivation_output_bytes() would have - * prevented this call. It could happen only if the operation - * object was corrupted or if this function is called directly - * inside the library. */ - if( hkdf->block_number == 0xff ) - return( PSA_ERROR_BAD_STATE ); - - /* We need a new block */ - ++hkdf->block_number; - hkdf->offset_in_block = 0; - status = psa_hmac_setup_internal( &hkdf->hmac, - hkdf->prk, hash_length, - hash_alg ); - if( status != PSA_SUCCESS ) - return( status ); - if( hkdf->block_number != 1 ) - { - status = psa_hash_update( &hkdf->hmac.hash_ctx, - hkdf->output_block, - hash_length ); - if( status != PSA_SUCCESS ) - return( status ); - } - status = psa_hash_update( &hkdf->hmac.hash_ctx, - hkdf->info, - hkdf->info_length ); - if( status != PSA_SUCCESS ) - return( status ); - status = psa_hash_update( &hkdf->hmac.hash_ctx, - &hkdf->block_number, 1 ); - if( status != PSA_SUCCESS ) - return( status ); - status = psa_hmac_finish_internal( &hkdf->hmac, - hkdf->output_block, - sizeof( hkdf->output_block ) ); - if( status != PSA_SUCCESS ) - return( status ); - } - - return( PSA_SUCCESS ); -} - -static psa_status_t psa_key_derivation_tls12_prf_generate_next_block( - psa_tls12_prf_key_derivation_t *tls12_prf, - psa_algorithm_t alg ) -{ - psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH( alg ); - uint8_t hash_length = PSA_HASH_SIZE( hash_alg ); - psa_hash_operation_t backup = PSA_HASH_OPERATION_INIT; - psa_status_t status, cleanup_status; - - /* We can't be wanting more output after block 0xff, otherwise - * the capacity check in psa_key_derivation_output_bytes() would have - * prevented this call. It could happen only if the operation - * object was corrupted or if this function is called directly - * inside the library. */ - if( tls12_prf->block_number == 0xff ) - return( PSA_ERROR_CORRUPTION_DETECTED ); - - /* We need a new block */ - ++tls12_prf->block_number; - tls12_prf->left_in_block = hash_length; - - /* Recall the definition of the TLS-1.2-PRF from RFC 5246: - * - * PRF(secret, label, seed) = P_(secret, label + seed) - * - * P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + - * HMAC_hash(secret, A(2) + seed) + - * HMAC_hash(secret, A(3) + seed) + ... - * - * A(0) = seed - * A(i) = HMAC_hash(secret, A(i-1)) - * - * The `psa_tls12_prf_key_derivation` structure saves the block - * `HMAC_hash(secret, A(i) + seed)` from which the output - * is currently extracted as `output_block` and where i is - * `block_number`. - */ - - /* Save the hash context before using it, to preserve the hash state with - * only the inner padding in it. We need this, because inner padding depends - * on the key (secret in the RFC's terminology). */ - status = psa_hash_clone( &tls12_prf->hmac.hash_ctx, &backup ); - if( status != PSA_SUCCESS ) - goto cleanup; - - /* Calculate A(i) where i = tls12_prf->block_number. */ - if( tls12_prf->block_number == 1 ) - { - /* A(1) = HMAC_hash(secret, A(0)), where A(0) = seed. (The RFC overloads - * the variable seed and in this instance means it in the context of the - * P_hash function, where seed = label + seed.) */ - status = psa_hash_update( &tls12_prf->hmac.hash_ctx, - tls12_prf->label, tls12_prf->label_length ); - if( status != PSA_SUCCESS ) - goto cleanup; - status = psa_hash_update( &tls12_prf->hmac.hash_ctx, - tls12_prf->seed, tls12_prf->seed_length ); - if( status != PSA_SUCCESS ) - goto cleanup; - } - else - { - /* A(i) = HMAC_hash(secret, A(i-1)) */ - status = psa_hash_update( &tls12_prf->hmac.hash_ctx, - tls12_prf->Ai, hash_length ); - if( status != PSA_SUCCESS ) - goto cleanup; - } - - status = psa_hmac_finish_internal( &tls12_prf->hmac, - tls12_prf->Ai, hash_length ); - if( status != PSA_SUCCESS ) - goto cleanup; - status = psa_hash_clone( &backup, &tls12_prf->hmac.hash_ctx ); - if( status != PSA_SUCCESS ) - goto cleanup; - - /* Calculate HMAC_hash(secret, A(i) + label + seed). */ - status = psa_hash_update( &tls12_prf->hmac.hash_ctx, - tls12_prf->Ai, hash_length ); - if( status != PSA_SUCCESS ) - goto cleanup; - status = psa_hash_update( &tls12_prf->hmac.hash_ctx, - tls12_prf->label, tls12_prf->label_length ); - if( status != PSA_SUCCESS ) - goto cleanup; - status = psa_hash_update( &tls12_prf->hmac.hash_ctx, - tls12_prf->seed, tls12_prf->seed_length ); - if( status != PSA_SUCCESS ) - goto cleanup; - status = psa_hmac_finish_internal( &tls12_prf->hmac, - tls12_prf->output_block, hash_length ); - if( status != PSA_SUCCESS ) - goto cleanup; - status = psa_hash_clone( &backup, &tls12_prf->hmac.hash_ctx ); - if( status != PSA_SUCCESS ) - goto cleanup; - - -cleanup: - - cleanup_status = psa_hash_abort( &backup ); - if( status == PSA_SUCCESS && cleanup_status != PSA_SUCCESS ) - status = cleanup_status; - - return( status ); -} - -static psa_status_t psa_key_derivation_tls12_prf_read( - psa_tls12_prf_key_derivation_t *tls12_prf, - psa_algorithm_t alg, - uint8_t *output, - size_t output_length ) -{ - psa_algorithm_t hash_alg = PSA_ALG_TLS12_PRF_GET_HASH( alg ); - uint8_t hash_length = PSA_HASH_SIZE( hash_alg ); - psa_status_t status; - uint8_t offset, length; - - while( output_length != 0 ) - { - /* Check if we have fully processed the current block. */ - if( tls12_prf->left_in_block == 0 ) - { - status = psa_key_derivation_tls12_prf_generate_next_block( tls12_prf, - alg ); - if( status != PSA_SUCCESS ) - return( status ); - - continue; - } - - if( tls12_prf->left_in_block > output_length ) - length = (uint8_t) output_length; - else - length = tls12_prf->left_in_block; - - offset = hash_length - tls12_prf->left_in_block; - memcpy( output, tls12_prf->output_block + offset, length ); - output += length; - output_length -= length; - tls12_prf->left_in_block -= length; - } - - return( PSA_SUCCESS ); -} -#endif /* MBEDTLS_MD_C */ - -psa_status_t psa_key_derivation_output_bytes( - psa_key_derivation_operation_t *operation, - uint8_t *output, - size_t output_length ) -{ - psa_status_t status; - psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg( operation ); - - if( operation->alg == 0 ) - { - /* This is a blank operation. */ - return PSA_ERROR_BAD_STATE; - } - - if( output_length > operation->capacity ) - { - operation->capacity = 0; - /* Go through the error path to wipe all confidential data now - * that the operation object is useless. */ - status = PSA_ERROR_INSUFFICIENT_DATA; - goto exit; - } - if( output_length == 0 && operation->capacity == 0 ) - { - /* Edge case: this is a finished operation, and 0 bytes - * were requested. The right error in this case could - * be either INSUFFICIENT_CAPACITY or BAD_STATE. Return - * INSUFFICIENT_CAPACITY, which is right for a finished - * operation, for consistency with the case when - * output_length > 0. */ - return( PSA_ERROR_INSUFFICIENT_DATA ); - } - operation->capacity -= output_length; - -#if defined(MBEDTLS_MD_C) - if( PSA_ALG_IS_HKDF( kdf_alg ) ) - { - psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH( kdf_alg ); - status = psa_key_derivation_hkdf_read( &operation->ctx.hkdf, hash_alg, - output, output_length ); - } - else - if( PSA_ALG_IS_TLS12_PRF( kdf_alg ) || - PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) ) - { - status = psa_key_derivation_tls12_prf_read( &operation->ctx.tls12_prf, - kdf_alg, output, - output_length ); - } - else -#endif /* MBEDTLS_MD_C */ - { - return( PSA_ERROR_BAD_STATE ); - } - -exit: - if( status != PSA_SUCCESS ) - { - /* Preserve the algorithm upon errors, but clear all sensitive state. - * This allows us to differentiate between exhausted operations and - * blank operations, so we can return PSA_ERROR_BAD_STATE on blank - * operations. */ - psa_algorithm_t alg = operation->alg; - psa_key_derivation_abort( operation ); - operation->alg = alg; - memset( output, '!', output_length ); - } - return( status ); -} - -#if defined(MBEDTLS_DES_C) -static void psa_des_set_key_parity( uint8_t *data, size_t data_size ) -{ - if( data_size >= 8 ) - mbedtls_des_key_set_parity( data ); - if( data_size >= 16 ) - mbedtls_des_key_set_parity( data + 8 ); - if( data_size >= 24 ) - mbedtls_des_key_set_parity( data + 16 ); -} -#endif /* MBEDTLS_DES_C */ - -static psa_status_t psa_generate_derived_key_internal( - psa_key_slot_t *slot, - size_t bits, - psa_key_derivation_operation_t *operation ) -{ - uint8_t *data = NULL; - size_t bytes = PSA_BITS_TO_BYTES( bits ); - psa_status_t status; - - if( ! key_type_is_raw_bytes( slot->attr.type ) ) - return( PSA_ERROR_INVALID_ARGUMENT ); - if( bits % 8 != 0 ) - return( PSA_ERROR_INVALID_ARGUMENT ); - data = mbedtls_calloc( 1, bytes ); - if( data == NULL ) - return( PSA_ERROR_INSUFFICIENT_MEMORY ); - - status = psa_key_derivation_output_bytes( operation, data, bytes ); - if( status != PSA_SUCCESS ) - goto exit; -#if defined(MBEDTLS_DES_C) - if( slot->attr.type == PSA_KEY_TYPE_DES ) - psa_des_set_key_parity( data, bytes ); -#endif /* MBEDTLS_DES_C */ - status = psa_import_key_into_slot( slot, data, bytes ); - -exit: - mbedtls_free( data ); - return( status ); -} - -psa_status_t psa_key_derivation_output_key( const psa_key_attributes_t *attributes, - psa_key_derivation_operation_t *operation, - psa_key_handle_t *handle ) -{ - psa_status_t status; - psa_key_slot_t *slot = NULL; - psa_se_drv_table_entry_t *driver = NULL; - - /* Reject any attempt to create a zero-length key so that we don't - * risk tripping up later, e.g. on a malloc(0) that returns NULL. */ - if( psa_get_key_bits( attributes ) == 0 ) - return( PSA_ERROR_INVALID_ARGUMENT ); - - if( ! operation->can_output_key ) - return( PSA_ERROR_NOT_PERMITTED ); - - status = psa_start_key_creation( PSA_KEY_CREATION_DERIVE, - attributes, handle, &slot, &driver ); -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - if( driver != NULL ) - { - /* Deriving a key in a secure element is not implemented yet. */ - status = PSA_ERROR_NOT_SUPPORTED; - } -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - if( status == PSA_SUCCESS ) - { - status = psa_generate_derived_key_internal( slot, - attributes->core.bits, - operation ); - } - if( status == PSA_SUCCESS ) - status = psa_finish_key_creation( slot, driver ); - if( status != PSA_SUCCESS ) - { - psa_fail_key_creation( slot, driver ); - *handle = 0; - } - return( status ); -} - - - -/****************************************************************/ -/* Key derivation */ -/****************************************************************/ - -static psa_status_t psa_key_derivation_setup_kdf( - psa_key_derivation_operation_t *operation, - psa_algorithm_t kdf_alg ) -{ - /* Make sure that operation->ctx is properly zero-initialised. (Macro - * initialisers for this union leave some bytes unspecified.) */ - memset( &operation->ctx, 0, sizeof( operation->ctx ) ); - - /* Make sure that kdf_alg is a supported key derivation algorithm. */ -#if defined(MBEDTLS_MD_C) - if( PSA_ALG_IS_HKDF( kdf_alg ) || - PSA_ALG_IS_TLS12_PRF( kdf_alg ) || - PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) ) - { - psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH( kdf_alg ); - size_t hash_size = PSA_HASH_SIZE( hash_alg ); - if( hash_size == 0 ) - return( PSA_ERROR_NOT_SUPPORTED ); - if( ( PSA_ALG_IS_TLS12_PRF( kdf_alg ) || - PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) ) && - ! ( hash_alg == PSA_ALG_SHA_256 || hash_alg == PSA_ALG_SHA_384 ) ) - { - return( PSA_ERROR_NOT_SUPPORTED ); - } - operation->capacity = 255 * hash_size; - return( PSA_SUCCESS ); - } -#endif /* MBEDTLS_MD_C */ - else - return( PSA_ERROR_NOT_SUPPORTED ); -} - -psa_status_t psa_key_derivation_setup( psa_key_derivation_operation_t *operation, - psa_algorithm_t alg ) -{ - psa_status_t status; - - if( operation->alg != 0 ) - return( PSA_ERROR_BAD_STATE ); - - if( PSA_ALG_IS_RAW_KEY_AGREEMENT( alg ) ) - return( PSA_ERROR_INVALID_ARGUMENT ); - else if( PSA_ALG_IS_KEY_AGREEMENT( alg ) ) - { - psa_algorithm_t kdf_alg = PSA_ALG_KEY_AGREEMENT_GET_KDF( alg ); - status = psa_key_derivation_setup_kdf( operation, kdf_alg ); - } - else if( PSA_ALG_IS_KEY_DERIVATION( alg ) ) - { - status = psa_key_derivation_setup_kdf( operation, alg ); - } - else - return( PSA_ERROR_INVALID_ARGUMENT ); - - if( status == PSA_SUCCESS ) - operation->alg = alg; - return( status ); -} - -#if defined(MBEDTLS_MD_C) -static psa_status_t psa_hkdf_input( psa_hkdf_key_derivation_t *hkdf, - psa_algorithm_t hash_alg, - psa_key_derivation_step_t step, - const uint8_t *data, - size_t data_length ) -{ - psa_status_t status; - switch( step ) - { - case PSA_KEY_DERIVATION_INPUT_SALT: - if( hkdf->state != HKDF_STATE_INIT ) - return( PSA_ERROR_BAD_STATE ); - status = psa_hmac_setup_internal( &hkdf->hmac, - data, data_length, - hash_alg ); - if( status != PSA_SUCCESS ) - return( status ); - hkdf->state = HKDF_STATE_STARTED; - return( PSA_SUCCESS ); - case PSA_KEY_DERIVATION_INPUT_SECRET: - /* If no salt was provided, use an empty salt. */ - if( hkdf->state == HKDF_STATE_INIT ) - { - status = psa_hmac_setup_internal( &hkdf->hmac, - NULL, 0, - hash_alg ); - if( status != PSA_SUCCESS ) - return( status ); - hkdf->state = HKDF_STATE_STARTED; - } - if( hkdf->state != HKDF_STATE_STARTED ) - return( PSA_ERROR_BAD_STATE ); - status = psa_hash_update( &hkdf->hmac.hash_ctx, - data, data_length ); - if( status != PSA_SUCCESS ) - return( status ); - status = psa_hmac_finish_internal( &hkdf->hmac, - hkdf->prk, - sizeof( hkdf->prk ) ); - if( status != PSA_SUCCESS ) - return( status ); - hkdf->offset_in_block = PSA_HASH_SIZE( hash_alg ); - hkdf->block_number = 0; - hkdf->state = HKDF_STATE_KEYED; - return( PSA_SUCCESS ); - case PSA_KEY_DERIVATION_INPUT_INFO: - if( hkdf->state == HKDF_STATE_OUTPUT ) - return( PSA_ERROR_BAD_STATE ); - if( hkdf->info_set ) - return( PSA_ERROR_BAD_STATE ); - hkdf->info_length = data_length; - if( data_length != 0 ) - { - hkdf->info = mbedtls_calloc( 1, data_length ); - if( hkdf->info == NULL ) - return( PSA_ERROR_INSUFFICIENT_MEMORY ); - memcpy( hkdf->info, data, data_length ); - } - hkdf->info_set = 1; - return( PSA_SUCCESS ); - default: - return( PSA_ERROR_INVALID_ARGUMENT ); - } -} - -static psa_status_t psa_tls12_prf_set_seed( psa_tls12_prf_key_derivation_t *prf, - const uint8_t *data, - size_t data_length ) -{ - if( prf->state != TLS12_PRF_STATE_INIT ) - return( PSA_ERROR_BAD_STATE ); - - if( data_length != 0 ) - { - prf->seed = mbedtls_calloc( 1, data_length ); - if( prf->seed == NULL ) - return( PSA_ERROR_INSUFFICIENT_MEMORY ); - - memcpy( prf->seed, data, data_length ); - prf->seed_length = data_length; - } - - prf->state = TLS12_PRF_STATE_SEED_SET; - - return( PSA_SUCCESS ); -} - -static psa_status_t psa_tls12_prf_set_key( psa_tls12_prf_key_derivation_t *prf, - psa_algorithm_t hash_alg, - const uint8_t *data, - size_t data_length ) -{ - psa_status_t status; - if( prf->state != TLS12_PRF_STATE_SEED_SET ) - return( PSA_ERROR_BAD_STATE ); - - status = psa_hmac_setup_internal( &prf->hmac, data, data_length, hash_alg ); - if( status != PSA_SUCCESS ) - return( status ); - - prf->state = TLS12_PRF_STATE_KEY_SET; - - return( PSA_SUCCESS ); -} - -static psa_status_t psa_tls12_prf_psk_to_ms_set_key( - psa_tls12_prf_key_derivation_t *prf, - psa_algorithm_t hash_alg, - const uint8_t *data, - size_t data_length ) -{ - psa_status_t status; - uint8_t pms[ 4 + 2 * PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN ]; - uint8_t *cur = pms; - - if( data_length > PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN ) - return( PSA_ERROR_INVALID_ARGUMENT ); - - /* Quoting RFC 4279, Section 2: - * - * The premaster secret is formed as follows: if the PSK is N octets - * long, concatenate a uint16 with the value N, N zero octets, a second - * uint16 with the value N, and the PSK itself. - */ - - *cur++ = ( data_length >> 8 ) & 0xff; - *cur++ = ( data_length >> 0 ) & 0xff; - memset( cur, 0, data_length ); - cur += data_length; - *cur++ = pms[0]; - *cur++ = pms[1]; - memcpy( cur, data, data_length ); - cur += data_length; - - status = psa_tls12_prf_set_key( prf, hash_alg, pms, cur - pms ); - - mbedtls_platform_zeroize( pms, sizeof( pms ) ); - return( status ); -} - -static psa_status_t psa_tls12_prf_set_label( psa_tls12_prf_key_derivation_t *prf, - const uint8_t *data, - size_t data_length ) -{ - if( prf->state != TLS12_PRF_STATE_KEY_SET ) - return( PSA_ERROR_BAD_STATE ); - - if( data_length != 0 ) - { - prf->label = mbedtls_calloc( 1, data_length ); - if( prf->label == NULL ) - return( PSA_ERROR_INSUFFICIENT_MEMORY ); - - memcpy( prf->label, data, data_length ); - prf->label_length = data_length; - } - - prf->state = TLS12_PRF_STATE_LABEL_SET; - - return( PSA_SUCCESS ); -} - -static psa_status_t psa_tls12_prf_input( psa_tls12_prf_key_derivation_t *prf, - psa_algorithm_t hash_alg, - psa_key_derivation_step_t step, - const uint8_t *data, - size_t data_length ) -{ - switch( step ) - { - case PSA_KEY_DERIVATION_INPUT_SEED: - return( psa_tls12_prf_set_seed( prf, data, data_length ) ); - case PSA_KEY_DERIVATION_INPUT_SECRET: - return( psa_tls12_prf_set_key( prf, hash_alg, data, data_length ) ); - case PSA_KEY_DERIVATION_INPUT_LABEL: - return( psa_tls12_prf_set_label( prf, data, data_length ) ); - default: - return( PSA_ERROR_INVALID_ARGUMENT ); - } -} - -static psa_status_t psa_tls12_prf_psk_to_ms_input( - psa_tls12_prf_key_derivation_t *prf, - psa_algorithm_t hash_alg, - psa_key_derivation_step_t step, - const uint8_t *data, - size_t data_length ) -{ - if( step == PSA_KEY_DERIVATION_INPUT_SECRET ) - { - return( psa_tls12_prf_psk_to_ms_set_key( prf, hash_alg, - data, data_length ) ); - } - - return( psa_tls12_prf_input( prf, hash_alg, step, data, data_length ) ); -} -#endif /* MBEDTLS_MD_C */ - -/** Check whether the given key type is acceptable for the given - * input step of a key derivation. - * - * Secret inputs must have the type #PSA_KEY_TYPE_DERIVE. - * Non-secret inputs must have the type #PSA_KEY_TYPE_RAW_DATA. - * Both secret and non-secret inputs can alternatively have the type - * #PSA_KEY_TYPE_NONE, which is never the type of a key object, meaning - * that the input was passed as a buffer rather than via a key object. - */ -static int psa_key_derivation_check_input_type( - psa_key_derivation_step_t step, - psa_key_type_t key_type ) -{ - switch( step ) - { - case PSA_KEY_DERIVATION_INPUT_SECRET: - if( key_type == PSA_KEY_TYPE_DERIVE ) - return( PSA_SUCCESS ); - if( key_type == PSA_KEY_TYPE_NONE ) - return( PSA_SUCCESS ); - break; - case PSA_KEY_DERIVATION_INPUT_LABEL: - case PSA_KEY_DERIVATION_INPUT_SALT: - case PSA_KEY_DERIVATION_INPUT_INFO: - case PSA_KEY_DERIVATION_INPUT_SEED: - if( key_type == PSA_KEY_TYPE_RAW_DATA ) - return( PSA_SUCCESS ); - if( key_type == PSA_KEY_TYPE_NONE ) - return( PSA_SUCCESS ); - break; - } - return( PSA_ERROR_INVALID_ARGUMENT ); -} - -static psa_status_t psa_key_derivation_input_internal( - psa_key_derivation_operation_t *operation, - psa_key_derivation_step_t step, - psa_key_type_t key_type, - const uint8_t *data, - size_t data_length ) -{ - psa_status_t status; - psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg( operation ); - - status = psa_key_derivation_check_input_type( step, key_type ); - if( status != PSA_SUCCESS ) - goto exit; - -#if defined(MBEDTLS_MD_C) - if( PSA_ALG_IS_HKDF( kdf_alg ) ) - { - status = psa_hkdf_input( &operation->ctx.hkdf, - PSA_ALG_HKDF_GET_HASH( kdf_alg ), - step, data, data_length ); - } - else if( PSA_ALG_IS_TLS12_PRF( kdf_alg ) ) - { - status = psa_tls12_prf_input( &operation->ctx.tls12_prf, - PSA_ALG_HKDF_GET_HASH( kdf_alg ), - step, data, data_length ); - } - else if( PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) ) - { - status = psa_tls12_prf_psk_to_ms_input( &operation->ctx.tls12_prf, - PSA_ALG_HKDF_GET_HASH( kdf_alg ), - step, data, data_length ); - } - else -#endif /* MBEDTLS_MD_C */ - { - /* This can't happen unless the operation object was not initialized */ - return( PSA_ERROR_BAD_STATE ); - } - -exit: - if( status != PSA_SUCCESS ) - psa_key_derivation_abort( operation ); - return( status ); -} - -psa_status_t psa_key_derivation_input_bytes( - psa_key_derivation_operation_t *operation, - psa_key_derivation_step_t step, - const uint8_t *data, - size_t data_length ) -{ - return( psa_key_derivation_input_internal( operation, step, - PSA_KEY_TYPE_NONE, - data, data_length ) ); -} - -psa_status_t psa_key_derivation_input_key( - psa_key_derivation_operation_t *operation, - psa_key_derivation_step_t step, - psa_key_handle_t handle ) -{ - psa_key_slot_t *slot; - psa_status_t status; - - status = psa_get_transparent_key( handle, &slot, - PSA_KEY_USAGE_DERIVE, - operation->alg ); - if( status != PSA_SUCCESS ) - { - psa_key_derivation_abort( operation ); - return( status ); - } - - /* Passing a key object as a SECRET input unlocks the permission - * to output to a key object. */ - if( step == PSA_KEY_DERIVATION_INPUT_SECRET ) - operation->can_output_key = 1; - - return( psa_key_derivation_input_internal( operation, - step, slot->attr.type, - slot->data.raw.data, - slot->data.raw.bytes ) ); -} - - - -/****************************************************************/ -/* Key agreement */ -/****************************************************************/ - -#if defined(MBEDTLS_ECDH_C) -static psa_status_t psa_key_agreement_ecdh( const uint8_t *peer_key, - size_t peer_key_length, - const mbedtls_ecp_keypair *our_key, - uint8_t *shared_secret, - size_t shared_secret_size, - size_t *shared_secret_length ) -{ - mbedtls_ecp_keypair *their_key = NULL; - mbedtls_ecdh_context ecdh; - psa_status_t status; - size_t bits = 0; - psa_ecc_curve_t curve = mbedtls_ecc_group_to_psa( our_key->grp.id, &bits ); - mbedtls_ecdh_init( &ecdh ); - - status = psa_import_ec_public_key( curve, - peer_key, peer_key_length, - &their_key ); - if( status != PSA_SUCCESS ) - goto exit; - - status = mbedtls_to_psa_error( - mbedtls_ecdh_get_params( &ecdh, their_key, MBEDTLS_ECDH_THEIRS ) ); - if( status != PSA_SUCCESS ) - goto exit; - status = mbedtls_to_psa_error( - mbedtls_ecdh_get_params( &ecdh, our_key, MBEDTLS_ECDH_OURS ) ); - if( status != PSA_SUCCESS ) - goto exit; - - status = mbedtls_to_psa_error( - mbedtls_ecdh_calc_secret( &ecdh, - shared_secret_length, - shared_secret, shared_secret_size, - mbedtls_ctr_drbg_random, - &global_data.ctr_drbg ) ); - if( status != PSA_SUCCESS ) - goto exit; - if( PSA_BITS_TO_BYTES( bits ) != *shared_secret_length ) - status = PSA_ERROR_CORRUPTION_DETECTED; - -exit: - if( status != PSA_SUCCESS ) - mbedtls_platform_zeroize( shared_secret, shared_secret_size ); - mbedtls_ecdh_free( &ecdh ); - mbedtls_ecp_keypair_free( their_key ); - mbedtls_free( their_key ); - return( status ); -} -#endif /* MBEDTLS_ECDH_C */ - -#define PSA_KEY_AGREEMENT_MAX_SHARED_SECRET_SIZE MBEDTLS_ECP_MAX_BYTES - -static psa_status_t psa_key_agreement_raw_internal( psa_algorithm_t alg, - psa_key_slot_t *private_key, - const uint8_t *peer_key, - size_t peer_key_length, - uint8_t *shared_secret, - size_t shared_secret_size, - size_t *shared_secret_length ) -{ - switch( alg ) - { -#if defined(MBEDTLS_ECDH_C) - case PSA_ALG_ECDH: - if( ! PSA_KEY_TYPE_IS_ECC_KEY_PAIR( private_key->attr.type ) ) - return( PSA_ERROR_INVALID_ARGUMENT ); - return( psa_key_agreement_ecdh( peer_key, peer_key_length, - private_key->data.ecp, - shared_secret, shared_secret_size, - shared_secret_length ) ); -#endif /* MBEDTLS_ECDH_C */ - default: - (void) private_key; - (void) peer_key; - (void) peer_key_length; - (void) shared_secret; - (void) shared_secret_size; - (void) shared_secret_length; - return( PSA_ERROR_NOT_SUPPORTED ); - } -} - -/* Note that if this function fails, you must call psa_key_derivation_abort() - * to potentially free embedded data structures and wipe confidential data. - */ -static psa_status_t psa_key_agreement_internal( psa_key_derivation_operation_t *operation, - psa_key_derivation_step_t step, - psa_key_slot_t *private_key, - const uint8_t *peer_key, - size_t peer_key_length ) -{ - psa_status_t status; - uint8_t shared_secret[PSA_KEY_AGREEMENT_MAX_SHARED_SECRET_SIZE]; - size_t shared_secret_length = 0; - psa_algorithm_t ka_alg = PSA_ALG_KEY_AGREEMENT_GET_BASE( operation->alg ); - - /* Step 1: run the secret agreement algorithm to generate the shared - * secret. */ - status = psa_key_agreement_raw_internal( ka_alg, - private_key, - peer_key, peer_key_length, - shared_secret, - sizeof( shared_secret ), - &shared_secret_length ); - if( status != PSA_SUCCESS ) - goto exit; - - /* Step 2: set up the key derivation to generate key material from - * the shared secret. A shared secret is permitted wherever a key - * of type DERIVE is permitted. */ - status = psa_key_derivation_input_internal( operation, step, - PSA_KEY_TYPE_DERIVE, - shared_secret, - shared_secret_length ); - -exit: - mbedtls_platform_zeroize( shared_secret, shared_secret_length ); - return( status ); -} - -psa_status_t psa_key_derivation_key_agreement( psa_key_derivation_operation_t *operation, - psa_key_derivation_step_t step, - psa_key_handle_t private_key, - const uint8_t *peer_key, - size_t peer_key_length ) -{ - psa_key_slot_t *slot; - psa_status_t status; - if( ! PSA_ALG_IS_KEY_AGREEMENT( operation->alg ) ) - return( PSA_ERROR_INVALID_ARGUMENT ); - status = psa_get_transparent_key( private_key, &slot, - PSA_KEY_USAGE_DERIVE, operation->alg ); - if( status != PSA_SUCCESS ) - return( status ); - status = psa_key_agreement_internal( operation, step, - slot, - peer_key, peer_key_length ); - if( status != PSA_SUCCESS ) - psa_key_derivation_abort( operation ); - return( status ); -} - -psa_status_t psa_raw_key_agreement( psa_algorithm_t alg, - psa_key_handle_t private_key, - const uint8_t *peer_key, - size_t peer_key_length, - uint8_t *output, - size_t output_size, - size_t *output_length ) -{ - psa_key_slot_t *slot; - psa_status_t status; - - if( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) ) - { - status = PSA_ERROR_INVALID_ARGUMENT; - goto exit; - } - status = psa_get_transparent_key( private_key, &slot, - PSA_KEY_USAGE_DERIVE, alg ); - if( status != PSA_SUCCESS ) - goto exit; - - status = psa_key_agreement_raw_internal( alg, slot, - peer_key, peer_key_length, - output, output_size, - output_length ); - -exit: - if( status != PSA_SUCCESS ) - { - /* If an error happens and is not handled properly, the output - * may be used as a key to protect sensitive data. Arrange for such - * a key to be random, which is likely to result in decryption or - * verification errors. This is better than filling the buffer with - * some constant data such as zeros, which would result in the data - * being protected with a reproducible, easily knowable key. - */ - psa_generate_random( output, output_size ); - *output_length = output_size; - } - return( status ); -} - - -/****************************************************************/ -/* Random generation */ -/****************************************************************/ - -psa_status_t psa_generate_random( uint8_t *output, - size_t output_size ) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - GUARD_MODULE_INITIALIZED; - - while( output_size > MBEDTLS_CTR_DRBG_MAX_REQUEST ) - { - ret = mbedtls_ctr_drbg_random( &global_data.ctr_drbg, - output, - MBEDTLS_CTR_DRBG_MAX_REQUEST ); - if( ret != 0 ) - return( mbedtls_to_psa_error( ret ) ); - output += MBEDTLS_CTR_DRBG_MAX_REQUEST; - output_size -= MBEDTLS_CTR_DRBG_MAX_REQUEST; - } - - ret = mbedtls_ctr_drbg_random( &global_data.ctr_drbg, output, output_size ); - return( mbedtls_to_psa_error( ret ) ); -} - -#if defined(MBEDTLS_PSA_INJECT_ENTROPY) -#include "mbedtls/entropy_poll.h" - -psa_status_t mbedtls_psa_inject_entropy( const uint8_t *seed, - size_t seed_size ) -{ - if( global_data.initialized ) - return( PSA_ERROR_NOT_PERMITTED ); - - if( ( ( seed_size < MBEDTLS_ENTROPY_MIN_PLATFORM ) || - ( seed_size < MBEDTLS_ENTROPY_BLOCK_SIZE ) ) || - ( seed_size > MBEDTLS_ENTROPY_MAX_SEED_SIZE ) ) - return( PSA_ERROR_INVALID_ARGUMENT ); - - return( mbedtls_psa_storage_inject_entropy( seed, seed_size ) ); -} -#endif /* MBEDTLS_PSA_INJECT_ENTROPY */ - -#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_GENPRIME) -static psa_status_t psa_read_rsa_exponent( const uint8_t *domain_parameters, - size_t domain_parameters_size, - int *exponent ) -{ - size_t i; - uint32_t acc = 0; - - if( domain_parameters_size == 0 ) - { - *exponent = 65537; - return( PSA_SUCCESS ); - } - - /* Mbed TLS encodes the public exponent as an int. For simplicity, only - * support values that fit in a 32-bit integer, which is larger than - * int on just about every platform anyway. */ - if( domain_parameters_size > sizeof( acc ) ) - return( PSA_ERROR_NOT_SUPPORTED ); - for( i = 0; i < domain_parameters_size; i++ ) - acc = ( acc << 8 ) | domain_parameters[i]; - if( acc > INT_MAX ) - return( PSA_ERROR_NOT_SUPPORTED ); - *exponent = acc; - return( PSA_SUCCESS ); -} -#endif /* MBEDTLS_RSA_C && MBEDTLS_GENPRIME */ - -static psa_status_t psa_generate_key_internal( - psa_key_slot_t *slot, size_t bits, - const uint8_t *domain_parameters, size_t domain_parameters_size ) -{ - psa_key_type_t type = slot->attr.type; - - if( domain_parameters == NULL && domain_parameters_size != 0 ) - return( PSA_ERROR_INVALID_ARGUMENT ); - - if( key_type_is_raw_bytes( type ) ) - { - psa_status_t status; - status = prepare_raw_data_slot( type, bits, &slot->data.raw ); - if( status != PSA_SUCCESS ) - return( status ); - status = psa_generate_random( slot->data.raw.data, - slot->data.raw.bytes ); - if( status != PSA_SUCCESS ) - return( status ); -#if defined(MBEDTLS_DES_C) - if( type == PSA_KEY_TYPE_DES ) - psa_des_set_key_parity( slot->data.raw.data, - slot->data.raw.bytes ); -#endif /* MBEDTLS_DES_C */ - } - else - -#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_GENPRIME) - if ( type == PSA_KEY_TYPE_RSA_KEY_PAIR ) - { - mbedtls_rsa_context *rsa; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - int exponent; - psa_status_t status; - if( bits > PSA_VENDOR_RSA_MAX_KEY_BITS ) - return( PSA_ERROR_NOT_SUPPORTED ); - /* Accept only byte-aligned keys, for the same reasons as - * in psa_import_rsa_key(). */ - if( bits % 8 != 0 ) - return( PSA_ERROR_NOT_SUPPORTED ); - status = psa_read_rsa_exponent( domain_parameters, - domain_parameters_size, - &exponent ); - if( status != PSA_SUCCESS ) - return( status ); - rsa = mbedtls_calloc( 1, sizeof( *rsa ) ); - if( rsa == NULL ) - return( PSA_ERROR_INSUFFICIENT_MEMORY ); - mbedtls_rsa_init( rsa, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE ); - ret = mbedtls_rsa_gen_key( rsa, - mbedtls_ctr_drbg_random, - &global_data.ctr_drbg, - (unsigned int) bits, - exponent ); - if( ret != 0 ) - { - mbedtls_rsa_free( rsa ); - mbedtls_free( rsa ); - return( mbedtls_to_psa_error( ret ) ); - } - slot->data.rsa = rsa; - } - else -#endif /* MBEDTLS_RSA_C && MBEDTLS_GENPRIME */ - -#if defined(MBEDTLS_ECP_C) - if ( PSA_KEY_TYPE_IS_ECC( type ) && PSA_KEY_TYPE_IS_KEY_PAIR( type ) ) - { - psa_ecc_curve_t curve = PSA_KEY_TYPE_GET_CURVE( type ); - mbedtls_ecp_group_id grp_id = - mbedtls_ecc_group_of_psa( curve, PSA_BITS_TO_BYTES( bits ) ); - const mbedtls_ecp_curve_info *curve_info = - mbedtls_ecp_curve_info_from_grp_id( grp_id ); - mbedtls_ecp_keypair *ecp; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - if( domain_parameters_size != 0 ) - return( PSA_ERROR_NOT_SUPPORTED ); - if( grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL ) - return( PSA_ERROR_NOT_SUPPORTED ); - if( curve_info->bit_size != bits ) - return( PSA_ERROR_INVALID_ARGUMENT ); - ecp = mbedtls_calloc( 1, sizeof( *ecp ) ); - if( ecp == NULL ) - return( PSA_ERROR_INSUFFICIENT_MEMORY ); - mbedtls_ecp_keypair_init( ecp ); - ret = mbedtls_ecp_gen_key( grp_id, ecp, - mbedtls_ctr_drbg_random, - &global_data.ctr_drbg ); - if( ret != 0 ) - { - mbedtls_ecp_keypair_free( ecp ); - mbedtls_free( ecp ); - return( mbedtls_to_psa_error( ret ) ); - } - slot->data.ecp = ecp; - } - else -#endif /* MBEDTLS_ECP_C */ - - return( PSA_ERROR_NOT_SUPPORTED ); - - return( PSA_SUCCESS ); -} - -psa_status_t psa_generate_key( const psa_key_attributes_t *attributes, - psa_key_handle_t *handle ) -{ - psa_status_t status; - psa_key_slot_t *slot = NULL; - psa_se_drv_table_entry_t *driver = NULL; - - /* Reject any attempt to create a zero-length key so that we don't - * risk tripping up later, e.g. on a malloc(0) that returns NULL. */ - if( psa_get_key_bits( attributes ) == 0 ) - return( PSA_ERROR_INVALID_ARGUMENT ); - - status = psa_start_key_creation( PSA_KEY_CREATION_GENERATE, - attributes, handle, &slot, &driver ); - if( status != PSA_SUCCESS ) - goto exit; - -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - if( driver != NULL ) - { - const psa_drv_se_t *drv = psa_get_se_driver_methods( driver ); - size_t pubkey_length = 0; /* We don't support this feature yet */ - if( drv->key_management == NULL || - drv->key_management->p_generate == NULL ) - { - status = PSA_ERROR_NOT_SUPPORTED; - goto exit; - } - status = drv->key_management->p_generate( - psa_get_se_driver_context( driver ), - slot->data.se.slot_number, attributes, - NULL, 0, &pubkey_length ); - } - else -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - { - status = psa_generate_key_internal( - slot, attributes->core.bits, - attributes->domain_parameters, attributes->domain_parameters_size ); - } - -exit: - if( status == PSA_SUCCESS ) - status = psa_finish_key_creation( slot, driver ); - if( status != PSA_SUCCESS ) - { - psa_fail_key_creation( slot, driver ); - *handle = 0; - } - return( status ); -} - - - -/****************************************************************/ -/* Module setup */ -/****************************************************************/ - -psa_status_t mbedtls_psa_crypto_configure_entropy_sources( - void (* entropy_init )( mbedtls_entropy_context *ctx ), - void (* entropy_free )( mbedtls_entropy_context *ctx ) ) -{ - if( global_data.rng_state != RNG_NOT_INITIALIZED ) - return( PSA_ERROR_BAD_STATE ); - global_data.entropy_init = entropy_init; - global_data.entropy_free = entropy_free; - return( PSA_SUCCESS ); -} - -void mbedtls_psa_crypto_free( void ) -{ - psa_wipe_all_key_slots( ); - if( global_data.rng_state != RNG_NOT_INITIALIZED ) - { - mbedtls_ctr_drbg_free( &global_data.ctr_drbg ); - global_data.entropy_free( &global_data.entropy ); - } - /* Wipe all remaining data, including configuration. - * In particular, this sets all state indicator to the value - * indicating "uninitialized". */ - mbedtls_platform_zeroize( &global_data, sizeof( global_data ) ); -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - /* Unregister all secure element drivers, so that we restart from - * a pristine state. */ - psa_unregister_all_se_drivers( ); -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ -} - -#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) -/** Recover a transaction that was interrupted by a power failure. - * - * This function is called during initialization, before psa_crypto_init() - * returns. If this function returns a failure status, the initialization - * fails. - */ -static psa_status_t psa_crypto_recover_transaction( - const psa_crypto_transaction_t *transaction ) -{ - switch( transaction->unknown.type ) - { - case PSA_CRYPTO_TRANSACTION_CREATE_KEY: - case PSA_CRYPTO_TRANSACTION_DESTROY_KEY: - /* TODO - fall through to the failure case until this - * is implemented. - * https://github.com/ARMmbed/mbed-crypto/issues/218 - */ - default: - /* We found an unsupported transaction in the storage. - * We don't know what state the storage is in. Give up. */ - return( PSA_ERROR_STORAGE_FAILURE ); - } -} -#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */ - -psa_status_t psa_crypto_init( void ) -{ - psa_status_t status; - const unsigned char drbg_seed[] = "PSA"; - - /* Double initialization is explicitly allowed. */ - if( global_data.initialized != 0 ) - return( PSA_SUCCESS ); - - /* Set default configuration if - * mbedtls_psa_crypto_configure_entropy_sources() hasn't been called. */ - if( global_data.entropy_init == NULL ) - global_data.entropy_init = mbedtls_entropy_init; - if( global_data.entropy_free == NULL ) - global_data.entropy_free = mbedtls_entropy_free; - - /* Initialize the random generator. */ - global_data.entropy_init( &global_data.entropy ); -#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ - defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) - /* The PSA entropy injection feature depends on using NV seed as an entropy - * source. Add NV seed as an entropy source for PSA entropy injection. */ - mbedtls_entropy_add_source( &global_data.entropy, - mbedtls_nv_seed_poll, NULL, - MBEDTLS_ENTROPY_BLOCK_SIZE, - MBEDTLS_ENTROPY_SOURCE_STRONG ); -#endif - mbedtls_ctr_drbg_init( &global_data.ctr_drbg ); - global_data.rng_state = RNG_INITIALIZED; - status = mbedtls_to_psa_error( - mbedtls_ctr_drbg_seed( &global_data.ctr_drbg, - mbedtls_entropy_func, - &global_data.entropy, - drbg_seed, sizeof( drbg_seed ) - 1 ) ); - if( status != PSA_SUCCESS ) - goto exit; - global_data.rng_state = RNG_SEEDED; - - status = psa_initialize_key_slots( ); - if( status != PSA_SUCCESS ) - goto exit; - -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - status = psa_init_all_se_drivers( ); - if( status != PSA_SUCCESS ) - goto exit; -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - -#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) - status = psa_crypto_load_transaction( ); - if( status == PSA_SUCCESS ) - { - status = psa_crypto_recover_transaction( &psa_crypto_transaction ); - if( status != PSA_SUCCESS ) - goto exit; - status = psa_crypto_stop_transaction( ); - } - else if( status == PSA_ERROR_DOES_NOT_EXIST ) - { - /* There's no transaction to complete. It's all good. */ - status = PSA_SUCCESS; - } -#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */ - - /* All done. */ - global_data.initialized = 1; - -exit: - if( status != PSA_SUCCESS ) - mbedtls_psa_crypto_free( ); - return( status ); -} - -#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_core.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_core.h deleted file mode 100644 index edf3ab6..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_core.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - * PSA crypto core internal interfaces - */ -/* Copyright (C) 2018, ARM Limited, 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. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#ifndef PSA_CRYPTO_CORE_H -#define PSA_CRYPTO_CORE_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "psa/crypto.h" -#include "psa/crypto_se_driver.h" - -#include "mbedtls/ecp.h" -#include "mbedtls/rsa.h" - -/** The data structure representing a key slot, containing key material - * and metadata for one key. - */ -typedef struct -{ - psa_core_key_attributes_t attr; - union - { - /* Raw-data key (key_type_is_raw_bytes() in psa_crypto.c) */ - struct raw_data - { - uint8_t *data; - size_t bytes; - } raw; -#if defined(MBEDTLS_RSA_C) - /* RSA public key or key pair */ - mbedtls_rsa_context *rsa; -#endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_ECP_C) - /* EC public key or key pair */ - mbedtls_ecp_keypair *ecp; -#endif /* MBEDTLS_ECP_C */ -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - /* Any key type in a secure element */ - struct se - { - psa_key_slot_number_t slot_number; - } se; -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - } data; -} psa_key_slot_t; - -/* A mask of key attribute flags used only internally. - * Currently there aren't any. */ -#define PSA_KA_MASK_INTERNAL_ONLY ( \ - 0 ) - -/** Test whether a key slot is occupied. - * - * A key slot is occupied iff the key type is nonzero. This works because - * no valid key can have 0 as its key type. - * - * \param[in] slot The key slot to test. - * - * \return 1 if the slot is occupied, 0 otherwise. - */ -static inline int psa_is_key_slot_occupied( const psa_key_slot_t *slot ) -{ - return( slot->attr.type != 0 ); -} - -/** Retrieve flags from psa_key_slot_t::attr::core::flags. - * - * \param[in] slot The key slot to query. - * \param mask The mask of bits to extract. - * - * \return The key attribute flags in the given slot, - * bitwise-anded with \p mask. - */ -static inline uint16_t psa_key_slot_get_flags( const psa_key_slot_t *slot, - uint16_t mask ) -{ - return( slot->attr.flags & mask ); -} - -/** Set flags in psa_key_slot_t::attr::core::flags. - * - * \param[in,out] slot The key slot to modify. - * \param mask The mask of bits to modify. - * \param value The new value of the selected bits. - */ -static inline void psa_key_slot_set_flags( psa_key_slot_t *slot, - uint16_t mask, - uint16_t value ) -{ - slot->attr.flags = ( ( ~mask & slot->attr.flags ) | - ( mask & value ) ); -} - -/** Turn on flags in psa_key_slot_t::attr::core::flags. - * - * \param[in,out] slot The key slot to modify. - * \param mask The mask of bits to set. - */ -static inline void psa_key_slot_set_bits_in_flags( psa_key_slot_t *slot, - uint16_t mask ) -{ - slot->attr.flags |= mask; -} - -/** Turn off flags in psa_key_slot_t::attr::core::flags. - * - * \param[in,out] slot The key slot to modify. - * \param mask The mask of bits to clear. - */ -static inline void psa_key_slot_clear_bits( psa_key_slot_t *slot, - uint16_t mask ) -{ - slot->attr.flags &= ~mask; -} - -/** Completely wipe a slot in memory, including its policy. - * - * Persistent storage is not affected. - * - * \param[in,out] slot The key slot to wipe. - * - * \retval PSA_SUCCESS - * Success. This includes the case of a key slot that was - * already fully wiped. - * \retval PSA_ERROR_CORRUPTION_DETECTED - */ -psa_status_t psa_wipe_key_slot( psa_key_slot_t *slot ); - -/** Import key data into a slot. - * - * `slot->type` must have been set previously. - * This function assumes that the slot does not contain any key material yet. - * On failure, the slot content is unchanged. - * - * Persistent storage is not affected. - * - * \param[in,out] slot The key slot to import data into. - * Its `type` field must have previously been set to - * the desired key type. - * It must not contain any key material yet. - * \param[in] data Buffer containing the key material to parse and import. - * \param data_length Size of \p data in bytes. - * - * \retval PSA_SUCCESS - * \retval PSA_ERROR_INVALID_ARGUMENT - * \retval PSA_ERROR_NOT_SUPPORTED - * \retval PSA_ERROR_INSUFFICIENT_MEMORY - */ -psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, - const uint8_t *data, - size_t data_length ); - -#endif /* PSA_CRYPTO_CORE_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_invasive.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_invasive.h deleted file mode 100644 index 642652a..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_invasive.h +++ /dev/null @@ -1,79 +0,0 @@ -/** - * \file psa_crypto_invasive.h - * - * \brief PSA cryptography module: invasive interfaces for test only. - * - * The interfaces in this file are intended for testing purposes only. - * They MUST NOT be made available to clients over IPC in integrations - * with isolation, and they SHOULD NOT be made available in library - * integrations except when building the library for testing. - */ -/* - * Copyright (C) 2018, ARM Limited, 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. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#ifndef PSA_CRYPTO_INVASIVE_H -#define PSA_CRYPTO_INVASIVE_H - -#if defined(MBEDTLS_CONFIG_FILE) -#include MBEDTLS_CONFIG_FILE -#else -#include "mbedtls/config.h" -#endif - -#include "psa/crypto.h" - -#include "mbedtls/entropy.h" - -/** \brief Configure entropy sources. - * - * This function may only be called before a call to psa_crypto_init(), - * or after a call to mbedtls_psa_crypto_free() and before any - * subsequent call to psa_crypto_init(). - * - * This function is only intended for test purposes. The functionality - * it provides is also useful for system integrators, but - * system integrators should configure entropy drivers instead of - * breaking through to the Mbed TLS API. - * - * \param entropy_init Function to initialize the entropy context - * and set up the desired entropy sources. - * It is called by psa_crypto_init(). - * By default this is mbedtls_entropy_init(). - * This function cannot report failures directly. - * To indicate a failure, set the entropy context - * to a state where mbedtls_entropy_func() will - * return an error. - * \param entropy_free Function to free the entropy context - * and associated resources. - * It is called by mbedtls_psa_crypto_free(). - * By default this is mbedtls_entropy_free(). - * - * \retval PSA_SUCCESS - * Success. - * \retval PSA_ERROR_NOT_PERMITTED - * The caller does not have the permission to configure - * entropy sources. - * \retval PSA_ERROR_BAD_STATE - * The library has already been initialized. - */ -psa_status_t mbedtls_psa_crypto_configure_entropy_sources( - void (* entropy_init )( mbedtls_entropy_context *ctx ), - void (* entropy_free )( mbedtls_entropy_context *ctx ) ); - -#endif /* PSA_CRYPTO_INVASIVE_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_its.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_its.h deleted file mode 100644 index 3809787..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_its.h +++ /dev/null @@ -1,144 +0,0 @@ -/** \file psa_crypto_its.h - * \brief Interface of trusted storage that crypto is built on. - */ -/* Copyright (C) 2019, ARM Limited, 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 PSA_CRYPTO_ITS_H -#define PSA_CRYPTO_ITS_H - -#include -#include - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** \brief Flags used when creating a data entry - */ -typedef uint32_t psa_storage_create_flags_t; - -/** \brief A type for UIDs used for identifying data - */ -typedef uint64_t psa_storage_uid_t; - -#define PSA_STORAGE_FLAG_NONE 0 /**< No flags to pass */ -#define PSA_STORAGE_FLAG_WRITE_ONCE (1 << 0) /**< The data associated with the uid will not be able to be modified or deleted. Intended to be used to set bits in `psa_storage_create_flags_t`*/ - -/** - * \brief A container for metadata associated with a specific uid - */ -struct psa_storage_info_t -{ - uint32_t size; /**< The size of the data associated with a uid **/ - psa_storage_create_flags_t flags; /**< The flags set when the uid was created **/ -}; - -/** Flag indicating that \ref psa_storage_create and \ref psa_storage_set_extended are supported */ -#define PSA_STORAGE_SUPPORT_SET_EXTENDED (1 << 0) - -/** \brief PSA storage specific error codes - */ -#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) -#define PSA_ERROR_DATA_CORRUPT ((psa_status_t)-152) - -#define PSA_ITS_API_VERSION_MAJOR 1 /**< The major version number of the PSA ITS API. It will be incremented on significant updates that may include breaking changes */ -#define PSA_ITS_API_VERSION_MINOR 1 /**< The minor version number of the PSA ITS API. It will be incremented in small updates that are unlikely to include breaking changes */ - -/** - * \brief create a new or modify an existing uid/value pair - * - * \param[in] uid the identifier for the data - * \param[in] data_length The size in bytes of the data in `p_data` - * \param[in] p_data A buffer containing the data - * \param[in] create_flags The flags that the data will be stored with - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the provided `uid` value was already created with PSA_STORAGE_WRITE_ONCE_FLAG - * \retval PSA_ERROR_NOT_SUPPORTED The operation failed because one or more of the flags provided in `create_flags` is not supported or is not valid - * \retval PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because there was insufficient space on the storage medium - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_data`) - * is invalid, for example is `NULL` or references memory the caller cannot access - */ -psa_status_t psa_its_set(psa_storage_uid_t uid, - uint32_t data_length, - const void *p_data, - psa_storage_create_flags_t create_flags); - -/** - * \brief Retrieve the value associated with a provided uid - * - * \param[in] uid The uid value - * \param[in] data_offset The starting offset of the data requested - * \param[in] data_length the amount of data requested (and the minimum allocated size of the `p_data` buffer) - * \param[out] p_data The buffer where the data will be placed upon successful completion - * \param[out] p_data_length The amount of data returned in the p_data buffer - * - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided `uid` value was not found in the storage - * \retval PSA_ERROR_INVALID_SIZE The operation failed because the data associated with provided uid is larger than `data_size` - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_data`, `p_data_length`) - * is invalid. For example is `NULL` or references memory the caller cannot access. - * In addition, this can also happen if an invalid offset was provided. - */ -psa_status_t psa_its_get(psa_storage_uid_t uid, - uint32_t data_offset, - uint32_t data_length, - void *p_data, - size_t *p_data_length ); - -/** - * \brief Retrieve the metadata about the provided uid - * - * \param[in] uid The uid value - * \param[out] p_info A pointer to the `psa_storage_info_t` struct that will be populated with the metadata - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided uid value was not found in the storage - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_info`) - * is invalid, for example is `NULL` or references memory the caller cannot access - */ -psa_status_t psa_its_get_info(psa_storage_uid_t uid, - struct psa_storage_info_t *p_info); - -/** - * \brief Remove the provided key and its associated data from the storage - * - * \param[in] uid The uid value - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided key value was not found in the storage - * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the provided key value was created with PSA_STORAGE_WRITE_ONCE_FLAG - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) - */ -psa_status_t psa_its_remove(psa_storage_uid_t uid); - -#endif /* PSA_CRYPTO_ITS_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_se.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_se.c deleted file mode 100644 index b7fa0c5..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_se.c +++ /dev/null @@ -1,388 +0,0 @@ -/* - * PSA crypto support for secure element drivers - */ -/* Copyright (C) 2019, ARM Limited, 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. - * - * This file is part of Mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - -#include -#include -#include - -#include "psa/crypto_se_driver.h" - -#include "psa_crypto_se.h" - -#if defined(MBEDTLS_PSA_ITS_FILE_C) -#include "psa_crypto_its.h" -#else /* Native ITS implementation */ -#include "psa/error.h" -#include "psa/internal_trusted_storage.h" -#endif - -#include "mbedtls/platform.h" -#if !defined(MBEDTLS_PLATFORM_C) -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - - - -/****************************************************************/ -/* Driver lookup */ -/****************************************************************/ - -/* This structure is identical to psa_drv_se_context_t declared in - * `crypto_se_driver.h`, except that some parts are writable here - * (non-const, or pointer to non-const). */ -typedef struct -{ - void *persistent_data; - size_t persistent_data_size; - uintptr_t transient_data; -} psa_drv_se_internal_context_t; - -typedef struct psa_se_drv_table_entry_s -{ - psa_key_lifetime_t lifetime; - const psa_drv_se_t *methods; - union - { - psa_drv_se_internal_context_t internal; - psa_drv_se_context_t context; - }; -} psa_se_drv_table_entry_t; - -static psa_se_drv_table_entry_t driver_table[PSA_MAX_SE_DRIVERS]; - -psa_se_drv_table_entry_t *psa_get_se_driver_entry( - psa_key_lifetime_t lifetime ) -{ - size_t i; - /* In the driver table, lifetime=0 means an entry that isn't used. - * No driver has a lifetime of 0 because it's a reserved value - * (which designates volatile keys). Make sure we never return - * a driver entry for lifetime 0. */ - if( lifetime == 0 ) - return( NULL ); - for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ ) - { - if( driver_table[i].lifetime == lifetime ) - return( &driver_table[i] ); - } - return( NULL ); -} - -const psa_drv_se_t *psa_get_se_driver_methods( - const psa_se_drv_table_entry_t *driver ) -{ - return( driver->methods ); -} - -psa_drv_se_context_t *psa_get_se_driver_context( - psa_se_drv_table_entry_t *driver ) -{ - return( &driver->context ); -} - -int psa_get_se_driver( psa_key_lifetime_t lifetime, - const psa_drv_se_t **p_methods, - psa_drv_se_context_t **p_drv_context) -{ - psa_se_drv_table_entry_t *driver = psa_get_se_driver_entry( lifetime ); - if( p_methods != NULL ) - *p_methods = ( driver ? driver->methods : NULL ); - if( p_drv_context != NULL ) - *p_drv_context = ( driver ? &driver->context : NULL ); - return( driver != NULL ); -} - - - -/****************************************************************/ -/* Persistent data management */ -/****************************************************************/ - -static psa_status_t psa_get_se_driver_its_file_uid( - const psa_se_drv_table_entry_t *driver, - psa_storage_uid_t *uid ) -{ - if( driver->lifetime > PSA_MAX_SE_LIFETIME ) - return( PSA_ERROR_NOT_SUPPORTED ); - -#if SIZE_MAX > UINT32_MAX - /* ITS file sizes are limited to 32 bits. */ - if( driver->internal.persistent_data_size > UINT32_MAX ) - return( PSA_ERROR_NOT_SUPPORTED ); -#endif - - /* See the documentation of PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE. */ - *uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + driver->lifetime; - return( PSA_SUCCESS ); -} - -psa_status_t psa_load_se_persistent_data( - const psa_se_drv_table_entry_t *driver ) -{ - psa_status_t status; - psa_storage_uid_t uid; - size_t length; - - status = psa_get_se_driver_its_file_uid( driver, &uid ); - if( status != PSA_SUCCESS ) - return( status ); - - /* Read the amount of persistent data that the driver requests. - * If the data in storage is larger, it is truncated. If the data - * in storage is smaller, silently keep what is already at the end - * of the output buffer. */ - /* psa_get_se_driver_its_file_uid ensures that the size_t - * persistent_data_size is in range, but compilers don't know that, - * so cast to reassure them. */ - return( psa_its_get( uid, 0, - (uint32_t) driver->internal.persistent_data_size, - driver->internal.persistent_data, - &length ) ); -} - -psa_status_t psa_save_se_persistent_data( - const psa_se_drv_table_entry_t *driver ) -{ - psa_status_t status; - psa_storage_uid_t uid; - - status = psa_get_se_driver_its_file_uid( driver, &uid ); - if( status != PSA_SUCCESS ) - return( status ); - - /* psa_get_se_driver_its_file_uid ensures that the size_t - * persistent_data_size is in range, but compilers don't know that, - * so cast to reassure them. */ - return( psa_its_set( uid, - (uint32_t) driver->internal.persistent_data_size, - driver->internal.persistent_data, - 0 ) ); -} - -psa_status_t psa_destroy_se_persistent_data( psa_key_lifetime_t lifetime ) -{ - psa_storage_uid_t uid; - if( lifetime > PSA_MAX_SE_LIFETIME ) - return( PSA_ERROR_NOT_SUPPORTED ); - uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + lifetime; - return( psa_its_remove( uid ) ); -} - -psa_status_t psa_find_se_slot_for_key( - const psa_key_attributes_t *attributes, - psa_key_creation_method_t method, - psa_se_drv_table_entry_t *driver, - psa_key_slot_number_t *slot_number ) -{ - psa_status_t status; - - /* If the lifetime is wrong, it's a bug in the library. */ - if( driver->lifetime != psa_get_key_lifetime( attributes ) ) - return( PSA_ERROR_CORRUPTION_DETECTED ); - - /* If the driver doesn't support key creation in any way, give up now. */ - if( driver->methods->key_management == NULL ) - return( PSA_ERROR_NOT_SUPPORTED ); - - if( psa_get_key_slot_number( attributes, slot_number ) == PSA_SUCCESS ) - { - /* The application wants to use a specific slot. Allow it if - * the driver supports it. On a system with isolation, - * the crypto service must check that the application is - * permitted to request this slot. */ - psa_drv_se_validate_slot_number_t p_validate_slot_number = - driver->methods->key_management->p_validate_slot_number; - if( p_validate_slot_number == NULL ) - return( PSA_ERROR_NOT_SUPPORTED ); - status = p_validate_slot_number( &driver->context, - driver->internal.persistent_data, - attributes, method, - *slot_number ); - } - else if( method == PSA_KEY_CREATION_REGISTER ) - { - /* The application didn't specify a slot number. This doesn't - * make sense when registering a slot. */ - return( PSA_ERROR_INVALID_ARGUMENT ); - } - else - { - /* The application didn't tell us which slot to use. Let the driver - * choose. This is the normal case. */ - psa_drv_se_allocate_key_t p_allocate = - driver->methods->key_management->p_allocate; - if( p_allocate == NULL ) - return( PSA_ERROR_NOT_SUPPORTED ); - status = p_allocate( &driver->context, - driver->internal.persistent_data, - attributes, method, - slot_number ); - } - return( status ); -} - -psa_status_t psa_destroy_se_key( psa_se_drv_table_entry_t *driver, - psa_key_slot_number_t slot_number ) -{ - psa_status_t status; - psa_status_t storage_status; - /* Normally a missing method would mean that the action is not - * supported. But psa_destroy_key() is not supposed to return - * PSA_ERROR_NOT_SUPPORTED: if you can create a key, you should - * be able to destroy it. The only use case for a driver that - * does not have a way to destroy keys at all is if the keys are - * locked in a read-only state: we can use the keys but not - * destroy them. Hence, if the driver doesn't support destroying - * keys, it's really a lack of permission. */ - if( driver->methods->key_management == NULL || - driver->methods->key_management->p_destroy == NULL ) - return( PSA_ERROR_NOT_PERMITTED ); - status = driver->methods->key_management->p_destroy( - &driver->context, - driver->internal.persistent_data, - slot_number ); - storage_status = psa_save_se_persistent_data( driver ); - return( status == PSA_SUCCESS ? storage_status : status ); -} - -psa_status_t psa_init_all_se_drivers( void ) -{ - size_t i; - for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ ) - { - psa_se_drv_table_entry_t *driver = &driver_table[i]; - if( driver->lifetime == 0 ) - continue; /* skipping unused entry */ - const psa_drv_se_t *methods = psa_get_se_driver_methods( driver ); - if( methods->p_init != NULL ) - { - psa_status_t status = methods->p_init( - &driver->context, - driver->internal.persistent_data, - driver->lifetime ); - if( status != PSA_SUCCESS ) - return( status ); - status = psa_save_se_persistent_data( driver ); - if( status != PSA_SUCCESS ) - return( status ); - } - } - return( PSA_SUCCESS ); -} - - - -/****************************************************************/ -/* Driver registration */ -/****************************************************************/ - -psa_status_t psa_register_se_driver( - psa_key_lifetime_t lifetime, - const psa_drv_se_t *methods) -{ - size_t i; - psa_status_t status; - - if( methods->hal_version != PSA_DRV_SE_HAL_VERSION ) - return( PSA_ERROR_NOT_SUPPORTED ); - /* Driver table entries are 0-initialized. 0 is not a valid driver - * lifetime because it means a volatile key. */ -#if defined(static_assert) - static_assert( PSA_KEY_LIFETIME_VOLATILE == 0, - "Secure element support requires 0 to mean a volatile key" ); -#endif - if( lifetime == PSA_KEY_LIFETIME_VOLATILE || - lifetime == PSA_KEY_LIFETIME_PERSISTENT ) - { - return( PSA_ERROR_INVALID_ARGUMENT ); - } - if( lifetime > PSA_MAX_SE_LIFETIME ) - return( PSA_ERROR_NOT_SUPPORTED ); - - for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ ) - { - if( driver_table[i].lifetime == 0 ) - break; - /* Check that lifetime isn't already in use up to the first free - * entry. Since entries are created in order and never deleted, - * there can't be a used entry after the first free entry. */ - if( driver_table[i].lifetime == lifetime ) - return( PSA_ERROR_ALREADY_EXISTS ); - } - if( i == PSA_MAX_SE_DRIVERS ) - return( PSA_ERROR_INSUFFICIENT_MEMORY ); - - driver_table[i].lifetime = lifetime; - driver_table[i].methods = methods; - driver_table[i].internal.persistent_data_size = - methods->persistent_data_size; - - if( methods->persistent_data_size != 0 ) - { - driver_table[i].internal.persistent_data = - mbedtls_calloc( 1, methods->persistent_data_size ); - if( driver_table[i].internal.persistent_data == NULL ) - { - status = PSA_ERROR_INSUFFICIENT_MEMORY; - goto error; - } - /* Load the driver's persistent data. On first use, the persistent - * data does not exist in storage, and is initialized to - * all-bits-zero by the calloc call just above. */ - status = psa_load_se_persistent_data( &driver_table[i] ); - if( status != PSA_SUCCESS && status != PSA_ERROR_DOES_NOT_EXIST ) - goto error; - } - - return( PSA_SUCCESS ); - -error: - memset( &driver_table[i], 0, sizeof( driver_table[i] ) ); - return( status ); -} - -void psa_unregister_all_se_drivers( void ) -{ - size_t i; - for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ ) - { - if( driver_table[i].internal.persistent_data != NULL ) - mbedtls_free( driver_table[i].internal.persistent_data ); - } - memset( driver_table, 0, sizeof( driver_table ) ); -} - - - -/****************************************************************/ -/* The end */ -/****************************************************************/ - -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_se.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_se.h deleted file mode 100644 index 86bf7a7..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_se.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * PSA crypto support for secure element drivers - */ -/* Copyright (C) 2019, ARM Limited, 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. - * - * This file is part of Mbed TLS (https://tls.mbed.org) - */ - -#ifndef PSA_CRYPTO_SE_H -#define PSA_CRYPTO_SE_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "psa/crypto.h" -#include "psa/crypto_se_driver.h" - -/** The maximum lifetime value that this implementation supports - * for a secure element. - * - * This is not a characteristic that each PSA implementation has, but a - * limitation of the current implementation due to the constraints imposed - * by storage. See #PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE. - * - * The minimum lifetime value for a secure element is 2, like on any - * PSA implementation (0=volatile and 1=internal-storage are taken). - */ -#define PSA_MAX_SE_LIFETIME 255 - -/** The base of the range of ITS file identifiers for secure element - * driver persistent data. - * - * We use a slice of the implemenation reserved range 0xffff0000..0xffffffff, - * specifically the range 0xfffffe00..0xfffffeff. The length of this range - * drives the value of #PSA_MAX_SE_LIFETIME. - * The identifiers 0xfffffe00 and 0xfffffe01 are actually not used since - * they correspond to #PSA_KEY_LIFETIME_VOLATILE and - * #PSA_KEY_LIFETIME_PERSISTENT which don't have a driver. - */ -#define PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE ( (psa_key_id_t) 0xfffffe00 ) - -/** The maximum number of registered secure element driver lifetimes. */ -#define PSA_MAX_SE_DRIVERS 4 - -/** Unregister all secure element drivers. - * - * \warning Do not call this function while the library is in the initialized - * state. This function is only intended to be called at the end - * of mbedtls_psa_crypto_free(). - */ -void psa_unregister_all_se_drivers( void ); - -/** Initialize all secure element drivers. - * - * Called from psa_crypto_init(). - */ -psa_status_t psa_init_all_se_drivers( void ); - -/** A structure that describes a registered secure element driver. - * - * A secure element driver table entry contains a pointer to the - * driver's method table as well as the driver context structure. - */ -typedef struct psa_se_drv_table_entry_s psa_se_drv_table_entry_t; - -/** Return the secure element driver information for a lifetime value. - * - * \param lifetime The lifetime value to query. - * \param[out] p_methods On output, if there is a driver, - * \c *methods points to its method table. - * Otherwise \c *methods is \c NULL. - * \param[out] p_drv_context On output, if there is a driver, - * \c *drv_context points to its context - * structure. - * Otherwise \c *drv_context is \c NULL. - * - * \retval 1 - * \p lifetime corresponds to a registered driver. - * \retval 0 - * \p lifetime does not correspond to a registered driver. - */ -int psa_get_se_driver( psa_key_lifetime_t lifetime, - const psa_drv_se_t **p_methods, - psa_drv_se_context_t **p_drv_context); - -/** Return the secure element driver table entry for a lifetime value. - * - * \param lifetime The lifetime value to query. - * - * \return The driver table entry for \p lifetime, or - * \p NULL if \p lifetime does not correspond to a registered driver. - */ -psa_se_drv_table_entry_t *psa_get_se_driver_entry( - psa_key_lifetime_t lifetime ); - -/** Return the method table for a secure element driver. - * - * \param[in] driver The driver table entry to access, or \c NULL. - * - * \return The driver's method table. - * \c NULL if \p driver is \c NULL. - */ -const psa_drv_se_t *psa_get_se_driver_methods( - const psa_se_drv_table_entry_t *driver ); - -/** Return the context of a secure element driver. - * - * \param[in] driver The driver table entry to access, or \c NULL. - * - * \return A pointer to the driver context. - * \c NULL if \p driver is \c NULL. - */ -psa_drv_se_context_t *psa_get_se_driver_context( - psa_se_drv_table_entry_t *driver ); - -/** Find a free slot for a key that is to be created. - * - * This function calls the relevant method in the driver to find a suitable - * slot for a key with the given attributes. - * - * \param[in] attributes Metadata about the key that is about to be created. - * \param[in] driver The driver table entry to query. - * \param[out] slot_number On success, a slot number that is free in this - * secure element. - */ -psa_status_t psa_find_se_slot_for_key( - const psa_key_attributes_t *attributes, - psa_key_creation_method_t method, - psa_se_drv_table_entry_t *driver, - psa_key_slot_number_t *slot_number ); - -/** Destoy a key in a secure element. - * - * This function calls the relevant driver method to destroy a key - * and updates the driver's persistent data. - */ -psa_status_t psa_destroy_se_key( psa_se_drv_table_entry_t *driver, - psa_key_slot_number_t slot_number ); - -/** Load the persistent data of a secure element driver. - * - * \param driver The driver table entry containing the persistent - * data to load from storage. - */ -psa_status_t psa_load_se_persistent_data( - const psa_se_drv_table_entry_t *driver ); - -/** Save the persistent data of a secure element driver. - * - * \param[in] driver The driver table entry containing the persistent - * data to save to storage. - */ -psa_status_t psa_save_se_persistent_data( - const psa_se_drv_table_entry_t *driver ); - -/** Destroy the persistent data of a secure element driver. - * - * This is currently only used for testing. - * - * \param[in] lifetime The driver lifetime whose persistent data should - * be erased. - */ -psa_status_t psa_destroy_se_persistent_data( psa_key_lifetime_t lifetime ); - - -/** The storage representation of a key whose data is in a secure element. - */ -typedef struct -{ - uint8_t slot_number[sizeof( psa_key_slot_number_t )]; - uint8_t bits[sizeof( psa_key_bits_t )]; -} psa_se_key_data_storage_t; - -#endif /* PSA_CRYPTO_SE_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_service_integration.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_service_integration.h deleted file mode 100644 index 938bfe1..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_service_integration.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Copyright (C) 2019, ARM Limited, 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. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#ifndef PSA_CRYPTO_SERVICE_INTEGRATION_H -#define PSA_CRYPTO_SERVICE_INTEGRATION_H - -/* - * When MBEDTLS_PSA_CRYPTO_SPM is defined, the code is being built for SPM - * (Secure Partition Manager) integration which separates the code into two - * parts: NSPE (Non-Secure Processing Environment) and SPE (Secure Processing - * Environment). When building for the SPE, an additional header file should be - * included. - */ -#if defined(MBEDTLS_PSA_CRYPTO_SPM) -/* - * PSA_CRYPTO_SECURE means that the file which included this file is being - * compiled for SPE. The files crypto_structs.h and crypto_types.h have - * different implementations for NSPE and SPE and are compiled according to this - * flag. - */ -#define PSA_CRYPTO_SECURE 1 -#include "crypto_spe.h" -#endif // MBEDTLS_PSA_CRYPTO_SPM - -#endif // PSA_CRYPTO_SERVICE_INTEGRATION_H diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_slot_management.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_slot_management.c deleted file mode 100644 index 6cd6a11..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_slot_management.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * PSA crypto layer on top of Mbed TLS crypto - */ -/* Copyright (C) 2018, ARM Limited, 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. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_PSA_CRYPTO_C) - -#include "psa_crypto_service_integration.h" -#include "psa/crypto.h" - -#include "psa_crypto_core.h" -#include "psa_crypto_slot_management.h" -#include "psa_crypto_storage.h" -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) -#include "psa_crypto_se.h" -#endif - -#include -#include -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#define ARRAY_LENGTH( array ) ( sizeof( array ) / sizeof( *( array ) ) ) - -typedef struct -{ - psa_key_slot_t key_slots[PSA_KEY_SLOT_COUNT]; - unsigned key_slots_initialized : 1; -} psa_global_data_t; - -static psa_global_data_t global_data; - -/* Access a key slot at the given handle. The handle of a key slot is - * the index of the slot in the global slot array, plus one so that handles - * start at 1 and not 0. */ -psa_status_t psa_get_key_slot( psa_key_handle_t handle, - psa_key_slot_t **p_slot ) -{ - psa_key_slot_t *slot = NULL; - - if( ! global_data.key_slots_initialized ) - return( PSA_ERROR_BAD_STATE ); - - /* 0 is not a valid handle under any circumstance. This - * implementation provides slots number 1 to N where N is the - * number of available slots. */ - if( handle == 0 || handle > ARRAY_LENGTH( global_data.key_slots ) ) - return( PSA_ERROR_INVALID_HANDLE ); - slot = &global_data.key_slots[handle - 1]; - - /* If the slot isn't occupied, the handle is invalid. */ - if( ! psa_is_key_slot_occupied( slot ) ) - return( PSA_ERROR_INVALID_HANDLE ); - - *p_slot = slot; - return( PSA_SUCCESS ); -} - -psa_status_t psa_initialize_key_slots( void ) -{ - /* Nothing to do: program startup and psa_wipe_all_key_slots() both - * guarantee that the key slots are initialized to all-zero, which - * means that all the key slots are in a valid, empty state. */ - global_data.key_slots_initialized = 1; - return( PSA_SUCCESS ); -} - -void psa_wipe_all_key_slots( void ) -{ - psa_key_handle_t key; - for( key = 1; key <= PSA_KEY_SLOT_COUNT; key++ ) - { - psa_key_slot_t *slot = &global_data.key_slots[key - 1]; - (void) psa_wipe_key_slot( slot ); - } - global_data.key_slots_initialized = 0; -} - -psa_status_t psa_get_empty_key_slot( psa_key_handle_t *handle, - psa_key_slot_t **p_slot ) -{ - if( ! global_data.key_slots_initialized ) - return( PSA_ERROR_BAD_STATE ); - - for( *handle = PSA_KEY_SLOT_COUNT; *handle != 0; --( *handle ) ) - { - *p_slot = &global_data.key_slots[*handle - 1]; - if( ! psa_is_key_slot_occupied( *p_slot ) ) - return( PSA_SUCCESS ); - } - *p_slot = NULL; - return( PSA_ERROR_INSUFFICIENT_MEMORY ); -} - -#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) -static psa_status_t psa_load_persistent_key_into_slot( psa_key_slot_t *slot ) -{ - psa_status_t status = PSA_SUCCESS; - uint8_t *key_data = NULL; - size_t key_data_length = 0; - - status = psa_load_persistent_key( &slot->attr, - &key_data, &key_data_length ); - if( status != PSA_SUCCESS ) - goto exit; - -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - if( psa_key_lifetime_is_external( slot->attr.lifetime ) ) - { - psa_se_key_data_storage_t *data; - if( key_data_length != sizeof( *data ) ) - { - status = PSA_ERROR_STORAGE_FAILURE; - goto exit; - } - data = (psa_se_key_data_storage_t *) key_data; - memcpy( &slot->data.se.slot_number, &data->slot_number, - sizeof( slot->data.se.slot_number ) ); - memcpy( &slot->attr.bits, &data->bits, - sizeof( slot->attr.bits ) ); - } - else -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - { - status = psa_import_key_into_slot( slot, key_data, key_data_length ); - } - -exit: - psa_free_persistent_key_data( key_data, key_data_length ); - return( status ); -} - -/** Check whether a key identifier is acceptable. - * - * For backward compatibility, key identifiers that were valid in a - * past released version must remain valid, unless a migration path - * is provided. - * - * \param file_id The key identifier to check. - * \param vendor_ok Nonzero to allow key ids in the vendor range. - * 0 to allow only key ids in the application range. - * - * \return 1 if \p file_id is acceptable, otherwise 0. - */ -static int psa_is_key_id_valid( psa_key_file_id_t file_id, - int vendor_ok ) -{ - psa_app_key_id_t key_id = PSA_KEY_FILE_GET_KEY_ID( file_id ); - if( PSA_KEY_ID_USER_MIN <= key_id && key_id <= PSA_KEY_ID_USER_MAX ) - return( 1 ); - else if( vendor_ok && - PSA_KEY_ID_VENDOR_MIN <= key_id && - key_id <= PSA_KEY_ID_VENDOR_MAX ) - return( 1 ); - else - return( 0 ); -} -#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ - -psa_status_t psa_validate_persistent_key_parameters( - psa_key_lifetime_t lifetime, - psa_key_file_id_t id, - psa_se_drv_table_entry_t **p_drv, - int creating ) -{ - if( p_drv != NULL ) - *p_drv = NULL; -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - if( psa_key_lifetime_is_external( lifetime ) ) - { - *p_drv = psa_get_se_driver_entry( lifetime ); - if( *p_drv == NULL ) - return( PSA_ERROR_INVALID_ARGUMENT ); - } - else -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - if( lifetime != PSA_KEY_LIFETIME_PERSISTENT ) - return( PSA_ERROR_INVALID_ARGUMENT ); - -#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) - if( ! psa_is_key_id_valid( id, ! creating ) ) - return( PSA_ERROR_INVALID_ARGUMENT ); - return( PSA_SUCCESS ); - -#else /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ - (void) id; - (void) creating; - return( PSA_ERROR_NOT_SUPPORTED ); -#endif /* !MBEDTLS_PSA_CRYPTO_STORAGE_C */ -} - -psa_status_t psa_open_key( psa_key_file_id_t id, psa_key_handle_t *handle ) -{ -#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) - psa_status_t status; - psa_key_slot_t *slot; - - *handle = 0; - - status = psa_validate_persistent_key_parameters( - PSA_KEY_LIFETIME_PERSISTENT, id, NULL, 0 ); - if( status != PSA_SUCCESS ) - return( status ); - - status = psa_get_empty_key_slot( handle, &slot ); - if( status != PSA_SUCCESS ) - return( status ); - - slot->attr.lifetime = PSA_KEY_LIFETIME_PERSISTENT; - slot->attr.id = id; - - status = psa_load_persistent_key_into_slot( slot ); - if( status != PSA_SUCCESS ) - { - psa_wipe_key_slot( slot ); - *handle = 0; - } - return( status ); - -#else /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ - (void) id; - *handle = 0; - return( PSA_ERROR_NOT_SUPPORTED ); -#endif /* !defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ -} - -psa_status_t psa_close_key( psa_key_handle_t handle ) -{ - psa_status_t status; - psa_key_slot_t *slot; - - if( handle == 0 ) - return( PSA_SUCCESS ); - - status = psa_get_key_slot( handle, &slot ); - if( status != PSA_SUCCESS ) - return( status ); - - return( psa_wipe_key_slot( slot ) ); -} - -void mbedtls_psa_get_stats( mbedtls_psa_stats_t *stats ) -{ - psa_key_handle_t key; - memset( stats, 0, sizeof( *stats ) ); - for( key = 1; key <= PSA_KEY_SLOT_COUNT; key++ ) - { - const psa_key_slot_t *slot = &global_data.key_slots[key - 1]; - if( ! psa_is_key_slot_occupied( slot ) ) - { - ++stats->empty_slots; - continue; - } - if( slot->attr.lifetime == PSA_KEY_LIFETIME_VOLATILE ) - ++stats->volatile_slots; - else if( slot->attr.lifetime == PSA_KEY_LIFETIME_PERSISTENT ) - { - psa_app_key_id_t id = PSA_KEY_FILE_GET_KEY_ID(slot->attr.id); - ++stats->persistent_slots; - if( id > stats->max_open_internal_key_id ) - stats->max_open_internal_key_id = id; - } - else - { - psa_app_key_id_t id = PSA_KEY_FILE_GET_KEY_ID(slot->attr.id); - ++stats->external_slots; - if( id > stats->max_open_external_key_id ) - stats->max_open_external_key_id = id; - } - } -} - -#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_slot_management.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_slot_management.h deleted file mode 100644 index 472253d..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_slot_management.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * PSA crypto layer on top of Mbed TLS crypto - */ -/* Copyright (C) 2018, ARM Limited, 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. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#ifndef PSA_CRYPTO_SLOT_MANAGEMENT_H -#define PSA_CRYPTO_SLOT_MANAGEMENT_H - -#include "psa/crypto.h" -#include "psa_crypto_se.h" - -/* Number of key slots (plus one because 0 is not used). - * The value is a compile-time constant for now, for simplicity. */ -#define PSA_KEY_SLOT_COUNT 32 - -/** Access a key slot at the given handle. - * - * \param handle Key handle to query. - * \param[out] p_slot On success, `*p_slot` contains a pointer to the - * key slot in memory designated by \p handle. - * - * \retval PSA_SUCCESS - * Success: \p handle is a handle to `*p_slot`. Note that `*p_slot` - * may be empty or occupied. - * \retval PSA_ERROR_INVALID_HANDLE - * \p handle is out of range or is not in use. - * \retval PSA_ERROR_BAD_STATE - * The library has not been initialized. - */ -psa_status_t psa_get_key_slot( psa_key_handle_t handle, - psa_key_slot_t **p_slot ); - -/** Initialize the key slot structures. - * - * \retval PSA_SUCCESS - * Currently this function always succeeds. - */ -psa_status_t psa_initialize_key_slots( void ); - -/** Delete all data from key slots in memory. - * - * This does not affect persistent storage. */ -void psa_wipe_all_key_slots( void ); - -/** Find a free key slot. - * - * This function returns a key slot that is available for use and is in its - * ground state (all-bits-zero). - * - * \param[out] handle On success, a slot number that can be used as a - * handle to the slot. - * \param[out] p_slot On success, a pointer to the slot. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_BAD_STATE - */ -psa_status_t psa_get_empty_key_slot( psa_key_handle_t *handle, - psa_key_slot_t **p_slot ); - -/** Test whether a lifetime designates a key in an external cryptoprocessor. - * - * \param lifetime The lifetime to test. - * - * \retval 1 - * The lifetime designates an external key. There should be a - * registered driver for this lifetime, otherwise the key cannot - * be created or manipulated. - * \retval 0 - * The lifetime designates a key that is volatile or in internal - * storage. - */ -static inline int psa_key_lifetime_is_external( psa_key_lifetime_t lifetime ) -{ - return( lifetime != PSA_KEY_LIFETIME_VOLATILE && - lifetime != PSA_KEY_LIFETIME_PERSISTENT ); -} - -/** Test whether the given parameters are acceptable for a persistent key. - * - * This function does not access the storage in any way. It only tests - * whether the parameters are meaningful and permitted by general policy. - * It does not test whether the a file by the given id exists or could be - * created. - * - * If the key is in external storage, this function returns the corresponding - * driver. - * - * \param lifetime The lifetime to test. - * \param id The key id to test. - * \param[out] p_drv On output, if \p lifetime designates a key - * in an external processor, \c *p_drv is a pointer - * to the driver table entry fot this lifetime. - * If \p lifetime designates a transparent key, - * \c *p_drv is \c NULL. - * \param creating 0 if attempting to open an existing key. - * Nonzero if attempting to create a key. - * - * \retval PSA_SUCCESS - * The given parameters are valid. - * \retval PSA_ERROR_INVALID_ARGUMENT - * \p lifetime is volatile or is invalid. - * \retval PSA_ERROR_INVALID_ARGUMENT - * \p id is invalid. - */ -psa_status_t psa_validate_persistent_key_parameters( - psa_key_lifetime_t lifetime, - psa_key_file_id_t id, - psa_se_drv_table_entry_t **p_drv, - int creating ); - - -#endif /* PSA_CRYPTO_SLOT_MANAGEMENT_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_storage.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_storage.c deleted file mode 100644 index fa1214c..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_storage.c +++ /dev/null @@ -1,504 +0,0 @@ -/* - * PSA persistent key storage - */ -/* Copyright (C) 2018, ARM Limited, 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. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if defined(MBEDTLS_CONFIG_FILE) -#include MBEDTLS_CONFIG_FILE -#else -#include "mbedtls/config.h" -#endif - -#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) - -#include -#include - -#include "psa_crypto_service_integration.h" -#include "psa/crypto.h" -#include "psa_crypto_storage.h" -#include "mbedtls/platform_util.h" - -#if defined(MBEDTLS_PSA_ITS_FILE_C) -#include "psa_crypto_its.h" -#else /* Native ITS implementation */ -#include "psa/error.h" -#include "psa/internal_trusted_storage.h" -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - - - -/****************************************************************/ -/* Key storage */ -/****************************************************************/ - -/* Determine a file name (ITS file identifier) for the given key file - * identifier. The file name must be distinct from any file that is used - * for a purpose other than storing a key. Currently, the only such file - * is the random seed file whose name is PSA_CRYPTO_ITS_RANDOM_SEED_UID - * and whose value is 0xFFFFFF52. */ -static psa_storage_uid_t psa_its_identifier_of_slot( psa_key_file_id_t file_id ) -{ -#if defined(MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER) && \ - defined(PSA_CRYPTO_SECURE) - /* Encode the owner in the upper 32 bits. This means that if - * owner values are nonzero (as they are on a PSA platform), - * no key file will ever have a value less than 0x100000000, so - * the whole range 0..0xffffffff is available for non-key files. */ - uint32_t unsigned_owner = (uint32_t) file_id.owner; - return( (uint64_t) unsigned_owner << 32 | file_id.key_id ); -#else - /* Use the key id directly as a file name. - * psa_is_key_file_id_valid() in psa_crypto_slot_management.c - * is responsible for ensuring that key identifiers do not have a - * value that is reserved for non-key files. */ - return( file_id ); -#endif -} - -/** - * \brief Load persistent data for the given key slot number. - * - * This function reads data from a storage backend and returns the data in a - * buffer. - * - * \param key Persistent identifier of the key to be loaded. This - * should be an occupied storage location. - * \param[out] data Buffer where the data is to be written. - * \param data_size Size of the \c data buffer in bytes. - * - * \retval PSA_SUCCESS - * \retval PSA_ERROR_STORAGE_FAILURE - * \retval PSA_ERROR_DOES_NOT_EXIST - */ -static psa_status_t psa_crypto_storage_load( const psa_key_file_id_t key, - uint8_t *data, - size_t data_size ) -{ - psa_status_t status; - psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key ); - struct psa_storage_info_t data_identifier_info; - size_t data_length = 0; - - status = psa_its_get_info( data_identifier, &data_identifier_info ); - if( status != PSA_SUCCESS ) - return( status ); - - status = psa_its_get( data_identifier, 0, (uint32_t) data_size, data, &data_length ); - if( data_size != data_length ) - return( PSA_ERROR_STORAGE_FAILURE ); - - return( status ); -} - -int psa_is_key_present_in_storage( const psa_key_file_id_t key ) -{ - psa_status_t ret; - psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key ); - struct psa_storage_info_t data_identifier_info; - - ret = psa_its_get_info( data_identifier, &data_identifier_info ); - - if( ret == PSA_ERROR_DOES_NOT_EXIST ) - return( 0 ); - return( 1 ); -} - -/** - * \brief Store persistent data for the given key slot number. - * - * This function stores the given data buffer to a persistent storage. - * - * \param key Persistent identifier of the key to be stored. This - * should be an unoccupied storage location. - * \param[in] data Buffer containing the data to be stored. - * \param data_length The number of bytes - * that make up the data. - * - * \retval PSA_SUCCESS - * \retval PSA_ERROR_INSUFFICIENT_STORAGE - * \retval PSA_ERROR_STORAGE_FAILURE - * \retval PSA_ERROR_ALREADY_EXISTS - */ -static psa_status_t psa_crypto_storage_store( const psa_key_file_id_t key, - const uint8_t *data, - size_t data_length ) -{ - psa_status_t status; - psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key ); - struct psa_storage_info_t data_identifier_info; - - if( psa_is_key_present_in_storage( key ) == 1 ) - return( PSA_ERROR_ALREADY_EXISTS ); - - status = psa_its_set( data_identifier, (uint32_t) data_length, data, 0 ); - if( status != PSA_SUCCESS ) - { - return( PSA_ERROR_STORAGE_FAILURE ); - } - - status = psa_its_get_info( data_identifier, &data_identifier_info ); - if( status != PSA_SUCCESS ) - { - goto exit; - } - - if( data_identifier_info.size != data_length ) - { - status = PSA_ERROR_STORAGE_FAILURE; - goto exit; - } - -exit: - if( status != PSA_SUCCESS ) - psa_its_remove( data_identifier ); - return( status ); -} - -psa_status_t psa_destroy_persistent_key( const psa_key_file_id_t key ) -{ - psa_status_t ret; - psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key ); - struct psa_storage_info_t data_identifier_info; - - ret = psa_its_get_info( data_identifier, &data_identifier_info ); - if( ret == PSA_ERROR_DOES_NOT_EXIST ) - return( PSA_SUCCESS ); - - if( psa_its_remove( data_identifier ) != PSA_SUCCESS ) - return( PSA_ERROR_STORAGE_FAILURE ); - - ret = psa_its_get_info( data_identifier, &data_identifier_info ); - if( ret != PSA_ERROR_DOES_NOT_EXIST ) - return( PSA_ERROR_STORAGE_FAILURE ); - - return( PSA_SUCCESS ); -} - -/** - * \brief Get data length for given key slot number. - * - * \param key Persistent identifier whose stored data length - * is to be obtained. - * \param[out] data_length The number of bytes that make up the data. - * - * \retval PSA_SUCCESS - * \retval PSA_ERROR_STORAGE_FAILURE - */ -static psa_status_t psa_crypto_storage_get_data_length( - const psa_key_file_id_t key, - size_t *data_length ) -{ - psa_status_t status; - psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key ); - struct psa_storage_info_t data_identifier_info; - - status = psa_its_get_info( data_identifier, &data_identifier_info ); - if( status != PSA_SUCCESS ) - return( status ); - - *data_length = (size_t) data_identifier_info.size; - - return( PSA_SUCCESS ); -} - -/* - * 32-bit integer manipulation macros (little endian) - */ -#ifndef GET_UINT32_LE -#define GET_UINT32_LE( n, b, i ) \ -{ \ - (n) = ( (uint32_t) (b)[(i) ] ) \ - | ( (uint32_t) (b)[(i) + 1] << 8 ) \ - | ( (uint32_t) (b)[(i) + 2] << 16 ) \ - | ( (uint32_t) (b)[(i) + 3] << 24 ); \ -} -#endif - -#ifndef PUT_UINT32_LE -#define PUT_UINT32_LE( n, b, i ) \ -{ \ - (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ - (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ - (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ - (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ -} -#endif - -/** - * Persistent key storage magic header. - */ -#define PSA_KEY_STORAGE_MAGIC_HEADER "PSA\0KEY" -#define PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH ( sizeof( PSA_KEY_STORAGE_MAGIC_HEADER ) ) - -typedef struct { - uint8_t magic[PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH]; - uint8_t version[4]; - uint8_t lifetime[sizeof( psa_key_lifetime_t )]; - uint8_t type[4]; /* Size=4 for a 2-byte type to keep the structure more - * regular and aligned and to make potential future - * extensibility easier. */ - uint8_t policy[sizeof( psa_key_policy_t )]; - uint8_t data_len[4]; - uint8_t key_data[]; -} psa_persistent_key_storage_format; - -void psa_format_key_data_for_storage( const uint8_t *data, - const size_t data_length, - const psa_core_key_attributes_t *attr, - uint8_t *storage_data ) -{ - psa_persistent_key_storage_format *storage_format = - (psa_persistent_key_storage_format *) storage_data; - - memcpy( storage_format->magic, PSA_KEY_STORAGE_MAGIC_HEADER, PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH ); - PUT_UINT32_LE( 0, storage_format->version, 0 ); - PUT_UINT32_LE( attr->lifetime, storage_format->lifetime, 0 ); - PUT_UINT32_LE( (uint32_t) attr->type, storage_format->type, 0 ); - PUT_UINT32_LE( attr->policy.usage, storage_format->policy, 0 ); - PUT_UINT32_LE( attr->policy.alg, storage_format->policy, sizeof( uint32_t ) ); - PUT_UINT32_LE( attr->policy.alg2, storage_format->policy, 2 * sizeof( uint32_t ) ); - PUT_UINT32_LE( data_length, storage_format->data_len, 0 ); - memcpy( storage_format->key_data, data, data_length ); -} - -static psa_status_t check_magic_header( const uint8_t *data ) -{ - if( memcmp( data, PSA_KEY_STORAGE_MAGIC_HEADER, - PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH ) != 0 ) - return( PSA_ERROR_STORAGE_FAILURE ); - return( PSA_SUCCESS ); -} - -psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data, - size_t storage_data_length, - uint8_t **key_data, - size_t *key_data_length, - psa_core_key_attributes_t *attr ) -{ - psa_status_t status; - const psa_persistent_key_storage_format *storage_format = - (const psa_persistent_key_storage_format *)storage_data; - uint32_t version; - uint32_t type; - - if( storage_data_length < sizeof(*storage_format) ) - return( PSA_ERROR_STORAGE_FAILURE ); - - status = check_magic_header( storage_data ); - if( status != PSA_SUCCESS ) - return( status ); - - GET_UINT32_LE( version, storage_format->version, 0 ); - if( version != 0 ) - return( PSA_ERROR_STORAGE_FAILURE ); - - GET_UINT32_LE( *key_data_length, storage_format->data_len, 0 ); - if( *key_data_length > ( storage_data_length - sizeof(*storage_format) ) || - *key_data_length > PSA_CRYPTO_MAX_STORAGE_SIZE ) - return( PSA_ERROR_STORAGE_FAILURE ); - - if( *key_data_length == 0 ) - { - *key_data = NULL; - } - else - { - *key_data = mbedtls_calloc( 1, *key_data_length ); - if( *key_data == NULL ) - return( PSA_ERROR_INSUFFICIENT_MEMORY ); - memcpy( *key_data, storage_format->key_data, *key_data_length ); - } - - GET_UINT32_LE( attr->lifetime, storage_format->lifetime, 0 ); - GET_UINT32_LE( type, storage_format->type, 0 ); - if( type <= (psa_key_type_t) -1 ) - attr->type = (psa_key_type_t) type; - else - return( PSA_ERROR_STORAGE_FAILURE ); - GET_UINT32_LE( attr->policy.usage, storage_format->policy, 0 ); - GET_UINT32_LE( attr->policy.alg, storage_format->policy, sizeof( uint32_t ) ); - GET_UINT32_LE( attr->policy.alg2, storage_format->policy, 2 * sizeof( uint32_t ) ); - - return( PSA_SUCCESS ); -} - -psa_status_t psa_save_persistent_key( const psa_core_key_attributes_t *attr, - const uint8_t *data, - const size_t data_length ) -{ - size_t storage_data_length; - uint8_t *storage_data; - psa_status_t status; - - if( data_length > PSA_CRYPTO_MAX_STORAGE_SIZE ) - return PSA_ERROR_INSUFFICIENT_STORAGE; - storage_data_length = data_length + sizeof( psa_persistent_key_storage_format ); - - storage_data = mbedtls_calloc( 1, storage_data_length ); - if( storage_data == NULL ) - return( PSA_ERROR_INSUFFICIENT_MEMORY ); - - psa_format_key_data_for_storage( data, data_length, attr, storage_data ); - - status = psa_crypto_storage_store( attr->id, - storage_data, storage_data_length ); - - mbedtls_free( storage_data ); - - return( status ); -} - -void psa_free_persistent_key_data( uint8_t *key_data, size_t key_data_length ) -{ - if( key_data != NULL ) - { - mbedtls_platform_zeroize( key_data, key_data_length ); - } - mbedtls_free( key_data ); -} - -psa_status_t psa_load_persistent_key( psa_core_key_attributes_t *attr, - uint8_t **data, - size_t *data_length ) -{ - psa_status_t status = PSA_SUCCESS; - uint8_t *loaded_data; - size_t storage_data_length = 0; - psa_key_id_t key = attr->id; - - status = psa_crypto_storage_get_data_length( key, &storage_data_length ); - if( status != PSA_SUCCESS ) - return( status ); - - loaded_data = mbedtls_calloc( 1, storage_data_length ); - - if( loaded_data == NULL ) - return( PSA_ERROR_INSUFFICIENT_MEMORY ); - - status = psa_crypto_storage_load( key, loaded_data, storage_data_length ); - if( status != PSA_SUCCESS ) - goto exit; - - status = psa_parse_key_data_from_storage( loaded_data, storage_data_length, - data, data_length, attr ); - -exit: - mbedtls_free( loaded_data ); - return( status ); -} - - - -/****************************************************************/ -/* Transactions */ -/****************************************************************/ - -#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) - -psa_crypto_transaction_t psa_crypto_transaction; - -psa_status_t psa_crypto_save_transaction( void ) -{ - struct psa_storage_info_t p_info; - psa_status_t status; - status = psa_its_get_info( PSA_CRYPTO_ITS_TRANSACTION_UID, &p_info ); - if( status == PSA_SUCCESS ) - { - /* This shouldn't happen: we're trying to start a transaction while - * there is still a transaction that hasn't been replayed. */ - return( PSA_ERROR_CORRUPTION_DETECTED ); - } - else if( status != PSA_ERROR_DOES_NOT_EXIST ) - return( status ); - return( psa_its_set( PSA_CRYPTO_ITS_TRANSACTION_UID, - sizeof( psa_crypto_transaction ), - &psa_crypto_transaction, - 0 ) ); -} - -psa_status_t psa_crypto_load_transaction( void ) -{ - psa_status_t status; - size_t length; - status = psa_its_get( PSA_CRYPTO_ITS_TRANSACTION_UID, 0, - sizeof( psa_crypto_transaction ), - &psa_crypto_transaction, &length ); - if( status != PSA_SUCCESS ) - return( status ); - if( length != sizeof( psa_crypto_transaction ) ) - return( PSA_ERROR_STORAGE_FAILURE ); - return( PSA_SUCCESS ); -} - -psa_status_t psa_crypto_stop_transaction( void ) -{ - psa_status_t status = psa_its_remove( PSA_CRYPTO_ITS_TRANSACTION_UID ); - /* Whether or not updating the storage succeeded, the transaction is - * finished now. It's too late to go back, so zero out the in-memory - * data. */ - memset( &psa_crypto_transaction, 0, sizeof( psa_crypto_transaction ) ); - return( status ); -} - -#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */ - - - -/****************************************************************/ -/* Random generator state */ -/****************************************************************/ - -#if defined(MBEDTLS_PSA_INJECT_ENTROPY) -psa_status_t mbedtls_psa_storage_inject_entropy( const unsigned char *seed, - size_t seed_size ) -{ - psa_status_t status; - struct psa_storage_info_t p_info; - - status = psa_its_get_info( PSA_CRYPTO_ITS_RANDOM_SEED_UID, &p_info ); - - if( PSA_ERROR_DOES_NOT_EXIST == status ) /* No seed exists */ - { - status = psa_its_set( PSA_CRYPTO_ITS_RANDOM_SEED_UID, seed_size, seed, 0 ); - } - else if( PSA_SUCCESS == status ) - { - /* You should not be here. Seed needs to be injected only once */ - status = PSA_ERROR_NOT_PERMITTED; - } - return( status ); -} -#endif /* MBEDTLS_PSA_INJECT_ENTROPY */ - - - -/****************************************************************/ -/* The end */ -/****************************************************************/ - -#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_storage.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_storage.h deleted file mode 100644 index 1b7dbd6..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_storage.h +++ /dev/null @@ -1,390 +0,0 @@ -/** - * \file psa_crypto_storage.h - * - * \brief PSA cryptography module: Mbed TLS key storage - */ -/* - * Copyright (C) 2018, ARM Limited, 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. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#ifndef PSA_CRYPTO_STORAGE_H -#define PSA_CRYPTO_STORAGE_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "psa/crypto.h" -#include "psa/crypto_se_driver.h" - -#include -#include - -/* Limit the maximum key size in storage. This should have no effect - * since the key size is limited in memory. */ -#define PSA_CRYPTO_MAX_STORAGE_SIZE ( PSA_BITS_TO_BYTES( PSA_MAX_KEY_BITS ) ) -/* Sanity check: a file size must fit in 32 bits. Allow a generous - * 64kB of metadata. */ -#if PSA_CRYPTO_MAX_STORAGE_SIZE > 0xffff0000 -#error PSA_CRYPTO_MAX_STORAGE_SIZE > 0xffff0000 -#endif - -/** The maximum permitted persistent slot number. - * - * In Mbed Crypto 0.1.0b: - * - Using the file backend, all key ids are ok except 0. - * - Using the ITS backend, all key ids are ok except 0xFFFFFF52 - * (#PSA_CRYPTO_ITS_RANDOM_SEED_UID) for which the file contains the - * device's random seed (if this feature is enabled). - * - Only key ids from 1 to #PSA_KEY_SLOT_COUNT are actually used. - * - * Since we need to preserve the random seed, avoid using that key slot. - * Reserve a whole range of key slots just in case something else comes up. - * - * This limitation will probably become moot when we implement client - * separation for key storage. - */ -#define PSA_MAX_PERSISTENT_KEY_IDENTIFIER PSA_KEY_ID_VENDOR_MAX - -/** - * \brief Checks if persistent data is stored for the given key slot number - * - * This function checks if any key data or metadata exists for the key slot in - * the persistent storage. - * - * \param key Persistent identifier to check. - * - * \retval 0 - * No persistent data present for slot number - * \retval 1 - * Persistent data present for slot number - */ -int psa_is_key_present_in_storage( const psa_key_file_id_t key ); - -/** - * \brief Format key data and metadata and save to a location for given key - * slot. - * - * This function formats the key data and metadata and saves it to a - * persistent storage backend. The storage location corresponding to the - * key slot must be empty, otherwise this function will fail. This function - * should be called after psa_import_key_into_slot() to ensure the - * persistent key is not saved into a storage location corresponding to an - * already occupied non-persistent key, as well as validating the key data. - * - * - * \param[in] attr The attributes of the key to save. - * The key identifier field in the attributes - * determines the key's location. - * \param[in] data Buffer containing the key data. - * \param data_length The number of bytes that make up the key data. - * - * \retval PSA_SUCCESS - * \retval PSA_ERROR_INSUFFICIENT_MEMORY - * \retval PSA_ERROR_INSUFFICIENT_STORAGE - * \retval PSA_ERROR_STORAGE_FAILURE - * \retval PSA_ERROR_ALREADY_EXISTS - */ -psa_status_t psa_save_persistent_key( const psa_core_key_attributes_t *attr, - const uint8_t *data, - const size_t data_length ); - -/** - * \brief Parses key data and metadata and load persistent key for given - * key slot number. - * - * This function reads from a storage backend, parses the key data and - * metadata and writes them to the appropriate output parameters. - * - * Note: This function allocates a buffer and returns a pointer to it through - * the data parameter. psa_free_persistent_key_data() must be called after - * this function to zeroize and free this buffer, regardless of whether this - * function succeeds or fails. - * - * \param[in,out] attr On input, the key identifier field identifies - * the key to load. Other fields are ignored. - * On success, the attribute structure contains - * the key metadata that was loaded from storage. - * \param[out] data Pointer to an allocated key data buffer on return. - * \param[out] data_length The number of bytes that make up the key data. - * - * \retval PSA_SUCCESS - * \retval PSA_ERROR_INSUFFICIENT_MEMORY - * \retval PSA_ERROR_STORAGE_FAILURE - * \retval PSA_ERROR_DOES_NOT_EXIST - */ -psa_status_t psa_load_persistent_key( psa_core_key_attributes_t *attr, - uint8_t **data, - size_t *data_length ); - -/** - * \brief Remove persistent data for the given key slot number. - * - * \param key Persistent identifier of the key to remove - * from persistent storage. - * - * \retval PSA_SUCCESS - * The key was successfully removed, - * or the key did not exist. - * \retval PSA_ERROR_STORAGE_FAILURE - */ -psa_status_t psa_destroy_persistent_key( const psa_key_file_id_t key ); - -/** - * \brief Free the temporary buffer allocated by psa_load_persistent_key(). - * - * This function must be called at some point after psa_load_persistent_key() - * to zeroize and free the memory allocated to the buffer in that function. - * - * \param key_data Buffer for the key data. - * \param key_data_length Size of the key data buffer. - * - */ -void psa_free_persistent_key_data( uint8_t *key_data, size_t key_data_length ); - -/** - * \brief Formats key data and metadata for persistent storage - * - * \param[in] data Buffer containing the key data. - * \param data_length Length of the key data buffer. - * \param[in] attr The core attributes of the key. - * \param[out] storage_data Output buffer for the formatted data. - * - */ -void psa_format_key_data_for_storage( const uint8_t *data, - const size_t data_length, - const psa_core_key_attributes_t *attr, - uint8_t *storage_data ); - -/** - * \brief Parses persistent storage data into key data and metadata - * - * \param[in] storage_data Buffer for the storage data. - * \param storage_data_length Length of the storage data buffer - * \param[out] key_data On output, pointer to a newly allocated buffer - * containing the key data. This must be freed - * using psa_free_persistent_key_data() - * \param[out] key_data_length Length of the key data buffer - * \param[out] attr On success, the attribute structure is filled - * with the loaded key metadata. - * - * \retval PSA_SUCCESS - * \retval PSA_ERROR_INSUFFICIENT_STORAGE - * \retval PSA_ERROR_INSUFFICIENT_MEMORY - * \retval PSA_ERROR_STORAGE_FAILURE - */ -psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data, - size_t storage_data_length, - uint8_t **key_data, - size_t *key_data_length, - psa_core_key_attributes_t *attr ); - -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) -/** This symbol is defined if transaction support is required. */ -#define PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS -#endif - -#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) - -/** The type of transaction that is in progress. - */ -/* This is an integer type rather than an enum for two reasons: to support - * unknown values when loading a transaction file, and to ensure that the - * type has a known size. - */ -typedef uint16_t psa_crypto_transaction_type_t; - -/** No transaction is in progress. - * - * This has the value 0, so zero-initialization sets a transaction's type to - * this value. - */ -#define PSA_CRYPTO_TRANSACTION_NONE ( (psa_crypto_transaction_type_t) 0x0000 ) - -/** A key creation transaction. - * - * This is only used for keys in an external cryptoprocessor (secure element). - * Keys in RAM or in internal storage are created atomically in storage - * (simple file creation), so they do not need a transaction mechanism. - */ -#define PSA_CRYPTO_TRANSACTION_CREATE_KEY ( (psa_crypto_transaction_type_t) 0x0001 ) - -/** A key destruction transaction. - * - * This is only used for keys in an external cryptoprocessor (secure element). - * Keys in RAM or in internal storage are destroyed atomically in storage - * (simple file deletion), so they do not need a transaction mechanism. - */ -#define PSA_CRYPTO_TRANSACTION_DESTROY_KEY ( (psa_crypto_transaction_type_t) 0x0002 ) - -/** Transaction data. - * - * This type is designed to be serialized by writing the memory representation - * and reading it back on the same device. - * - * \note The transaction mechanism is designed for a single active transaction - * at a time. The transaction object is #psa_crypto_transaction. - * - * \note If an API call starts a transaction, it must complete this transaction - * before returning to the application. - * - * The lifetime of a transaction is the following (note that only one - * transaction may be active at a time): - * - * -# Call psa_crypto_prepare_transaction() to initialize the transaction - * object in memory and declare the type of transaction that is starting. - * -# Fill in the type-specific fields of #psa_crypto_transaction. - * -# Call psa_crypto_save_transaction() to start the transaction. This - * saves the transaction data to internal storage. - * -# Perform the work of the transaction by modifying files, contacting - * external entities, or whatever needs doing. Note that the transaction - * may be interrupted by a power failure, so you need to have a way - * recover from interruptions either by undoing what has been done - * so far or by resuming where you left off. - * -# If there are intermediate stages in the transaction, update - * the fields of #psa_crypto_transaction and call - * psa_crypto_save_transaction() again when each stage is reached. - * -# When the transaction is over, call psa_crypto_stop_transaction() to - * remove the transaction data in storage and in memory. - * - * If the system crashes while a transaction is in progress, psa_crypto_init() - * calls psa_crypto_load_transaction() and takes care of completing or - * rewinding the transaction. This is done in psa_crypto_recover_transaction() - * in psa_crypto.c. If you add a new type of transaction, be - * sure to add code for it in psa_crypto_recover_transaction(). - */ -typedef union -{ - /* Each element of this union must have the following properties - * to facilitate serialization and deserialization: - * - * - The element is a struct. - * - The first field of the struct is `psa_crypto_transaction_type_t type`. - * - Elements of the struct are arranged such a way that there is - * no padding. - */ - struct psa_crypto_transaction_unknown_s - { - psa_crypto_transaction_type_t type; - uint16_t unused1; - uint32_t unused2; - uint64_t unused3; - uint64_t unused4; - } unknown; - /* ::type is #PSA_CRYPTO_TRANSACTION_CREATE_KEY or - * #PSA_CRYPTO_TRANSACTION_DESTROY_KEY. */ - struct psa_crypto_transaction_key_s - { - psa_crypto_transaction_type_t type; - uint16_t unused1; - psa_key_lifetime_t lifetime; - psa_key_slot_number_t slot; - psa_key_id_t id; - } key; -} psa_crypto_transaction_t; - -/** The single active transaction. - */ -extern psa_crypto_transaction_t psa_crypto_transaction; - -/** Prepare for a transaction. - * - * There must not be an ongoing transaction. - * - * \param type The type of transaction to start. - */ -static inline void psa_crypto_prepare_transaction( - psa_crypto_transaction_type_t type ) -{ - psa_crypto_transaction.unknown.type = type; -} - -/** Save the transaction data to storage. - * - * You may call this function multiple times during a transaction to - * atomically update the transaction state. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INSUFFICIENT_STORAGE - * \retval #PSA_ERROR_STORAGE_FAILURE - */ -psa_status_t psa_crypto_save_transaction( void ); - -/** Load the transaction data from storage, if any. - * - * This function is meant to be called from psa_crypto_init() to recover - * in case a transaction was interrupted by a system crash. - * - * \retval #PSA_SUCCESS - * The data about the ongoing transaction has been loaded to - * #psa_crypto_transaction. - * \retval #PSA_ERROR_DOES_NOT_EXIST - * There is no ongoing transaction. - * \retval #PSA_ERROR_STORAGE_FAILURE - */ -psa_status_t psa_crypto_load_transaction( void ); - -/** Indicate that the current transaction is finished. - * - * Call this function at the very end of transaction processing. - * This function does not "commit" or "abort" the transaction: the storage - * subsystem has no concept of "commit" and "abort", just saving and - * removing the transaction information in storage. - * - * This function erases the transaction data in storage (if any) and - * resets the transaction data in memory. - * - * \retval #PSA_SUCCESS - * There was transaction data in storage. - * \retval #PSA_ERROR_DOES_NOT_EXIST - * There was no transaction data in storage. - * \retval #PSA_ERROR_STORAGE_FAILURE - * It was impossible to determine whether there was transaction data - * in storage, or the transaction data could not be erased. - */ -psa_status_t psa_crypto_stop_transaction( void ); - -/** The ITS file identifier for the transaction data. - * - * 0xffffffNN = special file; 0x74 = 't' for transaction. - */ -#define PSA_CRYPTO_ITS_TRANSACTION_UID ( (psa_key_id_t) 0xffffff74 ) - -#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */ - -#if defined(MBEDTLS_PSA_INJECT_ENTROPY) -/** Backend side of mbedtls_psa_inject_entropy(). - * - * This function stores the supplied data into the entropy seed file. - * - * \retval #PSA_SUCCESS - * Success - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_INSUFFICIENT_STORAGE - * \retval #PSA_ERROR_NOT_PERMITTED - * The entropy seed file already exists. - */ -psa_status_t mbedtls_psa_storage_inject_entropy( const unsigned char *seed, - size_t seed_size ); -#endif /* MBEDTLS_PSA_INJECT_ENTROPY */ - -#ifdef __cplusplus -} -#endif - -#endif /* PSA_CRYPTO_STORAGE_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_its_file.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_its_file.c deleted file mode 100644 index 0935b27..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_its_file.c +++ /dev/null @@ -1,255 +0,0 @@ -/* - * PSA ITS simulator over stdio files. - */ -/* Copyright (C) 2018, ARM Limited, 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. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if defined(MBEDTLS_CONFIG_FILE) -#include MBEDTLS_CONFIG_FILE -#else -#include "mbedtls/config.h" -#endif - -#if defined(MBEDTLS_PSA_ITS_FILE_C) - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#define mbedtls_snprintf snprintf -#endif - -#if defined(_WIN32) -#include -#endif - -#include "psa_crypto_its.h" - -#include -#include -#include -#include - -#if !defined(PSA_ITS_STORAGE_PREFIX) -#define PSA_ITS_STORAGE_PREFIX "" -#endif - -#define PSA_ITS_STORAGE_FILENAME_PATTERN "%08lx%08lx" -#define PSA_ITS_STORAGE_SUFFIX ".psa_its" -#define PSA_ITS_STORAGE_FILENAME_LENGTH \ - ( sizeof( PSA_ITS_STORAGE_PREFIX ) - 1 + /*prefix without terminating 0*/ \ - 16 + /*UID (64-bit number in hex)*/ \ - sizeof( PSA_ITS_STORAGE_SUFFIX ) - 1 + /*suffix without terminating 0*/ \ - 1 /*terminating null byte*/ ) -#define PSA_ITS_STORAGE_TEMP \ - PSA_ITS_STORAGE_PREFIX "tempfile" PSA_ITS_STORAGE_SUFFIX - -/* The maximum value of psa_storage_info_t.size */ -#define PSA_ITS_MAX_SIZE 0xffffffff - -#define PSA_ITS_MAGIC_STRING "PSA\0ITS\0" -#define PSA_ITS_MAGIC_LENGTH 8 - -/* As rename fails on Windows if the new filepath already exists, - * use MoveFileExA with the MOVEFILE_REPLACE_EXISTING flag instead. - * Returns 0 on success, nonzero on failure. */ -#if defined(_WIN32) -#define rename_replace_existing( oldpath, newpath ) \ - ( ! MoveFileExA( oldpath, newpath, MOVEFILE_REPLACE_EXISTING ) ) -#else -#define rename_replace_existing( oldpath, newpath ) rename( oldpath, newpath ) -#endif - -typedef struct -{ - uint8_t magic[PSA_ITS_MAGIC_LENGTH]; - uint8_t size[sizeof( uint32_t )]; - uint8_t flags[sizeof( psa_storage_create_flags_t )]; -} psa_its_file_header_t; - -static void psa_its_fill_filename( psa_storage_uid_t uid, char *filename ) -{ - /* Break up the UID into two 32-bit pieces so as not to rely on - * long long support in snprintf. */ - mbedtls_snprintf( filename, PSA_ITS_STORAGE_FILENAME_LENGTH, - "%s" PSA_ITS_STORAGE_FILENAME_PATTERN "%s", - PSA_ITS_STORAGE_PREFIX, - (unsigned long) ( uid >> 32 ), - (unsigned long) ( uid & 0xffffffff ), - PSA_ITS_STORAGE_SUFFIX ); -} - -static psa_status_t psa_its_read_file( psa_storage_uid_t uid, - struct psa_storage_info_t *p_info, - FILE **p_stream ) -{ - char filename[PSA_ITS_STORAGE_FILENAME_LENGTH]; - psa_its_file_header_t header; - size_t n; - - *p_stream = NULL; - psa_its_fill_filename( uid, filename ); - *p_stream = fopen( filename, "rb" ); - if( *p_stream == NULL ) - return( PSA_ERROR_DOES_NOT_EXIST ); - - n = fread( &header, 1, sizeof( header ), *p_stream ); - if( n != sizeof( header ) ) - return( PSA_ERROR_DATA_CORRUPT ); - if( memcmp( header.magic, PSA_ITS_MAGIC_STRING, - PSA_ITS_MAGIC_LENGTH ) != 0 ) - return( PSA_ERROR_DATA_CORRUPT ); - - p_info->size = ( header.size[0] | - header.size[1] << 8 | - header.size[2] << 16 | - header.size[3] << 24 ); - p_info->flags = ( header.flags[0] | - header.flags[1] << 8 | - header.flags[2] << 16 | - header.flags[3] << 24 ); - return( PSA_SUCCESS ); -} - -psa_status_t psa_its_get_info( psa_storage_uid_t uid, - struct psa_storage_info_t *p_info ) -{ - psa_status_t status; - FILE *stream = NULL; - status = psa_its_read_file( uid, p_info, &stream ); - if( stream != NULL ) - fclose( stream ); - return( status ); -} - -psa_status_t psa_its_get( psa_storage_uid_t uid, - uint32_t data_offset, - uint32_t data_length, - void *p_data, - size_t *p_data_length ) -{ - psa_status_t status; - FILE *stream = NULL; - size_t n; - struct psa_storage_info_t info; - - status = psa_its_read_file( uid, &info, &stream ); - if( status != PSA_SUCCESS ) - goto exit; - status = PSA_ERROR_INVALID_ARGUMENT; - if( data_offset + data_length < data_offset ) - goto exit; -#if SIZE_MAX < 0xffffffff - if( data_offset + data_length > SIZE_MAX ) - goto exit; -#endif - if( data_offset + data_length > info.size ) - goto exit; - - status = PSA_ERROR_STORAGE_FAILURE; -#if LONG_MAX < 0xffffffff - while( data_offset > LONG_MAX ) - { - if( fseek( stream, LONG_MAX, SEEK_CUR ) != 0 ) - goto exit; - data_offset -= LONG_MAX; - } -#endif - if( fseek( stream, data_offset, SEEK_CUR ) != 0 ) - goto exit; - n = fread( p_data, 1, data_length, stream ); - if( n != data_length ) - goto exit; - status = PSA_SUCCESS; - if( p_data_length != NULL ) - *p_data_length = n; - -exit: - if( stream != NULL ) - fclose( stream ); - return( status ); -} - -psa_status_t psa_its_set( psa_storage_uid_t uid, - uint32_t data_length, - const void *p_data, - psa_storage_create_flags_t create_flags ) -{ - psa_status_t status = PSA_ERROR_STORAGE_FAILURE; - char filename[PSA_ITS_STORAGE_FILENAME_LENGTH]; - FILE *stream = NULL; - psa_its_file_header_t header; - size_t n; - - memcpy( header.magic, PSA_ITS_MAGIC_STRING, PSA_ITS_MAGIC_LENGTH ); - header.size[0] = data_length & 0xff; - header.size[1] = ( data_length >> 8 ) & 0xff; - header.size[2] = ( data_length >> 16 ) & 0xff; - header.size[3] = ( data_length >> 24 ) & 0xff; - header.flags[0] = create_flags & 0xff; - header.flags[1] = ( create_flags >> 8 ) & 0xff; - header.flags[2] = ( create_flags >> 16 ) & 0xff; - header.flags[3] = ( create_flags >> 24 ) & 0xff; - - psa_its_fill_filename( uid, filename ); - stream = fopen( PSA_ITS_STORAGE_TEMP, "wb" ); - if( stream == NULL ) - goto exit; - - status = PSA_ERROR_INSUFFICIENT_STORAGE; - n = fwrite( &header, 1, sizeof( header ), stream ); - if( n != sizeof( header ) ) - goto exit; - if( data_length != 0 ) - { - n = fwrite( p_data, 1, data_length, stream ); - if( n != data_length ) - goto exit; - } - status = PSA_SUCCESS; - -exit: - if( stream != NULL ) - { - int ret = fclose( stream ); - if( status == PSA_SUCCESS && ret != 0 ) - status = PSA_ERROR_INSUFFICIENT_STORAGE; - } - if( status == PSA_SUCCESS ) - { - if( rename_replace_existing( PSA_ITS_STORAGE_TEMP, filename ) != 0 ) - status = PSA_ERROR_STORAGE_FAILURE; - } - remove( PSA_ITS_STORAGE_TEMP ); - return( status ); -} - -psa_status_t psa_its_remove( psa_storage_uid_t uid ) -{ - char filename[PSA_ITS_STORAGE_FILENAME_LENGTH]; - FILE *stream; - psa_its_fill_filename( uid, filename ); - stream = fopen( filename, "rb" ); - if( stream == NULL ) - return( PSA_ERROR_DOES_NOT_EXIST ); - fclose( stream ); - if( remove( filename ) != 0 ) - return( PSA_ERROR_STORAGE_FAILURE ); - return( PSA_SUCCESS ); -} - -#endif /* MBEDTLS_PSA_ITS_FILE_C */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_attestation_eat.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_attestation_eat.c deleted file mode 100644 index 8683680..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_attestation_eat.c +++ /dev/null @@ -1,365 +0,0 @@ -/** @file - * Copyright (c) 2019, 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 "pal_attestation_eat.h" - -uint32_t mandatory_claims = 0, mandaroty_sw_components = 0; -bool_t sw_component_present = 0; - -static int get_items_in_map(QCBORDecodeContext *decode_context, - struct items_to_get_t *item_list) -{ - int item_index; - QCBORItem item; - struct items_to_get_t *item_ptr = item_list; - - /* initialize the data type of all items in the list */ - while (item_ptr->label != 0) { - item_ptr->item.uDataType = QCBOR_TYPE_NONE; - item_ptr++; - } - - QCBORDecode_GetNext(decode_context, &item); - if (item.uDataType != QCBOR_TYPE_MAP) { - return PAL_ATTEST_ERROR; - } - - for (item_index = item.val.uCount; item_index != 0; item_index--) { - if (QCBORDecode_GetNext(decode_context, &item) != QCBOR_SUCCESS) { - return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; - } - if (item.uLabelType != QCBOR_TYPE_INT64) { - continue; - } - - item_ptr = item_list; - while (item_ptr->label != 0) { - if (item.label.int64 == item_ptr->label) { - item_ptr->item = item; - } - item_ptr++; - } - } - - return PAL_ATTEST_SUCCESS; -} - -static int get_item_in_map(QCBORDecodeContext *decode_context, - int32_t label, - QCBORItem *item) -{ - struct items_to_get_t item_list[2]; - - item_list[0].label = label; - item_list[1].label = 0; - - if (get_items_in_map(decode_context, item_list)) { - return PAL_ATTEST_ERROR; - } - - if (item_list[0].item.uDataType == QCBOR_TYPE_NONE) { - return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; - } - - *item = item_list[0].item; - - return PAL_ATTEST_SUCCESS; -} - -static int parse_unprotected_headers(QCBORDecodeContext *decode_context, - struct useful_buf_c *child, - bool *loop_back) -{ - struct items_to_get_t item_list[3]; - - item_list[0].label = COSE_HEADER_PARAM_KID; - item_list[1].label = T_COSE_SHORT_CIRCUIT_LABEL; - item_list[2].label = 0; - *loop_back = false; - - if (get_items_in_map(decode_context, item_list)) { - return PAL_ATTEST_ERROR; - } - - if (item_list[1].item.uDataType == QCBOR_TYPE_TRUE) { - *loop_back = true; - } - - if (item_list[0].item.uDataType != QCBOR_TYPE_BYTE_STRING) { - return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; - } - - *child = item_list[0].item.val.string; - - return PAL_ATTEST_SUCCESS; -} - -static int parse_protected_headers(struct useful_buf_c protected_headers, - int32_t *alg_id) -{ - QCBORDecodeContext decode_context; - QCBORItem item; - - QCBORDecode_Init(&decode_context, protected_headers, 0); - - if (get_item_in_map(&decode_context, COSE_HEADER_PARAM_ALG, &item)) { - return PAL_ATTEST_ERROR; - } - - if (QCBORDecode_Finish(&decode_context)) { - return PAL_ATTEST_ERROR; - } - - if ((item.uDataType != QCBOR_TYPE_INT64) || (item.val.int64 > INT32_MAX)) { - return PAL_ATTEST_ERROR; - } - - *alg_id = (int32_t)item.val.int64; - - return PAL_ATTEST_SUCCESS; -} - -/** - @brief - This API will verify the claims - @param - decode_context : The buffer containing the challenge - item : context for decoding the data items - completed_challenge : Buffer containing the challenge - @return - error status -**/ -static int parse_claims(QCBORDecodeContext *decode_context, QCBORItem item, - struct useful_buf_c completed_challenge) -{ - int i, count = 0; - int status = PAL_ATTEST_SUCCESS; - - /* Parse each claim and validate their data type */ - while (status == PAL_ATTEST_SUCCESS) { - status = QCBORDecode_GetNext(decode_context, &item); - if (status != PAL_ATTEST_SUCCESS) { - break; - } - - mandatory_claims |= 1 << (EAT_CBOR_ARM_RANGE_BASE - item.label.int64); - if (item.uLabelType == QCBOR_TYPE_INT64) { - if (item.label.int64 == EAT_CBOR_ARM_LABEL_NONCE) { - if (item.uDataType == QCBOR_TYPE_BYTE_STRING) { - /* Given challenge vs challenge in token */ - if (UsefulBuf_Compare(item.val.string, completed_challenge)) { - return PAL_ATTEST_TOKEN_CHALLENGE_MISMATCH; - } - } else { - return PAL_ATTEST_TOKEN_NOT_SUPPORTED; - } - } else if (item.label.int64 == EAT_CBOR_ARM_LABEL_BOOT_SEED || - item.label.int64 == EAT_CBOR_ARM_LABEL_IMPLEMENTATION_ID || - item.label.int64 == EAT_CBOR_ARM_LABEL_UEID) { - if (item.uDataType != QCBOR_TYPE_BYTE_STRING) { - return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; - } - } else if (item.label.int64 == EAT_CBOR_ARM_LABEL_ORIGINATION || - item.label.int64 == EAT_CBOR_ARM_LABEL_PROFILE_DEFINITION || - item.label.int64 == EAT_CBOR_ARM_LABEL_HW_VERSION) { - if (item.uDataType != QCBOR_TYPE_TEXT_STRING) { - return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; - } - } else if (item.label.int64 == EAT_CBOR_ARM_LABEL_CLIENT_ID || - item.label.int64 == EAT_CBOR_ARM_LABEL_SECURITY_LIFECYCLE) { - if (item.uDataType != QCBOR_TYPE_INT64) { - return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; - } - } else if (item.label.int64 == EAT_CBOR_ARM_LABEL_SW_COMPONENTS) { - if (item.uDataType != QCBOR_TYPE_ARRAY) { - return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; - } - - sw_component_present = 1; - status = QCBORDecode_GetNext(decode_context, &item); - if (status != PAL_ATTEST_SUCCESS) { - continue; - } - - count = item.val.uCount; - for (i = 0; i <= count; i++) { - mandaroty_sw_components |= 1 << item.label.int64; - - if (item.label.int64 == EAT_CBOR_SW_COMPONENT_MEASUREMENT) { - if (item.uDataType != QCBOR_TYPE_BYTE_STRING) { - return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; - } - } else if (item.label.int64 == EAT_CBOR_SW_COMPONENT_MEASUREMENT_DESC) { - if (item.uDataType != QCBOR_TYPE_TEXT_STRING) { - return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; - } - } else if (item.label.int64 == EAT_CBOR_SW_COMPONENT_VERSION) { - if (item.uDataType != QCBOR_TYPE_TEXT_STRING) { - return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; - } - } else if (item.label.int64 == EAT_CBOR_SW_COMPONENT_SIGNER_ID) { - if (item.uDataType != QCBOR_TYPE_BYTE_STRING) { - return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; - } - } else if (item.label.int64 == EAT_CBOR_SW_COMPONENT_EPOCH) { - if (item.uDataType != QCBOR_TYPE_INT64) { - return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; - } - } else if (item.label.int64 == EAT_CBOR_SW_COMPONENT_TYPE) { - if (item.uDataType != QCBOR_TYPE_TEXT_STRING) { - return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; - } - } - - if (i < count) { - status = QCBORDecode_GetNext(decode_context, &item); - if (status != PAL_ATTEST_SUCCESS) { - return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; - } - } - } - - } - } else { - /* ToDo: Add other claim types */ - } - } - - if (status == QCBOR_ERR_HIT_END) { - return PAL_ATTEST_SUCCESS; - } else { - return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; - } -} - -/** - @brief - This API will verify the attestation token - @param - challenge : The buffer containing the challenge - challenge_size : Size of the challenge buffer - token : The buffer containing the attestation token - token_size : Size of the token buffer - @return - error status -**/ -int32_t pal_initial_attest_verify_token(uint8_t *challenge, uint32_t challenge_size, - uint8_t *token, uint32_t token_size) -{ - int status = PAL_ATTEST_SUCCESS; - bool short_circuit; - int32_t cose_algorithm_id; - QCBORItem item; - QCBORDecodeContext decode_context; - struct useful_buf_c completed_challenge; - struct useful_buf_c completed_token; - struct useful_buf_c payload; - struct useful_buf_c protected_headers; - struct useful_buf_c kid; - - /* Construct the token buffer for validation */ - completed_token.ptr = token; - completed_token.len = token_size; - - /* Construct the challenge buffer for validation */ - completed_challenge.ptr = challenge; - completed_challenge.len = challenge_size; - - /* - ------------------------- - | CBOR Array Type | - ------------------------- - | Protected Headers | - ------------------------- - | Unprotected Headers | - ------------------------- - | Payload | - ------------------------- - | Signature | - ------------------------- - */ - - /* Initialize the decorder */ - QCBORDecode_Init(&decode_context, completed_token, QCBOR_DECODE_MODE_NORMAL); - - /* Get the Header */ - QCBORDecode_GetNext(&decode_context, &item); - - /* Check the CBOR Array type. Check if the count is 4. - * Only COSE_SIGN1 is supported now. - */ - if (item.uDataType != QCBOR_TYPE_ARRAY || item.val.uCount != 4 || - !QCBORDecode_IsTagged(&decode_context, &item, CBOR_TAG_COSE_SIGN1)) { - return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; - } - - /* Get the next headers */ - QCBORDecode_GetNext(&decode_context, &item); - if (item.uDataType != QCBOR_TYPE_BYTE_STRING) { - return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; - } - - protected_headers = item.val.string; - - /* Parse the protected headers and check the data type and value*/ - status = parse_protected_headers(protected_headers, &cose_algorithm_id); - if (status != PAL_ATTEST_SUCCESS) { - return status; - } - - /* Parse the unprotected headers and check the data type and value */ - short_circuit = false; - status = parse_unprotected_headers(&decode_context, &kid, &short_circuit); - if (status != PAL_ATTEST_SUCCESS) { - return status; - } - - /* Get the payload */ - QCBORDecode_GetNext(&decode_context, &item); - if (item.uDataType != QCBOR_TYPE_BYTE_STRING) { - return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; - } - - payload = item.val.string; - - /* Get the digital signature */ - QCBORDecode_GetNext(&decode_context, &item); - if (item.uDataType != QCBOR_TYPE_BYTE_STRING) { - return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; - } - - /* Initialize the Decoder and validate the payload format */ - QCBORDecode_Init(&decode_context, payload, QCBOR_DECODE_MODE_NORMAL); - status = QCBORDecode_GetNext(&decode_context, &item); - if (status != PAL_ATTEST_SUCCESS) { - return status; - } - - if (item.uDataType != QCBOR_TYPE_MAP) { - return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; - } - - /* Parse the payload and check the data type of each claim */ - status = parse_claims(&decode_context, item, completed_challenge); - if (status != PAL_ATTEST_SUCCESS) { - return status; - } - - if ((mandatory_claims & MANDATORY_CLAIM_WITH_SW_COMP) == MANDATORY_CLAIM_WITH_SW_COMP) { - if ((mandaroty_sw_components & MANDATORY_SW_COMP) != MANDATORY_SW_COMP) { - return PAL_ATTEST_TOKEN_NOT_ALL_MANDATORY_CLAIMS; - } - } else if ((mandatory_claims & MANDATORY_CLAIM_NO_SW_COMP) != MANDATORY_CLAIM_NO_SW_COMP) { - return PAL_ATTEST_TOKEN_NOT_ALL_MANDATORY_CLAIMS; - } - - return PAL_ATTEST_SUCCESS; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_attestation_eat.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_attestation_eat.h deleted file mode 100644 index 9f435fb..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_attestation_eat.h +++ /dev/null @@ -1,73 +0,0 @@ -/** @file - * Copyright (c) 2019, 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 "qcbor.h" -#include "pal_common.h" - -#define PAL_ATTEST_MIN_ERROR 30 - -#define COSE_HEADER_PARAM_ALG 1 -#define COSE_HEADER_PARAM_KID 4 - -#define MANDATORY_CLAIM_WITH_SW_COMP 862 -#define MANDATORY_CLAIM_NO_SW_COMP 926 -#define MANDATORY_SW_COMP 36 -#define CBOR_ARM_TOTAL_CLAIM_INSTANCE 10 - -/* - CBOR Label for proprietary header indicating short-circuit - signing was used. Just a random number in the proprietary - label space */ -#define T_COSE_SHORT_CIRCUIT_LABEL (-8675309) - -#define EAT_CBOR_ARM_RANGE_BASE (-75000) -#define EAT_CBOR_ARM_LABEL_PROFILE_DEFINITION (EAT_CBOR_ARM_RANGE_BASE - 0) -#define EAT_CBOR_ARM_LABEL_CLIENT_ID (EAT_CBOR_ARM_RANGE_BASE - 1) -#define EAT_CBOR_ARM_LABEL_SECURITY_LIFECYCLE (EAT_CBOR_ARM_RANGE_BASE - 2) -#define EAT_CBOR_ARM_LABEL_IMPLEMENTATION_ID (EAT_CBOR_ARM_RANGE_BASE - 3) -#define EAT_CBOR_ARM_LABEL_BOOT_SEED (EAT_CBOR_ARM_RANGE_BASE - 4) -#define EAT_CBOR_ARM_LABEL_HW_VERSION (EAT_CBOR_ARM_RANGE_BASE - 5) -#define EAT_CBOR_ARM_LABEL_SW_COMPONENTS (EAT_CBOR_ARM_RANGE_BASE - 6) -#define EAT_CBOR_ARM_LABEL_NO_SW_COMPONENTS (EAT_CBOR_ARM_RANGE_BASE - 7) -#define EAT_CBOR_ARM_LABEL_NONCE (EAT_CBOR_ARM_RANGE_BASE - 8) -#define EAT_CBOR_ARM_LABEL_UEID (EAT_CBOR_ARM_RANGE_BASE - 9) -#define EAT_CBOR_ARM_LABEL_ORIGINATION (EAT_CBOR_ARM_RANGE_BASE - 10) - -#define EAT_CBOR_SW_COMPONENT_TYPE (1u) -#define EAT_CBOR_SW_COMPONENT_MEASUREMENT (2u) -#define EAT_CBOR_SW_COMPONENT_EPOCH (3u) -#define EAT_CBOR_SW_COMPONENT_VERSION (4u) -#define EAT_CBOR_SW_COMPONENT_SIGNER_ID (5u) -#define EAT_CBOR_SW_COMPONENT_MEASUREMENT_DESC (6u) - - -enum attestation_error_code { - PAL_ATTEST_SUCCESS = 0, - PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING = PAL_ATTEST_MIN_ERROR, - PAL_ATTEST_TOKEN_CHALLENGE_MISMATCH, - PAL_ATTEST_TOKEN_NOT_SUPPORTED, - PAL_ATTEST_TOKEN_NOT_ALL_MANDATORY_CLAIMS, - PAL_ATTEST_ERROR, -}; - -struct items_to_get_t { - int64_t label; - QCBORItem item; -}; - -int32_t pal_initial_attest_verify_token(uint8_t *challenge, uint32_t challenge_size, - uint8_t *token, uint32_t token_size); diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_attestation_intf.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_attestation_intf.c deleted file mode 100644 index 66b3ab4..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_attestation_intf.c +++ /dev/null @@ -1,53 +0,0 @@ -/** @file - * Copyright (c) 2019, 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 "pal_attestation_intf.h" - -/** - @brief - This API will call the requested attestation function - @param - type : function code - valist : variable argument list - @return - error status -**/ -int32_t pal_attestation_function(int type, va_list valist) -{ - uint8_t *challenge, *token; - uint32_t challenge_size, *token_size, verify_token_size; - - switch (type) { - case PAL_INITIAL_ATTEST_GET_TOKEN: - challenge = va_arg(valist, uint8_t *); - challenge_size = va_arg(valist, uint32_t); - token = va_arg(valist, uint8_t *); - token_size = va_arg(valist, uint32_t *); - return psa_initial_attest_get_token(challenge, challenge_size, token, token_size); - case PAL_INITIAL_ATTEST_GET_TOKEN_SIZE: - challenge_size = va_arg(valist, uint32_t); - token_size = va_arg(valist, uint32_t *); - return psa_initial_attest_get_token_size(challenge_size, token_size); - case PAL_INITIAL_ATTEST_VERIFY_TOKEN: - challenge = va_arg(valist, uint8_t *); - challenge_size = va_arg(valist, uint32_t); - token = va_arg(valist, uint8_t *); - verify_token_size = va_arg(valist, uint32_t); - return pal_initial_attest_verify_token(challenge, challenge_size, - token, verify_token_size); - default: - return PAL_STATUS_UNSUPPORTED_FUNC; - } -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_attestation_intf.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_attestation_intf.h deleted file mode 100644 index fdefc83..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_attestation_intf.h +++ /dev/null @@ -1,31 +0,0 @@ -/** @file - * Copyright (c) 2019, 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 _PAL_INITIAL_ATTESTATION_H_ -#define _PAL_INITIAL_ATTESTATION_H_ - -#include "psa_initial_attestation_api.h" -#include "pal_attestation_eat.h" - -enum attestation_function_code { - PAL_INITIAL_ATTEST_GET_TOKEN = 0x1, - PAL_INITIAL_ATTEST_GET_TOKEN_SIZE = 0x2, - PAL_INITIAL_ATTEST_VERIFY_TOKEN = 0x3, -}; - -int32_t pal_attestation_function(int type, va_list valist); -#endif /* _PAL_INITIAL_ATTESTATION_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_client_api_empty_intf.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_client_api_empty_intf.c deleted file mode 100644 index 8e9b90d..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_client_api_empty_intf.c +++ /dev/null @@ -1,94 +0,0 @@ -/** @file - * Copyright (c) 2018-2020, 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 "pal_common.h" -#include "pal_client_api_intf.h" - - -/** - * @brief - Retrieve the version of the PSA Framework API that is implemented. - * This is a wrapper API for psa_framework_version API. - * @param - void - * @return - The PSA Framework API version. - */ - -uint32_t pal_ipc_framework_version(void) -{ - return 0; -} - -/** - * @brief - Retrieve the minor version of a Root of Trust Service by its SID. - * This is a wrapper API for the psa_version API. - * @param - sid The Root of Trust Service ID - * @return - Minor version of Root of Trust Service or PSA_VERSION_NONE if Root of Trust - * Service not present on the system. - */ - -uint32_t pal_ipc_version(uint32_t sid) -{ - return PSA_VERSION_NONE; -} - -/** - * @brief - Connect to given sid. - * This is a wrapper API for the psa_connect API. - * @param - sid : RoT service id - * @param - minor_version : minor_version of RoT service - * @return - psa_handle_t : return connection handle - */ - -psa_handle_t pal_ipc_connect(uint32_t sid, uint32_t minor_version) -{ - return PSA_NULL_HANDLE; -} - -/** - * @brief Call a connected Root of Trust Service. - * This is a wrapper API for the psa_call API. - * The caller must provide an array of ::psa_invec_t structures as the input payload. - * - * @param -handle Handle for the connection. - * @param -in_vec Array of psa_invec structures. - * @param -in_len Number of psa_invec structures in in_vec. - * @param -out_vec Array of psa_outvec structures for optional Root of Trust Service response. - * @param -out_len Number of psa_outvec structures in out_vec. - * @return -psa_status_t - */ - -psa_status_t pal_ipc_call(psa_handle_t handle, - const psa_invec *in_vec, - size_t in_len, - psa_outvec *out_vec, - size_t out_len) -{ - return (PSA_SUCCESS - 1); -} - -/** - * @brief Close a connection to a Root of Trust Service. - * This is a wrapper API for the psa_close API. - * Sends the PSA_IPC_DISCONNECT message to the Root of Trust Service so it can clean up resources. - * - * @param handle Handle for the connection. - * @return void - */ - -void pal_ipc_close(psa_handle_t handle) -{ - return; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_client_api_intf.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_client_api_intf.c deleted file mode 100644 index 73ca73c..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_client_api_intf.c +++ /dev/null @@ -1,101 +0,0 @@ -/** @file - * Copyright (c) 2018, 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. -**/ - -#ifdef COMPONENT_PSA_SRV_IPC - -#include "pal_common.h" -#include "pal_client_api_intf.h" - -/** - * @brief - Retrieve the version of the PSA Framework API that is implemented. - * This is a wrapper API for psa_framework_version API. - * @param - void - * @return - The PSA Framework API version. - * Note - Return PAL_STATUS_ERROR if PSA IPC is not implemented. - */ - -uint32_t pal_ipc_framework_version(void) -{ - return (psa_framework_version()); -} - -/** - * @brief - Retrieve the minor version of a Root of Trust Service by its SID. - * This is a wrapper API for the psa_version API. - * @param - sid The Root of Trust Service ID - * @return - Minor version of Root of Trust Service or PSA_VERSION_NONE if Root of Trust - * Service not present on the system. - * Note - Return PAL_STATUS_ERROR if PSA IPC is not implemented. - */ - -uint32_t pal_ipc_version(uint32_t sid) -{ - return (psa_version(sid)); -} - -/** - * @brief - Connect to given sid. - * This is a wrapper API for the psa_connect API. - * @param - sid : RoT service id - * @param - minor_version : minor_version of RoT service - * @return - psa_handle_t : return connection handle - * Note - Return PSA_NULL_HANDLE if PSA IPC is not implemented. - */ - -psa_handle_t pal_ipc_connect(uint32_t sid, uint32_t minor_version) -{ - return (psa_connect(sid, minor_version)); -} - -/** - * @brief Call a connected Root of Trust Service. - * This is a wrapper API for the psa_call API. - * The caller must provide an array of ::psa_invec_t structures as the input payload. - * - * @param -handle Handle for the connection. - * @param -in_vec Array of psa_invec structures. - * @param -in_len Number of psa_invec structures in in_vec. - * @param -out_vec Array of psa_outvec structures for optional Root of Trust Service response. - * @param -out_len Number of psa_outvec structures in out_vec. - * @return -psa_status_t - * Note - Return -1 if PSA IPC is not implemented. - */ - -psa_status_t pal_ipc_call(psa_handle_t handle, - const psa_invec *in_vec, - size_t in_len, - psa_outvec *out_vec, - size_t out_len) -{ - return (psa_call(handle, in_vec, in_len, out_vec, out_len)); -} - -/** - * @brief Close a connection to a Root of Trust Service. - * This is a wrapper API for the psa_close API. - * Sends the PSA_IPC_DISCONNECT message to the Root of Trust Service so it can clean up resources. - * - * @param - handle Handle for the connection. - * @return - void - */ - -void pal_ipc_close(psa_handle_t handle) -{ - psa_close(handle); -} - -#endif diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_client_api_intf.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_client_api_intf.h deleted file mode 100644 index 3c53f5e..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_client_api_intf.h +++ /dev/null @@ -1,61 +0,0 @@ -/** @file - * Copyright (c) 2018-2020, 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 _PAL_CLIENT_API_H_ -#define _PAL_CLIENT_API_H_ - -#include "pal_common.h" - -#define PSA_VERSION_NONE (0) -#define PSA_CONNECTION_REFUSED (INT32_MIN + 1) -#define PSA_CONNECTION_BUSY (INT32_MIN + 2) -#define PSA_DROP_CONNECTION (INT32_MIN) -#define PSA_NULL_HANDLE ((psa_handle_t)0) - -typedef int32_t psa_status_t; -typedef int32_t psa_handle_t; - -typedef struct psa_invec { - const void *base; - size_t len; -} psa_invec; - -typedef struct psa_outvec { - void *base; - size_t len; -} psa_outvec; - -uint32_t psa_framework_version(void); -uint32_t psa_version(uint32_t sid); -psa_handle_t psa_connect(uint32_t sid, uint32_t minor_version); -psa_status_t psa_call(psa_handle_t handle, - const psa_invec *in_vec, - size_t in_len, - psa_outvec *out_vec, - size_t out_len); -void psa_close(psa_handle_t handle); - -uint32_t pal_ipc_framework_version(void); -uint32_t pal_ipc_version(uint32_t sid); -psa_handle_t pal_ipc_connect(uint32_t sid, uint32_t minor_version); -psa_status_t pal_ipc_call(psa_handle_t handle, - const psa_invec *in_vec, - size_t in_len, - psa_outvec *out_vec, - size_t out_len); -void pal_ipc_close(psa_handle_t handle); -#endif /* _PAL_CLIENT_API_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_common.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_common.h deleted file mode 100644 index eaa6b4a..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_common.h +++ /dev/null @@ -1,106 +0,0 @@ -/** @file - * Copyright (c) 2018, 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 _PAL_COMMON_H_ -#define _PAL_COMMON_H_ - -#include -#include -#include -#include -#include - -#ifndef PSA_PROTECTED_STORAGE_IMPLEMENTED -#define PSA_INTERNAL_TRUSTED_STORAGE_IMPLEMENTED 1 /* Use ITS by default */ -#define ITS_TEST 1 -#endif - -#include "internal_trusted_storage.h" - -/* typedef's */ -typedef uint8_t bool_t; -typedef uint32_t addr_t; -typedef uint32_t test_id_t; -typedef uint32_t block_id_t; -typedef char char8_t; -typedef uint32_t cfg_id_t; - -#define PAL_STATUS_UNSUPPORTED_FUNC 0xFF - -typedef enum { - PAL_STATUS_SUCCESS = 0x0, - PAL_STATUS_ERROR = 0x80 -} pal_status_t; - -typedef enum { - NVMEM_READ = 0x1, - NVMEM_WRITE = 0x2, -} nvmem_fn_type_t; - -typedef struct { - nvmem_fn_type_t nvmem_fn_type; - addr_t base; - uint32_t offset; - int size; -} nvmem_param_t; - -typedef enum { - WD_INIT_SEQ = 0x1, - WD_ENABLE_SEQ = 0x2, - WD_DISABLE_SEQ = 0x3, - WD_STATUS_SEQ = 0x4, -} wd_fn_type_t; - -typedef enum { - WD_LOW_TIMEOUT = 0x1, - WD_MEDIUM_TIMEOUT = 0x2, - WD_HIGH_TIMEOUT = 0x3, - WD_CRYPTO_TIMEOUT = 0x4, -} wd_timeout_type_t; - -typedef struct { - wd_fn_type_t wd_fn_type; - addr_t wd_base_addr; - uint32_t wd_time_us; - uint32_t wd_timer_tick_us; -} wd_param_t; - -typedef enum { - UART_INIT = 0x1, - UART_PRINT = 0x2, -} uart_fn_type_t; - -/* - * Redefining some of the client.h elements for compilation to go through - * when PSA IPC APIs are not implemented. - */ -#if (PSA_IPC_IMPLEMENTED == 0) - -#ifndef PSA_VERSION_NONE -#define PSA_VERSION_NONE (0) -#endif - -typedef int32_t psa_handle_t; - -#ifndef PSA_NULL_HANDLE -#define PSA_NULL_HANDLE ((psa_handle_t)0) -#endif - - -#endif /* PSA_IPC_IMPLEMENTED */ - -#endif /* _PAL_COMMON_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_interfaces_ns.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_interfaces_ns.h deleted file mode 100644 index 6393a47..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_interfaces_ns.h +++ /dev/null @@ -1,187 +0,0 @@ -/** @file - * Copyright (c) 2018-2019, 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 _PAL_INTERFACES_NS_H_ -#define _PAL_INTERFACES_NS_H_ - -#include "val.h" -#include "val_client_defs.h" -#include - -/** - @brief - This function will read peripherals using SPI commands - @param - addr : address of the peripheral - - data : read buffer - - len : length of the read buffer in bytes - @return - error status -**/ -int pal_spi_read(addr_t addr, uint8_t *data, uint32_t len); - -/** - * @brief - Retrieve the version of the PSA Framework API that is implemented. - * This is a wrapper API for psa_framework_version API. - * @param - void - * @return - The PSA Framework API version. - * Note - Return PAL_STATUS_ERROR if PSA IPC is not implemented. - */ -uint32_t pal_ipc_framework_version(void); - -/** - * @brief - Retrieve the minor version of a Root of Trust Service by its SID. - * This is a wrapper API for the psa_version API. - * @param - sid The Root of Trust Service ID - * @return - Minor version of Root of Trust Service or PSA_VERSION_NONE if Root of Trust Service - * not present on the system. - * Note - Return PAL_STATUS_ERROR if PSA IPC is not implemented. - */ -uint32_t pal_ipc_version(uint32_t sid); - -/** - * @brief - Connect to given sid. - * This is a wrapper API for the psa_connect API. - * @param - sid : RoT service id - * - minor_version : minor_version of RoT service - * @return - psa_handle_t : return connection handle - * Note - Return PSA_NULL_HANDLE if PSA IPC is not implemented. - */ -psa_handle_t pal_ipc_connect(uint32_t sid, uint32_t minor_version); - -/** - * @brief - Call a connected Root of Trust Service. - * This is a wrapper API for the psa_call API. The caller must provide an array of - * psa_invec_t structures as the input payload. - * @param - handle: Handle for the connection. - * - in_vec: Array of psa_invec structures. - * - in_len: Number of psa_invec structures in in_vec. - * - out_vec: Array of psa_outvec structures for optional Root of Trust Service response. - * - out_len: Number of psa_outvec structures in out_vec. - * @return - psa_status_t - */ - -psa_status_t pal_ipc_call(psa_handle_t handle, - const psa_invec *in_vec, - size_t in_len, - psa_outvec *out_vec, - size_t out_len); - -/** - * @brief - Close a connection to a Root of Trust Service. - * This is a wrapper API for the psa_close API. - * Sends the PSA_IPC_DISCONNECT message to the Root of Trust Service - * so it can clean up resources. - * @param - handle Handle for the connection. - * @return - void - */ -void pal_ipc_close(psa_handle_t handle); -/** - @brief - This function initializes the UART - @param - uart base addr - @return - SUCCESS/FAILURE -**/ -int pal_uart_init_ns(uint32_t uart_base_addr); - -/** - * @brief - This function parses the input string and writes bytes into UART TX FIFO - * @param - str : Input String - * - data : Value for format specifier - * @return - SUCCESS/FAILURE -**/ - -int pal_print_ns(char *str, uint32_t data); - -/** - * @brief - Initializes an hardware watchdog timer - * @param - base_addr : Base address of the watchdog module - * - time_us : Time in micro seconds - * - timer_tick_us : Number of ticks per micro second - * @return - SUCCESS/FAILURE -**/ -int pal_wd_timer_init_ns(addr_t base_addr, uint32_t time_us, uint32_t timer_tick_us); - -/** - * @brief - Enables a hardware watchdog timer - * @param - base_addr : Base address of the watchdog module - * @return - SUCCESS/FAILURE -**/ -int pal_wd_timer_enable_ns(addr_t base_addr); - -/** - * @brief - Disables a hardware watchdog timer - * @param - base_addr : Base address of the watchdog module - * @return - SUCCESS/FAILURE -**/ -int pal_wd_timer_disable_ns(addr_t base_addr); - -/** - * @brief - Reads from given non-volatile address. - * @param - base : Base address of nvmem - * offset : Offset - * buffer : Pointer to source address - * size : Number of bytes - * @return - SUCCESS/FAILURE -**/ -int pal_nvmem_read_ns(addr_t base, uint32_t offset, void *buffer, int size); - -/** - * @brief - Writes into given non-volatile address. - * @param - base : Base address of nvmem - * offset : Offset - * buffer : Pointer to source address - * size : Number of bytes - * @return - SUCCESS/FAILURE -**/ -int pal_nvmem_write_ns(addr_t base, uint32_t offset, void *buffer, int size); - -/** - * @brief - This API will call the requested crypto function - * @param - type : function code - * valist : variable argument list - * @return - error status -**/ -int32_t pal_crypto_function(int type, va_list valist); - -/** - * @brief - This API will call the requested internal trusted storage function - * @param - type : function code - * valist : variable argument list - * @return - error status -**/ -uint32_t pal_its_function(int type, va_list valist); - -/** - * @brief - This API will call the requested protected storage function - * @param - type : function code - * valist : variable argument list - * @return - error status -**/ -uint32_t pal_ps_function(int type, va_list valist); - -/** - * @brief - This API will call the requested attestation function - * @param - type : function code - * valist : variable argument list - * @return - error status -**/ -int32_t pal_attestation_function(int type, va_list valist); - -/** - * @brief - Terminates the simulation at the end of all tests completion. - * By default, it put cpus into power down mode. - * @param - void - * @return - void -**/ -void pal_terminate_simulation(void); -#endif diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_internal_trusted_storage_intf.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_internal_trusted_storage_intf.c deleted file mode 100644 index 2e9de8c..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_internal_trusted_storage_intf.c +++ /dev/null @@ -1,92 +0,0 @@ -/** @file - * Copyright (c) 2018, 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 "pal_internal_trusted_storage_intf.h" - -/** - @brief - This API will call the requested internal trusted storage function - @param - type : function code - valist : variable argument list - @return - error status -**/ -uint32_t pal_its_function(int type, va_list valist) -{ -#if PSA_INTERNAL_TRUSTED_STORAGE_IMPLEMENTED - uint32_t uid, data_length, offset; - const void *p_write_data; - void *p_read_data; - psa_storage_create_flags_t its_create_flags; - //psa_ps_create_flags_t ps_create_flags; - struct psa_its_info_t *its_p_info; - //struct psa_eps_info_t *ps_p_info; - /* TODO: Actual size argument is currently not supported by the testing framework. - * Changes need to be implemented in the actual tests. - * Should be fixed by the next import of the tests. - */ - size_t actual_size; - - switch (type) { - case PAL_ITS_SET: - uid = va_arg(valist, psa_storage_uid_t); - data_length = va_arg(valist, uint32_t); - p_write_data = va_arg(valist, const void *); - its_create_flags = va_arg(valist, psa_storage_create_flags_t); - return psa_its_set(uid, data_length, p_write_data, its_create_flags); - case PAL_ITS_GET: - uid = va_arg(valist, psa_storage_uid_t); - offset = va_arg(valist, uint32_t); - data_length = va_arg(valist, uint32_t); - p_read_data = va_arg(valist, void *); - /* TODO: Actual size argument is currently not supported by the testing framework. - * Changes need to be implemented in the actual tests. - * Should be fixed by the next import of the tests. - */ - return psa_its_get(uid, offset, data_length, p_read_data, &actual_size); - case PAL_ITS_GET_INFO: - uid = va_arg(valist, psa_storage_uid_t); - its_p_info = va_arg(valist, struct psa_its_info_t *); - return psa_its_get_info(uid, (struct psa_storage_info_t *)its_p_info); - case PAL_ITS_REMOVE: - uid = va_arg(valist, psa_storage_uid_t); - return psa_its_remove(uid); - /* case PAL_PS_SET: */ - /* uid = va_arg(valist, uint32_t); */ - /* data_length = va_arg(valist, uint32_t); */ - /* p_write_data = va_arg(valist, const void*); */ - /* ps_create_flags = va_arg(valist, psa_ps_create_flags_t); */ - /* return psa_ps_set(uid, data_length, p_write_data, ps_create_flags); */ - /* case PAL_PS_GET: */ - /* uid = va_arg(valist, uint32_t); */ - /* offset = va_arg(valist, uint32_t); */ - /* data_length = va_arg(valist, uint32_t); */ - /* p_read_data = va_arg(valist, void*); */ - /* return psa_ps_get(uid, offset, data_length, p_read_data); */ - /* case PAL_PS_GET_INFO: */ - /* uid = va_arg(valist, uint32_t); */ - /* ps_p_info = va_arg(valist, struct psa_eps_info_t*); */ - /* return psa_ps_get_info(uid, ps_p_info); */ - /* case PAL_PS_REMOVE: */ - /* uid = va_arg(valist, uint32_t); */ - /* return psa_ps_remove(uid); */ - default: - return PAL_STATUS_UNSUPPORTED_FUNC; - } -#else - return PAL_STATUS_ERROR; -#endif -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_internal_trusted_storage_intf.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_internal_trusted_storage_intf.h deleted file mode 100644 index c40aa43..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_internal_trusted_storage_intf.h +++ /dev/null @@ -1,36 +0,0 @@ -/** @file - * Copyright (c) 2018, 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 _PAL_INTERNAL_TRUSTED_STORAGE_INTF_H_ -#define _PAL_INTERNAL_TRUSTED_STORAGE_INTF_H_ - -#include -#include "pal_common.h" - -#if PSA_INTERNAL_TRUSTED_STORAGE_IMPLEMENTED -#include "psa/internal_trusted_storage.h" -#endif - -enum its_function_code { - PAL_ITS_SET = 0x1, - PAL_ITS_GET = 0x2, - PAL_ITS_GET_INFO = 0x3, - PAL_ITS_REMOVE = 0x4, -}; - -uint32_t pal_its_function(int type, va_list valist); -#endif /* _PAL_INTERNAL_TRUSTED_STORAGE_INTF_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_mbed_os_intf.cpp b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_mbed_os_intf.cpp deleted file mode 100644 index be1c70e..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_mbed_os_intf.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (c) 2019-2020 Arm Limited. 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 "rtos.h" -#include "mbed_assert.h" -#include "val_interfaces.h" -#include "pal_common.h" - -#include "psa/crypto.h" -#include "entropy_poll.h" - -#include "psa_attest_inject_key.h" -#include "psa_initial_attestation_api.h" - -#include "pal_mbed_os_intf.h" - -#include "lifecycle.h" - -#define TEST_STACK_SIZE 8192 -#define TEST_KEY_ID_VALUE 17 - -extern val_api_t val_api; -extern psa_api_t psa_api; -#ifdef PS_TEST -extern "C" psa_status_t psa_ps_reset(); -#endif - -test_entry_f test_g = NULL; -compliance_test_type type_g = COMPLIANCE_TEST_UNDEFINED; - -// randomly generated attestation key used for testing the attestation feature. -// The specific key chosen shouldn't matter to the attestation test -// the test just needs a key to be injected before it is run. -static const uint8_t private_key_data[] = { - 0x49, 0xc9, 0xa8, 0xc1, 0x8c, 0x4b, 0x88, 0x56, - 0x38, 0xc4, 0x31, 0xcf, 0x1d, 0xf1, 0xc9, 0x94, - 0x13, 0x16, 0x09, 0xb5, 0x80, 0xd4, 0xfd, 0x43, - 0xa0, 0xca, 0xb1, 0x7d, 0xb2, 0xf1, 0x3e, 0xee -}; - -static const uint8_t public_key_data[] = { - 0x04, 0x77, 0x72, 0x65, 0x6f, 0x81, 0x4b, 0x39, - 0x92, 0x79, 0xd5, 0xe1, 0xf1, 0x78, 0x1f, 0xac, - 0x6f, 0x09, 0x9a, 0x3c, 0x5c, 0xa1, 0xb0, 0xe3, - 0x53, 0x51, 0x83, 0x4b, 0x08, 0xb6, 0x5e, 0x0b, - 0x57, 0x25, 0x90, 0xcd, 0xaf, 0x8f, 0x76, 0x93, - 0x61, 0xbc, 0xf3, 0x4a, 0xcf, 0xc1, 0x1e, 0x5e, - 0x07, 0x4e, 0x84, 0x26, 0xbd, 0xde, 0x04, 0xbe, - 0x6e, 0x65, 0x39, 0x45, 0x44, 0x96, 0x17, 0xde, - 0x45 -}; - -static void psa_attestation_destroy_key_for_test() -{ - psa_key_handle_t handle = 0; - psa_open_key(TEST_KEY_ID_VALUE, &handle); - psa_destroy_key(handle); -} - -static void psa_attestation_inject_key_for_test(void) -{ - size_t exported_length; - uint8_t exported[sizeof(public_key_data)]; - - psa_attestation_destroy_key_for_test(); - psa_attestation_inject_key(private_key_data, - sizeof(private_key_data), - PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1), - exported, - sizeof(exported), - &exported_length); -} - - - -static void reset_storage_for_compliance_test() -{ -#ifdef ITS_TEST - mbed_psa_reboot_and_request_new_security_state(PSA_LIFECYCLE_ASSEMBLY_AND_TEST); -#elif PS_TEST - psa_ps_reset(); -#endif -} - -#if !defined(MAX) -#define MAX(a,b) (((a)>(b))?(a):(b)) -#endif - -#define MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE \ - MAX(MBEDTLS_ENTROPY_MIN_PLATFORM, MBEDTLS_ENTROPY_BLOCK_SIZE) - -static void inject_entropy() -{ -#if defined(MBEDTLS_ENTROPY_NV_SEED) - uint8_t seed[MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE] = { 0 }; - for (int i = 0; i < MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE; ++i) { - seed[i] = i; - } - mbedtls_psa_inject_entropy(seed, MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE); -#endif // defined(MBEDTLS_ENTROPY_NV_SEED) -} - - - -void main_wrapper(void) -{ - test_g(&val_api, &psa_api); -} - - -void pal_mbed_os_compliance_test_initialize(void) -{ - if (COMPLIANCE_TEST_CRYPTO == type_g) { - inject_entropy(); - } else if (COMPLIANCE_TEST_STORAGE == type_g) { - reset_storage_for_compliance_test(); - } else if (COMPLIANCE_TEST_ATTESTATION == type_g) { - reset_storage_for_compliance_test(); - inject_entropy(); - psa_crypto_init(); - psa_attestation_inject_key_for_test(); // inject key in case needed - } - -} - -void pal_mbed_os_compliance_test_destroy(void) -{ - reset_storage_for_compliance_test(); -} - -int test_start(test_entry_f test_f, compliance_test_type type) -{ - test_g = test_f; - type_g = type; -#if defined(MBED_CONF_RTOS_PRESENT) - MBED_ASSERT((type > COMPLIANCE_TEST_START) && (type < COMPLIANCE_TEST_END)); - Thread thread(osPriorityNormal, TEST_STACK_SIZE, NULL); - thread.start(main_wrapper); - thread.join(); -#endif - return 0; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_mbed_os_intf.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_mbed_os_intf.h deleted file mode 100644 index 5308bf9..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_mbed_os_intf.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef PAL_MBED_OS_CRYPTO_H_ -#define PAL_MBED_OS_CRYPTO_H_ - -#include "val_interfaces.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum _compliance_test_type { - COMPLIANCE_TEST_UNDEFINED, - COMPLIANCE_TEST_START = COMPLIANCE_TEST_UNDEFINED, - COMPLIANCE_TEST_CRYPTO, - COMPLIANCE_TEST_ATTESTATION, - COMPLIANCE_TEST_STORAGE, - COMPLIANCE_TEST_END -} compliance_test_type; - -typedef void (*test_entry_f)(val_api_t *val_api, psa_api_t *psa_api); -int test_start(test_entry_f test_f, compliance_test_type type); - -#ifdef __cplusplus -} -#endif - -#endif /* PAL_MBED_OS_CRYPTO_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_protected_storage_intf.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_protected_storage_intf.c deleted file mode 100644 index 893e5f3..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_protected_storage_intf.c +++ /dev/null @@ -1,63 +0,0 @@ -/** @file - * Copyright (c) 2018, 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 "pal_protected_storage_intf.h" - -/** - @brief - This API will call the requested protected storage function - @param - type : function code - valist : variable argument list - @return - error status -**/ -uint32_t pal_ps_function(int type, va_list valist) -{ -#if PSA_PROTECTED_STORAGE_IMPLEMENTED - uint32_t uid, data_length, offset; - size_t actual_length; - const void *p_write_data; - void *p_read_data; - psa_storage_create_flags_t ps_create_flags; - struct psa_ps_info_t *ps_p_info; - - switch (type) { - case PAL_PS_SET: - uid = va_arg(valist, psa_storage_uid_t); - data_length = va_arg(valist, uint32_t); - p_write_data = va_arg(valist, const void *); - ps_create_flags = va_arg(valist, psa_storage_create_flags_t); - return psa_ps_set(uid, data_length, p_write_data, ps_create_flags); - case PAL_PS_GET: - uid = va_arg(valist, psa_storage_uid_t); - offset = va_arg(valist, uint32_t); - data_length = va_arg(valist, uint32_t); - p_read_data = va_arg(valist, void *); - return psa_ps_get(uid, offset, data_length, p_read_data, &actual_length); - case PAL_PS_GET_INFO: - uid = va_arg(valist, psa_storage_uid_t); - ps_p_info = va_arg(valist, struct psa_ps_info_t *); - return psa_ps_get_info(uid, ps_p_info); - case PAL_PS_REMOVE: - uid = va_arg(valist, psa_storage_uid_t); - return psa_ps_remove(uid); - default: - return PAL_STATUS_UNSUPPORTED_FUNC; - } -#else - return PAL_STATUS_ERROR; -#endif -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_protected_storage_intf.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_protected_storage_intf.h deleted file mode 100644 index 3ebe86a..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_protected_storage_intf.h +++ /dev/null @@ -1,36 +0,0 @@ -/** @file - * Copyright (c) 2018, 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 _PAL_PROTECTED_STORAGE_INTF_H_ -#define _PAL_PROTECTED_STORAGE_INTF_H_ - -#include -#include "pal_common.h" - -#if PSA_PROTECTED_STORAGE_IMPLEMENTED -#include "psa/protected_storage.h" -#endif - -enum ps_function_code { - PAL_PS_SET = 0x1, - PAL_PS_GET = 0x2, - PAL_PS_GET_INFO = 0x3, - PAL_PS_REMOVE = 0x4, -}; - -uint32_t pal_ps_function(int type, va_list valist); -#endif /* _PAL_PROTECTED_STORAGE_INTF_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/LICENSE b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/LICENSE deleted file mode 100644 index 96810fd..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/LICENSE +++ /dev/null @@ -1,2 +0,0 @@ -Unless specifically indicated otherwise in a file, TF-M files in this directory are licensed under the BSD-3-Clause license, -as can be found in: LICENSE-bsd-3-clause.txt diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/LICENSE-BSD-3-Clause b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/LICENSE-BSD-3-Clause deleted file mode 100644 index 476769c..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/LICENSE-BSD-3-Clause +++ /dev/null @@ -1,26 +0,0 @@ -Copyright 2019 Arm Limited and affiliates. -SPDX-License-Identifier: BSD-3-Clause - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. Neither the name of the copyright holder nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attest_boot_status_loader.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attest_boot_status_loader.c deleted file mode 100755 index 8413a67..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attest_boot_status_loader.c +++ /dev/null @@ -1,95 +0,0 @@ -/* -* Copyright (c) 2018-2019 ARM Limited. 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 -#include -#include "attestation.h" -#include "attestation_bootloader_data.h" -#include "tfm_impl/tfm_boot_status.h" -#ifdef TARGET_TFM -#include "region_defs.h" -#endif - -/*! - * \def SHARED_DATA_INITIALZED and SHARED_DATA_UNNITIALZED - * - * \brief Indicates that shared data was already initialized. - */ -#define SHARED_DATA_UNNITIALZED (0u) -#define SHARED_DATA_INITIALZED (1u) - -/*! - * \var shared_data_init_done - * - * \brief Indicates whether shared data area was already initialized. - * - */ -static uint32_t shared_data_init_done = SHARED_DATA_UNNITIALZED; - -enum psa_attest_err_t -attest_get_boot_data(uint8_t major_type, void *ptr, uint32_t len) { - if (shared_data_init_done == SHARED_DATA_INITIALZED) - { - return PSA_ATTEST_ERR_SUCCESS; - } - struct shared_data_tlv_header *tlv_header; - struct shared_data_tlv_header *ptr_tlv_header; - struct shared_data_tlv_entry *tlv_entry; - uintptr_t tlv_end, offset; - - /* Get the boundaries of TLV section */ - tlv_header = (struct shared_data_tlv_header *)BOOT_TFM_SHARED_DATA_BASE; - if (tlv_header->tlv_magic != SHARED_DATA_TLV_INFO_MAGIC) - { - return PSA_ATTEST_ERR_INIT_FAILED; - } - tlv_end = (uintptr_t)BOOT_TFM_SHARED_DATA_BASE + (uintptr_t)tlv_header->tlv_tot_len; - offset = (uintptr_t)BOOT_TFM_SHARED_DATA_BASE + (uintptr_t)SHARED_DATA_HEADER_SIZE; - - /* Add header to output buffer as well */ - if (len < SHARED_DATA_HEADER_SIZE) - { - return PSA_ATTEST_ERR_INIT_FAILED; - } - ptr_tlv_header = (struct shared_data_tlv_header *)ptr; - ptr_tlv_header->tlv_magic = SHARED_DATA_TLV_INFO_MAGIC; - ptr_tlv_header->tlv_tot_len = SHARED_DATA_HEADER_SIZE; - - ptr = (uint8_t *)ptr + SHARED_DATA_HEADER_SIZE; - /* Iterates over the TLV section and copy TLVs with requested major - * type to the provided buffer. - */ - for (; offset < tlv_end; offset += tlv_entry->tlv_len) - { - tlv_entry = (struct shared_data_tlv_entry *)offset; - if (GET_MAJOR(tlv_entry->tlv_type) == major_type) { - if (len < ptr_tlv_header->tlv_tot_len + tlv_entry->tlv_len) { - return PSA_ATTEST_ERR_INIT_FAILED; - } - memcpy(ptr, (const void *)tlv_entry, tlv_entry->tlv_len); - ptr = (uint8_t *)ptr + tlv_entry->tlv_len; - ptr_tlv_header->tlv_tot_len += tlv_entry->tlv_len; - } - if (tlv_entry->tlv_len == 0) { - break; - } - } - - shared_data_init_done = SHARED_DATA_INITIALZED; - return PSA_ATTEST_ERR_SUCCESS; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attest_crypto.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attest_crypto.c deleted file mode 100755 index f92fc18..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attest_crypto.c +++ /dev/null @@ -1,275 +0,0 @@ -/* - * attest_crypto.c - * - * Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * See BSD-3-Clause license in README.md - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "t_cose_crypto.h" -#include "tfm_plat_defs.h" -#include "psa/crypto.h" -#include "tfm_plat_crypto_keys.h" -#include - -#define PSA_ATTESTATION_PRIVATE_KEY_ID 17 - -/** - * \brief Context for PSA hash adaptation. - * - * Hash context for PSA hash implementation. This is fit into and cast - * to/from struct \ref t_cose_crypto_hash. - */ -struct t_cose_psa_crypto_hash { - psa_status_t status; - psa_hash_operation_t operation; -}; - -enum t_cose_err_t -t_cose_crypto_pub_key_sign(int32_t cose_alg_id, - int32_t key_select, - struct useful_buf_c hash_to_sign, - struct useful_buf signature_buffer, - struct useful_buf_c *signature) { - enum t_cose_err_t cose_ret = T_COSE_SUCCESS; - psa_status_t crypto_ret; - const size_t sig_size = t_cose_signature_size(cose_alg_id); - - (void)key_select; - - psa_key_handle_t handle; - - if (sig_size > signature_buffer.len) - { - return T_COSE_ERR_SIG_BUFFER_SIZE; - } - - crypto_ret = psa_open_key(PSA_ATTESTATION_PRIVATE_KEY_ID, &handle); - if (crypto_ret != PSA_SUCCESS) - { - return T_COSE_ERR_NO_KID; - } - - crypto_ret = psa_sign_hash(handle, - PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256), - hash_to_sign.ptr, - hash_to_sign.len, - signature_buffer.ptr, - signature_buffer.len, - &(signature->len)); - - - if (crypto_ret != PSA_SUCCESS) - { - psa_close_key(handle); - cose_ret = T_COSE_ERR_UNSUPPORTED_SIGNING_ALG; - } else - { - signature->ptr = signature_buffer.ptr; - } - - psa_close_key(handle); - return cose_ret; -} - -enum t_cose_err_t -t_cose_crypto_get_ec_pub_key(int32_t key_select, - struct useful_buf_c kid, - int32_t *cose_curve_id, - struct useful_buf buf_to_hold_x_coord, - struct useful_buf buf_to_hold_y_coord, - struct useful_buf_c *x_coord, - struct useful_buf_c *y_coord) { - - enum tfm_plat_err_t err; - enum ecc_curve_t cose_curve; - struct ecc_key_t attest_key = {0}; - uint8_t key_buf[ECC_P_256_KEY_SIZE] = {0}; - - (void)key_select; - - /* Get the initial attestation key */ - err = tfm_plat_get_initial_attest_key(key_buf, sizeof(key_buf), - &attest_key, &cose_curve); - - /* Check the availability of the private key */ - if (err != TFM_PLAT_ERR_SUCCESS || - attest_key.pubx_key == NULL || - attest_key.puby_key == NULL) - { - return T_COSE_ERR_KEY_BUFFER_SIZE; - } - - *cose_curve_id = (int32_t)cose_curve; - - /* Check buffer size to avoid overflow */ - if (buf_to_hold_x_coord.len < attest_key.pubx_key_size) - { - return T_COSE_ERR_KEY_BUFFER_SIZE; - } - - /* Copy the X coordinate of the public key to the buffer */ - memcpy(buf_to_hold_x_coord.ptr, - (const void *)attest_key.pubx_key, - attest_key.pubx_key_size); - - /* Update size */ - buf_to_hold_x_coord.len = attest_key.pubx_key_size; - - /* Check buffer size to avoid overflow */ - if (buf_to_hold_y_coord.len < attest_key.puby_key_size) - { - return T_COSE_ERR_KEY_BUFFER_SIZE; - } - - /* Copy the Y coordinate of the public key to the buffer */ - memcpy(buf_to_hold_y_coord.ptr, - (const void *)attest_key.puby_key, - attest_key.puby_key_size); - - /* Update size */ - buf_to_hold_y_coord.len = attest_key.puby_key_size; - - x_coord->ptr = buf_to_hold_x_coord.ptr; - x_coord->len = buf_to_hold_x_coord.len; - y_coord->ptr = buf_to_hold_y_coord.ptr; - y_coord->len = buf_to_hold_y_coord.len; - - return T_COSE_SUCCESS; -} - -/** - * \brief Check some of the sizes for hash implementation. - * - * \return Value from \ref t_cose_err_t error if sizes are not correct. - * - * It makes sure the constants in the header file match the local - * implementation. This gets evaluated at compile time and will - * optimize out to nothing when all checks pass. - */ -static inline enum t_cose_err_t check_hash_sizes() -{ - if (T_COSE_CRYPTO_SHA256_SIZE != PSA_HASH_SIZE(PSA_ALG_SHA_256)) { - return T_COSE_ERR_HASH_GENERAL_FAIL; - } - - return T_COSE_SUCCESS; -} - -/** - * \brief Convert COSE algorithm ID to a PSA algorithm ID - * - * \param[in] cose_hash_alg_id The COSE-based ID for the - * - * \return PSA-based hash algorithm ID, or MD4 in the case of error. - * - */ -static inline psa_algorithm_t cose_hash_alg_id_to_psa(int32_t cose_hash_alg_id) -{ - psa_algorithm_t return_value; - - switch (cose_hash_alg_id) { - case COSE_ALG_SHA256_PROPRIETARY: - return_value = PSA_ALG_SHA_256; - break; - default: - return_value = PSA_ALG_MD4; - break; - } - - return return_value; -} - -enum t_cose_err_t -t_cose_crypto_hash_start(struct t_cose_crypto_hash *hash_ctx, - int32_t cose_hash_alg_id) { - enum t_cose_err_t cose_ret = T_COSE_SUCCESS; - psa_status_t psa_ret; - struct t_cose_psa_crypto_hash *psa_hash_ctx; - - /* These next 3 lines optimize to nothing except when there is - * failure. - */ - cose_ret = check_hash_sizes(); - if (cose_ret != T_COSE_SUCCESS) - { - return cose_ret; - } - - psa_hash_ctx = (struct t_cose_psa_crypto_hash *)hash_ctx; - memset(&psa_hash_ctx->operation, 0, sizeof(psa_hash_operation_t)); - - psa_ret = psa_hash_setup(&psa_hash_ctx->operation, - cose_hash_alg_id_to_psa(cose_hash_alg_id)); - - if (psa_ret == PSA_SUCCESS) - { - psa_hash_ctx->status = PSA_SUCCESS; - cose_ret = T_COSE_SUCCESS; - } else if (psa_ret == PSA_ERROR_NOT_SUPPORTED) - { - cose_ret = T_COSE_ERR_UNSUPPORTED_HASH; - } else - { - cose_ret = T_COSE_ERR_HASH_GENERAL_FAIL; - } - - return cose_ret; -} - -void t_cose_crypto_hash_update(struct t_cose_crypto_hash *hash_ctx, - struct useful_buf_c data_to_hash) -{ - struct t_cose_psa_crypto_hash *psa_hash_ctx; - - psa_hash_ctx = (struct t_cose_psa_crypto_hash *)hash_ctx; - - if (psa_hash_ctx->status == PSA_SUCCESS) { - if (data_to_hash.ptr != NULL) { - psa_hash_ctx->status = psa_hash_update(&psa_hash_ctx->operation, - data_to_hash.ptr, - data_to_hash.len); - } - } -} - -enum t_cose_err_t -t_cose_crypto_hash_finish(struct t_cose_crypto_hash *hash_ctx, - struct useful_buf buffer_to_hold_result, - struct useful_buf_c *hash_result) { - enum t_cose_err_t cose_ret = T_COSE_SUCCESS; - psa_status_t psa_ret; - struct t_cose_psa_crypto_hash *psa_hash_ctx; - - psa_hash_ctx = (struct t_cose_psa_crypto_hash *)hash_ctx; - - if (psa_hash_ctx->status == PSA_SUCCESS) - { - psa_ret = psa_hash_finish(&psa_hash_ctx->operation, - buffer_to_hold_result.ptr, - buffer_to_hold_result.len, - &(hash_result->len)); - - if (psa_ret == PSA_SUCCESS) { - hash_result->ptr = buffer_to_hold_result.ptr; - cose_ret = T_COSE_SUCCESS; - } else if (psa_ret == PSA_ERROR_BUFFER_TOO_SMALL) { - cose_ret = T_COSE_ERR_HASH_BUFFER_SIZE; - } else { - cose_ret = T_COSE_ERR_HASH_GENERAL_FAIL; - } - } else - { - cose_ret = T_COSE_ERR_HASH_GENERAL_FAIL; - } - - return cose_ret; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attest_crypto_keys.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attest_crypto_keys.c deleted file mode 100755 index e67227c..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attest_crypto_keys.c +++ /dev/null @@ -1,182 +0,0 @@ -/* -* Copyright (c) 2018-2019 ARM Limited. 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 "tfm_plat_crypto_keys.h" -#include "psa/crypto.h" - -#include -#include - - -#define ONE_BYTE (1u) -#define PSA_ATTESTATION_PRIVATE_KEY_ID 17 - -/** - * \brief Copy the key to the destination buffer - * - * \param[out] p_dst Pointer to buffer where to store the key - * \param[in] p_src Pointer to the key - * \param[in] size Length of the key - */ -static inline void copy_key(uint8_t *p_dst, const uint8_t *p_src, size_t size) -{ - uint32_t i; - - for (i = size; i > 0; i--) { - *p_dst = *p_src; - p_src++; - p_dst++; - } -} - -static psa_status_t get_curve(psa_key_type_t type, enum ecc_curve_t *curve_type) -{ - psa_ecc_curve_t curve = PSA_KEY_TYPE_GET_CURVE(type); - switch (curve) { - case PSA_ECC_CURVE_SECP_R1: - *curve_type = P_256; - break; - case PSA_ECC_CURVE_MONTGOMERY: - *curve_type = X25519; - break; - default: - return (PSA_ERROR_NOT_SUPPORTED); - } - - return PSA_SUCCESS; -} - -enum tfm_plat_err_t -tfm_plat_get_initial_attest_key(uint8_t *key_buf, - uint32_t size, - struct ecc_key_t *ecc_key, - enum ecc_curve_t *curve_type) - -{ - uint8_t *key_dst = NULL; - uint8_t *key_src; - uint32_t key_size; - - psa_status_t crypto_ret; - - uint8_t *public_key = NULL; - psa_key_type_t type; - psa_key_type_t public_type; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - size_t bits; - size_t public_key_size = 0; - size_t public_key_length = 0; - - uint32_t initial_attestation_public_x_key_size = 0; - uint32_t initial_attestation_public_y_key_size = 0; - - psa_key_handle_t handle; - - crypto_ret = psa_open_key(PSA_ATTESTATION_PRIVATE_KEY_ID, &handle); - if (crypto_ret != PSA_SUCCESS) - { - return TFM_PLAT_ERR_SYSTEM_ERR; - } - - crypto_ret = psa_get_key_attributes(handle, &attributes); - if (crypto_ret != PSA_SUCCESS) - { - psa_close_key(handle); - return TFM_PLAT_ERR_SYSTEM_ERR; - } - type = psa_get_key_type(&attributes); - if (!PSA_KEY_TYPE_IS_ECC(type)) - { - psa_close_key(handle); - return TFM_PLAT_ERR_SYSTEM_ERR; - } - public_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type); - bits = psa_get_key_bits(&attributes); - public_key_size = PSA_KEY_EXPORT_MAX_SIZE(public_type, bits); - public_key = (uint8_t *) malloc(public_key_size); - if (public_key == NULL) - { - psa_close_key(handle); - return TFM_PLAT_ERR_SYSTEM_ERR; - } - - crypto_ret = psa_export_public_key(handle, - public_key, public_key_size, - &public_key_length); - if (crypto_ret != PSA_SUCCESS) - { - free(public_key); - psa_close_key(handle); - return TFM_PLAT_ERR_SYSTEM_ERR; - } - - /* Set the EC curve type which the key belongs to */ - crypto_ret = get_curve(type, curve_type); - if (crypto_ret != PSA_SUCCESS) - { - free(public_key); - psa_close_key(handle); - return TFM_PLAT_ERR_SYSTEM_ERR; - } - - key_src = public_key; - key_dst = key_buf; - - /* The representation of an ECC public key is: - ** -The byte 0x04 - ** - `x_P` as a `ceiling(m/8)`-byte string, big-endian - ** - `y_P` as a `ceiling(m/8)`-byte string, big-endian - ** - where m is the bit size associated with the curve - ** - 1 byte + 2 * point size - */ - initial_attestation_public_x_key_size = ceil((public_key_length - 1) / 2); - initial_attestation_public_y_key_size = ceil((public_key_length - 1) / 2); - - /* Copy the x-coordinate of public key to the buffer */ - if (initial_attestation_public_x_key_size != 0) - { - key_src = key_src + ONE_BYTE; - key_size = initial_attestation_public_x_key_size; - copy_key(key_dst, key_src, key_size); - ecc_key->pubx_key = key_dst; - ecc_key->pubx_key_size = key_size; - key_dst = key_dst + key_size; - } else - { - ecc_key->pubx_key = NULL; - ecc_key->pubx_key_size = 0; - } - - /* Copy the y-coordinate of public key to the buffer */ - if (initial_attestation_public_y_key_size != 0) - { - key_src += initial_attestation_public_x_key_size; - key_size = initial_attestation_public_y_key_size; - copy_key(key_dst, key_src, key_size); - ecc_key->puby_key = key_dst; - ecc_key->puby_key_size = key_size; - } else - { - ecc_key->puby_key = NULL; - ecc_key->puby_key_size = 0; - } - - free(public_key); - psa_close_key(handle); - return TFM_PLAT_ERR_SUCCESS; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attest_iat_claims_loader.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attest_iat_claims_loader.c deleted file mode 100755 index 8cae245..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attest_iat_claims_loader.c +++ /dev/null @@ -1,222 +0,0 @@ -/* -* Copyright (c) 2018-2019 ARM Limited. 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 -#include -#include -#include -#include "tfm_plat_boot_seed.h" -#include "attestation_bootloader_data.h" -#include "tfm_attest_hal.h" -#include "psa_initial_attestation_api.h" -#include "attestation.h" -#include "psa/crypto.h" -#include "psa/lifecycle.h" - -extern int32_t g_caller_id; - -#define ATTEST_PUB_KEY_SHA_256_SIZE (32u) -#define PSA_ATTESTATION_PRIVATE_KEY_ID 17 - -static enum tfm_security_lifecycle_t security_lifecycle_psa_to_tfm(void) -{ - uint32_t lc = psa_security_lifecycle_state(); - switch (lc) { - case PSA_LIFECYCLE_UNKNOWN: - return TFM_SLC_UNKNOWN; - case PSA_LIFECYCLE_ASSEMBLY_AND_TEST: - return TFM_SLC_ASSEMBLY_AND_TEST; - case PSA_LIFECYCLE_PSA_ROT_PROVISIONING: - return TFM_SLC_PSA_ROT_PROVISIONING; - case PSA_LIFECYCLE_SECURED: - return TFM_SLC_SECURED; - case PSA_LIFECYCLE_NON_PSA_ROT_DEBUG: - return TFM_SLC_NON_PSA_ROT_DEBUG; - case PSA_LIFECYCLE_RECOVERABLE_PSA_ROT_DEBUG: - return TFM_SLC_RECOVERABLE_PSA_ROT_DEBUG; - case PSA_LIFECYCLE_DECOMMISSIONED: - return TFM_SLC_DECOMMISSIONED; - default: - return TFM_SLC_UNKNOWN; - } -} - -/* Hash of attestation public key */ -static enum tfm_plat_err_t attest_public_key_sha256(uint32_t *size, uint8_t *buf) -{ - psa_key_handle_t handle = 0; - - uint8_t *public_key = NULL; - psa_key_type_t type; - psa_key_type_t public_type; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - size_t bits; - size_t public_key_size = 0; - size_t public_key_length = 0; - - psa_status_t crypto_ret; - enum tfm_plat_err_t status = TFM_PLAT_ERR_SUCCESS; - psa_hash_operation_t hash_handle = {0}; - - crypto_ret = psa_open_key(PSA_ATTESTATION_PRIVATE_KEY_ID, &handle); - if (crypto_ret != PSA_SUCCESS) { - return TFM_PLAT_ERR_SYSTEM_ERR; - } - - crypto_ret = psa_get_key_attributes(handle, &attributes); - if (crypto_ret != PSA_SUCCESS) { - status = TFM_PLAT_ERR_SYSTEM_ERR; - goto exit; - } - type = psa_get_key_type(&attributes); - if (!PSA_KEY_TYPE_IS_ECC(type)) { - status = TFM_PLAT_ERR_SYSTEM_ERR; - goto exit; - } - public_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type); - bits = psa_get_key_bits(&attributes); - public_key_size = PSA_KEY_EXPORT_MAX_SIZE(public_type, bits); - public_key = (uint8_t *) malloc(public_key_size); - if (public_key == NULL) { - status = TFM_PLAT_ERR_SYSTEM_ERR; - goto exit; - } - - crypto_ret = psa_export_public_key(handle, - public_key, public_key_size, - &public_key_length); - if (crypto_ret != PSA_SUCCESS) { - status = TFM_PLAT_ERR_SYSTEM_ERR; - goto exit; - } - - crypto_ret = psa_hash_setup(&hash_handle, PSA_ALG_SHA_256); - if (crypto_ret != PSA_SUCCESS) { - status = TFM_PLAT_ERR_SYSTEM_ERR; - goto exit; - } - - psa_hash_update(&hash_handle, public_key, public_key_length); - - crypto_ret = psa_hash_finish(&hash_handle, - buf, - ATTEST_PUB_KEY_SHA_256_SIZE, - (size_t *) size); - if (crypto_ret != PSA_SUCCESS) { - status = TFM_PLAT_ERR_SYSTEM_ERR; - goto exit; - } - -exit: - if (public_key != NULL) { - free(public_key); - } - psa_close_key(handle); - return status; -} - -/** - * \brief Copy the device specific ID to the destination buffer - * - * \param[out] p_dst Pointer to buffer where to store ID - * \param[in] p_src Pointer to the ID - * \param[in] size Length of the ID - */ -static inline void copy_id(uint8_t *p_dst, uint8_t *p_src, size_t size) -{ - uint32_t i; - - for (i = size; i > 0; i--) { - *p_dst = *p_src; - p_src++; - p_dst++; - } -} - -enum psa_attest_err_t attest_get_caller_client_id(int32_t *caller_id) -{ - *caller_id = g_caller_id; - return PSA_ATTEST_ERR_SUCCESS; -} - -/* Boot seed data is part of bootloader status*/ -enum tfm_plat_err_t tfm_plat_get_boot_seed(uint32_t size, uint8_t *buf) -{ - return (enum tfm_plat_err_t)PSA_ATTEST_ERR_CLAIM_UNAVAILABLE; -} - -/** - * Instance ID is mapped to EAT Universal Entity ID (UEID) - * This implementation creates the instance ID as follows: - * - byte 0: 0x01 indicates the type of UEID to be GUID - * - byte 1-32: Hash of attestation public key. Public key is hashed in raw - * format without any encoding. - */ -enum tfm_plat_err_t tfm_plat_get_instance_id(uint32_t *size, uint8_t *buf) -{ - enum tfm_plat_err_t status; - - buf[0] = 0x01; /* First byte is type byte: 0x01 indicates GUID */ - - status = attest_public_key_sha256(size, &buf[1]); - - /* Instance ID size: 1 type byte + size of public key hash */ - *size = *size + 1; - - return status; -} - -/* HW version data is part of bootloader status*/ -enum tfm_plat_err_t tfm_plat_get_hw_version(uint32_t *size, uint8_t *buf) -{ - return (enum tfm_plat_err_t)PSA_ATTEST_ERR_CLAIM_UNAVAILABLE; -} - -enum tfm_plat_err_t tfm_plat_get_implementation_id(uint32_t *size, uint8_t *buf) -{ - memcpy(buf, impl_id_data, *size); - return (enum tfm_plat_err_t)PSA_ATTEST_ERR_SUCCESS; -} - -/* Temporary Implementation of security lifecycle data: mandatory claim. -** tfm_attest_hal_get_security_lifecycle function should return -** 'PSA_ATTEST_ERR_CLAIM_UNAVAILABLE' if been called. -** Security lifecycle data is part of bootloader status data. -** Temp implementation of using psa_security_lifecycle_state */ - -enum tfm_security_lifecycle_t tfm_attest_hal_get_security_lifecycle(void) -{ - return security_lifecycle_psa_to_tfm(); -} - - -const char * -tfm_attest_hal_get_verification_service(uint32_t *size) -{ - *size = sizeof(verification_service_url) - 1; - return verification_service_url; -} - -const char * -tfm_attest_hal_get_profile_definition(uint32_t *size) -{ - *size = sizeof(attestation_profile_definition) - 1; - return attestation_profile_definition; -} - - diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attestation.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attestation.h deleted file mode 100755 index b2b8d1b..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attestation.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2018-2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/** @addtogroup PSA-Attestation - * @{ - */ - - -#ifndef __ATTESTATION_H__ -#define __ATTESTATION_H__ - -#include "psa_initial_attestation_api.h" -#include "tfm_client.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Type of memory access - */ -enum attest_memory_access_t { - TFM_ATTEST_ACCESS_RO = 1, - TFM_ATTEST_ACCESS_RW = 2, -}; - -/** - * \brief Copy the boot data (coming from boot loader) from shared memory area - * to service memory area - * - * \param[in] major_type Major type of TLV entries to copy - * \param[out] ptr Pointer to the buffer to store the boot data - * \parma[in] len Size of the buffer to store the boot data - * - * \return Returns error code as specified in \ref psa_attest_err_t - */ -enum psa_attest_err_t -attest_get_boot_data(uint8_t major_type, void *ptr, uint32_t len); - -/** - * \brief Get the ID of the caller thread. - * - * \param[out] caller_id Pointer where to store caller ID - * - * \return Returns error code as specified in \ref psa_attest_err_t - */ -enum psa_attest_err_t -attest_get_caller_client_id(int32_t *caller_id); - -/** - * \brief Verify memory access rights - * - * \param[in] addr Pointer to the base of the address range to check - * \param[in] size Size of the address range to check - * \param[in] access Type of memory access as specified in - * \ref attest_memory_access - * - * \return Returns error code as specified in \ref psa_attest_err_t - */ -enum psa_attest_err_t -attest_check_memory_access(void *addr, - uint32_t size, - enum attest_memory_access_t access); - -/** - * \brief Initialise the initial attestation service during the TF-M boot up - * process. - * - * \return Returns PSA_ATTEST_ERR_SUCCESS if init has been completed, - * otherwise error as specified in \ref psa_attest_err_t - */ -enum psa_attest_err_t attest_init(void); - -/** - * \brief Get initial attestation token - * - * \param[in] in_vec Pointer to in_vec array, which contains input data - * to attestation service - * \param[in] num_invec Number of elements in in_vec array - * \param[in/out] out_vec Pointer out_vec array, which contains output data - * to attestation service - * \param[in] num_outvec Number of elements in out_vec array - * - * \return Returns error code as specified in \ref psa_attest_err_t - */ -enum psa_attest_err_t -initial_attest_get_token(const psa_invec *in_vec, uint32_t num_invec, - psa_outvec *out_vec, uint32_t num_outvec); - -/** - * \brief Get the size of the initial attestation token - * - * \param[in] in_vec Pointer to in_vec array, which contains input data - * to attestation service - * \param[in] num_invec Number of elements in in_vec array - * \param[out] out_vec Pointer to out_vec array, which contains pointer - * where to store the output data - * \param[in] num_outvec Number of elements in out_vec array - * - * \return Returns error code as specified in \ref psa_attest_err_t - */ -enum psa_attest_err_t -initial_attest_get_token_size(const psa_invec *in_vec, uint32_t num_invec, - psa_outvec *out_vec, uint32_t num_outvec); -#ifdef __cplusplus -} -#endif - -/** @}*/ // PSA-Attestation - -#endif /* __ATTESTATION_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attestation_bootloader_data.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attestation_bootloader_data.c deleted file mode 100755 index 797ecea..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attestation_bootloader_data.c +++ /dev/null @@ -1,64 +0,0 @@ -/* -* Copyright (c) 2018-2019 ARM Limited. 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 "attestation_bootloader_data.h" - -/* Temporary Boodloader data - contains temp mandatory claims */ -__attribute__((aligned(4))) -const uint8_t temp_ram_page_data[] = { - 0x16, 0x20, 0xAC, 0x00, //shared_data_tlv_header - 0x83, 0x11, 0x0C, 0x00, // SW_TYPE - 0x4E, 0x53, 0x50, 0x45, 0x5F, 0x53, 0x50, 0x45, - 0x80, 0x11, 0x0A, 0x00, //SW_VERSION - 0x31, 0x2E, 0x31, 0x2E, 0x31, 0x31, - 0x82, 0x11, 0x06, 0x00, //SW_EPOCH - 0x00, 0x00, - 0x88, 0x11, 0x24, 0x00, //SW_MEASURE_VALUE - 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, - 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, - 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, - 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, - 0x81, 0x11, 0x24, 0x00, //SW_SIGNER_ID - 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, - 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, - 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, - 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, - 0x89, 0x11, 0x0A, 0x00, //SW_MEASURE_TYPE - 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, - 0x00, 0x10, 0x24, 0x00, //TLV_MINOR_IAS_BOOT_SEED - 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, - 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, - 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, - 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, - 0x01, 0x10, 0x16, 0x00, //TLV_MINOR_IAS_HW_VERSION - 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, - 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, - 0x31, 0x32 -}; - -/* Temporary Implementation ID data: mandatory claim represents the original -** implementation signer of the attestation key and identifies the contract -** between the report and verification */ -#define TEMP_IMPL_ID_DATA_SIZE (32u) - -#define TEMP_IMPL_ID_DATA 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, \ - 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, \ - 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, \ - 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF - -const uint8_t impl_id_data[TEMP_IMPL_ID_DATA_SIZE] = {TEMP_IMPL_ID_DATA}; diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attestation_bootloader_data.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attestation_bootloader_data.h deleted file mode 100755 index 6f0c560..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attestation_bootloader_data.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -* Copyright (c) 2018-2019 ARM Limited. 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 __ATTESTATION_BOOTLOADER_DATA_H__ -#define __ATTESTATION_BOOTLOADER_DATA_H__ - -#include -#include - - -#ifdef __cplusplus -extern "C" { -#endif - -/* Temp Shared data area between bootloader and runtime firmware */ -extern const uint8_t temp_ram_page_data[]; - -#define S_RAM_ALIAS_BASE (temp_ram_page_data) - -#define BOOT_TFM_SHARED_DATA_BASE S_RAM_ALIAS_BASE - -extern const uint8_t impl_id_data[]; - -/* Example verification service URL for initial attestation token - temporary data*/ -static const char verification_service_url[] = "www.mbed.com"; -/* Example profile definition document for initial attestation token - temporary data*/ -static const char attestation_profile_definition[] = "psa-attest.md"; - -#ifdef __cplusplus -} -#endif - -#endif /* __ATTESTATION_BOOTLOADER_DATA_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_attest_inject_key.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_attest_inject_key.c deleted file mode 100755 index acb93a6..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_attest_inject_key.c +++ /dev/null @@ -1,38 +0,0 @@ -/* -* Copyright (c) 2018-2019 ARM Limited. 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 "psa_attest_inject_key.h" -#include "psa_inject_attestation_key_impl.h" - -psa_status_t -psa_attestation_inject_key(const uint8_t *key_data, - size_t key_data_length, - psa_key_type_t type, - uint8_t *public_key_data, - size_t public_key_data_size, - size_t *public_key_data_length) -{ - psa_status_t status = PSA_SUCCESS; - status = psa_attestation_inject_key_impl(key_data, - key_data_length, - type, - public_key_data, - public_key_data_size, - public_key_data_length); - return (status); -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_attest_inject_key.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_attest_inject_key.h deleted file mode 100644 index 3e934d3..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_attest_inject_key.h +++ /dev/null @@ -1,87 +0,0 @@ -/* -* Copyright (c) 2018-2019 ARM Limited. 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. -*/ - -/** @addtogroup PSA-Attestation - * @{ - */ - -#ifndef __PSA_INJECT_KEY_H__ -#define __PSA_INJECT_KEY_H__ - -#include "psa/crypto.h" -#include -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -/** - * \brief Generate or import a given key pair and export the public part in a binary format. - * Initial attestation key: Private key for ECDSA-P256 to sign initial attestation token. - * Attestation private key is a persistent key that saved to - * persistent storage with persistent storage id = 17. - * - * \param[in] key_data Buffer containing the private key data if given. - * It must conain the format described in the documentation - * of psa_export_public_key() for - * the chosen type. - * In case of generate the private key - NULL will pass. - * \param key_data_length Size of the \p data buffer in bytes - must be 256 bits. in case key_data isn't NULL. - * In case of private key generation - 0 will pass. - * \param type Key type - must be a ECC key type - * (a \c PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_XXX) value). - * \param[out] data Buffer where the key data is to be written. - * \param data_size Size of the \p data buffer in bytes - - * needs to be bigger then the max size of the public part. - * \param[out] data_length On success, the number of bytes - * that make up the key data. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_OCCUPIED_SLOT - * There is already a key in the specified slot. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t -psa_attestation_inject_key(const uint8_t *key_data, - size_t key_data_length, - psa_key_type_t type, - uint8_t *public_key_data, - size_t public_key_data_size, - size_t *public_key_data_length); - -#ifdef __cplusplus -} -#endif - -/** @}*/ // PSA-Attestation - -#endif /* __PSA_INJECT_KEY_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_attestation_stubs.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_attestation_stubs.c deleted file mode 100755 index b36c64a..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_attestation_stubs.c +++ /dev/null @@ -1,31 +0,0 @@ -/* -* Copyright (c) 2018-2019 ARM Limited. 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 -#include "attestation.h" - -enum psa_attest_err_t -attest_check_memory_access(void *addr, - uint32_t size, - enum attest_memory_access_t access) { - if (size == 0) - { - return PSA_ATTEST_ERR_INVALID_INPUT; - } - return PSA_ATTEST_ERR_SUCCESS; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_initial_attestation_api.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_initial_attestation_api.c deleted file mode 100755 index c4eb017..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_initial_attestation_api.c +++ /dev/null @@ -1,70 +0,0 @@ -/* -* Copyright (c) 2018-2019 ARM Limited. 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 "psa_initial_attestation_api.h" -#include "psa/client.h" -#include "attestation.h" -#include - -int32_t g_caller_id = 0; - -enum psa_attest_err_t -psa_initial_attest_get_token(const uint8_t *challenge_obj, - uint32_t challenge_size, - uint8_t *token, - uint32_t *token_size) { - enum psa_attest_err_t err; - - err = attest_init(); - if (err != PSA_ATTEST_ERR_SUCCESS) - { - return err; - } - - psa_invec in_vec[1] = { { challenge_obj, challenge_size } }; - psa_outvec out_vec[1] = { { token, *token_size } }; - - err = initial_attest_get_token(in_vec, 1, out_vec, 1); - if (err != PSA_ATTEST_ERR_SUCCESS) - { - return err; - } - - *token_size = out_vec[0].len; - - return err; -} - -enum psa_attest_err_t -psa_initial_attest_get_token_size(uint32_t challenge_size, - uint32_t *token_size) { - enum psa_attest_err_t err; - - err = attest_init(); - if (err != PSA_ATTEST_ERR_SUCCESS) - { - return err; - } - - psa_invec in_vec[1] = { { &challenge_size, sizeof(challenge_size) } }; - psa_outvec out_vec[1] = { { token_size, sizeof(*token_size) } }; - - err = initial_attest_get_token_size(in_vec, 1, out_vec, 1); - - return err; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_initial_attestation_api.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_initial_attestation_api.h deleted file mode 100644 index 0b56499..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_initial_attestation_api.h +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (c) 2018-2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/***************************************************************************/ -/* DRAFT UNDER REVIEW */ -/* These APIs are still evolving and are meant as a prototype for review.*/ -/* The APIs will change depending on feedback and will be firmed up */ -/* to a stable set of APIs once all the feedback has been considered. */ -/***************************************************************************/ - -/** @addtogroup PSA-Attestation - * @{ - */ - - -#ifndef __PSA_INITIAL_ATTESTATION_API_H__ -#define __PSA_INITIAL_ATTESTATION_API_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief PSA INITIAL ATTESTATION API version - */ -#define PSA_INITIAL_ATTEST_API_VERSION_MAJOR (0) -#define PSA_INITIAL_ATTEST_API_VERSION_MINOR (9) - -/** - * \enum psa_attest_err_t - * - * \brief Initial attestation service error types - * - */ -enum psa_attest_err_t { - /** Action was performed successfully */ - PSA_ATTEST_ERR_SUCCESS = 0, - /** Boot status data is unavailable or malformed */ - PSA_ATTEST_ERR_INIT_FAILED, - /** Token buffer is too small to store the created token there */ - PSA_ATTEST_ERR_TOKEN_BUFFER_OVERFLOW, - /** Some of the mandatory claims are unavailable*/ - PSA_ATTEST_ERR_CLAIM_UNAVAILABLE, - /** Some parameter or combination of parameters are recognised as invalid: - * - challenge size is not allowed - * - challenge object is unavailable - * - token buffer is unavailable - */ - PSA_ATTEST_ERR_INVALID_INPUT, - /** Unexpected error happened during operation */ - PSA_ATTEST_ERR_GENERAL, - /** Following entry is only to ensure the error code of integer size */ - PSA_ATTEST_ERR_FORCE_INT_SIZE = INT_MAX -}; - -/** - * The allowed size of input challenge in bytes: 32, 48, 64 - * Challenge can be a nonce from server - * or the hash of some combined data : nonce + attested data by caller. - */ -#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32 (32u) -#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48 (48u) -#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64 (64u) - -/** - * The list of fixed claims in the initial attestation token is still evolving, - * you can expect slight changes in the future. - * - * The initial attestation token is planned to be aligned with future version of - * Entity Attestation Token format: - * https://tools.ietf.org/html/draft-mandyam-eat-01 - * - * Current list of claims: - * - Challenge: Input object from caller. Can be a single nonce from server - * or hash of nonce and attested data. It is intended to provide - * freshness to reports and the caller has responsibility to - * arrange this. Allowed length: 32, 48, 64 bytes. The claim is - * modeled to be eventually represented by the EAT standard - * claim nonce. Until such a time as that standard exists, - * the claim will be represented by a custom claim. Value - * is encoded as byte string. - * - * - Instance ID: It represents the unique identifier of the instance. In the - * PSA definition it is a hash of the public attestation key - * of the instance. The claim is modeled to be eventually - * represented by the EAT standard claim UEID of type GUID. - * Until such a time as that standard exists, the claim will be - * represented by a custom claim Value is encoded as byte - * string. - * - * - Verification service indicator: Optional, recommended claim. It is used by - * a Relying Party to locate a validation service for the token. - * The value is a text string that can be used to locate the - * service or a URL specifying the address of the service. The - * claim is modeled to be eventually represented by the EAT - * standard claim origination. Until such a time as that - * standard exists, the claim will be represented by a custom - * claim. Value is encoded as text string. - * - * - Profile definition: Optional, recommended claim. It contains the name of - * a document that describes the 'profile' of the token, being - * a full description of the claims, their usage, verification - * and token signing. The document name may include versioning. - * Custom claim with a value encoded as text string. - * - * - Implementation ID: It represents the original implementation signer of the - * attestation key and identifies the contract between the - * report and verification. A verification service will use this - * claim to locate the details of the verification process. - * Custom claim with a value encoded as byte string. - * - * - Security lifecycle: It represents the current lifecycle state of the - * instance. Custom claim with a value encoded as integer that - * is divided to convey a major state and a minor state. The - * PSA state and implementation state are encoded as follows: - * - version[15:8] - PSA lifecycle state - major - * - version[7:0] - IMPLEMENTATION DEFINED state - minor - * Possible PSA lifecycle states: - * - Unknown (0x1000u), - * - PSA_RoT_Provisioning (0x2000u), - * - Secured (0x3000u), - * - Non_PSA_RoT_Debug(0x4000u), - * - Recoverable_PSA_RoT_Debug (0x5000u), - * - Decommissioned (0x6000u) - * - * - Client ID: The partition ID of that secure partition or non-secure - * thread who called the initial attestation API. Custom claim - * with a value encoded as a *signed* integer. Negative number - * represents non-secure caller, positive numbers represents - * secure callers, zero is invalid. - * - * - HW version: Optional claim. Globally unique number in EAN-13 format - * identifying the GDSII that went to fabrication, HW and ROM. - * It can be used to reference the security level of the PSA-ROT - * via a certification website. Custom claim with a value is - * encoded as text string. - - * - Boot seed: It represents a random value created at system boot time that - * will allow differentiation of reports from different system - * sessions. The size is 32 bytes. Custom claim with a value is - * encoded as byte string. - * - * - Software components: Recommended claim. It represents the software state - * of the system. The value of the claim is an array of CBOR map - * entries, with one entry per software component within the - * device. Each map contains multiple claims that describe - * evidence about the details of the software component. - * - * - Measurement type: Optional claim. It represents the role of the - * software component. Value is encoded as short(!) text - * string. - * - * - Measurement value: It represents a hash of the invariant software - * component in memory at start-up time. The value must be a - * cryptographic hash of 256 bits or stronger.Value is - * encoded as byte string. - * - * - Security epoch: Optional claim. It represents the security control - * point of the software component. Value is encoded as - * unsigned integer. - * - * - Version: Optional claim. It represents the issued software version. - * Value is encoded as text string. - * - * - Signer ID: It represents the hash of a signing authority public key. - * Value is encoded as byte string. - * - * - Measurement description: Optional claim. It represents the way in which - * the measurement value of the software component is - * computed. Value is encoded as text string containing an - * abbreviated description (name) of the measurement method. - * - * - No software measurements: In the event that the implementation does not - * contain any software measurements then the software - * components claim above can be omitted but instead - * it is mandatory to include this claim to indicate this is a - * deliberate state. Custom claim a value is encoded as unsigned - * integer set to 1. - */ - -/** - * \brief Get initial attestation token - * - * \param[in] challenge_obj Pointer to buffer where challenge input is - * stored. Nonce and / or hash of attested data. - * Must be always - * \ref PSA_INITIAL_ATTEST_CHALLENGE_SIZE bytes - * long. - * \param[in] challenge_size Size of challenge object in bytes. - * \param[out] token Pointer to the buffer where attestation token - * must be stored. - * \param[in/out] token_size Size of allocated buffer for token, which - * updated by initial attestation service with - * final token size. - * - * \return Returns error code as specified in \ref psa_attest_err_t - */ -enum psa_attest_err_t -psa_initial_attest_get_token(const uint8_t *challenge_obj, - uint32_t challenge_size, - uint8_t *token, - uint32_t *token_size); - -/** - * \brief Get the exact size of initial attestation token in bytes. - * - * It just returns with the size of the IAT token. It can be used if the caller - * dynamically allocates memory for the token buffer. - * - * \param[in] challenge_size Size of challenge object in bytes. - * \param[out] token_size Size of the token in bytes, which is created by - * initial attestation service. - * - * \return Returns error code as specified in \ref psa_attest_err_t - */ -enum psa_attest_err_t -psa_initial_attest_get_token_size(uint32_t challenge_size, - uint32_t *token_size); - -#ifdef __cplusplus -} -#endif - -/** @}*/ // PSA-Attestation - -#endif /* __PSA_INITIAL_ATTESTATION_API_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_inject_attestation_key_impl.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_inject_attestation_key_impl.c deleted file mode 100755 index c63d93e..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_inject_attestation_key_impl.c +++ /dev/null @@ -1,108 +0,0 @@ -/* -* Copyright (c) 2018-2019 ARM Limited. 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 "psa_inject_attestation_key_impl.h" - -#define ECDSA_P256_KEY_SIZE_IN_BYTES 32 -#define PSA_ATTESTATION_PRIVATE_KEY_ID 17 - -psa_status_t -psa_attestation_inject_key_impl(const uint8_t *key_data, - size_t key_data_length, - psa_key_type_t type, - uint8_t *public_key_data, - size_t public_key_data_size, - size_t *public_key_data_length) -{ - psa_status_t status = PSA_SUCCESS; - size_t key_data_bits = ECDSA_P256_KEY_SIZE_IN_BYTES * 8; - psa_key_handle_t handle = 0; - psa_key_id_t key_id = PSA_ATTESTATION_PRIVATE_KEY_ID; - psa_key_lifetime_t lifetime = PSA_KEY_LIFETIME_PERSISTENT; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_key_usage_t usage = PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY; - psa_key_type_t public_type; - size_t bits; - size_t exported_size = 0; - psa_key_type_t type_key; - -#if defined(MBEDTLS_ECP_C) - - status = psa_open_key(key_id, &handle); - if (status == PSA_SUCCESS) { - /* The key already has been injected */ - goto exit; - } - - psa_set_key_usage_flags(&attributes, usage); - psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)); - psa_set_key_type(&attributes, type); - psa_set_key_bits(&attributes, key_data_bits); - psa_set_key_lifetime(&attributes, lifetime); - psa_set_key_id(&attributes, key_id); - - if (! PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) { - return (PSA_ERROR_INVALID_ARGUMENT); - } - - if (key_data != NULL) { - if (key_data_length != ECDSA_P256_KEY_SIZE_IN_BYTES) { - status = PSA_ERROR_INVALID_ARGUMENT; - goto exit; - } - status = psa_import_key(&attributes, key_data, key_data_length, &handle); - if (status != PSA_SUCCESS) { - goto exit; - } - } else { - /* generating key pair */ - key_data_bits = ECDSA_P256_KEY_SIZE_IN_BYTES * 8; - status = psa_generate_key(&attributes, &handle); - if (status != PSA_SUCCESS) { - goto exit; - } - } - - status = psa_get_key_attributes(handle, &attributes); - if (status != PSA_SUCCESS) { - goto exit; - } - - type_key = psa_get_key_type(&attributes); - public_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type_key); - bits = psa_get_key_bits(&attributes); - exported_size = PSA_KEY_EXPORT_MAX_SIZE(public_type, bits); - - status = psa_export_public_key(handle, - public_key_data, - public_key_data_size, - public_key_data_length); - if (status != PSA_SUCCESS) { - goto exit; - } - if (*public_key_data_length > exported_size) { - status = PSA_ERROR_INVALID_ARGUMENT; - goto exit; - } - -exit: - psa_close_key(handle); - return (status); -#endif /* MBEDTLS_ECP_C */ - - return (PSA_ERROR_NOT_SUPPORTED); -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_inject_attestation_key_impl.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_inject_attestation_key_impl.h deleted file mode 100755 index de6e1bb..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_inject_attestation_key_impl.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -* Copyright (c) 2018-2019 ARM Limited. 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 __PSA_INITIAL_ATTESTATION_IMPL_H__ -#define __PSA_INITIAL_ATTESTATION_IMPL_H__ - -#include "psa/crypto.h" -#include -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -psa_status_t -psa_attestation_inject_key_impl(const uint8_t *key_data, - size_t key_data_length, - psa_key_type_t type, - uint8_t *public_key_data, - size_t public_key_data_size, - size_t *public_key_data_length); - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_INITIAL_ATTESTATION_IMPL_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/.mbedignore b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/.mbedignore deleted file mode 100644 index ab1cfb4..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/.mbedignore +++ /dev/null @@ -1 +0,0 @@ -test/* diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/CMakeLists.txt b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/CMakeLists.txt deleted file mode 100644 index 060462a..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/CMakeLists.txt +++ /dev/null @@ -1,41 +0,0 @@ -#------------------------------------------------------------------------------- -# Copyright (c) 2019, Arm Limited. All rights reserved. -# -# SPDX-License-Identifier: BSD-3-Clause -# -#------------------------------------------------------------------------------- - -cmake_minimum_required(VERSION 3.7) - -#Tell cmake where our modules can be found -list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/../../../cmake) - -#Include common stuff to control cmake. -include("Common/BuildSys") - -#Start an embedded project. -embedded_project_start(CONFIG "${CMAKE_CURRENT_LIST_DIR}/../../../ConfigDefault.cmake") -project(tfm_qcbor LANGUAGES C) -embedded_project_fixup() - -#Some project global settings -set (QCBOR_DIR "${CMAKE_CURRENT_LIST_DIR}") - -#Append all our source files to global lists. -list(APPEND ALL_SRC_C - "${QCBOR_DIR}/src/ieee754.c" - "${QCBOR_DIR}/src/qcbor_decode.c" - "${QCBOR_DIR}/src/qcbor_encode.c" - "${QCBOR_DIR}/src/UsefulBuf.c" - ) - -#Setting include directories -embedded_include_directories(PATH ${QCBOR_DIR}/inc ABSOLUTE) - -#Specify what we build (for the QCBOR, build as an object library) -add_library(${PROJECT_NAME} OBJECT ${ALL_SRC_C}) - -#Set common compiler flags -config_setting_shared_compiler_flags(${PROJECT_NAME}) - -embedded_project_end(${PROJECT_NAME}) diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/README.md b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/README.md deleted file mode 100644 index 58a7080..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/README.md +++ /dev/null @@ -1,175 +0,0 @@ -# QCBOR - -QCBOR encodes and decodes [RFC 7049](https://tools.ietf.org/html/rfc7049) CBOR. - -## Characteristics - -**Implemented in C with minimal dependency** – Only dependencies are - C99, , , and making it - highly portable. There are no #ifdefs to be configured at all. - -**Focused on C / native data representation** – Simpler code because - there is no support for encoding/decoding to/from JSON, pretty - printing, diagnostic notation... Only encoding from native C - representations and decoding to native C representations is supported. - -**Small simple memory model** – Malloc is not needed. The encode - context is 136 bytes, decode context is 104 bytes and the - description of decoded data item is 56 bytes. Stack use is light and - there is no recursion. The caller supplies the memory to hold the - encoded CBOR and encode/decode contexts so caller has full control - of memory usage making it good for embedded implementations that - have to run in small fixed memory. - -**Supports nearly all of RFC 7049** – Only minor, corner-case parts of - RFC 7049 are not directly supported (canonicalization, decimal - fractions, big floats). Decoding indefinite length strings is supported, - but requires a string allocator (see documentation). Encoding indefinite - length strings is not supported, but is also not necessary or - preferred. - -**Extensible and general** – Provides a way to handle data types that - are not directly supported. - -**Secure coding style** – Uses a construct called UsefulBuf as a - discipline for very safe coding the handling of binary data. - -**Small code size** – When optimized for size using the compiler -Os - option, x86 code is about 4KB (~1.1KB encode, ~2.5KB decode, - ~0.4KB common). Other decoders may be smaller, but they may - also do less for you, so overall size of the implementation may - be larger. For example, QCBOR internally tracks error status - so you don't have to check a return code on every operation. - -**Clear documented public interface** – The public interface is - separated from the implementation. It can be put to use without - reading the source. - -**Comprehensive test suite** – Easy to verify on a new platform - or OS with the test suite. The test suite dependencies are also - minimal, only additionally requiring for floating point - tests. - -## Code Status - -QCBOR was originally developed by Qualcomm. It was [open sourced -through CAF](https://source.codeaurora.org/quic/QCBOR/QCBOR/) with a -permissive Linux license, September 2018 (thanks Qualcomm!). - -This code in [Laurence's -GitHub](https://github.com/laurencelundblade/QCBOR) has diverged from -the CAF source with some small simplifications and tidying up. - -From Nov 3, 2018, the interface and code are fairly stable. Large -changes are not planned or expected, particularly in the -interface. The test coverage is pretty good. - -## Building - -There is a simple makefile for the UNIX style command line binary that -compiles everything to run the tests. - -These seven files, the contents of the src and inc directories, make -up the entire implementation. - -* inc - * UsefulBuf.h - * qcbor.h -* src - * UsefulBuf.c - * qcbor_encode.c - * qcbor_decode.c - * ieee754.h - * ieee754.c - -For most use cases you should just be able to add them to your -project. Hopefully the easy portability of this implementation makes -this work straight away, whatever your development environment is. - -The files ieee754.c and ieee754.h are support for half-precision -floating point. The encoding side of the floating point functionality -is about 500 bytes. If it is never called because no floating point -numbers are ever encoded, all 500 bytes will be dead stripped and not -impact code size. The decoding side is about 150 bytes of object -code. It is never dead stripped because it directly referenced by the -core decoder, however it doesn't add very much to the size. - -The test directory includes some tests that are nearly as portable as -the main implementation. If your development environment doesn't -support UNIX style command line and make, you should be able to make a -simple project and add the test files to it. Then just call -RunTests() to invoke them all. - - -## Changes from CAF Version -* Float support is restored -* Minimal length float encoding is added -* indefinite length arrays/maps are supported -* indefinite length strings are supported -* Tag decoding is changed; unlimited number of tags supported, any tag -value supported, tag utility function for easier tag checking -* Addition functions in UsefulBuf -* QCBOREncode_Init takes a UsefulBuf instead of a pointer and size -* QCBOREncode_Finish takes a UsefulBufC and EncodedCBOR is remove -* bstr wrapping of arrays/maps is replaced with OpenBstrwrap -* AddRaw renamed to AddEncoded and can now only add whole arrays or maps, -not partial maps and arrays (simplification; was a dangerous feature) -* Finish cannot be called repeatedly on a partial decode (some tests used -this, but it is not really a good thing to use in the first place) -* UsefulOutBuf_OutUBuf changed to work differently -* UsefulOutBuf_Init works differently -* The "_3" functions are replaced with a small number of simpler functions -* There is a new AddTag functon instead of the "_3" functions, making -the interface simpler and saving some code -* QCBOREncode_AddRawSimple_2 is removed (the macros that referenced -still exist and work the same) - -## Credits -* Ganesh Kanike for porting to QSEE -* Mark Bapst for sponsorship and release as open source by Qualcomm -* Sachin Sharma for release through CAF -* Tamas Ban for porting to TF-M and 32-bit ARM - -## Copyright and License - -QCBOR is available under what is essentially the 3-Clause BSD License. - -Files created inside Qualcomm and open-sourced through CAF (The Code -Aurora Forum) have a slightly modified 3-Clause BSD License. The -modification additionally disclaims NON-INFRINGEMENT. - -Files created after release to CAF use the standard 3-Clause BSD -License with no modification. These files have the SPDX license -identifier, "SPDX-License-Identifier: BSD-3-Clause" in them. - -### BSD-3-Clause license - -* Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. - -* Neither the name of the copyright holder nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -### Copyright for this README - -Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. - - - diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/inc/UsefulBuf.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/inc/UsefulBuf.h deleted file mode 100644 index fa17b6c..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/inc/UsefulBuf.h +++ /dev/null @@ -1,1536 +0,0 @@ -/*============================================================================== - Copyright (c) 2016-2018, The Linux Foundation. - Copyright (c) 2018-2019, Laurence Lundblade. - All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of The Linux Foundation nor the names of its - contributors, nor the name "Laurence Lundblade" may be used to - endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS -BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ==============================================================================*/ - -/*=================================================================================== - FILE: UsefulBuf.h - - DESCRIPTION: General purpose input and output buffers - - EDIT HISTORY FOR FILE: - - This section contains comments describing changes made to the module. - Notice that changes are listed in reverse chronological order. - - when who what, where, why - -------- ---- --------------------------------------------------- - 12/17/2018 llundblade Remove const from UsefulBuf and UsefulBufC .len - 12/13/2018 llundblade Documentation improvements - 09/18/2018 llundblade Cleaner distinction between UsefulBuf and UsefulBufC - 02/02/18 llundbla Full support for integers in and out; fix pointer - alignment bug. Incompatible change: integers in/out - are now in network byte order. - 08/12/17 llundbla Added UsefulOutBuf_AtStart and UsefulBuf_Find - 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected comparison - for < or > for unequal length buffers. Added - UsefulBuf_Set() function. - 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst - 11/13/16 llundbla Initial Version. - - - =====================================================================================*/ - -#ifndef _UsefulBuf_h -#define _UsefulBuf_h - - -#include // for uint8_t, uint16_t.... -#include // for strlen, memcpy, memmove, memset -#include // for size_t - -/** - @file UsefulBuf.h - - The goal of this code is to make buffer and pointer manipulation - easier and safer when working with binary data. - - You use the UsefulBuf, UsefulOutBuf and UsefulInputBuf - structures to represent buffers rather than ad hoc pointers and lengths. - - With these it will often be possible to write code that does little or no - direct pointer manipulation for copying and formatting data. For example - the QCBOR encoder was rewritten using these and has no direct pointer - manipulation. - - While it is true that object code using these functions will be a little - larger and slower than a white-knuckle clever use of pointers might be, but - not by that much or enough to have an affect for most use cases. For - security-oriented code this is highly worthwhile. Clarity, simplicity, - reviewability and are more important. - - There are some extra sanity and double checks in this code to help catch - coding errors and simple memory corruption. They are helpful, but not a - substitute for proper code review, input validation and such. - - This code consists of a lot of inline functions and a few that are not. - It should not generate very much object code, especially with the - optimizer turned up to -Os or -O3. The idea is that the inline - functions are easier to review and understand and the optimizer does - the work of making the code small. - */ - - -/*...... This is a ruler that is 80 characters long...........................*/ - -/** - UsefulBufC and UsefulBuf are simple data structures to hold a pointer and - length for a binary data. In C99 this data structure can be passed on the - stack making a lot of code cleaner than carrying around a pointer and - length as two parameters. - - This is also conducive to secure code practice as the lengths are - always carried with the pointer and the convention for handling a - pointer and a length is clear. - - While it might be possible to write buffer and pointer code more - efficiently in some use cases, the thought is that unless there is an - extreme need for performance (e.g., you are building a gigabit-per-second - IP router), it is probably better to have cleaner code you can be most - certain about the security of. - - The non-const UsefulBuf is usually used to refer a buffer to be filled in. - The length is the size of the buffer. - - The const UsefulBufC is usually used to refer to some data that has been - filled in. The length is amount of valid data pointed to. - - A common use is to pass a UsefulBuf to a function, the function fills it - in, the function returns a UsefulBufC. The pointer is the same in both. - - A UsefulBuf is NULL, it has no value, when the ptr in it is NULL. - - There are utility functions for the following: - - Checking for UsefulBufs that are NULL, empty or both - - Copying, copying with offset, copying head or tail - - Comparing and finding substrings - - Initializating - - Create initialized const UsefulBufC from compiler literals - - Create initialized const UsefulBufC from NULL-terminated string - - Make an empty UsefulBuf on the stack - - See also UsefulOutBuf. It is a richer structure that has both the size of - the valid data and the size of the buffer. - - UsefulBuf is only 16 or 8 bytes on a 64- or 32-bit machine so it can go - on the stack and be a function parameter or return value. - - UsefulBuf is kind of like the Useful Pot Pooh gave Eeyore on his birthday. - Eeyore's balloon fits beautifully, "it goes in and out like anything". - -*/ -typedef struct useful_buf_c { - const void *ptr; - size_t len; -} UsefulBufC; - - -/** - The non-const UsefulBuf typically used for some allocated memory - that is to be filled in. The len is the amount of memory, - not the length of the valid data in the buffer. - */ -typedef struct useful_buf { - void *ptr; - size_t len; -} UsefulBuf; - - -/** - A "NULL" UsefulBufC is one that has no value in the same way a NULL pointer has no value. - A UsefulBuf is NULL when the ptr field is NULL. It doesn't matter what len is. - See UsefulBuf_IsEmpty() for the distinction between NULL and empty. - */ -#define NULLUsefulBufC ((UsefulBufC) {NULL, 0}) - -/** A NULL UsefulBuf is one that has no memory associated the say way - NULL points to nothing. It does not matter what len is. - */ -#define NULLUsefulBuf ((UsefulBuf) {NULL, 0}) - - -/** - @brief Check if a UsefulBuf is NULL or not - - @param[in] UB The UsefulBuf to check - - @return 1 if it is NULL, 0 if not. - */ -static inline int UsefulBuf_IsNULL(UsefulBuf UB) { - return !UB.ptr; -} - - -/** - @brief Check if a UsefulBufC is NULL or not - - @param[in] UB The UsefulBufC to check - - @return 1 if it is NULL, 0 if not. - */ -static inline int UsefulBuf_IsNULLC(UsefulBufC UB) { - return !UB.ptr; -} - - -/** - @brief Check if a UsefulBuf is empty or not - - @param[in] UB The UsefulBuf to check - - @return 1 if it is empty, 0 if not. - - An "Empty" UsefulBuf is one that has a value and can be considered to be set, - but that value is of zero length. It is empty when len is zero. It - doesn't matter what the ptr is. - - A lot of uses will not need to clearly distinguish a NULL UsefulBuf - from an empty one and can have the ptr NULL and the len 0. However - if a use of UsefulBuf needs to make a distinction then ptr should - not be NULL when the UsefulBuf is considered empty, but not NULL. - - */ -static inline int UsefulBuf_IsEmpty(UsefulBuf UB) { - return !UB.len; -} - - -/** - @brief Check if a UsefulBufC is empty or not - - @param[in] UB The UsefulBufC to check - - @return 1 if it is empty, 0 if not. - */ -static inline int UsefulBuf_IsEmptyC(UsefulBufC UB) { - return !UB.len; -} - - -/** - @brief Check if a UsefulBuf is NULL or empty - - @param[in] UB The UsefulBuf to check - - @return 1 if it is either NULL or empty, 0 if not. - */ -static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB) { - return UsefulBuf_IsEmpty(UB) || UsefulBuf_IsNULL(UB); -} - - -/** - @brief Check if a UsefulBufC is NULL or empty - - @param[in] UB The UsefulBufC to check - - @return 1 if it is either NULL or empty, 0 if not. - */ -static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB) { - return UsefulBuf_IsEmptyC(UB) || UsefulBuf_IsNULLC(UB); -} - - -/** - @brief Convert a non const UsefulBuf to a const UsefulBufC - - @param[in] UB The UsefulBuf to convert - - Returns: a UsefulBufC struct - */ - -static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB) -{ - return (UsefulBufC){UB.ptr, UB.len}; -} - - -/** - @brief Convert a const UsefulBufC to a non-const UsefulBuf - - @param[in] UBC The UsefulBuf to convert - - Returns: a non const UsefulBuf struct - */ -static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC) -{ - return (UsefulBuf){(void *)UBC.ptr, UBC.len}; -} - - -/** - Convert a literal string to a UsefulBufC. - - szString must be a literal string that you can take sizeof. - This is better for literal strings than UsefulBuf_FromSZ() - because it generates less code. It will not work on - non-literal strings. - - The terminating \0 (NULL) is NOT included in the length! - - */ -#define UsefulBuf_FROM_SZ_LITERAL(szString) \ - ((UsefulBufC) {(szString), sizeof(szString)-1}) - - -/** - Convert a literal byte array to a UsefulBufC. - - pBytes must be a literal string that you can take sizeof. - It will not work on non-literal arrays. - - */ -#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) \ - ((UsefulBufC) {(pBytes), sizeof(pBytes)}) - - -/** - Make an automatic variable with name of type UsefulBuf and point it to a stack - variable of the give size - */ -#define UsefulBuf_MAKE_STACK_UB(name, size) \ - uint8_t __pBuf##name[(size)];\ - UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )} - - -/** - Make a byte array in to a UsefulBuf - */ -#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) \ - ((UsefulBuf) {(pBytes), sizeof(pBytes)}) - -/** - @brief Convert a NULL terminated string to a UsefulBufC. - - @param[in] szString The string to convert - - @return a UsefulBufC struct - - UsefulBufC.ptr points to the string so it's lifetime - must be maintained. - - The terminating \0 (NULL) is NOT included in the length! - - */ -static inline UsefulBufC UsefulBuf_FromSZ(const char *szString){ - return ((UsefulBufC) {szString, strlen(szString)}); -} - - -/** - @brief Copy one UsefulBuf into another at an offset - - @param[in] Dest Destiation buffer to copy into - @param[in] uOffset The byte offset in Dest at which to copy to - @param[in] Src The bytes to copy - - @return Pointer and length of the copy - - This fails and returns NULLUsefulBufC Src.len + uOffset > Dest.len. - - Like memcpy, there is no check for NULL. If NULL is passed - this will crash. - - There is an assumption that there is valid data in Dest up to - uOffset as the resulting UsefulBufC returned starts - at the beginning of Dest and goes to Src.len + uOffset. - - */ -UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src); - - -/** - @brief Copy one UsefulBuf into another - - @param[in] Dest The destination buffer to copy into - @param[out] Src The source to copy from - - @return filled in UsefulBufC on success, NULLUsefulBufC on failure - - This fails if Src.len is greater than Dest.len. - - Note that like memcpy, the pointers are not checked and - this will crash, rather than return NULLUsefulBufC if - they are NULL or invalid. - - Results are undefined if Dest and Src overlap. - - */ -static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src) { - return UsefulBuf_CopyOffset(Dest, 0, Src); -} - - -/** - @brief Set all bytes in a UsefulBuf to a value, for example 0 - - @param[in] pDest The destination buffer to copy into - @param[in] value The value to set the bytes to - - Note that like memset, the pointer in pDest is not checked and - this will crash if NULL or invalid. - - */ -static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value) -{ - memset(pDest.ptr, value, pDest.len); - return (UsefulBufC){pDest.ptr, pDest.len}; -} - - -/** - @brief Copy a pointer into a UsefulBuf - - @param[in,out] Dest The destination buffer to copy into - @param[in] ptr The source to copy from - @param[in] len Length of the source; amoutn to copy - - @return 0 on success, 1 on failure - - This fails and returns NULLUsefulBufC if len is greater than - pDest->len. - - Note that like memcpy, the pointers are not checked and - this will crash, rather than return 1 if they are NULL - or invalid. - - */ -inline static UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest, const void *ptr, size_t len) -{ - return UsefulBuf_Copy(Dest, (UsefulBufC){ptr, len}); -} - - -/** - @brief Returns a truncation of a UsefulBufC - - @param[in] UB The buffer to get the head of - @param[in] uAmount The number of bytes in the head - - @return A UsefulBufC that is the head of UB - - */ -static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount) -{ - if(uAmount > UB.len) { - return NULLUsefulBufC; - } - return (UsefulBufC){UB.ptr, uAmount}; -} - - -/** - @brief Returns bytes from the end of a UsefulBufC - - @param[in] UB The buffer to get the tail of - @param[in] uAmount The offset from the start where the tail is to begin - - @return A UsefulBufC that is the tail of UB or NULLUsefulBufC if - uAmount is greater than the length of the UsefulBufC - - If the input UsefulBufC is NULL, but the len is not, then the - length of the tail will be calculated and returned along - with a NULL ptr. - */ -static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount) -{ - UsefulBufC ReturnValue; - - if(uAmount > UB.len) { - ReturnValue = NULLUsefulBufC; - } else if(UB.ptr == NULL) { - ReturnValue = (UsefulBufC){NULL, UB.len - uAmount}; - } else { - ReturnValue = (UsefulBufC){(uint8_t *)UB.ptr + uAmount, UB.len - uAmount}; - } - - return ReturnValue; -} - - -/** - @brief Compare two UsefulBufCs - - @param[in] UB1 The destination buffer to copy into - @param[in] UB2 The source to copy from - - @return 0 if equal... - - Returns a negative value if UB1 if is less than UB2. UB1 is - less than UB2 if it is shorter or the first byte that is not - the same is less. - - Returns 0 if the UsefulBufs are the same. - - Returns a positive value if UB2 is less than UB1. - - All that is of significance is that the result is positive, - negative or 0. (This doesn't return the difference between - the first non-matching byte like memcmp). - - */ -int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2); - - -/** - @brief Find one UsefulBuf in another - - @param[in] BytesToSearch UsefulBuf to search through - @param[in] BytesToFind UsefulBuf with bytes to be found - - @return position of found bytes or SIZE_MAX if not found. - - */ -size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind); - - - - -#if 0 // NOT_DEPRECATED -/** Deprecated macro; use UsefulBuf_FROM_SZ_LITERAL instead */ -#define SZLiteralToUsefulBufC(szString) \ - ((UsefulBufC) {(szString), sizeof(szString)-1}) - -/** Deprecated macro; use UsefulBuf_MAKE_STACK_UB instead */ -#define MakeUsefulBufOnStack(name, size) \ - uint8_t __pBuf##name[(size)];\ - UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )} - -/** Deprecated macro; use UsefulBuf_FROM_BYTE_ARRAY_LITERAL instead */ -#define ByteArrayLiteralToUsefulBufC(pBytes) \ - ((UsefulBufC) {(pBytes), sizeof(pBytes)}) - -/** Deprecated function; use UsefulBuf_Unconst() instead */ -static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC) -{ - return (UsefulBuf){(void *)UBC.ptr, UBC.len}; -} -#endif - - - -/* - Convenient functions to avoid type punning, compiler warnings and such - The optimizer reduces them to a simple assignment - This is a crusty corner of C. It shouldn't be this hard. - */ -static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f) -{ - uint32_t u32; - memcpy(&u32, &f, sizeof(uint32_t)); - return u32; -} - -static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d) -{ - uint64_t u64; - memcpy(&u64, &d, sizeof(uint64_t)); - return u64; -} - -static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64) -{ - double d; - memcpy(&d, &u64, sizeof(uint64_t)); - return d; -} - -static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32) -{ - float f; - memcpy(&f, &u32, sizeof(uint32_t)); - return f; -} - - - - - -/** - UsefulOutBuf is a structure and functions (an object) that are good - for serializing data into a buffer such as is often done with network - protocols or data written to files. - - The main idea is that all the pointer manipulation for adding data is - done by UsefulOutBuf functions so the caller doesn't have to do any. - All the pointer manipulation is centralized here. This code will - have been reviewed and written carefully so it spares the caller of - much of this work and results in much safer code with much less work. - - The functions to add data to the output buffer always check the - length and will never write off the end of the output buffer. If an - attempt to add data that will not fit is made, an internal error flag - will be set and further attempts to add data will not do anything. - - Basically, if you initialized with the correct buffer, there is no - way to ever write off the end of that buffer when calling the Add - and Insert functions here. - - The functions to add data do not return an error. The working model - is that the caller just makes all the calls to add data without any - error checking on each one. The error is instead checked after all the - data is added when the result is to be used. This makes the caller's - code cleaner. - - There is a utility function to get the error status anytime along the - way if the caller wants. There are functions to see how much room is - left and see if some data will fit too, but their use is generally - not necessary. - - The general call flow is like this: - - - Initialize the UsefulOutBuf with the buffer that is to have the - data added. The caller allocates the buffer. It can be heap - or stack or shared memory (or other). - - - Make calls to add data to the output buffer. Insert and append - are both supported. The append and insert calls will never write - off the end of the buffer. - - - When all data is added, check the error status to make sure - everything fit. - - - Get the resulting serialized data either as a UsefulBuf (a - pointer and length) or have it copied to another buffer. - - UsefulOutBuf can be initialized with just a buffer length by passing - NULL as the pointer to the output buffer. This is useful if you want - to go through the whole serialization process to either see if it - will fit into a given buffer or compute the size of the buffer - needed. Pass a very large buffer size when calling Init, if you want - just to compute the size. - - Some inexpensive simple sanity checks are performed before every data - addition to guard against use of an uninitialized or corrupted - UsefulOutBuf. - - This has been used to create a CBOR encoder. The CBOR encoder has - almost no pointer manipulation in it, is much easier to read, and - easier to review. - - A UsefulOutBuf is 27 bytes or 15 bytes on 64- or 32-bit machines so it - can go on the stack or be a C99 function parameter. - */ - -typedef struct useful_out_buf { - UsefulBuf UB; // Memory that is being output to - size_t data_len; // length of the data - uint16_t magic; // Used to detect corruption and lack of initialization - uint8_t err; -} UsefulOutBuf; - - -/** - @brief Initialize and supply the actual output buffer - - @param[out] me The UsefulOutBuf to initialize - @param[in] Storage Buffer to output into - - Intializes the UsefulOutBuf with storage. Sets the current position - to the beginning of the buffer clears the error. - - This must be called before the UsefulOutBuf is used. - */ -void UsefulOutBuf_Init(UsefulOutBuf *me, UsefulBuf Storage); - - - - -/** Convenience marco to make a UsefulOutBuf on the stack and - initialize it with stack buffer - */ -#define UsefulOutBuf_MakeOnStack(name, size) \ - uint8_t __pBuf##name[(size)];\ - UsefulOutBuf name;\ - UsefulOutBuf_Init(&(name), (UsefulBuf){__pBuf##name, (size)}); - - - -/** - @brief Reset a UsefulOutBuf for re use - - @param[in] me Pointer to the UsefulOutBuf - - This sets the amount of data in the output buffer to none and - clears the error state. - - The output buffer is still the same one and size as from the - UsefulOutBuf_Init() call. - - It doesn't zero the data, just resets to 0 bytes of valid data. - */ -static inline void UsefulOutBuf_Reset(UsefulOutBuf *me) -{ - me->data_len = 0; - me->err = 0; -} - - -/** - @brief Returns position of end of data in the UsefulOutBuf - - @param[in] me Pointer to the UsefulOutBuf - - @return position of end of data - - On a freshly initialized UsefulOutBuf with no data added, this will - return 0. After ten bytes have been added, it will return 10 and so - on. - - Generally callers will not need this function for most uses of - UsefulOutBuf. - - */ -static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *me) -{ - return me->data_len; -} - - -/** - @brief Returns whether any data has been added to the UsefulOutBuf - - @param[in] me Pointer to the UsefulOutBuf - - @return 1 if output position is at start - - */ -static inline int UsefulOutBuf_AtStart(UsefulOutBuf *me) -{ - return 0 == me->data_len; -} - - -/** - @brief Inserts bytes into the UsefulOutBuf - - @param[in] me Pointer to the UsefulOutBuf - @param[in] NewData UsefulBuf with the bytes to insert - @param[in] uPos Index in output buffer at which to insert - - NewData is the pointer and length for the bytes to be added to the - output buffer. There must be room in the output buffer for all of - NewData or an error will occur. - - The insertion point must be between 0 and the current valid data. If - not an error will occur. Appending data to the output buffer is - achieved by inserting at the end of the valid data. This can be - retrieved by calling UsefulOutBuf_GetEndPosition(). - - When insertion is performed, the bytes between the insertion point and - the end of data previously added to the output buffer is slid to the - right to make room for the new data. - - Overlapping buffers are OK. NewData can point to data in the output - buffer. - - If an error occurs an error state is set in the UsefulOutBuf. No - error is returned. All subsequent attempts to add data will do - nothing. - - Call UsefulOutBuf_GetError() to find out if there is an error. This - is usually not needed until all additions of data are complete. - - */ -void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *me, UsefulBufC NewData, size_t uPos); - - -/** - @brief Insert a data buffer into the UsefulOutBuf - - @param[in] me Pointer to the UsefulOutBul - @param[in] pBytes Pointer to the bytes to insert - @param[in] uLen Length of the bytes to insert - @param[in] uPos Index in output buffer at which to insert - - See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with - the difference being a pointer and length is passed in rather than an - UsefulBuf. - - */ -static inline void UsefulOutBuf_InsertData(UsefulOutBuf *me, const void *pBytes, size_t uLen, size_t uPos) -{ - UsefulBufC Data = {pBytes, uLen}; - UsefulOutBuf_InsertUsefulBuf(me, Data, uPos); -} - - -/** - @brief Insert a NULL-terminated string into the UsefulOutBuf - - @param[in] me Pointer to the UsefulOutBuf - @param[in] szString string to append - - */ -static inline void UsefulOutBuf_InsertString(UsefulOutBuf *me, const char *szString, size_t uPos) -{ - UsefulOutBuf_InsertUsefulBuf(me, (UsefulBufC){szString, strlen(szString)}, uPos); -} - - -/** - @brief Insert a byte into the UsefulOutBuf - - @param[in] me Pointer to the UsefulOutBul - @param[in] byte Bytes to insert - @param[in] uPos Index in output buffer at which to insert - - See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with - the difference being a single byte is to be inserted. - */ -static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *me, uint8_t byte, size_t uPos) -{ - UsefulOutBuf_InsertData(me, &byte, 1, uPos); -} - - -/** - @brief Insert a 16-bit integer into the UsefulOutBuf - - @param[in] me Pointer to the UsefulOutBul - @param[in] uInteger16 Integer to insert - @param[in] uPos Index in output buffer at which to insert - - See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with - the difference being a single byte is to be inserted. - - The integer will be inserted in network byte order (big endian) - */ -static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *me, uint16_t uInteger16, size_t uPos) -{ - // Converts native integer format to network byte order (big endian) - uint8_t tmp[2]; - tmp[0] = (uInteger16 & 0xff00) >> 8; - tmp[1] = (uInteger16 & 0xff); - UsefulOutBuf_InsertData(me, tmp, 2, uPos); -} - - -/** - @brief Insert a 32-bit integer into the UsefulOutBuf - - @param[in] me Pointer to the UsefulOutBul - @param[in] uInteger32 Integer to insert - @param[in] uPos Index in output buffer at which to insert - - See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with - the difference being a single byte is to be inserted. - - The integer will be inserted in network byte order (big endian) - */ -static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *me, uint32_t uInteger32, size_t uPos) -{ - // Converts native integer format to network byte order (big endian) - uint8_t tmp[4]; - tmp[0] = (uInteger32 & 0xff000000) >> 24; - tmp[1] = (uInteger32 & 0xff0000) >> 16; - tmp[2] = (uInteger32 & 0xff00) >> 8; - tmp[3] = (uInteger32 & 0xff); - UsefulOutBuf_InsertData(me, tmp, 4, uPos); -} - - -/** - @brief Insert a 64-bit integer into the UsefulOutBuf - - @param[in] me Pointer to the UsefulOutBul - @param[in] uInteger64 Integer to insert - @param[in] uPos Index in output buffer at which to insert - - See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with - the difference being a single byte is to be inserted. - - The integer will be inserted in network byte order (big endian) - */ -static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *me, uint64_t uInteger64, size_t uPos) -{ - // Converts native integer format to network byte order (big endian) - uint8_t tmp[8]; - tmp[0] = (uInteger64 & 0xff00000000000000) >> 56; - tmp[1] = (uInteger64 & 0xff000000000000) >> 48; - tmp[2] = (uInteger64 & 0xff0000000000) >> 40; - tmp[3] = (uInteger64 & 0xff00000000) >> 32; - tmp[4] = (uInteger64 & 0xff000000) >> 24; - tmp[5] = (uInteger64 & 0xff0000) >> 16; - tmp[6] = (uInteger64 & 0xff00) >> 8; - tmp[7] = (uInteger64 & 0xff); - UsefulOutBuf_InsertData(me, tmp, 8, uPos); -} - - -/** - @brief Insert a float into the UsefulOutBuf - - @param[in] me Pointer to the UsefulOutBul - @param[in] f Integer to insert - @param[in] uPos Index in output buffer at which to insert - - See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with - the difference being a single byte is to be inserted. - - The float will be inserted in network byte order (big endian) - */ -static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *me, float f, size_t uPos) -{ - UsefulOutBuf_InsertUint32(me, UsefulBufUtil_CopyFloatToUint32(f), uPos); -} - - -/** - @brief Insert a double into the UsefulOutBuf - - @param[in] me Pointer to the UsefulOutBul - @param[in] d Integer to insert - @param[in] uPos Index in output buffer at which to insert - - See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with - the difference being a single byte is to be inserted. - - The double will be inserted in network byte order (big endian) - */ -static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *me, double d, size_t uPos) -{ - UsefulOutBuf_InsertUint64(me, UsefulBufUtil_CopyDoubleToUint64(d), uPos); -} - - - -/** - Append a UsefulBuf into the UsefulOutBuf - - @param[in] me Pointer to the UsefulOutBuf - @param[in] NewData UsefulBuf with the bytes to append - - See UsefulOutBuf_InsertUsefulBuf() for details. This does the same - with the insertion point at the end of the valid data. - -*/ -static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *me, UsefulBufC NewData) -{ - // An append is just a insert at the end - UsefulOutBuf_InsertUsefulBuf(me, NewData, UsefulOutBuf_GetEndPosition(me)); -} - - -/** - Append bytes to the UsefulOutBuf - - @param[in] me Pointer to the UsefulOutBuf - @param[in] pBytes Pointer to bytes to append - @param[in] uLen Index in output buffer at which to append - - See UsefulOutBuf_InsertUsefulBuf() for details. This does the same - with the insertion point at the end of the valid data. - */ - -static inline void UsefulOutBuf_AppendData(UsefulOutBuf *me, const void *pBytes, size_t uLen) -{ - UsefulBufC Data = {pBytes, uLen}; - UsefulOutBuf_AppendUsefulBuf(me, Data); -} - - -/** - Append a NULL-terminated string to the UsefulOutBuf - - @param[in] me Pointer to the UsefulOutBuf - @param[in] szString string to append - - */ -static inline void UsefulOutBuf_AppendString(UsefulOutBuf *me, const char *szString) -{ - UsefulOutBuf_AppendUsefulBuf(me, (UsefulBufC){szString, strlen(szString)}); -} - - -/** - @brief Append a byte to the UsefulOutBuf - - @param[in] me Pointer to the UsefulOutBuf - @param[in] byte Bytes to append - - See UsefulOutBuf_InsertUsefulBuf() for details. This does the same - with the insertion point at the end of the valid data. - */ -static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *me, uint8_t byte) -{ - UsefulOutBuf_AppendData(me, &byte, 1); -} - -/** - @brief Append an integer to the UsefulOutBuf - - @param[in] me Pointer to the UsefulOutBuf - @param[in] uInteger16 Integer to append - - See UsefulOutBuf_InsertUsefulBuf() for details. This does the same - with the insertion point at the end of the valid data. - - The integer will be appended in network byte order (big endian). - */ -static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *me, uint16_t uInteger16){ - UsefulOutBuf_InsertUint16(me, uInteger16, UsefulOutBuf_GetEndPosition(me)); -} - -/** - @brief Append an integer to the UsefulOutBuf - - @param[in] me Pointer to the UsefulOutBuf - @param[in] uInteger32 Integer to append - - See UsefulOutBuf_InsertUsefulBuf() for details. This does the same - with the insertion point at the end of the valid data. - - The integer will be appended in network byte order (big endian). - */ -static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *me, uint32_t uInteger32){ - UsefulOutBuf_InsertUint32(me, uInteger32, UsefulOutBuf_GetEndPosition(me)); -} - -/** - @brief Append an integer to the UsefulOutBuf - - @param[in] me Pointer to the UsefulOutBuf - @param[in] uInteger64 Integer to append - - See UsefulOutBuf_InsertUsefulBuf() for details. This does the same - with the insertion point at the end of the valid data. - - The integer will be appended in network byte order (big endian). - */ -static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *me, uint64_t uInteger64){ - UsefulOutBuf_InsertUint64(me, uInteger64, UsefulOutBuf_GetEndPosition(me)); -} - - -/** - @brief Append a float to the UsefulOutBuf - - @param[in] me Pointer to the UsefulOutBuf - @param[in] f Float to append - - See UsefulOutBuf_InsertUsefulBuf() for details. This does the same - with the insertion point at the end of the valid data. - - The float will be appended in network byte order (big endian). - */ -static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *me, float f){ - UsefulOutBuf_InsertFloat(me, f, UsefulOutBuf_GetEndPosition(me)); -} - -/** - @brief Append a float to the UsefulOutBuf - - @param[in] me Pointer to the UsefulOutBuf - @param[in] d Double to append - - See UsefulOutBuf_InsertUsefulBuf() for details. This does the same - with the insertion point at the end of the valid data. - - The double will be appended in network byte order (big endian). - */ -static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *me, double d){ - UsefulOutBuf_InsertDouble(me, d, UsefulOutBuf_GetEndPosition(me)); -} - -/** - @brief Returns the current error status - - @param[in] me Pointer to the UsefulOutBuf - - @return 0 if all OK, 1 on error - - This is the error status since the call to either - UsefulOutBuf_Reset() of UsefulOutBuf_Init(). Once it goes into error - state it will stay until one of those functions is called. - - Possible error conditions are: - - bytes to be inserted will not fit - - insertion point is out of buffer or past valid data - - current position is off end of buffer (probably corruption or uninitialized) - - detect corruption / uninitialized by bad magic number - */ - -static inline int UsefulOutBuf_GetError(UsefulOutBuf *me) -{ - return me->err; -} - - -/** - @brief Returns number of bytes unused used in the output buffer - - @param[in] me Pointer to the UsefulOutBuf - - @return Number of unused bytes or zero - - Because of the error handling strategy and checks in UsefulOutBuf_InsertUsefulBuf() - it is usually not necessary to use this. - */ - -static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *me) -{ - return me->UB.len - me->data_len; -} - - -/** - @brief Returns true / false if some number of bytes will fit in the UsefulOutBuf - - @param[in] me Pointer to the UsefulOutBuf - @param[in] uLen Number of bytes for which to check - - @return 1 or 0 if nLen bytes would fit - - Because of the error handling strategy and checks in UsefulOutBuf_InsertUsefulBuf() - it is usually not necessary to use this. - */ - -static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *me, size_t uLen) -{ - return uLen <= UsefulOutBuf_RoomLeft(me); -} - - -/** - @brief Returns the resulting valid data in a UsefulOutBuf - - @param[in] me Pointer to the UsefulOutBuf. - - @return The valid data in UsefulOutBuf. - - The storage for the returned data is Storage parameter passed - to UsefulOutBuf_Init(). See also UsefulOutBuf_CopyOut(). - - This can be called anytime and many times to get intermediate - results. It doesn't change the data or reset the current position - so you can keep adding data. - */ - -UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *me); - - -/** - @brief Copies the valid data out into a supplied buffer - - @param[in] me Pointer to the UsefulOutBuf - @param[out] Dest The destination buffer to copy into - - @return Pointer and length of copied data. - - This is the same as UsefulOutBuf_OutUBuf() except it copies the data. -*/ - -UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *me, UsefulBuf Dest); - - - - - - - - - - - - - -/** - UsefulInputBuf is the counterpart to UsefulOutBuf and is for parsing - data read or received. Initialize it with the data - from the network and its length. Then use the functions - here to get the various data types out of it. It maintains a position - for getting the next item. This means you don't have to track a - pointer as you get each object. UsefulInputBuf does that for you and - makes sure it never goes off the end of the buffer. The QCBOR - implementation parser makes use of this for all its pointer math and - length checking. - - UsefulInputBuf also maintains an internal error state so you do not have - to. Once data has been requested off the end of the buffer, it goes - into an error state. You can keep calling functions to get more data - but they will either return 0 or NULL. As long as you don't - dereference the NULL, you can wait until all data items have been - fetched before checking for the error and this can simplify your - code. - - The integer and float parsing expects network byte order (big endian). - Network byte order is what is used by TCP/IP, CBOR and most internet - protocols. - - Lots of inlining is used to keep code size down. The code optimizer, - particularly with the -Os, also reduces code size a lot. The only - non-inline code is UsefulInputBuf_GetBytes() which is less than 100 - bytes so use of UsefulInputBuf doesn't add much code for all the messy - hard-to-get right issues with parsing in C that is solves. - - The parse context size is: - 64-bit machine: 16 + 8 + 2 + 1 (5 bytes padding to align) = 32 bytes - 32-bit machine: 8 + 4 + 2 + 1 (1 byte padding to align) = 16 bytes - - */ - -#define UIB_MAGIC (0xB00F) - -typedef struct useful_input_buf { - // Private data structure - UsefulBufC UB; // Data being parsed - size_t cursor; // Current offset in data being parse - uint16_t magic; // Check for corrupted or uninitialized UsefulInputBuf - uint8_t err; // Set request goes off end or magic number is bad -} UsefulInputBuf; - - - -/** - @brief Initialize the UsefulInputBuf structure before use. - - @param[in] me Pointer to the UsefulInputBuf instance. - @param[in] UB Pointer to the data to parse. - - */ -static inline void UsefulInputBuf_Init(UsefulInputBuf *me, UsefulBufC UB) -{ - me->cursor = 0; - me->err = 0; - me->magic = UIB_MAGIC; - me->UB = UB; -} - - -/** - @brief Returns current position in input buffer - - @param[in] me Pointer to the UsefulInputBuf. - - @return Integer position of the cursor - - The position that the next bytes will be returned from. - - */ -static inline size_t UsefulInputBuf_Tell(UsefulInputBuf *me) -{ - return me->cursor; -} - - -/** - @brief Sets current position in input buffer - - @param[in] me Pointer to the UsefulInputBuf. - @param[in] uPos Position to set to - - If the position is off the end of the input buffer, the error state - is entered and all functions will do nothing. - - Seeking to a valid position in the buffer will not reset the error - state. Only re initialization will do that. - - */ -static inline void UsefulInputBuf_Seek(UsefulInputBuf *me, size_t uPos) -{ - if(uPos > me->UB.len) { - me->err = 1; - } else { - me->cursor = uPos; - } -} - - -/** - @brief Returns the number of bytes from the cursor to the end of the buffer, - the uncomsummed bytes. - - @param[in] me Pointer to the UsefulInputBuf. - - @return number of bytes unconsumed or 0 on error. - - This is a critical function for input length validation. This does - some pointer / offset math. - - Returns 0 if the cursor it invalid or corruption of the structure is - detected. - - Code Reviewers: THIS FUNCTION DOES POINTER MATH - */ -static inline size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *me) -{ - // Magic number is messed up. Either the structure got overwritten - // or was never initialized. - if(me->magic != UIB_MAGIC) { - return 0; - } - - // The cursor is off the end of the input buffer given - // Presuming there are no bugs in this code, this should never happen. - // If it so, the struct was corrupted. The check is retained as - // as a defense in case there is a bug in this code or the struct is corrupted. - if(me->cursor > me->UB.len) { - return 0; - } - - // subtraction can't go neative because of check above - return me->UB.len - me->cursor; -} - - -/** - @brief Check if there are any unconsumed bytes - - @param[in] me Pointer to the UsefulInputBuf. - - @return 1 if len bytes are available after the cursor, and 0 if not - - */ -static inline int UsefulInputBuf_BytesAvailable(UsefulInputBuf *me, size_t uLen) -{ - return UsefulInputBuf_BytesUnconsumed(me) >= uLen ? 1 : 0; -} - - -/** - @brief Get pointer to bytes out of the input buffer - - @param[in] me Pointer to the UsefulInputBuf. - @param[in] uNum Number of bytes to get - - @return Pointer to bytes. - - This consumes n bytes from the input buffer. It returns a pointer to - the start of the n bytes. - - If there are not n bytes in the input buffer, NULL will be returned - and an error will be set. - - It advances the current position by n bytes. - */ -const void * UsefulInputBuf_GetBytes(UsefulInputBuf *me, size_t uNum); - - -/** - @brief Get UsefulBuf out of the input buffer - - @param[in] me Pointer to the UsefulInputBuf. - @param[in] uNum Number of bytes to get - - @return UsefulBufC with ptr and length for bytes consumed. - - This consumes n bytes from the input buffer and returns the pointer - and len to them as a UsefulBufC. The len returned will always be n. - - If there are not n bytes in the input buffer, UsefulBufC.ptr will be - NULL and UsefulBufC.len will be 0. An error will be set. - - It advances the current position by n bytes. - */ -static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *me, size_t uNum) -{ - const void *pResult = UsefulInputBuf_GetBytes(me, uNum); - if(!pResult) { - return NULLUsefulBufC; - } else { - return (UsefulBufC){pResult, uNum}; - } -} - - -/** - @brief Get a byte out of the input buffer. - - @param[in] me Pointer to the UsefulInputBuf. - - @return The byte - - This consumes 1 byte from the input buffer. It returns the byte. - - If there is not 1 byte in the buffer, 0 will be returned for the byte - and an error set internally. You must check the error at some point - to know whether the 0 was the real value or just returned in error, - but you may not have to do that right away. Check the error state - with UsefulInputBuf_GetError(). You can also know you are in the - error state if UsefulInputBuf_GetBytes() returns NULL or the ptr from - UsefulInputBuf_GetUsefulBuf() is NULL. - - It advances the current position by 1 byte. - */ -static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *me) -{ - const void *pResult = UsefulInputBuf_GetBytes(me, sizeof(uint8_t)); - - return pResult ? *(uint8_t *)pResult : 0; -} - - -/** - @brief Get a uint16_t out of the input buffer - - @param[in] me Pointer to the UsefulInputBuf. - - @return The uint16_t - - See UsefulInputBuf_GetByte(). This works the same, except it returns - a uint16_t and two bytes are consumed. - - The input bytes must be in network order (big endian). - */ -static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *me) -{ - const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(me, sizeof(uint16_t)); - - if(!pResult) { - return 0; - } - - return ((uint16_t)pResult[0] << 8) + (uint16_t)pResult[1]; -} - - -/** - @brief Get a uint32_t out of the input buffer - - @param[in] me Pointer to the UsefulInputBuf. - - @return The uint32_t - - See UsefulInputBuf_GetByte(). This works the same, except it returns - a uint32_t and four bytes are consumed. - - The input bytes must be in network order (big endian). - */ -static inline uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *me) -{ - const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(me, sizeof(uint32_t)); - - if(!pResult) { - return 0; - } - - return ((uint32_t)pResult[0]<<24) + - ((uint32_t)pResult[1]<<16) + - ((uint32_t)pResult[2]<<8) + - (uint32_t)pResult[3]; -} - - -/** - @brief Get a uint64_t out of the input buffer - - @param[in] me Pointer to the UsefulInputBuf. - - @return The uint64_t - - See UsefulInputBuf_GetByte(). This works the same, except it returns - a uint64_t and eight bytes are consumed. - - The input bytes must be in network order (big endian). - */ -static inline uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *me) -{ - const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(me, sizeof(uint64_t)); - - if(!pResult) { - return 0; - } - - return ((uint64_t)pResult[0]<<56) + - ((uint64_t)pResult[1]<<48) + - ((uint64_t)pResult[2]<<40) + - ((uint64_t)pResult[3]<<32) + - ((uint64_t)pResult[4]<<24) + - ((uint64_t)pResult[5]<<16) + - ((uint64_t)pResult[6]<<8) + - (uint64_t)pResult[7]; -} - - -/** - @brief Get a float out of the input buffer - - @param[in] me Pointer to the UsefulInputBuf. - - @return The float - - See UsefulInputBuf_GetByte(). This works the same, except it returns - a float and four bytes are consumed. - - The input bytes must be in network order (big endian). - */ -static inline float UsefulInputBuf_GetFloat(UsefulInputBuf *me) -{ - uint32_t uResult = UsefulInputBuf_GetUint32(me); - - return uResult ? UsefulBufUtil_CopyUint32ToFloat(uResult) : 0; -} - -/** - @brief Get a double out of the input buffer - - @param[in] me Pointer to the UsefulInputBuf. - - @return The double - - See UsefulInputBuf_GetByte(). This works the same, except it returns - a double and eight bytes are consumed. - - The input bytes must be in network order (big endian). - */ -static inline double UsefulInputBuf_GetDouble(UsefulInputBuf *me) -{ - uint64_t uResult = UsefulInputBuf_GetUint64(me); - - return uResult ? UsefulBufUtil_CopyUint64ToDouble(uResult) : 0; -} - - -/** - @brief Get the error status - - @param[in] me Pointer to the UsefulInputBuf. - - @return The error. - - Zero is success, non-zero is error. Once in the error state, the only - way to clear it is to call Init again. - - You may be able to only check the error state at the end after all - the Get()'s have been done, but if what you get later depends on what - you get sooner you cannot. For example if you get a length or count - of following items you will have to check the error. - - */ -static inline int UsefulInputBuf_GetError(UsefulInputBuf *me) -{ - return me->err; -} - - -#endif // _UsefulBuf_h - - diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/inc/qcbor.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/inc/qcbor.h deleted file mode 100644 index f050988..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/inc/qcbor.h +++ /dev/null @@ -1,2598 +0,0 @@ -/*============================================================================== - Copyright (c) 2016-2018, The Linux Foundation. - Copyright (c) 2018-2019, Laurence Lundblade. - All rights reserved. - SPDX-License-Identifier: BSD-3-Clause - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of The Linux Foundation nor the names of its - contributors, nor the name "Laurence Lundblade" may be used to - endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS -BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ==============================================================================*/ - - -/*=================================================================================== - FILE: qcbor.h - - DESCRIPTION: This is the full public API and data structures for QCBOR - - EDIT HISTORY FOR FILE: - - This section contains comments describing changes made to the module. - Notice that changes are listed in reverse chronological order. - - when who what, where, why - -------- ---- --------------------------------------------------- - 12/18/18 llundblade Move decode malloc optional code to separate repository - 12/13/18 llundblade Documentatation improvements - 11/29/18 llundblade Rework to simpler handling of tags and labels. - 11/9/18 llundblade Error codes are now enums. - 11/1/18 llundblade Floating support. - 10/31/18 llundblade Switch to one license that is almost BSD-3. - 10/15/18 llundblade Indefinite length maps and arrays supported - 10/8/18 llundblade Indefinite length strings supported - 09/28/18 llundblade Added bstr wrapping feature for COSE implementation. - 07/05/17 llundbla Add bstr wrapping of maps/arrays for COSE. - 03/01/17 llundbla More data types; decoding improvements and fixes. - 11/13/16 llundbla Integrate most TZ changes back into github version. - 09/30/16 gkanike Porting to TZ. - 03/15/16 llundbla Initial Version. - - =====================================================================================*/ - -#ifndef __QCBOR__qcbor__ -#define __QCBOR__qcbor__ - -/*...... This is a ruler that is 80 characters long...........................*/ - -/* =========================================================================== - BEGINNING OF PRIVATE PART OF THIS FILE - - Caller of QCBOR should not reference any of the details below up until - the start of the public part. - =========================================================================== */ - -/* - Standard integer types are used in the interface to be precise about - sizes to be better at preventing underflow/overflow errors. - */ -#include -#include -#include "UsefulBuf.h" - - -/* - The maxium nesting of arrays and maps when encoding or decoding. - (Further down in the file there is a definition that refers to this - that is public. This is done this way so there can be a nice - separation of public and private parts in this file. -*/ -#define QCBOR_MAX_ARRAY_NESTING1 15 // Do not increase this over 255 - - -/* The largest offset to the start of an array or map. It is slightly - less than UINT32_MAX so the error condition can be tests on 32-bit machines. - UINT32_MAX comes from uStart in QCBORTrackNesting being a uin32_t. - - This will cause trouble on a machine where size_t is less than 32-bits. - */ -#define QCBOR_MAX_ARRAY_OFFSET (UINT32_MAX - 100) - -/* - PRIVATE DATA STRUCTURE - - Holds the data for tracking array and map nesting during encoding. Pairs up with - the Nesting_xxx functions to make an "object" to handle nesting encoding. - - uStart is a uint32_t instead of a size_t to keep the size of this - struct down so it can be on the stack without any concern. It would be about - double if size_t was used instead. - - Size approximation (varies with CPU/compiler): - 64-bit machine: (15 + 1) * (4 + 2 + 1 + 1 pad) + 8 = 136 bytes - 32-bit machine: (15 + 1) * (4 + 2 + 1 + 1 pad) + 4 = 132 bytes -*/ -typedef struct __QCBORTrackNesting { - // PRIVATE DATA STRUCTURE - struct { - // See function OpenArrayInternal() for detailed comments on how this works - uint32_t uStart; // uStart is the byte position where the array starts - uint16_t uCount; // Number of items in the arrary or map; counts items in a map, not pairs of items - uint8_t uMajorType; // Indicates if item is a map or an array - } pArrays[QCBOR_MAX_ARRAY_NESTING1+1], // stored state for the nesting levels - *pCurrentNesting; // the current nesting level -} QCBORTrackNesting; - - -/* - PRIVATE DATA STRUCTURE - - Context / data object for encoding some CBOR. Used by all encode functions to - form a public "object" that does the job of encdoing. - - Size approximation (varies with CPU/compiler): - 64-bit machine: 27 + 1 (+ 4 padding) + 136 = 32 + 136 = 168 bytes - 32-bit machine: 15 + 1 + 132 = 148 bytes -*/ -struct _QCBOREncodeContext { - // PRIVATE DATA STRUCTURE - UsefulOutBuf OutBuf; // Pointer to output buffer, its length and position in it - uint8_t uError; // Error state - QCBORTrackNesting nesting; // Keep track of array and map nesting -}; - - -/* - PRIVATE DATA STRUCTURE - - Holds the data for array and map nesting for decoding work. This structure - and the DecodeNesting_xxx functions form an "object" that does the work - for arrays and maps. - - Size approximation (varies with CPU/compiler): - 64-bit machine: 4 * 16 + 8 = 72 - 32-bit machine: 4 * 16 + 4 = 68 - */ -typedef struct __QCBORDecodeNesting { - // PRIVATE DATA STRUCTURE - struct { - uint16_t uCount; - uint8_t uMajorType; - } pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING1+1], - *pCurrent; -} QCBORDecodeNesting; - - -/* - PRIVATE DATA STRUCTURE - - The decode context. This data structure plus the public QCBORDecode_xxx - functions form an "object" that does CBOR decoding. - - Size approximation (varies with CPU/compiler): - 64-bit machine: 32 + 1 + 1 + 6 bytes padding + 72 + 16 = 128 bytes - 32-bit machine: 16 + 1 + 1 + 2 bytes padding + 68 + 8 = 68 bytes - */ -struct _QCBORDecodeContext { - // PRIVATE DATA STRUCTURE - UsefulInputBuf InBuf; - - uint8_t uDecodeMode; - uint8_t bStringAllocateAll; - - QCBORDecodeNesting nesting; - - // This is NULL or points to a QCBORStringAllocator. It is void - // here because _QCBORDecodeContext is defined early in the - // private part of this file and QCBORStringAllocat is defined - // later in the public part of this file. - void *pStringAllocator; - - // This is NULL or points to QCBORTagList. - // It is type void for the same reason as above. - const void *pCallerConfiguredTagList; -}; - -// Used internally in the impementation here -// Must not conflict with any of the official CBOR types -#define CBOR_MAJOR_NONE_TYPE_RAW 9 -#define CBOR_MAJOR_NONE_TAG_LABEL_REORDER 10 - - -/* =========================================================================== - END OF PRIVATE PART OF THIS FILE - - BEGINNING OF PUBLIC PART OF THIS FILE - =========================================================================== */ - - - -/* =========================================================================== - BEGINNING OF CONSTANTS THAT COME FROM THE CBOR STANDARD, RFC 7049 - - It is not necessary to use these directly when encoding or decoding - CBOR with this implementation. - =========================================================================== */ - -/* Standard CBOR Major type for positive integers of various lengths */ -#define CBOR_MAJOR_TYPE_POSITIVE_INT 0 - -/* Standard CBOR Major type for negative integer of various lengths */ -#define CBOR_MAJOR_TYPE_NEGATIVE_INT 1 - -/* Standard CBOR Major type for an array of arbitrary 8-bit bytes. */ -#define CBOR_MAJOR_TYPE_BYTE_STRING 2 - -/* Standard CBOR Major type for a UTF-8 string. Note this is true 8-bit UTF8 - with no encoding and no NULL termination */ -#define CBOR_MAJOR_TYPE_TEXT_STRING 3 - -/* Standard CBOR Major type for an ordered array of other CBOR data items */ -#define CBOR_MAJOR_TYPE_ARRAY 4 - -/* Standard CBOR Major type for CBOR MAP. Maps an array of pairs. The - first item in the pair is the "label" (key, name or identfier) and the second - item is the value. */ -#define CBOR_MAJOR_TYPE_MAP 5 - -/* Standard CBOR optional tagging. This tags things like dates and URLs */ -#define CBOR_MAJOR_TYPE_OPTIONAL 6 - -/* Standard CBOR extra simple types like floats and the values true and false */ -#define CBOR_MAJOR_TYPE_SIMPLE 7 - - -/* - These are special values for the AdditionalInfo bits that are part of the first byte. - Mostly they encode the length of the data item. - */ -#define LEN_IS_ONE_BYTE 24 -#define LEN_IS_TWO_BYTES 25 -#define LEN_IS_FOUR_BYTES 26 -#define LEN_IS_EIGHT_BYTES 27 -#define ADDINFO_RESERVED1 28 -#define ADDINFO_RESERVED2 29 -#define ADDINFO_RESERVED3 30 -#define LEN_IS_INDEFINITE 31 - - -/* - 24 is a special number for CBOR. Integers and lengths - less than it are encoded in the same byte as the major type - */ -#define CBOR_TWENTY_FOUR 24 - - -/* - Tags that are used with CBOR_MAJOR_TYPE_OPTIONAL. These are - the ones defined in the CBOR spec. - */ -/** See QCBOREncode_AddDateString() below */ -#define CBOR_TAG_DATE_STRING 0 -/** See QCBOREncode_AddDateEpoch_2() */ -#define CBOR_TAG_DATE_EPOCH 1 -#define CBOR_TAG_POS_BIGNUM 2 -#define CBOR_TAG_NEG_BIGNUM 3 -#define CBOR_TAG_FRACTION 4 -#define CBOR_TAG_BIGFLOAT 5 - -#define CBOR_TAG_COSE_ENCRYPTO 16 -#define CBOR_TAG_COSE_MAC0 17 -#define CBOR_TAG_COSE_SIGN1 18 - -/* The data in byte string should be converted in base 64 URL when encoding in JSON or similar text-based representations */ -#define CBOR_TAG_ENC_AS_B64URL 21 -/* The data in byte string should be encoded in base 64 when encoding in JSON */ -#define CBOR_TAG_ENC_AS_B64 22 -/* The data in byte string should be encoded in base 16 when encoding in JSON */ -#define CBOR_TAG_ENC_AS_B16 23 -#define CBOR_TAG_CBOR 24 -/** The data in the string is a URIs, as defined in RFC3986 */ -#define CBOR_TAG_URI 32 -/** The data in the string is a base 64'd URL */ -#define CBOR_TAG_B64URL 33 -/** The data in the string is base 64'd */ -#define CBOR_TAG_B64 34 -/** regular expressions in Perl Compatible Regular Expressions (PCRE) / JavaScript syntax ECMA262. */ -#define CBOR_TAG_REGEX 35 -/** MIME messages (including all headers), as defined in RFC2045 */ -#define CBOR_TAG_MIME 36 -/** Binary UUID */ -#define CBOR_TAG_BIN_UUID 37 - -#define CBOR_TAG_CWT 61 - -#define CBOR_TAG_ENCRYPT 96 -#define CBOR_TAG_MAC 97 -#define CBOR_TAG_SIGN 98 - -#define CBOR_TAG_GEO_COORD 103 - - -/** The data is CBOR data */ -#define CBOR_TAG_CBOR_MAGIC 55799 -#define CBOR_TAG_NONE UINT64_MAX - - -/* - Values for the 5 bits for items of major type 7 - */ -#define CBOR_SIMPLEV_FALSE 20 -#define CBOR_SIMPLEV_TRUE 21 -#define CBOR_SIMPLEV_NULL 22 -#define CBOR_SIMPLEV_UNDEF 23 -#define CBOR_SIMPLEV_ONEBYTE 24 -#define HALF_PREC_FLOAT 25 -#define SINGLE_PREC_FLOAT 26 -#define DOUBLE_PREC_FLOAT 27 -#define CBOR_SIMPLE_BREAK 31 - - - -/* =========================================================================== - - END OF CONSTANTS THAT COME FROM THE CBOR STANDARD, RFC 7049 - - BEGINNING OF PUBLIC INTERFACE FOR QCBOR ENCODER / DECODER - - =========================================================================== */ - -/** - - @file qcbor.h - - Q C B O R E n c o d e / D e c o d e - - This implements CBOR -- Concise Binary Object Representation as defined - in RFC 7049. More info is at http://cbor.io. This is a near-complete - implementation of the specification. Limitations are listed further down. - - CBOR is intentionally designed to be translatable to JSON, but not - all CBOR can convert to JSON. See RFC 7049 for more info on how to - construct CBOR that is the most JSON friendly. - - The memory model for encoding and decoding is that encoded CBOR - must be in a contiguous buffer in memory. During encoding the - caller must supply an output buffer and if the encoding would go - off the end of the buffer an error is returned. During decoding - the caller supplies the encoded CBOR in a contiguous buffer - and the decoder returns pointers and lengths into that buffer - for strings. - - This implementation does not require malloc. All data structures - passed in/out of the APIs can fit on the stack. - - Decoding of indefinite length strings is a special case that requires - a "string allocator" to allocate memory into which the segments of - the string are coalesced. Without this, decoding will error out if - an indefinite length string is encountered (indefinite length maps - and arrays do not require the string allocator). A simple string - allocator called MemPool is built-in and will work if supplied with - a block of memory to allocate. The string allocator can optionally - use malloc() or some other custom scheme. - - Here are some terms and definitions: - - - "Item", "Data Item": An integer or string or such. The basic "thing" that - CBOR is about. An array is an item itself that contains some items. - - - "Array": An ordered sequence of items, the same as JSON. - - - "Map": A collection of label/value pairs. Each pair is a data - item. A JSON "object" is the same as a CBOR "map". - - - "Label": The data item in a pair in a map that names or identifies the - pair, not the value. This implementation refers to it as a "label". - JSON refers to it as the "name". The CBOR RFC refers to it this as a "key". - This implementation chooses label instead because key is too easily confused - with a cryptographic key. The COSE standard, which uses CBOR, has also - chosen to use the term "label" rather than "key" for this same reason. - - - "Key": See "Label" above. - - - "Tag": Optional info that can be added before each data item. This is always - CBOR major type 6. - - - "Initial Byte": The first byte of an encoded item. Encoding and decoding of - this byte is taken care of by the implementation. - - - "Additional Info": In addition to the major type, all data items have some - other info. This is usually the length of the data, but can be several - other things. Encoding and decoding of this is taken care of by the - implementation. - - CBOR has two mechanisms for tagging and labeling the data - values like integers and strings. For example, an integer that - represents someone's birthday in epoch seconds since Jan 1, 1970 - could be encoded like this: - - - First it is CBOR_MAJOR_TYPE_POSITIVE_INT, the primitive positive - integer. - - Next it has a "tag" CBOR_TAG_DATE_EPOCH indicating the integer - represents a date in the form of the number of seconds since - Jan 1, 1970. - - Last it has a string "label" like "BirthDate" indicating - the meaning of the data. - - The encoded binary looks like this: - a1 # Map of 1 item - 69 # Indicates text string of 9 bytes - 426972746844617465 # The text "BirthDate" - c1 # Tags next int as epoch date - 1a # Indicates 4 byte integer - 580d4172 # unsigned integer date 1477263730 - - Implementors using this API will primarily work with labels. Generally - tags are only needed for making up new data types. This implementation - covers most of the data types defined in the RFC using tags. It also, - allows for the creation of news tags if necessary. - - This implementation explicitly supports labels that are text strings - and integers. Text strings translate nicely into JSON objects and - are very readable. Integer labels are much less readable, but - can be very compact. If they are in the range of -23 to - 23 they take up only one byte. - - CBOR allows a label to be any type of data including an array or - a map. It is possible to use this API to construct and - parse such labels, but it is not explicitly supported. - - A common encoding usage mode is to invoke the encoding twice. First - with no output buffer to compute the length of the needed output - buffer. Then the correct sized output buffer is allocated. Last the - encoder is invoked again, this time with the output buffer. - - The double invocation is not required if the max output buffer size - can be predicted. This is usually possible for simple CBOR structures. - If the double invocation is implemented, it can be - in a loop or function as in the example code so that the code doesn't - have to actually be written twice, saving code size. - - If a buffer too small to hold the encoded output is given, the error - QCBOR_ERR_BUFFER_TOO_SMALL will be returned. Data will never be - written off the end of the output buffer no matter which functions - here are called or what parameters are passed to them. - - The error handling is simple. The only possible errors are trying to - encode structures that are too large or too complex. There are no - internal malloc calls so there will be no failures for out of memory. - Only the final call, QCBOREncode_Finish(), returns an error code. - Once an error happens, the encoder goes into an error state and calls - to it will do nothing so the encoding can just go on. An error - check is not needed after every data item is added. - - Encoding generally proceeds by calling QCBOREncode_Init(), calling - lots of "Add" functions and calling QCBOREncode_Finish(). There - are many "Add" functions for various data types. The input - buffers need only to be valid during the "Add" calls. The - data is copied into the output buf during the "Add" call. - - There are three `Add` functions for each data type. The first - / main one for the type is for adding the data item to an array. - The second one's name ends in `ToMap`, is used for adding - data items to maps and takes a string - argument that is its label in the map. The third one ends in - `ToMapN`, is also used for adding data items to maps, and - takes an integer argument that is its label in the map. - - The simplest aggregate type is an array, which is a simple ordered - set of items without labels the same as JSON arrays. Call - QCBOREncode_OpenArray() to open a new array, then "Add" to - put items in the array and then QCBOREncode_CloseArray(). Nesting - to a limit is allowed. All opens must be matched by closes or an - encoding error will be returned. - - The other aggregate type is a map which does use labels. The - `Add` functions that end in `ToMap` and `ToMapN` are convenient - ways to add labeled data items to a map. You can also call - any type of `Add` function once to add a label of any time and - then call any type of `Add` again to add its value. - - Note that when you nest arrays or maps in a map, the nested - array or map has a label. - - Usually it is not necessary to add tags explicitly as most - tagged types have functions here, but they can be added by - calling QCBOREncode_AddTag(). There is an IANA registry for new tags that are - for broad use and standardization as per RFC 7049. It is also - allowed for protocols to make up new tags in the range above 256. - Note that even arrays and maps can be tagged. - - Summary Limits of this implementation: - - The entire encoded CBOR must fit into contiguous memory. - - Max size of encoded / decoded CBOR data is UINT32_MAX (4GB). - - Max array / map nesting level when encoding / decoding is - QCBOR_MAX_ARRAY_NESTING (this is typically 15). - - Max items in an array or map when encoding / decoding is - QCBOR_MAX_ITEMS_IN_ARRAY (typically 65,536). - - Does not support encoding indefinite lengths (decoding is supported). - - Does not directly support some tagged types: decimal fractions, big floats - - Does not directly support labels in maps other than text strings and ints. - - Does not directly support int labels greater than INT64_MAX - - Epoch dates limited to INT64_MAX (+/- 292 billion years) - - Tags on labels are ignored during decoding - - This implementation is intended to run on 32 and 64-bit CPUs. Minor - modifications are needed for it to work on 16-bit CPUs. - - The public interface uses size_t for all lengths. Internally the - implementation uses 32-bit lengths by design to use less memory and - fit structures on the stack. This limits the encoded - CBOR it can work with to size UINT32_MAX (4GB) which should be - enough. - - This implementation assumes two's compliment integer - machines. Stdint.h also requires this. It of course would be easy to - fix this implementation for another integer representation, but all - modern machines seem to be two's compliment. - - */ - - -/** - The maximum number of items in a single array or map when encoding of decoding. -*/ -// -1 is because the value UINT16_MAX is used to track indefinite length arraysUINT16_MAX -#define QCBOR_MAX_ITEMS_IN_ARRAY (UINT16_MAX-1) - -/** - The maximum nesting of arrays and maps when encoding or decoding. The - error QCBOR_ERR_ARRAY_NESTING_TOO_DEEP will be returned on encoding - of decoding if it is exceeded -*/ -#define QCBOR_MAX_ARRAY_NESTING QCBOR_MAX_ARRAY_NESTING1 - -/** - The maximum number of tags that can be in QCBORTagListIn and passed to - QCBORDecode_SetCallerConfiguredTagList() - */ -#define QCBOR_MAX_CUSTOM_TAGS 16 - - -typedef enum { - /** The encode or decode completely correctly. */ - QCBOR_SUCCESS = 0, - - /** The buffer provided for the encoded output when doing encoding was - too small and the encoded output will not fit. Also, when the buffer - given to QCBORDecode_SetMemPool() is too small. */ - QCBOR_ERR_BUFFER_TOO_SMALL, - - /** During encoding or decoding, the array or map nesting was deeper than - this implementation can handle. Note that in the interest of code size - and memory use, this implementation has a hard limit on array nesting. The - limit is defined as the constant QCBOR_MAX_ARRAY_NESTING. */ - QCBOR_ERR_ARRAY_NESTING_TOO_DEEP, - - /** During decoding or encoding, the array or map had too many items in it. - This limit QCBOR_MAX_ITEMS_IN_ARRAY, typically 65,535. */ - QCBOR_ERR_ARRAY_TOO_LONG, - - /** During encoding, more arrays or maps were closed than opened. This is a - coding error on the part of the caller of the encoder. */ - QCBOR_ERR_TOO_MANY_CLOSES, - - /** During decoding, some CBOR construct was encountered that this decoder - doesn't support, primarily this is the reserved additional info values, - 28 through 30. */ - QCBOR_ERR_UNSUPPORTED, - - /** During decoding, hit the end of the given data to decode. For example, - a byte string of 100 bytes was expected, but the end of the input was - hit before finding those 100 bytes. Corrupted CBOR input will often - result in this error. */ - QCBOR_ERR_HIT_END, - - /** During encoding, the length of the encoded CBOR exceeded UINT32_MAX. - */ - QCBOR_ERR_BUFFER_TOO_LARGE, - - /** During decoding, an integer smaller than INT64_MIN was received (CBOR - can represent integers smaller than INT64_MIN, but C cannot). */ - QCBOR_ERR_INT_OVERFLOW, - - /** During decoding, the label for a map entry is bad. What causes this - error depends on the decoding mode. */ - QCBOR_ERR_MAP_LABEL_TYPE, - - /** During encoding or decoding, the number of array or map opens was not - matched by the number of closes. */ - QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN, - - /** During encoding, the simple value is not between CBOR_SIMPLEV_FALSE - and CBOR_SIMPLEV_UNDEF. */ - QCBOR_ERR_BAD_SIMPLE, - - /** During decoding, a date greater than +- 292 billion years from Jan 1 - 1970 encountered during parsing. */ - QCBOR_ERR_DATE_OVERFLOW, - - /** During decoding, the CBOR is not valid, primarily a simple type is encoded in - a prohibited way. */ - QCBOR_ERR_INVALID_CBOR, - - /** Optional tagging that doesn't make sense (an int is tagged as a - date string) or can't be handled. */ - QCBOR_ERR_BAD_OPT_TAG, - - /** Returned by QCBORDecode_Finish() if all the inputs bytes have not - been consumed. */ - QCBOR_ERR_EXTRA_BYTES, - - /** During encoding, QCBOREncode_Close() call with a different type than - is currently open. */ - QCBOR_ERR_CLOSE_MISMATCH, - - /** Unable to decode an indefinite length string because no string - allocator was configured. */ - QCBOR_ERR_NO_STRING_ALLOCATOR, - - /** One of the chunks in an indefinite length string is not of the type of - the string. */ - QCBOR_ERR_INDEFINITE_STRING_CHUNK, - - /** Error allocating space for a string, usually for an indefinite length - string. */ - QCBOR_ERR_STRING_ALLOCATE, - - /** During decoding, a break occurred outside an indefinite length item. */ - QCBOR_ERR_BAD_BREAK, - - /** During decoding, too many tags in the caller-configured tag list, or not - enough space in QCBORTagListOut. */ - QCBOR_ERR_TOO_MANY_TAGS, - - /** Returned by QCBORDecode_SetMemPool() when xx is too small. This should - never happen on a machine with 64-bit or smaller pointers. Fixing - it is probably by increasing QCBOR_DECODE_MIN_MEM_POOL_SIZE. */ - QCBOR_ERR_MEM_POOL_INTERNAL - -} QCBORError; - - -typedef enum { - /** See QCBORDecode_Init() */ - QCBOR_DECODE_MODE_NORMAL = 0, - /** See QCBORDecode_Init() */ - QCBOR_DECODE_MODE_MAP_STRINGS_ONLY = 1, - /** See QCBORDecode_Init() */ - QCBOR_DECODE_MODE_MAP_AS_ARRAY = 2 -} QCBORDecodeMode; - - - - - -/* Do not renumber these. Code depends on some of these values. */ -/** The type is unknown, unset or invalid */ -#define QCBOR_TYPE_NONE 0 -/** Type for an integer that decoded either between INT64_MIN and INT32_MIN or INT32_MAX and INT64_MAX; val.int64 */ -#define QCBOR_TYPE_INT64 2 -/** Type for an integer that decoded to a more than INT64_MAX and UINT64_MAX; val.uint64 */ -#define QCBOR_TYPE_UINT64 3 -/** Type for an array. The number of items in the array is in val.uCount. */ -#define QCBOR_TYPE_ARRAY 4 -/** Type for a map; number of items in map is in val.uCount */ -#define QCBOR_TYPE_MAP 5 -/** Type for a buffer full of bytes. Data is in val.string. */ -#define QCBOR_TYPE_BYTE_STRING 6 -/** Type for a UTF-8 string. It is not NULL terminated. Data is in val.string. */ -#define QCBOR_TYPE_TEXT_STRING 7 -/** Type for a positive big number. Data is in val.bignum, a pointer and a length. */ -#define QCBOR_TYPE_POSBIGNUM 9 -/** Type for a negative big number. Data is in val.bignum, a pointer and a length. */ -#define QCBOR_TYPE_NEGBIGNUM 10 -/** Type for RFC 3339 date string, possibly with time zone. Data is in val.dateString */ -#define QCBOR_TYPE_DATE_STRING 11 -/** Type for integer seconds since Jan 1970 + floating point fraction. Data is in val.epochDate */ -#define QCBOR_TYPE_DATE_EPOCH 12 -/** A simple type that this CBOR implementation doesn't know about; Type is in val.uSimple. */ -#define QCBOR_TYPE_UKNOWN_SIMPLE 13 -/** Type for the simple value false; nothing more; nothing in val union. */ -#define QCBOR_TYPE_FALSE 20 -/** Type for the simple value true; nothing more; nothing in val union. */ -#define QCBOR_TYPE_TRUE 21 -/** Type for the simple value null; nothing more; nothing in val union. */ -#define QCBOR_TYPE_NULL 22 -/** Type for the simple value undef; nothing more; nothing in val union. */ -#define QCBOR_TYPE_UNDEF 23 -/** Type for a floating point number. Data is in val.float. */ -#define QCBOR_TYPE_FLOAT 26 -/** Type for a double floating point number. Data is in val.double. */ -#define QCBOR_TYPE_DOUBLE 27 -/** For QCBOR_DECODE_MODE_MAP_AS_ARRAY decode mode, a map that is being traversed as an array. See QCBORDecode_Init() */ -#define QCBOR_TYPE_MAP_AS_ARRAY 32 - -#define QCBOR_TYPE_BREAK 31 // Used internally; never returned - -#define QCBOR_TYPE_OPTTAG 254 // Used internally; never returned - - - -/* - Approx Size of this: - 8 + 8 + 1 + 1 + 1 + (1 padding) + (4 padding on 64-bit machine) = 24 for first part (20 on a 32-bit machine) - 16 bytes for the val union - 16 bytes for label union - total = 56 bytes (52 bytes on 32-bit machine) - */ - -/** - QCBORItem holds the type, value and other info for a decoded item returned by GetNextItem(). - */ -typedef struct _QCBORItem { - uint8_t uDataType; /** Tells what element of the val union to use. One of QCBOR_TYPE_XXXX */ - uint8_t uNestingLevel; /** How deep the nesting from arrays and maps are. 0 is the top level with no arrays or maps entered */ - uint8_t uLabelType; /** Tells what element of the label union to use */ - uint8_t uDataAlloc; /** 1 if allocated with string allocator, 0 if not. See QCBORDecode_MakeMallocStringAllocator() */ - uint8_t uLabelAlloc; /** Like uDataAlloc, but for label */ - uint8_t uNextNestLevel; /** If not equal to uNestingLevel, this item closed out at least one map/array */ - - union { - int64_t int64; /** The value for uDataType QCBOR_TYPE_INT64 */ - uint64_t uint64; /** The value for uDataType QCBOR_TYPE_UINT64 */ - - UsefulBufC string; /** The value for uDataType QCBOR_TYPE_BYTE_STRING and QCBOR_TYPE_TEXT_STRING */ - uint16_t uCount; /** The "value" for uDataType QCBOR_TYPE_ARRAY or QCBOR_TYPE_MAP -- the number of items in the array or map - UINT16_MAX when decoding indefinite lengths maps and arrays. */ - double dfnum; /** The value for uDataType QCBOR_TYPE_DOUBLE */ - struct { - int64_t nSeconds; - double fSecondsFraction; - } epochDate; /** The value for uDataType QCBOR_TYPE_DATE_EPOCH */ - UsefulBufC dateString; /** The value for uDataType QCBOR_TYPE_DATE_STRING */ - UsefulBufC bigNum; /** The value for uDataType QCBOR_TYPE_BIGNUM */ - uint8_t uSimple; /** The integer value for unknown simple types */ - uint64_t uTagV; - - } val; /** The union holding the item's value. Select union member based on uDataType */ - - union { - UsefulBufC string; /** The label for uLabelType QCBOR_TYPE_BYTE_STRING and QCBOR_TYPE_TEXT_STRING */ - int64_t int64; /** The label for uLabelType for QCBOR_TYPE_INT64 */ - uint64_t uint64; /** The label for uLabelType for QCBOR_TYPE_UINT64 */ - } label; /** Union holding the different label types selected based on uLabelType */ - - uint64_t uTagBits; /** Bit indicating which tags (major type 6) on this item. */ - -} QCBORItem; - - -/** - This is a set of functions and pointer context (in object-oriented parlance, - an "object") used to allocate memory for coalescing the segments of an indefinite - length string into one. - - The fAllocate function works as an initial allocator and a reallocator to - expand the string for each new segment. When it is an initial allocator - pOldMem is NULL. - - The fFree function is called to clean up an individual allocation when an error occurs. - - The fDesctructor function is called when QCBORDecode_Finish is called. - - Any memory allocated with this will be marked by setting uDataAlloc - or uLabelAlloc in the QCBORItem structure so the caller knows they - have to free it. - - fAllocate is only ever called to increase the single most recent - allocation made, making implementation of a memory pool very simple. - - fFree is also only called on the single most recent allocation. - */ -typedef struct { - void *pAllocaterContext; - UsefulBuf (*fAllocate)(void *pAllocaterContext, void *pOldMem, size_t uNewSize); - void (*fFree)(void *pAllocaterContext, void *pMem); - void (*fDestructor)(void *pAllocaterContext); -} QCBORStringAllocator; - - -/** - This only matters if you use a string allocator - and and set it up with QCBORDecode_SetMemPool(). It is - the size of the overhead needed needed by - QCBORDecode_SetMemPool(). If you write your own - string allocator or use the separately available malloc - based string allocator, this size will not apply - */ -#define QCBOR_DECODE_MIN_MEM_POOL_SIZE 72 - - -/** - This is used to tell the decoder about tags that it should - record in uTagBits in QCBORItem beyond the built-in - tags. puTags points to an - array of uint64_t integers that are the tags. uNumTags - is the number of integers in the array. The maximum - size is QCBOR_MAX_CUSTOM_TAGS. See QCBORDecode_IsTagged() - and QCBORDecode_SetCallerAddedTagMap(). - */ -typedef struct { - uint8_t uNumTags; - const uint64_t *puTags; -} QCBORTagListIn; - - -/** - This is for QCBORDecode_GetNextWithTags() to be able to return the - full list of tags on an item. It not needed for most CBOR protocol - implementations. Its primary use is for pretty-printing CBOR or - protocol conversion to another format. - - On input, puTags points to a buffer to be filled in - and uNumAllocated is the number of uint64_t values - in the buffer. - - On output the buffer contains the tags for the item. - uNumUsed tells how many there are. - */ -typedef struct { - uint8_t uNumUsed; - uint8_t uNumAllocated; - uint64_t *puTags; -} QCBORTagListOut; - - -/** - QCBOREncodeContext is the data type that holds context for all the - encoding functions. It is less than 200 bytes, so it can go on - the stack. The contents are opaque, and the caller should not access - any internal items. A context may be re used serially as long as - it is re initialized. - */ -typedef struct _QCBOREncodeContext QCBOREncodeContext; - - -/** - Initialize the the encoder to prepare to encode some CBOR. - - @param[in,out] pCtx The encoder context to initialize. - @param[in] Storage The buffer into which this encoded result will be placed. - - Call this once at the start of an encoding of a CBOR structure. Then - call the various QCBOREncode_AddXXX() functions to add the data - items. Then call QCBOREncode_Finish(). - - The maximum output buffer is UINT32_MAX (4GB). This is not a practical - limit in any way and reduces the memory needed by the implementation. - The error QCBOR_ERR_BUFFER_TOO_LARGE will be returned by QCBOR_Finish() - if a larger buffer length is passed in. - - If this is called with pBuf as NULL and uBufLen a large value like - UINT32_MAX, all the QCBOREncode_AddXXXX() functions and - QCBORE_Encode_Finish() can still be called. No data will be encoded, - but the length of what would be encoded will be calculated. The - length of the encoded structure will be handed back in the call to - QCBOREncode_Finish(). You can then allocate a buffer of that size - and call all the encoding again, this time to fill in the buffer. - - A QCBORContext can be reused over and over as long as - QCBOREncode_Init() is called. - */ -void QCBOREncode_Init(QCBOREncodeContext *pCtx, UsefulBuf Storage); - - -/** - @brief Add a signed 64-bit integer to the encoded output. - - @param[in] pCtx The encoding context to add the integer to. - @param[in] nNum The integer to add. - - The integer will be encoded and added to the CBOR output. - - This function figures out the size and the sign and encodes in the - correct minimal CBOR. Specifically, it will select CBOR major type 0 or 1 - based on sign and will encode to 1, 2, 4 or 8 bytes depending on the - value of the integer. Values less than 24 effectively encode to one - byte because they are encoded in with the CBOR major type. This is - a neat and efficient characteristic of CBOR that can be taken - advantage of when designing CBOR-based protocols. If integers like - tags can be kept between -23 and 23 they will be encoded in one byte - including the major type. - - If you pass a smaller int, say an int16_t or a small value, say 100, - the encoding will still be CBOR's most compact that can represent the - value. For example, CBOR always encodes the value 0 as one byte, - 0x00. The representation as 0x00 includes identification of the type - as an integer too as the major type for an integer is 0. See RFC 7049 - Appendix A for more examples of CBOR encoding. This compact encoding - is also canonical CBOR as per section 3.9 in RFC 7049. - - There are no functions to add int16_t or int32_t because they are - not necessary because this always encodes to the smallest number - of bytes based on the value (If this code is running on a 32-bit - machine having a way to add 32-bit integers would reduce code size some). - - If the encoding context is in an error state, this will do - nothing. If an error occurs when adding this integer, the internal - error flag will be set, and the error will be returned when - QCBOREncode_Finish() is called. - - See also QCBOREncode_AddUInt64(). - */ -void QCBOREncode_AddInt64(QCBOREncodeContext *pCtx, int64_t nNum); - -static void QCBOREncode_AddInt64ToMap(QCBOREncodeContext *pCtx, const char *szLabel, int64_t uNum); - -static void QCBOREncode_AddInt64ToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, int64_t uNum); - - -/** - @brief Add an unsigned 64-bit integer to the encoded output. - - @param[in] pCtx The encoding context to add the integer to. - @param[in] uNum The integer to add. - - The integer will be encoded and added to the CBOR output. - - The only reason so use this function is for integers larger than - INT64_MAX and smaller than UINT64_MAX. Otherwise QCBOREncode_AddInt64() - will work fine. - - Error handling is the same as for QCBOREncode_AddInt64(). - */ -void QCBOREncode_AddUInt64(QCBOREncodeContext *pCtx, uint64_t uNum); - -static void QCBOREncode_AddUInt64ToMap(QCBOREncodeContext *pCtx, const char *szLabel, uint64_t uNum); - -static void QCBOREncode_AddUInt64ToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, uint64_t uNum); - - -/** - - @brief Add a UTF-8 text string to the encoded output - - @param[in] pCtx The context to initialize. - @param[in] Text Pointer and length of text to add. - - The text passed in must be unencoded UTF-8 according to RFC - 3629. There is no NULL termination. The text is added as CBOR - major type 3. - - If called with nBytesLen equal to 0, an empty string will be - added. When nBytesLen is 0, pBytes may be NULL. - - Note that the restriction of the buffer length to an uint32_t is - entirely intentional as this encoder is not capable of encoding - lengths greater. This limit to 4GB for a text string should not be a - problem. - - Error handling is the same as QCBOREncode_AddInt64(). - */ -static void QCBOREncode_AddText(QCBOREncodeContext *pCtx, UsefulBufC Text); - -static void QCBOREncode_AddTextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Text); - -static void QCBOREncode_AddTextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Text); - - -/** - @brief Add a UTF-8 text string to the encoded output - - @param[in] pCtx The context to initialize. - @param[in] szString Null-terminated text to add. - - This works the same as QCBOREncode_AddText(). - */ -static void QCBOREncode_AddSZString(QCBOREncodeContext *pCtx, const char *szString); - -static void QCBOREncode_AddSZStringToMap(QCBOREncodeContext *pCtx, const char *szLabel, const char *szString); - -static void QCBOREncode_AddSZStringToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, const char *szString); - - -/** - @brief Add a floating-point number to the encoded output - - @param[in] pCtx The encoding context to add the float to. - @param[in] dNum The double precision number to add. - - This outputs a floating-point number with CBOR major type 7. - - This will selectively encode the double-precision floating point - number as either double-precision, single-precision or - half-precision. It will always encode infinity, NaN and 0 has half - precision. If no precision will be lost in the conversion to - half-precision then it will be converted and encoded. If not and no - precision will be lost in conversion to single-precision, then it - will be converted and encoded. If not, then no conversion is - performed, and it encoded as a double. - - Half-precision floating point numbers take up 2 bytes, half that of - single-precision, one quarter of double-precision - - This automatically reduces the size of encoded messages a lot, maybe - even by four if most of values are 0, infinity or NaN. - - On decode, these will always be returned as a double. - - Error handling is the same as QCBOREncode_AddInt64(). - */ -void QCBOREncode_AddDouble(QCBOREncodeContext *pCtx, double dNum); - -static void QCBOREncode_AddDoubleToMap(QCBOREncodeContext *pCtx, const char *szLabel, double dNum); - -static void QCBOREncode_AddDoubleToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, double dNum); - - -/** - @brief[in] Add an optional tag - - @param[in] pCtx The encoding context to add the integer to. - @param[in] uTag The tag to add - - This outputs a CBOR major type 6 optional tag. - - The tag is applied to the next data item added to the encoded - output. That data item that is to be tagged can be of any major - CBOR type. Any number of tags can be added to a data item by calling - this multiple times before the data item is added. - - For many of the common standard tags a function to encode - data using it already exists and this is not needed. For example, - QCBOREncode_AddDateEpoch() already exists to output - integers representing dates with the right tag. -*/ -void QCBOREncode_AddTag(QCBOREncodeContext *pCtx,uint64_t uTag); - - -/** - @brief Add an epoch-based date - - @param[in] pCtx The encoding context to add the simple value to. - @param[in] date Number of seconds since 1970-01-01T00:00Z in UTC time. - - As per RFC 7049 this is similar to UNIX/Linux/POSIX dates. This is - the most compact way to specify a date and time in CBOR. Note that this - is always UTC and does not include the time zone. Use - QCBOREncode_AddDateString() if you want to include the time zone. - - The integer encoding rules apply here so the date will be encoded in a - minimal number of 1, 2 4 or 8 bytes. Until about the year 2106 these - dates should encode in 6 bytes -- one byte for the tag, one byte for the type - and 4 bytes for the integer. - - If you care about leap-seconds and that level of accuracy, make sure the - system you are running this code on does it correctly. This code just takes - the value passed in. - - This implementation cannot encode fractional seconds using float or double - even though that is allowed by CBOR, but you can encode them if you - want to by calling QCBOREncode_AddDouble() - with the right parameters. - - Error handling is the same as QCBOREncode_AddInt64(). - */ -static void QCBOREncode_AddDateEpoch(QCBOREncodeContext *pCtx, int64_t date); - -static void QCBOREncode_AddDateEpochToMap(QCBOREncodeContext *pCtx, const char *szLabel, int64_t date); - -static void QCBOREncode_AddDateEpochToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, int64_t date); - - -/** - @brief Add a byte string to the encoded output. - - @param[in] pCtx The context to initialize. - @param[in] Bytes Pointer and length of the input data. - - Simply adds the bytes to the encoded output as CBOR major type 2. - - If called with Bytes.len equal to 0, an empty string will be - added. When Bytes.len is 0, Bytes.ptr may be NULL. - - Error handling is the same as QCBOREncode_AddInt64(). - */ -static void QCBOREncode_AddBytes(QCBOREncodeContext *pCtx, UsefulBufC Bytes); - -static void QCBOREncode_AddBytesToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes); - -static void QCBOREncode_AddBytesToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes); - - - -/** - @brief Add a binary UUID to the encoded output. - - @param[in] pCtx The context to initialize. - @param[in] Bytes Pointer and length of the binary UUID. - - A binary UUID as defined in RFC 4122 is added to the ouput. - - It is output as CBOR major type 2, a binary string, with - optional tag 36 indicating the binary string is a UUID. - */ -static void QCBOREncode_AddBinaryUUID(QCBOREncodeContext *pCtx, UsefulBufC Bytes); - -static void QCBOREncode_AddBinaryUUIDToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes); - -static void QCBOREncode_AddBinaryUUIDToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes); - - -/** - @brief Add a positive big number to the encoded output. - - @param[in] pCtx The context to initialize. - @param[in] Bytes Pointer and length of the big number. - - Big numbers are integers larger than 64-bits. Their format - is described in RFC 7049. - - It is output as CBOR major type 2, a binary string, with - optional tag 2 indicating the binary string is a positive big - number. - - Often big numbers are used to represent cryptographic keys, - however, COSE which defines representations for keys chose not - to use this particular type. - */ -static void QCBOREncode_AddPositiveBignum(QCBOREncodeContext *pCtx, UsefulBufC Bytes); - -static void QCBOREncode_AddPositiveBignumToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes); - -static void QCBOREncode_AddPositiveBignumToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes); - - -/** - @brief Add a negative big number to the encoded output. - - @param[in] pCtx The context to initialize. - @param[in] Bytes Pointer and length of the big number. - - Big numbers are integers larger than 64-bits. Their format - is described in RFC 7049. - - It is output as CBOR major type 2, a binary string, with - optional tag 2 indicating the binary string is a negative big - number. - - Often big numbers are used to represent cryptographic keys, - however, COSE which defines representations for keys chose not - to use this particular type. - */ -static void QCBOREncode_AddNegativeBignum(QCBOREncodeContext *pCtx, UsefulBufC Bytes); - -static void QCBOREncode_AddNegativeBignumToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes); - -static void QCBOREncode_AddNegativeBignumToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes); - - -/** - @brief Add a text URI to the encoded output. - - @param[in] pCtx The context to initialize. - @param[in] URI Pointer and length of the URI. - - The format of URI is RFC 3986. - - It is output as CBOR major type 3, a text string, with - optional tag 32 indicating the text string is a URI. - */ -static void QCBOREncode_AddURI(QCBOREncodeContext *pCtx, UsefulBufC URI); - -static void QCBOREncode_AddURIToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC URI); - -static void QCBOREncode_AddURIToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC URI); - - -/** - @brief Add base 64-encoded text to encoded output. - - @param[in] pCtx The context to initialize. - @param[in] B64Text Pointer and length of the base-64 encoded text. - - The text content is base 64 encoded data per RFC 4648. - - It is output as CBOR major type 3, a text string, with - optional tag 34 indicating the text string is a URI. - */ -static void QCBOREncode_AddB64Text(QCBOREncodeContext *pCtx, UsefulBufC B64Text); - -static void QCBOREncode_AddB64TextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC B64Text); - -static void QCBOREncode_AddB64TextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC B64Text); - - -/** - @brief Add base 64URL -encoded URL to encoded output. - - @param[in] pCtx The context to initialize. - @param[in] B64Text Pointer and length of the base-64 encoded text. - - The text content is base 64 URL format encoded text as per RFC 4648. - - It is output as CBOR major type 3, a text string, with - optional tag 33 indicating the text string is a URI. - */ -static void QCBOREncode_AddB64URLText(QCBOREncodeContext *pCtx, UsefulBufC B64Text); - -static void QCBOREncode_AddB64URLTextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC B64Text); - -static void QCBOREncode_AddB64URLTextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC B64Text); - - -/** - @brief Add Perl Compatible Regular Expression - - @param[in] pCtx The context to initialize. - @param[in] Regex Pointer and length of the regular expression. - - The text content is Perl Compatible Regular - Expressions (PCRE) / JavaScript syntax [ECMA262]. - - It is output as CBOR major type 3, a text string, with - optional tag 35 indicating the text string is a regular expression. - */ -static void QCBOREncode_AddRegex(QCBOREncodeContext *pCtx, UsefulBufC Regex); - -static void QCBOREncode_AddRegexToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Regex); - -static void QCBOREncode_AddRegexToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Regex); - - -/** - @brief MIME encoded text to the encoded output. - - @param[in] pCtx The context to initialize. - @param[in] MIMEData Pointer and length of the regular expression. - - The text content is in MIME format per RFC 2045 including the headers. - - It is output as CBOR major type 3, a text string, with - optional tag 36 indicating the text string is MIME data. - */ -static void QCBOREncode_AddMIMEData(QCBOREncodeContext *pCtx, UsefulBufC MIMEData); - -static void QCBOREncode_AddMIMEDataToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC MIMEData); - -static void QCBOREncode_AddMIMEDataToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC MIMEData); - - -/** - @brief Add an RFC 3339 date string - - @param[in] pCtx The encoding context to add the simple value to. - @param[in] szDate Null-terminated string with date to add - - The string szDate should be in the form of RFC 3339 as defined by section - 3.3 in RFC 4287. This is as described in section 2.4.1 in RFC 7049. - - Note that this function doesn't validate the format of the date string - at all. If you add an incorrect format date string, the generated - CBOR will be incorrect and the receiver may not be able to handle it. - - Error handling is the same as QCBOREncode_AddInt64(). - */ -static void QCBOREncode_AddDateString(QCBOREncodeContext *pCtx, const char *szDate); - -static void QCBOREncode_AddDateStringToMap(QCBOREncodeContext *pCtx, const char *szLabel, const char *szDate); - -static void QCBOREncode_AddDateStringToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, const char *szDate); - - -/** - @brief Add a standard boolean. - - @param[in] pCtx The encoding context to add the simple value to. - @param[in] b true or false from stdbool. Anything will result in an error. - - Adds a boolean value as CBOR major type 7. - - Error handling is the same as QCBOREncode_AddInt64(). - */ -static void QCBOREncode_AddBool(QCBOREncodeContext *pCtx, bool b); - -static void QCBOREncode_AddBoolToMap(QCBOREncodeContext *pCtx, const char *szLabel, bool b); - -static void QCBOREncode_AddBoolToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, bool b); - - - -/** - @brief Add a NULL to the encoded output. - - @param[in] pCtx The encoding context to add the simple value to. - - Adds the NULL value as CBOR major type 7. - - This NULL doesn't have any special meaning in CBOR such as a terminating - value for a string or an empty value. - - Error handling is the same as QCBOREncode_AddInt64(). - */ -static void QCBOREncode_AddNULL(QCBOREncodeContext *pCtx); - -static void QCBOREncode_AddNULLToMap(QCBOREncodeContext *pCtx, const char *szLabel); - -static void QCBOREncode_AddNULLToMapN(QCBOREncodeContext *pCtx, int64_t nLabel); - - -/** - @brief Add an "undef" to the encoded output. - - @param[in] pCtx The encoding context to add the simple value to. - - Adds the undef value as CBOR major type 7. - - Note that this value will not translate to JSON. - - This Undef doesn't have any special meaning in CBOR such as a terminating - value for a string or an empty value. - - Error handling is the same as QCBOREncode_AddInt64(). - */ -static void QCBOREncode_AddUndef(QCBOREncodeContext *pCtx); - -static void QCBOREncode_AddUndefToMap(QCBOREncodeContext *pCtx, const char *szLabel); - -static void QCBOREncode_AddUndefToMapN(QCBOREncodeContext *pCtx, int64_t nLabel); - - -/** - @brief Indicates that the next items added are in an array. - - @param[in] pCtx The encoding context to open the array in. - - Arrays are the basic CBOR aggregate or structure type. Call this - function to start or open an array. Then call the various AddXXX - functions to add the items that go into the array. Then call - QCBOREncode_CloseArray() when all items have been added. The data - items in the array can be of any type and can be of mixed types. - - Nesting of arrays and maps is allowed and supported just by calling - QCBOREncode_OpenArray() again before calling CloseArray. While CBOR - has no limit on nesting, this implementation does in order to keep it - smaller and simpler. The limit is QCBOR_MAX_ARRAY_NESTING. This is - the max number of times this can be called without calling - QCBOREncode_CloseArray(). QCBOREncode_Finish() will return - QCBOR_ERR_ARRAY_NESTING_TOO_DEEP when it is called as this function - just sets an error state and returns no value when this occurs. - - If you try to add more than QCBOR_MAX_ITEMS_IN_ARRAY items to a - single array or map, QCBOR_ERR_ARRAY_TOO_LONG will be returned when - QCBOREncode_Finish() is called. - - An array itself must have a label if it is being added to a map. - Note that array elements do not have labels (but map elements do). - - An array itself may be tagged. - */ -static void QCBOREncode_OpenArray(QCBOREncodeContext *pCtx); - -static void QCBOREncode_OpenArrayInMap(QCBOREncodeContext *pCtx, const char *szLabel); - -static void QCBOREncode_OpenArrayInMapN(QCBOREncodeContext *pCtx, int64_t nLabel); - - -/** - @brief Close an open array. - - @param[in] pCtx The context to add to. - - The closes an array opened by QCBOREncode_OpenArray(). It reduces - nesting level by one. All arrays (and maps) must be closed before - calling QCBOREncode_Finish(). - - When an error occurs as a result of this call, the encoder records - the error and enters the error state. The error will be returned when - QCBOREncode_Finish() is called. - - If this has been called more times than QCBOREncode_OpenArray(), then - QCBOR_ERR_TOO_MANY_CLOSES will be returned when QCBOREncode_Finish() - is called. - - If this is called and it is not an array that is currently open, - QCBOR_ERR_CLOSE_MISMATCH will be returned when QCBOREncode_Finish() - is called. - */ -static void QCBOREncode_CloseArray(QCBOREncodeContext *pCtx); - - -/** - @brief Indicates that the next items added are in a map. - - @param[in] pCtx The context to add to. - - See QCBOREncode_OpenArray() for more information, particularly error - handling. - - CBOR maps are an aggregate type where each item in the map consists - of a label and a value. They are similar to JSON objects. - - The value can be any CBOR type including another map. - - The label can also be any CBOR type, but in practice they are - typically, integers as this gives the most compact output. They might - also be text strings which gives readability and translation to JSON. - - Every QCBOREncode_AddXXX() call has once version that is "InMap" for - adding items to maps with string labels and on that is "InMapN" that - is for adding with integer labels. - - RFC 7049 uses the term "key" instead of "label". - - If you wish to use map labels that are neither integer labels or - text strings, then just call the QCBOREncode_AddXXX() function - explicitly to add the label. Then call it again to add the value. - - See the RFC7049 for a lot more information on creating maps. - */ -static void QCBOREncode_OpenMap(QCBOREncodeContext *pCtx); - -static void QCBOREncode_OpenMapInMap(QCBOREncodeContext *pCtx, const char *szLabel); - -static void QCBOREncode_OpenMapInMapN(QCBOREncodeContext *pCtx, int64_t nLabel); - - - -/** - @brief Close an open map. - - @param[in] pCtx The context to add to. - - The closes a map opened by QCBOREncode_OpenMap(). It reduces nesting - level by one. - - When an error occurs as a result of this call, the encoder records - the error and enters the error state. The error will be returned when - QCBOREncode_Finish() is called. - - If this has been called more times than QCBOREncode_OpenMap(), - then QCBOR_ERR_TOO_MANY_CLOSES will be returned when - QCBOREncode_Finish() is called. - - If this is called and it is not a map that is currently - open, QCBOR_ERR_CLOSE_MISMATCH will be returned when QCBOREncode_Finish() - is called. - */ -static void QCBOREncode_CloseMap(QCBOREncodeContext *pCtx); - - -/** - @brief Indicate start of encoded CBOR to be wrapped in a bstr. - - @param[in] pCtx The context to add to. - - All added encoded items between this call and a call to - QCBOREncode_CloseBstrWrap() will be wrapped in a bstr. They will - appear in the final output as a byte string. That byte string will - contain encoded CBOR. - - The typical use case is for encoded CBOR that is to be - cryptographically hashed, as part of a COSE (RFC 8152) - implementation. This avoids having to encode the items first in one - buffer (e.g., the COSE payload) and then add that buffer as a bstr to - another encoding (e.g. the COSE to-be-signed bytes, the - Sig_structure) potentially saving a lot of memory. - - When constructing cryptographically signed CBOR objects, maps or - arrays, they typically are encoded normally and then wrapped as a - byte string. The COSE standard for example does this. The wrapping is - simply treating the encoded CBOR map as a byte string. - - The stated purpose of this wrapping is to prevent code relaying the - signed data but not verifying it from tampering with the signed data - thus making the signature unverifiable. It is also quite beneficial - for the signature verification code. Standard CBOR parsers usually do - not give access to partially parsed CBOR as would be need to check - the signature of some CBOR. With this wrapping, standard CBOR parsers - can be used to get to all the data needed for a signature - verification. - */ -static void QCBOREncode_BstrWrap(QCBOREncodeContext *pCtx); - -static void QCBOREncode_BstrWrapInMap(QCBOREncodeContext *pCtx, const char *szLabel); - -static void QCBOREncode_BstrWrapInMapN(QCBOREncodeContext *pCtx, int64_t nLabel); - - -/** - @brief Close a wrapping bstr. - - @param[in] pCtx The context to add to. - @param[out] pWrappedCBOR UsefulBufC containing wrapped bytes - - The closes a wrapping bstr opened by QCBOREncode_BstrWrap(). It reduces - nesting level by one. - - A pointer and length of the enclosed encoded CBOR is returned in - *pWrappedCBOR if it is not NULL. The main purpose of this is so this - data can be hashed (e.g., with SHA-256) as part of a COSE (RFC 8152) - implementation. **WARNING**, this pointer and length should be used - right away before any other calls to QCBOREncode_xxxx() as they will - move data around and the pointer and length will no longer be to the - correct encoded CBOR. - - When an error occurs as a result of this call, the encoder records - the error and enters the error state. The error will be returned when - QCBOREncode_Finish() is called. - - If this has been called more times then QCBOREncode_BstrWrap(), - then QCBOR_ERR_TOO_MANY_CLOSES will be returned when - QCBOREncode_Finish() is called. - - If this is called and it is not a wrapping bstr that is currently - open, QCBOR_ERR_CLOSE_MISMATCH will be returned when QCBOREncode_Finish() - is called. - */ -static void QCBOREncode_CloseBstrWrap(QCBOREncodeContext *pCtx, UsefulBufC *pWrappedCBOR); - - -/** - @brief Add some already-encoded CBOR bytes. - - @param[in] pCtx The context to add to. - @param[in] Encoded The already-encoded CBOR to add to the context. - - The encoded CBOR being added must be fully conforming CBOR. It must - be complete with no arrays or maps that are incomplete. While this - encoder doesn't ever produce indefinite lengths, it is OK for the - raw CBOR added here to have indefinite lengths. - - The raw CBOR added here is not checked in anyway. If it is not - conforming or has open arrays or such, the final encoded CBOR - will probably be wrong or not what was intended. - - If the encoded CBOR being added here contains multiple items, they - must be enclosed in a map or array. At the top level the raw - CBOR must be a single data item. - */ -static void QCBOREncode_AddEncoded(QCBOREncodeContext *pCtx, UsefulBufC Encoded); - -static void QCBOREncode_AddEncodedToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Encoded); - -static void QCBOREncode_AddEncodedToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Encoded); - - -/** - @brief Get the encoded result. - - @param[in] pCtx The context to finish encoding with. - @param[out] pEncodedCBOR Pointer and length of encoded CBOR. - - @return - One of the CBOR error codes. - - If this returns success QCBOR_SUCCESS the encoding was a success and - the return length is correct and complete. - - If no buffer was passed to QCBOR_Init(), then only the length and - number of items was computed. The length is in - pEncodedCBOR->Bytes.len. pEncodedCBOR->Bytes.ptr is NULL. - - If a buffer was passed, then pEncodedCBOR->Bytes.ptr is the same as - the buffer passed to QCBOR_Init() and contains the encoded CBOR - and the length is filled in. - - If an error is returned, the buffer may have partially encoded - incorrect CBOR in it and it should not be used. Likewise, the length - may be incorrect and should not be used. - - Note that the error could have occurred in one of the many - QCBOR_AddXXX calls long before QCBOREncode_Finish() was called. This - error handling approach reduces the CBOR implementation size, but makes - debugging a problem a little more difficult. - */ -QCBORError QCBOREncode_Finish(QCBOREncodeContext *pCtx, UsefulBufC *pEncodedCBOR); - - -/** - @brief Get the encoded CBOR and error status. - - @param[in] pCtx The context to finish encoding with. - @param[out] uEncodedLen The length of the encoded or potentially encoded CBOR in bytes. - - @return - One of the CBOR error codes. - - If this returns success QCBOR_SUCCESS the encoding was a success and - the return length is correct and complete. - - If no buffer was passed to QCBOR_Init(), then only the length was - computed. If a buffer was passed, then the encoded CBOR is in the - buffer. - - If an error is returned, the buffer may have partially encoded - incorrect CBOR in it and it should not be used. Likewise, the length - may be incorrect and should not be used. - - Note that the error could have occurred in one of the many - QCBOR_AddXXX calls long before QCBOREncode_Finish() was called. This - error handling reduces the CBOR implementation size, but makes - debugging harder. - */ -QCBORError QCBOREncode_FinishGetSize(QCBOREncodeContext *pCtx, size_t *uEncodedLen); - - - - - - -/** - QCBORDecodeContext is the data type that holds context decoding the - data items for some received CBOR. It is about 100 bytes, so it can go - on the stack. The contents are opaque, and the caller should not - access any internal items. A context may be re used serially as long - as it is re initialized. - */ -typedef struct _QCBORDecodeContext QCBORDecodeContext; - - -/** - Initialize the CBOR decoder context. - - @param[in] pCtx The context to initialize. - @param[in] EncodedCBOR The buffer with CBOR encoded bytes to be decoded. - @param[in] nMode One of QCBOR_DECODE_MODE_xxx - - Initialize context for a pre-order travesal of the encoded CBOR tree. - - Most CBOR decoding can be completed by calling this function to start - and QCBORDecode_GetNext() in a loop. - - If indefinite length strings are to be decoded, then - QCBORDecode_SetMemPool() or QCBORDecode_SetUpAllocator() must be - called to set up a string allocator. - - If tags other than built-in tags are to be recognized, then - QCBORDecode_SetCallerAddedTagMap() must be called. The built-in tags - are those for which a macro of the form CBOR_TAG_XXX is defined. - - Three decoding modes are supported. In normal mode, - QCBOR_DECODE_MODE_NORMAL, maps are decoded and strings and ints are - accepted as map labels. If a label is other than these, the error - QCBOR_ERR_MAP_LABEL_TYPE is returned by QCBORDecode_GetNext(). - - In strings-only mode, QCBOR_DECODE_MODE_MAP_STRINGS_ONLY, only text - strings are accepted for map labels. This lines up with CBOR that - converts to JSON. The error QCBOR_ERR_MAP_LABEL_TYPE is returned by - QCBORDecode_GetNext() if anything but a text string label is - encountered. - - In QCBOR_DECODE_MODE_MAP_AS_ARRAY maps are treated as special arrays. - They will be return with special uDataType QCBOR_TYPE_MAP_AS_ARRAY - and uCount, the number of items, will be double what it would be - for a normal map because the labels are also counted. This mode - is useful for decoding CBOR that has labels that are not - integers or text strings, but the caller must manage much of - the map decoding. - */ -void QCBORDecode_Init(QCBORDecodeContext *pCtx, UsefulBufC EncodedCBOR, QCBORDecodeMode nMode); - - -/** - @brief Set up the MemPool string allocator for indefinite length strings. - - @param[in] pCtx The decode context. - @param[in] MemPool The pointer and length of the memory pool. - @param[in] bAllStrings true means to put even definite length strings in the pool. - - @return error if the MemPool was less than QCBOR_DECODE_MIN_MEM_POOL_SIZE. - - Indefinite length strings (text and byte) cannot be decoded unless - there is a string allocator configured. MemPool is a simple built-in - string allocator that allocates bytes from a memory pool handed to it - by calling this function. The memory pool is just a pointer and - length for some block of memory that is to be used for string - allocation. It can come from the stack, heap or other. - - The memory pool must be QCBOR_DECODE_MIN_MEM_POOL_SIZE plus space for - all the strings allocated. There is no overhead per string allocated - - This memory pool is used for all indefinite length strings that are - text strings or byte strings, including strings used as labels. - - The pointers to strings in QCBORItem will point into the memory pool set - here. They do not need to be individually freed. Just discard the buffer - when they are no longer needed. - - If bAllStrings is set, then the size will be the overhead plus the - space to hold **all** strings, definite and indefinite length, value - or label. The advantage of this is that after the decode is complete, - the original memory holding the encoded CBOR does not need to remain - valid. - - If this function is never called because there is no need to support - indefinite length strings, the MemPool implementation should be - dead-stripped by the loader and not add to code size. - */ -QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pCtx, UsefulBuf MemPool, bool bAllStrings); - - -/** - @brief Sets up a custom string allocator for indefinite length strings - - @param[in] pCtx The decoder context to set up an allocator for - @param[in] pAllocator The string allocator "object" - - See QCBORStringAllocator for the requirements of the string allocator. - - Typically, this is used if the simple MemPool allocator isn't desired. - - A malloc based string allocator can be obtained by calling - QCBOR_DMalloc(). This function is supply separately from qcbor - to keep qcbor smaller and neater. It is in a separate - GitHub repository. - - You can also write your own allocator. Create the allocate, free, - and destroy functions and put pointers to them in a QCBORStringAllocator. - */ -void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pCtx, const QCBORStringAllocator *pAllocator, bool bAllStrings); - - -/** - @brief Configure list of caller selected tags to be recognized - - @param[in] pCtx The decode context. - @param[out] pTagList Structure holding the list of tags to configure - - This is used to tell the decoder about tags beyond those that are - built-in that should be recognized. The built-in tags are those - with macros of the form CBOR_TAG_XXX. - - See description of QCBORTagListIn. - */ -void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pCtx, const QCBORTagListIn *pTagList); - - -/** - @brief Gets the next item (integer, byte string, array...) in pre order traversal of CBOR tree - - @param[in] pCtx The decoder context. - @param[out] pDecodedItem Holds the CBOR item just decoded. - - @return 0 or error. All errors except QCBOR_ERR_TOO_MANY_TAGS - and QCBOR_ERR_STRING_ALLOCATE indicate that the CBOR input - could not be decoded. In most cases - this is because the CBOR is invalid. In a few cases - (QCBOR_ERR_ARRAY_NESTING_TOO_DEEP, QCBOR_ERR_INT_OVERFLOW, - QCBOR_ERR_DATE_OVERFLOW) it is because the CBOR is beyond - the limits of what this implementation can handle. - QCBOR_ERR_NO_STRING_ALLOCATOR indicates CBOR that cannot - be handled unless a string allocator is configured. - QCBOR_ERR_MAP_LABEL_TYPE is in a way a limitation of - this implementation, but can be avoided by decoding - in QCBOR_DECODE_MODE_MAP_AS_ARRAY mode. - - pDecodedItem is filled in with the value parsed. Generally, the - following data is returned in the structure. - - - The data type in uDataType which indicates which member of the val - union the data is in. This decoder figures out the type based on the - CBOR major type, the CBOR "additionalInfo", the CBOR optional tags - and the value of the integer. - - - The value of the item, which might be an integer, a pointer and a - length, the count of items in an array, a floating-point number or - other. - - - The nesting level for maps and arrays. - - - The label for an item in a map, which may be a text or byte string or an integer. - - - The CBOR optional tag or tags. - - See documentation on in the data type QCBORItem for all the details - on what is returned. - - This function also handles arrays and maps. When first encountered a - QCBORItem will be returned with major type CBOR_MAJOR_TYPE_ARRAY or - CBOR_MAJOR_TYPE_ARRAY_MAP. QCBORItem.val.uCount will indicate the number - of Items in the array or map. Typically, an implementation will call - QCBORDecode_GetNext() in a for loop to fetch them all. When decoding - indefinite length maps and arrays, QCBORItem.val.uCount is UINT16_MAX - and uNextNestLevel must be used to know when the end of a map - or array is reached. - - Nesting level 0 is the outside top-most nesting level. For example, in - a CBOR structure with two items, an integer and a byte string only, - both would be at nesting level 0. A CBOR structure with an array - open, an integer and a byte string, would have the integer and byte - string as nesting level 1. - - Here is an example of how the nesting level is reported with no arrays - or maps at all - - @verbatim - CBOR Structure Nesting Level - Integer 0 - Byte String 0 - @endverbatim - - Here is an example of how the nesting level is reported with an a simple - array and some top-level items. - - @verbatim - Integer 0 - Array (with 2 items) 0 - Byte String 1 - Byte string 1 - Integer 0 - @endverbatim - - - Here's a more complex example - @verbatim - - Map with 2 items 0 - Text string 1 - Array with 3 integers 1 - integer 2 - integer 2 - integer 2 - text string 1 - byte string 1 - @endverbatim - - In QCBORItem, uNextNestLevel is the nesting level for the next call - to QCBORDecode_GetNext(). It indicates if any maps or arrays were closed - out during the processing of the just-fecthed QCBORItem. This processing - includes a look-ahead for any breaks that close out indefinite length - arrays or maps. This value is needed to be able to understand the - hierarchical structure. If uNextNestLevel is not equal to uNestLevel - the end of the current map or array has been encountered. This - works the same for both definite and indefinite length arrays. - - Most uses of this decoder will not need to do anything extra for - tag handling. The built-in tags, those with a macro of the form - CBOR_TAG_XXXX, will be enough. - - If tags beyond built-in tags are to be recognized, they must be - configured by calling QCBORDecode_SetCallerConfiguredTags(). If - a tag is not recognized it is silently ignored. - - Several tagged types are automatically recognized and decoded and - returned in their decoded form. - - To find out if a QCBORItem was tagged with a particular tag - call QCBORDecode_IsTagged(). This works only for built-in - tags and caller-configured tags. - - To get the full list of tags on an Item without having to - pre-configure any predetermined list of tags use - QCBORDecode_GetNextWithTags(). - */ -QCBORError QCBORDecode_GetNext(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem); - - -/** - @brief Gets the next item including full list of tags for item - - @param[in] pCtx The decoder context. - @param[out] pDecodedItem Holds the CBOR item just decoded. - @param[in,out] pTagList On input array to put tags in; on output the tags on this item. - - @return 0 or error. - - This works the same as QCBORDecode_GetNext() except that it also returns - the full list of tags for the data item. This function should only - be needed when parsing CBOR to print it out or convert it to some other - format. It should not be needed in an actual CBOR protocol implementation. - - Tags will be returned here whether or not they are in the built-in or - caller-configured tag lists. - - CBOR has no upper bound of limit on the number of tags that can be - associated with a data item. In practice the number of tags on an item - will usually be small, perhaps less than five. This will return an error - if the array in pTagList is too small to hold all the tags for an item. - - (This function is separate from QCBORDecode_GetNext() so as to not have to - make QCBORItem large enough to be able to hold a full list of tags. Even a list of - five tags would nearly double its size because tags can be a uint64_t). - */ -QCBORError QCBORDecode_GetNextWithTags(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem, QCBORTagListOut *pTagList); - - -/** - @brief Determine if a CBOR item was tagged with a particular tag - - @param[in] pCtx The decoder context. - @param[in] pItem The CBOR item to check - @param[in] uTag The tag to check - - @return 1 if it was tagged, 0 if not - - QCBORDecode_GetNext() processes tags by looking them up - in two lists and setting a bit corresponding to the tag - in uTagBits in the QCBORItem. To find out if a - QCBORItem was tagged with a particular tag, call - this function. It handles the mapping between - the two lists of tags and the bits set for it. - - The first tag list is the built-in tags, those - with a macro of the form CBOR_TAG_XXX in this - header file. There are up to 48 of these, - corresponding to the lower 48 tag bits. - - The other optional tag list is the ones - the caller configured using QCBORDecode_SetCallerConfiguredTagList() - There are QCBOR_MAX_CUSTOM_TAGS (16) of these corresponding to the - upper 16 tag bits. - - See also QCBORDecode_GetTags() and QCBORDecode_GetNextWithTags(). - */ -int QCBORDecode_IsTagged(QCBORDecodeContext *pCtx, const QCBORItem *pItem, uint64_t uTag); - - -/** - Check whether all the bytes have been decoded and maps and arrays closed. - - @param[in] pCtx The context to check - - @return QCBOR_SUCCESS or error - - This tells you if all the bytes given to QCBORDecode_Init() have - been consumed and whether all maps and arrays were closed. - The decode is considered to be incorrect or incomplete if not - and an error will be returned. - */ -QCBORError QCBORDecode_Finish(QCBORDecodeContext *pCtx); - - - - -/** - Convert int64_t to smaller int's safely - - @param [in] src An int64_t - @param [out] dest A smaller sized int to convert to - - @return 0 on success -1 if not - - When decoding an integer, the CBOR decoder will return the value as an - int64_t unless the integer is in the range of INT64_MAX and - UINT64_MAX. That is, unless the value is so large that it can only be - represented as a uint64_t, it will be an int64_t. - - CBOR itself doesn't size the individual integers it carries at - all. The only limits it puts on the major integer types is that they - are 8 bytes or less in length. Then encoders like this one use the - smallest number of 1, 2, 4 or 8 bytes to represent the integer based - on its value. There is thus no notion that one data item in CBOR is - an 1 byte integer and another is a 4 byte integer. - - The interface to this CBOR encoder only uses 64-bit integers. Some - CBOR protocols or implementations of CBOR protocols may not want to - work with something smaller than a 64-bit integer. Perhaps an array - of 1000 integers needs to be sent and none has a value larger than - 50,000 and are represented as uint16_t. - - The sending / encoding side is easy. Integers are temporarily widened - to 64-bits as a parameter passing through QCBOREncode_AddInt64() and - encoded in the smallest way possible for their value, possibly in - less than an uint16_t. - - On the decoding side the integers will be returned at int64_t even if - they are small and were represented by only 1 or 2 bytes in the - encoded CBOR. The functions here will convert integers to a small - representation with an overflow check. - - (The decoder could have support 8 different integer types and - represented the integer with the smallest type automatically, but - this would have made the decoder more complex and code calling the - decoder more complex in most use cases. In most use cases on 64-bit - machines it is no burden to carry around even small integers as - 64-bit values). - */ -static inline int QCBOR_Int64ToInt32(int64_t src, int32_t *dest) -{ - if(src > INT32_MAX || src < INT32_MIN) { - return -1; - } else { - *dest = (int32_t) src; - } - return 0; -} - -static inline int QCBOR_Int64ToInt16(int64_t src, int16_t *dest) -{ - if(src > INT16_MAX || src < INT16_MIN) { - return -1; - } else { - *dest = (int16_t) src; - } - return 0; -} - -static inline int QCBOR_Int64ToInt8(int64_t src, int8_t *dest) -{ - if(src > INT8_MAX || src < INT8_MIN) { - return -1; - } else { - *dest = (int8_t) src; - } - return 0; -} - -static inline int QCBOR_Int64ToUInt32(int64_t src, uint32_t *dest) -{ - if(src > UINT32_MAX || src < 0) { - return -1; - } else { - *dest = (uint32_t) src; - } - return 0; -} - -static inline int QCBOR_Int64UToInt16(int64_t src, uint16_t *dest) -{ - if(src > UINT16_MAX || src < 0) { - return -1; - } else { - *dest = (uint16_t) src; - } - return 0; -} - -static inline int QCBOR_Int64ToUInt8(int64_t src, uint8_t *dest) -{ - if(src > UINT8_MAX || src < 0) { - return -1; - } else { - *dest = (uint8_t) src; - } - return 0; -} - -static inline int QCBOR_Int64ToUInt64(int64_t src, uint64_t *dest) -{ - if(src > 0) { - return -1; - } else { - *dest = (uint64_t) src; - } - return 0; -} - - - - - -/* =========================================================================== - BEGINNING OF PRIVATE INLINE IMPLEMENTATION - - =========================================================================== */ - -/** - @brief Semi-private method to add a buffer full of bytes to encoded output - - @param[in] pCtx The encoding context to add the integer to. - @param[in] uMajorType The CBOR major type of the bytes. - @param[in] Bytes The bytes to add. - - Use QCBOREncode_AddText() or QCBOREncode_AddBytes() or - QCBOREncode_AddEncoded() instead. They are inline functions - that call this and supply the correct major type. This function - is public to make the inline functions work to keep the overall - code size down and because the C language has no way to make - it private. - - If this is called the major type should be CBOR_MAJOR_TYPE_TEXT_STRING, - CBOR_MAJOR_TYPE_BYTE_STRING or CBOR_MAJOR_NONE_TYPE_RAW. The last - one is special for adding already-encoded CBOR. - */ -void QCBOREncode_AddBuffer(QCBOREncodeContext *pCtx, uint8_t uMajorType, UsefulBufC Bytes); - - -/** - @brief Semi-private method to open a map, array or bstr wrapped CBOR - - @param[in] pCtx The context to add to. - @param[in] uMajorType The major CBOR type to close - - Call QCBOREncode_OpenArray(), QCBOREncode_OpenMap() or - QCBOREncode_BstrWrap() instead of this. - */ -void QCBOREncode_OpenMapOrArray(QCBOREncodeContext *pCtx, uint8_t uMajorType); - - -/** - @brief Semi-private method to close a map, array or bstr wrapped CBOR - - @param[in] pCtx The context to add to. - @param[in] uMajorType The major CBOR type to close - @param[out] pWrappedCBOR UsefulBufC containing wrapped bytes - - Call QCBOREncode_CloseArray(), QCBOREncode_CloseMap() or - QCBOREncode_CloseBstrWrap() instead of this. - */ -void QCBOREncode_CloseMapOrArray(QCBOREncodeContext *pCtx, uint8_t uMajorType, UsefulBufC *pWrappedCBOR); - - -/** - @brief Semi-private method to add simple types. - - @param[in] pCtx The encoding context to add the simple value to. - @param[in] uSize Minimum encoding size for uNum. Usually 0. - @param[in] uNum One of CBOR_SIMPLEV_FALSE through _UNDEF or other. - - This is used to add simple types like true and false. - - Call QCBOREncode_AddBool(), QCBOREncode_AddNULL(), QCBOREncode_AddUndef() - instead of this. - - This function can add simple values that are not defined by CBOR yet. This expansion - point in CBOR should not be used unless they are standardized. - - Error handling is the same as QCBOREncode_AddInt64(). - */ -void QCBOREncode_AddType7(QCBOREncodeContext *pCtx, size_t uSize, uint64_t uNum); - - -static inline void QCBOREncode_AddInt64ToMap(QCBOREncodeContext *pCtx, const char *szLabel, int64_t uNum) -{ - QCBOREncode_AddBuffer(pCtx, CBOR_MAJOR_TYPE_TEXT_STRING, UsefulBuf_FromSZ(szLabel)); // AddSZString not defined yet - QCBOREncode_AddInt64(pCtx, uNum); -} - -static inline void QCBOREncode_AddInt64ToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, int64_t uNum) -{ - QCBOREncode_AddInt64(pCtx, nLabel); - QCBOREncode_AddInt64(pCtx, uNum); -} - - -static inline void QCBOREncode_AddUInt64ToMap(QCBOREncodeContext *pCtx, const char *szLabel, uint64_t uNum) -{ - QCBOREncode_AddBuffer(pCtx, CBOR_MAJOR_TYPE_TEXT_STRING, UsefulBuf_FromSZ(szLabel)); // AddSZString not defined yet - QCBOREncode_AddUInt64(pCtx, uNum); -} - -static inline void QCBOREncode_AddUInt64ToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, uint64_t uNum) -{ - QCBOREncode_AddInt64(pCtx, nLabel); - QCBOREncode_AddUInt64(pCtx, uNum); -} - - -static inline void QCBOREncode_AddText(QCBOREncodeContext *pCtx, UsefulBufC Text) -{ - QCBOREncode_AddBuffer(pCtx, CBOR_MAJOR_TYPE_TEXT_STRING, Text); -} - -static inline void QCBOREncode_AddTextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Text) -{ - QCBOREncode_AddText(pCtx, UsefulBuf_FromSZ(szLabel)); // AddSZString not defined yet - QCBOREncode_AddText(pCtx, Text); -} - -static inline void QCBOREncode_AddTextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Text) -{ - QCBOREncode_AddInt64(pCtx, nLabel); - QCBOREncode_AddText(pCtx, Text); -} - - -inline static void QCBOREncode_AddSZString(QCBOREncodeContext *pCtx, const char *szString) -{ - QCBOREncode_AddText(pCtx, UsefulBuf_FromSZ(szString)); -} - -static inline void QCBOREncode_AddSZStringToMap(QCBOREncodeContext *pCtx, const char *szLabel, const char *szString) -{ - QCBOREncode_AddSZString(pCtx, szLabel); - QCBOREncode_AddSZString(pCtx, szString); -} - -static inline void QCBOREncode_AddSZStringToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, const char *szString) -{ - QCBOREncode_AddInt64(pCtx, nLabel); - QCBOREncode_AddSZString(pCtx, szString); -} - - -static inline void QCBOREncode_AddDoubleToMap(QCBOREncodeContext *pCtx, const char *szLabel, double dNum) -{ - QCBOREncode_AddSZString(pCtx, szLabel); - QCBOREncode_AddDouble(pCtx, dNum); -} - -static inline void QCBOREncode_AddDoubleToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, double dNum) -{ - QCBOREncode_AddInt64(pCtx, nLabel); - QCBOREncode_AddDouble(pCtx, dNum); -} - - -static inline void QCBOREncode_AddDateEpoch(QCBOREncodeContext *pCtx, int64_t date) -{ - QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_EPOCH); - QCBOREncode_AddInt64(pCtx, date); -} - -static inline void QCBOREncode_AddDateEpochToMap(QCBOREncodeContext *pCtx, const char *szLabel, int64_t date) -{ - QCBOREncode_AddSZString(pCtx, szLabel); - QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_EPOCH); - QCBOREncode_AddInt64(pCtx, date); -} - -static inline void QCBOREncode_AddDateEpochToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, int64_t date) -{ - QCBOREncode_AddInt64(pCtx, nLabel); - QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_EPOCH); - QCBOREncode_AddInt64(pCtx, date); -} - - -static inline void QCBOREncode_AddBytes(QCBOREncodeContext *pCtx, UsefulBufC Bytes) -{ - QCBOREncode_AddBuffer(pCtx, CBOR_MAJOR_TYPE_BYTE_STRING, Bytes); -} - -static inline void QCBOREncode_AddBytesToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes) -{ - QCBOREncode_AddSZString(pCtx, szLabel); - QCBOREncode_AddBytes(pCtx, Bytes); -} - -static inline void QCBOREncode_AddBytesToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes) -{ - QCBOREncode_AddInt64(pCtx, nLabel); - QCBOREncode_AddBytes(pCtx, Bytes); -} - - -static inline void QCBOREncode_AddBinaryUUID(QCBOREncodeContext *pCtx, UsefulBufC Bytes) -{ - QCBOREncode_AddTag(pCtx, CBOR_TAG_BIN_UUID); - QCBOREncode_AddBytes(pCtx, Bytes); -} - -static inline void QCBOREncode_AddBinaryUUIDToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes) -{ - QCBOREncode_AddSZString(pCtx, szLabel); - QCBOREncode_AddTag(pCtx, CBOR_TAG_BIN_UUID); - QCBOREncode_AddBytes(pCtx, Bytes); -} - -static inline void QCBOREncode_AddBinaryUUIDToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes) -{ - QCBOREncode_AddInt64(pCtx, nLabel); - QCBOREncode_AddTag(pCtx, CBOR_TAG_BIN_UUID); - QCBOREncode_AddBytes(pCtx, Bytes); -} - - -static inline void QCBOREncode_AddPositiveBignum(QCBOREncodeContext *pCtx, UsefulBufC Bytes) -{ - QCBOREncode_AddTag(pCtx, CBOR_TAG_POS_BIGNUM); - QCBOREncode_AddBytes(pCtx, Bytes); -} - -static inline void QCBOREncode_AddPositiveBignumToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes) -{ - QCBOREncode_AddSZString(pCtx, szLabel); - QCBOREncode_AddTag(pCtx, CBOR_TAG_POS_BIGNUM); - QCBOREncode_AddBytes(pCtx, Bytes); -} - -static inline void QCBOREncode_AddPositiveBignumToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes) -{ - QCBOREncode_AddInt64(pCtx, nLabel); - QCBOREncode_AddTag(pCtx, CBOR_TAG_POS_BIGNUM); - QCBOREncode_AddBytes(pCtx, Bytes); -} - - -static inline void QCBOREncode_AddNegativeBignum(QCBOREncodeContext *pCtx, UsefulBufC Bytes) -{ - QCBOREncode_AddTag(pCtx, CBOR_TAG_NEG_BIGNUM); - QCBOREncode_AddBytes(pCtx, Bytes); -} - -static inline void QCBOREncode_AddNegativeBignumToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes) -{ - QCBOREncode_AddSZString(pCtx, szLabel); - QCBOREncode_AddTag(pCtx, CBOR_TAG_NEG_BIGNUM); - QCBOREncode_AddBytes(pCtx, Bytes); -} - -static inline void QCBOREncode_AddNegativeBignumToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes) -{ - QCBOREncode_AddInt64(pCtx, nLabel); - QCBOREncode_AddTag(pCtx, CBOR_TAG_NEG_BIGNUM); - QCBOREncode_AddBytes(pCtx, Bytes); -} - - -static inline void QCBOREncode_AddURI(QCBOREncodeContext *pCtx, UsefulBufC URI) -{ - QCBOREncode_AddTag(pCtx, CBOR_TAG_URI); - QCBOREncode_AddText(pCtx, URI); -} - -static inline void QCBOREncode_AddURIToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC URI) -{ - QCBOREncode_AddSZString(pCtx, szLabel); - QCBOREncode_AddTag(pCtx, CBOR_TAG_URI); - QCBOREncode_AddText(pCtx, URI); -} - -static inline void QCBOREncode_AddURIToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC URI) -{ - QCBOREncode_AddInt64(pCtx, nLabel); - QCBOREncode_AddTag(pCtx, CBOR_TAG_URI); - QCBOREncode_AddText(pCtx, URI); -} - - - -static inline void QCBOREncode_AddB64Text(QCBOREncodeContext *pCtx, UsefulBufC B64Text) -{ - QCBOREncode_AddTag(pCtx, CBOR_TAG_B64); - QCBOREncode_AddText(pCtx, B64Text); -} - -static inline void QCBOREncode_AddB64TextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC B64Text) -{ - QCBOREncode_AddSZString(pCtx, szLabel); - QCBOREncode_AddTag(pCtx, CBOR_TAG_B64); - QCBOREncode_AddText(pCtx, B64Text); -} - -static inline void QCBOREncode_AddB64TextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC B64Text) -{ - QCBOREncode_AddInt64(pCtx, nLabel); - QCBOREncode_AddTag(pCtx, CBOR_TAG_B64); - QCBOREncode_AddText(pCtx, B64Text); -} - - -static inline void QCBOREncode_AddB64URLText(QCBOREncodeContext *pCtx, UsefulBufC B64Text) -{ - QCBOREncode_AddTag(pCtx, CBOR_TAG_B64URL); - QCBOREncode_AddText(pCtx, B64Text); -} - -static inline void QCBOREncode_AddB64URLTextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC B64Text) -{ - QCBOREncode_AddSZString(pCtx, szLabel); - QCBOREncode_AddTag(pCtx, CBOR_TAG_B64URL); - QCBOREncode_AddText(pCtx, B64Text); -} - -static inline void QCBOREncode_AddB64URLTextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC B64Text) -{ - QCBOREncode_AddInt64(pCtx, nLabel); - QCBOREncode_AddTag(pCtx, CBOR_TAG_B64URL); - QCBOREncode_AddText(pCtx, B64Text); -} - - -static inline void QCBOREncode_AddRegex(QCBOREncodeContext *pCtx, UsefulBufC Bytes) -{ - QCBOREncode_AddTag(pCtx, CBOR_TAG_REGEX); - QCBOREncode_AddText(pCtx, Bytes); -} - -static inline void QCBOREncode_AddRegexToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes) -{ - QCBOREncode_AddSZString(pCtx, szLabel); - QCBOREncode_AddTag(pCtx, CBOR_TAG_REGEX); - QCBOREncode_AddText(pCtx, Bytes); -} - -static inline void QCBOREncode_AddRegexToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes) -{ - QCBOREncode_AddInt64(pCtx, nLabel); - QCBOREncode_AddTag(pCtx, CBOR_TAG_REGEX); - QCBOREncode_AddText(pCtx, Bytes); -} - - -static inline void QCBOREncode_AddMIMEData(QCBOREncodeContext *pCtx, UsefulBufC MIMEData) -{ - QCBOREncode_AddTag(pCtx, CBOR_TAG_MIME); - QCBOREncode_AddText(pCtx, MIMEData); -} - -static inline void QCBOREncode_AddMIMEDataToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC MIMEData) -{ - QCBOREncode_AddSZString(pCtx, szLabel); - QCBOREncode_AddTag(pCtx, CBOR_TAG_MIME); - QCBOREncode_AddText(pCtx, MIMEData); -} - -static inline void QCBOREncode_AddMIMEDataToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC MIMEData) -{ - QCBOREncode_AddInt64(pCtx, nLabel); - QCBOREncode_AddTag(pCtx, CBOR_TAG_MIME); - QCBOREncode_AddText(pCtx, MIMEData); -} - - -static inline void QCBOREncode_AddDateString(QCBOREncodeContext *pCtx, const char *szDate) -{ - QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_STRING); - QCBOREncode_AddSZString(pCtx, szDate); -} - -static inline void QCBOREncode_AddDateStringToMap(QCBOREncodeContext *pCtx, const char *szLabel, const char *szDate) -{ - QCBOREncode_AddSZString(pCtx, szLabel); - QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_STRING); - QCBOREncode_AddSZString(pCtx, szDate); -} - -static inline void QCBOREncode_AddDateStringToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, const char *szDate) -{ - QCBOREncode_AddInt64(pCtx, nLabel); - QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_STRING); - QCBOREncode_AddSZString(pCtx, szDate); -} - - -static inline void QCBOREncode_AddSimple(QCBOREncodeContext *pCtx, uint64_t uNum) -{ - QCBOREncode_AddType7(pCtx, 0, uNum); -} - -static inline void QCBOREncode_AddSimpleToMap(QCBOREncodeContext *pCtx, const char *szLabel, uint8_t uSimple) -{ - QCBOREncode_AddSZString(pCtx, szLabel); - QCBOREncode_AddSimple(pCtx, uSimple); -} - -static inline void QCBOREncode_AddSimpleToMapN(QCBOREncodeContext *pCtx, int nLabel, uint8_t uSimple) -{ - QCBOREncode_AddInt64(pCtx, nLabel); - QCBOREncode_AddSimple(pCtx, uSimple); -} - - -static inline void QCBOREncode_AddBool(QCBOREncodeContext *pCtx, bool b) -{ - uint8_t uSimple = CBOR_SIMPLEV_FALSE; - if(b) { - uSimple = CBOR_SIMPLEV_TRUE; - } - QCBOREncode_AddSimple(pCtx, uSimple); -} - -static inline void QCBOREncode_AddBoolToMap(QCBOREncodeContext *pCtx, const char *szLabel, bool b) -{ - QCBOREncode_AddSZString(pCtx, szLabel); - QCBOREncode_AddBool(pCtx, b); -} - -static inline void QCBOREncode_AddBoolToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, bool b) -{ - QCBOREncode_AddInt64(pCtx, nLabel); - QCBOREncode_AddBool(pCtx, b); -} - - -static inline void QCBOREncode_AddNULL(QCBOREncodeContext *pCtx) -{ - QCBOREncode_AddSimple(pCtx, CBOR_SIMPLEV_NULL); -} - -static inline void QCBOREncode_AddNULLToMap(QCBOREncodeContext *pCtx, const char *szLabel) -{ - QCBOREncode_AddSZString(pCtx, szLabel); - QCBOREncode_AddNULL(pCtx); -} - -static inline void QCBOREncode_AddNULLToMapN(QCBOREncodeContext *pCtx, int64_t nLabel) -{ - QCBOREncode_AddInt64(pCtx, nLabel); - QCBOREncode_AddNULL(pCtx); -} - - -static inline void QCBOREncode_AddUndef(QCBOREncodeContext *pCtx) -{ - QCBOREncode_AddSimple(pCtx, CBOR_SIMPLEV_UNDEF); -} - -static inline void QCBOREncode_AddUndefToMap(QCBOREncodeContext *pCtx, const char *szLabel) -{ - QCBOREncode_AddSZString(pCtx, szLabel); - QCBOREncode_AddUndef(pCtx); -} - -static inline void QCBOREncode_AddUndefToMapN(QCBOREncodeContext *pCtx, int64_t nLabel) -{ - QCBOREncode_AddInt64(pCtx, nLabel); - QCBOREncode_AddUndef(pCtx); -} - - -static inline void QCBOREncode_OpenArray(QCBOREncodeContext *pCtx) -{ - QCBOREncode_OpenMapOrArray(pCtx, CBOR_MAJOR_TYPE_ARRAY); -} - -static inline void QCBOREncode_OpenArrayInMap(QCBOREncodeContext *pCtx, const char *szLabel) -{ - QCBOREncode_AddSZString(pCtx, szLabel); - QCBOREncode_OpenArray(pCtx); -} - -static inline void QCBOREncode_OpenArrayInMapN(QCBOREncodeContext *pCtx, int64_t nLabel) -{ - QCBOREncode_AddInt64(pCtx, nLabel); - QCBOREncode_OpenArray(pCtx); -} - -static inline void QCBOREncode_CloseArray(QCBOREncodeContext *pCtx) -{ - QCBOREncode_CloseMapOrArray(pCtx, CBOR_MAJOR_TYPE_ARRAY, NULL); -} - - -static inline void QCBOREncode_OpenMap(QCBOREncodeContext *pCtx) -{ - QCBOREncode_OpenMapOrArray(pCtx, CBOR_MAJOR_TYPE_MAP); -} - -static inline void QCBOREncode_OpenMapInMap(QCBOREncodeContext *pCtx, const char *szLabel) -{ - QCBOREncode_AddSZString(pCtx, szLabel); - QCBOREncode_OpenMap(pCtx); -} - -static inline void QCBOREncode_OpenMapInMapN(QCBOREncodeContext *pCtx, int64_t nLabel) -{ - QCBOREncode_AddInt64(pCtx, nLabel); - QCBOREncode_OpenMap(pCtx); -} - -static inline void QCBOREncode_CloseMap(QCBOREncodeContext *pCtx) -{ - QCBOREncode_CloseMapOrArray(pCtx, CBOR_MAJOR_TYPE_MAP, NULL); -} - - -static inline void QCBOREncode_BstrWrap(QCBOREncodeContext *pCtx) -{ - QCBOREncode_OpenMapOrArray(pCtx, CBOR_MAJOR_TYPE_BYTE_STRING); -} - -static inline void QCBOREncode_BstrWrapInMap(QCBOREncodeContext *pCtx, const char *szLabel) -{ - QCBOREncode_AddSZString(pCtx, szLabel); - QCBOREncode_BstrWrap(pCtx); -} - -static inline void QCBOREncode_BstrWrapInMapN(QCBOREncodeContext *pCtx, int64_t nLabel) -{ - QCBOREncode_AddInt64(pCtx, nLabel); - QCBOREncode_BstrWrap(pCtx); -} - -static inline void QCBOREncode_CloseBstrWrap(QCBOREncodeContext *pCtx, UsefulBufC *pWrappedCBOR) -{ - QCBOREncode_CloseMapOrArray(pCtx, CBOR_MAJOR_TYPE_BYTE_STRING, pWrappedCBOR); -} - - -static inline void QCBOREncode_AddEncoded(QCBOREncodeContext *pCtx, UsefulBufC Encoded) -{ - QCBOREncode_AddBuffer(pCtx, CBOR_MAJOR_NONE_TYPE_RAW, Encoded); -} - -static inline void QCBOREncode_AddEncodedToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Encoded) -{ - QCBOREncode_AddSZString(pCtx, szLabel); - QCBOREncode_AddEncoded(pCtx, Encoded); -} - -static inline void QCBOREncode_AddEncodedToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Encoded) -{ - QCBOREncode_AddInt64(pCtx, nLabel); - QCBOREncode_AddEncoded(pCtx, Encoded); -} - - -/* =========================================================================== - END OF PRIVATE INLINE IMPLEMENTATION - - =========================================================================== */ - -#endif /* defined(__QCBOR__qcbor__) */ - diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/inc/useful_buf.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/inc/useful_buf.h deleted file mode 100644 index dcb88b8..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/inc/useful_buf.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * useful_buf.h - * - * Copyright 2019, Laurence Lundblade - * - * SPDX-License-Identifier: BSD-3-Clause - * - * See BSD-3-Clause license in README.mdE. - */ - - -#ifndef __USEFUL_BUF_H__ -#define __USEFUL_BUF_H__ - -#include "UsefulBuf.h" - - -/** - * \file useful_buf.h - * - * \brief This is a TF-M coding style version of UsefulBuf. - * See UsefulBuf for documentation of these functions. - */ - - -#define NULL_USEFUL_BUF_C NULLUsefulBufC - -#define NULL_USEFUL_BUF NULLUsefulBuf - - -static inline int useful_buf_c_is_null(struct useful_buf_c in) -{ - return UsefulBuf_IsNULLC(in); -} - - -static inline int useful_buf_is_null(struct useful_buf in) -{ - return UsefulBuf_IsNULL(in); -} - - -static inline int useful_buf_c_is_empty(struct useful_buf_c in) -{ - return UsefulBuf_IsEmptyC(in); -} - -static inline int useful_buf_is_empty(struct useful_buf in) -{ - return UsefulBuf_IsEmpty(in); -} - - -static inline int useful_buf_is_null_or_empty(struct useful_buf in) -{ - return UsefulBuf_IsNULLOrEmpty(in); -} - - -static inline int useful_buf_c_is_null_or_empty(struct useful_buf_c in) -{ - return UsefulBuf_IsNULLOrEmptyC(in); -} - - -static inline struct useful_buf useful_buf_unconst(struct useful_buf_c in) -{ - return UsefulBuf_Unconst(in); -} - -#define USEFUL_BUF_FROM_SZ_LITERAL UsefulBuf_FROM_SZ_LITERAL - -#define USEFUL_BUF_FROM_BYTE_ARRAY_LITERAL UsefulBuf_FROM_BYTE_ARRAY_LITERAL - -#define USEFUL_BUF_MAKE_STACK_UB UsefulBuf_MAKE_STACK_UB - -#define USEFUL_BUF_FROM_BYTE_ARRAY UsefulBuf_FROM_BYTE_ARRAY - - -static inline struct useful_buf_c useful_buf_from_sz(const char *string) -{ - return UsefulBuf_FromSZ(string); -} - -static inline struct -useful_buf_c useful_buf_copy_offset(struct useful_buf dest, - size_t offset, - struct useful_buf_c src) -{ - return UsefulBuf_CopyOffset(dest, offset, src); -} - - - -static inline struct useful_buf_c useful_buf_copy(struct useful_buf dest, - struct useful_buf_c src) -{ - return UsefulBuf_Copy(dest, src); -} - - -static inline struct useful_buf_c useful_buf_set(struct useful_buf dest, - uint8_t value) -{ - return UsefulBuf_Set(dest, value); -} - - -static inline struct useful_buf_c useful_buf_copy_ptr(struct useful_buf dest, - const void *ptr, - size_t len) -{ - return UsefulBuf_CopyPtr(dest, ptr, len); -} - - -static inline struct useful_buf_c useful_buf_head(struct useful_buf_c buf, - size_t amount) -{ - return UsefulBuf_Head(buf, amount); -} - -static inline struct useful_buf_c useful_buf_tail(struct useful_buf_c buf, - size_t amount) -{ - return UsefulBuf_Tail(buf, amount); -} - -static inline int useful_buf_compare(const struct useful_buf_c buf1, - const struct useful_buf_c buf2) -{ - return UsefulBuf_Compare(buf1, buf2); -} - -static inline size_t -useful_buf_find_bytes(const struct useful_buf_c bytes_to_search, - const struct useful_buf_c bytes_to_find) -{ - return UsefulBuf_FindBytes(bytes_to_search, bytes_to_find); -} - - -#endif /* __USEFUL_BUF_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/src/UsefulBuf.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/src/UsefulBuf.c deleted file mode 100644 index d02708b..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/src/UsefulBuf.c +++ /dev/null @@ -1,330 +0,0 @@ -/*============================================================================== - Copyright (c) 2016-2018, The Linux Foundation. - Copyright (c) 2018-2019, Laurence Lundblade. - All rights reserved. - SPDX-License-Identifier: BSD-3-Clause - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of The Linux Foundation nor the names of its - contributors, nor the name "Laurence Lundblade" may be used to - endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS -BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ==============================================================================*/ - -/*=================================================================================== - FILE: UsefulBuf.c - - DESCRIPTION: General purpose input and output buffers - - EDIT HISTORY FOR FILE: - - This section contains comments describing changes made to the module. - Notice that changes are listed in reverse chronological order. - - when who what, where, why - -------- ---- --------------------------------------------------- - 09/07/17 llundbla Fix critical bug in UsefulBuf_Find() -- a read off - the end of memory when the bytes to find is longer - than the bytes to search. - 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected comparison - for < or > for unequal length buffers. Added - UsefulBuf_Set() function. - 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst - 11/13/16 llundbla Initial Version. - - =====================================================================================*/ - -#include "UsefulBuf.h" - -#define USEFUL_OUT_BUF_MAGIC (0x0B0F) // used to catch use of uninitialized or corrupted UOBs - - -/* - Public function -- see UsefulBuf.h - */ -UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src) -{ - // Do this with subtraction so it doesn't give erroneous result if uOffset + Src.len overflows - if(uOffset > Dest.len || Src.len > Dest.len - uOffset) { // uOffset + Src.len > Dest.len - return NULLUsefulBufC; - } - - memcpy((uint8_t *)Dest.ptr + uOffset, Src.ptr, Src.len); - - return (UsefulBufC){Dest.ptr, Src.len + uOffset}; -} - - -/* - Public function -- see UsefulBuf.h - */ -int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2) -{ - // use the comparisons rather than subtracting lengths to - // return an int instead of a size_t - if(UB1.len < UB2.len) { - return -1; - } else if (UB1.len > UB2.len) { - return 1; - } // else UB1.len == UB2.len - - return memcmp(UB1.ptr, UB2.ptr, UB1.len); -} - - - -/* - Public function -- see UsefulBuf.h - */ -size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind) -{ - if(BytesToSearch.len < BytesToFind.len) { - return SIZE_MAX; - } - - for(size_t uPos = 0; uPos <= BytesToSearch.len - BytesToFind.len; uPos++) { - if(!UsefulBuf_Compare((UsefulBufC){((uint8_t *)BytesToSearch.ptr) + uPos, BytesToFind.len}, BytesToFind)) { - return uPos; - } - } - - return SIZE_MAX; -} - - -/* - Public function -- see UsefulBuf.h - - Code Reviewers: THIS FUNCTION DOES POINTER MATH - */ -void UsefulOutBuf_Init(UsefulOutBuf *me, UsefulBuf Storage) -{ - me->magic = USEFUL_OUT_BUF_MAGIC; - UsefulOutBuf_Reset(me); - me->UB = Storage; - -#if 0 - // This check is off by default. - - // The following check fails on ThreadX - - // Sanity check on the pointer and size to be sure we are not - // passed a buffer that goes off the end of the address space. - // Given this test, we know that all unsigned lengths less than - // me->size are valid and won't wrap in any pointer additions - // based off of pStorage in the rest of this code. - const uintptr_t ptrM = UINTPTR_MAX - Storage.len; - if(Storage.ptr && (uintptr_t)Storage.ptr > ptrM) // Check #0 - me->err = 1; -#endif -} - - - -/* - Public function -- see UsefulBuf.h - - The core of UsefulOutBuf -- put some bytes in the buffer without writing off the end of it. - - Code Reviewers: THIS FUNCTION DOES POINTER MATH - - This function inserts the source buffer, NewData, into the destination buffer, me->UB.ptr. - - Destination is represented as: - me->UB.ptr -- start of the buffer - me->UB.len -- size of the buffer UB.ptr - me->data_len -- length of value data in UB - - Source is data: - NewData.ptr -- start of source buffer - NewData.len -- length of source buffer - - Insertion point: - uInsertionPos. - - Steps: - - 0. Corruption checks on UsefulOutBuf - - 1. Figure out if the new data will fit or not - - 2. Is insertion position in the range of valid data? - - 3. If insertion point is not at the end, slide data to the right of the insertion point to the right - - 4. Put the new data in at the insertion position. - - */ -void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *me, UsefulBufC NewData, size_t uInsertionPos) -{ - if(me->err) { - // Already in error state. - return; - } - - /* 0. Sanity check the UsefulOutBuf structure */ - // A "counter measure". If magic number is not the right number it - // probably means me was not initialized or it was corrupted. Attackers - // can defeat this, but it is a hurdle and does good with very - // little code. - if(me->magic != USEFUL_OUT_BUF_MAGIC) { - me->err = 1; - return; // Magic number is wrong due to uninitalization or corrption - } - - // Make sure valid data is less than buffer size. This would only occur - // if there was corruption of me, but it is also part of the checks to - // be sure there is no pointer arithmatic under/overflow. - if(me->data_len > me->UB.len) { // Check #1 - me->err = 1; - return; // Offset of valid data is off the end of the UsefulOutBuf due to uninitialization or corruption - } - - /* 1. Will it fit? */ - // WillItFit() is the same as: NewData.len <= (me->size - me->data_len) - // Check #1 makes sure subtraction in RoomLeft will not wrap around - if(! UsefulOutBuf_WillItFit(me, NewData.len)) { // Check #2 - // The new data will not fit into the the buffer. - me->err = 1; - return; - } - - /* 2. Check the Insertion Position */ - // This, with Check #1, also confirms that uInsertionPos <= me->data_len - if(uInsertionPos > me->data_len) { // Check #3 - // Off the end of the valid data in the buffer. - me->err = 1; - return; - } - - /* 3. Slide existing data to the right */ - uint8_t *pSourceOfMove = ((uint8_t *)me->UB.ptr) + uInsertionPos; // PtrMath #1 - size_t uNumBytesToMove = me->data_len - uInsertionPos; // PtrMath #2 - uint8_t *pDestinationOfMove = pSourceOfMove + NewData.len; // PtrMath #3 - - if(uNumBytesToMove && me->UB.ptr) { - // To know memmove won't go off end of destination, see PtrMath #4 - memmove(pDestinationOfMove, pSourceOfMove, uNumBytesToMove); - } - - /* 4. Put the new data in */ - uint8_t *pInsertionPoint = ((uint8_t *)me->UB.ptr) + uInsertionPos; // PtrMath #5 - if(me->UB.ptr) { - // To know memmove won't go off end of destination, see PtrMath #6 - memmove(pInsertionPoint, NewData.ptr, NewData.len); - } - me->data_len += NewData.len ; -} - - -/* - Rationale that describes why the above pointer math is safe - - PtrMath #1 will never wrap around over because - Check #0 in UsefulOutBuf_Init makes sure me->UB.ptr + me->UB.len doesn't wrap - Check #1 makes sure me->data_len is less than me->UB.len - Check #3 makes sure uInsertionPos is less than me->data_len - - PtrMath #2 will never wrap around under because - Check #3 makes sure uInsertionPos is less than me->data_len - - PtrMath #3 will never wrap around over because todo - PtrMath #1 is checked resulting in pSourceOfMove being between me->UB.ptr and a maximum valid ptr - Check #2 that NewData.len will fit - - PtrMath #4 will never wrap under because - Calculation for extent or memmove is uRoomInDestination = me->UB.len - (uInsertionPos + NewData.len) - Check #3 makes sure uInsertionPos is less than me->data_len - Check #3 allows Check #2 to be refactored as NewData.Len > (me->size - uInsertionPos) - This algebraically rearranges to me->size > uInsertionPos + NewData.len - - PtrMath #5 is exactly the same as PtrMath #1 - - PtrMath #6 will never wrap under because - Calculation for extent of memove is uRoomInDestination = me->UB.len - uInsertionPos; - Check #1 makes sure me->data_len is less than me->size - Check #3 makes sure uInsertionPos is less than me->data_len - */ - - -/* - Public function -- see UsefulBuf.h - */ -UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *me) -{ - if(me->err) { - return NULLUsefulBufC; - } - - if(me->magic != USEFUL_OUT_BUF_MAGIC) { - me->err = 1; - return NULLUsefulBufC; - } - - return (UsefulBufC){me->UB.ptr,me->data_len}; -} - - -/* - Public function -- see UsefulBuf.h - - Copy out the data accumulated in to the output buffer. - */ -UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *me, UsefulBuf pDest) -{ - const UsefulBufC Tmp = UsefulOutBuf_OutUBuf(me); - if(UsefulBuf_IsNULLC(Tmp)) { - return NULLUsefulBufC; - } - return UsefulBuf_Copy(pDest, Tmp); -} - - - - -/* - Public function -- see UsefulBuf.h - - The core of UsefulInputBuf -- consume some bytes without going off the end of the buffer. - - Code Reviewers: THIS FUNCTION DOES POINTER MATH - */ -const void * UsefulInputBuf_GetBytes(UsefulInputBuf *me, size_t uAmount) -{ - // Already in error state. Do nothing. - if(me->err) { - return NULL; - } - - if(!UsefulInputBuf_BytesAvailable(me, uAmount)) { - // The number of bytes asked for at current position are more than available - me->err = 1; - return NULL; - } - - // This is going to succeed - const void * const result = ((uint8_t *)me->UB.ptr) + me->cursor; - me->cursor += uAmount; // this will not overflow because of check using UsefulInputBuf_BytesAvailable() - return result; -} - diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/src/ieee754.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/src/ieee754.c deleted file mode 100644 index 6fdfda8..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/src/ieee754.c +++ /dev/null @@ -1,497 +0,0 @@ -/*============================================================================== - ieee754.c -- floating point conversion between half, double and single precision - - Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. - - SPDX-License-Identifier: BSD-3-Clause - - See BSD-3-Clause license in README.md - - Created on 7/23/18 - ==============================================================================*/ - -#include "ieee754.h" -#include // For memcpy() - - -/* - This code is written for clarity and verifiability, not for size, on the assumption - that the optimizer will do a good job. The LLVM optimizer, -Os, does seem to do the - job and the resulting object code is smaller from combining code for the many different - cases (normal, subnormal, infinity, zero...) for the conversions. - - Dead stripping is also really helpful to get code size down when floating point - encoding is not needed. - - This code works solely using shifts and masks and thus has no dependency on - any math libraries. It can even work if the CPU doesn't have any floating - point support, though that isn't the most useful thing to do. - - The memcpy() dependency is only for CopyFloatToUint32() and friends which only - is needed to avoid type punning when converting the actual float bits to - an unsigned value so the bit shifts and masks can work. - */ - -/* - The references used to write this code: - - - IEEE 754-2008, particularly section 3.6 and 6.2.1 - - - https://en.wikipedia.org/wiki/IEEE_754 and subordinate pages - - - https://stackoverflow.com/questions/19800415/why-does-ieee-754-reserve-so-many-nan-values - */ - - -// ----- Half Precsion ----------- -#define HALF_NUM_SIGNIFICAND_BITS (10) -#define HALF_NUM_EXPONENT_BITS (5) -#define HALF_NUM_SIGN_BITS (1) - -#define HALF_SIGNIFICAND_SHIFT (0) -#define HALF_EXPONENT_SHIFT (HALF_NUM_SIGNIFICAND_BITS) -#define HALF_SIGN_SHIFT (HALF_NUM_SIGNIFICAND_BITS + HALF_NUM_EXPONENT_BITS) - -#define HALF_SIGNIFICAND_MASK (0x3ff) // The lower 10 bits // 0x03ff -#define HALF_EXPONENT_MASK (0x1f << HALF_EXPONENT_SHIFT) // 0x7c00 5 bits of exponent -#define HALF_SIGN_MASK (0x01 << HALF_SIGN_SHIFT) // // 0x80001 bit of sign -#define HALF_QUIET_NAN_BIT (0x01 << (HALF_NUM_SIGNIFICAND_BITS-1)) // 0x0200 - -/* Biased Biased Unbiased Use - 0x00 0 -15 0 and subnormal - 0x01 1 -14 Smallest normal exponent - 0x1e 30 15 Largest normal exponent - 0x1F 31 16 NaN and Infinity */ -#define HALF_EXPONENT_BIAS (15) -#define HALF_EXPONENT_MAX (HALF_EXPONENT_BIAS) // 15 Unbiased -#define HALF_EXPONENT_MIN (-HALF_EXPONENT_BIAS+1) // -14 Unbiased -#define HALF_EXPONENT_ZERO (-HALF_EXPONENT_BIAS) // -15 Unbiased -#define HALF_EXPONENT_INF_OR_NAN (HALF_EXPONENT_BIAS+1) // 16 Unbiased - - -// ------ Single Precision -------- -#define SINGLE_NUM_SIGNIFICAND_BITS (23) -#define SINGLE_NUM_EXPONENT_BITS (8) -#define SINGLE_NUM_SIGN_BITS (1) - -#define SINGLE_SIGNIFICAND_SHIFT (0) -#define SINGLE_EXPONENT_SHIFT (SINGLE_NUM_SIGNIFICAND_BITS) -#define SINGLE_SIGN_SHIFT (SINGLE_NUM_SIGNIFICAND_BITS + SINGLE_NUM_EXPONENT_BITS) - -#define SINGLE_SIGNIFICAND_MASK (0x7fffffUL) // The lower 23 bits -#define SINGLE_EXPONENT_MASK (0xffUL << SINGLE_EXPONENT_SHIFT) // 8 bits of exponent -#define SINGLE_SIGN_MASK (0x01UL << SINGLE_SIGN_SHIFT) // 1 bit of sign -#define SINGLE_QUIET_NAN_BIT (0x01UL << (SINGLE_NUM_SIGNIFICAND_BITS-1)) - -/* Biased Biased Unbiased Use - 0x0000 0 -127 0 and subnormal - 0x0001 1 -126 Smallest normal exponent - 0x7f 127 0 1 - 0xfe 254 127 Largest normal exponent - 0xff 255 128 NaN and Infinity */ -#define SINGLE_EXPONENT_BIAS (127) -#define SINGLE_EXPONENT_MAX (SINGLE_EXPONENT_BIAS) // 127 unbiased -#define SINGLE_EXPONENT_MIN (-SINGLE_EXPONENT_BIAS+1) // -126 unbiased -#define SINGLE_EXPONENT_ZERO (-SINGLE_EXPONENT_BIAS) // -127 unbiased -#define SINGLE_EXPONENT_INF_OR_NAN (SINGLE_EXPONENT_BIAS+1) // 128 unbiased - - -// --------- Double Precision ---------- -#define DOUBLE_NUM_SIGNIFICAND_BITS (52) -#define DOUBLE_NUM_EXPONENT_BITS (11) -#define DOUBLE_NUM_SIGN_BITS (1) - -#define DOUBLE_SIGNIFICAND_SHIFT (0) -#define DOUBLE_EXPONENT_SHIFT (DOUBLE_NUM_SIGNIFICAND_BITS) -#define DOUBLE_SIGN_SHIFT (DOUBLE_NUM_SIGNIFICAND_BITS + DOUBLE_NUM_EXPONENT_BITS) - -#define DOUBLE_SIGNIFICAND_MASK (0xfffffffffffffULL) // The lower 52 bits -#define DOUBLE_EXPONENT_MASK (0x7ffULL << DOUBLE_EXPONENT_SHIFT) // 11 bits of exponent -#define DOUBLE_SIGN_MASK (0x01ULL << DOUBLE_SIGN_SHIFT) // 1 bit of sign -#define DOUBLE_QUIET_NAN_BIT (0x01ULL << (DOUBLE_NUM_SIGNIFICAND_BITS-1)) - - -/* Biased Biased Unbiased Use - 0x00000000 0 -1023 0 and subnormal - 0x00000001 1 -1022 Smallest normal exponent - 0x000007fe 2046 1023 Largest normal exponent - 0x000007ff 2047 1024 NaN and Infinity */ -#define DOUBLE_EXPONENT_BIAS (1023) -#define DOUBLE_EXPONENT_MAX (DOUBLE_EXPONENT_BIAS) // unbiased -#define DOUBLE_EXPONENT_MIN (-DOUBLE_EXPONENT_BIAS+1) // unbiased -#define DOUBLE_EXPONENT_ZERO (-DOUBLE_EXPONENT_BIAS) // unbiased -#define DOUBLE_EXPONENT_INF_OR_NAN (DOUBLE_EXPONENT_BIAS+1) // unbiased - - - -/* - Convenient functions to avoid type punning, compiler warnings and such - The optimizer reduces them to a simple assignment. - This is a crusty corner of C. It shouldn't be this hard. - - These are also in UsefulBuf.h under a different name. They are copied - here to avoid a dependency on UsefulBuf.h. There is no - object code size impact because these always optimze down to a - simple assignment. - */ -static inline uint32_t CopyFloatToUint32(float f) -{ - uint32_t u32; - memcpy(&u32, &f, sizeof(uint32_t)); - return u32; -} - -static inline uint64_t CopyDoubleToUint64(double d) -{ - uint64_t u64; - memcpy(&u64, &d, sizeof(uint64_t)); - return u64; -} - -static inline float CopyUint32ToFloat(uint32_t u32) -{ - float f; - memcpy(&f, &u32, sizeof(uint32_t)); - return f; -} - -static inline double CopyUint64ToDouble(uint64_t u64) -{ - double d; - memcpy(&d, &u64, sizeof(uint64_t)); - return d; -} - - -// Public function; see ieee754.h -uint16_t IEEE754_FloatToHalf(float f) -{ - // Pull the three parts out of the single-precision float - const uint32_t uSingle = CopyFloatToUint32(f); - const int32_t nSingleUnbiasedExponent = ((uSingle & SINGLE_EXPONENT_MASK) >> SINGLE_EXPONENT_SHIFT) - SINGLE_EXPONENT_BIAS; - const uint32_t uSingleSign = (uSingle & SINGLE_SIGN_MASK) >> SINGLE_SIGN_SHIFT; - const uint32_t uSingleSignificand = uSingle & SINGLE_SIGNIFICAND_MASK; - - - // Now convert the three parts to half-precision. - uint16_t uHalfSign, uHalfSignificand, uHalfBiasedExponent; - if(nSingleUnbiasedExponent == SINGLE_EXPONENT_INF_OR_NAN) { - // +/- Infinity and NaNs -- single biased exponent is 0xff - uHalfBiasedExponent = HALF_EXPONENT_INF_OR_NAN + HALF_EXPONENT_BIAS; - if(!uSingleSignificand) { - // Infinity - uHalfSignificand = 0; - } else { - // Copy the LBSs of the NaN payload that will fit from the single to the half - uHalfSignificand = uSingleSignificand & (HALF_SIGNIFICAND_MASK & ~HALF_QUIET_NAN_BIT); - if(uSingleSignificand & SINGLE_QUIET_NAN_BIT) { - // It's a qNaN; copy the qNaN bit - uHalfSignificand |= HALF_QUIET_NAN_BIT; - } else { - // It's a sNaN; make sure the significand is not zero so it stays a NaN - // This is needed because not all significand bits are copied from single - if(!uHalfSignificand) { - // Set the LSB. This is what wikipedia shows for sNAN. - uHalfSignificand |= 0x01; - } - } - } - } else if(nSingleUnbiasedExponent == SINGLE_EXPONENT_ZERO) { - // 0 or a subnormal number -- singled biased exponent is 0 - uHalfBiasedExponent = 0; - uHalfSignificand = 0; // Any subnormal single will be too small to express as a half precision - } else if(nSingleUnbiasedExponent > HALF_EXPONENT_MAX) { - // Exponent is too large to express in half-precision; round up to infinity - uHalfBiasedExponent = HALF_EXPONENT_INF_OR_NAN + HALF_EXPONENT_BIAS; - uHalfSignificand = 0; - } else if(nSingleUnbiasedExponent < HALF_EXPONENT_MIN) { - // Exponent is too small to express in half-precision normal; make it a half-precision subnormal - uHalfBiasedExponent = (uint16_t)(HALF_EXPONENT_ZERO + HALF_EXPONENT_BIAS); - // Difference between single normal exponent and the base exponent of a half subnormal - const uint32_t nExpDiff = -(nSingleUnbiasedExponent - HALF_EXPONENT_MIN); - // Also have to shift the significand by the difference in number of bits between a single and a half significand - const int32_t nSignificandBitsDiff = SINGLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS; - // Add in the 1 that is implied in the significand of a normal number; it needs to be present in a subnormal - const uint32_t uSingleSignificandSubnormal = uSingleSignificand + (0x01L << SINGLE_NUM_SIGNIFICAND_BITS); - uHalfSignificand = uSingleSignificandSubnormal >> (nExpDiff + nSignificandBitsDiff); - } else { - // The normal case - uHalfBiasedExponent = nSingleUnbiasedExponent + HALF_EXPONENT_BIAS; - uHalfSignificand = uSingleSignificand >> (SINGLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS); - } - uHalfSign = uSingleSign; - - // Put the 3 values in the right place for a half precision - const uint16_t uHalfPrecision = uHalfSignificand | - (uHalfBiasedExponent << HALF_EXPONENT_SHIFT) | - (uHalfSign << HALF_SIGN_SHIFT); - return uHalfPrecision; -} - - -// Public function; see ieee754.h -uint16_t IEEE754_DoubleToHalf(double d) -{ - // Pull the three parts out of the double-precision float - const uint64_t uDouble = CopyDoubleToUint64(d); - const int64_t nDoubleUnbiasedExponent = ((uDouble & DOUBLE_EXPONENT_MASK) >> DOUBLE_EXPONENT_SHIFT) - DOUBLE_EXPONENT_BIAS; - const uint64_t uDoubleSign = (uDouble & DOUBLE_SIGN_MASK) >> DOUBLE_SIGN_SHIFT; - const uint64_t uDoubleSignificand = uDouble & DOUBLE_SIGNIFICAND_MASK; - - - // Now convert the three parts to half-precision. - uint16_t uHalfSign, uHalfSignificand, uHalfBiasedExponent; - if(nDoubleUnbiasedExponent == DOUBLE_EXPONENT_INF_OR_NAN) { - // +/- Infinity and NaNs -- single biased exponent is 0xff - uHalfBiasedExponent = HALF_EXPONENT_INF_OR_NAN + HALF_EXPONENT_BIAS; - if(!uDoubleSignificand) { - // Infinity - uHalfSignificand = 0; - } else { - // Copy the LBSs of the NaN payload that will fit from the double to the half - uHalfSignificand = uDoubleSignificand & (HALF_SIGNIFICAND_MASK & ~HALF_QUIET_NAN_BIT); - if(uDoubleSignificand & DOUBLE_QUIET_NAN_BIT) { - // It's a qNaN; copy the qNaN bit - uHalfSignificand |= HALF_QUIET_NAN_BIT; - } else { - // It's an sNaN; make sure the significand is not zero so it stays a NaN - // This is needed because not all significand bits are copied from single - if(!uHalfSignificand) { - // Set the LSB. This is what wikipedia shows for sNAN. - uHalfSignificand |= 0x01; - } - } - } - } else if(nDoubleUnbiasedExponent == DOUBLE_EXPONENT_ZERO) { - // 0 or a subnormal number -- double biased exponent is 0 - uHalfBiasedExponent = 0; - uHalfSignificand = 0; // Any subnormal single will be too small to express as a half precision; TODO, is this really true? - } else if(nDoubleUnbiasedExponent > HALF_EXPONENT_MAX) { - // Exponent is too large to express in half-precision; round up to infinity; TODO, is this really true? - uHalfBiasedExponent = HALF_EXPONENT_INF_OR_NAN + HALF_EXPONENT_BIAS; - uHalfSignificand = 0; - } else if(nDoubleUnbiasedExponent < HALF_EXPONENT_MIN) { - // Exponent is too small to express in half-precision; round down to zero - uHalfBiasedExponent = (uint16_t)(HALF_EXPONENT_ZERO + HALF_EXPONENT_BIAS); - // Difference between double normal exponent and the base exponent of a half subnormal - const uint64_t nExpDiff = -(nDoubleUnbiasedExponent - HALF_EXPONENT_MIN); - // Also have to shift the significand by the difference in number of bits between a double and a half significand - const int64_t nSignificandBitsDiff = DOUBLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS; - // Add in the 1 that is implied in the significand of a normal number; it needs to be present in a subnormal - const uint64_t uDoubleSignificandSubnormal = uDoubleSignificand + (0x01ULL << DOUBLE_NUM_SIGNIFICAND_BITS); - uHalfSignificand = uDoubleSignificandSubnormal >> (nExpDiff + nSignificandBitsDiff); - } else { - // The normal case - uHalfBiasedExponent = nDoubleUnbiasedExponent + HALF_EXPONENT_BIAS; - uHalfSignificand = uDoubleSignificand >> (DOUBLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS); - } - uHalfSign = uDoubleSign; - - - // Put the 3 values in the right place for a half precision - const uint16_t uHalfPrecision = uHalfSignificand | - (uHalfBiasedExponent << HALF_EXPONENT_SHIFT) | - (uHalfSign << HALF_SIGN_SHIFT); - return uHalfPrecision; -} - - -// Public function; see ieee754.h -float IEEE754_HalfToFloat(uint16_t uHalfPrecision) -{ - // Pull out the three parts of the half-precision float - const uint16_t uHalfSignificand = uHalfPrecision & HALF_SIGNIFICAND_MASK; - const int16_t nHalfUnBiasedExponent = ((uHalfPrecision & HALF_EXPONENT_MASK) >> HALF_EXPONENT_SHIFT) - HALF_EXPONENT_BIAS; - const uint16_t uHalfSign = (uHalfPrecision & HALF_SIGN_MASK) >> HALF_SIGN_SHIFT; - - - // Make the three parts of the single-precision number - uint32_t uSingleSignificand, uSingleSign, uSingleBiasedExponent; - if(nHalfUnBiasedExponent == HALF_EXPONENT_ZERO) { - // 0 or subnormal - if(uHalfSignificand) { - // Subnormal case - uSingleBiasedExponent = -HALF_EXPONENT_BIAS + SINGLE_EXPONENT_BIAS +1; - // A half-precision subnormal can always be converted to a normal single-precision float because the ranges line up - uSingleSignificand = uHalfSignificand; - // Shift bits from right of the decimal to left, reducing the exponent by 1 each time - do { - uSingleSignificand <<= 1; - uSingleBiasedExponent--; - } while ((uSingleSignificand & 0x400) == 0); - uSingleSignificand &= HALF_SIGNIFICAND_MASK; - uSingleSignificand <<= (SINGLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS); - } else { - // Just zero - uSingleBiasedExponent = SINGLE_EXPONENT_ZERO + SINGLE_EXPONENT_BIAS; - uSingleSignificand = 0; - } - } else if(nHalfUnBiasedExponent == HALF_EXPONENT_INF_OR_NAN) { - // NaN or Inifinity - uSingleBiasedExponent = SINGLE_EXPONENT_INF_OR_NAN + SINGLE_EXPONENT_BIAS; - if(uHalfSignificand) { - // NaN - // First preserve the NaN payload from half to single - uSingleSignificand = uHalfSignificand & ~HALF_QUIET_NAN_BIT; - if(uHalfSignificand & HALF_QUIET_NAN_BIT) { - // Next, set qNaN if needed since half qNaN bit is not copied above - uSingleSignificand |= SINGLE_QUIET_NAN_BIT; - } - } else { - // Infinity - uSingleSignificand = 0; - } - } else { - // Normal number - uSingleBiasedExponent = nHalfUnBiasedExponent + SINGLE_EXPONENT_BIAS; - uSingleSignificand = uHalfSignificand << (SINGLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS); - } - uSingleSign = uHalfSign; - - - // Shift the three parts of the single precision into place - const uint32_t uSinglePrecision = uSingleSignificand | - (uSingleBiasedExponent << SINGLE_EXPONENT_SHIFT) | - (uSingleSign << SINGLE_SIGN_SHIFT); - - return CopyUint32ToFloat(uSinglePrecision); -} - - -// Public function; see ieee754.h -double IEEE754_HalfToDouble(uint16_t uHalfPrecision) -{ - // Pull out the three parts of the half-precision float - const uint16_t uHalfSignificand = uHalfPrecision & HALF_SIGNIFICAND_MASK; - const int16_t nHalfUnBiasedExponent = ((uHalfPrecision & HALF_EXPONENT_MASK) >> HALF_EXPONENT_SHIFT) - HALF_EXPONENT_BIAS; - const uint16_t uHalfSign = (uHalfPrecision & HALF_SIGN_MASK) >> HALF_SIGN_SHIFT; - - - // Make the three parts of hte single-precision number - uint64_t uDoubleSignificand, uDoubleSign, uDoubleBiasedExponent; - if(nHalfUnBiasedExponent == HALF_EXPONENT_ZERO) { - // 0 or subnormal - uDoubleBiasedExponent = DOUBLE_EXPONENT_ZERO + DOUBLE_EXPONENT_BIAS; - if(uHalfSignificand) { - // Subnormal case - uDoubleBiasedExponent = -HALF_EXPONENT_BIAS + DOUBLE_EXPONENT_BIAS +1; - // A half-precision subnormal can always be converted to a normal double-precision float because the ranges line up - uDoubleSignificand = uHalfSignificand; - // Shift bits from right of the decimal to left, reducing the exponent by 1 each time - do { - uDoubleSignificand <<= 1; - uDoubleBiasedExponent--; - } while ((uDoubleSignificand & 0x400) == 0); - uDoubleSignificand &= HALF_SIGNIFICAND_MASK; - uDoubleSignificand <<= (DOUBLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS); - } else { - // Just zero - uDoubleSignificand = 0; - } - } else if(nHalfUnBiasedExponent == HALF_EXPONENT_INF_OR_NAN) { - // NaN or Inifinity - uDoubleBiasedExponent = DOUBLE_EXPONENT_INF_OR_NAN + DOUBLE_EXPONENT_BIAS; - if(uHalfSignificand) { - // NaN - // First preserve the NaN payload from half to single - uDoubleSignificand = uHalfSignificand & ~HALF_QUIET_NAN_BIT; - if(uHalfSignificand & HALF_QUIET_NAN_BIT) { - // Next, set qNaN if needed since half qNaN bit is not copied above - uDoubleSignificand |= DOUBLE_QUIET_NAN_BIT; - } - } else { - // Infinity - uDoubleSignificand = 0; - } - } else { - // Normal number - uDoubleBiasedExponent = nHalfUnBiasedExponent + DOUBLE_EXPONENT_BIAS; - uDoubleSignificand = (uint64_t)uHalfSignificand << (DOUBLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS); - } - uDoubleSign = uHalfSign; - - - // Shift the 3 parts into place as a double-precision - const uint64_t uDouble = uDoubleSignificand | - (uDoubleBiasedExponent << DOUBLE_EXPONENT_SHIFT) | - (uDoubleSign << DOUBLE_SIGN_SHIFT); - return CopyUint64ToDouble(uDouble); -} - - -// Public function; see ieee754.h -IEEE754_union IEEE754_FloatToSmallest(float f) -{ - IEEE754_union result; - - // Pull the neeed two parts out of the single-precision float - const uint32_t uSingle = CopyFloatToUint32(f); - const int32_t nSingleExponent = ((uSingle & SINGLE_EXPONENT_MASK) >> SINGLE_EXPONENT_SHIFT) - SINGLE_EXPONENT_BIAS; - const uint32_t uSingleSignificand = uSingle & SINGLE_SIGNIFICAND_MASK; - - // Bit mask that is the significand bits that would be lost when converting - // from single-precision to half-precision - const uint64_t uDroppedSingleBits = SINGLE_SIGNIFICAND_MASK >> HALF_NUM_SIGNIFICAND_BITS; - - // Optimizer will re organize so there is only one call to IEEE754_FloatToHalf() - if(uSingle == 0) { - // Value is 0.0000, not a a subnormal - result.uSize = IEEE754_UNION_IS_HALF; - result.uValue = IEEE754_FloatToHalf(f); - } else if(nSingleExponent == SINGLE_EXPONENT_INF_OR_NAN) { - // NaN, +/- infinity - result.uSize = IEEE754_UNION_IS_HALF; - result.uValue = IEEE754_FloatToHalf(f); - } else if((nSingleExponent >= HALF_EXPONENT_MIN) && nSingleExponent <= HALF_EXPONENT_MAX && (!(uSingleSignificand & uDroppedSingleBits))) { - // Normal number in exponent range and precision won't be lost - result.uSize = IEEE754_UNION_IS_HALF; - result.uValue = IEEE754_FloatToHalf(f); - } else { - // Subnormal, exponent out of range, or precision will be lost - result.uSize = IEEE754_UNION_IS_SINGLE; - result.uValue = uSingle; - } - - return result; -} - -// Public function; see ieee754.h -IEEE754_union IEEE754_DoubleToSmallestInternal(double d, int bAllowHalfPrecision) -{ - IEEE754_union result; - - // Pull the needed two parts out of the double-precision float - const uint64_t uDouble = CopyDoubleToUint64(d); - const int64_t nDoubleExponent = ((uDouble & DOUBLE_EXPONENT_MASK) >> DOUBLE_EXPONENT_SHIFT) - DOUBLE_EXPONENT_BIAS; - const uint64_t uDoubleSignificand = uDouble & DOUBLE_SIGNIFICAND_MASK; - - // Masks to check whether dropped significand bits are zero or not - const uint64_t uDroppedDoubleBits = DOUBLE_SIGNIFICAND_MASK >> HALF_NUM_SIGNIFICAND_BITS; - const uint64_t uDroppedSingleBits = DOUBLE_SIGNIFICAND_MASK >> SINGLE_NUM_SIGNIFICAND_BITS; - - // The various cases - if(d == 0.0) { // Take care of positive and negative zero - // Value is 0.0000, not a a subnormal - result.uSize = IEEE754_UNION_IS_HALF; - result.uValue = IEEE754_DoubleToHalf(d); - } else if(nDoubleExponent == DOUBLE_EXPONENT_INF_OR_NAN) { - // NaN, +/- infinity - result.uSize = IEEE754_UNION_IS_HALF; - result.uValue = IEEE754_DoubleToHalf(d); - } else if(bAllowHalfPrecision && (nDoubleExponent >= HALF_EXPONENT_MIN) && nDoubleExponent <= HALF_EXPONENT_MAX && (!(uDoubleSignificand & uDroppedDoubleBits))) { - // Can convert to half without precision loss - result.uSize = IEEE754_UNION_IS_HALF; - result.uValue = IEEE754_DoubleToHalf(d); - } else if((nDoubleExponent >= SINGLE_EXPONENT_MIN) && nDoubleExponent <= SINGLE_EXPONENT_MAX && (!(uDoubleSignificand & uDroppedSingleBits))) { - // Can convert to single without precision loss - result.uSize = IEEE754_UNION_IS_SINGLE; - result.uValue = CopyFloatToUint32((float)d); - } else { - // Can't convert without precision loss - result.uSize = IEEE754_UNION_IS_DOUBLE; - result.uValue = uDouble; - } - - return result; -} - diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/src/ieee754.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/src/ieee754.h deleted file mode 100644 index 2530f98..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/src/ieee754.h +++ /dev/null @@ -1,168 +0,0 @@ -/*============================================================================== - ieee754.c -- floating point conversion between half, double and single precision - - Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. - - SPDX-License-Identifier: BSD-3-Clause - - See BSD-3-Clause license in README.md - - Created on 7/23/18 - ==============================================================================*/ - -#ifndef ieee754_h -#define ieee754_h - -#include - - - -/* - General comments - - This is a complete in that it handles all conversion cases - including +/- infinity, +/- zero, subnormal numbers, qNaN, sNaN - and NaN payloads. - - This confirms to IEEE 754-2008, but note that this doesn't - specify conversions, just the encodings. - - NaN payloads are preserved with alignment on the LSB. The - qNaN bit is handled differently and explicity copied. It - is always the MSB of the significand. The NaN payload MSBs - (except the qNaN bit) are truncated when going from - double or single to half. - - TODO: what does the C cast do with NaN payloads from - double to single? - - - - */ - -/* - Most simply just explicilty encode the type you want, single or double. - This works easily everywhere since standard C supports both - these types and so does qcbor. This encoder also supports - half precision and there's a few ways to use it to encode - floating point numbers in less space. - - Without losing precision, you can encode a single or double - such that the special values of 0, NaN and Infinity encode - as half-precision. This CBOR decodoer and most others - should handle this properly. - - If you don't mind losing precision, then you can use half-precision. - One way to do this is to set up your environment to use - ___fp_16. Some compilers and CPUs support it even though it is not - standard C. What is nice about this is that your program - will use less memory and floating point operations like - multiplying, adding and such will be faster. - - Another way to make use of half-precision is to represent - the values in your program as single or double, but encode - them in CBOR as half-precision. This cuts the size - of the encoded messages by 2 or 4, but doesn't reduce - memory needs or speed because you are still using - single or double in your code. - - - encode: - - float as float - - double as double - - half as half - - float as half_precision, for environments that don't support a half-precision type - - double as half_precision, for environments that don't support a half-precision type - - float with NaN, Infinity and 0 as half - - double with NaN, Infinity and 0 as half - - - - - */ - - - -/* - Convert single precision float to half-precision float. - Precision and NaN payload bits will be lost. Too large - values will round up to infinity and too small to zero. - */ -uint16_t IEEE754_FloatToHalf(float f); - - -/* - Convert half precision float to single precision float. - This is a loss-less conversion. - */ -float IEEE754_HalfToFloat(uint16_t uHalfPrecision); - - -/* - Convert double precision float to half-precision float. - Precision and NaN payload bits will be lost. Too large - values will round up to infinity and too small to zero. - */ -uint16_t IEEE754_DoubleToHalf(double d); - - -/* - Convert half precision float to double precision float. - This is a loss-less conversion. - */ -double IEEE754_HalfToDouble(uint16_t uHalfPrecision); - - - -// Both tags the value and gives the size -#define IEEE754_UNION_IS_HALF 2 -#define IEEE754_UNION_IS_SINGLE 4 -#define IEEE754_UNION_IS_DOUBLE 8 - -typedef struct { - uint8_t uSize; // One of IEEE754_IS_xxxx - uint64_t uValue; -} IEEE754_union; - - -/* - Converts double-precision to single-precision or half-precision if possible without - loss of precisions. If not, leaves it as a double. Only converts to single-precision - unless bAllowHalfPrecision is set. - */ -IEEE754_union IEEE754_DoubleToSmallestInternal(double d, int bAllowHalfPrecision); - -/* - Converts double-precision to single-precision if possible without - loss of precision. If not, leaves it as a double. - */ -static inline IEEE754_union IEEE754_DoubleToSmall(double d) -{ - return IEEE754_DoubleToSmallestInternal(d, 0); -} - - -/* - Converts double-precision to single-precision or half-precision if possible without - loss of precisions. If not, leaves it as a double. - */ -static inline IEEE754_union IEEE754_DoubleToSmallest(double d) -{ - return IEEE754_DoubleToSmallestInternal(d, 1); -} - -/* - Converts single-precision to half-precision if possible without - loss of precision. If not leaves as single-precision. - */ -IEEE754_union IEEE754_FloatToSmallest(float f); - - -#endif /* ieee754_h */ - - - - - - - diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/src/qcbor_decode.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/src/qcbor_decode.c deleted file mode 100644 index 2cfb130..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/src/qcbor_decode.c +++ /dev/null @@ -1,1320 +0,0 @@ -/*============================================================================== - Copyright (c) 2016-2018, The Linux Foundation. - Copyright (c) 2018-2019, Laurence Lundblade. - All rights reserved. - SPDX-License-Identifier: BSD-3-Clause - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of The Linux Foundation nor the names of its - contributors, nor the name "Laurence Lundblade" may be used to - endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS -BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ==============================================================================*/ - -/*=================================================================================== - FILE: qcbor_decode.c - - DESCRIPTION: This file contains the implementation of QCBOR. - - EDIT HISTORY FOR FILE: - - This section contains comments describing changes made to the module. - Notice that changes are listed in reverse chronological order. - - when who what, where, why - -------- ---- --------------------------------------------------- - 01/10/19 llundblade Clever type and argument decoder is 250 bytes smaller - 11/9/18 llundblade Error codes are now enums. - 11/2/18 llundblade Simplify float decoding and align with preferred - float encoding - 10/31/18 llundblade Switch to one license that is almost BSD-3. - 10/28/18 llundblade Reworked tag decoding - 10/15/18 llundblade Indefinite length maps and arrays supported - 10/8/18 llundblade Indefinite length strings supported - 02/04/17 llundbla Work on CPUs that don's require pointer alignment - by making use of changes in UsefulBuf - 03/01/17 llundbla More data types; decoding improvements and fixes - 11/13/16 llundbla Integrate most TZ changes back into github version. - 09/30/16 gkanike Porting to TZ. - 03/15/16 llundbla Initial Version. - - =====================================================================================*/ - -#include "qcbor.h" -#include "ieee754.h" - - -/* - This casts away the const-ness of a pointer, usually so it can be - freed or realloced. - */ -#define UNCONST_POINTER(ptr) ((void *)(ptr)) - - -/* - Collection of functions to track the map/array nesting for decoding - */ - -inline static int IsMapOrArray(uint8_t uDataType) -{ - return uDataType == QCBOR_TYPE_MAP || uDataType == QCBOR_TYPE_ARRAY; -} - -inline static int DecodeNesting_IsNested(const QCBORDecodeNesting *pNesting) -{ - return pNesting->pCurrent != &(pNesting->pMapsAndArrays[0]); -} - -inline static int DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting) -{ - return pNesting->pCurrent->uCount == UINT16_MAX; -} - -inline static uint8_t DecodeNesting_GetLevel(QCBORDecodeNesting *pNesting) -{ - return pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]); -} - -inline static int DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting) -{ - if(!DecodeNesting_IsNested(pNesting)) { - return 0; - } - - return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType; -} - -// Process a break. This will either ascend the nesting or error out -inline static QCBORError DecodeNesting_BreakAscend(QCBORDecodeNesting *pNesting) -{ - // breaks must always occur when there is nesting - if(!DecodeNesting_IsNested(pNesting)) { - return QCBOR_ERR_BAD_BREAK; - } - - // breaks can only occur when the map/array is indefinite length - if(!DecodeNesting_IsIndefiniteLength(pNesting)) { - return QCBOR_ERR_BAD_BREAK; - } - - // if all OK, the break reduces the level of nesting - pNesting->pCurrent--; - - return QCBOR_SUCCESS; -} - -// Called on every single item except breaks including the opening of a map/array -inline static void DecodeNesting_DecrementCount(QCBORDecodeNesting *pNesting) -{ - if(!DecodeNesting_IsNested(pNesting)) { - // at top level where there is no tracking - return; - } - - if(DecodeNesting_IsIndefiniteLength(pNesting)) { - // There is no count for indefinite length arrays/maps - return; - } - - // Decrement the count of items in this array/map - pNesting->pCurrent->uCount--; - - // Pop up nesting levels if the counts at the levels are zero - while(DecodeNesting_IsNested(pNesting) && 0 == pNesting->pCurrent->uCount) { - pNesting->pCurrent--; - if(!DecodeNesting_IsIndefiniteLength(pNesting)) { - pNesting->pCurrent->uCount--; - } - } -} - -// Called on every map/array -inline static QCBORError DecodeNesting_Descend(QCBORDecodeNesting *pNesting, QCBORItem *pItem) -{ - QCBORError nReturn = QCBOR_SUCCESS; - - if(pItem->val.uCount == 0) { - // Nothing to do for empty definite lenth arrays. They are just are - // effectively the same as an item that is not a map or array - goto Done; - // Empty indefinite length maps and arrays are handled elsewhere - } - - // Error out if arrays is too long to handle - if(pItem->val.uCount != UINT16_MAX && pItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY) { - nReturn = QCBOR_ERR_ARRAY_TOO_LONG; - goto Done; - } - - // Error out if nesting is too deep - if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) { - nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP; - goto Done; - } - - // The actual descend - pNesting->pCurrent++; - - // Record a few details for this nesting level - pNesting->pCurrent->uMajorType = pItem->uDataType; - pNesting->pCurrent->uCount = pItem->val.uCount; - -Done: - return nReturn;; -} - -inline static void DecodeNesting_Init(QCBORDecodeNesting *pNesting) -{ - pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]); -} - - - -/* - This list of built-in tags. Only add tags here that are - clearly established and useful. Once a tag is added here - it can't be taken out as that would break backwards compatibility. - There are only 48 slots available forever. - */ -static const uint16_t spBuiltInTagMap[] = { - CBOR_TAG_DATE_STRING, // See TAG_MAPPER_FIRST_FOUR - CBOR_TAG_DATE_EPOCH, // See TAG_MAPPER_FIRST_FOUR - CBOR_TAG_POS_BIGNUM, // See TAG_MAPPER_FIRST_FOUR - CBOR_TAG_NEG_BIGNUM, // See TAG_MAPPER_FIRST_FOUR - CBOR_TAG_FRACTION, - CBOR_TAG_BIGFLOAT, - CBOR_TAG_COSE_ENCRYPTO, - CBOR_TAG_COSE_MAC0, - CBOR_TAG_COSE_SIGN1, - CBOR_TAG_ENC_AS_B64URL, - CBOR_TAG_ENC_AS_B64, - CBOR_TAG_ENC_AS_B16, - CBOR_TAG_CBOR, - CBOR_TAG_URI, - CBOR_TAG_B64URL, - CBOR_TAG_B64, - CBOR_TAG_REGEX, - CBOR_TAG_MIME, - CBOR_TAG_BIN_UUID, - CBOR_TAG_CWT, - CBOR_TAG_ENCRYPT, - CBOR_TAG_MAC, - CBOR_TAG_SIGN, - CBOR_TAG_GEO_COORD, - CBOR_TAG_CBOR_MAGIC -}; - -// This is used in a bit of cleverness in GetNext_TaggedItem() to -// keep code size down and switch for the internal processing of -// these types. This will break if the first four items in -// spBuiltInTagMap don't have values 0,1,2,3. That is the -// mapping is 0 to 0, 1 to 1, 2 to 2 and 3 to 3. -#define QCBOR_TAGFLAG_DATE_STRING (0x01LL << CBOR_TAG_DATE_STRING) -#define QCBOR_TAGFLAG_DATE_EPOCH (0x01LL << CBOR_TAG_DATE_EPOCH) -#define QCBOR_TAGFLAG_POS_BIGNUM (0x01LL << CBOR_TAG_POS_BIGNUM) -#define QCBOR_TAGFLAG_NEG_BIGNUM (0x01LL << CBOR_TAG_NEG_BIGNUM) - -#define TAG_MAPPER_FIRST_FOUR (QCBOR_TAGFLAG_DATE_STRING |\ - QCBOR_TAGFLAG_DATE_EPOCH |\ - QCBOR_TAGFLAG_POS_BIGNUM |\ - QCBOR_TAGFLAG_NEG_BIGNUM) - -#define TAG_MAPPER_TOTAL_TAG_BITS 64 // Number of bits in a uint64_t -#define TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS) // 48 -#define TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS ) // 48 - -static inline int TagMapper_LookupBuiltIn(uint64_t uTag) -{ - if(sizeof(spBuiltInTagMap)/sizeof(uint16_t) > TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS) { - // This is a cross-check to make sure the above array doesn't - // accidentally get made too big. - // In normal conditions the above test should optimize out - // as all the values are known at compile time. - return -1; - } - - if(uTag > UINT16_MAX) { - // This tag map works only on 16-bit tags - return -1; - } - - for(int nTagBitIndex = 0; nTagBitIndex < (int)(sizeof(spBuiltInTagMap)/sizeof(uint16_t)); nTagBitIndex++) { - if(spBuiltInTagMap[nTagBitIndex] == uTag) { - return nTagBitIndex; - } - } - return -1; // Indicates no match -} - -static inline int TagMapper_LookupCallerConfigured(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag) -{ - for(int nTagBitIndex = 0; nTagBitIndex < pCallerConfiguredTagMap->uNumTags; nTagBitIndex++) { - if(pCallerConfiguredTagMap->puTags[nTagBitIndex] == uTag) { - return nTagBitIndex + TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX; - } - } - - return -1; // Indicates no match -} - -/* - Find the tag bit index for a given tag value, or error out - - This and the above functions could probably be optimized and made - clearer and neater. - */ -static QCBORError TagMapper_Lookup(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag, uint8_t *puTagBitIndex) -{ - int nTagBitIndex = TagMapper_LookupBuiltIn(uTag); - if(nTagBitIndex >= 0) { - // Cast is safe because TagMapper_LookupBuiltIn never returns > 47 - *puTagBitIndex = (uint8_t)nTagBitIndex; - return QCBOR_SUCCESS; - } - - if(pCallerConfiguredTagMap) { - if(pCallerConfiguredTagMap->uNumTags > QCBOR_MAX_CUSTOM_TAGS) { - return QCBOR_ERR_TOO_MANY_TAGS; - } - nTagBitIndex = TagMapper_LookupCallerConfigured(pCallerConfiguredTagMap, uTag); - if(nTagBitIndex >= 0) { - // Cast is safe because TagMapper_LookupBuiltIn never returns > 63 - - *puTagBitIndex = (uint8_t)nTagBitIndex; - return QCBOR_SUCCESS; - } - } - - return QCBOR_ERR_BAD_OPT_TAG; -} - - - - -/* - Public function, see header file - */ -void QCBORDecode_Init(QCBORDecodeContext *me, UsefulBufC EncodedCBOR, QCBORDecodeMode nDecodeMode) -{ - memset(me, 0, sizeof(QCBORDecodeContext)); - UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR); - // Don't bother with error check on decode mode. If a bad value is passed it will just act as - // if the default normal mode of 0 was set. - me->uDecodeMode = nDecodeMode; - DecodeNesting_Init(&(me->nesting)); -} - - -/* - Public function, see header file - */ -void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pCtx, const QCBORStringAllocator *pAllocator, bool bAllocAll) -{ - pCtx->pStringAllocator = (void *)pAllocator; - pCtx->bStringAllocateAll = bAllocAll; -} - -void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me, const QCBORTagListIn *pTagList) -{ - me->pCallerConfiguredTagList = pTagList; -} - - -/* - This decodes the fundamental part of a CBOR data item, the type and number - - This is the Counterpart to InsertEncodedTypeAndNumber(). - - This does the network->host byte order conversion. The conversion here - also results in the conversion for floats in addition to that for - lengths, tags and integer values. - - This returns: - pnMajorType -- the major type for the item - puNumber -- the "number" which is used a the value for integers, tags and floats and length for strings and arrays - puAdditionalInfo -- Pass this along to know what kind of float or if length is indefinite - - */ -inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf, - int *pnMajorType, - uint64_t *puArgument, - uint8_t *puAdditionalInfo) -{ - QCBORError nReturn; - - // Get the initial byte that every CBOR data item has - const uint8_t uInitialByte = UsefulInputBuf_GetByte(pUInBuf); - - // Break down the initial byte - const uint8_t uTmpMajorType = uInitialByte >> 5; - const uint8_t uAdditionalInfo = uInitialByte & 0x1f; - - // Where the number or argument accumulates - uint64_t uArgument; - - if(uAdditionalInfo >= LEN_IS_ONE_BYTE && uAdditionalInfo <= LEN_IS_EIGHT_BYTES) { - // Need to get 1,2,4 or 8 additional argument bytes - // Map LEN_IS_ONE_BYTE.. LEN_IS_EIGHT_BYTES to actual length - static const uint8_t aIterate[] = {1,2,4,8}; - - // Loop getting all the bytes in the argument - uArgument = 0; - for(int i = aIterate[uAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) { - // This shift and add gives the endian conversion - uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf); - } - } else if(uAdditionalInfo >= ADDINFO_RESERVED1 && uAdditionalInfo <= ADDINFO_RESERVED3) { - // The reserved and thus-far unused additional info values - nReturn = QCBOR_ERR_UNSUPPORTED; - goto Done; - } else { - // Less than 24, additional info is argument or 31, an indefinite length - // No more bytes to get - uArgument = uAdditionalInfo; - } - - if(UsefulInputBuf_GetError(pUInBuf)) { - nReturn = QCBOR_ERR_HIT_END; - goto Done; - } - - // All successful if we got here. - nReturn = QCBOR_SUCCESS; - *pnMajorType = uTmpMajorType; - *puArgument = uArgument; - *puAdditionalInfo = uAdditionalInfo; - -Done: - return nReturn; -} - -/* - CBOR doesn't explicitly specify two's compliment for integers but all CPUs - use it these days and the test vectors in the RFC are so. All integers in the CBOR - structure are positive and the major type indicates positive or negative. - CBOR can express positive integers up to 2^x - 1 where x is the number of bits - and negative integers down to 2^x. Note that negative numbers can be one - more away from zero than positive. - Stdint, as far as I can tell, uses two's compliment to represent - negative integers. - - See http://www.unix.org/whitepapers/64bit.html for reasons int isn't - used here in any way including in the interface - */ -inline static QCBORError DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem) -{ - // Stack usage: int/ptr 1 -- 8 - QCBORError nReturn = QCBOR_SUCCESS; - - if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) { - if (uNumber <= INT64_MAX) { - pDecodedItem->val.int64 = (int64_t)uNumber; - pDecodedItem->uDataType = QCBOR_TYPE_INT64; - - } else { - pDecodedItem->val.uint64 = uNumber; - pDecodedItem->uDataType = QCBOR_TYPE_UINT64; - - } - } else { - if(uNumber <= INT64_MAX) { - pDecodedItem->val.int64 = -uNumber-1; - pDecodedItem->uDataType = QCBOR_TYPE_INT64; - - } else { - // C can't represent a negative integer in this range - // so it is an error. todo -- test this condition - nReturn = QCBOR_ERR_INT_OVERFLOW; - } - } - - return nReturn; -} - -// Make sure #define value line up as DecodeSimple counts on this. -#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE -#error QCBOR_TYPE_FALSE macro value wrong -#endif - -#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE -#error QCBOR_TYPE_TRUE macro value wrong -#endif - -#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL -#error QCBOR_TYPE_NULL macro value wrong -#endif - -#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF -#error QCBOR_TYPE_UNDEF macro value wrong -#endif - -#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK -#error QCBOR_TYPE_BREAK macro value wrong -#endif - -#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT -#error QCBOR_TYPE_DOUBLE macro value wrong -#endif - -#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT -#error QCBOR_TYPE_FLOAT macro value wrong -#endif - -/* - Decode true, false, floats, break... - */ - -inline static QCBORError DecodeSimple(uint8_t uAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem) -{ - // Stack usage: 0 - QCBORError nReturn = QCBOR_SUCCESS; - - // uAdditionalInfo is 5 bits from the initial byte - // compile time checks above make sure uAdditionalInfo values line up with uDataType values - pDecodedItem->uDataType = uAdditionalInfo; - - switch(uAdditionalInfo) { - case ADDINFO_RESERVED1: // 28 - case ADDINFO_RESERVED2: // 29 - case ADDINFO_RESERVED3: // 30 - nReturn = QCBOR_ERR_UNSUPPORTED; - break; - - case HALF_PREC_FLOAT: - pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber); - pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE; - break; - case SINGLE_PREC_FLOAT: - pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber); - pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE; - break; - case DOUBLE_PREC_FLOAT: - pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber); - pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE; - break; - - case CBOR_SIMPLEV_FALSE: // 20 - case CBOR_SIMPLEV_TRUE: // 21 - case CBOR_SIMPLEV_NULL: // 22 - case CBOR_SIMPLEV_UNDEF: // 23 - case CBOR_SIMPLE_BREAK: // 31 - break; // nothing to do - - case CBOR_SIMPLEV_ONEBYTE: // 24 - if(uNumber <= CBOR_SIMPLE_BREAK) { - // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7 - nReturn = QCBOR_ERR_INVALID_CBOR; - goto Done; - } - /* FALLTHROUGH */ - // fall through intentionally - - default: // 0-19 - pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE; - // DecodeTypeAndNumber will make uNumber equal to uAdditionalInfo when uAdditionalInfo is < 24 - // This cast is safe because the 2, 4 and 8 byte lengths of uNumber are in the double/float cases above - pDecodedItem->val.uSimple = (uint8_t)uNumber; - break; - } - -Done: - return nReturn; -} - - - -/* - Decode text and byte strings. Call the string allocator if asked to. - */ -inline static QCBORError DecodeBytes(const QCBORStringAllocator *pAlloc, int nMajorType, uint64_t uStrLen, UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem) -{ - // Stack usage: UsefulBuf 2, int/ptr 1 40 - QCBORError nReturn = QCBOR_SUCCESS; - - const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, uStrLen); - if(UsefulBuf_IsNULLC(Bytes)) { - // Failed to get the bytes for this string item - nReturn = QCBOR_ERR_HIT_END; - goto Done; - } - - if(pAlloc) { - // We are asked to use string allocator to make a copy - UsefulBuf NewMem = pAlloc->fAllocate(pAlloc->pAllocaterContext, NULL, uStrLen); - if(UsefulBuf_IsNULL(NewMem)) { - nReturn = QCBOR_ERR_STRING_ALLOCATE; - goto Done; - } - pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes); - } else { - // Normal case with no string allocator - pDecodedItem->val.string = Bytes; - } - pDecodedItem->uDataType = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING; - -Done: - return nReturn; -} - - -/* - Mostly just assign the right data type for the date string. - */ -inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem) -{ - // Stack Use: UsefulBuf 1 16 - if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) { - return QCBOR_ERR_BAD_OPT_TAG; - } - - const UsefulBufC Temp = pDecodedItem->val.string; - pDecodedItem->val.dateString = Temp; - pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING; - return QCBOR_SUCCESS; -} - - -/* - Mostly just assign the right data type for the bignum. - */ -inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem) -{ - // Stack Use: UsefulBuf 1 -- 16 - if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) { - return QCBOR_ERR_BAD_OPT_TAG; - } - const UsefulBufC Temp = pDecodedItem->val.string; - pDecodedItem->val.bigNum = Temp; - pDecodedItem->uDataType = pDecodedItem->uTagBits & QCBOR_TAGFLAG_POS_BIGNUM ? QCBOR_TYPE_POSBIGNUM : QCBOR_TYPE_NEGBIGNUM; - return QCBOR_SUCCESS; -} - - -/* - The epoch formatted date. Turns lots of different forms of encoding date into uniform one - */ -static int DecodeDateEpoch(QCBORItem *pDecodedItem) -{ - // Stack usage: 1 - QCBORError nReturn = QCBOR_SUCCESS; - - pDecodedItem->val.epochDate.fSecondsFraction = 0; - - switch (pDecodedItem->uDataType) { - - case QCBOR_TYPE_INT64: - pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64; - break; - - case QCBOR_TYPE_UINT64: - if(pDecodedItem->val.uint64 > INT64_MAX) { - nReturn = QCBOR_ERR_DATE_OVERFLOW; - goto Done; - } - pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.uint64; - break; - - case QCBOR_TYPE_DOUBLE: - { - const double d = pDecodedItem->val.dfnum; - if(d > INT64_MAX) { - nReturn = QCBOR_ERR_DATE_OVERFLOW; - goto Done; - } - pDecodedItem->val.epochDate.nSeconds = d; // Float to integer conversion happening here. - pDecodedItem->val.epochDate.fSecondsFraction = d - pDecodedItem->val.epochDate.nSeconds; - } - break; - - default: - nReturn = QCBOR_ERR_BAD_OPT_TAG; - goto Done; - } - pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH; - -Done: - return nReturn; -} - - - - -// Make sure the constants align as this is assumed by the GetAnItem() implementation -#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY -#error QCBOR_TYPE_ARRAY value not lined up with major type -#endif -#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP -#error QCBOR_TYPE_MAP value not lined up with major type -#endif - -/* - This gets a single data item and decodes it including preceding optional tagging. This does not - deal with arrays and maps and nesting except to decode the data item introducing them. Arrays and - maps are handled at the next level up in GetNext(). - - Errors detected here include: an array that is too long to decode, hit end of buffer unexpectedly, - a few forms of invalid encoded CBOR - */ -static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem, const QCBORStringAllocator *pAlloc) -{ - // Stack usage: int/ptr 3 -- 24 - QCBORError nReturn; - - // Get the major type and the number. Number could be length of more bytes or the value depending on the major type - // nAdditionalInfo is an encoding of the length of the uNumber and is needed to decode floats and doubles - int uMajorType; - uint64_t uNumber; - uint8_t uAdditionalInfo; - - nReturn = DecodeTypeAndNumber(pUInBuf, &uMajorType, &uNumber, &uAdditionalInfo); - - // Error out here if we got into trouble on the type and number. - // The code after this will not work if the type and number is not good. - if(nReturn) - goto Done; - - memset(pDecodedItem, 0, sizeof(QCBORItem)); - - // At this point the major type and the value are valid. We've got the type and the number that - // starts every CBOR data item. - switch (uMajorType) { - case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0 - case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1 - nReturn = DecodeInteger(uMajorType, uNumber, pDecodedItem); - break; - - case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2 - case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3 - if(uAdditionalInfo == LEN_IS_INDEFINITE) { - pDecodedItem->uDataType = (uMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING; - pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX}; - } else { - nReturn = DecodeBytes(pAlloc, uMajorType, uNumber, pUInBuf, pDecodedItem); - } - break; - - case CBOR_MAJOR_TYPE_ARRAY: // Major type 4 - case CBOR_MAJOR_TYPE_MAP: // Major type 5 - // Record the number of items in the array or map - if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) { - nReturn = QCBOR_ERR_ARRAY_TOO_LONG; - goto Done; - } - if(uAdditionalInfo == LEN_IS_INDEFINITE) { - pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length - } else { - pDecodedItem->val.uCount = (uint16_t)uNumber; // type conversion OK because of check above - } - pDecodedItem->uDataType = uMajorType; // C preproc #if above makes sure constants align - break; - - case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags - pDecodedItem->val.uTagV = uNumber; - pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG; - break; - - case CBOR_MAJOR_TYPE_SIMPLE: // Major type 7, float, double, true, false, null... - nReturn = DecodeSimple(uAdditionalInfo, uNumber, pDecodedItem); - break; - - default: // Should never happen because DecodeTypeAndNumber() should never return > 7 - nReturn = QCBOR_ERR_UNSUPPORTED; - break; - } - -Done: - return nReturn; -} - - - -/* - This layer deals with indefinite length strings. It pulls all the - individual chunk items together into one QCBORItem using the - string allocator. - - Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH - */ -static inline QCBORError GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem) -{ - // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96 - QCBORError nReturn; - QCBORStringAllocator *pAlloc = (QCBORStringAllocator *)me->pStringAllocator; - UsefulBufC FullString = NULLUsefulBufC; - - nReturn = GetNext_Item(&(me->InBuf), pDecodedItem, me->bStringAllocateAll ? pAlloc: NULL); - if(nReturn) { - goto Done; - } - - // To reduce code size by removing support for indefinite length strings, the - // code in this function from here down can be eliminated. Run tests, except - // indefinite length string tests, to be sure all is OK if this is removed. - - // Only do indefinite length processing on strings - if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING && pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) { - goto Done; // no need to do any work here on non-string types - } - - // Is this a string with an indefinite length? - if(pDecodedItem->val.string.len != SIZE_MAX) { - goto Done; // length is not indefinite, so no work to do here - } - - // Can't do indefinite length strings without a string allocator - if(pAlloc == NULL) { - nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR; - goto Done; - } - - // There is an indefinite length string to work on... - // Track which type of string it is - const uint8_t uStringType = pDecodedItem->uDataType; - - // Loop getting chunk of indefinite string - for(;;) { - // Get item for next chunk - QCBORItem StringChunkItem; - // NULL passed to never string alloc chunk of indefinite length strings - nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL); - if(nReturn) { - break; // Error getting the next chunk - } - - // See if it is a marker at end of indefinite length string - if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) { - // String is complete - pDecodedItem->val.string = FullString; - pDecodedItem->uDataAlloc = 1; - break; - } - - // Match data type of chunk to type at beginning. - // Also catches error of other non-string types that don't belong. - if(StringChunkItem.uDataType != uStringType) { - nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK; - break; - } - - // Alloc new buffer or expand previously allocated buffer so it can fit - UsefulBuf NewMem = (*pAlloc->fAllocate)(pAlloc->pAllocaterContext, - UNCONST_POINTER(FullString.ptr), - FullString.len + StringChunkItem.val.string.len); - if(UsefulBuf_IsNULL(NewMem)) { - // Allocation of memory for the string failed - nReturn = QCBOR_ERR_STRING_ALLOCATE; - break; - } - - // Copy new string chunk at the end of string so far. - FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string); - } - -Done: - if(pAlloc && nReturn && !UsefulBuf_IsNULLC(FullString)) { - // Getting item failed, clean up the allocated memory - (pAlloc->fFree)(pAlloc->pAllocaterContext, UNCONST_POINTER(FullString.ptr)); - } - - return nReturn; -} - - -/* - Returns an error if there was something wrong with the optional item or it couldn't - be handled. - */ -static QCBORError GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem, QCBORTagListOut *pTags) -{ - // Stack usage: int/ptr: 3 -- 24 - QCBORError nReturn; - uint64_t uTagBits = 0; - if(pTags) { - pTags->uNumUsed = 0; - } - - for(;;) { - nReturn = GetNext_FullItem(me, pDecodedItem); - if(nReturn) { - goto Done; // Error out of the loop - } - - if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) { - // Successful exit from loop; maybe got some tags, maybe not - pDecodedItem->uTagBits = uTagBits; - break; - } - - uint8_t uTagBitIndex; - // Tag was mapped, tag was not mapped, error with tag list - switch(TagMapper_Lookup(me->pCallerConfiguredTagList, pDecodedItem->val.uTagV, &uTagBitIndex)) { - - case QCBOR_SUCCESS: - // Successfully mapped the tag - uTagBits |= 0x01ULL << uTagBitIndex; - break; - - case QCBOR_ERR_BAD_OPT_TAG: - // Tag is not recognized. Do nothing - break; - - default: - // Error Condition - goto Done; - } - - if(pTags) { - // Caller wants all tags recorded in the provided buffer - if(pTags->uNumUsed >= pTags->uNumAllocated) { - nReturn = QCBOR_ERR_TOO_MANY_TAGS; - goto Done; - } - pTags->puTags[pTags->uNumUsed] = pDecodedItem->val.uTagV; - pTags->uNumUsed++; - } - } - - switch(pDecodedItem->uTagBits & TAG_MAPPER_FIRST_FOUR) { - case 0: - // No tags at all or none we know about. Nothing to do. - // This is part of the pass-through path of this function - // that will mostly be taken when decoding any item. - break; - - case QCBOR_TAGFLAG_DATE_STRING: - nReturn = DecodeDateString(pDecodedItem); - break; - - case QCBOR_TAGFLAG_DATE_EPOCH: - nReturn = DecodeDateEpoch(pDecodedItem); - break; - - case QCBOR_TAGFLAG_POS_BIGNUM: - case QCBOR_TAGFLAG_NEG_BIGNUM: - nReturn = DecodeBigNum(pDecodedItem); - break; - - default: - // Encountering some mixed up CBOR like something that - // is tagged as both a string and integer date. - nReturn = QCBOR_ERR_BAD_OPT_TAG; - } - -Done: - return nReturn; -} - - -/* - This layer takes care of map entries. It combines the label and data items into one QCBORItem. - */ -static inline QCBORError GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem, QCBORTagListOut *pTags) -{ - // Stack use: int/ptr 1, QCBORItem -- 56 - QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags); - if(nReturn) - goto Done; - - if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) { - // Break can't be a map entry - goto Done; - } - - if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) { - // In a map and caller wants maps decoded, not treated as arrays - - if(DecodeNesting_TypeIsMap(&(me->nesting))) { - // If in a map and the right decoding mode, get the label - - // Get the next item which will be the real data; Item will be the label - QCBORItem LabelItem = *pDecodedItem; - nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags); - if(nReturn) - goto Done; - - pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc; - - if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) { - // strings are always good labels - pDecodedItem->label.string = LabelItem.val.string; - pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING; - } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) { - // It's not a string and we only want strings, probably for easy translation to JSON - nReturn = QCBOR_ERR_MAP_LABEL_TYPE; - goto Done; - } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) { - pDecodedItem->label.int64 = LabelItem.val.int64; - pDecodedItem->uLabelType = QCBOR_TYPE_INT64; - } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) { - pDecodedItem->label.uint64 = LabelItem.val.uint64; - pDecodedItem->uLabelType = QCBOR_TYPE_UINT64; - } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) { - pDecodedItem->label.string = LabelItem.val.string; - pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc; - pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING; - } else { - // label is not an int or a string. It is an arrray - // or a float or such and this implementation doesn't handle that. - // Also, tags on labels are ignored. - nReturn = QCBOR_ERR_MAP_LABEL_TYPE; - goto Done; - } - } - } else { - if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) { - // Decoding a map as an array - pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY; - pDecodedItem->val.uCount *= 2; - } - } - -Done: - return nReturn; -} - - -/* - Public function, see header qcbor.h file - */ -QCBORError QCBORDecode_GetNextWithTags(QCBORDecodeContext *me, QCBORItem *pDecodedItem, QCBORTagListOut *pTags) -{ - // Stack ptr/int: 2, QCBORItem : 64 - - // The public entry point for fetching and parsing the next QCBORItem. - // All the CBOR parsing work is here and in subordinate calls. - QCBORError nReturn; - - nReturn = GetNext_MapEntry(me, pDecodedItem, pTags); - if(nReturn) { - goto Done; - } - - // Break ending arrays/maps are always processed at the end of this function. - // They should never show up here. - if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) { - nReturn = QCBOR_ERR_BAD_BREAK; - goto Done; - } - - // Record the nesting level for this data item before processing any of - // decrementing and descending. - pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting)); - - // Process the item just received for descent or decrement, and - // ascent if decrements are enough to close out a definite length array/map - if(IsMapOrArray(pDecodedItem->uDataType)) { - // If the new item is array or map, the nesting level descends - nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem); - // Maps and arrays do count in as items in the map/array that encloses - // them so a decrement needs to be done for them too, but that is done - // only when all the items in them have been processed, not when they - // are opened. - } else { - // Decrement the count of items in the enclosing map/array - // If the count in the enclosing map/array goes to zero, that - // triggers a decrement in the map/array above that and - // an ascend in nesting level. - DecodeNesting_DecrementCount(&(me->nesting)); - } - if(nReturn) { - goto Done; - } - - // For indefinite length maps/arrays, looking at any and - // all breaks that might terminate them. The equivalent - // for definite length maps/arrays happens in - // DecodeNesting_DecrementCount(). - if(DecodeNesting_IsNested(&(me->nesting)) && DecodeNesting_IsIndefiniteLength(&(me->nesting))) { - while(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) { - // Peek forward one item to see if it is a break. - QCBORItem Peek; - size_t uPeek = UsefulInputBuf_Tell(&(me->InBuf)); - nReturn = GetNext_Item(&(me->InBuf), &Peek, NULL); - if(nReturn) { - goto Done; - } - if(Peek.uDataType != QCBOR_TYPE_BREAK) { - // It is not a break, rewind so it can be processed normally. - UsefulInputBuf_Seek(&(me->InBuf), uPeek); - break; - } - // It is a break. Ascend one nesting level. - // The break is consumed. - nReturn = DecodeNesting_BreakAscend(&(me->nesting)); - if(nReturn) { - // break occured outside of an indefinite length array/map - goto Done; - } - } - } - - // Tell the caller what level is next. This tells them what maps/arrays - // were closed out and makes it possible for them to reconstruct - // the tree with just the information returned by GetNext - pDecodedItem->uNextNestLevel = DecodeNesting_GetLevel(&(me->nesting)); - -Done: - return nReturn; -} - - -QCBORError QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem) -{ - return QCBORDecode_GetNextWithTags(me, pDecodedItem, NULL); -} - - -/* - Decoding items is done in 5 layered functions, one calling the - next one down. If a layer has no work to do for a particular item - it returns quickly. - - - QCBORDecode_GetNext -- The top layer manages the beginnings and - ends of maps and arrays. It tracks descending into and ascending - out of maps/arrays. It processes all breaks that terminate - maps and arrays. - - - GetNext_MapEntry -- This handles the combining of two - items, the label and the data, that make up a map entry. - It only does work on maps. It combines the label and data - items into one labeled item. - - - GetNext_TaggedItem -- This handles the type 6 tagged items. - It accumulates all the tags and combines them with the following - non-tagged item. If the tagged item is something that is understood - like a date, the decoding of that item is invoked. - - - GetNext_FullItem -- This assembles the sub items that make up - an indefinte length string into one string item. It uses the - string allocater to create contiguous space for the item. It - processes all breaks that are part of indefinite length strings. - - - GetNext_Item -- This gets and decodes the most atomic - item in CBOR, the thing with an initial byte containing - the major type. - - Roughly this takes 300 bytes of stack for vars. Need to - evaluate this more carefully and correctly. - - */ - - -/* - Public function, see header qcbor.h file - */ -int QCBORDecode_IsTagged(QCBORDecodeContext *me, const QCBORItem *pItem, uint64_t uTag) -{ - const QCBORTagListIn *pCallerConfiguredTagMap = me->pCallerConfiguredTagList; - - uint8_t uTagBitIndex; - // Do not care about errors in pCallerConfiguredTagMap here. They are - // caught during GetNext() before this is called. - if(TagMapper_Lookup(pCallerConfiguredTagMap, uTag, &uTagBitIndex)) { - return 0; - } - - const uint64_t uTagBit = 0x01ULL << uTagBitIndex; - return (uTagBit & pItem->uTagBits) != 0; -} - - -/* - Public function, see header qcbor.h file - */ -QCBORError QCBORDecode_Finish(QCBORDecodeContext *me) -{ - int nReturn = QCBOR_SUCCESS; - - // Error out if all the maps/arrays are not closed out - if(DecodeNesting_IsNested(&(me->nesting))) { - nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN; - goto Done; - } - - // Error out if not all the bytes are consumed - if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) { - nReturn = QCBOR_ERR_EXTRA_BYTES; - } - -Done: - // Call the destructor for the string allocator if there is one. - // Always called, even if there are errors; always have to clean up - if(me->pStringAllocator) { - QCBORStringAllocator *pAllocator = (QCBORStringAllocator *)me->pStringAllocator; - if(pAllocator->fDestructor) { - (pAllocator->fDestructor)(pAllocator->pAllocaterContext); - } - } - - return nReturn; -} - - - -/* - -Decoder errors handled in this file - - - Hit end of input before it was expected while decoding type and number QCBOR_ERR_HIT_END - - - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW - - - Hit end of input while decoding a text or byte string QCBOR_ERR_HIT_END - - - Encountered conflicting tags -- e.g., an item is tagged both a date string and an epoch date QCBOR_ERR_UNSUPPORTED - - - Encontered an array or mapp that has too many items QCBOR_ERR_ARRAY_TOO_LONG - - - Encountered array/map nesting that is too deep QCBOR_ERR_ARRAY_NESTING_TOO_DEEP - - - An epoch date > INT64_MAX or < INT64_MIN was encountered QCBOR_ERR_DATE_OVERFLOW - - - The type of a map label is not a string or int QCBOR_ERR_MAP_LABEL_TYPE - - - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES - - */ - - - - -/* - This is a very primitive memory allocator. It does not track individual - allocations, only a high-water mark. A free or reallotcation must be of - the last chunk allocated. - - All of this following code will get dead-stripped if QCBORDecode_SetMemPool() - is not called. - */ - -typedef struct { - QCBORStringAllocator StringAllocator; - uint8_t *pStart; // First byte that can be allocated - uint8_t *pEnd; // One past the last byte that can be allocated - uint8_t *pFree; // Where the next free chunk is -} MemPool; - - -/* - Internal function for an allocation - - Code Reviewers: THIS FUNCTION DOES POINTER MATH - */ -static UsefulBuf MemPool_Alloc(void *ctx, void *pMem, size_t uNewSize) -{ - MemPool *me = (MemPool *)ctx; - void *pReturn = NULL; - - if(pMem) { - // Realloc case - // This check will work even if uNewSize is a super-large value like UINT64_MAX - if((uNewSize <= (size_t)(me->pEnd - (uint8_t *)pMem)) && ((uint8_t *)pMem >= me->pStart)) { - me->pFree = (uint8_t *)pMem + uNewSize; - pReturn = pMem; - } - } else { - // New chunk case - // This check will work even if uNewSize is a super large value like UINT64_MAX - if(uNewSize <= (size_t)(me->pEnd - me->pFree)) { - pReturn = me->pFree; - me->pFree += uNewSize; - } - } - - return (UsefulBuf){pReturn, uNewSize}; -} - -/* - Internal function to free memory - */ -static void MemPool_Free(void *ctx, void *pOldMem) -{ - MemPool *me = (MemPool *)ctx; - me->pFree = pOldMem; -} - -/* - Public function, see header qcbor.h file - */ -QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *me, UsefulBuf Pool, bool bAllStrings) -{ - // The idea behind QCBOR_MIN_MEM_POOL_SIZE is - // that the caller knows exactly what size to - // allocate and that the tests can run conclusively - // no matter what size MemPool is - // even though it wastes some memory. MemPool - // will vary depending on pointer size of the - // the machine. QCBOR_MIN_MEM_POOL_SIZE is - // set for pointers up to 64-bits. This - // wastes about 50 bytes on a 32-bit machine. - // This check makes sure things don't go - // horribly wrong. It should optimize out - // when there is no problem as the sizes are - // known at compile time. - if(sizeof(MemPool) > QCBOR_DECODE_MIN_MEM_POOL_SIZE) { - return QCBOR_ERR_MEM_POOL_INTERNAL; - } - - // The first bytes of the Pool passed in are used - // as the context (vtable of sorts) for the memory pool - // allocator. - if(Pool.len < QCBOR_DECODE_MIN_MEM_POOL_SIZE) { - return QCBOR_ERR_BUFFER_TOO_SMALL; - } - MemPool *pMP = (MemPool *)Pool.ptr; - - // Fill in the "vtable" - pMP->StringAllocator.fAllocate = MemPool_Alloc; - pMP->StringAllocator.fFree = MemPool_Free; - pMP->StringAllocator.fDestructor = NULL; - - // Set up the pointers to the memory to be allocated - pMP->pStart = (uint8_t *)Pool.ptr + QCBOR_DECODE_MIN_MEM_POOL_SIZE; - pMP->pFree = pMP->pStart; - pMP->pEnd = (uint8_t *)Pool.ptr + Pool.len; - - // More book keeping of context - pMP->StringAllocator.pAllocaterContext = pMP; - me->pStringAllocator = pMP; - - // The flag indicating when to use the allocator - me->bStringAllocateAll = bAllStrings; - - return QCBOR_SUCCESS; -} - - -/* - Extra little hook to make MemPool testing work right - without adding any code size or overhead to non-test - uses. This will get dead-stripped for non-test use. - - This is not a public function. - */ -size_t MemPoolTestHook_GetPoolSize(void *ctx) -{ - MemPool *me = (MemPool *)ctx; - - return me->pEnd - me->pStart; -} - diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/src/qcbor_encode.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/src/qcbor_encode.c deleted file mode 100644 index d18d811..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/src/qcbor_encode.c +++ /dev/null @@ -1,651 +0,0 @@ -/*============================================================================== - Copyright (c) 2016-2018, The Linux Foundation. - Copyright (c) 2018-2019, Laurence Lundblade. - All rights reserved. - SPDX-License-Identifier: BSD-3-Clause - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of The Linux Foundation nor the names of its - contributors, nor the name "Laurence Lundblade" may be used to - endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS -BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ==============================================================================*/ - -/*=================================================================================== - FILE: qcbor_encode.c - - DESCRIPTION: This file contains the implementation of QCBOR. - - EDIT HISTORY FOR FILE: - - This section contains comments describing changes made to the module. - Notice that changes are listed in reverse chronological order. - - when who what, where, why - -------- ---- --------------------------------------------------- - 12/30/18 llundblade Small efficient clever encode of type & argument. - 11/29/18 llundblade Rework to simpler handling of tags and labels. - 11/9/18 llundblade Error codes are now enums. - 11/1/18 llundblade Floating support. - 10/31/18 llundblade Switch to one license that is almost BSD-3. - 09/28/18 llundblade Added bstr wrapping feature for COSE implementation. - 02/05/18 llundbla Works on CPUs which require integer alignment. - Requires new version of UsefulBuf. - 07/05/17 llundbla Add bstr wrapping of maps/arrays for COSE - 03/01/17 llundbla More data types - 11/13/16 llundbla Integrate most TZ changes back into github version. - 09/30/16 gkanike Porting to TZ. - 03/15/16 llundbla Initial Version. - - =====================================================================================*/ - -#include "qcbor.h" -#include "ieee754.h" - - -/*...... This is a ruler that is 80 characters long...........................*/ - - -/* - CBOR's two nesting types, arrays and maps, are tracked here. There is a - limit of QCBOR_MAX_ARRAY_NESTING to the number of arrays and maps - that can be nested in one encoding so the encoding context stays - small enough to fit on the stack. - - When an array / map is opened, pCurrentNesting points to the element - in pArrays that records the type, start position and accumluates a - count of the number of items added. When closed the start position is - used to go back and fill in the type and number of items in the array - / map. - - Encoded output be just items like ints and strings that are - not part of any array / map. That is, the first thing encoded - does not have to be an array or a map. - */ -inline static void Nesting_Init(QCBORTrackNesting *pNesting) -{ - // assumes pNesting has been zeroed - pNesting->pCurrentNesting = &pNesting->pArrays[0]; - // Implied CBOR array at the top nesting level. This is never returned, - // but makes the item count work correctly. - pNesting->pCurrentNesting->uMajorType = CBOR_MAJOR_TYPE_ARRAY; -} - -inline static QCBORError Nesting_Increase(QCBORTrackNesting *pNesting, - uint8_t uMajorType, - uint32_t uPos) -{ - QCBORError nReturn = QCBOR_SUCCESS; - - if(pNesting->pCurrentNesting == &pNesting->pArrays[QCBOR_MAX_ARRAY_NESTING]) { - // trying to open one too many - nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP; - } else { - pNesting->pCurrentNesting++; - pNesting->pCurrentNesting->uCount = 0; - pNesting->pCurrentNesting->uStart = uPos; - pNesting->pCurrentNesting->uMajorType = uMajorType; - } - return nReturn; -} - -inline static void Nesting_Decrease(QCBORTrackNesting *pNesting) -{ - pNesting->pCurrentNesting--; -} - -inline static QCBORError Nesting_Increment(QCBORTrackNesting *pNesting) -{ - if(1 >= QCBOR_MAX_ITEMS_IN_ARRAY - pNesting->pCurrentNesting->uCount) { - return QCBOR_ERR_ARRAY_TOO_LONG; - } - - pNesting->pCurrentNesting->uCount += 1; - - return QCBOR_SUCCESS; -} - -inline static uint16_t Nesting_GetCount(QCBORTrackNesting *pNesting) -{ - // The nesting count recorded is always the actual number of individiual - // data items in the array or map. For arrays CBOR uses the actual item - // count. For maps, CBOR uses the number of pairs. This function returns - // the number needed for the CBOR encoding, so it divides the number of - // items by two for maps to get the number of pairs. This implementation - // takes advantage of the map major type being one larger the array major - // type, hence uDivisor is either 1 or 2. - const uint16_t uDivisor = pNesting->pCurrentNesting->uMajorType - CBOR_MAJOR_TYPE_ARRAY+1; - - return pNesting->pCurrentNesting->uCount / uDivisor; -} - -inline static uint32_t Nesting_GetStartPos(QCBORTrackNesting *pNesting) -{ - return pNesting->pCurrentNesting->uStart; -} - -inline static uint8_t Nesting_GetMajorType(QCBORTrackNesting *pNesting) -{ - return pNesting->pCurrentNesting->uMajorType; -} - -inline static int Nesting_IsInNest(QCBORTrackNesting *pNesting) -{ - return pNesting->pCurrentNesting == &pNesting->pArrays[0] ? 0 : 1; -} - - - - -/* - Error tracking plan -- Errors are tracked internally and not returned - until Finish is called. The CBOR errors are in me->uError. - UsefulOutBuf also tracks whether the buffer is full or not in its - context. Once either of these errors is set they are never - cleared. Only QCBOREncode_Init() resets them. Or said another way, they must - never be cleared or we'll tell the caller all is good when it is not. - - Only one error code is reported by QCBOREncode_Finish() even if there are - multiple errors. The last one set wins. The caller might have to fix - one error to reveal the next one they have to fix. This is OK. - - The buffer full error tracked by UsefulBuf is only pulled out of - UsefulBuf in Finish() so it is the one that usually wins. UsefulBuf - will never go off the end of the buffer even if it is called again - and again when full. - - It is really tempting to not check for overflow on the count in the - number of items in an array. It would save a lot of code, it is - extremely unlikely that any one will every put 65,000 items in an - array, and the only bad thing that would happen is the CBOR would be - bogus. - - Since this does not parse any input, you could in theory remove all - error checks in this code if you knew the caller called it - correctly. Maybe someday CDDL or some such language will be able to - generate the code to call this and the calling code would always be - correct. This could also automatically size some of the data - structures like array/map nesting resulting in some stack memory - savings. - - Errors returned here fall into two categories: - - Sizes - QCBOR_ERR_BUFFER_TOO_LARGE -- Encoded output exceeded UINT32_MAX - QCBOR_ERR_BUFFER_TOO_SMALL -- output buffer too small - - QCBOR_ERR_ARRAY_NESTING_TOO_DEEP -- Array/map nesting > QCBOR_MAX_ARRAY_NESTING1 - QCBOR_ERR_ARRAY_TOO_LONG -- Too many things added to an array/map - - Nesting constructed incorrectly - QCBOR_ERR_TOO_MANY_CLOSES -- more close calls than opens - QCBOR_ERR_CLOSE_MISMATCH -- Type of close does not match open - QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN -- Finish called without enough closes - */ - - - - -/* - Public function for initialization. See header qcbor.h - */ -void QCBOREncode_Init(QCBOREncodeContext *me, UsefulBuf Storage) -{ - memset(me, 0, sizeof(QCBOREncodeContext)); - UsefulOutBuf_Init(&(me->OutBuf), Storage); - Nesting_Init(&(me->nesting)); -} - - - - -/* - All CBOR data items have a type and an "argument". The argument is - either the value of the item for integer types, the length of the - content for string, byte, array and map types, a tag for major type - 6, and has several uses for major type 7. - - This function encodes the type and the argument. There are several - encodings for the argument depending on how large it is and how it is - used. - - Every encoding of the type and argument has at least one byte, the - "initial byte". - - The top three bits of the initial byte are the major type for the - CBOR data item. The eight major types defined by the standard are - defined as CBOR_MAJOR_TYPE_xxxx in qcbor.h. - - The remaining five bits, known as "additional information", and - possibly more bytes encode the argument. If the argument is less than - 24, then it is encoded entirely in the five bits. This is neat - because it allows you to encode an entire CBOR data item in 1 byte - for many values and types (integers 0-23, true, false, and tags). - - If the argument is larger than 24, then it is encoded in 1,2,4 or 8 - additional bytes, with the number of these bytes indicated by the - values of the 5 bits 24, 25, 25 and 27. - - It is possible to encode a particular argument in many ways with this - representation. This implementation always uses the smallest - possible representation. This conforms with CBOR preferred encoding. - - This function inserts them into the output buffer at the specified - position. AppendEncodedTypeAndNumber() appends to the end. - - This function takes care of converting to network byte order. - - This function is also used to insert floats and doubles. Before this - function is called the float or double must be copied into a - uint64_t. That is how they are passed in. They are then converted to - network byte order correctly. The uMinLen param makes sure that even - - if all the digits of a half, float or double are 0 it is still - correctly encoded in 2, 4 or 8 bytes. - */ - -static void InsertEncodedTypeAndNumber(QCBOREncodeContext *me, - uint8_t uMajorType, - int nMinLen, - uint64_t uNumber, - size_t uPos) -{ - /* - This code does endian conversion without hton or knowing the - endianness of the machine using masks and shifts. This avoids the - dependency on hton and the mess of figuring out how to find the - machine's endianness. - - This is a good efficient implementation on little-endian machines. - A faster and small implementation is possible on big-endian - machines because CBOR/network byte order is big endian. However - big endian machines are uncommon. - - On x86, it is about 200 bytes instead of 500 bytes for the more - formal unoptimized code. - - This also does the CBOR preferred shortest encoding for integers - and is called to do endian conversion for floats. - - It works backwards from the LSB to the MSB as needed. - - Code Reviewers: THIS FUNCTION DOES POINTER MATH - */ - // Holds up to 9 bytes of type and argument - // plus one extra so pointer always points to - // valid bytes. - uint8_t bytes[sizeof(uint64_t)+2]; - // Point to the last bytes and work backwards - uint8_t *pByte = &bytes[sizeof(bytes)-1]; - // This is the 5 bits in the initial byte that is not the major type - uint8_t uAdditionalInfo; - - if(uNumber < CBOR_TWENTY_FOUR && nMinLen == 0) { - // Simple case where argument is < 24 - uAdditionalInfo = uNumber; - } else { - /* - Encode argument in 1,2,4 or 8 bytes. Outer loop - runs once for 1 byte and 4 times for 8 bytes. - Inner loop runs 1, 2 or 4 times depending on - outer loop counter. This works backwards taking - 8 bits off the argument being encoded at a time - until all bits from uNumber have been encoded - and the minimum encoding size is reached. - Minimum encoding size is for floating point - numbers with zero bytes. - */ - static const uint8_t aIterate[] = {1,1,2,4}; - uint8_t i; - for(i = 0; uNumber || nMinLen > 0; i++) { - const uint8_t uIterations = aIterate[i]; - for(int j = 0; j < uIterations; j++) { - *--pByte = uNumber & 0xff; - uNumber = uNumber >> 8; - } - nMinLen -= uIterations; - } - // Additional info is the encoding of the - // number of additional bytes to encode - // argument. - uAdditionalInfo = LEN_IS_ONE_BYTE-1 + i; - } - *--pByte = (uMajorType << 5) + uAdditionalInfo; - - UsefulOutBuf_InsertData(&(me->OutBuf), pByte, &bytes[sizeof(bytes)-1] - pByte, uPos); -} - - -/* - Append the type and number info to the end of the buffer. - - See InsertEncodedTypeAndNumber() function above for details -*/ -inline static void AppendEncodedTypeAndNumber(QCBOREncodeContext *me, - uint8_t uMajorType, - uint64_t uNumber) -{ - // An append is an insert at the end. - InsertEncodedTypeAndNumber(me, - uMajorType, - 0, - uNumber, - UsefulOutBuf_GetEndPosition(&(me->OutBuf))); -} - - - - -/* - Public functions for closing arrays and maps. See header qcbor.h - */ -void QCBOREncode_AddUInt64(QCBOREncodeContext *me, uint64_t uValue) -{ - if(me->uError == QCBOR_SUCCESS) { - AppendEncodedTypeAndNumber(me, CBOR_MAJOR_TYPE_POSITIVE_INT, uValue); - me->uError = Nesting_Increment(&(me->nesting)); - } -} - - -/* - Public functions for closing arrays and maps. See header qcbor.h - */ -void QCBOREncode_AddInt64(QCBOREncodeContext *me, int64_t nNum) -{ - if(me->uError == QCBOR_SUCCESS) { - uint8_t uMajorType; - uint64_t uValue; - - if(nNum < 0) { - // In CBOR -1 encodes as 0x00 with major type negative int. - uValue = (uint64_t)(-nNum - 1); - uMajorType = CBOR_MAJOR_TYPE_NEGATIVE_INT; - } else { - uValue = (uint64_t)nNum; - uMajorType = CBOR_MAJOR_TYPE_POSITIVE_INT; - } - - AppendEncodedTypeAndNumber(me, uMajorType, uValue); - me->uError = Nesting_Increment(&(me->nesting)); - } -} - - -/* - Semi-private function. It is exposed to user of the interface, - but they will usually call one of the inline wrappers rather than this. - - See header qcbor.h - - Does the work of adding some bytes to the CBOR output. Works for a - byte and text strings, which are the same in in CBOR though they have - different major types. This is also used to insert raw - pre-encoded CBOR. - */ -void QCBOREncode_AddBuffer(QCBOREncodeContext *me, uint8_t uMajorType, UsefulBufC Bytes) -{ - if(me->uError == QCBOR_SUCCESS) { - // If it is not Raw CBOR, add the type and the length - if(uMajorType != CBOR_MAJOR_NONE_TYPE_RAW) { - AppendEncodedTypeAndNumber(me, uMajorType, Bytes.len); - } - - // Actually add the bytes - UsefulOutBuf_AppendUsefulBuf(&(me->OutBuf), Bytes); - - // Update the array counting if there is any nesting at all - me->uError = Nesting_Increment(&(me->nesting)); - } -} - - -/* - Public functions for closing arrays and maps. See header qcbor.h - */ -void QCBOREncode_AddTag(QCBOREncodeContext *me, uint64_t uTag) -{ - AppendEncodedTypeAndNumber(me, CBOR_MAJOR_TYPE_OPTIONAL, uTag); -} - - -/* - Semi-private function. It is exposed to user of the interface, - but they will usually call one of the inline wrappers rather than this. - - See header qcbor.h - */ -void QCBOREncode_AddType7(QCBOREncodeContext *me, size_t uSize, uint64_t uNum) -{ - if(me->uError == QCBOR_SUCCESS) { - // This function call takes care of endian swapping for the float / double - InsertEncodedTypeAndNumber(me, - // The major type for floats and doubles - CBOR_MAJOR_TYPE_SIMPLE, - // size makes sure floats with zeros encode correctly - (int)uSize, - // Bytes of the floating point number as a uint - uNum, - // end position because this is append - UsefulOutBuf_GetEndPosition(&(me->OutBuf))); - - me->uError = Nesting_Increment(&(me->nesting)); - } -} - - -/* - Public functions for closing arrays and maps. See header qcbor.h - */ -void QCBOREncode_AddDouble(QCBOREncodeContext *me, double dNum) -{ - const IEEE754_union uNum = IEEE754_DoubleToSmallest(dNum); - - QCBOREncode_AddType7(me, uNum.uSize, uNum.uValue); -} - - -/* - Semi-public function. It is exposed to user of the interface, - but they will usually call one of the inline wrappers rather than this. - - See header qcbor.h -*/ -void QCBOREncode_OpenMapOrArray(QCBOREncodeContext *me, uint8_t uMajorType) -{ - // Add one item to the nesting level we are in for the new map or array - me->uError = Nesting_Increment(&(me->nesting)); - if(me->uError == QCBOR_SUCCESS) { - // The offset where the length of an array or map will get written - // is stored in a uint32_t, not a size_t to keep stack usage smaller. This - // checks to be sure there is no wrap around when recording the offset. - // Note that on 64-bit machines CBOR larger than 4GB can be encoded as long as no - // array / map offsets occur past the 4GB mark, but the public interface - // says that the maximum is 4GB to keep the discussion simpler. - size_t uEndPosition = UsefulOutBuf_GetEndPosition(&(me->OutBuf)); - - // QCBOR_MAX_ARRAY_OFFSET is slightly less than UINT32_MAX so this - // code can run on a 32-bit machine and tests can pass on a 32-bit - // machine. If it was exactly UINT32_MAX, then this code would - // not compile or run on a 32-bit machine and an #ifdef or some - // machine size detection would be needed reducing portability. - if(uEndPosition >= QCBOR_MAX_ARRAY_OFFSET) { - me->uError = QCBOR_ERR_BUFFER_TOO_LARGE; - - } else { - // Increase nesting level because this is a map or array. - // Cast from size_t to uin32_t is safe because of check above - me->uError = Nesting_Increase(&(me->nesting), uMajorType, (uint32_t)uEndPosition); - } - } -} - - -/* - Public functions for closing arrays and maps. See header qcbor.h - */ -void QCBOREncode_CloseMapOrArray(QCBOREncodeContext *me, - uint8_t uMajorType, - UsefulBufC *pWrappedCBOR) -{ - if(me->uError == QCBOR_SUCCESS) { - if(!Nesting_IsInNest(&(me->nesting))) { - me->uError = QCBOR_ERR_TOO_MANY_CLOSES; - } else if(Nesting_GetMajorType(&(me->nesting)) != uMajorType) { - me->uError = QCBOR_ERR_CLOSE_MISMATCH; - } else { - // When the array, map or bstr wrap was started, nothing was done - // except note the position of the start of it. This code goes back - // and inserts the actual CBOR array, map or bstr and its length. - // That means all the data that is in the array, map or wrapped - // needs to be slid to the right. This is done by UsefulOutBuf's - // insert function that is called from inside - // InsertEncodedTypeAndNumber() - const size_t uInsertPosition = Nesting_GetStartPos(&(me->nesting)); - const size_t uEndPosition = UsefulOutBuf_GetEndPosition(&(me->OutBuf)); - // This can't go negative because the UsefulOutBuf always only grows - // and never shrinks. UsefulOutBut itself also has defenses such that - // it won't write were it should not even if given hostile input lengths - const size_t uLenOfEncodedMapOrArray = uEndPosition - uInsertPosition; - - // Length is number of bytes for a bstr and number of items a for map & array - const size_t uLength = uMajorType == CBOR_MAJOR_TYPE_BYTE_STRING ? - uLenOfEncodedMapOrArray : Nesting_GetCount(&(me->nesting)); - - // Actually insert - InsertEncodedTypeAndNumber(me, - uMajorType, // major type bstr, array or map - 0, // no minimum length for encoding - uLength, // either len of bstr or num map / array items - uInsertPosition); // position in out buffer - - // Return pointer and length to the enclosed encoded CBOR. The intended - // use is for it to be hashed (e.g., SHA-256) in a COSE implementation. - // This must be used right away, as the pointer and length go invalid - // on any subsequent calls to this function because of the - // InsertEncodedTypeAndNumber() call that slides data to the right. - if(pWrappedCBOR) { - const UsefulBufC PartialResult = UsefulOutBuf_OutUBuf(&(me->OutBuf)); - const size_t uBstrLen = UsefulOutBuf_GetEndPosition(&(me->OutBuf)) - uEndPosition; - *pWrappedCBOR = UsefulBuf_Tail(PartialResult, uInsertPosition+uBstrLen); - } - Nesting_Decrease(&(me->nesting)); - } - } -} - - - - -/* - Public functions to finish and get the encoded result. See header qcbor.h - */ -QCBORError QCBOREncode_Finish(QCBOREncodeContext *me, UsefulBufC *pEncodedCBOR) -{ - QCBORError uReturn = me->uError; - - if(uReturn != QCBOR_SUCCESS) { - goto Done; - } - - if (Nesting_IsInNest(&(me->nesting))) { - uReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN; - goto Done; - } - - if(UsefulOutBuf_GetError(&(me->OutBuf))) { - // Stuff didn't fit in the buffer. - // This check catches this condition for all the appends and inserts - // so checks aren't needed when the appends and inserts are performed. - // And of course UsefulBuf will never overrun the input buffer given - // to it. No complex analysis of the error handling in this file is - // needed to know that is true. Just read the UsefulBuf code. - uReturn = QCBOR_ERR_BUFFER_TOO_SMALL; - goto Done; - } - - *pEncodedCBOR = UsefulOutBuf_OutUBuf(&(me->OutBuf)); - -Done: - return uReturn; -} - - -/* - Public functions to finish and get the encoded result. See header qcbor.h - */ -QCBORError QCBOREncode_FinishGetSize(QCBOREncodeContext *me, size_t *puEncodedLen) -{ - UsefulBufC Enc; - - QCBORError nReturn = QCBOREncode_Finish(me, &Enc); - - if(nReturn == QCBOR_SUCCESS) { - *puEncodedLen = Enc.len; - } - - return nReturn; -} - - - - -/* - Notes on the code - - CBOR Major Type Public Function - 0 QCBOREncode_AddUInt64 - 0, 1 QCBOREncode_AddUInt64, QCBOREncode_AddInt64 - 2, 3 QCBOREncode_AddBuffer, Also QCBOREncode_OpenMapOrArray - 4, 5 QCBOREncode_OpenMapOrArray - 6 QCBOREncode_AddTag - 7 QCBOREncode_AddDouble, QCBOREncode_AddType7 - - Object code sizes on X86 with LLVM compiler and -Os (Dec 30, 2018) - - _QCBOREncode_Init 69 - _QCBOREncode_AddUInt64 76 - _QCBOREncode_AddInt64 87 - _QCBOREncode_AddBuffer 113 - _QCBOREncode_AddTag 27 - _QCBOREncode_AddType7 87 - _QCBOREncode_AddDouble 36 - _QCBOREncode_OpenMapOrArray 103 - _QCBOREncode_CloseMapOrArray 181 - _InsertEncodedTypeAndNumber 190 - _QCBOREncode_Finish 72 - _QCBOREncode_FinishGetSize 70 - - Total is about 1.1KB - - _QCBOREncode_CloseMapOrArray is larger because it has a lot - of nesting tracking to do and much of Nesting_ inlines - into it. It probably can't be reduced much. - - If the error returned by Nesting_Increment() can be ignored - because the limit is so high and the consequence of exceeding - is proved to be inconsequential, then a lot of if(me->uError) - instance can be removed, saving some code. - - */ - diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/UsefulBuf_Tests.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/UsefulBuf_Tests.c deleted file mode 100644 index c0568b4..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/UsefulBuf_Tests.c +++ /dev/null @@ -1,701 +0,0 @@ -/*============================================================================== - Copyright (c) 2016-2018, The Linux Foundation. - Copyright (c) 2018-2019, Laurence Lundblade. - All rights reserved. - SPDX-License-Identifier: BSD-3-Clause - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of The Linux Foundation nor the names of its - contributors, nor the name "Laurence Lundblade" may be used to - endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS -BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ==============================================================================*/ - -#include "UsefulBuf.h" - - -/* Basic exercise... - - Call all the main public functions. - - Binary compare the result to the expected. - - There is nothing adversarial in this test - */ -const char * UOBTest_NonAdversarial() -{ - const char *szReturn = NULL; - - UsefulBuf_MAKE_STACK_UB(outbuf,50); - - UsefulOutBuf UOB; - - UsefulOutBuf_Init(&UOB, outbuf); - - if(!UsefulOutBuf_AtStart(&UOB)) { - szReturn = "Not at start"; - goto Done; - } - - // Put 7 bytes at beginning of buf - UsefulOutBuf_AppendData(&UOB, "bluster", 7); - - if(UsefulOutBuf_AtStart(&UOB)) { - szReturn = "At start"; - goto Done; - } - - // add a space to end - UsefulOutBuf_AppendByte(&UOB, ' '); - - // Add 5 bytes to the end - UsefulBufC UBC = {"hunny", 5}; - UsefulOutBuf_AppendUsefulBuf(&UOB, UBC); - - // Insert 9 bytes at the beginning, slide the previous stuff right - UsefulOutBuf_InsertData(&UOB, "heffalump", 9, 0); - UsefulOutBuf_InsertByte(&UOB, ' ', 9); - - // Put 9 bytes in at position 10 -- just after "heffalump " - UsefulBufC UBC2 = {"unbounce ", 9}; - UsefulOutBuf_InsertUsefulBuf(&UOB, UBC2, 10); - - // Make it a null terminated string (because all the appends and inserts above not strcpy !) - UsefulOutBuf_AppendByte(&UOB, '\0'); - - - UsefulBufC U = UsefulOutBuf_OutUBuf(&UOB); - - const char *expected = "heffalump unbounce bluster hunny"; - - if(UsefulBuf_IsNULLC(U) || U.len-1 != strlen(expected) || strcmp(expected, U.ptr) || UsefulOutBuf_GetError(&UOB)) { - szReturn = "OutUBuf"; - } - - UsefulBuf_MAKE_STACK_UB(buf, 50); - UsefulBufC Out = UsefulOutBuf_CopyOut(&UOB, buf); - - if(UsefulBuf_IsNULLC(Out) || Out.len-1 != strlen(expected) || strcmp(expected, Out.ptr)) { - szReturn = "CopyOut"; - } - -Done: - return szReturn; -} - - -/* - Append test utility. - pUOB is the buffer to append too - num is the amount to append - expected is the expected return code, 0 or 1 - - returns 0 if test passed - - */ -static int AppendTest(UsefulOutBuf *pUOB, size_t num, int expected) -{ - //reset - UsefulOutBuf_Reset(pUOB); - - // check status first - if(UsefulOutBuf_GetError(pUOB)) - return 1; - - // append the bytes - UsefulOutBuf_AppendData(pUOB, (const uint8_t *)"bluster", num); - - // check error status after - if(UsefulOutBuf_GetError(pUOB) != expected) - return 1; - - return 0; -} - - -/* - Same as append, but takes a position param too - */ -static int InsertTest(UsefulOutBuf *pUOB, size_t num, size_t pos, int expected) -{ - // reset - UsefulOutBuf_Reset(pUOB); - - // check - if(UsefulOutBuf_GetError(pUOB)) - return 1; - - UsefulOutBuf_InsertData(pUOB, (const uint8_t *)"bluster", num, pos); - - if(UsefulOutBuf_GetError(pUOB) != expected) - return 1; - - return 0; -} - - -/* - Boundary conditions to test - - around 0 - - around the buffer size - - around MAX size_t - - - Test these for the buffer size and the cursor, the insert amount, the append amount and the insert position - - */ - -const char *UOBTest_BoundaryConditionsTest() -{ - UsefulBuf_MAKE_STACK_UB(outbuf,2); - - UsefulOutBuf UOB; - - UsefulOutBuf_Init(&UOB, outbuf); - - // append 0 byte to a 2 byte buffer --> success - if(AppendTest(&UOB, 0, 0)) - return "Append 0 bytes failed"; - - // append 1 byte to a 2 byte buffer --> success - if(AppendTest(&UOB, 1, 0)) - return "Append of 1 byte failed"; - - // append 2 byte to a 2 byte buffer --> success - if(AppendTest(&UOB, 2, 0)) - return "Append to fill buffer failed"; - - // append 3 bytes to a 2 byte buffer --> failure - if(AppendTest(&UOB, 3, 1)) - return "Overflow of buffer not caught"; - - // append max size_t to a 2 byte buffer --> failure - if(AppendTest(&UOB, SIZE_MAX, 1)) - return "Append of SIZE_MAX error not caught"; - - if(InsertTest(&UOB, 1, 0, 0)) - return "Insert 1 byte at start failed"; - - if(InsertTest(&UOB, 2, 0, 0)) - return "Insert 2 bytes at start failed"; - - if(InsertTest(&UOB, 3, 0, 1)) - return "Insert overflow not caught"; - - if(InsertTest(&UOB, 1, 1, 1)) - return "Bad insertion point not caught"; - - - UsefulBuf_MAKE_STACK_UB(outBuf2,10); - - UsefulOutBuf_Init(&UOB, outBuf2); - - UsefulOutBuf_Reset(&UOB); - // put data in the buffer - UsefulOutBuf_AppendString(&UOB, "abc123"); - - UsefulOutBuf_InsertString(&UOB, "xyz*&^", 0); - - if(!UsefulOutBuf_GetError(&UOB)) { - return "insert with data should have failed"; - } - - - UsefulOutBuf_Init(&UOB, (UsefulBuf){NULL, SIZE_MAX - 5}); - UsefulOutBuf_AppendData(&UOB, "123456789", SIZE_MAX -6); - if(UsefulOutBuf_GetError(&UOB)) { - return "insert in huge should have succeeded"; - } - - UsefulOutBuf_Init(&UOB, (UsefulBuf){NULL, SIZE_MAX - 5}); - UsefulOutBuf_AppendData(&UOB, "123456789", SIZE_MAX -5); - if(UsefulOutBuf_GetError(&UOB)) { - return "insert in huge should have succeeded"; - } - - UsefulOutBuf_Init(&UOB, (UsefulBuf){NULL, SIZE_MAX - 5}); - UsefulOutBuf_AppendData(&UOB, "123456789", SIZE_MAX - 4); - if(!UsefulOutBuf_GetError(&UOB)) { - return "lengths near max size"; - } - - return NULL; -} - - - - - -// Test function to get size and magic number check - -const char *TestBasicSanity() -{ - UsefulBuf_MAKE_STACK_UB(outbuf,10); - - UsefulOutBuf UOB; - - // First -- make sure that the room left function returns the right amount - UsefulOutBuf_Init(&UOB, outbuf); - - if(UsefulOutBuf_RoomLeft(&UOB) != 10) - return "room left failed"; - - if(!UsefulOutBuf_WillItFit(&UOB, 9)) { - return "it did not fit"; - } - - if(UsefulOutBuf_WillItFit(&UOB, 11)) { - return "it should have not fit"; - } - - - // Next -- make sure that the magic number checking is working right - UOB.magic = 8888; // make magic bogus - - UsefulOutBuf_AppendData(&UOB, (const uint8_t *)"bluster", 7); - - if(!UsefulOutBuf_GetError(&UOB)) - return "magic corruption check failed"; - - - - // Next make sure that the valid data length check is working right - UsefulOutBuf_Init(&UOB, outbuf); - - UOB.data_len = UOB.UB.len+1; // make size bogus - - UsefulOutBuf_AppendData(&UOB, (const uint8_t *)"bluster", 7); - if(!UsefulOutBuf_GetError(&UOB)) - return "valid data check failed"; - - return NULL; -} - - - -const char *UBMacroConversionsTest() -{ - char *szFoo = "foo"; - - UsefulBufC Foo = UsefulBuf_FromSZ(szFoo); - if(Foo.len != 3 || strncmp(Foo.ptr, szFoo, 3)) - return "SZToUsefulBufC failed"; - - UsefulBufC Too = UsefulBuf_FROM_SZ_LITERAL("Toooo"); - if(Too.len != 5 || strncmp(Too.ptr, "Toooo", 5)) - return "UsefulBuf_FROM_SZ_LITERAL failed"; - - uint8_t pB[] = {0x42, 0x6f, 0x6f}; - UsefulBufC Boo = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pB); - if(Boo.len != 3 || strncmp(Boo.ptr, "Boo", 3)) - return "UsefulBuf_FROM_BYTE_ARRAY_LITERAL failed"; - - char *sz = "not const"; // some data for the test - UsefulBuf B = (UsefulBuf){sz, sizeof(sz)}; - UsefulBufC BC = UsefulBuf_Const(B); - if(BC.len != sizeof(sz) || BC.ptr != sz) - return "UsefulBufConst failed"; - - return NULL; -} - - -const char *UBUtilTests() -{ - UsefulBuf UB = NULLUsefulBuf; - - if(!UsefulBuf_IsNULL(UB)){ - return "IsNull failed"; - } - - if(!UsefulBuf_IsEmpty(UB)){ - return "IsEmpty failed"; - } - - if(!UsefulBuf_IsNULLOrEmpty(UB)) { - return "IsNULLOrEmpty failed"; - } - - const UsefulBufC UBC = UsefulBuf_Const(UB); - - if(!UsefulBuf_IsNULLC(UBC)){ - return "IsNull const failed"; - } - - if(!UsefulBuf_IsEmptyC(UBC)){ - return "IsEmptyC failed"; - } - - if(!UsefulBuf_IsNULLOrEmptyC(UBC)){ - return "IsNULLOrEmptyC failed"; - } - - const UsefulBuf UB2 = UsefulBuf_Unconst(UBC); - if(!UsefulBuf_IsEmpty(UB2)) { - return "Back to UB is Empty failed"; - } - - UB.ptr = "x"; // just some valid pointer - - if(UsefulBuf_IsNULL(UB)){ - return "IsNull failed"; - } - - if(!UsefulBuf_IsEmptyC(UBC)){ - return "IsEmpty failed"; - } - - // test the Unconst. - if(UsefulBuf_Unconst(UBC).ptr != NULL) { - return "Unconst failed"; - } - - // Set 100 bytes of '+'; validated a few tests later - UsefulBuf_MAKE_STACK_UB(Temp, 100); - const UsefulBufC TempC = UsefulBuf_Set(Temp, '+'); - - // Try to copy into a buf that is too small and see failure - UsefulBuf_MAKE_STACK_UB(Temp2, 99); - if(!UsefulBuf_IsNULLC(UsefulBuf_Copy(Temp2, TempC))) { - return "Copy should have failed"; - } - - if(UsefulBuf_IsNULLC(UsefulBuf_CopyPtr(Temp2, "xx", 2))) { - return "CopyPtr failed"; - } - - UsefulBufC xxyy = UsefulBuf_CopyOffset(Temp2, 2, UsefulBuf_FROM_SZ_LITERAL("yy")); - if(UsefulBuf_IsNULLC(xxyy)) { - return "CopyOffset Failed"; - } - - if(UsefulBuf_Compare(UsefulBuf_Head(xxyy, 3), UsefulBuf_FROM_SZ_LITERAL("xxy"))) { - return "head failed"; - } - - if(UsefulBuf_Compare(UsefulBuf_Tail(xxyy, 1), UsefulBuf_FROM_SZ_LITERAL("xyy"))) { - return "tail failed"; - } - - if(!UsefulBuf_IsNULLC(UsefulBuf_Head(xxyy, 5))) { - return "head should have failed"; - } - - if(!UsefulBuf_IsNULLC(UsefulBuf_Tail(xxyy, 5))) { - return "tail should have failed"; - } - - if(!UsefulBuf_IsNULLC(UsefulBuf_Tail(NULLUsefulBufC, 0))) { - return "tail of NULLUsefulBufC is not NULLUsefulBufC"; - } - - const UsefulBufC TailResult = UsefulBuf_Tail((UsefulBufC){NULL, 100}, 99); - if(TailResult.ptr != NULL || TailResult.len != 1) { - return "tail of NULL and length incorrect"; - } - - if(!UsefulBuf_IsNULLC(UsefulBuf_CopyOffset(Temp2, 100, UsefulBuf_FROM_SZ_LITERAL("yy")))) { - return "Copy Offset should have failed"; - } - - // Try to copy into a NULL/empty buf and see failure - const UsefulBuf UBNull = NULLUsefulBuf; - if(!UsefulBuf_IsNULLC(UsefulBuf_Copy(UBNull, TempC))) { - return "Copy to NULL should have failed"; - } - - - // Try to set a NULL/empty buf; nothing should happen - UsefulBuf_Set(UBNull, '+'); // This will crash on failure - - // Copy successfully to a buffer - UsefulBuf_MAKE_STACK_UB(Temp3, 101); - if(UsefulBuf_IsNULLC(UsefulBuf_Copy(Temp3, TempC))) { - return "Copy should not have failed"; - } - - static const uint8_t pExpected[] = { - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - }; - UsefulBufC Expected = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExpected); - // This validates comparison for equality and the UsefulBuf_Set - if(UsefulBuf_Compare(Expected, TempC)) { - return "Set / Copy / Compare failed"; - } - - // Compare two empties and expect success - if(UsefulBuf_Compare(NULLUsefulBufC, NULLUsefulBufC)){ - return "Compare Empties failed"; - } - - // Compare with empty and expect the first to be larger - if(UsefulBuf_Compare(Expected, NULLUsefulBufC) <= 0){ - return "Compare with empty failed"; - } - - - static const uint8_t pExpectedBigger[] = { - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', ',', - }; - const UsefulBufC ExpectedBigger = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExpectedBigger); - - // Expect -1 when the first arg is smaller - if(UsefulBuf_Compare(Expected, ExpectedBigger) >= 0){ - return "Compare with bigger"; - } - - - static const uint8_t pExpectedSmaller[] = { - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '*', - }; - const UsefulBufC ExpectedSmaller = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExpectedSmaller); - // Expect +1 when the first arg is larger - if(UsefulBuf_Compare(Expected, ExpectedSmaller) <= 0){ - return "Compare with smaller"; - } - - - static const uint8_t pExpectedLonger[] = { - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+' - }; - const UsefulBufC ExpectedLonger = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExpectedLonger); - - // Expect -1 when the first arg is smaller - if(UsefulBuf_Compare(Expected, ExpectedLonger) >= 0){ - return "Compare with longer"; - } - - - static const uint8_t pExpectedShorter[] = { - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', - '+', '+', '+', '+', '+', '+', '+', '+', '+', - }; - const UsefulBufC ExpectedShorter = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExpectedShorter); - // Expect +1 with the first arg is larger - if(UsefulBuf_Compare(Expected, ExpectedShorter) <= 0){ - return "Compare with shorter"; - } - - - if(UsefulBuf_IsNULLC(UsefulBuf_Copy(Temp, NULLUsefulBufC))) { - return "Copy null/empty failed"; - } - - // Look for +++++... in +++++... and find it at the beginning - if(0 != UsefulBuf_FindBytes(ExpectedLonger, ExpectedShorter)){ - return "Failed to find"; - } - - // look for ++* in ....++* and find it at the end - static const uint8_t pToFind[] = {'+', '+', '*'}; - const UsefulBufC ToBeFound = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pToFind); - - if(97 != UsefulBuf_FindBytes(ExpectedSmaller, ToBeFound)){ - return "Failed to find 2"; - } - - // look for ++* in ....++, and find it near the end - if(SIZE_MAX != UsefulBuf_FindBytes(ExpectedBigger, ToBeFound)){ - return "Failed to not find"; - } - - // Look for the whole buffer in itself and succeed. - if(0 != UsefulBuf_FindBytes(ExpectedLonger, ExpectedLonger)){ - return "Failed to find 3"; - } - - return NULL; -} - - -const char * UIBTest_IntegerFormat() -{ - UsefulOutBuf_MakeOnStack(UOB,100); - - const uint32_t u32 = 0x0A0B0C0D; // from https://en.wikipedia.org/wiki/Endianness - const uint64_t u64 = 1984738472938472; - const uint16_t u16 = 40000; - const uint8_t u8 = 9; - const float f = (float)314.15; - const double d = 2.1e10; - - - UsefulOutBuf_AppendUint32(&UOB, u32); // Also tests UsefulOutBuf_InsertUint64 and UsefulOutBuf_GetEndPosition - UsefulOutBuf_AppendUint64(&UOB, u64); // Also tests UsefulOutBuf_InsertUint32 - UsefulOutBuf_AppendUint16(&UOB, u16); // Also tests UsefulOutBuf_InsertUint16 - UsefulOutBuf_AppendByte(&UOB, u8); - UsefulOutBuf_AppendFloat(&UOB, f); // Also tests UsefulOutBuf_InsertFloat - UsefulOutBuf_AppendDouble(&UOB, d); // Also tests UsefulOutBuf_InsertDouble - - const UsefulBufC O = UsefulOutBuf_OutUBuf(&UOB); - if(UsefulBuf_IsNULLC(O)) - return "Couldn't output integers"; - - // from https://en.wikipedia.org/wiki/Endianness - const uint8_t pExpectedNetworkOrder[4] = {0x0A, 0x0B, 0x0C, 0x0D}; - if(memcmp(O.ptr, pExpectedNetworkOrder, 4)) { - return "not in network order"; - } - - UsefulInputBuf UIB; - - UsefulInputBuf_Init(&UIB, O); - - if(UsefulInputBuf_Tell(&UIB) != 0) { - return "UsefulInputBuf_Tell failed"; - } - - if(UsefulInputBuf_GetUint32(&UIB) != u32) { - return "u32 out then in failed"; - } - if(UsefulInputBuf_GetUint64(&UIB) != u64) { - return "u64 out then in failed"; - } - if(UsefulInputBuf_GetUint16(&UIB) != u16) { - return "u16 out then in failed"; - } - if(UsefulInputBuf_GetByte(&UIB) != u8) { - return "u8 out then in failed"; - } - if(UsefulInputBuf_GetFloat(&UIB) != f) { - return "float out then in failed"; - } - if(UsefulInputBuf_GetDouble(&UIB) != d) { - return "double out then in failed"; - } - - // Reset and go again for a few more tests - UsefulInputBuf_Init(&UIB, O); - - const UsefulBufC Four = UsefulInputBuf_GetUsefulBuf(&UIB, 4); - if(UsefulBuf_IsNULLC(Four)) { - return "Four is NULL"; - } - if(UsefulBuf_Compare(Four, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExpectedNetworkOrder))) { - return "Four compare failed"; - } - - if(UsefulInputBuf_BytesUnconsumed(&UIB) != 23){ - return "Wrong number of unconsumed bytes"; - } - - if(!UsefulInputBuf_BytesAvailable(&UIB, 23)){ - return "Wrong number of bytes available I"; - } - - if(UsefulInputBuf_BytesAvailable(&UIB, 24)){ - return "Wrong number of bytes available II"; - } - - UsefulInputBuf_Seek(&UIB, 0); - - if(UsefulInputBuf_GetError(&UIB)) { - return "unexpected error after seek"; - } - - const uint8_t *pGetBytes = (const uint8_t *)UsefulInputBuf_GetBytes(&UIB, 4); - if(pGetBytes == NULL) { - return "GetBytes returns NULL"; - } - - if(memcmp(pGetBytes, pExpectedNetworkOrder, 4)) { - return "Got wrong bytes"; - } - - UsefulInputBuf_Seek(&UIB, 28); - - if(!UsefulInputBuf_GetError(&UIB)) { - return "expected error after seek"; - } - - return NULL; -} - - -const char *UBUTest_CopyUtil() -{ - if(UsefulBufUtil_CopyFloatToUint32(65536.0F) != 0x47800000) { - return "CopyFloatToUint32 failed"; - } - - if(UsefulBufUtil_CopyDoubleToUint64(4e-40L) != 0X37C16C2800000000ULL) { - return "CopyDoubleToUint64 failed"; - } - - if(UsefulBufUtil_CopyUint64ToDouble(0X37C16C2800000000ULL) != 4e-40L) { - return "CopyUint64ToDouble failed"; - } - - if(UsefulBufUtil_CopyUint32ToFloat(0x47800000) != 65536.0F) { - return "CopyUint32ToFloat failed"; - } - - return NULL; -} - - - diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/UsefulBuf_Tests.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/UsefulBuf_Tests.h deleted file mode 100644 index d85b951..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/UsefulBuf_Tests.h +++ /dev/null @@ -1,51 +0,0 @@ -/*============================================================================== - Copyright (c) 2016-2018, The Linux Foundation. - Copyright (c) 2018, Laurence Lundblade. - All rights reserved. - SPDX-License-Identifier: BSD-3-Clause - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of The Linux Foundation nor the names of its - contributors, nor the name "Laurence Lundblade" may be used to - endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS -BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ==============================================================================*/ - -#ifndef UsefulBuf_UsefulBuf_Tests_h -#define UsefulBuf_UsefulBuf_Tests_h - -const char * UOBTest_NonAdversarial(void); - -const char * TestBasicSanity(void); - -const char * UOBTest_BoundaryConditionsTest(void); - -const char * UBMacroConversionsTest(void); - -const char * UBUtilTests(void); - -const char * UIBTest_IntegerFormat(void); - -const char * UBUTest_CopyUtil(void); - -#endif diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/float_tests.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/float_tests.c deleted file mode 100644 index dd211c3..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/float_tests.c +++ /dev/null @@ -1,474 +0,0 @@ -/*============================================================================== - float_tests.c -- tests for float and conversion to/from half-precision - - Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. - - SPDX-License-Identifier: BSD-3-Clause - - See BSD-3-Clause license in README.md - - Created on 9/19/18 - ==============================================================================*/ - -#include "float_tests.h" -#include "qcbor.h" -#include "half_to_double_from_rfc7049.h" -#include // For INFINITY and NAN and isnan() - - - -static const uint8_t spExpectedHalf[] = { - 0xB1, - 0x64, - 0x7A, 0x65, 0x72, 0x6F, - 0xF9, 0x00, 0x00, // 0.000 - 0x6A, - 0x69, 0x6E, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79, - 0xF9, 0x7C, 0x00, // Infinity - 0x73, - 0x6E, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x69, 0x6E, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79, - 0xF9, 0xFC, 0x00, // -Inifinity - 0x63, - 0x4E, 0x61, 0x4E, - 0xF9, 0x7E, 0x00, // NaN - 0x63, - 0x6F, 0x6E, 0x65, - 0xF9, 0x3C, 0x00, // 1.0 - 0x69, - 0x6F, 0x6E, 0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64, - 0xF9, 0x35, 0x55, // 0.333251953125 - 0x76, - 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x68, 0x61, 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6F, 0x6E, - 0xF9, 0x7B, 0xFF, // 65504.0 - 0x78, 0x18, 0x74, 0x6F, 0x6F, 0x2D, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x20, 0x68, 0x61, 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6F, 0x6E, - 0xF9, 0x7C, 0x00, // Infinity - 0x72, - 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x73, 0x75, 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, - 0xF9, 0x00, 0x01, // 0.000000059604 - 0x6F, - 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, - 0xF9, 0x03, 0xFF, // 0.0000609755516 - 0x71, - 0x62, 0x69, 0x67, 0x67, 0x65, 0x73, 0x74, 0x20, 0x73, 0x75, 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, - 0xF9, 0x04, 0x00, // 0.000061988 - 0x70, - 0x73, 0x75, 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x20, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, - 0xF9, 0x00, 0x00, - 0x03, - 0xF9, 0xC0, 0x00, // -2 - 0x04, - 0xF9, 0x7E, 0x00, // qNaN - 0x05, - 0xF9, 0x7C, 0x01, // sNaN - 0x06, - 0xF9, 0x7E, 0x0F, // qNaN with payload 0x0f - 0x07, - 0xF9, 0x7C, 0x0F, // sNaN with payload 0x0f - -}; - - -int HalfPrecisionDecodeBasicTests() -{ - UsefulBufC HalfPrecision = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedHalf); - - QCBORDecodeContext DC; - QCBORDecode_Init(&DC, HalfPrecision, 0); - - QCBORItem Item; - - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_MAP) { - return -1; - } - - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.0F) { - return -2; - } - - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != INFINITY) { - return -3; - } - - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != -INFINITY) { - return -4; - } - - QCBORDecode_GetNext(&DC, &Item); // TODO, is this really converting right? It is carrying payload, but this confuses things. - if(Item.uDataType != QCBOR_TYPE_DOUBLE || !isnan(Item.val.dfnum)) { - return -5; - } - - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 1.0F) { - return -6; - } - - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.333251953125F) { - return -7; - } - - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 65504.0F) { - return -8; - } - - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != INFINITY) { - return -9; - } - - QCBORDecode_GetNext(&DC, &Item); // TODO: check this - if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.0000000596046448F) { - return -10; - } - - QCBORDecode_GetNext(&DC, &Item); // TODO: check this - if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.0000609755516F) { - return -11; - } - - QCBORDecode_GetNext(&DC, &Item); // TODO check this - if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.0000610351563F) { - return -12; - } - - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0) { - return -13; - } - - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != -2.0F) { - return -14; - } - - // TODO: double check these four tests - QCBORDecode_GetNext(&DC, &Item); // qNaN - if(Item.uDataType != QCBOR_TYPE_DOUBLE || UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum) != 0x7ff8000000000000ULL) { - return -15; - } - QCBORDecode_GetNext(&DC, &Item); // sNaN - if(Item.uDataType != QCBOR_TYPE_DOUBLE || UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum) != 0x7ff0000000000001ULL) { - return -16; - } - QCBORDecode_GetNext(&DC, &Item); // qNaN with payload 0x0f - if(Item.uDataType != QCBOR_TYPE_DOUBLE || UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum) != 0x7ff800000000000fULL) { - return -17; - } - QCBORDecode_GetNext(&DC, &Item); // sNaN with payload 0x0f - if(Item.uDataType != QCBOR_TYPE_DOUBLE || UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum) != 0x7ff000000000000fULL) { - return -18; - } - - if(QCBORDecode_Finish(&DC)) { - return -19; - } - - return 0; -} - - - - -int HalfPrecisionAgainstRFCCodeTest() -{ - for(uint32_t uHalfP = 0; uHalfP < 0xffff; uHalfP += 60) { - unsigned char x[2]; - x[1] = uHalfP & 0xff; - x[0] = uHalfP >> 8; - double d = decode_half(x); - - // Contruct the CBOR for the half-precision float by hand - UsefulBuf_MAKE_STACK_UB(__xx, 3); - UsefulOutBuf UOB; - UsefulOutBuf_Init(&UOB, __xx); - - const uint8_t uHalfPrecInitialByte = HALF_PREC_FLOAT + (CBOR_MAJOR_TYPE_SIMPLE << 5); // 0xf9 - UsefulOutBuf_AppendByte(&UOB, uHalfPrecInitialByte); // The initial byte for a half-precision float - UsefulOutBuf_AppendUint16(&UOB, (uint16_t)uHalfP); - - // Now parse the hand-constructed CBOR. This will invoke the conversion to a float - QCBORDecodeContext DC; - QCBORDecode_Init(&DC, UsefulOutBuf_OutUBuf(&UOB), 0); - - QCBORItem Item; - - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_DOUBLE) { - return -1; - } - - //printf("%04x QCBOR:%15.15f RFC: %15.15f (%8x)\n", uHalfP,Item.val.fnum, d , UsefulBufUtil_CopyFloatToUint32(d)); - - if(isnan(d)) { - // The RFC code uses the native instructions which may or may not - // handle sNaN, qNaN and NaN payloads correctly. This test just - // makes sure it is a NaN and doesn't worry about the type of NaN - if(!isnan(Item.val.dfnum)) { - return -3; - } - } else { - if(Item.val.dfnum != d) { - return -2; - } - } - } - return 0; -} - - -/* - {"zero": 0.0, - "negative zero": -0.0, - "infinitity": Infinity, - "negative infinitity": -Infinity, - "NaN": NaN, - "one": 1.0, - "one third": 0.333251953125, - "largest half-precision": 65504.0, - "largest half-precision point one": 65504.1, - "too-large half-precision": 65536.0, - "smallest subnormal": 5.96046448e-8, - "smallest normal": 0.00006103515261202119, - "biggest subnormal": 0.00006103515625, - "subnormal single": 4.00000646641519e-40, - 3: -2.0, - "large single exp": 2.5521177519070385e+38, - "too-large single exp": 5.104235503814077e+38, - "biggest single with prec": 16777216.0, - "first single with prec loss": 16777217.0, - 1: "fin"} - */ -static const uint8_t spExpectedSmallest[] = { - 0xB4, 0x64, 0x7A, 0x65, 0x72, 0x6F, 0xF9, 0x00, 0x00, 0x6D, - 0x6E, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x7A, - 0x65, 0x72, 0x6F, 0xF9, 0x80, 0x00, 0x6A, 0x69, 0x6E, 0x66, - 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79, 0xF9, 0x7C, 0x00, - 0x73, 0x6E, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, - 0x69, 0x6E, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79, - 0xF9, 0xFC, 0x00, 0x63, 0x4E, 0x61, 0x4E, 0xF9, 0x7E, 0x00, - 0x63, 0x6F, 0x6E, 0x65, 0xF9, 0x3C, 0x00, 0x69, 0x6F, 0x6E, - 0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64, 0xF9, 0x35, 0x55, - 0x76, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x68, - 0x61, 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, - 0x69, 0x6F, 0x6E, 0xF9, 0x7B, 0xFF, 0x78, 0x20, 0x6C, 0x61, - 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x68, 0x61, 0x6C, 0x66, - 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6F, 0x6E, - 0x20, 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x20, 0x6F, 0x6E, 0x65, - 0xFB, 0x40, 0xEF, 0xFC, 0x03, 0x33, 0x33, 0x33, 0x33, 0x78, - 0x18, 0x74, 0x6F, 0x6F, 0x2D, 0x6C, 0x61, 0x72, 0x67, 0x65, - 0x20, 0x68, 0x61, 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, - 0x69, 0x73, 0x69, 0x6F, 0x6E, 0xFA, 0x47, 0x80, 0x00, 0x00, - 0x72, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, - 0x73, 0x75, 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0xFB, - 0x3E, 0x70, 0x00, 0x00, 0x00, 0x1C, 0x5F, 0x68, 0x6F, 0x73, - 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x6E, 0x6F, - 0x72, 0x6D, 0x61, 0x6C, 0xFA, 0x38, 0x7F, 0xFF, 0xFF, 0x71, - 0x62, 0x69, 0x67, 0x67, 0x65, 0x73, 0x74, 0x20, 0x73, 0x75, - 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0xF9, 0x04, 0x00, - 0x70, 0x73, 0x75, 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, - 0x20, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0xFB, 0x37, 0xC1, - 0x6C, 0x28, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF9, 0xC0, 0x00, - 0x70, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x20, 0x73, 0x69, 0x6E, - 0x67, 0x6C, 0x65, 0x20, 0x65, 0x78, 0x70, 0xFA, 0x7F, 0x40, - 0x00, 0x00, 0x74, 0x74, 0x6F, 0x6F, 0x2D, 0x6C, 0x61, 0x72, - 0x67, 0x65, 0x20, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, - 0x65, 0x78, 0x70, 0xFB, 0x47, 0xF8, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x78, 0x18, 0x62, 0x69, 0x67, 0x67, 0x65, 0x73, - 0x74, 0x20, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x77, - 0x69, 0x74, 0x68, 0x20, 0x70, 0x72, 0x65, 0x63, 0xFA, 0x4B, - 0x80, 0x00, 0x00, 0x78, 0x1B, 0x66, 0x69, 0x72, 0x73, 0x74, - 0x20, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x77, 0x69, - 0x74, 0x68, 0x20, 0x70, 0x72, 0x65, 0x63, 0x20, 0x6C, 0x6F, - 0x73, 0x73, 0xFB, 0x41, 0x70, 0x00, 0x00, 0x10, 0x00, 0x00, - 0x00, 0x01, 0x63, 0x66, 0x69, 0x6E -}; - - -int DoubleAsSmallestTest() -{ - UsefulBuf_MAKE_STACK_UB(EncodedHalfsMem, 420); - -#define QCBOREncode_AddDoubleAsSmallestToMap QCBOREncode_AddDoubleToMap -#define QCBOREncode_AddDoubleAsSmallestToMapN QCBOREncode_AddDoubleToMapN - - - QCBOREncodeContext EC; - QCBOREncode_Init(&EC, EncodedHalfsMem); - // These are mostly from https://en.wikipedia.org/wiki/Half-precision_floating-point_format - QCBOREncode_OpenMap(&EC); - // 64 # text(4) - // 7A65726F # "zero" - // F9 0000 # primitive(0) - QCBOREncode_AddDoubleAsSmallestToMap(&EC, "zero", 0.00); - - // 64 # text(4) - // 7A65726F # "negative zero" - // F9 8000 # primitive(0) - QCBOREncode_AddDoubleAsSmallestToMap(&EC, "negative zero", -0.00); - - // 6A # text(10) - // 696E66696E6974697479 # "infinitity" - // F9 7C00 # primitive(31744) - QCBOREncode_AddDoubleAsSmallestToMap(&EC, "infinitity", INFINITY); - - // 73 # text(19) - // 6E6567617469766520696E66696E6974697479 # "negative infinitity" - // F9 FC00 # primitive(64512) - QCBOREncode_AddDoubleAsSmallestToMap(&EC, "negative infinitity", -INFINITY); - - // 63 # text(3) - // 4E614E # "NaN" - // F9 7E00 # primitive(32256) - QCBOREncode_AddDoubleAsSmallestToMap(&EC, "NaN", NAN); - - // TODO: test a few NaN variants - - // 63 # text(3) - // 6F6E65 # "one" - // F9 3C00 # primitive(15360) - QCBOREncode_AddDoubleAsSmallestToMap(&EC, "one", 1.0); - - // 69 # text(9) - // 6F6E65207468697264 # "one third" - // F9 3555 # primitive(13653) - QCBOREncode_AddDoubleAsSmallestToMap(&EC, "one third", 0.333251953125); - - // 76 # text(22) - // 6C6172676573742068616C662D707265636973696F6E # "largest half-precision" - // F9 7BFF # primitive(31743) - QCBOREncode_AddDoubleAsSmallestToMap(&EC, "largest half-precision",65504.0); - - // 76 # text(22) - // 6C6172676573742068616C662D707265636973696F6E # "largest half-precision" - // F9 7BFF # primitive(31743) - QCBOREncode_AddDoubleAsSmallestToMap(&EC, "largest half-precision point one",65504.1); - - // Float 65536.0F is 0x47800000 in hex. It has an exponent of 16, which is larger than 15, the largest half-precision exponent - // 78 18 # text(24) - // 746F6F2D6C617267652068616C662D707265636973696F6E # "too-large half-precision" - // FA 47800000 # primitive(31743) - QCBOREncode_AddDoubleAsSmallestToMap(&EC, "too-large half-precision", 65536.0); - - // The smallest possible half-precision subnormal, but digitis are lost converting - // to half, so this turns into a double - // 72 # text(18) - // 736D616C6C657374207375626E6F726D616C # "smallest subnormal" - // FB 3E700000001C5F68 # primitive(4499096027744984936) - QCBOREncode_AddDoubleAsSmallestToMap(&EC, "smallest subnormal", 0.0000000596046448); - - // The smallest possible half-precision snormal, but digitis are lost converting - // to half, so this turns into a single TODO: confirm this is right - // 6F # text(15) - // 736D616C6C657374206E6F726D616C # "smallest normal" - // FA 387FFFFF # primitive(947912703) - // in hex single is 0x387fffff, exponent -15, significand 7fffff - QCBOREncode_AddDoubleAsSmallestToMap(&EC, "smallest normal", 0.0000610351526F); - - // 71 # text(17) - // 62696767657374207375626E6F726D616C # "biggest subnormal" - // F9 0400 # primitive(1024) - // in hex single is 0x38800000, exponent -14, significand 0 - QCBOREncode_AddDoubleAsSmallestToMap(&EC, "biggest subnormal", 0.0000610351563F); - - // 70 # text(16) - // 7375626E6F726D616C2073696E676C65 # "subnormal single" - // FB 37C16C2800000000 # primitive(4017611261645684736) - QCBOREncode_AddDoubleAsSmallestToMap(&EC, "subnormal single", 4e-40L); - - // 03 # unsigned(3) - // F9 C000 # primitive(49152) - QCBOREncode_AddDoubleAsSmallestToMapN(&EC, 3, -2.0); - - // 70 # text(16) - // 6C617267652073696E676C6520657870 # "large single exp" - // FA 7F400000 # primitive(2134900736) - // (0x01LL << (DOUBLE_NUM_SIGNIFICAND_BITS-1)) | ((127LL + DOUBLE_EXPONENT_BIAS) << DOUBLE_EXPONENT_SHIFT); - QCBOREncode_AddDoubleAsSmallestToMap(&EC, "large single exp", 2.5521177519070385E+38); // Exponent fits single - - // 74 # text(20) - // 746F6F2D6C617267652073696E676C6520657870 # "too-large single exp" - // FB 47F8000000000000 # primitive(5185894970917126144) - // (0x01LL << (DOUBLE_NUM_SIGNIFICAND_BITS-1)) | ((128LL + DOUBLE_EXPONENT_BIAS) << DOUBLE_EXPONENT_SHIFT); - QCBOREncode_AddDoubleAsSmallestToMap(&EC, "too-large single exp", 5.104235503814077E+38); // Exponent too large for single - - // 66 # text(6) - // 646664666465 # "dfdfde" - // FA 4B800000 # primitive(1266679808) - QCBOREncode_AddDoubleAsSmallestToMap(&EC, "biggest single with prec",16777216); // Single with no precision loss - - // 78 18 # text(24) - // 626967676573742073696E676C6520776974682070726563 # "biggest single with prec" - // FA 4B800000 # primitive(1266679808) - QCBOREncode_AddDoubleAsSmallestToMap(&EC, "first single with prec loss",16777217); // Double becuase of precision loss - - // Just a convenient marker when cutting and pasting encoded CBOR - QCBOREncode_AddSZStringToMapN(&EC, 1, "fin"); - - QCBOREncode_CloseMap(&EC); - - UsefulBufC EncodedHalfs; - int nReturn = QCBOREncode_Finish(&EC, &EncodedHalfs); - if(nReturn) { - return -1; - } - - if(UsefulBuf_Compare(EncodedHalfs, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedSmallest))) { - return -3; - } - - return 0; -} - - - -#ifdef NAN_EXPERIMENT -/* - Code for checking what the double to float cast does with - NaNs. Not run as part of tests. Keep it around to - be able to check various platforms and CPUs. - */ - -#define DOUBLE_NUM_SIGNIFICAND_BITS (52) -#define DOUBLE_NUM_EXPONENT_BITS (11) -#define DOUBLE_NUM_SIGN_BITS (1) - -#define DOUBLE_SIGNIFICAND_SHIFT (0) -#define DOUBLE_EXPONENT_SHIFT (DOUBLE_NUM_SIGNIFICAND_BITS) -#define DOUBLE_SIGN_SHIFT (DOUBLE_NUM_SIGNIFICAND_BITS + DOUBLE_NUM_EXPONENT_BITS) - -#define DOUBLE_SIGNIFICAND_MASK (0xfffffffffffffULL) // The lower 52 bits -#define DOUBLE_EXPONENT_MASK (0x7ffULL << DOUBLE_EXPONENT_SHIFT) // 11 bits of exponent -#define DOUBLE_SIGN_MASK (0x01ULL << DOUBLE_SIGN_SHIFT) // 1 bit of sign -#define DOUBLE_QUIET_NAN_BIT (0x01ULL << (DOUBLE_NUM_SIGNIFICAND_BITS-1)) - - -static int NaNExperiments() { - double dqNaN = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | DOUBLE_QUIET_NAN_BIT); - double dsNaN = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | 0x01); - double dqNaNPayload = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | DOUBLE_QUIET_NAN_BIT | 0xf00f); - - float f1 = (float)dqNaN; - float f2 = (float)dsNaN; - float f3 = (float)dqNaNPayload; - - - uint32_t uqNaN = UsefulBufUtil_CopyFloatToUint32((float)dqNaN); - uint32_t usNaN = UsefulBufUtil_CopyFloatToUint32((float)dsNaN); - uint32_t uqNaNPayload = UsefulBufUtil_CopyFloatToUint32((float)dqNaNPayload); - - // Result of this on x86 is that every NaN is a qNaN. The intel - // CVTSD2SS instruction ignores the NaN payload and even converts - // a sNaN to a qNaN. - - return 0; -} -#endif - - - diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/float_tests.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/float_tests.h deleted file mode 100644 index b7174c8..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/float_tests.h +++ /dev/null @@ -1,23 +0,0 @@ -/*============================================================================== - float_tests.h -- tests for float and conversion to/from half-precision - - Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. - - SPDX-License-Identifier: BSD-3-Clause - - See BSD-3-Clause license in README.md - - Created on 9/19/18 - ==============================================================================*/ - -#ifndef float_tests_h -#define float_tests_h - -int HalfPrecisionDecodeBasicTests(void); - -int DoubleAsSmallestTest(void); - -int HalfPrecisionAgainstRFCCodeTest(void); - - -#endif /* float_tests_h */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/half_to_double_from_rfc7049.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/half_to_double_from_rfc7049.c deleted file mode 100644 index 4d8fb67..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/half_to_double_from_rfc7049.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - SPDX-License-Identifier: BSD-2-Clause - - Copyright (c) 2013 IETF Trust and the persons identified as the - document authors. All rights reserved. - - This document is subject to BCP 78 and the IETF Trust's Legal - Provisions Relating to IETF Documents - (http://trustee.ietf.org/license-info) in effect on the date of - publication of this document. Please review these documents - carefully, as they describe your rights and restrictions with respect - to this document. Code Components extracted from this document must - include Simplified BSD License text as described in Section 4.e of - the Trust Legal Provisions and are provided without warranty as - described in the Simplified BSD License. - - */ - -/* - This code is from RFC 7049. It is not used in the main implementation - because: - a) it adds a dependency on and ldexp(). - b) the license may be an issue - - QCBOR does support half-precision, but rather than using - floating point math like this, it does it with bit shifting - and masking. - - This code is here to test that code. - - */ - -#include "half_to_double_from_rfc7049.h" - -#include - -double decode_half(unsigned char *halfp) { - int half = (halfp[0] << 8) + halfp[1]; - int exp = (half >> 10) & 0x1f; - int mant = half & 0x3ff; - double val; - if (exp == 0) val = ldexp(mant, -24); - else if (exp != 31) val = ldexp(mant + 1024, exp - 25); - else val = mant == 0 ? INFINITY : NAN; - return half & 0x8000 ? -val : val; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/half_to_double_from_rfc7049.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/half_to_double_from_rfc7049.h deleted file mode 100644 index 9f69e35..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/half_to_double_from_rfc7049.h +++ /dev/null @@ -1,18 +0,0 @@ -/*============================================================================== - half_to_double_from_rfc7049.h -- interface to IETF float conversion code. - - Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. - - SPDX-License-Identifier: BSD-3-Clause - - See BSD-3-Clause license in README.md - - Created on 9/23/18 - ==============================================================================*/ - -#ifndef half_to_double_from_rfc7049_h -#define half_to_double_from_rfc7049_h - -double decode_half(unsigned char *halfp); - -#endif /* half_to_double_from_rfc7049_h */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/qcbor_decode_tests.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/qcbor_decode_tests.c deleted file mode 100644 index 9ffc3a0..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/qcbor_decode_tests.c +++ /dev/null @@ -1,2837 +0,0 @@ -/*============================================================================== - Copyright (c) 2016-2018, The Linux Foundation. - Copyright (c) 2018-2019, Laurence Lundblade. - All rights reserved. - SPDX-License-Identifier: BSD-3-Clause - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of The Linux Foundation nor the names of its - contributors, nor the name "Laurence Lundblade" may be used to - endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS -BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ==============================================================================*/ - -#include "qcbor_decode_tests.h" -#include "qcbor.h" -#include -#include // for fabs() - - -#ifdef PRINT_FUNCTIONS_FOR_DEBUGGING -#include - -static void PrintUsefulBufC(const char *szLabel, UsefulBufC Buf) -{ - if(szLabel) { - printf("%s ", szLabel); - } - - size_t i; - for(i = 0; i < Buf.len; i++) { - uint8_t Z = ((uint8_t *)Buf.ptr)[i]; - printf("%02x ", Z); - } - printf("\n"); - - fflush(stdout); -} - -/*static void printencoded(const char *szLabel, const uint8_t *pEncoded, size_t nLen) -{ - PrintUsefulBufC(szLabel, (UsefulBufC){pEncoded, nLen}); -}*/ -#endif - - -static const uint8_t spExpectedEncodedInts[] = { - 0x98, 0x2f, 0x3b, 0x7f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x3b, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x3a, 0xff, 0xff, 0xff, - 0xff, 0x3a, 0xff, 0xff, 0xff, 0xfe, 0x3a, 0xff, - 0xff, 0xff, 0xfd, 0x3a, 0x7f, 0xff, 0xff, 0xff, - 0x3a, 0x7f, 0xff, 0xff, 0xfe, 0x3a, 0x00, 0x01, - 0x00, 0x01, 0x3a, 0x00, 0x01, 0x00, 0x00, 0x39, - 0xff, 0xff, 0x39, 0xff, 0xfe, 0x39, 0xff, 0xfd, - 0x39, 0x01, 0x00, 0x38, 0xff, 0x38, 0xfe, 0x38, - 0xfd, 0x38, 0x18, 0x37, 0x36, 0x20, 0x00, 0x00, - 0x01, 0x16, 0x17, 0x18, 0x18, 0x18, 0x19, 0x18, - 0x1a, 0x18, 0xfe, 0x18, 0xff, 0x19, 0x01, 0x00, - 0x19, 0x01, 0x01, 0x19, 0xff, 0xfe, 0x19, 0xff, - 0xff, 0x1a, 0x00, 0x01, 0x00, 0x00, 0x1a, 0x00, - 0x01, 0x00, 0x01, 0x1a, 0x00, 0x01, 0x00, 0x02, - 0x1a, 0x7f, 0xff, 0xff, 0xff, 0x1a, 0x7f, 0xff, - 0xff, 0xff, 0x1a, 0x80, 0x00, 0x00, 0x00, 0x1a, - 0x80, 0x00, 0x00, 0x01, 0x1a, 0xff, 0xff, 0xff, - 0xfe, 0x1a, 0xff, 0xff, 0xff, 0xff, 0x1b, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1b, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, - 0x1b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff}; - - -// return CBOR error or -1 if type of value doesn't match - -static int IntegerValuesParseTestInternal(QCBORDecodeContext *pDCtx) -{ - QCBORItem Item; - int nCBORError; - - if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_ARRAY) - return -1; - - if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || // Todo; fix this for 32-bit machines - Item.val.int64 != -9223372036854775807LL - 1) - return -1; - - if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != -4294967297) - return -1; - - if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != -4294967296) - return -1; - - if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != -4294967295) - return -1; - - if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != -4294967294) - return -1; - - - if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != -2147483648) - return -1; - - if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != -2147483647) - return -1; - - if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != -65538) - return -1; - - if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != -65537) - return -1; - - if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != -65536) - return -1; - - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != -65535) - return -1; - - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != -65534) - return -1; - - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != -257) - return -1; - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != -256) - return -1; - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != -255) - return -1; - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != -254) - return -1; - - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != -25) - return -1; - - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != -24) - return -1; - - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != -23) - return -1; - - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != -1) - return -1; - - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 0) - return -1; - - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 0) - return -1; - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 1) - return -1; - - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 22) - return -1; - - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 23) - return -1; - - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 24) - return -1; - - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 25) - return -1; - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 26) - return -1; - - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 254) - return -1; - - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 255) - return -1; - - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 256) - return -1; - - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 257) - return -1; - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 65534) - return -1; - - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 65535) - return -1; - - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 65536) - return -1; - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 65537) - return -1; - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 65538) - return -1; - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 2147483647) - return -1; - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 2147483647) - return -1; - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 2147483648) - return -1; - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 2147483649) - return -1; - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 4294967294) - return -1; - - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 4294967295) - return -1; - - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 4294967296) - return -1; - - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 4294967297) - return -1; - - - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 9223372036854775807LL) - return -1; - - - if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_UINT64 || - Item.val.uint64 != 18446744073709551615ULL) - return -1; - - - if(QCBORDecode_Finish(pDCtx) != QCBOR_SUCCESS) { - return -1; - } - - return 0; -} - - -/* - Tests the decoding of lots of different integers sizes - and values. - */ - -int IntegerValuesParseTest() -{ - int n; - QCBORDecodeContext DCtx; - - QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedEncodedInts), QCBOR_DECODE_MODE_NORMAL); - - n = IntegerValuesParseTestInternal(&DCtx); - - return(n); -} - - -/* - Creates a simple CBOR array and returns it in *pEncoded. The array is malloced - and needs to be freed. This is used by several tests. - - Two of the inputs can be set. Two other items in the array are fixed. - - */ - -static uint8_t spSimpleArrayBuffer[50]; - -static int CreateSimpleArray(int nInt1, int nInt2, uint8_t **pEncoded, size_t *pEncodedLen) -{ - QCBOREncodeContext ECtx; - int nReturn = -1; - - *pEncoded = NULL; - *pEncodedLen = INT32_MAX; - - // loop runs CBOR encoding twice. First with no buffer to - // calculate the length so buffer can be allocated correctly, - // and last with the buffer to do the actual encoding - do { - QCBOREncode_Init(&ECtx, (UsefulBuf){*pEncoded, *pEncodedLen}); - QCBOREncode_OpenArray(&ECtx); - QCBOREncode_AddInt64(&ECtx, nInt1); - QCBOREncode_AddInt64(&ECtx, nInt2); - QCBOREncode_AddBytes(&ECtx, ((UsefulBufC) {"galactic", 8})); - QCBOREncode_AddBytes(&ECtx, ((UsefulBufC) {"haven token", 11})); - QCBOREncode_CloseArray(&ECtx); - - if(QCBOREncode_FinishGetSize(&ECtx, pEncodedLen)) - goto Done; - - if(*pEncoded != NULL) { - nReturn = 0; - goto Done; - } - - // Use static buffer to avoid dependency on malloc() - if(*pEncodedLen > sizeof(spSimpleArrayBuffer)) { - goto Done; - } - *pEncoded = spSimpleArrayBuffer; - - } while(1); - -Done: - return nReturn; -} - - -/* - {"first integer": 42, - "an array of two strings": [ - "string1", "string2" - ], - "map in a map": { - "bytes 1": h'78787878', - "bytes 2": h'79797979', - "another int": 98, - "text 2": "lies, damn lies and statistics" - } - } - */ - -static uint8_t pValidMapEncoded[] = { - 0xa3, 0x6d, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x69, 0x6e, - 0x74, 0x65, 0x67, 0x65, 0x72, 0x18, 0x2a, 0x77, 0x61, 0x6e, - 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, - 0x74, 0x77, 0x6f, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x73, 0x82, 0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x31, - 0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x32, 0x6c, 0x6d, - 0x61, 0x70, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x6d, 0x61, - 0x70, 0xa4, 0x67, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x31, - 0x44, 0x78, 0x78, 0x78, 0x78, 0x67, 0x62, 0x79, 0x74, 0x65, - 0x73, 0x20, 0x32, 0x44, 0x79, 0x79, 0x79, 0x79, 0x6b, 0x61, - 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x74, - 0x18, 0x62, 0x66, 0x74, 0x65, 0x78, 0x74, 0x20, 0x32, 0x78, - 0x1e, 0x6c, 0x69, 0x65, 0x73, 0x2c, 0x20, 0x64, 0x61, 0x6d, - 0x6e, 0x20, 0x6c, 0x69, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, - 0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, - 0x73 } ; - -static int ParseOrderedArray(const uint8_t *pEncoded, size_t nLen, int64_t *pInt1, int64_t *pInt2, const uint8_t **pBuf3, size_t *pBuf3Len, const uint8_t **pBuf4, size_t *pBuf4Len) -{ - QCBORDecodeContext DCtx; - QCBORItem Item; - int nReturn = -1; // assume error until success - - QCBORDecode_Init(&DCtx, (UsefulBufC){pEncoded, nLen}, QCBOR_DECODE_MODE_NORMAL); - - // Make sure the first thing is a map - if(QCBORDecode_GetNext(&DCtx, &Item) != 0 || Item.uDataType != QCBOR_TYPE_ARRAY) - goto Done; - - // First integer - if(QCBORDecode_GetNext(&DCtx, &Item) != 0 || Item.uDataType != QCBOR_TYPE_INT64) - goto Done; - *pInt1 = Item.val.int64; - - // Second integer - if(QCBORDecode_GetNext(&DCtx, &Item) != 0 || Item.uDataType != QCBOR_TYPE_INT64) - goto Done; - *pInt2 = Item.val.int64; - - // First string - if(QCBORDecode_GetNext(&DCtx, &Item) != 0 || Item.uDataType != QCBOR_TYPE_BYTE_STRING) - goto Done; - *pBuf3 = Item.val.string.ptr; - *pBuf3Len = Item.val.string.len; - - // Second string - if(QCBORDecode_GetNext(&DCtx, &Item) != 0 || Item.uDataType != QCBOR_TYPE_BYTE_STRING) - goto Done; - *pBuf4 = Item.val.string.ptr; - *pBuf4Len = Item.val.string.len; - - nReturn = 0; - -Done: - return(nReturn); -} - - - - -int SimpleArrayTest() -{ - uint8_t *pEncoded; - size_t nEncodedLen; - - int64_t i1=0, i2=0; - size_t i3=0, i4=0; - const uint8_t *s3= (uint8_t *)""; - const uint8_t *s4= (uint8_t *)""; - - - if(CreateSimpleArray(23, 6000, &pEncoded, &nEncodedLen) < 0) { - return(-1); - } - - ParseOrderedArray(pEncoded, nEncodedLen, &i1, &i2, &s3, &i3, &s4, &i4); - - if(i1 != 23 || - i2 != 6000 || - i3 != 8 || - i4 != 11 || - memcmp("galactic", s3, 8) !=0 || - memcmp("haven token", s4, 11) !=0) { - return(-1); - } - - return(0); -} - - - -static uint8_t spDeepArrays[] = {0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80}; - -int ParseDeepArrayTest() -{ - QCBORDecodeContext DCtx; - int nReturn = 0; - int i; - - QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spDeepArrays), QCBOR_DECODE_MODE_NORMAL); - - for(i = 0; i < 10; i++) { - QCBORItem Item; - - if(QCBORDecode_GetNext(&DCtx, &Item) != 0 || - Item.uDataType != QCBOR_TYPE_ARRAY || - Item.uNestingLevel != i) { - nReturn = -1; - break; - } - } - - return(nReturn); -} - -// Big enough to test nesting to the depth of 24 -static uint8_t spTooDeepArrays[] = {0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x80}; - -int ParseTooDeepArrayTest() -{ - QCBORDecodeContext DCtx; - int nReturn = 0; - int i; - QCBORItem Item; - - - QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spTooDeepArrays), QCBOR_DECODE_MODE_NORMAL); - - for(i = 0; i < QCBOR_MAX_ARRAY_NESTING1; i++) { - - if(QCBORDecode_GetNext(&DCtx, &Item) != 0 || - Item.uDataType != QCBOR_TYPE_ARRAY || - Item.uNestingLevel != i) { - nReturn = -1; - break; - } - } - - if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_ARRAY_NESTING_TOO_DEEP) - nReturn = -1; - - return(nReturn); -} - - - - -int ShortBufferParseTest() -{ - int nResult = 0; - QCBORDecodeContext DCtx; - int num; - - for(num = sizeof(spExpectedEncodedInts)-1; num; num--) { - int n; - - QCBORDecode_Init(&DCtx, (UsefulBufC){spExpectedEncodedInts, num}, QCBOR_DECODE_MODE_NORMAL); - - n = IntegerValuesParseTestInternal(&DCtx); - - //printf("Len %d, result: %d\n", num, n); - - if(n != QCBOR_ERR_HIT_END) { - nResult = -1; - goto Done; - } - } -Done: - return nResult; -} - - - -int ShortBufferParseTest2() -{ - uint8_t *pEncoded; - int nReturn; - size_t nEncodedLen; - - int64_t i1, i2; - size_t i3, i4; - const uint8_t *s3, *s4; - - nReturn = 0; - - if(CreateSimpleArray(23, 6000, &pEncoded, &nEncodedLen) < 0) { - return(-1); - } - - for(nEncodedLen--; nEncodedLen; nEncodedLen--) { - int nResult = ParseOrderedArray(pEncoded, (uint32_t)nEncodedLen, &i1, &i2, &s3, &i3, &s4, &i4); - if(nResult == 0) { - nReturn = -1; - } - } - - return(nReturn); -} - -/* - Decode and thoroughly check a moderately complex - set of maps - */ -static int ParseMapTest1(QCBORDecodeMode nMode) -{ - QCBORDecodeContext DCtx; - QCBORItem Item; - int nCBORError; - - QCBORDecode_Init(&DCtx, (UsefulBufC){pValidMapEncoded, sizeof(pValidMapEncoded)}, nMode); - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uDataType != QCBOR_TYPE_MAP || - Item.val.uCount != 3) - return -1; - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || - Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 42 || - Item.uDataAlloc || - Item.uLabelAlloc || - UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("first integer"))) { - return -1; - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || - Item.uDataAlloc || - Item.uLabelAlloc || - UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("an array of two strings")) || - Item.uDataType != QCBOR_TYPE_ARRAY || - Item.val.uCount != 2) - return -1; - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || - Item.uDataAlloc || - Item.uLabelAlloc || - UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("string1"))) { - return -1; - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || - Item.uDataAlloc || - Item.uLabelAlloc || - UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("string2"))) { - return -1; - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || - Item.uDataAlloc || - Item.uLabelAlloc || - UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("map in a map")) || - Item.uDataType != QCBOR_TYPE_MAP || - Item.val.uCount != 4) { - return -1; - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || - UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("bytes 1"))|| - Item.uDataType != QCBOR_TYPE_BYTE_STRING || - Item.uDataAlloc || - Item.uLabelAlloc || - UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("xxxx"))) { - return -1; - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || - UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("bytes 2")) || - Item.uDataType != QCBOR_TYPE_BYTE_STRING || - Item.uDataAlloc || - Item.uLabelAlloc || - UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("yyyy"))) { - return -1; - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || - Item.uDataAlloc || - Item.uLabelAlloc || - UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("another int")) || - Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 98) - return -1; - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || - UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("text 2"))|| - Item.uDataType != QCBOR_TYPE_TEXT_STRING || - Item.uDataAlloc || - Item.uLabelAlloc || - UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("lies, damn lies and statistics"))) { - return -1; - } - - return 0; -} - - -/* - Decode and thoroughly check a moderately complex - set of maps - */ -int ParseMapAsArrayTest() -{ - QCBORDecodeContext DCtx; - QCBORItem Item; - int nCBORError; - - QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded), QCBOR_DECODE_MODE_MAP_AS_ARRAY); - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uDataType != QCBOR_TYPE_MAP_AS_ARRAY || - Item.val.uCount != 6) { - return -1; - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || - Item.uDataAlloc || - Item.uLabelAlloc || - Item.uLabelType != QCBOR_TYPE_NONE || - UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("first integer"))) { - return -2; - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uLabelType != QCBOR_TYPE_NONE || - Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 42 || - Item.uDataAlloc || - Item.uLabelAlloc) { - return -3; - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uLabelType != QCBOR_TYPE_NONE || - Item.uDataAlloc || - Item.uLabelAlloc || - UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("an array of two strings")) || - Item.uDataType != QCBOR_TYPE_TEXT_STRING) { - return -4; - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uLabelType != QCBOR_TYPE_NONE || - Item.uDataAlloc || - Item.uLabelAlloc || - Item.uDataType != QCBOR_TYPE_ARRAY || - Item.val.uCount != 2) { - return -5; - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || - Item.val.string.len != 7 || - Item.uDataAlloc || - Item.uLabelAlloc || - UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("string1"))) { - return -6; - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || - Item.uDataAlloc || - Item.uLabelAlloc || - UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("string2"))) { - return -7; - } - - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uLabelType != QCBOR_TYPE_NONE || - Item.uDataAlloc || - Item.uLabelAlloc || - UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("map in a map"))) { - return -8; - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uLabelType != QCBOR_TYPE_NONE || - Item.uDataAlloc || - Item.uLabelAlloc || - Item.uDataType != QCBOR_TYPE_MAP_AS_ARRAY || - Item.val.uCount != 8) { - return -9; - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uLabelType != QCBOR_TYPE_NONE || - UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("bytes 1"))|| - Item.uDataType != QCBOR_TYPE_TEXT_STRING || - Item.uDataAlloc || - Item.uLabelAlloc) { - return -10; - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uLabelType != QCBOR_TYPE_NONE || - Item.uDataType != QCBOR_TYPE_BYTE_STRING || - Item.uDataAlloc || - Item.uLabelAlloc || - UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("xxxx"))) { - return -11; - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uLabelType != QCBOR_TYPE_NONE || - UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("bytes 2")) || - Item.uDataType != QCBOR_TYPE_TEXT_STRING || - Item.uDataAlloc || - Item.uLabelAlloc) { - return -12; - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uLabelType != QCBOR_TYPE_NONE || - Item.uDataType != QCBOR_TYPE_BYTE_STRING || - Item.uDataAlloc || - Item.uLabelAlloc || - UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("yyyy"))) { - return -13; - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uLabelType != QCBOR_TYPE_NONE || - Item.uDataAlloc || - Item.uLabelAlloc || - UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("another int")) || - Item.uDataType != QCBOR_TYPE_TEXT_STRING) { - return -14; - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uLabelType != QCBOR_TYPE_NONE || - Item.uDataAlloc || - Item.uLabelAlloc || - Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 98) { - return -15; - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uLabelType != QCBOR_TYPE_NONE || - UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("text 2"))|| - Item.uDataType != QCBOR_TYPE_TEXT_STRING || - Item.uDataAlloc || - Item.uLabelAlloc) { - return -16; - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uLabelType != QCBOR_TYPE_NONE || - Item.uDataType != QCBOR_TYPE_TEXT_STRING || - Item.uDataAlloc || - Item.uLabelAlloc || - UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("lies, damn lies and statistics"))) { - return -17; - } - - return 0; -} - - -/* - Fully or partially decode pValidMapEncoded. When - partially decoding check for the right error code. - How much partial decoding depends on nLevel. - - The partial decodes test error conditions of - incomplete encoded input. - - This could be combined with the above test - and made prettier and maybe a little more - thorough. - */ -static int ExtraBytesTest(int nLevel) -{ - QCBORDecodeContext DCtx; - QCBORItem Item; - int nCBORError; - - QCBORDecode_Init(&DCtx, (UsefulBufC){pValidMapEncoded, sizeof(pValidMapEncoded)}, QCBOR_DECODE_MODE_NORMAL); - - if(nLevel < 1) { - if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_EXTRA_BYTES) { - return -1; - } else { - return 0; - } - } - - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uDataType != QCBOR_TYPE_MAP || - Item.val.uCount != 3) - return -1; - - if(nLevel < 2) { - if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN) { - return -1; - } else { - return 0; - } - } - - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || - Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.uCount != 42 || - UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("first integer"))) { - return -1; - } - - if(nLevel < 3) { - if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN) { - return -1; - } else { - return 0; - } - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || - UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("an array of two strings")) || - Item.uDataType != QCBOR_TYPE_ARRAY || - Item.val.uCount != 2) { - return -1; - } - - - if(nLevel < 4) { - if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN) { - return -1; - } else { - return 0; - } - } - - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || - UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("string1"))) { - return -1; - } - - if(nLevel < 5) { - if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN) { - return -1; - } else { - return 0; - } - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || - UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("string2"))) { - return -1; - } - - if(nLevel < 6) { - if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN) { - return -1; - } else { - return 0; - } - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || - UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("map in a map")) || - Item.uDataType != QCBOR_TYPE_MAP || - Item.val.uCount != 4) - return -1; - - if(nLevel < 7) { - if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN) { - return -1; - } else { - return 0; - } - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || - UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("bytes 1")) || - Item.uDataType != QCBOR_TYPE_BYTE_STRING || - UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("xxxx"))) { - return -1; - } - - if(nLevel < 8) { - if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN) { - return -1; - } else { - return 0; - } - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || - UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("bytes 2")) || - Item.uDataType != QCBOR_TYPE_BYTE_STRING || - UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("yyyy"))) { - return -1; - } - - if(nLevel < 9) { - if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN) { - return -1; - } else { - return 0; - } - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || - UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("another int")) || - Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != 98) - return -1; - - if(nLevel < 10) { - if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN) { - return -1; - } else { - return 0; - } - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { - return nCBORError; - } - if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || - UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("text 2"))|| - Item.uDataType != QCBOR_TYPE_TEXT_STRING || - UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("lies, damn lies and statistics"))) { - return -1; - } - - if(QCBORDecode_Finish(&DCtx)) { - return -1; - } - - return 0; -} - - - - -int ParseMapTest() -{ - // Parse a moderatly complex map structure very thoroughl - int n = ParseMapTest1(QCBOR_DECODE_MODE_NORMAL); - - n = ParseMapTest1(QCBOR_DECODE_MODE_MAP_STRINGS_ONLY); - - if(!n) { - for(int i = 0; i < 10; i++) { - n = ExtraBytesTest(i); - if(n) { - break; - } - } - } - - return(n); -} - - -static uint8_t spSimpleValues[] = {0x8a, 0xf4, 0xf5, 0xf6, 0xf7, 0xff, 0xe0, 0xf3, 0xf8, 0x00, 0xf8, 0x13, 0xf8, 0x1f, 0xf8, 0x20, 0xf8, 0xff}; - -int ParseSimpleTest() -{ - QCBORDecodeContext DCtx; - QCBORItem Item; - int nCBORError; - - - QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSimpleValues), QCBOR_DECODE_MODE_NORMAL); - - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_ARRAY || - Item.val.uCount != 10) - return -1; - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_FALSE) - return -1; - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_TRUE) - return -1; - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_NULL) - return -1; - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_UNDEF) - return -1; - - // A break - if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_BAD_BREAK) - return -1; - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_UKNOWN_SIMPLE || Item.val.uSimple != 0) - return -1; - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_UKNOWN_SIMPLE || Item.val.uSimple != 19) - return -1; - - if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_INVALID_CBOR) - return -1; - - if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_INVALID_CBOR) - return -1; - - if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_INVALID_CBOR) - return -1; - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_UKNOWN_SIMPLE || Item.val.uSimple != 32) - return -1; - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_UKNOWN_SIMPLE || Item.val.uSimple != 255) - return -1; - - return 0; - -} - - -struct FailInput { - UsefulBufC Input; - int nError; -}; - - -struct FailInput Failures[] = { - { {(uint8_t[]){0x18}, 1}, QCBOR_ERR_HIT_END }, // 1 byte integer missing the byte - { {(uint8_t[]){0x1c}, 1}, QCBOR_ERR_UNSUPPORTED }, // Reserved additional info = 28 - { {(uint8_t[]){0x1d}, 1}, QCBOR_ERR_UNSUPPORTED }, // Reserved additional info = 29 - { {(uint8_t[]){0x1e}, 1}, QCBOR_ERR_UNSUPPORTED }, // Reserved additional info = 30 - { {(uint8_t[]){0x1f}, 1}, QCBOR_ERR_UNSUPPORTED }, // Indefinite length integer - { {(uint8_t[]){0x3c}, 1}, QCBOR_ERR_UNSUPPORTED }, // 1 byte integer missing the byte - { {(uint8_t[]){0x3d}, 1}, QCBOR_ERR_UNSUPPORTED }, // 1 byte integer missing the byte - { {(uint8_t[]){0x3e}, 1}, QCBOR_ERR_UNSUPPORTED }, // 1 byte integer missing the byte - { {(uint8_t[]){0x3f}, 1}, QCBOR_ERR_UNSUPPORTED }, // Indefinite length negative integer - { {(uint8_t[]){0x41}, 1}, QCBOR_ERR_HIT_END }, // Short byte string - { {(uint8_t[]){0x5c}, 1}, QCBOR_ERR_UNSUPPORTED }, // Reserved additional info = 28 - { {(uint8_t[]){0x5f}, 1}, QCBOR_ERR_UNSUPPORTED }, // Indefinite length byte string - { {(uint8_t[]){0x61}, 1}, QCBOR_ERR_HIT_END }, // Short UTF-8 string - { {(uint8_t[]){0x7c}, 1}, QCBOR_ERR_UNSUPPORTED }, // Reserved additional info = 28 - { {(uint8_t[]){0x7f}, 1}, QCBOR_ERR_UNSUPPORTED }, // Indefinite length UTF-8 string - { {(uint8_t[]){0xff}, 1}, QCBOR_ERR_UNSUPPORTED } , // break - { {(uint8_t[]){0xf8, 0x00}, 2}, QCBOR_ERR_INVALID_CBOR }, // An invalid encoding of a simple type - { {(uint8_t[]){0xf8, 0x1f}, 2}, QCBOR_ERR_INVALID_CBOR }, // An invalid encoding of a simple type - { {(uint8_t[]){0xc0, 0x00}, 2}, QCBOR_ERR_BAD_OPT_TAG }, // Text-based date, with an integer - { {(uint8_t[]){0xc1, 0x41, 0x33}, 3}, QCBOR_ERR_BAD_OPT_TAG }, // Epoch date, with an byte string - { {(uint8_t[]){0xc1, 0xc0, 0x00}, 3}, QCBOR_ERR_BAD_OPT_TAG }, // tagged as both epoch and string dates - { {(uint8_t[]){0xc2, 0x00}, 2}, QCBOR_ERR_BAD_OPT_TAG } // big num tagged an int, not a byte string - -}; - - -int FailureTests() -{ - int nResult = 0; - - struct FailInput *pFEnd = &Failures[0] + sizeof(Failures)/sizeof(struct FailInput); - - for(struct FailInput *pF = &Failures[0]; pF < pFEnd ;pF++) { - QCBORDecodeContext DCtx; - QCBORItem Item; - int nCBORError; - - QCBORDecode_Init(&DCtx, pF->Input, QCBOR_DECODE_MODE_NORMAL); - - while(1) { - nCBORError = QCBORDecode_GetNext(&DCtx, &Item); - if(QCBOR_ERR_HIT_END == nCBORError) { - break; - } - if(nCBORError != pF->nError) { - nResult = 1; - break; - } - } - } - - { - QCBORDecodeContext DCtx; - QCBORItem Item; - int nCBORError; - - QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSimpleValues), QCBOR_DECODE_MODE_NORMAL); - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) - return nCBORError; - if(Item.uDataType != QCBOR_TYPE_ARRAY || - Item.val.uCount != 10) - return -1; - - DCtx.InBuf.magic = 0; // Corrupt the UsefulInputBuf - - nCBORError = QCBORDecode_GetNext(&DCtx, &Item); - if(nCBORError != QCBOR_ERR_HIT_END) - return -1; - } - - - return nResult; -} - - -/* Try all 256 values of the byte at nLen including recursing for - each of the values to try values at nLen+1 ... up to nLenMax - */ -static void ComprehensiveInputRecurser(uint8_t *pBuf, int nLen, int nLenMax) -{ - if(nLen >= nLenMax) { - return; - } - - for(int inputByte = 0; inputByte < 256; inputByte++) { - // Set up the input - pBuf[nLen] = inputByte; - const UsefulBufC Input = {pBuf, nLen+1}; - - // Get ready to parse - QCBORDecodeContext DCtx; - QCBORDecode_Init(&DCtx, Input, QCBOR_DECODE_MODE_NORMAL); - - // Parse by getting the next item until an error occurs - // Just about every possible decoder error can occur here - // The goal of this test is not to check for the correct - // error since that is not really possible. It is to - // see that there is no crash on hostile input. - while(1) { - QCBORItem Item; - QCBORError nCBORError = QCBORDecode_GetNext(&DCtx, &Item); - if(nCBORError != QCBOR_SUCCESS) { - break; - } - } - - ComprehensiveInputRecurser(pBuf, nLen+1, nLenMax); - } -} - - -/* - Public function for initialization. See header qcbor.h - */ -int ComprehensiveInputTest() -{ - // Size 2 tests 64K inputs and runs quickly - uint8_t pBuf[2]; - - ComprehensiveInputRecurser(pBuf, 0, sizeof(pBuf)); - - return 0; -} - - -/* - Public function for initialization. See header qcbor.h - */ -int BigComprehensiveInputTest() -{ - // size 3 tests 16 million inputs and runs OK - // in seconds on fast machines. Size 4 takes - // 10+ minutes and 5 half a day on fast - // machines. This test is kept separate from - // the others so as to no slow down the use - // of them as a very frequent regression. - uint8_t pBuf[3]; // - - ComprehensiveInputRecurser(pBuf, 0, sizeof(pBuf)); - - return 0; -} - - -static uint8_t spDateTestInput[] = { - 0xc0, // tag for string date - 0x6a, '1','9','8','5','-','0','4','-','1','2', // Date string - - 0xc1, // tag for epoch date - 0x1a, 0x53, 0x72, 0x4E, 0x00, // Epoch date 1400000000; Tue, 13 May 2014 16:53:20 GMT - - // CBOR_TAG_B64 - 0xc1, 0xcf, 0xd8, 0x22, // 0xee, // Epoch date with extra tags TODO: fix this test - 0x1a, 0x53, 0x72, 0x4E, 0x01, - - 0xc1, // tag for epoch date - 0x1b, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // Too large integer - - 0xc1, // tag for epoch date - 0xfa, 0x3f, 0x8c, 0xcc, 0xcd, // double with value 1.1 - - 0xc1, // tag for epoch date - 0xfa, 0x7f, 0x7f, 0xff, 0xff // 3.4028234663852886e+38 too large - -}; - - -// have to check float expected only to within an epsilon -int CHECK_EXPECTED_DOUBLE(double val, double expected) { - - double diff = val - expected; - - diff = fabs(diff); - - return diff > 0.0000001; -} - - -int DateParseTest() -{ - QCBORDecodeContext DCtx; - QCBORItem Item; - int nCBORError; - - QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spDateTestInput), QCBOR_DECODE_MODE_NORMAL); - - const uint64_t uTags[] = {15}; - QCBORTagListIn TagList = {1, uTags}; - - QCBORDecode_SetCallerConfiguredTagList(&DCtx, &TagList); - - // String date - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) - return -1; - if(Item.uDataType != QCBOR_TYPE_DATE_STRING || - UsefulBuf_Compare(Item.val.dateString, UsefulBuf_FromSZ("1985-04-12"))){ - return -2; - } - - // Epoch date - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) - return -3; - if(Item.uDataType != QCBOR_TYPE_DATE_EPOCH || - Item.val.epochDate.nSeconds != 1400000000 || - Item.val.epochDate.fSecondsFraction != 0 ) { - return -4; - } - - // Epoch date with extra CBOR_TAG_B64 tag that doesn't really mean anything - // but want to be sure extra tag doesn't cause a problem - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) - return -5; - if(Item.uDataType != QCBOR_TYPE_DATE_EPOCH || - Item.val.epochDate.nSeconds != 1400000001 || - Item.val.epochDate.fSecondsFraction != 0 || - !QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_B64)) { - return -6; - } - - // Epoch date that is too large for our representation - if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_DATE_OVERFLOW) { - return -7; - } - - // Epoch date in float format with fractional seconds - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) - return -8; - if(Item.uDataType != QCBOR_TYPE_DATE_EPOCH || - Item.val.epochDate.nSeconds != 1 || - CHECK_EXPECTED_DOUBLE(Item.val.epochDate.fSecondsFraction, 0.1 )) { - return -9; - } - - // Epoch date float that is too large for our representation - if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_DATE_OVERFLOW) { - return -10; - } - - // TODO: could use a few more tests with float, double, and half precsion and negative (but coverage is still pretty good) - - return 0; -} - -// Really simple basic input for tagging test -static uint8_t spOptTestInput[] = { - 0xd9, 0xd9, 0xf7, // CBOR magic number - 0x81, // Array of one - 0xd8, 0x04, // non-preferred serialization of tag 4 - 0x82, 0x01, 0x03}; // fraction 1/3 - -static uint8_t spEncodedLargeTag[] = {0xdb, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x80}; - -// 0x9192939495969798, 0x88, 0x01, 0x04 -static uint8_t spLotsOfTags[] = {0xdb, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0xd8, 0x88, 0xc5, 0xc4, 0x80}; - -/* - The cbor.me parse of this. - 55799(55799(55799({6(7(-23)): 5859837686836516696(7({7(-20): 11({17(-18): 17(17(17("Organization"))), - 9(-17): 773("SSG"), -15: 4(5(6(7(8(9(10(11(12(13(14(15("Confusion")))))))))))), 17(-16): 17("San Diego"), - 17(-14): 17("US")}), 23(-19): 19({-11: 9({-9: -7}), - 90599561(90599561(90599561(-10))): 12(h'0102030405060708090A')})})), - 16(-22): 23({11(8(7(-5))): 8(-3)})}))) - */ -static uint8_t spCSRWithTags[] = { - 0xd9, 0xd9, 0xf7, 0xd9, 0xd9, 0xf7, 0xd9, 0xd9, 0xf7, 0xa2, - 0xc6, 0xc7, 0x36, - 0xdb, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0xc7, 0xa2, - 0xda, 0x00, 0x00, 0x00, 0x07, 0x33, - 0xcb, 0xa5, - 0xd1, 0x31, - 0xd1, 0xd1, 0xd1, 0x6c, - 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0xc9, 0x30, - 0xd9, 0x03, 0x05, 0x63, - 0x53, 0x53, 0x47, - 0x2e, - 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0x69, - 0x43, 0x6f, 0x6e, 0x66, 0x75, 0x73, 0x69, 0x6f, 0x6e, - 0xd1, 0x2f, - 0xd1, 0x69, - 0x53, 0x61, 0x6e, 0x20, 0x44, 0x69, 0x65, 0x67, 0x6f, - 0xd1, 0x2d, - 0xd1, 0x62, - 0x55, 0x53, - 0xd7, 0x32, - 0xd3, 0xa2, - 0x2a, - 0xc9, 0xa1, - 0x28, - 0x26, - 0xda, 0x05, 0x66, 0x70, 0x89, 0xda, 0x05, 0x66, 0x70, 0x89, 0xda, 0x05, 0x66, 0x70, 0x89, 0x29, - 0xcc, 0x4a, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,0x07, 0x08, 0x09, 0x0a, - 0xd0, 0x35, - 0xd7, 0xa1, - 0xcb, 0xc8, 0xc7, 0x24, - 0xc8, 0x22}; - -static int CheckCSRMaps(QCBORDecodeContext *pDC); - - -int OptTagParseTest() -{ - QCBORDecodeContext DCtx; - QCBORItem Item; - - QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spOptTestInput), QCBOR_DECODE_MODE_NORMAL); - - //------------------------- - // This text matches the magic number tag and the fraction tag - if(QCBORDecode_GetNext(&DCtx, &Item)) { - return -2; - } - if(Item.uDataType != QCBOR_TYPE_ARRAY || - !QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_CBOR_MAGIC)) { - return -3; - } - - if(QCBORDecode_GetNext(&DCtx, &Item)) { - return -4; - } - if(Item.uDataType != QCBOR_TYPE_ARRAY || - !QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_FRACTION) || - Item.val.uCount != 2) { - return -5; - } - - // -------------------------------- - // This test decodes the very large tag, but it is not in - // any list so it is ignored. - QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spEncodedLargeTag), QCBOR_DECODE_MODE_NORMAL); - if(QCBORDecode_GetNext(&DCtx, &Item)) { - return -6; - } - if(Item.uTagBits) { - return -7; - } - - // ---------------------------------- - // This test sets up a caller-config list that includes the very large tage and then matches it. - QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spEncodedLargeTag), QCBOR_DECODE_MODE_NORMAL); - const uint64_t puList[] = {0x9192939495969798, 257}; - const QCBORTagListIn TL = {2, puList}; - QCBORDecode_SetCallerConfiguredTagList(&DCtx, &TL); - - if(QCBORDecode_GetNext(&DCtx, &Item)) { - return -8; - } - if(Item.uDataType != QCBOR_TYPE_ARRAY || - !QCBORDecode_IsTagged(&DCtx, &Item, 0x9192939495969798) || - QCBORDecode_IsTagged(&DCtx, &Item, 257) || - QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_BIGFLOAT) || - Item.val.uCount != 0) { - return -9; - } - - //------------------------ - // This test sets up a caller-configured list, and looks up something not in it - const uint64_t puLongList[17] = {1,2,1}; - const QCBORTagListIn TLLong = {17, puLongList}; - QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spEncodedLargeTag), QCBOR_DECODE_MODE_NORMAL); - QCBORDecode_SetCallerConfiguredTagList(&DCtx, &TLLong); - if(QCBORDecode_GetNext(&DCtx, &Item)) { - return -11; - } - - // ----------------------- - // This tests retrievel of the full tag list - QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spLotsOfTags), QCBOR_DECODE_MODE_NORMAL); - uint64_t puTags[16]; - QCBORTagListOut Out = {0, 4, puTags}; - if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { - return -12; - } - if(puTags[0] != 0x9192939495969798 || - puTags[1] != 0x88 || - puTags[2] != 0x05 || - puTags[3] != 0x04) { - return -13; - } - - // ---------------------- - // This text if too small of an out list - QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spLotsOfTags), QCBOR_DECODE_MODE_NORMAL); - QCBORTagListOut OutSmall = {0, 3, puTags}; - if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &OutSmall) != QCBOR_ERR_TOO_MANY_TAGS) { - return -14; - } - - // --------------- - // Parse a version of the "CSR" that has had a ton of tags randomly inserted - QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spCSRWithTags), QCBOR_DECODE_MODE_NORMAL); - int n = CheckCSRMaps(&DCtx); - if(n) { - return n-2000; - } - - Out = (QCBORTagListOut){0,16, puTags}; - QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spCSRWithTags), QCBOR_DECODE_MODE_NORMAL); - - const uint64_t puTagList[] = {773, 1, 90599561}; - const QCBORTagListIn TagList = {3, puTagList}; - QCBORDecode_SetCallerConfiguredTagList(&DCtx, &TagList); - - - if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { - return -100; - } - if(Item.uDataType != QCBOR_TYPE_MAP || - !QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_CBOR_MAGIC) || - QCBORDecode_IsTagged(&DCtx, &Item, 90599561) || - QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_DATE_EPOCH) || - Item.val.uCount != 2 || - puTags[0] != CBOR_TAG_CBOR_MAGIC || - puTags[1] != CBOR_TAG_CBOR_MAGIC || - puTags[2] != CBOR_TAG_CBOR_MAGIC || - Out.uNumUsed != 3) { - return -101; - } - - if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { - return -102; - } - if(Item.uDataType != QCBOR_TYPE_MAP || - QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_CBOR_MAGIC) || - QCBORDecode_IsTagged(&DCtx, &Item, 6) || - QCBORDecode_IsTagged(&DCtx, &Item, 7) || // item is tagged 7, but 7 is not configured to be recognized - Item.val.uCount != 2 || - puTags[0] != 5859837686836516696 || - puTags[1] != 7 || - Out.uNumUsed != 2) { - return -103; - } - - if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { - return -104; - } - if(Item.uDataType != QCBOR_TYPE_MAP || - Item.uTagBits || - Item.val.uCount != 5 || - puTags[0] != 0x0b || - Out.uNumUsed != 1) { - return -105; - } - - if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { - return -106; - } - if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || - !QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_COSE_MAC0) || - Item.val.string.len != 12 || - puTags[0] != CBOR_TAG_COSE_MAC0 || - puTags[1] != CBOR_TAG_COSE_MAC0 || - puTags[2] != CBOR_TAG_COSE_MAC0 || - Out.uNumUsed != 3) { - return -105; - } - - if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { - return -107; - } - if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || - !QCBORDecode_IsTagged(&DCtx, &Item, 773) || - Item.val.string.len != 3 || - puTags[0] != 773 || - Out.uNumUsed != 1) { - return -108; - } - - if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { - return -109; - } - if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || - !QCBORDecode_IsTagged(&DCtx, &Item, 4) || - Item.val.string.len != 9 || - puTags[0] != 4 || - puTags[11] != 0x0f || - Out.uNumUsed != 12) { - return -110; - } - - if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { - return -111; - } - if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || - !QCBORDecode_IsTagged(&DCtx, &Item, 17) || - Item.val.string.len != 9 || - puTags[0] != 17 || - Out.uNumUsed != 1) { - return -112; - } - - if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { - return -111; - } - if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || - !QCBORDecode_IsTagged(&DCtx, &Item, 17) || - Item.val.string.len != 2 || - puTags[0] != 17 || - Out.uNumUsed != 1) { - return -112; - } - - if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { - return -113; - } - if(Item.uDataType != QCBOR_TYPE_MAP || - QCBORDecode_IsTagged(&DCtx, &Item, 19) || - Item.val.uCount != 2 || - puTags[0] != 19 || - Out.uNumUsed != 1) { - return -114; - } - - if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { - return -115; - } - if(Item.uDataType != QCBOR_TYPE_MAP || - QCBORDecode_IsTagged(&DCtx, &Item, 9) || - Item.uTagBits || - Item.val.uCount != 1 || - puTags[0] != 9 || - Out.uNumUsed != 1) { - return -116; - } - - if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { - return -116; - } - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.val.int64 != -7 || - Item.uTagBits || - Out.uNumUsed != 0) { - return -117; - } - - if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { - return -118; - } - if(Item.uDataType != QCBOR_TYPE_BYTE_STRING || - Item.val.string.len != 10 || - Item.uTagBits || - puTags[0] != 12 || - Out.uNumUsed != 1) { - return -119; - } - - if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { - return -120; - } - if(Item.uDataType != QCBOR_TYPE_MAP || - !QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_ENC_AS_B16) || - Item.val.uCount != 1 || - puTags[0] != 0x17 || - Out.uNumUsed != 1) { - return -121; - } - - if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { - return -122; - } - if(Item.uDataType != QCBOR_TYPE_INT64 || - QCBORDecode_IsTagged(&DCtx, &Item, 8) || - Item.val.int64 != -3 || - puTags[0] != 8 || - Out.uNumUsed != 1) { - return -123; - } - - if(QCBORDecode_Finish(&DCtx)) { - return -124; - } - - return 0; -} - - - - -static uint8_t spBigNumInput[] = { - 0x83, - 0xC2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xC3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xA4, - 0x63, 0x42, 0x4E, 0x2B, - 0xC2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x40, - 0xC2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x63, 0x42, 0x4E, 0x2D, - 0xC3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x38, 0x3F, - 0xC3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - - -static uint8_t spBigNum[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - - -int BignumParseTest() -{ - QCBORDecodeContext DCtx; - QCBORItem Item; - int nCBORError; - - QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNumInput), QCBOR_DECODE_MODE_NORMAL); - - - // - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) - return -1; - if(Item.uDataType != QCBOR_TYPE_ARRAY) { - return -1; - } - - // - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) - return -1; - if(Item.uDataType != QCBOR_TYPE_POSBIGNUM || - UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){ - return -1; - } - - // - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) - return -1; - if(Item.uDataType != QCBOR_TYPE_NEGBIGNUM || - UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){ - return -1; - } - - // - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) - return -1; - if(Item.uDataType != QCBOR_TYPE_MAP) { - return -1; - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) - return -1; - if(Item.uDataType != QCBOR_TYPE_POSBIGNUM || - Item.uLabelType != QCBOR_TYPE_TEXT_STRING || - UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){ - return -1; - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) - return -1; - if(Item.uDataType != QCBOR_TYPE_POSBIGNUM || - Item.uLabelType != QCBOR_TYPE_INT64 || - Item.label.int64 != 64 || - UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){ - return -1; - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) - return -1; - if(Item.uDataType != QCBOR_TYPE_NEGBIGNUM || - Item.uLabelType != QCBOR_TYPE_TEXT_STRING || - UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){ - return -1; - } - - if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) - return -1; - if(Item.uDataType != QCBOR_TYPE_NEGBIGNUM || - Item.uLabelType != QCBOR_TYPE_INT64 || - Item.label.int64 != -64 || - UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){ - return -1; - } - - return 0; -} - - - -static int CheckItemWithIntLabel(QCBORDecodeContext *pCtx, uint8_t uDataType, uint8_t uNestingLevel, uint8_t uNextNest, int64_t nLabel, QCBORItem *pItem) -{ - QCBORItem Item; - int nCBORError; - - if((nCBORError = QCBORDecode_GetNext(pCtx, &Item))) return -1; - if(Item.uDataType != uDataType) return -1; - if(uNestingLevel > 0) { - if(Item.uLabelType != QCBOR_TYPE_INT64 && Item.uLabelType != QCBOR_TYPE_UINT64) return -1; - if(Item.uLabelType == QCBOR_TYPE_INT64) { - if(Item.label.int64 != nLabel) return -1; - } else { - if(Item.label.uint64 != (uint64_t)nLabel) return -1; - } - } - if(Item.uNestingLevel != uNestingLevel) return -1; - if(Item.uNextNestLevel != uNextNest) return -1; - - if(pItem) { - *pItem = Item; - } - return 0; -} - - -// Same code checks definite and indefinite length versions of the map -static int CheckCSRMaps(QCBORDecodeContext *pDC) -{ - if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_MAP, 0, 1, 0, NULL)) return -1; - - if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_MAP, 1, 2, -23, NULL)) return -1; - - if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_MAP, 2, 3, -20, NULL)) return -1; - - if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_TEXT_STRING, 3, 3, -18, NULL)) return -1; - if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_TEXT_STRING, 3, 3, -17, NULL)) return -1; - if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_TEXT_STRING, 3, 3, -15, NULL)) return -1; - if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_TEXT_STRING, 3, 3, -16, NULL)) return -1; - if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_TEXT_STRING, 3, 2, -14, NULL)) return -1; - - if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_MAP, 2, 3, -19, NULL)) return -1; - if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_MAP, 3, 4, -11, NULL)) return -1; - - if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_INT64, 4, 3, -9, NULL)) return -1; - if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_BYTE_STRING, 3, 1, -10, NULL)) return -1; - - if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_MAP, 1, 2, -22, NULL)) return -1; - if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_INT64, 2, 0, -5, NULL)) return -1; - - if(QCBORDecode_Finish(pDC)) return -2; - - return 0; -} - - -/* -// cbor.me decoded output -{ - -23: { - -20: { - -18: "Organization", - -17: "SSG", - -15: "Confusion", - -16: "San Diego", - -14: "US" - }, - -19: { - -11: { - -9: -7 - }, - -10: '\u0001\u0002\u0003\u0004\u0005\u0006\a\b\t\n' - } - }, - -22: { - -5: -3 - } -} - */ - - -static uint8_t spCSRInput[] = { - 0xa2, 0x36, 0xa2, 0x33, 0xa5, 0x31, 0x6c, 0x4f, - 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x30, 0x63, 0x53, 0x53, 0x47, - 0x2e, 0x69, 0x43, 0x6f, 0x6e, 0x66, 0x75, 0x73, - 0x69, 0x6f, 0x6e, 0x2f, 0x69, 0x53, 0x61, 0x6e, - 0x20, 0x44, 0x69, 0x65, 0x67, 0x6f, 0x2d, 0x62, - 0x55, 0x53, 0x32, 0xa2, 0x2a, 0xa1, 0x28, 0x26, - 0x29, 0x4a, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, - 0x07, 0x08, 0x09, 0x0a, 0x35, 0xa1, 0x24, 0x22}; - -int NestedMapTest() -{ - QCBORDecodeContext DCtx; - - QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spCSRInput), QCBOR_DECODE_MODE_NORMAL); - - return CheckCSRMaps(&DCtx); -} - - - -int StringDecoderModeFailTest() -{ - QCBORDecodeContext DCtx; - - QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spCSRInput), QCBOR_DECODE_MODE_MAP_STRINGS_ONLY); - - QCBORItem Item; - QCBORError nCBORError; - - if(QCBORDecode_GetNext(&DCtx, &Item)) { - return -1; - } - if(Item.uDataType != QCBOR_TYPE_MAP) { - return -2; - } - - nCBORError = QCBORDecode_GetNext(&DCtx, &Item); - if(nCBORError != QCBOR_ERR_MAP_LABEL_TYPE) { - return -3; - } - - return 0; -} - - -// Same map as above, but using indefinite lengths -static uint8_t spCSRInputIndefLen[] = { - 0xbf, 0x36, 0xbf, 0x33, 0xbf, 0x31, 0x6c, 0x4f, - 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x30, 0x63, 0x53, 0x53, 0x47, - 0x2e, 0x69, 0x43, 0x6f, 0x6e, 0x66, 0x75, 0x73, - 0x69, 0x6f, 0x6e, 0x2f, 0x69, 0x53, 0x61, 0x6e, - 0x20, 0x44, 0x69, 0x65, 0x67, 0x6f, 0x2d, 0x62, - 0x55, 0x53, 0xff, 0x32, 0xbf, 0x2a, 0xbf, 0x28, - 0x26, 0xff, 0x29, 0x4a, 0x01, 0x02, 0x03, 0x04, - 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0xff, 0xff, - 0x35, 0xbf, 0x24, 0x22, 0xff, 0xff}; - -int NestedMapTestIndefLen() -{ - QCBORDecodeContext DCtx; - - QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spCSRInputIndefLen), QCBOR_DECODE_MODE_NORMAL); - - return CheckCSRMaps(&DCtx); -} - - - -static UsefulBufC make_nested_indefinite_arrays(int n, UsefulBuf Storage) -{ - UsefulOutBuf UOB; - UsefulOutBuf_Init(&UOB, Storage); - - int i; - for(i = 0; i < n; i++) { - UsefulOutBuf_AppendByte(&UOB, 0x9f); - } - - for(i = 0; i < n; i++) { - UsefulOutBuf_AppendByte(&UOB, 0xff); - } - return UsefulOutBuf_OutUBuf(&UOB); -} - - -static int parse_indeflen_nested(UsefulBufC Nested, int nNestLevel) -{ - QCBORDecodeContext DC; - QCBORDecode_Init(&DC, Nested, 0); - - int j; - for(j = 0; j < nNestLevel; j++) { - QCBORItem Item; - int nReturn = QCBORDecode_GetNext(&DC, &Item); - if(j >= QCBOR_MAX_ARRAY_NESTING) { - // Should be in error - if(nReturn != QCBOR_ERR_ARRAY_NESTING_TOO_DEEP) { - return -4; - } else { - return 0; // Decoding doesn't recover after an error - } - } else { - // Should be no error - if(nReturn) { - return -9; // Should not have got an error - } - } - if(Item.uDataType != QCBOR_TYPE_ARRAY) { - return -7; - } - } - int nReturn = QCBORDecode_Finish(&DC); - if(nReturn) { - return -3; - } - return 0; -} - - -int IndefiniteLengthNestTest() -{ - UsefulBuf_MAKE_STACK_UB(Storage, 50); - int i; - for(i=1; i < QCBOR_MAX_ARRAY_NESTING+4; i++) { - const UsefulBufC Nested = make_nested_indefinite_arrays(i, Storage); - int nReturn = parse_indeflen_nested(Nested, i); - if(nReturn) { - return nReturn; - } - } - return 0; -} - - - -static const uint8_t spIndefiniteArray[] = {0x9f, 0x01, 0x82, 0x02, 0x03, 0xff}; // [1, [2, 3]] -static const uint8_t spIndefiniteArrayBad1[] = {0x9f}; // No closing break -static const uint8_t spIndefiniteArrayBad2[] = {0x9f, 0x9f, 0x02, 0xff}; // Not enough closing breaks -static const uint8_t spIndefiniteArrayBad3[] = {0x9f, 0x02, 0xff, 0xff}; // Too many closing breaks -static const uint8_t spIndefiniteArrayBad4[] = {0x81, 0x9f}; // Unclosed indeflen inside def len -static const uint8_t spIndefiniteArrayBad5[] = {0x9f, 0xd1, 0xff}; // confused tag - -int IndefiniteLengthArrayMapTest() -{ - int nResult; - // --- first test ----- - UsefulBufC IndefLen = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteArray); - - // Decode it and see if it is OK - UsefulBuf_MAKE_STACK_UB(MemPool, 150); - QCBORDecodeContext DC; - QCBORItem Item; - QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL); - - QCBORDecode_SetMemPool(&DC, MemPool, false); - - QCBORDecode_GetNext(&DC, &Item); - - if(Item.uDataType != QCBOR_TYPE_ARRAY || - Item.uNestingLevel != 0 || - Item.uNextNestLevel != 1) { - return -111; - } - - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.uNestingLevel != 1 || - Item.uNextNestLevel != 1) { - return -2; - } - - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_ARRAY || - Item.uNestingLevel != 1 || - Item.uNextNestLevel != 2) { - return -3; - } - - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.uNestingLevel != 2 || - Item.uNextNestLevel != 2) { - return -4; - } - - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_INT64 || - Item.uNestingLevel != 2 || - Item.uNextNestLevel != 0) { - return -5; - } - - if(QCBORDecode_Finish(&DC)) { - return -6; - } - - // --- next test ----- - IndefLen = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteArrayBad1); - - QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL); - - QCBORDecode_SetMemPool(&DC, MemPool, false); - - nResult = QCBORDecode_GetNext(&DC, &Item); - if(nResult || Item.uDataType != QCBOR_TYPE_ARRAY) { - return -7; - } - - nResult = QCBORDecode_Finish(&DC); - if(nResult != QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN) { - return -8; - } - - - // --- next test ----- - IndefLen = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteArrayBad2); - - QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL); - - QCBORDecode_SetMemPool(&DC, MemPool, false); - - nResult = QCBORDecode_GetNext(&DC, &Item); - if(nResult || Item.uDataType != QCBOR_TYPE_ARRAY) { - return -9; - } - - nResult = QCBORDecode_GetNext(&DC, &Item); - if(nResult || Item.uDataType != QCBOR_TYPE_ARRAY) { - return -10; - } - - nResult = QCBORDecode_GetNext(&DC, &Item); - if(nResult || Item.uDataType != QCBOR_TYPE_INT64) { - return -11; - } - - nResult = QCBORDecode_Finish(&DC); - if(nResult != QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN) { - return -12; - } - - - // --- next test ----- - IndefLen = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteArrayBad3); - - QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL); - - QCBORDecode_SetMemPool(&DC, MemPool, false); - - nResult = QCBORDecode_GetNext(&DC, &Item); - if(nResult || Item.uDataType != QCBOR_TYPE_ARRAY) { - return -13; - } - - nResult = QCBORDecode_GetNext(&DC, &Item); - if(nResult != QCBOR_ERR_BAD_BREAK) { - return -14; - } - - - // --- next test ----- - IndefLen = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteArrayBad4); - - QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL); - - QCBORDecode_SetMemPool(&DC, MemPool, false); - - nResult = QCBORDecode_GetNext(&DC, &Item); - if(nResult || Item.uDataType != QCBOR_TYPE_ARRAY) { - return -15; - } - - nResult = QCBORDecode_GetNext(&DC, &Item); - if(nResult || Item.uDataType != QCBOR_TYPE_ARRAY) { - return -16; - } - - nResult = QCBORDecode_Finish(&DC); - if(nResult != QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN) { - return -17; - } - - // --- next test ----- - IndefLen = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteArrayBad5); - - QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL); - - QCBORDecode_SetMemPool(&DC, MemPool, false); - - nResult = QCBORDecode_GetNext(&DC, &Item); - if(nResult || Item.uDataType != QCBOR_TYPE_ARRAY) { - return -18; - } - - nResult = QCBORDecode_GetNext(&DC, &Item); - if(nResult != QCBOR_ERR_BAD_BREAK) { - return -19; - } - - return 0; -} - - -static const uint8_t spIndefiniteLenString[] = { - 0x81, // Array of length one - 0x7f, // text string marked with indefinite length - 0x65, 0x73, 0x74, 0x72, 0x65, 0x61, // first segment - 0x64, 0x6d, 0x69, 0x6e, 0x67, // second segment - 0xff // ending break -}; - -static const uint8_t spIndefiniteLenStringBad2[] = { - 0x81, // Array of length one - 0x7f, // text string marked with indefinite length - 0x65, 0x73, 0x74, 0x72, 0x65, 0x61, // first segment - 0x44, 0x6d, 0x69, 0x6e, 0x67, // second segment of wrong type - 0xff // ending break -}; - -static const uint8_t spIndefiniteLenStringBad3[] = { - 0x81, // Array of length one - 0x7f, // text string marked with indefinite length - 0x01, 0x02, // Not a string - 0xff // ending break -}; - -static const uint8_t spIndefiniteLenStringBad4[] = { - 0x81, // Array of length one - 0x7f, // text string marked with indefinite length - 0x65, 0x73, 0x74, 0x72, 0x65, 0x61, // first segment - 0x64, 0x6d, 0x69, 0x6e, 0x67, // second segment - // missing end of string -}; - -static const uint8_t spIndefiniteLenStringLabel[] = { - 0xa1, // Array of length one - 0x7f, // text string marked with indefinite length - 0x65, 0x73, 0x74, 0x72, 0x75, 0x75, // first segment - 0x64, 0x6d, 0x69, 0x6e, 0x67, // second segment - 0xff, // ending break - 0x01 // integer being labeled. -}; - -static UsefulBufC MakeIndefiniteBigBstr(UsefulBuf Storage) // TODO: size this -{ - UsefulOutBuf UOB; - - UsefulOutBuf_Init(&UOB, Storage); - UsefulOutBuf_AppendByte(&UOB, 0x81); - UsefulOutBuf_AppendByte(&UOB, 0x5f); - - int i = 0; - for(int nChunkSize = 1; nChunkSize <= 128; nChunkSize *= 2) { - UsefulOutBuf_AppendByte(&UOB, 0x58); - UsefulOutBuf_AppendByte(&UOB, (uint8_t)nChunkSize); - for(int j = 0; j < nChunkSize; j++ ) { - UsefulOutBuf_AppendByte(&UOB, i); - i++; - } - } - UsefulOutBuf_AppendByte(&UOB, 0xff); - - return UsefulOutBuf_OutUBuf(&UOB); -} - -static int CheckBigString(UsefulBufC BigString) -{ - if(BigString.len != 255) { - return 1; - } - - for(uint8_t i = 0; i < 255; i++){ - if(((const uint8_t *)BigString.ptr)[i] != i) { - return 1; - } - } - return 0; -} - - -int IndefiniteLengthStringTest() -{ - QCBORDecodeContext DC; - QCBORItem Item; - // big enough for MakeIndefiniteBigBstr() + MemPool overhead - UsefulBuf_MAKE_STACK_UB(MemPool, 350); - - // --- Simple normal indefinite length string ------ - UsefulBufC IndefLen = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteLenString); - QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL); - - if(QCBORDecode_SetMemPool(&DC, MemPool, false)) { - return -1; - } - - if(QCBORDecode_GetNext(&DC, &Item)) { - return -2; - } - if(Item.uDataType != QCBOR_TYPE_ARRAY || Item.uDataAlloc) { - return -3; - } - - if(QCBORDecode_GetNext(&DC, &Item)) { - return -4; - } - if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || !Item.uDataAlloc) { - return -5; - } - if(QCBORDecode_Finish(&DC)) { - return -6; - } - - // ----- types mismatch --- - QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteLenStringBad2), QCBOR_DECODE_MODE_NORMAL); - - if(QCBORDecode_SetMemPool(&DC, MemPool, false)) { - return -7; - } - - if(QCBORDecode_GetNext(&DC, &Item)) { - return -8; - } - if(Item.uDataType != QCBOR_TYPE_ARRAY) { - return -9; - } - - if(QCBORDecode_GetNext(&DC, &Item) != QCBOR_ERR_INDEFINITE_STRING_CHUNK) { - return -10; - } - - // ----- not a string --- - QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteLenStringBad3), QCBOR_DECODE_MODE_NORMAL); - - if(QCBORDecode_SetMemPool(&DC, MemPool, false)) { - return -11; - } - - if(QCBORDecode_GetNext(&DC, &Item)) { - return -12; - } - if(Item.uDataType != QCBOR_TYPE_ARRAY) { - return -13; - } - - if(QCBORDecode_GetNext(&DC, &Item) != QCBOR_ERR_INDEFINITE_STRING_CHUNK) { - return -14; - } - - // ----- no end ----- - QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteLenStringBad4), QCBOR_DECODE_MODE_NORMAL); - - if(QCBORDecode_SetMemPool(&DC, MemPool, false)) { - return -15; - } - - if(QCBORDecode_GetNext(&DC, &Item)) { - return -16; - } - if(Item.uDataType != QCBOR_TYPE_ARRAY) { - return -17; - } - - if(QCBORDecode_GetNext(&DC, &Item) != QCBOR_ERR_HIT_END) { - return -18; - } - - // ------ Don't set a string allocator and see an error ----- - QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL); - - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_ARRAY) { - return -19; - } - - if(QCBORDecode_GetNext(&DC, &Item) != QCBOR_ERR_NO_STRING_ALLOCATOR) { - return -20; - } - - // ----- Mempool is way too small ----- - UsefulBuf_MAKE_STACK_UB(MemPoolTooSmall, 20); // 20 is too small no matter what - - QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL); - if(!QCBORDecode_SetMemPool(&DC, MemPoolTooSmall, false)) { - return -21; - } - - // ----- Mempool is way too small ----- - UsefulBuf_MAKE_STACK_UB(BigIndefBStrStorage, 290); - const UsefulBufC BigIndefBStr = MakeIndefiniteBigBstr(BigIndefBStrStorage); - - UsefulBuf_MAKE_STACK_UB(MemPoolSmall, 80); // 80 is big enough for MemPool overhead, but not BigIndefBStr - - QCBORDecode_Init(&DC, BigIndefBStr, QCBOR_DECODE_MODE_NORMAL); - if(QCBORDecode_SetMemPool(&DC, MemPoolSmall, false)) { - return -22; - } - - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_ARRAY) { - return -23; - } - if(QCBORDecode_GetNext(&DC, &Item) != QCBOR_ERR_STRING_ALLOCATE) { - return -24; - } - - // ---- big bstr ----- - QCBORDecode_Init(&DC, BigIndefBStr, QCBOR_DECODE_MODE_NORMAL); - - if(QCBORDecode_SetMemPool(&DC, MemPool, false)) { - return -25; - } - - if(QCBORDecode_GetNext(&DC, &Item)) { - return -26; - } - if(Item.uDataType != QCBOR_TYPE_ARRAY || Item.uDataAlloc) { - return -26; - } - - if(QCBORDecode_GetNext(&DC, &Item)) { - return -27; - } - if(Item.uDataType != QCBOR_TYPE_BYTE_STRING || !Item.uDataAlloc || Item.uNestingLevel != 1) { - return -28; - } - if(CheckBigString(Item.val.string)) { - return -3; - } - if(QCBORDecode_Finish(&DC)) { - return -29; - } - - // --- label is an indefinite length string ------ - QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteLenStringLabel), QCBOR_DECODE_MODE_NORMAL); - - if(QCBORDecode_SetMemPool(&DC, MemPool, false)) { - return -30; - } - - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_MAP) { - return -31; - } - - if(QCBORDecode_GetNext(&DC, &Item)){ - return -32; - } - if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || Item.uDataType != QCBOR_TYPE_INT64 || - Item.uDataAlloc || !Item.uLabelAlloc || - UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("struuming"))) { - return -33; - } - - if(QCBORDecode_Finish(&DC)) { - return -34; - } - - return 0; -} - - -int AllocAllStringsTest() -{ - QCBORDecodeContext DC; - QCBORError nCBORError; - - - // First test, use the "CSRMap" as easy input and checking - QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spCSRInput), QCBOR_DECODE_MODE_NORMAL); - - UsefulBuf_MAKE_STACK_UB(Pool, sizeof(spCSRInput) + QCBOR_DECODE_MIN_MEM_POOL_SIZE); - - nCBORError = QCBORDecode_SetMemPool(&DC, Pool, 1); // Turn on copying. - if(nCBORError) { - return -1; - } - - if(CheckCSRMaps(&DC)) { - return -2; - } - - // Next parse, save pointers to a few strings, destroy original and see all is OK. - UsefulBuf_MAKE_STACK_UB(CopyOfStorage, sizeof(pValidMapEncoded) + QCBOR_DECODE_MIN_MEM_POOL_SIZE); - const UsefulBufC CopyOf = UsefulBuf_Copy(CopyOfStorage, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded)); - - QCBORDecode_Init(&DC, CopyOf, QCBOR_DECODE_MODE_NORMAL); - UsefulBuf_Set(Pool, '/'); - QCBORDecode_SetMemPool(&DC, Pool, 1); // Turn on copying. - - QCBORItem Item1, Item2, Item3, Item4; - if((nCBORError = QCBORDecode_GetNext(&DC, &Item1))) - return nCBORError; - if(Item1.uDataType != QCBOR_TYPE_MAP || - Item1.val.uCount != 3) - return -3; - if((nCBORError = QCBORDecode_GetNext(&DC, &Item1))) - return nCBORError; - if((nCBORError = QCBORDecode_GetNext(&DC, &Item2))) - return nCBORError; - if((nCBORError = QCBORDecode_GetNext(&DC, &Item3))) - return nCBORError; - if((nCBORError = QCBORDecode_GetNext(&DC, &Item4))) - return nCBORError; - - UsefulBuf_Set(CopyOfStorage, '_'); - - if(Item1.uLabelType != QCBOR_TYPE_TEXT_STRING || - Item1.uDataType != QCBOR_TYPE_INT64 || - Item1.val.int64 != 42 || - UsefulBuf_Compare(Item1.label.string, UsefulBuf_FromSZ("first integer"))) { - return -4; - } - - - if(Item2.uLabelType != QCBOR_TYPE_TEXT_STRING || - UsefulBuf_Compare(Item2.label.string, UsefulBuf_FromSZ("an array of two strings")) || - Item2.uDataType != QCBOR_TYPE_ARRAY || - Item2.val.uCount != 2) - return -5; - - if(Item3.uDataType != QCBOR_TYPE_TEXT_STRING || - UsefulBuf_Compare(Item3.val.string, UsefulBuf_FromSZ("string1"))) { - return -6; - } - - if(Item4.uDataType != QCBOR_TYPE_TEXT_STRING || - UsefulBuf_Compare(Item4.val.string, UsefulBuf_FromSZ("string2"))) { - return -7; - } - - // Next parse with a pool that is too small - UsefulBuf_MAKE_STACK_UB(SmallPool, QCBOR_DECODE_MIN_MEM_POOL_SIZE + 1); - QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded), QCBOR_DECODE_MODE_NORMAL); - QCBORDecode_SetMemPool(&DC, SmallPool, 1); // Turn on copying. - if((nCBORError = QCBORDecode_GetNext(&DC, &Item1))) - return -8; - if(Item1.uDataType != QCBOR_TYPE_MAP || - Item1.val.uCount != 3) { - return -9; - } - if(!(nCBORError = QCBORDecode_GetNext(&DC, &Item1))){ - if(!(nCBORError = QCBORDecode_GetNext(&DC, &Item2))) { - if(!(nCBORError = QCBORDecode_GetNext(&DC, &Item3))) { - nCBORError = QCBORDecode_GetNext(&DC, &Item4); - } - } - } - if(nCBORError != QCBOR_ERR_STRING_ALLOCATE) { - return -10; - } - - return 0; -} - -// Cheating declaration to get to the special test hook -size_t MemPoolTestHook_GetPoolSize(void *ctx); - - -int MemPoolTest(void) -{ - // Set up the decoder with a tiny bit of CBOR to parse - QCBORDecodeContext DC; - const uint8_t pMinimalCBOR[] = {0xa0}; // One empty map - QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pMinimalCBOR),0); - - // Set up an memory pool of 100 bytes - UsefulBuf_MAKE_STACK_UB(Pool, 100); - QCBORError nError = QCBORDecode_SetMemPool(&DC, Pool, 0); - if(nError) { - return -9; - } - - // Cheat a little to get to the string allocator object - // so we can call it directly to test it - QCBORStringAllocator *pAlloc = (QCBORStringAllocator *)DC.pStringAllocator; - // Cheat some more to know exactly the - size_t uAvailPool = MemPoolTestHook_GetPoolSize(pAlloc); - - // First test -- ask for too much in one go - UsefulBuf Allocated = (*pAlloc->fAllocate)(pAlloc->pAllocaterContext, NULL, uAvailPool+1); - if(!UsefulBuf_IsNULL(Allocated)) { - return -1; - } - - - // Re do the set up for the next test that will do a successful alloc, - // a fail, a free and then success - // This test should work on 32 and 64-bit machines if the compiler - // does the expected thing with pointer sizes for the internal - // MemPool implementation leaving 44 or 72 bytes of pool memory. - QCBORDecode_SetMemPool(&DC, Pool, 0); - - // Cheat a little to get to the string allocator object - // so we can call it directly to test it - pAlloc = (QCBORStringAllocator *)DC.pStringAllocator; - // Cheat some more to know exactly the - uAvailPool = MemPoolTestHook_GetPoolSize(pAlloc); - - Allocated = (*pAlloc->fAllocate)(pAlloc->pAllocaterContext, NULL, uAvailPool-1); - if(UsefulBuf_IsNULL(Allocated)) { // expected to succeed - return -2; - } - UsefulBuf Allocated2 = (*pAlloc->fAllocate)(pAlloc->pAllocaterContext, NULL, uAvailPool/2); - if(!UsefulBuf_IsNULL(Allocated2)) { // expected to fail - return -3; - } - (*pAlloc->fFree)(pAlloc->pAllocaterContext, Allocated.ptr); - Allocated = (*pAlloc->fAllocate)(pAlloc->pAllocaterContext, NULL, uAvailPool/2); - if(UsefulBuf_IsNULL(Allocated)) { // succeed because of the free - return -4; - } - - - // Re do set up for next test that involves a successful alloc, - // and a successful realloc and a failed realloc - QCBORDecode_SetMemPool(&DC, Pool, 0); - - // Cheat a little to get to the string allocator object - // so we can call it directly to test it - pAlloc = (QCBORStringAllocator *)DC.pStringAllocator; - Allocated = (*pAlloc->fAllocate)(pAlloc->pAllocaterContext, NULL, uAvailPool/2); - if(UsefulBuf_IsNULL(Allocated)) { // expected to succeed - return -5; - } - Allocated2 = (*pAlloc->fAllocate)(pAlloc->pAllocaterContext, Allocated.ptr, uAvailPool); - if(UsefulBuf_IsNULL(Allocated2)) { - return -6; - } - if(Allocated2.ptr != Allocated.ptr || Allocated2.len != uAvailPool) { - return -7; - } - UsefulBuf Allocated3 = (*pAlloc->fAllocate)(pAlloc->pAllocaterContext, Allocated.ptr, uAvailPool+1); - if(!UsefulBuf_IsNULL(Allocated3)) { // expected to fail - return -8; - } - - return 0; -} - diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/qcbor_decode_tests.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/qcbor_decode_tests.h deleted file mode 100644 index cbd352e..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/qcbor_decode_tests.h +++ /dev/null @@ -1,230 +0,0 @@ -/*============================================================================== - Copyright (c) 2016-2018, The Linux Foundation. - Copyright (c) 2018-2019, Laurence Lundblade. - All rights reserved. - SPDX-License-Identifier: BSD-3-Clause - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of The Linux Foundation nor the names of its - contributors, nor the name "Laurence Lundblade" may be used to - endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS -BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ==============================================================================*/ - -#ifndef __QCBOR__qcbort_decode_tests__ -#define __QCBOR__qcbort_decode_tests__ - -#include "qcbor.h" - - -/* - Notes: - - - All the functions in qcbor.h are called once in the aggregation of all the tests below. - - - All the types that are supported are given as input and parsed by these tests - - - There is some hostile input such as invalid lengths and CBOR too complex - and types this parser doesn't handle - - */ - - - - -/* - Parse a well-known set of integers including those around the boundaries and - make sure the expected values come out - */ -int IntegerValuesParseTest(void); - - - - - -/* - Decode a simple CBOR encoded array and make sure it returns all the correct values. - This is a decode test. - */ -int SimpleArrayTest(void); - - -/* - Make sure a maximally deep array can be parsed and that the - reported nesting level is correct. This uses test vector - of CBOR encoded data with a depth of 10. This a parse test. - */ -int ParseDeepArrayTest(void); - - -/* - See that the correct error is reported when parsing - an array of depth 11, one too large. - */ -int ParseTooDeepArrayTest(void); - - -/* - Try to parse some legit CBOR types that this parsers - doesn't support. - */ -int UnsupportedCBORDecodeTest(void); - - -/* - This takes the encoded CBOR integers used in the above test and parses - it over and over with one more byte less each time. It should fail - every time on incorrect CBOR input. This is a hostile input decode test. - */ -int ShortBufferParseTest(void); - - -/* - Same as ShortBufferParseTest, but with a different encoded CBOR input. - It is another hostile input test - */ -int ShortBufferParseTest2(void); - - -/* - Parses the somewhat complicated CBOR MAP and makes sure all the correct - values parse out. About 15 values are tested. This is a decode test. - */ -int ParseMapTest(void); - - - -int FloatValuesTest1(void); - - - -int SimpleValuesTest1(void); - - -/* - - */ -int ParseMapAsArrayTest(void); - - - -int ParseSimpleTest(void); - - - -/* - Tests a number of failure cases on bad CBOR to get the right error code - */ -int FailureTests(void); - - -/* - Parses all possible inputs that are two bytes long. Main point - is that the test doesn't crash as it doesn't evaluate the - input for correctness in any way. - - (Parsing all possible 3 byte strings takes too long on all but - very fast machines). - */ -int ComprehensiveInputTest(void); - - -/* - Parses all possible inputs that are four bytes long. Main point - is that the test doesn't crash as it doesn't evaluate the - input for correctness in any way. This runs very slow, so it - is only practical as a once-in-a-while regression test on - fast machines. - */ -int BigComprehensiveInputTest(void); - - -/* - Thest the date types -- epoch and strings - */ -int DateParseTest(void); - - -/* - Test optional tags like the CBOR magic number. - */ -int OptTagParseTest(void); - - -/* - Parse some big numbers, positive and negative - */ -int BignumParseTest(void); - - -int StringDecoderModeFailTest(void); - - -/* - Parse some nested maps - */ -int NestedMapTest(void); - - -/* - Parse maps with indefinite lengths - */ -int NestedMapTestIndefLen(void); - - -/* - Parse some maps and arrays with indefinite lengths. - Includes some error cases. - */ -int IndefiniteLengthArrayMapTest(void); - - -/* - Parse indefinite length strings. Uses - MemPool. Includes error cases. - */ -int IndefiniteLengthStringTest(void); - - -/* - Test deep nesting of indefinite length - maps and arrays including too deep. - */ -int IndefiniteLengthNestTest(void); - - -/* - Test parsing strings were all strings, not - just indefinite length strings, are - allocated. Includes error test cases. - */ -int AllocAllStringsTest(void); - - -/* - Direct test of MemPool string allocator - */ -int MemPoolTest(void); - - -#endif /* defined(__QCBOR__qcbort_decode_tests__) */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/qcbor_encode_tests.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/qcbor_encode_tests.c deleted file mode 100644 index ca46460..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/qcbor_encode_tests.c +++ /dev/null @@ -1,2008 +0,0 @@ -/*============================================================================== - Copyright (c) 2016-2018, The Linux Foundation. - Copyright (c) 2018-2019, Laurence Lundblade. - All rights reserved. - SPDX-License-Identifier: BSD-3-Clause - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of The Linux Foundation nor the names of its - contributors, nor the name "Laurence Lundblade" may be used to - endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS -BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ==============================================================================*/ - -#include "qcbor.h" -#include "qcbor_encode_tests.h" - - -/* - This is the test set for CBOR encoding. - - This is largely complete for the implemented. - - A few more things to do include: - - Add a test for counting the top level items and adding it back in with AddRaw() - - Run on some different CPUs like 32-bit and maybe even 16-bit - - Test the large array count limit - - Add the CBOR diagnostic output for every expected - - */ - -//#define PRINT_FUNCTIONS_FOR_DEBUGGINGXX - -#ifdef PRINT_FUNCTIONS_FOR_DEBUGGINGXX -#include - -// ifdef these out to not have compiler warnings -static void printencoded(const uint8_t *pEncoded, size_t nLen) -{ - size_t i; - for(i = 0; i < nLen; i++) { - uint8_t Z = pEncoded[i]; - printf("%02x ", Z); - } - printf("\n"); - - fflush(stdout); -} - - -// Do the comparison and print out where it fails -static int UsefulBuf_Compare_Print(UsefulBufC U1, UsefulBufC U2) { - size_t i; - for(i = 0; i < U1.len; i++) { - if(((uint8_t *)U1.ptr)[i] != ((uint8_t *)U2.ptr)[i]) { - printf("Position: %d Actual: 0x%x Expected: 0x%x\n", i, ((uint8_t *)U1.ptr)[i], ((uint8_t *)U2.ptr)[i]); - return 1; - } - } - return 0; - -} - -#define CheckResults(Enc, Expected) \ - UsefulBuf_Compare_Print(Enc, (UsefulBufC){Expected, sizeof(Expected)}) - -#else - -#define CheckResults(Enc, Expected) \ - UsefulBuf_Compare(Enc, (UsefulBufC){Expected, sizeof(Expected)}) - -#endif - - - -// One big buffer that is used by all the tests to encode into -// Putting it in uninitialized data is better than using a lot -// of stack. The tests should run on small devices too. -static uint8_t spBigBuf[2200]; - - - -/* - Some very minimal tests. - */ -int BasicEncodeTest() -{ - // Very simple CBOR, a map with one boolean that is true in it - QCBOREncodeContext EC; - - QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); - - QCBOREncode_OpenMap(&EC); - QCBOREncode_AddBoolToMapN(&EC, 66, true); - QCBOREncode_CloseMap(&EC); - - UsefulBufC Encoded; - if(QCBOREncode_Finish(&EC, &Encoded)) { - return -1; - } - - - // Decode it and see that is right - QCBORDecodeContext DC; - QCBORItem Item; - QCBORDecode_Init(&DC, Encoded, QCBOR_DECODE_MODE_NORMAL); - - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_MAP) { - return -2; - } - - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_TRUE) { - return -3; - } - - if(QCBORDecode_Finish(&DC)) { - return -4; - } - - - // Make another encoded message with the CBOR from the previous put into this one - UsefulBuf_MAKE_STACK_UB(MemoryForEncoded2, 20); - QCBOREncode_Init(&EC, MemoryForEncoded2); - QCBOREncode_OpenArray(&EC); - QCBOREncode_AddUInt64(&EC, 451); - QCBOREncode_AddEncoded(&EC, Encoded); - QCBOREncode_OpenMap(&EC); - QCBOREncode_AddEncodedToMapN(&EC, -70000, Encoded); - QCBOREncode_CloseMap(&EC); - QCBOREncode_CloseArray(&EC); - - UsefulBufC Encoded2; - if(QCBOREncode_Finish(&EC, &Encoded2)) { - return -5; - } - /* - [ // 0 1:3 - 451, // 1 1:2 - { // 1 1:2 2:1 - 66: true // 2 1:1 - }, - { // 1 1:1 2:1 - -70000: { // 2 1:1 2:1 3:1 - 66: true // 3 XXXXXX - } - } - ] - - - - 83 # array(3) - 19 01C3 # unsigned(451) - A1 # map(1) - 18 42 # unsigned(66) - F5 # primitive(21) - A1 # map(1) - 3A 0001116F # negative(69999) - A1 # map(1) - 18 42 # unsigned(66) - F5 # primitive(21) - */ - - // Decode it and see if it is OK - QCBORDecode_Init(&DC, Encoded2, QCBOR_DECODE_MODE_NORMAL); - - // 0 1:3 - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_ARRAY || Item.val.uCount != 3) { - return -6; - } - - // 1 1:2 - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_INT64 || Item.val.uint64 != 451) { - return -7; - } - - // 1 1:2 2:1 - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_MAP || Item.val.uCount != 1) { - return -8; - } - - // 2 1:1 - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_TRUE) { - return -9; - } - - // 1 1:1 2:1 - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_MAP || Item.val.uCount != 1) { - return -10; - } - - // 2 1:1 2:1 3:1 - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_MAP || Item.val.uCount != 1 || Item.uLabelType != QCBOR_TYPE_INT64 || Item.label.int64 != -70000) { - return -11; - } - - // 3 XXXXXX - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_TRUE || Item.uLabelType != QCBOR_TYPE_INT64 || Item.label.int64 != 66) { - return -12; - } - - if(QCBORDecode_Finish(&DC)) { - return -13; - } - - return 0; -} - - - -static const uint8_t spExpectedEncodedAll[] = { - 0x98, 0x22, 0x66, 0x55, 0x49, 0x4e, 0x54, 0x36, 0x32, 0xd8, - 0x64, 0x1a, 0x05, 0x5d, 0x23, 0x15, 0x65, 0x49, 0x4e, 0x54, - 0x36, 0x34, 0xd8, 0x4c, 0x1b, 0x00, 0x00, 0x00, 0x12, 0x16, - 0xaf, 0x2b, 0x15, 0x00, 0x38, 0x2b, 0xa4, 0x63, 0x4c, 0x42, - 0x4c, 0x18, 0x4d, 0x23, 0x18, 0x58, 0x78, 0x1a, 0x4e, 0x45, - 0x47, 0x4c, 0x42, 0x4c, 0x54, 0x48, 0x41, 0x54, 0x20, 0x49, - 0x53, 0x20, 0x4b, 0x49, 0x4e, 0x44, 0x20, 0x4f, 0x46, 0x20, - 0x4c, 0x4f, 0x4e, 0x47, 0x3b, 0x00, 0x00, 0x02, 0x2d, 0x9a, - 0xc6, 0x94, 0x55, 0x3a, 0x05, 0xf5, 0xe0, 0xff, 0x3a, 0x2f, - 0xaf, 0x07, 0xff, 0xc1, 0x1a, 0x8e, 0x15, 0x1c, 0x8a, - 0xa3, 0x74, 0x4c, 0x6f, 0x6e, 0x67, 0x4c, 0x69, 0x76, 0x65, - 0x44, 0x65, 0x6e, 0x69, 0x73, 0x52, 0x69, 0x74, 0x63, 0x68, - 0x69, 0x65, 0xc1, 0x1a, 0x53, 0x72, 0x4e, 0x00, 0x66, 0x74, - 0x69, 0x6d, 0x65, 0x28, 0x29, 0xc1, 0x1a, 0x58, 0x0d, 0x41, - 0x72, 0x39, 0x07, 0xb0, 0xc1, 0x1a, 0x58, 0x0d, 0x3f, 0x76, - 0x42, 0xff, 0x00, 0xa3, 0x66, 0x62, 0x69, 0x6e, 0x62, 0x69, - 0x6e, 0xda, 0x00, 0x01, 0x86, 0xa0, 0x41, 0x00, 0x66, 0x62, - 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x43, 0x01, 0x02, 0x03, 0x00, - 0x44, 0x04, 0x02, 0x03, 0xfe, 0x6f, 0x62, 0x61, 0x72, 0x20, - 0x62, 0x61, 0x72, 0x20, 0x66, 0x6f, 0x6f, 0x20, 0x62, 0x61, - 0x72, 0x64, 0x6f, 0x6f, 0x66, 0x0a, 0xd8, 0x20, 0x78, 0x6b, - 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x73, 0x74, 0x61, - 0x63, 0x6b, 0x6f, 0x76, 0x65, 0x72, 0x66, 0x6c, 0x6f, 0x77, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x32, 0x38, 0x30, 0x35, 0x39, - 0x36, 0x39, 0x37, 0x2f, 0x68, 0x6f, 0x77, 0x2d, 0x64, 0x6f, - 0x2d, 0x69, 0x2d, 0x74, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x2d, - 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x2d, 0x64, 0x65, - 0x62, 0x75, 0x67, 0x2d, 0x61, 0x6e, 0x64, 0x2d, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2d, 0x62, 0x75, 0x69, 0x6c, - 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x2d, 0x78, 0x63, 0x6f, 0x64, - 0x65, 0x2d, 0x36, 0x2d, 0x37, 0x2d, 0x38, 0xd8, 0x22, 0x78, - 0x1c, 0x59, 0x57, 0x35, 0x35, 0x49, 0x47, 0x4e, 0x68, 0x63, - 0x6d, 0x35, 0x68, 0x62, 0x43, 0x42, 0x77, 0x62, 0x47, 0x56, - 0x68, 0x63, 0x33, 0x56, 0x79, 0x5a, 0x51, 0x3d, 0x3d, 0xd8, - 0x23, 0x67, 0x5b, 0x5e, 0x61, 0x62, 0x63, 0x5d, 0x2b, 0xd8, - 0x24, 0x79, 0x01, 0x57, 0x4d, 0x49, 0x4d, 0x45, 0x2d, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x2e, - 0x30, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, - 0x54, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x6d, 0x75, 0x6c, 0x74, - 0x69, 0x70, 0x61, 0x72, 0x74, 0x2f, 0x6d, 0x69, 0x78, 0x65, - 0x64, 0x3b, 0x0a, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, - 0x79, 0x3d, 0x22, 0x58, 0x58, 0x58, 0x58, 0x62, 0x6f, 0x75, - 0x6e, 0x64, 0x61, 0x72, 0x79, 0x20, 0x74, 0x65, 0x78, 0x74, - 0x22, 0x0a, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, - 0x20, 0x61, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, - 0x72, 0x74, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x20, 0x69, 0x6e, 0x20, 0x4d, 0x49, 0x4d, 0x45, 0x20, 0x66, - 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x2e, 0x0a, 0x0a, 0x2d, 0x2d, - 0x58, 0x58, 0x58, 0x58, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, - 0x72, 0x79, 0x20, 0x74, 0x65, 0x78, 0x74, 0x0a, 0x43, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, 0x70, 0x65, - 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, 0x61, - 0x69, 0x6e, 0x0a, 0x0a, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, - 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6f, 0x64, 0x79, - 0x20, 0x74, 0x65, 0x78, 0x74, 0x0a, 0x0a, 0x2d, 0x2d, 0x58, - 0x58, 0x58, 0x58, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, - 0x79, 0x20, 0x74, 0x65, 0x78, 0x74, 0x0a, 0x43, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, 0x70, 0x65, 0x3a, - 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, 0x61, 0x69, - 0x6e, 0x3b, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x2d, 0x44, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x3a, 0x20, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, - 0x6d, 0x65, 0x6e, 0x74, 0x3b, 0x0a, 0x66, 0x69, 0x6c, 0x65, - 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x65, 0x73, 0x74, - 0x2e, 0x74, 0x78, 0x74, 0x22, 0x0a, 0x0a, 0x74, 0x68, 0x69, - 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, - 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x20, - 0x74, 0x65, 0x78, 0x74, 0x0a, 0x0a, 0x2d, 0x2d, 0x58, 0x58, - 0x58, 0x58, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, - 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x2d, 0xae, 0x65, 0x23, - 0x23, 0x23, 0x23, 0x23, 0x6f, 0x66, 0x6f, 0x6f, 0x20, 0x62, - 0x61, 0x72, 0x20, 0x66, 0x6f, 0x6f, 0x20, 0x66, 0x6f, 0x6f, - 0x64, 0x5f, 0x5f, 0x5f, 0x5f, 0x67, 0x66, 0x6f, 0x6f, 0x20, - 0x62, 0x61, 0x72, 0x66, 0x28, 0x29, 0x28, 0x29, 0x28, 0x29, - 0xd9, 0x03, 0xe8, 0x6b, 0x72, 0x61, 0x62, 0x20, 0x72, 0x61, - 0x62, 0x20, 0x6f, 0x6f, 0x66, 0x16, 0x6f, 0x66, 0x6f, 0x6f, - 0x20, 0x66, 0x6f, 0x6f, 0x20, 0x66, 0x6f, 0x6f, 0x20, 0x66, - 0x6f, 0x6f, 0x62, 0x5e, 0x5e, 0x69, 0x6f, 0x6f, 0x6f, 0x6f, - 0x6f, 0x6f, 0x6f, 0x6f, 0x66, 0x18, 0x63, 0x6d, 0x66, 0x66, - 0x66, 0x66, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, - 0x66, 0x63, 0x52, 0x46, 0x43, 0xd8, 0x20, 0x78, 0x31, 0x68, - 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x74, 0x6f, 0x6f, - 0x6c, 0x73, 0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e, 0x6f, 0x72, - 0x67, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x2f, 0x72, 0x66, 0x63, - 0x37, 0x30, 0x34, 0x39, 0x23, 0x73, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x2d, 0x32, 0x2e, 0x34, 0x2e, 0x35, 0x18, 0x89, - 0xd8, 0x20, 0x6f, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, - 0x63, 0x62, 0x6f, 0x72, 0x2e, 0x6d, 0x65, 0x2f, 0x68, 0x77, - 0x68, 0x65, 0x6e, 0x69, 0x6d, 0x36, 0x34, 0xd8, 0x22, 0x6c, - 0x63, 0x47, 0x78, 0x6c, 0x59, 0x58, 0x4e, 0x31, 0x63, 0x6d, - 0x55, 0x75, 0x18, 0x40, 0xd8, 0x22, 0x68, 0x63, 0x33, 0x56, - 0x79, 0x5a, 0x53, 0x34, 0x3d, 0x64, 0x70, 0x6f, 0x70, 0x6f, - 0xd8, 0x23, 0x68, 0x31, 0x30, 0x30, 0x5c, 0x73, 0x2a, 0x6d, - 0x6b, 0x38, 0x32, 0xd8, 0x23, 0x66, 0x70, 0x65, 0x72, 0x6c, - 0x5c, 0x42, 0x63, 0x4e, 0x65, 0x64, 0xd8, 0x24, 0x79, 0x01, - 0x57, 0x4d, 0x49, 0x4d, 0x45, 0x2d, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x2e, 0x30, 0x0a, 0x43, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, 0x70, - 0x65, 0x3a, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, - 0x72, 0x74, 0x2f, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x3b, 0x0a, - 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x3d, 0x22, - 0x58, 0x58, 0x58, 0x58, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, - 0x72, 0x79, 0x20, 0x74, 0x65, 0x78, 0x74, 0x22, 0x0a, 0x0a, - 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, - 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74, 0x20, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x69, 0x6e, - 0x20, 0x4d, 0x49, 0x4d, 0x45, 0x20, 0x66, 0x6f, 0x72, 0x6d, - 0x61, 0x74, 0x2e, 0x0a, 0x0a, 0x2d, 0x2d, 0x58, 0x58, 0x58, - 0x58, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x20, - 0x74, 0x65, 0x78, 0x74, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x2d, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, - 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x0a, - 0x0a, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x74, 0x65, - 0x78, 0x74, 0x0a, 0x0a, 0x2d, 0x2d, 0x58, 0x58, 0x58, 0x58, - 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x20, 0x74, - 0x65, 0x78, 0x74, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x2d, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, - 0x78, 0x74, 0x2f, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x3b, 0x0a, - 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x44, 0x69, - 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, - 0x20, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, - 0x74, 0x3b, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, - 0x65, 0x3d, 0x22, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74, 0x78, - 0x74, 0x22, 0x0a, 0x0a, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, - 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x74, 0x74, 0x61, - 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x65, 0x78, - 0x74, 0x0a, 0x0a, 0x2d, 0x2d, 0x58, 0x58, 0x58, 0x58, 0x62, - 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x20, 0x74, 0x65, - 0x78, 0x74, 0x2d, 0x2d, 0x0a, 0xd8, 0x24, 0x79, 0x01, 0x57, - 0x4d, 0x49, 0x4d, 0x45, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x2e, 0x30, 0x0a, 0x43, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, 0x70, 0x65, - 0x3a, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, - 0x74, 0x2f, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x3b, 0x0a, 0x62, - 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x3d, 0x22, 0x58, - 0x58, 0x58, 0x58, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, - 0x79, 0x20, 0x74, 0x65, 0x78, 0x74, 0x22, 0x0a, 0x0a, 0x54, - 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x6d, - 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x69, 0x6e, 0x20, - 0x4d, 0x49, 0x4d, 0x45, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, - 0x74, 0x2e, 0x0a, 0x0a, 0x2d, 0x2d, 0x58, 0x58, 0x58, 0x58, - 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x20, 0x74, - 0x65, 0x78, 0x74, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x2d, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, - 0x78, 0x74, 0x2f, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x0a, 0x0a, - 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x74, 0x65, 0x78, - 0x74, 0x0a, 0x0a, 0x2d, 0x2d, 0x58, 0x58, 0x58, 0x58, 0x62, - 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x20, 0x74, 0x65, - 0x78, 0x74, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x2d, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, - 0x74, 0x2f, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x3b, 0x0a, 0x43, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x44, 0x69, 0x73, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, - 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, - 0x3b, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, - 0x3d, 0x22, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74, 0x78, 0x74, - 0x22, 0x0a, 0x0a, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x74, 0x74, 0x61, 0x63, - 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x65, 0x78, 0x74, - 0x0a, 0x0a, 0x2d, 0x2d, 0x58, 0x58, 0x58, 0x58, 0x62, 0x6f, - 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x20, 0x74, 0x65, 0x78, - 0x74, 0x2d, 0x2d, 0xc0, 0x74, 0x32, 0x30, 0x30, 0x33, 0x2d, - 0x31, 0x32, 0x2d, 0x31, 0x33, 0x54, 0x31, 0x38, 0x3a, 0x33, - 0x30, 0x3a, 0x30, 0x32, 0x5a, 0xa2, 0x68, 0x42, 0x65, 0x64, - 0x20, 0x74, 0x69, 0x6d, 0x65, 0xc0, 0x78, 0x1c, 0x32, 0x30, - 0x30, 0x33, 0x2d, 0x31, 0x32, 0x2d, 0x31, 0x33, 0x54, 0x31, - 0x38, 0x3a, 0x33, 0x30, 0x3a, 0x30, 0x32, 0x2e, 0x32, 0x35, - 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0x18, 0x58, 0xc0, 0x78, - 0x1c, 0x32, 0x30, 0x30, 0x33, 0x2d, 0x31, 0x32, 0x2d, 0x31, - 0x33, 0x54, 0x31, 0x38, 0x3a, 0x33, 0x30, 0x3a, 0x30, 0x32, - 0x2e, 0x32, 0x35, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0xf7, - 0xa3, 0x64, 0x64, 0x61, 0x72, 0x65, 0xd8, 0x42, 0xf5, 0x62, - 0x75, 0x75, 0xf4, 0x1a, 0x00, 0x0b, 0x41, 0x62, 0xf6, 0x80, - 0xa3, 0x78, 0x1c, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x20, 0x61, - 0x6e, 0x64, 0x20, 0x74, 0x61, 0x67, 0x67, 0x65, 0x64, 0x20, - 0x65, 0x6d, 0x70, 0x74, 0x79, 0x20, 0x61, 0x72, 0x72, 0x61, - 0x79, 0xd9, 0x04, 0x45, 0x80, 0x65, 0x61, 0x6c, 0x61, 0x62, - 0x6c, 0x80, 0x18, 0x2a, 0x80, 0xa1, 0x68, 0x69, 0x6e, 0x20, - 0x61, 0x20, 0x6d, 0x61, 0x70, 0xa1, 0x19, 0x15, 0xb4, 0xa1, - 0x6e, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x69, 0x6e, 0x20, 0x61, - 0x20, 0x69, 0x6e, 0x20, 0x61, 0xd9, 0x23, 0x7f, 0xa0, 0xa5, - 0x62, 0x73, 0x31, 0xd8, 0x58, 0xf8, 0xff, 0x62, 0x73, 0x32, - 0xe0, 0x62, 0x73, 0x33, 0xd8, 0x58, 0xf8, 0x21, 0x1a, 0x05, - 0x44, 0x8c, 0x06, 0xd8, 0x58, 0xf8, 0xff, 0x18, 0x59, 0xd8, - 0x58, 0xf3, 0xd8, 0x25, 0x50, 0x53, 0x4d, 0x41, 0x52, 0x54, - 0x43, 0x53, 0x4c, 0x54, 0x54, 0x43, 0x46, 0x49, 0x43, 0x41, - 0x32, 0xa2, 0x64, 0x55, 0x55, 0x55, 0x55, 0xd8, 0x25, 0x50, - 0x53, 0x4d, 0x41, 0x52, 0x54, 0x43, 0x53, 0x4c, 0x54, 0x54, - 0x43, 0x46, 0x49, 0x43, 0x41, 0x32, 0x18, 0x63, 0xd8, 0x25, - 0x50, 0x53, 0x4d, 0x41, 0x52, 0x54, 0x43, 0x53, 0x4c, 0x54, - 0x54, 0x43, 0x46, 0x49, 0x43, 0x41, 0x32, 0xf5, 0xf4, 0xa2, - 0x71, 0x47, 0x65, 0x6f, 0x72, 0x67, 0x65, 0x20, 0x69, 0x73, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0xf5, 0x19, - 0x10, 0x41, 0xf5, 0xC2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xC3, 0x49, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0x63, 0x42, 0x4E, 0x2B, - 0xC2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x18, 0x40, 0xC2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x63, 0x42, 0x4E, 0x2D, 0xC3, 0x49, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, - 0x3F, 0xC3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 -}; - - -static const char *szMIME = "\ -MIME-Version: 1.0\n\ -Content-Type: multipart/mixed;\n\ -boundary=\"XXXXboundary text\"\n\ -\n\ -This is a multipart message in MIME format.\n\ -\n\ ---XXXXboundary text\n\ -Content-Type: text/plain\n\ -\n\ -this is the body text\n\ -\n\ ---XXXXboundary text\n\ -Content-Type: text/plain;\n\ -Content-Disposition: attachment;\n\ -filename=\"test.txt\"\n\ -\n\ -this is the attachment text\n\ -\n\ ---XXXXboundary text--"; - - -int AllAddMethodsTest() -{ - // TODO: this test should be broken down into several so it is more managable. Tags and labels could be more sensible - QCBOREncodeContext ECtx; - int nReturn = 0; - - QCBOREncode_Init(&ECtx, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); - - QCBOREncode_OpenArray(&ECtx); - - // Some ints that are tagged and have strings preceeding them (not labels becase it is not a map) - QCBOREncode_AddSZString(&ECtx, "UINT62"); - QCBOREncode_AddTag(&ECtx, 100); - QCBOREncode_AddUInt64(&ECtx, 89989909); - QCBOREncode_AddSZString(&ECtx, "INT64"); - QCBOREncode_AddTag(&ECtx, 76); - QCBOREncode_AddInt64(&ECtx, 77689989909); - QCBOREncode_AddUInt64(&ECtx,0); - QCBOREncode_AddInt64(&ECtx, -44); - - // ints that go in maps - QCBOREncode_OpenMap(&ECtx); - QCBOREncode_AddUInt64ToMap(&ECtx, "LBL", 77); - QCBOREncode_AddUInt64ToMapN(&ECtx, -4, 88); - QCBOREncode_AddInt64ToMap(&ECtx, "NEGLBLTHAT IS KIND OF LONG", -2394893489238); - QCBOREncode_AddInt64ToMapN(&ECtx, -100000000, -800000000); - QCBOREncode_CloseMap(&ECtx); - - // Epoch Date - QCBOREncode_AddDateEpoch(&ECtx, 2383748234); - - // Epoch date with labels - QCBOREncode_OpenMap(&ECtx); - QCBOREncode_AddDateEpochToMap(&ECtx, "LongLiveDenisRitchie", 1400000000); - QCBOREncode_AddDateEpochToMap(&ECtx, "time()", 1477263730); - QCBOREncode_AddDateEpochToMapN(&ECtx, -1969, 1477263222); - QCBOREncode_CloseMap(&ECtx); - - // Binary blobs - QCBOREncode_AddBytes(&ECtx, ((UsefulBufC) {(uint8_t []){0xff, 0x00}, 2})); - - // binary blobs in maps - QCBOREncode_OpenMap(&ECtx); - QCBOREncode_AddSZString(&ECtx, "binbin"); - QCBOREncode_AddTag(&ECtx, 100000); - QCBOREncode_AddBytes(&ECtx, ((UsefulBufC) {(uint8_t []){0x00}, 1})); - QCBOREncode_AddBytesToMap(&ECtx, "blabel", ((UsefulBufC) {(uint8_t []){0x01, 0x02, 0x03}, 3})); - QCBOREncode_AddBytesToMapN(&ECtx, 0, ((UsefulBufC){(uint8_t []){0x04, 0x02, 0x03, 0xfe}, 4})); - QCBOREncode_CloseMap(&ECtx); - - // text blobs - QCBOREncode_AddText(&ECtx, UsefulBuf_FROM_SZ_LITERAL("bar bar foo bar")); - QCBOREncode_AddSZString(&ECtx, "oof\n"); - QCBOREncode_AddURI(&ECtx, UsefulBuf_FROM_SZ_LITERAL("http://stackoverflow.com/questions/28059697/how-do-i-toggle-between-debug-and-release-builds-in-xcode-6-7-8")); - QCBOREncode_AddB64Text(&ECtx, UsefulBuf_FROM_SZ_LITERAL("YW55IGNhcm5hbCBwbGVhc3VyZQ==")); - QCBOREncode_AddRegex(&ECtx, UsefulBuf_FROM_SZ_LITERAL("[^abc]+")); - QCBOREncode_AddMIMEData(&ECtx, UsefulBuf_FromSZ(szMIME)); - - // text blobs in maps - QCBOREncode_OpenMap(&ECtx); - QCBOREncode_AddTextToMap(&ECtx, "#####", UsefulBuf_FROM_SZ_LITERAL("foo bar foo foo")); - QCBOREncode_AddTextToMap(&ECtx, "____", UsefulBuf_FROM_SZ_LITERAL("foo bar")); - QCBOREncode_AddSZString(&ECtx, "()()()"); - QCBOREncode_AddTag(&ECtx, 1000); - QCBOREncode_AddSZString(&ECtx, "rab rab oof"); - QCBOREncode_AddTextToMapN(&ECtx,22, UsefulBuf_FROM_SZ_LITERAL("foo foo foo foo")); - QCBOREncode_AddSZStringToMap(&ECtx, "^^", "oooooooof"); - QCBOREncode_AddSZStringToMapN(&ECtx, 99, "ffffoooooooof"); - QCBOREncode_AddURIToMap(&ECtx, "RFC", UsefulBuf_FROM_SZ_LITERAL("https://tools.ietf.org/html/rfc7049#section-2.4.5")); - QCBOREncode_AddURIToMapN(&ECtx, 0x89, UsefulBuf_FROM_SZ_LITERAL("http://cbor.me/")); - QCBOREncode_AddB64TextToMap(&ECtx, "whenim64", UsefulBuf_FROM_SZ_LITERAL("cGxlYXN1cmUu")); - QCBOREncode_AddB64TextToMapN(&ECtx, 64, UsefulBuf_FROM_SZ_LITERAL("c3VyZS4=")); - QCBOREncode_AddRegexToMap(&ECtx, "popo", UsefulBuf_FROM_SZ_LITERAL("100\\s*mk")); // x code string literal bug - QCBOREncode_AddRegexToMapN(&ECtx, -51, UsefulBuf_FROM_SZ_LITERAL("perl\\B")); // x code string literal bug - QCBOREncode_AddMIMEDataToMap(&ECtx, "Ned", UsefulBuf_FromSZ(szMIME)); - QCBOREncode_AddMIMEDataToMapN(&ECtx, 10, UsefulBuf_FromSZ(szMIME)); - QCBOREncode_CloseMap(&ECtx); - - // Date strings - QCBOREncode_AddDateString(&ECtx, "2003-12-13T18:30:02Z"); - QCBOREncode_OpenMap(&ECtx); - QCBOREncode_AddDateStringToMap(&ECtx, "Bed time", "2003-12-13T18:30:02.25+01:00"); - QCBOREncode_AddDateStringToMapN(&ECtx, 88, "2003-12-13T18:30:02.25+01:00"); - QCBOREncode_CloseMap(&ECtx); - - // true / false ... - QCBOREncode_AddSimple(&ECtx, CBOR_SIMPLEV_UNDEF); - QCBOREncode_OpenMap(&ECtx); - QCBOREncode_AddSZString(&ECtx, "dare"); - QCBOREncode_AddTag(&ECtx, 66); - QCBOREncode_AddBool(&ECtx, true); - QCBOREncode_AddBoolToMap(&ECtx, "uu", false); - QCBOREncode_AddSimpleToMapN(&ECtx, 737634, CBOR_SIMPLEV_NULL); - QCBOREncode_CloseMap(&ECtx); - - // opening an array - QCBOREncode_OpenArray(&ECtx); - QCBOREncode_CloseArray(&ECtx); - - // opening arrays in a map - QCBOREncode_OpenMap(&ECtx); - QCBOREncode_AddSZString(&ECtx, "label and tagged empty array"); - QCBOREncode_AddTag(&ECtx, 1093); - QCBOREncode_OpenArray(&ECtx); - QCBOREncode_CloseArray(&ECtx); - QCBOREncode_OpenArrayInMap(&ECtx, "alabl"); - QCBOREncode_CloseArray(&ECtx); - QCBOREncode_OpenArrayInMapN(&ECtx, 42); - QCBOREncode_CloseArray(&ECtx); - QCBOREncode_CloseMap(&ECtx); - - // opening maps with labels and tagging - QCBOREncode_OpenMap(&ECtx); - QCBOREncode_OpenMapInMap(&ECtx, "in a map"); - QCBOREncode_OpenMapInMapN(&ECtx, 5556); - QCBOREncode_AddSZString(&ECtx, "in a in a in a"); - QCBOREncode_AddTag(&ECtx, 9087); - QCBOREncode_OpenMap(&ECtx); - QCBOREncode_CloseMap(&ECtx); - QCBOREncode_CloseMap(&ECtx); - QCBOREncode_CloseMap(&ECtx); - QCBOREncode_CloseMap(&ECtx); - - - // Extended simple values (these are not standard...) - QCBOREncode_OpenMap(&ECtx); - QCBOREncode_AddSZString(&ECtx, "s1"); - QCBOREncode_AddTag(&ECtx, 88); - QCBOREncode_AddSimple(&ECtx, 255); - QCBOREncode_AddSimpleToMap(&ECtx, "s2", 0); - QCBOREncode_AddSZString(&ECtx, "s3"); - QCBOREncode_AddTag(&ECtx, 88); - QCBOREncode_AddSimple(&ECtx, 33); - QCBOREncode_AddInt64(&ECtx, 88378374); // label before tag - QCBOREncode_AddTag(&ECtx, 88); - QCBOREncode_AddSimple(&ECtx, 255); - QCBOREncode_AddInt64(&ECtx, 89); // label before tag - QCBOREncode_AddTag(&ECtx, 88); - QCBOREncode_AddSimple(&ECtx, 19); - QCBOREncode_CloseMap(&ECtx); - - // UUIDs - static const uint8_t ppppUUID[] = {0x53, 0x4D, 0x41, 0x52, 0x54, 0x43, 0x53, 0x4C, 0x54, 0x54, 0x43, 0x46, 0x49, 0x43, 0x41, 0x32}; - const UsefulBufC XXUUID = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(ppppUUID); - QCBOREncode_AddBinaryUUID(&ECtx, XXUUID); - QCBOREncode_OpenMap(&ECtx); - QCBOREncode_AddBinaryUUIDToMap(&ECtx, "UUUU", XXUUID); - QCBOREncode_AddBinaryUUIDToMapN(&ECtx, 99, XXUUID); - QCBOREncode_CloseMap(&ECtx); - - // Bool - QCBOREncode_AddBool(&ECtx, true); - QCBOREncode_AddBool(&ECtx, false); - QCBOREncode_OpenMap(&ECtx); - QCBOREncode_AddBoolToMap(&ECtx, "George is the man", true); - QCBOREncode_AddBoolToMapN(&ECtx, 010101, true); - QCBOREncode_CloseMap(&ECtx); - - - static const uint8_t pBignum[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - const UsefulBufC BIGNUM = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBignum); - QCBOREncode_AddPositiveBignum(&ECtx, BIGNUM); - QCBOREncode_AddNegativeBignum(&ECtx, BIGNUM); - QCBOREncode_OpenMap(&ECtx); - QCBOREncode_AddPositiveBignumToMap(&ECtx, "BN+", BIGNUM); - QCBOREncode_AddPositiveBignumToMapN(&ECtx, 64, BIGNUM); - QCBOREncode_AddNegativeBignumToMap(&ECtx, "BN-", BIGNUM); - QCBOREncode_AddNegativeBignumToMapN(&ECtx, -64, BIGNUM); - QCBOREncode_CloseMap(&ECtx); - - QCBOREncode_CloseArray(&ECtx); - - UsefulBufC Enc; - - if(QCBOREncode_Finish(&ECtx, &Enc)) { - nReturn = -1; - goto Done; - } - - if(CheckResults(Enc, spExpectedEncodedAll)) - nReturn = -2; - -Done: - return nReturn; -} - -/* - 98 2F # array(47) - 3B 7FFFFFFFFFFFFFFF # negative(9223372036854775807) - 3B 0000000100000000 # negative(4294967296) - 3A FFFFFFFF # negative(4294967295) - 3A FFFFFFFE # negative(4294967294) - 3A FFFFFFFD # negative(4294967293) - 3A 7FFFFFFF # negative(2147483647) - 3A 7FFFFFFE # negative(2147483646) - 3A 00010001 # negative(65537) - 3A 00010000 # negative(65536) - 39 FFFF # negative(65535) - 39 FFFE # negative(65534) - 39 FFFD # negative(65533) - 39 0100 # negative(256) - 38 FF # negative(255) - 38 FE # negative(254) - 38 FD # negative(253) - 38 18 # negative(24) - 37 # negative(23) - 36 # negative(22) - 20 # negative(0) - 00 # unsigned(0) - 00 # unsigned(0) - 01 # unsigned(1) - 16 # unsigned(22) - 17 # unsigned(23) - 18 18 # unsigned(24) - 18 19 # unsigned(25) - 18 1A # unsigned(26) - 18 FE # unsigned(254) - 18 FF # unsigned(255) - 19 0100 # unsigned(256) - 19 0101 # unsigned(257) - 19 FFFE # unsigned(65534) - 19 FFFF # unsigned(65535) - 1A 00010000 # unsigned(65536) - 1A 00010001 # unsigned(65537) - 1A 00010002 # unsigned(65538) - 1A 7FFFFFFF # unsigned(2147483647) - 1A 7FFFFFFF # unsigned(2147483647) - 1A 80000000 # unsigned(2147483648) - 1A 80000001 # unsigned(2147483649) - 1A FFFFFFFE # unsigned(4294967294) - 1A FFFFFFFF # unsigned(4294967295) - 1B 0000000100000000 # unsigned(4294967296) - 1B 0000000100000001 # unsigned(4294967297) - 1B 7FFFFFFFFFFFFFFF # unsigned(9223372036854775807) - 1B FFFFFFFFFFFFFFFF # unsigned(18446744073709551615) - */ -static const uint8_t spExpectedEncodedInts[] = { - 0x98, 0x2f, 0x3b, 0x7f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x3b, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x3a, 0xff, 0xff, 0xff, - 0xff, 0x3a, 0xff, 0xff, 0xff, 0xfe, 0x3a, 0xff, - 0xff, 0xff, 0xfd, 0x3a, 0x7f, 0xff, 0xff, 0xff, - 0x3a, 0x7f, 0xff, 0xff, 0xfe, 0x3a, 0x00, 0x01, - 0x00, 0x01, 0x3a, 0x00, 0x01, 0x00, 0x00, 0x39, - 0xff, 0xff, 0x39, 0xff, 0xfe, 0x39, 0xff, 0xfd, - 0x39, 0x01, 0x00, 0x38, 0xff, 0x38, 0xfe, 0x38, - 0xfd, 0x38, 0x18, 0x37, 0x36, 0x20, 0x00, 0x00, - 0x01, 0x16, 0x17, 0x18, 0x18, 0x18, 0x19, 0x18, - 0x1a, 0x18, 0xfe, 0x18, 0xff, 0x19, 0x01, 0x00, - 0x19, 0x01, 0x01, 0x19, 0xff, 0xfe, 0x19, 0xff, - 0xff, 0x1a, 0x00, 0x01, 0x00, 0x00, 0x1a, 0x00, - 0x01, 0x00, 0x01, 0x1a, 0x00, 0x01, 0x00, 0x02, - 0x1a, 0x7f, 0xff, 0xff, 0xff, 0x1a, 0x7f, 0xff, - 0xff, 0xff, 0x1a, 0x80, 0x00, 0x00, 0x00, 0x1a, - 0x80, 0x00, 0x00, 0x01, 0x1a, 0xff, 0xff, 0xff, - 0xfe, 0x1a, 0xff, 0xff, 0xff, 0xff, 0x1b, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1b, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, - 0x1b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff}; - -/* - - Test the generation of integers. This also ends up testing - encoding of all the different lengths. It encodes integers - of many lengths and values, especially around the boundaries - for different types of integers. It compares the output - to expected values generated from http://cbor.me. - - */ -int IntegerValuesTest1() -{ - QCBOREncodeContext ECtx; - int nReturn = 0; - - QCBOREncode_Init(&ECtx, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); - QCBOREncode_OpenArray(&ECtx); - - QCBOREncode_AddInt64(&ECtx, -9223372036854775807LL - 1); - QCBOREncode_AddInt64(&ECtx, -4294967297); - QCBOREncode_AddInt64(&ECtx, -4294967296); - QCBOREncode_AddInt64(&ECtx, -4294967295); - QCBOREncode_AddInt64(&ECtx, -4294967294); - QCBOREncode_AddInt64(&ECtx, -2147483648); - QCBOREncode_AddInt64(&ECtx, -2147483647); - QCBOREncode_AddInt64(&ECtx, -65538); - QCBOREncode_AddInt64(&ECtx, -65537); - QCBOREncode_AddInt64(&ECtx, -65536); - QCBOREncode_AddInt64(&ECtx, -65535); - QCBOREncode_AddInt64(&ECtx, -65534); - QCBOREncode_AddInt64(&ECtx, -257); - QCBOREncode_AddInt64(&ECtx, -256); - QCBOREncode_AddInt64(&ECtx, -255); - QCBOREncode_AddInt64(&ECtx, -254); - QCBOREncode_AddInt64(&ECtx, -25); - QCBOREncode_AddInt64(&ECtx, -24); - QCBOREncode_AddInt64(&ECtx, -23); - QCBOREncode_AddInt64(&ECtx, -1); - QCBOREncode_AddInt64(&ECtx, 0); - QCBOREncode_AddUInt64(&ECtx, 0ULL); - QCBOREncode_AddInt64(&ECtx, 1); - QCBOREncode_AddInt64(&ECtx, 22); - QCBOREncode_AddInt64(&ECtx, 23); - QCBOREncode_AddInt64(&ECtx, 24); - QCBOREncode_AddInt64(&ECtx, 25); - QCBOREncode_AddInt64(&ECtx, 26); - QCBOREncode_AddInt64(&ECtx, 254); - QCBOREncode_AddInt64(&ECtx, 255); - QCBOREncode_AddInt64(&ECtx, 256); - QCBOREncode_AddInt64(&ECtx, 257); - QCBOREncode_AddInt64(&ECtx, 65534); - QCBOREncode_AddInt64(&ECtx, 65535); - QCBOREncode_AddInt64(&ECtx, 65536); - QCBOREncode_AddInt64(&ECtx, 65537); - QCBOREncode_AddInt64(&ECtx, 65538); - QCBOREncode_AddInt64(&ECtx, 2147483647); - QCBOREncode_AddInt64(&ECtx, 2147483647); - QCBOREncode_AddInt64(&ECtx, 2147483648); - QCBOREncode_AddInt64(&ECtx, 2147483649); - QCBOREncode_AddInt64(&ECtx, 4294967294); - QCBOREncode_AddInt64(&ECtx, 4294967295); - QCBOREncode_AddInt64(&ECtx, 4294967296); - QCBOREncode_AddInt64(&ECtx, 4294967297); - QCBOREncode_AddInt64(&ECtx, 9223372036854775807LL); - QCBOREncode_AddUInt64(&ECtx, 18446744073709551615ULL); - - QCBOREncode_CloseArray(&ECtx); - - UsefulBufC Enc; - if(QCBOREncode_Finish(&ECtx, &Enc)) { - nReturn = -1; - } - - if(CheckResults(Enc, spExpectedEncodedInts)) - return -2; - - return(nReturn); -} - - -/* - 85 # array(5) - F5 # primitive(21) - F4 # primitive(20) - F6 # primitive(22) - F7 # primitive(23) - A1 # map(1) - 65 # text(5) - 554E446566 # "UNDef" - F7 # primitive(23) - */ -static const uint8_t spExpectedEncodedSimple[] = { - 0x85, 0xf5, 0xf4, 0xf6, 0xf7, 0xa1, 0x65, 0x55, 0x4e, 0x44, 0x65, 0x66, 0xf7}; - -int SimpleValuesTest1() -{ - QCBOREncodeContext ECtx; - int nReturn = 0; - - QCBOREncode_Init(&ECtx, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); - QCBOREncode_OpenArray(&ECtx); - - QCBOREncode_AddSimple(&ECtx, CBOR_SIMPLEV_TRUE); - QCBOREncode_AddSimple(&ECtx, CBOR_SIMPLEV_FALSE); - QCBOREncode_AddSimple(&ECtx, CBOR_SIMPLEV_NULL); - QCBOREncode_AddSimple(&ECtx, CBOR_SIMPLEV_UNDEF); - - QCBOREncode_OpenMap(&ECtx); - - QCBOREncode_AddSimpleToMap(&ECtx, "UNDef", CBOR_SIMPLEV_UNDEF); - QCBOREncode_CloseMap(&ECtx); - - QCBOREncode_CloseArray(&ECtx); - - UsefulBufC ECBOR; - if(QCBOREncode_Finish(&ECtx, &ECBOR)) { - nReturn = -1; - } - - if(CheckResults(ECBOR, spExpectedEncodedSimple)) - return -2; - - return(nReturn); -} - - -/* - 83 # array(3) - C0 # tag(0) - 74 # text(20) - 323031332D30332D32315432303A30343A30305A # "2013-03-21T20:04:00Z" - C1 # tag(1) - 1A 514B67B0 # unsigned(1363896240) - A2 # map(2) - 78 19 # text(25) - 53616D706C6520446174652066726F6D205246432033333339 # "Sample Date from RFC 3339" - C0 # tag(0) - 77 # text(23) - 313938352D30342D31325432333A32303A35302E35325A # "1985-04-12T23:20:50.52Z" - 62 # text(2) - 5344 # "SD" - C1 # tag(1) - 19 03E7 # unsigned(999) - */ -static const uint8_t spExpectedEncodedDates[] = { - 0x83, 0xc0, 0x74, 0x32, 0x30, 0x31, 0x33, 0x2d, 0x30, 0x33, - 0x2d, 0x32, 0x31, 0x54, 0x32, 0x30, 0x3a, 0x30, 0x34, 0x3a, - 0x30, 0x30, 0x5a, 0xc1, 0x1a, 0x51, 0x4b, 0x67, 0xb0, 0xa2, - 0x78, 0x19, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x44, - 0x61, 0x74, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x52, - 0x46, 0x43, 0x20, 0x33, 0x33, 0x33, 0x39, 0xc0, 0x77, 0x31, - 0x39, 0x38, 0x35, 0x2d, 0x30, 0x34, 0x2d, 0x31, 0x32, 0x54, - 0x32, 0x33, 0x3a, 0x32, 0x30, 0x3a, 0x35, 0x30, 0x2e, 0x35, - 0x32, 0x5a, 0x62, 0x53, 0x44, 0xc1, 0x19, 0x03, 0xe7 -}; - -int EncodeDateTest() -{ - QCBOREncodeContext ECtx; - int nReturn = 0; - - QCBOREncode_Init(&ECtx, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); - - QCBOREncode_OpenArray(&ECtx); - - - QCBOREncode_AddDateString(&ECtx, "2013-03-21T20:04:00Z"); // from CBOR RFC - QCBOREncode_AddDateEpoch(&ECtx, 1363896240); // from CBOR RFC - - - QCBOREncode_OpenMap(&ECtx); - - QCBOREncode_AddDateStringToMap(&ECtx, "Sample Date from RFC 3339", "1985-04-12T23:20:50.52Z"); - - QCBOREncode_AddDateEpochToMap(&ECtx, "SD", 999); - - QCBOREncode_CloseMap(&ECtx); - - QCBOREncode_CloseArray(&ECtx); - - UsefulBufC ECBOR; - - if(QCBOREncode_Finish(&ECtx, &ECBOR)) { - nReturn = -1; - } - - if(CheckResults(ECBOR, spExpectedEncodedDates)) - return -2; - - return(nReturn); -} - - -int ArrayNestingTest1() -{ - QCBOREncodeContext ECtx; - int i; - int nReturn = 0; - - QCBOREncode_Init(&ECtx, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); - for(i = QCBOR_MAX_ARRAY_NESTING; i; i--) { - QCBOREncode_OpenArray(&ECtx); - } - for(i = QCBOR_MAX_ARRAY_NESTING; i; i--) { - QCBOREncode_CloseArray(&ECtx); - } - UsefulBufC Encoded; - if(QCBOREncode_Finish(&ECtx, &Encoded)) { - nReturn = -1; - } - - return(nReturn); -} - - - -int ArrayNestingTest2() -{ - QCBOREncodeContext ECtx; - int i; - int nReturn = 0; - - QCBOREncode_Init(&ECtx, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); - for(i = QCBOR_MAX_ARRAY_NESTING+1; i; i--) { - QCBOREncode_OpenArray(&ECtx); - } - for(i = QCBOR_MAX_ARRAY_NESTING; i; i--) { - QCBOREncode_CloseArray(&ECtx); - } - - UsefulBufC Encoded; - if(QCBOREncode_Finish(&ECtx, &Encoded) != QCBOR_ERR_ARRAY_NESTING_TOO_DEEP) { - nReturn = -1; - } - - return(nReturn); -} - - - -int ArrayNestingTest3() -{ - QCBOREncodeContext ECtx; - int i; - int nReturn = 0; - - QCBOREncode_Init(&ECtx, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); - for(i = QCBOR_MAX_ARRAY_NESTING; i; i--) { - QCBOREncode_OpenArray(&ECtx); - } - for(i = QCBOR_MAX_ARRAY_NESTING+1 ; i; i--) { - QCBOREncode_CloseArray(&ECtx); - } - UsefulBufC Encoded; - if(QCBOREncode_Finish(&ECtx, &Encoded) != QCBOR_ERR_TOO_MANY_CLOSES) { - nReturn = -1; - } - - return(nReturn); -} - - -/* - 81 # array(1) - 81 # array(1) - 81 # array(1) - 81 # array(1) - 80 # array(0) -*/ -static const uint8_t spFiveArrarys[] = {0x81, 0x81, 0x81, 0x81, 0x80}; - -// Validated at http://cbor.me and by manually examining its output -/* - 82 # array(2) - 81 # array(1) - 81 # array(1) - 81 # array(1) - 81 # array(1) - 80 # array(0) - 98 2F # array(47) - 3B 7FFFFFFFFFFFFFFF # negative(9223372036854775807) - 3B 0000000100000000 # negative(4294967296) - 3A FFFFFFFF # negative(4294967295) - 3A FFFFFFFE # negative(4294967294) - 3A FFFFFFFD # negative(4294967293) - 3A 7FFFFFFF # negative(2147483647) - 3A 7FFFFFFE # negative(2147483646) - 3A 00010001 # negative(65537) - 3A 00010000 # negative(65536) - 39 FFFF # negative(65535) - 39 FFFE # negative(65534) - 39 FFFD # negative(65533) - 39 0100 # negative(256) - 38 FF # negative(255) - 38 FE # negative(254) - 38 FD # negative(253) - 38 18 # negative(24) - 37 # negative(23) - 36 # negative(22) - 20 # negative(0) - 00 # unsigned(0) - 00 # unsigned(0) - 01 # unsigned(1) - 16 # unsigned(22) - 17 # unsigned(23) - 18 18 # unsigned(24) - 18 19 # unsigned(25) - 18 1A # unsigned(26) - 18 FE # unsigned(254) - 18 FF # unsigned(255) - 19 0100 # unsigned(256) - 19 0101 # unsigned(257) - 19 FFFE # unsigned(65534) - 19 FFFF # unsigned(65535) - 1A 00010000 # unsigned(65536) - 1A 00010001 # unsigned(65537) - 1A 00010002 # unsigned(65538) - 1A 7FFFFFFF # unsigned(2147483647) - 1A 7FFFFFFF # unsigned(2147483647) - 1A 80000000 # unsigned(2147483648) - 1A 80000001 # unsigned(2147483649) - 1A FFFFFFFE # unsigned(4294967294) - 1A FFFFFFFF # unsigned(4294967295) - 1B 0000000100000000 # unsigned(4294967296) - 1B 0000000100000001 # unsigned(4294967297) - 1B 7FFFFFFFFFFFFFFF # unsigned(9223372036854775807) - 1B FFFFFFFFFFFFFFFF # unsigned(18446744073709551615) - */ -static const uint8_t spEncodeRawExpected[] = { - 0x82, 0x81, 0x81, 0x81, 0x81, 0x80, 0x98, 0x2f, - 0x3b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x3b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x3a, 0xff, 0xff, 0xff, 0xff, 0x3a, - 0xff, 0xff, 0xff, 0xfe, 0x3a, 0xff, 0xff, 0xff, - 0xfd, 0x3a, 0x7f, 0xff, 0xff, 0xff, 0x3a, 0x7f, - 0xff, 0xff, 0xfe, 0x3a, 0x00, 0x01, 0x00, 0x01, - 0x3a, 0x00, 0x01, 0x00, 0x00, 0x39, 0xff, 0xff, - 0x39, 0xff, 0xfe, 0x39, 0xff, 0xfd, 0x39, 0x01, - 0x00, 0x38, 0xff, 0x38, 0xfe, 0x38, 0xfd, 0x38, - 0x18, 0x37, 0x36, 0x20, 0x00, 0x00, 0x01, 0x16, - 0x17, 0x18, 0x18, 0x18, 0x19, 0x18, 0x1a, 0x18, - 0xfe, 0x18, 0xff, 0x19, 0x01, 0x00, 0x19, 0x01, - 0x01, 0x19, 0xff, 0xfe, 0x19, 0xff, 0xff, 0x1a, - 0x00, 0x01, 0x00, 0x00, 0x1a, 0x00, 0x01, 0x00, - 0x01, 0x1a, 0x00, 0x01, 0x00, 0x02, 0x1a, 0x7f, - 0xff, 0xff, 0xff, 0x1a, 0x7f, 0xff, 0xff, 0xff, - 0x1a, 0x80, 0x00, 0x00, 0x00, 0x1a, 0x80, 0x00, - 0x00, 0x01, 0x1a, 0xff, 0xff, 0xff, 0xfe, 0x1a, - 0xff, 0xff, 0xff, 0xff, 0x1b, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x1b, 0x7f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1b, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - - -int EncodeRawTest() -{ - QCBOREncodeContext ECtx; - - QCBOREncode_Init(&ECtx, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); - QCBOREncode_OpenArray(&ECtx); - QCBOREncode_AddEncoded(&ECtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spFiveArrarys)); - QCBOREncode_AddEncoded(&ECtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedEncodedInts)); - QCBOREncode_CloseArray(&ECtx); - - UsefulBufC EncodedRawTest; - - if(QCBOREncode_Finish(&ECtx, &EncodedRawTest)) { - return -4; - } - - if(CheckResults(EncodedRawTest, spEncodeRawExpected)) { - return -5; - } - - return 0; -} - -/* - This returns a pointer to spBigBuf - */ -static int CreateMap(uint8_t **pEncoded, size_t *pEncodedLen) -{ - QCBOREncodeContext ECtx; - int nReturn = -1; - - *pEncoded = NULL; - *pEncodedLen = INT32_MAX; - size_t uFirstSizeEstimate = 0; - - // loop runs CBOR encoding twice. First with no buffer to - // calucate the length so buffer can be allocated correctly, - // and last with the buffer to do the actual encoding - do { - QCBOREncode_Init(&ECtx, (UsefulBuf){*pEncoded, *pEncodedLen}); - QCBOREncode_OpenMap(&ECtx); - QCBOREncode_AddInt64ToMap(&ECtx, "first integer", 42); - QCBOREncode_OpenArrayInMap(&ECtx, "an array of two strings"); - QCBOREncode_AddText(&ECtx, ((UsefulBufC) {"string1", 7})); - QCBOREncode_AddText(&ECtx, ((UsefulBufC) {"string2", 7})); - QCBOREncode_CloseArray(&ECtx); - QCBOREncode_OpenMapInMap(&ECtx, "map in a map"); - QCBOREncode_AddBytesToMap(&ECtx,"bytes 1", ((UsefulBufC) { "xxxx", 4})); - QCBOREncode_AddBytesToMap(&ECtx, "bytes 2",((UsefulBufC) { "yyyy", 4})); - QCBOREncode_AddInt64ToMap(&ECtx, "another int", 98); - QCBOREncode_AddTextToMap(&ECtx, "text 2", ((UsefulBufC) {"lies, damn lies and statistics", 30})); - QCBOREncode_CloseMap(&ECtx); - QCBOREncode_CloseMap(&ECtx); - - if(QCBOREncode_FinishGetSize(&ECtx, pEncodedLen)) - goto Done; - if(*pEncoded != NULL) { - if(uFirstSizeEstimate != *pEncodedLen) { - nReturn = 1; - } else { - nReturn = 0; - } - goto Done; - } - *pEncoded = spBigBuf; - uFirstSizeEstimate = *pEncodedLen; - - } while(1); - - Done: - return(nReturn); -} - -/* - A3 # map(3) - 6D # text(13) - 666972737420696E7465676572 # "first integer" - 18 2A # unsigned(42) - 77 # text(23) - 616E206172726179206F662074776F20737472696E6773 # "an array of two strings" - 82 # array(2) - 67 # text(7) - 737472696E6731 # "string1" - 67 # text(7) - 737472696E6732 # "string2" - 6C # text(12) - 6D617020696E2061206D6170 # "map in a map" - A4 # map(4) - 67 # text(7) - 62797465732031 # "bytes 1" - 44 # bytes(4) - 78787878 # "xxxx" - 67 # text(7) - 62797465732032 # "bytes 2" - 44 # bytes(4) - 79797979 # "yyyy" - 6B # text(11) - 616E6F7468657220696E74 # "another int" - 18 62 # unsigned(98) - 66 # text(6) - 746578742032 # "text 2" - 78 1E # text(30) - 6C6965732C2064616D6E206C69657320616E642073746174697374696373 # "lies, damn lies and statistics" - */ -static const uint8_t spValidMapEncoded[] = { - 0xa3, 0x6d, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x69, 0x6e, - 0x74, 0x65, 0x67, 0x65, 0x72, 0x18, 0x2a, 0x77, 0x61, 0x6e, - 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, - 0x74, 0x77, 0x6f, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x73, 0x82, 0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x31, - 0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x32, 0x6c, 0x6d, - 0x61, 0x70, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x6d, 0x61, - 0x70, 0xa4, 0x67, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x31, - 0x44, 0x78, 0x78, 0x78, 0x78, 0x67, 0x62, 0x79, 0x74, 0x65, - 0x73, 0x20, 0x32, 0x44, 0x79, 0x79, 0x79, 0x79, 0x6b, 0x61, - 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x74, - 0x18, 0x62, 0x66, 0x74, 0x65, 0x78, 0x74, 0x20, 0x32, 0x78, - 0x1e, 0x6c, 0x69, 0x65, 0x73, 0x2c, 0x20, 0x64, 0x61, 0x6d, - 0x6e, 0x20, 0x6c, 0x69, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, - 0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, - 0x73 } ; - - -int MapEncodeTest() -{ - uint8_t *pEncodedMaps; - size_t nEncodedMapLen; - - if(CreateMap(&pEncodedMaps, &nEncodedMapLen)) { - return -1; - } - - int nReturn = 0; - if(memcmp(spValidMapEncoded, pEncodedMaps, sizeof(spValidMapEncoded))) - nReturn = 2; - - return(nReturn); -} - - -/* - @brief Encode the RTIC results - - @param[in] nRResult CBOR_SIMPLEV_TRUE, CBOR_SIMPLEV_FALSE or CBOR_SIMPLEV_NULL - @param[in] time Time stamp in UNIX epoch time or 0 for no time stamp - @param[in] szAlexString Diagnostic code. - @param[in[ pOut Buffer to put the result in - @param[in/out] pnLen Size of pOut buffer when called; length of data output in buffer on return - - @return - One of the CBOR encoder errors. QCBOR_SUCCESS, which is has value 0, if no error. - - The size of pOut should be 30 bytes plus the length of pnLen. If you make it too - short an error will be returned. This function will never write off the end - of the buffer passed to it. - - If the result is 0, then the correct encoded CBOR is in pOut and *pnLen is the - length of the encoded CBOR. - - */ - -static UsefulBufC FormatRTICResults(int nRResult, uint64_t time, const char *szType, const char *szAlexString, UsefulBuf Storage) -{ - // Buffer that the result will be written in to - // It is fixed size and small that a stack variable will be fine - // QCBOREncode will never write off the end of this buffer. If it won't fit QCBOREncode_Finish will return an error. - - // Context for the encoder - QCBOREncodeContext ECtx; - QCBOREncode_Init(&ECtx, Storage); - - // All the RTIC results are grouped in a CBOR Map which will get turned into a JSON Object - // Contents are label / value pairs - QCBOREncode_OpenMap(&ECtx); - - { // Brace / indention just to show CBOR encoding nesting - - // The result: 0 if scan happened and found nothing; 1 if it happened and found something wrong; 2 if it didn't happen - QCBOREncode_AddSimpleToMap(&ECtx, "integrity", nRResult); - - // Add the diagnostic code - QCBOREncode_AddSZStringToMap(&ECtx, "type", szType); - - // Add a time stamp - if(time) { - QCBOREncode_AddDateEpochToMap(&ECtx, "time", time); - } - - // Add the diagnostic code - QCBOREncode_AddSZStringToMap(&ECtx, "diag", szAlexString); - - // Open a subordinate map for telemtry data - QCBOREncode_OpenMapInMap(&ECtx, "telemetry"); - - { // Brace / indention just to show CBOR encoding nesting - - // Add a few fake integers and buffers for now. - QCBOREncode_AddInt64ToMap(&ECtx, "Shoe Size", 12); - - // Add a few fake integers and buffers for now. - QCBOREncode_AddInt64ToMap(&ECtx, "IQ", 0xffffffff); - - // Add a few fake integers and buffers for now. - static const uint8_t pPV[] = {0x66, 0x67, 0x00, 0x56, 0xaa, 0xbb, 0x01, 0x01}; - const UsefulBufC WSPV = {pPV, sizeof(pPV)}; - - QCBOREncode_AddBytesToMap(&ECtx, "WhaleSharkPatternVector", WSPV); - } - } - - // Close the telemetry map - QCBOREncode_CloseMap(&ECtx); - - // Close the map - QCBOREncode_CloseMap(&ECtx); - - UsefulBufC Result; - - QCBOREncode_Finish(&ECtx, &Result); - - return Result; -} - - -/* - A5 # map(5) - 69 # text(9) - 696E74656772697479 # "integrity" - F4 # primitive(20) - 64 # text(4) - 74797065 # "type" - 66 # text(6) - 726563656E74 # "recent" - 64 # text(4) - 74696D65 # "time" - C1 # tag(1) - 1A 580D4172 # unsigned(1477263730) - 64 # text(4) - 64696167 # "diag" - 6A # text(10) - 30784131654335303031 # "0xA1eC5001" - 69 # text(9) - 74656C656D65747279 # "telemetry" - A3 # map(3) - 69 # text(9) - 53686F652053697A65 # "Shoe Size" - 0C # unsigned(12) - 62 # text(2) - 4951 # "IQ" - 1A FFFFFFFF # unsigned(4294967295) - 77 # text(23) - 5768616C65536861726B5061747465726E566563746F72 # "WhaleSharkPatternVector" - 48 # bytes(8) - 66670056AABB0101 # "fg\x00V\xAA\xBB\x01\x01" - */ -static const uint8_t spExpectedRTIC[] = { - 0xa5, 0x69, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x69, 0x74, - 0x79, 0xf4, 0x64, 0x74, 0x79, 0x70, 0x65, 0x66, 0x72, 0x65, - 0x63, 0x65, 0x6e, 0x74, 0x64, 0x74, 0x69, 0x6d, 0x65, 0xc1, - 0x1a, 0x58, 0x0d, 0x41, 0x72, 0x64, 0x64, 0x69, 0x61, 0x67, - 0x6a, 0x30, 0x78, 0x41, 0x31, 0x65, 0x43, 0x35, 0x30, 0x30, - 0x31, 0x69, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, - 0x79, 0xa3, 0x69, 0x53, 0x68, 0x6f, 0x65, 0x20, 0x53, 0x69, - 0x7a, 0x65, 0x0c, 0x62, 0x49, 0x51, 0x1a, 0xff, 0xff, 0xff, - 0xff, 0x77, 0x57, 0x68, 0x61, 0x6c, 0x65, 0x53, 0x68, 0x61, - 0x72, 0x6b, 0x50, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x56, - 0x65, 0x63, 0x74, 0x6f, 0x72, 0x48, 0x66, 0x67, 0x00, 0x56, - 0xaa, 0xbb, 0x01, 0x01}; - - -int RTICResultsTest() -{ - const UsefulBufC Encoded = FormatRTICResults(CBOR_SIMPLEV_FALSE, 1477263730, - "recent", "0xA1eC5001", - UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); - if(UsefulBuf_IsNULLC(Encoded)) { - return -1; - } - - if(CheckResults(Encoded, spExpectedRTIC)) { - return -2; - } - - return 0; -} - - -/* - 82 # array(2) - 19 01C3 # unsigned(451) - 43 # bytes(3) - 1901D2 # "\x19\x01\xD2" -*/ -static const uint8_t spExpectedBstrWrap[] = {0x82, 0x19, 0x01, 0xC3, 0x43, 0x19, 0x01, 0xD2}; - -/* - Very basic bstr wrapping test - */ -int BstrWrapTest() -{ - QCBOREncodeContext EC; - - QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); - - QCBOREncode_OpenArray(&EC); - QCBOREncode_AddUInt64(&EC, 451); - - QCBOREncode_BstrWrap(&EC); - QCBOREncode_AddUInt64(&EC, 466); - - UsefulBufC Wrapped; - QCBOREncode_CloseBstrWrap(&EC, &Wrapped); - - QCBOREncode_CloseArray(&EC); - - UsefulBufC Encoded; - if(QCBOREncode_Finish(&EC, &Encoded)) { - return -1; - } - - if(CheckResults(Encoded, spExpectedBstrWrap)) { - return -2; - } - - /* Another test; see about handling length calculation */ - QCBOREncode_Init(&EC, (UsefulBuf){NULL, INT32_MAX}); - QCBOREncode_OpenArray(&EC); - QCBOREncode_BstrWrap(&EC); - QCBOREncode_OpenArray(&EC); - QCBOREncode_AddNULL(&EC); - QCBOREncode_CloseArray(&EC); - UsefulBufC BStr; - QCBOREncode_CloseBstrWrap(&EC, &BStr); - // 2 is one byte for an array of length 1 and 1 byte for a NULL - if(BStr.ptr != NULL || BStr.len != 2) { - return -5; - } - - return 0; -} - - - -int BstrWrapErrorTest() -{ - // -------------- Test closing a bstrwrap when it is an array that is open ----------- - QCBOREncodeContext EC; - - QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); - - QCBOREncode_OpenArray(&EC); - QCBOREncode_AddUInt64(&EC, 451); - - QCBOREncode_BstrWrap(&EC); - QCBOREncode_AddUInt64(&EC, 466); - QCBOREncode_OpenArray(&EC); - - UsefulBufC Wrapped; - QCBOREncode_CloseBstrWrap(&EC, &Wrapped); - - QCBOREncode_CloseArray(&EC); - - UsefulBufC Encoded2; - if(QCBOREncode_Finish(&EC, &Encoded2) != QCBOR_ERR_CLOSE_MISMATCH) { - return -1; - } - - // ----------- test closing a bstrwrap when nothing is open --------------------- - QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); - QCBOREncode_CloseBstrWrap(&EC, &Wrapped); - if(QCBOREncode_Finish(&EC, &Encoded2) != QCBOR_ERR_TOO_MANY_CLOSES) { - return -2; - } - - // --------------- test nesting too deep ---------------------------------- - QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); - for(int i = 1; i < 18; i++) { - QCBOREncode_BstrWrap(&EC); - } - QCBOREncode_AddBool(&EC, true); - - for(int i = 1; i < 18; i++) { - QCBOREncode_CloseBstrWrap(&EC, &Wrapped); - } - - if(QCBOREncode_Finish(&EC, &Encoded2) != QCBOR_ERR_ARRAY_NESTING_TOO_DEEP) { - return -3; - } - - return 0; -} - - - -// Part of bstr_wrap_nest_test -/* - 83 array with three - 53 byte string with 19 bytes - 01 #1 - 50 byte string with 16 bytes - 02 - 4D byte string with 13 bytes - 03 - 4A byte string with 10 bytes - 04 - 47 byte string with 7 bytes - 05 - 44 byte string with 4 bytes - 06 - 41 byte string with 1 byte - 07 - 01 - 02 - 03 - 04 - 05 - 06 - 07 - A2 map with two items - 18 20 label for byte string - 54 byte string of length 20 - 82 Array with two items - 10 The integer value 10 - A2 map with two items - 18 21 label for byte string - 44 byte string with 4 bytes - 81 array with 1 item - 11 integer value 11 - 18 30 integer value 30 - 18 40 integer label 40 - 65 68 65 6C 6C 6F text string hello - 18 31 integer value 31 - 18 41 integer label 41 - 65 68 65 6C 6C 6F text string hello - - - */ - - -/* - 83 # array(3) - 56 # bytes(22) - 00530150024D034A0447054406410700010203040506 # "\x00S\x01P\x02M\x03J\x04G\x05D\x06A\a\x00\x01\x02\x03\x04\x05\x06" - 07 # unsigned(7) - A2 # map(2) - 18 20 # unsigned(32) - 54 # bytes(20) - 8210A21821448111183018406568656C6C6F1831 # "\x82\x10\xA2\x18!D\x81\x11\x180\x18@ehello\x181" - 18 41 # unsigned(65) - 65 # text(5) - 68656C6C6F # "hello" - */ -static const uint8_t spExpectedDeepBstr[] = -{ - 0x83, 0x56, 0x00, 0x53, 0x01, 0x50, 0x02, 0x4D, - 0x03, 0x4A, 0x04, 0x47, 0x05, 0x44, 0x06, 0x41, - 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, - 0x07, 0xA2, 0x18, 0x20, 0x54, 0x82, 0x10, 0xA2, - 0x18, 0x21, 0x44, 0x81, 0x11, 0x18, 0x30, 0x18, - 0x40, 0x65, 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x18, - 0x31, 0x18, 0x41, 0x65, 0x68, 0x65, 0x6C, 0x6C, - 0x6F -}; - -// Part of bstr_wrap_nest_test -static int DecodeNextNested(UsefulBufC Wrapped) -{ - int nReturn; - QCBORDecodeContext DC; - QCBORDecode_Init(&DC, Wrapped, QCBOR_DECODE_MODE_NORMAL); - - QCBORItem Item; - nReturn = QCBORDecode_GetNext(&DC, &Item); - if(nReturn) { - return -11; - } - if(Item.uDataType != QCBOR_TYPE_INT64) { - return -12; - } - - nReturn = QCBORDecode_GetNext(&DC, &Item); - if(nReturn == QCBOR_ERR_HIT_END) { - return 0; - } - if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) { - return -13; - } - nReturn = DecodeNextNested(Item.val.string); - if(nReturn) { - return nReturn; - } - - nReturn = QCBORDecode_GetNext(&DC, &Item); - if(nReturn) { - return -14; - } - if(Item.uDataType != QCBOR_TYPE_INT64) { - return -15; - } - - if(QCBORDecode_Finish(&DC)) { - return -16; - } - - return 0; -} - -// Part of bstr_wrap_nest_test -static int DecodeNextNested2(UsefulBufC Wrapped) -{ - int nReturn; - QCBORDecodeContext DC; - QCBORDecode_Init(&DC, Wrapped, QCBOR_DECODE_MODE_NORMAL); - - QCBORItem Item; - nReturn = QCBORDecode_GetNext(&DC, &Item); - if(nReturn) { - return -11; - } - if(Item.uDataType != QCBOR_TYPE_ARRAY) { - return -12; - } - - nReturn = QCBORDecode_GetNext(&DC, &Item); - if(nReturn) { - return -11; - } - if(Item.uDataType != QCBOR_TYPE_INT64) { - return -12; - } - - nReturn = QCBORDecode_GetNext(&DC, &Item); - if(nReturn) { - return -11; - } - if(Item.uDataType != QCBOR_TYPE_MAP) { - return 0; - } - - nReturn = QCBORDecode_GetNext(&DC, &Item); - if(nReturn) { - return -11; - } - if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) { - return -13; - } - nReturn = DecodeNextNested2(Item.val.string); - if(nReturn) { - return nReturn; - } - - nReturn = QCBORDecode_GetNext(&DC, &Item); - if(nReturn) { - return -11; - } - if(Item.uDataType != QCBOR_TYPE_TEXT_STRING) { - return -12; - } - nReturn = QCBORDecode_GetNext(&DC, &Item); - if(nReturn) { - return -11; - } - if(Item.uDataType != QCBOR_TYPE_INT64) { - return -12; - } - - if(QCBORDecode_Finish(&DC)) { - return -16; - } - - return 0; -} - - -int BstrWrapNestTest() -{ - QCBOREncodeContext EC; - QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); - - // ---- Make a complicated nested CBOR structure --- -#define BSTR_TEST_DEPTH 10 - - QCBOREncode_OpenArray(&EC); - - for(int i = 0; i < BSTR_TEST_DEPTH-2; i++) { - QCBOREncode_BstrWrap(&EC); - QCBOREncode_AddUInt64(&EC, i); - } - - for(int i = 0; i < BSTR_TEST_DEPTH-2; i++) { - QCBOREncode_CloseBstrWrap(&EC, NULL); - QCBOREncode_AddUInt64(&EC, i); - } - - for(int i = 0; i < (BSTR_TEST_DEPTH-2)/3; i++) { - QCBOREncode_OpenMap(&EC); - QCBOREncode_BstrWrapInMapN(&EC, i+0x20); - QCBOREncode_OpenArray(&EC); - QCBOREncode_AddUInt64(&EC, i+0x10); - } - - for(int i = 0; i < (BSTR_TEST_DEPTH-2)/3; i++) { - QCBOREncode_CloseArray(&EC); - QCBOREncode_AddUInt64(&EC, i+0x30); - QCBOREncode_CloseBstrWrap(&EC, NULL); - QCBOREncode_AddSZStringToMapN(&EC, i+0x40, "hello"); - QCBOREncode_CloseMap(&EC); - } - QCBOREncode_CloseArray(&EC); - - UsefulBufC Encoded; - if(QCBOREncode_Finish(&EC, &Encoded)) { - return -1; - } - - // ---Compare it to expected. Expected was hand checked with use of CBOR playground ---- - if(UsefulBuf_Compare(UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedDeepBstr), Encoded)) { - return -25; - } - - - // ---- Decode it and see if it is OK ------ - QCBORDecodeContext DC; - QCBORDecode_Init(&DC, Encoded, QCBOR_DECODE_MODE_NORMAL); - - QCBORItem Item; - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_ARRAY || Item.val.uCount != 3) { - return -2; - } - - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) { - return -3; - } - - int nReturn = DecodeNextNested(Item.val.string); - if(nReturn) { - return nReturn; - } - - nReturn = QCBORDecode_GetNext(&DC, &Item); - if(nReturn) { - return -11; - } - if(Item.uDataType != QCBOR_TYPE_INT64) { - return -12; - } - - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_MAP || Item.val.uCount != 2) { - return -2; - } - - QCBORDecode_GetNext(&DC, &Item); - if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) { - return -3; - } - nReturn = DecodeNextNested2(Item.val.string); - if(nReturn) { - return nReturn; - } - - nReturn = QCBORDecode_GetNext(&DC, &Item); - if(nReturn) { - return -11; - } - if(Item.uDataType != QCBOR_TYPE_TEXT_STRING) { - return -12; - } - - if(QCBORDecode_Finish(&DC)) { - return -16; - } - - return 0; -} - - -static const uint8_t spSignature[] = { - 0x8e, 0xb3, 0x3e, 0x4c, 0xa3, 0x1d, 0x1c, 0x46, 0x5a, 0xb0, - 0x5a, 0xac, 0x34, 0xcc, 0x6b, 0x23, 0xd5, 0x8f, 0xef, 0x5c, - 0x08, 0x31, 0x06, 0xc4, 0xd2, 0x5a, 0x91, 0xae, 0xf0, 0xb0, - 0x11, 0x7e, 0x2a, 0xf9, 0xa2, 0x91, 0xaa, 0x32, 0xe1, 0x4a, - 0xb8, 0x34, 0xdc, 0x56, 0xed, 0x2a, 0x22, 0x34, 0x44, 0x54, - 0x7e, 0x01, 0xf1, 0x1d, 0x3b, 0x09, 0x16, 0xe5, 0xa4, 0xc3, - 0x45, 0xca, 0xcb, 0x36}; - -/* - D2 # tag(18) - 84 # array(4) - 43 # bytes(3) - A10126 # "\xA1\x01&" - A1 # map(1) - 04 # unsigned(4) - 42 # bytes(2) - 3131 # "11" - 54 # bytes(20) - 546869732069732074686520636F6E74656E742E # "This is the content." - 58 40 # bytes(64) - 8EB33E4CA31D1C465AB05AAC34CC6B23D58FEF5C083106C4D25A91AEF0B0117E2AF9A291AA32E14AB834DC56ED2A223444547E01F11D3B0916E5A4C345CACB36 # "\x8E\xB3>L\xA3\x1D\x1CFZ\xB0Z\xAC4\xCCk#\xD5\x8F\xEF\\\b1\x06\xC4\xD2Z\x91\xAE\xF0\xB0\x11~*\xF9\xA2\x91\xAA2\xE1J\xB84\xDCV\xED*\"4DT~\x01\xF1\x1D;\t\x16\xE5\xA4\xC3E\xCA\xCB6" - */ -static const uint8_t spExpected[] = { - 0xD2, 0x84, 0x43, 0xA1, 0x01, 0x26, 0xA1, 0x04, 0x42, 0x31, - 0x31, 0x54, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, - 0x74, 0x2E, 0x58, 0x40, 0x8E, 0xB3, 0x3E, 0x4C, 0xA3, 0x1D, - 0x1C, 0x46, 0x5A, 0xB0, 0x5A, 0xAC, 0x34, 0xCC, 0x6B, 0x23, - 0xD5, 0x8F, 0xEF, 0x5C, 0x08, 0x31, 0x06, 0xC4, 0xD2, 0x5A, - 0x91, 0xAE, 0xF0, 0xB0, 0x11, 0x7E, 0x2A, 0xF9, 0xA2, 0x91, - 0xAA, 0x32, 0xE1, 0x4A, 0xB8, 0x34, 0xDC, 0x56, 0xED, 0x2A, - 0x22, 0x34, 0x44, 0x54, 0x7E, 0x01, 0xF1, 0x1D, 0x3B, 0x09, - 0x16, 0xE5, 0xA4, 0xC3, 0x45, 0xCA, 0xCB, 0x36}; - -/* - this corresponds exactly to the example in RFC 8152 - section C.2.1. This doesn't actually verify the signature - though that would be nice as it would make the test - really good. That would require bring in ECDSA crypto - to this test. - */ -int CoseSign1TBSTest() -{ - // All of this is from RFC 8152 C.2.1 - const char *szKid = "11"; - const UsefulBufC Kid = UsefulBuf_FromSZ(szKid); - const char *szPayload = "This is the content."; - const UsefulBufC Payload = UsefulBuf_FromSZ(szPayload); - static const uint8_t pProtectedHeaders[] = {0xa1, 0x01, 0x26}; - const UsefulBufC ProtectedHeaders = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pProtectedHeaders); - - // It would be good to compare this to the output from - // a COSE implementation like COSE-C. It has been checked - // against the CBOR playground. - const UsefulBufC Signature = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSignature); - - QCBOREncodeContext EC; - QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); - - // top level array for cose sign1, 18 is the tag for COSE sign - QCBOREncode_AddTag(&EC, CBOR_TAG_COSE_SIGN1); - QCBOREncode_OpenArray(&EC); - - // Add protected headers - QCBOREncode_AddBytes(&EC, ProtectedHeaders); - - // Empty map with unprotected headers - QCBOREncode_OpenMap(&EC); - QCBOREncode_AddBytesToMapN(&EC, 4, Kid); - QCBOREncode_CloseMap(&EC); - - // The payload - UsefulBufC WrappedPayload; - QCBOREncode_BstrWrap(&EC); - QCBOREncode_AddEncoded(&EC, Payload); // Payload is not actually CBOR in example C.2.1 - QCBOREncode_CloseBstrWrap(&EC, &WrappedPayload); - - // Check we got back the actual payload expected - if(UsefulBuf_Compare(WrappedPayload, Payload)) { - return -1; - } - - // The signature - QCBOREncode_AddBytes(&EC, Signature); - QCBOREncode_CloseArray(&EC); - - // Finish and check the results - UsefulBufC COSE_Sign1; - if(QCBOREncode_Finish(&EC, &COSE_Sign1)) { - return -2; - } - - // 98 is the size from RFC 8152 C.2.1 - if(COSE_Sign1.len != 98) { - return -3; - } - - if(CheckResults(COSE_Sign1, spExpected)) { - return -4; - } - - return 0; -} - - -int EncodeErrorTests() -{ - QCBOREncodeContext EC; - - - // ------ Test for QCBOR_ERR_BUFFER_TOO_LARGE ------ - // Do all of these tests with NULL buffers so no actual large allocations are neccesary - UsefulBuf Buffer = (UsefulBuf){NULL, UINT32_MAX}; - - // First verify no error from a big buffer - QCBOREncode_Init(&EC, Buffer); - QCBOREncode_OpenArray(&EC); - // 6 is the CBOR overhead for opening the array and encodng the length - // This exactly fills the buffer. - QCBOREncode_AddBytes(&EC, (UsefulBufC){NULL, UINT32_MAX-6}); - QCBOREncode_CloseArray(&EC); - size_t xx; - if(QCBOREncode_FinishGetSize(&EC, &xx) != QCBOR_SUCCESS) { - return -1; - } - - // Second verify error from an array in encoded output too large - QCBOREncode_Init(&EC, Buffer); - QCBOREncode_OpenArray(&EC); - QCBOREncode_AddBytes(&EC, (UsefulBufC){NULL, UINT32_MAX-6}); - QCBOREncode_OpenArray(&EC); // Where QCBOR internally encounters and records error - QCBOREncode_CloseArray(&EC); - QCBOREncode_CloseArray(&EC); - if(QCBOREncode_FinishGetSize(&EC, &xx) != QCBOR_ERR_BUFFER_TOO_LARGE) { - return -2; - } - - // Third, fit an array in exactly at max position allowed - QCBOREncode_Init(&EC, Buffer); - QCBOREncode_OpenArray(&EC); - QCBOREncode_AddBytes(&EC, (UsefulBufC){NULL, QCBOR_MAX_ARRAY_OFFSET-6}); - QCBOREncode_OpenArray(&EC); - QCBOREncode_CloseArray(&EC); - QCBOREncode_CloseArray(&EC); - if(QCBOREncode_FinishGetSize(&EC, &xx) != QCBOR_SUCCESS) { - return -10; - } - - - // ----- QCBOR_ERR_BUFFER_TOO_SMALL -------------- - // Work close to the 4GB size limit for a better test - const uint32_t uLargeSize = UINT32_MAX - 1024; - UsefulBuf Large = (UsefulBuf){NULL,uLargeSize}; - - QCBOREncode_Init(&EC, Large); - QCBOREncode_OpenArray(&EC); - QCBOREncode_AddBytes(&EC, (UsefulBufC){NULL, uLargeSize/2 + 1}); - QCBOREncode_CloseArray(&EC); - if(QCBOREncode_FinishGetSize(&EC, &xx) != QCBOR_SUCCESS) { - // Making sure it succeeds when it should first - return -3; - } - - QCBOREncode_Init(&EC, Large); - QCBOREncode_OpenArray(&EC); - QCBOREncode_AddBytes(&EC, (UsefulBufC){NULL, uLargeSize/2 + 1}); - QCBOREncode_AddBytes(&EC, (UsefulBufC){NULL, uLargeSize/2}); - QCBOREncode_CloseArray(&EC); - if(QCBOREncode_FinishGetSize(&EC, &xx) != QCBOR_ERR_BUFFER_TOO_SMALL) { - // Now just 1 byte over, see that it fails - return -4; - } - - - // ----- QCBOR_ERR_ARRAY_NESTING_TOO_DEEP ------- - QCBOREncode_Init(&EC, Large); - for(int i = QCBOR_MAX_ARRAY_NESTING; i > 0; i--) { - QCBOREncode_OpenArray(&EC); - } - for(int i = QCBOR_MAX_ARRAY_NESTING; i > 0; i--) { - QCBOREncode_CloseArray(&EC); - } - if(QCBOREncode_FinishGetSize(&EC, &xx) != QCBOR_SUCCESS) { - // Making sure it succeeds when it should first - return -5; - } - - QCBOREncode_Init(&EC, Large); - for(int i = QCBOR_MAX_ARRAY_NESTING+1; i > 0; i--) { - QCBOREncode_OpenArray(&EC); - } - for(int i = QCBOR_MAX_ARRAY_NESTING+1; i > 0; i--) { - QCBOREncode_CloseArray(&EC); - } - if(QCBOREncode_FinishGetSize(&EC, &xx) != QCBOR_ERR_ARRAY_NESTING_TOO_DEEP) { - // One more level to cause error - return -6; - } - - - // ------ QCBOR_ERR_TOO_MANY_CLOSES -------- - QCBOREncode_Init(&EC, Large); - for(int i = QCBOR_MAX_ARRAY_NESTING; i > 0; i--) { - QCBOREncode_OpenArray(&EC); - } - for(int i = QCBOR_MAX_ARRAY_NESTING+1; i > 0; i--) { - QCBOREncode_CloseArray(&EC); - } - if(QCBOREncode_FinishGetSize(&EC, &xx) != QCBOR_ERR_TOO_MANY_CLOSES) { - // One more level to cause error - return -7; - } - - - // ------ QCBOR_ERR_CLOSE_MISMATCH -------- - QCBOREncode_Init(&EC, Large); - QCBOREncode_OpenArray(&EC); - UsefulBufC Wrap; - QCBOREncode_CloseBstrWrap(&EC, &Wrap); - if(QCBOREncode_FinishGetSize(&EC, &xx) != QCBOR_ERR_CLOSE_MISMATCH) { - return -8; - } - - - // ------ QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN --------- - QCBOREncode_Init(&EC, Large); - for(int i = QCBOR_MAX_ARRAY_NESTING; i > 0; i--) { - QCBOREncode_OpenArray(&EC); - } - for(int i = QCBOR_MAX_ARRAY_NESTING-1; i > 0; i--) { - QCBOREncode_CloseArray(&EC); - } - if(QCBOREncode_FinishGetSize(&EC, &xx) != QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN) { - // One more level to cause error - return -9; - } - - /* QCBOR_ERR_ARRAY_TOO_LONG is not tested here as - it would require a 64KB of RAM to test */ - - return 0; -} - diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/qcbor_encode_tests.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/qcbor_encode_tests.h deleted file mode 100644 index 49362c6..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/qcbor_encode_tests.h +++ /dev/null @@ -1,146 +0,0 @@ -/*============================================================================== - Copyright (c) 2016-2018, The Linux Foundation. - Copyright (c) 2018-2019, Laurence Lundblade. - All rights reserved. - SPDX-License-Identifier: BSD-3-Clause - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of The Linux Foundation nor the names of its - contributors, nor the name "Laurence Lundblade" may be used to - endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS -BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ==============================================================================*/ - -#ifndef __QCBOR__qcbor_encode_tests__ -#define __QCBOR__qcbor_encode_tests__ - -#include "qcbor.h" - - -/* - Notes: - - - All the functions in qcbor.h are called once in the aggregation of all the tests below. - - - All the types that are supported are given as input and parsed by these tests - - - There is some hostile input such as invalid lengths and CBOR too complex - and types this parser doesn't handle - - */ - - -/* - Most basic test. - */ -int BasicEncodeTest(void); - - -/* - Encode lots of integer values, particularly around the boundary and make sure they - Match the expected binary output. Primarily an encoding test. - */ -int IntegerValuesTest1(void); - - - -/* - Create nested arrays to the max depth allowed and make sure it succeeds. - This is an encoding test. - */ -int ArrayNestingTest1(void); - - -/* - Create nested arrays to one more than the meax depth and make sure it fails. - This is an encoding test. - */ -int ArrayNestingTest2(void); - - -/* - Encoding test. - Create arrays to max depth and close one extra time and look for correct error code - */ -int ArrayNestingTest3(void); - - -/* - This tests the QCBOREncode_AddRaw() function by adding two chunks or RAWCBOR to an - array and comparing with expected values. This is an encoding test. - */ -int EncodeRawTest(void); - - -/* - This creates a somewhat complicated CBOR MAP and verifies it against expected - data. This is an encoding test. - */ -int MapEncodeTest(void); - - - -/* - Encodes a goodly number of floats and doubles and checks encoding is right - */ -int FloatValuesTest1(void); - - -/* - Encodes true, false and the like - */ -int SimpleValuesTest1(void); - - -/* - Encodes most data formats that are supported */ -int EncodeDateTest(void); - - -/* - Encodes particular data structure that a particular app will need... - */ -int RTICResultsTest(void); - - -/* - Calls all public encode methods in qcbor.h once. - */ -int AllAddMethodsTest(void); - -/* - The binary string wrapping of maps and arrays used by COSE - */ -int BstrWrapTest(void); - -int BstrWrapErrorTest(void); - -int BstrWrapNestTest(void); - -int CoseSign1TBSTest(void); - -int EncodeErrorTests(void); - - - -#endif /* defined(__QCBOR__qcbor_encode_tests__) */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/run_tests.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/run_tests.c deleted file mode 100644 index 6e35620..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/run_tests.c +++ /dev/null @@ -1,285 +0,0 @@ -/*============================================================================== - run_tests.c -- test aggregator and results reporting - - Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. - - SPDX-License-Identifier: BSD-3-Clause - - See BSD-3-Clause license in README.md - - Created on 9/30/18 - ==============================================================================*/ - -#include "run_tests.h" -#include "UsefulBuf.h" -#include - -#include "float_tests.h" -#include "qcbor_decode_tests.h" -#include "qcbor_encode_tests.h" -#include "UsefulBuf_Tests.h" - - - -// Used to test RunTests -int fail_test() -{ - return -44; -} - - - - -/* - Convert a number up to 999999999 to a string. This is so sprintf doesn't - have to be linked in so as to minimized dependencies even in test code. - */ -const char *NumToString(int32_t nNum, UsefulBuf StringMem) -{ - const int32_t nMax = 1000000000; - - UsefulOutBuf OutBuf; - UsefulOutBuf_Init(&OutBuf, StringMem); - - if(nNum < 0) { - UsefulOutBuf_AppendByte(&OutBuf, '-'); - nNum = -nNum; - } - if(nNum > nMax-1) { - return "XXX"; - } - - bool bDidSomeOutput = false; - for(int n = nMax; n > 0; n/=10) { - int x = nNum/n; - if(x || bDidSomeOutput){ - bDidSomeOutput = true; - UsefulOutBuf_AppendByte(&OutBuf, '0' + x); - nNum -= x * n; - } - } - if(!bDidSomeOutput){ - UsefulOutBuf_AppendByte(&OutBuf, '0'); - } - UsefulOutBuf_AppendByte(&OutBuf, '\0'); - - return UsefulOutBuf_GetError(&OutBuf) ? "" : StringMem.ptr; -} - - - - -typedef int (test_fun_t)(void); -typedef const char * (test_fun2_t)(void); - - -#define TEST_ENTRY(test_name) {#test_name, test_name, true} -#define TEST_ENTRY_DISABLED(test_name) {#test_name, test_name, false} - -typedef struct { - const char *szTestName; - test_fun_t *test_fun; - bool bEnabled; -} test_entry; - -typedef struct { - const char *szTestName; - test_fun2_t *test_fun; - bool bEnabled; -} test_entry2; - -test_entry2 s_tests2[] = { - TEST_ENTRY(UBUTest_CopyUtil), - TEST_ENTRY(UOBTest_NonAdversarial), - TEST_ENTRY(TestBasicSanity), - TEST_ENTRY(UOBTest_BoundaryConditionsTest), - TEST_ENTRY(UBMacroConversionsTest), - TEST_ENTRY(UBUtilTests), - TEST_ENTRY(UIBTest_IntegerFormat) -}; - - -test_entry s_tests[] = { - TEST_ENTRY(ParseMapAsArrayTest), - TEST_ENTRY_DISABLED(AllocAllStringsTest), - TEST_ENTRY(IndefiniteLengthNestTest), - TEST_ENTRY(NestedMapTestIndefLen), - TEST_ENTRY(ParseSimpleTest), - TEST_ENTRY(EncodeRawTest), - TEST_ENTRY(RTICResultsTest), - TEST_ENTRY(MapEncodeTest), - TEST_ENTRY(ArrayNestingTest1), - TEST_ENTRY(ArrayNestingTest2), - TEST_ENTRY(ArrayNestingTest3), - TEST_ENTRY(EncodeDateTest), - TEST_ENTRY(SimpleValuesTest1), - TEST_ENTRY(IntegerValuesTest1), - TEST_ENTRY(AllAddMethodsTest), - TEST_ENTRY(ParseTooDeepArrayTest), - TEST_ENTRY(ComprehensiveInputTest), - TEST_ENTRY(ParseMapTest), - TEST_ENTRY_DISABLED(IndefiniteLengthArrayMapTest), - TEST_ENTRY(BasicEncodeTest), - TEST_ENTRY(NestedMapTest), - TEST_ENTRY(BignumParseTest), - TEST_ENTRY(OptTagParseTest), - TEST_ENTRY(DateParseTest), - TEST_ENTRY(ShortBufferParseTest2), - TEST_ENTRY(ShortBufferParseTest), - TEST_ENTRY(ParseDeepArrayTest), - TEST_ENTRY(SimpleArrayTest), - TEST_ENTRY(IntegerValuesParseTest), - TEST_ENTRY_DISABLED(MemPoolTest), - TEST_ENTRY_DISABLED(IndefiniteLengthStringTest), - TEST_ENTRY(HalfPrecisionDecodeBasicTests), - TEST_ENTRY(DoubleAsSmallestTest), - TEST_ENTRY(HalfPrecisionAgainstRFCCodeTest), - TEST_ENTRY(BstrWrapTest), - TEST_ENTRY(BstrWrapErrorTest), - TEST_ENTRY(BstrWrapNestTest), - TEST_ENTRY(CoseSign1TBSTest), - TEST_ENTRY(StringDecoderModeFailTest), - TEST_ENTRY_DISABLED(BigComprehensiveInputTest), - TEST_ENTRY(EncodeErrorTests), - //TEST_ENTRY(fail_test), -}; - - -int RunTests(const char *szTestNames[], OutputStringCB pfOutput, void *poutCtx, int *pNumTestsRun) -{ - int nTestsFailed = 0; - int nTestsRun = 0; - UsefulBuf_MAKE_STACK_UB(StringStorage, 5); - - test_entry2 *t2; - const test_entry2 *s_tests2_end = s_tests2 + sizeof(s_tests2)/sizeof(test_entry2); - - for(t2 = s_tests2; t2 < s_tests2_end; t2++) { - if(szTestNames[0]) { - // Some tests have been named - const char **szRequestedNames; - for(szRequestedNames = szTestNames; *szRequestedNames; szRequestedNames++) { - if(!strcmp(t2->szTestName, *szRequestedNames)) { - break; // Name matched - } - } - if(*szRequestedNames == NULL) { - // Didn't match this test - continue; - } - } else { - // no tests named, but don't run "disabled" tests - if(!t2->bEnabled) { - // Don't run disabled tests when all tests are being run - // as indicated by no specific test names being given - continue; - } - } - - const char * szTestResult = (t2->test_fun)(); - nTestsRun++; - if(pfOutput) { - (*pfOutput)(t2->szTestName, poutCtx, 0); - } - - if(szTestResult) { - if(pfOutput) { - (*pfOutput)(" FAILED (returned ", poutCtx, 0); - (*pfOutput)(szTestResult, poutCtx, 0); - (*pfOutput)(")", poutCtx, 1); - } - nTestsFailed++; - } else { - if(pfOutput) { - (*pfOutput)( " PASSED", poutCtx, 1); - } - } - } - - - test_entry *t; - const test_entry *s_tests_end = s_tests + sizeof(s_tests)/sizeof(test_entry); - - for(t = s_tests; t < s_tests_end; t++) { - if(szTestNames[0]) { - // Some tests have been named - const char **szRequestedNames; - for(szRequestedNames = szTestNames; *szRequestedNames; szRequestedNames++) { - if(!strcmp(t->szTestName, *szRequestedNames)) { - break; // Name matched - } - } - if(*szRequestedNames == NULL) { - // Didn't match this test - continue; - } - } else { - // no tests named, but don't run "disabled" tests - if(!t->bEnabled) { - // Don't run disabled tests when all tests are being run - // as indicated by no specific test names being given - continue; - } - } - - int nTestResult = (t->test_fun)(); - nTestsRun++; - if(pfOutput) { - (*pfOutput)(t->szTestName, poutCtx, 0); - } - - if(nTestResult) { - if(pfOutput) { - (*pfOutput)(" FAILED (returned ", poutCtx, 0); - (*pfOutput)(NumToString(nTestResult, StringStorage), poutCtx, 0); - (*pfOutput)(")", poutCtx, 1); - } - nTestsFailed++; - } else { - if(pfOutput) { - (*pfOutput)( " PASSED", poutCtx, 1); - } - } - } - - if(pNumTestsRun) { - *pNumTestsRun = nTestsRun; - } - - if(pfOutput) { - (*pfOutput)( "SUMMARY: ", poutCtx, 0); - (*pfOutput)( NumToString(nTestsRun, StringStorage), poutCtx, 0); - (*pfOutput)( " tests run; ", poutCtx, 0); - (*pfOutput)( NumToString(nTestsFailed, StringStorage), poutCtx, 0); - (*pfOutput)( " tests failed", poutCtx, 1); - } - - return nTestsFailed; -} - - - - -static void PrintSize(const char *szWhat, uint32_t uSize, OutputStringCB pfOutput, void *pOutCtx) -{ - UsefulBuf_MAKE_STACK_UB(buffer, 20); - - (*pfOutput)(szWhat, pOutCtx, 0); - (*pfOutput)(" ", pOutCtx, 0); - (*pfOutput)(NumToString(uSize, buffer), pOutCtx, 0); - (*pfOutput)("", pOutCtx, 1); -} - -void PrintSizes(OutputStringCB pfOutput, void *pOutCtx) -{ - // Type and size of return from sizeof() varies. These will never be large so cast is safe - PrintSize("sizeof(QCBORTrackNesting)", (uint32_t)sizeof(QCBORTrackNesting), pfOutput, pOutCtx); - PrintSize("sizeof(QCBOREncodeContext)", (uint32_t)sizeof(QCBOREncodeContext), pfOutput, pOutCtx); - PrintSize("sizeof(QCBORDecodeNesting)", (uint32_t)sizeof(QCBORDecodeNesting), pfOutput, pOutCtx); - PrintSize("sizeof(QCBORDecodeContext)", (uint32_t)sizeof(QCBORDecodeContext), pfOutput, pOutCtx); - PrintSize("sizeof(QCBORItem)", (uint32_t)sizeof(QCBORItem), pfOutput, pOutCtx); - PrintSize("sizeof(QCBORStringAllocator)",(uint32_t)sizeof(QCBORStringAllocator), pfOutput, pOutCtx); - PrintSize("sizeof(QCBORTagListIn)", (uint32_t)sizeof(QCBORTagListIn), pfOutput, pOutCtx); - PrintSize("sizeof(QCBORTagListOut)", (uint32_t)sizeof(QCBORTagListOut), pfOutput, pOutCtx); - (*pfOutput)("", pOutCtx, 1); -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/run_tests.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/run_tests.h deleted file mode 100644 index 734d4f8..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/run_tests.h +++ /dev/null @@ -1,66 +0,0 @@ -/*============================================================================== - run_tests.h -- test aggregator and results reporting - - Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. - - SPDX-License-Identifier: BSD-3-Clause - - See BSD-3-Clause license in README.md - - Created 9/30/18 - ==============================================================================*/ - -/** - @file run_tests.h -*/ - -/** - @brief Type for function to output a text string - - @param[in] szString The string to output - @param[in] pOutCtx A context pointer; NULL if not needed - @param[in] bNewline If non-zero, output a newline after the string - - This is a prototype of a function to be passed to RunTests() to - output text strings. - - This can be implemented with stdio (if available) using a straight - call to fputs() where the FILE * is passed as the pOutCtx as shown in - the example code below. This code is for Linux where the newline is - a \\n. Windows usually prefers \\r\\n. - - @code - static void fputs_wrapper(const char *szString, void *pOutCtx, int bNewLine) - { - fputs(szString, (FILE *)pOutCtx); - if(bNewLine) { - fputs("\n", pOutCtx); - } - } - @endcode -*/ -typedef void (*OutputStringCB)(const char *szString, void *pOutCtx, int bNewline); - - -/** - @brief Runs the QCBOR tests. - - @param[in] szTestNames An argv-style list of test names to run. If - empty, all are run. - @param[in] pfOutput Function that is called to output text strings. - @param[in] pOutCtx Context pointer passed to output function. - @param[out] pNumTestsRun Returns the number of tests run. May be NULL. - - @return The number of tests that failed. Zero means overall success. - */ -int RunTests(const char *szTestNames[], OutputStringCB pfOutput, void *pOutCtx, int *pNumTestsRun); - - -/** - @brief Print sizes of encoder / decoder contexts. - - @param[in] pfOutput Function that is called to output text strings. - @param[in] pOutCtx Context pointer passed to output function. - */ -void PrintSizes(OutputStringCB pfOutput, void *pOutCtx); - diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_client.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_client.h deleted file mode 100755 index ee2645d..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_client.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -* Copyright (c) 2018-2019 ARM Limited. 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 __TFM_CLIENT_H__ -#define __TFM_CLIENT_H__ - -#include "psa/client.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* __TFM_CLIENT_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/attest_eat_defines.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/attest_eat_defines.h deleted file mode 100755 index 002e2a1..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/attest_eat_defines.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#ifndef __ATTEST_EAT_DEFINES_H__ -#define __ATTEST_EAT_DEFINES_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#define EAT_CBOR_ARM_RANGE_BASE (-75000) -#define EAT_CBOR_ARM_LABEL_PROFILE_DEFINITION (EAT_CBOR_ARM_RANGE_BASE - 0) -#define EAT_CBOR_ARM_LABEL_CLIENT_ID (EAT_CBOR_ARM_RANGE_BASE - 1) -#define EAT_CBOR_ARM_LABEL_SECURITY_LIFECYCLE (EAT_CBOR_ARM_RANGE_BASE - 2) -#define EAT_CBOR_ARM_LABEL_IMPLEMENTATION_ID (EAT_CBOR_ARM_RANGE_BASE - 3) -#define EAT_CBOR_ARM_LABEL_BOOT_SEED (EAT_CBOR_ARM_RANGE_BASE - 4) -#define EAT_CBOR_ARM_LABEL_HW_VERSION (EAT_CBOR_ARM_RANGE_BASE - 5) -#define EAT_CBOR_ARM_LABEL_SW_COMPONENTS (EAT_CBOR_ARM_RANGE_BASE - 6) -#define EAT_CBOR_ARM_LABEL_NO_SW_COMPONENTS (EAT_CBOR_ARM_RANGE_BASE - 7) -#define EAT_CBOR_ARM_LABEL_CHALLENGE (EAT_CBOR_ARM_RANGE_BASE - 8) -#define EAT_CBOR_ARM_LABEL_UEID (EAT_CBOR_ARM_RANGE_BASE - 9) -#define EAT_CBOR_ARM_LABEL_ORIGINATION (EAT_CBOR_ARM_RANGE_BASE - 10) - -#define EAT_CBOR_SW_COMPONENT_MEASUREMENT_TYPE (1) -#define EAT_CBOR_SW_COMPONENT_MEASUREMENT_VALUE (2) -#define EAT_CBOR_SW_COMPONENT_SECURITY_EPOCH (3) -#define EAT_CBOR_SW_COMPONENT_VERSION (4) -#define EAT_CBOR_SW_COMPONENT_SIGNER_ID (5) -#define EAT_CBOR_SW_COMPONENT_MEASUREMENT_DESC (6) - -#ifdef __cplusplus -} -#endif - -#endif /* __ATTEST_EAT_DEFINES_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/attest_token.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/attest_token.c deleted file mode 100755 index 8cf5f74..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/attest_token.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * attest_token.c - * - * Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * See BSD-3-Clause license in README.md - */ - -#include "attest_token.h" -#include "qcbor.h" -#include "t_cose_sign1_sign.h" - - -/** - * \file attest_token.c - * - * \brief Attestation token creation implementation - * - * Outline of token creation. Much of this occurs inside - * t_cose_sign1_init() and t_cose_sign1_finish(). - * - * - Create encoder context - * - Open the CBOR array that hold the \c COSE_Sign1 - * - Write COSE Headers - * - Protected Header - * - Algorithm ID - * - Unprotected Headers - * - Key ID - * - Open payload bstr - * - Write payload data… lots of it… - * - Get bstr that is the encoded payload - * - Compute signature - * - Create a separate encoder context for \c Sig_structure - * - Encode CBOR context identifier - * - Encode protected headers - * - Encode two empty bstr - * - Add one more empty bstr that is a "fake payload" - * - Close off \c Sig_structure - * - Hash all but "fake payload" of \c Sig_structure - * - Get payload bstr ptr and length - * - Continue hash of the real encoded payload - * - Run ECDSA - * - Write signature into the CBOR output - * - Close CBOR array holding the \c COSE_Sign1 - */ - -/* - * \brief Map t_cose error to attestation token error. - * - * \param[in] err The t_cose error to map. - * - * \return the attestation token error. - * - */ -static enum attest_token_err_t t_cose_err_to_attest_err(enum t_cose_err_t err) -{ - switch(err) { - - case T_COSE_SUCCESS: - return ATTEST_TOKEN_ERR_SUCCESS; - - case T_COSE_ERR_UNSUPPORTED_HASH: - return ATTEST_TOKEN_ERR_HASH_UNAVAILABLE; - - default: - /* A lot of the errors are not mapped because they are - * primarily internal errors that should never happen. They - * end up here. - */ - return ATTEST_TOKEN_ERR_GENERAL; - } -} - - -/* - Public function. See attest_token.h - */ -enum attest_token_err_t attest_token_start(struct attest_token_ctx *me, - uint32_t opt_flags, - int32_t key_select, - int32_t cose_alg_id, - const struct useful_buf *out_buf) -{ - /* approximate stack usage on 32-bit machine: 4 bytes */ - enum t_cose_err_t cose_return_value; - enum attest_token_err_t return_value; - - /* Remember some of the configuration values */ - me->opt_flags = opt_flags; - me->key_select = key_select; - - /* Spin up the CBOR encoder */ - QCBOREncode_Init(&(me->cbor_enc_ctx), *out_buf); - - - /* Initialize COSE signer. This will cause the cose headers to be - * encoded and written into out_buf using me->cbor_enc_ctx - */ - cose_return_value = t_cose_sign1_init(&(me->signer_ctx), - opt_flags & - TOKEN_OPT_SHORT_CIRCUIT_SIGN, - cose_alg_id, - key_select, - &(me->cbor_enc_ctx)); - if(cose_return_value) { - return_value = t_cose_err_to_attest_err(cose_return_value); - goto Done; - } - - /* Open the payload-wrapping bstr */ - QCBOREncode_BstrWrap(&(me->cbor_enc_ctx)); - - QCBOREncode_OpenMap(&(me->cbor_enc_ctx)); - - return_value = ATTEST_TOKEN_ERR_SUCCESS; - -Done: - return return_value; -} - - -/* - Public function. See attest_token.h - */ -QCBOREncodeContext *attest_token_borrow_cbor_cntxt(struct attest_token_ctx *me) -{ - return &(me->cbor_enc_ctx); -} - - -/* - Public function. See attest_token.h - */ -void attest_token_add_integer(struct attest_token_ctx *me, - int32_t label, - int64_t Value) -{ - QCBOREncode_AddInt64ToMapN(&(me->cbor_enc_ctx), label, Value); -} - - -/* - Public function. See attest_token.h - */ -void attest_token_add_bstr(struct attest_token_ctx *me, - int32_t label, - const struct useful_buf_c *bstr) -{ - QCBOREncode_AddBytesToMapN(&(me->cbor_enc_ctx), - label, - *bstr); -} - - -/* - Public function. See attest_token.h - */ -void attest_token_add_tstr(struct attest_token_ctx *me, - int32_t label, - const struct useful_buf_c *tstr) -{ - QCBOREncode_AddTextToMapN(&(me->cbor_enc_ctx), label, *tstr); -} - - -/* - See attest_token.h - */ -void attest_token_add_encoded(struct attest_token_ctx *me, - int32_t label, - const struct useful_buf_c *encoded) -{ - QCBOREncode_AddEncodedToMapN(&(me->cbor_enc_ctx), label, *encoded); -} - - -/* - Public function. See attest_token.h - */ -enum attest_token_err_t -attest_token_finish(struct attest_token_ctx *me, - struct useful_buf_c *completed_token) -{ - /* approximate stack usage on 32-bit machine: 4 + 4 + 8 + 8 = 24 */ - enum attest_token_err_t return_value = ATTEST_TOKEN_ERR_SUCCESS; - /* The payload with all the claims that is signed */ - struct useful_buf_c token_payload_ub; - /* The completed and signed encoded cose_sign1 */ - struct useful_buf_c completed_token_ub; - QCBORError qcbor_result; - enum t_cose_err_t cose_return_value; - - QCBOREncode_CloseMap(&(me->cbor_enc_ctx)); - - /* Close off the payload-wrapping bstr. This gives us back the - * pointer and length of the payload that needs to be hashed as - * part of the signature - */ - QCBOREncode_CloseBstrWrap(&(me->cbor_enc_ctx), &token_payload_ub); - - /* Finish off the cose signature. This does all the interesting work of - hashing and signing */ - cose_return_value = - t_cose_sign1_finish(&(me->signer_ctx), token_payload_ub); - if(cose_return_value) { - /* Main errors are invoking the hash or signature */ - return_value = t_cose_err_to_attest_err(cose_return_value); - goto Done; - } - - /* Close off the CBOR encoding and return the completed token */ - qcbor_result = QCBOREncode_Finish(&(me->cbor_enc_ctx), - &completed_token_ub); - if(qcbor_result == QCBOR_ERR_BUFFER_TOO_SMALL) { - return_value = ATTEST_TOKEN_ERR_TOO_SMALL; - } else if (qcbor_result != QCBOR_SUCCESS) { - /* likely from array not closed, too many closes, ... */ - return_value = ATTEST_TOKEN_ERR_CBOR_FORMATTING; - } else { - *completed_token = completed_token_ub; - } - -Done: - return return_value; -} - diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/attest_token.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/attest_token.h deleted file mode 100755 index 903c42b..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/attest_token.h +++ /dev/null @@ -1,241 +0,0 @@ -/* - * attest_token.h - * - * Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * See BSD-3-Clause license in README.md - */ - -#ifndef __ATTEST_TOKEN_H__ -#define __ATTEST_TOKEN_H__ - -#include -#include "qcbor.h" -#include "t_cose_sign1_sign.h" - - -/** - * \file attest_token.h - * - * \brief Attestation Token Creation Interface - * - * The context and functions here are the way to create an attestation - * token. The steps are roughly: - * - * -# Creation and initialize an attest_token_ctx indicating the - * options, key and such using attest_token_start(). - * - * -# Use various add methods to fill in the payload with claims. The - * encoding context can also be borrowed for more rich payloads. - * - * -# Call attest_token_finish() to create the signature and finish - * formatting the COSE signed output. - */ - - -/** - Error codes returned from attestation token creation. - */ -enum attest_token_err_t { - /** Success */ - ATTEST_TOKEN_ERR_SUCCESS = 0, - /** The buffer passed in to receive the output is too small. */ - ATTEST_TOKEN_ERR_TOO_SMALL, - /** Something went wrong formatting the CBOR, most likely the - payload has maps or arrays that are not closed. */ - ATTEST_TOKEN_ERR_CBOR_FORMATTING, - /** A general, unspecific error when creating or decoding the - token. */ - ATTEST_TOKEN_ERR_GENERAL, - /** A hash function that is needed to make the token is not - available. */ - ATTEST_TOKEN_ERR_HASH_UNAVAILABLE, - /** CBOR Syntax not well-formed -- a CBOR syntax error. */ - ATTEST_TOKEN_ERR_CBOR_NOT_WELL_FORMED, - /** Bad CBOR structure, for example not a map when was is - required. */ - ATTEST_TOKEN_ERR_CBOR_STRUCTURE, - /** Bad CBOR type, for example an not a text string, when a text - string is required. */ - ATTETST_TOKEN_ERR_CBOR_TYPE, - /** Integer too large, for example an \c int32_t is required, but - value only fits in \c int64_t */ - ATTEST_TOKEN_ERR_INTEGER_VALUE, - /** Something is wrong with the COSE signing structure, missing - headers or such. */ - ATTEST_TOKEN_ERR_COSE_SIGN1_FORMAT, - /** COSE signature is invalid, data is corrupted. */ - ATTEST_TOKEN_ERR_COSE_SIGN1_VALIDATION, - /** The signing algorithm is not supported. */ - ATTEST_TOKEN_ERR_UNSUPPORTED_SIG_ALG, - /** Out of memory. */ - ATTEST_TOKEN_ERR_INSUFFICIENT_MEMORY, - /** Tampering detected in cryptographic function. */ - ATTEST_TOKEN_ERR_TAMPERING_DETECTED, - /** Verification key is not found or of wrong type. */ - ATTEST_TOKEN_ERR_VERIFICATION_KEY -}; - - - -/** - * Request that the claims internally generated not be added to the - * token. This is a test mode that results in a static token that - * never changes. Only the nonce is included. The nonce is under - * the callers control unlike the other claims. - */ -#define TOKEN_OPT_OMIT_CLAIMS 0x40000000 - - -/** - * A special test mode where a proper signature is not produced. In - * its place there is a concatenation of hashes of the payload to be - * the same size as the signature. This works and can be used to - * verify all of the SW stack except the public signature part. The - * token has no security value in this mode because anyone can - * replicate it. */ -#define TOKEN_OPT_SHORT_CIRCUIT_SIGN 0x80000000 - - -/** - * The context for creating an attestation token. The caller of - * attest_token must create one of these and pass it to the functions - * here. It is small enough that it can go on the stack. It is most of - * the memory needed to create a token except the output buffer and - * any memory requirements for the cryptographic operations. - * - * The structure is opaque for the caller. - * - * This is roughly 148 + 8 + 32 = 188 bytes - */ -struct attest_token_ctx { - /* Private data structure */ - QCBOREncodeContext cbor_enc_ctx; - uint32_t opt_flags; - int32_t key_select; - struct t_cose_sign1_ctx signer_ctx; -}; - - -/** - * \brief Initialize a token creation context. - * - * \param[in] me The token creation context to be initialized. - * \param[in] opt_flags Flags to select different custom options, - for example \ref TOKEN_OPT_OMIT_CLAIMS. - * \param[in] key_select Selects which attestation key to sign with. - * \param[in] cose_alg_id The algorithm to sign with. The IDs are - * defined in [COSE (RFC 8152)] - * (https://tools.ietf.org/html/rfc8152) or - * in the [IANA COSE Registry] - * (https://www.iana.org/assignments/cose/cose.xhtml). - * \param[out] out_buffer The output buffer to write the encoded token into. - * - * \return one of the \ref attest_token_err_t errors. - * - * The size of the buffer in \c out_buffer->len - * determines the size of the token that can be created. It must be - * able to hold the final encoded and signed token. The data encoding - * overhead is just that of CBOR. The signing overhead depends on the - * signing key size. It is about 150 bytes for 256-bit ECDSA. - * - * If \c out_buffer->ptr is \c NULL and \c out_buffer_ptr->len is - * large like \c UINT32_MAX no token will be created but the length of - * the token that would be created will be in \c completed_token as - * returned by attest_token_finish(). None of the cryptographic - * functions run during this, but the sizes of what they would output - * is taken into account. - */ -enum attest_token_err_t -attest_token_start(struct attest_token_ctx *me, - uint32_t opt_flags, - int32_t key_select, - int32_t cose_alg_id, - const struct useful_buf *out_buffer); - - - -/** - * \brief Get a copy of the CBOR encoding context - * - * \param[in] me Token creation context. - * - * \return The CBOR encoding context - * - * Allows the caller to encode CBOR right into the output buffer using - * any of the \c QCBOREncode_AddXXXX() methods. Anything added here - * will be part of the payload that gets hashed. This can be used to - * make complex CBOR structures. All open arrays and maps must be - * close before calling any other \c attest_token methods. \c - * QCBOREncode_Finish() should not be closed on this context. - */ -QCBOREncodeContext *attest_token_borrow_cbor_cntxt(struct attest_token_ctx *me); - -/** - * \brief Add a 64-bit signed integer claim - * - * \param[in] me Token creation context. - * \param[in] label Integer label for claim. - * \param[in] value The integer claim data. - */ -void attest_token_add_integer(struct attest_token_ctx *me, - int32_t label, - int64_t value); - -/** - * \brief Add a binary string claim - * - * \param[in] me Token creation context. - * \param[in] label Integer label for claim. - * \param[in] value The binary claim data. - */ -void attest_token_add_bstr(struct attest_token_ctx *me, - int32_t label, - const struct useful_buf_c *value); - -/** - * \brief Add a text string claim - * - * \param[in] me Token creation context. - * \param[in] label Integer label for claim. - * \param[in] value The text claim data. - */ -void attest_token_add_tstr(struct attest_token_ctx *me, - int32_t label, - const struct useful_buf_c *value); - -/** - * \brief Add some already-encoded CBOR to payload - * - * \param[in] me Token creation context. - * \param[in] label Integer label for claim. - * \param[in] encoded The already-encoded CBOR. - * - * Encoded CBOR must be a full map or full array or a non-aggregate - * type. It cannot be a partial map or array. It can be nested maps - * and arrays, but they must all be complete. - */ -void attest_token_add_encoded(struct attest_token_ctx *me, - int32_t label, - const struct useful_buf_c *encoded); - - -/** - * \brief Finish the token, complete the signing and get the result - * - * \param[in] me Token Creation Context. - * \param[out] completed_token Pointer and length to completed token. - * - * \return one of the \ref attest_token_err_t errors. - * - * This completes the token after the payload has been added. When - * this is called the signing algorithm is run and the final - * formatting of the token is completed. - */ -enum attest_token_err_t -attest_token_finish(struct attest_token_ctx *me, - struct useful_buf_c *completed_token); - -#endif /* __ATTEST_TOKEN_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/attestation_core.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/attestation_core.c deleted file mode 100755 index a7e46da..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/attestation_core.c +++ /dev/null @@ -1,1032 +0,0 @@ -/* - * Copyright (c) 2018-2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#include -#include -#include -#include "tfm_client.h" -#include "attestation.h" -#include "tfm_impl/tfm_boot_status.h" -#include "tfm_plat_defs.h" -#include "tfm_plat_device_id.h" -#include "tfm_plat_boot_seed.h" -#include "tfm_attest_hal.h" -#include "attest_token.h" -#include "attest_eat_defines.h" -#include "t_cose_defines.h" -#include "tfm_memory_utils.h" - -#define MAX_BOOT_STATUS 512 - -/* Indicates how to encode SW components' measurements in the CBOR map */ -#define EAT_SW_COMPONENT_NESTED 1 /* Nested map */ -#define EAT_SW_COMPONENT_NOT_NESTED 0 /* Flat structure */ - -/* Indicates that the boot status does not contain any SW components' - * measurement - */ -#define NO_SW_COMPONENT_FIXED_VALUE 1 - -/*! - * \var boot_status - * - * \brief Array variable to store the boot status in service's memory. - * - * \details Boot status comes from the secure bootloader and primarily stored - * on a memory area which is shared between bootloader and SPM. - * SPM provides the \ref tfm_core_get_boot_data() API to retrieve - * the service related data from shared area. - */ - -/* Enforcement of 4 byte alignment, which is checked by TF-M SPM */ -__attribute__ ((aligned(4))) -static uint8_t boot_status[MAX_BOOT_STATUS]; - -enum psa_attest_err_t attest_init(void) -{ - enum psa_attest_err_t res; - - res = attest_get_boot_data(TLV_MAJOR_IAS, boot_status, MAX_BOOT_STATUS); - - return res; -} - -/*! - * \brief Static function to map return values between \ref attest_token_err_t - * and \ref psa_attest_err_t - * - * \param[in] token_err Token encoding return value - * - * \return Returns error code as specified in \ref psa_attest_err_t - */ -static inline enum psa_attest_err_t -error_mapping(enum attest_token_err_t token_err) -{ - switch (token_err) { - case ATTEST_TOKEN_ERR_SUCCESS: - return PSA_ATTEST_ERR_SUCCESS; - break; - case ATTEST_TOKEN_ERR_TOO_SMALL: - return PSA_ATTEST_ERR_TOKEN_BUFFER_OVERFLOW; - break; - default: - return PSA_ATTEST_ERR_GENERAL; - } -} - -/*! - * \brief Static function to convert a pointer and size info to unsigned - * integer number. Max 32bits unsigned integers are supported. - * - * This implementation assumes that the endianness of the sender and receiver - * of the data is the same because they are actually running on the same CPU - * instance. If this assumption is not true than this function must be - * refactored accordingly. - * - * \param[in] int_ptr Pointer to the unsigned integer - * \param[in] len Size of the unsigned integers in bytes - * \param[in] value Pointer where to store the converted value - * - * \return Returns 0 on success and -1 on error. - */ -static inline int32_t get_uint(const void *int_ptr, - size_t len, - uint32_t *value) -{ - uint16_t uint16; - - switch (len) { - case 1: - *value = (uint32_t)(*(uint8_t *)(int_ptr)); - break; - case 2: - /* Avoid unaligned access */ - tfm_memcpy(&uint16, int_ptr, sizeof(uint16)); - *value = (uint32_t)uint16; - break; - case 4: - /* Avoid unaligned access */ - tfm_memcpy(value, int_ptr, sizeof(uint32_t)); - break; - default: - return -1; - } - - return 0; -} -/*! - * \brief Static function to look up all entires in the shared data area - * (boot status) which belong to a specific module. - * - * \param[in] module The identifier of SW module to look up based on this - * \param[out] claim The type of SW module's attribute - * \param[out] tlv_len Length of the shared data entry - * \param[in/out] tlv_ptr Pointer to the shared data entry. If its value NULL as - * input then it will starts the look up from the - * beginning of the shared data section. If not NULL then - * it continue look up from the next entry. It returns - * the address of next found entry which belongs to - * module. - * - * \retval -1 Error, boot status is malformed - * \retval 0 Entry not found - * \retval 1 Entry found - */ -static int32_t attest_get_tlv_by_module(uint8_t module, - uint8_t *claim, - uint16_t *tlv_len, - uint8_t **tlv_ptr) -{ - struct shared_data_tlv_header *tlv_header; - struct shared_data_tlv_entry tlv_entry; - uint8_t *tlv_end; - uint8_t *tlv_curr; - - tlv_header = (struct shared_data_tlv_header *)boot_status; - if (tlv_header->tlv_magic != SHARED_DATA_TLV_INFO_MAGIC) { - return -1; - } - - /* Get the boundaries of TLV section where to lookup*/ - tlv_end = (uint8_t *)boot_status + tlv_header->tlv_tot_len; - if (*tlv_ptr == NULL) { - /* At first call set to the beginning of the TLV section */ - tlv_curr = (uint8_t *)boot_status + SHARED_DATA_HEADER_SIZE; - } else { - /* Any subsequent call set to the next TLV entry */ - tfm_memcpy(&tlv_entry, *tlv_ptr, SHARED_DATA_ENTRY_HEADER_SIZE); - tlv_curr = (*tlv_ptr) + tlv_entry.tlv_len; - } - - /* Iterates over the TLV section and returns the address and size of TLVs - * with requested module identifier - */ - for (; tlv_curr < tlv_end; tlv_curr += tlv_entry.tlv_len) { - /* Create local copy to avoid unaligned access */ - tfm_memcpy(&tlv_entry, tlv_curr, SHARED_DATA_ENTRY_HEADER_SIZE); - if (GET_IAS_MODULE(tlv_entry.tlv_type) == module) { - *claim = GET_IAS_CLAIM(tlv_entry.tlv_type); - *tlv_ptr = tlv_curr; - *tlv_len = tlv_entry.tlv_len; - return 1; - } - } - - return 0; -} - -/*! - * \brief Static function to look up specific claim belongs to SW_GENERAL module - * - * \param[in] claim The claim ID to look for - * \param[out] tlv_len Length of the shared data entry - * \param[out] tlv_ptr Pointer to a shared data entry which belongs to the - * SW_GENERAL module. - * - * \retval -1 Error, boot status is malformed - * \retval 0 Entry not found - * \retval 1 Entry found - */ -static int32_t attest_get_tlv_by_id(uint8_t claim, - uint16_t *tlv_len, - uint8_t **tlv_ptr) -{ - uint8_t tlv_id; - uint8_t module = SW_GENERAL; - int32_t found; - - /* Ensure that look up starting from the beginning of the boot status */ - *tlv_ptr = NULL; - - /* Look up specific TLV entry which belongs to SW_GENERAL module */ - do { - /* Look up next entry */ - found = attest_get_tlv_by_module(module, &tlv_id, - tlv_len, tlv_ptr); - if (found != 1) { - break; - } - /* At least one entry was found which belongs to SW_GENERAL, - * check whether this one is looked for - */ - if (claim == tlv_id) { - break; - } - } while (found == 1); - - return found; -} - -/*! - * \brief Static function to add SW component related claims to attestation - * token in CBOR format. - * - * This function translates between TLV and CBOR encoding. - * - * \param[in] token_ctx Attestation token encoding context - * \param[in] tlv_id The ID of claim - * \param[in] claim_value A structure which carries a pointer and size about - * the data item to be added to the token - * - * \return Returns error code as specified in \ref psa_attest_err_t - */ -static enum psa_attest_err_t -attest_add_sw_component_claim(struct attest_token_ctx *token_ctx, - uint8_t tlv_id, - const struct useful_buf_c *claim_value) -{ - int32_t res; - uint32_t value; - - switch (tlv_id) { - case SW_MEASURE_VALUE: - attest_token_add_bstr(token_ctx, - EAT_CBOR_SW_COMPONENT_MEASUREMENT_VALUE, - claim_value); - break; - case SW_MEASURE_TYPE: - attest_token_add_tstr(token_ctx, - EAT_CBOR_SW_COMPONENT_MEASUREMENT_DESC, - claim_value); - break; - case SW_VERSION: - attest_token_add_tstr(token_ctx, - EAT_CBOR_SW_COMPONENT_VERSION, - claim_value); - break; - case SW_SIGNER_ID: - attest_token_add_bstr(token_ctx, - EAT_CBOR_SW_COMPONENT_SIGNER_ID, - claim_value); - break; - case SW_EPOCH: - res = get_uint(claim_value->ptr, claim_value->len, &value); - if (res) { - return PSA_ATTEST_ERR_GENERAL; - } - attest_token_add_integer(token_ctx, - EAT_CBOR_SW_COMPONENT_SECURITY_EPOCH, - (int64_t)value); - break; - case SW_TYPE: - attest_token_add_tstr(token_ctx, - EAT_CBOR_SW_COMPONENT_MEASUREMENT_TYPE, - claim_value); - break; - default: - return PSA_ATTEST_ERR_GENERAL; - } - - return PSA_ATTEST_ERR_SUCCESS; -} - -/*! - * \brief Static function to add the measurement data of a single SW components - * to the attestation token. - * - * \param[in] token_ctx Token encoding context - * \param[in] module SW component identifier - * \param[in] tlv_address Address of the first TLV entry in the boot status, - * which belongs to this SW component. - * \param[in] nested_map Flag to indicate that how to encode the SW component - * measurement data: nested map or non-nested map. - * - * \return Returns error code as specified in \ref psa_attest_err_t - */ -static enum psa_attest_err_t -attest_add_single_sw_measurment(struct attest_token_ctx *token_ctx, - uint32_t module, - uint8_t *tlv_address, - uint32_t nested_map) -{ - struct shared_data_tlv_entry tlv_entry; - uint16_t tlv_len; - uint8_t tlv_id; - uint8_t *tlv_ptr = tlv_address; - int32_t found = 1; - struct useful_buf_c claim_value; - enum psa_attest_err_t res; - QCBOREncodeContext *cbor_encode_ctx; - - /* Create local copy to avoid unaligned access */ - tfm_memcpy(&tlv_entry, tlv_address, SHARED_DATA_ENTRY_HEADER_SIZE); - tlv_len = tlv_entry.tlv_len; - tlv_id = GET_IAS_CLAIM(tlv_entry.tlv_type); - - cbor_encode_ctx = attest_token_borrow_cbor_cntxt(token_ctx); - - /* Open nested map for SW component measurement claims */ - if (nested_map) { - QCBOREncode_OpenMapInMapN(cbor_encode_ctx, - EAT_CBOR_SW_COMPONENT_MEASUREMENT_VALUE); - } - - /* Look up all measurement TLV entry which belongs to the SW component */ - while (found) { - /* Here only measurement claims are added to the token */ - if (GET_IAS_MEASUREMENT_CLAIM(tlv_id)) { - claim_value.ptr = tlv_ptr + SHARED_DATA_ENTRY_HEADER_SIZE; - claim_value.len = tlv_len - SHARED_DATA_ENTRY_HEADER_SIZE; - res = attest_add_sw_component_claim(token_ctx, - tlv_id, - &claim_value); - if (res != PSA_ATTEST_ERR_SUCCESS) { - return res; - } - } - - /* Look up next entry it can be non-measurement claim*/ - found = attest_get_tlv_by_module(module, &tlv_id, - &tlv_len, &tlv_ptr); - if (found == -1) { - return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE; - } - } - - if (nested_map) { - QCBOREncode_CloseMap(cbor_encode_ctx); - } - - return PSA_ATTEST_ERR_SUCCESS; -} - -/*! - * \brief Static function to add the claims of a single SW components to the - * attestation token. - * - * \param[in] token_ctx Token encoding context - * \param[in] module SW component identifier - * \param[in] tlv_address Address of the first TLV entry in the boot status, - * which belongs to this SW component. - * - * \return Returns error code as specified in \ref psa_attest_err_t - */ -static enum psa_attest_err_t -attest_add_single_sw_component(struct attest_token_ctx *token_ctx, - uint32_t module, - uint8_t *tlv_address) -{ - struct shared_data_tlv_entry tlv_entry; - uint16_t tlv_len; - uint8_t tlv_id; - uint8_t *tlv_ptr = tlv_address; - int32_t found = 1; - uint32_t measurement_claim_cnt = 0; - struct useful_buf_c claim_value; - QCBOREncodeContext *cbor_encode_ctx; - - /* Create local copy to avoid unaligned access */ - tfm_memcpy(&tlv_entry, tlv_address, SHARED_DATA_ENTRY_HEADER_SIZE); - tlv_len = tlv_entry.tlv_len; - tlv_id = GET_IAS_CLAIM(tlv_entry.tlv_type); - - /* Open map which stores claims belong to a SW component */ - cbor_encode_ctx = attest_token_borrow_cbor_cntxt(token_ctx); - QCBOREncode_OpenMap(cbor_encode_ctx); - - /*Look up all TLV entry which belongs to the same SW component */ - while (found) { - /* Check whether claim is measurement claim */ - if (GET_IAS_MEASUREMENT_CLAIM(tlv_id)) { - if (measurement_claim_cnt == 0) { - /* Call only once when first measurement claim found */ - measurement_claim_cnt++; - attest_add_single_sw_measurment(token_ctx, - module, - tlv_ptr, - EAT_SW_COMPONENT_NOT_NESTED); - } - } else { - /* Adding top level claims */ - claim_value.ptr = tlv_ptr + SHARED_DATA_ENTRY_HEADER_SIZE; - claim_value.len = tlv_len - SHARED_DATA_ENTRY_HEADER_SIZE; - attest_add_sw_component_claim(token_ctx, tlv_id, &claim_value); - } - - /* Look up next entry which belongs to SW component */ - found = attest_get_tlv_by_module(module, &tlv_id, - &tlv_len, &tlv_ptr); - if (found == -1) { - return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE; - } - } - - /* Close map which stores claims belong to a SW component */ - QCBOREncode_CloseMap(cbor_encode_ctx); - - return PSA_ATTEST_ERR_SUCCESS; -} - -/*! - * \brief Static function to add the claims of all SW components to the - * attestation token. - * - * \param[in] token_ctx Token encoding context - * - * \return Returns error code as specified in \ref psa_attest_err_t - */ -static enum psa_attest_err_t -attest_add_all_sw_components(struct attest_token_ctx *token_ctx) -{ - uint16_t tlv_len; - uint8_t *tlv_ptr; - uint8_t tlv_id; - int32_t found; - uint32_t cnt = 0; - uint32_t module; - QCBOREncodeContext *cbor_encode_ctx; - - /* Starting from module 1, because module 0 contains general claims which - * are not related to SW module(i.e: boot_seed, etc.) - */ - for (module = 1; module < SW_MAX; ++module) { - /* Indicates to restart the look up from the beginning of the shared - * data section - */ - tlv_ptr = NULL; - - /* Look up the first TLV entry which belongs to the SW module */ - found = attest_get_tlv_by_module(module, &tlv_id, - &tlv_len, &tlv_ptr); - if (found == -1) { - return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE; - } - - if (found == 1) { - cnt++; - if (cnt == 1) { - /* Open array which stores SW components claims */ - cbor_encode_ctx = attest_token_borrow_cbor_cntxt(token_ctx); - QCBOREncode_OpenArrayInMapN(cbor_encode_ctx, - EAT_CBOR_ARM_LABEL_SW_COMPONENTS); - } - attest_add_single_sw_component(token_ctx, module, tlv_ptr); - } - } - - if (cnt != 0) { - /* Close array which stores SW components claims*/ - QCBOREncode_CloseArray(cbor_encode_ctx); - } else { - /* If there is not any SW components' measurement in the boot status - * then include this claim to indicate that this state is intentional - */ - attest_token_add_integer(token_ctx, - EAT_CBOR_ARM_LABEL_NO_SW_COMPONENTS, - (int64_t)NO_SW_COMPONENT_FIXED_VALUE); - } - - return PSA_ATTEST_ERR_SUCCESS; -} - -/*! - * \brief Static function to add boot seed claim to attestation token. - * - * \param[in] token_ctx Token encoding context - * - * \return Returns error code as specified in \ref psa_attest_err_t - */ -static enum psa_attest_err_t -attest_add_boot_seed_claim(struct attest_token_ctx *token_ctx) -{ - /* FixMe: Enforcement of 4 byte alignment can be removed as soon as memory - * type is configured in the MPU to be normal, instead of device, - * which prohibits unaligned access. - */ - __attribute__ ((aligned(4))) - uint8_t boot_seed[BOOT_SEED_SIZE]; - enum tfm_plat_err_t res; - struct useful_buf_c claim_value = {0}; - uint16_t tlv_len; - uint8_t *tlv_ptr = NULL; - int32_t found = 0; - - /* First look up BOOT_SEED in boot status, it might comes from bootloader */ - found = attest_get_tlv_by_id(BOOT_SEED, &tlv_len, &tlv_ptr); - if (found == 1) { - claim_value.ptr = tlv_ptr + SHARED_DATA_ENTRY_HEADER_SIZE; - claim_value.len = tlv_len - SHARED_DATA_ENTRY_HEADER_SIZE; - } else { - /* If not found in boot status then use callback function to get it - * from runtime SW - */ - res = tfm_plat_get_boot_seed(sizeof(boot_seed), boot_seed); - if (res != TFM_PLAT_ERR_SUCCESS) { - return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE; - } - claim_value.ptr = boot_seed; - claim_value.len = BOOT_SEED_SIZE; - } - - attest_token_add_bstr(token_ctx, - EAT_CBOR_ARM_LABEL_BOOT_SEED, - &claim_value); - - return PSA_ATTEST_ERR_SUCCESS; -} - -/* FixMe: Remove this #if when MPU will be configured properly. Currently - * in case of TFM_LVL == 3 unaligned access triggers a usage fault - * exception. - */ -#if !defined(TFM_LVL) || (TFM_LVL == 1) -/*! - * \brief Static function to add instance id claim to attestation token. - * - * \param[in] token_ctx Token encoding context - * - * \return Returns error code as specified in \ref psa_attest_err_t - */ -static enum psa_attest_err_t -attest_add_instance_id_claim(struct attest_token_ctx *token_ctx) -{ - /* FixMe: Enforcement of 4 byte alignment can be removed as soon as memory - * type is configured in the MPU to be normal, instead of device, - * which prohibits unaligned access. - */ - __attribute__ ((aligned(4))) - uint8_t instance_id[INSTANCE_ID_MAX_SIZE]; - enum tfm_plat_err_t res_plat; - uint32_t size = sizeof(instance_id); - struct useful_buf_c claim_value; - - res_plat = tfm_plat_get_instance_id(&size, instance_id); - if (res_plat != TFM_PLAT_ERR_SUCCESS) { - return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE; - } - - claim_value.ptr = instance_id; - claim_value.len = size; - attest_token_add_bstr(token_ctx, - EAT_CBOR_ARM_LABEL_UEID, - &claim_value); - - return PSA_ATTEST_ERR_SUCCESS; -} - -/*! - * \brief Static function to add implementation id claim to attestation token. - * - * \param[in] token_ctx Token encoding context - * - * \return Returns error code as specified in \ref psa_attest_err_t - */ -static enum psa_attest_err_t -attest_add_implementation_id_claim(struct attest_token_ctx *token_ctx) -{ - /* FixMe: Enforcement of 4 byte alignment can be removed as soon as memory - * type is configured in the MPU to be normal, instead of device, - * which prohibits unaligned access. - */ - __attribute__ ((aligned(4))) - uint8_t implementation_id[IMPLEMENTATION_ID_MAX_SIZE]; - enum tfm_plat_err_t res_plat; - uint32_t size = sizeof(implementation_id); - struct useful_buf_c claim_value; - - res_plat = tfm_plat_get_implementation_id(&size, implementation_id); - if (res_plat != TFM_PLAT_ERR_SUCCESS) { - return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE; - } - - claim_value.ptr = implementation_id; - claim_value.len = size; - attest_token_add_bstr(token_ctx, - EAT_CBOR_ARM_LABEL_IMPLEMENTATION_ID, - &claim_value); - - return PSA_ATTEST_ERR_SUCCESS; -} - -/*! - * \brief Static function to add hardware version claim to attestation token. - * - * \param[in] token_ctx Token encoding context - * - * \return Returns error code as specified in \ref psa_attest_err_t - */ -static enum psa_attest_err_t -attest_add_hw_version_claim(struct attest_token_ctx *token_ctx) -{ - /* FixMe: Enforcement of 4 byte alignment can be removed as soon as memory - * type is configured in the MPU to be normal, instead of device, - * which prohibits unaligned access. - */ - __attribute__ ((aligned(4))) - uint8_t hw_version[HW_VERSION_MAX_SIZE]; - enum tfm_plat_err_t res_plat; - uint32_t size = sizeof(hw_version); - struct useful_buf_c claim_value = {0}; - uint16_t tlv_len; - uint8_t *tlv_ptr = NULL; - int32_t found = 0; - - /* First look up HW version in boot status, it might comes - * from bootloader - */ - found = attest_get_tlv_by_id(HW_VERSION, &tlv_len, &tlv_ptr); - if (found == 1) { - claim_value.ptr = tlv_ptr + SHARED_DATA_ENTRY_HEADER_SIZE; - claim_value.len = tlv_len - SHARED_DATA_ENTRY_HEADER_SIZE; - } else { - /* If not found in boot status then use callback function to get it - * from runtime SW - */ - res_plat = tfm_plat_get_hw_version(&size, hw_version); - if (res_plat != TFM_PLAT_ERR_SUCCESS) { - return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE; - } - claim_value.ptr = hw_version; - claim_value.len = size; - } - - attest_token_add_tstr(token_ctx, - EAT_CBOR_ARM_LABEL_HW_VERSION, - &claim_value); - - return PSA_ATTEST_ERR_SUCCESS; -} -#endif - -/*! - * \brief Static function to add caller id claim to attestation token. - * - * \param[in] token_ctx Token encoding context - * - * \return Returns error code as specified in \ref psa_attest_err_t - */ -static enum psa_attest_err_t -attest_add_caller_id_claim(struct attest_token_ctx *token_ctx) -{ - enum psa_attest_err_t res; - int32_t caller_id; - - res = attest_get_caller_client_id(&caller_id); - if (res != PSA_ATTEST_ERR_SUCCESS) { - return res; - } - - attest_token_add_integer(token_ctx, - EAT_CBOR_ARM_LABEL_CLIENT_ID, - (int64_t)caller_id); - - return PSA_ATTEST_ERR_SUCCESS; -} - -/*! - * \brief Static function to add security lifecycle claim to attestation token. - * - * \param[in] token_ctx Token encoding context - * - * \return Returns error code as specified in \ref psa_attest_err_t - */ - -static enum psa_attest_err_t -attest_add_security_lifecycle_claim(struct attest_token_ctx *token_ctx) -{ - enum tfm_security_lifecycle_t security_lifecycle; - uint32_t slc_value; - int32_t res; - struct useful_buf_c claim_value = {0}; - uint16_t tlv_len; - uint8_t *tlv_ptr = NULL; - int32_t found = 0; - - /* First look up lifecycle state in boot status, it might comes - * from bootloader - */ - found = attest_get_tlv_by_id(SECURITY_LIFECYCLE, &tlv_len, &tlv_ptr); - if (found == 1) { - claim_value.ptr = tlv_ptr + SHARED_DATA_ENTRY_HEADER_SIZE; - claim_value.len = tlv_len - SHARED_DATA_ENTRY_HEADER_SIZE; - res = get_uint(claim_value.ptr, claim_value.len, &slc_value); - if (res) { - return PSA_ATTEST_ERR_GENERAL; - } - security_lifecycle = (enum tfm_security_lifecycle_t)slc_value; - } else { - /* If not found in boot status then use callback function to get it - * from runtime SW - */ - security_lifecycle = tfm_attest_hal_get_security_lifecycle(); - } - - /* Sanity check */ - if (security_lifecycle < TFM_SLC_UNKNOWN || - security_lifecycle > TFM_SLC_DECOMMISSIONED) { - return PSA_ATTEST_ERR_GENERAL; - } - - attest_token_add_integer(token_ctx, - EAT_CBOR_ARM_LABEL_SECURITY_LIFECYCLE, - (int64_t)security_lifecycle); - - return PSA_ATTEST_ERR_SUCCESS; -} - -/*! - * \brief Static function to add challenge claim to attestation token. - * - * \param[in] token_ctx Token encoding context - * \param[in] challenge Pointer to buffer which stores the challenge - * - * \return Returns error code as specified in \ref psa_attest_err_t - */ -static enum psa_attest_err_t -attest_add_challenge_claim(struct attest_token_ctx *token_ctx, - const struct useful_buf_c *challenge) -{ - attest_token_add_bstr(token_ctx, EAT_CBOR_ARM_LABEL_CHALLENGE, challenge); - - return PSA_ATTEST_ERR_SUCCESS; -} - -/*! - * \brief Static function to add the verification service indicator claim - * to the attestation token. - * - * \param[in] token_ctx Token encoding context - * - * \return Returns error code as specified in \ref psa_attest_err_t - */ -static enum psa_attest_err_t -attest_add_verification_service(struct attest_token_ctx *token_ctx) -{ - struct useful_buf_c service; - uint32_t size; - - service.ptr = tfm_attest_hal_get_verification_service(&size); - - if (service.ptr) { - service.len = size; - attest_token_add_tstr(token_ctx, - EAT_CBOR_ARM_LABEL_ORIGINATION, - &service); - } - - return PSA_ATTEST_ERR_SUCCESS; -} - -/*! - * \brief Static function to add the name of the profile definition document - * - * \param[in] token_ctx Token encoding context - * - * \return Returns error code as specified in \ref psa_attest_err_t - */ -static enum psa_attest_err_t -attest_add_profile_definition(struct attest_token_ctx *token_ctx) -{ - struct useful_buf_c profile; - uint32_t size; - - profile.ptr = tfm_attest_hal_get_profile_definition(&size); - - if (profile.ptr) { - profile.len = size; - attest_token_add_tstr(token_ctx, - EAT_CBOR_ARM_LABEL_PROFILE_DEFINITION, - &profile); - } - - return PSA_ATTEST_ERR_SUCCESS; -} - -/*! - * \brief Static function to verify the input challenge size - * - * Only discrete sizes are accepted. - * - * \param[in] challenge_size Size of challenge object in bytes. - * - * \retval PSA_ATTEST_ERR_SUCCESS - * \retval PSA_ATTEST_ERR_INVALID_INPUT - */ -static enum psa_attest_err_t attest_verify_challenge_size(size_t challenge_size) -{ - switch (challenge_size) { - /* Intentional fall through */ - case PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32: - case PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48: - case PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64: - case (PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32 + 4): /* Test purpose */ - return PSA_ATTEST_ERR_SUCCESS; - } - - return PSA_ATTEST_ERR_INVALID_INPUT; -} - -/*! - * \brief Static function to create the initial attestation token - * - * \param[in] challenge Structure to carry the challenge value: - * pointer + challeng's length - * \param[in] token Structure to carry the token info, where to - * create it: pointer + buffer's length - * \param[out] completed_token Structure to carry the info about the created - * token: pointer + final token's length - * - * \return Returns error code as specified in \ref psa_attest_err_t - */ -static enum psa_attest_err_t -attest_create_token(struct useful_buf_c *challenge, - struct useful_buf *token, - struct useful_buf_c *completed_token) -{ - enum psa_attest_err_t attest_err = PSA_ATTEST_ERR_SUCCESS; - enum attest_token_err_t token_err; - struct attest_token_ctx attest_token_ctx; - int32_t key_select; - uint32_t option_flags = 0; - - if (challenge->len == 36) { - /* FixMe: Special challenge with option flags appended. This might can - * be removed when the public API can take option_flags. - */ - option_flags = *(uint32_t *)((uint8_t*)challenge->ptr + 32); - challenge->len = 32; - } - - /* Lower three bits are the key select */ - key_select = option_flags & 0x7; - - /* Get started creating the token. This sets up the CBOR and COSE contexts - * which causes the COSE headers to be constructed. - */ - token_err = attest_token_start(&attest_token_ctx, - option_flags, /* option_flags */ - key_select, /* key_select */ - COSE_ALGORITHM_ES256, /* alg_select */ - token); - - if (token_err != ATTEST_TOKEN_ERR_SUCCESS) { - attest_err = error_mapping(token_err); - goto error; - } - - attest_err = attest_add_challenge_claim(&attest_token_ctx, - challenge); - if (attest_err != PSA_ATTEST_ERR_SUCCESS) { - goto error; - } - - if (!(option_flags & TOKEN_OPT_OMIT_CLAIMS)) { - attest_err = attest_add_boot_seed_claim(&attest_token_ctx); - if (attest_err != PSA_ATTEST_ERR_SUCCESS) { - goto error; - } - - attest_err = attest_add_verification_service(&attest_token_ctx); - if (attest_err != PSA_ATTEST_ERR_SUCCESS) { - goto error; - } - - attest_err = attest_add_profile_definition(&attest_token_ctx); - if (attest_err != PSA_ATTEST_ERR_SUCCESS) { - goto error; - } - - /* FixMe: Remove this #if when MPU will be configured properly. - * Currently in case of TFM_LVL == 3 unaligned access triggers - * a usage fault exception. - */ -#if !defined(TFM_LVL) || (TFM_LVL == 1) - attest_err = attest_add_instance_id_claim(&attest_token_ctx); - if (attest_err != PSA_ATTEST_ERR_SUCCESS) { - goto error; - } - - attest_err = attest_add_hw_version_claim(&attest_token_ctx); - if (attest_err != PSA_ATTEST_ERR_SUCCESS) { - goto error; - } - - attest_err = attest_add_implementation_id_claim(&attest_token_ctx); - if (attest_err != PSA_ATTEST_ERR_SUCCESS) { - goto error; - } -#endif - - attest_err = attest_add_caller_id_claim(&attest_token_ctx); - if (attest_err != PSA_ATTEST_ERR_SUCCESS) { - goto error; - } - - attest_err = attest_add_security_lifecycle_claim(&attest_token_ctx); - if (attest_err != PSA_ATTEST_ERR_SUCCESS) { - goto error; - } - - attest_err = attest_add_all_sw_components(&attest_token_ctx); - if (attest_err != PSA_ATTEST_ERR_SUCCESS) { - goto error; - } - } - - /* Finish up creating the token. This is where the actual signature - * is generated. This finishes up the CBOR encoding too. - */ - token_err = attest_token_finish(&attest_token_ctx, completed_token); - if (token_err) { - attest_err = error_mapping(token_err); - goto error; - } - -error: - return attest_err; -} - -/* Limitations of the current implementation: - * - Token is not signed yet properly, just a fake signature is added to the - * token due to lack of psa_sign_hash() implementation in crypto - * service. - */ -enum psa_attest_err_t -initial_attest_get_token(const psa_invec *in_vec, uint32_t num_invec, - psa_outvec *out_vec, uint32_t num_outvec) -{ - enum psa_attest_err_t attest_err = PSA_ATTEST_ERR_SUCCESS; - struct useful_buf_c challenge; - struct useful_buf token; - struct useful_buf_c completed_token; - - challenge.ptr = in_vec[0].base; - challenge.len = in_vec[0].len; - token.ptr = out_vec[0].base; - token.len = out_vec[0].len; - - attest_err = attest_verify_challenge_size(challenge.len); - if (attest_err != PSA_ATTEST_ERR_SUCCESS) { - goto error; - } - - attest_err = attest_check_memory_access((void *)challenge.ptr, - challenge.len, - TFM_ATTEST_ACCESS_RO); - if (attest_err != PSA_ATTEST_ERR_SUCCESS) { - goto error; - } - - attest_err = attest_check_memory_access(token.ptr, - token.len, - TFM_ATTEST_ACCESS_RW); - if (attest_err != PSA_ATTEST_ERR_SUCCESS) { - goto error; - } - - attest_err = attest_create_token(&challenge, &token, &completed_token); - if (attest_err != PSA_ATTEST_ERR_SUCCESS) { - goto error; - } - - out_vec[0].base = (void *)completed_token.ptr; - out_vec[0].len = completed_token.len; - -error: - return attest_err; -} - -/* Initial implementation, just returns with hard coded value */ -enum psa_attest_err_t -initial_attest_get_token_size(const psa_invec *in_vec, uint32_t num_invec, - psa_outvec *out_vec, uint32_t num_outvec) -{ - enum psa_attest_err_t attest_err = PSA_ATTEST_ERR_SUCCESS; - uint32_t challenge_size = *(uint32_t *)in_vec[0].base; - uint32_t *token_buf_size = (uint32_t *)out_vec[0].base; - struct useful_buf_c challenge; - struct useful_buf token; - struct useful_buf_c completed_token; - - /* Only the size of the challenge is needed */ - challenge.ptr = NULL; - challenge.len = challenge_size; - - /* Special value to get the size of the token, but token is not created */ - token.ptr = NULL; - token.len = INT32_MAX; - - if (out_vec[0].len < sizeof(uint32_t)) { - attest_err = PSA_ATTEST_ERR_INVALID_INPUT; - goto error; - } - - attest_err = attest_verify_challenge_size(challenge_size); - if (attest_err != PSA_ATTEST_ERR_SUCCESS) { - goto error; - } - - attest_err = attest_create_token(&challenge, &token, &completed_token); - if (attest_err != PSA_ATTEST_ERR_SUCCESS) { - goto error; - } - - *token_buf_size = completed_token.len; - -error: - return attest_err; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/CMakeLists.txt b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/CMakeLists.txt deleted file mode 100644 index e1f1985..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/CMakeLists.txt +++ /dev/null @@ -1,40 +0,0 @@ -#------------------------------------------------------------------------------- -# Copyright (c) 2019, Arm Limited. All rights reserved. -# -# SPDX-License-Identifier: BSD-3-Clause -# -#------------------------------------------------------------------------------- - -cmake_minimum_required(VERSION 3.7) - -#Tell cmake where our modules can be found -list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/../../../cmake) - -#Include common stuff to control cmake. -include("Common/BuildSys") - -#Start an embedded project. -embedded_project_start(CONFIG "${CMAKE_CURRENT_LIST_DIR}/../../ConfigDefault.cmake") -project(tfm_t_cose LANGUAGES C) -embedded_project_fixup() - -#Some project global settings -set(T_COSE_DIR "${CMAKE_CURRENT_LIST_DIR}") - -#Append all our source files to global lists. -list(APPEND ALL_SRC_C - "${T_COSE_DIR}/src/t_cose_sign1_sign.c" - "${T_COSE_DIR}/src/t_cose_util.c" - "${T_COSE_DIR}/src/t_cose_psa_crypto.c" - ) - -#Setting include directories -embedded_include_directories(PATH ${T_COSE_DIR}/inc ABSOLUTE) - -#Specify what we build (for the t_cose, build as an object library) -add_library(${PROJECT_NAME} OBJECT ${ALL_SRC_C}) - -#Set common compiler flags -config_setting_shared_compiler_flags(${PROJECT_NAME}) - -embedded_project_end(${PROJECT_NAME}) diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/README.md b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/README.md deleted file mode 100644 index 9501806..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/README.md +++ /dev/null @@ -1,95 +0,0 @@ -# t_cose - -## Introduction - -t_cose is a partial implementation of the COSE standard (RFC 8152). -COSE is quite a large standard so a full implementation of all of it -is a large undertaking. This implementation is starting out as just -enough for attestation and maybe CWT (Cbor Web Token) which is very -similar. - -As it may grow to support more of COSE over time, it is structured -with that in mind. - -It is also trying to be portable, the most interesting part of which -is interfacing with the libraries for performing cryptography and -access cryptographic keys. - -## Source files -The following files are more or less the public interface. -* t_cose_common.h -* t_cose_sign1.h -* t_cose_sign1_verify.h - -The rest of the files are internal source files that callers should -not depend on. - -t_cose_defines.h contains contants from RFC 8152 that are -part of the COSE standard. It should never have anything else -in it. - -t_cose_util is some utilities and code common to -signing and verification. Both signing and verifcation -depend on it. - -t_cose_crypto is the crypto porting layer. Generally -the .h file should not need to change for a new -platform. The .c file will be changed lots for -each new platform. - -## Dependency and Portability -t_cose is attempting to be very portable and -have a minmum number of #ifdefs. It is -designed to run 64-bit and 32-bit machines. - -It uses a minimum number of standard C -libraries, mostly just , and . - -It uses QCBOR for CBOR encoding and decoding. -QCBOR is very portable. - -### Cryptography and Keys -There is a cryptographic adaption layer that -provides the following: -* Impedence match of parameters passed to/from the crypto -* Management of algorithm identifiers -* Management of error codes -* Management of key identifiers - -It is framed for the needs of t_cose, and is -not trying to be any kind of general crypto API. - -#### Question -Q: How many crypto APIs does it take to screw in a light bulb? -A: One more than it takes to screw in a light bulb. - -## Copyright and License - -### BSD-3-Clause license - -* Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. - -* Neither the name of the copyright holder nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -### Copyright for this README - -Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/inc/t_cose_common.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/inc/t_cose_common.h deleted file mode 100644 index d509a4b..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/inc/t_cose_common.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - * t_cose_common.h - * - * Copyright 2019, Laurence Lundblade - * - * SPDX-License-Identifier: BSD-3-Clause - * - * See BSD-3-Clause license in README.mdE. - */ - - -#ifndef __T_COSE_COMMON_H__ -#define __T_COSE_COMMON_H__ - - -/** - * \file t_cose_common.h - * - * \brief Defines common to all public t_cose interfaces. - * - */ - - -/* Private value. Intentionally not documented for Doxygen. - * This is the size allocated for the encoded protected headers. It - * needs to be big enough for make_protected_header() to succeed. It - * currently sized for one header with an algorithm ID up to 32 bits - * long -- one byte for the wrapping map, one byte for the label, 5 - * bytes for the ID. If this is made accidentially too small, QCBOR will - * only return an error, and not overrun any buffers. - * - * 9 extra bytes are added, rounding it up to 16 total, in case some - * other protected header is to be added. - */ -#define T_COSE_SIGN1_MAX_PROT_HEADER (1+1+5+9) - - -/** - * Error codes return by t_cose. - * - * Do not reorder these. It is OK to add - * new ones at the end. - */ -enum t_cose_err_t { - /** - * Operation completed successfully - */ - T_COSE_SUCCESS = 0, - /** - * The requested signing algorithm is not supported. - */ - T_COSE_ERR_UNSUPPORTED_SIGNING_ALG, - /** - * Error constructing the protected headers. - */ - T_COSE_ERR_PROTECTED_HEADERS, - /** - * The hash algorithm needed is not supported. Note that the - * signing algorithm identifier usually identifies the hash - * algorithm. - */ - T_COSE_ERR_UNSUPPORTED_HASH, - /** - * Some system failure when running the hash algorithm. - */ - T_COSE_ERR_HASH_GENERAL_FAIL, - /** - * The buffer to receive a hash result is too small. - */ - T_COSE_ERR_HASH_BUFFER_SIZE, - /** - * The buffer to receive result of a signing operation is too - * small. - */ - T_COSE_ERR_SIG_BUFFER_SIZE, - /** - * The buffer to receive to receive a key is too small. - */ - T_COSE_ERR_KEY_BUFFER_SIZE, - /** - * When verifying a \c COSE_Sign1, something is wrong with the - * format of the CBOR. For example, it is missing something like - * the payload. - */ - T_COSE_ERR_SIGN1_FORMAT, - /** - * When decoding some CBOR like a \c COSE_Sign1, the CBOR was not - * well-formed. Most likely what was supposed to be CBOR was is - * either not or it has been corrupted. - */ - T_COSE_ERR_CBOR_NOT_WELL_FORMED, - /** - * No algorithm ID was found when one is needed. For example, when - * verifying a \c COSE_Sign1. - */ - T_COSE_ERR_NO_ALG_ID, - /** - * No key ID was found when one is needed. For example, when - * verifying a \c COSE_Sign1. - */ - T_COSE_ERR_NO_KID, - /** - * Signature verification failed. For example, the cryptographic - * operations completed successfully but hash wasn't as expected. - */ - T_COSE_ERR_SIG_VERIFY, - /** - * Verification of a short-circuit signature failed. - */ - T_COSE_ERR_BAD_SHORT_CIRCUIT_KID, - /** - * Some (unspecified) argument was not valid. - */ - T_COSE_ERR_INVALID_ARGUMENT, - /** - * Out of heap memory. - */ - T_COSE_ERR_INSUFFICIENT_MEMORY, - /** - * General unspecific failure. - */ - T_COSE_ERR_FAIL, - /** - * Equivalent to \c PSA_ERROR_TAMPERING_DETECTED. - */ - T_COSE_ERR_TAMPERING_DETECTED, - /** - * The key identified by a key slot of a key ID was not found. - */ - T_COSE_ERR_UNKNOWN_KEY, - /** - * The key was found, but it was the wrong type for the operation. - */ - T_COSE_ERR_WRONG_TYPE_OF_KEY, - /** - * Error constructing the \c Sig_structure when signing or verify. - */ - T_COSE_ERR_SIG_STRUCT, - /** - * Signature was short-circuit. THe option to allow verification - * of short-circuit signatures was not set - */ - T_COSE_ERR_SHORT_CIRCUIT_SIG -}; - - - -#endif /* __T_COSE_COMMON_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/inc/t_cose_sign1_sign.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/inc/t_cose_sign1_sign.h deleted file mode 100644 index 35b26e5..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/inc/t_cose_sign1_sign.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - * t_cose_sign1_sign.h - * - * Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * See BSD-3-Clause license in README.md - */ - -#ifndef __T_COSE_SIGN1_H__ -#define __T_COSE_SIGN1_H__ - -#include -#include -#include "qcbor.h" -#include "t_cose_common.h" - - -/** - * \file t_cose_sign1_sign.h - * - * \brief Create a \c COSE_Sign1, usually for EAT or CWT Token. - * - * This creates a \c COSE_Sign1 in compliance with [COSE (RFC 8152)] - * (https://tools.ietf.org/html/rfc8152). A \c COSE_Sign1 is a CBOR - * encoded binary blob that contains headers, a payload and a - * signature. Usually the signature is made with an EC signing - * algorithm like ECDSA. - * - * This implementation is intended to be small and portable to - * different OS's and platforms. Its dependencies are: - * - QCBOR - * - , , - * - Hash functions like SHA-256 - * - Signing functions like ECDSA - * - * There is a cryptographic adaptation layer defined in - * t_cose_crypto.h. An implementation can be made of the functions in - * it for different platforms or OS's. This means that different - * platforms and OS's may support only signing with a particular set - * of algorithms. - * - * This \c COSE_Sign1 implementations is optimized for creating EAT - * tokens. - * - * It should work for CWT and others use cases too. The main point of - * the optimization is that only one output buffer is needed. There is - * no need for one buffer to hold the payload and another to hold the - * end result \c COSE_Sign1. The payload is encoded right into its final - * place in the end result \c COSE_Sign1. - */ - - -/** - * This is the context for creating a \c COSE_Sign1 structure. The caller - * should allocate it and pass it to the functions here. This is - * about 32 bytes so it fits easily on the stack. - */ -struct t_cose_sign1_ctx { - /* Private data structure */ - uint8_t buffer_for_protected_headers[ - T_COSE_SIGN1_MAX_PROT_HEADER]; - struct useful_buf_c protected_headers; - int32_t cose_algorithm_id; - int32_t key_select; - bool short_circuit_sign; - QCBOREncodeContext *cbor_encode_ctx; -}; - - -/** - * \brief Initialize to start creating a \c COSE_Sign1. - * - * \param[in] me The t_cose signing context. - * \param[in] short_circuit_sign \c true to select special test mode. - * \param[in] cose_algorithm_id The algorithm to sign with. The IDs are - * defined in [COSE (RFC 8152)] - * (https://tools.ietf.org/html/rfc8152) or - * in the [IANA COSE Registry] - * (https://www.iana.org/assignments/cose/cose.xhtml). - * \param[in] key_select Which signing key to use. - * \param[in] cbor_encode_ctx The CBOR encoder context to output to. - * - * \return This returns one of the error codes defined by \ref t_cose_err_t. - * - * It is possible to use this to compute the exact size of the - * resulting token so the exact sized buffer can be allocated. To do - * this initialize the \c cbor_encode_ctx with \c UsefulBufC that has - * a \c NULL pointer and large length like \c UINT32_MAX. Then run the - * normal token creation. The result will have a NULL pointer and the - * length of the token that would have been created. When this is run - * like this, the cryptographic functions will not actually run, but - * the size of their output will be taken into account. - * - * The key selection depends on the platform / OS. - * - * Which signing algorithms are supported depends on the platform/OS. - * The header file t_cose_defines.h contains defined constants for - * some of them. A typical example is \ref COSE_ALGORITHM_ES256 which - * indicates ECDSA with the NIST P-256 curve and SHA-256. - * - * To use this, create a \c QCBOREncodeContext and initialize it with - * an output buffer big enough to hold the payload and the COSE Sign 1 - * overhead. This overhead is about 30 bytes plus the size of the - * signature and the size of the key ID. - * - * After the \c QCBOREncodeContext is initialized, call - * t_cose_sign1_init() on it. - * - * Next call \c QCBOREncode_BstrWrap() to indicate the start of the - * payload. - * - * Next call various \c QCBOREncode_Addxxxx() methods to create the - * payload. - * - * Next call \c QCBOREncode_CloseBstrWrap() to indicate the end of the - * payload. This will also return a pointer and length of the payload - * that gets hashed. - * - * Next call t_cose_sign1_finish() with the pointer and length of the - * payload. This will do all the cryptography and complete the COSE - * Sign1. - * - * Finally, call \c QCBOREncode_Finish() to get the pointer and length - * of the complete token. - * - * This implements a special signing test mode called _short_ - * _circuit_ _signing_. This mode is useful when there is no signing - * key available, perhaps because it has not been provisioned or - * configured for the particular device. It may also be because the - * public key cryptographic functions have not been connected up in - * the cryptographic adaptation layer. - * - * It has no value for security at all. Data signed this way should - * not be trusted as anyone can sign like this. - * - * In this mode the signature is the hash of that would normally be - * signed by the public key algorithm. To make the signature the - * correct size for the particular algorithm instances of the hash are - * concatenated to pad it out. - * - * This mode is very useful for testing because all the code except - * the actual signing algorithm is run exactly as it would if a proper - * signing algorithm was run. - * - * The kid (Key ID) put in the unprotected headers is created as - * follows. The EC public key is CBOR encoded as a \c COSE_Key as - * defined in the COSE standard. That encoded CBOR is then - * hashed with SHA-256. This is similar to key IDs defined in IETF - * PKIX, but is based on COSE and CBOR rather than ASN.1. - */ -enum t_cose_err_t t_cose_sign1_init(struct t_cose_sign1_ctx *me, - bool short_circuit_sign, - int32_t cose_algorithm_id, - int32_t key_select, - QCBOREncodeContext *cbor_encode_ctx); - - -/** - * \brief Finish creation of the \c COSE_Sign1. - * - * \param[in] me The t_cose signing context. - * \param[in] payload The pointer and length of the payload. - * - * \return This returns one of the error codes defined by \ref t_cose_err_t. - * - * Call this to complete creation of a signed token started with - * t_cose_sign1_init(). - * - * This is when the signature algorithm is run. - * - * The payload parameter is used only to compute the hash for - * signing. The completed \c COSE_Sign1 is retrieved from the \c - * cbor_encode_ctx by calling \c QCBOREncode_Finish() - */ -enum t_cose_err_t t_cose_sign1_finish(struct t_cose_sign1_ctx *me, - struct useful_buf_c payload); - - -#endif /* __T_COSE_SIGN1_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/src/t_cose_crypto.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/src/t_cose_crypto.h deleted file mode 100644 index ab4faac..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/src/t_cose_crypto.h +++ /dev/null @@ -1,413 +0,0 @@ -/* - * t_cose_crypto.h - * - * Copyright 2019, Laurence Lundblade - * - * SPDX-License-Identifier: BSD-3-Clause - * - * See BSD-3-Clause license in README.mdE. - */ - - -#ifndef __T_COSE_CRYPTO_H__ -#define __T_COSE_CRYPTO_H__ - -#include "t_cose_common.h" -#include "useful_buf.h" -#include -#include "t_cose_defines.h" - - -/** - * \file t_cose_crypto.h - * - * \brief This is the adaptation layer for cryptographic functions used by - * t_cose. - * - * This is small wrapper around the cryptographic functions to: - * - Map COSE algorithm IDs to TF-M algorithm IDs - * - Map crypto errors to \ref t_cose_err_t errors - * - Have inputs and outputs be \c struct \c useful_buf_c and - * \c struct \c useful_buf - * - Handle key selection - * - * The idea is that implementations can be made of these functions - * that adapt to various cryptographic libraries that are used on - * various platforms and OSs. - * - * This runs entirely off of COSE-style algorithm identifiers. They - * are simple integers and thus work nice as function parameters. An - * initial set is defined by [COSE (RFC 8152)] - * (https://tools.ietf.org/html/rfc8152). New ones can be registered - * in the [IANA COSE Registry] - * (https://www.iana.org/assignments/cose/cose.xhtml). Local use new - * ones can also be defined (\c \#define) if what is needed is not in - * the IANA registry. - * - * Binary data is returned to the caller using a \c struct \c - * useful_buf to pass the buffer to receive the data and its length in - * and a \c useful_buf_c to return the pointer and length of the - * returned data. The point of this is coding hygiene. The buffer - * passed in is not const as it is to be modified. The \c - * useful_buf_c returned is const. - * - * The pointer in the \c useful_buf_c will always point to the buffer - * passed in via the \c useful_buf so the lifetime of the data is - * under control of the caller. - * - * This is not intended as any sort of general cryptographic API. It - * is just the functions needed by t_cose in the form that is most - * useful for t_cose. - */ - - -/** - * Size of the signature output for the NIST P-256 Curve. - */ -#define T_COSE_EC_P256_SIG_SIZE 64 - -/** - * Size of the largest signature of any of the algorithm types - * supported. - * - * This will have to be adjusted if support for other algorithms - * larger is added. - * - * This is a compile time constant so it can be used to define stack - * variable sizes. - */ -#define T_COSE_MAX_EC_SIG_SIZE T_COSE_EC_P256_SIG_SIZE - - -/** - * \brief Get the size in bytes of a particular signature type. - * - * \param[in] cose_sig_alg_id The COSE algorithm ID. - * - * \return The size in bytes of the signature for a public-key signing - * algorithm. - */ -static inline size_t t_cose_signature_size(int32_t cose_sig_alg_id); - - -/** - * \brief Perform public key signing. Part of the t_cose crypto - * adaptation layer. - * - * \param[in] cose_alg_id The algorithm to sign with. The IDs are - * defined in [COSE (RFC 8152)] - * (https://tools.ietf.org/html/rfc8152) or - * in the [IANA COSE Registry] - * (https://www.iana.org/assignments/cose/cose.xhtml). - * A proprietary ID can also be defined - * locally (\c \#define) if the needed - * one hasn't been registered. - * \param[in] key_select Indicates which key to use to sign. - * \param[in] hash_to_sign The bytes to sign. Typically, a hash of - * a payload. - * \param[in] signature_buffer Pointer and length of buffer into which - * the resulting signature is put. - * \param[in] signature Pointer and length of the signature - * returned. - * - * \retval T_COSE_SUCCESS - * Successfully created the signature. - * \retval T_COSE_ERR_SIG_BUFFER_SIZE - * The \c signature_buffer too small. - * \retval T_COSE_ERR_UNSUPPORTED_SIGNING_ALG - * The requested signing algorithm, \c cose_alg_id, is not - * supported. - * \retval T_COSE_ERR_UNKNOWN_KEY - * The key identified by \c key_select was not found. - * \retval T_COSE_ERR_WRONG_TYPE_OF_KEY - * The key was found, but it was the wrong type. - * \retval T_COSE_ERR_INVALID_ARGUMENT - * Some (unspecified) argument was not valid. - * \retval T_COSE_ERR_INSUFFICIENT_MEMORY - * Insufficient heap memory. - * \retval T_COSE_ERR_FAIL - * General unspecific failure. - * \retval T_COSE_ERR_TAMPERING_DETECTED - * Equivalent to \c PSA_ERROR_TAMPERING_DETECTED. - * - * This is called to do public key signing. The implementation will - * vary from one platform / OS to another but should conform to the - * description here. - * - * The key selection depends on the platform / OS. - * - * See the note in the Detailed Description (the \\file comment block) - * for details on how \c useful_buf and \c useful_buf_c are used to - * return the signature. - * - * To find out the size of the signature buffer needed, call this with - * \c signature_buffer->ptr \c NULL and \c signature_buffer->len a - * very large number like \c UINT32_MAX. The size will be returned in - * \c signature->len. - */ -enum t_cose_err_t -t_cose_crypto_pub_key_sign(int32_t cose_alg_id, - int32_t key_select, - struct useful_buf_c hash_to_sign, - struct useful_buf signature_buffer, - struct useful_buf_c *signature); - - -/** - * \brief perform public key signature verification. Part of the - * t_cose crypto adaptation layer. - * - * \param[in] cose_alg_id The algorithm to use for verification. - * The IDs are defined in [COSE (RFC 8152)] - * (https://tools.ietf.org/html/rfc8152) - * or in the [IANA COSE Registry] - * (https://www.iana.org/assignments/cose/cose.xhtml). - * A proprietary ID can also be defined - * locally (\c \#define) if the needed one - * hasn't been registered. - * \param[in] key_select Verification key selection. - * \param[in] key_id A key id or \c NULL_USEFUL_BUF_C. - * \param[in] hash_to_verify The data or hash that is to be verified. - * \param[in] signature The signature. - * - * This verifies that the \c signature passed in was over the \c - * hash_to_verify passed in. - * - * The public key used to verify the signature is selected by the \c - * key_id if it is not \c NULL_USEFUL_BUF_C or the \c key_select if it - * is. - * - * The key selected must be, or include, a public key of the correct - * type for \c cose_alg_id. - * - * \retval T_COSE_SUCCESS - * The signature is valid - * \retval T_COSE_ERR_SIG_VERIFY - * Signature verification failed. For example, the - * cryptographic operations completed successfully but hash - * wasn't as expected. - * \retval T_COSE_ERR_UNKNOWN_KEY - * The key identified by \c key_select or a \c kid was - * not found. - * \retval T_COSE_ERR_WRONG_TYPE_OF_KEY - * The key was found, but it was the wrong type - * for the operation. - * \retval T_COSE_ERR_UNSUPPORTED_SIGNING_ALG - * The requested signing algorithm is not supported. - * \retval T_COSE_ERR_INVALID_ARGUMENT - * Some (unspecified) argument was not valid. - * \retval T_COSE_ERR_INSUFFICIENT_MEMORY - * Out of heap memory. - * \retval T_COSE_ERR_FAIL - * General unspecific failure. - * \retval T_COSE_ERR_TAMPERING_DETECTED - * Equivalent to \c PSA_ERROR_TAMPERING_DETECTED. - */ -enum t_cose_err_t -t_cose_crypto_pub_key_verify(int32_t cose_alg_id, - int32_t key_select, - struct useful_buf_c key_id, - struct useful_buf_c hash_to_verify, - struct useful_buf_c signature); - - -/** - * The size of X and Y coordinate in 2 parameter style EC public - * key. Format is as defined in [COSE (RFC 8152)] - * (https://tools.ietf.org/html/rfc8152) and [SEC 1: Elliptic Curve - * Cryptography](http://www.secg.org/sec1-v2.pdf). - * - * This size is well-known and documented in public standards. - */ -#define T_COSE_CRYPTO_EC_P256_COORD_SIZE 32 - - -/** - * \brief Get an elliptic curve public key. Part of the t_cose crypto - * adaptation layer. - * - * \param[in] key_select Used to look up the public - * key to return when \c kid is - * \c NULL_USEFUL_BUF_C. - * \param[in] kid A key ID to look up against. May be - * \c NULL_USEFUL_BUF_C. This is typically - * the kid from the COSE unprotected header. - * \param[out] cose_curve_id The curve ID of the key returned as - * defined by [COSE (RFC 8152)] - * (https://tools.ietf.org/html/rfc8152) - * or the IANA COSE registry. - * \param[in] buf_to_hold_x_coord Pointer and length into which the - * X coordinate is put. - * \param[in] buf_to_hold_y_coord Pointer and length into which the - * Y coordinate is put. - * \param[out] x_coord Pointer and length of the returned X - * coordinate. - * \param[out] y_coord Pointer and length of the returned Y - * coordinate. - * - * \retval T_COSE_SUCCESS - * The key was found and is returned. - * \retval T_COSE_ERR_UNKNOWN_KEY - * The key identified by \c key_select or a \c kid was not - * found. - * \retval T_COSE_ERR_WRONG_TYPE_OF_KEY - * The key was found, but it was the wrong type for the - * operation. - * \retval T_COSE_ERR_FAIL - * General unspecific failure. - * \retval T_COSE_ERR_KEY_BUFFER_SIZE - * Buffer to hold the output was too small. - * - * This finds and returns a public key. Where it looks for the key is - * dependent on the OS / platform. - * - * \ref T_COSE_CRYPTO_EC_P256_COORD_SIZE is the size of the X or Y - * coordinate for the NIST P-256 curve. - * - * See the note in the Detailed Description (the \\file comment block) - * for details on how \c useful_buf and \c useful_buf_c are used to - * return the X and Y coordinates. - */ -enum t_cose_err_t -t_cose_crypto_get_ec_pub_key(int32_t key_select, - struct useful_buf_c kid, - int32_t *cose_curve_id, - struct useful_buf buf_to_hold_x_coord, - struct useful_buf buf_to_hold_y_coord, - struct useful_buf_c *x_coord, - struct useful_buf_c *y_coord); - - -/* - * No function to get private key because there is no need for it. - * The private signing key only needs to exist behind - * t_cose_crypto_pub_key_sign(). - */ - - - - -/** - * The context for use with the hash adaptation layer here. - */ -struct t_cose_crypto_hash { - /* Can't put the actual size here without creating dependecy on - * actual hash implementation, so this is a fairly large and - * accommodating size. - */ - uint8_t bytes[280]; -}; - - -/** - * The size of the output of SHA-256 in bytes. - * - * (It is safe to define this independently here as its size is - * well-known and fixed. There is no need to reference - * platform-specific headers and incur messy dependence.) - */ -#define T_COSE_CRYPTO_SHA256_SIZE 32 - - -/** - * \brief Start cryptographic hash. Part of the t_cose crypto - * adaptation layer. - * - * \param[in,out] hash_ctx Pointer to the hash context that - * will be initialized. - * \param[in] cose_hash_alg_id Algorithm ID that identifies the - * hash to use. This is from the - * [IANA COSE Registry] - * (https://www.iana.org/assignments/cose/cose.xhtml). - * As of the creation of this interface - * no identifiers of only a hash - * functions have been registered. - * Signature algorithms that include - * specification of the hash have been - * registered, but they are not to be - * used here. Until hash functions only - * have been officially registered, some - * IDs are defined in the proprietary - * space in t_cose_common.h. - * - * \retval T_COSE_ERR_UNSUPPORTED_HASH - * The requested algorithm is unknown or unsupported. - * - * \retval T_COSE_ERR_HASH_GENERAL_FAIL - * Some general failure of the hash function - * - * This initializes the hash context for the particular algorithm. It - * must be called first. A \c hash_ctx can be reused if it is - * reinitialized. - */ -enum t_cose_err_t -t_cose_crypto_hash_start(struct t_cose_crypto_hash *hash_ctx, - int32_t cose_hash_alg_id); - - -/** - * \brief Feed data into a cryptographic hash. Part of the t_cose - * crypto adaptation layer. - * - * \param[in,out] hash_ctx Pointer to the hash context in which - * accumulate the hash. - * \param[in] data_to_hash Pointer and length of data to feed into - * hash. The pointer may by \c NULL in which - * case no hashing is performed. - * - * There is no return value. If an error occurs it is remembered in \c - * hash_ctx and returned when t_cose_crypto_hash_finish() is called. - * Once in the error state, this function may be called, but it will - * not do anything. - */ -void t_cose_crypto_hash_update(struct t_cose_crypto_hash *hash_ctx, - struct useful_buf_c data_to_hash); - - -/** - * \brief Finish a cryptographic hash. Part of the t_cose crypto - * adaptation layer. - * - * \param[in,out] hash_ctx Pointer to the hash context. - * \param[in] buffer_to_hold_result Pointer and length into which - * the resulting hash is put. - * \param[out] hash_result Pointer and length of the - * resulting hash. - * - * \retval T_COSE_ERR_HASH_GENERAL_FAIL - * Some general failure of the hash function. - * \retval T_COSE_ERR_HASH_BUFFER_SIZE - * The size of the buffer to hold the hash result was - * too small. - * - * Call this to complete the hashing operation. If the everything - * completed correctly, the resulting hash is returned. Note that any - * errors that occurred during t_cose_crypto_hash_update() are - * returned here. - * - * See the note in the Detailed Description (the \\file comment block) - * for details on how \c useful_buf and \c useful_buf_c are used to - * return the hash. - */ -enum t_cose_err_t -t_cose_crypto_hash_finish(struct t_cose_crypto_hash *hash_ctx, - struct useful_buf buffer_to_hold_result, - struct useful_buf_c *hash_result); - - - -/* - * Public inline function. See documentation above. - */ -static inline size_t t_cose_signature_size(int32_t cose_sig_alg_id) -{ - switch(cose_sig_alg_id) { - case COSE_ALGORITHM_ES256: - return T_COSE_EC_P256_SIG_SIZE; - default: - return T_COSE_EC_P256_SIG_SIZE; - } -} - - -#endif /* __T_COSE_CRYPTO_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/src/t_cose_defines.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/src/t_cose_defines.h deleted file mode 100644 index e2cc970..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/src/t_cose_defines.h +++ /dev/null @@ -1,291 +0,0 @@ -/* - * t_cose_defines.h - * - * Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * See BSD-3-Clause license in README.md - */ - -#ifndef __T_COSE_DEFINES_H__ -#define __T_COSE_DEFINES_H__ - -/** - * \file t_cose_defines.h - * - * \brief Constants from COSE standard and IANA registry. - * - * This file contains constants identifiers defined in [COSE (RFC - * 8152)] (https://tools.ietf.org/html/rfc8152) and [IANA COSE - * Registry] (https://www.iana.org/assignments/cose/cose.xhtml). They - * include algorithm IDs and other constants. - * - * Many constants in the IANA registry are not included here yet as - * they are not needed by t_cose. They can be added if they become - * needed. - */ - - - - -/* --------------- COSE Header parameters ----------- - * https://www.iana.org/assignments/cose/cose.xhtml#header-parameters - */ - -/** - * \def COSE_HEADER_PARAM_ALG - * - * \brief Label of COSE header that indicates an algorithm. - */ -#define COSE_HEADER_PARAM_ALG 1 - -/** - * \def COSE_HEADER_PARAM_KID - * - * \brief Label of COSE header that contains a key ID. - */ -#define COSE_HEADER_PARAM_KID 4 - - - - -/* ------------ COSE Header Algorithm Parameters -------------- - * https://www.iana.org/assignments/cose/cose.xhtml#header-algorithm-parameters - * - * None of these are defined here yet, as they are not needed by t_cose yet. - */ - - - - -/* ------------- COSE Algorithms ---------------------------- - * https://www.iana.org/assignments/cose/cose.xhtml#algorithms - */ - -/** - * \def COSE_ALGORITHM_ES256 - * - * \brief Indicates ECDSA with SHA-256. - * - * Value for \ref COSE_HEADER_PARAM_ALG to indicate ECDSA. w/SHA-256 - */ -#define COSE_ALGORITHM_ES256 -7 - -/** - * \def COSE_ALGORITHM_ES384 - * - * \brief Indicates ECDSA with SHA-384. - * - * Value for \ref COSE_HEADER_PARAM_ALG to indicate ECDSA. w/SHA-384 - */ -#define COSE_ALGORITHM_ES384 -35 - -/** - * \def COSE_ALGORITHM_ES512 - * - * \brief Indicates ECDSA with SHA-384. - * - * Value for \ref COSE_HEADER_PARAM_ALG to indicate ECDSA. w/SHA-512 - */ -#define COSE_ALGORITHM_ES512 -36 - - -/** - * \def COSE_ALG_SHA256_PROPRIETARY - * - * \brief COSE-style algorithm ID for SHA256. The official COSE - * algorithm registry doesn't yet define an ID for a pure hash - * function. One is needed for internal use, so this is defined. - * - * This is only used internally in the implementation and doesn't - * appear in any protocol messages so there are no interoperability - * issues. When this gets defined in the IANA registry, that value can - * be substituted here and all will work fine. - */ -#define COSE_ALG_SHA256_PROPRIETARY -72000 - - - - -/* ---------- COSE Key Common Parameters -------------- - * https://www.iana.org/assignments/cose/cose.xhtml#key-common-parameters - */ - -/** - * \def COSE_KEY_COMMON_KTY - * - * \brief Label for data item containing the key type. - * - * In a \c COSE_Key, label that indicates the data item containing the - * key type. - */ -#define COSE_KEY_COMMON_KTY 1 - -/** - * \def COSE_KEY_COMMON_KID - * - * \brief Label for data item containing the key's kid. - * - * In a \c COSE_Key, label that indicates the data item containing the - * kid of this key. - */ -#define COSE_KEY_COMMON_KID 2 - - - - -/* ---------- COSE Key Type Parameters -------------------- - * https://www.iana.org/assignments/cose/cose.xhtml#key-type-parameters - */ - -/** - * \def COSE_KEY_PARAM_CRV - * - * \brief Label for data item indicating EC curve. - * - * In a \c COSE_Key that holds an EC key of either type \ref - * COSE_KEY_TYPE_EC2 or \ref COSE_KEY_TYPE_OKP this labels the data - * item with the EC curve for the key. - */ -#define COSE_KEY_PARAM_CRV -1 - -/** - * \def COSE_KEY_PARAM_X_COORDINATE - * - * \brief Label for data item that is an X coordinate of an EC key. - * - * In a \c COSE_Key that holds an EC key, this is label that indicates - * the data item containing the X coordinate. - * - * This is used for both key types \ref COSE_KEY_TYPE_EC2 and \ref - * COSE_KEY_TYPE_OKP. - */ -#define COSE_KEY_PARAM_X_COORDINATE -2 - -/** - * \def COSE_KEY_PARAM_Y_COORDINATE - * - * \brief Label for data item that is a y coordinate of an EC key. - * - * In a COSE_Key that holds an EC key, this is label that indicates - * the data item containing the Y coordinate. - * - * This is used only for key type \ref COSE_KEY_TYPE_EC2. - */ -#define COSE_KEY_PARAM_Y_COORDINATE -3 - -/** - * \def COSE_KEY_PARAM_PRIVATE_D - * - * \brief Label for data item that is d, the private part of EC key. - * - * In a \c COSE_Key that holds an EC key, this is label that indicates - * the data item containing the Y coordinate. - * - * This is used for both key types \ref COSE_KEY_TYPE_EC2 and \ref - * COSE_KEY_TYPE_OKP. - */ -#define COSE_KEY_PARAM_PRIVATE_D -4 - - - - -/* ---------- COSE Key Types -------------------------------- - * https://www.iana.org/assignments/cose/cose.xhtml#key-type - */ - -/** - * \def COSE_KEY_TYPE_OKP - * - * \brief Key type is Octet Key Pair - * - * In a \c COSE_Key, this is a value of the data item labeled \ref - * COSE_KEY_COMMON_KTY that indicates the \c COSE_Key is some sort of - * key pair represented by some octets. It may or may not be an EC - * key. - */ -#define COSE_KEY_TYPE_OKP 1 - -/** - * \def COSE_KEY_TYPE_EC2 - * - * \brief Key is a 2-parameter EC key. - * - * In a \c COSE_Key, this is a value of the data item labeled \ref - * COSE_KEY_COMMON_KTY that indicates the \c COSE_Key is an EC key - * specified with two coordinates, X and Y. - */ -#define COSE_KEY_TYPE_EC2 2 - -/** - * \def COSE_KEY_TYPE_SYMMETRIC - * - * \brief Key is a symmetric key. - * - * In a \c COSE_Key, this is a value of the data item labeled \ref - * COSE_KEY_COMMON_KTY that indicates the \c COSE_Key is a symmetric - * key. - */ -#define COSE_KEY_TYPE_SYMMETRIC 4 - - - - -/* ----------- COSE Elliptic Curves --------------------- - * https://www.iana.org/assignments/cose/cose.xhtml#elliptic-curves - */ - -/** - * \def COSE_ELLIPTIC_CURVE_P_256 - * - * \brief Key type for NIST P-256 key - * - * In a \c COSE_Key, this is a value of the data item labeled \ref - * COSE_KEY_PARAM_CRV to indicate the NIST P-256 curve, also known as - * secp256r1. - * - * This key type is always \ref COSE_KEY_TYPE_EC2. - */ -#define COSE_ELLIPTIC_CURVE_P_256 1 - -/** - * \def COSE_ELLIPTIC_CURVE_P_384 - * - * \brief Key type for NIST P-384 key - * - * In a \c COSE_Key, this is a value of the data item labeled \ref - * COSE_KEY_PARAM_CRV to indicate the NIST P-384 curve, also known as - * secp384r1. - * - * This key type is always \ref COSE_KEY_TYPE_EC2. - */ -#define COSE_ELLIPTIC_CURVE_P_384 2 - -/** - * \def COSE_ELLIPTIC_CURVE_P_521 - * - * \brief Key type for NIST P-521 key - * - * In a \c COSE_Key, this is a value of the data item labeled \ref - * COSE_KEY_PARAM_CRV to indicate the NIST P-521 curve, also known as - * secp521r1. - */ -#define COSE_ELLIPTIC_CURVE_P_521 3 - - - - -/* ------- Constants from RFC 8152 --------- - */ - -/** - * \def COSE_SIG_CONTEXT_STRING_SIGNATURE1 - * - * \brief This is a string constant used by COSE to label \c COSE_Sign1 - * structures. See RFC 8152, section 4.4. - */ -#define COSE_SIG_CONTEXT_STRING_SIGNATURE1 "Signature1" - - -#endif /* __T_COSE_DEFINES_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/src/t_cose_sign1_sign.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/src/t_cose_sign1_sign.c deleted file mode 100644 index 8f55bc0..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/src/t_cose_sign1_sign.c +++ /dev/null @@ -1,499 +0,0 @@ -/* - * t_cose_sign1_sign.c - * - * Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * See BSD-3-Clause license in README.md - */ - -#include "t_cose_sign1_sign.h" -#include "qcbor.h" -#include "t_cose_defines.h" -#include "t_cose_crypto.h" -#include "t_cose_util.h" - - -/** - * \file t_cose_sign1_sign.c - * - * \brief This implements t_cose signing - */ - - -/** - * \brief Create a short-circuit signature - * - * \param[in] cose_alg_id Algorithm ID. This is used only to make - * the short-circuit signature the same size - * as the real signature would be for the - * particular algorithm. - * \param[in] hash_to_sign The bytes to sign. Typically, a hash of - * a payload. - * \param[in] signature_buffer Pointer and length of buffer into which - * the resulting signature is put. - * \param[in] signature Pointer and length of the signature - * returned. - * - * \return This returns one of the error codes defined by \ref t_cose_err_t. - * - * This creates the short-circuit signature that is a concatenation of - * hashes up to the expected size of the signature. This is a test - * mode only has it has no security value. This is retained in - * commercial production code as a useful test or demo that can run - * even if key material is not set up or accessible. - */ -static inline enum t_cose_err_t -short_circuit_sign(int32_t cose_alg_id, - struct useful_buf_c hash_to_sign, - struct useful_buf signature_buffer, - struct useful_buf_c *signature) -{ - /* approximate stack use on 32-bit machine: local use: 16 - */ - enum t_cose_err_t return_value; - size_t array_indx; - size_t amount_to_copy; - size_t sig_size; - - sig_size = t_cose_signature_size(cose_alg_id); - - if(sig_size > signature_buffer.len) { - /* Buffer too small for this signature type */ - return_value = T_COSE_ERR_SIG_BUFFER_SIZE; - goto Done; - } - - /* Loop concatening copies of the hash to fill out to signature size */ - for(array_indx = 0; array_indx < sig_size; array_indx += hash_to_sign.len) { - amount_to_copy = sig_size - array_indx; - if(amount_to_copy > hash_to_sign.len) { - amount_to_copy = hash_to_sign.len; - } - memcpy((uint8_t *)signature_buffer.ptr + array_indx, - hash_to_sign.ptr, - amount_to_copy); - } - signature->ptr = signature_buffer.ptr; - signature->len = sig_size; - return_value = T_COSE_SUCCESS; - -Done: - return return_value; -} - - - -/** - * The maximum size of a CBOR Encoded \c COSE_Key that this - * implementation can handle. \c COSE_Key is the serialization format - * for public and other types of keys defined by [COSE (RFC 8152)] - * (https://tools.ietf.org/html/rfc8152). - * - * This can be increased to handle larger keys, but stack usage will - * go up with this increase. - */ -#define MAX_ENCODED_COSE_KEY_SIZE \ - 1 + /* 1 byte to encode map */ \ - 2 + /* 2 bytes to encode key type */ \ - 2 + /* 2 bytes to encode curve */ \ - 2 * /* the X and Y coordinates at 32 bytes each */ \ - (T_COSE_CRYPTO_EC_P256_COORD_SIZE + 1 + 2) - - -/** - * \brief CBOR encode a public key as a \c COSE_Key - * - * \param[in] key_select Identifies the public key to encode. - * - * \param[in] buffer_for_cose_key Pointer and length of buffer into which - * the encoded \c COSE_Key is put. - * \param[in] cose_key Pointer and length of the encoded \c COSE_Key. - * - * \return This returns one of the error codes defined by \ref t_cose_err_t. - * - * \c COSE_Key is the COSE-defined format for serializing a key for - * transmission in a protocol. This function encodes an EC public key - * expressed as an X and Y coordinate. - */ -static enum t_cose_err_t -t_cose_encode_cose_key(int32_t key_select, - struct useful_buf buffer_for_cose_key, - struct useful_buf_c *cose_key) -{ - /* approximate stack use on 32-bit machine: - * local use: 328 - * with calls: 370 - */ - enum t_cose_err_t return_value; - QCBORError qcbor_result; - QCBOREncodeContext cbor_encode_ctx; - USEFUL_BUF_MAKE_STACK_UB( buffer_for_x_coord, - T_COSE_CRYPTO_EC_P256_COORD_SIZE); - USEFUL_BUF_MAKE_STACK_UB( buffer_for_y_coord, - T_COSE_CRYPTO_EC_P256_COORD_SIZE); - struct useful_buf_c x_coord; - struct useful_buf_c y_coord; - int32_t cose_curve_id; - struct useful_buf_c encoded_key_id; - - /* Get the public key x and y */ - return_value = t_cose_crypto_get_ec_pub_key(key_select, - NULL_USEFUL_BUF_C, - &cose_curve_id, - buffer_for_x_coord, - buffer_for_y_coord, - &x_coord, - &y_coord); - if(return_value != T_COSE_SUCCESS) { - goto Done; - } - - /* Encode it into a COSE_Key structure */ - QCBOREncode_Init(&cbor_encode_ctx, buffer_for_cose_key); - QCBOREncode_OpenMap(&cbor_encode_ctx); - QCBOREncode_AddInt64ToMapN(&cbor_encode_ctx, - COSE_KEY_COMMON_KTY, - COSE_KEY_TYPE_EC2); - QCBOREncode_AddInt64ToMapN(&cbor_encode_ctx, - COSE_KEY_PARAM_CRV, - cose_curve_id); - QCBOREncode_AddBytesToMapN(&cbor_encode_ctx, - COSE_KEY_PARAM_X_COORDINATE, - x_coord); - QCBOREncode_AddBytesToMapN(&cbor_encode_ctx, - COSE_KEY_PARAM_Y_COORDINATE, - y_coord); - QCBOREncode_CloseMap(&cbor_encode_ctx); - - qcbor_result = QCBOREncode_Finish(&cbor_encode_ctx, &encoded_key_id); - if(qcbor_result != QCBOR_SUCCESS) { - /* Mainly means that the COSE_Key was too big for buffer_for_cose_key */ - return_value = T_COSE_ERR_PROTECTED_HEADERS; - goto Done; - } - - /* Finish up and return */ - *cose_key = encoded_key_id; - return_value = T_COSE_SUCCESS; - -Done: - return return_value; -} - - -/** - * \brief SHA-256 hash a buffer in one quick function - * - * \param[in] bytes_to_hash The bytes to be hashed. - * - * \param[in] buffer_for_hash Pointer and length into which - * the resulting hash is put. - * \param[out] hash Pointer and length of the - * resulting hash. - * \return This returns one of the error codes defined by \ref t_cose_err_t. - * - * Simple wrapper for start, update and finish interface to a hash. - * - * Having this as a separate function helps keep stack usage down and - * is convenient. - */ -static enum t_cose_err_t quick_sha256(struct useful_buf_c bytes_to_hash, - struct useful_buf buffer_for_hash, - struct useful_buf_c *hash) -{ - /* approximate stack use on 32-bit machine: - local use: 132 - */ - enum t_cose_err_t return_value = 0; - struct t_cose_crypto_hash hash_ctx; - - return_value = t_cose_crypto_hash_start(&hash_ctx, - COSE_ALG_SHA256_PROPRIETARY); - if(return_value) { - goto Done; - } - t_cose_crypto_hash_update(&hash_ctx, bytes_to_hash); - return_value = t_cose_crypto_hash_finish(&hash_ctx, - buffer_for_hash, - hash); - -Done: - return return_value; -} - - -/** - * \brief Make a key ID based on the public key to go in the kid - * unprotected header. - * - * \param[in] key_select Identifies the public key. - * \param[in] buffer_for_key_id Pointer and length into which - * the resulting key ID is put. - * \param[out] key_id Pointer and length of the - * resulting key ID. - * - * \return This returns one of the error codes defined by \ref t_cose_err_t. - * - * - * See t_cose_sign1_init() for documentation of the key ID format - * created here. - */ -static inline enum t_cose_err_t get_keyid(int32_t key_select, - struct useful_buf buffer_for_key_id, - struct useful_buf_c *key_id) -{ - /* approximate stack use on 32-bit machine: - * local use: 100 - * with calls inlined: 560 - * with calls not inlined: 428 - */ - enum t_cose_err_t return_value; - USEFUL_BUF_MAKE_STACK_UB( buffer_for_cose_key, - MAX_ENCODED_COSE_KEY_SIZE); - struct useful_buf_c cose_key; - - /* Doing the COSE encoding and the hashing in separate functions - * called from here reduces the stack usage in this function by a - * lot - */ - - /* Get the key and encode it as a COSE_Key */ - return_value = t_cose_encode_cose_key(key_select, - buffer_for_cose_key, - &cose_key); - if(return_value != T_COSE_SUCCESS) { - goto Done; - } - - /* SHA256 hash of it is all we care about in the end */ - return_value = quick_sha256(cose_key, buffer_for_key_id, key_id); - -Done: - return return_value; -} - - -/** - * \brief Makes the protected headers for COSE. - * - * \param[in] cose_alg_id The COSE algorithm ID to put in the headers. - * - * \param[in] buffer_for_header Pointer and length into which - * the resulting encoded protected - * headers is put. - * - * \return The pointer and length of the protected headers is - * returned, or \c NULL_USEFUL_BUF_C if this fails. - * - * The protected headers are returned in fully encoded CBOR format as - * they are added to the \c COSE_Sign1 as a binary string. This is - * different from the unprotected headers which are not handled this - * way. - * - * This returns \c NULL_USEFUL_BUF_C if buffer_for_header was too - * small. See also definition of \ref T_COSE_SIGN1_MAX_PROT_HEADER - */ -static inline struct useful_buf_c -make_protected_header(int32_t cose_alg_id, - struct useful_buf buffer_for_header) -{ - /* approximate stack use on 32-bit machine: - * local use: 170 - * with calls: 210 - */ - struct useful_buf_c protected_headers; - QCBORError qcbor_result; - QCBOREncodeContext cbor_encode_ctx; - struct useful_buf_c return_value; - - QCBOREncode_Init(&cbor_encode_ctx, buffer_for_header); - QCBOREncode_OpenMap(&cbor_encode_ctx); - QCBOREncode_AddInt64ToMapN(&cbor_encode_ctx, - COSE_HEADER_PARAM_ALG, - cose_alg_id); - QCBOREncode_CloseMap(&cbor_encode_ctx); - qcbor_result = QCBOREncode_Finish(&cbor_encode_ctx, &protected_headers); - - if(qcbor_result == QCBOR_SUCCESS) { - return_value = protected_headers; - } else { - return_value = NULL_USEFUL_BUF_C; - } - - return return_value; -} - - -/** - * \brief Add the unprotected headers to a CBOR encoding context - * - * \param[in] cbor_encode_ctx CBOR encoding context to output to - * \param[in] kid The key ID to go into the kid header. - * - * No error is returned. If an error occurred it will be returned when - * \c QCBOR_Finish() is called on \c cbor_encode_ctx. - * - * The unprotected headers added by this are just the key ID - */ -static inline void add_unprotected_headers(QCBOREncodeContext *cbor_encode_ctx, - struct useful_buf_c kid) -{ - QCBOREncode_OpenMap(cbor_encode_ctx); - QCBOREncode_AddBytesToMapN(cbor_encode_ctx, COSE_HEADER_PARAM_KID, kid); - QCBOREncode_CloseMap(cbor_encode_ctx); -} - - -/* - * Public function. See t_cose_sign1_sign.h - */ -enum t_cose_err_t t_cose_sign1_init(struct t_cose_sign1_ctx *me, - bool short_circuit_sign, - int32_t cose_alg_id, - int32_t key_select, - QCBOREncodeContext *cbor_encode_ctx) -{ - /* approximate stack use on 32-bit machine: - * local use: 66 - * with calls inlined: 900 - * with calls not inlined: 500 - */ - - int32_t hash_alg; - enum t_cose_err_t return_value; - USEFUL_BUF_MAKE_STACK_UB( buffer_for_kid, T_COSE_CRYPTO_SHA256_SIZE); - struct useful_buf_c kid; - struct useful_buf buffer_for_protected_header; - - /* Check the cose_alg_id now by getting the hash alg as an early - error check even though it is not used until later. */ - hash_alg = hash_alg_id_from_sig_alg_id(cose_alg_id); - if(hash_alg == INT32_MAX) { - return T_COSE_ERR_UNSUPPORTED_SIGNING_ALG; - } - - /* Remember all the parameters in the context */ - me->cose_algorithm_id = cose_alg_id; - me->key_select = key_select; - me->short_circuit_sign = short_circuit_sign; - me->cbor_encode_ctx = cbor_encode_ctx; - - /* Get the key id because it goes into the headers that are about - to be made. */ - if(short_circuit_sign) { - return_value = get_short_circuit_kid(buffer_for_kid, &kid); - } else { - return_value = get_keyid(key_select, buffer_for_kid, &kid); - } - if(return_value) { - goto Done; - } - - /* Get started with the tagged array that holds the four parts of - a cose single signed message */ - QCBOREncode_AddTag(cbor_encode_ctx, CBOR_TAG_COSE_SIGN1); - QCBOREncode_OpenArray(cbor_encode_ctx); - - /* The protected headers, which are added as a wrapped bstr */ - buffer_for_protected_header = - USEFUL_BUF_FROM_BYTE_ARRAY(me->buffer_for_protected_headers); - me->protected_headers = make_protected_header(cose_alg_id, - buffer_for_protected_header); - if(useful_buf_c_is_null(me->protected_headers)) { - /* The sizing of storage for protected headers is - off (should never happen in tested, released code) */ - return_value = T_COSE_SUCCESS; - goto Done; - } - QCBOREncode_AddBytes(cbor_encode_ctx, me->protected_headers); - - /* The Unprotected headers */ - add_unprotected_headers(cbor_encode_ctx, kid); - - /* Any failures in CBOR encoding will be caught in finish - when the CBOR encoding is closed off. No need to track - here as the CBOR encoder tracks it internally. */ - - return_value = T_COSE_SUCCESS; - -Done: - return return_value; -} - - -/* - * Public function. See t_cose_sign1_sign.h - */ -enum t_cose_err_t t_cose_sign1_finish(struct t_cose_sign1_ctx *me, - struct useful_buf_c signed_payload) -{ - /* approximate stack use on 32-bit machine: - * local use: 116 - * with calls inline: 500 - * with calls not inlined; 450 - */ - enum t_cose_err_t return_value; - /* pointer and length of the completed tbs hash */ - struct useful_buf_c tbs_hash; - /* Pointer and length of the completed signature */ - struct useful_buf_c signature; - /* Buffer for the actual signature */ - USEFUL_BUF_MAKE_STACK_UB( buffer_for_signature, - T_COSE_MAX_EC_SIG_SIZE); - /* Buffer for the tbs hash. Only big enough for SHA256 */ - USEFUL_BUF_MAKE_STACK_UB( buffer_for_tbs_hash, - T_COSE_CRYPTO_SHA256_SIZE); - - /* Create the hash of the to-be-signed bytes. Inputs to the hash - * are the protected headers, the payload that getting signed, the - * cose signature alg from which the hash alg is determined. The - * cose_algorithm_id was checked in t_cose_sign1_init() so it - * doesn't need to be checked here. - */ - return_value = create_tbs_hash(me->cose_algorithm_id, - buffer_for_tbs_hash, - &tbs_hash, - me->protected_headers, - signed_payload); - if(return_value) { - goto Done; - } - - /* Compute the signature using public key crypto. The key selector - * and algorithm ID are passed in to know how and what to sign - * with. The hash of the TBS bytes are what is signed. A buffer in - * which to place the signature is passed in and the signature is - * returned. - * - * Short-circuit signing is invoked if requested. It does no - * public key operation and requires no key. It is just a test - * mode that always works. - */ - if(me->short_circuit_sign) { - return_value = short_circuit_sign(me->cose_algorithm_id, - tbs_hash, - buffer_for_signature, - &signature); - } else { - return_value = t_cose_crypto_pub_key_sign(me->cose_algorithm_id, - me->key_select, - tbs_hash, - buffer_for_signature, - &signature); - } - if(return_value) { - goto Done; - } - - /* Add signature to CBOR and close out the array */ - QCBOREncode_AddBytes(me->cbor_encode_ctx, signature); - QCBOREncode_CloseArray(me->cbor_encode_ctx); - - /* CBOR encoding errors are tracked in the CBOR encoding context - and handled in the layer above this */ - -Done: - return return_value; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/src/t_cose_util.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/src/t_cose_util.c deleted file mode 100644 index ba4910e..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/src/t_cose_util.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * t_cose_util.c - * - * Copyright 2019, Laurence Lundblade - * - * SPDX-License-Identifier: BSD-3-Clause - * - * See BSD-3-Clause license in README.mdE. - */ - -#include "t_cose_util.h" -#include "qcbor.h" -#include "t_cose_defines.h" -#include "t_cose_common.h" -#include "t_cose_crypto.h" - - -/** - * \file t_cose_util.c - * - * \brief Implementation of t_cose utility functions. - * - */ - - -/* - * Public function. See t_cose_util.h - */ -int32_t hash_alg_id_from_sig_alg_id(int32_t cose_sig_alg_id) -{ - /* if other hashes, particularly those that output bigger hashes - * are added here, various other parts of this code have to be - * changed to have larger buffers. - */ - switch(cose_sig_alg_id) { - - case COSE_ALGORITHM_ES256: - return COSE_ALG_SHA256_PROPRIETARY; - - default: - return INT32_MAX; - } -} - - -/* - * Format of to-be-signed bytes used by create_tbs_hash(). - * This is defined in COSE (RFC 8152). It is the input - * to the hash. - * - * Sig_structure = [ - * context : "Signature" / "Signature1" / "CounterSignature", - * body_protected : empty_or_serialized_map, - * ? sign_protected : empty_or_serialized_map, - * external_aad : bstr, - * payload : bstr - * ] - */ - - -/** - * This is the size of the first part of the CBOR encoded TBS - * bytes. It is around 20 bytes. See create_tbs_hash(). - */ -#define T_COSE_SIZE_OF_TBS \ - 1 + /* For opening the array */ \ - sizeof(COSE_SIG_CONTEXT_STRING_SIGNATURE1) + /* "Signature1" */ \ - 2 + /* Overhead for encoding string */ \ - T_COSE_SIGN1_MAX_PROT_HEADER + /* entire protected headers */ \ - 3 * ( /* 3 NULL bstrs for fields not used */ \ - 1 /* size of a NULL bstr */ \ - ) - - -/* - * Public function. See t_cose_util.h - */ -enum t_cose_err_t create_tbs_hash(int32_t cose_alg_id, - struct useful_buf buffer_for_hash, - struct useful_buf_c *hash, - struct useful_buf_c protected_headers, - struct useful_buf_c payload) -{ - /* approximate stack use on 32-bit machine: - * local use: 320 - * with calls: 360 - */ - enum t_cose_err_t return_value; - QCBOREncodeContext cbor_encode_ctx; - UsefulBuf_MAKE_STACK_UB( buffer_for_TBS_first_part, T_COSE_SIZE_OF_TBS); - struct useful_buf_c tbs_first_part; - QCBORError qcbor_result; - struct t_cose_crypto_hash hash_ctx; - int32_t hash_alg_id; - - /* This builds the CBOR-format to-be-signed bytes */ - QCBOREncode_Init(&cbor_encode_ctx, buffer_for_TBS_first_part); - QCBOREncode_OpenArray(&cbor_encode_ctx); - /* context */ - QCBOREncode_AddSZString(&cbor_encode_ctx, - COSE_SIG_CONTEXT_STRING_SIGNATURE1); - /* body_protected */ - QCBOREncode_AddBytes(&cbor_encode_ctx, - protected_headers); - /* sign_protected */ - QCBOREncode_AddBytes(&cbor_encode_ctx, NULL_USEFUL_BUF_C); - /* external_aad */ - QCBOREncode_AddBytes(&cbor_encode_ctx, NULL_USEFUL_BUF_C); - /* fake payload */ - QCBOREncode_AddBytes(&cbor_encode_ctx, NULL_USEFUL_BUF_C); - QCBOREncode_CloseArray(&cbor_encode_ctx); - - /* get the result and convert it to struct useful_buf_c representation */ - qcbor_result = QCBOREncode_Finish(&cbor_encode_ctx, &tbs_first_part); - if(qcbor_result) { - /* Mainly means that the protected_headers were too big - (which should never happen) */ - return_value = T_COSE_ERR_SIG_STRUCT; - goto Done; - } - - /* Start the hashing */ - hash_alg_id = hash_alg_id_from_sig_alg_id(cose_alg_id); - /* Don't check hash_alg_id for failure. t_cose_crypto_hash_start() - will handle it properly - */ - return_value = t_cose_crypto_hash_start(&hash_ctx, hash_alg_id); - if(return_value) { - goto Done; - } - - /* Hash the first part of the TBS. Take all but the last two - * bytes. The last two bytes are the fake payload from above. It - * is replaced by the real payload which is hashed next. The fake - * payload is needed so the array count is right. This is one of - * the main things that make it possible to implement with one - * buffer for the whole cose sign1. - */ - t_cose_crypto_hash_update(&hash_ctx, - useful_buf_head(tbs_first_part, - tbs_first_part.len - 2)); - - /* Hash the payload */ - t_cose_crypto_hash_update(&hash_ctx, payload); - - /* Finish the hash and set up to return it */ - return_value = t_cose_crypto_hash_finish(&hash_ctx, - buffer_for_hash, - hash); - -Done: - return return_value; -} - - -/* - * Public function. See t_cose_util.h - */ -enum t_cose_err_t -get_short_circuit_kid(struct useful_buf buffer_for_kid, - struct useful_buf_c *kid) -{ - /* This is a random hard coded key ID that is used to indicate - * short-circuit signing. It is OK to hard code this as the - * probability of collision with this ID is very low and the same - * as for collision between any two key IDs of any sort. - */ - uint8_t defined_short_circuit_kid[] = { - 0xef, 0x95, 0x4b, 0x4b, 0xd9, 0xbd, 0xf6, 0x70, - 0xd0, 0x33, 0x60, 0x82, 0xf5, 0xef, 0x15, 0x2a, - 0xf8, 0xf3, 0x5b, 0x6a, 0x6c, 0x00, 0xef, 0xa6, - 0xa9, 0xa7, 0x1f, 0x49, 0x51, 0x7e, 0x18, 0xc6}; - - /* Prevent a dumb error where the size constant in the header is - * wrong.This check will be evaluated at compile time and optimize - * out when all is correct. - */ - if(sizeof(defined_short_circuit_kid) != T_COSE_SHORT_CIRCUIT_KID_SIZE) { - return T_COSE_ERR_BAD_SHORT_CIRCUIT_KID; - } - - *kid = useful_buf_copy(buffer_for_kid, - USEFUL_BUF_FROM_BYTE_ARRAY_LITERAL( - defined_short_circuit_kid)); - - return useful_buf_c_is_null(*kid) ? - T_COSE_ERR_KEY_BUFFER_SIZE : - T_COSE_SUCCESS; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/src/t_cose_util.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/src/t_cose_util.h deleted file mode 100644 index 7b39dc3..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/src/t_cose_util.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * t_cose_util.h - * - * Copyright 2019, Laurence Lundblade - * - * SPDX-License-Identifier: BSD-3-Clause - * - * See BSD-3-Clause license in README.mdE. - */ - - -#ifndef __T_COSE_UTIL_H__ -#define __T_COSE_UTIL_H__ - -#include -#include "useful_buf.h" -#include "t_cose_common.h" - -/** - * \file t_cose_util.h - * - * \brief Utility functions used internally by the t_cose implementation. - * - */ - - -/** - * \brief Return hash algorithm ID from a signature algorithm ID - * - * \param[in] cose_sig_alg_id A COSE signature algorithm identifier. - * - * \return \c INT32_MAX when the signature algorithm ID is not known. - * - * This works off of algorithm identifiers defined in the [IANA COSE - * Registry] (https://www.iana.org/assignments/cose/cose.xhtml). - * Corresponding local integer constants are defined in - * t_cose_defines.h. - * - * COSE signing algorithms are the combination of public key - * algorithm, curve, key size, hash algorithm and hash size. They are - * simple integers making them convenient for direct use in code. - * - * This function returns an identifier for only the hash algorithm - * from the combined identifier. - * - * If the needed algorithm identifiers are not in the IANA registry, - * they can be added to it. This will take some time and work. It is - * also fine to use algorithms in the proprietary space. - */ -int32_t hash_alg_id_from_sig_alg_id(int32_t cose_sig_alg_id); - - -/** - * \brief Create the hash of the to-be-signed (TBS) bytes for COSE. - * - * \param[in] cose_alg_id The COSE signing algorithm ID. Used to - * determine which hash function to use. - * \param[in] buffer_for_hash Pointer and length of buffer into which - * the resulting hash is put. - * \param[out] hash Pointer and length of the - * resulting hash. - * \param[in] protected_headers The CBOR encoded protected headers. - * \param[in] payload The CBOR encoded payload - * - * \return This returns one of the error codes defined by \ref t_cose_err_t. - * - * \retval T_COSE_ERR_SIG_STRUCT - * Most likely this is because the protected_headers passed in - * is larger than \ref T_COSE_SIGN1_MAX_PROT_HEADER. - * \retval T_COSE_ERR_UNSUPPORTED_HASH - * If the hash algorithm is not known. - * \retval T_COSE_ERR_HASH_GENERAL_FAIL - * In case of some general hash failure. - * - * The input to the public key signature algorithm in COSE is the hash - * of a CBOR encoded structure containing the protected headers - * algorithm ID and a few other things. This formats that structure - * and computes the hash of it. These are known as the to-be-signed or - * "TBS" bytes. - */ -enum t_cose_err_t create_tbs_hash(int32_t cose_alg_id, - struct useful_buf buffer_for_hash, - struct useful_buf_c *hash, - struct useful_buf_c protected_headers, - struct useful_buf_c payload); - - -/** - * Size of the key returned by get_short_circuit_kid(). It is always - * this size. - */ -#define T_COSE_SHORT_CIRCUIT_KID_SIZE 32 - - -/** - * \brief Get the special kid for short-circuit signing. - * - * \param[in] buffer_for_kid Pointer and length of buffer into which - * the resulting hash is put. It should - * always be at least \ref - * T_COSE_SHORT_CIRCUIT_KID_SIZE. - * \param[out] kid Pointer and length of the returned kid. - * - * \retval T_COSE_SUCCESS - * The kid was returned. - * \retval T_COSE_ERR_KEY_BUFFER_SIZE - * \c buffer_for_kid is too small - * - * This always returns the same key ID. It always indicates - * short-circuit signing. It is OK to hard code this as the - * probability of collision with this ID is extremely low and the same - * as for collision between any two key IDs (kids) of any sort. - * - * This is the value of the kid. - * - * 0xef, 0x95, 0x4b, 0x4b, 0xd9, 0xbd, 0xf6, 0x70, - * 0xd0, 0x33, 0x60, 0x82, 0xf5, 0xef, 0x15, 0x2a, - * 0xf8, 0xf3, 0x5b, 0x6a, 0x6c, 0x00, 0xef, 0xa6, - * 0xa9, 0xa7, 0x1f, 0x49, 0x51, 0x7e, 0x18, 0xc6 - * - */ -enum t_cose_err_t -get_short_circuit_kid(struct useful_buf buffer_for_kid, - struct useful_buf_c *kid); - -#endif /* __T_COSE_UTIL_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_attest_hal.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_attest_hal.h deleted file mode 100755 index b43b109..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_attest_hal.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#ifndef __TFM_ATTEST_HAL_H__ -#define __TFM_ATTEST_HAL_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Security lifecycle of the device - */ -enum tfm_security_lifecycle_t { - TFM_SLC_UNKNOWN = 0x0000u, - TFM_SLC_ASSEMBLY_AND_TEST = 0x1000u, - TFM_SLC_PSA_ROT_PROVISIONING = 0x2000u, - TFM_SLC_SECURED = 0x3000u, - TFM_SLC_NON_PSA_ROT_DEBUG = 0x4000u, - TFM_SLC_RECOVERABLE_PSA_ROT_DEBUG = 0x5000u, - TFM_SLC_DECOMMISSIONED = 0x6000u, -}; - -/** - * \brief Retrieve the security lifecycle of the device - * - * Security lifecycle is a mandatory claim in the initial attestation token. - * - * \return According to \ref tfm_security_lifecycle_t - */ -enum tfm_security_lifecycle_t tfm_attest_hal_get_security_lifecycle(void); - -/** - * \brief Retrieve the verification service indicator for initial attestation. - * - * It is used by relying party to locate a validation service for the token. - * It can be a text string that can be used to locate the service or can be a - * URL specifying the address of the service. - * - * \param[out] size Length of the string, without the termination zero byte. - * - * \return NULL pointer if not available otherwise the address of the - * verification service string in the device memory. - */ -const char * -tfm_attest_hal_get_verification_service(uint32_t *size); - -/** - * \brief Retrieve the name of the profile definition document for initial - * attestation. - * - * This document describes the 'profile' of the initial attestation token, - * being a full description of the claims, their usage, verification and - * token signing. - * - * \param[out] size Length of the document name, without the termination zero - * byte. - * - * \return NULL pointer if not available otherwise the address of the document - * name string in the device memory. - */ -const char * -tfm_attest_hal_get_profile_definition(uint32_t *size); - -#ifdef __cplusplus -} -#endif - -#endif /* __TFM_ATTEST_HAL_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_boot_status.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_boot_status.h deleted file mode 100755 index dbcc6ce..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_boot_status.h +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (c) 2018-2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#ifndef __TFM_BOOT_STATUS_H__ -#define __TFM_BOOT_STATUS_H__ - -#include -#include - - -#ifdef __cplusplus -extern "C" { -#endif - -/* Major numbers (4 bit) to identify - * the consumer of shared data in runtime SW - */ -#define TLV_MAJOR_CORE 0x0 -#define TLV_MAJOR_IAS 0x1 - -/** - * The shared data between boot loader and runtime SW is TLV encoded. The - * shared data is stored in a well known location in secure memory and this is - * a contract between boot loader and runtime SW. - * - * The structure of shared data must be the following: - * - At the beginning there must be a header: struct shared_data_tlv_header - * This contains a magic number and a size field which covers the entire - * size of the shared data area including this header. - * - After the header there come the entries which are composed from an entry - * header structure: struct shared_data_tlv_entry and the data. In the entry - * header is a type field (tly_type) which identify the consumer of the - * entry in the runtime SW and specify the subtype of that data item. There - * is a size field (tlv_len) which covers the size of the entry header and - * the data. After this structure comes the actual data. - * - Arbitrary number and size of data entry can be in the shared memory area. - * - * This table gives of overview about the tlv_type field in the entry header. - * The tlv_type always composed from a major and minor number. Major number - * identifies the addressee in runtime SW, who should process the data entry. - * Minor number used to encode more info about the data entry. The actual - * definition of minor number could change per major number. In case of boot - * status data, which is going to be processed by initial attestation service - * the minor number is split further to two part: sw_module and claim. The - * sw_module identifies the SW component in the system which the data item - * belongs to and the claim part identifies the exact type of the data. - * - * |---------------------------------------| - * | tlv_type (16) | - * |---------------------------------------| - * | tlv_major(4)| tlv_minor(12) | - * |---------------------------------------| - * | MAJOR_IAS | sw_module(6) | claim(6) | - * |---------------------------------------| - * | MAJOR_CORE | TBD | - * |---------------------------------------| - */ - -/* Initial attestation: SW components / SW modules - * This list is intended to be adjusted per device. It contains more SW - * components than currently available in TF-M project. It serves as an example, - * what kind of SW components might be available. - */ -#define SW_GENERAL 0x00 -#define SW_BL2 0x01 -#define SW_PROT 0x02 -#define SW_AROT 0x03 -#define SW_SPE 0x04 -#define SW_NSPE 0x05 -#define SW_S_NS 0x06 -#define SW_MAX 0x07 - -/* Initial attestation: Claim per SW components / SW modules */ -/* Bits: 0-2 */ -#define SW_VERSION 0x00 -#define SW_SIGNER_ID 0x01 -#define SW_EPOCH 0x02 -#define SW_TYPE 0x03 -/* Bits: 3-5 */ -#define SW_MEASURE_VALUE 0x08 -#define SW_MEASURE_TYPE 0x09 - -/* Initial attestation: General claim does not belong any particular SW - * component. But they might be part of the boot status. - */ -#define BOOT_SEED 0x00 -#define HW_VERSION 0x01 -#define SECURITY_LIFECYCLE 0x02 - -/* Minor numbers (12 bit) to identify attestation service related data */ -#define TLV_MINOR_IAS_BOOT_SEED ((SW_GENERAL << 6) | BOOT_SEED) -#define TLV_MINOR_IAS_HW_VERSION ((SW_GENERAL << 6) | HW_VERSION) -#define TLV_MINOR_IAS_SLC ((SW_GENERAL << 6) | SECURITY_LIFECYCLE) - -/* Bootloader - It can be more stage */ -#define TLV_MINOR_IAS_BL2_MEASURE_VALUE ((SW_BL2 << 6) | SW_MEASURE_VALUE) -#define TLV_MINOR_IAS_BL2_MEASURE_TYPE ((SW_BL2 << 6) | SW_MEASURE_TYPE) -#define TLV_MINOR_IAS_BL2_VERSION ((SW_BL2 << 6) | SW_VERSION) -#define TLV_MINOR_IAS_BL2_SIGNER_ID ((SW_BL2 << 6) | SW_SIGNER_ID) -#define TLV_MINOR_IAS_BL2_EPOCH ((SW_BL2 << 6) | SW_EPOCH) -#define TLV_MINOR_IAS_BL2_TYPE ((SW_BL2 << 6) | SW_TYPE) - -/* PROT: PSA Root of Trust */ -#define TLV_MINOR_IAS_PROT_MEASURE_VALUE ((SW_PROT << 6) | SW_MEASURE_VALUE) -#define TLV_MINOR_IAS_PROT_MEASURE_TYPE ((SW_PROT << 6) | SW_MEASURE_TYPE) -#define TLV_MINOR_IAS_PROT_VERSION ((SW_PROT << 6) | SW_VERSION) -#define TLV_MINOR_IAS_PROT_SIGNER_ID ((SW_PROT << 6) | SW_SIGNER_ID) -#define TLV_MINOR_IAS_PROT_EPOCH ((SW_PROT << 6) | SW_EPOCH) -#define TLV_MINOR_IAS_PROT_TYPE ((SW_PROT << 6) | SW_TYPE) - -/* AROT: Application Root of Trust */ -#define TLV_MINOR_IAS_AROT_MEASURE_VALUE ((SW_AROT << 6) | SW_MEASURE_VALUE) -#define TLV_MINOR_IAS_AROT_MEASURE_TYPE ((SW_AROT << 6) | SW_MEASURE_TYPE) -#define TLV_MINOR_IAS_AROT_VERSION ((SW_AROT << 6) | SW_VERSION) -#define TLV_MINOR_IAS_AROT_SIGNER_ID ((SW_AROT << 6) | SW_SIGNER_ID) -#define TLV_MINOR_IAS_AROT_EPOCH ((SW_AROT << 6) | SW_EPOCH) -#define TLV_MINOR_IAS_AROT_TYPE ((SW_AROT << 6) | SW_TYPE) - -/* Non-secure processing environment - single non-secure image */ -#define TLV_MINOR_IAS_NSPE_MEASURE_VALUE ((SW_NSPE << 6) | SW_MEASURE_VALUE) -#define TLV_MINOR_IAS_NSPE_MEASURE_TYPE ((SW_NSPE << 6) | SW_MEASURE_TYPE) -#define TLV_MINOR_IAS_NSPE_VERSION ((SW_NSPE << 6) | SW_VERSION) -#define TLV_MINOR_IAS_NSPE_SIGNER_ID ((SW_NSPE << 6) | SW_SIGNER_ID) -#define TLV_MINOR_IAS_NSPE_EPOCH ((SW_NSPE << 6) | SW_EPOCH) -#define TLV_MINOR_IAS_NSPE_TYPE ((SW_NSPE << 6) | SW_TYPE) - -/* Secure processing environment (ARoT + PRoT) - single secure image */ -#define TLV_MINOR_IAS_SPE_MEASURE_VALUE ((SW_SPE << 6) | SW_MEASURE_VALUE) -#define TLV_MINOR_IAS_SPE_MEASURE_TYPE ((SW_SPE << 6) | SW_MEASURE_TYPE) -#define TLV_MINOR_IAS_SPE_VERSION ((SW_SPE << 6) | SW_VERSION) -#define TLV_MINOR_IAS_SPE_SIGNER_ID ((SW_SPE << 6) | SW_SIGNER_ID) -#define TLV_MINOR_IAS_SPE_EPOCH ((SW_SPE << 6) | SW_EPOCH) -#define TLV_MINOR_IAS_SPE_TYPE ((SW_SPE << 6) | SW_TYPE) - -/* SPE + NSPE - combined secure and non-secure image */ -#define TLV_MINOR_IAS_S_NS_MEASURE_VALUE ((SW_S_NS << 6) | SW_MEASURE_VALUE) -#define TLV_MINOR_IAS_S_NS_MEASURE_TYPE ((SW_S_NS << 6) | SW_MEASURE_TYPE) -#define TLV_MINOR_IAS_S_NS_VERSION ((SW_S_NS << 6) | SW_VERSION) -#define TLV_MINOR_IAS_S_NS_SIGNER_ID ((SW_S_NS << 6) | SW_SIGNER_ID) -#define TLV_MINOR_IAS_S_NS_EPOCH ((SW_S_NS << 6) | SW_EPOCH) -#define TLV_MINOR_IAS_S_NS_TYPE ((SW_S_NS << 6) | SW_TYPE) - -/* General macros to handle TLV type */ -#define MAJOR_MASK 0xF /* 4 bit */ -#define MAJOR_POS 12 /* 12 bit */ -#define MINOR_MASK 0xFFF /* 12 bit */ - -#define SET_TLV_TYPE(major, minor) \ - ((((major) & MAJOR_MASK) << MAJOR_POS) | ((minor) & MINOR_MASK)) -#define GET_MAJOR(tlv_type) ((tlv_type) >> MAJOR_POS) -#define GET_MINOR(tlv_type) ((tlv_type) & MINOR_MASK) - -/* Initial attestation specific macros */ -#define MODULE_POS 6 /* 6 bit */ -#define CLAIM_MASK 0x3F /* 6 bit */ -#define MEASUREMENT_CLAIM_POS 3 /* 3 bit */ - -#define GET_IAS_MODULE(tlv_type) (GET_MINOR(tlv_type) >> MODULE_POS) -#define GET_IAS_CLAIM(tlv_type) (GET_MINOR(tlv_type) & CLAIM_MASK) -#define SET_IAS_MINOR(sw_module, claim) (((sw_module) << 6) | (claim)) - -#define GET_IAS_MEASUREMENT_CLAIM(ias_claim) ((ias_claim) >> \ - MEASUREMENT_CLAIM_POS) - -/* Magic value which marks the beginning of shared data area in memory */ -#define SHARED_DATA_TLV_INFO_MAGIC 0x2016 - -/** - * Shared data TLV header. All fields in little endian. - * - * ----------------------------------- - * | tlv_magic(16) | tlv_tot_len(16) | - * ----------------------------------- - */ -struct shared_data_tlv_header { - uint16_t tlv_magic; - uint16_t tlv_tot_len; /* size of whole TLV area (including this header) */ -}; - -#define SHARED_DATA_HEADER_SIZE sizeof(struct shared_data_tlv_header) - -/** - * Shared data TLV entry header format. All fields in little endian. - * - * ------------------------------- - * | tlv_type(16) | tlv_len(16) | - * ------------------------------- - * | Raw data | - * ------------------------------- - */ -struct shared_data_tlv_entry { - uint16_t tlv_type; - uint16_t tlv_len; /* size of single TLV entry (including this header). */ -}; - -#define SHARED_DATA_ENTRY_HEADER_SIZE sizeof(struct shared_data_tlv_entry) -#define SHARED_DATA_ENTRY_SIZE(size) (size + SHARED_DATA_ENTRY_HEADER_SIZE) - -#ifdef __cplusplus -} -#endif - -#endif /* __TFM_BOOT_STATUS_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_plat_boot_seed.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_plat_boot_seed.h deleted file mode 100755 index 11b79f0..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_plat_boot_seed.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2018, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#ifndef __TFM_PLAT_BOOT_SEED_H__ -#define __TFM_PLAT_BOOT_SEED_H__ -/** - * \file tfm_plat_boot_seed.h - * - * Boot seed is used by a validating entity to ensure multiple reports were - * generated in the same boot session. Boot seed is a random number, generated - * only once during a boot cycle and its value is constant in the same cycle. - * Size recommendation is 256-bit to meet the statistically improbable property. - * Boot seed can be generated by secure boot loader an included to the measured - * boot state or can be generated by PRoT SW. - */ - -/** - * \note The interfaces defined in this file must be implemented for each - * SoC. - */ - -#include -#include "tfm_plat_defs.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/*! - * \def BOOT_SEED_SIZE - * - * \brief Size of boot seed in bytes. - */ -#define BOOT_SEED_SIZE (32u) - -/** - * \brief Gets the boot seed, which is a constant random number during a boot - * cycle. - * - * \param[in] size The required size of boot seed in bytes - * \param[out] buf Pointer to the buffer to store boot seed - * - * \return TFM_PLAT_ERR_SUCCESS if the value is generated correctly. Otherwise, - * it returns TFM_PLAT_ERR_SYSTEM_ERR. - */ -enum tfm_plat_err_t tfm_plat_get_boot_seed(uint32_t size, uint8_t *buf); - -#ifdef __cplusplus -} -#endif - -#endif /* __TFM_PLAT_BOOT_SEED_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_plat_crypto_keys.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_plat_crypto_keys.h deleted file mode 100755 index 386d61f..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_plat_crypto_keys.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2017-2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#ifndef __TFM_PLAT_CRYPTO_KEYS_H__ -#define __TFM_PLAT_CRYPTO_KEYS_H__ -/** - * \note The interfaces defined in this file must be implemented for each - * SoC. - */ - -#include -#include "tfm_plat_defs.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Elliptic curve key type identifiers according to RFC8152 (COSE encoding) - * https://www.iana.org/assignments/cose/cose.xhtml#elliptic-curves - */ -enum ecc_curve_t { - P_256 = 1, /* NIST P-256 also known as secp256r1 */ - P_384 = 2, /* NIST P-384 also known as secp384r1 */ - P_521 = 3, /* NIST P-521 also known as secp521r1 */ - X25519 = 4, /* X25519 for use with ECDH only */ - X448 = 5, /* X448 for use with ECDH only */ - ED25519 = 6, /* Ed25519 for use with EdDSA only */ - ED448 = 7, /* Ed448 for use with EdDSA only */ -}; - -/** - * Structure definition to carry pointer and size information about an Elliptic - * curve key which is stored in a buffer(key_buf) in raw format (without - * encoding): - * - priv_key Base address of the private key in key_buf. It must be - * present on the device. - * - priv_key_size Size of the private key in bytes. - * - pubx_key Base address of x-coordinate of the public key in key_buf. - * It can be empty, because it can be recomputed based on - * private key. - * - pubx_key_size Length of x-coordinate of the public key in key_buf. - * It can be empty, because it can be recomputed based on - * private key. - * - puby_key Base address of y-coordinate of the public key in key_buf. - * It can be empty, because either it can be recomputed based - * on private key or some curve type works without it. - * - puby_key_size Length of y-coordinate of the public key in key_buf. - */ -struct ecc_key_t { - uint8_t *priv_key; - uint32_t priv_key_size; - uint8_t *pubx_key; - uint32_t pubx_key_size; - uint8_t *puby_key; - uint32_t puby_key_size; -}; - -#define ECC_P_256_KEY_SIZE (96u) /* 3 x 32 = 96 bytes priv + pub-x + pub-y */ - -/** - * \brief Gets hardware unique key for encryption - * - * \param[out] key Buf to store the key in - * \param[in] size Size of the buffer - * - * \return Returns error code specified in \ref tfm_plat_err_t - */ -enum tfm_plat_err_t tfm_plat_get_crypto_huk(uint8_t *key, uint32_t size); - -/** - * \brief Get the initial attestation key - * - * The device MUST contain an initial attestation key, which is used to sign the - * token. Initial attestation service supports elliptic curve signing - * algorithms. Device maker can decide whether store only the private key on the - * device or store both (public and private) key. Public key can be recomputed - * based on private key. Keys must be provided in raw format, just binary data - * without any encoding (DER, COSE). Caller provides a buffer to copy all the - * available key components to there. Key components must be copied after - * each other to the buffer. The base address and the length of each key - * component must be indicating in the corresponding field of ecc_key - * (\ref struct ecc_key_t). - * Curve_type indicates to which curve belongs the key. - * - * - * Keys must be provided in - * - * \param[in/out] key_buf Buffer to store the initial attestation key. - * \param[in] size Size of the buffer. - * \param[out] ecc_key A structure to carry pointer and size information - * about the initial attestation key, which is - * stored in key_buf. - * \param[out] curve_type The type of the EC curve, which the key belongs - * to according to \ref ecc_curve_t - * - * \return Returns error code specified in \ref tfm_plat_err_t - */ -enum tfm_plat_err_t -tfm_plat_get_initial_attest_key(uint8_t *key_buf, - uint32_t size, - struct ecc_key_t *ecc_key, - enum ecc_curve_t *curve_type); - -#ifdef __cplusplus -} -#endif - -#endif /* __TFM_PLAT_CRYPTO_KEYS_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_plat_defs.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_plat_defs.h deleted file mode 100755 index 66747ee..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_plat_defs.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2017-2018, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#ifndef __TFM_PLAT_DEFS_H__ -#define __TFM_PLAT_DEFS_H__ -/** - * \note The interfaces defined in this file must be implemented for each - * target. - */ - -#include -#include - -enum tfm_plat_err_t { - TFM_PLAT_ERR_SUCCESS = 0, - TFM_PLAT_ERR_SYSTEM_ERR, - TFM_PLAT_ERR_MAX_VALUE, - /* Following entry is only to ensure the error code of int size */ - TFM_PLAT_ERR_FORCE_INT_SIZE = INT_MAX -}; - -/*! - * \def TFM_LINK_SET_OBJECT_IN_PARTITION_SECTION(TFM_PARTITION_NAME) - * - * \brief This macro provides a mechanism to place a function code in a specific - * secure partition at linker time in TF-M Level 3. - * - * \param[in] TFM_PARTITION_NAME TF-M partition name assigned in the manifest - * file "tfm_partition_name" field. - */ -#define TFM_LINK_SET_OBJECT_IN_PARTITION_SECTION(TFM_PARTITION_NAME) \ - __attribute__((section(TFM_PARTITION_NAME"_ATTR_FN"))) - -#endif /* __TFM_PLAT_DEFS_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_plat_device_id.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_plat_device_id.h deleted file mode 100755 index dcce837..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_plat_device_id.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2018-2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#ifndef __TFM_PLAT_DEVICE_ID_H__ -#define __TFM_PLAT_DEVICE_ID_H__ -/** - * \file tfm_plat_device_id.h - * - * The interfaces defined in this file are meant to provide the following - * attributes of the device: - * - Instance ID: Unique identifier of the device. - * - Implementation ID: Original implementation signer of the attestation key. - * - Hardware version: Identify the GDSII that went to fabrication. - */ - -/** - * \note The interfaces defined in this file must be implemented for each - * SoC. - */ - -#include -#include "tfm_plat_defs.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \def INSTANCE_ID_MAX_SIZE - * - * \brief Maximum size of instance ID in bytes - */ -#define INSTANCE_ID_MAX_SIZE (33u) - -/** - * \def IMPLEMENTATION_ID_MAX_SIZE - * - * \brief Maximum size of implementation ID in bytes - */ -#define IMPLEMENTATION_ID_MAX_SIZE (32u) - -/** - * \def HW_VERSION_MAX_SIZE - * - * \brief Maximum size of hardware version in bytes - * - * Recommended to use the European Article Number format: EAN-13+5 - */ -#define HW_VERSION_MAX_SIZE (18u) - -/** - * \brief Get the UEID of the device. - * - * This mandatory claim represents the unique identifier of the instance. - * In the PSA definition is a hash of the public attestation key of the - * instance. The claim will be represented by the EAT standard claim UEID - * of type GUID. The EAT definition of a GUID type is that it will be between - * 128 & 256 bits but this implementation will use the full 256 bits to - * accommodate a hash result. - * - * \param[in/out] size As an input value it indicates the size of the caller - * allocated buffer (in bytes) to store the UEID. At return - * its value is updated with the exact size of the UEID. - * \param[out] buf Pointer to the buffer to store the UEID - * - * \return Returns error code specified in \ref tfm_plat_err_t - */ -enum tfm_plat_err_t tfm_plat_get_instance_id(uint32_t *size, uint8_t *buf); - -/** - * \brief Get the Implementation ID of the device. - * - * This mandatory claim represents the original implementation signer of the - * attestation key and identifies the contract between the report and - * verification. A verification service will use this claim to locate the - * details of the verification process. The claim will be represented by a - * custom EAT claim with a value consisting of a CBOR byte string. The size of - * this string will normally be 32 bytes to accommodate a 256 bit hash. - * - * \param[in/out] size As an input value it indicates the size of the caller - * allocated buffer (in bytes) to store the implementation - * ID. At return its value is updated with the exact size - * of the implementation ID. - * \param[out] buf Pointer to the buffer to store the implementation ID - * - * \return Returns error code specified in \ref tfm_plat_err_t - */ -enum tfm_plat_err_t tfm_plat_get_implementation_id(uint32_t *size, - uint8_t *buf); - -/** - * \brief Get the hardware version of the device. - * - * This optional claim provides metadata linking the token to the GDSII that - * went to fabrication for this instance. It is represented as CBOR text string. - * It is recommended to use for identification the format of the European - * Article Number: EAN-13+5. - * - * \param[in/out] size As an input value it indicates the size of the caller - * allocated buffer (in bytes) to store the HW version. At - * return its value is updated with the exact size of the - * HW version. - * \param[out] buf Pointer to the buffer to store the HW version - * - * \return Returns error code specified in \ref tfm_plat_err_t - */ -enum tfm_plat_err_t tfm_plat_get_hw_version(uint32_t *size, uint8_t *buf); - -#ifdef __cplusplus -} -#endif - -#endif /* __TFM_PLAT_DEVICE_ID_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_memory_utils.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_memory_utils.h deleted file mode 100644 index 852399e..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_memory_utils.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -* Copyright (c) 2018-2019 ARM Limited. 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 __TFM_MEMORY_UTILS_H__ -#define __TFM_MEMORY_UTILS_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -void *tfm_memcpy(void *dest, const void *src, size_t num) -{ - return (memcpy(dest, src, num)); -} - -#ifdef __cplusplus -} -#endif - -#endif /* __TFM_MEMORY_UTILS_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/platform/platform_emul.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/platform/platform_emul.c deleted file mode 100644 index 8523413..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/platform/platform_emul.c +++ /dev/null @@ -1,40 +0,0 @@ -/* Copyright (c) 2019 ARM Limited - * - * 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 "psa/lifecycle.h" -#include "platform_srv_impl.h" - -uint32_t psa_security_lifecycle_state(void) -{ - uint32_t lc_state = 0; - psa_status_t status = PSA_SUCCESS; - status = psa_platfrom_lifecycle_get_impl(&lc_state); - if (status != PSA_SUCCESS) { - lc_state = PSA_LIFECYCLE_UNKNOWN; - } - return lc_state; -} - -psa_status_t mbed_psa_reboot_and_request_new_security_state(uint32_t new_state) -{ - return psa_platfrom_lifecycle_change_request_impl(new_state); -} - -void mbed_psa_system_reset(void) -{ - mbed_psa_system_reset_impl(); -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/platform/platform_srv_impl.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/platform/platform_srv_impl.c deleted file mode 100644 index 9854633..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/platform/platform_srv_impl.c +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright (c) 2019-2020 Arm Limited - * - * 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 "psa/lifecycle.h" -#include "psa/internal_trusted_storage.h" -#include "platform_srv_impl.h" -#include "cmsis.h" - -#ifndef MBED_CONF_LIFECYCLE_STATE -#define MBED_CONF_LIFECYCLE_STATE PSA_LIFECYCLE_ASSEMBLY_AND_TEST -#endif - -psa_status_t psa_platfrom_lifecycle_get_impl(uint32_t *lc_state) -{ - *lc_state = MBED_CONF_LIFECYCLE_STATE; - return PSA_SUCCESS; -} - -psa_status_t psa_its_reset(); - -psa_status_t psa_platfrom_lifecycle_change_request_impl(uint32_t state) -{ - if (PSA_LIFECYCLE_ASSEMBLY_AND_TEST == state) { - return psa_its_reset(); - } - return PSA_ERROR_NOT_SUPPORTED; -} - -MBED_WEAK void mbed_psa_system_reset_impl(void) -{ - /* Reset the system */ - NVIC_SystemReset(); -} - -MBED_WEAK enum tfm_platform_err_t tfm_platform_hal_ioctl(tfm_platform_ioctl_req_t request, - psa_invec *in_vec, - psa_outvec *out_vec) -{ - (void)in_vec; - (void)out_vec; - return TFM_PLATFORM_ERR_NOT_SUPPORTED; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/platform/platform_srv_impl.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/platform/platform_srv_impl.h deleted file mode 100644 index 29e704f..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/platform/platform_srv_impl.h +++ /dev/null @@ -1,43 +0,0 @@ -/* Copyright (c) 2019-2020 Arm Limited - * - * 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 __PLATFROM_SRV_IMPL_H__ -#define __PLATFROM_SRV_IMPL_H__ - -#include "psa/client.h" -#include "psa/lifecycle.h" -#include "mbed_toolchain.h" -#include "tfm_platform_api.h" - -psa_status_t psa_platfrom_lifecycle_get_impl(uint32_t *lc_state); -psa_status_t psa_platfrom_lifecycle_change_request_impl(uint32_t lc_state); -MBED_NORETURN void mbed_psa_system_reset_impl(void); - -/*! - * \brief Performs a platform-specific service - * - * \param[in] request Request identifier (valid values vary - * based on the platform) - * \param[in] in_vec Input buffer to the requested service (or NULL) - * \param[out] out_vec Output buffer to the requested service (or NULL) - * - * \return Returns values as specified by the \ref tfm_platform_err_t - */ -enum tfm_platform_err_t tfm_platform_hal_ioctl(tfm_platform_ioctl_req_t request, - psa_invec *in_vec, - psa_outvec *out_vec); -#endif // __PLATFROM_SRV_IMPL_H__ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/common/psa_storage_common_impl.cpp b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/common/psa_storage_common_impl.cpp deleted file mode 100644 index 1f68596..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/common/psa_storage_common_impl.cpp +++ /dev/null @@ -1,287 +0,0 @@ -/* Copyright (c) 2018 ARM Limited - * - * 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 -#include "TDBStore.h" -#include "psa_storage_common_impl.h" -#include "mbed_error.h" -#include "mbed_assert.h" -#include "mbed_toolchain.h" - -using namespace mbed; - -#ifdef __cplusplus -extern "C" -{ -#endif - -// Maximum length of filename we use for kvstore API. -// pid: 6; delimiter: 1; uid: 11; str terminator: 1 -#define PSA_STORAGE_FILE_NAME_MAX 19 - -#define FLAGS_MSK PSA_STORAGE_FLAG_WRITE_ONCE - -#define STR_EXPAND(tok) #tok - -const uint8_t base64_coding_table[] = { - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', - 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', - 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', - 'w', 'x', 'y', 'z', '0', '1', '2', '3', - '4', '5', '6', '7', '8', '9', '+', '-' -}; - -void psa_storage_handle_version(KVStore *kvstore, const char *version_key, const psa_storage_version_t *curr_version, - migrate_func_t migrate_func) -{ - psa_storage_version_t read_version = {0, 0}; - size_t actual_size = 0; - bool write_version = false; - int status = kvstore->get(version_key, &read_version, sizeof(read_version), &actual_size, 0); - if (status == MBED_SUCCESS) { - if (actual_size != sizeof(read_version)) { - error("PSA storage version data is corrupt"); - } - } else if (status == MBED_ERROR_ITEM_NOT_FOUND) { - write_version = true; - } else { - error("Could not read PSA storage version data"); - } - - if ((read_version.major > curr_version->major) || - ((read_version.major == curr_version->major) && (read_version.minor > curr_version->minor))) { - error("Downgrading PSA storage version is not allowed"); - } - - if ((read_version.major < curr_version->major) || - ((read_version.major == curr_version->major) && (read_version.minor < curr_version->minor))) { - psa_status_t migration_status = migrate_func(kvstore, &read_version, curr_version); - if (migration_status != PSA_SUCCESS) { - error("PSA storage migration failed"); - } - - write_version = true; - } - - if (write_version) { - if (kvstore->set(version_key, curr_version, sizeof(psa_storage_version_t), 0) != MBED_SUCCESS) { - error("Could not write PSA storage version"); - } - } -} - -/* - * \brief Convert KVStore stauts codes to PSA internal storage status codes - * - * \param[in] status - KVStore status code - * \return PSA internal storage status code - */ -static psa_status_t convert_status(int status) -{ - switch (status) { - case MBED_SUCCESS: - return PSA_SUCCESS; - case MBED_ERROR_WRITE_PROTECTED: - return PSA_ERROR_NOT_PERMITTED; - case MBED_ERROR_MEDIA_FULL: - return PSA_ERROR_INSUFFICIENT_STORAGE; - case MBED_ERROR_ITEM_NOT_FOUND: - return PSA_ERROR_DOES_NOT_EXIST; - case MBED_ERROR_INVALID_DATA_DETECTED: - return PSA_ERROR_DATA_CORRUPT; - case MBED_ERROR_INVALID_ARGUMENT: - return PSA_ERROR_INVALID_ARGUMENT; - case MBED_ERROR_READ_FAILED: // fallthrough - case MBED_ERROR_WRITE_FAILED: - return PSA_ERROR_STORAGE_FAILURE; - case MBED_ERROR_AUTHENTICATION_FAILED: // fallthrough - case MBED_ERROR_RBP_AUTHENTICATION_FAILED: - return PSA_ERROR_INVALID_SIGNATURE; - default: - return PSA_ERROR_GENERIC_ERROR; - } -} - -/* - * \brief Logic shift right - * - * \note must operate on unsinged integers to prevent negative carry - * \param x[in] input number for shifting - * \param n[in] number of bits to shift right - * \return the result - */ -static MBED_FORCEINLINE uint32_t lsr32(uint32_t x, uint32_t n) -{ - return x >> n; -} - -/* - * \brief Logic shift right - * - * \note must operate on unsinged integers to prevent negative carry - * \param x[in] input number for shifting - * \param n[in] number of bits to shift right - * \return the result - */ -static MBED_FORCEINLINE uint64_t lsr64(uint64_t x, uint32_t n) -{ - return x >> n; -} - -/* - * \breif Generate KVStore file name - * - * Generate KVStore file name by Base64 encoding PID and UID with a delimiter. - * Delimiter is required for determining between PID and UID. - * - * \param[out] tdb_filename - pointer to a buffer for the file name - * \param[in] tdb_filename_size - output buffer size - * \param[in] uid - PSA internal storage unique ID - * \param[in] pid - owner PSA partition ID - */ -static void generate_fn(char *tdb_filename, uint32_t tdb_filename_size, psa_storage_uid_t uid, int32_t pid) -{ - MBED_ASSERT(tdb_filename != NULL); - MBED_ASSERT(tdb_filename_size == PSA_STORAGE_FILE_NAME_MAX); - - uint8_t filename_idx = 0; - uint32_t unsigned_pid = (uint32_t)pid; // binary only representation for bitwise operations - - // Iterate on PID; each time convert 6 bits of PID into a character; first iteration must be done - do { - tdb_filename[filename_idx++] = base64_coding_table[unsigned_pid & 0x3F]; - unsigned_pid = lsr32(unsigned_pid, 6); - } while (unsigned_pid != 0); - - // Write delimiter - tdb_filename[filename_idx++] = '#'; - - // Iterate on UID; each time convert 6 bits of UID into a character; first iteration must be done - do { - tdb_filename[filename_idx++] = base64_coding_table[uid & 0x3F]; - uid = lsr64(uid, 6); - } while (uid != 0); - - tdb_filename[filename_idx++] = '\0'; - MBED_ASSERT(filename_idx <= PSA_STORAGE_FILE_NAME_MAX); -} - -psa_status_t psa_storage_set_impl(KVStore *kvstore, int32_t pid, psa_storage_uid_t uid, - size_t data_length, const void *p_data, - uint32_t kv_create_flags) -{ - if (uid == 0) { - return PSA_ERROR_INVALID_ARGUMENT; - } - // Generate KVStore key - char kv_key[PSA_STORAGE_FILE_NAME_MAX] = {'\0'}; - generate_fn(kv_key, PSA_STORAGE_FILE_NAME_MAX, uid, pid); - - int status = kvstore->set(kv_key, p_data, data_length, kv_create_flags); - - return convert_status(status); -} - -psa_status_t psa_storage_get_impl(KVStore *kvstore, int32_t pid, psa_storage_uid_t uid, - size_t data_offset, size_t data_length, void *p_data, size_t *p_data_length) -{ - if (uid == 0) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - // Generate KVStore key - char kv_key[PSA_STORAGE_FILE_NAME_MAX] = {'\0'}; - generate_fn(kv_key, PSA_STORAGE_FILE_NAME_MAX, uid, pid); - - KVStore::info_t kv_info; - int status = kvstore->get_info(kv_key, &kv_info); - - if (status == MBED_SUCCESS) { - if (data_offset > kv_info.size) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - // Verify (size + offset) does not wrap around - if (data_length + data_offset < data_length) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - if (data_offset + data_length > kv_info.size) { - return PSA_ERROR_BUFFER_TOO_SMALL; - } - - status = kvstore->get(kv_key, p_data, data_length, p_data_length, data_offset); - } - - return convert_status(status); -} - -psa_status_t psa_storage_get_info_impl(KVStore *kvstore, int32_t pid, psa_storage_uid_t uid, - struct psa_storage_info_t *p_info, uint32_t *kv_get_flags) -{ - - if (uid == 0) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - // Generate KVStore key - char kv_key[PSA_STORAGE_FILE_NAME_MAX] = {'\0'}; - generate_fn(kv_key, PSA_STORAGE_FILE_NAME_MAX, uid, pid); - - KVStore::info_t kv_info; - int status = kvstore->get_info(kv_key, &kv_info); - - if (status == MBED_SUCCESS) { - p_info->flags = 0; - if (kv_info.flags & KVStore::WRITE_ONCE_FLAG) { - p_info->flags |= PSA_STORAGE_FLAG_WRITE_ONCE; - } - *kv_get_flags = kv_info.flags; - p_info->size = kv_info.size; - p_info->capacity = kv_info.size; - } - - return convert_status(status); -} - -psa_status_t psa_storage_remove_impl(KVStore *kvstore, int32_t pid, psa_storage_uid_t uid) -{ - if (uid == 0) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - // Generate KVStore key - char kv_key[PSA_STORAGE_FILE_NAME_MAX] = {'\0'}; - generate_fn(kv_key, PSA_STORAGE_FILE_NAME_MAX, uid, pid); - - int status = kvstore->remove(kv_key); - - return convert_status(status); -} - -psa_status_t psa_storage_reset_impl(KVStore *kvstore) -{ - int status = kvstore->reset(); - return convert_status(status); -} - -#ifdef __cplusplus -} -#endif diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/common/psa_storage_common_impl.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/common/psa_storage_common_impl.h deleted file mode 100644 index 86f3617..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/common/psa_storage_common_impl.h +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright (c) 2019 ARM Limited - * - * 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 __PSA_STORAGE_COMMON_IMPL_H__ -#define __PSA_STORAGE_COMMON_IMPL_H__ - -#include "psa/error.h" -#include "psa/storage_common.h" -#include "KVStore.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -typedef struct { - uint32_t major; - uint32_t minor; -} psa_storage_version_t; - -typedef psa_status_t (*migrate_func_t)(mbed::KVStore *kvstore, const psa_storage_version_t *old_version, const psa_storage_version_t *new_version); - -void psa_storage_handle_version(mbed::KVStore *kvstore, const char *version_key, const psa_storage_version_t *version, - migrate_func_t migrate_func); -psa_status_t psa_storage_set_impl(mbed::KVStore *kvstore, int32_t pid, psa_storage_uid_t uid, size_t data_length, const void *p_data, uint32_t kv_create_flags); -psa_status_t psa_storage_get_impl(mbed::KVStore *kvstore, int32_t pid, psa_storage_uid_t uid, size_t data_offset, size_t data_length, void *p_data, size_t *p_data_length); -psa_status_t psa_storage_get_info_impl(mbed::KVStore *kvstore, int32_t pid, psa_storage_uid_t uid, struct psa_storage_info_t *p_info, uint32_t *kv_get_flags); -psa_status_t psa_storage_remove_impl(mbed::KVStore *kvstore, int32_t pid, psa_storage_uid_t uid); -psa_status_t psa_storage_reset_impl(mbed::KVStore *kvstore); - -#ifdef __cplusplus -} -#endif - - -#endif // __PSA_STORAGE_COMMON_IMPL_H__ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/its/pits_impl.cpp b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/its/pits_impl.cpp deleted file mode 100644 index 6f0835d..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/its/pits_impl.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/* Copyright (c) 2019 ARM Limited - * - * 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 -#include "KVStore.h" -#include "TDBStore.h" -#include "psa/internal_trusted_storage.h" -#include "psa_storage_common_impl.h" -#include "pits_impl.h" -#include "mbed_error.h" -#include "mbed_toolchain.h" - -using namespace mbed; - -#if defined(TARGET_TFM) -KVStore *get_its_kvstore_instance(void); -#else -#include "KVMap.h" -#endif - - - -#ifdef __cplusplus -extern "C" -{ -#endif - -#define STR_EXPAND(tok) #tok -#define ITS_VERSION_KEY "PSA_ITS_VERSION" // ITS version entry identifier in TDBStore - -static KVStore *kvstore = NULL; -static bool initialized = false; - - -MBED_WEAK psa_status_t its_version_migrate(KVStore *kvstore, - const psa_storage_version_t *old_version, const psa_storage_version_t *new_version) -{ - (void)kvstore; - (void)old_version; - (void)new_version; - return PSA_SUCCESS; -} - - -static void its_init(void) -{ -#if defined(TARGET_TFM) - kvstore = get_its_kvstore_instance(); -#else - KVMap &kv_map = KVMap::get_instance(); - kvstore = kv_map.get_internal_kv_instance(STR_EXPAND(MBED_CONF_STORAGE_DEFAULT_KV)); -#endif - psa_storage_version_t version = {PSA_ITS_API_VERSION_MAJOR, PSA_ITS_API_VERSION_MINOR}; - if (!kvstore) { - // Can only happen due to system misconfiguration. - // Thus considered as unrecoverable error for runtime. - error("Failed getting kvstore instance\n"); - } - - psa_storage_handle_version(kvstore, ITS_VERSION_KEY, &version, its_version_migrate); - initialized = true; -} - -// used from test only -void its_deinit(void) -{ - kvstore = NULL; - initialized = false; -} - - -psa_status_t psa_its_set_impl(int32_t pid, psa_storage_uid_t uid, size_t data_length, const void *p_data, psa_storage_create_flags_t create_flags) -{ - if (!initialized) { - its_init(); - } - - if (create_flags & ~PSA_STORAGE_FLAG_WRITE_ONCE) { - return PSA_ERROR_NOT_SUPPORTED; - } - - return psa_storage_set_impl(kvstore, pid, uid, data_length, p_data, create_flags); -} - -psa_status_t psa_its_get_impl(int32_t pid, psa_storage_uid_t uid, size_t data_offset, size_t data_length, void *p_data, size_t *p_data_length) -{ - if (!initialized) { - its_init(); - } - - return psa_storage_get_impl(kvstore, pid, uid, data_offset, data_length, p_data, p_data_length); -} - -psa_status_t psa_its_get_info_impl(int32_t pid, psa_storage_uid_t uid, struct psa_storage_info_t *p_info) -{ - uint32_t kv_get_flags; - if (!initialized) { - its_init(); - } - - return psa_storage_get_info_impl(kvstore, pid, uid, p_info, &kv_get_flags); -} - -psa_status_t psa_its_remove_impl(int32_t pid, psa_storage_uid_t uid) -{ - if (!initialized) { - its_init(); - } - - return psa_storage_remove_impl(kvstore, pid, uid); -} - -psa_status_t psa_its_reset_impl() -{ - // Do not call its_init here to avoid version check before reset -#if defined(TARGET_TFM) - kvstore = get_its_kvstore_instance(); -#else - KVMap &kv_map = KVMap::get_instance(); - kvstore = kv_map.get_internal_kv_instance(STR_EXPAND(MBED_CONF_STORAGE_DEFAULT_KV)); -#endif - if (!kvstore) { - // Can only happen due to system misconfiguration. - // Thus considered as unrecoverable error for runtime. - error("Failed getting kvstore instance\n"); - } - - return psa_storage_reset_impl(kvstore); -} - -#ifdef __cplusplus -} -#endif diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/its/pits_impl.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/its/pits_impl.h deleted file mode 100644 index 43d076d..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/its/pits_impl.h +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright (c) 2018 ARM Limited - * - * 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 __PITS_IMPL_H__ -#define __PITS_IMPL_H__ - -#include "psa/error.h" -#include "psa/storage_common.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -psa_status_t psa_its_set_impl(int32_t pid, psa_storage_uid_t uid, size_t data_length, const void *p_data, psa_storage_create_flags_t create_flags); -psa_status_t psa_its_get_impl(int32_t pid, psa_storage_uid_t uid, size_t data_offset, size_t data_length, void *p_data, size_t *p_data_length); -psa_status_t psa_its_get_info_impl(int32_t pid, psa_storage_uid_t uid, struct psa_storage_info_t *p_info); -psa_status_t psa_its_remove_impl(int32_t pid, psa_storage_uid_t uid); -psa_status_t psa_its_reset_impl(); - -#ifdef __cplusplus -} -#endif - -#endif // __PITS_IMPL_H__ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/its/psa_prot_internal_storage.cpp b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/its/psa_prot_internal_storage.cpp deleted file mode 100644 index bce3709..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/its/psa_prot_internal_storage.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* Copyright (c) 2018 ARM Limited - * - * 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 -#include - -#include "psa/internal_trusted_storage.h" -#include "psa/storage_common.h" -#include "pits_impl.h" -#include "kv_config.h" -#include "mbed_error.h" - -// In EMUL world, there is no real partitioning, which makes the source partition irrelevant. -// So here we set a global pid value to be used for when calling IMPL functions -#define PSA_ITS_EMUL_PID 1 - -psa_status_t psa_its_set(psa_storage_uid_t uid, size_t data_length, const void *p_data, psa_storage_create_flags_t create_flags) -{ - if (!p_data && data_length) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - // KVStore initiation: - // - In EMUL (non-secure single core) we do it here since we don't have another context to do it inside. - // - Repeating calls has no effect - int kv_status = kv_init_storage_config(); - if (kv_status != MBED_SUCCESS) { - return PSA_ERROR_STORAGE_FAILURE; - } - - psa_status_t res = psa_its_set_impl(PSA_ITS_EMUL_PID, uid, data_length, p_data, create_flags); - - return res; -} - -psa_status_t psa_its_get(psa_storage_uid_t uid, size_t data_offset, size_t data_length, void *p_data, size_t *p_data_length) -{ - if ((!p_data && data_length) || !p_data_length) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - // KVStore initiation: - // - In EMUL (non-secure single core) we do it here since we don't have another context to do it inside. - // - Repeating calls has no effect - int kv_status = kv_init_storage_config(); - if (kv_status != MBED_SUCCESS) { - return PSA_ERROR_STORAGE_FAILURE; - } - - return psa_its_get_impl(PSA_ITS_EMUL_PID, uid, data_offset, data_length, p_data, p_data_length); -} - -psa_status_t psa_its_get_info(psa_storage_uid_t uid, struct psa_storage_info_t *p_info) -{ - if (!p_info) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - // KVStore initiation: - // - In EMUL (non-secure single core) we do it here since we don't have another context to do it inside. - // - Repeating calls has no effect - int kv_status = kv_init_storage_config(); - if (kv_status != MBED_SUCCESS) { - return PSA_ERROR_STORAGE_FAILURE; - } - - return psa_its_get_info_impl(PSA_ITS_EMUL_PID, uid, p_info); -} - -psa_status_t psa_its_remove(psa_storage_uid_t uid) -{ - // KVStore initiation: - // - In EMUL (non-secure single core) we do it here since we don't have another context to do it inside. - // - Repeating calls has no effect - int kv_status = kv_init_storage_config(); - if (kv_status != MBED_SUCCESS) { - return PSA_ERROR_STORAGE_FAILURE; - } - - return psa_its_remove_impl(PSA_ITS_EMUL_PID, uid); -} - -extern "C" psa_status_t psa_its_reset() -{ - // KVStore initiation: - // - In EMUL (non-secure single core) we do it here since we don't have another context to do it inside. - // - Repeating calls has no effect - int kv_status = kv_init_storage_config(); - if (kv_status != MBED_SUCCESS) { - return PSA_ERROR_STORAGE_FAILURE; - } - - return psa_its_reset_impl(); -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/its/psa_prot_internal_storage.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/its/psa_prot_internal_storage.h deleted file mode 100644 index b4e1a0e..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/its/psa_prot_internal_storage.h +++ /dev/null @@ -1,164 +0,0 @@ -/* Copyright (C) 2019, ARM Limited, 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. - */ -/** @file -@brief This file describes the PSA Internal Trusted Storage API -*/ - -#ifndef __PSA_INTERNAL_TRUSTED_STORAGE_H__ -#define __PSA_INTERNAL_TRUSTED_STORAGE_H__ - -#include -#include - -#include "psa/error.h" -#include "psa/storage_common.h" -#include "mbed_toolchain.h" - -#ifdef __cplusplus -extern "C" { -#endif -#define PSA_ITS_API_VERSION_MAJOR 1 /**< The major version number of the PSA ITS API. It will be incremented on significant updates that may include breaking changes */ -#define PSA_ITS_API_VERSION_MINOR 1 /**< The minor version number of the PSA ITS API. It will be incremented in small updates that are unlikely to include breaking changes */ - -// These deprecated types are still used by our PSA compliance test tools -MBED_DEPRECATED("ITS specific types should not be used") -typedef psa_status_t psa_its_status_t; - -MBED_DEPRECATED("ITS specific types should not be used") -typedef psa_storage_create_flags_t psa_its_create_flags_t; - -MBED_DEPRECATED("ITS specific types should not be used") -typedef psa_storage_uid_t psa_its_uid_t; - -MBED_DEPRECATED("ITS specific types should not be used") -#define psa_its_info_t psa_storage_info_t - -// These defines should also be deprecated -#define PSA_ITS_SUCCESS PSA_SUCCESS -#define PSA_ITS_ERROR_UID_NOT_FOUND PSA_ERROR_DOES_NOT_EXIST -#define PSA_ITS_ERROR_STORAGE_FAILURE PSA_ERROR_STORAGE_FAILURE -#define PSA_ITS_ERROR_INSUFFICIENT_SPACE PSA_ERROR_INSUFFICIENT_STORAGE -#define PSA_ITS_ERROR_OFFSET_INVALID PSA_ERROR_INVALID_ARGUMENT -#define PSA_ITS_ERROR_INCORRECT_SIZE PSA_ERROR_BUFFER_TOO_SMALL -#define PSA_ITS_ERROR_INVALID_ARGUMENTS PSA_ERROR_INVALID_ARGUMENT -#define PSA_ITS_ERROR_FLAGS_NOT_SUPPORTED PSA_ERROR_NOT_SUPPORTED -#define PSA_ITS_ERROR_WRITE_ONCE PSA_ERROR_NOT_PERMITTED -#define PSA_ITS_FLAG_WRITE_ONCE PSA_STORAGE_FLAG_WRITE_ONCE - -MBED_DEPRECATED("PS specific types should not be used") -typedef psa_status_t psa_ps_status_t; -MBED_DEPRECATED("PS specific types should not be used") -typedef psa_storage_uid_t psa_ps_uid_t; -MBED_DEPRECATED("PS specific types should not be used") -typedef psa_storage_create_flags_t psa_ps_create_flags_t; -MBED_DEPRECATED("PS specific types should not be used") -#define psa_ps_info_t psa_storage_info_t - -#define PSA_PS_SUCCESS PSA_SUCCESS -#define PSA_PS_ERROR_UID_NOT_FOUND PSA_ERROR_DOES_NOT_EXIST -#define PSA_PS_ERROR_STORAGE_FAILURE PSA_ERROR_STORAGE_FAILURE -#define PSA_PS_ERROR_INSUFFICIENT_SPACE PSA_ERROR_INSUFFICIENT_STORAGE -#define PSA_PS_ERROR_OFFSET_INVALID PSA_ERROR_INVALID_ARGUMENT -#define PSA_PS_ERROR_INCORRECT_SIZE PSA_ERROR_BUFFER_TOO_SMALL -#define PSA_PS_ERROR_INVALID_ARGUMENT PSA_ERROR_INVALID_ARGUMENT -#define PSA_PS_ERROR_FLAGS_NOT_SUPPORTED PSA_ERROR_NOT_SUPPORTED -#define PSA_PS_ERROR_WRITE_ONCE PSA_ERROR_NOT_PERMITTED -#define PSA_PS_FLAG_WRITE_ONCE PSA_STORAGE_FLAG_WRITE_ONCE - -/** - * \brief create a new or modify an existing uid/value pair - * - * \param[in] uid the identifier for the data - * \param[in] data_length The size in bytes of the data in `p_data` - * \param[in] p_data A buffer containing the data - * \param[in] create_flags The flags that the data will be stored with - * - * \return A status indicating the success/failure of the operation - - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the provided `uid` value was already created with PSA_STORAGE_WRITE_ONCE_FLAG - * \retval PSA_ERROR_NOT_SUPPORTED The operation failed because one or more of the flags provided in `create_flags` is not supported or is not valid - * \retval PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because there was insufficient space on the storage medium - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) - * \retval PSA_ERROR_INVALID_ARGUMENTS The operation failed because one of the provided pointers(`p_data`) - * is invalid, for example is `NULL` or references memory the caller cannot access - */ -psa_status_t psa_its_set(psa_storage_uid_t uid, - size_t data_length, - const void *p_data, - psa_storage_create_flags_t create_flags); - -/** - * \brief Retrieve the value associated with a provided uid - * - * \param[in] uid The uid value - * \param[in] data_offset The starting offset of the data requested - * \param[in] data_length the amount of data requested (and the minimum allocated size of the `p_data` buffer) - * \param[out] p_data The buffer where the data will be placed upon successful completion - * \param[out] p_data_length The actual amount of data returned - - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided `uid` value was not found in the storage - * \retval PSA_ERROR_BUFFER_TOO_SMALL The operation failed because the data associated with provided `uid` is not the same size as `data_size` - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_data`, `p_data_length`) - * is invalid. For example is `NULL` or references memory the caller cannot access - */ -psa_status_t psa_its_get(psa_storage_uid_t uid, - size_t data_offset, - size_t data_length, - void *p_data, - size_t *p_data_length); - -/** - * \brief Retrieve the metadata about the provided uid - * - * \param[in] uid The uid value - * \param[out] p_info A pointer to the `psa_storage_info_t` struct that will be populated with the metadata - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided uid value was not found in the storage - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_info`) - * is invalid, for example is `NULL` or references memory the caller cannot access - */ -psa_status_t psa_its_get_info(psa_storage_uid_t uid, - struct psa_storage_info_t *p_info); - -/** - * \brief Remove the provided key and its associated data from the storage - * - * \param[in] uid The uid value - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided key value was not found in the storage - * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the provided key value was created with PSA_STORAGE_WRITE_ONCE_FLAG - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) - */ -psa_status_t psa_its_remove(psa_storage_uid_t uid); - -#ifdef __cplusplus -} -#endif - -#endif // __PSA_INTERNAL_TRUSTED_STORAGE_H__ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/ps/protected_storage.cpp b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/ps/protected_storage.cpp deleted file mode 100644 index 65aea41..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/ps/protected_storage.cpp +++ /dev/null @@ -1,173 +0,0 @@ -/* Copyright (c) 2019 ARM Limited - * - * 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 -#include "KVMap.h" -#include "KVStore.h" -#include "kv_config.h" -#include "TDBStore.h" -#include "psa/protected_storage.h" -#include "psa_storage_common_impl.h" -#include "mbed_error.h" -#include "mbed_toolchain.h" - -using namespace mbed; - -#ifdef __cplusplus -extern "C" -{ -#endif - -#define STR_EXPAND(tok) #tok -#define PS_VERSION_KEY "PSA_PS_VERSION" // PS version entry identifier in TDBStore - -// Global PID for protected storage, used when calling IMPL functions -#define PSA_PS_GLOBAL_PID 1 - -static KVStore *kvstore = NULL; -static bool initialized = false; - -MBED_WEAK psa_status_t ps_version_migrate(KVStore *kvstore, - const psa_storage_version_t *old_version, const psa_storage_version_t *new_version) -{ - (void)kvstore; - (void)old_version; - (void)new_version; - return PSA_SUCCESS; -} - - -static void ps_init(void) -{ - int ret = kv_init_storage_config(); - if (ret) { - // Can only happen due to system misconfiguration. - // Thus considered as unrecoverable error for runtime. - error("Failed initializing kvstore configuration\n"); - } - KVMap &kv_map = KVMap::get_instance(); - psa_storage_version_t version = {PSA_PS_API_VERSION_MAJOR, PSA_PS_API_VERSION_MINOR}; - kvstore = kv_map.get_main_kv_instance(STR_EXPAND(MBED_CONF_STORAGE_DEFAULT_KV)); - KVStore *int_kvstore = kv_map.get_internal_kv_instance(STR_EXPAND(MBED_CONF_STORAGE_DEFAULT_KV));; - if (!kvstore || !int_kvstore) { - // Can only happen due to system misconfiguration. - // Thus considered as unrecoverable error for runtime. - error("Failed getting kvstore instance\n"); - } - - psa_storage_handle_version(kvstore, PS_VERSION_KEY, &version, ps_version_migrate); - initialized = true; -} - -// used from test only -void ps_deinit(void) -{ - kvstore = NULL; - initialized = false; -} - - -psa_status_t psa_ps_set(psa_storage_uid_t uid, size_t data_length, const void *p_data, psa_storage_create_flags_t create_flags) -{ - if (!initialized) { - ps_init(); - } - - if (create_flags & ~ - (PSA_STORAGE_FLAG_WRITE_ONCE | PSA_STORAGE_FLAG_NO_CONFIDENTIALITY | PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION)) { - return PSA_ERROR_NOT_SUPPORTED; - } - - // Assume confidentiality and replay protection are set by default - uint32_t kv_create_flags = KVStore::REQUIRE_CONFIDENTIALITY_FLAG | KVStore::REQUIRE_REPLAY_PROTECTION_FLAG; - - if (create_flags & PSA_STORAGE_FLAG_NO_CONFIDENTIALITY) { - kv_create_flags &= ~KVStore::REQUIRE_CONFIDENTIALITY_FLAG; - } - if (create_flags & PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION) { - kv_create_flags &= ~KVStore::REQUIRE_REPLAY_PROTECTION_FLAG; - } - if (create_flags & PSA_STORAGE_FLAG_WRITE_ONCE) { - kv_create_flags |= KVStore::WRITE_ONCE_FLAG; - } - - return psa_storage_set_impl(kvstore, PSA_PS_GLOBAL_PID, uid, data_length, p_data, kv_create_flags); -} - -psa_status_t psa_ps_get(psa_storage_uid_t uid, size_t data_offset, size_t data_length, void *p_data, size_t *p_data_length) -{ - if (!initialized) { - ps_init(); - } - - return psa_storage_get_impl(kvstore, PSA_PS_GLOBAL_PID, uid, data_offset, data_length, p_data, p_data_length); -} - -psa_status_t psa_ps_get_info(psa_storage_uid_t uid, struct psa_storage_info_t *p_info) -{ - psa_status_t ret; - uint32_t kv_get_flags; - - if (!initialized) { - ps_init(); - } - - ret = psa_storage_get_info_impl(kvstore, PSA_PS_GLOBAL_PID, uid, p_info, &kv_get_flags); - - if ((kv_get_flags & ~KVStore::REQUIRE_CONFIDENTIALITY_FLAG) == kv_get_flags) { - p_info->flags |= PSA_STORAGE_FLAG_NO_CONFIDENTIALITY; - } - if ((kv_get_flags & ~KVStore::REQUIRE_REPLAY_PROTECTION_FLAG) == kv_get_flags) { - p_info->flags |= PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION; - } - - return ret; -} - -psa_status_t psa_ps_remove(psa_storage_uid_t uid) -{ - if (!initialized) { - ps_init(); - } - - return psa_storage_remove_impl(kvstore, PSA_PS_GLOBAL_PID, uid); -} - -extern "C" psa_status_t psa_ps_reset() -{ - // Do not call its_init here to avoid version check before reset - int ret = kv_init_storage_config(); - if (ret) { - // Can only happen due to system misconfiguration. - // Thus considered as unrecoverable error for runtime. - error("Failed initializing kvstore configuration\n"); - } - - KVMap &kv_map = KVMap::get_instance(); - kvstore = kv_map.get_main_kv_instance(STR_EXPAND(MBED_CONF_STORAGE_DEFAULT_KV)); - if (!kvstore) { - // Can only happen due to system misconfiguration. - // Thus considered as unrecoverable error for runtime. - error("Failed getting kvstore instance\n"); - } - - return psa_storage_reset_impl(kvstore); -} - -#ifdef __cplusplus -} -#endif diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/src/client.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/src/client.c deleted file mode 100644 index 2cc8bb4..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/src/client.c +++ /dev/null @@ -1,51 +0,0 @@ -/* Copyright (c) 2017-2020 ARM Limited - * - * 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. - */ - -/* This implementation of the PSA Client API is provided for application - * compatibility on single v7-M targets. The client implementation is stubbed - * and non-functional, but present and returns sane errors. */ - -#include "psa/client.h" - -uint32_t psa_framework_version(void) -{ - return PSA_FRAMEWORK_VERSION; -} - -uint32_t psa_version(uint32_t sid) -{ - return PSA_VERSION_NONE; -} - -psa_handle_t psa_connect(uint32_t sid, uint32_t version) -{ - return PSA_ERROR_PROGRAMMER_ERROR; -} - -psa_status_t psa_call(psa_handle_t handle, int32_t type, - const psa_invec *in_vec, - size_t in_len, - psa_outvec *out_vec, - size_t out_len) -{ - return PSA_ERROR_PROGRAMMER_ERROR; -} - -void psa_close(psa_handle_t handle) -{ - return; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/src/default_random_seed.cpp b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/src/default_random_seed.cpp deleted file mode 100644 index 8c955f1..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/src/default_random_seed.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "mbed.h" -#include "crypto.h" -#include "default_random_seed.h" -#include "psa/internal_trusted_storage.h" - -int mbed_default_seed_read(unsigned char *buf, size_t buf_len) -{ - size_t actual_size; - psa_status_t rc = psa_its_get(PSA_CRYPTO_ITS_RANDOM_SEED_UID, 0, buf_len, buf, &actual_size); - return (rc); -} - -int mbed_default_seed_write(unsigned char *buf, size_t buf_len) -{ - psa_status_t rc = psa_its_set(PSA_CRYPTO_ITS_RANDOM_SEED_UID, buf_len, buf, 0); - return (rc); -} - diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val.h deleted file mode 100644 index e4d1fa4..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val.h +++ /dev/null @@ -1,277 +0,0 @@ -/** @file - * Copyright (c) 2018-2019, 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 _VAL_COMMON_H_ -#define _VAL_COMMON_H_ - -#include "pal_common.h" - -#ifndef VAL_NSPE_BUILD -#define STATIC_DECLARE static -#else -#define STATIC_DECLARE -#endif - -#ifndef __WEAK -#define __WEAK __attribute__((weak)) -#endif - -#ifndef __UNUSED -#define __UNUSED __attribute__((unused)) -#endif - -#ifndef TRUE -#define TRUE 0 -#endif -#ifndef FALSE -#define FALSE 1 -#endif - -#ifndef INT_MAX -#define INT_MAX 0xFFFFFFFF -#endif - -#define _CONCAT(A,B) A##B -#define CONCAT(A,B) _CONCAT(A,B) - -/* test status defines */ -#define TEST_START 0x01 -#define TEST_END 0x02 -#define TEST_PASS 0x04 -#define TEST_FAIL 0x08 -#define TEST_SKIP 0x10 -#define TEST_PENDING 0x20 - -#define TEST_NUM_BIT 32 -#define TEST_STATE_BIT 8 -#define TEST_STATUS_BIT 0 - -#define TEST_NUM_MASK 0xFFFFFFFF -#define TEST_STATE_MASK 0xFF -#define TEST_STATUS_MASK 0xFF - -#define RESULT_START(status) (((TEST_START) << TEST_STATE_BIT) | ((status) << TEST_STATUS_BIT)) -#define RESULT_END(status) (((TEST_END) << TEST_STATE_BIT) | ((status) << TEST_STATUS_BIT)) -#define RESULT_PASS(status) (((TEST_PASS) << TEST_STATE_BIT) | ((status) << TEST_STATUS_BIT)) -#define RESULT_FAIL(status) (((TEST_FAIL) << TEST_STATE_BIT) | ((status) << TEST_STATUS_BIT)) -#define RESULT_SKIP(status) (((TEST_SKIP) << TEST_STATE_BIT) | ((status) << TEST_STATUS_BIT)) -#define RESULT_PENDING(status) (((TEST_PENDING) << TEST_STATE_BIT) | ((status) << TEST_STATUS_BIT)) - -#define IS_TEST_FAIL(status) (((status >> TEST_STATE_BIT) & TEST_STATE_MASK) == TEST_FAIL) -#define IS_TEST_PASS(status) (((status >> TEST_STATE_BIT) & TEST_STATE_MASK) == TEST_PASS) -#define IS_TEST_SKIP(status) (((status >> TEST_STATE_BIT) & TEST_STATE_MASK) == TEST_SKIP) -#define IS_TEST_PENDING(status) (((status >> TEST_STATE_BIT) & TEST_STATE_MASK) == TEST_PENDING) -#define IS_TEST_START(status) (((status >> TEST_STATE_BIT) & TEST_STATE_MASK) == TEST_START) -#define IS_TEST_END(status) (((status >> TEST_STATE_BIT) & TEST_STATE_MASK) == TEST_END) -#define VAL_ERROR(status) ((status & TEST_STATUS_MASK) ? 1 : 0) - - - -/* Test Defines */ -#define TEST_PUBLISH(test_id, entry) - -#define VAL_MAX_TEST_PER_COMP 200 -#define VAL_FF_BASE 0 -#define VAL_CRYPTO_BASE 1 -#define VAL_PROTECTED_STORAGE_BASE 2 -#define VAL_INTERNAL_TRUSTED_STORAGE_BASE 3 -#define VAL_INITIAL_ATTESTATION_BASE 4 - -#define VAL_GET_COMP_NUM(test_id) \ - ((test_id - (test_id % VAL_MAX_TEST_PER_COMP)) / VAL_MAX_TEST_PER_COMP) -#define VAL_GET_TEST_NUM(test_id) (test_id % VAL_MAX_TEST_PER_COMP) -#define VAL_CREATE_TEST_ID(comp,num) ((comp*VAL_MAX_TEST_PER_COMP) + num) - -#define TEST_FIELD(num1,num2) (num2 << 8 | num1) -#define GET_TEST_ISOLATION_LEVEL(num) (num & 0x3) -#define GET_WD_TIMOUT_TYPE(num) ((num >> 8) & 0x7) - -#define TEST_CHECKPOINT_NUM(n) n -#define TEST(n) n -#define BLOCK(n) n - -#define BLOCK_NUM_POS 8 -#define ACTION_POS 16 -#define GET_TEST_NUM(n) (0xff & n) -#define GET_BLOCK_NUM(n) ((n >> BLOCK_NUM_POS) & 0xff) - -#define GET_ACTION_NUM(n) ((n >> ACTION_POS) & 0xff) -#define TEST_EXECUTE_FUNC 1 -#define TEST_RETURN_RESULT 2 -#define INVALID_HANDLE 0x1234DEAD - -#define VAL_NVMEM_BLOCK_SIZE 4 -#define VAL_NVMEM_OFFSET(nvmem_idx) (nvmem_idx * VAL_NVMEM_BLOCK_SIZE) - -#define UART_INIT_SIGN 0xff -#define UART_PRINT_SIGN 0xfe - -#define TEST_PANIC() \ - do { \ - } while(1) - -#define TEST_ASSERT_EQUAL(arg1, arg2, checkpoint) \ - do { \ - if ((arg1) != arg2) \ - { \ - val->print(PRINT_ERROR, "\tFailed at Checkpoint: %d\n", checkpoint); \ - val->print(PRINT_ERROR, "\tActual: %d\n", arg1); \ - val->print(PRINT_ERROR, "\tExpected: %d\n", arg2); \ - return 1; \ - } \ - } while (0) - -#define TEST_ASSERT_DUAL(arg1, status1, status2, checkpoint) \ - do { \ - if ((arg1) != status1 && (arg1) != status2) \ - { \ - val->print(PRINT_ERROR, "\tFailed at Checkpoint: %d\n", checkpoint); \ - val->print(PRINT_ERROR, "\tActual: %d\n", arg1); \ - val->print(PRINT_ERROR, "\tExpected: %d", status1); \ - val->print(PRINT_ERROR, "or %d\n", status2); \ - return 1; \ - } \ - } while (0) - -#define TEST_ASSERT_NOT_EQUAL(arg1, arg2, checkpoint) \ - do { \ - if ((arg1) == arg2) \ - { \ - val->print(PRINT_ERROR, "\tFailed at Checkpoint: %d\n", checkpoint); \ - val->print(PRINT_ERROR, "\tValue: %d\n", arg1); \ - return 1; \ - } \ - } while (0) - -#define TEST_ASSERT_MEMCMP(buf1, buf2, size, checkpoint) \ - do { \ - if (memcmp(buf1, buf2, size)) \ - { \ - val->print(PRINT_ERROR, "\tFailed at Checkpoint: %d : ", checkpoint); \ - val->print(PRINT_ERROR, "Unequal data in compared buffers\n", 0); \ - return 1; \ - } \ - } while (0) - -/* enums */ -typedef enum { - CALLER_NONSECURE = 0x0, - CALLER_SECURE = 0x1, -} caller_security_t; - -typedef enum { - TEST_ISOLATION_L1 = 0x1, - TEST_ISOLATION_L2 = 0x2, - TEST_ISOLATION_L3 = 0x3, -} test_isolation_level_t; - -typedef enum { - BOOT_UNKNOWN = 0x1, - BOOT_NOT_EXPECTED = 0x2, - BOOT_EXPECTED_NS = 0x3, - BOOT_EXPECTED_S = 0x4, - BOOT_EXPECTED_BUT_FAILED = 0x5, - BOOT_EXPECTED_CRYPTO = 0x6, -} boot_state_t; - -typedef enum { - NV_BOOT = 0x0, - NV_TEST_ID_PREVIOUS = 0x1, - NV_TEST_ID_CURRENT = 0x2, - NV_TEST_CNT = 0x3, -} nvmem_index_t; - -/* enums to report test sub-state */ -typedef enum { - VAL_STATUS_SUCCESS = 0x0, - VAL_STATUS_INVALID = 0x10, - VAL_STATUS_ERROR = 0x11, - VAL_STATUS_NOT_FOUND = 0x12, - VAL_STATUS_LOAD_ERROR = 0x13, - VAL_STATUS_INSUFFICIENT_SIZE = 0x14, - VAL_STATUS_CONNECTION_FAILED = 0x15, - VAL_STATUS_CALL_FAILED = 0x16, - VAL_STATUS_READ_FAILED = 0x17, - VAL_STATUS_WRITE_FAILED = 0x18, - VAL_STATUS_ISOLATION_LEVEL_NOT_SUPP = 0x19, - VAL_STATUS_INIT_FAILED = 0x1A, - VAL_STATUS_SPM_FAILED = 0x1B, - VAL_STATUS_SPM_UNEXPECTED_BEH = 0x1C, - VAL_STATUS_FRAMEWORK_VERSION_FAILED = 0x1D, - VAL_STATUS_VERSION_API_FAILED = 0x1E, - VAL_STATUS_INVALID_HANDLE = 0x1F, - VAL_STATUS_INVALID_MSG_TYPE = 0x20, - VAL_STATUS_WRONG_IDENTITY = 0x21, - VAL_STATUS_MSG_INSIZE_FAILED = 0x22, - VAL_STATUS_MSG_OUTSIZE_FAILED = 0x23, - VAL_STATUS_SKIP_FAILED = 0x24, - VAL_STATUS_CRYPTO_FAILURE = 0x25, - VAL_STATUS_INVALID_SIZE = 0x26, - VAL_STATUS_DATA_MISMATCH = 0x27, - VAL_STATUS_BOOT_EXPECTED_BUT_FAILED = 0x28, - VAL_STATUS_INIT_ALREADY_DONE = 0x29, - VAL_STATUS_HEAP_NOT_AVAILABLE = 0x2A, - VAL_STATUS_UNSUPPORTED = 0x2B, - VAL_STATUS_ERROR_MAX = INT_MAX, -} val_status_t; - -/* verbosity enums */ -typedef enum { - PRINT_INFO = 1, - PRINT_DEBUG = 2, - PRINT_TEST = 3, - PRINT_WARN = 4, - PRINT_ERROR = 5, - PRINT_ALWAYS = 9 -} print_verbosity_t; - -/* Interrupt test function id enums */ -typedef enum { - TEST_PSA_EOI_WITH_NON_INTR_SIGNAL = 1, - TEST_PSA_EOI_WITH_MULTIPLE_SIGNALS = 2, - TEST_PSA_EOI_WITH_UNASSERTED_SIGNAL = 3, - TEST_INTR_SERVICE = 4, -} test_intr_fn_id_t; - -/* typedef's */ -typedef struct { - boot_state_t state; -} boot_t; - -typedef struct { - uint32_t pass_cnt: 8; - uint32_t skip_cnt: 8; - uint32_t fail_cnt: 8; - uint32_t sim_error_cnt: 8; -} test_count_t; - -typedef struct { - uint16_t test_num; - uint8_t block_num; -} test_info_t; - - -/* struture to capture test state */ -typedef struct { - uint16_t reserved; - uint8_t state; - uint8_t status; -} test_status_buffer_t; - -typedef int32_t (*client_test_t)(caller_security_t caller); -typedef int32_t (*server_test_t)(void); -#endif /* VAL_COMMON_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_attestation.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_attestation.c deleted file mode 100644 index cd8069a..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_attestation.c +++ /dev/null @@ -1,40 +0,0 @@ -/** @file - * Copyright (c) 2019, 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_target.h" -#include "pal_interfaces_ns.h" -#include "val_framework.h" -#include "val_client_defs.h" -#include "val_attestation.h" - -/** - @brief - This API will call the requested attestation function - @param - type : function code - ... : variable number of arguments - @return - Error status -**/ - -int32_t val_attestation_function(int type, ...) -{ - va_list valist; - val_status_t status; - - va_start(valist, type); - status = pal_attestation_function(type, valist); - va_end(valist); - return status; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_attestation.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_attestation.h deleted file mode 100644 index 5322723..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_attestation.h +++ /dev/null @@ -1,33 +0,0 @@ -/** @file - * Copyright (c) 2019, 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 _VAL_INITIAL_ATTESTATION_H_ -#define _VAL_INITIAL_ATTESTATION_H_ - -#include "val.h" -#include "psa_initial_attestation_api.h" - -#define MAX_CHALLENGE_SIZE PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64 - -enum attestation_function_code { - VAL_INITIAL_ATTEST_GET_TOKEN = 0x1, - VAL_INITIAL_ATTEST_GET_TOKEN_SIZE = 0x2, - VAL_INITIAL_ATTEST_VERIFY_TOKEN = 0x3, -}; - -int32_t val_attestation_function(int type, ...); -#endif /* _VAL_INITIAL_ATTESTATION_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_client_defs.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_client_defs.h deleted file mode 100644 index d1d18d7..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_client_defs.h +++ /dev/null @@ -1,34 +0,0 @@ -/** @file - * Copyright (c) 2018-2019, 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 _VAL_CLIENT_H_ -#define _VAL_CLIENT_H_ - -#include "val.h" -#include "psa/client.h" -#include "crypto_values.h" - -#define INVALID_SID 0x0000FA20 - -#ifndef CLIENT_TEST_DISPATCHER_SID -#define CLIENT_TEST_DISPATCHER_SID 0x0 -#endif - -#ifndef SERVER_TEST_DISPATCHER_SID -#define SERVER_TEST_DISPATCHER_SID 0x0 -#endif -#endif /* _VAL_CLIENT_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_entry.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_entry.h deleted file mode 100644 index 2b885e0..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_entry.h +++ /dev/null @@ -1,32 +0,0 @@ -/** @file - * Copyright (c) 2018-2019, 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 _VAL_ENTRY_H_ -#define _VAL_ENTRY_H_ - -#include "val_framework.h" - -#define PSA_ACS_MAJOR_VER 0 -#define PSA_ACS_MINOR_VER 8 - -/** - @brief - PSA Test Suite C main function, does VAL init and calls test dispatcher - @param - None - @return - void -**/ -extern void val_entry(void); -#endif diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_framework.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_framework.h deleted file mode 100644 index e69de29..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_framework.h +++ /dev/null diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_greentea.cpp b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_greentea.cpp deleted file mode 100644 index 8ac4815..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_greentea.cpp +++ /dev/null @@ -1,298 +0,0 @@ -#include "greentea-client/test_env.h" -#include "inttypes.h" -#include "val_greentea.h" - -void pal_mbed_os_compliance_test_initialize(void); -void pal_mbed_os_compliance_test_destroy(void); - -#ifdef __cplusplus -extern "C" { -#endif - - - -/* globals */ -test_status_buffer_t g_status_buffer; - -void mbed_val_test_init(uint32_t test_num, char8_t *desc, uint32_t test_bitfield) -{ - /*global init*/ - g_status_buffer.state = 0; - g_status_buffer.status = VAL_STATUS_INVALID; - - mbed_val_print(PRINT_ALWAYS, "\nTEST: %d | DESCRIPTION: ", test_num); - mbed_val_print(PRINT_ALWAYS, desc, 0); - GREENTEA_SETUP(100, "default_auto"); - mbed_val_set_status(RESULT_START(VAL_STATUS_SUCCESS)); - pal_mbed_os_compliance_test_initialize(); - return; -} - -void mbed_val_test_exit(void) -{ - uint32_t status = mbed_val_get_status(); - pal_mbed_os_compliance_test_destroy(); - /* return if test skipped or failed */ - if (IS_TEST_FAIL(status) || IS_TEST_SKIP(status)) { - GREENTEA_TESTSUITE_RESULT(false); - } else { - GREENTEA_TESTSUITE_RESULT(true); - mbed_val_set_status(RESULT_END(VAL_STATUS_SUCCESS)); - } -} - -/** -@brief - This function executes given list of tests from non-secure sequentially - This covers non-secure to secure IPC API scenario -@param - test_num : Test_num -@param - tests_list : list of tests to be executed -@param - server_hs : Initiate a server handshake -@return - val_status_t -**/ -val_status_t mbed_val_execute_non_secure_tests(uint32_t test_num, client_test_t *tests_list, - bool_t server_hs) -{ - val_status_t status = VAL_STATUS_SUCCESS; - int32_t test_status = VAL_STATUS_SUCCESS; - psa_handle_t handle; - uint32_t i = 1; - test_info_t test_info; - char testcase_name[100] = ""; - bool continue_test = true; - - test_info.test_num = test_num; - - mbed_val_print(PRINT_TEST, "[Info] Executing tests from non-secure\n", 0); - while (tests_list[i] != NULL) { - memset(testcase_name, 0, 100); - sprintf(testcase_name, "Check%" PRIu32, i); - GREENTEA_TESTCASE_START(testcase_name); - if (server_hs == TRUE) { - /* Handshake with server tests */ - test_info.block_num = i; - status = mbed_val_execute_secure_test_func(&handle, test_info, - SERVER_TEST_DISPATCHER_SID); - if (VAL_ERROR(status)) { - mbed_val_set_status(RESULT_FAIL(status)); - mbed_val_print(PRINT_ERROR, "[Check%d] START\n", i); - return status; - } else { - mbed_val_print(PRINT_DEBUG, "[Check%d] START\n", i); - } - } - - /* Execute client tests */ - test_status = tests_list[i](CALLER_NONSECURE); - - if (server_hs == TRUE) { - /* Retrive Server test status */ - status = mbed_val_get_secure_test_result(&handle); - } - - if (test_status != VAL_STATUS_SUCCESS) { - status = VAL_STATUS_ERROR; - } - - if (IS_TEST_SKIP(status)) { - mbed_val_set_status(status); - mbed_val_print(PRINT_DEBUG, "[Check%d] SKIPPED\n", i); - GREENTEA_TESTCASE_FINISH(testcase_name, 1, 0); - continue_test = false; - } else if (VAL_ERROR(status)) { - mbed_val_set_status(RESULT_FAIL(status)); - if (server_hs == TRUE) { - mbed_val_print(PRINT_ERROR, "[Check%d] FAILED\n", i); - } - GREENTEA_TESTCASE_FINISH(testcase_name, 0, 1); - continue_test = false; - } else { - if (server_hs == TRUE) { - mbed_val_print(PRINT_DEBUG, "[Check%d] PASSED\n", i); - } - GREENTEA_TESTCASE_FINISH(testcase_name, 1, 0); - continue_test = true; - } - - if (!continue_test) { - return status; - } - - i++; - } - return status; -} - -/** -@brief - Records the state and status of test -@return - val_status_t -**/ -val_status_t mbed_val_set_status(uint32_t status) -{ - g_status_buffer.state = ((status >> TEST_STATE_BIT) & TEST_STATE_MASK); - g_status_buffer.status = (status & TEST_STATUS_MASK); - - return VAL_STATUS_SUCCESS; -} - -/** -@brief - Updates the state and status for a given test -@return - test status -**/ -uint32_t mbed_val_get_status(void) -{ - return ((g_status_buffer.state) << TEST_STATE_BIT) | (g_status_buffer.status); -} - -/** -@brief - This function is used to handshake between: - - nonsecure client fn to server test fn - - secure client fn and server test fn - - nonsecure client fn to secure client test fn -@param - handle : handle returned while connecting given sid -@param - test_info : Test_num and block_num to be executed -@param - sid : RoT service to be connected. Partition dispatcher sid -@return - val_status_t -**/ -val_status_t mbed_val_execute_secure_test_func(psa_handle_t *handle, test_info_t test_info, uint32_t sid) -{ - uint32_t test_data; - val_status_t status = VAL_STATUS_SUCCESS; - psa_status_t status_of_call = PSA_SUCCESS; - - *handle = pal_ipc_connect(sid, 0); - if (*handle < 0) { - mbed_val_print(PRINT_ERROR, "Could not connect SID. Handle=%x\n", *handle); - return VAL_STATUS_CONNECTION_FAILED; - } - - test_data = ((uint32_t)(test_info.test_num) | ((uint32_t)(test_info.block_num) << BLOCK_NUM_POS) | ((uint32_t)(TEST_EXECUTE_FUNC) << ACTION_POS)); - psa_invec data[1] = {{&test_data, sizeof(test_data)}}; - - status_of_call = pal_ipc_call(*handle, data, 1, NULL, 0); - if (status_of_call != PSA_SUCCESS) { - status = VAL_STATUS_CALL_FAILED; - mbed_val_print(PRINT_ERROR, "Call to dispatch SF failed. Status=%x\n", status_of_call); - pal_ipc_close(*handle); - } - - return status; -} - -/** -@brief - Print module. This is client interface API of secure partition - mbed_val_print_sf API for nspe world -@param - verbosity: Print verbosity level - - string : Input string - - data : Value for format specifier -@return - val_status_t -**/ -val_status_t mbed_val_print(print_verbosity_t verbosity, const char *string, uint32_t data) -{ - if (data != 0) { - printf(string, data); - } else { - printf(string); - } - - return VAL_STATUS_SUCCESS; -} - -/** -@brief - This function is used to retrive the status of previously connected test function - using mbed_val_execute_secure_test_func -@param - handle : handle of server function. Handle of Partition dispatcher sid -@return - The status of test functions -**/ -val_status_t mbed_val_get_secure_test_result(psa_handle_t *handle) -{ - uint32_t test_data; - val_status_t status = VAL_STATUS_SUCCESS; - psa_status_t status_of_call = PSA_SUCCESS; - - test_data = (TEST_RETURN_RESULT << ACTION_POS); - - psa_outvec resp = {&status, sizeof(status)}; - psa_invec data[1] = {{&test_data, sizeof(test_data)}}; - - status_of_call = pal_ipc_call(*handle, data, 1, &resp, 1); - if (status_of_call != PSA_SUCCESS) { - status = VAL_STATUS_CALL_FAILED; - mbed_val_print(PRINT_ERROR, "Call to dispatch SF failed. Status=%x\n", status_of_call); - } - - pal_ipc_close(*handle); - return status; -} - -/** - * @brief Connect to given sid - @param -sid : RoT service id - @param -minor_version : minor_version of RoT service - @param -handle - return connection handle - * @return val_status_t - */ -val_status_t mbed_val_ipc_connect(uint32_t sid, uint32_t minor_version, psa_handle_t *handle) -{ - *handle = pal_ipc_connect(sid, minor_version); - - if (*handle < 0) { - return VAL_STATUS_CONNECTION_FAILED; - } - - return VAL_STATUS_SUCCESS; -} - -/** - * @brief Call a connected Root of Trust Service.@n - * The caller must provide an array of ::psa_invec_t structures as the input payload. - * - * @param handle Handle for the connection. - * @param in_vec Array of psa_invec structures. - * @param in_len Number of psa_invec structures in in_vec. - * @param out_vec Array of psa_outvec structures for optional Root of Trust Service response. - * @param out_len Number of psa_outvec structures in out_vec. - * @return val_status_t - */ -val_status_t mbed_val_ipc_call(psa_handle_t handle, psa_invec *in_vec, size_t in_len, - psa_outvec *out_vec, size_t out_len) -{ - psa_status_t call_status = PSA_SUCCESS; - - call_status = pal_ipc_call(handle, in_vec, in_len, out_vec, out_len); - - if (call_status != PSA_SUCCESS) { - return VAL_STATUS_CALL_FAILED; - } - - return VAL_STATUS_SUCCESS; -} - -/** - * @brief Close a connection to a Root of Trust Service. - * Sends the PSA_IPC_DISCONNECT message to the Root of Trust Service so it can clean up resources. - * - * @param handle Handle for the connection. - * @return void - */ -void mbed_val_ipc_close(psa_handle_t handle) -{ - pal_ipc_close(handle); -} - - -/** - * @brief reprogram the watchdog timer - * always succeeds on mbed-greentead testing. - * - * @param timeout_type type of timeout. - * @return val_status_t - */ -val_status_t mbed_val_wd_reprogram_timer(wd_timeout_type_t timeout_type) -{ - return VAL_STATUS_SUCCESS; -} - -#ifdef __cplusplus -} // extern "C" -#endif - diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_greentea.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_greentea.h deleted file mode 100644 index a8d7da8..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_greentea.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef _VAL_GREENTEA_H_ -#define _VAL_GREENTEA_H_ - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include "val.h" -#include "val_interfaces.h" - -void mbed_val_test_init(uint32_t test_num, char8_t *desc, uint32_t test_bitfield); -void mbed_val_test_exit(void); -val_status_t mbed_val_execute_non_secure_tests(uint32_t test_num, client_test_t *tests_list, bool_t server_hs); -val_status_t mbed_val_set_status(uint32_t status); -uint32_t mbed_val_get_status(void); -val_status_t mbed_val_execute_secure_test_func(psa_handle_t *handle, test_info_t test_info, uint32_t sid); -val_status_t mbed_val_print(print_verbosity_t verbosity, const char *string, uint32_t data); -val_status_t mbed_val_get_secure_test_result(psa_handle_t *handle); -val_status_t mbed_val_ipc_connect(uint32_t sid, uint32_t minor_version, psa_handle_t *handle); -val_status_t mbed_val_ipc_call(psa_handle_t handle, psa_invec *in_vec, size_t in_len, - psa_outvec *out_vec, size_t out_len); -void mbed_val_ipc_close(psa_handle_t handle); -val_status_t mbed_val_wd_reprogram_timer(wd_timeout_type_t timeout_type); - -#ifdef __cplusplus -} -#endif - -#endif // _VAL_GREENTEA_H_ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_interfaces.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_interfaces.c deleted file mode 100644 index b6bf085..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_interfaces.c +++ /dev/null @@ -1,60 +0,0 @@ -/** @file - * Copyright (c) 2018-2019, 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_greentea.h" -#include "val_interfaces.h" -#include "val_internal_trusted_storage.h" -#include "val_protected_storage.h" -#include "val_attestation.h" - -/*VAL APIs to be used by test */ -const val_api_t val_api = { - .print = mbed_val_print, - .set_status = mbed_val_set_status, - .get_status = mbed_val_get_status, - .test_init = mbed_val_test_init, - .test_exit = mbed_val_test_exit, - .err_check_set = NULL, - .target_get_config = NULL, - .execute_non_secure_tests = mbed_val_execute_non_secure_tests, - .switch_to_secure_client = NULL, - .execute_secure_test_func = mbed_val_execute_secure_test_func, - .get_secure_test_result = mbed_val_get_secure_test_result, - .ipc_connect = mbed_val_ipc_connect, - .ipc_call = mbed_val_ipc_call, - .ipc_close = mbed_val_ipc_close, - .nvmem_read = NULL, - .nvmem_write = NULL, - .wd_timer_init = NULL, - .wd_timer_enable = NULL, - .wd_timer_disable = NULL, - .wd_reprogram_timer = mbed_val_wd_reprogram_timer, - .set_boot_flag = NULL, - .get_boot_flag = NULL, - .its_function = val_its_function, - .ps_function = val_ps_function, - .attestation_function = val_attestation_function, -}; - -const psa_api_t psa_api = { - .framework_version = pal_ipc_framework_version, - .version = pal_ipc_version, - .connect = pal_ipc_connect, - .call = pal_ipc_call, - .close = pal_ipc_close, -}; diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_interfaces.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_interfaces.h deleted file mode 100644 index 40bc673..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_interfaces.h +++ /dev/null @@ -1,83 +0,0 @@ -/** @file - * Copyright (c) 2018-2019, 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 _VAL_INTERFACES_H_ -#define _VAL_INTERFACES_H_ - -#include "val.h" -#include "val_client_defs.h" -#include "pal_interfaces_ns.h" - -/* typedef's */ -typedef struct { - val_status_t (*print)(print_verbosity_t verbosity, - const char *string, uint32_t data); - val_status_t (*set_status)(uint32_t status); - uint32_t (*get_status)(void); - void (*test_init)(uint32_t test_num, char8_t *desc, - uint32_t test_bitfield); - void (*test_exit)(void); - val_status_t (*err_check_set)(uint32_t checkpoint, val_status_t status); - val_status_t (*target_get_config)(cfg_id_t cfg_id, uint8_t **data, uint32_t *size); - val_status_t (*execute_non_secure_tests)(uint32_t test_num, client_test_t *tests_list, - bool_t server_hs); - val_status_t (*switch_to_secure_client)(uint32_t test_num); - val_status_t (*execute_secure_test_func)(psa_handle_t *handle, test_info_t test_info, - uint32_t sid); - val_status_t (*ipc_connect)(uint32_t sid, uint32_t minor_version, - psa_handle_t *handle); - val_status_t (*ipc_call)(psa_handle_t handle, psa_invec *in_vec, - size_t in_len, psa_outvec *out_vec, - size_t out_len); - void (*ipc_close)(psa_handle_t handle); - val_status_t (*get_secure_test_result)(psa_handle_t *handle); - val_status_t (*nvmem_read)(uint32_t offset, void *buffer, int size); - val_status_t (*nvmem_write)(uint32_t offset, void *buffer, int size); - val_status_t (*wd_timer_init)(wd_timeout_type_t timeout_type); - val_status_t (*wd_timer_enable)(void); - val_status_t (*wd_timer_disable)(void); - val_status_t (*wd_reprogram_timer)(wd_timeout_type_t timeout_type); - val_status_t (*set_boot_flag)(boot_state_t state); - val_status_t (*get_boot_flag)(boot_state_t *state); - int32_t (*crypto_function)(int type, ...); - uint32_t (*its_function)(int type, ...); - uint32_t (*ps_function)(int type, ...); - int32_t (*attestation_function)(int type, ...); -} val_api_t; - -typedef struct { - uint32_t (*framework_version)(void); - uint32_t (*version)(uint32_t sid); - psa_handle_t (*connect)(uint32_t sid, uint32_t minor_version); - psa_status_t (*call)(psa_handle_t handle, - const psa_invec *in_vec, - size_t in_len, - psa_outvec *out_vec, - size_t out_len - ); - void (*close)(psa_handle_t handle); -} psa_api_t; - -typedef void (*test_fptr_t)(val_api_t *val, psa_api_t *psa); - -typedef struct { - test_id_t test_id; - test_fptr_t entry_addr; -} val_test_info_t; - -void test_entry(val_api_t *val, psa_api_t *psa); -#endif diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_internal_trusted_storage.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_internal_trusted_storage.c deleted file mode 100644 index e79e9c0..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_internal_trusted_storage.c +++ /dev/null @@ -1,39 +0,0 @@ -/** @file - * Copyright (c) 2019, 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_target.h" -#include "pal_interfaces_ns.h" -#include "val_framework.h" -#include "val_client_defs.h" -#include "val_internal_trusted_storage.h" - -/** - @brief - This API will call the requested internal trusted storage function - @param - type : function code - ... : variable number of arguments - @return - Error status -**/ -uint32_t val_its_function(int type, ...) -{ - va_list valist; - uint32_t status; - - va_start(valist, type); - status = pal_its_function(type, valist); - va_end(valist); - return status; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_internal_trusted_storage.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_internal_trusted_storage.h deleted file mode 100644 index 2f9384d..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_internal_trusted_storage.h +++ /dev/null @@ -1,34 +0,0 @@ -/** @file - * Copyright (c) 2019, 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 _VAL_INTERNAL_TRUSTED_STORAGE_H_ -#define _VAL_INTERNAL_TRUSTED_STORAGE_H_ - -#include "val.h" - -#define UID_BASE_VALUE 0 -#define BYTES_TO_BITS(byte) (byte * 8) - -enum its_function_code { - VAL_ITS_SET = 0x1, - VAL_ITS_GET = 0x2, - VAL_ITS_GET_INFO = 0x3, - VAL_ITS_REMOVE = 0x4, -}; - -uint32_t val_its_function(int type, ...); -#endif /* _VAL_INTERNAL_TRUSTED_STORAGE_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_protected_storage.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_protected_storage.c deleted file mode 100644 index 06c1f50..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_protected_storage.c +++ /dev/null @@ -1,39 +0,0 @@ -/** @file - * Copyright (c) 2019, 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_target.h" -#include "pal_interfaces_ns.h" -#include "val_framework.h" -#include "val_client_defs.h" -#include "val_protected_storage.h" - -/** - @brief - This API will call the requested protected storage function - @param - type : function code - ... : variable number of arguments - @return - Error status -**/ -uint32_t val_ps_function(int type, ...) -{ - va_list valist; - uint32_t status; - - va_start(valist, type); - status = pal_ps_function(type, valist); - va_end(valist); - return status; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_protected_storage.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_protected_storage.h deleted file mode 100644 index 7f05cea..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_protected_storage.h +++ /dev/null @@ -1,37 +0,0 @@ -/** @file - * Copyright (c) 2019, 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 _VAL_PROTECTED_STORAGE_H_ -#define _VAL_PROTECTED_STORAGE_H_ - -#include "val.h" - -#define UID_BASE_VALUE 0 -#define BYTES_TO_BITS(byte) (byte * 8) - -enum ps_function_code { - VAL_PS_SET = 0x1, - VAL_PS_GET = 0x2, - VAL_PS_GET_INFO = 0x3, - VAL_PS_REMOVE = 0x4, - VAL_PS_CREATE = 0x5, - VAL_PS_SET_EXTENDED = 0x6, - VAL_PS_GET_SUPPORT = 0x7, -}; - -uint32_t val_ps_function(int type, ...); -#endif /* _VAL_PROTECTED_STORAGE_H_ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_target.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_target.h deleted file mode 100644 index 1eb7a61..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_target.h +++ /dev/null @@ -1,205 +0,0 @@ -/** @file - * Copyright (c) 2018-2019, 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 _TARGET_INFO_DATA_H_ -#define _TARGET_INFO_DATA_H_ - -#include "val.h" - -#define TARGET_CONFIG_CREATE_ID(major, minor, index) \ - (((major & 0xFF) << 24) | ((minor & 0xFF) << 16) | (index & 0xFFFF)) -#define TARGET_CONFIG_GET_MAJOR(config_id) ((config_id >> 24) & 0xFF) -#define TARGET_CONFIG_GET_MINOR(config_id) ((config_id >> 16) & 0xFF) -#define TARGET_CONFIG_INCREMENT_INDEX(config_id) \ - ((config_id & 0xFFFF0000) | ((config_id & 0xFFFF) + 1)) -#define GET_NUM_INSTANCE(struct_type) (struct_type->cfg_type.size >> 24) -#define VAL_TEST_MAJOR_GROUP_MASK 0xFF000000UL -#define VAL_TEST_MINOR_GROUP_MASK 0x00FF0000UL -#define VAL_TEST_CFG_INSTANCE_MASK 0x0000FFFFUL -#define VAL_TEST_INVALID_CFG_ID 0xFFFFFFFFUL -#define TARGET_MIN_CFG_ID TARGET_CONFIG_CREATE_ID(GROUP_SOC_PERIPHERAL, 0, 0) -#define TARGET_MAX_CFG_ID TARGET_CONFIG_CREATE_ID(GROUP_MAX, 0, 0) - -/** - Config IDs for each group/component - 31:24 : MAJOR (group) - 23:16 : MINOR (component) - 16:8 : SUB-component - 7:0 : INSTANCE (instance of same component) -**/ - -/* - MAJOR IDs -*/ -typedef enum _GROUP_CONFIG_ID_ { - GROUP_SOC_PERIPHERAL = 0x1, - GROUP_MEMORY = 0x2, - GROUP_MISCELLANEOUS = 0x3, - GROUP_MAX = 0xFF, -} group_cfg_id_t; - -/* - MINOR IDs - */ -typedef enum _SOC_PERIPHERAL_CONFIG_ID_ { - SOC_PERIPHERAL_UART = 0x1, - SOC_PERIPHERAL_TIMER = 0x2, - SOC_PERIPHERAL_WATCHDOG = 0x3, -} soc_peripheral_cfg_id_t; - -typedef enum _MEMORY_CONFIG_ID_ { - MEMORY_NVMEM = 0x2, - MEMORY_NSPE_MMIO = 0x3, - MEMORY_CLIENT_PARTITION_MMIO = 0x4, - MEMORY_DRIVER_PARTITION_MMIO = 0x5, -} memory_cfg_id_t; - -typedef enum _MISCELLANEOUS_CONFIG_ID_ { - MISCELLANEOUS_BOOT = 0x1, - MISCELLANEOUS_DUT = 0x2 -} miscellaneous_cfg_id_t; - -/** - Assign group type to each system component -**/ -typedef enum _COMPONENT_GROUPING_ { - UART = GROUP_SOC_PERIPHERAL, - TIMER = GROUP_SOC_PERIPHERAL, - WATCHDOG = GROUP_SOC_PERIPHERAL, - NVMEM = GROUP_MEMORY, - NSPE_MMIO = GROUP_MEMORY, - CLIENT_PARTITION_MMIO = GROUP_MEMORY, - DRIVER_PARTITION_MMIO = GROUP_MEMORY, - BOOT = GROUP_MISCELLANEOUS, - DUT = GROUP_MISCELLANEOUS, -} comp_group_assign_t; - -/** - Target Configuration Header -**/ -typedef struct _TARGET_CFG_HDR_ { - /* PSA_CFG */ - uint32_t signature[2]; - /* 8 byte String describing the Target platform */ - uint32_t target_string[2]; - /* version = 1 for now */ - uint32_t version; - /* Header Size */ - uint32_t size; -} target_cfg_hdr_t; - -typedef enum { - LEVEL1 = 0x1, - LEVEL2, - LEVEL3, -} firmware_level_t; - -typedef enum { - NOT_AVAILABLE = 0x0, - AVAILABLE = 0x1, -} is_available_t; - -typedef enum { - SECURE_ACCESS = 0x100, - NONSECURE_ACCESS, - SECURE_PROGRAMMABLE, - NONSECURE_PROGRAMMABLE -} dev_attr_t; - -typedef enum { - MEM_SECURE = 0x100, - MEM_NONSECURE, - MEM_NSC, -} mem_tgt_attr_t; - -typedef enum { - TYPE_READ_ONLY = 0x10, - TYPE_WRITE_ONLY, - TYPE_READ_WRITE, - TYPE_EXECUTE, - TYPE_RESERVED, -} perm_type_t; - -typedef struct _CFG_HDR_TYPE_ { - cfg_id_t cfg_id; - /* size inclusive of this header */ - uint32_t size; -} cfg_type_t; - -/** - Memory Information -**/ -typedef struct _MEM_INFO_DESC_ { - cfg_type_t cfg_type; - uint32_t num; -} memory_hdr_t; - -typedef struct _MEM_REGION_ { - cfg_type_t cfg_type; - addr_t start; - addr_t end; - mem_tgt_attr_t attribute; - perm_type_t permission; -} memory_desc_t; - -/* - SOC Peripheral description structures -*/ -typedef struct _SOC_PER_INFO_NUM_ { - cfg_type_t cfg_type; - uint32_t num; -} soc_peripheral_hdr_t; - -typedef struct _SOC_PER_INFO_DESC_ { - cfg_type_t cfg_type; - uint32_t vendor_id; - uint32_t device_id; - addr_t base; - uint32_t size; - uint32_t intr_id; - perm_type_t permission; - uint32_t timeout_in_micro_sec_low; - uint32_t timeout_in_micro_sec_medium; - uint32_t timeout_in_micro_sec_high; - uint32_t timeout_in_micro_sec_crypto; - uint32_t num_of_tick_per_micro_sec; - dev_attr_t attribute; -} soc_peripheral_desc_t; - -/** - System Miscellaneous Information -**/ - -typedef struct _MISCELLANEOUS_INFO_HDR_ { - cfg_type_t cfg_type; - uint32_t num; -} miscellaneous_hdr_t; - -typedef struct _MISCELLANEOUS_INFO_DESC_ { - cfg_type_t cfg_type; - firmware_level_t implemented_psa_firmware_isolation_level; - addr_t ns_start_addr_of_combine_test_binary; - is_available_t combine_test_binary_in_ram; - addr_t ns_test_addr; -} miscellaneous_desc_t; - -/*val target config read apis */ -STATIC_DECLARE val_status_t val_target_get_config(cfg_id_t cfg_id, uint8_t **data, uint32_t *size); -STATIC_DECLARE val_status_t val_target_cfg_get_next(void **blob); -STATIC_DECLARE val_status_t val_target_get_cfg_blob(cfg_id_t cfg_id, uint8_t **data, uint32_t *size); -STATIC_DECLARE val_status_t val_target_get_config(cfg_id_t cfg_id, uint8_t **data, uint32_t *size); -#endif diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/platform_multicore.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/platform_multicore.c deleted file mode 100644 index e860ae0..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/platform_multicore.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (c) 2019 Arm Limited. All rights reserved. - * Copyright (c) 2019 Cypress Semiconductor Corporation. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include "cmsis_compiler.h" - -#include "platform_multicore.h" -#include "tfm_multi_core_api.h" -#include "tfm_ns_mailbox.h" - -#include "cy_ipc_drv.h" -#include "cy_sysint.h" -#if CY_SYSTEM_CPU_CM0P -#include "spe_ipc_config.h" -#else -#include "ns_ipc_config.h" -#endif - -int platform_mailbox_fetch_msg_ptr(void **msg_ptr) -{ - cy_en_ipcdrv_status_t status; - - if (!msg_ptr) { - return PLATFORM_MAILBOX_INVAL_PARAMS; - } - - status = Cy_IPC_Drv_ReadMsgPtr(Cy_IPC_Drv_GetIpcBaseAddress(IPC_RX_CHAN), - msg_ptr); - if (status != CY_IPC_DRV_SUCCESS) { - return PLATFORM_MAILBOX_RX_ERROR; - } - - Cy_IPC_Drv_ReleaseNotify(Cy_IPC_Drv_GetIpcBaseAddress(IPC_RX_CHAN), - IPC_RX_RELEASE_MASK); - return PLATFORM_MAILBOX_SUCCESS; -} - -int platform_mailbox_fetch_msg_data(uint32_t *data_ptr) -{ - cy_en_ipcdrv_status_t status; - - if (!data_ptr) { - return PLATFORM_MAILBOX_INVAL_PARAMS; - } - - status = Cy_IPC_Drv_ReadMsgWord(Cy_IPC_Drv_GetIpcBaseAddress(IPC_RX_CHAN), - data_ptr); - if (status != CY_IPC_DRV_SUCCESS) { - return PLATFORM_MAILBOX_RX_ERROR; - } - - Cy_IPC_Drv_ReleaseNotify(Cy_IPC_Drv_GetIpcBaseAddress(IPC_RX_CHAN), - IPC_RX_RELEASE_MASK); - return PLATFORM_MAILBOX_SUCCESS; -} - -int platform_mailbox_send_msg_ptr(const void *msg_ptr) -{ - cy_en_ipcdrv_status_t status; - - if (!msg_ptr) - return PLATFORM_MAILBOX_INVAL_PARAMS; - - status = Cy_IPC_Drv_SendMsgPtr(Cy_IPC_Drv_GetIpcBaseAddress(IPC_TX_CHAN), - IPC_TX_NOTIFY_MASK, msg_ptr); - if (status != CY_IPC_DRV_SUCCESS) { - return PLATFORM_MAILBOX_TX_ERROR; - } - - return PLATFORM_MAILBOX_SUCCESS; -} - -int platform_mailbox_send_msg_data(uint32_t data) -{ - cy_en_ipcdrv_status_t status; - - status = Cy_IPC_Drv_SendMsgWord(Cy_IPC_Drv_GetIpcBaseAddress(IPC_TX_CHAN), - IPC_TX_NOTIFY_MASK, data); - if (status != CY_IPC_DRV_SUCCESS) { - return PLATFORM_MAILBOX_TX_ERROR; - } - - return PLATFORM_MAILBOX_SUCCESS; -} - -void platform_mailbox_wait_for_notify(void) -{ - uint32_t status; - - while (1) { - status = Cy_IPC_Drv_GetInterruptStatusMasked( - Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT)); - status >>= CY_IPC_NOTIFY_SHIFT; - if (status & IPC_RX_INT_MASK) { - break; - } - } - - Cy_IPC_Drv_ClearInterrupt(Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT), - 0, IPC_RX_INT_MASK); -} - -int platform_ns_ipc_init(void) -{ - Cy_IPC_Drv_SetInterruptMask(Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT), - 0, IPC_RX_INT_MASK); - return PLATFORM_MAILBOX_SUCCESS; -} - -int32_t tfm_platform_ns_wait_for_s_cpu_ready(void) -{ - uint32_t data = 0; - - if (platform_ns_ipc_init() != PLATFORM_MAILBOX_SUCCESS) { - return PLATFORM_MAILBOX_INVAL_PARAMS; - } - while(data != IPC_SYNC_MAGIC) - { - platform_mailbox_wait_for_notify(); - platform_mailbox_fetch_msg_data(&data); - } - - if (platform_mailbox_send_msg_data(~IPC_SYNC_MAGIC) != - PLATFORM_MAILBOX_SUCCESS) { - return PLATFORM_MAILBOX_RX_ERROR; - } - return PLATFORM_MAILBOX_SUCCESS; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/platform_ns_mailbox.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/platform_ns_mailbox.c deleted file mode 100644 index dc94e63..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/platform_ns_mailbox.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (c) 2019-2020, Arm Limited. All rights reserved. - * Copyright (c) 2019, Cypress Semiconductor Corporation. All rights reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -/* -------------------------------------- Includes ----------------------------------- */ -#include -#include - -#include "cmsis_compiler.h" - -#include "cy_ipc_drv.h" -#include "cy_sysint.h" - -#include "ns_ipc_config.h" -#include "tfm_ns_mailbox.h" -#include "platform_multicore.h" -#include "cmsis_os2.h" - -static uint8_t saved_irq_state = 1; - -/* -------------------------------------- HAL API ------------------------------------ */ - -static void mailbox_ipc_init(void) -{ - Cy_IPC_Drv_SetInterruptMask(Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT), - 0, IPC_RX_INT_MASK); -} - -static void mailbox_ipc_config(void) -{ - NVIC_SetPriority(PSA_CLIENT_REPLY_NVIC_IRQn, PSA_CLIENT_REPLY_IRQ_PRIORITY); - - NVIC_EnableIRQ(PSA_CLIENT_REPLY_NVIC_IRQn); -} - -int32_t tfm_ns_mailbox_hal_notify_peer(void) -{ - cy_en_ipcdrv_status_t status; - - status = Cy_IPC_Drv_SendMsgWord(Cy_IPC_Drv_GetIpcBaseAddress(IPC_TX_CHAN), - IPC_TX_NOTIFY_MASK, - PSA_CLIENT_CALL_REQ_MAGIC); - - if (status == CY_IPC_DRV_SUCCESS) { - return MAILBOX_SUCCESS; - } else { - return MAILBOX_CHAN_BUSY; - } -} - -int32_t tfm_ns_mailbox_hal_init(struct ns_mailbox_queue_t *queue) -{ - uint32_t stage; - - if (!queue) { - return MAILBOX_INVAL_PARAMS; - } - - /* - * FIXME - * Further verification of mailbox queue address may be required according - * to diverse NSPE implementations. - */ - - mailbox_ipc_init(); - - /* - * Wait until SPE mailbox library is ready to receive NSPE mailbox queue - * address. - */ - while (1) { - platform_mailbox_wait_for_notify(); - - platform_mailbox_fetch_msg_data(&stage); - if (stage == NS_MAILBOX_INIT_ENABLE) { - break; - } - } - - /* Send out the address */ - platform_mailbox_send_msg_ptr(queue); - - /* Wait until SPE mailbox service is ready */ - while (1) { - platform_mailbox_wait_for_notify(); - - platform_mailbox_fetch_msg_data(&stage); - if (stage == S_MAILBOX_READY) { - break; - } - } - - mailbox_ipc_config(); - - return MAILBOX_SUCCESS; -} - -const void *tfm_ns_mailbox_get_task_handle(void) -{ - return osThreadGetId(); -} - -void tfm_ns_mailbox_hal_wait_reply(mailbox_msg_handle_t handle) -{ - osThreadFlagsWait(handle, osFlagsWaitAll, osWaitForever); -} - -void tfm_ns_mailbox_hal_enter_critical(void) -{ - saved_irq_state = Cy_SysLib_EnterCriticalSection(); - - IPC_STRUCT_Type* ipc_struct = - Cy_IPC_Drv_GetIpcBaseAddress(IPC_PSA_MAILBOX_LOCK_CHAN); - while(CY_IPC_DRV_SUCCESS != Cy_IPC_Drv_LockAcquire (ipc_struct)) - { - } -} - -void tfm_ns_mailbox_hal_exit_critical(void) -{ - IPC_STRUCT_Type* ipc_struct = - Cy_IPC_Drv_GetIpcBaseAddress(IPC_PSA_MAILBOX_LOCK_CHAN); - Cy_IPC_Drv_LockRelease(ipc_struct, CY_IPC_NO_NOTIFICATION); - Cy_SysLib_ExitCriticalSection(saved_irq_state); -} - -void tfm_ns_mailbox_hal_enter_critical_isr(void) -{ - IPC_STRUCT_Type* ipc_struct = - Cy_IPC_Drv_GetIpcBaseAddress(IPC_PSA_MAILBOX_LOCK_CHAN); - while(CY_IPC_DRV_SUCCESS != Cy_IPC_Drv_LockAcquire (ipc_struct)) - { - } -} - -void tfm_ns_mailbox_hal_exit_critical_isr(void) -{ - IPC_STRUCT_Type* ipc_struct = - Cy_IPC_Drv_GetIpcBaseAddress(IPC_PSA_MAILBOX_LOCK_CHAN); - Cy_IPC_Drv_LockRelease(ipc_struct, CY_IPC_NO_NOTIFICATION); -} - -static bool mailbox_clear_intr(void) -{ - uint32_t status; - - status = Cy_IPC_Drv_GetInterruptStatusMasked( - Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT)); - status >>= CY_IPC_NOTIFY_SHIFT; - if ((status & IPC_RX_INT_MASK) == 0) { - return false; - } - - Cy_IPC_Drv_ClearInterrupt(Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT), - 0, IPC_RX_INT_MASK); - return true; -} - -void cpuss_interrupts_ipc_8_IRQHandler(void) -{ - uint32_t magic; - mailbox_msg_handle_t handle; - osThreadId_t task_handle; - - if (!mailbox_clear_intr()) - return; - - platform_mailbox_fetch_msg_data(&magic); - if (magic == PSA_CLIENT_CALL_REPLY_MAGIC) { - /* Handle all the pending replies */ - while (1) { - handle = tfm_ns_mailbox_fetch_reply_msg_isr(); - if (handle == MAILBOX_MSG_NULL_HANDLE) { - break; - } - - task_handle = (osThreadId_t)tfm_ns_mailbox_get_msg_owner(handle); - if (task_handle) { - osThreadFlagsSet(task_handle, handle); - } - } - } -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_mbed_boot.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_mbed_boot.c deleted file mode 100644 index c8d595f..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_mbed_boot.c +++ /dev/null @@ -1,67 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2020 ARM Limited - * 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 "mbed_error.h" -#include "tfm_multi_core_api.h" -#include "tfm_ns_mailbox.h" -#include "platform_multicore.h" -#include "tfm_ns_interface.h" - -static struct ns_mailbox_queue_t ns_mailbox_queue; - -void mbed_tfm_init(void) -{ - /* - * In case the of dual CPU, we need to initialize IPC, mailbox - * and NS interface after the RTOS has started to enable - * communication from Secure and Non-Secure cores. - */ - int32_t ret; - - ret = tfm_ns_wait_for_s_cpu_ready(); - /* - * Normally would expect "TFM_SUCCESS" returned here by TF-M, as this - * isn't a mailbox function. There may be some platforms other than PSoC6, - * which doesn't require tfm_ns_wait_for_s_cpu_ready() implementation. - * "PLATFORM_MAILBOX_SUCCESS" is a low-level error code and should be - * replaced by "TFM_SUCCESS". - * As the function definition has been imported from the TF-M, therefore - * a issue has been raised - https://developer.trustedfirmware.org/T660 - */ - if (ret != PLATFORM_MAILBOX_SUCCESS) { - /* Avoid undefined behavior after multi-core sync-up failed */ - MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, - MBED_ERROR_CODE_INITIALIZATION_FAILED), - "Failed to sync-up multi-core"); - } - - ret = tfm_ns_mailbox_init(&ns_mailbox_queue); - if (ret != MAILBOX_SUCCESS) { - /* Avoid undefined behavior after NS mailbox initialization failed */ - MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, - MBED_ERROR_CODE_INITIALIZATION_FAILED), - "Failed to initialize NS mailbox"); - } - - ret = tfm_ns_interface_init(); - if (ret != TFM_SUCCESS) { - /* Avoid undefined behavior after NS interface initialization failed */ - MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, - MBED_ERROR_CODE_INITIALIZATION_FAILED), - "Failed to initialize NS interface"); - } -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_multi_core_api.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_multi_core_api.c deleted file mode 100644 index 231e895..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_multi_core_api.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#include "tfm_api.h" -#include "tfm_mailbox.h" -#include "tfm_multi_core_api.h" -#include "cmsis_os2.h" -#include "mbed_rtos_storage.h" - -#define MAX_SEMAPHORE_COUNT NUM_MAILBOX_QUEUE_SLOT - -static void *ns_lock_handle = NULL; -static mbed_rtos_storage_semaphore_t tfm_ns_sema_obj; - -__attribute__((weak)) -enum tfm_status_e tfm_ns_interface_init(void) -{ - osSemaphoreAttr_t sema_attrib = { - .name = "tfm_ns_lock", - .attr_bits = 0, - .cb_size = sizeof(tfm_ns_sema_obj), - .cb_mem = &tfm_ns_sema_obj - }; - - ns_lock_handle = osSemaphoreNew(MAX_SEMAPHORE_COUNT, - MAX_SEMAPHORE_COUNT, - &sema_attrib); - if (!ns_lock_handle) { - return TFM_ERROR_GENERIC; - } - - return TFM_SUCCESS; -} - -int32_t tfm_ns_wait_for_s_cpu_ready(void) -{ - return tfm_platform_ns_wait_for_s_cpu_ready(); -} - -uint32_t tfm_ns_multi_core_lock_acquire(void) -{ - return osSemaphoreAcquire(ns_lock_handle, osWaitForever); -} - -uint32_t tfm_ns_multi_core_lock_release(void) -{ - return osSemaphoreRelease(ns_lock_handle); -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_multi_core_psa_ns_api.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_multi_core_psa_ns_api.c deleted file mode 100644 index fae580e..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_multi_core_psa_ns_api.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (c) 2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#include -#include - -#include "psa/client.h" -#include "psa/error.h" -#include "tfm_api.h" -#include "tfm_multi_core_api.h" -#include "tfm_ns_mailbox.h" - -/* - * TODO - * Currently, force all the non-secure client to share the same ID. - * - * It requires a more clear mechanism to synchronize the non-secure client - * ID with SPE in dual core scenario. - * In current design, the value is transferred to SPE via mailbox message. - * A dedicated routine to receive the non-secure client information in - * TF-M core/SPM in dual core scenario should be added besides current - * implementation for single Armv8-M. - * The non-secure client identification is shared with SPE in - * single Armv8-M scenario via CMSIS TrustZone context management API, - * which may not work in dual core scenario. - */ -#define NON_SECURE_CLIENT_ID (1) - -/* - * TODO - * Require a formal definition of errors related to mailbox in PSA client call. - */ -#define PSA_INTER_CORE_COMM_ERR (INT32_MIN + 0xFF) - -static void mailbox_wait_reply(mailbox_msg_handle_t handle) -{ - /* - * If the system can support multiple outstanding NS PSA Client calls, call - * tfm_ns_mailbox_wait_reply() to sleep and wait for reply. The NS side - * should implement tfm_ns_mailbox_hal_wait_reply() and wake-up mechanism. - * Otherwise, by default, call tfm_ns_mailbox_is_msg_replied() to simply - * poll the reply status of the mailbox message of current thread. - */ -#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL - tfm_ns_mailbox_wait_reply(handle); -#else - while (!tfm_ns_mailbox_is_msg_replied(handle)) { - } -#endif -} - -/**** API functions ****/ - -uint32_t psa_framework_version(void) -{ - struct psa_client_params_t params; - mailbox_msg_handle_t handle; - uint32_t version; - int32_t ret; - - if (tfm_ns_multi_core_lock_acquire() != 0) { - return PSA_VERSION_NONE; - } - - handle = tfm_ns_mailbox_tx_client_req(MAILBOX_PSA_FRAMEWORK_VERSION, - ¶ms, NON_SECURE_CLIENT_ID); - if (handle < 0) { - tfm_ns_multi_core_lock_release(); - return PSA_VERSION_NONE; - } - - mailbox_wait_reply(handle); - - ret = tfm_ns_mailbox_rx_client_reply(handle, (int32_t *)&version); - if (ret != MAILBOX_SUCCESS) { - version = PSA_VERSION_NONE; - } - - if (tfm_ns_multi_core_lock_release() != 0) { - return PSA_VERSION_NONE; - } - - return version; -} - -uint32_t psa_version(uint32_t sid) -{ - struct psa_client_params_t params; - mailbox_msg_handle_t handle; - uint32_t version; - int32_t ret; - - params.psa_version_params.sid = sid; - - if (tfm_ns_multi_core_lock_acquire() != 0) { - return PSA_VERSION_NONE; - } - - handle = tfm_ns_mailbox_tx_client_req(MAILBOX_PSA_VERSION, ¶ms, - NON_SECURE_CLIENT_ID); - if (handle < 0) { - tfm_ns_multi_core_lock_release(); - return PSA_VERSION_NONE; - } - - mailbox_wait_reply(handle); - - ret = tfm_ns_mailbox_rx_client_reply(handle, (int32_t *)&version); - if (ret != MAILBOX_SUCCESS) { - version = PSA_VERSION_NONE; - } - - if (tfm_ns_multi_core_lock_release() != 0) { - return PSA_VERSION_NONE; - } - - return version; -} - -psa_handle_t psa_connect(uint32_t sid, uint32_t version) -{ - struct psa_client_params_t params; - mailbox_msg_handle_t handle; - psa_handle_t psa_handle; - int32_t ret; - - params.psa_connect_params.sid = sid; - params.psa_connect_params.version = version; - - if (tfm_ns_multi_core_lock_acquire() != 0) { - return PSA_NULL_HANDLE; - } - - handle = tfm_ns_mailbox_tx_client_req(MAILBOX_PSA_CONNECT, ¶ms, - NON_SECURE_CLIENT_ID); - if (handle < 0) { - tfm_ns_multi_core_lock_release(); - return PSA_NULL_HANDLE; - } - - mailbox_wait_reply(handle); - - ret = tfm_ns_mailbox_rx_client_reply(handle, (int32_t *)&psa_handle); - if (ret != MAILBOX_SUCCESS) { - psa_handle = PSA_NULL_HANDLE; - } - - if (tfm_ns_multi_core_lock_release() != 0) { - return PSA_NULL_HANDLE; - } - - return psa_handle; -} - -psa_status_t psa_call(psa_handle_t handle, int32_t type, - const psa_invec *in_vec, size_t in_len, - psa_outvec *out_vec, size_t out_len) -{ - struct psa_client_params_t params; - mailbox_msg_handle_t msg_handle; - int32_t ret; - psa_status_t status; - - params.psa_call_params.handle = handle; - params.psa_call_params.type = type; - params.psa_call_params.in_vec = in_vec; - params.psa_call_params.in_len = in_len; - params.psa_call_params.out_vec = out_vec; - params.psa_call_params.out_len = out_len; - - if (tfm_ns_multi_core_lock_acquire() != 0) { - return PSA_ERROR_GENERIC_ERROR; - } - - msg_handle = tfm_ns_mailbox_tx_client_req(MAILBOX_PSA_CALL, ¶ms, - NON_SECURE_CLIENT_ID); - if (msg_handle < 0) { - tfm_ns_multi_core_lock_release(); - return PSA_INTER_CORE_COMM_ERR; - } - - mailbox_wait_reply(msg_handle); - - ret = tfm_ns_mailbox_rx_client_reply(msg_handle, (int32_t *)&status); - if (ret != MAILBOX_SUCCESS) { - status = PSA_INTER_CORE_COMM_ERR; - } - - if (tfm_ns_multi_core_lock_release() != 0) { - return PSA_ERROR_GENERIC_ERROR; - } - - return status; -} - -void psa_close(psa_handle_t handle) -{ - struct psa_client_params_t params; - mailbox_msg_handle_t msg_handle; - int32_t reply; - - params.psa_close_params.handle = handle; - - if (tfm_ns_multi_core_lock_acquire() != 0) { - return; - } - - msg_handle = tfm_ns_mailbox_tx_client_req(MAILBOX_PSA_CLOSE, ¶ms, - NON_SECURE_CLIENT_ID); - if (msg_handle < 0) { - tfm_ns_multi_core_lock_release(); - return; - } - - mailbox_wait_reply(msg_handle); - - (void)tfm_ns_mailbox_rx_client_reply(msg_handle, &reply); - - tfm_ns_multi_core_lock_release(); -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_ns_mailbox.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_ns_mailbox.c deleted file mode 100644 index f7326f0..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_ns_mailbox.c +++ /dev/null @@ -1,425 +0,0 @@ -/* - * Copyright (c) 2019-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#include -#include "tfm_ns_mailbox.h" - -/* The pointer to NSPE mailbox queue */ -static struct ns_mailbox_queue_t *mailbox_queue_ptr = NULL; - -static inline void clear_queue_slot_empty(uint8_t idx) -{ - if (idx < NUM_MAILBOX_QUEUE_SLOT) { - mailbox_queue_ptr->empty_slots &= ~(1 << idx); - } -} - -static inline void set_queue_slot_empty(uint8_t idx) -{ - if (idx < NUM_MAILBOX_QUEUE_SLOT) { - mailbox_queue_ptr->empty_slots |= (1 << idx); - } -} - -static inline void set_queue_slot_pend(uint8_t idx) -{ - if (idx < NUM_MAILBOX_QUEUE_SLOT) { - mailbox_queue_ptr->pend_slots |= (1 << idx); - } -} - -static inline int32_t get_mailbox_msg_handle(uint8_t idx, - mailbox_msg_handle_t *handle) -{ - if ((idx >= NUM_MAILBOX_QUEUE_SLOT) || !handle) { - return MAILBOX_INVAL_PARAMS; - } - - *handle = (mailbox_msg_handle_t)(idx + 1); - - return MAILBOX_SUCCESS; -} - -static inline int32_t get_mailbox_msg_idx(mailbox_msg_handle_t handle, - uint8_t *idx) -{ - if ((handle == MAILBOX_MSG_NULL_HANDLE) || !idx) { - return MAILBOX_INVAL_PARAMS; - } - - *idx = (uint8_t)(handle - 1); - - return MAILBOX_SUCCESS; -} - -static inline void clear_queue_slot_replied(uint8_t idx) -{ - if (idx < NUM_MAILBOX_QUEUE_SLOT) { - mailbox_queue_ptr->replied_slots &= ~(1 << idx); - } -} - -static inline void set_queue_slot_woken(uint8_t idx) -{ - if (idx < NUM_MAILBOX_QUEUE_SLOT) { - mailbox_queue_ptr->queue[idx].is_woken = true; - } -} - -static inline bool is_queue_slot_woken(uint8_t idx) -{ - if (idx < NUM_MAILBOX_QUEUE_SLOT) { - return mailbox_queue_ptr->queue[idx].is_woken; - } - - return false; -} - -static inline void clear_queue_slot_woken(uint8_t idx) -{ - if (idx < NUM_MAILBOX_QUEUE_SLOT) { - mailbox_queue_ptr->queue[idx].is_woken = false; - } -} - -static uint8_t acquire_empty_slot(const struct ns_mailbox_queue_t *queue) -{ - uint8_t idx; - mailbox_queue_status_t status; - - tfm_ns_mailbox_hal_enter_critical(); - status = queue->empty_slots; - - if (!status) { - /* No empty slot */ - tfm_ns_mailbox_hal_exit_critical(); - return NUM_MAILBOX_QUEUE_SLOT; - } - - for (idx = 0; idx < NUM_MAILBOX_QUEUE_SLOT; idx++) { - if (status & (1 << idx)) { - break; - } - } - - clear_queue_slot_empty(idx); - - tfm_ns_mailbox_hal_exit_critical(); - - return idx; -} - -static void set_msg_owner(uint8_t idx, const void *owner) -{ - if (idx < NUM_MAILBOX_QUEUE_SLOT) { - mailbox_queue_ptr->queue[idx].owner = owner; - } -} - -#ifdef TFM_MULTI_CORE_TEST -void tfm_ns_mailbox_tx_stats_init(void) -{ - if (!mailbox_queue_ptr) { - return; - } - - tfm_ns_mailbox_hal_enter_critical(); - - mailbox_queue_ptr->nr_tx = 0; - mailbox_queue_ptr->nr_used_slots = 0; - - tfm_ns_mailbox_hal_exit_critical(); -} - -static void mailbox_tx_stats_update(struct ns_mailbox_queue_t *ns_queue) -{ - mailbox_queue_status_t empty_status; - uint8_t idx, nr_empty = 0; - - if (!ns_queue) { - return; - } - - tfm_ns_mailbox_hal_enter_critical(); - - ns_queue->nr_tx++; - - /* Count the number of used slots when this tx arrives */ - empty_status = ns_queue->empty_slots; - tfm_ns_mailbox_hal_exit_critical(); - - if (empty_status) { - for (idx = 0; idx < NUM_MAILBOX_QUEUE_SLOT; idx++) { - if (empty_status & (0x1UL << idx)) { - nr_empty++; - } - } - } - - tfm_ns_mailbox_hal_enter_critical(); - ns_queue->nr_used_slots += (NUM_MAILBOX_QUEUE_SLOT - nr_empty); - tfm_ns_mailbox_hal_exit_critical(); -} - -void tfm_ns_mailbox_stats_avg_slot(struct ns_mailbox_stats_res_t *stats_res) -{ - uint32_t nr_used_slots, nr_tx; - - if (!mailbox_queue_ptr || !stats_res) { - return; - } - - tfm_ns_mailbox_hal_enter_critical(); - nr_used_slots = mailbox_queue_ptr->nr_used_slots; - nr_tx = mailbox_queue_ptr->nr_tx; - tfm_ns_mailbox_hal_exit_critical(); - - stats_res->avg_nr_slots = nr_used_slots / nr_tx; - nr_used_slots %= nr_tx; - stats_res->avg_nr_slots_tenths = nr_used_slots * 10 / nr_tx; -} -#endif - -mailbox_msg_handle_t tfm_ns_mailbox_tx_client_req(uint32_t call_type, - const struct psa_client_params_t *params, - int32_t client_id) -{ - uint8_t idx; - struct mailbox_msg_t *msg_ptr; - mailbox_msg_handle_t handle; - const void *task_handle; - - if (!mailbox_queue_ptr) { - return MAILBOX_MSG_NULL_HANDLE; - } - - if (!params) { - return MAILBOX_MSG_NULL_HANDLE; - } - - idx = acquire_empty_slot(mailbox_queue_ptr); - if (idx >= NUM_MAILBOX_QUEUE_SLOT) { - return MAILBOX_QUEUE_FULL; - } - -#ifdef TFM_MULTI_CORE_TEST - mailbox_tx_stats_update(mailbox_queue_ptr); -#endif - - /* Fill the mailbox message */ - msg_ptr = &mailbox_queue_ptr->queue[idx].msg; - - msg_ptr->call_type = call_type; - memcpy(&msg_ptr->params, params, sizeof(msg_ptr->params)); - msg_ptr->client_id = client_id; - - /* - * Fetch the current task handle. The task will be woken up according the - * handle value set in the owner field. - */ - task_handle = tfm_ns_mailbox_get_task_handle(); - set_msg_owner(idx, task_handle); - - get_mailbox_msg_handle(idx, &handle); - - tfm_ns_mailbox_hal_enter_critical(); - set_queue_slot_pend(idx); - tfm_ns_mailbox_hal_exit_critical(); - - tfm_ns_mailbox_hal_notify_peer(); - - return handle; -} - -int32_t tfm_ns_mailbox_rx_client_reply(mailbox_msg_handle_t handle, - int32_t *reply) -{ - uint8_t idx; - int32_t ret; - - if (!mailbox_queue_ptr) { - return MAILBOX_INVAL_PARAMS; - } - - if ((handle == MAILBOX_MSG_NULL_HANDLE) || (!reply)) { - return MAILBOX_INVAL_PARAMS; - } - - ret = get_mailbox_msg_idx(handle, &idx); - if (ret != MAILBOX_SUCCESS) { - return ret; - } - - *reply = mailbox_queue_ptr->queue[idx].reply.return_val; - - /* Clear up the owner field */ - set_msg_owner(idx, NULL); - - tfm_ns_mailbox_hal_enter_critical(); - clear_queue_slot_replied(idx); - clear_queue_slot_woken(idx); - /* - * Make sure that the empty flag is set after all the other status flags are - * re-initialized. - */ - set_queue_slot_empty(idx); - tfm_ns_mailbox_hal_exit_critical(); - - return MAILBOX_SUCCESS; -} - -bool tfm_ns_mailbox_is_msg_replied(mailbox_msg_handle_t handle) -{ - uint8_t idx; - int32_t ret; - mailbox_queue_status_t status; - - if (!mailbox_queue_ptr) { - return false; - } - - if (handle == MAILBOX_MSG_NULL_HANDLE) { - return false; - } - - ret = get_mailbox_msg_idx(handle, &idx); - if (ret != MAILBOX_SUCCESS) { - return false; - } - - tfm_ns_mailbox_hal_enter_critical(); - status = mailbox_queue_ptr->replied_slots; - tfm_ns_mailbox_hal_exit_critical(); - - if (status & (1 << idx)) { - return true; - } - - return false; -} - -mailbox_msg_handle_t tfm_ns_mailbox_fetch_reply_msg_isr(void) -{ - uint8_t idx; - mailbox_msg_handle_t handle; - mailbox_queue_status_t replied_status; - - if (!mailbox_queue_ptr) { - return MAILBOX_MSG_NULL_HANDLE; - } - - tfm_ns_mailbox_hal_enter_critical_isr(); - replied_status = mailbox_queue_ptr->replied_slots; - tfm_ns_mailbox_hal_exit_critical_isr(); - - if (!replied_status) { - return MAILBOX_MSG_NULL_HANDLE; - } - - for (idx = 0; idx < NUM_MAILBOX_QUEUE_SLOT; idx++) { - /* Find the first replied message in queue */ - if (replied_status & (0x1UL << idx)) { - tfm_ns_mailbox_hal_enter_critical_isr(); - clear_queue_slot_replied(idx); - set_queue_slot_woken(idx); - tfm_ns_mailbox_hal_exit_critical_isr(); - - if (get_mailbox_msg_handle(idx, &handle) == MAILBOX_SUCCESS) { - return handle; - } - } - } - - return MAILBOX_MSG_NULL_HANDLE; -} - -const void *tfm_ns_mailbox_get_msg_owner(mailbox_msg_handle_t handle) -{ - uint8_t idx; - - if (get_mailbox_msg_idx(handle, &idx) != MAILBOX_SUCCESS) { - return NULL; - } - - if (idx < NUM_MAILBOX_QUEUE_SLOT) { - return mailbox_queue_ptr->queue[idx].owner; - } - - return NULL; -} - -int32_t tfm_ns_mailbox_init(struct ns_mailbox_queue_t *queue) -{ - int32_t ret; - - if (!queue) { - return MAILBOX_INVAL_PARAMS; - } - - /* - * Further verification of mailbox queue address may be required according - * to non-secure memory assignment. - */ - - memset(queue, 0, sizeof(*queue)); - - /* Initialize empty bitmask */ - queue->empty_slots = - (mailbox_queue_status_t)((1UL << (NUM_MAILBOX_QUEUE_SLOT - 1)) - 1); - queue->empty_slots += - (mailbox_queue_status_t)(1UL << (NUM_MAILBOX_QUEUE_SLOT - 1)); - - mailbox_queue_ptr = queue; - - /* Platform specific initialization. */ - ret = tfm_ns_mailbox_hal_init(queue); - -#ifdef TFM_MULTI_CORE_TEST - tfm_ns_mailbox_tx_stats_init(); -#endif - - return ret; -} - -#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL -int32_t tfm_ns_mailbox_wait_reply(mailbox_msg_handle_t handle) -{ - uint8_t idx; - int32_t ret; - - if (!mailbox_queue_ptr) { - return MAILBOX_INVAL_PARAMS; - } - - if (handle == MAILBOX_MSG_NULL_HANDLE) { - return MAILBOX_INVAL_PARAMS; - } - - ret = get_mailbox_msg_idx(handle, &idx); - if (ret != MAILBOX_SUCCESS) { - return ret; - } - - while (1) { - tfm_ns_mailbox_hal_wait_reply(handle); - - /* - * Woken up from sleep - * Check the completed flag to make sure that the current thread is - * woken up by reply event, rather than other events. - */ - tfm_ns_mailbox_hal_enter_critical(); - if (is_queue_slot_woken(idx)) { - tfm_ns_mailbox_hal_exit_critical(); - break; - } - tfm_ns_mailbox_hal_exit_critical(); - } - - return MAILBOX_SUCCESS; -} -#endif diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/cmsis_nvic_virtual.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/cmsis_nvic_virtual.c deleted file mode 100644 index bee8597..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/cmsis_nvic_virtual.c +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2019-2020 Arm Limited - * - * 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 "cmsis_nvic_virtual.h" -#include "tfm_platform_api.h" - -void NVIC_SystemReset(void) -{ - tfm_platform_system_reset(); -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/tfm_mbed_boot.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/tfm_mbed_boot.c deleted file mode 100644 index 87bcbbb..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/tfm_mbed_boot.c +++ /dev/null @@ -1,37 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2020 ARM Limited - * 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 "mbed_error.h" -#include "tfm_ns_interface.h" - -void mbed_tfm_init(void) -{ - /* - * In case of V8-M, we need to initialize NS interface - * after the RTOS has started to enable - * communication from Secure and Non-Secure cores. - */ - int32_t ret; - - ret = tfm_ns_interface_init(); - if (ret != TFM_SUCCESS) { - /* Avoid undefined behavior after NS interface initialization failed */ - MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, - MBED_ERROR_CODE_INITIALIZATION_FAILED), - "Failed to initialize NS interface"); - } -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/tfm_ns_interface.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/tfm_ns_interface.c deleted file mode 100644 index 9759145..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/tfm_ns_interface.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2017-2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ -#include -#include - -#include "tfm_api.h" -#include "tfm_ns_interface.h" -#include "cmsis_os2.h" - -/** - * \brief the ns_lock ID - */ -static osMutexId_t ns_lock_handle = NULL; - -__attribute__((weak)) -int32_t tfm_ns_interface_dispatch(veneer_fn fn, - uint32_t arg0, uint32_t arg1, - uint32_t arg2, uint32_t arg3) -{ - int32_t result; - osStatus_t status; - - /* TFM request protected by NS lock */ - status = osMutexAcquire(ns_lock_handle, osWaitForever); - if (status != osOK) { - return (int32_t)TFM_ERROR_GENERIC; - } - - result = fn(arg0, arg1, arg2, arg3); - - status = osMutexRelease(ns_lock_handle); - if (status != osOK) { - return (int32_t)TFM_ERROR_GENERIC; - } - - return result; -} - -__attribute__((weak)) -enum tfm_status_e tfm_ns_interface_init(void) -{ - const osMutexAttr_t attr = { - .name = NULL, - .attr_bits = osMutexPrioInherit, /* Priority inheritance is recommended - * to enable if it is supported. - * For recursive mutex and the ability - * of auto release when owner being - * terminated is not required. - */ - .cb_mem = NULL, - .cb_size = 0U - }; - - ns_lock_handle = osMutexNew(&attr); - if (!ns_lock_handle) { - return TFM_ERROR_GENERIC; - } - - return TFM_SUCCESS; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/tfm_psa_ns_api.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/tfm_psa_ns_api.c deleted file mode 100644 index 9a677a2..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/tfm_psa_ns_api.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2018-2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#include "psa/client.h" -#include "tfm_ns_interface.h" -#include "tfm_api.h" - -/**** API functions ****/ - -uint32_t psa_framework_version(void) -{ - return tfm_ns_interface_dispatch( - (veneer_fn)tfm_psa_framework_version_veneer, - 0, - 0, - 0, - 0); -} - -uint32_t psa_version(uint32_t sid) -{ - return tfm_ns_interface_dispatch( - (veneer_fn)tfm_psa_version_veneer, - sid, - 0, - 0, - 0); -} - -psa_handle_t psa_connect(uint32_t sid, uint32_t version) -{ - return tfm_ns_interface_dispatch( - (veneer_fn)tfm_psa_connect_veneer, - sid, - version, - 0, - 0); -} - -psa_status_t psa_call(psa_handle_t handle, int32_t type, - const psa_invec *in_vec, - size_t in_len, - psa_outvec *out_vec, - size_t out_len) -{ - /* FixMe: sanity check can be added to offload some NS thread checks from - * TFM secure API - */ - - /* Due to v8M restrictions, TF-M NS API needs to add another layer of - * serialization in order for NS to pass arguments to S - */ - const struct tfm_control_parameter_t ctrl_param = { - .type = type, - .in_len = in_len, - .out_len = out_len, - }; - - return tfm_ns_interface_dispatch( - (veneer_fn)tfm_psa_call_veneer, - (uint32_t)handle, - (uint32_t)&ctrl_param, - (uint32_t)in_vec, - (uint32_t)out_vec); -} - -void psa_close(psa_handle_t handle) -{ - (void)tfm_ns_interface_dispatch( - (veneer_fn)tfm_psa_close_veneer, - (uint32_t)handle, - 0, - 0, - 0); -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/VERSION.txt b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/VERSION.txt deleted file mode 100644 index cc1d7ed..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/VERSION.txt +++ /dev/null @@ -1 +0,0 @@ -9fd2fd6250d5 diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/cmsis_nvic_virtual.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/cmsis_nvic_virtual.h deleted file mode 100644 index a1a8b61..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/cmsis_nvic_virtual.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2019 Arm Limited - * - * 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 "cmsis.h" - -#ifndef NVIC_VIRTUAL_H -#define NVIC_VIRTUAL_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* NVIC functions */ -#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping -#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping -#define NVIC_EnableIRQ __NVIC_EnableIRQ -#define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ -#define NVIC_DisableIRQ __NVIC_DisableIRQ -#define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ -#define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ -#define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ -#define NVIC_GetActive __NVIC_GetActive -#define NVIC_SetPriority __NVIC_SetPriority -#define NVIC_GetPriority __NVIC_GetPriority - -/** - * \brief Overriding the default CMSIS system reset implementation by calling - * secure TFM service. - * - */ -void NVIC_SystemReset(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/ns_ipc_config.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/ns_ipc_config.h deleted file mode 100644 index e1cd7b7..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/ns_ipc_config.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2019 Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#ifndef _IPC_CONFIG_H_ -#define _IPC_CONFIG_H_ - -#include "platform_multicore.h" - -#define IPC_RX_CHAN IPC_PSA_CLIENT_REPLY_CHAN -#define IPC_RX_INTR_STRUCT IPC_PSA_CLIENT_REPLY_INTR_STRUCT -#define IPC_RX_INT_MASK IPC_PSA_CLIENT_REPLY_INTR_MASK - -#define IPC_TX_CHAN IPC_PSA_CLIENT_CALL_CHAN -#define IPC_TX_NOTIFY_MASK IPC_PSA_CLIENT_CALL_NOTIFY_MASK - -#define PSA_CLIENT_REPLY_NVIC_IRQn IPC_PSA_CLIENT_REPLY_IPC_INTR -#define PSA_CLIENT_REPLY_IRQ_PRIORITY 3 - -#endif diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/platform_multicore.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/platform_multicore.h deleted file mode 100644 index ae9855e..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/platform_multicore.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2019, Arm Limited. All rights reserved. - * Copyright (c) 2019, Cypress Semiconductor Corporation. All rights reserved - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#ifndef _TFM_PLATFORM_MULTICORE_ -#define _TFM_PLATFORM_MULTICORE_ - -#include -#include "cy_device_headers.h" - -#define IPC_PSA_CLIENT_CALL_CHAN (8) -#define IPC_PSA_CLIENT_CALL_INTR_STRUCT (6) -#define IPC_PSA_CLIENT_CALL_INTR_MASK (1 << IPC_PSA_CLIENT_CALL_CHAN) -#define IPC_PSA_CLIENT_CALL_NOTIFY_MASK (1 << IPC_PSA_CLIENT_CALL_INTR_STRUCT) -#define IPC_PSA_CLIENT_CALL_IPC_INTR cpuss_interrupts_ipc_6_IRQn - -#define IPC_PSA_CLIENT_REPLY_CHAN (9) -#define IPC_PSA_CLIENT_REPLY_INTR_STRUCT (8) -#define IPC_PSA_CLIENT_REPLY_INTR_MASK (1 << IPC_PSA_CLIENT_REPLY_CHAN) -#define IPC_PSA_CLIENT_REPLY_NOTIFY_MASK (1 << IPC_PSA_CLIENT_REPLY_INTR_STRUCT) -#define IPC_PSA_CLIENT_REPLY_IPC_INTR cpuss_interrupts_ipc_8_IRQn - -#define IPC_PSA_MAILBOX_LOCK_CHAN (10) - -#define IPC_RX_RELEASE_MASK (0) - -#define CY_IPC_NOTIFY_SHIFT (16) - -#define PSA_CLIENT_CALL_REQ_MAGIC (0xA5CF50C6) -#define PSA_CLIENT_CALL_REPLY_MAGIC (0xC605FC5A) - -#define NS_MAILBOX_INIT_ENABLE (0xAE) -#define S_MAILBOX_READY (0xC3) - -#define PLATFORM_MAILBOX_SUCCESS (0x0) -#define PLATFORM_MAILBOX_INVAL_PARAMS (INT32_MIN + 1) -#define PLATFORM_MAILBOX_TX_ERROR (INT32_MIN + 2) -#define PLATFORM_MAILBOX_RX_ERROR (INT32_MIN + 3) -#define PLATFORM_MAILBOX_INIT_ERROR (INT32_MIN + 4) - -/* Inter-Processor Communication (IPC) data channel for the Semaphores */ -#define PLATFORM_MAILBOX_IPC_CHAN_SEMA CY_IPC_CHAN_SEMA -#define MAILBOX_SEMAPHORE_NUM (16) - -#define IPC_SYNC_MAGIC 0x7DADE011 - -/** - * \brief Fetch a pointer from mailbox message - * - * \param[out] msg_ptr The address to write the pointer value to. - * - * \retval 0 The operation succeeds. - * \retval else The operation fails. - */ -int platform_mailbox_fetch_msg_ptr(void **msg_ptr); - -/** - * \brief Fetch a data value from mailbox message - * - * \param[out] data_ptr The address to write the pointer value to. - * - * \retval 0 The operation succeeds. - * \retval else The operation fails. - */ -int platform_mailbox_fetch_msg_data(uint32_t *data_ptr); - -/** - * \brief Send a pointer via mailbox message - * - * \param[in] msg_ptr The pointer value to be sent. - * - * \retval 0 The operation succeeds. - * \retval else The operation fails. - */ -int platform_mailbox_send_msg_ptr(const void *msg_ptr); - -/** - * \brief Send a data value via mailbox message - * - * \param[in] data The data value to be sent - * - * \retval 0 The operation succeeds. - * \retval else The operation fails. - */ -int platform_mailbox_send_msg_data(uint32_t data); - -/** - * \brief Wait for a mailbox notify event. - */ -void platform_mailbox_wait_for_notify(void); - -/** - * \brief IPC initialization - * - * \retval 0 The operation succeeds. - * \retval else The operation fails. - */ -int platform_ns_ipc_init(void); - -#endif diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/client.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/client.h deleted file mode 100644 index 4115f93..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/client.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2018-2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#ifndef __PSA_CLIENT_H__ -#define __PSA_CLIENT_H__ - -#include -#include - -#include "psa/error.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/*********************** PSA Client Macros and Types *************************/ - -/** - * The version of the PSA Framework API that is being used to build the calling - * firmware. - */ -#define PSA_FRAMEWORK_VERSION (0x0100u) - -/** - * Return value from psa_version() if the requested RoT Service is not present - * in the system. - */ -#define PSA_VERSION_NONE (0u) - -/** - * The zero-value null handle can be assigned to variables used in clients and - * RoT Services, indicating that there is no current connection or message. - */ -#define PSA_NULL_HANDLE ((psa_handle_t)0) - -/** - * Tests whether a handle value returned by psa_connect() is valid. - */ -#define PSA_HANDLE_IS_VALID(handle) ((psa_handle_t)(handle) > 0) - -/** - * Converts the handle value returned from a failed call psa_connect() into - * an error code. - */ -#define PSA_HANDLE_TO_ERROR(handle) ((psa_status_t)(handle)) - -/** - * Maximum number of input and output vectors for a request to psa_call(). - */ -#define PSA_MAX_IOVEC (4u) - -/** - * An IPC message type that indicates a generic client request. - */ -#define PSA_IPC_CALL (0) - -typedef int32_t psa_handle_t; - -/** - * A read-only input memory region provided to an RoT Service. - */ -typedef struct psa_invec { - const void *base; /*!< the start address of the memory buffer */ - size_t len; /*!< the size in bytes */ -} psa_invec; - -/** - * A writable output memory region provided to an RoT Service. - */ -typedef struct psa_outvec { - void *base; /*!< the start address of the memory buffer */ - size_t len; /*!< the size in bytes */ -} psa_outvec; - -/*************************** PSA Client API **********************************/ - -/** - * \brief Retrieve the version of the PSA Framework API that is implemented. - * - * \return version The version of the PSA Framework implementation - * that is providing the runtime services to the - * caller. The major and minor version are encoded - * as follows: - * \arg version[15:8] -- major version number. - * \arg version[7:0] -- minor version number. - */ -uint32_t psa_framework_version(void); - -/** - * \brief Retrieve the version of an RoT Service or indicate that it is not - * present on this system. - * - * \param[in] sid ID of the RoT Service to query. - * - * \retval PSA_VERSION_NONE The RoT Service is not implemented, or the - * caller is not permitted to access the service. - * \retval > 0 The version of the implemented RoT Service. - */ -uint32_t psa_version(uint32_t sid); - -/** - * \brief Connect to an RoT Service by its SID. - * - * \param[in] sid ID of the RoT Service to connect to. - * \param[in] version Requested version of the RoT Service. - * - * \retval > 0 A handle for the connection. - * \retval PSA_ERROR_CONNECTION_REFUSED The SPM or RoT Service has refused the - * connection. - * \retval PSA_ERROR_CONNECTION_BUSY The SPM or RoT Service cannot make the - * connection at the moment. - * \retval "PROGRAMMER ERROR" The call is a PROGRAMMER ERROR if one or more - * of the following are true: - * \arg The RoT Service ID is not present. - * \arg The RoT Service version is not supported. - * \arg The caller is not allowed to access the RoT - * service. - */ -psa_handle_t psa_connect(uint32_t sid, uint32_t version); - -/** - * \brief Call an RoT Service on an established connection. - * - * \param[in] handle A handle to an established connection. - * \param[in] type The reuqest type. - * Must be zero( \ref PSA_IPC_CALL) or positive. - * \param[in] in_vec Array of input \ref psa_invec structures. - * \param[in] in_len Number of input \ref psa_invec structures. - * \param[in/out] out_vec Array of output \ref psa_outvec structures. - * \param[in] out_len Number of output \ref psa_outvec structures. - * - * \retval >=0 RoT Service-specific status value. - * \retval <0 RoT Service-specific error code. - * \retval PSA_ERROR_PROGRAMMER_ERROR The connection has been terminated by the - * RoT Service. The call is a PROGRAMMER ERROR if - * one or more of the following are true: - * \arg An invalid handle was passed. - * \arg The connection is already handling a request. - * \arg type < 0. - * \arg An invalid memory reference was provided. - * \arg in_len + out_len > PSA_MAX_IOVEC. - * \arg The message is unrecognized by the RoT - * Service or incorrectly formatted. - */ -psa_status_t psa_call(psa_handle_t handle, int32_t type, - const psa_invec *in_vec, - size_t in_len, - psa_outvec *out_vec, - size_t out_len); - -/** - * \brief Close a connection to an RoT Service. - * - * \param[in] handle A handle to an established connection, or the - * null handle. - * - * \retval void Success. - * \retval "PROGRAMMER ERROR" The call is a PROGRAMMER ERROR if one or more - * of the following are true: - * \arg An invalid handle was provided that is not - * the null handle. - * \arg The connection is currently handling a - * request. - */ -void psa_close(psa_handle_t handle); - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_CLIENT_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto.h deleted file mode 100644 index 9158117..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto.h +++ /dev/null @@ -1,3770 +0,0 @@ -/* - * Copyright (c) 2018-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ -/** - * \file psa/crypto.h - * \brief Platform Security Architecture cryptography module - */ - -#ifndef PSA_CRYPTO_H -#define PSA_CRYPTO_H - -#include "psa/crypto_platform.h" - -#include - -#ifdef __DOXYGEN_ONLY__ -/* This __DOXYGEN_ONLY__ block contains mock definitions for things that - * must be defined in the crypto_platform.h header. These mock definitions - * are present in this file as a convenience to generate pretty-printed - * documentation that includes those definitions. */ - -/** \defgroup platform Implementation-specific definitions - * @{ - */ - -/** \brief Key handle. - * - * This type represents open handles to keys. It must be an unsigned integral - * type. The choice of type is implementation-dependent. - * - * 0 is not a valid key handle. How other handle values are assigned is - * implementation-dependent. - */ -typedef _unsigned_integral_type_ psa_key_handle_t; - -/**@}*/ -#endif /* __DOXYGEN_ONLY__ */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* The file "crypto_types.h" declares types that encode errors, - * algorithms, key types, policies, etc. */ -#include "psa/crypto_types.h" - -/** \defgroup version API version - * @{ - */ - -/** - * The major version of this implementation of the PSA Crypto API - */ -#define PSA_CRYPTO_API_VERSION_MAJOR 1 - -/** - * The minor version of this implementation of the PSA Crypto API - */ -#define PSA_CRYPTO_API_VERSION_MINOR 0 - -/**@}*/ - -/* The file "crypto_values.h" declares macros to build and analyze values - * of integral types defined in "crypto_types.h". */ -#include "psa/crypto_values.h" - -/** \defgroup initialization Library initialization - * @{ - */ - -/** - * \brief Library initialization. - * - * Applications must call this function before calling any other - * function in this module. - * - * Applications may call this function more than once. Once a call - * succeeds, subsequent calls are guaranteed to succeed. - * - * If the application calls other functions before calling psa_crypto_init(), - * the behavior is undefined. Implementations are encouraged to either perform - * the operation as if the library had been initialized or to return - * #PSA_ERROR_BAD_STATE or some other applicable error. In particular, - * implementations should not return a success status if the lack of - * initialization may have security implications, for example due to improper - * seeding of the random number generator. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY - */ -psa_status_t psa_crypto_init(void); - -/**@}*/ - -/** \addtogroup attributes - * @{ - */ - -/** \def PSA_KEY_ATTRIBUTES_INIT - * - * This macro returns a suitable initializer for a key attribute structure - * of type #psa_key_attributes_t. - */ -#ifdef __DOXYGEN_ONLY__ -/* This is an example definition for documentation purposes. - * Implementations should define a suitable value in `crypto_struct.h`. - */ -#define PSA_KEY_ATTRIBUTES_INIT {0} -#endif - -/** Return an initial value for a key attributes structure. - */ -static psa_key_attributes_t psa_key_attributes_init(void); - -/** Declare a key as persistent and set its key identifier. - * - * If the attribute structure currently declares the key as volatile (which - * is the default content of an attribute structure), this function sets - * the lifetime attribute to #PSA_KEY_LIFETIME_PERSISTENT. - * - * This function does not access storage, it merely stores the given - * value in the structure. - * The persistent key will be written to storage when the attribute - * structure is passed to a key creation function such as - * psa_import_key(), psa_generate_key(), - * psa_key_derivation_output_key() or psa_copy_key(). - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate each of its arguments exactly once. - * - * \param[out] attributes The attribute structure to write to. - * \param id The persistent identifier for the key. - */ -static void psa_set_key_id(psa_key_attributes_t *attributes, - psa_key_id_t id); - -/** Set the location of a persistent key. - * - * To make a key persistent, you must give it a persistent key identifier - * with psa_set_key_id(). By default, a key that has a persistent identifier - * is stored in the default storage area identifier by - * #PSA_KEY_LIFETIME_PERSISTENT. Call this function to choose a storage - * area, or to explicitly declare the key as volatile. - * - * This function does not access storage, it merely stores the given - * value in the structure. - * The persistent key will be written to storage when the attribute - * structure is passed to a key creation function such as - * psa_import_key(), psa_generate_key(), - * psa_key_derivation_output_key() or psa_copy_key(). - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate each of its arguments exactly once. - * - * \param[out] attributes The attribute structure to write to. - * \param lifetime The lifetime for the key. - * If this is #PSA_KEY_LIFETIME_VOLATILE, the - * key will be volatile, and the key identifier - * attribute is reset to 0. - */ -static void psa_set_key_lifetime(psa_key_attributes_t *attributes, - psa_key_lifetime_t lifetime); - -/** Retrieve the key identifier from key attributes. - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate its argument exactly once. - * - * \param[in] attributes The key attribute structure to query. - * - * \return The persistent identifier stored in the attribute structure. - * This value is unspecified if the attribute structure declares - * the key as volatile. - */ -static psa_key_id_t psa_get_key_id(const psa_key_attributes_t *attributes); - -/** Retrieve the lifetime from key attributes. - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate its argument exactly once. - * - * \param[in] attributes The key attribute structure to query. - * - * \return The lifetime value stored in the attribute structure. - */ -static psa_key_lifetime_t psa_get_key_lifetime( - const psa_key_attributes_t *attributes); - -/** Declare usage flags for a key. - * - * Usage flags are part of a key's usage policy. They encode what - * kind of operations are permitted on the key. For more details, - * refer to the documentation of the type #psa_key_usage_t. - * - * This function overwrites any usage flags - * previously set in \p attributes. - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate each of its arguments exactly once. - * - * \param[out] attributes The attribute structure to write to. - * \param usage_flags The usage flags to write. - */ -static void psa_set_key_usage_flags(psa_key_attributes_t *attributes, - psa_key_usage_t usage_flags); - -/** Retrieve the usage flags from key attributes. - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate its argument exactly once. - * - * \param[in] attributes The key attribute structure to query. - * - * \return The usage flags stored in the attribute structure. - */ -static psa_key_usage_t psa_get_key_usage_flags( - const psa_key_attributes_t *attributes); - -/** Declare the permitted algorithm policy for a key. - * - * The permitted algorithm policy of a key encodes which algorithm or - * algorithms are permitted to be used with this key. The following - * algorithm policies are supported: - * - 0 does not allow any cryptographic operation with the key. The key - * may be used for non-cryptographic actions such as exporting (if - * permitted by the usage flags). - * - An algorithm value permits this particular algorithm. - * - An algorithm wildcard built from #PSA_ALG_ANY_HASH allows the specified - * signature scheme with any hash algorithm. - * - * This function overwrites any algorithm policy - * previously set in \p attributes. - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate each of its arguments exactly once. - * - * \param[out] attributes The attribute structure to write to. - * \param alg The permitted algorithm policy to write. - */ -static void psa_set_key_algorithm(psa_key_attributes_t *attributes, - psa_algorithm_t alg); - - -/** Retrieve the algorithm policy from key attributes. - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate its argument exactly once. - * - * \param[in] attributes The key attribute structure to query. - * - * \return The algorithm stored in the attribute structure. - */ -static psa_algorithm_t psa_get_key_algorithm( - const psa_key_attributes_t *attributes); - -/** Declare the type of a key. - * - * This function overwrites any key type - * previously set in \p attributes. - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate each of its arguments exactly once. - * - * \param[out] attributes The attribute structure to write to. - * \param type The key type to write. - * If this is 0, the key type in \p attributes - * becomes unspecified. - */ -static void psa_set_key_type(psa_key_attributes_t *attributes, - psa_key_type_t type); - - -/** Declare the size of a key. - * - * This function overwrites any key size previously set in \p attributes. - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate each of its arguments exactly once. - * - * \param[out] attributes The attribute structure to write to. - * \param bits The key size in bits. - * If this is 0, the key size in \p attributes - * becomes unspecified. Keys of size 0 are - * not supported. - */ -static void psa_set_key_bits(psa_key_attributes_t *attributes, - size_t bits); - -/** Retrieve the key type from key attributes. - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate its argument exactly once. - * - * \param[in] attributes The key attribute structure to query. - * - * \return The key type stored in the attribute structure. - */ -static psa_key_type_t psa_get_key_type(const psa_key_attributes_t *attributes); - -/** Retrieve the key size from key attributes. - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate its argument exactly once. - * - * \param[in] attributes The key attribute structure to query. - * - * \return The key size stored in the attribute structure, in bits. - */ -static size_t psa_get_key_bits(const psa_key_attributes_t *attributes); - -/** Retrieve the attributes of a key. - * - * This function first resets the attribute structure as with - * psa_reset_key_attributes(). It then copies the attributes of - * the given key into the given attribute structure. - * - * \note This function may allocate memory or other resources. - * Once you have called this function on an attribute structure, - * you must call psa_reset_key_attributes() to free these resources. - * - * \param[in] handle Handle to the key to query. - * \param[in,out] attributes On success, the attributes of the key. - * On failure, equivalent to a - * freshly-initialized structure. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_get_key_attributes(psa_key_handle_t handle, - psa_key_attributes_t *attributes); - -/** Reset a key attribute structure to a freshly initialized state. - * - * You must initialize the attribute structure as described in the - * documentation of the type #psa_key_attributes_t before calling this - * function. Once the structure has been initialized, you may call this - * function at any time. - * - * This function frees any auxiliary resources that the structure - * may contain. - * - * \param[in,out] attributes The attribute structure to reset. - */ -void psa_reset_key_attributes(psa_key_attributes_t *attributes); - -/**@}*/ - -/** \defgroup key_management Key management - * @{ - */ - -/** Open a handle to an existing persistent key. - * - * Open a handle to a persistent key. A key is persistent if it was created - * with a lifetime other than #PSA_KEY_LIFETIME_VOLATILE. A persistent key - * always has a nonzero key identifier, set with psa_set_key_id() when - * creating the key. Implementations may provide additional pre-provisioned - * keys that can be opened with psa_open_key(). Such keys have a key identifier - * in the vendor range, as documented in the description of #psa_key_id_t. - * - * The application must eventually close the handle with psa_close_key() or - * psa_destroy_key() to release associated resources. If the application dies - * without calling one of these functions, the implementation should perform - * the equivalent of a call to psa_close_key(). - * - * Some implementations permit an application to open the same key multiple - * times. If this is successful, each call to psa_open_key() will return a - * different key handle. - * - * \note Applications that rely on opening a key multiple times will not be - * portable to implementations that only permit a single key handle to be - * opened. See also :ref:\`key-handles\`. - * - * \param id The persistent identifier of the key. - * \param[out] handle On success, a handle to the key. - * - * \retval #PSA_SUCCESS - * Success. The application can now use the value of `*handle` - * to access the key. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * The implementation does not have sufficient resources to open the - * key. This can be due to reaching an implementation limit on the - * number of open keys, the number of open key handles, or available - * memory. - * \retval #PSA_ERROR_DOES_NOT_EXIST - * There is no persistent key with key identifier \p id. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p id is not a valid persistent key identifier. - * \retval #PSA_ERROR_NOT_PERMITTED - * The specified key exists, but the application does not have the - * permission to access it. Note that this specification does not - * define any way to create such a key, but it may be possible - * through implementation-specific means. - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_open_key(psa_key_id_t id, - psa_key_handle_t *handle); - - -/** Close a key handle. - * - * If the handle designates a volatile key, this will destroy the key material - * and free all associated resources, just like psa_destroy_key(). - * - * If this is the last open handle to a persistent key, then closing the handle - * will free all resources associated with the key in volatile memory. The key - * data in persistent storage is not affected and can be opened again later - * with a call to psa_open_key(). - * - * Closing the key handle makes the handle invalid, and the key handle - * must not be used again by the application. - * - * \note If the key handle was used to set up an active - * :ref:\`multipart operation \`, then closing the - * key handle can cause the multipart operation to fail. Applications should - * maintain the key handle until after the multipart operation has finished. - * - * \param handle The key handle to close. - * If this is \c 0, do nothing and return \c PSA_SUCCESS. - * - * \retval #PSA_SUCCESS - * \p handle was a valid handle or \c 0. It is now closed. - * \retval #PSA_ERROR_INVALID_HANDLE - * \p handle is not a valid handle nor \c 0. - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_close_key(psa_key_handle_t handle); - -/** Make a copy of a key. - * - * Copy key material from one location to another. - * - * This function is primarily useful to copy a key from one location - * to another, since it populates a key using the material from - * another key which may have a different lifetime. - * - * This function may be used to share a key with a different party, - * subject to implementation-defined restrictions on key sharing. - * - * The policy on the source key must have the usage flag - * #PSA_KEY_USAGE_COPY set. - * This flag is sufficient to permit the copy if the key has the lifetime - * #PSA_KEY_LIFETIME_VOLATILE or #PSA_KEY_LIFETIME_PERSISTENT. - * Some secure elements do not provide a way to copy a key without - * making it extractable from the secure element. If a key is located - * in such a secure element, then the key must have both usage flags - * #PSA_KEY_USAGE_COPY and #PSA_KEY_USAGE_EXPORT in order to make - * a copy of the key outside the secure element. - * - * The resulting key may only be used in a way that conforms to - * both the policy of the original key and the policy specified in - * the \p attributes parameter: - * - The usage flags on the resulting key are the bitwise-and of the - * usage flags on the source policy and the usage flags in \p attributes. - * - If both allow the same algorithm or wildcard-based - * algorithm policy, the resulting key has the same algorithm policy. - * - If either of the policies allows an algorithm and the other policy - * allows a wildcard-based algorithm policy that includes this algorithm, - * the resulting key allows the same algorithm. - * - If the policies do not allow any algorithm in common, this function - * fails with the status #PSA_ERROR_INVALID_ARGUMENT. - * - * The effect of this function on implementation-defined attributes is - * implementation-defined. - * - * \param source_handle The key to copy. It must be a valid key handle. - * \param[in] attributes The attributes for the new key. - * They are used as follows: - * - The key type and size may be 0. If either is - * nonzero, it must match the corresponding - * attribute of the source key. - * - The key location (the lifetime and, for - * persistent keys, the key identifier) is - * used directly. - * - The policy constraints (usage flags and - * algorithm policy) are combined from - * the source key and \p attributes so that - * both sets of restrictions apply, as - * described in the documentation of this function. - * \param[out] target_handle On success, a handle to the newly created key. - * \c 0 on failure. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_HANDLE - * \p source_handle is invalid. - * \retval #PSA_ERROR_ALREADY_EXISTS - * This is an attempt to create a persistent key, and there is - * already a persistent key with the given identifier. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The lifetime or identifier in \p attributes are invalid. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The policy constraints on the source and specified in - * \p attributes are incompatible. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p attributes specifies a key type or key size - * which does not match the attributes of the source key. - * \retval #PSA_ERROR_NOT_PERMITTED - * The source key does not have the #PSA_KEY_USAGE_COPY usage flag. - * \retval #PSA_ERROR_NOT_PERMITTED - * The source key is not exportable and its lifetime does not - * allow copying it to the target's lifetime. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_INSUFFICIENT_STORAGE - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_copy_key(psa_key_handle_t source_handle, - const psa_key_attributes_t *attributes, - psa_key_handle_t *target_handle); - - -/** - * \brief Destroy a key. - * - * This function destroys a key from both volatile - * memory and, if applicable, non-volatile storage. Implementations shall - * make a best effort to ensure that that the key material cannot be recovered. - * - * This function also erases any metadata such as policies and frees - * resources associated with the key. To free all resources associated with - * the key, all handles to the key must be closed or destroyed. - * - * Destroying the key makes the handle invalid, and the key handle - * must not be used again by the application. Using other open handles to the - * destroyed key in a cryptographic operation will result in an error. - * - * If a key is currently in use in a multipart operation, then destroying the - * key will cause the multipart operation to fail. - * - * \param handle Handle to the key to erase. - * If this is \c 0, do nothing and return \c PSA_SUCCESS. - * - * \retval #PSA_SUCCESS - * \p handle was a valid handle and the key material that it - * referred to has been erased. - * Alternatively, \p handle is \c 0. - * \retval #PSA_ERROR_NOT_PERMITTED - * The key cannot be erased because it is - * read-only, either due to a policy or due to physical restrictions. - * \retval #PSA_ERROR_INVALID_HANDLE - * \p handle is not a valid handle nor \c 0. - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * There was an failure in communication with the cryptoprocessor. - * The key material may still be present in the cryptoprocessor. - * \retval #PSA_ERROR_STORAGE_FAILURE - * The storage is corrupted. Implementations shall make a best effort - * to erase key material even in this stage, however applications - * should be aware that it may be impossible to guarantee that the - * key material is not recoverable in such cases. - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * An unexpected condition which is not a storage corruption or - * a communication failure occurred. The cryptoprocessor may have - * been compromised. - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_destroy_key(psa_key_handle_t handle); - -/**@}*/ - -/** \defgroup import_export Key import and export - * @{ - */ - -/** - * \brief Import a key in binary format. - * - * This function supports any output from psa_export_key(). Refer to the - * documentation of psa_export_public_key() for the format of public keys - * and to the documentation of psa_export_key() for the format for - * other key types. - * - * The key data determines the key size. The attributes may optionally - * specify a key size; in this case it must match the size determined - * from the key data. A key size of 0 in \p attributes indicates that - * the key size is solely determined by the key data. - * - * Implementations must reject an attempt to import a key of size 0. - * - * This specification supports a single format for each key type. - * Implementations may support other formats as long as the standard - * format is supported. Implementations that support other formats - * should ensure that the formats are clearly unambiguous so as to - * minimize the risk that an invalid input is accidentally interpreted - * according to a different format. - * - * \param[in] attributes The attributes for the new key. - * The key size is always determined from the - * \p data buffer. - * If the key size in \p attributes is nonzero, - * it must be equal to the size from \p data. - * \param[out] handle On success, a handle to the newly created key. - * \c 0 on failure. - * \param[in] data Buffer containing the key data. The content of this - * buffer is interpreted according to the type declared - * in \p attributes. - * All implementations must support at least the format - * described in the documentation - * of psa_export_key() or psa_export_public_key() for - * the chosen type. Implementations may allow other - * formats, but should be conservative: implementations - * should err on the side of rejecting content if it - * may be erroneous (e.g. wrong type or truncated data). - * \param data_length Size of the \p data buffer in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * If the key is persistent, the key material and the key's metadata - * have been saved to persistent storage. - * \retval #PSA_ERROR_ALREADY_EXISTS - * This is an attempt to create a persistent key, and there is - * already a persistent key with the given identifier. - * \retval #PSA_ERROR_NOT_SUPPORTED - * The key type or key size is not supported, either by the - * implementation in general or in this particular persistent location. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The key attributes, as a whole, are invalid. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The key data is not correctly formatted. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The size in \p attributes is nonzero and does not match the size - * of the key data. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_INSUFFICIENT_STORAGE - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_import_key(const psa_key_attributes_t *attributes, - const uint8_t *data, - size_t data_length, - psa_key_handle_t *handle); - - - -/** - * \brief Export a key in binary format. - * - * The output of this function can be passed to psa_import_key() to - * create an equivalent object. - * - * If the implementation of psa_import_key() supports other formats - * beyond the format specified here, the output from psa_export_key() - * must use the representation specified here, not the original - * representation. - * - * For standard key types, the output format is as follows: - * - * - For symmetric keys (including MAC keys), the format is the - * raw bytes of the key. - * - For DES, the key data consists of 8 bytes. The parity bits must be - * correct. - * - For Triple-DES, the format is the concatenation of the - * two or three DES keys. - * - For RSA key pairs (#PSA_KEY_TYPE_RSA_KEY_PAIR), the format - * is the non-encrypted DER encoding of the representation defined by - * PKCS\#1 (RFC 8017) as `RSAPrivateKey`, version 0. - * ``` - * RSAPrivateKey ::= SEQUENCE { - * version INTEGER, -- must be 0 - * modulus INTEGER, -- n - * publicExponent INTEGER, -- e - * privateExponent INTEGER, -- d - * prime1 INTEGER, -- p - * prime2 INTEGER, -- q - * exponent1 INTEGER, -- d mod (p-1) - * exponent2 INTEGER, -- d mod (q-1) - * coefficient INTEGER, -- (inverse of q) mod p - * } - * ``` - * - For elliptic curve key pairs (key types for which - * #PSA_KEY_TYPE_IS_ECC_KEY_PAIR is true), the format is - * a representation of the private value as a `ceiling(m/8)`-byte string - * where `m` is the bit size associated with the curve, i.e. the bit size - * of the order of the curve's coordinate field. This byte string is - * in little-endian order for Montgomery curves (curve types - * `PSA_ECC_CURVE_CURVEXXX`), and in big-endian order for Weierstrass - * curves (curve types `PSA_ECC_CURVE_SECTXXX`, `PSA_ECC_CURVE_SECPXXX` - * and `PSA_ECC_CURVE_BRAINPOOL_PXXX`). - * This is the content of the `privateKey` field of the `ECPrivateKey` - * format defined by RFC 5915. - * - For Diffie-Hellman key exchange key pairs (key types for which - * #PSA_KEY_TYPE_IS_DH_KEY_PAIR is true), the - * format is the representation of the private key `x` as a big-endian byte - * string. The length of the byte string is the private key size in bytes - * (leading zeroes are not stripped). - * - For public keys (key types for which #PSA_KEY_TYPE_IS_PUBLIC_KEY is - * true), the format is the same as for psa_export_public_key(). - * - * The policy on the key must have the usage flag #PSA_KEY_USAGE_EXPORT set. - * - * \param handle Handle to the key to export. - * \param[out] data Buffer where the key data is to be written. - * \param data_size Size of the \p data buffer in bytes. - * \param[out] data_length On success, the number of bytes - * that make up the key data. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * The key does not have the #PSA_KEY_USAGE_EXPORT flag. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p data buffer is too small. You can determine a - * sufficient buffer size by calling - * #PSA_KEY_EXPORT_MAX_SIZE(\c type, \c bits) - * where \c type is the key type - * and \c bits is the key size in bits. - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_export_key(psa_key_handle_t handle, - uint8_t *data, - size_t data_size, - size_t *data_length); - -/** - * \brief Export a public key or the public part of a key pair in binary format. - * - * The output of this function can be passed to psa_import_key() to - * create an object that is equivalent to the public key. - * - * This specification supports a single format for each key type. - * Implementations may support other formats as long as the standard - * format is supported. Implementations that support other formats - * should ensure that the formats are clearly unambiguous so as to - * minimize the risk that an invalid input is accidentally interpreted - * according to a different format. - * - * For standard key types, the output format is as follows: - * - For RSA public keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY), the DER encoding of - * the representation defined by RFC 3279 §2.3.1 as `RSAPublicKey`. - * ``` - * RSAPublicKey ::= SEQUENCE { - * modulus INTEGER, -- n - * publicExponent INTEGER } -- e - * ``` - * - For elliptic curve public keys (key types for which - * #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true), the format is the uncompressed - * representation defined by SEC1 §2.3.3 as the content of an ECPoint. - * Let `m` be the bit size associated with the curve, i.e. the bit size of - * `q` for a curve over `F_q`. The representation consists of: - * - The byte 0x04; - * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; - * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. - * - For Diffie-Hellman key exchange public keys (key types for which - * #PSA_KEY_TYPE_IS_DH_PUBLIC_KEY is true), - * the format is the representation of the public key `y = g^x mod p` as a - * big-endian byte string. The length of the byte string is the length of the - * base prime `p` in bytes. - * - * Exporting a public key object or the public part of a key pair is - * always permitted, regardless of the key's usage flags. - * - * \param handle Handle to the key to export. - * \param[out] data Buffer where the key data is to be written. - * \param data_size Size of the \p data buffer in bytes. - * \param[out] data_length On success, the number of bytes - * that make up the key data. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The key is neither a public key nor a key pair. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p data buffer is too small. You can determine a - * sufficient buffer size by calling - * #PSA_KEY_EXPORT_MAX_SIZE(#PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(\c type), \c bits) - * where \c type is the key type - * and \c bits is the key size in bits. - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_export_public_key(psa_key_handle_t handle, - uint8_t *data, - size_t data_size, - size_t *data_length); - - - -/**@}*/ - -/** \defgroup hash Message digests - * @{ - */ - -/** Calculate the hash (digest) of a message. - * - * \note To verify the hash of a message against an - * expected value, use psa_hash_compare() instead. - * - * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value - * such that #PSA_ALG_IS_HASH(\p alg) is true). - * \param[in] input Buffer containing the message to hash. - * \param input_length Size of the \p input buffer in bytes. - * \param[out] hash Buffer where the hash is to be written. - * \param hash_size Size of the \p hash buffer in bytes. - * \param[out] hash_length On success, the number of bytes - * that make up the hash value. This is always - * #PSA_HASH_SIZE(\p alg). - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not a hash algorithm. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * \p hash_size is too small - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_hash_compute(psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - uint8_t *hash, - size_t hash_size, - size_t *hash_length); - -/** Calculate the hash (digest) of a message and compare it with a - * reference value. - * - * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value - * such that #PSA_ALG_IS_HASH(\p alg) is true). - * \param[in] input Buffer containing the message to hash. - * \param input_length Size of the \p input buffer in bytes. - * \param[out] hash Buffer containing the expected hash value. - * \param hash_length Size of the \p hash buffer in bytes. - * - * \retval #PSA_SUCCESS - * The expected hash is identical to the actual hash of the input. - * \retval #PSA_ERROR_INVALID_SIGNATURE - * The hash of the message was calculated successfully, but it - * differs from the expected hash. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not a hash algorithm. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p input_length or \p hash_length do not match the hash size for \p alg - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_hash_compare(psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - const uint8_t *hash, - const size_t hash_length); - -/** The type of the state data structure for multipart hash operations. - * - * Before calling any function on a hash operation object, the application must - * initialize it by any of the following means: - * - Set the structure to all-bits-zero, for example: - * \code - * psa_hash_operation_t operation; - * memset(&operation, 0, sizeof(operation)); - * \endcode - * - Initialize the structure to logical zero values, for example: - * \code - * psa_hash_operation_t operation = {0}; - * \endcode - * - Initialize the structure to the initializer #PSA_HASH_OPERATION_INIT, - * for example: - * \code - * psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; - * \endcode - * - Assign the result of the function psa_hash_operation_init() - * to the structure, for example: - * \code - * psa_hash_operation_t operation; - * operation = psa_hash_operation_init(); - * \endcode - * - * This is an implementation-defined \c struct. Applications should not - * make any assumptions about the content of this structure except - * as directed by the documentation of a specific implementation. */ -typedef struct psa_hash_operation_s psa_hash_operation_t; - -/** \def PSA_HASH_OPERATION_INIT - * - * This macro returns a suitable initializer for a hash operation object - * of type #psa_hash_operation_t. - */ -#ifdef __DOXYGEN_ONLY__ -/* This is an example definition for documentation purposes. - * Implementations should define a suitable value in `crypto_struct.h`. - */ -#define PSA_HASH_OPERATION_INIT {0} -#endif - -/** Return an initial value for a hash operation object. - */ -static psa_hash_operation_t psa_hash_operation_init(void); - -/** Set up a multipart hash operation. - * - * The sequence of operations to calculate a hash (message digest) - * is as follows: - * -# Allocate an operation object which will be passed to all the functions - * listed here. - * -# Initialize the operation object with one of the methods described in the - * documentation for #psa_hash_operation_t, e.g. #PSA_HASH_OPERATION_INIT. - * -# Call psa_hash_setup() to specify the algorithm. - * -# Call psa_hash_update() zero, one or more times, passing a fragment - * of the message each time. The hash that is calculated is the hash - * of the concatenation of these messages in order. - * -# To calculate the hash, call psa_hash_finish(). - * To compare the hash with an expected value, call psa_hash_verify(). - * - * If an error occurs at any step after a call to psa_hash_setup(), the - * operation will need to be reset by a call to psa_hash_abort(). The - * application may call psa_hash_abort() at any time after the operation - * has been initialized. - * - * After a successful call to psa_hash_setup(), the application must - * eventually terminate the operation. The following events terminate an - * operation: - * - A successful call to psa_hash_finish() or psa_hash_verify(). - * - A call to psa_hash_abort(). - * - * \param[in,out] operation The operation object to set up. It must have - * been initialized as per the documentation for - * #psa_hash_operation_t and not yet in use. - * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value - * such that #PSA_ALG_IS_HASH(\p alg) is true). - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not a supported hash algorithm. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p alg is not a hash algorithm. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be inactive). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_hash_setup(psa_hash_operation_t *operation, - psa_algorithm_t alg); - -/** Add a message fragment to a multipart hash operation. - * - * The application must call psa_hash_setup() before calling this function. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_hash_abort(). - * - * \param[in,out] operation Active hash operation. - * \param[in] input Buffer containing the message fragment to hash. - * \param input_length Size of the \p input buffer in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it muct be active). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_hash_update(psa_hash_operation_t *operation, - const uint8_t *input, - size_t input_length); - -/** Finish the calculation of the hash of a message. - * - * The application must call psa_hash_setup() before calling this function. - * This function calculates the hash of the message formed by concatenating - * the inputs passed to preceding calls to psa_hash_update(). - * - * When this function returns successfuly, the operation becomes inactive. - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_hash_abort(). - * - * \warning Applications should not call this function if they expect - * a specific value for the hash. Call psa_hash_verify() instead. - * Beware that comparing integrity or authenticity data such as - * hash values with a function such as \c memcmp is risky - * because the time taken by the comparison may leak information - * about the hashed data which could allow an attacker to guess - * a valid hash and thereby bypass security controls. - * - * \param[in,out] operation Active hash operation. - * \param[out] hash Buffer where the hash is to be written. - * \param hash_size Size of the \p hash buffer in bytes. - * \param[out] hash_length On success, the number of bytes - * that make up the hash value. This is always - * #PSA_HASH_SIZE(\c alg) where \c alg is the - * hash algorithm that is calculated. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active). - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p hash buffer is too small. You can determine a - * sufficient buffer size by calling #PSA_HASH_SIZE(\c alg) - * where \c alg is the hash algorithm that is calculated. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_hash_finish(psa_hash_operation_t *operation, - uint8_t *hash, - size_t hash_size, - size_t *hash_length); - -/** Finish the calculation of the hash of a message and compare it with - * an expected value. - * - * The application must call psa_hash_setup() before calling this function. - * This function calculates the hash of the message formed by concatenating - * the inputs passed to preceding calls to psa_hash_update(). It then - * compares the calculated hash with the expected hash passed as a - * parameter to this function. - * - * When this function returns successfuly, the operation becomes inactive. - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_hash_abort(). - * - * \note Implementations shall make the best effort to ensure that the - * comparison between the actual hash and the expected hash is performed - * in constant time. - * - * \param[in,out] operation Active hash operation. - * \param[in] hash Buffer containing the expected hash value. - * \param hash_length Size of the \p hash buffer in bytes. - * - * \retval #PSA_SUCCESS - * The expected hash is identical to the actual hash of the message. - * \retval #PSA_ERROR_INVALID_SIGNATURE - * The hash of the message was calculated successfully, but it - * differs from the expected hash. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_hash_verify(psa_hash_operation_t *operation, - const uint8_t *hash, - size_t hash_length); - -/** Abort a hash operation. - * - * Aborting an operation frees all associated resources except for the - * \p operation structure itself. Once aborted, the operation object - * can be reused for another operation by calling - * psa_hash_setup() again. - * - * You may call this function any time after the operation object has - * been initialized by one of the methods described in #psa_hash_operation_t. - * - * In particular, calling psa_hash_abort() after the operation has been - * terminated by a call to psa_hash_abort(), psa_hash_finish() or - * psa_hash_verify() is safe and has no effect. - * - * \param[in,out] operation Initialized hash operation. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_hash_abort(psa_hash_operation_t *operation); - -/** Clone a hash operation. - * - * This function copies the state of an ongoing hash operation to - * a new operation object. In other words, this function is equivalent - * to calling psa_hash_setup() on \p target_operation with the same - * algorithm that \p source_operation was set up for, then - * psa_hash_update() on \p target_operation with the same input that - * that was passed to \p source_operation. After this function returns, the - * two objects are independent, i.e. subsequent calls involving one of - * the objects do not affect the other object. - * - * \param[in] source_operation The active hash operation to clone. - * \param[in,out] target_operation The operation object to set up. - * It must be initialized but not active. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_BAD_STATE - * The \p source_operation state is not valid (it must be active). - * \retval #PSA_ERROR_BAD_STATE - * The \p target_operation state is not valid (it must be inactive). - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation, - psa_hash_operation_t *target_operation); - -/**@}*/ - -/** \defgroup MAC Message authentication codes - * @{ - */ - -/** Calculate the MAC (message authentication code) of a message. - * - * \note To verify the MAC of a message against an - * expected value, use psa_mac_verify() instead. - * Beware that comparing integrity or authenticity data such as - * MAC values with a function such as \c memcmp is risky - * because the time taken by the comparison may leak information - * about the MAC value which could allow an attacker to guess - * a valid MAC and thereby bypass security controls. - * - * \param handle Handle to the key to use for the operation. - * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value - * such that #PSA_ALG_IS_MAC(\p alg) is true). - * \param[in] input Buffer containing the input message. - * \param input_length Size of the \p input buffer in bytes. - * \param[out] mac Buffer where the MAC value is to be written. - * \param mac_size Size of the \p mac buffer in bytes. - * \param[out] mac_length On success, the number of bytes - * that make up the MAC value. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not a MAC algorithm. - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * \p mac_size is too small - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * The key could not be retrieved from storage. - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_mac_compute(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - uint8_t *mac, - size_t mac_size, - size_t *mac_length); - -/** Calculate the MAC of a message and compare it with a reference value. - * - * \param handle Handle to the key to use for the operation. - * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value - * such that #PSA_ALG_IS_MAC(\p alg) is true). - * \param[in] input Buffer containing the input message. - * \param input_length Size of the \p input buffer in bytes. - * \param[out] mac Buffer containing the expected MAC value. - * \param mac_length Size of the \p mac buffer in bytes. - * - * \retval #PSA_SUCCESS - * The expected MAC is identical to the actual MAC of the input. - * \retval #PSA_ERROR_INVALID_SIGNATURE - * The MAC of the message was calculated successfully, but it - * differs from the expected value. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not a MAC algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * The key could not be retrieved from storage. - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_mac_verify(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - const uint8_t *mac, - const size_t mac_length); - -/** The type of the state data structure for multipart MAC operations. - * - * Before calling any function on a MAC operation object, the application must - * initialize it by any of the following means: - * - Set the structure to all-bits-zero, for example: - * \code - * psa_mac_operation_t operation; - * memset(&operation, 0, sizeof(operation)); - * \endcode - * - Initialize the structure to logical zero values, for example: - * \code - * psa_mac_operation_t operation = {0}; - * \endcode - * - Initialize the structure to the initializer #PSA_MAC_OPERATION_INIT, - * for example: - * \code - * psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; - * \endcode - * - Assign the result of the function psa_mac_operation_init() - * to the structure, for example: - * \code - * psa_mac_operation_t operation; - * operation = psa_mac_operation_init(); - * \endcode - * - * This is an implementation-defined \c struct. Applications should not - * make any assumptions about the content of this structure except - * as directed by the documentation of a specific implementation. */ -typedef struct psa_mac_operation_s psa_mac_operation_t; - -/** \def PSA_MAC_OPERATION_INIT - * - * This macro returns a suitable initializer for a MAC operation object of type - * #psa_mac_operation_t. - */ -#ifdef __DOXYGEN_ONLY__ -/* This is an example definition for documentation purposes. - * Implementations should define a suitable value in `crypto_struct.h`. - */ -#define PSA_MAC_OPERATION_INIT {0} -#endif - -/** Return an initial value for a MAC operation object. - */ -static psa_mac_operation_t psa_mac_operation_init(void); - -/** Set up a multipart MAC calculation operation. - * - * This function sets up the calculation of the MAC - * (message authentication code) of a byte string. - * To verify the MAC of a message against an - * expected value, use psa_mac_verify_setup() instead. - * - * The sequence of operations to calculate a MAC is as follows: - * -# Allocate an operation object which will be passed to all the functions - * listed here. - * -# Initialize the operation object with one of the methods described in the - * documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT. - * -# Call psa_mac_sign_setup() to specify the algorithm and key. - * -# Call psa_mac_update() zero, one or more times, passing a fragment - * of the message each time. The MAC that is calculated is the MAC - * of the concatenation of these messages in order. - * -# At the end of the message, call psa_mac_sign_finish() to finish - * calculating the MAC value and retrieve it. - * - * If an error occurs at any step after a call to psa_mac_sign_setup(), the - * operation will need to be reset by a call to psa_mac_abort(). The - * application may call psa_mac_abort() at any time after the operation - * has been initialized. - * - * After a successful call to psa_mac_sign_setup(), the application must - * eventually terminate the operation through one of the following methods: - * - A successful call to psa_mac_sign_finish(). - * - A call to psa_mac_abort(). - * - * \param[in,out] operation The operation object to set up. It must have - * been initialized as per the documentation for - * #psa_mac_operation_t and not yet in use. - * \param handle Handle to the key to use for the operation. - * It must remain valid until the operation - * terminates. - * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value - * such that #PSA_ALG_IS_MAC(\p alg) is true). - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not a MAC algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * The key could not be retrieved from storage. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be inactive). - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg); - -/** Set up a multipart MAC verification operation. - * - * This function sets up the verification of the MAC - * (message authentication code) of a byte string against an expected value. - * - * The sequence of operations to verify a MAC is as follows: - * -# Allocate an operation object which will be passed to all the functions - * listed here. - * -# Initialize the operation object with one of the methods described in the - * documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT. - * -# Call psa_mac_verify_setup() to specify the algorithm and key. - * -# Call psa_mac_update() zero, one or more times, passing a fragment - * of the message each time. The MAC that is calculated is the MAC - * of the concatenation of these messages in order. - * -# At the end of the message, call psa_mac_verify_finish() to finish - * calculating the actual MAC of the message and verify it against - * the expected value. - * - * If an error occurs at any step after a call to psa_mac_verify_setup(), the - * operation will need to be reset by a call to psa_mac_abort(). The - * application may call psa_mac_abort() at any time after the operation - * has been initialized. - * - * After a successful call to psa_mac_verify_setup(), the application must - * eventually terminate the operation through one of the following methods: - * - A successful call to psa_mac_verify_finish(). - * - A call to psa_mac_abort(). - * - * \param[in,out] operation The operation object to set up. It must have - * been initialized as per the documentation for - * #psa_mac_operation_t and not yet in use. - * \param handle Handle to the key to use for the operation. - * It must remain valid until the operation - * terminates. - * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value - * such that #PSA_ALG_IS_MAC(\p alg) is true). - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \c key is not compatible with \c alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \c alg is not supported or is not a MAC algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * The key could not be retrieved from storage - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be inactive). - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg); - -/** Add a message fragment to a multipart MAC operation. - * - * The application must call psa_mac_sign_setup() or psa_mac_verify_setup() - * before calling this function. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_mac_abort(). - * - * \param[in,out] operation Active MAC operation. - * \param[in] input Buffer containing the message fragment to add to - * the MAC calculation. - * \param input_length Size of the \p input buffer in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_mac_update(psa_mac_operation_t *operation, - const uint8_t *input, - size_t input_length); - -/** Finish the calculation of the MAC of a message. - * - * The application must call psa_mac_sign_setup() before calling this function. - * This function calculates the MAC of the message formed by concatenating - * the inputs passed to preceding calls to psa_mac_update(). - * - * When this function returns successfuly, the operation becomes inactive. - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_mac_abort(). - * - * \warning Applications should not call this function if they expect - * a specific value for the MAC. Call psa_mac_verify_finish() instead. - * Beware that comparing integrity or authenticity data such as - * MAC values with a function such as \c memcmp is risky - * because the time taken by the comparison may leak information - * about the MAC value which could allow an attacker to guess - * a valid MAC and thereby bypass security controls. - * - * \param[in,out] operation Active MAC operation. - * \param[out] mac Buffer where the MAC value is to be written. - * \param mac_size Size of the \p mac buffer in bytes. - * \param[out] mac_length On success, the number of bytes - * that make up the MAC value. This is always - * #PSA_MAC_FINAL_SIZE(\c key_type, \c key_bits, \c alg) - * where \c key_type and \c key_bits are the type and - * bit-size respectively of the key and \c alg is the - * MAC algorithm that is calculated. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be an active mac sign - * operation). - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p mac buffer is too small. You can determine a - * sufficient buffer size by calling PSA_MAC_FINAL_SIZE(). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, - uint8_t *mac, - size_t mac_size, - size_t *mac_length); - -/** Finish the calculation of the MAC of a message and compare it with - * an expected value. - * - * The application must call psa_mac_verify_setup() before calling this function. - * This function calculates the MAC of the message formed by concatenating - * the inputs passed to preceding calls to psa_mac_update(). It then - * compares the calculated MAC with the expected MAC passed as a - * parameter to this function. - * - * When this function returns successfuly, the operation becomes inactive. - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_mac_abort(). - * - * \note Implementations shall make the best effort to ensure that the - * comparison between the actual MAC and the expected MAC is performed - * in constant time. - * - * \param[in,out] operation Active MAC operation. - * \param[in] mac Buffer containing the expected MAC value. - * \param mac_length Size of the \p mac buffer in bytes. - * - * \retval #PSA_SUCCESS - * The expected MAC is identical to the actual MAC of the message. - * \retval #PSA_ERROR_INVALID_SIGNATURE - * The MAC of the message was calculated successfully, but it - * differs from the expected MAC. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be an active mac verify - * operation). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation, - const uint8_t *mac, - size_t mac_length); - -/** Abort a MAC operation. - * - * Aborting an operation frees all associated resources except for the - * \p operation structure itself. Once aborted, the operation object - * can be reused for another operation by calling - * psa_mac_sign_setup() or psa_mac_verify_setup() again. - * - * You may call this function any time after the operation object has - * been initialized by one of the methods described in #psa_mac_operation_t. - * - * In particular, calling psa_mac_abort() after the operation has been - * terminated by a call to psa_mac_abort(), psa_mac_sign_finish() or - * psa_mac_verify_finish() is safe and has no effect. - * - * \param[in,out] operation Initialized MAC operation. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_mac_abort(psa_mac_operation_t *operation); - -/**@}*/ - -/** \defgroup cipher Symmetric ciphers - * @{ - */ - -/** Encrypt a message using a symmetric cipher. - * - * This function encrypts a message with a random IV (initialization - * vector). Use the multipart operation interface with a - * #psa_cipher_operation_t object to provide other forms of IV. - * - * \param handle Handle to the key to use for the operation. - * It must remain valid until the operation - * terminates. - * \param alg The cipher algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_CIPHER(\p alg) is true). - * \param[in] input Buffer containing the message to encrypt. - * \param input_length Size of the \p input buffer in bytes. - * \param[out] output Buffer where the output is to be written. - * The output contains the IV followed by - * the ciphertext proper. - * \param output_size Size of the \p output buffer in bytes. - * \param[out] output_length On success, the number of bytes - * that make up the output. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not a cipher algorithm. - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_cipher_encrypt(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - uint8_t *output, - size_t output_size, - size_t *output_length); - -/** Decrypt a message using a symmetric cipher. - * - * This function decrypts a message encrypted with a symmetric cipher. - * - * \param handle Handle to the key to use for the operation. - * It must remain valid until the operation - * terminates. - * \param alg The cipher algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_CIPHER(\p alg) is true). - * \param[in] input Buffer containing the message to decrypt. - * This consists of the IV followed by the - * ciphertext proper. - * \param input_length Size of the \p input buffer in bytes. - * \param[out] output Buffer where the plaintext is to be written. - * \param output_size Size of the \p output buffer in bytes. - * \param[out] output_length On success, the number of bytes - * that make up the output. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not a cipher algorithm. - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_cipher_decrypt(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - uint8_t *output, - size_t output_size, - size_t *output_length); - -/** The type of the state data structure for multipart cipher operations. - * - * Before calling any function on a cipher operation object, the application - * must initialize it by any of the following means: - * - Set the structure to all-bits-zero, for example: - * \code - * psa_cipher_operation_t operation; - * memset(&operation, 0, sizeof(operation)); - * \endcode - * - Initialize the structure to logical zero values, for example: - * \code - * psa_cipher_operation_t operation = {0}; - * \endcode - * - Initialize the structure to the initializer #PSA_CIPHER_OPERATION_INIT, - * for example: - * \code - * psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; - * \endcode - * - Assign the result of the function psa_cipher_operation_init() - * to the structure, for example: - * \code - * psa_cipher_operation_t operation; - * operation = psa_cipher_operation_init(); - * \endcode - * - * This is an implementation-defined \c struct. Applications should not - * make any assumptions about the content of this structure except - * as directed by the documentation of a specific implementation. */ -typedef struct psa_cipher_operation_s psa_cipher_operation_t; - -/** \def PSA_CIPHER_OPERATION_INIT - * - * This macro returns a suitable initializer for a cipher operation object of - * type #psa_cipher_operation_t. - */ -#ifdef __DOXYGEN_ONLY__ -/* This is an example definition for documentation purposes. - * Implementations should define a suitable value in `crypto_struct.h`. - */ -#define PSA_CIPHER_OPERATION_INIT {0} -#endif - -/** Return an initial value for a cipher operation object. - */ -static psa_cipher_operation_t psa_cipher_operation_init(void); - -/** Set the key for a multipart symmetric encryption operation. - * - * The sequence of operations to encrypt a message with a symmetric cipher - * is as follows: - * -# Allocate an operation object which will be passed to all the functions - * listed here. - * -# Initialize the operation object with one of the methods described in the - * documentation for #psa_cipher_operation_t, e.g. - * #PSA_CIPHER_OPERATION_INIT. - * -# Call psa_cipher_encrypt_setup() to specify the algorithm and key. - * -# Call either psa_cipher_generate_iv() or psa_cipher_set_iv() to - * generate or set the IV (initialization vector). You should use - * psa_cipher_generate_iv() unless the protocol you are implementing - * requires a specific IV value. - * -# Call psa_cipher_update() zero, one or more times, passing a fragment - * of the message each time. - * -# Call psa_cipher_finish(). - * - * If an error occurs at any step after a call to psa_cipher_encrypt_setup(), - * the operation will need to be reset by a call to psa_cipher_abort(). The - * application may call psa_cipher_abort() at any time after the operation - * has been initialized. - * - * After a successful call to psa_cipher_encrypt_setup(), the application must - * eventually terminate the operation. The following events terminate an - * operation: - * - A successful call to psa_cipher_finish(). - * - A call to psa_cipher_abort(). - * - * \param[in,out] operation The operation object to set up. It must have - * been initialized as per the documentation for - * #psa_cipher_operation_t and not yet in use. - * \param handle Handle to the key to use for the operation. - * It must remain valid until the operation - * terminates. - * \param alg The cipher algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_CIPHER(\p alg) is true). - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not a cipher algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be inactive). - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg); - -/** Set the key for a multipart symmetric decryption operation. - * - * The sequence of operations to decrypt a message with a symmetric cipher - * is as follows: - * -# Allocate an operation object which will be passed to all the functions - * listed here. - * -# Initialize the operation object with one of the methods described in the - * documentation for #psa_cipher_operation_t, e.g. - * #PSA_CIPHER_OPERATION_INIT. - * -# Call psa_cipher_decrypt_setup() to specify the algorithm and key. - * -# Call psa_cipher_set_iv() with the IV (initialization vector) for the - * decryption. If the IV is prepended to the ciphertext, you can call - * psa_cipher_update() on a buffer containing the IV followed by the - * beginning of the message. - * -# Call psa_cipher_update() zero, one or more times, passing a fragment - * of the message each time. - * -# Call psa_cipher_finish(). - * - * If an error occurs at any step after a call to psa_cipher_decrypt_setup(), - * the operation will need to be reset by a call to psa_cipher_abort(). The - * application may call psa_cipher_abort() at any time after the operation - * has been initialized. - * - * After a successful call to psa_cipher_decrypt_setup(), the application must - * eventually terminate the operation. The following events terminate an - * operation: - * - A successful call to psa_cipher_finish(). - * - A call to psa_cipher_abort(). - * - * \param[in,out] operation The operation object to set up. It must have - * been initialized as per the documentation for - * #psa_cipher_operation_t and not yet in use. - * \param handle Handle to the key to use for the operation. - * It must remain valid until the operation - * terminates. - * \param alg The cipher algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_CIPHER(\p alg) is true). - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not a cipher algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be inactive). - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg); - -/** Generate an IV for a symmetric encryption operation. - * - * This function generates a random IV (initialization vector), nonce - * or initial counter value for the encryption operation as appropriate - * for the chosen algorithm, key type and key size. - * - * The application must call psa_cipher_encrypt_setup() before - * calling this function. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_cipher_abort(). - * - * \param[in,out] operation Active cipher operation. - * \param[out] iv Buffer where the generated IV is to be written. - * \param iv_size Size of the \p iv buffer in bytes. - * \param[out] iv_length On success, the number of bytes of the - * generated IV. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active, with no IV set). - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p iv buffer is too small. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation, - uint8_t *iv, - size_t iv_size, - size_t *iv_length); - -/** Set the IV for a symmetric encryption or decryption operation. - * - * This function sets the IV (initialization vector), nonce - * or initial counter value for the encryption or decryption operation. - * - * The application must call psa_cipher_encrypt_setup() before - * calling this function. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_cipher_abort(). - * - * \note When encrypting, applications should use psa_cipher_generate_iv() - * instead of this function, unless implementing a protocol that requires - * a non-random IV. - * - * \param[in,out] operation Active cipher operation. - * \param[in] iv Buffer containing the IV to use. - * \param iv_length Size of the IV in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be an active cipher - * encrypt operation, with no IV set). - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The size of \p iv is not acceptable for the chosen algorithm, - * or the chosen algorithm does not use an IV. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, - const uint8_t *iv, - size_t iv_length); - -/** Encrypt or decrypt a message fragment in an active cipher operation. - * - * Before calling this function, you must: - * 1. Call either psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup(). - * The choice of setup function determines whether this function - * encrypts or decrypts its input. - * 2. If the algorithm requires an IV, call psa_cipher_generate_iv() - * (recommended when encrypting) or psa_cipher_set_iv(). - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_cipher_abort(). - * - * \param[in,out] operation Active cipher operation. - * \param[in] input Buffer containing the message fragment to - * encrypt or decrypt. - * \param input_length Size of the \p input buffer in bytes. - * \param[out] output Buffer where the output is to be written. - * \param output_size Size of the \p output buffer in bytes. - * \param[out] output_length On success, the number of bytes - * that make up the returned output. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active, with an IV set - * if required for the algorithm). - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p output buffer is too small. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, - const uint8_t *input, - size_t input_length, - uint8_t *output, - size_t output_size, - size_t *output_length); - -/** Finish encrypting or decrypting a message in a cipher operation. - * - * The application must call psa_cipher_encrypt_setup() or - * psa_cipher_decrypt_setup() before calling this function. The choice - * of setup function determines whether this function encrypts or - * decrypts its input. - * - * This function finishes the encryption or decryption of the message - * formed by concatenating the inputs passed to preceding calls to - * psa_cipher_update(). - * - * When this function returns successfuly, the operation becomes inactive. - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_cipher_abort(). - * - * \param[in,out] operation Active cipher operation. - * \param[out] output Buffer where the output is to be written. - * \param output_size Size of the \p output buffer in bytes. - * \param[out] output_length On success, the number of bytes - * that make up the returned output. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The total input size passed to this operation is not valid for - * this particular algorithm. For example, the algorithm is a based - * on block cipher and requires a whole number of blocks, but the - * total input size is not a multiple of the block size. - * \retval #PSA_ERROR_INVALID_PADDING - * This is a decryption operation for an algorithm that includes - * padding, and the ciphertext does not contain valid padding. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active, with an IV set - * if required for the algorithm). - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p output buffer is too small. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, - uint8_t *output, - size_t output_size, - size_t *output_length); - -/** Abort a cipher operation. - * - * Aborting an operation frees all associated resources except for the - * \p operation structure itself. Once aborted, the operation object - * can be reused for another operation by calling - * psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup() again. - * - * You may call this function any time after the operation object has - * been initialized as described in #psa_cipher_operation_t. - * - * In particular, calling psa_cipher_abort() after the operation has been - * terminated by a call to psa_cipher_abort() or psa_cipher_finish() - * is safe and has no effect. - * - * \param[in,out] operation Initialized cipher operation. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation); - -/**@}*/ - -/** \defgroup aead Authenticated encryption with associated data (AEAD) - * @{ - */ - -/** Process an authenticated encryption operation. - * - * \param handle Handle to the key to use for the operation. - * \param alg The AEAD algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * \param[in] nonce Nonce or IV to use. - * \param nonce_length Size of the \p nonce buffer in bytes. - * \param[in] additional_data Additional data that will be authenticated - * but not encrypted. - * \param additional_data_length Size of \p additional_data in bytes. - * \param[in] plaintext Data that will be authenticated and - * encrypted. - * \param plaintext_length Size of \p plaintext in bytes. - * \param[out] ciphertext Output buffer for the authenticated and - * encrypted data. The additional data is not - * part of this output. For algorithms where the - * encrypted data and the authentication tag - * are defined as separate outputs, the - * authentication tag is appended to the - * encrypted data. - * \param ciphertext_size Size of the \p ciphertext buffer in bytes. - * This must be at least - * #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\p alg, - * \p plaintext_length). - * \param[out] ciphertext_length On success, the size of the output - * in the \p ciphertext buffer. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not an AEAD algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * \p ciphertext_size is too small - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_encrypt(psa_key_handle_t handle, - 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 *ciphertext, - size_t ciphertext_size, - size_t *ciphertext_length); - -/** Process an authenticated decryption operation. - * - * \param handle Handle to the key to use for the operation. - * \param alg The AEAD algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * \param[in] nonce Nonce or IV to use. - * \param nonce_length Size of the \p nonce buffer in bytes. - * \param[in] additional_data Additional data that has been authenticated - * but not encrypted. - * \param additional_data_length Size of \p additional_data in bytes. - * \param[in] ciphertext Data that has been authenticated and - * encrypted. For algorithms where the - * encrypted data and the authentication tag - * are defined as separate inputs, the buffer - * must contain the encrypted data followed - * by the authentication tag. - * \param ciphertext_length Size of \p ciphertext in bytes. - * \param[out] plaintext Output buffer for the decrypted data. - * \param plaintext_size Size of the \p plaintext buffer in bytes. - * This must be at least - * #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\p alg, - * \p ciphertext_length). - * \param[out] plaintext_length On success, the size of the output - * in the \p plaintext buffer. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_INVALID_SIGNATURE - * The ciphertext is not authentic. - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not an AEAD algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * \p plaintext_size or \p nonce_length is too small - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_decrypt(psa_key_handle_t handle, - 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 *ciphertext, - size_t ciphertext_length, - uint8_t *plaintext, - size_t plaintext_size, - size_t *plaintext_length); - -/** The type of the state data structure for multipart AEAD operations. - * - * Before calling any function on an AEAD operation object, the application - * must initialize it by any of the following means: - * - Set the structure to all-bits-zero, for example: - * \code - * psa_aead_operation_t operation; - * memset(&operation, 0, sizeof(operation)); - * \endcode - * - Initialize the structure to logical zero values, for example: - * \code - * psa_aead_operation_t operation = {0}; - * \endcode - * - Initialize the structure to the initializer #PSA_AEAD_OPERATION_INIT, - * for example: - * \code - * psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT; - * \endcode - * - Assign the result of the function psa_aead_operation_init() - * to the structure, for example: - * \code - * psa_aead_operation_t operation; - * operation = psa_aead_operation_init(); - * \endcode - * - * This is an implementation-defined \c struct. Applications should not - * make any assumptions about the content of this structure except - * as directed by the documentation of a specific implementation. */ -typedef struct psa_aead_operation_s psa_aead_operation_t; - -/** \def PSA_AEAD_OPERATION_INIT - * - * This macro returns a suitable initializer for an AEAD operation object of - * type #psa_aead_operation_t. - */ -#ifdef __DOXYGEN_ONLY__ -/* This is an example definition for documentation purposes. - * Implementations should define a suitable value in `crypto_struct.h`. - */ -#define PSA_AEAD_OPERATION_INIT {0} -#endif - -/** Return an initial value for an AEAD operation object. - */ -static psa_aead_operation_t psa_aead_operation_init(void); - -/** Set the key for a multipart authenticated encryption operation. - * - * The sequence of operations to encrypt a message with authentication - * is as follows: - * -# Allocate an operation object which will be passed to all the functions - * listed here. - * -# Initialize the operation object with one of the methods described in the - * documentation for #psa_aead_operation_t, e.g. - * #PSA_AEAD_OPERATION_INIT. - * -# Call psa_aead_encrypt_setup() to specify the algorithm and key. - * -# If needed, call psa_aead_set_lengths() to specify the length of the - * inputs to the subsequent calls to psa_aead_update_ad() and - * psa_aead_update(). See the documentation of psa_aead_set_lengths() - * for details. - * -# Call either psa_aead_generate_nonce() or psa_aead_set_nonce() to - * generate or set the nonce. You should use - * psa_aead_generate_nonce() unless the protocol you are implementing - * requires a specific nonce value. - * -# Call psa_aead_update_ad() zero, one or more times, passing a fragment - * of the non-encrypted additional authenticated data each time. - * -# Call psa_aead_update() zero, one or more times, passing a fragment - * of the message to encrypt each time. - * -# Call psa_aead_finish(). - * - * If an error occurs at any step after a call to psa_aead_encrypt_setup(), - * the operation will need to be reset by a call to psa_aead_abort(). The - * application may call psa_aead_abort() at any time after the operation - * has been initialized. - * - * After a successful call to psa_aead_encrypt_setup(), the application must - * eventually terminate the operation. The following events terminate an - * operation: - * - A successful call to psa_aead_finish(). - * - A call to psa_aead_abort(). - * - * \param[in,out] operation The operation object to set up. It must have - * been initialized as per the documentation for - * #psa_aead_operation_t and not yet in use. - * \param handle Handle to the key to use for the operation. - * It must remain valid until the operation - * terminates. - * \param alg The AEAD algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be inactive). - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not an AEAD algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg); - -/** Set the key for a multipart authenticated decryption operation. - * - * The sequence of operations to decrypt a message with authentication - * is as follows: - * -# Allocate an operation object which will be passed to all the functions - * listed here. - * -# Initialize the operation object with one of the methods described in the - * documentation for #psa_aead_operation_t, e.g. - * #PSA_AEAD_OPERATION_INIT. - * -# Call psa_aead_decrypt_setup() to specify the algorithm and key. - * -# If needed, call psa_aead_set_lengths() to specify the length of the - * inputs to the subsequent calls to psa_aead_update_ad() and - * psa_aead_update(). See the documentation of psa_aead_set_lengths() - * for details. - * -# Call psa_aead_set_nonce() with the nonce for the decryption. - * -# Call psa_aead_update_ad() zero, one or more times, passing a fragment - * of the non-encrypted additional authenticated data each time. - * -# Call psa_aead_update() zero, one or more times, passing a fragment - * of the ciphertext to decrypt each time. - * -# Call psa_aead_verify(). - * - * If an error occurs at any step after a call to psa_aead_decrypt_setup(), - * the operation will need to be reset by a call to psa_aead_abort(). The - * application may call psa_aead_abort() at any time after the operation - * has been initialized. - * - * After a successful call to psa_aead_decrypt_setup(), the application must - * eventually terminate the operation. The following events terminate an - * operation: - * - A successful call to psa_aead_verify(). - * - A call to psa_aead_abort(). - * - * \param[in,out] operation The operation object to set up. It must have - * been initialized as per the documentation for - * #psa_aead_operation_t and not yet in use. - * \param handle Handle to the key to use for the operation. - * It must remain valid until the operation - * terminates. - * \param alg The AEAD algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be inactive). - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not an AEAD algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg); - -/** Generate a random nonce for an authenticated encryption operation. - * - * This function generates a random nonce for the authenticated encryption - * operation with an appropriate size for the chosen algorithm, key type - * and key size. - * - * The application must call psa_aead_encrypt_setup() before - * calling this function. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_aead_abort(). - * - * \param[in,out] operation Active AEAD operation. - * \param[out] nonce Buffer where the generated nonce is to be - * written. - * \param nonce_size Size of the \p nonce buffer in bytes. - * \param[out] nonce_length On success, the number of bytes of the - * generated nonce. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be an active aead encrypt - operation, with no nonce set). - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p nonce buffer is too small. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation, - uint8_t *nonce, - size_t nonce_size, - size_t *nonce_length); - -/** Set the nonce for an authenticated encryption or decryption operation. - * - * This function sets the nonce for the authenticated - * encryption or decryption operation. - * - * The application must call psa_aead_encrypt_setup() or - * psa_aead_decrypt_setup() before calling this function. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_aead_abort(). - * - * \note When encrypting, applications should use psa_aead_generate_nonce() - * instead of this function, unless implementing a protocol that requires - * a non-random IV. - * - * \param[in,out] operation Active AEAD operation. - * \param[in] nonce Buffer containing the nonce to use. - * \param nonce_length Size of the nonce in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active, with no nonce - * set). - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The size of \p nonce is not acceptable for the chosen algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation, - const uint8_t *nonce, - size_t nonce_length); - -/** Declare the lengths of the message and additional data for AEAD. - * - * The application must call this function before calling - * psa_aead_update_ad() or psa_aead_update() if the algorithm for - * the operation requires it. If the algorithm does not require it, - * calling this function is optional, but if this function is called - * then the implementation must enforce the lengths. - * - * You may call this function before or after setting the nonce with - * psa_aead_set_nonce() or psa_aead_generate_nonce(). - * - * - For #PSA_ALG_CCM, calling this function is required. - * - For the other AEAD algorithms defined in this specification, calling - * this function is not required. - * - For vendor-defined algorithm, refer to the vendor documentation. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_aead_abort(). - * - * \param[in,out] operation Active AEAD operation. - * \param ad_length Size of the non-encrypted additional - * authenticated data in bytes. - * \param plaintext_length Size of the plaintext to encrypt in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active, and - * psa_aead_update_ad() and psa_aead_update() must not have been - * called yet). - * \retval #PSA_ERROR_INVALID_ARGUMENT - * At least one of the lengths is not acceptable for the chosen - * algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation, - size_t ad_length, - size_t plaintext_length); - -/** Pass additional data to an active AEAD operation. - * - * Additional data is authenticated, but not encrypted. - * - * You may call this function multiple times to pass successive fragments - * of the additional data. You may not call this function after passing - * data to encrypt or decrypt with psa_aead_update(). - * - * Before calling this function, you must: - * 1. Call either psa_aead_encrypt_setup() or psa_aead_decrypt_setup(). - * 2. Set the nonce with psa_aead_generate_nonce() or psa_aead_set_nonce(). - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_aead_abort(). - * - * \warning When decrypting, until psa_aead_verify() has returned #PSA_SUCCESS, - * there is no guarantee that the input is valid. Therefore, until - * you have called psa_aead_verify() and it has returned #PSA_SUCCESS, - * treat the input as untrusted and prepare to undo any action that - * depends on the input if psa_aead_verify() returns an error status. - * - * \param[in,out] operation Active AEAD operation. - * \param[in] input Buffer containing the fragment of - * additional data. - * \param input_length Size of the \p input buffer in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active, have a nonce - * set, have lengths set if required by the algorithm, and - * psa_aead_update() must not have been called yet). - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The total input length overflows the additional data length that - * was previously specified with psa_aead_set_lengths(). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation, - const uint8_t *input, - size_t input_length); - -/** Encrypt or decrypt a message fragment in an active AEAD operation. - * - * Before calling this function, you must: - * 1. Call either psa_aead_encrypt_setup() or psa_aead_decrypt_setup(). - * The choice of setup function determines whether this function - * encrypts or decrypts its input. - * 2. Set the nonce with psa_aead_generate_nonce() or psa_aead_set_nonce(). - * 3. Call psa_aead_update_ad() to pass all the additional data. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_aead_abort(). - * - * \warning When decrypting, until psa_aead_verify() has returned #PSA_SUCCESS, - * there is no guarantee that the input is valid. Therefore, until - * you have called psa_aead_verify() and it has returned #PSA_SUCCESS: - * - Do not use the output in any way other than storing it in a - * confidential location. If you take any action that depends - * on the tentative decrypted data, this action will need to be - * undone if the input turns out not to be valid. Furthermore, - * if an adversary can observe that this action took place - * (for example through timing), they may be able to use this - * fact as an oracle to decrypt any message encrypted with the - * same key. - * - In particular, do not copy the output anywhere but to a - * memory or storage space that you have exclusive access to. - * - * This function does not require the input to be aligned to any - * particular block boundary. If the implementation can only process - * a whole block at a time, it must consume all the input provided, but - * it may delay the end of the corresponding output until a subsequent - * call to psa_aead_update(), psa_aead_finish() or psa_aead_verify() - * provides sufficient input. The amount of data that can be delayed - * in this way is bounded by #PSA_AEAD_UPDATE_OUTPUT_SIZE. - * - * \param[in,out] operation Active AEAD operation. - * \param[in] input Buffer containing the message fragment to - * encrypt or decrypt. - * \param input_length Size of the \p input buffer in bytes. - * \param[out] output Buffer where the output is to be written. - * \param output_size Size of the \p output buffer in bytes. - * This must be at least - * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c alg, - * \p input_length) where \c alg is the - * algorithm that is being calculated. - * \param[out] output_length On success, the number of bytes - * that make up the returned output. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active, have a nonce - * set, and have lengths set if required by the algorithm). - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p output buffer is too small. - * You can determine a sufficient buffer size by calling - * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c alg, \p input_length) - * where \c alg is the algorithm that is being calculated. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The total length of input to psa_aead_update_ad() so far is - * less than the additional data length that was previously - * specified with psa_aead_set_lengths(). - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The total input length overflows the plaintext length that - * was previously specified with psa_aead_set_lengths(). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_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); - -/** Finish encrypting a message in an AEAD operation. - * - * The operation must have been set up with psa_aead_encrypt_setup(). - * - * This function finishes the authentication of the additional data - * formed by concatenating the inputs passed to preceding calls to - * psa_aead_update_ad() with the plaintext formed by concatenating the - * inputs passed to preceding calls to psa_aead_update(). - * - * This function has two output buffers: - * - \p ciphertext contains trailing ciphertext that was buffered from - * preceding calls to psa_aead_update(). - * - \p tag contains the authentication tag. Its length is always - * #PSA_AEAD_TAG_LENGTH(\c alg) where \c alg is the AEAD algorithm - * that the operation performs. - * - * When this function returns successfuly, the operation becomes inactive. - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_aead_abort(). - * - * \param[in,out] operation Active AEAD operation. - * \param[out] ciphertext Buffer where the last part of the ciphertext - * is to be written. - * \param ciphertext_size Size of the \p ciphertext buffer in bytes. - * This must be at least - * #PSA_AEAD_FINISH_OUTPUT_SIZE(\c alg) where - * \c alg is the algorithm that is being - * calculated. - * \param[out] ciphertext_length On success, the number of bytes of - * returned ciphertext. - * \param[out] tag Buffer where the authentication tag is - * to be written. - * \param tag_size Size of the \p tag buffer in bytes. - * This must be at least - * #PSA_AEAD_TAG_LENGTH(\c alg) where \c alg is - * the algorithm that is being calculated. - * \param[out] tag_length On success, the number of bytes - * that make up the returned tag. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be an active encryption - * operation with a nonce set). - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p ciphertext or \p tag buffer is too small. - * You can determine a sufficient buffer size for \p ciphertext by - * calling #PSA_AEAD_FINISH_OUTPUT_SIZE(\c alg) - * where \c alg is the algorithm that is being calculated. - * You can determine a sufficient buffer size for \p tag by - * calling #PSA_AEAD_TAG_LENGTH(\c alg). - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The total length of input to psa_aead_update_ad() so far is - * less than the additional data length that was previously - * specified with psa_aead_set_lengths(). - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The total length of input to psa_aead_update() so far is - * less than the plaintext length that was previously - * specified with psa_aead_set_lengths(). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_finish(psa_aead_operation_t *operation, - uint8_t *ciphertext, - size_t ciphertext_size, - size_t *ciphertext_length, - uint8_t *tag, - size_t tag_size, - size_t *tag_length); - -/** Finish authenticating and decrypting a message in an AEAD operation. - * - * The operation must have been set up with psa_aead_decrypt_setup(). - * - * This function finishes the authenticated decryption of the message - * components: - * - * - The additional data consisting of the concatenation of the inputs - * passed to preceding calls to psa_aead_update_ad(). - * - The ciphertext consisting of the concatenation of the inputs passed to - * preceding calls to psa_aead_update(). - * - The tag passed to this function call. - * - * If the authentication tag is correct, this function outputs any remaining - * plaintext and reports success. If the authentication tag is not correct, - * this function returns #PSA_ERROR_INVALID_SIGNATURE. - * - * When this function returns successfuly, the operation becomes inactive. - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_aead_abort(). - * - * \note Implementations shall make the best effort to ensure that the - * comparison between the actual tag and the expected tag is performed - * in constant time. - * - * \param[in,out] operation Active AEAD operation. - * \param[out] plaintext Buffer where the last part of the plaintext - * is to be written. This is the remaining data - * from previous calls to psa_aead_update() - * that could not be processed until the end - * of the input. - * \param plaintext_size Size of the \p plaintext buffer in bytes. - * This must be at least - * #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c alg) where - * \c alg is the algorithm that is being - * calculated. - * \param[out] plaintext_length On success, the number of bytes of - * returned plaintext. - * \param[in] tag Buffer containing the authentication tag. - * \param tag_length Size of the \p tag buffer in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_SIGNATURE - * The calculations were successful, but the authentication tag is - * not correct. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be an active decryption - * operation with a nonce set). - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p plaintext buffer is too small. - * You can determine a sufficient buffer size for \p plaintext by - * calling #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c alg) - * where \c alg is the algorithm that is being calculated. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The total length of input to psa_aead_update_ad() so far is - * less than the additional data length that was previously - * specified with psa_aead_set_lengths(). - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The total length of input to psa_aead_update() so far is - * less than the plaintext length that was previously - * specified with psa_aead_set_lengths(). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_verify(psa_aead_operation_t *operation, - uint8_t *plaintext, - size_t plaintext_size, - size_t *plaintext_length, - const uint8_t *tag, - size_t tag_length); - -/** Abort an AEAD operation. - * - * Aborting an operation frees all associated resources except for the - * \p operation structure itself. Once aborted, the operation object - * can be reused for another operation by calling - * psa_aead_encrypt_setup() or psa_aead_decrypt_setup() again. - * - * You may call this function any time after the operation object has - * been initialized as described in #psa_aead_operation_t. - * - * In particular, calling psa_aead_abort() after the operation has been - * terminated by a call to psa_aead_abort(), psa_aead_finish() or - * psa_aead_verify() is safe and has no effect. - * - * \param[in,out] operation Initialized AEAD operation. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_abort(psa_aead_operation_t *operation); - -/**@}*/ - -/** \defgroup asymmetric Asymmetric cryptography - * @{ - */ - -/** - * \brief Sign a hash or short message with a private key. - * - * Note that to perform a hash-and-sign signature algorithm, you must - * first calculate the hash by calling psa_hash_setup(), psa_hash_update() - * and psa_hash_finish(). Then pass the resulting hash as the \p hash - * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) - * to determine the hash algorithm to use. - * - * \param handle Handle to the key to use for the operation. - * It must be an asymmetric key pair. - * \param alg A signature algorithm that is compatible with - * the type of \p handle. - * \param[in] hash The hash or message to sign. - * \param hash_length Size of the \p hash buffer in bytes. - * \param[out] signature Buffer where the signature is to be written. - * \param signature_size Size of the \p signature buffer in bytes. - * \param[out] signature_length On success, the number of bytes - * that make up the returned signature value. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p signature buffer is too small. You can - * determine a sufficient buffer size by calling - * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) - * where \c key_type and \c key_bits are the type and bit-size - * respectively of \p handle. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_sign_hash(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *hash, - size_t hash_length, - uint8_t *signature, - size_t signature_size, - size_t *signature_length); - -/** - * \brief Verify the signature a hash or short message using a public key. - * - * Note that to perform a hash-and-sign signature algorithm, you must - * first calculate the hash by calling psa_hash_setup(), psa_hash_update() - * and psa_hash_finish(). Then pass the resulting hash as the \p hash - * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) - * to determine the hash algorithm to use. - * - * \param handle Handle to the key to use for the operation. - * It must be a public key or an asymmetric key pair. - * \param alg A signature algorithm that is compatible with - * the type of \p handle. - * \param[in] hash The hash or message whose signature is to be - * verified. - * \param hash_length Size of the \p hash buffer in bytes. - * \param[in] signature Buffer containing the signature to verify. - * \param signature_length Size of the \p signature buffer in bytes. - * - * \retval #PSA_SUCCESS - * The signature is valid. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_SIGNATURE - * The calculation was perfomed successfully, but the passed - * signature is not a valid signature. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_verify_hash(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *hash, - size_t hash_length, - const uint8_t *signature, - size_t signature_length); - -/** - * \brief Encrypt a short message with a public key. - * - * \param handle Handle to the key to use for the operation. - * It must be a public key or an asymmetric - * key pair. - * \param alg An asymmetric encryption algorithm that is - * compatible with the type of \p handle. - * \param[in] input The message to encrypt. - * \param input_length Size of the \p input buffer in bytes. - * \param[in] salt A salt or label, if supported by the - * encryption algorithm. - * If the algorithm does not support a - * salt, pass \c NULL. - * If the algorithm supports an optional - * salt and you do not want to pass a salt, - * pass \c NULL. - * - * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is - * supported. - * \param salt_length Size of the \p salt buffer in bytes. - * If \p salt is \c NULL, pass 0. - * \param[out] output Buffer where the encrypted message is to - * be written. - * \param output_size Size of the \p output buffer in bytes. - * \param[out] output_length On success, the number of bytes - * that make up the returned output. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p output buffer is too small. You can - * determine a sufficient buffer size by calling - * #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) - * where \c key_type and \c key_bits are the type and bit-size - * respectively of \p handle. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_asymmetric_encrypt(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - const uint8_t *salt, - size_t salt_length, - uint8_t *output, - size_t output_size, - size_t *output_length); - -/** - * \brief Decrypt a short message with a private key. - * - * \param handle Handle to the key to use for the operation. - * It must be an asymmetric key pair. - * \param alg An asymmetric encryption algorithm that is - * compatible with the type of \p handle. - * \param[in] input The message to decrypt. - * \param input_length Size of the \p input buffer in bytes. - * \param[in] salt A salt or label, if supported by the - * encryption algorithm. - * If the algorithm does not support a - * salt, pass \c NULL. - * If the algorithm supports an optional - * salt and you do not want to pass a salt, - * pass \c NULL. - * - * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is - * supported. - * \param salt_length Size of the \p salt buffer in bytes. - * If \p salt is \c NULL, pass 0. - * \param[out] output Buffer where the decrypted message is to - * be written. - * \param output_size Size of the \c output buffer in bytes. - * \param[out] output_length On success, the number of bytes - * that make up the returned output. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p output buffer is too small. You can - * determine a sufficient buffer size by calling - * #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) - * where \c key_type and \c key_bits are the type and bit-size - * respectively of \p handle. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY - * \retval #PSA_ERROR_INVALID_PADDING - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_asymmetric_decrypt(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - const uint8_t *salt, - size_t salt_length, - uint8_t *output, - size_t output_size, - size_t *output_length); - -/**@}*/ - -/** \defgroup key_derivation Key derivation and pseudorandom generation - * @{ - */ - -/** The type of the state data structure for key derivation operations. - * - * Before calling any function on a key derivation operation object, the - * application must initialize it by any of the following means: - * - Set the structure to all-bits-zero, for example: - * \code - * psa_key_derivation_operation_t operation; - * memset(&operation, 0, sizeof(operation)); - * \endcode - * - Initialize the structure to logical zero values, for example: - * \code - * psa_key_derivation_operation_t operation = {0}; - * \endcode - * - Initialize the structure to the initializer #PSA_KEY_DERIVATION_OPERATION_INIT, - * for example: - * \code - * psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT; - * \endcode - * - Assign the result of the function psa_key_derivation_operation_init() - * to the structure, for example: - * \code - * psa_key_derivation_operation_t operation; - * operation = psa_key_derivation_operation_init(); - * \endcode - * - * This is an implementation-defined \c struct. Applications should not - * make any assumptions about the content of this structure except - * as directed by the documentation of a specific implementation. - */ -typedef struct psa_key_derivation_s psa_key_derivation_operation_t; - -/** \def PSA_KEY_DERIVATION_OPERATION_INIT - * - * This macro returns a suitable initializer for a key derivation operation - * object of type #psa_key_derivation_operation_t. - */ -#ifdef __DOXYGEN_ONLY__ -/* This is an example definition for documentation purposes. - * Implementations should define a suitable value in `crypto_struct.h`. - */ -#define PSA_KEY_DERIVATION_OPERATION_INIT {0} -#endif - -/** Return an initial value for a key derivation operation object. - */ -static psa_key_derivation_operation_t psa_key_derivation_operation_init(void); - -/** Set up a key derivation operation. - * - * A key derivation algorithm takes some inputs and uses them to generate - * a byte stream in a deterministic way. - * This byte stream can be used to produce keys and other - * cryptographic material. - * - * To derive a key: - * -# Start with an initialized object of type #psa_key_derivation_operation_t. - * -# Call psa_key_derivation_setup() to select the algorithm. - * -# Provide the inputs for the key derivation by calling - * psa_key_derivation_input_bytes() or psa_key_derivation_input_key() - * as appropriate. Which inputs are needed, in what order, and whether - * they may be keys and if so of what type depends on the algorithm. - * -# Optionally set the operation's maximum capacity with - * psa_key_derivation_set_capacity(). You may do this before, in the middle - * of or after providing inputs. For some algorithms, this step is mandatory - * because the output depends on the maximum capacity. - * -# To derive a key, call psa_key_derivation_output_key(). - * To derive a byte string for a different purpose, call - * psa_key_derivation_output_bytes(). - * Successive calls to these functions use successive output bytes - * calculated by the key derivation algorithm. - * -# Clean up the key derivation operation object with - * psa_key_derivation_abort(). - * - * If this function returns an error, the key derivation operation object is - * not changed. - * - * If an error occurs at any step after a call to psa_key_derivation_setup(), - * the operation will need to be reset by a call to psa_key_derivation_abort(). - * - * Implementations must reject an attempt to derive a key of size 0. - * - * \param[in,out] operation The key derivation operation object - * to set up. It must - * have been initialized but not set up yet. - * \param alg The key derivation algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_KEY_DERIVATION(\p alg) is true). - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \c alg is not a key derivation algorithm. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \c alg is not supported or is not a key derivation algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be inactive). - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_key_derivation_setup( - psa_key_derivation_operation_t *operation, - psa_algorithm_t alg); - -/** Retrieve the current capacity of a key derivation operation. - * - * The capacity of a key derivation is the maximum number of bytes that it can - * return. When you get *N* bytes of output from a key derivation operation, - * this reduces its capacity by *N*. - * - * \param[in] operation The operation to query. - * \param[out] capacity On success, the capacity of the operation. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active). - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_key_derivation_get_capacity( - const psa_key_derivation_operation_t *operation, - size_t *capacity); - -/** Set the maximum capacity of a key derivation operation. - * - * The capacity of a key derivation operation is the maximum number of bytes - * that the key derivation operation can return from this point onwards. - * - * \param[in,out] operation The key derivation operation object to modify. - * \param capacity The new capacity of the operation. - * It must be less or equal to the operation's - * current capacity. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p capacity is larger than the operation's current capacity. - * In this case, the operation object remains valid and its capacity - * remains unchanged. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active). - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_key_derivation_set_capacity( - psa_key_derivation_operation_t *operation, - size_t capacity); - -/** Use the maximum possible capacity for a key derivation operation. - * - * Use this value as the capacity argument when setting up a key derivation - * to indicate that the operation should have the maximum possible capacity. - * The value of the maximum possible capacity depends on the key derivation - * algorithm. - */ -#define PSA_KEY_DERIVATION_UNLIMITED_CAPACITY ((size_t)(-1)) - -/** Provide an input for key derivation or key agreement. - * - * Which inputs are required and in what order depends on the algorithm. - * Refer to the documentation of each key derivation or key agreement - * algorithm for information. - * - * This function passes direct inputs, which is usually correct for - * non-secret inputs. To pass a secret input, which should be in a key - * object, call psa_key_derivation_input_key() instead of this function. - * Refer to the documentation of individual step types - * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t) - * for more information. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_key_derivation_abort(). - * - * \param[in,out] operation The key derivation operation object to use. - * It must have been set up with - * psa_key_derivation_setup() and must not - * have produced any output yet. - * \param step Which step the input data is for. - * \param[in] data Input data to use. - * \param data_length Size of the \p data buffer in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \c step is not compatible with the operation's algorithm. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \c step does not allow direct inputs. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid for this input \p step. - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_key_derivation_input_bytes( - psa_key_derivation_operation_t *operation, - psa_key_derivation_step_t step, - const uint8_t *data, - size_t data_length); - -/** Provide an input for key derivation in the form of a key. - * - * Which inputs are required and in what order depends on the algorithm. - * Refer to the documentation of each key derivation or key agreement - * algorithm for information. - * - * This function obtains input from a key object, which is usually correct for - * secret inputs or for non-secret personalization strings kept in the key - * store. To pass a non-secret parameter which is not in the key store, - * call psa_key_derivation_input_bytes() instead of this function. - * Refer to the documentation of individual step types - * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t) - * for more information. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_key_derivation_abort(). - * - * \param[in,out] operation The key derivation operation object to use. - * It must have been set up with - * psa_key_derivation_setup() and must not - * have produced any output yet. - * \param step Which step the input data is for. - * \param handle Handle to the key. It must have an - * appropriate type for \p step and must - * allow the usage #PSA_KEY_USAGE_DERIVE. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \c step is not compatible with the operation's algorithm. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \c step does not allow key inputs of the given type - * or does not allow key inputs at all. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid for this input \p step. - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_key_derivation_input_key( - psa_key_derivation_operation_t *operation, - psa_key_derivation_step_t step, - psa_key_handle_t handle); - -/** Perform a key agreement and use the shared secret as input to a key - * derivation. - * - * A key agreement algorithm takes two inputs: a private key \p private_key - * a public key \p peer_key. - * The result of this function is passed as input to a key derivation. - * The output of this key derivation can be extracted by reading from the - * resulting operation to produce keys and other cryptographic material. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_key_derivation_abort(). - * - * \param[in,out] operation The key derivation operation object to use. - * It must have been set up with - * psa_key_derivation_setup() with a - * key agreement and derivation algorithm - * \c alg (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_KEY_AGREEMENT(\c alg) is true - * and #PSA_ALG_IS_RAW_KEY_AGREEMENT(\c alg) - * is false). - * The operation must be ready for an - * input of the type given by \p step. - * \param step Which step the input data is for. - * \param private_key Handle to the private key to use. - * \param[in] peer_key Public key of the peer. The peer key must be in the - * same format that psa_import_key() accepts for the - * public key type corresponding to the type of - * private_key. That is, this function performs the - * equivalent of - * #psa_import_key(..., - * `peer_key`, `peer_key_length`) where - * with key attributes indicating the public key - * type corresponding to the type of `private_key`. - * For example, for EC keys, this means that peer_key - * is interpreted as a point on the curve that the - * private key is on. The standard formats for public - * keys are documented in the documentation of - * psa_export_public_key(). - * \param peer_key_length Size of \p peer_key in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid for this key agreement \p step. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \c private_key is not compatible with \c alg, - * or \p peer_key is not valid for \c alg or not compatible with - * \c private_key. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \c alg is not supported or is not a key derivation algorithm. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \c step does not allow an input resulting from a key agreement. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_key_derivation_key_agreement( - psa_key_derivation_operation_t *operation, - psa_key_derivation_step_t step, - psa_key_handle_t private_key, - const uint8_t *peer_key, - size_t peer_key_length); - -/** Read some data from a key derivation operation. - * - * This function calculates output bytes from a key derivation algorithm and - * return those bytes. - * If you view the key derivation's output as a stream of bytes, this - * function destructively reads the requested number of bytes from the - * stream. - * The operation's capacity decreases by the number of bytes read. - * - * If this function returns an error status other than - * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error - * state and must be aborted by calling psa_key_derivation_abort(). - * - * \param[in,out] operation The key derivation operation object to read from. - * \param[out] output Buffer where the output will be written. - * \param output_length Number of bytes to output. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INSUFFICIENT_DATA - * The operation's capacity was less than - * \p output_length bytes. Note that in this case, - * no output is written to the output buffer. - * The operation's capacity is set to 0, thus - * subsequent calls to this function will not - * succeed, even with a smaller output buffer. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active and completed - * all required input steps). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_key_derivation_output_bytes( - psa_key_derivation_operation_t *operation, - uint8_t *output, - size_t output_length); - -/** Derive a key from an ongoing key derivation operation. - * - * This function calculates output bytes from a key derivation algorithm - * and uses those bytes to generate a key deterministically. - * The key's location, usage policy, type and size are taken from - * \p attributes. - * - * If you view the key derivation's output as a stream of bytes, this - * function destructively reads as many bytes as required from the - * stream. - * The operation's capacity decreases by the number of bytes read. - * - * If this function returns an error status other than - * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error - * state and must be aborted by calling psa_key_derivation_abort(). - * - * How much output is produced and consumed from the operation, and how - * the key is derived, depends on the key type: - * - * - For key types for which the key is an arbitrary sequence of bytes - * of a given size, this function is functionally equivalent to - * calling #psa_key_derivation_output_bytes - * and passing the resulting output to #psa_import_key. - * However, this function has a security benefit: - * if the implementation provides an isolation boundary then - * the key material is not exposed outside the isolation boundary. - * As a consequence, for these key types, this function always consumes - * exactly (\p bits / 8) bytes from the operation. - * The following key types defined in this specification follow this scheme: - * - * - #PSA_KEY_TYPE_AES; - * - #PSA_KEY_TYPE_ARC4; - * - #PSA_KEY_TYPE_CAMELLIA; - * - #PSA_KEY_TYPE_DERIVE; - * - #PSA_KEY_TYPE_HMAC. - * - * - For ECC keys on a Montgomery elliptic curve - * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a - * Montgomery curve), this function always draws a byte string whose - * length is determined by the curve, and sets the mandatory bits - * accordingly. That is: - * - * - #PSA_ECC_CURVE_CURVE25519: draw a 32-byte string - * and process it as specified in RFC 7748 §5. - * - #PSA_ECC_CURVE_CURVE448: draw a 56-byte string - * and process it as specified in RFC 7748 §5. - * - * - For key types for which the key is represented by a single sequence of - * \p bits bits with constraints as to which bit sequences are acceptable, - * this function draws a byte string of length (\p bits / 8) bytes rounded - * up to the nearest whole number of bytes. If the resulting byte string - * is acceptable, it becomes the key, otherwise the drawn bytes are discarded. - * This process is repeated until an acceptable byte string is drawn. - * The byte string drawn from the operation is interpreted as specified - * for the output produced by psa_export_key(). - * The following key types defined in this specification follow this scheme: - * - * - #PSA_KEY_TYPE_DES. - * Force-set the parity bits, but discard forbidden weak keys. - * For 2-key and 3-key triple-DES, the three keys are generated - * successively (for example, for 3-key triple-DES, - * if the first 8 bytes specify a weak key and the next 8 bytes do not, - * discard the first 8 bytes, use the next 8 bytes as the first key, - * and continue reading output from the operation to derive the other - * two keys). - * - Finite-field Diffie-Hellman keys (#PSA_KEY_TYPE_DH_KEY_PAIR(\c group) - * where \c group designates any Diffie-Hellman group) and - * ECC keys on a Weierstrass elliptic curve - * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a - * Weierstrass curve). - * For these key types, interpret the byte string as integer - * in big-endian order. Discard it if it is not in the range - * [0, *N* - 2] where *N* is the boundary of the private key domain - * (the prime *p* for Diffie-Hellman, the subprime *q* for DSA, - * or the order of the curve's base point for ECC). - * Add 1 to the resulting integer and use this as the private key *x*. - * This method allows compliance to NIST standards, specifically - * the methods titled "key-pair generation by testing candidates" - * in NIST SP 800-56A §5.6.1.1.4 for Diffie-Hellman, - * in FIPS 186-4 §B.1.2 for DSA, and - * in NIST SP 800-56A §5.6.1.2.2 or - * FIPS 186-4 §B.4.2 for elliptic curve keys. - * - * - For other key types, including #PSA_KEY_TYPE_RSA_KEY_PAIR, - * the way in which the operation output is consumed is - * implementation-defined. - * - * In all cases, the data that is read is discarded from the operation. - * The operation's capacity is decreased by the number of bytes read. - * - * For algorithms that take an input step #PSA_KEY_DERIVATION_INPUT_SECRET, - * the input to that step must be provided with psa_key_derivation_input_key(). - * Future versions of this specification may include additional restrictions - * on the derived key based on the attributes and strength of the secret key. - * - * \param[in] attributes The attributes for the new key. - * \param[in,out] operation The key derivation operation object to read from. - * \param[out] handle On success, a handle to the newly created key. - * \c 0 on failure. - * - * \retval #PSA_SUCCESS - * Success. - * If the key is persistent, the key material and the key's metadata - * have been saved to persistent storage. - * \retval #PSA_ERROR_ALREADY_EXISTS - * This is an attempt to create a persistent key, and there is - * already a persistent key with the given identifier. - * \retval #PSA_ERROR_INSUFFICIENT_DATA - * There was not enough data to create the desired key. - * Note that in this case, no output is written to the output buffer. - * The operation's capacity is set to 0, thus subsequent calls to - * this function will not succeed, even with a smaller output buffer. - * \retval #PSA_ERROR_NOT_SUPPORTED - * The key type or key size is not supported, either by the - * implementation in general or in this particular location. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The provided key attributes are not valid for the operation. - * \retval #PSA_ERROR_NOT_PERMITTED - * The #PSA_KEY_DERIVATION_INPUT_SECRET input was not provided through - * a key. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active and completed - * all required input steps). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_INSUFFICIENT_STORAGE - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_key_derivation_output_key( - const psa_key_attributes_t *attributes, - psa_key_derivation_operation_t *operation, - psa_key_handle_t *handle); - -/** Abort a key derivation operation. - * - * Aborting an operation frees all associated resources except for the \c - * operation structure itself. Once aborted, the operation object can be reused - * for another operation by calling psa_key_derivation_setup() again. - * - * This function may be called at any time after the operation - * object has been initialized as described in #psa_key_derivation_operation_t. - * - * In particular, it is valid to call psa_key_derivation_abort() twice, or to - * call psa_key_derivation_abort() on an operation that has not been set up. - * - * \param[in,out] operation The operation to abort. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_key_derivation_abort( - psa_key_derivation_operation_t *operation); - -/** Perform a key agreement and return the raw shared secret. - * - * \warning The raw result of a key agreement algorithm such as finite-field - * Diffie-Hellman or elliptic curve Diffie-Hellman has biases and should - * not be used directly as key material. It should instead be passed as - * input to a key derivation algorithm. To chain a key agreement with - * a key derivation, use psa_key_derivation_key_agreement() and other - * functions from the key derivation interface. - * - * \param alg The key agreement algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_RAW_KEY_AGREEMENT(\p alg) - * is true). - * \param private_key Handle to the private key to use. - * \param[in] peer_key Public key of the peer. It must be - * in the same format that psa_import_key() - * accepts. The standard formats for public - * keys are documented in the documentation - * of psa_export_public_key(). - * \param peer_key_length Size of \p peer_key in bytes. - * \param[out] output Buffer where the decrypted message is to - * be written. - * \param output_size Size of the \c output buffer in bytes. - * \param[out] output_length On success, the number of bytes - * that make up the returned output. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p alg is not a key agreement algorithm - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p private_key is not compatible with \p alg, - * or \p peer_key is not valid for \p alg or not compatible with - * \p private_key. - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * \p output_size is too small - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not a supported key agreement algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, - psa_key_handle_t private_key, - const uint8_t *peer_key, - size_t peer_key_length, - uint8_t *output, - size_t output_size, - size_t *output_length); - -/**@}*/ - -/** \defgroup random Random generation - * @{ - */ - -/** - * \brief Generate random bytes. - * - * \warning This function **can** fail! Callers MUST check the return status - * and MUST NOT use the content of the output buffer if the return - * status is not #PSA_SUCCESS. - * - * \note To generate a key, use psa_generate_key() instead. - * - * \param[out] output Output buffer for the generated data. - * \param output_size Number of bytes to generate and output. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_generate_random(uint8_t *output, - size_t output_size); - -/** - * \brief Generate a key or key pair. - * - * The key is generated randomly. - * Its location, usage policy, type and size are taken from \p attributes. - * - * Implementations must reject an attempt to generate a key of size 0. - * - * The following type-specific considerations apply: - * - For RSA keys (#PSA_KEY_TYPE_RSA_KEY_PAIR), - * the public exponent is 65537. - * The modulus is a product of two probabilistic primes - * between 2^{n-1} and 2^n where n is the bit size specified in the - * attributes. - * - * \param[in] attributes The attributes for the new key. - * \param[out] handle On success, a handle to the newly created key. - * \c 0 on failure. - * - * \retval #PSA_SUCCESS - * Success. - * If the key is persistent, the key material and the key's metadata - * have been saved to persistent storage. - * \retval #PSA_ERROR_ALREADY_EXISTS - * This is an attempt to create a persistent key, and there is - * already a persistent key with the given identifier. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_INSUFFICIENT_STORAGE - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, - psa_key_handle_t *handle); - -/**@}*/ - -#ifdef __cplusplus -} -#endif - -/* The file "crypto_sizes.h" contains definitions for size calculation - * macros whose definitions are implementation-specific. */ -#include "psa/crypto_sizes.h" - -/* The file "crypto_struct.h" contains definitions for - * implementation-specific structs that are declared above. */ -#include "psa/crypto_struct.h" - -/* The file "crypto_extra.h" contains vendor-specific definitions. This - * can include vendor-defined algorithms, extra functions, etc. */ -#include "psa/crypto_extra.h" - -#endif /* PSA_CRYPTO_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_compat.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_compat.h deleted file mode 100644 index 518008b..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_compat.h +++ /dev/null @@ -1,111 +0,0 @@ -/** - * \file psa/crypto_compat.h - * - * \brief PSA cryptography module: Backward compatibility aliases - * - * This header declares alternative names for macro and functions. - * New application code should not use these names. - * These names may be removed in a future version of Mbed Crypto. - * - * \note This file may not be included directly. Applications must - * include psa/crypto.h. - */ -/* - * Copyright (C) 2019-2020, ARM Limited, 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. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#ifndef PSA_CRYPTO_COMPAT_H -#define PSA_CRYPTO_COMPAT_H - -#ifdef __cplusplus -extern "C" { -#endif - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) - -/* - * Mechanism for declaring deprecated values - */ -#if defined(MBEDTLS_DEPRECATED_WARNING) && !defined(MBEDTLS_PSA_DEPRECATED) -#define MBEDTLS_PSA_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_PSA_DEPRECATED -#endif - -typedef MBEDTLS_PSA_DEPRECATED size_t mbedtls_deprecated_size_t; -typedef MBEDTLS_PSA_DEPRECATED psa_status_t mbedtls_deprecated_psa_status_t; -typedef MBEDTLS_PSA_DEPRECATED psa_key_usage_t mbedtls_deprecated_psa_key_usage_t; - -#define MBEDTLS_DEPRECATED_CONSTANT( type, value ) \ - ( (mbedtls_deprecated_##type) ( value ) ) - -/* - * Deprecated PSA Crypto error code definitions (PSA Crypto API <= 1.0 beta2) - */ -#define PSA_ERROR_UNKNOWN_ERROR \ - MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_GENERIC_ERROR ) -#define PSA_ERROR_OCCUPIED_SLOT \ - MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_ALREADY_EXISTS ) -#define PSA_ERROR_EMPTY_SLOT \ - MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_DOES_NOT_EXIST ) -#define PSA_ERROR_INSUFFICIENT_CAPACITY \ - MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_INSUFFICIENT_DATA ) -#define PSA_ERROR_TAMPERING_DETECTED \ - MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_CORRUPTION_DETECTED ) - -/* - * Deprecated PSA Crypto numerical encodings (PSA Crypto API <= 1.0 beta3) - */ -#define PSA_KEY_USAGE_SIGN \ - MBEDTLS_DEPRECATED_CONSTANT( psa_key_usage_t, PSA_KEY_USAGE_SIGN_HASH ) -#define PSA_KEY_USAGE_VERIFY \ - MBEDTLS_DEPRECATED_CONSTANT( psa_key_usage_t, PSA_KEY_USAGE_VERIFY_HASH ) - -/* - * Deprecated PSA Crypto size calculation macros (PSA Crypto API <= 1.0 beta3) - */ -#define PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE \ - MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_SIGNATURE_MAX_SIZE ) -#define PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE( key_type, key_bits, alg ) \ - MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_SIGN_OUTPUT_SIZE( key_type, key_bits, alg ) ) - -/* - * Deprecated PSA Crypto function names (PSA Crypto API <= 1.0 beta3) - */ -MBEDTLS_PSA_DEPRECATED psa_status_t psa_asymmetric_sign( psa_key_handle_t key, - psa_algorithm_t alg, - const uint8_t *hash, - size_t hash_length, - uint8_t *signature, - size_t signature_size, - size_t *signature_length ); - -MBEDTLS_PSA_DEPRECATED psa_status_t psa_asymmetric_verify( psa_key_handle_t key, - psa_algorithm_t alg, - const uint8_t *hash, - size_t hash_length, - const uint8_t *signature, - size_t signature_length ); - -#endif /* MBEDTLS_DEPRECATED_REMOVED */ - -#ifdef __cplusplus -} -#endif - -#endif /* PSA_CRYPTO_COMPAT_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_extra.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_extra.h deleted file mode 100644 index 33c9c05..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_extra.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2018-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ -/** - * \file psa/crypto_extra.h - * - * \brief PSA cryptography module: vendor extensions - * - * \note This file may not be included directly. Applications must - * include psa/crypto.h. - * - * This file is reserved for vendor-specific definitions. - */ - -#ifndef PSA_CRYPTO_EXTRA_H -#define PSA_CRYPTO_EXTRA_H - -#include "psa/crypto_compat.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** \brief Declare the enrollment algorithm for a key. - * - * An operation on a key may indifferently use the algorithm set with - * psa_set_key_algorithm() or with this function. - * - * \param[out] attributes The attribute structure to write to. - * \param alg2 A second algorithm that the key may be used - * for, in addition to the algorithm set with - * psa_set_key_algorithm(). - * - * \warning Setting an enrollment algorithm is not recommended, because - * using the same key with different algorithms can allow some - * attacks based on arithmetic relations between different - * computations made with the same key, or can escalate harmless - * side channels into exploitable ones. Use this function only - * if it is necessary to support a protocol for which it has been - * verified that the usage of the key with multiple algorithms - * is safe. - */ -static inline void psa_set_key_enrollment_algorithm( - psa_key_attributes_t *attributes, - psa_algorithm_t alg2) -{ - attributes->core.policy.alg2 = alg2; -} - -#ifdef __cplusplus -} -#endif - -#endif /* PSA_CRYPTO_EXTRA_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_platform.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_platform.h deleted file mode 100644 index c3120e4..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_platform.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2018-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ -/** - * \file psa/crypto_platform.h - * - * \brief PSA cryptography module: Mbed TLS platform definitions - * - * \note This file may not be included directly. Applications must - * include psa/crypto.h. - * - * This file contains platform-dependent type definitions. - * - * In implementations with isolation between the application and the - * cryptography module, implementers should take care to ensure that - * the definitions that are exposed to applications match what the - * module implements. - */ - -#ifndef PSA_CRYPTO_PLATFORM_H -#define PSA_CRYPTO_PLATFORM_H - -/* PSA requires several types which C99 provides in stdint.h. */ -#include - -/* Integral type representing a key handle. */ -typedef uint16_t psa_key_handle_t; - -/* This implementation distinguishes *application key identifiers*, which - * are the key identifiers specified by the application, from - * *key file identifiers*, which are the key identifiers that the library - * sees internally. The two types can be different if there is a remote - * call layer between the application and the library which supports - * multiple client applications that do not have access to each others' - * keys. The point of having different types is that the key file - * identifier may encode not only the key identifier specified by the - * application, but also the the identity of the application. - * - * Note that this is an internal concept of the library and the remote - * call layer. The application itself never sees anything other than - * #psa_app_key_id_t with its standard definition. - */ - -/* The application key identifier is always what the application sees as - * #psa_key_id_t. */ -typedef uint32_t psa_app_key_id_t; - -#endif /* PSA_CRYPTO_PLATFORM_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_sizes.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_sizes.h deleted file mode 100644 index 4f67501..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_sizes.h +++ /dev/null @@ -1,650 +0,0 @@ -/* - * Copyright (c) 2018-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ -/** - * \file psa/crypto_sizes.h - * - * \brief PSA cryptography module: Mbed TLS buffer size macros - * - * \note This file may not be included directly. Applications must - * include psa/crypto.h. - * - * This file contains the definitions of macros that are useful to - * compute buffer sizes. The signatures and semantics of these macros - * are standardized, but the definitions are not, because they depend on - * the available algorithms and, in some cases, on permitted tolerances - * on buffer sizes. - * - * In implementations with isolation between the application and the - * cryptography module, implementers should take care to ensure that - * the definitions that are exposed to applications match what the - * module implements. - * - * Macros that compute sizes whose values do not depend on the - * implementation are in crypto.h. - */ - -#ifndef PSA_CRYPTO_SIZES_H -#define PSA_CRYPTO_SIZES_H - -#define PSA_BITS_TO_BYTES(bits) (((bits) + 7) / 8) -#define PSA_BYTES_TO_BITS(bytes) ((bytes) * 8) - -#define PSA_ROUND_UP_TO_MULTIPLE(block_size, length) \ - (((length) + (block_size) - 1) / (block_size) * (block_size)) - -/** The size of the output of psa_hash_finish(), in bytes. - * - * This is also the hash size that psa_hash_verify() expects. - * - * \param alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p alg) is true), or an HMAC algorithm - * (#PSA_ALG_HMAC(\c hash_alg) where \c hash_alg is a - * hash algorithm). - * - * \return The hash size for the specified hash algorithm. - * If the hash algorithm is not recognized, return 0. - * An implementation may return either 0 or the correct size - * for a hash algorithm that it recognizes, but does not support. - */ -#define PSA_HASH_SIZE(alg) \ - ( \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD2 ? 16 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD4 ? 16 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 16 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 20 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 20 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_224 ? 28 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_256 ? 32 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_384 ? 48 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512 ? 64 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 28 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 32 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 28 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 32 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 48 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 64 : \ - 0) - -/** \def PSA_HASH_MAX_SIZE - * - * Maximum size of a hash. - * - * This macro must expand to a compile-time constant integer. This value - * should be the maximum size of a hash supported by the implementation, - * in bytes, and must be no smaller than this maximum. - */ -/* Note: for HMAC-SHA-3, the block size is 144 bytes for HMAC-SHA3-226, - * 136 bytes for HMAC-SHA3-256, 104 bytes for SHA3-384, 72 bytes for - * HMAC-SHA3-512. */ -#define PSA_HASH_MAX_SIZE 64 -#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 128 - -/** \def PSA_MAC_MAX_SIZE - * - * Maximum size of a MAC. - * - * This macro must expand to a compile-time constant integer. This value - * should be the maximum size of a MAC supported by the implementation, - * in bytes, and must be no smaller than this maximum. - */ -/* All non-HMAC MACs have a maximum size that's smaller than the - * minimum possible value of PSA_HASH_MAX_SIZE in this implementation. */ -/* Note that the encoding of truncated MAC algorithms limits this value - * to 64 bytes. - */ -#define PSA_MAC_MAX_SIZE PSA_HASH_MAX_SIZE - -/** The tag size for an AEAD algorithm, in bytes. - * - * \param alg An AEAD algorithm - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * - * \return The tag size for the specified algorithm. - * If the AEAD algorithm does not have an identified - * tag that can be distinguished from the rest of - * the ciphertext, return 0. - * If the AEAD algorithm is not recognized, return 0. - * An implementation may return either 0 or a - * correct size for an AEAD algorithm that it - * recognizes, but does not support. - */ -#define PSA_AEAD_TAG_LENGTH(alg) \ - (PSA_ALG_IS_AEAD(alg) ? \ - (((alg) & PSA_ALG_AEAD_TAG_LENGTH_MASK) >> PSA_AEAD_TAG_LENGTH_OFFSET) : \ - 0) - -/* The maximum size of an RSA key on this implementation, in bits. - * This is a vendor-specific macro. - * - * Mbed TLS does not set a hard limit on the size of RSA keys: any key - * whose parameters fit in a bignum is accepted. However large keys can - * induce a large memory usage and long computation times. Unlike other - * auxiliary macros in this file and in crypto.h, which reflect how the - * library is configured, this macro defines how the library is - * configured. This implementation refuses to import or generate an - * RSA key whose size is larger than the value defined here. - * - * Note that an implementation may set different size limits for different - * operations, and does not need to accept all key sizes up to the limit. */ -#define PSA_VENDOR_RSA_MAX_KEY_BITS 4096 - -/* The maximum size of an ECC key on this implementation, in bits. - * This is a vendor-specific macro. */ -#define PSA_VENDOR_ECC_MAX_CURVE_BITS 521 - -/** Bit size associated with an elliptic curve. - * - * \param curve An elliptic curve (value of type #psa_ecc_curve_t). - * - * \return The size associated with \p curve, in bits. - * This may be 0 if the implementation does not support - * the specified curve. - */ -#define PSA_ECC_CURVE_BITS(curve) \ - ((curve) == PSA_ECC_CURVE_SECT163K1 ? 163 : \ - (curve) == PSA_ECC_CURVE_SECT163R1 ? 163 : \ - (curve) == PSA_ECC_CURVE_SECT163R2 ? 163 : \ - (curve) == PSA_ECC_CURVE_SECT193R1 ? 193 : \ - (curve) == PSA_ECC_CURVE_SECT193R2 ? 193 : \ - (curve) == PSA_ECC_CURVE_SECT233K1 ? 233 : \ - (curve) == PSA_ECC_CURVE_SECT233R1 ? 233 : \ - (curve) == PSA_ECC_CURVE_SECT239K1 ? 239 : \ - (curve) == PSA_ECC_CURVE_SECT283K1 ? 283 : \ - (curve) == PSA_ECC_CURVE_SECT283R1 ? 283 : \ - (curve) == PSA_ECC_CURVE_SECT409K1 ? 409 : \ - (curve) == PSA_ECC_CURVE_SECT409R1 ? 409 : \ - (curve) == PSA_ECC_CURVE_SECT571K1 ? 571 : \ - (curve) == PSA_ECC_CURVE_SECT571R1 ? 571 : \ - (curve) == PSA_ECC_CURVE_SECP160K1 ? 160 : \ - (curve) == PSA_ECC_CURVE_SECP160R1 ? 160 : \ - (curve) == PSA_ECC_CURVE_SECP160R2 ? 160 : \ - (curve) == PSA_ECC_CURVE_SECP192K1 ? 192 : \ - (curve) == PSA_ECC_CURVE_SECP192R1 ? 192 : \ - (curve) == PSA_ECC_CURVE_SECP224K1 ? 224 : \ - (curve) == PSA_ECC_CURVE_SECP224R1 ? 224 : \ - (curve) == PSA_ECC_CURVE_SECP256K1 ? 256 : \ - (curve) == PSA_ECC_CURVE_SECP256R1 ? 256 : \ - (curve) == PSA_ECC_CURVE_SECP384R1 ? 384 : \ - (curve) == PSA_ECC_CURVE_SECP521R1 ? 521 : \ - (curve) == PSA_ECC_CURVE_BRAINPOOL_P256R1 ? 256 : \ - (curve) == PSA_ECC_CURVE_BRAINPOOL_P384R1 ? 384 : \ - (curve) == PSA_ECC_CURVE_BRAINPOOL_P512R1 ? 512 : \ - (curve) == PSA_ECC_CURVE_CURVE25519 ? 255 : \ - (curve) == PSA_ECC_CURVE_CURVE448 ? 448 : \ - 0) - -/** \def PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN - * - * This macro returns the maximum length of the PSK supported - * by the TLS-1.2 PSK-to-MS key derivation. - * - * Quoting RFC 4279, Sect 5.3: - * TLS implementations supporting these ciphersuites MUST support - * arbitrary PSK identities up to 128 octets in length, and arbitrary - * PSKs up to 64 octets in length. Supporting longer identities and - * keys is RECOMMENDED. - * - * Therefore, no implementation should define a value smaller than 64 - * for #PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN. - */ -#define PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN 128 - -/** The maximum size of a block cipher supported by the implementation. */ -#define PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE 16 - -/** The size of the output of psa_mac_sign_finish(), in bytes. - * - * This is also the MAC size that psa_mac_verify_finish() expects. - * - * \param key_type The type of the MAC key. - * \param key_bits The size of the MAC key in bits. - * \param alg A MAC algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_MAC(\p alg) is true). - * - * \return The MAC size for the specified algorithm with - * the specified key parameters. - * \return 0 if the MAC algorithm is not recognized. - * \return Either 0 or the correct size for a MAC algorithm that - * the implementation recognizes, but does not support. - * \return Unspecified if the key parameters are not consistent - * with the algorithm. - */ -#define PSA_MAC_FINAL_SIZE(key_type, key_bits, alg) \ - ((alg) & PSA_ALG_MAC_TRUNCATION_MASK ? PSA_MAC_TRUNCATED_LENGTH(alg) : \ - PSA_ALG_IS_HMAC(alg) ? PSA_HASH_SIZE(PSA_ALG_HMAC_GET_HASH(alg)) : \ - PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) ? PSA_BLOCK_CIPHER_BLOCK_SIZE(key_type) : \ - ((void)(key_type), (void)(key_bits), 0)) - -/** The maximum size of the output of psa_aead_encrypt(), in bytes. - * - * If the size of the ciphertext buffer is at least this large, it is - * guaranteed that psa_aead_encrypt() will not fail due to an - * insufficient buffer size. Depending on the algorithm, the actual size of - * the ciphertext may be smaller. - * - * \param alg An AEAD algorithm - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * \param plaintext_length Size of the plaintext in bytes. - * - * \return The AEAD ciphertext size for the specified - * algorithm. - * If the AEAD algorithm is not recognized, return 0. - * An implementation may return either 0 or a - * correct size for an AEAD algorithm that it - * recognizes, but does not support. - */ -#define PSA_AEAD_ENCRYPT_OUTPUT_SIZE(alg, plaintext_length) \ - (PSA_AEAD_TAG_LENGTH(alg) != 0 ? \ - (plaintext_length) + PSA_AEAD_TAG_LENGTH(alg) : \ - 0) - -/** The maximum size of the output of psa_aead_decrypt(), in bytes. - * - * If the size of the plaintext buffer is at least this large, it is - * guaranteed that psa_aead_decrypt() will not fail due to an - * insufficient buffer size. Depending on the algorithm, the actual size of - * the plaintext may be smaller. - * - * \param alg An AEAD algorithm - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * \param ciphertext_length Size of the plaintext in bytes. - * - * \return The AEAD ciphertext size for the specified - * algorithm. - * If the AEAD algorithm is not recognized, return 0. - * An implementation may return either 0 or a - * correct size for an AEAD algorithm that it - * recognizes, but does not support. - */ -#define PSA_AEAD_DECRYPT_OUTPUT_SIZE(alg, ciphertext_length) \ - (PSA_AEAD_TAG_LENGTH(alg) != 0 ? \ - (ciphertext_length) - PSA_AEAD_TAG_LENGTH(alg) : \ - 0) - -/** A sufficient output buffer size for psa_aead_update(). - * - * If the size of the output buffer is at least this large, it is - * guaranteed that psa_aead_update() will not fail due to an - * insufficient buffer size. The actual size of the output may be smaller - * in any given call. - * - * \param alg An AEAD algorithm - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * \param input_length Size of the input in bytes. - * - * \return A sufficient output buffer size for the specified - * algorithm. - * If the AEAD algorithm is not recognized, return 0. - * An implementation may return either 0 or a - * correct size for an AEAD algorithm that it - * recognizes, but does not support. - */ -/* For all the AEAD modes defined in this specification, it is possible - * to emit output without delay. However, hardware may not always be - * capable of this. So for modes based on a block cipher, allow the - * implementation to delay the output until it has a full block. */ -#define PSA_AEAD_UPDATE_OUTPUT_SIZE(alg, input_length) \ - (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ - PSA_ROUND_UP_TO_MULTIPLE(PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE, (input_length)) : \ - (input_length)) - -/** A sufficient ciphertext buffer size for psa_aead_finish(). - * - * If the size of the ciphertext buffer is at least this large, it is - * guaranteed that psa_aead_finish() will not fail due to an - * insufficient ciphertext buffer size. The actual size of the output may - * be smaller in any given call. - * - * \param alg An AEAD algorithm - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * - * \return A sufficient ciphertext buffer size for the - * specified algorithm. - * If the AEAD algorithm is not recognized, return 0. - * An implementation may return either 0 or a - * correct size for an AEAD algorithm that it - * recognizes, but does not support. - */ -#define PSA_AEAD_FINISH_OUTPUT_SIZE(alg) \ - (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ - PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE : \ - 0) - -/** A sufficient plaintext buffer size for psa_aead_verify(). - * - * If the size of the plaintext buffer is at least this large, it is - * guaranteed that psa_aead_verify() will not fail due to an - * insufficient plaintext buffer size. The actual size of the output may - * be smaller in any given call. - * - * \param alg An AEAD algorithm - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * - * \return A sufficient plaintext buffer size for the - * specified algorithm. - * If the AEAD algorithm is not recognized, return 0. - * An implementation may return either 0 or a - * correct size for an AEAD algorithm that it - * recognizes, but does not support. - */ -#define PSA_AEAD_VERIFY_OUTPUT_SIZE(alg) \ - (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ - PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE : \ - 0) - -#define PSA_RSA_MINIMUM_PADDING_SIZE(alg) \ - (PSA_ALG_IS_RSA_OAEP(alg) ? \ - 2 * PSA_HASH_SIZE(PSA_ALG_RSA_OAEP_GET_HASH(alg)) + 1 : \ - 11 /*PKCS#1v1.5*/) - -/** - * \brief ECDSA signature size for a given curve bit size - * - * \param curve_bits Curve size in bits. - * \return Signature size in bytes. - * - * \note This macro returns a compile-time constant if its argument is one. - */ -#define PSA_ECDSA_SIGNATURE_SIZE(curve_bits) \ - (PSA_BITS_TO_BYTES(curve_bits) * 2) - -/** Sufficient signature buffer size for psa_sign_hash(). - * - * This macro returns a sufficient buffer size for a signature using a key - * of the specified type and size, with the specified algorithm. - * Note that the actual size of the signature may be smaller - * (some algorithms produce a variable-size signature). - * - * \warning This function may call its arguments multiple times or - * zero times, so you should not pass arguments that contain - * side effects. - * - * \param key_type An asymmetric key type (this may indifferently be a - * key pair type or a public key type). - * \param key_bits The size of the key in bits. - * \param alg The signature algorithm. - * - * \return If the parameters are valid and supported, return - * a buffer size in bytes that guarantees that - * psa_sign_hash() will not fail with - * #PSA_ERROR_BUFFER_TOO_SMALL. - * If the parameters are a valid combination that is not supported - * by the implementation, this macro shall return either a - * sensible size or 0. - * If the parameters are not valid, the - * return value is unspecified. - */ -#define PSA_SIGN_OUTPUT_SIZE(key_type, key_bits, alg) \ - (PSA_KEY_TYPE_IS_RSA(key_type) ? ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \ - PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_ECDSA_SIGNATURE_SIZE(key_bits) : \ - ((void)alg, 0)) - -#define PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE \ - PSA_ECDSA_SIGNATURE_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) - -/** \def PSA_SIGNATURE_MAX_SIZE - * - * Maximum size of an asymmetric signature. - * - * This macro must expand to a compile-time constant integer. This value - * should be the maximum size of a signature supported by the implementation, - * in bytes, and must be no smaller than this maximum. - */ -#define PSA_SIGNATURE_MAX_SIZE \ - (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) > PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE ? \ - PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) : \ - PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE) - -/** Sufficient output buffer size for psa_asymmetric_encrypt(). - * - * This macro returns a sufficient buffer size for a ciphertext produced using - * a key of the specified type and size, with the specified algorithm. - * Note that the actual size of the ciphertext may be smaller, depending - * on the algorithm. - * - * \warning This function may call its arguments multiple times or - * zero times, so you should not pass arguments that contain - * side effects. - * - * \param key_type An asymmetric key type (this may indifferently be a - * key pair type or a public key type). - * \param key_bits The size of the key in bits. - * \param alg The signature algorithm. - * - * \return If the parameters are valid and supported, return - * a buffer size in bytes that guarantees that - * psa_asymmetric_encrypt() will not fail with - * #PSA_ERROR_BUFFER_TOO_SMALL. - * If the parameters are a valid combination that is not supported - * by the implementation, this macro shall return either a - * sensible size or 0. - * If the parameters are not valid, the - * return value is unspecified. - */ -#define PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \ - (PSA_KEY_TYPE_IS_RSA(key_type) ? \ - ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \ - 0) - -/** Sufficient output buffer size for psa_asymmetric_decrypt(). - * - * This macro returns a sufficient buffer size for a ciphertext produced using - * a key of the specified type and size, with the specified algorithm. - * Note that the actual size of the ciphertext may be smaller, depending - * on the algorithm. - * - * \warning This function may call its arguments multiple times or - * zero times, so you should not pass arguments that contain - * side effects. - * - * \param key_type An asymmetric key type (this may indifferently be a - * key pair type or a public key type). - * \param key_bits The size of the key in bits. - * \param alg The signature algorithm. - * - * \return If the parameters are valid and supported, return - * a buffer size in bytes that guarantees that - * psa_asymmetric_decrypt() will not fail with - * #PSA_ERROR_BUFFER_TOO_SMALL. - * If the parameters are a valid combination that is not supported - * by the implementation, this macro shall return either a - * sensible size or 0. - * If the parameters are not valid, the - * return value is unspecified. - */ -#define PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \ - (PSA_KEY_TYPE_IS_RSA(key_type) ? \ - PSA_BITS_TO_BYTES(key_bits) - PSA_RSA_MINIMUM_PADDING_SIZE(alg) : \ - 0) - -/* Maximum size of the ASN.1 encoding of an INTEGER with the specified - * number of bits. - * - * This definition assumes that bits <= 2^19 - 9 so that the length field - * is at most 3 bytes. The length of the encoding is the length of the - * bit string padded to a whole number of bytes plus: - * - 1 type byte; - * - 1 to 3 length bytes; - * - 0 to 1 bytes of leading 0 due to the sign bit. - */ -#define PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(bits) \ - ((bits) / 8 + 5) - -/* Maximum size of the export encoding of an RSA public key. - * Assumes that the public exponent is less than 2^32. - * - * RSAPublicKey ::= SEQUENCE { - * modulus INTEGER, -- n - * publicExponent INTEGER } -- e - * - * - 4 bytes of SEQUENCE overhead; - * - n : INTEGER; - * - 7 bytes for the public exponent. - */ -#define PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) \ - (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) + 11) - -/* Maximum size of the export encoding of an RSA key pair. - * Assumes thatthe public exponent is less than 2^32 and that the size - * difference between the two primes is at most 1 bit. - * - * RSAPrivateKey ::= SEQUENCE { - * version Version, -- 0 - * modulus INTEGER, -- N-bit - * publicExponent INTEGER, -- 32-bit - * privateExponent INTEGER, -- N-bit - * prime1 INTEGER, -- N/2-bit - * prime2 INTEGER, -- N/2-bit - * exponent1 INTEGER, -- N/2-bit - * exponent2 INTEGER, -- N/2-bit - * coefficient INTEGER, -- N/2-bit - * } - * - * - 4 bytes of SEQUENCE overhead; - * - 3 bytes of version; - * - 7 half-size INTEGERs plus 2 full-size INTEGERs, - * overapproximated as 9 half-size INTEGERS; - * - 7 bytes for the public exponent. - */ -#define PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits) \ - (9 * PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE((key_bits) / 2 + 1) + 14) - -/* Maximum size of the export encoding of a DSA public key. - * - * SubjectPublicKeyInfo ::= SEQUENCE { - * algorithm AlgorithmIdentifier, - * subjectPublicKey BIT STRING } -- contains DSAPublicKey - * AlgorithmIdentifier ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters Dss-Parms } -- SEQUENCE of 3 INTEGERs - * DSAPublicKey ::= INTEGER -- public key, Y - * - * - 3 * 4 bytes of SEQUENCE overhead; - * - 1 + 1 + 7 bytes of algorithm (DSA OID); - * - 4 bytes of BIT STRING overhead; - * - 3 full-size INTEGERs (p, g, y); - * - 1 + 1 + 32 bytes for 1 sub-size INTEGER (q <= 256 bits). - */ -#define PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) \ - (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3 + 59) - -/* Maximum size of the export encoding of a DSA key pair. - * - * DSAPrivateKey ::= SEQUENCE { - * version Version, -- 0 - * prime INTEGER, -- p - * subprime INTEGER, -- q - * generator INTEGER, -- g - * public INTEGER, -- y - * private INTEGER, -- x - * } - * - * - 4 bytes of SEQUENCE overhead; - * - 3 bytes of version; - * - 3 full-size INTEGERs (p, g, y); - * - 2 * (1 + 1 + 32) bytes for 2 sub-size INTEGERs (q, x <= 256 bits). - */ -#define PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits) \ - (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3 + 75) - -/* Maximum size of the export encoding of an ECC public key. - * - * The representation of an ECC public key is: - * - The byte 0x04; - * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; - * - `y_P` as a `ceiling(m/8)`-byte string, big-endian; - * - where m is the bit size associated with the curve. - * - * - 1 byte + 2 * point size. - */ -#define PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) \ - (2 * PSA_BITS_TO_BYTES(key_bits) + 1) - -/* Maximum size of the export encoding of an ECC key pair. - * - * An ECC key pair is represented by the secret value. - */ -#define PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) \ - (PSA_BITS_TO_BYTES(key_bits)) - -/** Sufficient output buffer size for psa_export_key() or psa_export_public_key(). - * - * This macro returns a compile-time constant if its arguments are - * compile-time constants. - * - * \warning This function may call its arguments multiple times or - * zero times, so you should not pass arguments that contain - * side effects. - * - * The following code illustrates how to allocate enough memory to export - * a key by querying the key type and size at runtime. - * \code{c} - * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - * psa_status_t status; - * status = psa_get_key_attributes(key, &attributes); - * if (status != PSA_SUCCESS) handle_error(...); - * psa_key_type_t key_type = psa_get_key_type(&attributes); - * size_t key_bits = psa_get_key_bits(&attributes); - * size_t buffer_size = PSA_KEY_EXPORT_MAX_SIZE(key_type, key_bits); - * psa_reset_key_attributes(&attributes); - * uint8_t *buffer = malloc(buffer_size); - * if (buffer == NULL) handle_error(...); - * size_t buffer_length; - * status = psa_export_key(key, buffer, buffer_size, &buffer_length); - * if (status != PSA_SUCCESS) handle_error(...); - * \endcode - * - * For psa_export_public_key(), calculate the buffer size from the - * public key type. You can use the macro #PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR - * to convert a key pair type to the corresponding public key type. - * \code{c} - * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - * psa_status_t status; - * status = psa_get_key_attributes(key, &attributes); - * if (status != PSA_SUCCESS) handle_error(...); - * psa_key_type_t key_type = psa_get_key_type(&attributes); - * psa_key_type_t public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(key_type); - * size_t key_bits = psa_get_key_bits(&attributes); - * size_t buffer_size = PSA_KEY_EXPORT_MAX_SIZE(public_key_type, key_bits); - * psa_reset_key_attributes(&attributes); - * uint8_t *buffer = malloc(buffer_size); - * if (buffer == NULL) handle_error(...); - * size_t buffer_length; - * status = psa_export_public_key(key, buffer, buffer_size, &buffer_length); - * if (status != PSA_SUCCESS) handle_error(...); - * \endcode - * - * \param key_type A supported key type. - * \param key_bits The size of the key in bits. - * - * \return If the parameters are valid and supported, return - * a buffer size in bytes that guarantees that - * psa_sign_hash() will not fail with - * #PSA_ERROR_BUFFER_TOO_SMALL. - * If the parameters are a valid combination that is not supported - * by the implementation, this macro shall return either a - * sensible size or 0. - * If the parameters are not valid, the - * return value is unspecified. - */ -#define PSA_KEY_EXPORT_MAX_SIZE(key_type, key_bits) \ - (PSA_KEY_TYPE_IS_UNSTRUCTURED(key_type) ? PSA_BITS_TO_BYTES(key_bits) : \ - (key_type) == PSA_KEY_TYPE_RSA_KEY_PAIR ? PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits) : \ - (key_type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY ? PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ - (key_type) == PSA_KEY_TYPE_DSA_KEY_PAIR ? PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits) : \ - (key_type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY ? PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ - PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) ? PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) : \ - PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type) ? PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) : \ - 0) - -#endif /* PSA_CRYPTO_SIZES_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_struct.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_struct.h deleted file mode 100644 index 403a734..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_struct.h +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Copyright (c) 2018-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ -/** - * \file psa/crypto_struct.h - * - * \brief PSA cryptography module: structured type implementations - * - * \note This file may not be included directly. Applications must - * include psa/crypto.h. - * - * This file contains the definitions of some data structures with - * implementation-specific definitions. - * - * In implementations with isolation between the application and the - * cryptography module, it is expected that the front-end and the back-end - * would have different versions of this file. - */ - -#ifndef PSA_CRYPTO_STRUCT_H -#define PSA_CRYPTO_STRUCT_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Note that the below structures are different from the decalrations in - * mbed-crypto. This is because TF-M maintains 'front-end' and 'back-end' - * versions of this header. In the front-end version, exported to NS - * clients in interface/include/psa, a crypto operation is defined as an - * opaque handle to a context in the Crypto service. The back-end - * version, directly included from the mbed-crypto repo by the Crypto - * service, contains the full definition of the operation structs. - * - * One of the functions of the Crypto service is to allocate the back-end - * operation contexts in its own partition memory (in crypto_alloc.c), - * and then do the mapping between front-end operation handles passed by - * NS clients and the corresponding back-end operation contexts. The - * advantage of doing it this way is that internal mbed-crypto state is never - * exposed to the NS client. - */ - -struct psa_hash_operation_s -{ - uint32_t handle; -}; - -#define PSA_HASH_OPERATION_INIT {0} -static inline struct psa_hash_operation_s psa_hash_operation_init( void ) -{ - const struct psa_hash_operation_s v = PSA_HASH_OPERATION_INIT; - return( v ); -} - -struct psa_mac_operation_s -{ - uint32_t handle; -}; - -#define PSA_MAC_OPERATION_INIT {0} -static inline struct psa_mac_operation_s psa_mac_operation_init( void ) -{ - const struct psa_mac_operation_s v = PSA_MAC_OPERATION_INIT; - return( v ); -} - -struct psa_cipher_operation_s -{ - uint32_t handle; -}; - -#define PSA_CIPHER_OPERATION_INIT {0} -static inline struct psa_cipher_operation_s psa_cipher_operation_init( void ) -{ - const struct psa_cipher_operation_s v = PSA_CIPHER_OPERATION_INIT; - return( v ); -} - -struct psa_aead_operation_s -{ - uint32_t handle; -}; - -#define PSA_AEAD_OPERATION_INIT {0} -static inline struct psa_aead_operation_s psa_aead_operation_init( void ) -{ - const struct psa_aead_operation_s v = PSA_AEAD_OPERATION_INIT; - return( v ); -} - -struct psa_key_derivation_s -{ - uint32_t handle; -}; - -#define PSA_KEY_DERIVATION_OPERATION_INIT {0} -static inline struct psa_key_derivation_s psa_key_derivation_operation_init( void ) -{ - const struct psa_key_derivation_s v = PSA_KEY_DERIVATION_OPERATION_INIT; - return( v ); -} - -struct psa_key_policy_s -{ - psa_key_usage_t usage; - psa_algorithm_t alg; - psa_algorithm_t alg2; -}; -typedef struct psa_key_policy_s psa_key_policy_t; - -#define PSA_KEY_POLICY_INIT {0, 0, 0} -static inline struct psa_key_policy_s psa_key_policy_init( void ) -{ - const struct psa_key_policy_s v = PSA_KEY_POLICY_INIT; - return( v ); -} - -/* The type used internally for key sizes. - * Public interfaces use size_t, but internally we use a smaller type. */ -typedef uint16_t psa_key_bits_t; -/* The maximum value of the type used to represent bit-sizes. - * This is used to mark an invalid key size. */ -#define PSA_KEY_BITS_TOO_LARGE ( (psa_key_bits_t) ( -1 ) ) -/* The maximum size of a key in bits. - * Currently defined as the maximum that can be represented, rounded down - * to a whole number of bytes. - * This is an uncast value so that it can be used in preprocessor - * conditionals. */ -#define PSA_MAX_KEY_BITS 0xfff8 - -/** A mask of flags that can be stored in key attributes. - * - * This type is also used internally to store flags in slots. Internal - * flags are defined in library/psa_crypto_core.h. Internal flags may have - * the same value as external flags if they are properly handled during - * key creation and in psa_get_key_attributes. - */ -typedef uint16_t psa_key_attributes_flag_t; - -#define MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER \ - ( (psa_key_attributes_flag_t) 0x0001 ) - -/* A mask of key attribute flags used externally only. - * Only meant for internal checks inside the library. */ -#define MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY ( \ - MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER | \ - 0 ) - -/* A mask of key attribute flags used both internally and externally. - * Currently there aren't any. */ -#define MBEDTLS_PSA_KA_MASK_DUAL_USE ( \ - 0 ) - -typedef struct -{ - psa_key_type_t type; - psa_key_lifetime_t lifetime; - psa_key_id_t id; - psa_key_policy_t policy; - psa_key_bits_t bits; - psa_key_attributes_flag_t flags; -} psa_core_key_attributes_t; - -#define PSA_CORE_KEY_ATTRIBUTES_INIT {0, 0, PSA_KEY_ID_INIT, PSA_KEY_POLICY_INIT, 0, 0} - -struct psa_key_attributes_s -{ - psa_core_key_attributes_t core; -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - psa_key_slot_number_t slot_number; -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - void *domain_parameters; - size_t domain_parameters_size; -}; - -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) -#define PSA_KEY_ATTRIBUTES_INIT {PSA_CORE_KEY_ATTRIBUTES_INIT, 0, NULL, 0} -#else -#define PSA_KEY_ATTRIBUTES_INIT {PSA_CORE_KEY_ATTRIBUTES_INIT, NULL, 0} -#endif - -static inline struct psa_key_attributes_s psa_key_attributes_init( void ) -{ - const struct psa_key_attributes_s v = PSA_KEY_ATTRIBUTES_INIT; - return( v ); -} - -static inline void psa_set_key_id(psa_key_attributes_t *attributes, - psa_key_id_t id) -{ - attributes->core.id = id; - if( attributes->core.lifetime == PSA_KEY_LIFETIME_VOLATILE ) - attributes->core.lifetime = PSA_KEY_LIFETIME_PERSISTENT; -} - -static inline psa_key_id_t psa_get_key_id( - const psa_key_attributes_t *attributes) -{ - return( attributes->core.id ); -} - -static inline void psa_set_key_lifetime(psa_key_attributes_t *attributes, - psa_key_lifetime_t lifetime) -{ - attributes->core.lifetime = lifetime; - if( lifetime == PSA_KEY_LIFETIME_VOLATILE ) - { -#ifdef MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER - attributes->core.id.key_id = 0; - attributes->core.id.owner = 0; -#else - attributes->core.id = 0; -#endif - } -} - -static inline psa_key_lifetime_t psa_get_key_lifetime( - const psa_key_attributes_t *attributes) -{ - return( attributes->core.lifetime ); -} - -static inline void psa_set_key_usage_flags(psa_key_attributes_t *attributes, - psa_key_usage_t usage_flags) -{ - attributes->core.policy.usage = usage_flags; -} - -static inline psa_key_usage_t psa_get_key_usage_flags( - const psa_key_attributes_t *attributes) -{ - return( attributes->core.policy.usage ); -} - -static inline void psa_set_key_algorithm(psa_key_attributes_t *attributes, - psa_algorithm_t alg) -{ - attributes->core.policy.alg = alg; -} - -static inline psa_algorithm_t psa_get_key_algorithm( - const psa_key_attributes_t *attributes) -{ - return( attributes->core.policy.alg ); -} - -/* This function is declared in crypto_extra.h, which comes after this - * header file, but we need the function here, so repeat the declaration. */ -psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes, - psa_key_type_t type, - const uint8_t *data, - size_t data_length); - -static inline void psa_set_key_type(psa_key_attributes_t *attributes, - psa_key_type_t type) -{ - if( attributes->domain_parameters == NULL ) - { - /* Common case: quick path */ - attributes->core.type = type; - } - else - { - /* Call the bigger function to free the old domain paramteres. - * Ignore any errors which may arise due to type requiring - * non-default domain parameters, since this function can't - * report errors. */ - (void) psa_set_key_domain_parameters( attributes, type, NULL, 0 ); - } -} - -static inline psa_key_type_t psa_get_key_type( - const psa_key_attributes_t *attributes) -{ - return( attributes->core.type ); -} - -static inline void psa_set_key_bits(psa_key_attributes_t *attributes, - size_t bits) -{ - if( bits > PSA_MAX_KEY_BITS ) - attributes->core.bits = PSA_KEY_BITS_TOO_LARGE; - else - attributes->core.bits = (psa_key_bits_t) bits; -} - -static inline size_t psa_get_key_bits( - const psa_key_attributes_t *attributes) -{ - return( attributes->core.bits ); -} - -#ifdef __cplusplus -} -#endif - -#endif /* PSA_CRYPTO_STRUCT_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_types.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_types.h deleted file mode 100644 index 690999f..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_types.h +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Copyright (c) 2018-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ -/** - * \file psa/crypto_types.h - * - * \brief PSA cryptography module: type aliases. - * - * \note This file may not be included directly. Applications must - * include psa/crypto.h. Drivers must include the appropriate driver - * header file. - * - * This file contains portable definitions of integral types for properties - * of cryptographic keys, designations of cryptographic algorithms, and - * error codes returned by the library. - * - * This header file does not declare any function. - */ - -#ifndef PSA_CRYPTO_TYPES_H -#define PSA_CRYPTO_TYPES_H - -#include - -/** \defgroup error Error codes - * @{ - */ - -/** - * \brief Function return status. - * - * This is either #PSA_SUCCESS (which is zero), indicating success, - * or a small negative value indicating that an error occurred. Errors are - * encoded as one of the \c PSA_ERROR_xxx values defined here. */ -/* If #PSA_SUCCESS is already defined, it means that #psa_status_t - * is also defined in an external header, so prevent its multiple - * definition. - */ -#ifndef PSA_SUCCESS -typedef int32_t psa_status_t; -#endif - -/**@}*/ - -/** \defgroup crypto_types Key and algorithm types - * @{ - */ - -/** \brief Encoding of a key type. - */ -typedef uint32_t psa_key_type_t; - -/** The type of PSA elliptic curve identifiers. - * - * The curve identifier is required to create an ECC key using the - * PSA_KEY_TYPE_ECC_KEY_PAIR() or PSA_KEY_TYPE_ECC_PUBLIC_KEY() - * macros. - * - * The encoding of curve identifiers is taken from the - * TLS Supported Groups Registry (formerly known as the - * TLS EC Named Curve Registry) - * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 - * - * This specification defines identifiers for some of the curves in the IANA - * registry. Implementations that support other curves that are in the IANA - * registry should use the IANA value and a implementation-specific identifier. - * Implemenations that support non-IANA curves should use one of the following - * approaches for allocating a key type: - * - * 1. Select a ::psa_ecc_curve_t value in the range #PSA_ECC_CURVE_VENDOR_MIN to - * #PSA_ECC_CURVE_VENDOR_MAX, which is a subset of the IANA private use - * range. - * 2. Use a ::psa_key_type_t value that is vendor-defined. - * - * The first option is recommended. - */ -typedef uint16_t psa_ecc_curve_t; - -/** The type of PSA Diffie-Hellman group identifiers. - * - * The group identifier is required to create an Diffie-Hellman key using the - * PSA_KEY_TYPE_DH_KEY_PAIR() or PSA_KEY_TYPE_DH_PUBLIC_KEY() - * macros. - * - * The encoding of group identifiers is taken from the - * TLS Supported Groups Registry (formerly known as the - * TLS EC Named Curve Registry) - * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 - * - * This specification defines identifiers for some of the groups in the IANA - * registry. Implementations that support other groups that are in the IANA - * registry should use the IANA value and a implementation-specific identifier. - * Implemenations that support non-IANA groups should use one of the following - * approaches for allocating a key type: - * - * 1. Select a ::psa_dh_group_t value in the range #PSA_DH_GROUP_VENDOR_MIN to - * #PSA_DH_GROUP_VENDOR_MAX, which is a subset of the IANA private use - * range. - * 2. Select a ::psa_dh_group_t value from the named groups allocated for - * GREASE in the IETF draft specification. The GREASE specification and - * values are listed below. - * 3. Use a ::psa_key_type_t value that is vendor-defined. - * - * Option 1 or 2 are recommended. - * - * The current draft of the GREASE specification is - * https://datatracker.ietf.org/doc/draft-ietf-tls-grease - * - * The following GREASE values are allocated for named groups: - * \code - * 0x0A0A - * 0x1A1A - * 0x2A2A - * 0x3A3A - * 0x4A4A - * 0x5A5A - * 0x6A6A - * 0x7A7A - * 0x8A8A - * 0x9A9A - * 0xAAAA - * 0xBABA - * 0xCACA - * 0xDADA - * 0xEAEA - * 0xFAFA - * \endcode - */ -typedef uint16_t psa_dh_group_t; - -/** \brief Encoding of a cryptographic algorithm. - * - * For algorithms that can be applied to multiple key types, this type - * does not encode the key type. For example, for symmetric ciphers - * based on a block cipher, #psa_algorithm_t encodes the block cipher - * mode and the padding mode while the block cipher itself is encoded - * via #psa_key_type_t. - */ -typedef uint32_t psa_algorithm_t; - -/**@}*/ - -/** \defgroup key_lifetimes Key lifetimes - * @{ - */ - -/** Encoding of key lifetimes. - * - * The lifetime of a key indicates where it is stored and what system actions - * may create and destroy it. - * - * Keys with the lifetime #PSA_KEY_LIFETIME_VOLATILE are automatically - * destroyed when the application terminates or on a power reset. - * - * Keys with a lifetime other than #PSA_KEY_LIFETIME_VOLATILE are said - * to be _persistent_. - * Persistent keys are preserved if the application or the system restarts. - * Persistent keys have a key identifier of type #psa_key_id_t. - * The application can call psa_open_key() to open a persistent key that - * it created previously. - */ -typedef uint32_t psa_key_lifetime_t; - -/** Encoding of identifiers of persistent keys. - * - * - Applications may freely choose key identifiers in the range - * #PSA_KEY_ID_USER_MIN to #PSA_KEY_ID_USER_MAX. - * - Implementations may define additional key identifiers in the range - * #PSA_KEY_ID_VENDOR_MIN to #PSA_KEY_ID_VENDOR_MAX. - * - 0 is reserved as an invalid key identifier. - * - Key identifiers outside these ranges are reserved for future use. - */ -typedef uint32_t psa_key_id_t; -#define PSA_KEY_ID_INIT 0 - -/**@}*/ - -/** \defgroup policy Key policies - * @{ - */ - -/** \brief Encoding of permitted usage on a key. */ -typedef uint32_t psa_key_usage_t; - -/**@}*/ - -/** \defgroup attributes Key attributes - * @{ - */ - -/** The type of a structure containing key attributes. - * - * This is an opaque structure that can represent the metadata of a key - * object. Metadata that can be stored in attributes includes: - * - The location of the key in storage, indicated by its key identifier - * and its lifetime. - * - The key's policy, comprising usage flags and a specification of - * the permitted algorithm(s). - * - Information about the key itself: the key type and its size. - * - Implementations may define additional attributes. - * - * The actual key material is not considered an attribute of a key. - * Key attributes do not contain information that is generally considered - * highly confidential. - * - * An attribute structure can be a simple data structure where each function - * `psa_set_key_xxx` sets a field and the corresponding function - * `psa_get_key_xxx` retrieves the value of the corresponding field. - * However, implementations may report values that are equivalent to the - * original one, but have a different encoding. For example, an - * implementation may use a more compact representation for types where - * many bit-patterns are invalid or not supported, and store all values - * that it does not support as a special marker value. In such an - * implementation, after setting an invalid value, the corresponding - * get function returns an invalid value which may not be the one that - * was originally stored. - * - * An attribute structure may contain references to auxiliary resources, - * for example pointers to allocated memory or indirect references to - * pre-calculated values. In order to free such resources, the application - * must call psa_reset_key_attributes(). As an exception, calling - * psa_reset_key_attributes() on an attribute structure is optional if - * the structure has only been modified by the following functions - * since it was initialized or last reset with psa_reset_key_attributes(): - * - psa_set_key_id() - * - psa_set_key_lifetime() - * - psa_set_key_type() - * - psa_set_key_bits() - * - psa_set_key_usage_flags() - * - psa_set_key_algorithm() - * - * Before calling any function on a key attribute structure, the application - * must initialize it by any of the following means: - * - Set the structure to all-bits-zero, for example: - * \code - * psa_key_attributes_t attributes; - * memset(&attributes, 0, sizeof(attributes)); - * \endcode - * - Initialize the structure to logical zero values, for example: - * \code - * psa_key_attributes_t attributes = {0}; - * \endcode - * - Initialize the structure to the initializer #PSA_KEY_ATTRIBUTES_INIT, - * for example: - * \code - * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - * \endcode - * - Assign the result of the function psa_key_attributes_init() - * to the structure, for example: - * \code - * psa_key_attributes_t attributes; - * attributes = psa_key_attributes_init(); - * \endcode - * - * A freshly initialized attribute structure contains the following - * values: - * - * - lifetime: #PSA_KEY_LIFETIME_VOLATILE. - * - key identifier: 0 (which is not a valid key identifier). - * - type: \c 0 (meaning that the type is unspecified). - * - key size: \c 0 (meaning that the size is unspecified). - * - usage flags: \c 0 (which allows no usage except exporting a public key). - * - algorithm: \c 0 (which allows no cryptographic usage, but allows - * exporting). - * - * A typical sequence to create a key is as follows: - * -# Create and initialize an attribute structure. - * -# If the key is persistent, call psa_set_key_id(). - * Also call psa_set_key_lifetime() to place the key in a non-default - * location. - * -# Set the key policy with psa_set_key_usage_flags() and - * psa_set_key_algorithm(). - * -# Set the key type with psa_set_key_type(). - * Skip this step if copying an existing key with psa_copy_key(). - * -# When generating a random key with psa_generate_key() or deriving a key - * with psa_key_derivation_output_key(), set the desired key size with - * psa_set_key_bits(). - * -# Call a key creation function: psa_import_key(), psa_generate_key(), - * psa_key_derivation_output_key() or psa_copy_key(). This function reads - * the attribute structure, creates a key with these attributes, and - * outputs a handle to the newly created key. - * -# The attribute structure is now no longer necessary. - * You may call psa_reset_key_attributes(), although this is optional - * with the workflow presented here because the attributes currently - * defined in this specification do not require any additional resources - * beyond the structure itself. - * - * A typical sequence to query a key's attributes is as follows: - * -# Call psa_get_key_attributes(). - * -# Call `psa_get_key_xxx` functions to retrieve the attribute(s) that - * you are interested in. - * -# Call psa_reset_key_attributes() to free any resources that may be - * used by the attribute structure. - * - * Once a key has been created, it is impossible to change its attributes. - */ -typedef struct psa_key_attributes_s psa_key_attributes_t; - -/**@}*/ - -/** \defgroup derivation Key derivation - * @{ - */ - -/** \brief Encoding of the step of a key derivation. */ -typedef uint16_t psa_key_derivation_step_t; - -/**@}*/ - -#endif /* PSA_CRYPTO_TYPES_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_values.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_values.h deleted file mode 100644 index 7fde073..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_values.h +++ /dev/null @@ -1,1701 +0,0 @@ -/* - * Copyright (c) 2018-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ -/** - * \file psa/crypto_values.h - * - * \brief PSA cryptography module: macros to build and analyze integer values. - * - * \note This file may not be included directly. Applications must - * include psa/crypto.h. Drivers must include the appropriate driver - * header file. - * - * This file contains portable definitions of macros to build and analyze - * values of integral types that encode properties of cryptographic keys, - * designations of cryptographic algorithms, and error codes returned by - * the library. - * - * This header file only defines preprocessor macros. - */ - -#ifndef PSA_CRYPTO_VALUES_H -#define PSA_CRYPTO_VALUES_H - -/** \defgroup error Error codes - * @{ - */ - -/* PSA error codes */ - -/** The action was completed successfully. */ -#ifndef PSA_SUCCESS -#define PSA_SUCCESS ((psa_status_t)0) -#endif - -/** An error occurred that does not correspond to any defined - * failure cause. - * - * Implementations may use this error code if none of the other standard - * error codes are applicable. */ -#define PSA_ERROR_GENERIC_ERROR ((psa_status_t)-132) - -/** The requested operation or a parameter is not supported - * by this implementation. - * - * Implementations should return this error code when an enumeration - * parameter such as a key type, algorithm, etc. is not recognized. - * If a combination of parameters is recognized and identified as - * not valid, return #PSA_ERROR_INVALID_ARGUMENT instead. */ -#define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)-134) - -/** The requested action is denied by a policy. - * - * Implementations should return this error code when the parameters - * are recognized as valid and supported, and a policy explicitly - * denies the requested operation. - * - * If a subset of the parameters of a function call identify a - * forbidden operation, and another subset of the parameters are - * not valid or not supported, it is unspecified whether the function - * returns #PSA_ERROR_NOT_PERMITTED, #PSA_ERROR_NOT_SUPPORTED or - * #PSA_ERROR_INVALID_ARGUMENT. */ -#define PSA_ERROR_NOT_PERMITTED ((psa_status_t)-133) - -/** An output buffer is too small. - * - * Applications can call the \c PSA_xxx_SIZE macro listed in the function - * description to determine a sufficient buffer size. - * - * Implementations should preferably return this error code only - * in cases when performing the operation with a larger output - * buffer would succeed. However implementations may return this - * error if a function has invalid or unsupported parameters in addition - * to the parameters that determine the necessary output buffer size. */ -#define PSA_ERROR_BUFFER_TOO_SMALL ((psa_status_t)-138) - -/** Asking for an item that already exists - * - * Implementations should return this error, when attempting - * to write an item (like a key) that already exists. */ -#define PSA_ERROR_ALREADY_EXISTS ((psa_status_t)-139) - -/** Asking for an item that doesn't exist - * - * Implementations should return this error, if a requested item (like - * a key) does not exist. */ -#define PSA_ERROR_DOES_NOT_EXIST ((psa_status_t)-140) - -/** The requested action cannot be performed in the current state. - * - * Multipart operations return this error when one of the - * functions is called out of sequence. Refer to the function - * descriptions for permitted sequencing of functions. - * - * Implementations shall not return this error code to indicate - * that a key either exists or not, - * but shall instead return #PSA_ERROR_ALREADY_EXISTS or #PSA_ERROR_DOES_NOT_EXIST - * as applicable. - * - * Implementations shall not return this error code to indicate that a - * key handle is invalid, but shall return #PSA_ERROR_INVALID_HANDLE - * instead. */ -#define PSA_ERROR_BAD_STATE ((psa_status_t)-137) - -/** The parameters passed to the function are invalid. - * - * Implementations may return this error any time a parameter or - * combination of parameters are recognized as invalid. - * - * Implementations shall not return this error code to indicate that a - * key handle is invalid, but shall return #PSA_ERROR_INVALID_HANDLE - * instead. - */ -#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)-135) - -/** There is not enough runtime memory. - * - * If the action is carried out across multiple security realms, this - * error can refer to available memory in any of the security realms. */ -#define PSA_ERROR_INSUFFICIENT_MEMORY ((psa_status_t)-141) - -/** There is not enough persistent storage. - * - * Functions that modify the key storage return this error code if - * there is insufficient storage space on the host media. In addition, - * many functions that do not otherwise access storage may return this - * error code if the implementation requires a mandatory log entry for - * the requested action and the log storage space is full. */ -#define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)-142) - -/** There was a communication failure inside the implementation. - * - * This can indicate a communication failure between the application - * and an external cryptoprocessor or between the cryptoprocessor and - * an external volatile or persistent memory. A communication failure - * may be transient or permanent depending on the cause. - * - * \warning If a function returns this error, it is undetermined - * whether the requested action has completed or not. Implementations - * should return #PSA_SUCCESS on successful completion whenever - * possible, however functions may return #PSA_ERROR_COMMUNICATION_FAILURE - * if the requested action was completed successfully in an external - * cryptoprocessor but there was a breakdown of communication before - * the cryptoprocessor could report the status to the application. - */ -#define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t)-145) - -/** There was a storage failure that may have led to data loss. - * - * This error indicates that some persistent storage is corrupted. - * It should not be used for a corruption of volatile memory - * (use #PSA_ERROR_CORRUPTION_DETECTED), for a communication error - * between the cryptoprocessor and its external storage (use - * #PSA_ERROR_COMMUNICATION_FAILURE), or when the storage is - * in a valid state but is full (use #PSA_ERROR_INSUFFICIENT_STORAGE). - * - * Note that a storage failure does not indicate that any data that was - * previously read is invalid. However this previously read data may no - * longer be readable from storage. - * - * When a storage failure occurs, it is no longer possible to ensure - * the global integrity of the keystore. Depending on the global - * integrity guarantees offered by the implementation, access to other - * data may or may not fail even if the data is still readable but - * its integrity cannot be guaranteed. - * - * Implementations should only use this error code to report a - * permanent storage corruption. However application writers should - * keep in mind that transient errors while reading the storage may be - * reported using this error code. */ -#define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)-146) - -/** A hardware failure was detected. - * - * A hardware failure may be transient or permanent depending on the - * cause. */ -#define PSA_ERROR_HARDWARE_FAILURE ((psa_status_t)-147) - -/** A tampering attempt was detected. - * - * If an application receives this error code, there is no guarantee - * that previously accessed or computed data was correct and remains - * confidential. Applications should not perform any security function - * and should enter a safe failure state. - * - * Implementations may return this error code if they detect an invalid - * state that cannot happen during normal operation and that indicates - * that the implementation's security guarantees no longer hold. Depending - * on the implementation architecture and on its security and safety goals, - * the implementation may forcibly terminate the application. - * - * This error code is intended as a last resort when a security breach - * is detected and it is unsure whether the keystore data is still - * protected. Implementations shall only return this error code - * to report an alarm from a tampering detector, to indicate that - * the confidentiality of stored data can no longer be guaranteed, - * or to indicate that the integrity of previously returned data is now - * considered compromised. Implementations shall not use this error code - * to indicate a hardware failure that merely makes it impossible to - * perform the requested operation (use #PSA_ERROR_COMMUNICATION_FAILURE, - * #PSA_ERROR_STORAGE_FAILURE, #PSA_ERROR_HARDWARE_FAILURE, - * #PSA_ERROR_INSUFFICIENT_ENTROPY or other applicable error code - * instead). - * - * This error indicates an attack against the application. Implementations - * shall not return this error code as a consequence of the behavior of - * the application itself. */ -#define PSA_ERROR_CORRUPTION_DETECTED ((psa_status_t)-151) - -/** There is not enough entropy to generate random data needed - * for the requested action. - * - * This error indicates a failure of a hardware random generator. - * Application writers should note that this error can be returned not - * only by functions whose purpose is to generate random data, such - * as key, IV or nonce generation, but also by functions that execute - * an algorithm with a randomized result, as well as functions that - * use randomization of intermediate computations as a countermeasure - * to certain attacks. - * - * Implementations should avoid returning this error after psa_crypto_init() - * has succeeded. Implementations should generate sufficient - * entropy during initialization and subsequently use a cryptographically - * secure pseudorandom generator (PRNG). However implementations may return - * this error at any time if a policy requires the PRNG to be reseeded - * during normal operation. */ -#define PSA_ERROR_INSUFFICIENT_ENTROPY ((psa_status_t)-148) - -/** The signature, MAC or hash is incorrect. - * - * Verification functions return this error if the verification - * calculations completed successfully, and the value to be verified - * was determined to be incorrect. - * - * If the value to verify has an invalid size, implementations may return - * either #PSA_ERROR_INVALID_ARGUMENT or #PSA_ERROR_INVALID_SIGNATURE. */ -#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) - -/** The decrypted padding is incorrect. - * - * \warning In some protocols, when decrypting data, it is essential that - * the behavior of the application does not depend on whether the padding - * is correct, down to precise timing. Applications should prefer - * protocols that use authenticated encryption rather than plain - * encryption. If the application must perform a decryption of - * unauthenticated data, the application writer should take care not - * to reveal whether the padding is invalid. - * - * Implementations should strive to make valid and invalid padding - * as close as possible to indistinguishable to an external observer. - * In particular, the timing of a decryption operation should not - * depend on the validity of the padding. */ -#define PSA_ERROR_INVALID_PADDING ((psa_status_t)-150) - -/** Return this error when there's insufficient data when attempting - * to read from a resource. */ -#define PSA_ERROR_INSUFFICIENT_DATA ((psa_status_t)-143) - -/** The key handle is not valid. See also :ref:\`key-handles\`. - */ -#define PSA_ERROR_INVALID_HANDLE ((psa_status_t)-136) - -/**@}*/ - -/** \defgroup crypto_types Key and algorithm types - * @{ - */ - -/** An invalid key type value. - * - * Zero is not the encoding of any key type. - */ -#define PSA_KEY_TYPE_NONE ((psa_key_type_t)0x00000000) - -/** Vendor-defined key type flag. - * - * Key types defined by this standard will never have the - * #PSA_KEY_TYPE_VENDOR_FLAG bit set. Vendors who define additional key types - * must use an encoding with the #PSA_KEY_TYPE_VENDOR_FLAG bit set and should - * respect the bitwise structure used by standard encodings whenever practical. - */ -#define PSA_KEY_TYPE_VENDOR_FLAG ((psa_key_type_t)0x80000000) - -#define PSA_KEY_TYPE_CATEGORY_MASK ((psa_key_type_t)0x70000000) -#define PSA_KEY_TYPE_CATEGORY_SYMMETRIC ((psa_key_type_t)0x40000000) -#define PSA_KEY_TYPE_CATEGORY_RAW ((psa_key_type_t)0x50000000) -#define PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY ((psa_key_type_t)0x60000000) -#define PSA_KEY_TYPE_CATEGORY_KEY_PAIR ((psa_key_type_t)0x70000000) - -#define PSA_KEY_TYPE_CATEGORY_FLAG_PAIR ((psa_key_type_t)0x10000000) - -/** Whether a key type is vendor-defined. - * - * See also #PSA_KEY_TYPE_VENDOR_FLAG. - */ -#define PSA_KEY_TYPE_IS_VENDOR_DEFINED(type) \ - (((type) & PSA_KEY_TYPE_VENDOR_FLAG) != 0) - -/** Whether a key type is an unstructured array of bytes. - * - * This encompasses both symmetric keys and non-key data. - */ -#define PSA_KEY_TYPE_IS_UNSTRUCTURED(type) \ - (((type) & PSA_KEY_TYPE_CATEGORY_MASK & ~(psa_key_type_t)0x10000000) == \ - PSA_KEY_TYPE_CATEGORY_SYMMETRIC) - -/** Whether a key type is asymmetric: either a key pair or a public key. */ -#define PSA_KEY_TYPE_IS_ASYMMETRIC(type) \ - (((type) & PSA_KEY_TYPE_CATEGORY_MASK \ - & ~PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) == \ - PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY) -/** Whether a key type is the public part of a key pair. */ -#define PSA_KEY_TYPE_IS_PUBLIC_KEY(type) \ - (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY) -/** Whether a key type is a key pair containing a private part and a public - * part. */ -#define PSA_KEY_TYPE_IS_KEY_PAIR(type) \ - (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_KEY_PAIR) -/** The key pair type corresponding to a public key type. - * - * You may also pass a key pair type as \p type, it will be left unchanged. - * - * \param type A public key type or key pair type. - * - * \return The corresponding key pair type. - * If \p type is not a public key or a key pair, - * the return value is undefined. - */ -#define PSA_KEY_TYPE_KEY_PAIR_OF_PUBLIC_KEY(type) \ - ((type) | PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) -/** The public key type corresponding to a key pair type. - * - * You may also pass a key pair type as \p type, it will be left unchanged. - * - * \param type A public key type or key pair type. - * - * \return The corresponding public key type. - * If \p type is not a public key or a key pair, - * the return value is undefined. - */ -#define PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) \ - ((type) & ~PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) - -/** Raw data. - * - * A "key" of this type cannot be used for any cryptographic operation. - * Applications may use this type to store arbitrary data in the keystore. */ -#define PSA_KEY_TYPE_RAW_DATA ((psa_key_type_t)0x50000001) - -/** HMAC key. - * - * The key policy determines which underlying hash algorithm the key can be - * used for. - * - * HMAC keys should generally have the same size as the underlying hash. - * This size can be calculated with #PSA_HASH_SIZE(\c alg) where - * \c alg is the HMAC algorithm or the underlying hash algorithm. */ -#define PSA_KEY_TYPE_HMAC ((psa_key_type_t)0x51000000) - -/** A secret for key derivation. - * - * The key policy determines which key derivation algorithm the key - * can be used for. - */ -#define PSA_KEY_TYPE_DERIVE ((psa_key_type_t)0x52000000) - -/** Key for a cipher, AEAD or MAC algorithm based on the AES block cipher. - * - * The size of the key can be 16 bytes (AES-128), 24 bytes (AES-192) or - * 32 bytes (AES-256). - */ -#define PSA_KEY_TYPE_AES ((psa_key_type_t)0x40000001) - -/** Key for a cipher or MAC algorithm based on DES or 3DES (Triple-DES). - * - * The size of the key can be 8 bytes (single DES), 16 bytes (2-key 3DES) or - * 24 bytes (3-key 3DES). - * - * Note that single DES and 2-key 3DES are weak and strongly - * deprecated and should only be used to decrypt legacy data. 3-key 3DES - * is weak and deprecated and should only be used in legacy protocols. - */ -#define PSA_KEY_TYPE_DES ((psa_key_type_t)0x40000002) - -/** Key for a cipher, AEAD or MAC algorithm based on the - * Camellia block cipher. */ -#define PSA_KEY_TYPE_CAMELLIA ((psa_key_type_t)0x40000003) - -/** Key for the RC4 stream cipher. - * - * Note that RC4 is weak and deprecated and should only be used in - * legacy protocols. */ -#define PSA_KEY_TYPE_ARC4 ((psa_key_type_t)0x40000004) - -/** Key for the ChaCha20 stream cipher or the Chacha20-Poly1305 AEAD algorithm. - * - * ChaCha20 and the ChaCha20_Poly1305 construction are defined in RFC 7539. - * - * Implementations must support 12-byte nonces, may support 8-byte nonces, - * and should reject other sizes. - */ -#define PSA_KEY_TYPE_CHACHA20 ((psa_key_type_t)0x40000005) - -/** RSA public key. */ -#define PSA_KEY_TYPE_RSA_PUBLIC_KEY ((psa_key_type_t)0x60010000) -/** RSA key pair (private and public key). */ -#define PSA_KEY_TYPE_RSA_KEY_PAIR ((psa_key_type_t)0x70010000) -/** Whether a key type is an RSA key (pair or public-only). */ -#define PSA_KEY_TYPE_IS_RSA(type) \ - (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY) - -#define PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE ((psa_key_type_t)0x60030000) -#define PSA_KEY_TYPE_ECC_KEY_PAIR_BASE ((psa_key_type_t)0x70030000) -#define PSA_KEY_TYPE_ECC_CURVE_MASK ((psa_key_type_t)0x0000ffff) -/** Elliptic curve key pair. - * - * \param curve A value of type ::psa_ecc_curve_t that identifies the - * ECC curve to be used. - */ -#define PSA_KEY_TYPE_ECC_KEY_PAIR(curve) \ - (PSA_KEY_TYPE_ECC_KEY_PAIR_BASE | (curve)) -/** Elliptic curve public key. - * - * \param curve A value of type ::psa_ecc_curve_t that identifies the - * ECC curve to be used. - */ -#define PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve) \ - (PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE | (curve)) - -/** Whether a key type is an elliptic curve key (pair or public-only). */ -#define PSA_KEY_TYPE_IS_ECC(type) \ - ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) & \ - ~PSA_KEY_TYPE_ECC_CURVE_MASK) == PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE) -/** Whether a key type is an elliptic curve key pair. */ -#define PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type) \ - (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \ - PSA_KEY_TYPE_ECC_KEY_PAIR_BASE) -/** Whether a key type is an elliptic curve public key. */ -#define PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(type) \ - (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \ - PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE) - -/** Extract the curve from an elliptic curve key type. */ -#define PSA_KEY_TYPE_GET_CURVE(type) \ - ((psa_ecc_curve_t) (PSA_KEY_TYPE_IS_ECC(type) ? \ - ((type) & PSA_KEY_TYPE_ECC_CURVE_MASK) : \ - 0)) - -/* The encoding of curve identifiers is currently aligned with the - * TLS Supported Groups Registry (formerly known as the - * TLS EC Named Curve Registry) - * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 - * The values are defined by RFC 8422 and RFC 7027. */ -#define PSA_ECC_CURVE_SECT163K1 ((psa_ecc_curve_t) 0x0001) -#define PSA_ECC_CURVE_SECT163R1 ((psa_ecc_curve_t) 0x0002) -#define PSA_ECC_CURVE_SECT163R2 ((psa_ecc_curve_t) 0x0003) -#define PSA_ECC_CURVE_SECT193R1 ((psa_ecc_curve_t) 0x0004) -#define PSA_ECC_CURVE_SECT193R2 ((psa_ecc_curve_t) 0x0005) -#define PSA_ECC_CURVE_SECT233K1 ((psa_ecc_curve_t) 0x0006) -#define PSA_ECC_CURVE_SECT233R1 ((psa_ecc_curve_t) 0x0007) -#define PSA_ECC_CURVE_SECT239K1 ((psa_ecc_curve_t) 0x0008) -#define PSA_ECC_CURVE_SECT283K1 ((psa_ecc_curve_t) 0x0009) -#define PSA_ECC_CURVE_SECT283R1 ((psa_ecc_curve_t) 0x000a) -#define PSA_ECC_CURVE_SECT409K1 ((psa_ecc_curve_t) 0x000b) -#define PSA_ECC_CURVE_SECT409R1 ((psa_ecc_curve_t) 0x000c) -#define PSA_ECC_CURVE_SECT571K1 ((psa_ecc_curve_t) 0x000d) -#define PSA_ECC_CURVE_SECT571R1 ((psa_ecc_curve_t) 0x000e) -#define PSA_ECC_CURVE_SECP160K1 ((psa_ecc_curve_t) 0x000f) -#define PSA_ECC_CURVE_SECP160R1 ((psa_ecc_curve_t) 0x0010) -#define PSA_ECC_CURVE_SECP160R2 ((psa_ecc_curve_t) 0x0011) -#define PSA_ECC_CURVE_SECP192K1 ((psa_ecc_curve_t) 0x0012) -#define PSA_ECC_CURVE_SECP192R1 ((psa_ecc_curve_t) 0x0013) -#define PSA_ECC_CURVE_SECP224K1 ((psa_ecc_curve_t) 0x0014) -#define PSA_ECC_CURVE_SECP224R1 ((psa_ecc_curve_t) 0x0015) -#define PSA_ECC_CURVE_SECP256K1 ((psa_ecc_curve_t) 0x0016) -#define PSA_ECC_CURVE_SECP256R1 ((psa_ecc_curve_t) 0x0017) -#define PSA_ECC_CURVE_SECP384R1 ((psa_ecc_curve_t) 0x0018) -#define PSA_ECC_CURVE_SECP521R1 ((psa_ecc_curve_t) 0x0019) -#define PSA_ECC_CURVE_BRAINPOOL_P256R1 ((psa_ecc_curve_t) 0x001a) -#define PSA_ECC_CURVE_BRAINPOOL_P384R1 ((psa_ecc_curve_t) 0x001b) -#define PSA_ECC_CURVE_BRAINPOOL_P512R1 ((psa_ecc_curve_t) 0x001c) -/** Curve25519. - * - * This is the curve defined in Bernstein et al., - * _Curve25519: new Diffie-Hellman speed records_, LNCS 3958, 2006. - * The algorithm #PSA_ALG_ECDH performs X25519 when used with this curve. - */ -#define PSA_ECC_CURVE_CURVE25519 ((psa_ecc_curve_t) 0x001d) -/** Curve448 - * - * This is the curve defined in Hamburg, - * _Ed448-Goldilocks, a new elliptic curve_, NIST ECC Workshop, 2015. - * The algorithm #PSA_ALG_ECDH performs X448 when used with this curve. - */ -#define PSA_ECC_CURVE_CURVE448 ((psa_ecc_curve_t) 0x001e) - -/** Minimum value for a vendor-defined ECC curve identifier - * - * The range for vendor-defined curve identifiers is a subset of the IANA - * registry private use range, `0xfe00` - `0xfeff`. - */ -#define PSA_ECC_CURVE_VENDOR_MIN ((psa_ecc_curve_t) 0xfe00) -/** Maximum value for a vendor-defined ECC curve identifier - * - * The range for vendor-defined curve identifiers is a subset of the IANA - * registry private use range, `0xfe00` - `0xfeff`. - */ -#define PSA_ECC_CURVE_VENDOR_MAX ((psa_ecc_curve_t) 0xfe7f) - -#define PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE ((psa_key_type_t)0x60040000) -#define PSA_KEY_TYPE_DH_KEY_PAIR_BASE ((psa_key_type_t)0x70040000) -#define PSA_KEY_TYPE_DH_GROUP_MASK ((psa_key_type_t)0x0000ffff) -/** Diffie-Hellman key pair. - * - * \param group A value of type ::psa_dh_group_t that identifies the - * Diffie-Hellman group to be used. - */ -#define PSA_KEY_TYPE_DH_KEY_PAIR(group) \ - (PSA_KEY_TYPE_DH_KEY_PAIR_BASE | (group)) -/** Diffie-Hellman public key. - * - * \param group A value of type ::psa_dh_group_t that identifies the - * Diffie-Hellman group to be used. - */ -#define PSA_KEY_TYPE_DH_PUBLIC_KEY(group) \ - (PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE | (group)) - -/** Whether a key type is a Diffie-Hellman key (pair or public-only). */ -#define PSA_KEY_TYPE_IS_DH(type) \ - ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) & \ - ~PSA_KEY_TYPE_DH_GROUP_MASK) == PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE) -/** Whether a key type is a Diffie-Hellman key pair. */ -#define PSA_KEY_TYPE_IS_DH_KEY_PAIR(type) \ - (((type) & ~PSA_KEY_TYPE_DH_GROUP_MASK) == \ - PSA_KEY_TYPE_DH_KEY_PAIR_BASE) -/** Whether a key type is a Diffie-Hellman public key. */ -#define PSA_KEY_TYPE_IS_DH_PUBLIC_KEY(type) \ - (((type) & ~PSA_KEY_TYPE_DH_GROUP_MASK) == \ - PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE) - -/** Extract the group from a Diffie-Hellman key type. */ -#define PSA_KEY_TYPE_GET_GROUP(type) \ - ((psa_dh_group_t) (PSA_KEY_TYPE_IS_DH(type) ? \ - ((type) & PSA_KEY_TYPE_DH_GROUP_MASK) : \ - 0)) - -/* The encoding of group identifiers is currently aligned with the - * TLS Supported Groups Registry (formerly known as the - * TLS EC Named Curve Registry) - * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 - * The values are defined by RFC 7919. */ -#define PSA_DH_GROUP_FFDHE2048 ((psa_dh_group_t) 0x0100) -#define PSA_DH_GROUP_FFDHE3072 ((psa_dh_group_t) 0x0101) -#define PSA_DH_GROUP_FFDHE4096 ((psa_dh_group_t) 0x0102) -#define PSA_DH_GROUP_FFDHE6144 ((psa_dh_group_t) 0x0103) -#define PSA_DH_GROUP_FFDHE8192 ((psa_dh_group_t) 0x0104) - -/** Minimum value for a vendor-defined Diffie Hellman group identifier - * - * The range for vendor-defined group identifiers is a subset of the IANA - * registry private use range, `0x01fc` - `0x01ff`. - */ -#define PSA_DH_GROUP_VENDOR_MIN ((psa_dh_group_t) 0x01fc) -/** Maximum value for a vendor-defined Diffie Hellman group identifier - * - * The range for vendor-defined group identifiers is a subset of the IANA - * registry private use range, `0x01fc` - `0x01ff`. - */ -#define PSA_DH_GROUP_VENDOR_MAX ((psa_dh_group_t) 0x01fd) - -/** The block size of a block cipher. - * - * \param type A cipher key type (value of type #psa_key_type_t). - * - * \return The block size for a block cipher, or 1 for a stream cipher. - * The return value is undefined if \p type is not a supported - * cipher key type. - * - * \note It is possible to build stream cipher algorithms on top of a block - * cipher, for example CTR mode (#PSA_ALG_CTR). - * This macro only takes the key type into account, so it cannot be - * used to determine the size of the data that #psa_cipher_update() - * might buffer for future processing in general. - * - * \note This macro returns a compile-time constant if its argument is one. - * - * \warning This macro may evaluate its argument multiple times. - */ -#define PSA_BLOCK_CIPHER_BLOCK_SIZE(type) \ - ( \ - (type) == PSA_KEY_TYPE_AES ? 16 : \ - (type) == PSA_KEY_TYPE_DES ? 8 : \ - (type) == PSA_KEY_TYPE_CAMELLIA ? 16 : \ - (type) == PSA_KEY_TYPE_ARC4 ? 1 : \ - (type) == PSA_KEY_TYPE_CHACHA20 ? 1 : \ - 0) - -/** Vendor-defined algorithm flag. - * - * Algorithms defined by this standard will never have the #PSA_ALG_VENDOR_FLAG - * bit set. Vendors who define additional algorithms must use an encoding with - * the #PSA_ALG_VENDOR_FLAG bit set and should respect the bitwise structure - * used by standard encodings whenever practical. - */ -#define PSA_ALG_VENDOR_FLAG ((psa_algorithm_t)0x80000000) - -#define PSA_ALG_CATEGORY_MASK ((psa_algorithm_t)0x7f000000) -#define PSA_ALG_CATEGORY_HASH ((psa_algorithm_t)0x01000000) -#define PSA_ALG_CATEGORY_MAC ((psa_algorithm_t)0x02000000) -#define PSA_ALG_CATEGORY_CIPHER ((psa_algorithm_t)0x04000000) -#define PSA_ALG_CATEGORY_AEAD ((psa_algorithm_t)0x06000000) -#define PSA_ALG_CATEGORY_SIGN ((psa_algorithm_t)0x10000000) -#define PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION ((psa_algorithm_t)0x12000000) -#define PSA_ALG_CATEGORY_KEY_DERIVATION ((psa_algorithm_t)0x20000000) -#define PSA_ALG_CATEGORY_KEY_AGREEMENT ((psa_algorithm_t)0x30000000) - -/** Whether an algorithm is vendor-defined. - * - * See also #PSA_ALG_VENDOR_FLAG. - */ -#define PSA_ALG_IS_VENDOR_DEFINED(alg) \ - (((alg) & PSA_ALG_VENDOR_FLAG) != 0) - -/** Whether the specified algorithm is a hash algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a hash algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_HASH(alg) \ - (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_HASH) - -/** Whether the specified algorithm is a MAC algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a MAC algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_MAC(alg) \ - (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_MAC) - -/** Whether the specified algorithm is a symmetric cipher algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a symmetric cipher algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_CIPHER(alg) \ - (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_CIPHER) - -/** Whether the specified algorithm is an authenticated encryption - * with associated data (AEAD) algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is an AEAD algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_AEAD(alg) \ - (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_AEAD) - -/** Whether the specified algorithm is a public-key signature algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a public-key signature algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_SIGN(alg) \ - (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_SIGN) - -/** Whether the specified algorithm is a public-key encryption algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a public-key encryption algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg) \ - (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION) - -/** Whether the specified algorithm is a key agreement algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a key agreement algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_KEY_AGREEMENT(alg) \ - (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_AGREEMENT) - -/** Whether the specified algorithm is a key derivation algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a key derivation algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_KEY_DERIVATION(alg) \ - (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_DERIVATION) - -#define PSA_ALG_HASH_MASK ((psa_algorithm_t)0x000000ff) -/** MD2 */ -#define PSA_ALG_MD2 ((psa_algorithm_t)0x01000001) -/** MD4 */ -#define PSA_ALG_MD4 ((psa_algorithm_t)0x01000002) -/** MD5 */ -#define PSA_ALG_MD5 ((psa_algorithm_t)0x01000003) -/** PSA_ALG_RIPEMD160 */ -#define PSA_ALG_RIPEMD160 ((psa_algorithm_t)0x01000004) -/** SHA1 */ -#define PSA_ALG_SHA_1 ((psa_algorithm_t)0x01000005) -/** SHA2-224 */ -#define PSA_ALG_SHA_224 ((psa_algorithm_t)0x01000008) -/** SHA2-256 */ -#define PSA_ALG_SHA_256 ((psa_algorithm_t)0x01000009) -/** SHA2-384 */ -#define PSA_ALG_SHA_384 ((psa_algorithm_t)0x0100000a) -/** SHA2-512 */ -#define PSA_ALG_SHA_512 ((psa_algorithm_t)0x0100000b) -/** SHA2-512/224 */ -#define PSA_ALG_SHA_512_224 ((psa_algorithm_t)0x0100000c) -/** SHA2-512/256 */ -#define PSA_ALG_SHA_512_256 ((psa_algorithm_t)0x0100000d) -/** SHA3-224 */ -#define PSA_ALG_SHA3_224 ((psa_algorithm_t)0x01000010) -/** SHA3-256 */ -#define PSA_ALG_SHA3_256 ((psa_algorithm_t)0x01000011) -/** SHA3-384 */ -#define PSA_ALG_SHA3_384 ((psa_algorithm_t)0x01000012) -/** SHA3-512 */ -#define PSA_ALG_SHA3_512 ((psa_algorithm_t)0x01000013) - -/** In a hash-and-sign algorithm policy, allow any hash algorithm. - * - * This value may be used to form the algorithm usage field of a policy - * for a signature algorithm that is parametrized by a hash. The key - * may then be used to perform operations using the same signature - * algorithm parametrized with any supported hash. - * - * That is, suppose that `PSA_xxx_SIGNATURE` is one of the following macros: - * - #PSA_ALG_RSA_PKCS1V15_SIGN, #PSA_ALG_RSA_PSS, - * - #PSA_ALG_ECDSA, #PSA_ALG_DETERMINISTIC_ECDSA. - * Then you may create and use a key as follows: - * - Set the key usage field using #PSA_ALG_ANY_HASH, for example: - * ``` - * psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); // or VERIFY - * psa_set_key_algorithm(&attributes, PSA_xxx_SIGNATURE(PSA_ALG_ANY_HASH)); - * ``` - * - Import or generate key material. - * - Call psa_sign_hash() or psa_verify_hash(), passing - * an algorithm built from `PSA_xxx_SIGNATURE` and a specific hash. Each - * call to sign or verify a message may use a different hash. - * ``` - * psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA_256), ...); - * psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA_512), ...); - * psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA3_256), ...); - * ``` - * - * This value may not be used to build other algorithms that are - * parametrized over a hash. For any valid use of this macro to build - * an algorithm \c alg, #PSA_ALG_IS_HASH_AND_SIGN(\c alg) is true. - * - * This value may not be used to build an algorithm specification to - * perform an operation. It is only valid to build policies. - */ -#define PSA_ALG_ANY_HASH ((psa_algorithm_t)0x010000ff) - -#define PSA_ALG_MAC_SUBCATEGORY_MASK ((psa_algorithm_t)0x00c00000) -#define PSA_ALG_HMAC_BASE ((psa_algorithm_t)0x02800000) -/** Macro to build an HMAC algorithm. - * - * For example, #PSA_ALG_HMAC(#PSA_ALG_SHA_256) is HMAC-SHA-256. - * - * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true). - * - * \return The corresponding HMAC algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_HMAC(hash_alg) \ - (PSA_ALG_HMAC_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) - -#define PSA_ALG_HMAC_GET_HASH(hmac_alg) \ - (PSA_ALG_CATEGORY_HASH | ((hmac_alg) & PSA_ALG_HASH_MASK)) - -/** Whether the specified algorithm is an HMAC algorithm. - * - * HMAC is a family of MAC algorithms that are based on a hash function. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is an HMAC algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_HMAC(alg) \ - (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \ - PSA_ALG_HMAC_BASE) - -/* In the encoding of a MAC algorithm, the bits corresponding to - * PSA_ALG_MAC_TRUNCATION_MASK encode the length to which the MAC is - * truncated. As an exception, the value 0 means the untruncated algorithm, - * whatever its length is. The length is encoded in 6 bits, so it can - * reach up to 63; the largest MAC is 64 bytes so its trivial truncation - * to full length is correctly encoded as 0 and any non-trivial truncation - * is correctly encoded as a value between 1 and 63. */ -#define PSA_ALG_MAC_TRUNCATION_MASK ((psa_algorithm_t)0x00003f00) -#define PSA_MAC_TRUNCATION_OFFSET 8 - -/** Macro to build a truncated MAC algorithm. - * - * A truncated MAC algorithm is identical to the corresponding MAC - * algorithm except that the MAC value for the truncated algorithm - * consists of only the first \p mac_length bytes of the MAC value - * for the untruncated algorithm. - * - * \note This macro may allow constructing algorithm identifiers that - * are not valid, either because the specified length is larger - * than the untruncated MAC or because the specified length is - * smaller than permitted by the implementation. - * - * \note It is implementation-defined whether a truncated MAC that - * is truncated to the same length as the MAC of the untruncated - * algorithm is considered identical to the untruncated algorithm - * for policy comparison purposes. - * - * \param mac_alg A MAC algorithm identifier (value of type - * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg) - * is true). This may be a truncated or untruncated - * MAC algorithm. - * \param mac_length Desired length of the truncated MAC in bytes. - * This must be at most the full length of the MAC - * and must be at least an implementation-specified - * minimum. The implementation-specified minimum - * shall not be zero. - * - * \return The corresponding MAC algorithm with the specified - * length. - * \return Unspecified if \p alg is not a supported - * MAC algorithm or if \p mac_length is too small or - * too large for the specified MAC algorithm. - */ -#define PSA_ALG_TRUNCATED_MAC(mac_alg, mac_length) \ - (((mac_alg) & ~PSA_ALG_MAC_TRUNCATION_MASK) | \ - ((mac_length) << PSA_MAC_TRUNCATION_OFFSET & PSA_ALG_MAC_TRUNCATION_MASK)) - -/** Macro to build the base MAC algorithm corresponding to a truncated - * MAC algorithm. - * - * \param mac_alg A MAC algorithm identifier (value of type - * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg) - * is true). This may be a truncated or untruncated - * MAC algorithm. - * - * \return The corresponding base MAC algorithm. - * \return Unspecified if \p alg is not a supported - * MAC algorithm. - */ -#define PSA_ALG_FULL_LENGTH_MAC(mac_alg) \ - ((mac_alg) & ~PSA_ALG_MAC_TRUNCATION_MASK) - -/** Length to which a MAC algorithm is truncated. - * - * \param mac_alg A MAC algorithm identifier (value of type - * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg) - * is true). - * - * \return Length of the truncated MAC in bytes. - * \return 0 if \p alg is a non-truncated MAC algorithm. - * \return Unspecified if \p alg is not a supported - * MAC algorithm. - */ -#define PSA_MAC_TRUNCATED_LENGTH(mac_alg) \ - (((mac_alg) & PSA_ALG_MAC_TRUNCATION_MASK) >> PSA_MAC_TRUNCATION_OFFSET) - -#define PSA_ALG_CIPHER_MAC_BASE ((psa_algorithm_t)0x02c00000) -/** The CBC-MAC construction over a block cipher - * - * \warning CBC-MAC is insecure in many cases. - * A more secure mode, such as #PSA_ALG_CMAC, is recommended. - */ -#define PSA_ALG_CBC_MAC ((psa_algorithm_t)0x02c00001) -/** The CMAC construction over a block cipher */ -#define PSA_ALG_CMAC ((psa_algorithm_t)0x02c00002) - -/** Whether the specified algorithm is a MAC algorithm based on a block cipher. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a MAC algorithm based on a block cipher, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) \ - (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \ - PSA_ALG_CIPHER_MAC_BASE) - -#define PSA_ALG_CIPHER_STREAM_FLAG ((psa_algorithm_t)0x00800000) -#define PSA_ALG_CIPHER_FROM_BLOCK_FLAG ((psa_algorithm_t)0x00400000) - -/** Whether the specified algorithm is a stream cipher. - * - * A stream cipher is a symmetric cipher that encrypts or decrypts messages - * by applying a bitwise-xor with a stream of bytes that is generated - * from a key. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a stream cipher algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier or if it is not a symmetric cipher algorithm. - */ -#define PSA_ALG_IS_STREAM_CIPHER(alg) \ - (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_CIPHER_STREAM_FLAG)) == \ - (PSA_ALG_CATEGORY_CIPHER | PSA_ALG_CIPHER_STREAM_FLAG)) - -/** The ARC4 stream cipher algorithm. - */ -#define PSA_ALG_ARC4 ((psa_algorithm_t)0x04800001) - -/** The ChaCha20 stream cipher. - * - * ChaCha20 is defined in RFC 7539. - * - * The nonce size for psa_cipher_set_iv() or psa_cipher_generate_iv() - * must be 12. - * - * The initial block counter is always 0. - * - */ -#define PSA_ALG_CHACHA20 ((psa_algorithm_t)0x04800005) - -/** The CTR stream cipher mode. - * - * CTR is a stream cipher which is built from a block cipher. - * The underlying block cipher is determined by the key type. - * For example, to use AES-128-CTR, use this algorithm with - * a key of type #PSA_KEY_TYPE_AES and a length of 128 bits (16 bytes). - */ -#define PSA_ALG_CTR ((psa_algorithm_t)0x04c00001) - -/** The CFB stream cipher mode. - * - * The underlying block cipher is determined by the key type. - */ -#define PSA_ALG_CFB ((psa_algorithm_t)0x04c00002) - -/** The OFB stream cipher mode. - * - * The underlying block cipher is determined by the key type. - */ -#define PSA_ALG_OFB ((psa_algorithm_t)0x04c00003) - -/** The XTS cipher mode. - * - * XTS is a cipher mode which is built from a block cipher. It requires at - * least one full block of input, but beyond this minimum the input - * does not need to be a whole number of blocks. - */ -#define PSA_ALG_XTS ((psa_algorithm_t)0x044000ff) - -/** The CBC block cipher chaining mode, with no padding. - * - * The underlying block cipher is determined by the key type. - * - * This symmetric cipher mode can only be used with messages whose lengths - * are whole number of blocks for the chosen block cipher. - */ -#define PSA_ALG_CBC_NO_PADDING ((psa_algorithm_t)0x04600100) - -/** The CBC block cipher chaining mode with PKCS#7 padding. - * - * The underlying block cipher is determined by the key type. - * - * This is the padding method defined by PKCS#7 (RFC 2315) §10.3. - */ -#define PSA_ALG_CBC_PKCS7 ((psa_algorithm_t)0x04600101) - -#define PSA_ALG_AEAD_FROM_BLOCK_FLAG ((psa_algorithm_t)0x00400000) - -/** Whether the specified algorithm is an AEAD mode on a block cipher. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is an AEAD algorithm which is an AEAD mode based on - * a block cipher, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) \ - (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_AEAD_FROM_BLOCK_FLAG)) == \ - (PSA_ALG_CATEGORY_AEAD | PSA_ALG_AEAD_FROM_BLOCK_FLAG)) - -/** The CCM authenticated encryption algorithm. - * - * The underlying block cipher is determined by the key type. - */ -#define PSA_ALG_CCM ((psa_algorithm_t)0x06401001) - -/** The GCM authenticated encryption algorithm. - * - * The underlying block cipher is determined by the key type. - */ -#define PSA_ALG_GCM ((psa_algorithm_t)0x06401002) - -/** The Chacha20-Poly1305 AEAD algorithm. - * - * The ChaCha20_Poly1305 construction is defined in RFC 7539. - * - * Implementations must support 12-byte nonces, may support 8-byte nonces, - * and should reject other sizes. - * - * Implementations must support 16-byte tags and should reject other sizes. - */ -#define PSA_ALG_CHACHA20_POLY1305 ((psa_algorithm_t)0x06001005) - -/* In the encoding of a AEAD algorithm, the bits corresponding to - * PSA_ALG_AEAD_TAG_LENGTH_MASK encode the length of the AEAD tag. - * The constants for default lengths follow this encoding. - */ -#define PSA_ALG_AEAD_TAG_LENGTH_MASK ((psa_algorithm_t)0x00003f00) -#define PSA_AEAD_TAG_LENGTH_OFFSET 8 - -/** Macro to build a shortened AEAD algorithm. - * - * A shortened AEAD algorithm is similar to the corresponding AEAD - * algorithm, but has an authentication tag that consists of fewer bytes. - * Depending on the algorithm, the tag length may affect the calculation - * of the ciphertext. - * - * \param aead_alg An AEAD algorithm identifier (value of type - * #psa_algorithm_t such that #PSA_ALG_IS_AEAD(\p alg) - * is true). - * \param tag_length Desired length of the authentication tag in bytes. - * - * \return The corresponding AEAD algorithm with the specified - * length. - * \return Unspecified if \p alg is not a supported - * AEAD algorithm or if \p tag_length is not valid - * for the specified AEAD algorithm. - */ -#define PSA_ALG_AEAD_WITH_TAG_LENGTH(aead_alg, tag_length) \ - (((aead_alg) & ~PSA_ALG_AEAD_TAG_LENGTH_MASK) | \ - ((tag_length) << PSA_AEAD_TAG_LENGTH_OFFSET & \ - PSA_ALG_AEAD_TAG_LENGTH_MASK)) - -/** Calculate the corresponding AEAD algorithm with the default tag length. - * - * \param aead_alg An AEAD algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * - * \return The corresponding AEAD algorithm with the default - * tag length for that algorithm. - */ -#define PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH(aead_alg) \ - ( \ - PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, PSA_ALG_CCM) \ - PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, PSA_ALG_GCM) \ - PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, PSA_ALG_CHACHA20_POLY1305) \ - 0) -#define PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, ref) \ - PSA_ALG_AEAD_WITH_TAG_LENGTH(aead_alg, 0) == \ - PSA_ALG_AEAD_WITH_TAG_LENGTH(ref, 0) ? \ - ref : - -#define PSA_ALG_RSA_PKCS1V15_SIGN_BASE ((psa_algorithm_t)0x10020000) -/** RSA PKCS#1 v1.5 signature with hashing. - * - * This is the signature scheme defined by RFC 8017 - * (PKCS#1: RSA Cryptography Specifications) under the name - * RSASSA-PKCS1-v1_5. - * - * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true). - * This includes #PSA_ALG_ANY_HASH - * when specifying the algorithm in a usage policy. - * - * \return The corresponding RSA PKCS#1 v1.5 signature algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_RSA_PKCS1V15_SIGN(hash_alg) \ - (PSA_ALG_RSA_PKCS1V15_SIGN_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) -/** Raw PKCS#1 v1.5 signature. - * - * The input to this algorithm is the DigestInfo structure used by - * RFC 8017 (PKCS#1: RSA Cryptography Specifications), §9.2 - * steps 3–6. - */ -#define PSA_ALG_RSA_PKCS1V15_SIGN_RAW PSA_ALG_RSA_PKCS1V15_SIGN_BASE -#define PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) \ - (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PKCS1V15_SIGN_BASE) - -#define PSA_ALG_RSA_PSS_BASE ((psa_algorithm_t)0x10030000) -/** RSA PSS signature with hashing. - * - * This is the signature scheme defined by RFC 8017 - * (PKCS#1: RSA Cryptography Specifications) under the name - * RSASSA-PSS, with the message generation function MGF1, and with - * a salt length equal to the length of the hash. The specified - * hash algorithm is used to hash the input message, to create the - * salted hash, and for the mask generation. - * - * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true). - * This includes #PSA_ALG_ANY_HASH - * when specifying the algorithm in a usage policy. - * - * \return The corresponding RSA PSS signature algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_RSA_PSS(hash_alg) \ - (PSA_ALG_RSA_PSS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) -#define PSA_ALG_IS_RSA_PSS(alg) \ - (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PSS_BASE) - -#define PSA_ALG_ECDSA_BASE ((psa_algorithm_t)0x10060000) -/** ECDSA signature with hashing. - * - * This is the ECDSA signature scheme defined by ANSI X9.62, - * with a random per-message secret number (*k*). - * - * The representation of the signature as a byte string consists of - * the concatentation of the signature values *r* and *s*. Each of - * *r* and *s* is encoded as an *N*-octet string, where *N* is the length - * of the base point of the curve in octets. Each value is represented - * in big-endian order (most significant octet first). - * - * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true). - * This includes #PSA_ALG_ANY_HASH - * when specifying the algorithm in a usage policy. - * - * \return The corresponding ECDSA signature algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_ECDSA(hash_alg) \ - (PSA_ALG_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) -/** ECDSA signature without hashing. - * - * This is the same signature scheme as #PSA_ALG_ECDSA(), but - * without specifying a hash algorithm. This algorithm may only be - * used to sign or verify a sequence of bytes that should be an - * already-calculated hash. Note that the input is padded with - * zeros on the left or truncated on the left as required to fit - * the curve size. - */ -#define PSA_ALG_ECDSA_ANY PSA_ALG_ECDSA_BASE -#define PSA_ALG_DETERMINISTIC_ECDSA_BASE ((psa_algorithm_t)0x10070000) -/** Deterministic ECDSA signature with hashing. - * - * This is the deterministic ECDSA signature scheme defined by RFC 6979. - * - * The representation of a signature is the same as with #PSA_ALG_ECDSA(). - * - * Note that when this algorithm is used for verification, signatures - * made with randomized ECDSA (#PSA_ALG_ECDSA(\p hash_alg)) with the - * same private key are accepted. In other words, - * #PSA_ALG_DETERMINISTIC_ECDSA(\p hash_alg) differs from - * #PSA_ALG_ECDSA(\p hash_alg) only for signature, not for verification. - * - * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true). - * This includes #PSA_ALG_ANY_HASH - * when specifying the algorithm in a usage policy. - * - * \return The corresponding deterministic ECDSA signature - * algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_DETERMINISTIC_ECDSA(hash_alg) \ - (PSA_ALG_DETERMINISTIC_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) -#define PSA_ALG_ECDSA_DETERMINISTIC_FLAG ((psa_algorithm_t)0x00010000) -#define PSA_ALG_IS_ECDSA(alg) \ - (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_ECDSA_DETERMINISTIC_FLAG) == \ - PSA_ALG_ECDSA_BASE) -#define PSA_ALG_ECDSA_IS_DETERMINISTIC(alg) \ - (((alg) & PSA_ALG_ECDSA_DETERMINISTIC_FLAG) != 0) -#define PSA_ALG_IS_DETERMINISTIC_ECDSA(alg) \ - (PSA_ALG_IS_ECDSA(alg) && PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) -#define PSA_ALG_IS_RANDOMIZED_ECDSA(alg) \ - (PSA_ALG_IS_ECDSA(alg) && !PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) - -/** Whether the specified algorithm is a hash-and-sign algorithm. - * - * Hash-and-sign algorithms are public-key signature algorithms structured - * in two parts: first the calculation of a hash in a way that does not - * depend on the key, then the calculation of a signature from the - * hash value and the key. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a hash-and-sign algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_HASH_AND_SIGN(alg) \ - (PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || \ - PSA_ALG_IS_ECDSA(alg)) - -/** Get the hash used by a hash-and-sign signature algorithm. - * - * A hash-and-sign algorithm is a signature algorithm which is - * composed of two phases: first a hashing phase which does not use - * the key and produces a hash of the input message, then a signing - * phase which only uses the hash and the key and not the message - * itself. - * - * \param alg A signature algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_SIGN(\p alg) is true). - * - * \return The underlying hash algorithm if \p alg is a hash-and-sign - * algorithm. - * \return 0 if \p alg is a signature algorithm that does not - * follow the hash-and-sign structure. - * \return Unspecified if \p alg is not a signature algorithm or - * if it is not supported by the implementation. - */ -#define PSA_ALG_SIGN_GET_HASH(alg) \ - (PSA_ALG_IS_HASH_AND_SIGN(alg) ? \ - ((alg) & PSA_ALG_HASH_MASK) == 0 ? /*"raw" algorithm*/ 0 : \ - ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ - 0) - -/** RSA PKCS#1 v1.5 encryption. - */ -#define PSA_ALG_RSA_PKCS1V15_CRYPT ((psa_algorithm_t)0x12020000) - -#define PSA_ALG_RSA_OAEP_BASE ((psa_algorithm_t)0x12030000) -/** RSA OAEP encryption. - * - * This is the encryption scheme defined by RFC 8017 - * (PKCS#1: RSA Cryptography Specifications) under the name - * RSAES-OAEP, with the message generation function MGF1. - * - * \param hash_alg The hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true) to use - * for MGF1. - * - * \return The corresponding RSA OAEP signature algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_RSA_OAEP(hash_alg) \ - (PSA_ALG_RSA_OAEP_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) -#define PSA_ALG_IS_RSA_OAEP(alg) \ - (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_OAEP_BASE) -#define PSA_ALG_RSA_OAEP_GET_HASH(alg) \ - (PSA_ALG_IS_RSA_OAEP(alg) ? \ - ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ - 0) - -#define PSA_ALG_HKDF_BASE ((psa_algorithm_t)0x20000100) -/** Macro to build an HKDF algorithm. - * - * For example, `PSA_ALG_HKDF(PSA_ALG_SHA256)` is HKDF using HMAC-SHA-256. - * - * This key derivation algorithm uses the following inputs: - * - #PSA_KEY_DERIVATION_INPUT_SALT is the salt used in the "extract" step. - * It is optional; if omitted, the derivation uses an empty salt. - * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key used in the "extract" step. - * - #PSA_KEY_DERIVATION_INPUT_INFO is the info string used in the "expand" step. - * You must pass #PSA_KEY_DERIVATION_INPUT_SALT before #PSA_KEY_DERIVATION_INPUT_SECRET. - * You may pass #PSA_KEY_DERIVATION_INPUT_INFO at any time after steup and before - * starting to generate output. - * - * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true). - * - * \return The corresponding HKDF algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_HKDF(hash_alg) \ - (PSA_ALG_HKDF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) -/** Whether the specified algorithm is an HKDF algorithm. - * - * HKDF is a family of key derivation algorithms that are based on a hash - * function and the HMAC construction. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \c alg is an HKDF algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \c alg is not a supported - * key derivation algorithm identifier. - */ -#define PSA_ALG_IS_HKDF(alg) \ - (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_BASE) -#define PSA_ALG_HKDF_GET_HASH(hkdf_alg) \ - (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) - -#define PSA_ALG_TLS12_PRF_BASE ((psa_algorithm_t)0x20000200) -/** Macro to build a TLS-1.2 PRF algorithm. - * - * TLS 1.2 uses a custom pseudorandom function (PRF) for key schedule, - * specified in Section 5 of RFC 5246. It is based on HMAC and can be - * used with either SHA-256 or SHA-384. - * - * This key derivation algorithm uses the following inputs, which must be - * passed in the order given here: - * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed. - * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key. - * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label. - * - * For the application to TLS-1.2 key expansion, the seed is the - * concatenation of ServerHello.Random + ClientHello.Random, - * and the label is "key expansion". - * - * For example, `PSA_ALG_TLS12_PRF(PSA_ALG_SHA256)` represents the - * TLS 1.2 PRF using HMAC-SHA-256. - * - * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true). - * - * \return The corresponding TLS-1.2 PRF algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_TLS12_PRF(hash_alg) \ - (PSA_ALG_TLS12_PRF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) - -/** Whether the specified algorithm is a TLS-1.2 PRF algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \c alg is a TLS-1.2 PRF algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \c alg is not a supported - * key derivation algorithm identifier. - */ -#define PSA_ALG_IS_TLS12_PRF(alg) \ - (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_TLS12_PRF_BASE) -#define PSA_ALG_TLS12_PRF_GET_HASH(hkdf_alg) \ - (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) - -#define PSA_ALG_TLS12_PSK_TO_MS_BASE ((psa_algorithm_t)0x20000300) -/** Macro to build a TLS-1.2 PSK-to-MasterSecret algorithm. - * - * In a pure-PSK handshake in TLS 1.2, the master secret is derived - * from the PreSharedKey (PSK) through the application of padding - * (RFC 4279, Section 2) and the TLS-1.2 PRF (RFC 5246, Section 5). - * The latter is based on HMAC and can be used with either SHA-256 - * or SHA-384. - * - * This key derivation algorithm uses the following inputs, which must be - * passed in the order given here: - * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed. - * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key. - * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label. - * - * For the application to TLS-1.2, the seed (which is - * forwarded to the TLS-1.2 PRF) is the concatenation of the - * ClientHello.Random + ServerHello.Random, - * and the label is "master secret" or "extended master secret". - * - * For example, `PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA256)` represents the - * TLS-1.2 PSK to MasterSecret derivation PRF using HMAC-SHA-256. - * - * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true). - * - * \return The corresponding TLS-1.2 PSK to MS algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_TLS12_PSK_TO_MS(hash_alg) \ - (PSA_ALG_TLS12_PSK_TO_MS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) - -/** Whether the specified algorithm is a TLS-1.2 PSK to MS algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \c alg is a TLS-1.2 PSK to MS algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \c alg is not a supported - * key derivation algorithm identifier. - */ -#define PSA_ALG_IS_TLS12_PSK_TO_MS(alg) \ - (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_TLS12_PSK_TO_MS_BASE) -#define PSA_ALG_TLS12_PSK_TO_MS_GET_HASH(hkdf_alg) \ - (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) - -#define PSA_ALG_KEY_DERIVATION_MASK ((psa_algorithm_t)0x0803ffff) -#define PSA_ALG_KEY_AGREEMENT_MASK ((psa_algorithm_t)0x10fc0000) - -/** Macro to build a combined algorithm that chains a key agreement with - * a key derivation. - * - * \param ka_alg A key agreement algorithm (\c PSA_ALG_XXX value such - * that #PSA_ALG_IS_KEY_AGREEMENT(\p ka_alg) is true). - * \param kdf_alg A key derivation algorithm (\c PSA_ALG_XXX value such - * that #PSA_ALG_IS_KEY_DERIVATION(\p kdf_alg) is true). - * - * \return The corresponding key agreement and derivation - * algorithm. - * \return Unspecified if \p ka_alg is not a supported - * key agreement algorithm or \p kdf_alg is not a - * supported key derivation algorithm. - */ -#define PSA_ALG_KEY_AGREEMENT(ka_alg, kdf_alg) \ - ((ka_alg) | (kdf_alg)) - -#define PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) \ - (((alg) & PSA_ALG_KEY_DERIVATION_MASK) | PSA_ALG_CATEGORY_KEY_DERIVATION) - -#define PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) \ - (((alg) & PSA_ALG_KEY_AGREEMENT_MASK) | PSA_ALG_CATEGORY_KEY_AGREEMENT) - -/** Whether the specified algorithm is a raw key agreement algorithm. - * - * A raw key agreement algorithm is one that does not specify - * a key derivation function. - * Usually, raw key agreement algorithms are constructed directly with - * a \c PSA_ALG_xxx macro while non-raw key agreement algorithms are - * constructed with PSA_ALG_KEY_AGREEMENT(). - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a raw key agreement algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_RAW_KEY_AGREEMENT(alg) \ - (PSA_ALG_IS_KEY_AGREEMENT(alg) && \ - PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) == PSA_ALG_CATEGORY_KEY_DERIVATION) - -#define PSA_ALG_IS_KEY_DERIVATION_OR_AGREEMENT(alg) \ - ((PSA_ALG_IS_KEY_DERIVATION(alg) || PSA_ALG_IS_KEY_AGREEMENT(alg))) - -/** The finite-field Diffie-Hellman (DH) key agreement algorithm. - * - * The shared secret produced by key agreement is - * `g^{ab}` in big-endian format. - * It is `ceiling(m / 8)` bytes long where `m` is the size of the prime `p` - * in bits. - */ -#define PSA_ALG_FFDH ((psa_algorithm_t)0x30100000) - -/** Whether the specified algorithm is a finite field Diffie-Hellman algorithm. - * - * This includes the raw finite field Diffie-Hellman algorithm as well as - * finite-field Diffie-Hellman followed by any supporter key derivation - * algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \c alg is a finite field Diffie-Hellman algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \c alg is not a supported - * key agreement algorithm identifier. - */ -#define PSA_ALG_IS_FFDH(alg) \ - (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_FFDH) - -/** The elliptic curve Diffie-Hellman (ECDH) key agreement algorithm. - * - * The shared secret produced by key agreement is the x-coordinate of - * the shared secret point. It is always `ceiling(m / 8)` bytes long where - * `m` is the bit size associated with the curve, i.e. the bit size of the - * order of the curve's coordinate field. When `m` is not a multiple of 8, - * the byte containing the most significant bit of the shared secret - * is padded with zero bits. The byte order is either little-endian - * or big-endian depending on the curve type. - * - * - For Montgomery curves (curve types `PSA_ECC_CURVE_CURVEXXX`), - * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` - * in little-endian byte order. - * The bit size is 448 for Curve448 and 255 for Curve25519. - * - For Weierstrass curves over prime fields (curve types - * `PSA_ECC_CURVE_SECPXXX` and `PSA_ECC_CURVE_BRAINPOOL_PXXX`), - * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` - * in big-endian byte order. - * The bit size is `m = ceiling(log_2(p))` for the field `F_p`. - * - For Weierstrass curves over binary fields (curve types - * `PSA_ECC_CURVE_SECTXXX`), - * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` - * in big-endian byte order. - * The bit size is `m` for the field `F_{2^m}`. - */ -#define PSA_ALG_ECDH ((psa_algorithm_t)0x30200000) - -/** Whether the specified algorithm is an elliptic curve Diffie-Hellman - * algorithm. - * - * This includes the raw elliptic curve Diffie-Hellman algorithm as well as - * elliptic curve Diffie-Hellman followed by any supporter key derivation - * algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \c alg is an elliptic curve Diffie-Hellman algorithm, - * 0 otherwise. - * This macro may return either 0 or 1 if \c alg is not a supported - * key agreement algorithm identifier. - */ -#define PSA_ALG_IS_ECDH(alg) \ - (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_ECDH) - -/** Whether the specified algorithm encoding is a wildcard. - * - * Wildcard values may only be used to set the usage algorithm field in - * a policy, not to perform an operation. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \c alg is a wildcard algorithm encoding. - * \return 0 if \c alg is a non-wildcard algorithm encoding (suitable for - * an operation). - * \return This macro may return either 0 or 1 if \c alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_WILDCARD(alg) \ - (PSA_ALG_IS_HASH_AND_SIGN(alg) ? \ - PSA_ALG_SIGN_GET_HASH(alg) == PSA_ALG_ANY_HASH : \ - (alg) == PSA_ALG_ANY_HASH) - -/**@}*/ - -/** \defgroup key_lifetimes Key lifetimes - * @{ - */ - -/** A volatile key only exists as long as the handle to it is not closed. - * The key material is guaranteed to be erased on a power reset. - */ -#define PSA_KEY_LIFETIME_VOLATILE ((psa_key_lifetime_t)0x00000000) - -/** The default storage area for persistent keys. - * - * A persistent key remains in storage until it is explicitly destroyed or - * until the corresponding storage area is wiped. This specification does - * not define any mechanism to wipe a storage area, but implementations may - * provide their own mechanism (for example to perform a factory reset, - * to prepare for device refurbishment, or to uninstall an application). - * - * This lifetime value is the default storage area for the calling - * application. Implementations may offer other storage areas designated - * by other lifetime values as implementation-specific extensions. - */ -#define PSA_KEY_LIFETIME_PERSISTENT ((psa_key_lifetime_t)0x00000001) - -/** The minimum value for a key identifier chosen by the application. - */ -#define PSA_KEY_ID_USER_MIN ((psa_app_key_id_t)0x00000001) -/** The maximum value for a key identifier chosen by the application. - */ -#define PSA_KEY_ID_USER_MAX ((psa_app_key_id_t)0x3fffffff) -/** The minimum value for a key identifier chosen by the implementation. - */ -#define PSA_KEY_ID_VENDOR_MIN ((psa_app_key_id_t)0x40000000) -/** The maximum value for a key identifier chosen by the implementation. - */ -#define PSA_KEY_ID_VENDOR_MAX ((psa_app_key_id_t)0x7fffffff) - -/**@}*/ - -/** \defgroup policy Key policies - * @{ - */ - -/** Whether the key may be exported. - * - * A public key or the public part of a key pair may always be exported - * regardless of the value of this permission flag. - * - * If a key does not have export permission, implementations shall not - * allow the key to be exported in plain form from the cryptoprocessor, - * whether through psa_export_key() or through a proprietary interface. - * The key may however be exportable in a wrapped form, i.e. in a form - * where it is encrypted by another key. - */ -#define PSA_KEY_USAGE_EXPORT ((psa_key_usage_t)0x00000001) - -/** Whether the key may be copied. - * - * This flag allows the use of psa_copy_key() to make a copy of the key - * with the same policy or a more restrictive policy. - * - * For lifetimes for which the key is located in a secure element which - * enforce the non-exportability of keys, copying a key outside the secure - * element also requires the usage flag #PSA_KEY_USAGE_EXPORT. - * Copying the key inside the secure element is permitted with just - * #PSA_KEY_USAGE_COPY if the secure element supports it. - * For keys with the lifetime #PSA_KEY_LIFETIME_VOLATILE or - * #PSA_KEY_LIFETIME_PERSISTENT, the usage flag #PSA_KEY_USAGE_COPY - * is sufficient to permit the copy. - */ -#define PSA_KEY_USAGE_COPY ((psa_key_usage_t)0x00000002) - -/** Whether the key may be used to encrypt a message. - * - * This flag allows the key to be used for a symmetric encryption operation, - * for an AEAD encryption-and-authentication operation, - * or for an asymmetric encryption operation, - * if otherwise permitted by the key's type and policy. - * - * For a key pair, this concerns the public key. - */ -#define PSA_KEY_USAGE_ENCRYPT ((psa_key_usage_t)0x00000100) - -/** Whether the key may be used to decrypt a message. - * - * This flag allows the key to be used for a symmetric decryption operation, - * for an AEAD decryption-and-verification operation, - * or for an asymmetric decryption operation, - * if otherwise permitted by the key's type and policy. - * - * For a key pair, this concerns the private key. - */ -#define PSA_KEY_USAGE_DECRYPT ((psa_key_usage_t)0x00000200) - -/** Whether the key may be used to sign a message. - * - * This flag allows the key to be used for a MAC calculation operation - * or for an asymmetric signature operation, - * if otherwise permitted by the key's type and policy. - * - * For a key pair, this concerns the private key. - */ -#define PSA_KEY_USAGE_SIGN_HASH ((psa_key_usage_t)0x00000400) - -/** Whether the key may be used to verify a message signature. - * - * This flag allows the key to be used for a MAC verification operation - * or for an asymmetric signature verification operation, - * if otherwise permitted by by the key's type and policy. - * - * For a key pair, this concerns the public key. - */ -#define PSA_KEY_USAGE_VERIFY_HASH ((psa_key_usage_t)0x00000800) - -/** Whether the key may be used to derive other keys. - */ -#define PSA_KEY_USAGE_DERIVE ((psa_key_usage_t)0x00001000) - -/**@}*/ - -/** \defgroup derivation Key derivation - * @{ - */ - -/** A secret input for key derivation. - * - * This should be a key of type #PSA_KEY_TYPE_DERIVE - * (passed to psa_key_derivation_input_key()) - * or the shared secret resulting from a key agreement - * (obtained via psa_key_derivation_key_agreement()). - * - * The secret can also be a direct input (passed to - * key_derivation_input_bytes()). In this case, the derivation operation - * may not be used to derive keys: the operation will only allow - * psa_key_derivation_output_bytes(), not psa_key_derivation_output_key(). - */ -#define PSA_KEY_DERIVATION_INPUT_SECRET ((psa_key_derivation_step_t)0x0101) - -/** A label for key derivation. - * - * This should be a direct input. - * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. - */ -#define PSA_KEY_DERIVATION_INPUT_LABEL ((psa_key_derivation_step_t)0x0201) - -/** A salt for key derivation. - * - * This should be a direct input. - * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. - */ -#define PSA_KEY_DERIVATION_INPUT_SALT ((psa_key_derivation_step_t)0x0202) - -/** An information string for key derivation. - * - * This should be a direct input. - * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. - */ -#define PSA_KEY_DERIVATION_INPUT_INFO ((psa_key_derivation_step_t)0x0203) - -/** A seed for key derivation. - * - * This should be a direct input. - * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. - */ -#define PSA_KEY_DERIVATION_INPUT_SEED ((psa_key_derivation_step_t)0x0204) - -/**@}*/ - -#endif /* PSA_CRYPTO_VALUES_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/error.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/error.h deleted file mode 100644 index 439dba4..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/error.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/** - * \file psa/error.h - * \brief Standard error codes for the SPM and RoT Services - */ - -#ifndef __PSA_ERROR_H__ -#define __PSA_ERROR_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* If #PSA_SUCCESS is already defined, it means that #psa_status_t - * is also defined in an external header, so prevent its multiple - * definition. - */ -#ifndef PSA_SUCCESS -typedef int32_t psa_status_t; -#endif - -#define PSA_SUCCESS ((psa_status_t)0) - -#define PSA_ERROR_PROGRAMMER_ERROR ((psa_status_t)-129) -#define PSA_ERROR_CONNECTION_REFUSED ((psa_status_t)-130) -#define PSA_ERROR_CONNECTION_BUSY ((psa_status_t)-131) -#define PSA_ERROR_GENERIC_ERROR ((psa_status_t)-132) -#define PSA_ERROR_NOT_PERMITTED ((psa_status_t)-133) -#define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)-134) -#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)-135) -#define PSA_ERROR_INVALID_HANDLE ((psa_status_t)-136) -#define PSA_ERROR_BAD_STATE ((psa_status_t)-137) -#define PSA_ERROR_BUFFER_TOO_SMALL ((psa_status_t)-138) -#define PSA_ERROR_ALREADY_EXISTS ((psa_status_t)-139) -#define PSA_ERROR_DOES_NOT_EXIST ((psa_status_t)-140) -#define PSA_ERROR_INSUFFICIENT_MEMORY ((psa_status_t)-141) -#define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)-142) -#define PSA_ERROR_INSUFFICIENT_DATA ((psa_status_t)-143) -#define PSA_ERROR_SERVICE_FAILURE ((psa_status_t)-144) -#define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t)-145) -#define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)-146) -#define PSA_ERROR_HARDWARE_FAILURE ((psa_status_t)-147) -#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_ERROR_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/initial_attestation.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/initial_attestation.h deleted file mode 100644 index c125a4d..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/initial_attestation.h +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (c) 2018-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/***************************************************************************/ -/* DRAFT UNDER REVIEW */ -/* These APIs are still evolving and are meant as a prototype for review.*/ -/* The APIs will change depending on feedback and will be firmed up */ -/* to a stable set of APIs once all the feedback has been considered. */ -/***************************************************************************/ - -#ifndef __PSA_INITIAL_ATTESTATION_H__ -#define __PSA_INITIAL_ATTESTATION_H__ - -#include -#include -#include -#include "psa/crypto.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief PSA INITIAL ATTESTATION API version - * - * Initial attestation API version is: 1.0.0 - */ -#define PSA_INITIAL_ATTEST_API_VERSION_MAJOR (1) -#define PSA_INITIAL_ATTEST_API_VERSION_MINOR (0) - -/** - * The allowed size of input challenge in bytes: 32, 48, 64 - * Challenge can be a nonce from server - * or the hash of some combined data : nonce + attested data by caller. - */ -#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32 (32u) -#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48 (48u) -#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64 (64u) - -/** - * The maximum size of an attestation token that can be generated by the - * attestation service. Used to configure buffers for services that verify the - * produced tokens. - */ -#define PSA_INITIAL_ATTEST_MAX_TOKEN_SIZE (0x400) - -/** - * The list of fixed claims in the initial attestation token is still evolving, - * you can expect slight changes in the future. - * - * The initial attestation token is planned to be aligned with future version of - * Entity Attestation Token format: - * https://tools.ietf.org/html/draft-mandyam-eat-01 - * - * Current list of claims: - * - Challenge: Input object from caller. Can be a single nonce from server - * or hash of nonce and attested data. It is intended to provide - * freshness to reports and the caller has responsibility to - * arrange this. Allowed length: 32, 48, 64 bytes. The claim is - * modeled to be eventually represented by the EAT standard - * claim nonce. Until such a time as that standard exists, - * the claim will be represented by a custom claim. Value - * is encoded as byte string. - * - * - Instance ID: It represents the unique identifier of the instance. In the - * PSA definition it is a hash of the public attestation key - * of the instance. The claim is modeled to be eventually - * represented by the EAT standard claim UEID of type GUID. - * Until such a time as that standard exists, the claim will be - * represented by a custom claim Value is encoded as byte - * string. - * - * - Verification service indicator: Optional, recommended claim. It is used by - * a Relying Party to locate a validation service for the token. - * The value is a text string that can be used to locate the - * service or a URL specifying the address of the service. The - * claim is modeled to be eventually represented by the EAT - * standard claim origination. Until such a time as that - * standard exists, the claim will be represented by a custom - * claim. Value is encoded as text string. - * - * - Profile definition: Optional, recommended claim. It contains the name of - * a document that describes the 'profile' of the token, being - * a full description of the claims, their usage, verification - * and token signing. The document name may include versioning. - * Custom claim with a value encoded as text string. - * - * - Implementation ID: It represents the original implementation signer of the - * attestation key and identifies the contract between the - * report and verification. A verification service will use this - * claim to locate the details of the verification process. - * Custom claim with a value encoded as byte string. - * - * - Security lifecycle: It represents the current lifecycle state of the - * instance. Custom claim with a value encoded as integer that - * is divided to convey a major state and a minor state. The - * PSA state and implementation state are encoded as follows: - * - version[15:8] - PSA lifecycle state - major - * - version[7:0] - IMPLEMENTATION DEFINED state - minor - * Possible PSA lifecycle states: - * - Unknown (0x1000u), - * - PSA_RoT_Provisioning (0x2000u), - * - Secured (0x3000u), - * - Non_PSA_RoT_Debug(0x4000u), - * - Recoverable_PSA_RoT_Debug (0x5000u), - * - Decommissioned (0x6000u) - * - * - Client ID: The partition ID of that secure partition or non-secure - * thread who called the initial attestation API. Custom claim - * with a value encoded as a *signed* integer. Negative number - * represents non-secure caller, positive numbers represents - * secure callers, zero is invalid. - * - * - HW version: Optional claim. Globally unique number in EAN-13 format - * identifying the GDSII that went to fabrication, HW and ROM. - * It can be used to reference the security level of the PSA-ROT - * via a certification website. Custom claim with a value is - * encoded as text string. - - * - Boot seed: It represents a random value created at system boot time that - * will allow differentiation of reports from different system - * sessions. The size is 32 bytes. Custom claim with a value is - * encoded as byte string. - * - * - Software components: Recommended claim. It represents the software state - * of the system. The value of the claim is an array of CBOR map - * entries, with one entry per software component within the - * device. Each map contains multiple claims that describe - * evidence about the details of the software component. - * - * - Measurement type: Optional claim. It represents the role of the - * software component. Value is encoded as short(!) text - * string. - * - * - Measurement value: It represents a hash of the invariant software - * component in memory at start-up time. The value must be a - * cryptographic hash of 256 bits or stronger.Value is - * encoded as byte string. - * - * - Version: Optional claim. It represents the issued software version. - * Value is encoded as text string. - * - * - Signer ID: It represents the hash of a signing authority public key. - * Value is encoded as byte string. - * - * - Measurement description: Optional claim. It represents the way in which - * the measurement value of the software component is - * computed. Value is encoded as text string containing an - * abbreviated description (name) of the measurement method. - * - * - No software measurements: In the event that the implementation does not - * contain any software measurements then the software - * components claim above can be omitted but instead - * it is mandatory to include this claim to indicate this is a - * deliberate state. Custom claim a value is encoded as unsigned - * integer set to 1. - */ - -/** - * \brief Get initial attestation token - * - * \param[in] auth_challenge Pointer to buffer where challenge input is - * stored. Nonce and / or hash of attested data. - * Must be always - * \ref PSA_INITIAL_ATTEST_TOKEN_SIZE bytes - * long. - * \param[in] challenge_size Size of challenge object in bytes. - * \param[out] token_buf Pointer to the buffer where attestation token - * will be stored. - * \param[in] token_buf_size Size of allocated buffer for token, in bytes. - * \param[out] token_size Size of the token that has been returned, in - * bytes. - * - * \return Returns error code as specified in \ref psa_status_t - */ -psa_status_t -psa_initial_attest_get_token(const uint8_t *auth_challenge, - size_t challenge_size, - uint8_t *token_buf, - size_t token_buf_size, - size_t *token_size); - -/** - * \brief Get the exact size of initial attestation token in bytes. - * - * It just returns with the size of the IAT token. It can be used if the caller - * dynamically allocates memory for the token buffer. - * - * \param[in] challenge_size Size of challenge object in bytes. This must be - * a supported challenge size (as above). - * \param[out] token_size Size of the token in bytes, which is created by - * initial attestation service. - * - * \return Returns error code as specified in \ref psa_status_t - */ -psa_status_t -psa_initial_attest_get_token_size(size_t challenge_size, - size_t *token_size); - -/** - * \brief Get the initial attestation public key. - * - * \param[out] public_key Pointer to the buffer where the public key - * will be stored. - * \param[in] key_buf_size Size of allocated buffer for key, in bytes. - * \param[out] public_key_len Size of public key in bytes. - * \param[out] public_key_curve Type of the elliptic curve which the key - * belongs to. - * - * \note Currently only the ECDSA P-256 over SHA-256 algorithm is supported. - * - * \return Returns error code as specified in \ref psa_status_t - */ -psa_status_t -tfm_initial_attest_get_public_key(uint8_t *public_key, - size_t public_key_buf_size, - size_t *public_key_len, - psa_ecc_curve_t *elliptic_curve_type); - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_INITIAL_ATTESTATION_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/internal_trusted_storage.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/internal_trusted_storage.h deleted file mode 100644 index 3920bc9..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/internal_trusted_storage.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/** This file describes the PSA Internal Trusted Storage API -*/ - -#ifndef PSA_INTERNAL_TRUSTED_STORAGE_H -#define PSA_INTERNAL_TRUSTED_STORAGE_H - -#include -#include - -#include "psa/error.h" -#include "psa/storage_common.h" - -#ifdef __cplusplus -extern "C" { -#endif -#define PSA_ITS_API_VERSION_MAJOR 1 /**< The major version number of the - * PSA ITS API - */ -#define PSA_ITS_API_VERSION_MINOR 0 /**< The minor version number of the - * PSA ITS API - */ -// This version of the header file is associated with 1.0 final release. - -/** - * \brief Create a new, or modify an existing, uid/value pair - * - * Stores data in the internal storage. - * - * \param[in] uid The identifier for the data - * \param[in] data_length The size in bytes of the data in `p_data` - * \param[in] p_data A buffer containing the data - * \param[in] create_flags The flags that the data will be stored with - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the - * provided `uid` value was already - * created with - * PSA_STORAGE_FLAG_WRITE_ONCE - * \retval PSA_ERROR_NOT_SUPPORTED The operation failed because one or - * more of the flags provided in - * `create_flags` is not supported or is - * not valid - * \retval PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because there - * was insufficient space on the - * storage medium - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the - * physical storage has failed (Fatal - * error) - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one - * of the provided pointers(`p_data`) - * is invalid, for example is `NULL` or - * references memory the caller cannot - * access - */ -psa_status_t psa_its_set(psa_storage_uid_t uid, - size_t data_length, - const void *p_data, - psa_storage_create_flags_t create_flags); - -/** - * \brief Retrieve data associated with a provided UID - * - * Retrieves up to `data_size` bytes of the data associated with `uid`, starting - * at `data_offset` bytes from the beginning of the data. Upon successful - * completion, the data will be placed in the `p_data` buffer, which must be at - * least `data_size` bytes in size. The length of the data returned will be in - * `p_data_length`. If `data_size` is 0, the contents of `p_data_length` will - * be set to zero. - * - * \param[in] uid The uid value - * \param[in] data_offset The starting offset of the data requested - * \param[in] data_size The amount of data requested - * \param[out] p_data On success, the buffer where the data will - * be placed - * \param[out] p_data_length On success, this will contain size of the data - * placed in `p_data` - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the - * provided `uid` value was not found in - * the storage - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the - * physical storage has failed (Fatal - * error) - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the - * provided arguments (`p_data`, - * `p_data_length`) is invalid, for example - * is `NULL` or references memory the - * caller cannot access. In addition, this - * can also happen if `data_offset` is - * larger than the size of the data - * associated with `uid` - */ -psa_status_t psa_its_get(psa_storage_uid_t uid, - size_t data_offset, - size_t data_size, - void *p_data, - size_t *p_data_length); - -/** - * \brief Retrieve the metadata about the provided uid - * - * Retrieves the metadata stored for a given `uid` as a `psa_storage_info_t` - * structure. - * - * \param[in] uid The `uid` value - * \param[out] p_info A pointer to the `psa_storage_info_t` struct that will - * be populated with the metadata - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided - * uid value was not found in the storage - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical - * storage has failed (Fatal error) - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the - * provided pointers(`p_info`) - * is invalid, for example is `NULL` or - * references memory the caller cannot - * access - */ -psa_status_t psa_its_get_info(psa_storage_uid_t uid, - struct psa_storage_info_t *p_info); - -/** - * \brief Remove the provided uid and its associated data from the storage - * - * Deletes the data from internal storage. - * - * \param[in] uid The `uid` value - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more - * of the given arguments were invalid (null - * pointer, wrong flags and so on) - * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided - * uid value was not found in the storage - * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the provided - * uid value was created with - * PSA_STORAGE_FLAG_WRITE_ONCE - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical - * storage has failed (Fatal error) - */ -psa_status_t psa_its_remove(psa_storage_uid_t uid); - -#ifdef __cplusplus -} -#endif - -#endif // PSA_INTERNAL_TRUSTED_STORAGE_H diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/protected_storage.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/protected_storage.h deleted file mode 100644 index e76205c..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/protected_storage.h +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright (c) 2019-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/* This file describes the PSA Protected Storage API */ - -#ifndef PSA_PROTECTED_STORAGE_H -#define PSA_PROTECTED_STORAGE_H - -#include -#include - -#include "psa/error.h" -#include "psa/storage_common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief PSA_PS_API_VERSION version - * - * Major and minor PSA_PS_API_VERSION numbers - */ -#define PSA_PS_API_VERSION_MAJOR 1 -#define PSA_PS_API_VERSION_MINOR 0 - -// This version of the header file is associated with 1.0 final release - -/** - * \brief Create a new, or modify an existing, uid/value pair - * - * Stores data in the protected storage. - * - * \param[in] uid The identifier for the data - * \param[in] data_length The size in bytes of the data in `p_data` - * \param[in] p_data A buffer containing the data - * \param[in] create_flags The flags that the data will be stored with - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the - * provided `uid` value was already - * created with - * PSA_STORAGE_FLAG_WRITE_ONCE - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one - * of the provided pointers(`p_data`) - * is invalid, for example is `NULL` or - * references memory the caller cannot - * access - * \retval PSA_ERROR_NOT_SUPPORTED The operation failed because one or - * more of the flags provided in - * `create_flags` is not supported or is - * not valid - * \retval PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because there - * was insufficient space on the - * storage medium - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the - * physical storage has failed (Fatal - * error) - * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an - * unspecified internal failure - */ -psa_status_t psa_ps_set(psa_storage_uid_t uid, - size_t data_length, - const void *p_data, - psa_storage_create_flags_t create_flags); - -/** - * \brief Retrieve data associated with a provided uid - * - * Retrieves up to `data_size` bytes of the data associated with `uid`, starting - * at `data_offset` bytes from the beginning of the data. Upon successful - * completion, the data will be placed in the `p_data` buffer, which must be at - * least `data_size` bytes in size. The length of the data returned will be in - * `p_data_length`. If `data_size` is 0, the contents of `p_data_length` will - * be set to zero. - * - * \param[in] uid The uid value - * \param[in] data_offset The starting offset of the data requested - * \param[in] data_size The amount of data requested - * \param[out] p_data On success, the buffer where the data will - * be placed - * \param[out] p_data_length On success, this will contain size of the data - * placed in `p_data` - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the - * provided arguments (`p_data`, - * `p_data_length`) is invalid, for example - * is `NULL` or references memory the - * caller cannot access. In addition, this - * can also happen if `data_offset` is - * larger than the size of the data - * associated with `uid` - * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the - * provided `uid` value was not found in - * the storage - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the - * physical storage has failed (Fatal - * error) - * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an - * unspecified internal failure - * \retval PSA_ERROR_DATA_CORRUPT The operation failed because the data - * associated with the UID was corrupt - * \retval PSA_ERROR_INVALID_SIGNATURE The operation failed because the data - * associated with the UID failed - * authentication - */ -psa_status_t psa_ps_get(psa_storage_uid_t uid, - size_t data_offset, - size_t data_size, - void *p_data, - size_t *p_data_length); - -/** - * \brief Retrieve the metadata about the provided uid - * - * Retrieves the metadata stored for a given `uid` - * - * \param[in] uid The `uid` value - * \param[out] p_info A pointer to the `psa_storage_info_t` struct that will - * be populated with the metadata - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the - * provided pointers(`p_info`) - * is invalid, for example is `NULL` or - * references memory the caller cannot - * access - * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided - * uid value was not found in the storage - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical - * storage has failed (Fatal error) - * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an - * unspecified internal failure - * \retval PSA_ERROR_DATA_CORRUPT The operation failed because the data - * associated with the UID was corrupt - */ -psa_status_t psa_ps_get_info(psa_storage_uid_t uid, - struct psa_storage_info_t *p_info); - -/** - * \brief Remove the provided uid and its associated data from the storage - * - * Removes previously stored data and any associated metadata, - * including rollback protection data. - * - * \param[in] uid The `uid` value - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more - * of the given arguments were invalid (null - * pointer, wrong flags and so on) - * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided - * uid value was not found in the storage - * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the provided - * uid value was created with - * PSA_STORAGE_FLAG_WRITE_ONCE - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical - * storage has failed (Fatal error) - * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an - * unspecified internal failure - */ -psa_status_t psa_ps_remove(psa_storage_uid_t uid); - -/** - * \brief Reserves storage for the specified uid - * - * Upon success, the capacity of the storage will be capacity, and the size - * will be 0. It is only necessary to call this function for assets that will - * be written with the psa_ps_set_extended function. If only the psa_ps_set - * function is needed, calls to this function are redundant. - * - * \param[in] uid The `uid` value - * \param[in] capacity The capacity to be allocated in bytes - * \param[in] create_flags Flags indicating properties of storage - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the - * physical storage has failed - * (Fatal error) - * \retval PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because the - * capacity is bigger than the current - * available space - * \retval PSA_ERROR_NOT_SUPPORTED The operation failed because the - * function is not implemented or one - * or more create_flags are not - * supported. - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because uid was - * 0 or create_flags specified flags - * that are not defined in the API. - * \retval PSA_ERROR_GENERIC_ERROR The operation failed due to an - * unspecified error - * \retval PSA_ERROR_ALREADY_EXISTS Storage for the specified uid - * already exists - */ -psa_status_t psa_ps_create(psa_storage_uid_t uid, - size_t capacity, - psa_storage_create_flags_t create_flags); - -/** - * \brief Sets partial data into an asset - * - * Before calling this function, the storage must have been reserved with a call - * to psa_ps_create. It can also be used to overwrite data in an asset that was - * created with a call to psa_ps_set. Calling this function with data_length = 0 - * is permitted, which will make no change to the stored data.This function can - * overwrite existing data and/or extend it up to the capacity for the uid - * specified in psa_ps_create, but cannot create gaps. - * - * That is, it has preconditions: - * - data_offset <= size - * - data_offset + data_length <= capacity - * and postconditions: - * - size = max(size, data_offset + data_length) - * - capacity unchanged. - * - * \param[in] uid The `uid` value - * \param[in] data_offset Offset within the asset to start the write - * \param[in] data_length The size in bytes of the data in p_data to write - * \param[in] p_data Pointer to a buffer which contains the data to write - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The asset exists, the input parameters - * are correct and the data is correctly - * written in the physical storage. - * \retval PSA_ERROR_STORAGE_FAILURE The data was not written correctly in - * the physical storage - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more - * of the preconditions listed above - * regarding data_offset, size, or - * data_length was violated. - * \retval PSA_ERROR_DOES_NOT_EXIST The specified uid was not found - * \retval PSA_ERROR_NOT_SUPPORTED The implementation of the API does not - * support this function - * \retval PSA_ERROR_GENERIC_ERROR The operation failed due to an - * unspecified error - * \retval PSA_ERROR_DATA_CORRUPT The operation failed because the - * existing data has been corrupted. - * \retval PSA_ERROR_INVALID_SIGNATURE The operation failed because the - * existing data failed authentication - * (MAC check failed). - * \retval PSA_ERROR_NOT_PERMITTED The operation failed because it was - * attempted on an asset which was written - * with the flag - * PSA_STORAGE_FLAG_WRITE_ONCE - */ -psa_status_t psa_ps_set_extended(psa_storage_uid_t uid, - size_t data_offset, - size_t data_length, - const void *p_data); - -/** - * \brief Lists optional features. - * - * \return A bitmask with flags set for all of - * the optional features supported by the - * implementation.Currently defined flags - * are limited to - * PSA_STORAGE_SUPPORT_SET_EXTENDED - */ -uint32_t psa_ps_get_support(void); - -#ifdef __cplusplus -} -#endif - -#endif /* PSA_PROTECTED_STORAGE_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/storage_common.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/storage_common.h deleted file mode 100644 index 3f901c5..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/storage_common.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/* This file includes common definitions for PSA storage -*/ - -#ifndef PSA_STORAGE_COMMON_H -#define PSA_STORAGE_COMMON_H - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef uint32_t psa_storage_create_flags_t; - -typedef uint64_t psa_storage_uid_t; - -/* Flags */ - -#define PSA_STORAGE_FLAG_NONE 0u -#define PSA_STORAGE_FLAG_WRITE_ONCE (1u << 0) -#define PSA_STORAGE_FLAG_NO_CONFIDENTIALITY (1u << 1) -#define PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION (1u << 2) - -/* A container for metadata associated with a specific uid */ - -struct psa_storage_info_t { - size_t capacity; - size_t size; - psa_storage_create_flags_t flags; -}; - -#define PSA_STORAGE_SUPPORT_SET_EXTENDED (1u << 0) - -#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) -#define PSA_ERROR_DATA_CORRUPT ((psa_status_t)-152) - -#ifdef __cplusplus -} -#endif - -#endif // PSA_STORAGE_COMMON_H diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa_manifest/sid.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa_manifest/sid.h deleted file mode 100644 index 2fc3394..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa_manifest/sid.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (c) 2019-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#ifndef __PSA_MANIFEST_SID_H__ -#define __PSA_MANIFEST_SID_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/******** TFM_SP_STORAGE ********/ -#define TFM_SST_SET_SID (0x00000060U) -#define TFM_SST_SET_VERSION (1U) -#define TFM_SST_GET_SID (0x00000061U) -#define TFM_SST_GET_VERSION (1U) -#define TFM_SST_GET_INFO_SID (0x00000062U) -#define TFM_SST_GET_INFO_VERSION (1U) -#define TFM_SST_REMOVE_SID (0x00000063U) -#define TFM_SST_REMOVE_VERSION (1U) -#define TFM_SST_GET_SUPPORT_SID (0x00000064U) -#define TFM_SST_GET_SUPPORT_VERSION (1U) - -/******** TFM_SP_ITS ********/ -#define TFM_ITS_SET_SID (0x00000070U) -#define TFM_ITS_SET_VERSION (1U) -#define TFM_ITS_GET_SID (0x00000071U) -#define TFM_ITS_GET_VERSION (1U) -#define TFM_ITS_GET_INFO_SID (0x00000072U) -#define TFM_ITS_GET_INFO_VERSION (1U) -#define TFM_ITS_REMOVE_SID (0x00000073U) -#define TFM_ITS_REMOVE_VERSION (1U) - -/******** TFM_SP_CRYPTO ********/ -#define TFM_CRYPTO_SID (0x00000080U) -#define TFM_CRYPTO_VERSION (1U) - -/******** TFM_SP_PLATFORM ********/ -#define TFM_SP_PLATFORM_SYSTEM_RESET_SID (0x00000040U) -#define TFM_SP_PLATFORM_SYSTEM_RESET_VERSION (1U) -#define TFM_SP_PLATFORM_IOCTL_SID (0x00000041U) -#define TFM_SP_PLATFORM_IOCTL_VERSION (1U) -#define TFM_SP_PLATFORM_NV_COUNTER_SID (0x00000042U) -#define TFM_SP_PLATFORM_NV_COUNTER_VERSION (1U) - -/******** TFM_SP_INITIAL_ATTESTATION ********/ -#define TFM_ATTEST_GET_TOKEN_SID (0x00000020U) -#define TFM_ATTEST_GET_TOKEN_VERSION (1U) -#define TFM_ATTEST_GET_TOKEN_SIZE_SID (0x00000021U) -#define TFM_ATTEST_GET_TOKEN_SIZE_VERSION (1U) -#define TFM_ATTEST_GET_PUBLIC_KEY_SID (0x00000022U) -#define TFM_ATTEST_GET_PUBLIC_KEY_VERSION (1U) - -/******** TFM_SP_CORE_TEST ********/ -#define SPM_CORE_TEST_INIT_SUCCESS_SID (0x0000F020U) -#define SPM_CORE_TEST_INIT_SUCCESS_VERSION (1U) -#define SPM_CORE_TEST_DIRECT_RECURSION_SID (0x0000F021U) -#define SPM_CORE_TEST_DIRECT_RECURSION_VERSION (1U) -#define SPM_CORE_TEST_MPU_ACCESS_SID (0x0000F022U) -#define SPM_CORE_TEST_MPU_ACCESS_VERSION (1U) -#define SPM_CORE_TEST_MEMORY_PERMISSIONS_SID (0x0000F023U) -#define SPM_CORE_TEST_MEMORY_PERMISSIONS_VERSION (1U) -#define SPM_CORE_TEST_SS_TO_SS_SID (0x0000F024U) -#define SPM_CORE_TEST_SS_TO_SS_VERSION (1U) -#define SPM_CORE_TEST_SS_TO_SS_BUFFER_SID (0x0000F025U) -#define SPM_CORE_TEST_SS_TO_SS_BUFFER_VERSION (1U) -#define SPM_CORE_TEST_OUTVEC_WRITE_SID (0x0000F026U) -#define SPM_CORE_TEST_OUTVEC_WRITE_VERSION (1U) -#define SPM_CORE_TEST_PERIPHERAL_ACCESS_SID (0x0000F027U) -#define SPM_CORE_TEST_PERIPHERAL_ACCESS_VERSION (1U) -#define SPM_CORE_TEST_GET_CALLER_CLIENT_ID_SID (0x0000F028U) -#define SPM_CORE_TEST_GET_CALLER_CLIENT_ID_VERSION (1U) -#define SPM_CORE_TEST_SPM_REQUEST_SID (0x0000F029U) -#define SPM_CORE_TEST_SPM_REQUEST_VERSION (1U) -#define SPM_CORE_TEST_BLOCK_SID (0x0000F02AU) -#define SPM_CORE_TEST_BLOCK_VERSION (1U) -#define SPM_CORE_TEST_NS_THREAD_SID (0x0000F02BU) -#define SPM_CORE_TEST_NS_THREAD_VERSION (1U) - -/******** TFM_SP_CORE_TEST_2 ********/ -#define SPM_CORE_TEST_2_SLAVE_SERVICE_SID (0x0000F040U) -#define SPM_CORE_TEST_2_SLAVE_SERVICE_VERSION (1U) -#define SPM_CORE_TEST_2_CHECK_CALLER_CLIENT_ID_SID (0x0000F041U) -#define SPM_CORE_TEST_2_CHECK_CALLER_CLIENT_ID_VERSION (1U) -#define SPM_CORE_TEST_2_GET_EVERY_SECOND_BYTE_SID (0x0000F042U) -#define SPM_CORE_TEST_2_GET_EVERY_SECOND_BYTE_VERSION (1U) -#define SPM_CORE_TEST_2_INVERT_SID (0x0000F043U) -#define SPM_CORE_TEST_2_INVERT_VERSION (1U) -#define SPM_CORE_TEST_2_PREPARE_TEST_SCENARIO_SID (0x0000F044U) -#define SPM_CORE_TEST_2_PREPARE_TEST_SCENARIO_VERSION (1U) -#define SPM_CORE_TEST_2_EXECUTE_TEST_SCENARIO_SID (0x0000F045U) -#define SPM_CORE_TEST_2_EXECUTE_TEST_SCENARIO_VERSION (1U) - -/******** TFM_SP_SECURE_TEST_PARTITION ********/ -#define TFM_SECURE_CLIENT_SFN_RUN_TESTS_SID (0x0000F000U) -#define TFM_SECURE_CLIENT_SFN_RUN_TESTS_VERSION (1U) - -/******** TFM_SP_IPC_SERVICE_TEST ********/ -#define IPC_SERVICE_TEST_BASIC_SID (0x0000F080U) -#define IPC_SERVICE_TEST_BASIC_VERSION (1U) -#define IPC_SERVICE_TEST_PSA_ACCESS_APP_MEM_SID (0x0000F081U) -#define IPC_SERVICE_TEST_PSA_ACCESS_APP_MEM_VERSION (1U) -#define IPC_SERVICE_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_SID (0x0000F082U) -#define IPC_SERVICE_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_VERSION (1U) -#define IPC_SERVICE_TEST_APP_ACCESS_PSA_MEM_SID (0x0000F083U) -#define IPC_SERVICE_TEST_APP_ACCESS_PSA_MEM_VERSION (1U) -#define IPC_SERVICE_TEST_CLIENT_PROGRAMMER_ERROR_SID (0x0000F084U) -#define IPC_SERVICE_TEST_CLIENT_PROGRAMMER_ERROR_VERSION (1U) - -/******** TFM_SP_IPC_CLIENT_TEST ********/ -#define IPC_CLIENT_TEST_BASIC_SID (0x0000F060U) -#define IPC_CLIENT_TEST_BASIC_VERSION (1U) -#define IPC_CLIENT_TEST_PSA_ACCESS_APP_MEM_SID (0x0000F061U) -#define IPC_CLIENT_TEST_PSA_ACCESS_APP_MEM_VERSION (1U) -#define IPC_CLIENT_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_SID (0x0000F062U) -#define IPC_CLIENT_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_VERSION (1U) -#define IPC_CLIENT_TEST_APP_ACCESS_PSA_MEM_SID (0x0000F063U) -#define IPC_CLIENT_TEST_APP_ACCESS_PSA_MEM_VERSION (1U) -#define IPC_CLIENT_TEST_MEM_CHECK_SID (0x0000F064U) -#define IPC_CLIENT_TEST_MEM_CHECK_VERSION (1U) - -/******** TFM_IRQ_TEST_1 ********/ -#define SPM_CORE_IRQ_TEST_1_PREPARE_TEST_SCENARIO_SID (0x0000F0A0U) -#define SPM_CORE_IRQ_TEST_1_PREPARE_TEST_SCENARIO_VERSION (1U) -#define SPM_CORE_IRQ_TEST_1_EXECUTE_TEST_SCENARIO_SID (0x0000F0A1U) -#define SPM_CORE_IRQ_TEST_1_EXECUTE_TEST_SCENARIO_VERSION (1U) - -/******** TFM_SP_SST_TEST ********/ -#define TFM_SST_TEST_PREPARE_SID (0x0000F0C0U) -#define TFM_SST_TEST_PREPARE_VERSION (1U) - -/******** TFM_SP_SECURE_CLIENT_2 ********/ -#define TFM_SECURE_CLIENT_2_SID (0x0000F0E0U) -#define TFM_SECURE_CLIENT_2_VERSION (1U) - -/******** TFM_SP_MULTI_CORE_TEST ********/ -#define MULTI_CORE_MULTI_CLIENT_CALL_TEST_0_SID (0x0000F100U) -#define MULTI_CORE_MULTI_CLIENT_CALL_TEST_0_VERSION (1U) -#define MULTI_CORE_MULTI_CLIENT_CALL_TEST_1_SID (0x0000F101U) -#define MULTI_CORE_MULTI_CLIENT_CALL_TEST_1_VERSION (1U) - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_MANIFEST_SID_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_api.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_api.h deleted file mode 100644 index 09abc39..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_api.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2017-2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#ifndef __TFM_API_H__ -#define __TFM_API_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "psa/client.h" - -#define TFM_INVALID_CLIENT_ID 0 - -/** - * \brief Checks if the provided client ID is a secure client ID. - * - * \param[in] client_id Client ID to check. - * - * \retval 1 Client ID is secure. - * \retval 0 Client ID is non-secure. - */ -#define TFM_CLIENT_ID_IS_S(client_id) ((client_id)>0) - -/** - * \brief Checks if the provided client ID is a non-secure client ID. - * - * \param[in] client_id Client ID to check. - * - * \retval 1 Client ID is non-secure. - * \retval 0 Client ID is secure. - */ -#define TFM_CLIENT_ID_IS_NS(client_id) ((client_id)<0) - -/* The mask used for timeout values */ -#define PSA_TIMEOUT_MASK PSA_BLOCK - -/* FixMe: sort out DEBUG compile option and limit return value options - * on external interfaces */ -enum tfm_status_e -{ - TFM_SUCCESS = 0, - TFM_PARTITION_BUSY, - TFM_ERROR_SECURE_DOMAIN_LOCKED, - TFM_ERROR_INVALID_PARAMETER, - TFM_ERROR_PARTITION_NON_REENTRANT, - TFM_ERROR_NS_THREAD_MODE_CALL, - TFM_ERROR_NOT_INITIALIZED, - TFM_ERROR_NO_ACTIVE_PARTITION, - TFM_ERROR_INVALID_EXC_MODE, - TFM_SECURE_LOCK_FAILED, - TFM_SECURE_UNLOCK_FAILED, - TFM_ERROR_GENERIC = 0x1F, -}; - -/* - * Structure to package type, in_len and out_len, it is mainly used for - * psa_call. - */ -struct tfm_control_parameter_t { - int32_t type; - size_t in_len; - size_t out_len; -}; - -/********************* Secure function declarations ***************************/ - -/** - * \brief Assign client ID to the current TZ context. - * - * \param[in] ns_client_id The client ID to be assigned to the current - * context. - * \retval TFM_SUCCESS The client ID assigned successfully. - * \retval error code The client ID assignment failed, an error code - * returned according to \ref tfm_status_e. - * \note This function have to be called from handler mode. - */ -enum tfm_status_e tfm_register_client_id (int32_t ns_client_id); - -/** - * \brief Retrieve the version of the PSA Framework API that is implemented. - * - * \return The version of the PSA Framework. - */ -uint32_t tfm_psa_framework_version_veneer(void); - -/** - * \brief Return version of secure function provided by secure binary. - * - * \param[in] sid ID of secure service. - * - * \return Version number of secure function. - */ -uint32_t tfm_psa_version_veneer(uint32_t sid); - -/** - * \brief Connect to secure function. - * - * \param[in] sid ID of secure service. - * \param[in] version Version of SF requested by client. - * - * \return Returns handle to connection. - */ -psa_handle_t tfm_psa_connect_veneer(uint32_t sid, uint32_t version); - -/** - * \brief Call a secure function referenced by a connection handle. - * - * \param[in] handle Handle to connection. - * \param[in] ctrl_param Parameter structure, includes reuqest type, - * in_num and out_num. - * \param[in] in_vec Array of input \ref psa_invec structures. - * \param[in/out] out_vec Array of output \ref psa_outvec structures. - * - * \return Returns \ref psa_status_t status code. - */ -psa_status_t tfm_psa_call_veneer(psa_handle_t handle, - const struct tfm_control_parameter_t *ctrl_param, - const psa_invec *in_vec, - psa_outvec *out_vec); - -/** - * \brief Close connection to secure function referenced by a connection handle. - * - * \param[in] handle Handle to connection - * - * \return void - */ -void tfm_psa_close_veneer(psa_handle_t handle); - -/***************** End Secure function declarations ***************************/ - -#ifdef __cplusplus -} -#endif - -#endif /* __TFM_API_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_crypto_defs.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_crypto_defs.h deleted file mode 100644 index 53c03ce..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_crypto_defs.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2018-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#ifndef __TFM_CRYPTO_DEFS_H__ -#define __TFM_CRYPTO_DEFS_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include "tfm_api.h" -#include "psa/crypto.h" - -/** - * \brief This type is used to overcome a limitation in the number of maximum - * IOVECs that can be used especially in psa_aead_encrypt and - * psa_aead_decrypt. To be removed in case the AEAD APIs number of - * parameters passed gets restructured - */ -#define TFM_CRYPTO_MAX_NONCE_LENGTH (16u) -struct tfm_crypto_aead_pack_input { - uint8_t nonce[TFM_CRYPTO_MAX_NONCE_LENGTH]; - uint32_t nonce_length; -}; - -/** - * \brief Structure used to pack non-pointer types in a call - * - */ -struct tfm_crypto_pack_iovec { - uint32_t sfn_id; /*!< Secure function ID used to dispatch the - * request - */ - uint16_t step; /*!< Key derivation step */ - psa_key_handle_t key_handle; /*!< Key handle */ - psa_algorithm_t alg; /*!< Algorithm */ - uint32_t op_handle; /*!< Frontend context handle associated to a - * multipart operation - */ - size_t capacity; /*!< Key derivation capacity */ - - struct tfm_crypto_aead_pack_input aead_in; /*!< FixMe: Temporarily used for - * AEAD until the API is - * restructured - */ -}; - -/** - * \brief Define a progressive numerical value for each SID which can be used - * when dispatching the requests to the service - */ -enum { - TFM_CRYPTO_GET_KEY_ATTRIBUTES_SID = (0u), - TFM_CRYPTO_RESET_KEY_ATTRIBUTES_SID, - TFM_CRYPTO_OPEN_KEY_SID, - TFM_CRYPTO_CLOSE_KEY_SID, - TFM_CRYPTO_IMPORT_KEY_SID, - TFM_CRYPTO_DESTROY_KEY_SID, - TFM_CRYPTO_EXPORT_KEY_SID, - TFM_CRYPTO_EXPORT_PUBLIC_KEY_SID, - TFM_CRYPTO_COPY_KEY_SID, - TFM_CRYPTO_HASH_COMPUTE_SID, - TFM_CRYPTO_HASH_COMPARE_SID, - TFM_CRYPTO_HASH_SETUP_SID, - TFM_CRYPTO_HASH_UPDATE_SID, - TFM_CRYPTO_HASH_FINISH_SID, - TFM_CRYPTO_HASH_VERIFY_SID, - TFM_CRYPTO_HASH_ABORT_SID, - TFM_CRYPTO_HASH_CLONE_SID, - TFM_CRYPTO_MAC_COMPUTE_SID, - TFM_CRYPTO_MAC_VERIFY_SID, - TFM_CRYPTO_MAC_SIGN_SETUP_SID, - TFM_CRYPTO_MAC_VERIFY_SETUP_SID, - TFM_CRYPTO_MAC_UPDATE_SID, - TFM_CRYPTO_MAC_SIGN_FINISH_SID, - TFM_CRYPTO_MAC_VERIFY_FINISH_SID, - TFM_CRYPTO_MAC_ABORT_SID, - TFM_CRYPTO_CIPHER_ENCRYPT_SID, - TFM_CRYPTO_CIPHER_DECRYPT_SID, - TFM_CRYPTO_CIPHER_ENCRYPT_SETUP_SID, - TFM_CRYPTO_CIPHER_DECRYPT_SETUP_SID, - TFM_CRYPTO_CIPHER_GENERATE_IV_SID, - TFM_CRYPTO_CIPHER_SET_IV_SID, - TFM_CRYPTO_CIPHER_UPDATE_SID, - TFM_CRYPTO_CIPHER_FINISH_SID, - TFM_CRYPTO_CIPHER_ABORT_SID, - TFM_CRYPTO_AEAD_ENCRYPT_SID, - TFM_CRYPTO_AEAD_DECRYPT_SID, - TFM_CRYPTO_AEAD_ENCRYPT_SETUP_SID, - TFM_CRYPTO_AEAD_DECRYPT_SETUP_SID, - TFM_CRYPTO_AEAD_GENERATE_NONCE_SID, - TFM_CRYPTO_AEAD_SET_NONCE_SID, - TFM_CRYPTO_AEAD_SET_LENGTHS_SID, - TFM_CRYPTO_AEAD_UPDATE_AD_SID, - TFM_CRYPTO_AEAD_UPDATE_SID, - TFM_CRYPTO_AEAD_FINISH_SID, - TFM_CRYPTO_AEAD_VERIFY_SID, - TFM_CRYPTO_AEAD_ABORT_SID, - TFM_CRYPTO_SIGN_HASH_SID, - TFM_CRYPTO_VERIFY_HASH_SID, - TFM_CRYPTO_ASYMMETRIC_ENCRYPT_SID, - TFM_CRYPTO_ASYMMETRIC_DECRYPT_SID, - TFM_CRYPTO_KEY_DERIVATION_SETUP_SID, - TFM_CRYPTO_KEY_DERIVATION_GET_CAPACITY_SID, - TFM_CRYPTO_KEY_DERIVATION_SET_CAPACITY_SID, - TFM_CRYPTO_KEY_DERIVATION_INPUT_BYTES_SID, - TFM_CRYPTO_KEY_DERIVATION_INPUT_KEY_SID, - TFM_CRYPTO_KEY_DERIVATION_KEY_AGREEMENT_SID, - TFM_CRYPTO_KEY_DERIVATION_OUTPUT_BYTES_SID, - TFM_CRYPTO_KEY_DERIVATION_OUTPUT_KEY_SID, - TFM_CRYPTO_KEY_DERIVATION_ABORT_SID, - TFM_CRYPTO_RAW_KEY_AGREEMENT_SID, - TFM_CRYPTO_GENERATE_RANDOM_SID, - TFM_CRYPTO_GENERATE_KEY_SID, - TFM_CRYPTO_SET_KEY_DOMAIN_PARAMETERS_SID, - TFM_CRYPTO_GET_KEY_DOMAIN_PARAMETERS_SID, - TFM_CRYPTO_SID_MAX, -}; - -/** - * \brief Define an invalid value for an SID - * - */ -#define TFM_CRYPTO_SID_INVALID (~0x0u) - -/** - * \brief This value is used to mark an handle as invalid. - * - */ -#define TFM_CRYPTO_INVALID_HANDLE (0x0u) - -/** - * \brief The persistent key identifier that refers to the hardware unique key. - * - */ -#define TFM_CRYPTO_KEY_ID_HUK (0xFFFF815Bu) - -/** - * \brief The algorithm identifier that refers to key derivation from the - * hardware unique key. - * - */ -#define TFM_CRYPTO_ALG_HUK_DERIVATION ((psa_algorithm_t)0xB0000F00) - -/** - * \brief Define miscellaneous literal constants that are used in the service - * - */ -enum { - TFM_CRYPTO_NOT_IN_USE = 0, - TFM_CRYPTO_IN_USE = 1 -}; - -#ifdef __cplusplus -} -#endif - -#endif /* __TFM_CRYPTO_DEFS_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_mailbox.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_mailbox.h deleted file mode 100644 index 3d128f4..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_mailbox.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 2019-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/* - * This is header file of common mailbox objects shared by NSPE and SPE. - * Please refer to tfm_ns_mailbox.h for the definitions only used in NSPE - * mailbox library. - * Please refer to tfm_spe_mailbox.h for the SPE specific definitions and APIs. - */ - -#ifndef __TFM_MAILBOX_H__ -#define __TFM_MAILBOX_H__ - -#include -#include -#include -#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL -#include "device_cfg.h" -#endif -#include "psa/client.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * If multiple outstanding NS PSA Client calls is enabled, multi-core platform - * should define the number of mailbox queue slots NUM_MAILBOX_QUEUE_SLOT in - * platform device_cfg.h. - * Otherwise, NUM_MAILBOX_QUEUE_SLOT is defined as 1. - */ -#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL -#ifndef NUM_MAILBOX_QUEUE_SLOT -#error "Error: Platform doesn't define NUM_MAILBOX_QUEUE_SLOT for mailbox queue" -#endif - -#if (NUM_MAILBOX_QUEUE_SLOT < 2) -#error "Error: Invalid NUM_MAILBOX_QUEUE_SLOT. The value should be more than 1" -#endif - -/* - * The number of slots should be no more than the number of bits in - * mailbox_queue_status_t. - * Here the value is hardcoded. A better way is to define a sizeof() to - * calculate the bits in mailbox_queue_status_t and dump it with pragma message. - */ -#if (NUM_MAILBOX_QUEUE_SLOT > 32) -#error "Error: Invalid NUM_MAILBOX_QUEUE_SLOT. The value should be no more than 32" -#endif -#else /* TFM_MULTI_CORE_MULTI_CLIENT_CALL */ -/* Force the number of mailbox queue slots as 1. */ -#undef NUM_MAILBOX_QUEUE_SLOT -#define NUM_MAILBOX_QUEUE_SLOT (1) -#endif /* TFM_MULTI_CORE_MULTI_CLIENT_CALL */ - -/* PSA client call type value */ -#define MAILBOX_PSA_FRAMEWORK_VERSION (0x1) -#define MAILBOX_PSA_VERSION (0x2) -#define MAILBOX_PSA_CONNECT (0x3) -#define MAILBOX_PSA_CALL (0x4) -#define MAILBOX_PSA_CLOSE (0x5) - -/* Return code of mailbox APIs */ -#define MAILBOX_SUCCESS (0) -#define MAILBOX_QUEUE_FULL (INT32_MIN + 1) -#define MAILBOX_INVAL_PARAMS (INT32_MIN + 2) -#define MAILBOX_NO_PERMS (INT32_MIN + 3) -#define MAILBOX_NO_PEND_EVENT (INT32_MIN + 4) -#define MAILBOX_CHAN_BUSY (INT32_MIN + 5) -#define MAILBOX_CALLBACK_REG_ERROR (INT32_MIN + 6) -#define MAILBOX_INIT_ERROR (INT32_MIN + 7) - -/* - * This structure holds the parameters used in a PSA client call. - */ -struct psa_client_params_t { - union { - struct { - uint32_t sid; - } psa_version_params; - - struct { - uint32_t sid; - uint32_t version; - } psa_connect_params; - - struct { - psa_handle_t handle; - int32_t type; - const psa_invec *in_vec; - size_t in_len; - psa_outvec *out_vec; - size_t out_len; - } psa_call_params; - - struct { - psa_handle_t handle; - } psa_close_params; - }; -}; - -/* Mailbox message passed from NSPE to SPE to deliver a PSA client call */ -struct mailbox_msg_t { - uint32_t call_type; /* PSA client call type */ - struct psa_client_params_t params; /* Contain parameters used in PSA - * client call - */ - - int32_t client_id; /* Optional client ID of the - * non-secure caller. - * It is required to identify the - * non-secure task when NSPE OS - * enforces non-secure task isolation - */ -}; - -/* A handle to a mailbox message in use */ -typedef int32_t mailbox_msg_handle_t; - -#define MAILBOX_MSG_NULL_HANDLE ((mailbox_msg_handle_t)0) - -/* - * Mailbox reply structure in non-secure memory - * to hold the PSA client call return result from SPE - */ -struct mailbox_reply_t { - int32_t return_val; -}; - -/* A single slot structure in NSPE mailbox queue */ -struct ns_mailbox_slot_t { - struct mailbox_msg_t msg; - struct mailbox_reply_t reply; - const void *owner; /* Handle of the owner task of this - * slot - */ - bool is_woken; /* Indicate that owner task has been - * or should be woken up, after the - * replied is received. - */ -}; - -typedef uint32_t mailbox_queue_status_t; - -/* NSPE mailbox queue */ -struct ns_mailbox_queue_t { - mailbox_queue_status_t empty_slots; /* Bitmask of empty slots */ - mailbox_queue_status_t pend_slots; /* Bitmask of slots pending - * for SPE handling - */ - mailbox_queue_status_t replied_slots; /* Bitmask of active slots - * containing PSA client call - * return result - */ - - struct ns_mailbox_slot_t queue[NUM_MAILBOX_QUEUE_SLOT]; - -#ifdef TFM_MULTI_CORE_TEST - uint32_t nr_tx; /* The total number of - * submission of NS PSA Client - * calls from NS task via - * mailbox. - */ - uint32_t nr_used_slots; /* The total number of used - * mailbox queue slots each time - * NS thread requests a mailbox - * queue slot. - */ -#endif -}; - -#ifdef __cplusplus -} -#endif - -#endif /* __TFM_MAILBOX_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_multi_core_api.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_multi_core_api.h deleted file mode 100644 index 7999fa4..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_multi_core_api.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#ifndef __TFM_MULTI_CORE_API__ -#define __TFM_MULTI_CORE_API__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/** - * \brief Called on the non-secure CPU. - * Flags that the non-secure side has completed its initialization. - * Waits, if necessary, for the secure CPU to flag that it has completed - * its initialization. - * - * \return Return 0 if succeeds. - * \return Otherwise, return specific error code. - */ -int32_t tfm_ns_wait_for_s_cpu_ready(void); - -/** - * \brief Synchronisation with secure CPU, platform-specific implementation. - * Flags that the non-secure side has completed its initialization. - * Waits, if necessary, for the secure CPU to flag that it has completed - * its initialization. - * - * \retval Return 0 if succeeds. - * \retval Otherwise, return specific error code. - */ -int32_t tfm_platform_ns_wait_for_s_cpu_ready(void); - -/** - * \brief Acquire the multi-core lock for synchronizing PSA client call(s) - * The actual implementation depends on the use scenario. - * - * \return \ref TFM_SUCCESS on success - * \return \ref TFM_ERROR_GENERIC on error - */ -uint32_t tfm_ns_multi_core_lock_acquire(void); - -/** - * \brief Release the multi-core lock for synchronizing PSA client call(s) - * The actual implementation depends on the use scenario. - * - * \return \ref TFM_SUCCESS on success - * \return \ref TFM_ERROR_GENERIC on error - */ -uint32_t tfm_ns_multi_core_lock_release(void); - -#ifdef __cplusplus -} -#endif - -#endif /* __TFM_MULTI_CORE_API__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_ns_interface.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_ns_interface.h deleted file mode 100644 index 21857be..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_ns_interface.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2017-2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ -#ifndef __TFM_NS_INTERFACE_H__ -#define __TFM_NS_INTERFACE_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "tfm_api.h" - -typedef int32_t (*veneer_fn) (uint32_t arg0, uint32_t arg1, - uint32_t arg2, uint32_t arg3); - -/** - * \brief NS interface, veneer function dispatcher - * - * \details This function implements the dispatching mechanism for the - * desired veneer function, to be called with the parameters - * described from arg0 to arg3. - * - * \param[in] fn Function pointer to the veneer function desired - * \param[in] arg0 Argument 0 - * \param[in] arg1 Argument 1 - * \param[in] arg2 Argument 2 - * \param[in] arg3 Argument 3 - * - * \return Returns the same return value of the requested veneer function - */ -int32_t tfm_ns_interface_dispatch(veneer_fn fn, - uint32_t arg0, uint32_t arg1, - uint32_t arg2, uint32_t arg3); - -/** - * \brief NS interface, Initialise the NS interface - * - * \details This function needs to be called from the NS world to - * properly initialise the NS interface towards TF-M. This - * function will initialise all the objects required for - * runtime dispatching of TF-M requests to services - * - * \return A value according to \ref enum tfm_status_e - */ -enum tfm_status_e tfm_ns_interface_init(void); -#ifdef __cplusplus -} -#endif - -#endif /* __TFM_NS_INTERFACE_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_ns_mailbox.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_ns_mailbox.h deleted file mode 100644 index ba902aa..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_ns_mailbox.h +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (c) 2019-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/* Data types and API definitions in NSPE mailbox library */ - -#ifndef __TFM_NS_MAILBOX_H__ -#define __TFM_NS_MAILBOX_H__ - -#include -#include -#include "tfm_mailbox.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef TFM_MULTI_CORE_TEST -/** - * \brief The structure to hold the statistics result of NSPE mailbox - */ -struct ns_mailbox_stats_res_t { - uint8_t avg_nr_slots; /* The value before the decimal point - * in the average number of NSPE - * mailbox slots in use. - */ - uint8_t avg_nr_slots_tenths; /* The first digit value after the - * decimal point in the average - * number of NSPE mailbox slots in use. - */ -}; -#endif - -/** - * \brief Prepare and send PSA client request to SPE via mailbox. - * - * \param[in] call_type PSA client call type - * \param[in] params Parmaters used for PSA client call - * \param[in] client_id Optional client ID of non-secure caller. - * It is required to identify the non-secure caller - * when NSPE OS enforces non-secure task isolation. - * - * \retval >= 0 The handle to the mailbox message assigned. - * \retval < 0 Operation failed with an error code. - */ -mailbox_msg_handle_t tfm_ns_mailbox_tx_client_req(uint32_t call_type, - const struct psa_client_params_t *params, - int32_t client_id); - -/** - * \brief Fetch PSA client return result. - * - * \param[in] handle The handle to the mailbox message - * \param[out] reply The address to be written with return result. - * - * \retval MAILBOX_SUCCESS Successfully get PSA client call return result. - * \retval Other return code Operation failed with an error code. - */ -int32_t tfm_ns_mailbox_rx_client_reply(mailbox_msg_handle_t handle, - int32_t *reply); - -/** - * \brief Check whether a specific mailbox message has been replied. - * - * \param[in] handle The handle to the mailbox message - * - * \retval true The PSA client call return value is replied. - * \retval false The PSA client call return value is not - * replied yet. - */ -bool tfm_ns_mailbox_is_msg_replied(mailbox_msg_handle_t handle); - -/** - * \brief NSPE mailbox initialization - * - * \param[in] queue The base address of NSPE mailbox queue to be - * initialized. - * - * \retval MAILBOX_SUCCESS Operation succeeded. - * \retval Other return code Operation failed with an error code. - */ -int32_t tfm_ns_mailbox_init(struct ns_mailbox_queue_t *queue); - -#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL -/** - * \brief Get the handle of the current non-secure task executing mailbox - * functionalities - * - * \note This function should be implemented according to platform, NS OS - * and actual use scenario. - * This function can be ignored or return NULL if sleep/wake-up mechanism - * is not required in PSA Client API implementation. - * - * \return Return the handle of task. - */ -const void *tfm_ns_mailbox_get_task_handle(void); -#else -static inline const void *tfm_ns_mailbox_get_task_handle(void) -{ - return NULL; -} -#endif - -/** - * \brief Fetch the handle to the first replied mailbox message in the NSPE - * mailbox queue. - * This function is intended to be called inside platform specific - * notification IRQ handler. - * - * \note The replied status of the fetched mailbox message will be cleaned after - * the message is fetched. When this function is called again, it fetches - * the next replied mailbox message from the NSPE mailbox queue. - * - * \return Return the handle to the first replied mailbox message in the - * queue. - * Return \ref MAILBOX_MSG_NULL_HANDLE if no mailbox message is replied. - */ -mailbox_msg_handle_t tfm_ns_mailbox_fetch_reply_msg_isr(void); - -/** - * \brief Return the handle of owner task of a mailbox message according to the - * \ref mailbox_msg_handle_t - * - * \param[in] handle The handle of mailbox message. - * - * \return Return the handle value of the owner task. - */ -const void *tfm_ns_mailbox_get_msg_owner(mailbox_msg_handle_t handle); - -#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL -/** - * \brief Wait for the reply returned from SPE to the mailbox message specified - * by handle - * - * \param[in] handle The handle of mailbox message. - * - * \retval MAILBOX_SUCCESS Return from waiting successfully. - * \retval Other return code Failed to wait with an error code. - */ -int32_t tfm_ns_mailbox_wait_reply(mailbox_msg_handle_t handle); -#endif - -/** - * \brief Platform specific NSPE mailbox initialization. - * Invoked by \ref tfm_ns_mailbox_init(). - * - * \param[in] queue The base address of NSPE mailbox queue to be - * initialized. - * - * \retval MAILBOX_SUCCESS Operation succeeded. - * \retval Other return code Operation failed with an error code. - */ -int32_t tfm_ns_mailbox_hal_init(struct ns_mailbox_queue_t *queue); - -/** - * \brief Notify SPE to deal with the PSA client call sent via mailbox - * - * \note The implementation depends on platform specific hardware and use case. - * - * \retval MAILBOX_SUCCESS Operation succeeded. - * \retval Other return code Operation failed with an error code. - */ -int32_t tfm_ns_mailbox_hal_notify_peer(void); - -/** - * \brief Enter critical section of NSPE mailbox. - * - * \note The implementation depends on platform specific hardware and use case. - */ -void tfm_ns_mailbox_hal_enter_critical(void); - -/** - * \brief Exit critical section of NSPE mailbox. - * - * \note The implementation depends on platform specific hardware and use case. - */ -void tfm_ns_mailbox_hal_exit_critical(void); - -/** - * \brief Enter critical section of NSPE mailbox in IRQ handler. - * - * \note The implementation depends on platform specific hardware and use case. - */ -void tfm_ns_mailbox_hal_enter_critical_isr(void); - -/** - * \brief Enter critical section of NSPE mailbox in IRQ handler - * - * \note The implementation depends on platform specific hardware and use case. - */ -void tfm_ns_mailbox_hal_exit_critical_isr(void); - -#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL -/** - * \brief Performs platform and NS OS specific waiting mechanism to wait for - * the reply of the specified mailbox message to be returned from SPE. - * - * \note This function is implemented by platform and NS OS specific waiting - * mechanism accroding to use scenario. - * - * \param[in] handle The handle of mailbox message. - */ -void tfm_ns_mailbox_hal_wait_reply(mailbox_msg_handle_t handle); -#endif - -#ifdef TFM_MULTI_CORE_TEST -/** - * \brief Initialize the statistics module in TF-M NSPE mailbox. - * - * \note This function is only available when multi-core tests are enabled. - */ -void tfm_ns_mailbox_tx_stats_init(void); - -/** - * \brief Calculate the average number of used NS mailbox queue slots each time - * NS task requires a queue slot to submit mailbox message, which is - * recorded in NS mailbox statisitics module. - * - * \note This function is only available when multi-core tests are enabled. - * - * \param[in] stats_res The buffer to be written with - * \ref ns_mailbox_stats_res_t. - * - * \return Return the calculation result. - */ -void tfm_ns_mailbox_stats_avg_slot(struct ns_mailbox_stats_res_t *stats_res); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* __TFM_NS_MAILBOX_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_ns_svc.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_ns_svc.h deleted file mode 100644 index def0c2f..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_ns_svc.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2017-2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#include -#include "cmsis_compiler.h" - -#ifndef __TFM_NS_SVC_H__ -#define __TFM_NS_SVC_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Include all the SVC handler headers - */ -#include "tfm_nspm_svc_handler.h" - -/** - * \brief Macro to encode an svc instruction - * - */ -#define SVC(code) __ASM volatile("svc %0" : : "I" (code)) - -/** - * \def LIST_SVC_NSPM - * - * \brief This is an X macro which lists - * the SVC interface exposed by TF-M - * for the NS OS. - * - */ -#define LIST_SVC_NSPM \ - X(SVC_TFM_NSPM_REGISTER_CLIENT_ID, tfm_nspm_svc_register_client_id) \ - -/** - * \brief Numbers associated to each SVC available - * - * \details Start from 1 as 0 is reserved by RTX - */ -enum tfm_svc_num { - SVC_INVALID = 0, - -#define X(SVC_ENUM, SVC_HANDLER) SVC_ENUM, - - /* SVC API for Services */ -#ifdef TFM_NS_CLIENT_IDENTIFICATION - LIST_SVC_NSPM -#endif - -#undef X - - /* add all the new entries above this line */ - SVC_TFM_MAX, -}; - -/* number of user SVC functions */ -#define USER_SVC_COUNT ((uint32_t)SVC_TFM_MAX - 1) - -#ifdef __cplusplus -} -#endif - -#endif /* __TFM_NS_SVC_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_platform_api.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_platform_api.h deleted file mode 100644 index 8c9b0db..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_platform_api.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2018-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#ifndef __TFM_PLATFORM_API__ -#define __TFM_PLATFORM_API__ - -#include -#include -#include -#include "tfm_api.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief TFM secure partition platform API version - */ -#define TFM_PLATFORM_API_VERSION_MAJOR (0) -#define TFM_PLATFORM_API_VERSION_MINOR (3) - -#define TFM_PLATFORM_API_ID_NV_READ (1010) -#define TFM_PLATFORM_API_ID_NV_INCREMENT (1011) - -/*! - * \enum tfm_platform_err_t - * - * \brief Platform service error types - * - */ -enum tfm_platform_err_t { - TFM_PLATFORM_ERR_SUCCESS = 0, - TFM_PLATFORM_ERR_SYSTEM_ERROR, - TFM_PLATFORM_ERR_INVALID_PARAM, - TFM_PLATFORM_ERR_NOT_SUPPORTED, - - /* Following entry is only to ensure the error code of int size */ - TFM_PLATFORM_ERR_FORCE_INT_SIZE = INT_MAX -}; - -typedef int32_t tfm_platform_ioctl_req_t; - -/*! - * \brief Resets the system. - * - * \return Returns values as specified by the \ref tfm_platform_err_t - */ -enum tfm_platform_err_t tfm_platform_system_reset(void); - -/*! - * \brief Performs a platform-specific service - * - * \param[in] request Request identifier (valid values vary - * based on the platform) - * \param[in] input Input buffer to the requested service (or NULL) - * \param[in,out] output Output buffer to the requested service (or NULL) - * - * \return Returns values as specified by the \ref tfm_platform_err_t - */ -enum tfm_platform_err_t tfm_platform_ioctl(tfm_platform_ioctl_req_t request, - psa_invec *input, - psa_outvec *output); - -/*! - * \brief Increments the given non-volatile (NV) counter by one - * - * \param[in] counter_id NV counter ID. - * - * \return TFM_PLATFORM_ERR_SUCCESS if the value is read correctly. Otherwise, - * it returns TFM_PLATFORM_ERR_SYSTEM_ERROR. - */ -enum tfm_platform_err_t -tfm_platform_nv_counter_increment(uint32_t counter_id); - -/*! - * \brief Reads the given non-volatile (NV) counter - * - * \param[in] counter_id NV counter ID. - * \param[in] size Size of the buffer to store NV counter value - * in bytes. - * \param[out] val Pointer to store the current NV counter value. - * - * \return TFM_PLATFORM_ERR_SUCCESS if the value is read correctly. Otherwise, - * it returns TFM_PLATFORM_ERR_SYSTEM_ERROR. - */ -enum tfm_platform_err_t -tfm_platform_nv_counter_read(uint32_t counter_id, - uint32_t size, uint8_t *val); - -#ifdef __cplusplus -} -#endif - -#endif /* __TFM_PLATFORM_API__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_veneers.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_veneers.h deleted file mode 100644 index d2d9207..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_veneers.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 2018-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#ifndef __TFM_VENEERS_H__ -#define __TFM_VENEERS_H__ - -#include "tfm_api.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef TFM_PARTITION_SECURE_STORAGE -/******** TFM_SP_STORAGE ********/ -psa_status_t tfm_tfm_sst_set_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_sst_get_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_sst_get_info_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_sst_remove_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_sst_get_support_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_SECURE_STORAGE */ - -#ifdef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE -/******** TFM_SP_ITS ********/ -psa_status_t tfm_tfm_its_set_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_its_get_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_its_get_info_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_its_remove_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */ - -#ifdef TFM_PARTITION_AUDIT_LOG -/******** TFM_SP_AUDIT_LOG ********/ -psa_status_t tfm_audit_core_retrieve_record_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_audit_core_add_record_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_audit_core_get_info_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_audit_core_get_record_info_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_audit_core_delete_record_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_AUDIT_LOG */ - -#ifdef TFM_PARTITION_CRYPTO -/******** TFM_SP_CRYPTO ********/ -psa_status_t tfm_tfm_crypto_get_key_attributes_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_open_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_close_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_reset_key_attributes_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_import_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_destroy_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_export_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_export_public_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_copy_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_hash_compute_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_hash_compare_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_hash_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_hash_update_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_hash_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_hash_verify_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_hash_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_hash_clone_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_mac_compute_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_mac_verify_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_mac_sign_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_mac_verify_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_mac_update_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_mac_sign_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_mac_verify_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_mac_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_cipher_encrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_cipher_decrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_cipher_encrypt_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_cipher_decrypt_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_cipher_generate_iv_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_cipher_set_iv_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_cipher_update_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_cipher_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_cipher_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_aead_encrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_aead_decrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_aead_encrypt_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_aead_decrypt_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_aead_generate_nonce_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_aead_set_nonce_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_aead_set_lengths_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_aead_update_ad_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_aead_update_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_aead_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_aead_verify_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_aead_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_sign_hash_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_verify_hash_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_asymmetric_encrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_asymmetric_decrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_key_derivation_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_key_derivation_get_capacity_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_key_derivation_set_capacity_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_key_derivation_input_bytes_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_key_derivation_input_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_key_derivation_key_agreement_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_key_derivation_output_bytes_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_key_derivation_output_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_key_derivation_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_raw_key_agreement_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_generate_random_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_generate_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_CRYPTO */ - -#ifdef TFM_PARTITION_PLATFORM -/******** TFM_SP_PLATFORM ********/ -psa_status_t tfm_platform_sp_system_reset_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_platform_sp_ioctl_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_platform_sp_nv_counter_read_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_platform_sp_nv_counter_increment_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_PLATFORM */ - -#ifdef TFM_PARTITION_INITIAL_ATTESTATION -/******** TFM_SP_INITIAL_ATTESTATION ********/ -psa_status_t tfm_initial_attest_get_token_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_initial_attest_get_token_size_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_initial_attest_get_public_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_INITIAL_ATTESTATION */ - -#ifdef TFM_PARTITION_TEST_CORE -/******** TFM_SP_CORE_TEST ********/ -psa_status_t tfm_spm_core_test_sfn_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_spm_core_test_sfn_init_success_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_spm_core_test_sfn_direct_recursion_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_TEST_CORE */ - -#ifdef TFM_PARTITION_TEST_CORE -/******** TFM_SP_CORE_TEST_2 ********/ -psa_status_t tfm_spm_core_test_2_slave_service_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_spm_core_test_2_sfn_invert_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_spm_core_test_2_check_caller_client_id_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_spm_core_test_2_get_every_second_byte_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_spm_core_test_2_prepare_test_scenario_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_spm_core_test_2_execute_test_scenario_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_TEST_CORE */ - -#ifdef TFM_PARTITION_TEST_SECURE_SERVICES -/******** TFM_SP_SECURE_TEST_PARTITION ********/ -psa_status_t tfm_tfm_secure_client_service_sfn_run_tests_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ - -#ifdef TFM_PARTITION_TEST_CORE_IPC -/******** TFM_SP_IPC_SERVICE_TEST ********/ -#endif /* TFM_PARTITION_TEST_CORE_IPC */ - -#ifdef TFM_PARTITION_TEST_CORE_IPC -/******** TFM_SP_IPC_CLIENT_TEST ********/ -#endif /* TFM_PARTITION_TEST_CORE_IPC */ - -#ifdef TFM_ENABLE_IRQ_TEST -/******** TFM_IRQ_TEST_1 ********/ -psa_status_t tfm_spm_irq_test_1_prepare_test_scenario_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_spm_irq_test_1_execute_test_scenario_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_ENABLE_IRQ_TEST */ - -#ifdef TFM_PARTITION_TEST_SST -/******** TFM_SP_SST_TEST ********/ -psa_status_t tfm_tfm_sst_test_prepare_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_TEST_SST */ - -#ifdef TFM_PARTITION_TEST_SECURE_SERVICES -/******** TFM_SP_SECURE_CLIENT_2 ********/ -psa_status_t tfm_tfm_secure_client_2_call_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ - -#ifdef TFM_MULTI_CORE_TEST -/******** TFM_SP_MULTI_CORE_TEST ********/ -#endif /* TFM_MULTI_CORE_TEST */ - -#ifdef __cplusplus -} -#endif - -#endif /* __TFM_VENEERS_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_crypto_ipc_api.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_crypto_ipc_api.c deleted file mode 100644 index 70b3a0d..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_crypto_ipc_api.c +++ /dev/null @@ -1,1875 +0,0 @@ -/* - * Copyright (c) 2018-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#include "tfm_crypto_defs.h" -#include "psa/crypto.h" -#include "tfm_ns_interface.h" -#include "psa_manifest/sid.h" -#include "psa/client.h" - -#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0])) - -#define PSA_CONNECT(service) \ - psa_handle_t ipc_handle; \ - ipc_handle = psa_connect(service##_SID, service##_VERSION); \ - if (!PSA_HANDLE_IS_VALID(ipc_handle)) { \ - return PSA_ERROR_GENERIC_ERROR; \ - } \ - -#define PSA_CLOSE() psa_close(ipc_handle) - -#define API_DISPATCH(sfn_name, sfn_id) \ - psa_call(ipc_handle, PSA_IPC_CALL, \ - in_vec, ARRAY_SIZE(in_vec), \ - out_vec, ARRAY_SIZE(out_vec)) - -#define API_DISPATCH_NO_OUTVEC(sfn_name, sfn_id) \ - psa_call(ipc_handle, PSA_IPC_CALL, \ - in_vec, ARRAY_SIZE(in_vec), \ - (psa_outvec *)NULL, 0) - -psa_status_t psa_crypto_init(void) -{ - /* Service init is performed during TFM boot up, - * so application level initialisation is empty - */ - return PSA_SUCCESS; -} - -psa_status_t psa_open_key(psa_key_id_t id, - psa_key_handle_t *handle) -{ -#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - const struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_OPEN_KEY_SID, - }; - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = &id, .len = sizeof(psa_key_id_t)}, - }; - psa_outvec out_vec[] = { - {.base = handle, .len = sizeof(psa_key_handle_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_open_key, - TFM_CRYPTO_OPEN_KEY); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ -} - -psa_status_t psa_close_key(psa_key_handle_t handle) -{ -#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - const struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_CLOSE_KEY_SID, - .key_handle = handle, - }; - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH_NO_OUTVEC(tfm_crypto_close_key, - TFM_CRYPTO_CLOSE_KEY);; - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ -} - -psa_status_t psa_import_key(const psa_key_attributes_t *attributes, - const uint8_t *data, - size_t data_length, - psa_key_handle_t *handle) -{ -#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_IMPORT_KEY_SID, - }; - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = attributes, .len = sizeof(psa_key_attributes_t)}, - {.base = data, .len = data_length} - }; - psa_outvec out_vec[] = { - {.base = handle, .len = sizeof(psa_key_handle_t)} - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_import_key, - TFM_CRYPTO_IMPORT_KEY); - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ -} - -psa_status_t psa_destroy_key(psa_key_handle_t handle) -{ -#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_DESTROY_KEY_SID, - .key_handle = handle, - }; - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH_NO_OUTVEC(tfm_crypto_destroy_key, - TFM_CRYPTO_DESTROY_KEY); - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ -} - -psa_status_t psa_get_key_attributes(psa_key_handle_t handle, - psa_key_attributes_t *attributes) -{ -#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_GET_KEY_ATTRIBUTES_SID, - .key_handle = handle, - }; - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = attributes, .len = sizeof(psa_key_attributes_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_get_key_attributes, - TFM_CRYPTO_GET_KEY_ATTRIBUTES); - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ -} - -void psa_reset_key_attributes(psa_key_attributes_t *attributes) -{ -#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED - return; -#else - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_RESET_KEY_ATTRIBUTES_SID, - }; - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = attributes, .len = sizeof(psa_key_attributes_t)}, - }; - - psa_handle_t ipc_handle; - ipc_handle = psa_connect(TFM_CRYPTO_SID, TFM_CRYPTO_VERSION); - if (!PSA_HANDLE_IS_VALID(ipc_handle)) { - return; - } - - (void)API_DISPATCH(tfm_crypto_reset_key_attributes, - TFM_CRYPTO_RESET_KEY_ATTRIBUTES); - PSA_CLOSE(); - - return; -#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ -} - -psa_status_t psa_export_key(psa_key_handle_t handle, - uint8_t *data, - size_t data_size, - size_t *data_length) -{ -#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_EXPORT_KEY_SID, - .key_handle = handle, - }; - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = data, .len = data_size} - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_export_key, - TFM_CRYPTO_EXPORT_KEY); - - *data_length = out_vec[0].len; - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ -} - -psa_status_t psa_export_public_key(psa_key_handle_t handle, - uint8_t *data, - size_t data_size, - size_t *data_length) -{ -#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_EXPORT_PUBLIC_KEY_SID, - .key_handle = handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = data, .len = data_size} - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_export_public_key, - TFM_CRYPTO_EXPORT_PUBLIC_KEY); - - *data_length = out_vec[0].len; - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ -} - -psa_status_t psa_copy_key(psa_key_handle_t source_handle, - const psa_key_attributes_t *attributes, - psa_key_handle_t *target_handle) -{ -#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_COPY_KEY_SID, - .key_handle = source_handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = attributes, .len = sizeof(psa_key_attributes_t)}, - - }; - - psa_outvec out_vec[] = { - {.base = target_handle, .len = sizeof(psa_key_handle_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_copy_key, - TFM_CRYPTO_COPY_KEY); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ -} - -psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation, - unsigned char *iv, - size_t iv_size, - size_t *iv_length) -{ -#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_CIPHER_GENERATE_IV_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - {.base = iv, .len = iv_size}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_cipher_generate_iv, - TFM_CRYPTO_CIPHER_GENERATE_IV); - - *iv_length = out_vec[1].len; - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ -} - -psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, - const unsigned char *iv, - size_t iv_length) -{ -#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_CIPHER_SET_IV_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = iv, .len = iv_length}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_cipher_set_iv, - TFM_CRYPTO_CIPHER_SET_IV); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ -} - -psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg) -{ -#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_CIPHER_ENCRYPT_SETUP_SID, - .key_handle = handle, - .alg = alg, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_cipher_encrypt_setup, - TFM_CRYPTO_CIPHER_ENCRYPT_SETUP); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ -} - -psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg) -{ -#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_CIPHER_DECRYPT_SETUP_SID, - .key_handle = handle, - .alg = alg, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_cipher_decrypt_setup, - TFM_CRYPTO_CIPHER_DECRYPT_SETUP); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ -} - -psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, - const uint8_t *input, - size_t input_length, - unsigned char *output, - size_t output_size, - size_t *output_length) -{ -#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_CIPHER_UPDATE_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = input, .len = input_length}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - {.base = output, .len = output_size} - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_cipher_update, - TFM_CRYPTO_CIPHER_UPDATE); - - *output_length = out_vec[1].len; - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ -} - -psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation) -{ -#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_CIPHER_ABORT_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_cipher_abort, - TFM_CRYPTO_CIPHER_ABORT); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ -} - -psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, - uint8_t *output, - size_t output_size, - size_t *output_length) -{ -#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_CIPHER_FINISH_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - {.base = output, .len = output_size}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_cipher_finish, - TFM_CRYPTO_CIPHER_FINISH); - - *output_length = out_vec[1].len; - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ -} - -psa_status_t psa_hash_setup(psa_hash_operation_t *operation, - psa_algorithm_t alg) -{ -#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_HASH_SETUP_SID, - .alg = alg, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_hash_setup, - TFM_CRYPTO_HASH_SETUP); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_HASH_MODULE_DISABLED */ -} - -psa_status_t psa_hash_update(psa_hash_operation_t *operation, - const uint8_t *input, - size_t input_length) -{ -#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_HASH_UPDATE_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = input, .len = input_length}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_hash_update, - TFM_CRYPTO_HASH_UPDATE); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_HASH_MODULE_DISABLED */ -} - -psa_status_t psa_hash_finish(psa_hash_operation_t *operation, - uint8_t *hash, - size_t hash_size, - size_t *hash_length) -{ -#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_HASH_FINISH_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - {.base = hash, .len = hash_size}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_hash_finish, - TFM_CRYPTO_HASH_FINISH); - - *hash_length = out_vec[1].len; - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_HASH_MODULE_DISABLED */ -} - -psa_status_t psa_hash_verify(psa_hash_operation_t *operation, - const uint8_t *hash, - size_t hash_length) -{ -#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_HASH_VERIFY_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = hash, .len = hash_length}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_hash_verify, - TFM_CRYPTO_HASH_VERIFY); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_HASH_MODULE_DISABLED */ -} - -psa_status_t psa_hash_abort(psa_hash_operation_t *operation) -{ -#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_HASH_ABORT_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_hash_abort, - TFM_CRYPTO_HASH_ABORT); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_HASH_MODULE_DISABLED */ -} - -psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation, - psa_hash_operation_t *target_operation) -{ -#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_HASH_CLONE_SID, - .op_handle = source_operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = target_operation, .len = sizeof(psa_hash_operation_t)}, - }; - - if (target_operation && (target_operation->handle != 0)) { - return PSA_ERROR_BAD_STATE; - } - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_hash_clone, - TFM_CRYPTO_HASH_CLONE); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_HASH_MODULE_DISABLED */ -} - -psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg) -{ -#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_MAC_SIGN_SETUP_SID, - .key_handle = handle, - .alg = alg, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_mac_sign_setup, - TFM_CRYPTO_MAC_SIGN_SETUP); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */ -} - -psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg) -{ -#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_MAC_VERIFY_SETUP_SID, - .key_handle = handle, - .alg = alg, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_mac_verify_setup, - TFM_CRYPTO_MAC_VERIFY_SETUP); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */ -} - -psa_status_t psa_mac_update(psa_mac_operation_t *operation, - const uint8_t *input, - size_t input_length) -{ -#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_MAC_UPDATE_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = input, .len = input_length}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_mac_update, - TFM_CRYPTO_MAC_UPDATE); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */ -} - -psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, - uint8_t *mac, - size_t mac_size, - size_t *mac_length) -{ -#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_MAC_SIGN_FINISH_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - {.base = mac, .len = mac_size}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_mac_sign_finish, - TFM_CRYPTO_MAC_SIGN_FINISH); - - *mac_length = out_vec[1].len; - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */ -} - -psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation, - const uint8_t *mac, - size_t mac_length) -{ -#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_MAC_VERIFY_FINISH_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = mac, .len = mac_length}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_mac_verify_finish, - TFM_CRYPTO_MAC_VERIFY_FINISH); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */ -} - -psa_status_t psa_mac_abort(psa_mac_operation_t *operation) -{ -#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_MAC_ABORT_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_mac_abort, - TFM_CRYPTO_MAC_ABORT); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */ -} - -psa_status_t psa_aead_encrypt(psa_key_handle_t handle, - 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 *ciphertext, - size_t ciphertext_size, - size_t *ciphertext_length) -{ -#ifdef TFM_CRYPTO_AEAD_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_AEAD_ENCRYPT_SID, - .key_handle = handle, - .alg = alg, - .aead_in = {.nonce = {0}, .nonce_length = nonce_length} - }; - - /* Sanitize the optional input */ - if ((additional_data == NULL) && (additional_data_length != 0)) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - size_t idx = 0; - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = plaintext, .len = plaintext_length}, - {.base = additional_data, .len = additional_data_length}, - }; - psa_outvec out_vec[] = { - {.base = ciphertext, .len = ciphertext_size}, - }; - - if (nonce_length > TFM_CRYPTO_MAX_NONCE_LENGTH) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - if (nonce != NULL) { - for (idx = 0; idx < nonce_length; idx++) { - iov.aead_in.nonce[idx] = nonce[idx]; - } - } - - PSA_CONNECT(TFM_CRYPTO); - - size_t in_len = ARRAY_SIZE(in_vec); - if (additional_data == NULL) { - in_len--; - } - status = psa_call(ipc_handle, PSA_IPC_CALL, in_vec, in_len, - out_vec, ARRAY_SIZE(out_vec)); - - *ciphertext_length = out_vec[0].len; - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_AEAD_MODULE_DISABLED */ -} - -psa_status_t psa_aead_decrypt(psa_key_handle_t handle, - 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 *ciphertext, - size_t ciphertext_length, - uint8_t *plaintext, - size_t plaintext_size, - size_t *plaintext_length) -{ -#ifdef TFM_CRYPTO_AEAD_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_AEAD_DECRYPT_SID, - .key_handle = handle, - .alg = alg, - .aead_in = {.nonce = {0}, .nonce_length = nonce_length} - }; - - /* Sanitize the optional input */ - if ((additional_data == NULL) && (additional_data_length != 0)) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - size_t idx = 0; - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = ciphertext, .len = ciphertext_length}, - {.base = additional_data, .len = additional_data_length}, - }; - psa_outvec out_vec[] = { - {.base = plaintext, .len = plaintext_size}, - }; - - if (nonce_length > TFM_CRYPTO_MAX_NONCE_LENGTH) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - if (nonce != NULL) { - for (idx = 0; idx < nonce_length; idx++) { - iov.aead_in.nonce[idx] = nonce[idx]; - } - } - - PSA_CONNECT(TFM_CRYPTO); - - size_t in_len = ARRAY_SIZE(in_vec); - if (additional_data == NULL) { - in_len--; - } - status = psa_call(ipc_handle, PSA_IPC_CALL, in_vec, in_len, - out_vec, ARRAY_SIZE(out_vec)); - - *plaintext_length = out_vec[0].len; - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_AEAD_MODULE_DISABLED */ -} - -psa_status_t psa_asymmetric_sign(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *hash, - size_t hash_length, - uint8_t *signature, - size_t signature_size, - size_t *signature_length) -{ - return psa_sign_hash(handle, alg, hash, hash_length, signature, signature_size, signature_length); -} - -psa_status_t psa_sign_hash(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *hash, - size_t hash_length, - uint8_t *signature, - size_t signature_size, - size_t *signature_length) -{ -#ifdef TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_SIGN_HASH_SID, - .key_handle = handle, - .alg = alg, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = hash, .len = hash_length}, - }; - psa_outvec out_vec[] = { - {.base = signature, .len = signature_size}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_sign_hash, - TFM_CRYPTO_SIGN_HASH); - - *signature_length = out_vec[0].len; - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED */ -} - -psa_status_t psa_asymmetric_verify(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *hash, - size_t hash_length, - const uint8_t *signature, - size_t signature_length) -{ - return psa_verify_hash(handle, alg, hash, hash_length, signature, signature_length); -} - -psa_status_t psa_verify_hash(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *hash, - size_t hash_length, - const uint8_t *signature, - size_t signature_length) -{ -#ifdef TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_VERIFY_HASH_SID, - .key_handle = handle, - .alg = alg - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = hash, .len = hash_length}, - {.base = signature, .len = signature_length} - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH_NO_OUTVEC(tfm_crypto_verify_hash, - TFM_CRYPTO_VERIFY_HASH); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED */ -} - -psa_status_t psa_asymmetric_encrypt(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - const uint8_t *salt, - size_t salt_length, - uint8_t *output, - size_t output_size, - size_t *output_length) -{ -#ifdef TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_ASYMMETRIC_ENCRYPT_SID, - .key_handle = handle, - .alg = alg - }; - - /* Sanitize the optional input */ - if ((salt == NULL) && (salt_length != 0)) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = input, .len = input_length}, - {.base = salt, .len = salt_length} - }; - - psa_outvec out_vec[] = { - {.base = output, .len = output_size}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - size_t in_len = ARRAY_SIZE(in_vec); - if (salt == NULL) { - in_len--; - } - status = psa_call(ipc_handle, PSA_IPC_CALL, in_vec, in_len, - out_vec, ARRAY_SIZE(out_vec)); - - *output_length = out_vec[0].len; - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED */ -} - -psa_status_t psa_asymmetric_decrypt(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - const uint8_t *salt, - size_t salt_length, - uint8_t *output, - size_t output_size, - size_t *output_length) -{ -#ifdef TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_ASYMMETRIC_DECRYPT_SID, - .key_handle = handle, - .alg = alg - }; - - /* Sanitize the optional input */ - if ((salt == NULL) && (salt_length != 0)) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = input, .len = input_length}, - {.base = salt, .len = salt_length} - }; - - psa_outvec out_vec[] = { - {.base = output, .len = output_size}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - size_t in_len = ARRAY_SIZE(in_vec); - if (salt == NULL) { - in_len--; - } - status = psa_call(ipc_handle, PSA_IPC_CALL, in_vec, in_len, - out_vec, ARRAY_SIZE(out_vec)); - - *output_length = out_vec[0].len; - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED */ -} - -psa_status_t psa_key_derivation_get_capacity( - const psa_key_derivation_operation_t *operation, - size_t *capacity) -{ -#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_KEY_DERIVATION_GET_CAPACITY_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - - psa_outvec out_vec[] = { - {.base = capacity, .len = sizeof(size_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_key_derivation_get_capacity, - TFM_CRYPTO_KEY_DERIVATION_GET_CAPACITY); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ -} - -psa_status_t psa_key_derivation_output_bytes( - psa_key_derivation_operation_t *operation, - uint8_t *output, - size_t output_length) -{ -#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_KEY_DERIVATION_OUTPUT_BYTES_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - - psa_outvec out_vec[] = { - {.base = output, .len = output_length}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_key_derivation_output_bytes, - TFM_CRYPTO_KEY_DERIVATION_OUTPUT_BYTES); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ -} - -psa_status_t psa_key_derivation_input_key( - psa_key_derivation_operation_t *operation, - psa_key_derivation_step_t step, - psa_key_handle_t handle) -{ -#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_KEY_DERIVATION_INPUT_KEY_SID, - .key_handle = handle, - .step = step, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH_NO_OUTVEC(tfm_crypto_key_derivation_input_key, - TFM_CRYPTO_KEY_DERIVATION_INPUT_KEY); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ -} - -psa_status_t psa_key_derivation_abort( - psa_key_derivation_operation_t *operation) -{ -#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_KEY_DERIVATION_ABORT_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_key_derivation_abort, - TFM_CRYPTO_KEY_DERIVATION_ABORT); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ -} - -psa_status_t psa_key_derivation_key_agreement( - psa_key_derivation_operation_t *operation, - psa_key_derivation_step_t step, - psa_key_handle_t private_key, - const uint8_t *peer_key, - size_t peer_key_length) -{ -#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_KEY_DERIVATION_KEY_AGREEMENT_SID, - .key_handle = private_key, - .step = step, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = peer_key, .len = peer_key_length}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH_NO_OUTVEC(tfm_crypto_key_derivation_key_agreement, - TFM_CRYPTO_KEY_DERIVATION_KEY_AGREEMENT); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ -} - -psa_status_t psa_generate_random(uint8_t *output, - size_t output_size) -{ -#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_GENERATE_RANDOM_SID, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - - psa_outvec out_vec[] = { - {.base = output, .len = output_size}, - }; - - if (output_size == 0) { - return PSA_SUCCESS; - } - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_generate_random, - TFM_CRYPTO_GENERATE_RANDOM); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ -} - -psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, - psa_key_handle_t *handle) -{ -#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_GENERATE_KEY_SID, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = attributes, .len = sizeof(psa_key_attributes_t)}, - }; - - psa_outvec out_vec[] = { - {.base = handle, .len = sizeof(psa_key_handle_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_generate_key, - TFM_CRYPTO_GENERATE_KEY); - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ -} - -psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes, - psa_key_type_t type, - const uint8_t *data, - size_t data_length) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_get_key_domain_parameters( - const psa_key_attributes_t *attributes, - uint8_t *data, - size_t data_size, - size_t *data_length) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_hash_compare(psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - const uint8_t *hash, - const size_t hash_length) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation, - const uint8_t *input, - size_t input_length) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_aead_finish(psa_aead_operation_t *operation, - uint8_t *ciphertext, - size_t ciphertext_size, - size_t *ciphertext_length, - uint8_t *tag, - size_t tag_size, - size_t *tag_length) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_aead_verify(psa_aead_operation_t *operation, - uint8_t *plaintext, - size_t plaintext_size, - size_t *plaintext_length, - const uint8_t *tag, - size_t tag_length) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_aead_abort(psa_aead_operation_t *operation) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_mac_compute(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - uint8_t *mac, - size_t mac_size, - size_t *mac_length) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_mac_verify(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - const uint8_t *mac, - const size_t mac_length) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_cipher_encrypt(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - uint8_t *output, - size_t output_size, - size_t *output_length) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_cipher_decrypt(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - uint8_t *output, - size_t output_size, - size_t *output_length) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, - psa_key_handle_t private_key, - const uint8_t *peer_key, - size_t peer_key_length, - uint8_t *output, - size_t output_size, - size_t *output_length) -{ -#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_RAW_KEY_AGREEMENT_SID, - .alg = alg, - .key_handle = private_key - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = peer_key, .len = peer_key_length}, - }; - - psa_outvec out_vec[] = { - {.base = output, .len = output_size}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_raw_key_agreement, - TFM_CRYPTO_RAW_KEY_AGREEMENT); - - *output_length = out_vec[0].len; - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ -} - -psa_status_t psa_key_derivation_setup(psa_key_derivation_operation_t *operation, - psa_algorithm_t alg) -{ -#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_KEY_DERIVATION_SETUP_SID, - .alg = alg, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_key_derivation_setup, - TFM_CRYPTO_KEY_DERIVATION_SETUP); - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ -} - -psa_status_t psa_key_derivation_set_capacity( - psa_key_derivation_operation_t *operation, - size_t capacity) -{ -#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_KEY_DERIVATION_SET_CAPACITY_SID, - .capacity = capacity, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH_NO_OUTVEC(tfm_crypto_key_derivation_set_capacity, - TFM_CRYPTO_KEY_DERIVATION_SET_CAPACITY); - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ -} - -psa_status_t psa_key_derivation_input_bytes( - psa_key_derivation_operation_t *operation, - psa_key_derivation_step_t step, - const uint8_t *data, - size_t data_length) -{ -#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_KEY_DERIVATION_INPUT_BYTES_SID, - .step = step, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = data, .len = data_length}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH_NO_OUTVEC(tfm_crypto_key_derivation_input_bytes, - TFM_CRYPTO_KEY_DERIVATION_INPUT_BYTES); - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ -} - -psa_status_t psa_key_derivation_output_key( - const psa_key_attributes_t *attributes, - psa_key_derivation_operation_t *operation, - psa_key_handle_t *handle) -{ -#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_KEY_DERIVATION_OUTPUT_KEY_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = attributes, .len = sizeof(psa_key_attributes_t)}, - }; - - psa_outvec out_vec[] = { - {.base = handle, .len = sizeof(psa_key_handle_t)} - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_key_derivation_output_key, - TFM_CRYPTO_KEY_DERIVATION_OUTPUT_KEY); - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ -} - -psa_status_t psa_hash_compute(psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - uint8_t *hash, - size_t hash_size, - size_t *hash_length) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation, - uint8_t *nonce, - size_t nonce_size, - size_t *nonce_length) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation, - const uint8_t *nonce, - size_t nonce_length) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation, - size_t ad_length, - size_t plaintext_length) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_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 status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_initial_attestation_ipc_api.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_initial_attestation_ipc_api.c deleted file mode 100644 index 78f9dec..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_initial_attestation_ipc_api.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2018-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#include "psa/initial_attestation.h" -#include "tfm_ns_interface.h" -#include "psa/client.h" -#include "psa/crypto_types.h" -#include "psa_manifest/sid.h" - -#define IOVEC_LEN(x) (sizeof(x)/sizeof(x[0])) - -psa_status_t -psa_initial_attest_get_token(const uint8_t *auth_challenge, - size_t challenge_size, - uint8_t *token_buf, - size_t token_buf_size, - size_t *token_size) -{ - psa_handle_t handle = PSA_NULL_HANDLE; - psa_status_t status; - - psa_invec in_vec[] = { - {auth_challenge, challenge_size} - }; - psa_outvec out_vec[] = { - {token_buf, token_buf_size} - }; - - handle = psa_connect(TFM_ATTEST_GET_TOKEN_SID, - TFM_ATTEST_GET_TOKEN_VERSION); - if (!PSA_HANDLE_IS_VALID(handle)) { - return PSA_HANDLE_TO_ERROR(handle); - } - - status = psa_call(handle, PSA_IPC_CALL, - in_vec, IOVEC_LEN(in_vec), - out_vec, IOVEC_LEN(out_vec)); - psa_close(handle); - - if (status == PSA_SUCCESS) { - *token_size = out_vec[0].len; - } - - return status; -} - -psa_status_t -psa_initial_attest_get_token_size(size_t challenge_size, - size_t *token_size) -{ - psa_handle_t handle = PSA_NULL_HANDLE; - psa_status_t status; - psa_invec in_vec[] = { - {&challenge_size, sizeof(challenge_size)} - }; - psa_outvec out_vec[] = { - {token_size, sizeof(size_t)} - }; - - handle = psa_connect(TFM_ATTEST_GET_TOKEN_SIZE_SID, - TFM_ATTEST_GET_TOKEN_SIZE_VERSION); - if (!PSA_HANDLE_IS_VALID(handle)) { - return PSA_HANDLE_TO_ERROR(handle); - } - - status = psa_call(handle, PSA_IPC_CALL, - in_vec, IOVEC_LEN(in_vec), - out_vec, IOVEC_LEN(out_vec)); - psa_close(handle); - - return status; -} - -psa_status_t -tfm_initial_attest_get_public_key(uint8_t *public_key, - size_t public_key_buf_size, - size_t *public_key_len, - psa_ecc_curve_t *elliptic_curve_type) -{ - psa_handle_t handle = PSA_NULL_HANDLE; - psa_status_t status; - - psa_outvec out_vec[] = { - {.base = public_key, .len = public_key_buf_size}, - {.base = elliptic_curve_type, .len = sizeof(*elliptic_curve_type)}, - {.base = public_key_len, .len = sizeof(*public_key_len)} - }; - - handle = psa_connect(TFM_ATTEST_GET_PUBLIC_KEY_SID, - TFM_ATTEST_GET_PUBLIC_KEY_VERSION); - if (!PSA_HANDLE_IS_VALID(handle)) { - return PSA_HANDLE_TO_ERROR(handle); - } - - status = psa_call(handle, PSA_IPC_CALL, - NULL, 0, - out_vec, IOVEC_LEN(out_vec)); - psa_close(handle); - - return status; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_its_ipc_api.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_its_ipc_api.c deleted file mode 100644 index 9326f7b..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_its_ipc_api.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#include "psa/internal_trusted_storage.h" -#include "tfm_api.h" - -#include "psa/client.h" -#include "psa_manifest/sid.h" - -#define IOVEC_LEN(x) (sizeof(x)/sizeof(x[0])) - -psa_status_t psa_its_set(psa_storage_uid_t uid, - size_t data_length, - const void *p_data, - psa_storage_create_flags_t create_flags) -{ - psa_status_t status; - psa_handle_t handle; - - psa_invec in_vec[] = { - { .base = &uid, .len = sizeof(uid) }, - { .base = p_data, .len = data_length }, - { .base = &create_flags, .len = sizeof(create_flags) } - }; - - handle = psa_connect(TFM_ITS_SET_SID, TFM_ITS_SET_VERSION); - if (!PSA_HANDLE_IS_VALID(handle)) { - return PSA_ERROR_GENERIC_ERROR; - } - - status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), NULL, 0); - - psa_close(handle); - - if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - return status; -} - -psa_status_t psa_its_get(psa_storage_uid_t uid, - size_t data_offset, - size_t data_size, - void *p_data, - size_t *p_data_length) -{ - psa_status_t status; - psa_handle_t handle; - - psa_invec in_vec[] = { - { .base = &uid, .len = sizeof(uid) }, - { .base = &data_offset, .len = sizeof(data_offset) } - }; - - psa_outvec out_vec[] = { - { .base = p_data, .len = data_size } - }; - - if (p_data_length == NULL) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - handle = psa_connect(TFM_ITS_GET_SID, TFM_ITS_GET_VERSION); - if (!PSA_HANDLE_IS_VALID(handle)) { - return PSA_ERROR_GENERIC_ERROR; - } - - status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), out_vec, - IOVEC_LEN(out_vec)); - - psa_close(handle); - - if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - *p_data_length = out_vec[0].len; - - return status; -} - -psa_status_t psa_its_get_info(psa_storage_uid_t uid, - struct psa_storage_info_t *p_info) -{ - psa_status_t status; - psa_handle_t handle; - - psa_invec in_vec[] = { - { .base = &uid, .len = sizeof(uid) } - }; - - psa_outvec out_vec[] = { - { .base = p_info, .len = sizeof(*p_info) } - }; - - handle = psa_connect(TFM_ITS_GET_INFO_SID, TFM_ITS_GET_INFO_VERSION); - if (!PSA_HANDLE_IS_VALID(handle)) { - return PSA_ERROR_GENERIC_ERROR; - } - - status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), out_vec, - IOVEC_LEN(out_vec)); - - psa_close(handle); - - if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - return status; -} - -psa_status_t psa_its_remove(psa_storage_uid_t uid) -{ - psa_status_t status; - psa_handle_t handle; - - psa_invec in_vec[] = { - { .base = &uid, .len = sizeof(uid) } - }; - - handle = psa_connect(TFM_ITS_REMOVE_SID, TFM_ITS_REMOVE_VERSION); - if (!PSA_HANDLE_IS_VALID(handle)) { - return PSA_ERROR_GENERIC_ERROR; - } - - status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), NULL, 0); - - psa_close(handle); - - return status; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_platform_ipc_api.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_platform_ipc_api.c deleted file mode 100644 index 0c1edf4..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_platform_ipc_api.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#include -#include "tfm_platform_api.h" -#include "psa_manifest/sid.h" - -enum tfm_platform_err_t tfm_platform_system_reset(void) -{ - psa_status_t status = PSA_ERROR_CONNECTION_REFUSED; - psa_handle_t handle = PSA_NULL_HANDLE; - - handle = psa_connect(TFM_SP_PLATFORM_SYSTEM_RESET_SID, - TFM_SP_PLATFORM_SYSTEM_RESET_VERSION); - if (handle <= 0) { - return TFM_PLATFORM_ERR_SYSTEM_ERROR; - } - - status = psa_call(handle, PSA_IPC_CALL, - NULL, 0, NULL, 0); - psa_close(handle); - - if (status < PSA_SUCCESS) { - return TFM_PLATFORM_ERR_SYSTEM_ERROR; - } else { - return (enum tfm_platform_err_t) status; - } - -} - -enum tfm_platform_err_t -tfm_platform_ioctl(tfm_platform_ioctl_req_t request, - psa_invec *input, psa_outvec *output) -{ - tfm_platform_ioctl_req_t req = request; - struct psa_invec in_vec[2] = { {0} }; - size_t inlen, outlen; - psa_status_t status = PSA_ERROR_CONNECTION_REFUSED; - psa_handle_t handle = PSA_NULL_HANDLE; - - in_vec[0].base = &req; - in_vec[0].len = sizeof(req); - if (input != NULL) { - in_vec[1].base = input->base; - in_vec[1].len = input->len; - inlen = 2; - } else { - inlen = 1; - } - - if (output != NULL) { - outlen = 1; - } else { - outlen = 0; - } - - handle = psa_connect(TFM_SP_PLATFORM_IOCTL_SID, - TFM_SP_PLATFORM_IOCTL_VERSION); - if (handle <= 0) { - return TFM_PLATFORM_ERR_SYSTEM_ERROR; - } - - status = psa_call(handle, PSA_IPC_CALL, - in_vec, inlen, - output, outlen); - psa_close(handle); - - if (status < PSA_SUCCESS) { - return TFM_PLATFORM_ERR_SYSTEM_ERROR; - } else { - return (enum tfm_platform_err_t) status; - } -} - diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_sst_ipc_api.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_sst_ipc_api.c deleted file mode 100644 index 4130428..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_sst_ipc_api.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 2017-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#include "psa/protected_storage.h" - -#include "tfm_ns_interface.h" -#include "psa_manifest/sid.h" - -#define IOVEC_LEN(x) (uint32_t)(sizeof(x)/sizeof(x[0])) - -psa_status_t psa_ps_set(psa_storage_uid_t uid, - size_t data_length, - const void *p_data, - psa_storage_create_flags_t create_flags) -{ - psa_status_t status; - psa_handle_t handle; - - psa_invec in_vec[] = { - { .base = &uid, .len = sizeof(uid) }, - { .base = p_data, .len = data_length }, - { .base = &create_flags, .len = sizeof(create_flags) } - }; - - handle = psa_connect(TFM_SST_SET_SID, TFM_SST_SET_VERSION); - if (!PSA_HANDLE_IS_VALID(handle)) { - return PSA_ERROR_GENERIC_ERROR; - } - - status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), - NULL, 0); - - psa_close(handle); - - /* A parameter with a buffer pointer pointer that has data length longer - * than maximum permitted is treated as a secure violation. - * TF-M framework rejects the request with TFM_ERROR_INVALID_PARAMETER. - */ - if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - return status; -} - -psa_status_t psa_ps_get(psa_storage_uid_t uid, - size_t data_offset, - size_t data_size, - void *p_data, - size_t *p_data_length) -{ - psa_status_t status; - psa_handle_t handle; - - psa_invec in_vec[] = { - { .base = &uid, .len = sizeof(uid) }, - { .base = &data_offset, .len = sizeof(data_offset) } - }; - - psa_outvec out_vec[] = { - { .base = p_data, .len = data_size } - }; - - if (p_data_length == NULL) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - handle = psa_connect(TFM_SST_GET_SID, TFM_SST_GET_VERSION); - if (!PSA_HANDLE_IS_VALID(handle)) { - return PSA_ERROR_GENERIC_ERROR; - } - - status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), out_vec, - IOVEC_LEN(out_vec)); - - psa_close(handle); - - *p_data_length = out_vec[0].len; - - return status; -} - -psa_status_t psa_ps_get_info(psa_storage_uid_t uid, - struct psa_storage_info_t *p_info) -{ - psa_status_t status; - psa_handle_t handle; - - psa_invec in_vec[] = { - { .base = &uid, .len = sizeof(uid) } - }; - - psa_outvec out_vec[] = { - { .base = p_info, .len = sizeof(*p_info) } - }; - - handle = psa_connect(TFM_SST_GET_INFO_SID, TFM_SST_GET_INFO_VERSION); - if (!PSA_HANDLE_IS_VALID(handle)) { - return PSA_ERROR_GENERIC_ERROR; - } - - status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), out_vec, - IOVEC_LEN(out_vec)); - - psa_close(handle); - - return status; -} - -psa_status_t psa_ps_remove(psa_storage_uid_t uid) -{ - psa_status_t status; - psa_handle_t handle; - - psa_invec in_vec[] = { - { .base = &uid, .len = sizeof(uid) } - }; - - - handle = psa_connect(TFM_SST_REMOVE_SID, TFM_SST_REMOVE_VERSION); - if (!PSA_HANDLE_IS_VALID(handle)) { - return PSA_ERROR_GENERIC_ERROR; - } - - status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), - NULL, 0); - - psa_close(handle); - - return status; -} - -psa_status_t psa_ps_create(psa_storage_uid_t uid, size_t size, - psa_storage_create_flags_t create_flags) -{ - (void)uid; - (void)size; - (void)create_flags; - - return PSA_ERROR_NOT_SUPPORTED; -} - -psa_status_t psa_ps_set_extended(psa_storage_uid_t uid, size_t data_offset, - size_t data_length, const void *p_data) -{ - (void)uid; - (void)data_offset; - (void)data_length; - (void)p_data; - - return PSA_ERROR_NOT_SUPPORTED; -} - -uint32_t psa_ps_get_support(void) -{ - /* Initialise support_flags to a sensible default, to avoid returning an - * uninitialised value in case the secure function fails. - */ - uint32_t support_flags = 0; - psa_handle_t handle; - - psa_outvec out_vec[] = { - { .base = &support_flags, .len = sizeof(support_flags) } - }; - - /* The PSA API does not return an error, so any error from TF-M is - * ignored. - */ - handle = psa_connect(TFM_SST_GET_SUPPORT_SID, TFM_SST_GET_SUPPORT_VERSION); - if (!PSA_HANDLE_IS_VALID(handle)) { - return support_flags; - } - - (void)psa_call(handle, PSA_IPC_CALL, NULL, 0, out_vec, IOVEC_LEN(out_vec)); - - psa_close(handle); - - return support_flags; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/platform_multicore.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/platform_multicore.c deleted file mode 100644 index e860ae0..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/platform_multicore.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (c) 2019 Arm Limited. All rights reserved. - * Copyright (c) 2019 Cypress Semiconductor Corporation. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include "cmsis_compiler.h" - -#include "platform_multicore.h" -#include "tfm_multi_core_api.h" -#include "tfm_ns_mailbox.h" - -#include "cy_ipc_drv.h" -#include "cy_sysint.h" -#if CY_SYSTEM_CPU_CM0P -#include "spe_ipc_config.h" -#else -#include "ns_ipc_config.h" -#endif - -int platform_mailbox_fetch_msg_ptr(void **msg_ptr) -{ - cy_en_ipcdrv_status_t status; - - if (!msg_ptr) { - return PLATFORM_MAILBOX_INVAL_PARAMS; - } - - status = Cy_IPC_Drv_ReadMsgPtr(Cy_IPC_Drv_GetIpcBaseAddress(IPC_RX_CHAN), - msg_ptr); - if (status != CY_IPC_DRV_SUCCESS) { - return PLATFORM_MAILBOX_RX_ERROR; - } - - Cy_IPC_Drv_ReleaseNotify(Cy_IPC_Drv_GetIpcBaseAddress(IPC_RX_CHAN), - IPC_RX_RELEASE_MASK); - return PLATFORM_MAILBOX_SUCCESS; -} - -int platform_mailbox_fetch_msg_data(uint32_t *data_ptr) -{ - cy_en_ipcdrv_status_t status; - - if (!data_ptr) { - return PLATFORM_MAILBOX_INVAL_PARAMS; - } - - status = Cy_IPC_Drv_ReadMsgWord(Cy_IPC_Drv_GetIpcBaseAddress(IPC_RX_CHAN), - data_ptr); - if (status != CY_IPC_DRV_SUCCESS) { - return PLATFORM_MAILBOX_RX_ERROR; - } - - Cy_IPC_Drv_ReleaseNotify(Cy_IPC_Drv_GetIpcBaseAddress(IPC_RX_CHAN), - IPC_RX_RELEASE_MASK); - return PLATFORM_MAILBOX_SUCCESS; -} - -int platform_mailbox_send_msg_ptr(const void *msg_ptr) -{ - cy_en_ipcdrv_status_t status; - - if (!msg_ptr) - return PLATFORM_MAILBOX_INVAL_PARAMS; - - status = Cy_IPC_Drv_SendMsgPtr(Cy_IPC_Drv_GetIpcBaseAddress(IPC_TX_CHAN), - IPC_TX_NOTIFY_MASK, msg_ptr); - if (status != CY_IPC_DRV_SUCCESS) { - return PLATFORM_MAILBOX_TX_ERROR; - } - - return PLATFORM_MAILBOX_SUCCESS; -} - -int platform_mailbox_send_msg_data(uint32_t data) -{ - cy_en_ipcdrv_status_t status; - - status = Cy_IPC_Drv_SendMsgWord(Cy_IPC_Drv_GetIpcBaseAddress(IPC_TX_CHAN), - IPC_TX_NOTIFY_MASK, data); - if (status != CY_IPC_DRV_SUCCESS) { - return PLATFORM_MAILBOX_TX_ERROR; - } - - return PLATFORM_MAILBOX_SUCCESS; -} - -void platform_mailbox_wait_for_notify(void) -{ - uint32_t status; - - while (1) { - status = Cy_IPC_Drv_GetInterruptStatusMasked( - Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT)); - status >>= CY_IPC_NOTIFY_SHIFT; - if (status & IPC_RX_INT_MASK) { - break; - } - } - - Cy_IPC_Drv_ClearInterrupt(Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT), - 0, IPC_RX_INT_MASK); -} - -int platform_ns_ipc_init(void) -{ - Cy_IPC_Drv_SetInterruptMask(Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT), - 0, IPC_RX_INT_MASK); - return PLATFORM_MAILBOX_SUCCESS; -} - -int32_t tfm_platform_ns_wait_for_s_cpu_ready(void) -{ - uint32_t data = 0; - - if (platform_ns_ipc_init() != PLATFORM_MAILBOX_SUCCESS) { - return PLATFORM_MAILBOX_INVAL_PARAMS; - } - while(data != IPC_SYNC_MAGIC) - { - platform_mailbox_wait_for_notify(); - platform_mailbox_fetch_msg_data(&data); - } - - if (platform_mailbox_send_msg_data(~IPC_SYNC_MAGIC) != - PLATFORM_MAILBOX_SUCCESS) { - return PLATFORM_MAILBOX_RX_ERROR; - } - return PLATFORM_MAILBOX_SUCCESS; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/platform_ns_mailbox.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/platform_ns_mailbox.c deleted file mode 100644 index af08ac1..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/platform_ns_mailbox.c +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Copyright (c) 2019-2020, Arm Limited. All rights reserved. - * Copyright (c) 2019, Cypress Semiconductor Corporation. All rights reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -/* -------------------------------------- Includes ----------------------------------- */ -#include -#include - -#include "cmsis_compiler.h" - -#include "cy_ipc_drv.h" -#include "cy_sysint.h" -#include "cy_ipc_sema.h" - -#include "ns_ipc_config.h" -#include "tfm_ns_mailbox.h" -#include "platform_multicore.h" -#include "cmsis_os2.h" - -static uint8_t saved_irq_state = 1; - -/* -------------------------------------- HAL API ------------------------------------ */ - -static void mailbox_ipc_init(void) -{ - Cy_IPC_Drv_SetInterruptMask(Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT), - 0, IPC_RX_INT_MASK); -} - -static void mailbox_ipc_config(void) -{ - NVIC_SetPriority(PSA_CLIENT_REPLY_NVIC_IRQn, PSA_CLIENT_REPLY_IRQ_PRIORITY); - - NVIC_EnableIRQ(PSA_CLIENT_REPLY_NVIC_IRQn); -} - -int32_t tfm_ns_mailbox_hal_notify_peer(void) -{ - cy_en_ipcdrv_status_t status; - - status = Cy_IPC_Drv_SendMsgWord(Cy_IPC_Drv_GetIpcBaseAddress(IPC_TX_CHAN), - IPC_TX_NOTIFY_MASK, - PSA_CLIENT_CALL_REQ_MAGIC); - - if (status == CY_IPC_DRV_SUCCESS) { - return MAILBOX_SUCCESS; - } else { - return MAILBOX_CHAN_BUSY; - } -} - -static int32_t mailbox_sema_init(void) -{ - /* semaphore data */ - static uint32_t tfm_sema __attribute__((section("TFM_SHARED_DATA"))); - - if (Cy_IPC_Sema_Init(PLATFORM_MAILBOX_IPC_CHAN_SEMA, - sizeof(tfm_sema) * CHAR_BIT, - &tfm_sema) != CY_IPC_SEMA_SUCCESS) { - return PLATFORM_MAILBOX_INIT_ERROR; - } - return PLATFORM_MAILBOX_SUCCESS; -} - -int32_t tfm_ns_mailbox_hal_init(struct ns_mailbox_queue_t *queue) -{ - uint32_t stage; - - if (!queue) { - return MAILBOX_INVAL_PARAMS; - } - - /* Init semaphores used for critical sections */ - if (mailbox_sema_init() != PLATFORM_MAILBOX_SUCCESS) - return MAILBOX_INIT_ERROR; - - /* - * FIXME - * Further verification of mailbox queue address may be required according - * to diverse NSPE implementations. - */ - - mailbox_ipc_init(); - - /* - * Wait until SPE mailbox library is ready to receive NSPE mailbox queue - * address. - */ - while (1) { - platform_mailbox_wait_for_notify(); - - platform_mailbox_fetch_msg_data(&stage); - if (stage == NS_MAILBOX_INIT_ENABLE) { - break; - } - } - - /* Send out the address */ - platform_mailbox_send_msg_ptr(queue); - - /* Wait until SPE mailbox service is ready */ - while (1) { - platform_mailbox_wait_for_notify(); - - platform_mailbox_fetch_msg_data(&stage); - if (stage == S_MAILBOX_READY) { - break; - } - } - - mailbox_ipc_config(); - - return MAILBOX_SUCCESS; -} - -const void *tfm_ns_mailbox_get_task_handle(void) -{ -#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL - return osThreadGetId(); -#else - return NULL; -#endif -} - -void tfm_ns_mailbox_hal_wait_reply(mailbox_msg_handle_t handle) -{ - osThreadFlagsWait(handle, osFlagsWaitAll, osWaitForever); -} - -static cy_en_ipcsema_status_t mailbox_raw_spin_lock(uint32_t ipc_channel, - uint32_t sema_num) -{ - uint32_t semaIndex; - uint32_t semaMask; - cy_stc_ipc_sema_t *semaStruct; - cy_en_ipcdrv_status_t acqStatus; - cy_en_ipcsema_status_t ret = CY_IPC_SEMA_BAD_PARAM; - bool is_lock = false; - IPC_STRUCT_Type *semaIpcStruct; - - /* Get IPC register structure */ - semaIpcStruct = Cy_IPC_Drv_GetIpcBaseAddress(ipc_channel); - /* Get pointer to structure */ - semaStruct = (cy_stc_ipc_sema_t *)Cy_IPC_Drv_ReadDataValue(semaIpcStruct); - - if (sema_num < semaStruct->maxSema) { - semaIndex = sema_num / CY_IPC_SEMA_PER_WORD; - semaMask = (uint32_t)(1ul << (sema_num - \ - (semaIndex * CY_IPC_SEMA_PER_WORD))); - - while (!is_lock) { - /* Check to make sure the IPC channel is released - If so, check if specific channel can be locked. */ - do { - acqStatus = Cy_IPC_Drv_LockAcquire(semaIpcStruct); - } while (acqStatus != CY_IPC_DRV_SUCCESS); - - if ((semaStruct->arrayPtr[semaIndex] & semaMask) == 0ul) { - semaStruct->arrayPtr[semaIndex] |= semaMask; - is_lock = true; - } - - /* Release, but do not trigger a release event */ - (void)Cy_IPC_Drv_LockRelease(semaIpcStruct, - CY_IPC_NO_NOTIFICATION); - - if (!is_lock) { - /* - * The secure core is occupying this lock. Insert a small delay - * to give the secure core a chance to acquire the IPC channel - * and release the lock. - * Otherwise, the secure core may not be able to release the - * lock if non-secure core has higher CPU frequency. It will - * generate a deadlock. - * This delay won't harm performance too much since non-secure - * core has to busy wait here anyway. - * Alternatively, non-secure core can wait for release - * notification event from secure core. However, it is more - * complex and requires more code and more modifications. - */ - volatile uint32_t count = 1000; - while(count > 0) { - count--; - } - Cy_IPC_Sema_Status(sema_num); - } - } - - ret = CY_IPC_SEMA_SUCCESS; - } - - return ret; -} - -static cy_en_ipcsema_status_t mailbox_raw_spin_unlock(uint32_t ipc_channel, - uint32_t sema_num) -{ - uint32_t semaIndex; - uint32_t semaMask; - cy_stc_ipc_sema_t *semaStruct; - cy_en_ipcdrv_status_t acqStatus; - cy_en_ipcsema_status_t ret = CY_IPC_SEMA_BAD_PARAM; - bool is_unlock = false; - IPC_STRUCT_Type *semaIpcStruct; - - /* Get IPC register structure */ - semaIpcStruct = Cy_IPC_Drv_GetIpcBaseAddress(ipc_channel); - /* Get pointer to structure */ - semaStruct = (cy_stc_ipc_sema_t *)Cy_IPC_Drv_ReadDataValue(semaIpcStruct); - - if (sema_num < semaStruct->maxSema) { - semaIndex = sema_num / CY_IPC_SEMA_PER_WORD; - semaMask = (uint32_t)(1ul << (sema_num - \ - (semaIndex * CY_IPC_SEMA_PER_WORD))); - - while (!is_unlock) { - /* Check to make sure the IPC channel is released - If so, check if specific channel can be locked. */ - do { - acqStatus = Cy_IPC_Drv_LockAcquire(semaIpcStruct); - } while (acqStatus != CY_IPC_DRV_SUCCESS); - - if ((semaStruct->arrayPtr[semaIndex] & semaMask) != 0ul) { - semaStruct->arrayPtr[semaIndex] &= ~semaMask; - is_unlock = true; - } - - /* Release, but do not trigger a release event */ - (void)Cy_IPC_Drv_LockRelease(semaIpcStruct, - CY_IPC_NO_NOTIFICATION); - } - - ret = CY_IPC_SEMA_SUCCESS; - } - - return ret; -} - -void tfm_ns_mailbox_hal_enter_critical(void) -{ - saved_irq_state = Cy_SysLib_EnterCriticalSection(); - - mailbox_raw_spin_lock(CY_IPC_CHAN_SEMA, MAILBOX_SEMAPHORE_NUM); -} - -void tfm_ns_mailbox_hal_exit_critical(void) -{ - mailbox_raw_spin_unlock(CY_IPC_CHAN_SEMA, MAILBOX_SEMAPHORE_NUM); - - Cy_SysLib_ExitCriticalSection(saved_irq_state); -} - -void tfm_ns_mailbox_hal_enter_critical_isr(void) -{ - mailbox_raw_spin_lock(CY_IPC_CHAN_SEMA, MAILBOX_SEMAPHORE_NUM); -} - -void tfm_ns_mailbox_hal_exit_critical_isr(void) -{ - mailbox_raw_spin_unlock(CY_IPC_CHAN_SEMA, MAILBOX_SEMAPHORE_NUM); -} - -static bool mailbox_clear_intr(void) -{ - uint32_t status; - - status = Cy_IPC_Drv_GetInterruptStatusMasked( - Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT)); - status >>= CY_IPC_NOTIFY_SHIFT; - if ((status & IPC_RX_INT_MASK) == 0) { - return false; - } - - Cy_IPC_Drv_ClearInterrupt(Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT), - 0, IPC_RX_INT_MASK); - return true; -} - -void cpuss_interrupts_ipc_5_IRQHandler(void) -{ - uint32_t magic; - mailbox_msg_handle_t handle; - osThreadId_t task_handle; - - if (!mailbox_clear_intr()) - return; - - platform_mailbox_fetch_msg_data(&magic); - if (magic == PSA_CLIENT_CALL_REPLY_MAGIC) { - /* Handle all the pending replies */ - while (1) { - handle = tfm_ns_mailbox_fetch_reply_msg_isr(); - if (handle == MAILBOX_MSG_NULL_HANDLE) { - break; - } - - task_handle = (osThreadId_t)tfm_ns_mailbox_get_msg_owner(handle); - if (task_handle) { - /* According to the description of CMSIS-RTOS v2 Thread Flags, - * osThreadFlagsSet() can be called inside Interrupt Service - * Routine. */ - osThreadFlagsSet(task_handle, handle); - } - } - } -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/tfm_mbed_boot.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/tfm_mbed_boot.c deleted file mode 100644 index c8d595f..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/tfm_mbed_boot.c +++ /dev/null @@ -1,67 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2020 ARM Limited - * 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 "mbed_error.h" -#include "tfm_multi_core_api.h" -#include "tfm_ns_mailbox.h" -#include "platform_multicore.h" -#include "tfm_ns_interface.h" - -static struct ns_mailbox_queue_t ns_mailbox_queue; - -void mbed_tfm_init(void) -{ - /* - * In case the of dual CPU, we need to initialize IPC, mailbox - * and NS interface after the RTOS has started to enable - * communication from Secure and Non-Secure cores. - */ - int32_t ret; - - ret = tfm_ns_wait_for_s_cpu_ready(); - /* - * Normally would expect "TFM_SUCCESS" returned here by TF-M, as this - * isn't a mailbox function. There may be some platforms other than PSoC6, - * which doesn't require tfm_ns_wait_for_s_cpu_ready() implementation. - * "PLATFORM_MAILBOX_SUCCESS" is a low-level error code and should be - * replaced by "TFM_SUCCESS". - * As the function definition has been imported from the TF-M, therefore - * a issue has been raised - https://developer.trustedfirmware.org/T660 - */ - if (ret != PLATFORM_MAILBOX_SUCCESS) { - /* Avoid undefined behavior after multi-core sync-up failed */ - MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, - MBED_ERROR_CODE_INITIALIZATION_FAILED), - "Failed to sync-up multi-core"); - } - - ret = tfm_ns_mailbox_init(&ns_mailbox_queue); - if (ret != MAILBOX_SUCCESS) { - /* Avoid undefined behavior after NS mailbox initialization failed */ - MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, - MBED_ERROR_CODE_INITIALIZATION_FAILED), - "Failed to initialize NS mailbox"); - } - - ret = tfm_ns_interface_init(); - if (ret != TFM_SUCCESS) { - /* Avoid undefined behavior after NS interface initialization failed */ - MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, - MBED_ERROR_CODE_INITIALIZATION_FAILED), - "Failed to initialize NS interface"); - } -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/tfm_multi_core_api.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/tfm_multi_core_api.c deleted file mode 100644 index b58738f..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/tfm_multi_core_api.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#include "tfm_api.h" -#include "tfm_mailbox.h" -#include "tfm_multi_core_api.h" -#include "cmsis_os2.h" - -#define MAX_SEMAPHORE_COUNT NUM_MAILBOX_QUEUE_SLOT - -static osSemaphoreId_t ns_lock_handle = NULL; - -__attribute__((weak)) -enum tfm_status_e tfm_ns_interface_init(void) -{ - osSemaphoreAttr_t sema_attrib = {0}; - - ns_lock_handle = osSemaphoreNew(MAX_SEMAPHORE_COUNT, - MAX_SEMAPHORE_COUNT, - &sema_attrib); - if (!ns_lock_handle) { - return TFM_ERROR_GENERIC; - } - - return TFM_SUCCESS; -} - -int32_t tfm_ns_wait_for_s_cpu_ready(void) -{ - return tfm_platform_ns_wait_for_s_cpu_ready(); -} - -uint32_t tfm_ns_multi_core_lock_acquire(void) -{ - return osSemaphoreAcquire(ns_lock_handle, osWaitForever); -} - -uint32_t tfm_ns_multi_core_lock_release(void) -{ - return osSemaphoreRelease(ns_lock_handle); -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/tfm_multi_core_psa_ns_api.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/tfm_multi_core_psa_ns_api.c deleted file mode 100644 index 3af3af8..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/tfm_multi_core_psa_ns_api.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (c) 2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#include -#include - -#include "psa/client.h" -#include "psa/error.h" -#include "tfm_api.h" -#include "tfm_multi_core_api.h" -#include "tfm_ns_mailbox.h" - -/* - * TODO - * Currently, force all the non-secure client to share the same ID. - * - * It requires a more clear mechanism to synchronize the non-secure client - * ID with SPE in dual core scenario. - * In current design, the value is transferred to SPE via mailbox message. - * A dedicated routine to receive the non-secure client information in - * TF-M core/SPM in dual core scenario should be added besides current - * implementation for single Armv8-M. - * The non-secure client identification is shared with SPE in - * single Armv8-M scenario via CMSIS TrustZone context management API, - * which may not work in dual core scenario. - */ -#define NON_SECURE_CLIENT_ID (1) - -/* - * TODO - * Require a formal definition of errors related to mailbox in PSA client call. - */ -#define PSA_INTER_CORE_COMM_ERR (INT32_MIN + 0xFF) - -static void mailbox_wait_reply(mailbox_msg_handle_t handle) -{ - /* - * If the system can support multiple outstanding NS PSA Client calls, call - * tfm_ns_mailbox_wait_reply() to sleep and wait for reply. The NS side - * should implement tfm_ns_mailbox_hal_wait_reply() and wake-up mechanism. - * Otherwise, by default, call tfm_ns_mailbox_is_msg_replied() to simply - * poll the reply status of the mailbox message of current thread. - */ -#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL - tfm_ns_mailbox_wait_reply(handle); -#else - while (!tfm_ns_mailbox_is_msg_replied(handle)) { - } -#endif -} - -/**** API functions ****/ - -uint32_t psa_framework_version(void) -{ - struct psa_client_params_t params; - mailbox_msg_handle_t handle; - uint32_t version; - int32_t ret; - - if (tfm_ns_multi_core_lock_acquire() != TFM_SUCCESS) { - return PSA_VERSION_NONE; - } - - handle = tfm_ns_mailbox_tx_client_req(MAILBOX_PSA_FRAMEWORK_VERSION, - ¶ms, NON_SECURE_CLIENT_ID); - if (handle < 0) { - tfm_ns_multi_core_lock_release(); - return PSA_VERSION_NONE; - } - - mailbox_wait_reply(handle); - - ret = tfm_ns_mailbox_rx_client_reply(handle, (int32_t *)&version); - if (ret != MAILBOX_SUCCESS) { - version = PSA_VERSION_NONE; - } - - if (tfm_ns_multi_core_lock_release() != TFM_SUCCESS) { - return PSA_VERSION_NONE; - } - - return version; -} - -uint32_t psa_version(uint32_t sid) -{ - struct psa_client_params_t params; - mailbox_msg_handle_t handle; - uint32_t version; - int32_t ret; - - params.psa_version_params.sid = sid; - - if (tfm_ns_multi_core_lock_acquire() != TFM_SUCCESS) { - return PSA_VERSION_NONE; - } - - handle = tfm_ns_mailbox_tx_client_req(MAILBOX_PSA_VERSION, ¶ms, - NON_SECURE_CLIENT_ID); - if (handle < 0) { - tfm_ns_multi_core_lock_release(); - return PSA_VERSION_NONE; - } - - mailbox_wait_reply(handle); - - ret = tfm_ns_mailbox_rx_client_reply(handle, (int32_t *)&version); - if (ret != MAILBOX_SUCCESS) { - version = PSA_VERSION_NONE; - } - - if (tfm_ns_multi_core_lock_release() != TFM_SUCCESS) { - return PSA_VERSION_NONE; - } - - return version; -} - -psa_handle_t psa_connect(uint32_t sid, uint32_t version) -{ - struct psa_client_params_t params; - mailbox_msg_handle_t handle; - psa_handle_t psa_handle; - int32_t ret; - - params.psa_connect_params.sid = sid; - params.psa_connect_params.version = version; - - if (tfm_ns_multi_core_lock_acquire() != TFM_SUCCESS) { - return PSA_NULL_HANDLE; - } - - handle = tfm_ns_mailbox_tx_client_req(MAILBOX_PSA_CONNECT, ¶ms, - NON_SECURE_CLIENT_ID); - if (handle < 0) { - tfm_ns_multi_core_lock_release(); - return PSA_NULL_HANDLE; - } - - mailbox_wait_reply(handle); - - ret = tfm_ns_mailbox_rx_client_reply(handle, (int32_t *)&psa_handle); - if (ret != MAILBOX_SUCCESS) { - psa_handle = PSA_NULL_HANDLE; - } - - if (tfm_ns_multi_core_lock_release() != TFM_SUCCESS) { - return PSA_NULL_HANDLE; - } - - return psa_handle; -} - -psa_status_t psa_call(psa_handle_t handle, int32_t type, - const psa_invec *in_vec, size_t in_len, - psa_outvec *out_vec, size_t out_len) -{ - struct psa_client_params_t params; - mailbox_msg_handle_t msg_handle; - int32_t ret; - psa_status_t status; - - params.psa_call_params.handle = handle; - params.psa_call_params.type = type; - params.psa_call_params.in_vec = in_vec; - params.psa_call_params.in_len = in_len; - params.psa_call_params.out_vec = out_vec; - params.psa_call_params.out_len = out_len; - - if (tfm_ns_multi_core_lock_acquire() != TFM_SUCCESS) { - return PSA_ERROR_GENERIC_ERROR; - } - - msg_handle = tfm_ns_mailbox_tx_client_req(MAILBOX_PSA_CALL, ¶ms, - NON_SECURE_CLIENT_ID); - if (msg_handle < 0) { - tfm_ns_multi_core_lock_release(); - return PSA_INTER_CORE_COMM_ERR; - } - - mailbox_wait_reply(msg_handle); - - ret = tfm_ns_mailbox_rx_client_reply(msg_handle, (int32_t *)&status); - if (ret != MAILBOX_SUCCESS) { - status = PSA_INTER_CORE_COMM_ERR; - } - - if (tfm_ns_multi_core_lock_release() != TFM_SUCCESS) { - return PSA_ERROR_GENERIC_ERROR; - } - - return status; -} - -void psa_close(psa_handle_t handle) -{ - struct psa_client_params_t params; - mailbox_msg_handle_t msg_handle; - int32_t reply; - - params.psa_close_params.handle = handle; - - if (tfm_ns_multi_core_lock_acquire() != TFM_SUCCESS) { - return; - } - - msg_handle = tfm_ns_mailbox_tx_client_req(MAILBOX_PSA_CLOSE, ¶ms, - NON_SECURE_CLIENT_ID); - if (msg_handle < 0) { - tfm_ns_multi_core_lock_release(); - return; - } - - mailbox_wait_reply(msg_handle); - - (void)tfm_ns_mailbox_rx_client_reply(msg_handle, &reply); - - tfm_ns_multi_core_lock_release(); -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/tfm_ns_mailbox.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/tfm_ns_mailbox.c deleted file mode 100644 index f7326f0..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/tfm_ns_mailbox.c +++ /dev/null @@ -1,425 +0,0 @@ -/* - * Copyright (c) 2019-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#include -#include "tfm_ns_mailbox.h" - -/* The pointer to NSPE mailbox queue */ -static struct ns_mailbox_queue_t *mailbox_queue_ptr = NULL; - -static inline void clear_queue_slot_empty(uint8_t idx) -{ - if (idx < NUM_MAILBOX_QUEUE_SLOT) { - mailbox_queue_ptr->empty_slots &= ~(1 << idx); - } -} - -static inline void set_queue_slot_empty(uint8_t idx) -{ - if (idx < NUM_MAILBOX_QUEUE_SLOT) { - mailbox_queue_ptr->empty_slots |= (1 << idx); - } -} - -static inline void set_queue_slot_pend(uint8_t idx) -{ - if (idx < NUM_MAILBOX_QUEUE_SLOT) { - mailbox_queue_ptr->pend_slots |= (1 << idx); - } -} - -static inline int32_t get_mailbox_msg_handle(uint8_t idx, - mailbox_msg_handle_t *handle) -{ - if ((idx >= NUM_MAILBOX_QUEUE_SLOT) || !handle) { - return MAILBOX_INVAL_PARAMS; - } - - *handle = (mailbox_msg_handle_t)(idx + 1); - - return MAILBOX_SUCCESS; -} - -static inline int32_t get_mailbox_msg_idx(mailbox_msg_handle_t handle, - uint8_t *idx) -{ - if ((handle == MAILBOX_MSG_NULL_HANDLE) || !idx) { - return MAILBOX_INVAL_PARAMS; - } - - *idx = (uint8_t)(handle - 1); - - return MAILBOX_SUCCESS; -} - -static inline void clear_queue_slot_replied(uint8_t idx) -{ - if (idx < NUM_MAILBOX_QUEUE_SLOT) { - mailbox_queue_ptr->replied_slots &= ~(1 << idx); - } -} - -static inline void set_queue_slot_woken(uint8_t idx) -{ - if (idx < NUM_MAILBOX_QUEUE_SLOT) { - mailbox_queue_ptr->queue[idx].is_woken = true; - } -} - -static inline bool is_queue_slot_woken(uint8_t idx) -{ - if (idx < NUM_MAILBOX_QUEUE_SLOT) { - return mailbox_queue_ptr->queue[idx].is_woken; - } - - return false; -} - -static inline void clear_queue_slot_woken(uint8_t idx) -{ - if (idx < NUM_MAILBOX_QUEUE_SLOT) { - mailbox_queue_ptr->queue[idx].is_woken = false; - } -} - -static uint8_t acquire_empty_slot(const struct ns_mailbox_queue_t *queue) -{ - uint8_t idx; - mailbox_queue_status_t status; - - tfm_ns_mailbox_hal_enter_critical(); - status = queue->empty_slots; - - if (!status) { - /* No empty slot */ - tfm_ns_mailbox_hal_exit_critical(); - return NUM_MAILBOX_QUEUE_SLOT; - } - - for (idx = 0; idx < NUM_MAILBOX_QUEUE_SLOT; idx++) { - if (status & (1 << idx)) { - break; - } - } - - clear_queue_slot_empty(idx); - - tfm_ns_mailbox_hal_exit_critical(); - - return idx; -} - -static void set_msg_owner(uint8_t idx, const void *owner) -{ - if (idx < NUM_MAILBOX_QUEUE_SLOT) { - mailbox_queue_ptr->queue[idx].owner = owner; - } -} - -#ifdef TFM_MULTI_CORE_TEST -void tfm_ns_mailbox_tx_stats_init(void) -{ - if (!mailbox_queue_ptr) { - return; - } - - tfm_ns_mailbox_hal_enter_critical(); - - mailbox_queue_ptr->nr_tx = 0; - mailbox_queue_ptr->nr_used_slots = 0; - - tfm_ns_mailbox_hal_exit_critical(); -} - -static void mailbox_tx_stats_update(struct ns_mailbox_queue_t *ns_queue) -{ - mailbox_queue_status_t empty_status; - uint8_t idx, nr_empty = 0; - - if (!ns_queue) { - return; - } - - tfm_ns_mailbox_hal_enter_critical(); - - ns_queue->nr_tx++; - - /* Count the number of used slots when this tx arrives */ - empty_status = ns_queue->empty_slots; - tfm_ns_mailbox_hal_exit_critical(); - - if (empty_status) { - for (idx = 0; idx < NUM_MAILBOX_QUEUE_SLOT; idx++) { - if (empty_status & (0x1UL << idx)) { - nr_empty++; - } - } - } - - tfm_ns_mailbox_hal_enter_critical(); - ns_queue->nr_used_slots += (NUM_MAILBOX_QUEUE_SLOT - nr_empty); - tfm_ns_mailbox_hal_exit_critical(); -} - -void tfm_ns_mailbox_stats_avg_slot(struct ns_mailbox_stats_res_t *stats_res) -{ - uint32_t nr_used_slots, nr_tx; - - if (!mailbox_queue_ptr || !stats_res) { - return; - } - - tfm_ns_mailbox_hal_enter_critical(); - nr_used_slots = mailbox_queue_ptr->nr_used_slots; - nr_tx = mailbox_queue_ptr->nr_tx; - tfm_ns_mailbox_hal_exit_critical(); - - stats_res->avg_nr_slots = nr_used_slots / nr_tx; - nr_used_slots %= nr_tx; - stats_res->avg_nr_slots_tenths = nr_used_slots * 10 / nr_tx; -} -#endif - -mailbox_msg_handle_t tfm_ns_mailbox_tx_client_req(uint32_t call_type, - const struct psa_client_params_t *params, - int32_t client_id) -{ - uint8_t idx; - struct mailbox_msg_t *msg_ptr; - mailbox_msg_handle_t handle; - const void *task_handle; - - if (!mailbox_queue_ptr) { - return MAILBOX_MSG_NULL_HANDLE; - } - - if (!params) { - return MAILBOX_MSG_NULL_HANDLE; - } - - idx = acquire_empty_slot(mailbox_queue_ptr); - if (idx >= NUM_MAILBOX_QUEUE_SLOT) { - return MAILBOX_QUEUE_FULL; - } - -#ifdef TFM_MULTI_CORE_TEST - mailbox_tx_stats_update(mailbox_queue_ptr); -#endif - - /* Fill the mailbox message */ - msg_ptr = &mailbox_queue_ptr->queue[idx].msg; - - msg_ptr->call_type = call_type; - memcpy(&msg_ptr->params, params, sizeof(msg_ptr->params)); - msg_ptr->client_id = client_id; - - /* - * Fetch the current task handle. The task will be woken up according the - * handle value set in the owner field. - */ - task_handle = tfm_ns_mailbox_get_task_handle(); - set_msg_owner(idx, task_handle); - - get_mailbox_msg_handle(idx, &handle); - - tfm_ns_mailbox_hal_enter_critical(); - set_queue_slot_pend(idx); - tfm_ns_mailbox_hal_exit_critical(); - - tfm_ns_mailbox_hal_notify_peer(); - - return handle; -} - -int32_t tfm_ns_mailbox_rx_client_reply(mailbox_msg_handle_t handle, - int32_t *reply) -{ - uint8_t idx; - int32_t ret; - - if (!mailbox_queue_ptr) { - return MAILBOX_INVAL_PARAMS; - } - - if ((handle == MAILBOX_MSG_NULL_HANDLE) || (!reply)) { - return MAILBOX_INVAL_PARAMS; - } - - ret = get_mailbox_msg_idx(handle, &idx); - if (ret != MAILBOX_SUCCESS) { - return ret; - } - - *reply = mailbox_queue_ptr->queue[idx].reply.return_val; - - /* Clear up the owner field */ - set_msg_owner(idx, NULL); - - tfm_ns_mailbox_hal_enter_critical(); - clear_queue_slot_replied(idx); - clear_queue_slot_woken(idx); - /* - * Make sure that the empty flag is set after all the other status flags are - * re-initialized. - */ - set_queue_slot_empty(idx); - tfm_ns_mailbox_hal_exit_critical(); - - return MAILBOX_SUCCESS; -} - -bool tfm_ns_mailbox_is_msg_replied(mailbox_msg_handle_t handle) -{ - uint8_t idx; - int32_t ret; - mailbox_queue_status_t status; - - if (!mailbox_queue_ptr) { - return false; - } - - if (handle == MAILBOX_MSG_NULL_HANDLE) { - return false; - } - - ret = get_mailbox_msg_idx(handle, &idx); - if (ret != MAILBOX_SUCCESS) { - return false; - } - - tfm_ns_mailbox_hal_enter_critical(); - status = mailbox_queue_ptr->replied_slots; - tfm_ns_mailbox_hal_exit_critical(); - - if (status & (1 << idx)) { - return true; - } - - return false; -} - -mailbox_msg_handle_t tfm_ns_mailbox_fetch_reply_msg_isr(void) -{ - uint8_t idx; - mailbox_msg_handle_t handle; - mailbox_queue_status_t replied_status; - - if (!mailbox_queue_ptr) { - return MAILBOX_MSG_NULL_HANDLE; - } - - tfm_ns_mailbox_hal_enter_critical_isr(); - replied_status = mailbox_queue_ptr->replied_slots; - tfm_ns_mailbox_hal_exit_critical_isr(); - - if (!replied_status) { - return MAILBOX_MSG_NULL_HANDLE; - } - - for (idx = 0; idx < NUM_MAILBOX_QUEUE_SLOT; idx++) { - /* Find the first replied message in queue */ - if (replied_status & (0x1UL << idx)) { - tfm_ns_mailbox_hal_enter_critical_isr(); - clear_queue_slot_replied(idx); - set_queue_slot_woken(idx); - tfm_ns_mailbox_hal_exit_critical_isr(); - - if (get_mailbox_msg_handle(idx, &handle) == MAILBOX_SUCCESS) { - return handle; - } - } - } - - return MAILBOX_MSG_NULL_HANDLE; -} - -const void *tfm_ns_mailbox_get_msg_owner(mailbox_msg_handle_t handle) -{ - uint8_t idx; - - if (get_mailbox_msg_idx(handle, &idx) != MAILBOX_SUCCESS) { - return NULL; - } - - if (idx < NUM_MAILBOX_QUEUE_SLOT) { - return mailbox_queue_ptr->queue[idx].owner; - } - - return NULL; -} - -int32_t tfm_ns_mailbox_init(struct ns_mailbox_queue_t *queue) -{ - int32_t ret; - - if (!queue) { - return MAILBOX_INVAL_PARAMS; - } - - /* - * Further verification of mailbox queue address may be required according - * to non-secure memory assignment. - */ - - memset(queue, 0, sizeof(*queue)); - - /* Initialize empty bitmask */ - queue->empty_slots = - (mailbox_queue_status_t)((1UL << (NUM_MAILBOX_QUEUE_SLOT - 1)) - 1); - queue->empty_slots += - (mailbox_queue_status_t)(1UL << (NUM_MAILBOX_QUEUE_SLOT - 1)); - - mailbox_queue_ptr = queue; - - /* Platform specific initialization. */ - ret = tfm_ns_mailbox_hal_init(queue); - -#ifdef TFM_MULTI_CORE_TEST - tfm_ns_mailbox_tx_stats_init(); -#endif - - return ret; -} - -#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL -int32_t tfm_ns_mailbox_wait_reply(mailbox_msg_handle_t handle) -{ - uint8_t idx; - int32_t ret; - - if (!mailbox_queue_ptr) { - return MAILBOX_INVAL_PARAMS; - } - - if (handle == MAILBOX_MSG_NULL_HANDLE) { - return MAILBOX_INVAL_PARAMS; - } - - ret = get_mailbox_msg_idx(handle, &idx); - if (ret != MAILBOX_SUCCESS) { - return ret; - } - - while (1) { - tfm_ns_mailbox_hal_wait_reply(handle); - - /* - * Woken up from sleep - * Check the completed flag to make sure that the current thread is - * woken up by reply event, rather than other events. - */ - tfm_ns_mailbox_hal_enter_critical(); - if (is_queue_slot_woken(idx)) { - tfm_ns_mailbox_hal_exit_critical(); - break; - } - tfm_ns_mailbox_hal_exit_critical(); - } - - return MAILBOX_SUCCESS; -} -#endif diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_V8M/src/cmsis_nvic_virtual.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_V8M/src/cmsis_nvic_virtual.c deleted file mode 100644 index bee8597..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_V8M/src/cmsis_nvic_virtual.c +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2019-2020 Arm Limited - * - * 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 "cmsis_nvic_virtual.h" -#include "tfm_platform_api.h" - -void NVIC_SystemReset(void) -{ - tfm_platform_system_reset(); -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_V8M/src/tfm_mbed_boot.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_V8M/src/tfm_mbed_boot.c deleted file mode 100644 index 87bcbbb..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_V8M/src/tfm_mbed_boot.c +++ /dev/null @@ -1,37 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2020 ARM Limited - * 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 "mbed_error.h" -#include "tfm_ns_interface.h" - -void mbed_tfm_init(void) -{ - /* - * In case of V8-M, we need to initialize NS interface - * after the RTOS has started to enable - * communication from Secure and Non-Secure cores. - */ - int32_t ret; - - ret = tfm_ns_interface_init(); - if (ret != TFM_SUCCESS) { - /* Avoid undefined behavior after NS interface initialization failed */ - MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, - MBED_ERROR_CODE_INITIALIZATION_FAILED), - "Failed to initialize NS interface"); - } -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_V8M/src/tfm_ns_interface.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_V8M/src/tfm_ns_interface.c deleted file mode 100644 index 9759145..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_V8M/src/tfm_ns_interface.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2017-2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ -#include -#include - -#include "tfm_api.h" -#include "tfm_ns_interface.h" -#include "cmsis_os2.h" - -/** - * \brief the ns_lock ID - */ -static osMutexId_t ns_lock_handle = NULL; - -__attribute__((weak)) -int32_t tfm_ns_interface_dispatch(veneer_fn fn, - uint32_t arg0, uint32_t arg1, - uint32_t arg2, uint32_t arg3) -{ - int32_t result; - osStatus_t status; - - /* TFM request protected by NS lock */ - status = osMutexAcquire(ns_lock_handle, osWaitForever); - if (status != osOK) { - return (int32_t)TFM_ERROR_GENERIC; - } - - result = fn(arg0, arg1, arg2, arg3); - - status = osMutexRelease(ns_lock_handle); - if (status != osOK) { - return (int32_t)TFM_ERROR_GENERIC; - } - - return result; -} - -__attribute__((weak)) -enum tfm_status_e tfm_ns_interface_init(void) -{ - const osMutexAttr_t attr = { - .name = NULL, - .attr_bits = osMutexPrioInherit, /* Priority inheritance is recommended - * to enable if it is supported. - * For recursive mutex and the ability - * of auto release when owner being - * terminated is not required. - */ - .cb_mem = NULL, - .cb_size = 0U - }; - - ns_lock_handle = osMutexNew(&attr); - if (!ns_lock_handle) { - return TFM_ERROR_GENERIC; - } - - return TFM_SUCCESS; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_V8M/src/tfm_psa_ns_api.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_V8M/src/tfm_psa_ns_api.c deleted file mode 100644 index 9a677a2..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_V8M/src/tfm_psa_ns_api.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2018-2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#include "psa/client.h" -#include "tfm_ns_interface.h" -#include "tfm_api.h" - -/**** API functions ****/ - -uint32_t psa_framework_version(void) -{ - return tfm_ns_interface_dispatch( - (veneer_fn)tfm_psa_framework_version_veneer, - 0, - 0, - 0, - 0); -} - -uint32_t psa_version(uint32_t sid) -{ - return tfm_ns_interface_dispatch( - (veneer_fn)tfm_psa_version_veneer, - sid, - 0, - 0, - 0); -} - -psa_handle_t psa_connect(uint32_t sid, uint32_t version) -{ - return tfm_ns_interface_dispatch( - (veneer_fn)tfm_psa_connect_veneer, - sid, - version, - 0, - 0); -} - -psa_status_t psa_call(psa_handle_t handle, int32_t type, - const psa_invec *in_vec, - size_t in_len, - psa_outvec *out_vec, - size_t out_len) -{ - /* FixMe: sanity check can be added to offload some NS thread checks from - * TFM secure API - */ - - /* Due to v8M restrictions, TF-M NS API needs to add another layer of - * serialization in order for NS to pass arguments to S - */ - const struct tfm_control_parameter_t ctrl_param = { - .type = type, - .in_len = in_len, - .out_len = out_len, - }; - - return tfm_ns_interface_dispatch( - (veneer_fn)tfm_psa_call_veneer, - (uint32_t)handle, - (uint32_t)&ctrl_param, - (uint32_t)in_vec, - (uint32_t)out_vec); -} - -void psa_close(psa_handle_t handle) -{ - (void)tfm_ns_interface_dispatch( - (veneer_fn)tfm_psa_close_veneer, - (uint32_t)handle, - 0, - 0, - 0); -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/VERSION.txt b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/VERSION.txt deleted file mode 100644 index 54d3b42..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/VERSION.txt +++ /dev/null @@ -1 +0,0 @@ -a630d86e91a8 diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/cmsis_nvic_virtual.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/cmsis_nvic_virtual.h deleted file mode 100644 index a1a8b61..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/cmsis_nvic_virtual.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2019 Arm Limited - * - * 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 "cmsis.h" - -#ifndef NVIC_VIRTUAL_H -#define NVIC_VIRTUAL_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* NVIC functions */ -#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping -#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping -#define NVIC_EnableIRQ __NVIC_EnableIRQ -#define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ -#define NVIC_DisableIRQ __NVIC_DisableIRQ -#define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ -#define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ -#define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ -#define NVIC_GetActive __NVIC_GetActive -#define NVIC_SetPriority __NVIC_SetPriority -#define NVIC_GetPriority __NVIC_GetPriority - -/** - * \brief Overriding the default CMSIS system reset implementation by calling - * secure TFM service. - * - */ -void NVIC_SystemReset(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/ns_ipc_config.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/ns_ipc_config.h deleted file mode 100644 index e1cd7b7..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/ns_ipc_config.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2019 Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#ifndef _IPC_CONFIG_H_ -#define _IPC_CONFIG_H_ - -#include "platform_multicore.h" - -#define IPC_RX_CHAN IPC_PSA_CLIENT_REPLY_CHAN -#define IPC_RX_INTR_STRUCT IPC_PSA_CLIENT_REPLY_INTR_STRUCT -#define IPC_RX_INT_MASK IPC_PSA_CLIENT_REPLY_INTR_MASK - -#define IPC_TX_CHAN IPC_PSA_CLIENT_CALL_CHAN -#define IPC_TX_NOTIFY_MASK IPC_PSA_CLIENT_CALL_NOTIFY_MASK - -#define PSA_CLIENT_REPLY_NVIC_IRQn IPC_PSA_CLIENT_REPLY_IPC_INTR -#define PSA_CLIENT_REPLY_IRQ_PRIORITY 3 - -#endif diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/platform_multicore.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/platform_multicore.h deleted file mode 100644 index f90fb1e..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/platform_multicore.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2019, Arm Limited. All rights reserved. - * Copyright (c) 2019, Cypress Semiconductor Corporation. All rights reserved - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#ifndef _TFM_PLATFORM_MULTICORE_ -#define _TFM_PLATFORM_MULTICORE_ - -#include -#include "cy_device_headers.h" - -#define IPC_PSA_CLIENT_CALL_CHAN (8) -#define IPC_PSA_CLIENT_CALL_INTR_STRUCT (6) -#define IPC_PSA_CLIENT_CALL_INTR_MASK (1 << IPC_PSA_CLIENT_CALL_CHAN) -#define IPC_PSA_CLIENT_CALL_NOTIFY_MASK (1 << IPC_PSA_CLIENT_CALL_INTR_STRUCT) -#define IPC_PSA_CLIENT_CALL_IPC_INTR cpuss_interrupts_ipc_6_IRQn - -#define IPC_PSA_CLIENT_REPLY_CHAN (9) -#define IPC_PSA_CLIENT_REPLY_INTR_STRUCT (5) -#define IPC_PSA_CLIENT_REPLY_INTR_MASK (1 << IPC_PSA_CLIENT_REPLY_CHAN) -#define IPC_PSA_CLIENT_REPLY_NOTIFY_MASK (1 << IPC_PSA_CLIENT_REPLY_INTR_STRUCT) -#define IPC_PSA_CLIENT_REPLY_IPC_INTR cpuss_interrupts_ipc_5_IRQn - -#define IPC_RX_RELEASE_MASK (0) - -#define CY_IPC_NOTIFY_SHIFT (16) - -#define PSA_CLIENT_CALL_REQ_MAGIC (0xA5CF50C6) -#define PSA_CLIENT_CALL_REPLY_MAGIC (0xC605FC5A) - -#define NS_MAILBOX_INIT_ENABLE (0xAE) -#define S_MAILBOX_READY (0xC3) - -#define PLATFORM_MAILBOX_SUCCESS (0x0) -#define PLATFORM_MAILBOX_INVAL_PARAMS (INT32_MIN + 1) -#define PLATFORM_MAILBOX_TX_ERROR (INT32_MIN + 2) -#define PLATFORM_MAILBOX_RX_ERROR (INT32_MIN + 3) -#define PLATFORM_MAILBOX_INIT_ERROR (INT32_MIN + 4) - -/* Inter-Processor Communication (IPC) data channel for the Semaphores */ -#define PLATFORM_MAILBOX_IPC_CHAN_SEMA CY_IPC_CHAN_SEMA -#define MAILBOX_SEMAPHORE_NUM (16) - -#define IPC_SYNC_MAGIC 0x7DADE011 - -/** - * \brief Fetch a pointer from mailbox message - * - * \param[out] msg_ptr The address to write the pointer value to. - * - * \retval 0 The operation succeeds. - * \retval else The operation fails. - */ -int platform_mailbox_fetch_msg_ptr(void **msg_ptr); - -/** - * \brief Fetch a data value from mailbox message - * - * \param[out] data_ptr The address to write the pointer value to. - * - * \retval 0 The operation succeeds. - * \retval else The operation fails. - */ -int platform_mailbox_fetch_msg_data(uint32_t *data_ptr); - -/** - * \brief Send a pointer via mailbox message - * - * \param[in] msg_ptr The pointer value to be sent. - * - * \retval 0 The operation succeeds. - * \retval else The operation fails. - */ -int platform_mailbox_send_msg_ptr(const void *msg_ptr); - -/** - * \brief Send a data value via mailbox message - * - * \param[in] data The data value to be sent - * - * \retval 0 The operation succeeds. - * \retval else The operation fails. - */ -int platform_mailbox_send_msg_data(uint32_t data); - -/** - * \brief Wait for a mailbox notify event. - */ -void platform_mailbox_wait_for_notify(void); - -/** - * \brief IPC initialization - * - * \retval 0 The operation succeeds. - * \retval else The operation fails. - */ -int platform_ns_ipc_init(void); - -#endif diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/client.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/client.h deleted file mode 100644 index 4115f93..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/client.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2018-2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#ifndef __PSA_CLIENT_H__ -#define __PSA_CLIENT_H__ - -#include -#include - -#include "psa/error.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/*********************** PSA Client Macros and Types *************************/ - -/** - * The version of the PSA Framework API that is being used to build the calling - * firmware. - */ -#define PSA_FRAMEWORK_VERSION (0x0100u) - -/** - * Return value from psa_version() if the requested RoT Service is not present - * in the system. - */ -#define PSA_VERSION_NONE (0u) - -/** - * The zero-value null handle can be assigned to variables used in clients and - * RoT Services, indicating that there is no current connection or message. - */ -#define PSA_NULL_HANDLE ((psa_handle_t)0) - -/** - * Tests whether a handle value returned by psa_connect() is valid. - */ -#define PSA_HANDLE_IS_VALID(handle) ((psa_handle_t)(handle) > 0) - -/** - * Converts the handle value returned from a failed call psa_connect() into - * an error code. - */ -#define PSA_HANDLE_TO_ERROR(handle) ((psa_status_t)(handle)) - -/** - * Maximum number of input and output vectors for a request to psa_call(). - */ -#define PSA_MAX_IOVEC (4u) - -/** - * An IPC message type that indicates a generic client request. - */ -#define PSA_IPC_CALL (0) - -typedef int32_t psa_handle_t; - -/** - * A read-only input memory region provided to an RoT Service. - */ -typedef struct psa_invec { - const void *base; /*!< the start address of the memory buffer */ - size_t len; /*!< the size in bytes */ -} psa_invec; - -/** - * A writable output memory region provided to an RoT Service. - */ -typedef struct psa_outvec { - void *base; /*!< the start address of the memory buffer */ - size_t len; /*!< the size in bytes */ -} psa_outvec; - -/*************************** PSA Client API **********************************/ - -/** - * \brief Retrieve the version of the PSA Framework API that is implemented. - * - * \return version The version of the PSA Framework implementation - * that is providing the runtime services to the - * caller. The major and minor version are encoded - * as follows: - * \arg version[15:8] -- major version number. - * \arg version[7:0] -- minor version number. - */ -uint32_t psa_framework_version(void); - -/** - * \brief Retrieve the version of an RoT Service or indicate that it is not - * present on this system. - * - * \param[in] sid ID of the RoT Service to query. - * - * \retval PSA_VERSION_NONE The RoT Service is not implemented, or the - * caller is not permitted to access the service. - * \retval > 0 The version of the implemented RoT Service. - */ -uint32_t psa_version(uint32_t sid); - -/** - * \brief Connect to an RoT Service by its SID. - * - * \param[in] sid ID of the RoT Service to connect to. - * \param[in] version Requested version of the RoT Service. - * - * \retval > 0 A handle for the connection. - * \retval PSA_ERROR_CONNECTION_REFUSED The SPM or RoT Service has refused the - * connection. - * \retval PSA_ERROR_CONNECTION_BUSY The SPM or RoT Service cannot make the - * connection at the moment. - * \retval "PROGRAMMER ERROR" The call is a PROGRAMMER ERROR if one or more - * of the following are true: - * \arg The RoT Service ID is not present. - * \arg The RoT Service version is not supported. - * \arg The caller is not allowed to access the RoT - * service. - */ -psa_handle_t psa_connect(uint32_t sid, uint32_t version); - -/** - * \brief Call an RoT Service on an established connection. - * - * \param[in] handle A handle to an established connection. - * \param[in] type The reuqest type. - * Must be zero( \ref PSA_IPC_CALL) or positive. - * \param[in] in_vec Array of input \ref psa_invec structures. - * \param[in] in_len Number of input \ref psa_invec structures. - * \param[in/out] out_vec Array of output \ref psa_outvec structures. - * \param[in] out_len Number of output \ref psa_outvec structures. - * - * \retval >=0 RoT Service-specific status value. - * \retval <0 RoT Service-specific error code. - * \retval PSA_ERROR_PROGRAMMER_ERROR The connection has been terminated by the - * RoT Service. The call is a PROGRAMMER ERROR if - * one or more of the following are true: - * \arg An invalid handle was passed. - * \arg The connection is already handling a request. - * \arg type < 0. - * \arg An invalid memory reference was provided. - * \arg in_len + out_len > PSA_MAX_IOVEC. - * \arg The message is unrecognized by the RoT - * Service or incorrectly formatted. - */ -psa_status_t psa_call(psa_handle_t handle, int32_t type, - const psa_invec *in_vec, - size_t in_len, - psa_outvec *out_vec, - size_t out_len); - -/** - * \brief Close a connection to an RoT Service. - * - * \param[in] handle A handle to an established connection, or the - * null handle. - * - * \retval void Success. - * \retval "PROGRAMMER ERROR" The call is a PROGRAMMER ERROR if one or more - * of the following are true: - * \arg An invalid handle was provided that is not - * the null handle. - * \arg The connection is currently handling a - * request. - */ -void psa_close(psa_handle_t handle); - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_CLIENT_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto.h deleted file mode 100644 index 1459195..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto.h +++ /dev/null @@ -1,3774 +0,0 @@ -/* - * Copyright (c) 2018-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ -/** - * \file psa/crypto.h - * \brief Platform Security Architecture cryptography module - */ - -#ifndef PSA_CRYPTO_H -#define PSA_CRYPTO_H - -#include - -#ifdef __DOXYGEN_ONLY__ -/* This __DOXYGEN_ONLY__ block contains mock definitions for things that - * must be defined in the crypto_platform.h header. These mock definitions - * are present in this file as a convenience to generate pretty-printed - * documentation that includes those definitions. */ - -/** \defgroup platform Implementation-specific definitions - * @{ - */ - -/** \brief Key handle. - * - * This type represents open handles to keys. It must be an unsigned integral - * type. The choice of type is implementation-dependent. - * - * 0 is not a valid key handle. How other handle values are assigned is - * implementation-dependent. - */ -typedef _unsigned_integral_type_ psa_key_handle_t; - -/**@}*/ -#endif /* __DOXYGEN_ONLY__ */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* The file "crypto_types.h" declares types that encode errors, - * algorithms, key types, policies, etc. */ -#include "psa/crypto_types.h" - -/** \defgroup version API version - * @{ - */ - -/** - * The major version of this implementation of the PSA Crypto API - */ -#define PSA_CRYPTO_API_VERSION_MAJOR 1 - -/** - * The minor version of this implementation of the PSA Crypto API - */ -#define PSA_CRYPTO_API_VERSION_MINOR 0 - -/**@}*/ - -/* The file "crypto_values.h" declares macros to build and analyze values - * of integral types defined in "crypto_types.h". */ -#include "psa/crypto_values.h" - -/** \defgroup initialization Library initialization - * @{ - */ - -/** - * \brief Library initialization. - * - * Applications must call this function before calling any other - * function in this module. - * - * Applications may call this function more than once. Once a call - * succeeds, subsequent calls are guaranteed to succeed. - * - * If the application calls other functions before calling psa_crypto_init(), - * the behavior is undefined. Implementations are encouraged to either perform - * the operation as if the library had been initialized or to return - * #PSA_ERROR_BAD_STATE or some other applicable error. In particular, - * implementations should not return a success status if the lack of - * initialization may have security implications, for example due to improper - * seeding of the random number generator. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY - */ -psa_status_t psa_crypto_init(void); - -/**@}*/ - -/** \addtogroup attributes - * @{ - */ - -/** \def PSA_KEY_ATTRIBUTES_INIT - * - * This macro returns a suitable initializer for a key attribute structure - * of type #psa_key_attributes_t. - */ -#ifdef __DOXYGEN_ONLY__ -/* This is an example definition for documentation purposes. - * Implementations should define a suitable value in `crypto_struct.h`. - */ -#define PSA_KEY_ATTRIBUTES_INIT {0} -#endif - -/** Return an initial value for a key attributes structure. - */ -static psa_key_attributes_t psa_key_attributes_init(void); - -/** Declare a key as persistent and set its key identifier. - * - * If the attribute structure currently declares the key as volatile (which - * is the default content of an attribute structure), this function sets - * the lifetime attribute to #PSA_KEY_LIFETIME_PERSISTENT. - * - * This function does not access storage, it merely stores the given - * value in the structure. - * The persistent key will be written to storage when the attribute - * structure is passed to a key creation function such as - * psa_import_key(), psa_generate_key(), - * psa_key_derivation_output_key() or psa_copy_key(). - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate each of its arguments exactly once. - * - * \param[out] attributes The attribute structure to write to. - * \param id The persistent identifier for the key. - */ -static void psa_set_key_id(psa_key_attributes_t *attributes, - psa_key_id_t id); - -/** Set the location of a persistent key. - * - * To make a key persistent, you must give it a persistent key identifier - * with psa_set_key_id(). By default, a key that has a persistent identifier - * is stored in the default storage area identifier by - * #PSA_KEY_LIFETIME_PERSISTENT. Call this function to choose a storage - * area, or to explicitly declare the key as volatile. - * - * This function does not access storage, it merely stores the given - * value in the structure. - * The persistent key will be written to storage when the attribute - * structure is passed to a key creation function such as - * psa_import_key(), psa_generate_key(), - * psa_key_derivation_output_key() or psa_copy_key(). - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate each of its arguments exactly once. - * - * \param[out] attributes The attribute structure to write to. - * \param lifetime The lifetime for the key. - * If this is #PSA_KEY_LIFETIME_VOLATILE, the - * key will be volatile, and the key identifier - * attribute is reset to 0. - */ -static void psa_set_key_lifetime(psa_key_attributes_t *attributes, - psa_key_lifetime_t lifetime); - -/** Retrieve the key identifier from key attributes. - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate its argument exactly once. - * - * \param[in] attributes The key attribute structure to query. - * - * \return The persistent identifier stored in the attribute structure. - * This value is unspecified if the attribute structure declares - * the key as volatile. - */ -static psa_key_id_t psa_get_key_id(const psa_key_attributes_t *attributes); - -/** Retrieve the lifetime from key attributes. - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate its argument exactly once. - * - * \param[in] attributes The key attribute structure to query. - * - * \return The lifetime value stored in the attribute structure. - */ -static psa_key_lifetime_t psa_get_key_lifetime( - const psa_key_attributes_t *attributes); - -/** Declare usage flags for a key. - * - * Usage flags are part of a key's usage policy. They encode what - * kind of operations are permitted on the key. For more details, - * refer to the documentation of the type #psa_key_usage_t. - * - * This function overwrites any usage flags - * previously set in \p attributes. - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate each of its arguments exactly once. - * - * \param[out] attributes The attribute structure to write to. - * \param usage_flags The usage flags to write. - */ -static void psa_set_key_usage_flags(psa_key_attributes_t *attributes, - psa_key_usage_t usage_flags); - -/** Retrieve the usage flags from key attributes. - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate its argument exactly once. - * - * \param[in] attributes The key attribute structure to query. - * - * \return The usage flags stored in the attribute structure. - */ -static psa_key_usage_t psa_get_key_usage_flags( - const psa_key_attributes_t *attributes); - -/** Declare the permitted algorithm policy for a key. - * - * The permitted algorithm policy of a key encodes which algorithm or - * algorithms are permitted to be used with this key. The following - * algorithm policies are supported: - * - 0 does not allow any cryptographic operation with the key. The key - * may be used for non-cryptographic actions such as exporting (if - * permitted by the usage flags). - * - An algorithm value permits this particular algorithm. - * - An algorithm wildcard built from #PSA_ALG_ANY_HASH allows the specified - * signature scheme with any hash algorithm. - * - * This function overwrites any algorithm policy - * previously set in \p attributes. - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate each of its arguments exactly once. - * - * \param[out] attributes The attribute structure to write to. - * \param alg The permitted algorithm policy to write. - */ -static void psa_set_key_algorithm(psa_key_attributes_t *attributes, - psa_algorithm_t alg); - - -/** Retrieve the algorithm policy from key attributes. - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate its argument exactly once. - * - * \param[in] attributes The key attribute structure to query. - * - * \return The algorithm stored in the attribute structure. - */ -static psa_algorithm_t psa_get_key_algorithm( - const psa_key_attributes_t *attributes); - -/** Declare the type of a key. - * - * This function overwrites any key type - * previously set in \p attributes. - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate each of its arguments exactly once. - * - * \param[out] attributes The attribute structure to write to. - * \param type The key type to write. - * If this is 0, the key type in \p attributes - * becomes unspecified. - */ -static void psa_set_key_type(psa_key_attributes_t *attributes, - psa_key_type_t type); - - -/** Declare the size of a key. - * - * This function overwrites any key size previously set in \p attributes. - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate each of its arguments exactly once. - * - * \param[out] attributes The attribute structure to write to. - * \param bits The key size in bits. - * If this is 0, the key size in \p attributes - * becomes unspecified. Keys of size 0 are - * not supported. - */ -static void psa_set_key_bits(psa_key_attributes_t *attributes, - size_t bits); - -/** Retrieve the key type from key attributes. - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate its argument exactly once. - * - * \param[in] attributes The key attribute structure to query. - * - * \return The key type stored in the attribute structure. - */ -static psa_key_type_t psa_get_key_type(const psa_key_attributes_t *attributes); - -/** Retrieve the key size from key attributes. - * - * This function may be declared as `static` (i.e. without external - * linkage). This function may be provided as a function-like macro, - * but in this case it must evaluate its argument exactly once. - * - * \param[in] attributes The key attribute structure to query. - * - * \return The key size stored in the attribute structure, in bits. - */ -static size_t psa_get_key_bits(const psa_key_attributes_t *attributes); - -/** Retrieve the attributes of a key. - * - * This function first resets the attribute structure as with - * psa_reset_key_attributes(). It then copies the attributes of - * the given key into the given attribute structure. - * - * \note This function may allocate memory or other resources. - * Once you have called this function on an attribute structure, - * you must call psa_reset_key_attributes() to free these resources. - * - * \param[in] handle Handle to the key to query. - * \param[in,out] attributes On success, the attributes of the key. - * On failure, equivalent to a - * freshly-initialized structure. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_get_key_attributes(psa_key_handle_t handle, - psa_key_attributes_t *attributes); - -/** Reset a key attribute structure to a freshly initialized state. - * - * You must initialize the attribute structure as described in the - * documentation of the type #psa_key_attributes_t before calling this - * function. Once the structure has been initialized, you may call this - * function at any time. - * - * This function frees any auxiliary resources that the structure - * may contain. - * - * \param[in,out] attributes The attribute structure to reset. - */ -void psa_reset_key_attributes(psa_key_attributes_t *attributes); - -/**@}*/ - -/** \defgroup key_management Key management - * @{ - */ - -/** Open a handle to an existing persistent key. - * - * Open a handle to a persistent key. A key is persistent if it was created - * with a lifetime other than #PSA_KEY_LIFETIME_VOLATILE. A persistent key - * always has a nonzero key identifier, set with psa_set_key_id() when - * creating the key. Implementations may provide additional pre-provisioned - * keys that can be opened with psa_open_key(). Such keys have a key identifier - * in the vendor range, as documented in the description of #psa_key_id_t. - * - * The application must eventually close the handle with psa_close_key() or - * psa_destroy_key() to release associated resources. If the application dies - * without calling one of these functions, the implementation should perform - * the equivalent of a call to psa_close_key(). - * - * Some implementations permit an application to open the same key multiple - * times. If this is successful, each call to psa_open_key() will return a - * different key handle. - * - * \note Applications that rely on opening a key multiple times will not be - * portable to implementations that only permit a single key handle to be - * opened. See also :ref:\`key-handles\`. - * - * \param id The persistent identifier of the key. - * \param[out] handle On success, a handle to the key. - * - * \retval #PSA_SUCCESS - * Success. The application can now use the value of `*handle` - * to access the key. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * The implementation does not have sufficient resources to open the - * key. This can be due to reaching an implementation limit on the - * number of open keys, the number of open key handles, or available - * memory. - * \retval #PSA_ERROR_DOES_NOT_EXIST - * There is no persistent key with key identifier \p id. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p id is not a valid persistent key identifier. - * \retval #PSA_ERROR_NOT_PERMITTED - * The specified key exists, but the application does not have the - * permission to access it. Note that this specification does not - * define any way to create such a key, but it may be possible - * through implementation-specific means. - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_open_key(psa_key_id_t id, - psa_key_handle_t *handle); - - -/** Close a key handle. - * - * If the handle designates a volatile key, this will destroy the key material - * and free all associated resources, just like psa_destroy_key(). - * - * If this is the last open handle to a persistent key, then closing the handle - * will free all resources associated with the key in volatile memory. The key - * data in persistent storage is not affected and can be opened again later - * with a call to psa_open_key(). - * - * Closing the key handle makes the handle invalid, and the key handle - * must not be used again by the application. - * - * \note If the key handle was used to set up an active - * :ref:\`multipart operation \`, then closing the - * key handle can cause the multipart operation to fail. Applications should - * maintain the key handle until after the multipart operation has finished. - * - * \param handle The key handle to close. - * If this is \c 0, do nothing and return \c PSA_SUCCESS. - * - * \retval #PSA_SUCCESS - * \p handle was a valid handle or \c 0. It is now closed. - * \retval #PSA_ERROR_INVALID_HANDLE - * \p handle is not a valid handle nor \c 0. - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_close_key(psa_key_handle_t handle); - -/** Make a copy of a key. - * - * Copy key material from one location to another. - * - * This function is primarily useful to copy a key from one location - * to another, since it populates a key using the material from - * another key which may have a different lifetime. - * - * This function may be used to share a key with a different party, - * subject to implementation-defined restrictions on key sharing. - * - * The policy on the source key must have the usage flag - * #PSA_KEY_USAGE_COPY set. - * This flag is sufficient to permit the copy if the key has the lifetime - * #PSA_KEY_LIFETIME_VOLATILE or #PSA_KEY_LIFETIME_PERSISTENT. - * Some secure elements do not provide a way to copy a key without - * making it extractable from the secure element. If a key is located - * in such a secure element, then the key must have both usage flags - * #PSA_KEY_USAGE_COPY and #PSA_KEY_USAGE_EXPORT in order to make - * a copy of the key outside the secure element. - * - * The resulting key may only be used in a way that conforms to - * both the policy of the original key and the policy specified in - * the \p attributes parameter: - * - The usage flags on the resulting key are the bitwise-and of the - * usage flags on the source policy and the usage flags in \p attributes. - * - If both allow the same algorithm or wildcard-based - * algorithm policy, the resulting key has the same algorithm policy. - * - If either of the policies allows an algorithm and the other policy - * allows a wildcard-based algorithm policy that includes this algorithm, - * the resulting key allows the same algorithm. - * - If the policies do not allow any algorithm in common, this function - * fails with the status #PSA_ERROR_INVALID_ARGUMENT. - * - * The effect of this function on implementation-defined attributes is - * implementation-defined. - * - * \param source_handle The key to copy. It must be a valid key handle. - * \param[in] attributes The attributes for the new key. - * They are used as follows: - * - The key type and size may be 0. If either is - * nonzero, it must match the corresponding - * attribute of the source key. - * - The key location (the lifetime and, for - * persistent keys, the key identifier) is - * used directly. - * - The policy constraints (usage flags and - * algorithm policy) are combined from - * the source key and \p attributes so that - * both sets of restrictions apply, as - * described in the documentation of this function. - * \param[out] target_handle On success, a handle to the newly created key. - * \c 0 on failure. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_HANDLE - * \p source_handle is invalid. - * \retval #PSA_ERROR_ALREADY_EXISTS - * This is an attempt to create a persistent key, and there is - * already a persistent key with the given identifier. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The lifetime or identifier in \p attributes are invalid. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The policy constraints on the source and specified in - * \p attributes are incompatible. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p attributes specifies a key type or key size - * which does not match the attributes of the source key. - * \retval #PSA_ERROR_NOT_PERMITTED - * The source key does not have the #PSA_KEY_USAGE_COPY usage flag. - * \retval #PSA_ERROR_NOT_PERMITTED - * The source key is not exportable and its lifetime does not - * allow copying it to the target's lifetime. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_INSUFFICIENT_STORAGE - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_copy_key(psa_key_handle_t source_handle, - const psa_key_attributes_t *attributes, - psa_key_handle_t *target_handle); - - -/** - * \brief Destroy a key. - * - * This function destroys a key from both volatile - * memory and, if applicable, non-volatile storage. Implementations shall - * make a best effort to ensure that that the key material cannot be recovered. - * - * This function also erases any metadata such as policies and frees - * resources associated with the key. To free all resources associated with - * the key, all handles to the key must be closed or destroyed. - * - * Destroying the key makes the handle invalid, and the key handle - * must not be used again by the application. Using other open handles to the - * destroyed key in a cryptographic operation will result in an error. - * - * If a key is currently in use in a multipart operation, then destroying the - * key will cause the multipart operation to fail. - * - * \param handle Handle to the key to erase. - * If this is \c 0, do nothing and return \c PSA_SUCCESS. - * - * \retval #PSA_SUCCESS - * \p handle was a valid handle and the key material that it - * referred to has been erased. - * Alternatively, \p handle is \c 0. - * \retval #PSA_ERROR_NOT_PERMITTED - * The key cannot be erased because it is - * read-only, either due to a policy or due to physical restrictions. - * \retval #PSA_ERROR_INVALID_HANDLE - * \p handle is not a valid handle nor \c 0. - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * There was an failure in communication with the cryptoprocessor. - * The key material may still be present in the cryptoprocessor. - * \retval #PSA_ERROR_STORAGE_FAILURE - * The storage is corrupted. Implementations shall make a best effort - * to erase key material even in this stage, however applications - * should be aware that it may be impossible to guarantee that the - * key material is not recoverable in such cases. - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * An unexpected condition which is not a storage corruption or - * a communication failure occurred. The cryptoprocessor may have - * been compromised. - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_destroy_key(psa_key_handle_t handle); - -/**@}*/ - -/** \defgroup import_export Key import and export - * @{ - */ - -/** - * \brief Import a key in binary format. - * - * This function supports any output from psa_export_key(). Refer to the - * documentation of psa_export_public_key() for the format of public keys - * and to the documentation of psa_export_key() for the format for - * other key types. - * - * The key data determines the key size. The attributes may optionally - * specify a key size; in this case it must match the size determined - * from the key data. A key size of 0 in \p attributes indicates that - * the key size is solely determined by the key data. - * - * Implementations must reject an attempt to import a key of size 0. - * - * This specification supports a single format for each key type. - * Implementations may support other formats as long as the standard - * format is supported. Implementations that support other formats - * should ensure that the formats are clearly unambiguous so as to - * minimize the risk that an invalid input is accidentally interpreted - * according to a different format. - * - * \param[in] attributes The attributes for the new key. - * The key size is always determined from the - * \p data buffer. - * If the key size in \p attributes is nonzero, - * it must be equal to the size from \p data. - * \param[out] handle On success, a handle to the newly created key. - * \c 0 on failure. - * \param[in] data Buffer containing the key data. The content of this - * buffer is interpreted according to the type declared - * in \p attributes. - * All implementations must support at least the format - * described in the documentation - * of psa_export_key() or psa_export_public_key() for - * the chosen type. Implementations may allow other - * formats, but should be conservative: implementations - * should err on the side of rejecting content if it - * may be erroneous (e.g. wrong type or truncated data). - * \param data_length Size of the \p data buffer in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * If the key is persistent, the key material and the key's metadata - * have been saved to persistent storage. - * \retval #PSA_ERROR_ALREADY_EXISTS - * This is an attempt to create a persistent key, and there is - * already a persistent key with the given identifier. - * \retval #PSA_ERROR_NOT_SUPPORTED - * The key type or key size is not supported, either by the - * implementation in general or in this particular persistent location. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The key attributes, as a whole, are invalid. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The key data is not correctly formatted. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The size in \p attributes is nonzero and does not match the size - * of the key data. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_INSUFFICIENT_STORAGE - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_import_key(const psa_key_attributes_t *attributes, - const uint8_t *data, - size_t data_length, - psa_key_handle_t *handle); - - - -/** - * \brief Export a key in binary format. - * - * The output of this function can be passed to psa_import_key() to - * create an equivalent object. - * - * If the implementation of psa_import_key() supports other formats - * beyond the format specified here, the output from psa_export_key() - * must use the representation specified here, not the original - * representation. - * - * For standard key types, the output format is as follows: - * - * - For symmetric keys (including MAC keys), the format is the - * raw bytes of the key. - * - For DES, the key data consists of 8 bytes. The parity bits must be - * correct. - * - For Triple-DES, the format is the concatenation of the - * two or three DES keys. - * - For RSA key pairs (#PSA_KEY_TYPE_RSA_KEY_PAIR), the format - * is the non-encrypted DER encoding of the representation defined by - * PKCS\#1 (RFC 8017) as `RSAPrivateKey`, version 0. - * ``` - * RSAPrivateKey ::= SEQUENCE { - * version INTEGER, -- must be 0 - * modulus INTEGER, -- n - * publicExponent INTEGER, -- e - * privateExponent INTEGER, -- d - * prime1 INTEGER, -- p - * prime2 INTEGER, -- q - * exponent1 INTEGER, -- d mod (p-1) - * exponent2 INTEGER, -- d mod (q-1) - * coefficient INTEGER, -- (inverse of q) mod p - * } - * ``` - * - For elliptic curve key pairs (key types for which - * #PSA_KEY_TYPE_IS_ECC_KEY_PAIR is true), the format is - * a representation of the private value as a `ceiling(m/8)`-byte string - * where `m` is the bit size associated with the curve, i.e. the bit size - * of the order of the curve's coordinate field. This byte string is - * in little-endian order for Montgomery curves (curve types - * `PSA_ECC_CURVE_CURVEXXX`), and in big-endian order for Weierstrass - * curves (curve types `PSA_ECC_CURVE_SECTXXX`, `PSA_ECC_CURVE_SECPXXX` - * and `PSA_ECC_CURVE_BRAINPOOL_PXXX`). - * This is the content of the `privateKey` field of the `ECPrivateKey` - * format defined by RFC 5915. - * - For Diffie-Hellman key exchange key pairs (key types for which - * #PSA_KEY_TYPE_IS_DH_KEY_PAIR is true), the - * format is the representation of the private key `x` as a big-endian byte - * string. The length of the byte string is the private key size in bytes - * (leading zeroes are not stripped). - * - For public keys (key types for which #PSA_KEY_TYPE_IS_PUBLIC_KEY is - * true), the format is the same as for psa_export_public_key(). - * - * The policy on the key must have the usage flag #PSA_KEY_USAGE_EXPORT set. - * - * \param handle Handle to the key to export. - * \param[out] data Buffer where the key data is to be written. - * \param data_size Size of the \p data buffer in bytes. - * \param[out] data_length On success, the number of bytes - * that make up the key data. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * The key does not have the #PSA_KEY_USAGE_EXPORT flag. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p data buffer is too small. You can determine a - * sufficient buffer size by calling - * #PSA_KEY_EXPORT_MAX_SIZE(\c type, \c bits) - * where \c type is the key type - * and \c bits is the key size in bits. - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_export_key(psa_key_handle_t handle, - uint8_t *data, - size_t data_size, - size_t *data_length); - -/** - * \brief Export a public key or the public part of a key pair in binary format. - * - * The output of this function can be passed to psa_import_key() to - * create an object that is equivalent to the public key. - * - * This specification supports a single format for each key type. - * Implementations may support other formats as long as the standard - * format is supported. Implementations that support other formats - * should ensure that the formats are clearly unambiguous so as to - * minimize the risk that an invalid input is accidentally interpreted - * according to a different format. - * - * For standard key types, the output format is as follows: - * - For RSA public keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY), the DER encoding of - * the representation defined by RFC 3279 §2.3.1 as `RSAPublicKey`. - * ``` - * RSAPublicKey ::= SEQUENCE { - * modulus INTEGER, -- n - * publicExponent INTEGER } -- e - * ``` - * - For elliptic curve public keys (key types for which - * #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true), the format is the uncompressed - * representation defined by SEC1 §2.3.3 as the content of an ECPoint. - * Let `m` be the bit size associated with the curve, i.e. the bit size of - * `q` for a curve over `F_q`. The representation consists of: - * - The byte 0x04; - * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; - * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. - * - For Diffie-Hellman key exchange public keys (key types for which - * #PSA_KEY_TYPE_IS_DH_PUBLIC_KEY is true), - * the format is the representation of the public key `y = g^x mod p` as a - * big-endian byte string. The length of the byte string is the length of the - * base prime `p` in bytes. - * - * Exporting a public key object or the public part of a key pair is - * always permitted, regardless of the key's usage flags. - * - * \param handle Handle to the key to export. - * \param[out] data Buffer where the key data is to be written. - * \param data_size Size of the \p data buffer in bytes. - * \param[out] data_length On success, the number of bytes - * that make up the key data. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The key is neither a public key nor a key pair. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p data buffer is too small. You can determine a - * sufficient buffer size by calling - * #PSA_KEY_EXPORT_MAX_SIZE(#PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(\c type), \c bits) - * where \c type is the key type - * and \c bits is the key size in bits. - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_export_public_key(psa_key_handle_t handle, - uint8_t *data, - size_t data_size, - size_t *data_length); - - - -/**@}*/ - -/** \defgroup hash Message digests - * @{ - */ - -/** Calculate the hash (digest) of a message. - * - * \note To verify the hash of a message against an - * expected value, use psa_hash_compare() instead. - * - * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value - * such that #PSA_ALG_IS_HASH(\p alg) is true). - * \param[in] input Buffer containing the message to hash. - * \param input_length Size of the \p input buffer in bytes. - * \param[out] hash Buffer where the hash is to be written. - * \param hash_size Size of the \p hash buffer in bytes. - * \param[out] hash_length On success, the number of bytes - * that make up the hash value. This is always - * #PSA_HASH_SIZE(\p alg). - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not a hash algorithm. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * \p hash_size is too small - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_hash_compute(psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - uint8_t *hash, - size_t hash_size, - size_t *hash_length); - -/** Calculate the hash (digest) of a message and compare it with a - * reference value. - * - * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value - * such that #PSA_ALG_IS_HASH(\p alg) is true). - * \param[in] input Buffer containing the message to hash. - * \param input_length Size of the \p input buffer in bytes. - * \param[out] hash Buffer containing the expected hash value. - * \param hash_length Size of the \p hash buffer in bytes. - * - * \retval #PSA_SUCCESS - * The expected hash is identical to the actual hash of the input. - * \retval #PSA_ERROR_INVALID_SIGNATURE - * The hash of the message was calculated successfully, but it - * differs from the expected hash. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not a hash algorithm. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p input_length or \p hash_length do not match the hash size for \p alg - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_hash_compare(psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - const uint8_t *hash, - const size_t hash_length); - -/** The type of the state data structure for multipart hash operations. - * - * Before calling any function on a hash operation object, the application must - * initialize it by any of the following means: - * - Set the structure to all-bits-zero, for example: - * \code - * psa_hash_operation_t operation; - * memset(&operation, 0, sizeof(operation)); - * \endcode - * - Initialize the structure to logical zero values, for example: - * \code - * psa_hash_operation_t operation = {0}; - * \endcode - * - Initialize the structure to the initializer #PSA_HASH_OPERATION_INIT, - * for example: - * \code - * psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; - * \endcode - * - Assign the result of the function psa_hash_operation_init() - * to the structure, for example: - * \code - * psa_hash_operation_t operation; - * operation = psa_hash_operation_init(); - * \endcode - * - * This is an implementation-defined \c struct. Applications should not - * make any assumptions about the content of this structure except - * as directed by the documentation of a specific implementation. */ -typedef struct psa_hash_operation_s psa_hash_operation_t; - -/** \def PSA_HASH_OPERATION_INIT - * - * This macro returns a suitable initializer for a hash operation object - * of type #psa_hash_operation_t. - */ -#ifdef __DOXYGEN_ONLY__ -/* This is an example definition for documentation purposes. - * Implementations should define a suitable value in `crypto_struct.h`. - */ -#define PSA_HASH_OPERATION_INIT {0} -#endif - -/** Return an initial value for a hash operation object. - */ -static psa_hash_operation_t psa_hash_operation_init(void); - -/** Set up a multipart hash operation. - * - * The sequence of operations to calculate a hash (message digest) - * is as follows: - * -# Allocate an operation object which will be passed to all the functions - * listed here. - * -# Initialize the operation object with one of the methods described in the - * documentation for #psa_hash_operation_t, e.g. #PSA_HASH_OPERATION_INIT. - * -# Call psa_hash_setup() to specify the algorithm. - * -# Call psa_hash_update() zero, one or more times, passing a fragment - * of the message each time. The hash that is calculated is the hash - * of the concatenation of these messages in order. - * -# To calculate the hash, call psa_hash_finish(). - * To compare the hash with an expected value, call psa_hash_verify(). - * - * If an error occurs at any step after a call to psa_hash_setup(), the - * operation will need to be reset by a call to psa_hash_abort(). The - * application may call psa_hash_abort() at any time after the operation - * has been initialized. - * - * After a successful call to psa_hash_setup(), the application must - * eventually terminate the operation. The following events terminate an - * operation: - * - A successful call to psa_hash_finish() or psa_hash_verify(). - * - A call to psa_hash_abort(). - * - * \param[in,out] operation The operation object to set up. It must have - * been initialized as per the documentation for - * #psa_hash_operation_t and not yet in use. - * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value - * such that #PSA_ALG_IS_HASH(\p alg) is true). - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not a supported hash algorithm. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p alg is not a hash algorithm. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be inactive). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_hash_setup(psa_hash_operation_t *operation, - psa_algorithm_t alg); - -/** Add a message fragment to a multipart hash operation. - * - * The application must call psa_hash_setup() before calling this function. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_hash_abort(). - * - * \param[in,out] operation Active hash operation. - * \param[in] input Buffer containing the message fragment to hash. - * \param input_length Size of the \p input buffer in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it muct be active). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_hash_update(psa_hash_operation_t *operation, - const uint8_t *input, - size_t input_length); - -/** Finish the calculation of the hash of a message. - * - * The application must call psa_hash_setup() before calling this function. - * This function calculates the hash of the message formed by concatenating - * the inputs passed to preceding calls to psa_hash_update(). - * - * When this function returns successfuly, the operation becomes inactive. - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_hash_abort(). - * - * \warning Applications should not call this function if they expect - * a specific value for the hash. Call psa_hash_verify() instead. - * Beware that comparing integrity or authenticity data such as - * hash values with a function such as \c memcmp is risky - * because the time taken by the comparison may leak information - * about the hashed data which could allow an attacker to guess - * a valid hash and thereby bypass security controls. - * - * \param[in,out] operation Active hash operation. - * \param[out] hash Buffer where the hash is to be written. - * \param hash_size Size of the \p hash buffer in bytes. - * \param[out] hash_length On success, the number of bytes - * that make up the hash value. This is always - * #PSA_HASH_SIZE(\c alg) where \c alg is the - * hash algorithm that is calculated. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active). - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p hash buffer is too small. You can determine a - * sufficient buffer size by calling #PSA_HASH_SIZE(\c alg) - * where \c alg is the hash algorithm that is calculated. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_hash_finish(psa_hash_operation_t *operation, - uint8_t *hash, - size_t hash_size, - size_t *hash_length); - -/** Finish the calculation of the hash of a message and compare it with - * an expected value. - * - * The application must call psa_hash_setup() before calling this function. - * This function calculates the hash of the message formed by concatenating - * the inputs passed to preceding calls to psa_hash_update(). It then - * compares the calculated hash with the expected hash passed as a - * parameter to this function. - * - * When this function returns successfuly, the operation becomes inactive. - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_hash_abort(). - * - * \note Implementations shall make the best effort to ensure that the - * comparison between the actual hash and the expected hash is performed - * in constant time. - * - * \param[in,out] operation Active hash operation. - * \param[in] hash Buffer containing the expected hash value. - * \param hash_length Size of the \p hash buffer in bytes. - * - * \retval #PSA_SUCCESS - * The expected hash is identical to the actual hash of the message. - * \retval #PSA_ERROR_INVALID_SIGNATURE - * The hash of the message was calculated successfully, but it - * differs from the expected hash. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_hash_verify(psa_hash_operation_t *operation, - const uint8_t *hash, - size_t hash_length); - -/** Abort a hash operation. - * - * Aborting an operation frees all associated resources except for the - * \p operation structure itself. Once aborted, the operation object - * can be reused for another operation by calling - * psa_hash_setup() again. - * - * You may call this function any time after the operation object has - * been initialized by one of the methods described in #psa_hash_operation_t. - * - * In particular, calling psa_hash_abort() after the operation has been - * terminated by a call to psa_hash_abort(), psa_hash_finish() or - * psa_hash_verify() is safe and has no effect. - * - * \param[in,out] operation Initialized hash operation. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_hash_abort(psa_hash_operation_t *operation); - -/** Clone a hash operation. - * - * This function copies the state of an ongoing hash operation to - * a new operation object. In other words, this function is equivalent - * to calling psa_hash_setup() on \p target_operation with the same - * algorithm that \p source_operation was set up for, then - * psa_hash_update() on \p target_operation with the same input that - * that was passed to \p source_operation. After this function returns, the - * two objects are independent, i.e. subsequent calls involving one of - * the objects do not affect the other object. - * - * \param[in] source_operation The active hash operation to clone. - * \param[in,out] target_operation The operation object to set up. - * It must be initialized but not active. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_BAD_STATE - * The \p source_operation state is not valid (it must be active). - * \retval #PSA_ERROR_BAD_STATE - * The \p target_operation state is not valid (it must be inactive). - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation, - psa_hash_operation_t *target_operation); - -/**@}*/ - -/** \defgroup MAC Message authentication codes - * @{ - */ - -/** Calculate the MAC (message authentication code) of a message. - * - * \note To verify the MAC of a message against an - * expected value, use psa_mac_verify() instead. - * Beware that comparing integrity or authenticity data such as - * MAC values with a function such as \c memcmp is risky - * because the time taken by the comparison may leak information - * about the MAC value which could allow an attacker to guess - * a valid MAC and thereby bypass security controls. - * - * \param handle Handle to the key to use for the operation. - * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value - * such that #PSA_ALG_IS_MAC(\p alg) is true). - * \param[in] input Buffer containing the input message. - * \param input_length Size of the \p input buffer in bytes. - * \param[out] mac Buffer where the MAC value is to be written. - * \param mac_size Size of the \p mac buffer in bytes. - * \param[out] mac_length On success, the number of bytes - * that make up the MAC value. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not a MAC algorithm. - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * \p mac_size is too small - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * The key could not be retrieved from storage. - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_mac_compute(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - uint8_t *mac, - size_t mac_size, - size_t *mac_length); - -/** Calculate the MAC of a message and compare it with a reference value. - * - * \param handle Handle to the key to use for the operation. - * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value - * such that #PSA_ALG_IS_MAC(\p alg) is true). - * \param[in] input Buffer containing the input message. - * \param input_length Size of the \p input buffer in bytes. - * \param[out] mac Buffer containing the expected MAC value. - * \param mac_length Size of the \p mac buffer in bytes. - * - * \retval #PSA_SUCCESS - * The expected MAC is identical to the actual MAC of the input. - * \retval #PSA_ERROR_INVALID_SIGNATURE - * The MAC of the message was calculated successfully, but it - * differs from the expected value. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not a MAC algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * The key could not be retrieved from storage. - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_mac_verify(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - const uint8_t *mac, - const size_t mac_length); - -/** The type of the state data structure for multipart MAC operations. - * - * Before calling any function on a MAC operation object, the application must - * initialize it by any of the following means: - * - Set the structure to all-bits-zero, for example: - * \code - * psa_mac_operation_t operation; - * memset(&operation, 0, sizeof(operation)); - * \endcode - * - Initialize the structure to logical zero values, for example: - * \code - * psa_mac_operation_t operation = {0}; - * \endcode - * - Initialize the structure to the initializer #PSA_MAC_OPERATION_INIT, - * for example: - * \code - * psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; - * \endcode - * - Assign the result of the function psa_mac_operation_init() - * to the structure, for example: - * \code - * psa_mac_operation_t operation; - * operation = psa_mac_operation_init(); - * \endcode - * - * This is an implementation-defined \c struct. Applications should not - * make any assumptions about the content of this structure except - * as directed by the documentation of a specific implementation. */ -typedef struct psa_mac_operation_s psa_mac_operation_t; - -/** \def PSA_MAC_OPERATION_INIT - * - * This macro returns a suitable initializer for a MAC operation object of type - * #psa_mac_operation_t. - */ -#ifdef __DOXYGEN_ONLY__ -/* This is an example definition for documentation purposes. - * Implementations should define a suitable value in `crypto_struct.h`. - */ -#define PSA_MAC_OPERATION_INIT {0} -#endif - -/** Return an initial value for a MAC operation object. - */ -static psa_mac_operation_t psa_mac_operation_init(void); - -/** Set up a multipart MAC calculation operation. - * - * This function sets up the calculation of the MAC - * (message authentication code) of a byte string. - * To verify the MAC of a message against an - * expected value, use psa_mac_verify_setup() instead. - * - * The sequence of operations to calculate a MAC is as follows: - * -# Allocate an operation object which will be passed to all the functions - * listed here. - * -# Initialize the operation object with one of the methods described in the - * documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT. - * -# Call psa_mac_sign_setup() to specify the algorithm and key. - * -# Call psa_mac_update() zero, one or more times, passing a fragment - * of the message each time. The MAC that is calculated is the MAC - * of the concatenation of these messages in order. - * -# At the end of the message, call psa_mac_sign_finish() to finish - * calculating the MAC value and retrieve it. - * - * If an error occurs at any step after a call to psa_mac_sign_setup(), the - * operation will need to be reset by a call to psa_mac_abort(). The - * application may call psa_mac_abort() at any time after the operation - * has been initialized. - * - * After a successful call to psa_mac_sign_setup(), the application must - * eventually terminate the operation through one of the following methods: - * - A successful call to psa_mac_sign_finish(). - * - A call to psa_mac_abort(). - * - * \param[in,out] operation The operation object to set up. It must have - * been initialized as per the documentation for - * #psa_mac_operation_t and not yet in use. - * \param handle Handle to the key to use for the operation. - * It must remain valid until the operation - * terminates. - * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value - * such that #PSA_ALG_IS_MAC(\p alg) is true). - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not a MAC algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * The key could not be retrieved from storage. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be inactive). - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg); - -/** Set up a multipart MAC verification operation. - * - * This function sets up the verification of the MAC - * (message authentication code) of a byte string against an expected value. - * - * The sequence of operations to verify a MAC is as follows: - * -# Allocate an operation object which will be passed to all the functions - * listed here. - * -# Initialize the operation object with one of the methods described in the - * documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT. - * -# Call psa_mac_verify_setup() to specify the algorithm and key. - * -# Call psa_mac_update() zero, one or more times, passing a fragment - * of the message each time. The MAC that is calculated is the MAC - * of the concatenation of these messages in order. - * -# At the end of the message, call psa_mac_verify_finish() to finish - * calculating the actual MAC of the message and verify it against - * the expected value. - * - * If an error occurs at any step after a call to psa_mac_verify_setup(), the - * operation will need to be reset by a call to psa_mac_abort(). The - * application may call psa_mac_abort() at any time after the operation - * has been initialized. - * - * After a successful call to psa_mac_verify_setup(), the application must - * eventually terminate the operation through one of the following methods: - * - A successful call to psa_mac_verify_finish(). - * - A call to psa_mac_abort(). - * - * \param[in,out] operation The operation object to set up. It must have - * been initialized as per the documentation for - * #psa_mac_operation_t and not yet in use. - * \param handle Handle to the key to use for the operation. - * It must remain valid until the operation - * terminates. - * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value - * such that #PSA_ALG_IS_MAC(\p alg) is true). - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \c key is not compatible with \c alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \c alg is not supported or is not a MAC algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * The key could not be retrieved from storage - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be inactive). - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg); - -/** Add a message fragment to a multipart MAC operation. - * - * The application must call psa_mac_sign_setup() or psa_mac_verify_setup() - * before calling this function. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_mac_abort(). - * - * \param[in,out] operation Active MAC operation. - * \param[in] input Buffer containing the message fragment to add to - * the MAC calculation. - * \param input_length Size of the \p input buffer in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_mac_update(psa_mac_operation_t *operation, - const uint8_t *input, - size_t input_length); - -/** Finish the calculation of the MAC of a message. - * - * The application must call psa_mac_sign_setup() before calling this function. - * This function calculates the MAC of the message formed by concatenating - * the inputs passed to preceding calls to psa_mac_update(). - * - * When this function returns successfuly, the operation becomes inactive. - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_mac_abort(). - * - * \warning Applications should not call this function if they expect - * a specific value for the MAC. Call psa_mac_verify_finish() instead. - * Beware that comparing integrity or authenticity data such as - * MAC values with a function such as \c memcmp is risky - * because the time taken by the comparison may leak information - * about the MAC value which could allow an attacker to guess - * a valid MAC and thereby bypass security controls. - * - * \param[in,out] operation Active MAC operation. - * \param[out] mac Buffer where the MAC value is to be written. - * \param mac_size Size of the \p mac buffer in bytes. - * \param[out] mac_length On success, the number of bytes - * that make up the MAC value. This is always - * #PSA_MAC_FINAL_SIZE(\c key_type, \c key_bits, \c alg) - * where \c key_type and \c key_bits are the type and - * bit-size respectively of the key and \c alg is the - * MAC algorithm that is calculated. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be an active mac sign - * operation). - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p mac buffer is too small. You can determine a - * sufficient buffer size by calling PSA_MAC_FINAL_SIZE(). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, - uint8_t *mac, - size_t mac_size, - size_t *mac_length); - -/** Finish the calculation of the MAC of a message and compare it with - * an expected value. - * - * The application must call psa_mac_verify_setup() before calling this function. - * This function calculates the MAC of the message formed by concatenating - * the inputs passed to preceding calls to psa_mac_update(). It then - * compares the calculated MAC with the expected MAC passed as a - * parameter to this function. - * - * When this function returns successfuly, the operation becomes inactive. - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_mac_abort(). - * - * \note Implementations shall make the best effort to ensure that the - * comparison between the actual MAC and the expected MAC is performed - * in constant time. - * - * \param[in,out] operation Active MAC operation. - * \param[in] mac Buffer containing the expected MAC value. - * \param mac_length Size of the \p mac buffer in bytes. - * - * \retval #PSA_SUCCESS - * The expected MAC is identical to the actual MAC of the message. - * \retval #PSA_ERROR_INVALID_SIGNATURE - * The MAC of the message was calculated successfully, but it - * differs from the expected MAC. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be an active mac verify - * operation). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation, - const uint8_t *mac, - size_t mac_length); - -/** Abort a MAC operation. - * - * Aborting an operation frees all associated resources except for the - * \p operation structure itself. Once aborted, the operation object - * can be reused for another operation by calling - * psa_mac_sign_setup() or psa_mac_verify_setup() again. - * - * You may call this function any time after the operation object has - * been initialized by one of the methods described in #psa_mac_operation_t. - * - * In particular, calling psa_mac_abort() after the operation has been - * terminated by a call to psa_mac_abort(), psa_mac_sign_finish() or - * psa_mac_verify_finish() is safe and has no effect. - * - * \param[in,out] operation Initialized MAC operation. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_mac_abort(psa_mac_operation_t *operation); - -/**@}*/ - -/** \defgroup cipher Symmetric ciphers - * @{ - */ - -/** Encrypt a message using a symmetric cipher. - * - * This function encrypts a message with a random IV (initialization - * vector). Use the multipart operation interface with a - * #psa_cipher_operation_t object to provide other forms of IV. - * - * \param handle Handle to the key to use for the operation. - * It must remain valid until the operation - * terminates. - * \param alg The cipher algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_CIPHER(\p alg) is true). - * \param[in] input Buffer containing the message to encrypt. - * \param input_length Size of the \p input buffer in bytes. - * \param[out] output Buffer where the output is to be written. - * The output contains the IV followed by - * the ciphertext proper. - * \param output_size Size of the \p output buffer in bytes. - * \param[out] output_length On success, the number of bytes - * that make up the output. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not a cipher algorithm. - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_cipher_encrypt(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - uint8_t *output, - size_t output_size, - size_t *output_length); - -/** Decrypt a message using a symmetric cipher. - * - * This function decrypts a message encrypted with a symmetric cipher. - * - * \param handle Handle to the key to use for the operation. - * It must remain valid until the operation - * terminates. - * \param alg The cipher algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_CIPHER(\p alg) is true). - * \param[in] input Buffer containing the message to decrypt. - * This consists of the IV followed by the - * ciphertext proper. - * \param input_length Size of the \p input buffer in bytes. - * \param[out] output Buffer where the plaintext is to be written. - * \param output_size Size of the \p output buffer in bytes. - * \param[out] output_length On success, the number of bytes - * that make up the output. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not a cipher algorithm. - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_cipher_decrypt(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - uint8_t *output, - size_t output_size, - size_t *output_length); - -/** The type of the state data structure for multipart cipher operations. - * - * Before calling any function on a cipher operation object, the application - * must initialize it by any of the following means: - * - Set the structure to all-bits-zero, for example: - * \code - * psa_cipher_operation_t operation; - * memset(&operation, 0, sizeof(operation)); - * \endcode - * - Initialize the structure to logical zero values, for example: - * \code - * psa_cipher_operation_t operation = {0}; - * \endcode - * - Initialize the structure to the initializer #PSA_CIPHER_OPERATION_INIT, - * for example: - * \code - * psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; - * \endcode - * - Assign the result of the function psa_cipher_operation_init() - * to the structure, for example: - * \code - * psa_cipher_operation_t operation; - * operation = psa_cipher_operation_init(); - * \endcode - * - * This is an implementation-defined \c struct. Applications should not - * make any assumptions about the content of this structure except - * as directed by the documentation of a specific implementation. */ -typedef struct psa_cipher_operation_s psa_cipher_operation_t; - -/** \def PSA_CIPHER_OPERATION_INIT - * - * This macro returns a suitable initializer for a cipher operation object of - * type #psa_cipher_operation_t. - */ -#ifdef __DOXYGEN_ONLY__ -/* This is an example definition for documentation purposes. - * Implementations should define a suitable value in `crypto_struct.h`. - */ -#define PSA_CIPHER_OPERATION_INIT {0} -#endif - -/** Return an initial value for a cipher operation object. - */ -static psa_cipher_operation_t psa_cipher_operation_init(void); - -/** Set the key for a multipart symmetric encryption operation. - * - * The sequence of operations to encrypt a message with a symmetric cipher - * is as follows: - * -# Allocate an operation object which will be passed to all the functions - * listed here. - * -# Initialize the operation object with one of the methods described in the - * documentation for #psa_cipher_operation_t, e.g. - * #PSA_CIPHER_OPERATION_INIT. - * -# Call psa_cipher_encrypt_setup() to specify the algorithm and key. - * -# Call either psa_cipher_generate_iv() or psa_cipher_set_iv() to - * generate or set the IV (initialization vector). You should use - * psa_cipher_generate_iv() unless the protocol you are implementing - * requires a specific IV value. - * -# Call psa_cipher_update() zero, one or more times, passing a fragment - * of the message each time. - * -# Call psa_cipher_finish(). - * - * If an error occurs at any step after a call to psa_cipher_encrypt_setup(), - * the operation will need to be reset by a call to psa_cipher_abort(). The - * application may call psa_cipher_abort() at any time after the operation - * has been initialized. - * - * After a successful call to psa_cipher_encrypt_setup(), the application must - * eventually terminate the operation. The following events terminate an - * operation: - * - A successful call to psa_cipher_finish(). - * - A call to psa_cipher_abort(). - * - * \param[in,out] operation The operation object to set up. It must have - * been initialized as per the documentation for - * #psa_cipher_operation_t and not yet in use. - * \param handle Handle to the key to use for the operation. - * It must remain valid until the operation - * terminates. - * \param alg The cipher algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_CIPHER(\p alg) is true). - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not a cipher algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be inactive). - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg); - -/** Set the key for a multipart symmetric decryption operation. - * - * The sequence of operations to decrypt a message with a symmetric cipher - * is as follows: - * -# Allocate an operation object which will be passed to all the functions - * listed here. - * -# Initialize the operation object with one of the methods described in the - * documentation for #psa_cipher_operation_t, e.g. - * #PSA_CIPHER_OPERATION_INIT. - * -# Call psa_cipher_decrypt_setup() to specify the algorithm and key. - * -# Call psa_cipher_set_iv() with the IV (initialization vector) for the - * decryption. If the IV is prepended to the ciphertext, you can call - * psa_cipher_update() on a buffer containing the IV followed by the - * beginning of the message. - * -# Call psa_cipher_update() zero, one or more times, passing a fragment - * of the message each time. - * -# Call psa_cipher_finish(). - * - * If an error occurs at any step after a call to psa_cipher_decrypt_setup(), - * the operation will need to be reset by a call to psa_cipher_abort(). The - * application may call psa_cipher_abort() at any time after the operation - * has been initialized. - * - * After a successful call to psa_cipher_decrypt_setup(), the application must - * eventually terminate the operation. The following events terminate an - * operation: - * - A successful call to psa_cipher_finish(). - * - A call to psa_cipher_abort(). - * - * \param[in,out] operation The operation object to set up. It must have - * been initialized as per the documentation for - * #psa_cipher_operation_t and not yet in use. - * \param handle Handle to the key to use for the operation. - * It must remain valid until the operation - * terminates. - * \param alg The cipher algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_CIPHER(\p alg) is true). - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not a cipher algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be inactive). - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg); - -/** Generate an IV for a symmetric encryption operation. - * - * This function generates a random IV (initialization vector), nonce - * or initial counter value for the encryption operation as appropriate - * for the chosen algorithm, key type and key size. - * - * The application must call psa_cipher_encrypt_setup() before - * calling this function. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_cipher_abort(). - * - * \param[in,out] operation Active cipher operation. - * \param[out] iv Buffer where the generated IV is to be written. - * \param iv_size Size of the \p iv buffer in bytes. - * \param[out] iv_length On success, the number of bytes of the - * generated IV. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active, with no IV set). - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p iv buffer is too small. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation, - uint8_t *iv, - size_t iv_size, - size_t *iv_length); - -/** Set the IV for a symmetric encryption or decryption operation. - * - * This function sets the IV (initialization vector), nonce - * or initial counter value for the encryption or decryption operation. - * - * The application must call psa_cipher_encrypt_setup() before - * calling this function. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_cipher_abort(). - * - * \note When encrypting, applications should use psa_cipher_generate_iv() - * instead of this function, unless implementing a protocol that requires - * a non-random IV. - * - * \param[in,out] operation Active cipher operation. - * \param[in] iv Buffer containing the IV to use. - * \param iv_length Size of the IV in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be an active cipher - * encrypt operation, with no IV set). - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The size of \p iv is not acceptable for the chosen algorithm, - * or the chosen algorithm does not use an IV. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, - const uint8_t *iv, - size_t iv_length); - -/** Encrypt or decrypt a message fragment in an active cipher operation. - * - * Before calling this function, you must: - * 1. Call either psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup(). - * The choice of setup function determines whether this function - * encrypts or decrypts its input. - * 2. If the algorithm requires an IV, call psa_cipher_generate_iv() - * (recommended when encrypting) or psa_cipher_set_iv(). - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_cipher_abort(). - * - * \param[in,out] operation Active cipher operation. - * \param[in] input Buffer containing the message fragment to - * encrypt or decrypt. - * \param input_length Size of the \p input buffer in bytes. - * \param[out] output Buffer where the output is to be written. - * \param output_size Size of the \p output buffer in bytes. - * \param[out] output_length On success, the number of bytes - * that make up the returned output. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active, with an IV set - * if required for the algorithm). - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p output buffer is too small. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, - const uint8_t *input, - size_t input_length, - uint8_t *output, - size_t output_size, - size_t *output_length); - -/** Finish encrypting or decrypting a message in a cipher operation. - * - * The application must call psa_cipher_encrypt_setup() or - * psa_cipher_decrypt_setup() before calling this function. The choice - * of setup function determines whether this function encrypts or - * decrypts its input. - * - * This function finishes the encryption or decryption of the message - * formed by concatenating the inputs passed to preceding calls to - * psa_cipher_update(). - * - * When this function returns successfuly, the operation becomes inactive. - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_cipher_abort(). - * - * \param[in,out] operation Active cipher operation. - * \param[out] output Buffer where the output is to be written. - * \param output_size Size of the \p output buffer in bytes. - * \param[out] output_length On success, the number of bytes - * that make up the returned output. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The total input size passed to this operation is not valid for - * this particular algorithm. For example, the algorithm is a based - * on block cipher and requires a whole number of blocks, but the - * total input size is not a multiple of the block size. - * \retval #PSA_ERROR_INVALID_PADDING - * This is a decryption operation for an algorithm that includes - * padding, and the ciphertext does not contain valid padding. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active, with an IV set - * if required for the algorithm). - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p output buffer is too small. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, - uint8_t *output, - size_t output_size, - size_t *output_length); - -/** Abort a cipher operation. - * - * Aborting an operation frees all associated resources except for the - * \p operation structure itself. Once aborted, the operation object - * can be reused for another operation by calling - * psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup() again. - * - * You may call this function any time after the operation object has - * been initialized as described in #psa_cipher_operation_t. - * - * In particular, calling psa_cipher_abort() after the operation has been - * terminated by a call to psa_cipher_abort() or psa_cipher_finish() - * is safe and has no effect. - * - * \param[in,out] operation Initialized cipher operation. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation); - -/**@}*/ - -/** \defgroup aead Authenticated encryption with associated data (AEAD) - * @{ - */ - -/** Process an authenticated encryption operation. - * - * \param handle Handle to the key to use for the operation. - * \param alg The AEAD algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * \param[in] nonce Nonce or IV to use. - * \param nonce_length Size of the \p nonce buffer in bytes. - * \param[in] additional_data Additional data that will be authenticated - * but not encrypted. - * \param additional_data_length Size of \p additional_data in bytes. - * \param[in] plaintext Data that will be authenticated and - * encrypted. - * \param plaintext_length Size of \p plaintext in bytes. - * \param[out] ciphertext Output buffer for the authenticated and - * encrypted data. The additional data is not - * part of this output. For algorithms where the - * encrypted data and the authentication tag - * are defined as separate outputs, the - * authentication tag is appended to the - * encrypted data. - * \param ciphertext_size Size of the \p ciphertext buffer in bytes. - * This must be at least - * #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\p alg, - * \p plaintext_length). - * \param[out] ciphertext_length On success, the size of the output - * in the \p ciphertext buffer. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not an AEAD algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * \p ciphertext_size is too small - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_encrypt(psa_key_handle_t handle, - 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 *ciphertext, - size_t ciphertext_size, - size_t *ciphertext_length); - -/** Process an authenticated decryption operation. - * - * \param handle Handle to the key to use for the operation. - * \param alg The AEAD algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * \param[in] nonce Nonce or IV to use. - * \param nonce_length Size of the \p nonce buffer in bytes. - * \param[in] additional_data Additional data that has been authenticated - * but not encrypted. - * \param additional_data_length Size of \p additional_data in bytes. - * \param[in] ciphertext Data that has been authenticated and - * encrypted. For algorithms where the - * encrypted data and the authentication tag - * are defined as separate inputs, the buffer - * must contain the encrypted data followed - * by the authentication tag. - * \param ciphertext_length Size of \p ciphertext in bytes. - * \param[out] plaintext Output buffer for the decrypted data. - * \param plaintext_size Size of the \p plaintext buffer in bytes. - * This must be at least - * #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\p alg, - * \p ciphertext_length). - * \param[out] plaintext_length On success, the size of the output - * in the \p plaintext buffer. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_INVALID_SIGNATURE - * The ciphertext is not authentic. - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not an AEAD algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * \p plaintext_size or \p nonce_length is too small - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_decrypt(psa_key_handle_t handle, - 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 *ciphertext, - size_t ciphertext_length, - uint8_t *plaintext, - size_t plaintext_size, - size_t *plaintext_length); - -/** The type of the state data structure for multipart AEAD operations. - * - * Before calling any function on an AEAD operation object, the application - * must initialize it by any of the following means: - * - Set the structure to all-bits-zero, for example: - * \code - * psa_aead_operation_t operation; - * memset(&operation, 0, sizeof(operation)); - * \endcode - * - Initialize the structure to logical zero values, for example: - * \code - * psa_aead_operation_t operation = {0}; - * \endcode - * - Initialize the structure to the initializer #PSA_AEAD_OPERATION_INIT, - * for example: - * \code - * psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT; - * \endcode - * - Assign the result of the function psa_aead_operation_init() - * to the structure, for example: - * \code - * psa_aead_operation_t operation; - * operation = psa_aead_operation_init(); - * \endcode - * - * This is an implementation-defined \c struct. Applications should not - * make any assumptions about the content of this structure except - * as directed by the documentation of a specific implementation. */ -typedef struct psa_aead_operation_s psa_aead_operation_t; - -/** \def PSA_AEAD_OPERATION_INIT - * - * This macro returns a suitable initializer for an AEAD operation object of - * type #psa_aead_operation_t. - */ -#ifdef __DOXYGEN_ONLY__ -/* This is an example definition for documentation purposes. - * Implementations should define a suitable value in `crypto_struct.h`. - */ -#define PSA_AEAD_OPERATION_INIT {0} -#endif - -/** Return an initial value for an AEAD operation object. - */ -static psa_aead_operation_t psa_aead_operation_init(void); - -/** Set the key for a multipart authenticated encryption operation. - * - * The sequence of operations to encrypt a message with authentication - * is as follows: - * -# Allocate an operation object which will be passed to all the functions - * listed here. - * -# Initialize the operation object with one of the methods described in the - * documentation for #psa_aead_operation_t, e.g. - * #PSA_AEAD_OPERATION_INIT. - * -# Call psa_aead_encrypt_setup() to specify the algorithm and key. - * -# If needed, call psa_aead_set_lengths() to specify the length of the - * inputs to the subsequent calls to psa_aead_update_ad() and - * psa_aead_update(). See the documentation of psa_aead_set_lengths() - * for details. - * -# Call either psa_aead_generate_nonce() or psa_aead_set_nonce() to - * generate or set the nonce. You should use - * psa_aead_generate_nonce() unless the protocol you are implementing - * requires a specific nonce value. - * -# Call psa_aead_update_ad() zero, one or more times, passing a fragment - * of the non-encrypted additional authenticated data each time. - * -# Call psa_aead_update() zero, one or more times, passing a fragment - * of the message to encrypt each time. - * -# Call psa_aead_finish(). - * - * If an error occurs at any step after a call to psa_aead_encrypt_setup(), - * the operation will need to be reset by a call to psa_aead_abort(). The - * application may call psa_aead_abort() at any time after the operation - * has been initialized. - * - * After a successful call to psa_aead_encrypt_setup(), the application must - * eventually terminate the operation. The following events terminate an - * operation: - * - A successful call to psa_aead_finish(). - * - A call to psa_aead_abort(). - * - * \param[in,out] operation The operation object to set up. It must have - * been initialized as per the documentation for - * #psa_aead_operation_t and not yet in use. - * \param handle Handle to the key to use for the operation. - * It must remain valid until the operation - * terminates. - * \param alg The AEAD algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be inactive). - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not an AEAD algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg); - -/** Set the key for a multipart authenticated decryption operation. - * - * The sequence of operations to decrypt a message with authentication - * is as follows: - * -# Allocate an operation object which will be passed to all the functions - * listed here. - * -# Initialize the operation object with one of the methods described in the - * documentation for #psa_aead_operation_t, e.g. - * #PSA_AEAD_OPERATION_INIT. - * -# Call psa_aead_decrypt_setup() to specify the algorithm and key. - * -# If needed, call psa_aead_set_lengths() to specify the length of the - * inputs to the subsequent calls to psa_aead_update_ad() and - * psa_aead_update(). See the documentation of psa_aead_set_lengths() - * for details. - * -# Call psa_aead_set_nonce() with the nonce for the decryption. - * -# Call psa_aead_update_ad() zero, one or more times, passing a fragment - * of the non-encrypted additional authenticated data each time. - * -# Call psa_aead_update() zero, one or more times, passing a fragment - * of the ciphertext to decrypt each time. - * -# Call psa_aead_verify(). - * - * If an error occurs at any step after a call to psa_aead_decrypt_setup(), - * the operation will need to be reset by a call to psa_aead_abort(). The - * application may call psa_aead_abort() at any time after the operation - * has been initialized. - * - * After a successful call to psa_aead_decrypt_setup(), the application must - * eventually terminate the operation. The following events terminate an - * operation: - * - A successful call to psa_aead_verify(). - * - A call to psa_aead_abort(). - * - * \param[in,out] operation The operation object to set up. It must have - * been initialized as per the documentation for - * #psa_aead_operation_t and not yet in use. - * \param handle Handle to the key to use for the operation. - * It must remain valid until the operation - * terminates. - * \param alg The AEAD algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be inactive). - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p handle is not compatible with \p alg. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not an AEAD algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg); - -/** Generate a random nonce for an authenticated encryption operation. - * - * This function generates a random nonce for the authenticated encryption - * operation with an appropriate size for the chosen algorithm, key type - * and key size. - * - * The application must call psa_aead_encrypt_setup() before - * calling this function. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_aead_abort(). - * - * \param[in,out] operation Active AEAD operation. - * \param[out] nonce Buffer where the generated nonce is to be - * written. - * \param nonce_size Size of the \p nonce buffer in bytes. - * \param[out] nonce_length On success, the number of bytes of the - * generated nonce. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be an active aead encrypt - operation, with no nonce set). - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p nonce buffer is too small. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation, - uint8_t *nonce, - size_t nonce_size, - size_t *nonce_length); - -/** Set the nonce for an authenticated encryption or decryption operation. - * - * This function sets the nonce for the authenticated - * encryption or decryption operation. - * - * The application must call psa_aead_encrypt_setup() or - * psa_aead_decrypt_setup() before calling this function. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_aead_abort(). - * - * \note When encrypting, applications should use psa_aead_generate_nonce() - * instead of this function, unless implementing a protocol that requires - * a non-random IV. - * - * \param[in,out] operation Active AEAD operation. - * \param[in] nonce Buffer containing the nonce to use. - * \param nonce_length Size of the nonce in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active, with no nonce - * set). - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The size of \p nonce is not acceptable for the chosen algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation, - const uint8_t *nonce, - size_t nonce_length); - -/** Declare the lengths of the message and additional data for AEAD. - * - * The application must call this function before calling - * psa_aead_update_ad() or psa_aead_update() if the algorithm for - * the operation requires it. If the algorithm does not require it, - * calling this function is optional, but if this function is called - * then the implementation must enforce the lengths. - * - * You may call this function before or after setting the nonce with - * psa_aead_set_nonce() or psa_aead_generate_nonce(). - * - * - For #PSA_ALG_CCM, calling this function is required. - * - For the other AEAD algorithms defined in this specification, calling - * this function is not required. - * - For vendor-defined algorithm, refer to the vendor documentation. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_aead_abort(). - * - * \param[in,out] operation Active AEAD operation. - * \param ad_length Size of the non-encrypted additional - * authenticated data in bytes. - * \param plaintext_length Size of the plaintext to encrypt in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active, and - * psa_aead_update_ad() and psa_aead_update() must not have been - * called yet). - * \retval #PSA_ERROR_INVALID_ARGUMENT - * At least one of the lengths is not acceptable for the chosen - * algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation, - size_t ad_length, - size_t plaintext_length); - -/** Pass additional data to an active AEAD operation. - * - * Additional data is authenticated, but not encrypted. - * - * You may call this function multiple times to pass successive fragments - * of the additional data. You may not call this function after passing - * data to encrypt or decrypt with psa_aead_update(). - * - * Before calling this function, you must: - * 1. Call either psa_aead_encrypt_setup() or psa_aead_decrypt_setup(). - * 2. Set the nonce with psa_aead_generate_nonce() or psa_aead_set_nonce(). - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_aead_abort(). - * - * \warning When decrypting, until psa_aead_verify() has returned #PSA_SUCCESS, - * there is no guarantee that the input is valid. Therefore, until - * you have called psa_aead_verify() and it has returned #PSA_SUCCESS, - * treat the input as untrusted and prepare to undo any action that - * depends on the input if psa_aead_verify() returns an error status. - * - * \param[in,out] operation Active AEAD operation. - * \param[in] input Buffer containing the fragment of - * additional data. - * \param input_length Size of the \p input buffer in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active, have a nonce - * set, have lengths set if required by the algorithm, and - * psa_aead_update() must not have been called yet). - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The total input length overflows the additional data length that - * was previously specified with psa_aead_set_lengths(). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation, - const uint8_t *input, - size_t input_length); - -/** Encrypt or decrypt a message fragment in an active AEAD operation. - * - * Before calling this function, you must: - * 1. Call either psa_aead_encrypt_setup() or psa_aead_decrypt_setup(). - * The choice of setup function determines whether this function - * encrypts or decrypts its input. - * 2. Set the nonce with psa_aead_generate_nonce() or psa_aead_set_nonce(). - * 3. Call psa_aead_update_ad() to pass all the additional data. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_aead_abort(). - * - * \warning When decrypting, until psa_aead_verify() has returned #PSA_SUCCESS, - * there is no guarantee that the input is valid. Therefore, until - * you have called psa_aead_verify() and it has returned #PSA_SUCCESS: - * - Do not use the output in any way other than storing it in a - * confidential location. If you take any action that depends - * on the tentative decrypted data, this action will need to be - * undone if the input turns out not to be valid. Furthermore, - * if an adversary can observe that this action took place - * (for example through timing), they may be able to use this - * fact as an oracle to decrypt any message encrypted with the - * same key. - * - In particular, do not copy the output anywhere but to a - * memory or storage space that you have exclusive access to. - * - * This function does not require the input to be aligned to any - * particular block boundary. If the implementation can only process - * a whole block at a time, it must consume all the input provided, but - * it may delay the end of the corresponding output until a subsequent - * call to psa_aead_update(), psa_aead_finish() or psa_aead_verify() - * provides sufficient input. The amount of data that can be delayed - * in this way is bounded by #PSA_AEAD_UPDATE_OUTPUT_SIZE. - * - * \param[in,out] operation Active AEAD operation. - * \param[in] input Buffer containing the message fragment to - * encrypt or decrypt. - * \param input_length Size of the \p input buffer in bytes. - * \param[out] output Buffer where the output is to be written. - * \param output_size Size of the \p output buffer in bytes. - * This must be at least - * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c alg, - * \p input_length) where \c alg is the - * algorithm that is being calculated. - * \param[out] output_length On success, the number of bytes - * that make up the returned output. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active, have a nonce - * set, and have lengths set if required by the algorithm). - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p output buffer is too small. - * You can determine a sufficient buffer size by calling - * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c alg, \p input_length) - * where \c alg is the algorithm that is being calculated. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The total length of input to psa_aead_update_ad() so far is - * less than the additional data length that was previously - * specified with psa_aead_set_lengths(). - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The total input length overflows the plaintext length that - * was previously specified with psa_aead_set_lengths(). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_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); - -/** Finish encrypting a message in an AEAD operation. - * - * The operation must have been set up with psa_aead_encrypt_setup(). - * - * This function finishes the authentication of the additional data - * formed by concatenating the inputs passed to preceding calls to - * psa_aead_update_ad() with the plaintext formed by concatenating the - * inputs passed to preceding calls to psa_aead_update(). - * - * This function has two output buffers: - * - \p ciphertext contains trailing ciphertext that was buffered from - * preceding calls to psa_aead_update(). - * - \p tag contains the authentication tag. Its length is always - * #PSA_AEAD_TAG_LENGTH(\c alg) where \c alg is the AEAD algorithm - * that the operation performs. - * - * When this function returns successfuly, the operation becomes inactive. - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_aead_abort(). - * - * \param[in,out] operation Active AEAD operation. - * \param[out] ciphertext Buffer where the last part of the ciphertext - * is to be written. - * \param ciphertext_size Size of the \p ciphertext buffer in bytes. - * This must be at least - * #PSA_AEAD_FINISH_OUTPUT_SIZE(\c alg) where - * \c alg is the algorithm that is being - * calculated. - * \param[out] ciphertext_length On success, the number of bytes of - * returned ciphertext. - * \param[out] tag Buffer where the authentication tag is - * to be written. - * \param tag_size Size of the \p tag buffer in bytes. - * This must be at least - * #PSA_AEAD_TAG_LENGTH(\c alg) where \c alg is - * the algorithm that is being calculated. - * \param[out] tag_length On success, the number of bytes - * that make up the returned tag. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be an active encryption - * operation with a nonce set). - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p ciphertext or \p tag buffer is too small. - * You can determine a sufficient buffer size for \p ciphertext by - * calling #PSA_AEAD_FINISH_OUTPUT_SIZE(\c alg) - * where \c alg is the algorithm that is being calculated. - * You can determine a sufficient buffer size for \p tag by - * calling #PSA_AEAD_TAG_LENGTH(\c alg). - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The total length of input to psa_aead_update_ad() so far is - * less than the additional data length that was previously - * specified with psa_aead_set_lengths(). - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The total length of input to psa_aead_update() so far is - * less than the plaintext length that was previously - * specified with psa_aead_set_lengths(). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_finish(psa_aead_operation_t *operation, - uint8_t *ciphertext, - size_t ciphertext_size, - size_t *ciphertext_length, - uint8_t *tag, - size_t tag_size, - size_t *tag_length); - -/** Finish authenticating and decrypting a message in an AEAD operation. - * - * The operation must have been set up with psa_aead_decrypt_setup(). - * - * This function finishes the authenticated decryption of the message - * components: - * - * - The additional data consisting of the concatenation of the inputs - * passed to preceding calls to psa_aead_update_ad(). - * - The ciphertext consisting of the concatenation of the inputs passed to - * preceding calls to psa_aead_update(). - * - The tag passed to this function call. - * - * If the authentication tag is correct, this function outputs any remaining - * plaintext and reports success. If the authentication tag is not correct, - * this function returns #PSA_ERROR_INVALID_SIGNATURE. - * - * When this function returns successfuly, the operation becomes inactive. - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_aead_abort(). - * - * \note Implementations shall make the best effort to ensure that the - * comparison between the actual tag and the expected tag is performed - * in constant time. - * - * \param[in,out] operation Active AEAD operation. - * \param[out] plaintext Buffer where the last part of the plaintext - * is to be written. This is the remaining data - * from previous calls to psa_aead_update() - * that could not be processed until the end - * of the input. - * \param plaintext_size Size of the \p plaintext buffer in bytes. - * This must be at least - * #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c alg) where - * \c alg is the algorithm that is being - * calculated. - * \param[out] plaintext_length On success, the number of bytes of - * returned plaintext. - * \param[in] tag Buffer containing the authentication tag. - * \param tag_length Size of the \p tag buffer in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_SIGNATURE - * The calculations were successful, but the authentication tag is - * not correct. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be an active decryption - * operation with a nonce set). - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p plaintext buffer is too small. - * You can determine a sufficient buffer size for \p plaintext by - * calling #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c alg) - * where \c alg is the algorithm that is being calculated. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The total length of input to psa_aead_update_ad() so far is - * less than the additional data length that was previously - * specified with psa_aead_set_lengths(). - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The total length of input to psa_aead_update() so far is - * less than the plaintext length that was previously - * specified with psa_aead_set_lengths(). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_verify(psa_aead_operation_t *operation, - uint8_t *plaintext, - size_t plaintext_size, - size_t *plaintext_length, - const uint8_t *tag, - size_t tag_length); - -/** Abort an AEAD operation. - * - * Aborting an operation frees all associated resources except for the - * \p operation structure itself. Once aborted, the operation object - * can be reused for another operation by calling - * psa_aead_encrypt_setup() or psa_aead_decrypt_setup() again. - * - * You may call this function any time after the operation object has - * been initialized as described in #psa_aead_operation_t. - * - * In particular, calling psa_aead_abort() after the operation has been - * terminated by a call to psa_aead_abort(), psa_aead_finish() or - * psa_aead_verify() is safe and has no effect. - * - * \param[in,out] operation Initialized AEAD operation. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_aead_abort(psa_aead_operation_t *operation); - -/**@}*/ - -/** \defgroup asymmetric Asymmetric cryptography - * @{ - */ - -/** - * \brief Sign a hash or short message with a private key. - * - * Note that to perform a hash-and-sign signature algorithm, you must - * first calculate the hash by calling psa_hash_setup(), psa_hash_update() - * and psa_hash_finish(). Then pass the resulting hash as the \p hash - * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) - * to determine the hash algorithm to use. - * - * \param handle Handle to the key to use for the operation. - * It must be an asymmetric key pair. - * \param alg A signature algorithm that is compatible with - * the type of \p handle. - * \param[in] hash The hash or message to sign. - * \param hash_length Size of the \p hash buffer in bytes. - * \param[out] signature Buffer where the signature is to be written. - * \param signature_size Size of the \p signature buffer in bytes. - * \param[out] signature_length On success, the number of bytes - * that make up the returned signature value. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p signature buffer is too small. You can - * determine a sufficient buffer size by calling - * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) - * where \c key_type and \c key_bits are the type and bit-size - * respectively of \p handle. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_sign_hash(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *hash, - size_t hash_length, - uint8_t *signature, - size_t signature_size, - size_t *signature_length); - -/** - * \brief Verify the signature a hash or short message using a public key. - * - * Note that to perform a hash-and-sign signature algorithm, you must - * first calculate the hash by calling psa_hash_setup(), psa_hash_update() - * and psa_hash_finish(). Then pass the resulting hash as the \p hash - * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) - * to determine the hash algorithm to use. - * - * \param handle Handle to the key to use for the operation. - * It must be a public key or an asymmetric key pair. - * \param alg A signature algorithm that is compatible with - * the type of \p handle. - * \param[in] hash The hash or message whose signature is to be - * verified. - * \param hash_length Size of the \p hash buffer in bytes. - * \param[in] signature Buffer containing the signature to verify. - * \param signature_length Size of the \p signature buffer in bytes. - * - * \retval #PSA_SUCCESS - * The signature is valid. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_SIGNATURE - * The calculation was perfomed successfully, but the passed - * signature is not a valid signature. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_verify_hash(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *hash, - size_t hash_length, - const uint8_t *signature, - size_t signature_length); - -/** - * \brief Encrypt a short message with a public key. - * - * \param handle Handle to the key to use for the operation. - * It must be a public key or an asymmetric - * key pair. - * \param alg An asymmetric encryption algorithm that is - * compatible with the type of \p handle. - * \param[in] input The message to encrypt. - * \param input_length Size of the \p input buffer in bytes. - * \param[in] salt A salt or label, if supported by the - * encryption algorithm. - * If the algorithm does not support a - * salt, pass \c NULL. - * If the algorithm supports an optional - * salt and you do not want to pass a salt, - * pass \c NULL. - * - * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is - * supported. - * \param salt_length Size of the \p salt buffer in bytes. - * If \p salt is \c NULL, pass 0. - * \param[out] output Buffer where the encrypted message is to - * be written. - * \param output_size Size of the \p output buffer in bytes. - * \param[out] output_length On success, the number of bytes - * that make up the returned output. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p output buffer is too small. You can - * determine a sufficient buffer size by calling - * #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) - * where \c key_type and \c key_bits are the type and bit-size - * respectively of \p handle. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_asymmetric_encrypt(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - const uint8_t *salt, - size_t salt_length, - uint8_t *output, - size_t output_size, - size_t *output_length); - -/** - * \brief Decrypt a short message with a private key. - * - * \param handle Handle to the key to use for the operation. - * It must be an asymmetric key pair. - * \param alg An asymmetric encryption algorithm that is - * compatible with the type of \p handle. - * \param[in] input The message to decrypt. - * \param input_length Size of the \p input buffer in bytes. - * \param[in] salt A salt or label, if supported by the - * encryption algorithm. - * If the algorithm does not support a - * salt, pass \c NULL. - * If the algorithm supports an optional - * salt and you do not want to pass a salt, - * pass \c NULL. - * - * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is - * supported. - * \param salt_length Size of the \p salt buffer in bytes. - * If \p salt is \c NULL, pass 0. - * \param[out] output Buffer where the decrypted message is to - * be written. - * \param output_size Size of the \c output buffer in bytes. - * \param[out] output_length On success, the number of bytes - * that make up the returned output. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p output buffer is too small. You can - * determine a sufficient buffer size by calling - * #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) - * where \c key_type and \c key_bits are the type and bit-size - * respectively of \p handle. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY - * \retval #PSA_ERROR_INVALID_PADDING - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_asymmetric_decrypt(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - const uint8_t *salt, - size_t salt_length, - uint8_t *output, - size_t output_size, - size_t *output_length); - -/**@}*/ - -/** \defgroup key_derivation Key derivation and pseudorandom generation - * @{ - */ - -/** The type of the state data structure for key derivation operations. - * - * Before calling any function on a key derivation operation object, the - * application must initialize it by any of the following means: - * - Set the structure to all-bits-zero, for example: - * \code - * psa_key_derivation_operation_t operation; - * memset(&operation, 0, sizeof(operation)); - * \endcode - * - Initialize the structure to logical zero values, for example: - * \code - * psa_key_derivation_operation_t operation = {0}; - * \endcode - * - Initialize the structure to the initializer #PSA_KEY_DERIVATION_OPERATION_INIT, - * for example: - * \code - * psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT; - * \endcode - * - Assign the result of the function psa_key_derivation_operation_init() - * to the structure, for example: - * \code - * psa_key_derivation_operation_t operation; - * operation = psa_key_derivation_operation_init(); - * \endcode - * - * This is an implementation-defined \c struct. Applications should not - * make any assumptions about the content of this structure except - * as directed by the documentation of a specific implementation. - */ -typedef struct psa_key_derivation_s psa_key_derivation_operation_t; - -/** \def PSA_KEY_DERIVATION_OPERATION_INIT - * - * This macro returns a suitable initializer for a key derivation operation - * object of type #psa_key_derivation_operation_t. - */ -#ifdef __DOXYGEN_ONLY__ -/* This is an example definition for documentation purposes. - * Implementations should define a suitable value in `crypto_struct.h`. - */ -#define PSA_KEY_DERIVATION_OPERATION_INIT {0} -#endif - -/** Return an initial value for a key derivation operation object. - */ -static psa_key_derivation_operation_t psa_key_derivation_operation_init(void); - -/** Set up a key derivation operation. - * - * A key derivation algorithm takes some inputs and uses them to generate - * a byte stream in a deterministic way. - * This byte stream can be used to produce keys and other - * cryptographic material. - * - * To derive a key: - * -# Start with an initialized object of type #psa_key_derivation_operation_t. - * -# Call psa_key_derivation_setup() to select the algorithm. - * -# Provide the inputs for the key derivation by calling - * psa_key_derivation_input_bytes() or psa_key_derivation_input_key() - * as appropriate. Which inputs are needed, in what order, and whether - * they may be keys and if so of what type depends on the algorithm. - * -# Optionally set the operation's maximum capacity with - * psa_key_derivation_set_capacity(). You may do this before, in the middle - * of or after providing inputs. For some algorithms, this step is mandatory - * because the output depends on the maximum capacity. - * -# To derive a key, call psa_key_derivation_output_key(). - * To derive a byte string for a different purpose, call - * psa_key_derivation_output_bytes(). - * Successive calls to these functions use successive output bytes - * calculated by the key derivation algorithm. - * -# Clean up the key derivation operation object with - * psa_key_derivation_abort(). - * - * If this function returns an error, the key derivation operation object is - * not changed. - * - * If an error occurs at any step after a call to psa_key_derivation_setup(), - * the operation will need to be reset by a call to psa_key_derivation_abort(). - * - * Implementations must reject an attempt to derive a key of size 0. - * - * \param[in,out] operation The key derivation operation object - * to set up. It must - * have been initialized but not set up yet. - * \param alg The key derivation algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_KEY_DERIVATION(\p alg) is true). - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \c alg is not a key derivation algorithm. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \c alg is not supported or is not a key derivation algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be inactive). - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_key_derivation_setup( - psa_key_derivation_operation_t *operation, - psa_algorithm_t alg); - -/** Retrieve the current capacity of a key derivation operation. - * - * The capacity of a key derivation is the maximum number of bytes that it can - * return. When you get *N* bytes of output from a key derivation operation, - * this reduces its capacity by *N*. - * - * \param[in] operation The operation to query. - * \param[out] capacity On success, the capacity of the operation. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active). - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_key_derivation_get_capacity( - const psa_key_derivation_operation_t *operation, - size_t *capacity); - -/** Set the maximum capacity of a key derivation operation. - * - * The capacity of a key derivation operation is the maximum number of bytes - * that the key derivation operation can return from this point onwards. - * - * \param[in,out] operation The key derivation operation object to modify. - * \param capacity The new capacity of the operation. - * It must be less or equal to the operation's - * current capacity. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p capacity is larger than the operation's current capacity. - * In this case, the operation object remains valid and its capacity - * remains unchanged. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active). - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_key_derivation_set_capacity( - psa_key_derivation_operation_t *operation, - size_t capacity); - -/** Use the maximum possible capacity for a key derivation operation. - * - * Use this value as the capacity argument when setting up a key derivation - * to indicate that the operation should have the maximum possible capacity. - * The value of the maximum possible capacity depends on the key derivation - * algorithm. - */ -#define PSA_KEY_DERIVATION_UNLIMITED_CAPACITY ((size_t)(-1)) - -/** Provide an input for key derivation or key agreement. - * - * Which inputs are required and in what order depends on the algorithm. - * Refer to the documentation of each key derivation or key agreement - * algorithm for information. - * - * This function passes direct inputs, which is usually correct for - * non-secret inputs. To pass a secret input, which should be in a key - * object, call psa_key_derivation_input_key() instead of this function. - * Refer to the documentation of individual step types - * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t) - * for more information. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_key_derivation_abort(). - * - * \param[in,out] operation The key derivation operation object to use. - * It must have been set up with - * psa_key_derivation_setup() and must not - * have produced any output yet. - * \param step Which step the input data is for. - * \param[in] data Input data to use. - * \param data_length Size of the \p data buffer in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \c step is not compatible with the operation's algorithm. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \c step does not allow direct inputs. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid for this input \p step. - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_key_derivation_input_bytes( - psa_key_derivation_operation_t *operation, - psa_key_derivation_step_t step, - const uint8_t *data, - size_t data_length); - -/** Provide an input for key derivation in the form of a key. - * - * Which inputs are required and in what order depends on the algorithm. - * Refer to the documentation of each key derivation or key agreement - * algorithm for information. - * - * This function obtains input from a key object, which is usually correct for - * secret inputs or for non-secret personalization strings kept in the key - * store. To pass a non-secret parameter which is not in the key store, - * call psa_key_derivation_input_bytes() instead of this function. - * Refer to the documentation of individual step types - * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t) - * for more information. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_key_derivation_abort(). - * - * \param[in,out] operation The key derivation operation object to use. - * It must have been set up with - * psa_key_derivation_setup() and must not - * have produced any output yet. - * \param step Which step the input data is for. - * \param handle Handle to the key. It must have an - * appropriate type for \p step and must - * allow the usage #PSA_KEY_USAGE_DERIVE. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \c step is not compatible with the operation's algorithm. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \c step does not allow key inputs of the given type - * or does not allow key inputs at all. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid for this input \p step. - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_key_derivation_input_key( - psa_key_derivation_operation_t *operation, - psa_key_derivation_step_t step, - psa_key_handle_t handle); - -/** Perform a key agreement and use the shared secret as input to a key - * derivation. - * - * A key agreement algorithm takes two inputs: a private key \p private_key - * a public key \p peer_key. - * The result of this function is passed as input to a key derivation. - * The output of this key derivation can be extracted by reading from the - * resulting operation to produce keys and other cryptographic material. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_key_derivation_abort(). - * - * \param[in,out] operation The key derivation operation object to use. - * It must have been set up with - * psa_key_derivation_setup() with a - * key agreement and derivation algorithm - * \c alg (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_KEY_AGREEMENT(\c alg) is true - * and #PSA_ALG_IS_RAW_KEY_AGREEMENT(\c alg) - * is false). - * The operation must be ready for an - * input of the type given by \p step. - * \param step Which step the input data is for. - * \param private_key Handle to the private key to use. - * \param[in] peer_key Public key of the peer. The peer key must be in the - * same format that psa_import_key() accepts for the - * public key type corresponding to the type of - * private_key. That is, this function performs the - * equivalent of - * #psa_import_key(..., - * `peer_key`, `peer_key_length`) where - * with key attributes indicating the public key - * type corresponding to the type of `private_key`. - * For example, for EC keys, this means that peer_key - * is interpreted as a point on the curve that the - * private key is on. The standard formats for public - * keys are documented in the documentation of - * psa_export_public_key(). - * \param peer_key_length Size of \p peer_key in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid for this key agreement \p step. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \c private_key is not compatible with \c alg, - * or \p peer_key is not valid for \c alg or not compatible with - * \c private_key. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \c alg is not supported or is not a key derivation algorithm. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \c step does not allow an input resulting from a key agreement. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_key_derivation_key_agreement( - psa_key_derivation_operation_t *operation, - psa_key_derivation_step_t step, - psa_key_handle_t private_key, - const uint8_t *peer_key, - size_t peer_key_length); - -/** Read some data from a key derivation operation. - * - * This function calculates output bytes from a key derivation algorithm and - * return those bytes. - * If you view the key derivation's output as a stream of bytes, this - * function destructively reads the requested number of bytes from the - * stream. - * The operation's capacity decreases by the number of bytes read. - * - * If this function returns an error status other than - * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error - * state and must be aborted by calling psa_key_derivation_abort(). - * - * \param[in,out] operation The key derivation operation object to read from. - * \param[out] output Buffer where the output will be written. - * \param output_length Number of bytes to output. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INSUFFICIENT_DATA - * The operation's capacity was less than - * \p output_length bytes. Note that in this case, - * no output is written to the output buffer. - * The operation's capacity is set to 0, thus - * subsequent calls to this function will not - * succeed, even with a smaller output buffer. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active and completed - * all required input steps). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_key_derivation_output_bytes( - psa_key_derivation_operation_t *operation, - uint8_t *output, - size_t output_length); - -/** Derive a key from an ongoing key derivation operation. - * - * This function calculates output bytes from a key derivation algorithm - * and uses those bytes to generate a key deterministically. - * The key's location, usage policy, type and size are taken from - * \p attributes. - * - * If you view the key derivation's output as a stream of bytes, this - * function destructively reads as many bytes as required from the - * stream. - * The operation's capacity decreases by the number of bytes read. - * - * If this function returns an error status other than - * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error - * state and must be aborted by calling psa_key_derivation_abort(). - * - * How much output is produced and consumed from the operation, and how - * the key is derived, depends on the key type: - * - * - For key types for which the key is an arbitrary sequence of bytes - * of a given size, this function is functionally equivalent to - * calling #psa_key_derivation_output_bytes - * and passing the resulting output to #psa_import_key. - * However, this function has a security benefit: - * if the implementation provides an isolation boundary then - * the key material is not exposed outside the isolation boundary. - * As a consequence, for these key types, this function always consumes - * exactly (\p bits / 8) bytes from the operation. - * The following key types defined in this specification follow this scheme: - * - * - #PSA_KEY_TYPE_AES; - * - #PSA_KEY_TYPE_ARC4; - * - #PSA_KEY_TYPE_CAMELLIA; - * - #PSA_KEY_TYPE_DERIVE; - * - #PSA_KEY_TYPE_HMAC. - * - * - For ECC keys on a Montgomery elliptic curve - * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a - * Montgomery curve), this function always draws a byte string whose - * length is determined by the curve, and sets the mandatory bits - * accordingly. That is: - * - * - #PSA_ECC_CURVE_CURVE25519: draw a 32-byte string - * and process it as specified in RFC 7748 §5. - * - #PSA_ECC_CURVE_CURVE448: draw a 56-byte string - * and process it as specified in RFC 7748 §5. - * - * - For key types for which the key is represented by a single sequence of - * \p bits bits with constraints as to which bit sequences are acceptable, - * this function draws a byte string of length (\p bits / 8) bytes rounded - * up to the nearest whole number of bytes. If the resulting byte string - * is acceptable, it becomes the key, otherwise the drawn bytes are discarded. - * This process is repeated until an acceptable byte string is drawn. - * The byte string drawn from the operation is interpreted as specified - * for the output produced by psa_export_key(). - * The following key types defined in this specification follow this scheme: - * - * - #PSA_KEY_TYPE_DES. - * Force-set the parity bits, but discard forbidden weak keys. - * For 2-key and 3-key triple-DES, the three keys are generated - * successively (for example, for 3-key triple-DES, - * if the first 8 bytes specify a weak key and the next 8 bytes do not, - * discard the first 8 bytes, use the next 8 bytes as the first key, - * and continue reading output from the operation to derive the other - * two keys). - * - Finite-field Diffie-Hellman keys (#PSA_KEY_TYPE_DH_KEY_PAIR(\c group) - * where \c group designates any Diffie-Hellman group) and - * ECC keys on a Weierstrass elliptic curve - * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a - * Weierstrass curve). - * For these key types, interpret the byte string as integer - * in big-endian order. Discard it if it is not in the range - * [0, *N* - 2] where *N* is the boundary of the private key domain - * (the prime *p* for Diffie-Hellman, the subprime *q* for DSA, - * or the order of the curve's base point for ECC). - * Add 1 to the resulting integer and use this as the private key *x*. - * This method allows compliance to NIST standards, specifically - * the methods titled "key-pair generation by testing candidates" - * in NIST SP 800-56A §5.6.1.1.4 for Diffie-Hellman, - * in FIPS 186-4 §B.1.2 for DSA, and - * in NIST SP 800-56A §5.6.1.2.2 or - * FIPS 186-4 §B.4.2 for elliptic curve keys. - * - * - For other key types, including #PSA_KEY_TYPE_RSA_KEY_PAIR, - * the way in which the operation output is consumed is - * implementation-defined. - * - * In all cases, the data that is read is discarded from the operation. - * The operation's capacity is decreased by the number of bytes read. - * - * For algorithms that take an input step #PSA_KEY_DERIVATION_INPUT_SECRET, - * the input to that step must be provided with psa_key_derivation_input_key(). - * Future versions of this specification may include additional restrictions - * on the derived key based on the attributes and strength of the secret key. - * - * \param[in] attributes The attributes for the new key. - * \param[in,out] operation The key derivation operation object to read from. - * \param[out] handle On success, a handle to the newly created key. - * \c 0 on failure. - * - * \retval #PSA_SUCCESS - * Success. - * If the key is persistent, the key material and the key's metadata - * have been saved to persistent storage. - * \retval #PSA_ERROR_ALREADY_EXISTS - * This is an attempt to create a persistent key, and there is - * already a persistent key with the given identifier. - * \retval #PSA_ERROR_INSUFFICIENT_DATA - * There was not enough data to create the desired key. - * Note that in this case, no output is written to the output buffer. - * The operation's capacity is set to 0, thus subsequent calls to - * this function will not succeed, even with a smaller output buffer. - * \retval #PSA_ERROR_NOT_SUPPORTED - * The key type or key size is not supported, either by the - * implementation in general or in this particular location. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The provided key attributes are not valid for the operation. - * \retval #PSA_ERROR_NOT_PERMITTED - * The #PSA_KEY_DERIVATION_INPUT_SECRET input was not provided through - * a key. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active and completed - * all required input steps). - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_INSUFFICIENT_STORAGE - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_key_derivation_output_key( - const psa_key_attributes_t *attributes, - psa_key_derivation_operation_t *operation, - psa_key_handle_t *handle); - -/** Abort a key derivation operation. - * - * Aborting an operation frees all associated resources except for the \c - * operation structure itself. Once aborted, the operation object can be reused - * for another operation by calling psa_key_derivation_setup() again. - * - * This function may be called at any time after the operation - * object has been initialized as described in #psa_key_derivation_operation_t. - * - * In particular, it is valid to call psa_key_derivation_abort() twice, or to - * call psa_key_derivation_abort() on an operation that has not been set up. - * - * \param[in,out] operation The operation to abort. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_key_derivation_abort( - psa_key_derivation_operation_t *operation); - -/** Perform a key agreement and return the raw shared secret. - * - * \warning The raw result of a key agreement algorithm such as finite-field - * Diffie-Hellman or elliptic curve Diffie-Hellman has biases and should - * not be used directly as key material. It should instead be passed as - * input to a key derivation algorithm. To chain a key agreement with - * a key derivation, use psa_key_derivation_key_agreement() and other - * functions from the key derivation interface. - * - * \param alg The key agreement algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_RAW_KEY_AGREEMENT(\p alg) - * is true). - * \param private_key Handle to the private key to use. - * \param[in] peer_key Public key of the peer. It must be - * in the same format that psa_import_key() - * accepts. The standard formats for public - * keys are documented in the documentation - * of psa_export_public_key(). - * \param peer_key_length Size of \p peer_key in bytes. - * \param[out] output Buffer where the decrypted message is to - * be written. - * \param output_size Size of the \c output buffer in bytes. - * \param[out] output_length On success, the number of bytes - * that make up the returned output. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p alg is not a key agreement algorithm - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p private_key is not compatible with \p alg, - * or \p peer_key is not valid for \p alg or not compatible with - * \p private_key. - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * \p output_size is too small - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not a supported key agreement algorithm. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, - psa_key_handle_t private_key, - const uint8_t *peer_key, - size_t peer_key_length, - uint8_t *output, - size_t output_size, - size_t *output_length); - -/**@}*/ - -/** \defgroup random Random generation - * @{ - */ - -/** - * \brief Generate random bytes. - * - * \warning This function **can** fail! Callers MUST check the return status - * and MUST NOT use the content of the output buffer if the return - * status is not #PSA_SUCCESS. - * - * \note To generate a key, use psa_generate_key() instead. - * - * \param[out] output Output buffer for the generated data. - * \param output_size Number of bytes to generate and output. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_generate_random(uint8_t *output, - size_t output_size); - -/** - * \brief Generate a key or key pair. - * - * The key is generated randomly. - * Its location, usage policy, type and size are taken from \p attributes. - * - * Implementations must reject an attempt to generate a key of size 0. - * - * The following type-specific considerations apply: - * - For RSA keys (#PSA_KEY_TYPE_RSA_KEY_PAIR), - * the public exponent is 65537. - * The modulus is a product of two probabilistic primes - * between 2^{n-1} and 2^n where n is the bit size specified in the - * attributes. - * - * \param[in] attributes The attributes for the new key. - * \param[out] handle On success, a handle to the newly created key. - * \c 0 on failure. - * - * \retval #PSA_SUCCESS - * Success. - * If the key is persistent, the key material and the key's metadata - * have been saved to persistent storage. - * \retval #PSA_ERROR_ALREADY_EXISTS - * This is an attempt to create a persistent key, and there is - * already a persistent key with the given identifier. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_INSUFFICIENT_STORAGE - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, - psa_key_handle_t *handle); - -/**@}*/ - -#ifdef __cplusplus -} -#endif - -/* The file "crypto_sizes.h" contains definitions for size calculation - * macros whose definitions are implementation-specific. */ -#include "psa/crypto_sizes.h" - -/* The file "crypto_client_struct.h" contains definitions for structures - * whose definitions differ in the client view and the PSA server - * implementation in TF-M. */ -#include "psa/crypto_client_struct.h" - - -/* The file "crypto_struct.h" contains definitions for - * implementation-specific structs that are declared above. */ -#include "psa/crypto_struct.h" - -/* The file "crypto_extra.h" contains vendor-specific definitions. This - * can include vendor-defined algorithms, extra functions, etc. */ -#include "psa/crypto_extra.h" - -#endif /* PSA_CRYPTO_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_client_struct.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_client_struct.h deleted file mode 100644 index 1d919b0..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_client_struct.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ -/** - * \file psa/crypto_client_struct.h - * - * \brief PSA cryptography client key attribute definitions - * - * \note This file may not be included directly. Applications must - * include psa/crypto.h. - * - * This file contains the definitions of some data structures with - * PSA crypto client specific definitions. This is for implementations - * with isolation between the Client applications and the Crypto - * Server module, it is expected that the front-end and the back-end - * would have different versions of the data structure. - */ -#ifndef PSA_CRYPTO_CLIENT_STRUCT_H -#define PSA_CRYPTO_CLIENT_STRUCT_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* This is the client view of the `key_attributes` structure. Only - * fields which need to be set by the PSA crypto client are present. - * The PSA crypto service will maintain a different version of the - * data structure internally. */ -struct psa_client_key_attributes_s -{ - uint32_t type; - uint32_t lifetime; - uint32_t id; - uint32_t alg; - uint32_t alg2; - uint32_t usage; - uint16_t bits; -}; - -#define PSA_CLIENT_KEY_ATTRIBUTES_INIT {0, 0, 0, 0, 0, 0, 0} - -#ifdef __cplusplus -} -#endif - -#endif /* PSA_CRYPTO_CLIENT_STRUCT_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_compat.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_compat.h deleted file mode 100644 index 518008b..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_compat.h +++ /dev/null @@ -1,111 +0,0 @@ -/** - * \file psa/crypto_compat.h - * - * \brief PSA cryptography module: Backward compatibility aliases - * - * This header declares alternative names for macro and functions. - * New application code should not use these names. - * These names may be removed in a future version of Mbed Crypto. - * - * \note This file may not be included directly. Applications must - * include psa/crypto.h. - */ -/* - * Copyright (C) 2019-2020, ARM Limited, 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. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#ifndef PSA_CRYPTO_COMPAT_H -#define PSA_CRYPTO_COMPAT_H - -#ifdef __cplusplus -extern "C" { -#endif - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) - -/* - * Mechanism for declaring deprecated values - */ -#if defined(MBEDTLS_DEPRECATED_WARNING) && !defined(MBEDTLS_PSA_DEPRECATED) -#define MBEDTLS_PSA_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_PSA_DEPRECATED -#endif - -typedef MBEDTLS_PSA_DEPRECATED size_t mbedtls_deprecated_size_t; -typedef MBEDTLS_PSA_DEPRECATED psa_status_t mbedtls_deprecated_psa_status_t; -typedef MBEDTLS_PSA_DEPRECATED psa_key_usage_t mbedtls_deprecated_psa_key_usage_t; - -#define MBEDTLS_DEPRECATED_CONSTANT( type, value ) \ - ( (mbedtls_deprecated_##type) ( value ) ) - -/* - * Deprecated PSA Crypto error code definitions (PSA Crypto API <= 1.0 beta2) - */ -#define PSA_ERROR_UNKNOWN_ERROR \ - MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_GENERIC_ERROR ) -#define PSA_ERROR_OCCUPIED_SLOT \ - MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_ALREADY_EXISTS ) -#define PSA_ERROR_EMPTY_SLOT \ - MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_DOES_NOT_EXIST ) -#define PSA_ERROR_INSUFFICIENT_CAPACITY \ - MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_INSUFFICIENT_DATA ) -#define PSA_ERROR_TAMPERING_DETECTED \ - MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_CORRUPTION_DETECTED ) - -/* - * Deprecated PSA Crypto numerical encodings (PSA Crypto API <= 1.0 beta3) - */ -#define PSA_KEY_USAGE_SIGN \ - MBEDTLS_DEPRECATED_CONSTANT( psa_key_usage_t, PSA_KEY_USAGE_SIGN_HASH ) -#define PSA_KEY_USAGE_VERIFY \ - MBEDTLS_DEPRECATED_CONSTANT( psa_key_usage_t, PSA_KEY_USAGE_VERIFY_HASH ) - -/* - * Deprecated PSA Crypto size calculation macros (PSA Crypto API <= 1.0 beta3) - */ -#define PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE \ - MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_SIGNATURE_MAX_SIZE ) -#define PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE( key_type, key_bits, alg ) \ - MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_SIGN_OUTPUT_SIZE( key_type, key_bits, alg ) ) - -/* - * Deprecated PSA Crypto function names (PSA Crypto API <= 1.0 beta3) - */ -MBEDTLS_PSA_DEPRECATED psa_status_t psa_asymmetric_sign( psa_key_handle_t key, - psa_algorithm_t alg, - const uint8_t *hash, - size_t hash_length, - uint8_t *signature, - size_t signature_size, - size_t *signature_length ); - -MBEDTLS_PSA_DEPRECATED psa_status_t psa_asymmetric_verify( psa_key_handle_t key, - psa_algorithm_t alg, - const uint8_t *hash, - size_t hash_length, - const uint8_t *signature, - size_t signature_length ); - -#endif /* MBEDTLS_DEPRECATED_REMOVED */ - -#ifdef __cplusplus -} -#endif - -#endif /* PSA_CRYPTO_COMPAT_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_extra.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_extra.h deleted file mode 100644 index d658b76..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_extra.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2018-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ -/** - * \file psa/crypto_extra.h - * - * \brief PSA cryptography module: vendor extensions - * - * \note This file may not be included directly. Applications must - * include psa/crypto.h. - * - * This file is reserved for vendor-specific definitions. - */ - -#ifndef PSA_CRYPTO_EXTRA_H -#define PSA_CRYPTO_EXTRA_H - -#include "psa/crypto_compat.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** \addtogroup crypto_types - * @{ - */ - -/** DSA public key. - * - * The import and export format is the - * representation of the public key `y = g^x mod p` as a big-endian byte - * string. The length of the byte string is the length of the base prime `p` - * in bytes. - */ -#define PSA_KEY_TYPE_DSA_PUBLIC_KEY ((psa_key_type_t)0x60020000) - -/** DSA key pair (private and public key). - * - * The import and export format is the - * representation of the private key `x` as a big-endian byte string. The - * length of the byte string is the private key size in bytes (leading zeroes - * are not stripped). - * - * Determinstic DSA key derivation with psa_generate_derived_key follows - * FIPS 186-4 §B.1.2: interpret the byte string as integer - * in big-endian order. Discard it if it is not in the range - * [0, *N* - 2] where *N* is the boundary of the private key domain - * (the prime *p* for Diffie-Hellman, the subprime *q* for DSA, - * or the order of the curve's base point for ECC). - * Add 1 to the resulting integer and use this as the private key *x*. - * - */ -#define PSA_KEY_TYPE_DSA_KEY_PAIR ((psa_key_type_t)0x70020000) - -/**@}*/ - -/** \brief Declare the enrollment algorithm for a key. - * - * An operation on a key may indifferently use the algorithm set with - * psa_set_key_algorithm() or with this function. - * - * \param[out] attributes The attribute structure to write to. - * \param alg2 A second algorithm that the key may be used - * for, in addition to the algorithm set with - * psa_set_key_algorithm(). - * - * \warning Setting an enrollment algorithm is not recommended, because - * using the same key with different algorithms can allow some - * attacks based on arithmetic relations between different - * computations made with the same key, or can escalate harmless - * side channels into exploitable ones. Use this function only - * if it is necessary to support a protocol for which it has been - * verified that the usage of the key with multiple algorithms - * is safe. - */ -static inline void psa_set_key_enrollment_algorithm( - psa_key_attributes_t *attributes, - psa_algorithm_t alg2) -{ - attributes->alg2 = alg2; -} - -/** Retrieve the enrollment algorithm policy from key attributes. - * - * \param[in] attributes The key attribute structure to query. - * - * \return The enrollment algorithm stored in the attribute structure. - */ -static inline psa_algorithm_t psa_get_key_enrollment_algorithm( - const psa_key_attributes_t *attributes) -{ - return attributes->alg2; -} - -#ifdef __cplusplus -} -#endif - -#endif /* PSA_CRYPTO_EXTRA_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_platform.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_platform.h deleted file mode 100644 index c3120e4..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_platform.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2018-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ -/** - * \file psa/crypto_platform.h - * - * \brief PSA cryptography module: Mbed TLS platform definitions - * - * \note This file may not be included directly. Applications must - * include psa/crypto.h. - * - * This file contains platform-dependent type definitions. - * - * In implementations with isolation between the application and the - * cryptography module, implementers should take care to ensure that - * the definitions that are exposed to applications match what the - * module implements. - */ - -#ifndef PSA_CRYPTO_PLATFORM_H -#define PSA_CRYPTO_PLATFORM_H - -/* PSA requires several types which C99 provides in stdint.h. */ -#include - -/* Integral type representing a key handle. */ -typedef uint16_t psa_key_handle_t; - -/* This implementation distinguishes *application key identifiers*, which - * are the key identifiers specified by the application, from - * *key file identifiers*, which are the key identifiers that the library - * sees internally. The two types can be different if there is a remote - * call layer between the application and the library which supports - * multiple client applications that do not have access to each others' - * keys. The point of having different types is that the key file - * identifier may encode not only the key identifier specified by the - * application, but also the the identity of the application. - * - * Note that this is an internal concept of the library and the remote - * call layer. The application itself never sees anything other than - * #psa_app_key_id_t with its standard definition. - */ - -/* The application key identifier is always what the application sees as - * #psa_key_id_t. */ -typedef uint32_t psa_app_key_id_t; - -#endif /* PSA_CRYPTO_PLATFORM_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_sizes.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_sizes.h deleted file mode 100644 index 4f67501..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_sizes.h +++ /dev/null @@ -1,650 +0,0 @@ -/* - * Copyright (c) 2018-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ -/** - * \file psa/crypto_sizes.h - * - * \brief PSA cryptography module: Mbed TLS buffer size macros - * - * \note This file may not be included directly. Applications must - * include psa/crypto.h. - * - * This file contains the definitions of macros that are useful to - * compute buffer sizes. The signatures and semantics of these macros - * are standardized, but the definitions are not, because they depend on - * the available algorithms and, in some cases, on permitted tolerances - * on buffer sizes. - * - * In implementations with isolation between the application and the - * cryptography module, implementers should take care to ensure that - * the definitions that are exposed to applications match what the - * module implements. - * - * Macros that compute sizes whose values do not depend on the - * implementation are in crypto.h. - */ - -#ifndef PSA_CRYPTO_SIZES_H -#define PSA_CRYPTO_SIZES_H - -#define PSA_BITS_TO_BYTES(bits) (((bits) + 7) / 8) -#define PSA_BYTES_TO_BITS(bytes) ((bytes) * 8) - -#define PSA_ROUND_UP_TO_MULTIPLE(block_size, length) \ - (((length) + (block_size) - 1) / (block_size) * (block_size)) - -/** The size of the output of psa_hash_finish(), in bytes. - * - * This is also the hash size that psa_hash_verify() expects. - * - * \param alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p alg) is true), or an HMAC algorithm - * (#PSA_ALG_HMAC(\c hash_alg) where \c hash_alg is a - * hash algorithm). - * - * \return The hash size for the specified hash algorithm. - * If the hash algorithm is not recognized, return 0. - * An implementation may return either 0 or the correct size - * for a hash algorithm that it recognizes, but does not support. - */ -#define PSA_HASH_SIZE(alg) \ - ( \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD2 ? 16 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD4 ? 16 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 16 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 20 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 20 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_224 ? 28 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_256 ? 32 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_384 ? 48 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512 ? 64 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 28 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 32 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 28 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 32 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 48 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 64 : \ - 0) - -/** \def PSA_HASH_MAX_SIZE - * - * Maximum size of a hash. - * - * This macro must expand to a compile-time constant integer. This value - * should be the maximum size of a hash supported by the implementation, - * in bytes, and must be no smaller than this maximum. - */ -/* Note: for HMAC-SHA-3, the block size is 144 bytes for HMAC-SHA3-226, - * 136 bytes for HMAC-SHA3-256, 104 bytes for SHA3-384, 72 bytes for - * HMAC-SHA3-512. */ -#define PSA_HASH_MAX_SIZE 64 -#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 128 - -/** \def PSA_MAC_MAX_SIZE - * - * Maximum size of a MAC. - * - * This macro must expand to a compile-time constant integer. This value - * should be the maximum size of a MAC supported by the implementation, - * in bytes, and must be no smaller than this maximum. - */ -/* All non-HMAC MACs have a maximum size that's smaller than the - * minimum possible value of PSA_HASH_MAX_SIZE in this implementation. */ -/* Note that the encoding of truncated MAC algorithms limits this value - * to 64 bytes. - */ -#define PSA_MAC_MAX_SIZE PSA_HASH_MAX_SIZE - -/** The tag size for an AEAD algorithm, in bytes. - * - * \param alg An AEAD algorithm - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * - * \return The tag size for the specified algorithm. - * If the AEAD algorithm does not have an identified - * tag that can be distinguished from the rest of - * the ciphertext, return 0. - * If the AEAD algorithm is not recognized, return 0. - * An implementation may return either 0 or a - * correct size for an AEAD algorithm that it - * recognizes, but does not support. - */ -#define PSA_AEAD_TAG_LENGTH(alg) \ - (PSA_ALG_IS_AEAD(alg) ? \ - (((alg) & PSA_ALG_AEAD_TAG_LENGTH_MASK) >> PSA_AEAD_TAG_LENGTH_OFFSET) : \ - 0) - -/* The maximum size of an RSA key on this implementation, in bits. - * This is a vendor-specific macro. - * - * Mbed TLS does not set a hard limit on the size of RSA keys: any key - * whose parameters fit in a bignum is accepted. However large keys can - * induce a large memory usage and long computation times. Unlike other - * auxiliary macros in this file and in crypto.h, which reflect how the - * library is configured, this macro defines how the library is - * configured. This implementation refuses to import or generate an - * RSA key whose size is larger than the value defined here. - * - * Note that an implementation may set different size limits for different - * operations, and does not need to accept all key sizes up to the limit. */ -#define PSA_VENDOR_RSA_MAX_KEY_BITS 4096 - -/* The maximum size of an ECC key on this implementation, in bits. - * This is a vendor-specific macro. */ -#define PSA_VENDOR_ECC_MAX_CURVE_BITS 521 - -/** Bit size associated with an elliptic curve. - * - * \param curve An elliptic curve (value of type #psa_ecc_curve_t). - * - * \return The size associated with \p curve, in bits. - * This may be 0 if the implementation does not support - * the specified curve. - */ -#define PSA_ECC_CURVE_BITS(curve) \ - ((curve) == PSA_ECC_CURVE_SECT163K1 ? 163 : \ - (curve) == PSA_ECC_CURVE_SECT163R1 ? 163 : \ - (curve) == PSA_ECC_CURVE_SECT163R2 ? 163 : \ - (curve) == PSA_ECC_CURVE_SECT193R1 ? 193 : \ - (curve) == PSA_ECC_CURVE_SECT193R2 ? 193 : \ - (curve) == PSA_ECC_CURVE_SECT233K1 ? 233 : \ - (curve) == PSA_ECC_CURVE_SECT233R1 ? 233 : \ - (curve) == PSA_ECC_CURVE_SECT239K1 ? 239 : \ - (curve) == PSA_ECC_CURVE_SECT283K1 ? 283 : \ - (curve) == PSA_ECC_CURVE_SECT283R1 ? 283 : \ - (curve) == PSA_ECC_CURVE_SECT409K1 ? 409 : \ - (curve) == PSA_ECC_CURVE_SECT409R1 ? 409 : \ - (curve) == PSA_ECC_CURVE_SECT571K1 ? 571 : \ - (curve) == PSA_ECC_CURVE_SECT571R1 ? 571 : \ - (curve) == PSA_ECC_CURVE_SECP160K1 ? 160 : \ - (curve) == PSA_ECC_CURVE_SECP160R1 ? 160 : \ - (curve) == PSA_ECC_CURVE_SECP160R2 ? 160 : \ - (curve) == PSA_ECC_CURVE_SECP192K1 ? 192 : \ - (curve) == PSA_ECC_CURVE_SECP192R1 ? 192 : \ - (curve) == PSA_ECC_CURVE_SECP224K1 ? 224 : \ - (curve) == PSA_ECC_CURVE_SECP224R1 ? 224 : \ - (curve) == PSA_ECC_CURVE_SECP256K1 ? 256 : \ - (curve) == PSA_ECC_CURVE_SECP256R1 ? 256 : \ - (curve) == PSA_ECC_CURVE_SECP384R1 ? 384 : \ - (curve) == PSA_ECC_CURVE_SECP521R1 ? 521 : \ - (curve) == PSA_ECC_CURVE_BRAINPOOL_P256R1 ? 256 : \ - (curve) == PSA_ECC_CURVE_BRAINPOOL_P384R1 ? 384 : \ - (curve) == PSA_ECC_CURVE_BRAINPOOL_P512R1 ? 512 : \ - (curve) == PSA_ECC_CURVE_CURVE25519 ? 255 : \ - (curve) == PSA_ECC_CURVE_CURVE448 ? 448 : \ - 0) - -/** \def PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN - * - * This macro returns the maximum length of the PSK supported - * by the TLS-1.2 PSK-to-MS key derivation. - * - * Quoting RFC 4279, Sect 5.3: - * TLS implementations supporting these ciphersuites MUST support - * arbitrary PSK identities up to 128 octets in length, and arbitrary - * PSKs up to 64 octets in length. Supporting longer identities and - * keys is RECOMMENDED. - * - * Therefore, no implementation should define a value smaller than 64 - * for #PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN. - */ -#define PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN 128 - -/** The maximum size of a block cipher supported by the implementation. */ -#define PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE 16 - -/** The size of the output of psa_mac_sign_finish(), in bytes. - * - * This is also the MAC size that psa_mac_verify_finish() expects. - * - * \param key_type The type of the MAC key. - * \param key_bits The size of the MAC key in bits. - * \param alg A MAC algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_MAC(\p alg) is true). - * - * \return The MAC size for the specified algorithm with - * the specified key parameters. - * \return 0 if the MAC algorithm is not recognized. - * \return Either 0 or the correct size for a MAC algorithm that - * the implementation recognizes, but does not support. - * \return Unspecified if the key parameters are not consistent - * with the algorithm. - */ -#define PSA_MAC_FINAL_SIZE(key_type, key_bits, alg) \ - ((alg) & PSA_ALG_MAC_TRUNCATION_MASK ? PSA_MAC_TRUNCATED_LENGTH(alg) : \ - PSA_ALG_IS_HMAC(alg) ? PSA_HASH_SIZE(PSA_ALG_HMAC_GET_HASH(alg)) : \ - PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) ? PSA_BLOCK_CIPHER_BLOCK_SIZE(key_type) : \ - ((void)(key_type), (void)(key_bits), 0)) - -/** The maximum size of the output of psa_aead_encrypt(), in bytes. - * - * If the size of the ciphertext buffer is at least this large, it is - * guaranteed that psa_aead_encrypt() will not fail due to an - * insufficient buffer size. Depending on the algorithm, the actual size of - * the ciphertext may be smaller. - * - * \param alg An AEAD algorithm - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * \param plaintext_length Size of the plaintext in bytes. - * - * \return The AEAD ciphertext size for the specified - * algorithm. - * If the AEAD algorithm is not recognized, return 0. - * An implementation may return either 0 or a - * correct size for an AEAD algorithm that it - * recognizes, but does not support. - */ -#define PSA_AEAD_ENCRYPT_OUTPUT_SIZE(alg, plaintext_length) \ - (PSA_AEAD_TAG_LENGTH(alg) != 0 ? \ - (plaintext_length) + PSA_AEAD_TAG_LENGTH(alg) : \ - 0) - -/** The maximum size of the output of psa_aead_decrypt(), in bytes. - * - * If the size of the plaintext buffer is at least this large, it is - * guaranteed that psa_aead_decrypt() will not fail due to an - * insufficient buffer size. Depending on the algorithm, the actual size of - * the plaintext may be smaller. - * - * \param alg An AEAD algorithm - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * \param ciphertext_length Size of the plaintext in bytes. - * - * \return The AEAD ciphertext size for the specified - * algorithm. - * If the AEAD algorithm is not recognized, return 0. - * An implementation may return either 0 or a - * correct size for an AEAD algorithm that it - * recognizes, but does not support. - */ -#define PSA_AEAD_DECRYPT_OUTPUT_SIZE(alg, ciphertext_length) \ - (PSA_AEAD_TAG_LENGTH(alg) != 0 ? \ - (ciphertext_length) - PSA_AEAD_TAG_LENGTH(alg) : \ - 0) - -/** A sufficient output buffer size for psa_aead_update(). - * - * If the size of the output buffer is at least this large, it is - * guaranteed that psa_aead_update() will not fail due to an - * insufficient buffer size. The actual size of the output may be smaller - * in any given call. - * - * \param alg An AEAD algorithm - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * \param input_length Size of the input in bytes. - * - * \return A sufficient output buffer size for the specified - * algorithm. - * If the AEAD algorithm is not recognized, return 0. - * An implementation may return either 0 or a - * correct size for an AEAD algorithm that it - * recognizes, but does not support. - */ -/* For all the AEAD modes defined in this specification, it is possible - * to emit output without delay. However, hardware may not always be - * capable of this. So for modes based on a block cipher, allow the - * implementation to delay the output until it has a full block. */ -#define PSA_AEAD_UPDATE_OUTPUT_SIZE(alg, input_length) \ - (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ - PSA_ROUND_UP_TO_MULTIPLE(PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE, (input_length)) : \ - (input_length)) - -/** A sufficient ciphertext buffer size for psa_aead_finish(). - * - * If the size of the ciphertext buffer is at least this large, it is - * guaranteed that psa_aead_finish() will not fail due to an - * insufficient ciphertext buffer size. The actual size of the output may - * be smaller in any given call. - * - * \param alg An AEAD algorithm - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * - * \return A sufficient ciphertext buffer size for the - * specified algorithm. - * If the AEAD algorithm is not recognized, return 0. - * An implementation may return either 0 or a - * correct size for an AEAD algorithm that it - * recognizes, but does not support. - */ -#define PSA_AEAD_FINISH_OUTPUT_SIZE(alg) \ - (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ - PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE : \ - 0) - -/** A sufficient plaintext buffer size for psa_aead_verify(). - * - * If the size of the plaintext buffer is at least this large, it is - * guaranteed that psa_aead_verify() will not fail due to an - * insufficient plaintext buffer size. The actual size of the output may - * be smaller in any given call. - * - * \param alg An AEAD algorithm - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * - * \return A sufficient plaintext buffer size for the - * specified algorithm. - * If the AEAD algorithm is not recognized, return 0. - * An implementation may return either 0 or a - * correct size for an AEAD algorithm that it - * recognizes, but does not support. - */ -#define PSA_AEAD_VERIFY_OUTPUT_SIZE(alg) \ - (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ - PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE : \ - 0) - -#define PSA_RSA_MINIMUM_PADDING_SIZE(alg) \ - (PSA_ALG_IS_RSA_OAEP(alg) ? \ - 2 * PSA_HASH_SIZE(PSA_ALG_RSA_OAEP_GET_HASH(alg)) + 1 : \ - 11 /*PKCS#1v1.5*/) - -/** - * \brief ECDSA signature size for a given curve bit size - * - * \param curve_bits Curve size in bits. - * \return Signature size in bytes. - * - * \note This macro returns a compile-time constant if its argument is one. - */ -#define PSA_ECDSA_SIGNATURE_SIZE(curve_bits) \ - (PSA_BITS_TO_BYTES(curve_bits) * 2) - -/** Sufficient signature buffer size for psa_sign_hash(). - * - * This macro returns a sufficient buffer size for a signature using a key - * of the specified type and size, with the specified algorithm. - * Note that the actual size of the signature may be smaller - * (some algorithms produce a variable-size signature). - * - * \warning This function may call its arguments multiple times or - * zero times, so you should not pass arguments that contain - * side effects. - * - * \param key_type An asymmetric key type (this may indifferently be a - * key pair type or a public key type). - * \param key_bits The size of the key in bits. - * \param alg The signature algorithm. - * - * \return If the parameters are valid and supported, return - * a buffer size in bytes that guarantees that - * psa_sign_hash() will not fail with - * #PSA_ERROR_BUFFER_TOO_SMALL. - * If the parameters are a valid combination that is not supported - * by the implementation, this macro shall return either a - * sensible size or 0. - * If the parameters are not valid, the - * return value is unspecified. - */ -#define PSA_SIGN_OUTPUT_SIZE(key_type, key_bits, alg) \ - (PSA_KEY_TYPE_IS_RSA(key_type) ? ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \ - PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_ECDSA_SIGNATURE_SIZE(key_bits) : \ - ((void)alg, 0)) - -#define PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE \ - PSA_ECDSA_SIGNATURE_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) - -/** \def PSA_SIGNATURE_MAX_SIZE - * - * Maximum size of an asymmetric signature. - * - * This macro must expand to a compile-time constant integer. This value - * should be the maximum size of a signature supported by the implementation, - * in bytes, and must be no smaller than this maximum. - */ -#define PSA_SIGNATURE_MAX_SIZE \ - (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) > PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE ? \ - PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) : \ - PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE) - -/** Sufficient output buffer size for psa_asymmetric_encrypt(). - * - * This macro returns a sufficient buffer size for a ciphertext produced using - * a key of the specified type and size, with the specified algorithm. - * Note that the actual size of the ciphertext may be smaller, depending - * on the algorithm. - * - * \warning This function may call its arguments multiple times or - * zero times, so you should not pass arguments that contain - * side effects. - * - * \param key_type An asymmetric key type (this may indifferently be a - * key pair type or a public key type). - * \param key_bits The size of the key in bits. - * \param alg The signature algorithm. - * - * \return If the parameters are valid and supported, return - * a buffer size in bytes that guarantees that - * psa_asymmetric_encrypt() will not fail with - * #PSA_ERROR_BUFFER_TOO_SMALL. - * If the parameters are a valid combination that is not supported - * by the implementation, this macro shall return either a - * sensible size or 0. - * If the parameters are not valid, the - * return value is unspecified. - */ -#define PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \ - (PSA_KEY_TYPE_IS_RSA(key_type) ? \ - ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \ - 0) - -/** Sufficient output buffer size for psa_asymmetric_decrypt(). - * - * This macro returns a sufficient buffer size for a ciphertext produced using - * a key of the specified type and size, with the specified algorithm. - * Note that the actual size of the ciphertext may be smaller, depending - * on the algorithm. - * - * \warning This function may call its arguments multiple times or - * zero times, so you should not pass arguments that contain - * side effects. - * - * \param key_type An asymmetric key type (this may indifferently be a - * key pair type or a public key type). - * \param key_bits The size of the key in bits. - * \param alg The signature algorithm. - * - * \return If the parameters are valid and supported, return - * a buffer size in bytes that guarantees that - * psa_asymmetric_decrypt() will not fail with - * #PSA_ERROR_BUFFER_TOO_SMALL. - * If the parameters are a valid combination that is not supported - * by the implementation, this macro shall return either a - * sensible size or 0. - * If the parameters are not valid, the - * return value is unspecified. - */ -#define PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \ - (PSA_KEY_TYPE_IS_RSA(key_type) ? \ - PSA_BITS_TO_BYTES(key_bits) - PSA_RSA_MINIMUM_PADDING_SIZE(alg) : \ - 0) - -/* Maximum size of the ASN.1 encoding of an INTEGER with the specified - * number of bits. - * - * This definition assumes that bits <= 2^19 - 9 so that the length field - * is at most 3 bytes. The length of the encoding is the length of the - * bit string padded to a whole number of bytes plus: - * - 1 type byte; - * - 1 to 3 length bytes; - * - 0 to 1 bytes of leading 0 due to the sign bit. - */ -#define PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(bits) \ - ((bits) / 8 + 5) - -/* Maximum size of the export encoding of an RSA public key. - * Assumes that the public exponent is less than 2^32. - * - * RSAPublicKey ::= SEQUENCE { - * modulus INTEGER, -- n - * publicExponent INTEGER } -- e - * - * - 4 bytes of SEQUENCE overhead; - * - n : INTEGER; - * - 7 bytes for the public exponent. - */ -#define PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) \ - (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) + 11) - -/* Maximum size of the export encoding of an RSA key pair. - * Assumes thatthe public exponent is less than 2^32 and that the size - * difference between the two primes is at most 1 bit. - * - * RSAPrivateKey ::= SEQUENCE { - * version Version, -- 0 - * modulus INTEGER, -- N-bit - * publicExponent INTEGER, -- 32-bit - * privateExponent INTEGER, -- N-bit - * prime1 INTEGER, -- N/2-bit - * prime2 INTEGER, -- N/2-bit - * exponent1 INTEGER, -- N/2-bit - * exponent2 INTEGER, -- N/2-bit - * coefficient INTEGER, -- N/2-bit - * } - * - * - 4 bytes of SEQUENCE overhead; - * - 3 bytes of version; - * - 7 half-size INTEGERs plus 2 full-size INTEGERs, - * overapproximated as 9 half-size INTEGERS; - * - 7 bytes for the public exponent. - */ -#define PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits) \ - (9 * PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE((key_bits) / 2 + 1) + 14) - -/* Maximum size of the export encoding of a DSA public key. - * - * SubjectPublicKeyInfo ::= SEQUENCE { - * algorithm AlgorithmIdentifier, - * subjectPublicKey BIT STRING } -- contains DSAPublicKey - * AlgorithmIdentifier ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters Dss-Parms } -- SEQUENCE of 3 INTEGERs - * DSAPublicKey ::= INTEGER -- public key, Y - * - * - 3 * 4 bytes of SEQUENCE overhead; - * - 1 + 1 + 7 bytes of algorithm (DSA OID); - * - 4 bytes of BIT STRING overhead; - * - 3 full-size INTEGERs (p, g, y); - * - 1 + 1 + 32 bytes for 1 sub-size INTEGER (q <= 256 bits). - */ -#define PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) \ - (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3 + 59) - -/* Maximum size of the export encoding of a DSA key pair. - * - * DSAPrivateKey ::= SEQUENCE { - * version Version, -- 0 - * prime INTEGER, -- p - * subprime INTEGER, -- q - * generator INTEGER, -- g - * public INTEGER, -- y - * private INTEGER, -- x - * } - * - * - 4 bytes of SEQUENCE overhead; - * - 3 bytes of version; - * - 3 full-size INTEGERs (p, g, y); - * - 2 * (1 + 1 + 32) bytes for 2 sub-size INTEGERs (q, x <= 256 bits). - */ -#define PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits) \ - (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3 + 75) - -/* Maximum size of the export encoding of an ECC public key. - * - * The representation of an ECC public key is: - * - The byte 0x04; - * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; - * - `y_P` as a `ceiling(m/8)`-byte string, big-endian; - * - where m is the bit size associated with the curve. - * - * - 1 byte + 2 * point size. - */ -#define PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) \ - (2 * PSA_BITS_TO_BYTES(key_bits) + 1) - -/* Maximum size of the export encoding of an ECC key pair. - * - * An ECC key pair is represented by the secret value. - */ -#define PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) \ - (PSA_BITS_TO_BYTES(key_bits)) - -/** Sufficient output buffer size for psa_export_key() or psa_export_public_key(). - * - * This macro returns a compile-time constant if its arguments are - * compile-time constants. - * - * \warning This function may call its arguments multiple times or - * zero times, so you should not pass arguments that contain - * side effects. - * - * The following code illustrates how to allocate enough memory to export - * a key by querying the key type and size at runtime. - * \code{c} - * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - * psa_status_t status; - * status = psa_get_key_attributes(key, &attributes); - * if (status != PSA_SUCCESS) handle_error(...); - * psa_key_type_t key_type = psa_get_key_type(&attributes); - * size_t key_bits = psa_get_key_bits(&attributes); - * size_t buffer_size = PSA_KEY_EXPORT_MAX_SIZE(key_type, key_bits); - * psa_reset_key_attributes(&attributes); - * uint8_t *buffer = malloc(buffer_size); - * if (buffer == NULL) handle_error(...); - * size_t buffer_length; - * status = psa_export_key(key, buffer, buffer_size, &buffer_length); - * if (status != PSA_SUCCESS) handle_error(...); - * \endcode - * - * For psa_export_public_key(), calculate the buffer size from the - * public key type. You can use the macro #PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR - * to convert a key pair type to the corresponding public key type. - * \code{c} - * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - * psa_status_t status; - * status = psa_get_key_attributes(key, &attributes); - * if (status != PSA_SUCCESS) handle_error(...); - * psa_key_type_t key_type = psa_get_key_type(&attributes); - * psa_key_type_t public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(key_type); - * size_t key_bits = psa_get_key_bits(&attributes); - * size_t buffer_size = PSA_KEY_EXPORT_MAX_SIZE(public_key_type, key_bits); - * psa_reset_key_attributes(&attributes); - * uint8_t *buffer = malloc(buffer_size); - * if (buffer == NULL) handle_error(...); - * size_t buffer_length; - * status = psa_export_public_key(key, buffer, buffer_size, &buffer_length); - * if (status != PSA_SUCCESS) handle_error(...); - * \endcode - * - * \param key_type A supported key type. - * \param key_bits The size of the key in bits. - * - * \return If the parameters are valid and supported, return - * a buffer size in bytes that guarantees that - * psa_sign_hash() will not fail with - * #PSA_ERROR_BUFFER_TOO_SMALL. - * If the parameters are a valid combination that is not supported - * by the implementation, this macro shall return either a - * sensible size or 0. - * If the parameters are not valid, the - * return value is unspecified. - */ -#define PSA_KEY_EXPORT_MAX_SIZE(key_type, key_bits) \ - (PSA_KEY_TYPE_IS_UNSTRUCTURED(key_type) ? PSA_BITS_TO_BYTES(key_bits) : \ - (key_type) == PSA_KEY_TYPE_RSA_KEY_PAIR ? PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits) : \ - (key_type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY ? PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ - (key_type) == PSA_KEY_TYPE_DSA_KEY_PAIR ? PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits) : \ - (key_type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY ? PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ - PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) ? PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) : \ - PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type) ? PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) : \ - 0) - -#endif /* PSA_CRYPTO_SIZES_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_struct.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_struct.h deleted file mode 100644 index ac08987..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_struct.h +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (c) 2018-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ -/** - * \file psa/crypto_struct.h - * - * \brief PSA cryptography module: structured type implementations - * - * \note This file may not be included directly. Applications must - * include psa/crypto.h. - * - * This file contains the definitions of some data structures with - * implementation-specific definitions. - * - * In implementations with isolation between the application and the - * cryptography module, it is expected that the front-end and the back-end - * would have different versions of this file. - */ - -#ifndef PSA_CRYPTO_STRUCT_H -#define PSA_CRYPTO_STRUCT_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Note that the below structures are different from the decalrations in - * mbed-crypto. This is because TF-M maintains 'front-end' and 'back-end' - * versions of this header. In the front-end version, exported to NS - * clients in interface/include/psa, a crypto operation is defined as an - * opaque handle to a context in the Crypto service. The back-end - * version, directly included from the mbed-crypto repo by the Crypto - * service, contains the full definition of the operation structs. - * - * One of the functions of the Crypto service is to allocate the back-end - * operation contexts in its own partition memory (in crypto_alloc.c), - * and then do the mapping between front-end operation handles passed by - * NS clients and the corresponding back-end operation contexts. The - * advantage of doing it this way is that internal mbed-crypto state is never - * exposed to the NS client. - */ - -struct psa_hash_operation_s -{ - uint32_t handle; -}; - -#define PSA_HASH_OPERATION_INIT {0} -static inline struct psa_hash_operation_s psa_hash_operation_init( void ) -{ - const struct psa_hash_operation_s v = PSA_HASH_OPERATION_INIT; - return( v ); -} - -struct psa_mac_operation_s -{ - uint32_t handle; -}; - -#define PSA_MAC_OPERATION_INIT {0} -static inline struct psa_mac_operation_s psa_mac_operation_init( void ) -{ - const struct psa_mac_operation_s v = PSA_MAC_OPERATION_INIT; - return( v ); -} - -struct psa_cipher_operation_s -{ - uint32_t handle; -}; - -#define PSA_CIPHER_OPERATION_INIT {0} -static inline struct psa_cipher_operation_s psa_cipher_operation_init( void ) -{ - const struct psa_cipher_operation_s v = PSA_CIPHER_OPERATION_INIT; - return( v ); -} - -struct psa_aead_operation_s -{ - uint32_t handle; -}; - -#define PSA_AEAD_OPERATION_INIT {0} -static inline struct psa_aead_operation_s psa_aead_operation_init( void ) -{ - const struct psa_aead_operation_s v = PSA_AEAD_OPERATION_INIT; - return( v ); -} - -struct psa_key_derivation_s -{ - uint32_t handle; -}; - -#define PSA_KEY_DERIVATION_OPERATION_INIT {0} -static inline struct psa_key_derivation_s psa_key_derivation_operation_init( void ) -{ - const struct psa_key_derivation_s v = PSA_KEY_DERIVATION_OPERATION_INIT; - return( v ); -} - -/* The type used internally for key sizes. - * Public interfaces use size_t, but internally we use a smaller type. */ -typedef uint16_t psa_key_bits_t; -/* The maximum value of the type used to represent bit-sizes. - * This is used to mark an invalid key size. */ -#define PSA_KEY_BITS_TOO_LARGE ( (psa_key_bits_t) ( -1 ) ) -/* The maximum size of a key in bits. - * Currently defined as the maximum that can be represented, rounded down - * to a whole number of bytes. - * This is an uncast value so that it can be used in preprocessor - * conditionals. */ -#define PSA_MAX_KEY_BITS 0xfff8 - -#define PSA_KEY_ATTRIBUTES_INIT PSA_CLIENT_KEY_ATTRIBUTES_INIT - -static inline struct psa_client_key_attributes_s psa_key_attributes_init( void ) -{ - const struct psa_client_key_attributes_s v = PSA_KEY_ATTRIBUTES_INIT; - return( v ); -} - -static inline void psa_set_key_id(psa_key_attributes_t *attributes, - psa_key_id_t id) -{ - attributes->id = id; - if( attributes->lifetime == PSA_KEY_LIFETIME_VOLATILE ) - attributes->lifetime = PSA_KEY_LIFETIME_PERSISTENT; -} - -static inline psa_key_id_t psa_get_key_id( - const psa_key_attributes_t *attributes) -{ - return( attributes->id ); -} - -static inline void psa_set_key_lifetime(psa_key_attributes_t *attributes, - psa_key_lifetime_t lifetime) -{ - attributes->lifetime = lifetime; - if( lifetime == PSA_KEY_LIFETIME_VOLATILE ) - { - attributes->id = 0; - } -} - -static inline psa_key_lifetime_t psa_get_key_lifetime( - const psa_key_attributes_t *attributes) -{ - return( attributes->lifetime ); -} - -static inline void psa_set_key_usage_flags(psa_key_attributes_t *attributes, - psa_key_usage_t usage_flags) -{ - attributes->usage = usage_flags; -} - -static inline psa_key_usage_t psa_get_key_usage_flags( - const psa_key_attributes_t *attributes) -{ - return( attributes->usage ); -} - -static inline void psa_set_key_algorithm(psa_key_attributes_t *attributes, - psa_algorithm_t alg) -{ - attributes->alg = alg; -} - -static inline psa_algorithm_t psa_get_key_algorithm( - const psa_key_attributes_t *attributes) -{ - return( attributes->alg ); -} - -static inline void psa_set_key_type(psa_key_attributes_t *attributes, - psa_key_type_t type) -{ - attributes->type = type; -} - -static inline psa_key_type_t psa_get_key_type( - const psa_key_attributes_t *attributes) -{ - return( attributes->type ); -} - -static inline void psa_set_key_bits(psa_key_attributes_t *attributes, - size_t bits) -{ - if( bits > PSA_MAX_KEY_BITS ) - attributes->bits = PSA_KEY_BITS_TOO_LARGE; - else - attributes->bits = bits; -} - -static inline size_t psa_get_key_bits( - const psa_key_attributes_t *attributes) -{ - return( attributes->bits ); -} - -#ifdef __cplusplus -} -#endif - -#endif /* PSA_CRYPTO_STRUCT_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_types.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_types.h deleted file mode 100644 index 6ac95a8..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_types.h +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright (c) 2018-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ -/** - * \file psa/crypto_types.h - * - * \brief PSA cryptography module: type aliases. - * - * \note This file may not be included directly. Applications must - * include psa/crypto.h. Drivers must include the appropriate driver - * header file. - * - * This file contains portable definitions of integral types for properties - * of cryptographic keys, designations of cryptographic algorithms, and - * error codes returned by the library. - * - * This header file does not declare any function. - */ - -#ifndef PSA_CRYPTO_TYPES_H -#define PSA_CRYPTO_TYPES_H - -#include - -/** \defgroup error Error codes - * @{ - */ - -/** - * \brief Function return status. - * - * This is either #PSA_SUCCESS (which is zero), indicating success, - * or a small negative value indicating that an error occurred. Errors are - * encoded as one of the \c PSA_ERROR_xxx values defined here. */ -/* If #PSA_SUCCESS is already defined, it means that #psa_status_t - * is also defined in an external header, so prevent its multiple - * definition. - */ -#ifndef PSA_SUCCESS -typedef int32_t psa_status_t; -#endif - -/**@}*/ - -/** \defgroup crypto_types Key and algorithm types - * @{ - */ - -/* Integral type representing a key handle. */ -typedef uint16_t psa_key_handle_t; - - -/** \brief Encoding of a key type. - */ -typedef uint32_t psa_key_type_t; - -/** The type of PSA elliptic curve identifiers. - * - * The curve identifier is required to create an ECC key using the - * PSA_KEY_TYPE_ECC_KEY_PAIR() or PSA_KEY_TYPE_ECC_PUBLIC_KEY() - * macros. - * - * The encoding of curve identifiers is taken from the - * TLS Supported Groups Registry (formerly known as the - * TLS EC Named Curve Registry) - * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 - * - * This specification defines identifiers for some of the curves in the IANA - * registry. Implementations that support other curves that are in the IANA - * registry should use the IANA value and a implementation-specific identifier. - * Implemenations that support non-IANA curves should use one of the following - * approaches for allocating a key type: - * - * 1. Select a ::psa_ecc_curve_t value in the range #PSA_ECC_CURVE_VENDOR_MIN to - * #PSA_ECC_CURVE_VENDOR_MAX, which is a subset of the IANA private use - * range. - * 2. Use a ::psa_key_type_t value that is vendor-defined. - * - * The first option is recommended. - */ -typedef uint16_t psa_ecc_curve_t; - -/** The type of PSA Diffie-Hellman group identifiers. - * - * The group identifier is required to create an Diffie-Hellman key using the - * PSA_KEY_TYPE_DH_KEY_PAIR() or PSA_KEY_TYPE_DH_PUBLIC_KEY() - * macros. - * - * The encoding of group identifiers is taken from the - * TLS Supported Groups Registry (formerly known as the - * TLS EC Named Curve Registry) - * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 - * - * This specification defines identifiers for some of the groups in the IANA - * registry. Implementations that support other groups that are in the IANA - * registry should use the IANA value and a implementation-specific identifier. - * Implemenations that support non-IANA groups should use one of the following - * approaches for allocating a key type: - * - * 1. Select a ::psa_dh_group_t value in the range #PSA_DH_GROUP_VENDOR_MIN to - * #PSA_DH_GROUP_VENDOR_MAX, which is a subset of the IANA private use - * range. - * 2. Select a ::psa_dh_group_t value from the named groups allocated for - * GREASE in the IETF draft specification. The GREASE specification and - * values are listed below. - * 3. Use a ::psa_key_type_t value that is vendor-defined. - * - * Option 1 or 2 are recommended. - * - * The current draft of the GREASE specification is - * https://datatracker.ietf.org/doc/draft-ietf-tls-grease - * - * The following GREASE values are allocated for named groups: - * \code - * 0x0A0A - * 0x1A1A - * 0x2A2A - * 0x3A3A - * 0x4A4A - * 0x5A5A - * 0x6A6A - * 0x7A7A - * 0x8A8A - * 0x9A9A - * 0xAAAA - * 0xBABA - * 0xCACA - * 0xDADA - * 0xEAEA - * 0xFAFA - * \endcode - */ -typedef uint16_t psa_dh_group_t; - -/** \brief Encoding of a cryptographic algorithm. - * - * For algorithms that can be applied to multiple key types, this type - * does not encode the key type. For example, for symmetric ciphers - * based on a block cipher, #psa_algorithm_t encodes the block cipher - * mode and the padding mode while the block cipher itself is encoded - * via #psa_key_type_t. - */ -typedef uint32_t psa_algorithm_t; - -/**@}*/ - -/** \defgroup key_lifetimes Key lifetimes - * @{ - */ - -/** Encoding of key lifetimes. - * - * The lifetime of a key indicates where it is stored and what system actions - * may create and destroy it. - * - * Keys with the lifetime #PSA_KEY_LIFETIME_VOLATILE are automatically - * destroyed when the application terminates or on a power reset. - * - * Keys with a lifetime other than #PSA_KEY_LIFETIME_VOLATILE are said - * to be _persistent_. - * Persistent keys are preserved if the application or the system restarts. - * Persistent keys have a key identifier of type #psa_key_id_t. - * The application can call psa_open_key() to open a persistent key that - * it created previously. - */ -typedef uint32_t psa_key_lifetime_t; - -/** Encoding of identifiers of persistent keys. - * - * - Applications may freely choose key identifiers in the range - * #PSA_KEY_ID_USER_MIN to #PSA_KEY_ID_USER_MAX. - * - Implementations may define additional key identifiers in the range - * #PSA_KEY_ID_VENDOR_MIN to #PSA_KEY_ID_VENDOR_MAX. - * - 0 is reserved as an invalid key identifier. - * - Key identifiers outside these ranges are reserved for future use. - */ -typedef uint32_t psa_key_id_t; -#define PSA_KEY_ID_INIT 0 - -/**@}*/ - -/** \defgroup policy Key policies - * @{ - */ - -/** \brief Encoding of permitted usage on a key. */ -typedef uint32_t psa_key_usage_t; - -/**@}*/ - -/** \defgroup attributes Key attributes - * @{ - */ - -/** The type of a structure containing key attributes. - * - * This is an opaque structure that can represent the metadata of a key - * object. Metadata that can be stored in attributes includes: - * - The location of the key in storage, indicated by its key identifier - * and its lifetime. - * - The key's policy, comprising usage flags and a specification of - * the permitted algorithm(s). - * - Information about the key itself: the key type and its size. - * - Implementations may define additional attributes. - * - * The actual key material is not considered an attribute of a key. - * Key attributes do not contain information that is generally considered - * highly confidential. - * - * An attribute structure can be a simple data structure where each function - * `psa_set_key_xxx` sets a field and the corresponding function - * `psa_get_key_xxx` retrieves the value of the corresponding field. - * However, implementations may report values that are equivalent to the - * original one, but have a different encoding. For example, an - * implementation may use a more compact representation for types where - * many bit-patterns are invalid or not supported, and store all values - * that it does not support as a special marker value. In such an - * implementation, after setting an invalid value, the corresponding - * get function returns an invalid value which may not be the one that - * was originally stored. - * - * An attribute structure may contain references to auxiliary resources, - * for example pointers to allocated memory or indirect references to - * pre-calculated values. In order to free such resources, the application - * must call psa_reset_key_attributes(). As an exception, calling - * psa_reset_key_attributes() on an attribute structure is optional if - * the structure has only been modified by the following functions - * since it was initialized or last reset with psa_reset_key_attributes(): - * - psa_set_key_id() - * - psa_set_key_lifetime() - * - psa_set_key_type() - * - psa_set_key_bits() - * - psa_set_key_usage_flags() - * - psa_set_key_algorithm() - * - * Before calling any function on a key attribute structure, the application - * must initialize it by any of the following means: - * - Set the structure to all-bits-zero, for example: - * \code - * psa_key_attributes_t attributes; - * memset(&attributes, 0, sizeof(attributes)); - * \endcode - * - Initialize the structure to logical zero values, for example: - * \code - * psa_key_attributes_t attributes = {0}; - * \endcode - * - Initialize the structure to the initializer #PSA_KEY_ATTRIBUTES_INIT, - * for example: - * \code - * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - * \endcode - * - Assign the result of the function psa_key_attributes_init() - * to the structure, for example: - * \code - * psa_key_attributes_t attributes; - * attributes = psa_key_attributes_init(); - * \endcode - * - * A freshly initialized attribute structure contains the following - * values: - * - * - lifetime: #PSA_KEY_LIFETIME_VOLATILE. - * - key identifier: 0 (which is not a valid key identifier). - * - type: \c 0 (meaning that the type is unspecified). - * - key size: \c 0 (meaning that the size is unspecified). - * - usage flags: \c 0 (which allows no usage except exporting a public key). - * - algorithm: \c 0 (which allows no cryptographic usage, but allows - * exporting). - * - * A typical sequence to create a key is as follows: - * -# Create and initialize an attribute structure. - * -# If the key is persistent, call psa_set_key_id(). - * Also call psa_set_key_lifetime() to place the key in a non-default - * location. - * -# Set the key policy with psa_set_key_usage_flags() and - * psa_set_key_algorithm(). - * -# Set the key type with psa_set_key_type(). - * Skip this step if copying an existing key with psa_copy_key(). - * -# When generating a random key with psa_generate_key() or deriving a key - * with psa_key_derivation_output_key(), set the desired key size with - * psa_set_key_bits(). - * -# Call a key creation function: psa_import_key(), psa_generate_key(), - * psa_key_derivation_output_key() or psa_copy_key(). This function reads - * the attribute structure, creates a key with these attributes, and - * outputs a handle to the newly created key. - * -# The attribute structure is now no longer necessary. - * You may call psa_reset_key_attributes(), although this is optional - * with the workflow presented here because the attributes currently - * defined in this specification do not require any additional resources - * beyond the structure itself. - * - * A typical sequence to query a key's attributes is as follows: - * -# Call psa_get_key_attributes(). - * -# Call `psa_get_key_xxx` functions to retrieve the attribute(s) that - * you are interested in. - * -# Call psa_reset_key_attributes() to free any resources that may be - * used by the attribute structure. - * - * Once a key has been created, it is impossible to change its attributes. - */ -typedef struct psa_client_key_attributes_s psa_key_attributes_t; - -/**@}*/ - -/** \defgroup derivation Key derivation - * @{ - */ - -/** \brief Encoding of the step of a key derivation. */ -typedef uint16_t psa_key_derivation_step_t; - -/**@}*/ - -#endif /* PSA_CRYPTO_TYPES_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_values.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_values.h deleted file mode 100644 index e21ef27..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_values.h +++ /dev/null @@ -1,1701 +0,0 @@ -/* - * Copyright (c) 2018-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ -/** - * \file psa/crypto_values.h - * - * \brief PSA cryptography module: macros to build and analyze integer values. - * - * \note This file may not be included directly. Applications must - * include psa/crypto.h. Drivers must include the appropriate driver - * header file. - * - * This file contains portable definitions of macros to build and analyze - * values of integral types that encode properties of cryptographic keys, - * designations of cryptographic algorithms, and error codes returned by - * the library. - * - * This header file only defines preprocessor macros. - */ - -#ifndef PSA_CRYPTO_VALUES_H -#define PSA_CRYPTO_VALUES_H - -/** \defgroup error Error codes - * @{ - */ - -/* PSA error codes */ - -/** The action was completed successfully. */ -#ifndef PSA_SUCCESS -#define PSA_SUCCESS ((psa_status_t)0) -#endif - -/** An error occurred that does not correspond to any defined - * failure cause. - * - * Implementations may use this error code if none of the other standard - * error codes are applicable. */ -#define PSA_ERROR_GENERIC_ERROR ((psa_status_t)-132) - -/** The requested operation or a parameter is not supported - * by this implementation. - * - * Implementations should return this error code when an enumeration - * parameter such as a key type, algorithm, etc. is not recognized. - * If a combination of parameters is recognized and identified as - * not valid, return #PSA_ERROR_INVALID_ARGUMENT instead. */ -#define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)-134) - -/** The requested action is denied by a policy. - * - * Implementations should return this error code when the parameters - * are recognized as valid and supported, and a policy explicitly - * denies the requested operation. - * - * If a subset of the parameters of a function call identify a - * forbidden operation, and another subset of the parameters are - * not valid or not supported, it is unspecified whether the function - * returns #PSA_ERROR_NOT_PERMITTED, #PSA_ERROR_NOT_SUPPORTED or - * #PSA_ERROR_INVALID_ARGUMENT. */ -#define PSA_ERROR_NOT_PERMITTED ((psa_status_t)-133) - -/** An output buffer is too small. - * - * Applications can call the \c PSA_xxx_SIZE macro listed in the function - * description to determine a sufficient buffer size. - * - * Implementations should preferably return this error code only - * in cases when performing the operation with a larger output - * buffer would succeed. However implementations may return this - * error if a function has invalid or unsupported parameters in addition - * to the parameters that determine the necessary output buffer size. */ -#define PSA_ERROR_BUFFER_TOO_SMALL ((psa_status_t)-138) - -/** Asking for an item that already exists - * - * Implementations should return this error, when attempting - * to write an item (like a key) that already exists. */ -#define PSA_ERROR_ALREADY_EXISTS ((psa_status_t)-139) - -/** Asking for an item that doesn't exist - * - * Implementations should return this error, if a requested item (like - * a key) does not exist. */ -#define PSA_ERROR_DOES_NOT_EXIST ((psa_status_t)-140) - -/** The requested action cannot be performed in the current state. - * - * Multipart operations return this error when one of the - * functions is called out of sequence. Refer to the function - * descriptions for permitted sequencing of functions. - * - * Implementations shall not return this error code to indicate - * that a key either exists or not, - * but shall instead return #PSA_ERROR_ALREADY_EXISTS or #PSA_ERROR_DOES_NOT_EXIST - * as applicable. - * - * Implementations shall not return this error code to indicate that a - * key handle is invalid, but shall return #PSA_ERROR_INVALID_HANDLE - * instead. */ -#define PSA_ERROR_BAD_STATE ((psa_status_t)-137) - -/** The parameters passed to the function are invalid. - * - * Implementations may return this error any time a parameter or - * combination of parameters are recognized as invalid. - * - * Implementations shall not return this error code to indicate that a - * key handle is invalid, but shall return #PSA_ERROR_INVALID_HANDLE - * instead. - */ -#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)-135) - -/** There is not enough runtime memory. - * - * If the action is carried out across multiple security realms, this - * error can refer to available memory in any of the security realms. */ -#define PSA_ERROR_INSUFFICIENT_MEMORY ((psa_status_t)-141) - -/** There is not enough persistent storage. - * - * Functions that modify the key storage return this error code if - * there is insufficient storage space on the host media. In addition, - * many functions that do not otherwise access storage may return this - * error code if the implementation requires a mandatory log entry for - * the requested action and the log storage space is full. */ -#define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)-142) - -/** There was a communication failure inside the implementation. - * - * This can indicate a communication failure between the application - * and an external cryptoprocessor or between the cryptoprocessor and - * an external volatile or persistent memory. A communication failure - * may be transient or permanent depending on the cause. - * - * \warning If a function returns this error, it is undetermined - * whether the requested action has completed or not. Implementations - * should return #PSA_SUCCESS on successful completion whenever - * possible, however functions may return #PSA_ERROR_COMMUNICATION_FAILURE - * if the requested action was completed successfully in an external - * cryptoprocessor but there was a breakdown of communication before - * the cryptoprocessor could report the status to the application. - */ -#define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t)-145) - -/** There was a storage failure that may have led to data loss. - * - * This error indicates that some persistent storage is corrupted. - * It should not be used for a corruption of volatile memory - * (use #PSA_ERROR_CORRUPTION_DETECTED), for a communication error - * between the cryptoprocessor and its external storage (use - * #PSA_ERROR_COMMUNICATION_FAILURE), or when the storage is - * in a valid state but is full (use #PSA_ERROR_INSUFFICIENT_STORAGE). - * - * Note that a storage failure does not indicate that any data that was - * previously read is invalid. However this previously read data may no - * longer be readable from storage. - * - * When a storage failure occurs, it is no longer possible to ensure - * the global integrity of the keystore. Depending on the global - * integrity guarantees offered by the implementation, access to other - * data may or may not fail even if the data is still readable but - * its integrity cannot be guaranteed. - * - * Implementations should only use this error code to report a - * permanent storage corruption. However application writers should - * keep in mind that transient errors while reading the storage may be - * reported using this error code. */ -#define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)-146) - -/** A hardware failure was detected. - * - * A hardware failure may be transient or permanent depending on the - * cause. */ -#define PSA_ERROR_HARDWARE_FAILURE ((psa_status_t)-147) - -/** A tampering attempt was detected. - * - * If an application receives this error code, there is no guarantee - * that previously accessed or computed data was correct and remains - * confidential. Applications should not perform any security function - * and should enter a safe failure state. - * - * Implementations may return this error code if they detect an invalid - * state that cannot happen during normal operation and that indicates - * that the implementation's security guarantees no longer hold. Depending - * on the implementation architecture and on its security and safety goals, - * the implementation may forcibly terminate the application. - * - * This error code is intended as a last resort when a security breach - * is detected and it is unsure whether the keystore data is still - * protected. Implementations shall only return this error code - * to report an alarm from a tampering detector, to indicate that - * the confidentiality of stored data can no longer be guaranteed, - * or to indicate that the integrity of previously returned data is now - * considered compromised. Implementations shall not use this error code - * to indicate a hardware failure that merely makes it impossible to - * perform the requested operation (use #PSA_ERROR_COMMUNICATION_FAILURE, - * #PSA_ERROR_STORAGE_FAILURE, #PSA_ERROR_HARDWARE_FAILURE, - * #PSA_ERROR_INSUFFICIENT_ENTROPY or other applicable error code - * instead). - * - * This error indicates an attack against the application. Implementations - * shall not return this error code as a consequence of the behavior of - * the application itself. */ -#define PSA_ERROR_CORRUPTION_DETECTED ((psa_status_t)-151) - -/** There is not enough entropy to generate random data needed - * for the requested action. - * - * This error indicates a failure of a hardware random generator. - * Application writers should note that this error can be returned not - * only by functions whose purpose is to generate random data, such - * as key, IV or nonce generation, but also by functions that execute - * an algorithm with a randomized result, as well as functions that - * use randomization of intermediate computations as a countermeasure - * to certain attacks. - * - * Implementations should avoid returning this error after psa_crypto_init() - * has succeeded. Implementations should generate sufficient - * entropy during initialization and subsequently use a cryptographically - * secure pseudorandom generator (PRNG). However implementations may return - * this error at any time if a policy requires the PRNG to be reseeded - * during normal operation. */ -#define PSA_ERROR_INSUFFICIENT_ENTROPY ((psa_status_t)-148) - -/** The signature, MAC or hash is incorrect. - * - * Verification functions return this error if the verification - * calculations completed successfully, and the value to be verified - * was determined to be incorrect. - * - * If the value to verify has an invalid size, implementations may return - * either #PSA_ERROR_INVALID_ARGUMENT or #PSA_ERROR_INVALID_SIGNATURE. */ -#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) - -/** The decrypted padding is incorrect. - * - * \warning In some protocols, when decrypting data, it is essential that - * the behavior of the application does not depend on whether the padding - * is correct, down to precise timing. Applications should prefer - * protocols that use authenticated encryption rather than plain - * encryption. If the application must perform a decryption of - * unauthenticated data, the application writer should take care not - * to reveal whether the padding is invalid. - * - * Implementations should strive to make valid and invalid padding - * as close as possible to indistinguishable to an external observer. - * In particular, the timing of a decryption operation should not - * depend on the validity of the padding. */ -#define PSA_ERROR_INVALID_PADDING ((psa_status_t)-150) - -/** Return this error when there's insufficient data when attempting - * to read from a resource. */ -#define PSA_ERROR_INSUFFICIENT_DATA ((psa_status_t)-143) - -/** The key handle is not valid. See also :ref:\`key-handles\`. - */ -#define PSA_ERROR_INVALID_HANDLE ((psa_status_t)-136) - -/**@}*/ - -/** \defgroup crypto_types Key and algorithm types - * @{ - */ - -/** An invalid key type value. - * - * Zero is not the encoding of any key type. - */ -#define PSA_KEY_TYPE_NONE ((psa_key_type_t)0x00000000) - -/** Vendor-defined key type flag. - * - * Key types defined by this standard will never have the - * #PSA_KEY_TYPE_VENDOR_FLAG bit set. Vendors who define additional key types - * must use an encoding with the #PSA_KEY_TYPE_VENDOR_FLAG bit set and should - * respect the bitwise structure used by standard encodings whenever practical. - */ -#define PSA_KEY_TYPE_VENDOR_FLAG ((psa_key_type_t)0x80000000) - -#define PSA_KEY_TYPE_CATEGORY_MASK ((psa_key_type_t)0x70000000) -#define PSA_KEY_TYPE_CATEGORY_SYMMETRIC ((psa_key_type_t)0x40000000) -#define PSA_KEY_TYPE_CATEGORY_RAW ((psa_key_type_t)0x50000000) -#define PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY ((psa_key_type_t)0x60000000) -#define PSA_KEY_TYPE_CATEGORY_KEY_PAIR ((psa_key_type_t)0x70000000) - -#define PSA_KEY_TYPE_CATEGORY_FLAG_PAIR ((psa_key_type_t)0x10000000) - -/** Whether a key type is vendor-defined. - * - * See also #PSA_KEY_TYPE_VENDOR_FLAG. - */ -#define PSA_KEY_TYPE_IS_VENDOR_DEFINED(type) \ - (((type) & PSA_KEY_TYPE_VENDOR_FLAG) != 0) - -/** Whether a key type is an unstructured array of bytes. - * - * This encompasses both symmetric keys and non-key data. - */ -#define PSA_KEY_TYPE_IS_UNSTRUCTURED(type) \ - (((type) & PSA_KEY_TYPE_CATEGORY_MASK & ~(psa_key_type_t)0x10000000) == \ - PSA_KEY_TYPE_CATEGORY_SYMMETRIC) - -/** Whether a key type is asymmetric: either a key pair or a public key. */ -#define PSA_KEY_TYPE_IS_ASYMMETRIC(type) \ - (((type) & PSA_KEY_TYPE_CATEGORY_MASK \ - & ~PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) == \ - PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY) -/** Whether a key type is the public part of a key pair. */ -#define PSA_KEY_TYPE_IS_PUBLIC_KEY(type) \ - (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY) -/** Whether a key type is a key pair containing a private part and a public - * part. */ -#define PSA_KEY_TYPE_IS_KEY_PAIR(type) \ - (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_KEY_PAIR) -/** The key pair type corresponding to a public key type. - * - * You may also pass a key pair type as \p type, it will be left unchanged. - * - * \param type A public key type or key pair type. - * - * \return The corresponding key pair type. - * If \p type is not a public key or a key pair, - * the return value is undefined. - */ -#define PSA_KEY_TYPE_KEY_PAIR_OF_PUBLIC_KEY(type) \ - ((type) | PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) -/** The public key type corresponding to a key pair type. - * - * You may also pass a key pair type as \p type, it will be left unchanged. - * - * \param type A public key type or key pair type. - * - * \return The corresponding public key type. - * If \p type is not a public key or a key pair, - * the return value is undefined. - */ -#define PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) \ - ((type) & ~PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) - -/** Raw data. - * - * A "key" of this type cannot be used for any cryptographic operation. - * Applications may use this type to store arbitrary data in the keystore. */ -#define PSA_KEY_TYPE_RAW_DATA ((psa_key_type_t)0x50000001) - -/** HMAC key. - * - * The key policy determines which underlying hash algorithm the key can be - * used for. - * - * HMAC keys should generally have the same size as the underlying hash. - * This size can be calculated with #PSA_HASH_SIZE(\c alg) where - * \c alg is the HMAC algorithm or the underlying hash algorithm. */ -#define PSA_KEY_TYPE_HMAC ((psa_key_type_t)0x51000000) - -/** A secret for key derivation. - * - * The key policy determines which key derivation algorithm the key - * can be used for. - */ -#define PSA_KEY_TYPE_DERIVE ((psa_key_type_t)0x52000000) - -/** Key for a cipher, AEAD or MAC algorithm based on the AES block cipher. - * - * The size of the key can be 16 bytes (AES-128), 24 bytes (AES-192) or - * 32 bytes (AES-256). - */ -#define PSA_KEY_TYPE_AES ((psa_key_type_t)0x40000001) - -/** Key for a cipher or MAC algorithm based on DES or 3DES (Triple-DES). - * - * The size of the key can be 8 bytes (single DES), 16 bytes (2-key 3DES) or - * 24 bytes (3-key 3DES). - * - * Note that single DES and 2-key 3DES are weak and strongly - * deprecated and should only be used to decrypt legacy data. 3-key 3DES - * is weak and deprecated and should only be used in legacy protocols. - */ -#define PSA_KEY_TYPE_DES ((psa_key_type_t)0x40000002) - -/** Key for a cipher, AEAD or MAC algorithm based on the - * Camellia block cipher. */ -#define PSA_KEY_TYPE_CAMELLIA ((psa_key_type_t)0x40000003) - -/** Key for the RC4 stream cipher. - * - * Note that RC4 is weak and deprecated and should only be used in - * legacy protocols. */ -#define PSA_KEY_TYPE_ARC4 ((psa_key_type_t)0x40000004) - -/** Key for the ChaCha20 stream cipher or the Chacha20-Poly1305 AEAD algorithm. - * - * ChaCha20 and the ChaCha20_Poly1305 construction are defined in RFC 7539. - * - * Implementations must support 12-byte nonces, may support 8-byte nonces, - * and should reject other sizes. - */ -#define PSA_KEY_TYPE_CHACHA20 ((psa_key_type_t)0x40000005) - -/** RSA public key. */ -#define PSA_KEY_TYPE_RSA_PUBLIC_KEY ((psa_key_type_t)0x60010000) -/** RSA key pair (private and public key). */ -#define PSA_KEY_TYPE_RSA_KEY_PAIR ((psa_key_type_t)0x70010000) -/** Whether a key type is an RSA key (pair or public-only). */ -#define PSA_KEY_TYPE_IS_RSA(type) \ - (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY) - -#define PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE ((psa_key_type_t)0x60030000) -#define PSA_KEY_TYPE_ECC_KEY_PAIR_BASE ((psa_key_type_t)0x70030000) -#define PSA_KEY_TYPE_ECC_CURVE_MASK ((psa_key_type_t)0x0000ffff) -/** Elliptic curve key pair. - * - * \param curve A value of type ::psa_ecc_curve_t that identifies the - * ECC curve to be used. - */ -#define PSA_KEY_TYPE_ECC_KEY_PAIR(curve) \ - (PSA_KEY_TYPE_ECC_KEY_PAIR_BASE | (curve)) -/** Elliptic curve public key. - * - * \param curve A value of type ::psa_ecc_curve_t that identifies the - * ECC curve to be used. - */ -#define PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve) \ - (PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE | (curve)) - -/** Whether a key type is an elliptic curve key (pair or public-only). */ -#define PSA_KEY_TYPE_IS_ECC(type) \ - ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) & \ - ~PSA_KEY_TYPE_ECC_CURVE_MASK) == PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE) -/** Whether a key type is an elliptic curve key pair. */ -#define PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type) \ - (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \ - PSA_KEY_TYPE_ECC_KEY_PAIR_BASE) -/** Whether a key type is an elliptic curve public key. */ -#define PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(type) \ - (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \ - PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE) - -/** Extract the curve from an elliptic curve key type. */ -#define PSA_KEY_TYPE_GET_CURVE(type) \ - ((psa_ecc_curve_t) (PSA_KEY_TYPE_IS_ECC(type) ? \ - ((type) & PSA_KEY_TYPE_ECC_CURVE_MASK) : \ - 0)) - -/* The encoding of curve identifiers is currently aligned with the - * TLS Supported Groups Registry (formerly known as the - * TLS EC Named Curve Registry) - * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 - * The values are defined by RFC 8422 and RFC 7027. */ -#define PSA_ECC_CURVE_SECT163K1 ((psa_ecc_curve_t) 0x0001) -#define PSA_ECC_CURVE_SECT163R1 ((psa_ecc_curve_t) 0x0002) -#define PSA_ECC_CURVE_SECT163R2 ((psa_ecc_curve_t) 0x0003) -#define PSA_ECC_CURVE_SECT193R1 ((psa_ecc_curve_t) 0x0004) -#define PSA_ECC_CURVE_SECT193R2 ((psa_ecc_curve_t) 0x0005) -#define PSA_ECC_CURVE_SECT233K1 ((psa_ecc_curve_t) 0x0006) -#define PSA_ECC_CURVE_SECT233R1 ((psa_ecc_curve_t) 0x0007) -#define PSA_ECC_CURVE_SECT239K1 ((psa_ecc_curve_t) 0x0008) -#define PSA_ECC_CURVE_SECT283K1 ((psa_ecc_curve_t) 0x0009) -#define PSA_ECC_CURVE_SECT283R1 ((psa_ecc_curve_t) 0x000a) -#define PSA_ECC_CURVE_SECT409K1 ((psa_ecc_curve_t) 0x000b) -#define PSA_ECC_CURVE_SECT409R1 ((psa_ecc_curve_t) 0x000c) -#define PSA_ECC_CURVE_SECT571K1 ((psa_ecc_curve_t) 0x000d) -#define PSA_ECC_CURVE_SECT571R1 ((psa_ecc_curve_t) 0x000e) -#define PSA_ECC_CURVE_SECP160K1 ((psa_ecc_curve_t) 0x000f) -#define PSA_ECC_CURVE_SECP160R1 ((psa_ecc_curve_t) 0x0010) -#define PSA_ECC_CURVE_SECP160R2 ((psa_ecc_curve_t) 0x0011) -#define PSA_ECC_CURVE_SECP192K1 ((psa_ecc_curve_t) 0x0012) -#define PSA_ECC_CURVE_SECP192R1 ((psa_ecc_curve_t) 0x0013) -#define PSA_ECC_CURVE_SECP224K1 ((psa_ecc_curve_t) 0x0014) -#define PSA_ECC_CURVE_SECP224R1 ((psa_ecc_curve_t) 0x0015) -#define PSA_ECC_CURVE_SECP256K1 ((psa_ecc_curve_t) 0x0016) -#define PSA_ECC_CURVE_SECP256R1 ((psa_ecc_curve_t) 0x0017) -#define PSA_ECC_CURVE_SECP384R1 ((psa_ecc_curve_t) 0x0018) -#define PSA_ECC_CURVE_SECP521R1 ((psa_ecc_curve_t) 0x0019) -#define PSA_ECC_CURVE_BRAINPOOL_P256R1 ((psa_ecc_curve_t) 0x001a) -#define PSA_ECC_CURVE_BRAINPOOL_P384R1 ((psa_ecc_curve_t) 0x001b) -#define PSA_ECC_CURVE_BRAINPOOL_P512R1 ((psa_ecc_curve_t) 0x001c) -/** Curve25519. - * - * This is the curve defined in Bernstein et al., - * _Curve25519: new Diffie-Hellman speed records_, LNCS 3958, 2006. - * The algorithm #PSA_ALG_ECDH performs X25519 when used with this curve. - */ -#define PSA_ECC_CURVE_CURVE25519 ((psa_ecc_curve_t) 0x001d) -/** Curve448 - * - * This is the curve defined in Hamburg, - * _Ed448-Goldilocks, a new elliptic curve_, NIST ECC Workshop, 2015. - * The algorithm #PSA_ALG_ECDH performs X448 when used with this curve. - */ -#define PSA_ECC_CURVE_CURVE448 ((psa_ecc_curve_t) 0x001e) - -/** Minimum value for a vendor-defined ECC curve identifier - * - * The range for vendor-defined curve identifiers is a subset of the IANA - * registry private use range, `0xfe00` - `0xfeff`. - */ -#define PSA_ECC_CURVE_VENDOR_MIN ((psa_ecc_curve_t) 0xfe00) -/** Maximum value for a vendor-defined ECC curve identifier - * - * The range for vendor-defined curve identifiers is a subset of the IANA - * registry private use range, `0xfe00` - `0xfeff`. - */ -#define PSA_ECC_CURVE_VENDOR_MAX ((psa_ecc_curve_t) 0xfe7f) - -#define PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE ((psa_key_type_t)0x60040000) -#define PSA_KEY_TYPE_DH_KEY_PAIR_BASE ((psa_key_type_t)0x70040000) -#define PSA_KEY_TYPE_DH_GROUP_MASK ((psa_key_type_t)0x0000ffff) -/** Diffie-Hellman key pair. - * - * \param group A value of type ::psa_dh_group_t that identifies the - * Diffie-Hellman group to be used. - */ -#define PSA_KEY_TYPE_DH_KEY_PAIR(group) \ - (PSA_KEY_TYPE_DH_KEY_PAIR_BASE | (group)) -/** Diffie-Hellman public key. - * - * \param group A value of type ::psa_dh_group_t that identifies the - * Diffie-Hellman group to be used. - */ -#define PSA_KEY_TYPE_DH_PUBLIC_KEY(group) \ - (PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE | (group)) - -/** Whether a key type is a Diffie-Hellman key (pair or public-only). */ -#define PSA_KEY_TYPE_IS_DH(type) \ - ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) & \ - ~PSA_KEY_TYPE_DH_GROUP_MASK) == PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE) -/** Whether a key type is a Diffie-Hellman key pair. */ -#define PSA_KEY_TYPE_IS_DH_KEY_PAIR(type) \ - (((type) & ~PSA_KEY_TYPE_DH_GROUP_MASK) == \ - PSA_KEY_TYPE_DH_KEY_PAIR_BASE) -/** Whether a key type is a Diffie-Hellman public key. */ -#define PSA_KEY_TYPE_IS_DH_PUBLIC_KEY(type) \ - (((type) & ~PSA_KEY_TYPE_DH_GROUP_MASK) == \ - PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE) - -/** Extract the group from a Diffie-Hellman key type. */ -#define PSA_KEY_TYPE_GET_GROUP(type) \ - ((psa_dh_group_t) (PSA_KEY_TYPE_IS_DH(type) ? \ - ((type) & PSA_KEY_TYPE_DH_GROUP_MASK) : \ - 0)) - -/* The encoding of group identifiers is currently aligned with the - * TLS Supported Groups Registry (formerly known as the - * TLS EC Named Curve Registry) - * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 - * The values are defined by RFC 7919. */ -#define PSA_DH_GROUP_FFDHE2048 ((psa_dh_group_t) 0x0100) -#define PSA_DH_GROUP_FFDHE3072 ((psa_dh_group_t) 0x0101) -#define PSA_DH_GROUP_FFDHE4096 ((psa_dh_group_t) 0x0102) -#define PSA_DH_GROUP_FFDHE6144 ((psa_dh_group_t) 0x0103) -#define PSA_DH_GROUP_FFDHE8192 ((psa_dh_group_t) 0x0104) - -/** Minimum value for a vendor-defined Diffie Hellman group identifier - * - * The range for vendor-defined group identifiers is a subset of the IANA - * registry private use range, `0x01fc` - `0x01ff`. - */ -#define PSA_DH_GROUP_VENDOR_MIN ((psa_dh_group_t) 0x01fc) -/** Maximum value for a vendor-defined Diffie Hellman group identifier - * - * The range for vendor-defined group identifiers is a subset of the IANA - * registry private use range, `0x01fc` - `0x01ff`. - */ -#define PSA_DH_GROUP_VENDOR_MAX ((psa_dh_group_t) 0x01fd) - -/** The block size of a block cipher. - * - * \param type A cipher key type (value of type #psa_key_type_t). - * - * \return The block size for a block cipher, or 1 for a stream cipher. - * The return value is undefined if \p type is not a supported - * cipher key type. - * - * \note It is possible to build stream cipher algorithms on top of a block - * cipher, for example CTR mode (#PSA_ALG_CTR). - * This macro only takes the key type into account, so it cannot be - * used to determine the size of the data that #psa_cipher_update() - * might buffer for future processing in general. - * - * \note This macro returns a compile-time constant if its argument is one. - * - * \warning This macro may evaluate its argument multiple times. - */ -#define PSA_BLOCK_CIPHER_BLOCK_SIZE(type) \ - ( \ - (type) == PSA_KEY_TYPE_AES ? 16 : \ - (type) == PSA_KEY_TYPE_DES ? 8 : \ - (type) == PSA_KEY_TYPE_CAMELLIA ? 16 : \ - (type) == PSA_KEY_TYPE_ARC4 ? 1 : \ - (type) == PSA_KEY_TYPE_CHACHA20 ? 1 : \ - 0) - -/** Vendor-defined algorithm flag. - * - * Algorithms defined by this standard will never have the #PSA_ALG_VENDOR_FLAG - * bit set. Vendors who define additional algorithms must use an encoding with - * the #PSA_ALG_VENDOR_FLAG bit set and should respect the bitwise structure - * used by standard encodings whenever practical. - */ -#define PSA_ALG_VENDOR_FLAG ((psa_algorithm_t)0x80000000) - -#define PSA_ALG_CATEGORY_MASK ((psa_algorithm_t)0x7f000000) -#define PSA_ALG_CATEGORY_HASH ((psa_algorithm_t)0x01000000) -#define PSA_ALG_CATEGORY_MAC ((psa_algorithm_t)0x02000000) -#define PSA_ALG_CATEGORY_CIPHER ((psa_algorithm_t)0x04000000) -#define PSA_ALG_CATEGORY_AEAD ((psa_algorithm_t)0x06000000) -#define PSA_ALG_CATEGORY_SIGN ((psa_algorithm_t)0x10000000) -#define PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION ((psa_algorithm_t)0x12000000) -#define PSA_ALG_CATEGORY_KEY_DERIVATION ((psa_algorithm_t)0x20000000) -#define PSA_ALG_CATEGORY_KEY_AGREEMENT ((psa_algorithm_t)0x30000000) - -/** Whether an algorithm is vendor-defined. - * - * See also #PSA_ALG_VENDOR_FLAG. - */ -#define PSA_ALG_IS_VENDOR_DEFINED(alg) \ - (((alg) & PSA_ALG_VENDOR_FLAG) != 0) - -/** Whether the specified algorithm is a hash algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a hash algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_HASH(alg) \ - (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_HASH) - -/** Whether the specified algorithm is a MAC algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a MAC algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_MAC(alg) \ - (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_MAC) - -/** Whether the specified algorithm is a symmetric cipher algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a symmetric cipher algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_CIPHER(alg) \ - (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_CIPHER) - -/** Whether the specified algorithm is an authenticated encryption - * with associated data (AEAD) algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is an AEAD algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_AEAD(alg) \ - (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_AEAD) - -/** Whether the specified algorithm is a public-key signature algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a public-key signature algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_SIGN(alg) \ - (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_SIGN) - -/** Whether the specified algorithm is a public-key encryption algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a public-key encryption algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg) \ - (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION) - -/** Whether the specified algorithm is a key agreement algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a key agreement algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_KEY_AGREEMENT(alg) \ - (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_AGREEMENT) - -/** Whether the specified algorithm is a key derivation algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a key derivation algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_KEY_DERIVATION(alg) \ - (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_DERIVATION) - -#define PSA_ALG_HASH_MASK ((psa_algorithm_t)0x000000ff) -/** MD2 */ -#define PSA_ALG_MD2 ((psa_algorithm_t)0x01000001) -/** MD4 */ -#define PSA_ALG_MD4 ((psa_algorithm_t)0x01000002) -/** MD5 */ -#define PSA_ALG_MD5 ((psa_algorithm_t)0x01000003) -/** PSA_ALG_RIPEMD160 */ -#define PSA_ALG_RIPEMD160 ((psa_algorithm_t)0x01000004) -/** SHA1 */ -#define PSA_ALG_SHA_1 ((psa_algorithm_t)0x01000005) -/** SHA2-224 */ -#define PSA_ALG_SHA_224 ((psa_algorithm_t)0x01000008) -/** SHA2-256 */ -#define PSA_ALG_SHA_256 ((psa_algorithm_t)0x01000009) -/** SHA2-384 */ -#define PSA_ALG_SHA_384 ((psa_algorithm_t)0x0100000a) -/** SHA2-512 */ -#define PSA_ALG_SHA_512 ((psa_algorithm_t)0x0100000b) -/** SHA2-512/224 */ -#define PSA_ALG_SHA_512_224 ((psa_algorithm_t)0x0100000c) -/** SHA2-512/256 */ -#define PSA_ALG_SHA_512_256 ((psa_algorithm_t)0x0100000d) -/** SHA3-224 */ -#define PSA_ALG_SHA3_224 ((psa_algorithm_t)0x01000010) -/** SHA3-256 */ -#define PSA_ALG_SHA3_256 ((psa_algorithm_t)0x01000011) -/** SHA3-384 */ -#define PSA_ALG_SHA3_384 ((psa_algorithm_t)0x01000012) -/** SHA3-512 */ -#define PSA_ALG_SHA3_512 ((psa_algorithm_t)0x01000013) - -/** In a hash-and-sign algorithm policy, allow any hash algorithm. - * - * This value may be used to form the algorithm usage field of a policy - * for a signature algorithm that is parametrized by a hash. The key - * may then be used to perform operations using the same signature - * algorithm parametrized with any supported hash. - * - * That is, suppose that `PSA_xxx_SIGNATURE` is one of the following macros: - * - #PSA_ALG_RSA_PKCS1V15_SIGN, #PSA_ALG_RSA_PSS, - * - #PSA_ALG_ECDSA, #PSA_ALG_DETERMINISTIC_ECDSA. - * Then you may create and use a key as follows: - * - Set the key usage field using #PSA_ALG_ANY_HASH, for example: - * ``` - * psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); // or VERIFY - * psa_set_key_algorithm(&attributes, PSA_xxx_SIGNATURE(PSA_ALG_ANY_HASH)); - * ``` - * - Import or generate key material. - * - Call psa_sign_hash() or psa_verify_hash(), passing - * an algorithm built from `PSA_xxx_SIGNATURE` and a specific hash. Each - * call to sign or verify a message may use a different hash. - * ``` - * psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA_256), ...); - * psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA_512), ...); - * psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA3_256), ...); - * ``` - * - * This value may not be used to build other algorithms that are - * parametrized over a hash. For any valid use of this macro to build - * an algorithm \c alg, #PSA_ALG_IS_HASH_AND_SIGN(\c alg) is true. - * - * This value may not be used to build an algorithm specification to - * perform an operation. It is only valid to build policies. - */ -#define PSA_ALG_ANY_HASH ((psa_algorithm_t)0x010000ff) - -#define PSA_ALG_MAC_SUBCATEGORY_MASK ((psa_algorithm_t)0x00c00000) -#define PSA_ALG_HMAC_BASE ((psa_algorithm_t)0x02800000) -/** Macro to build an HMAC algorithm. - * - * For example, #PSA_ALG_HMAC(#PSA_ALG_SHA_256) is HMAC-SHA-256. - * - * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true). - * - * \return The corresponding HMAC algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_HMAC(hash_alg) \ - (PSA_ALG_HMAC_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) - -#define PSA_ALG_HMAC_GET_HASH(hmac_alg) \ - (PSA_ALG_CATEGORY_HASH | ((hmac_alg) & PSA_ALG_HASH_MASK)) - -/** Whether the specified algorithm is an HMAC algorithm. - * - * HMAC is a family of MAC algorithms that are based on a hash function. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is an HMAC algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_HMAC(alg) \ - (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \ - PSA_ALG_HMAC_BASE) - -/* In the encoding of a MAC algorithm, the bits corresponding to - * PSA_ALG_MAC_TRUNCATION_MASK encode the length to which the MAC is - * truncated. As an exception, the value 0 means the untruncated algorithm, - * whatever its length is. The length is encoded in 6 bits, so it can - * reach up to 63; the largest MAC is 64 bytes so its trivial truncation - * to full length is correctly encoded as 0 and any non-trivial truncation - * is correctly encoded as a value between 1 and 63. */ -#define PSA_ALG_MAC_TRUNCATION_MASK ((psa_algorithm_t)0x00003f00) -#define PSA_MAC_TRUNCATION_OFFSET 8 - -/** Macro to build a truncated MAC algorithm. - * - * A truncated MAC algorithm is identical to the corresponding MAC - * algorithm except that the MAC value for the truncated algorithm - * consists of only the first \p mac_length bytes of the MAC value - * for the untruncated algorithm. - * - * \note This macro may allow constructing algorithm identifiers that - * are not valid, either because the specified length is larger - * than the untruncated MAC or because the specified length is - * smaller than permitted by the implementation. - * - * \note It is implementation-defined whether a truncated MAC that - * is truncated to the same length as the MAC of the untruncated - * algorithm is considered identical to the untruncated algorithm - * for policy comparison purposes. - * - * \param mac_alg A MAC algorithm identifier (value of type - * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg) - * is true). This may be a truncated or untruncated - * MAC algorithm. - * \param mac_length Desired length of the truncated MAC in bytes. - * This must be at most the full length of the MAC - * and must be at least an implementation-specified - * minimum. The implementation-specified minimum - * shall not be zero. - * - * \return The corresponding MAC algorithm with the specified - * length. - * \return Unspecified if \p alg is not a supported - * MAC algorithm or if \p mac_length is too small or - * too large for the specified MAC algorithm. - */ -#define PSA_ALG_TRUNCATED_MAC(mac_alg, mac_length) \ - (((mac_alg) & ~PSA_ALG_MAC_TRUNCATION_MASK) | \ - ((mac_length) << PSA_MAC_TRUNCATION_OFFSET & PSA_ALG_MAC_TRUNCATION_MASK)) - -/** Macro to build the base MAC algorithm corresponding to a truncated - * MAC algorithm. - * - * \param mac_alg A MAC algorithm identifier (value of type - * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg) - * is true). This may be a truncated or untruncated - * MAC algorithm. - * - * \return The corresponding base MAC algorithm. - * \return Unspecified if \p alg is not a supported - * MAC algorithm. - */ -#define PSA_ALG_FULL_LENGTH_MAC(mac_alg) \ - ((mac_alg) & ~PSA_ALG_MAC_TRUNCATION_MASK) - -/** Length to which a MAC algorithm is truncated. - * - * \param mac_alg A MAC algorithm identifier (value of type - * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg) - * is true). - * - * \return Length of the truncated MAC in bytes. - * \return 0 if \p alg is a non-truncated MAC algorithm. - * \return Unspecified if \p alg is not a supported - * MAC algorithm. - */ -#define PSA_MAC_TRUNCATED_LENGTH(mac_alg) \ - (((mac_alg) & PSA_ALG_MAC_TRUNCATION_MASK) >> PSA_MAC_TRUNCATION_OFFSET) - -#define PSA_ALG_CIPHER_MAC_BASE ((psa_algorithm_t)0x02c00000) -/** The CBC-MAC construction over a block cipher - * - * \warning CBC-MAC is insecure in many cases. - * A more secure mode, such as #PSA_ALG_CMAC, is recommended. - */ -#define PSA_ALG_CBC_MAC ((psa_algorithm_t)0x02c00001) -/** The CMAC construction over a block cipher */ -#define PSA_ALG_CMAC ((psa_algorithm_t)0x02c00002) - -/** Whether the specified algorithm is a MAC algorithm based on a block cipher. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a MAC algorithm based on a block cipher, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) \ - (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \ - PSA_ALG_CIPHER_MAC_BASE) - -#define PSA_ALG_CIPHER_STREAM_FLAG ((psa_algorithm_t)0x00800000) -#define PSA_ALG_CIPHER_FROM_BLOCK_FLAG ((psa_algorithm_t)0x00400000) - -/** Whether the specified algorithm is a stream cipher. - * - * A stream cipher is a symmetric cipher that encrypts or decrypts messages - * by applying a bitwise-xor with a stream of bytes that is generated - * from a key. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a stream cipher algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier or if it is not a symmetric cipher algorithm. - */ -#define PSA_ALG_IS_STREAM_CIPHER(alg) \ - (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_CIPHER_STREAM_FLAG)) == \ - (PSA_ALG_CATEGORY_CIPHER | PSA_ALG_CIPHER_STREAM_FLAG)) - -/** The ARC4 stream cipher algorithm. - */ -#define PSA_ALG_ARC4 ((psa_algorithm_t)0x04800001) - -/** The ChaCha20 stream cipher. - * - * ChaCha20 is defined in RFC 7539. - * - * The nonce size for psa_cipher_set_iv() or psa_cipher_generate_iv() - * must be 12. - * - * The initial block counter is always 0. - * - */ -#define PSA_ALG_CHACHA20 ((psa_algorithm_t)0x04800005) - -/** The CTR stream cipher mode. - * - * CTR is a stream cipher which is built from a block cipher. - * The underlying block cipher is determined by the key type. - * For example, to use AES-128-CTR, use this algorithm with - * a key of type #PSA_KEY_TYPE_AES and a length of 128 bits (16 bytes). - */ -#define PSA_ALG_CTR ((psa_algorithm_t)0x04c00001) - -/** The CFB stream cipher mode. - * - * The underlying block cipher is determined by the key type. - */ -#define PSA_ALG_CFB ((psa_algorithm_t)0x04c00002) - -/** The OFB stream cipher mode. - * - * The underlying block cipher is determined by the key type. - */ -#define PSA_ALG_OFB ((psa_algorithm_t)0x04c00003) - -/** The XTS cipher mode. - * - * XTS is a cipher mode which is built from a block cipher. It requires at - * least one full block of input, but beyond this minimum the input - * does not need to be a whole number of blocks. - */ -#define PSA_ALG_XTS ((psa_algorithm_t)0x044000ff) - -/** The CBC block cipher chaining mode, with no padding. - * - * The underlying block cipher is determined by the key type. - * - * This symmetric cipher mode can only be used with messages whose lengths - * are whole number of blocks for the chosen block cipher. - */ -#define PSA_ALG_CBC_NO_PADDING ((psa_algorithm_t)0x04600100) - -/** The CBC block cipher chaining mode with PKCS#7 padding. - * - * The underlying block cipher is determined by the key type. - * - * This is the padding method defined by PKCS#7 (RFC 2315) §10.3. - */ -#define PSA_ALG_CBC_PKCS7 ((psa_algorithm_t)0x04600101) - -#define PSA_ALG_AEAD_FROM_BLOCK_FLAG ((psa_algorithm_t)0x00400000) - -/** Whether the specified algorithm is an AEAD mode on a block cipher. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is an AEAD algorithm which is an AEAD mode based on - * a block cipher, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) \ - (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_AEAD_FROM_BLOCK_FLAG)) == \ - (PSA_ALG_CATEGORY_AEAD | PSA_ALG_AEAD_FROM_BLOCK_FLAG)) - -/** The CCM authenticated encryption algorithm. - * - * The underlying block cipher is determined by the key type. - */ -#define PSA_ALG_CCM ((psa_algorithm_t)0x06401001) - -/** The GCM authenticated encryption algorithm. - * - * The underlying block cipher is determined by the key type. - */ -#define PSA_ALG_GCM ((psa_algorithm_t)0x06401002) - -/** The Chacha20-Poly1305 AEAD algorithm. - * - * The ChaCha20_Poly1305 construction is defined in RFC 7539. - * - * Implementations must support 12-byte nonces, may support 8-byte nonces, - * and should reject other sizes. - * - * Implementations must support 16-byte tags and should reject other sizes. - */ -#define PSA_ALG_CHACHA20_POLY1305 ((psa_algorithm_t)0x06001005) - -/* In the encoding of a AEAD algorithm, the bits corresponding to - * PSA_ALG_AEAD_TAG_LENGTH_MASK encode the length of the AEAD tag. - * The constants for default lengths follow this encoding. - */ -#define PSA_ALG_AEAD_TAG_LENGTH_MASK ((psa_algorithm_t)0x00003f00) -#define PSA_AEAD_TAG_LENGTH_OFFSET 8 - -/** Macro to build a shortened AEAD algorithm. - * - * A shortened AEAD algorithm is similar to the corresponding AEAD - * algorithm, but has an authentication tag that consists of fewer bytes. - * Depending on the algorithm, the tag length may affect the calculation - * of the ciphertext. - * - * \param aead_alg An AEAD algorithm identifier (value of type - * #psa_algorithm_t such that #PSA_ALG_IS_AEAD(\p alg) - * is true). - * \param tag_length Desired length of the authentication tag in bytes. - * - * \return The corresponding AEAD algorithm with the specified - * length. - * \return Unspecified if \p alg is not a supported - * AEAD algorithm or if \p tag_length is not valid - * for the specified AEAD algorithm. - */ -#define PSA_ALG_AEAD_WITH_TAG_LENGTH(aead_alg, tag_length) \ - (((aead_alg) & ~PSA_ALG_AEAD_TAG_LENGTH_MASK) | \ - ((tag_length) << PSA_AEAD_TAG_LENGTH_OFFSET & \ - PSA_ALG_AEAD_TAG_LENGTH_MASK)) - -/** Calculate the corresponding AEAD algorithm with the default tag length. - * - * \param aead_alg An AEAD algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * - * \return The corresponding AEAD algorithm with the default - * tag length for that algorithm. - */ -#define PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH(aead_alg) \ - ( \ - PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, PSA_ALG_CCM) \ - PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, PSA_ALG_GCM) \ - PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, PSA_ALG_CHACHA20_POLY1305) \ - 0) -#define PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, ref) \ - PSA_ALG_AEAD_WITH_TAG_LENGTH(aead_alg, 0) == \ - PSA_ALG_AEAD_WITH_TAG_LENGTH(ref, 0) ? \ - ref : - -#define PSA_ALG_RSA_PKCS1V15_SIGN_BASE ((psa_algorithm_t)0x10020000) -/** RSA PKCS#1 v1.5 signature with hashing. - * - * This is the signature scheme defined by RFC 8017 - * (PKCS#1: RSA Cryptography Specifications) under the name - * RSASSA-PKCS1-v1_5. - * - * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true). - * This includes #PSA_ALG_ANY_HASH - * when specifying the algorithm in a usage policy. - * - * \return The corresponding RSA PKCS#1 v1.5 signature algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_RSA_PKCS1V15_SIGN(hash_alg) \ - (PSA_ALG_RSA_PKCS1V15_SIGN_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) -/** Raw PKCS#1 v1.5 signature. - * - * The input to this algorithm is the DigestInfo structure used by - * RFC 8017 (PKCS#1: RSA Cryptography Specifications), §9.2 - * steps 3–6. - */ -#define PSA_ALG_RSA_PKCS1V15_SIGN_RAW PSA_ALG_RSA_PKCS1V15_SIGN_BASE -#define PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) \ - (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PKCS1V15_SIGN_BASE) - -#define PSA_ALG_RSA_PSS_BASE ((psa_algorithm_t)0x10030000) -/** RSA PSS signature with hashing. - * - * This is the signature scheme defined by RFC 8017 - * (PKCS#1: RSA Cryptography Specifications) under the name - * RSASSA-PSS, with the message generation function MGF1, and with - * a salt length equal to the length of the hash. The specified - * hash algorithm is used to hash the input message, to create the - * salted hash, and for the mask generation. - * - * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true). - * This includes #PSA_ALG_ANY_HASH - * when specifying the algorithm in a usage policy. - * - * \return The corresponding RSA PSS signature algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_RSA_PSS(hash_alg) \ - (PSA_ALG_RSA_PSS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) -#define PSA_ALG_IS_RSA_PSS(alg) \ - (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PSS_BASE) - -#define PSA_ALG_ECDSA_BASE ((psa_algorithm_t)0x10060000) -/** ECDSA signature with hashing. - * - * This is the ECDSA signature scheme defined by ANSI X9.62, - * with a random per-message secret number (*k*). - * - * The representation of the signature as a byte string consists of - * the concatentation of the signature values *r* and *s*. Each of - * *r* and *s* is encoded as an *N*-octet string, where *N* is the length - * of the base point of the curve in octets. Each value is represented - * in big-endian order (most significant octet first). - * - * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true). - * This includes #PSA_ALG_ANY_HASH - * when specifying the algorithm in a usage policy. - * - * \return The corresponding ECDSA signature algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_ECDSA(hash_alg) \ - (PSA_ALG_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) -/** ECDSA signature without hashing. - * - * This is the same signature scheme as #PSA_ALG_ECDSA(), but - * without specifying a hash algorithm. This algorithm may only be - * used to sign or verify a sequence of bytes that should be an - * already-calculated hash. Note that the input is padded with - * zeros on the left or truncated on the left as required to fit - * the curve size. - */ -#define PSA_ALG_ECDSA_ANY PSA_ALG_ECDSA_BASE -#define PSA_ALG_DETERMINISTIC_ECDSA_BASE ((psa_algorithm_t)0x10070000) -/** Deterministic ECDSA signature with hashing. - * - * This is the deterministic ECDSA signature scheme defined by RFC 6979. - * - * The representation of a signature is the same as with #PSA_ALG_ECDSA(). - * - * Note that when this algorithm is used for verification, signatures - * made with randomized ECDSA (#PSA_ALG_ECDSA(\p hash_alg)) with the - * same private key are accepted. In other words, - * #PSA_ALG_DETERMINISTIC_ECDSA(\p hash_alg) differs from - * #PSA_ALG_ECDSA(\p hash_alg) only for signature, not for verification. - * - * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true). - * This includes #PSA_ALG_ANY_HASH - * when specifying the algorithm in a usage policy. - * - * \return The corresponding deterministic ECDSA signature - * algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_DETERMINISTIC_ECDSA(hash_alg) \ - (PSA_ALG_DETERMINISTIC_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) -#define PSA_ALG_ECDSA_DETERMINISTIC_FLAG ((psa_algorithm_t)0x00010000) -#define PSA_ALG_IS_ECDSA(alg) \ - (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_ECDSA_DETERMINISTIC_FLAG) == \ - PSA_ALG_ECDSA_BASE) -#define PSA_ALG_ECDSA_IS_DETERMINISTIC(alg) \ - (((alg) & PSA_ALG_ECDSA_DETERMINISTIC_FLAG) != 0) -#define PSA_ALG_IS_DETERMINISTIC_ECDSA(alg) \ - (PSA_ALG_IS_ECDSA(alg) && PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) -#define PSA_ALG_IS_RANDOMIZED_ECDSA(alg) \ - (PSA_ALG_IS_ECDSA(alg) && !PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) - -/** Whether the specified algorithm is a hash-and-sign algorithm. - * - * Hash-and-sign algorithms are public-key signature algorithms structured - * in two parts: first the calculation of a hash in a way that does not - * depend on the key, then the calculation of a signature from the - * hash value and the key. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a hash-and-sign algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_HASH_AND_SIGN(alg) \ - (PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || \ - PSA_ALG_IS_ECDSA(alg)) - -/** Get the hash used by a hash-and-sign signature algorithm. - * - * A hash-and-sign algorithm is a signature algorithm which is - * composed of two phases: first a hashing phase which does not use - * the key and produces a hash of the input message, then a signing - * phase which only uses the hash and the key and not the message - * itself. - * - * \param alg A signature algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_SIGN(\p alg) is true). - * - * \return The underlying hash algorithm if \p alg is a hash-and-sign - * algorithm. - * \return 0 if \p alg is a signature algorithm that does not - * follow the hash-and-sign structure. - * \return Unspecified if \p alg is not a signature algorithm or - * if it is not supported by the implementation. - */ -#define PSA_ALG_SIGN_GET_HASH(alg) \ - (PSA_ALG_IS_HASH_AND_SIGN(alg) ? \ - ((alg) & PSA_ALG_HASH_MASK) == 0 ? /*"raw" algorithm*/ 0 : \ - ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ - 0) - -/** RSA PKCS#1 v1.5 encryption. - */ -#define PSA_ALG_RSA_PKCS1V15_CRYPT ((psa_algorithm_t)0x12020000) - -#define PSA_ALG_RSA_OAEP_BASE ((psa_algorithm_t)0x12030000) -/** RSA OAEP encryption. - * - * This is the encryption scheme defined by RFC 8017 - * (PKCS#1: RSA Cryptography Specifications) under the name - * RSAES-OAEP, with the message generation function MGF1. - * - * \param hash_alg The hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true) to use - * for MGF1. - * - * \return The corresponding RSA OAEP signature algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_RSA_OAEP(hash_alg) \ - (PSA_ALG_RSA_OAEP_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) -#define PSA_ALG_IS_RSA_OAEP(alg) \ - (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_OAEP_BASE) -#define PSA_ALG_RSA_OAEP_GET_HASH(alg) \ - (PSA_ALG_IS_RSA_OAEP(alg) ? \ - ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ - 0) - -#define PSA_ALG_HKDF_BASE ((psa_algorithm_t)0x20000100) -/** Macro to build an HKDF algorithm. - * - * For example, `PSA_ALG_HKDF(PSA_ALG_SHA256)` is HKDF using HMAC-SHA-256. - * - * This key derivation algorithm uses the following inputs: - * - #PSA_KEY_DERIVATION_INPUT_SALT is the salt used in the "extract" step. - * It is optional; if omitted, the derivation uses an empty salt. - * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key used in the "extract" step. - * - #PSA_KEY_DERIVATION_INPUT_INFO is the info string used in the "expand" step. - * You must pass #PSA_KEY_DERIVATION_INPUT_SALT before #PSA_KEY_DERIVATION_INPUT_SECRET. - * You may pass #PSA_KEY_DERIVATION_INPUT_INFO at any time after steup and before - * starting to generate output. - * - * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true). - * - * \return The corresponding HKDF algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_HKDF(hash_alg) \ - (PSA_ALG_HKDF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) -/** Whether the specified algorithm is an HKDF algorithm. - * - * HKDF is a family of key derivation algorithms that are based on a hash - * function and the HMAC construction. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \c alg is an HKDF algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \c alg is not a supported - * key derivation algorithm identifier. - */ -#define PSA_ALG_IS_HKDF(alg) \ - (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_BASE) -#define PSA_ALG_HKDF_GET_HASH(hkdf_alg) \ - (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) - -#define PSA_ALG_TLS12_PRF_BASE ((psa_algorithm_t)0x20000200) -/** Macro to build a TLS-1.2 PRF algorithm. - * - * TLS 1.2 uses a custom pseudorandom function (PRF) for key schedule, - * specified in Section 5 of RFC 5246. It is based on HMAC and can be - * used with either SHA-256 or SHA-384. - * - * This key derivation algorithm uses the following inputs, which must be - * passed in the order given here: - * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed. - * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key. - * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label. - * - * For the application to TLS-1.2 key expansion, the seed is the - * concatenation of ServerHello.Random + ClientHello.Random, - * and the label is "key expansion". - * - * For example, `PSA_ALG_TLS12_PRF(PSA_ALG_SHA256)` represents the - * TLS 1.2 PRF using HMAC-SHA-256. - * - * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true). - * - * \return The corresponding TLS-1.2 PRF algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_TLS12_PRF(hash_alg) \ - (PSA_ALG_TLS12_PRF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) - -/** Whether the specified algorithm is a TLS-1.2 PRF algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \c alg is a TLS-1.2 PRF algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \c alg is not a supported - * key derivation algorithm identifier. - */ -#define PSA_ALG_IS_TLS12_PRF(alg) \ - (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_TLS12_PRF_BASE) -#define PSA_ALG_TLS12_PRF_GET_HASH(hkdf_alg) \ - (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) - -#define PSA_ALG_TLS12_PSK_TO_MS_BASE ((psa_algorithm_t)0x20000300) -/** Macro to build a TLS-1.2 PSK-to-MasterSecret algorithm. - * - * In a pure-PSK handshake in TLS 1.2, the master secret is derived - * from the PreSharedKey (PSK) through the application of padding - * (RFC 4279, Section 2) and the TLS-1.2 PRF (RFC 5246, Section 5). - * The latter is based on HMAC and can be used with either SHA-256 - * or SHA-384. - * - * This key derivation algorithm uses the following inputs, which must be - * passed in the order given here: - * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed. - * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key. - * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label. - * - * For the application to TLS-1.2, the seed (which is - * forwarded to the TLS-1.2 PRF) is the concatenation of the - * ClientHello.Random + ServerHello.Random, - * and the label is "master secret" or "extended master secret". - * - * For example, `PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA256)` represents the - * TLS-1.2 PSK to MasterSecret derivation PRF using HMAC-SHA-256. - * - * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true). - * - * \return The corresponding TLS-1.2 PSK to MS algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_TLS12_PSK_TO_MS(hash_alg) \ - (PSA_ALG_TLS12_PSK_TO_MS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) - -/** Whether the specified algorithm is a TLS-1.2 PSK to MS algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \c alg is a TLS-1.2 PSK to MS algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \c alg is not a supported - * key derivation algorithm identifier. - */ -#define PSA_ALG_IS_TLS12_PSK_TO_MS(alg) \ - (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_TLS12_PSK_TO_MS_BASE) -#define PSA_ALG_TLS12_PSK_TO_MS_GET_HASH(hkdf_alg) \ - (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) - -#define PSA_ALG_KEY_DERIVATION_MASK ((psa_algorithm_t)0x0803ffff) -#define PSA_ALG_KEY_AGREEMENT_MASK ((psa_algorithm_t)0x10fc0000) - -/** Macro to build a combined algorithm that chains a key agreement with - * a key derivation. - * - * \param ka_alg A key agreement algorithm (\c PSA_ALG_XXX value such - * that #PSA_ALG_IS_KEY_AGREEMENT(\p ka_alg) is true). - * \param kdf_alg A key derivation algorithm (\c PSA_ALG_XXX value such - * that #PSA_ALG_IS_KEY_DERIVATION(\p kdf_alg) is true). - * - * \return The corresponding key agreement and derivation - * algorithm. - * \return Unspecified if \p ka_alg is not a supported - * key agreement algorithm or \p kdf_alg is not a - * supported key derivation algorithm. - */ -#define PSA_ALG_KEY_AGREEMENT(ka_alg, kdf_alg) \ - ((ka_alg) | (kdf_alg)) - -#define PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) \ - (((alg) & PSA_ALG_KEY_DERIVATION_MASK) | PSA_ALG_CATEGORY_KEY_DERIVATION) - -#define PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) \ - (((alg) & PSA_ALG_KEY_AGREEMENT_MASK) | PSA_ALG_CATEGORY_KEY_AGREEMENT) - -/** Whether the specified algorithm is a raw key agreement algorithm. - * - * A raw key agreement algorithm is one that does not specify - * a key derivation function. - * Usually, raw key agreement algorithms are constructed directly with - * a \c PSA_ALG_xxx macro while non-raw key agreement algorithms are - * constructed with PSA_ALG_KEY_AGREEMENT(). - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a raw key agreement algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_RAW_KEY_AGREEMENT(alg) \ - (PSA_ALG_IS_KEY_AGREEMENT(alg) && \ - PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) == PSA_ALG_CATEGORY_KEY_DERIVATION) - -#define PSA_ALG_IS_KEY_DERIVATION_OR_AGREEMENT(alg) \ - ((PSA_ALG_IS_KEY_DERIVATION(alg) || PSA_ALG_IS_KEY_AGREEMENT(alg))) - -/** The finite-field Diffie-Hellman (DH) key agreement algorithm. - * - * The shared secret produced by key agreement is - * `g^{ab}` in big-endian format. - * It is `ceiling(m / 8)` bytes long where `m` is the size of the prime `p` - * in bits. - */ -#define PSA_ALG_FFDH ((psa_algorithm_t)0x30100000) - -/** Whether the specified algorithm is a finite field Diffie-Hellman algorithm. - * - * This includes the raw finite field Diffie-Hellman algorithm as well as - * finite-field Diffie-Hellman followed by any supporter key derivation - * algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \c alg is a finite field Diffie-Hellman algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \c alg is not a supported - * key agreement algorithm identifier. - */ -#define PSA_ALG_IS_FFDH(alg) \ - (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_FFDH) - -/** The elliptic curve Diffie-Hellman (ECDH) key agreement algorithm. - * - * The shared secret produced by key agreement is the x-coordinate of - * the shared secret point. It is always `ceiling(m / 8)` bytes long where - * `m` is the bit size associated with the curve, i.e. the bit size of the - * order of the curve's coordinate field. When `m` is not a multiple of 8, - * the byte containing the most significant bit of the shared secret - * is padded with zero bits. The byte order is either little-endian - * or big-endian depending on the curve type. - * - * - For Montgomery curves (curve types `PSA_ECC_CURVE_CURVEXXX`), - * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` - * in little-endian byte order. - * The bit size is 448 for Curve448 and 255 for Curve25519. - * - For Weierstrass curves over prime fields (curve types - * `PSA_ECC_CURVE_SECPXXX` and `PSA_ECC_CURVE_BRAINPOOL_PXXX`), - * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` - * in big-endian byte order. - * The bit size is `m = ceiling(log_2(p))` for the field `F_p`. - * - For Weierstrass curves over binary fields (curve types - * `PSA_ECC_CURVE_SECTXXX`), - * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` - * in big-endian byte order. - * The bit size is `m` for the field `F_{2^m}`. - */ -#define PSA_ALG_ECDH ((psa_algorithm_t)0x30200000) - -/** Whether the specified algorithm is an elliptic curve Diffie-Hellman - * algorithm. - * - * This includes the raw elliptic curve Diffie-Hellman algorithm as well as - * elliptic curve Diffie-Hellman followed by any supporter key derivation - * algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \c alg is an elliptic curve Diffie-Hellman algorithm, - * 0 otherwise. - * This macro may return either 0 or 1 if \c alg is not a supported - * key agreement algorithm identifier. - */ -#define PSA_ALG_IS_ECDH(alg) \ - (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_ECDH) - -/** Whether the specified algorithm encoding is a wildcard. - * - * Wildcard values may only be used to set the usage algorithm field in - * a policy, not to perform an operation. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \c alg is a wildcard algorithm encoding. - * \return 0 if \c alg is a non-wildcard algorithm encoding (suitable for - * an operation). - * \return This macro may return either 0 or 1 if \c alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_WILDCARD(alg) \ - (PSA_ALG_IS_HASH_AND_SIGN(alg) ? \ - PSA_ALG_SIGN_GET_HASH(alg) == PSA_ALG_ANY_HASH : \ - (alg) == PSA_ALG_ANY_HASH) - -/**@}*/ - -/** \defgroup key_lifetimes Key lifetimes - * @{ - */ - -/** A volatile key only exists as long as the handle to it is not closed. - * The key material is guaranteed to be erased on a power reset. - */ -#define PSA_KEY_LIFETIME_VOLATILE ((psa_key_lifetime_t)0x00000000) - -/** The default storage area for persistent keys. - * - * A persistent key remains in storage until it is explicitly destroyed or - * until the corresponding storage area is wiped. This specification does - * not define any mechanism to wipe a storage area, but implementations may - * provide their own mechanism (for example to perform a factory reset, - * to prepare for device refurbishment, or to uninstall an application). - * - * This lifetime value is the default storage area for the calling - * application. Implementations may offer other storage areas designated - * by other lifetime values as implementation-specific extensions. - */ -#define PSA_KEY_LIFETIME_PERSISTENT ((psa_key_lifetime_t)0x00000001) - -/** The minimum value for a key identifier chosen by the application. - */ -#define PSA_KEY_ID_USER_MIN ((psa_key_id_t)0x00000001) -/** The maximum value for a key identifier chosen by the application. - */ -#define PSA_KEY_ID_USER_MAX ((psa_key_id_t)0x3fffffff) -/** The minimum value for a key identifier chosen by the implementation. - */ -#define PSA_KEY_ID_VENDOR_MIN ((psa_key_id_t)0x40000000) -/** The maximum value for a key identifier chosen by the implementation. - */ -#define PSA_KEY_ID_VENDOR_MAX ((psa_key_id_t)0x7fffffff) - -/**@}*/ - -/** \defgroup policy Key policies - * @{ - */ - -/** Whether the key may be exported. - * - * A public key or the public part of a key pair may always be exported - * regardless of the value of this permission flag. - * - * If a key does not have export permission, implementations shall not - * allow the key to be exported in plain form from the cryptoprocessor, - * whether through psa_export_key() or through a proprietary interface. - * The key may however be exportable in a wrapped form, i.e. in a form - * where it is encrypted by another key. - */ -#define PSA_KEY_USAGE_EXPORT ((psa_key_usage_t)0x00000001) - -/** Whether the key may be copied. - * - * This flag allows the use of psa_copy_key() to make a copy of the key - * with the same policy or a more restrictive policy. - * - * For lifetimes for which the key is located in a secure element which - * enforce the non-exportability of keys, copying a key outside the secure - * element also requires the usage flag #PSA_KEY_USAGE_EXPORT. - * Copying the key inside the secure element is permitted with just - * #PSA_KEY_USAGE_COPY if the secure element supports it. - * For keys with the lifetime #PSA_KEY_LIFETIME_VOLATILE or - * #PSA_KEY_LIFETIME_PERSISTENT, the usage flag #PSA_KEY_USAGE_COPY - * is sufficient to permit the copy. - */ -#define PSA_KEY_USAGE_COPY ((psa_key_usage_t)0x00000002) - -/** Whether the key may be used to encrypt a message. - * - * This flag allows the key to be used for a symmetric encryption operation, - * for an AEAD encryption-and-authentication operation, - * or for an asymmetric encryption operation, - * if otherwise permitted by the key's type and policy. - * - * For a key pair, this concerns the public key. - */ -#define PSA_KEY_USAGE_ENCRYPT ((psa_key_usage_t)0x00000100) - -/** Whether the key may be used to decrypt a message. - * - * This flag allows the key to be used for a symmetric decryption operation, - * for an AEAD decryption-and-verification operation, - * or for an asymmetric decryption operation, - * if otherwise permitted by the key's type and policy. - * - * For a key pair, this concerns the private key. - */ -#define PSA_KEY_USAGE_DECRYPT ((psa_key_usage_t)0x00000200) - -/** Whether the key may be used to sign a message. - * - * This flag allows the key to be used for a MAC calculation operation - * or for an asymmetric signature operation, - * if otherwise permitted by the key's type and policy. - * - * For a key pair, this concerns the private key. - */ -#define PSA_KEY_USAGE_SIGN_HASH ((psa_key_usage_t)0x00000400) - -/** Whether the key may be used to verify a message signature. - * - * This flag allows the key to be used for a MAC verification operation - * or for an asymmetric signature verification operation, - * if otherwise permitted by by the key's type and policy. - * - * For a key pair, this concerns the public key. - */ -#define PSA_KEY_USAGE_VERIFY_HASH ((psa_key_usage_t)0x00000800) - -/** Whether the key may be used to derive other keys. - */ -#define PSA_KEY_USAGE_DERIVE ((psa_key_usage_t)0x00001000) - -/**@}*/ - -/** \defgroup derivation Key derivation - * @{ - */ - -/** A secret input for key derivation. - * - * This should be a key of type #PSA_KEY_TYPE_DERIVE - * (passed to psa_key_derivation_input_key()) - * or the shared secret resulting from a key agreement - * (obtained via psa_key_derivation_key_agreement()). - * - * The secret can also be a direct input (passed to - * key_derivation_input_bytes()). In this case, the derivation operation - * may not be used to derive keys: the operation will only allow - * psa_key_derivation_output_bytes(), not psa_key_derivation_output_key(). - */ -#define PSA_KEY_DERIVATION_INPUT_SECRET ((psa_key_derivation_step_t)0x0101) - -/** A label for key derivation. - * - * This should be a direct input. - * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. - */ -#define PSA_KEY_DERIVATION_INPUT_LABEL ((psa_key_derivation_step_t)0x0201) - -/** A salt for key derivation. - * - * This should be a direct input. - * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. - */ -#define PSA_KEY_DERIVATION_INPUT_SALT ((psa_key_derivation_step_t)0x0202) - -/** An information string for key derivation. - * - * This should be a direct input. - * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. - */ -#define PSA_KEY_DERIVATION_INPUT_INFO ((psa_key_derivation_step_t)0x0203) - -/** A seed for key derivation. - * - * This should be a direct input. - * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. - */ -#define PSA_KEY_DERIVATION_INPUT_SEED ((psa_key_derivation_step_t)0x0204) - -/**@}*/ - -#endif /* PSA_CRYPTO_VALUES_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/error.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/error.h deleted file mode 100644 index 439dba4..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/error.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/** - * \file psa/error.h - * \brief Standard error codes for the SPM and RoT Services - */ - -#ifndef __PSA_ERROR_H__ -#define __PSA_ERROR_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* If #PSA_SUCCESS is already defined, it means that #psa_status_t - * is also defined in an external header, so prevent its multiple - * definition. - */ -#ifndef PSA_SUCCESS -typedef int32_t psa_status_t; -#endif - -#define PSA_SUCCESS ((psa_status_t)0) - -#define PSA_ERROR_PROGRAMMER_ERROR ((psa_status_t)-129) -#define PSA_ERROR_CONNECTION_REFUSED ((psa_status_t)-130) -#define PSA_ERROR_CONNECTION_BUSY ((psa_status_t)-131) -#define PSA_ERROR_GENERIC_ERROR ((psa_status_t)-132) -#define PSA_ERROR_NOT_PERMITTED ((psa_status_t)-133) -#define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)-134) -#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)-135) -#define PSA_ERROR_INVALID_HANDLE ((psa_status_t)-136) -#define PSA_ERROR_BAD_STATE ((psa_status_t)-137) -#define PSA_ERROR_BUFFER_TOO_SMALL ((psa_status_t)-138) -#define PSA_ERROR_ALREADY_EXISTS ((psa_status_t)-139) -#define PSA_ERROR_DOES_NOT_EXIST ((psa_status_t)-140) -#define PSA_ERROR_INSUFFICIENT_MEMORY ((psa_status_t)-141) -#define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)-142) -#define PSA_ERROR_INSUFFICIENT_DATA ((psa_status_t)-143) -#define PSA_ERROR_SERVICE_FAILURE ((psa_status_t)-144) -#define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t)-145) -#define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)-146) -#define PSA_ERROR_HARDWARE_FAILURE ((psa_status_t)-147) -#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_ERROR_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/initial_attestation.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/initial_attestation.h deleted file mode 100644 index c125a4d..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/initial_attestation.h +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (c) 2018-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/***************************************************************************/ -/* DRAFT UNDER REVIEW */ -/* These APIs are still evolving and are meant as a prototype for review.*/ -/* The APIs will change depending on feedback and will be firmed up */ -/* to a stable set of APIs once all the feedback has been considered. */ -/***************************************************************************/ - -#ifndef __PSA_INITIAL_ATTESTATION_H__ -#define __PSA_INITIAL_ATTESTATION_H__ - -#include -#include -#include -#include "psa/crypto.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief PSA INITIAL ATTESTATION API version - * - * Initial attestation API version is: 1.0.0 - */ -#define PSA_INITIAL_ATTEST_API_VERSION_MAJOR (1) -#define PSA_INITIAL_ATTEST_API_VERSION_MINOR (0) - -/** - * The allowed size of input challenge in bytes: 32, 48, 64 - * Challenge can be a nonce from server - * or the hash of some combined data : nonce + attested data by caller. - */ -#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32 (32u) -#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48 (48u) -#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64 (64u) - -/** - * The maximum size of an attestation token that can be generated by the - * attestation service. Used to configure buffers for services that verify the - * produced tokens. - */ -#define PSA_INITIAL_ATTEST_MAX_TOKEN_SIZE (0x400) - -/** - * The list of fixed claims in the initial attestation token is still evolving, - * you can expect slight changes in the future. - * - * The initial attestation token is planned to be aligned with future version of - * Entity Attestation Token format: - * https://tools.ietf.org/html/draft-mandyam-eat-01 - * - * Current list of claims: - * - Challenge: Input object from caller. Can be a single nonce from server - * or hash of nonce and attested data. It is intended to provide - * freshness to reports and the caller has responsibility to - * arrange this. Allowed length: 32, 48, 64 bytes. The claim is - * modeled to be eventually represented by the EAT standard - * claim nonce. Until such a time as that standard exists, - * the claim will be represented by a custom claim. Value - * is encoded as byte string. - * - * - Instance ID: It represents the unique identifier of the instance. In the - * PSA definition it is a hash of the public attestation key - * of the instance. The claim is modeled to be eventually - * represented by the EAT standard claim UEID of type GUID. - * Until such a time as that standard exists, the claim will be - * represented by a custom claim Value is encoded as byte - * string. - * - * - Verification service indicator: Optional, recommended claim. It is used by - * a Relying Party to locate a validation service for the token. - * The value is a text string that can be used to locate the - * service or a URL specifying the address of the service. The - * claim is modeled to be eventually represented by the EAT - * standard claim origination. Until such a time as that - * standard exists, the claim will be represented by a custom - * claim. Value is encoded as text string. - * - * - Profile definition: Optional, recommended claim. It contains the name of - * a document that describes the 'profile' of the token, being - * a full description of the claims, their usage, verification - * and token signing. The document name may include versioning. - * Custom claim with a value encoded as text string. - * - * - Implementation ID: It represents the original implementation signer of the - * attestation key and identifies the contract between the - * report and verification. A verification service will use this - * claim to locate the details of the verification process. - * Custom claim with a value encoded as byte string. - * - * - Security lifecycle: It represents the current lifecycle state of the - * instance. Custom claim with a value encoded as integer that - * is divided to convey a major state and a minor state. The - * PSA state and implementation state are encoded as follows: - * - version[15:8] - PSA lifecycle state - major - * - version[7:0] - IMPLEMENTATION DEFINED state - minor - * Possible PSA lifecycle states: - * - Unknown (0x1000u), - * - PSA_RoT_Provisioning (0x2000u), - * - Secured (0x3000u), - * - Non_PSA_RoT_Debug(0x4000u), - * - Recoverable_PSA_RoT_Debug (0x5000u), - * - Decommissioned (0x6000u) - * - * - Client ID: The partition ID of that secure partition or non-secure - * thread who called the initial attestation API. Custom claim - * with a value encoded as a *signed* integer. Negative number - * represents non-secure caller, positive numbers represents - * secure callers, zero is invalid. - * - * - HW version: Optional claim. Globally unique number in EAN-13 format - * identifying the GDSII that went to fabrication, HW and ROM. - * It can be used to reference the security level of the PSA-ROT - * via a certification website. Custom claim with a value is - * encoded as text string. - - * - Boot seed: It represents a random value created at system boot time that - * will allow differentiation of reports from different system - * sessions. The size is 32 bytes. Custom claim with a value is - * encoded as byte string. - * - * - Software components: Recommended claim. It represents the software state - * of the system. The value of the claim is an array of CBOR map - * entries, with one entry per software component within the - * device. Each map contains multiple claims that describe - * evidence about the details of the software component. - * - * - Measurement type: Optional claim. It represents the role of the - * software component. Value is encoded as short(!) text - * string. - * - * - Measurement value: It represents a hash of the invariant software - * component in memory at start-up time. The value must be a - * cryptographic hash of 256 bits or stronger.Value is - * encoded as byte string. - * - * - Version: Optional claim. It represents the issued software version. - * Value is encoded as text string. - * - * - Signer ID: It represents the hash of a signing authority public key. - * Value is encoded as byte string. - * - * - Measurement description: Optional claim. It represents the way in which - * the measurement value of the software component is - * computed. Value is encoded as text string containing an - * abbreviated description (name) of the measurement method. - * - * - No software measurements: In the event that the implementation does not - * contain any software measurements then the software - * components claim above can be omitted but instead - * it is mandatory to include this claim to indicate this is a - * deliberate state. Custom claim a value is encoded as unsigned - * integer set to 1. - */ - -/** - * \brief Get initial attestation token - * - * \param[in] auth_challenge Pointer to buffer where challenge input is - * stored. Nonce and / or hash of attested data. - * Must be always - * \ref PSA_INITIAL_ATTEST_TOKEN_SIZE bytes - * long. - * \param[in] challenge_size Size of challenge object in bytes. - * \param[out] token_buf Pointer to the buffer where attestation token - * will be stored. - * \param[in] token_buf_size Size of allocated buffer for token, in bytes. - * \param[out] token_size Size of the token that has been returned, in - * bytes. - * - * \return Returns error code as specified in \ref psa_status_t - */ -psa_status_t -psa_initial_attest_get_token(const uint8_t *auth_challenge, - size_t challenge_size, - uint8_t *token_buf, - size_t token_buf_size, - size_t *token_size); - -/** - * \brief Get the exact size of initial attestation token in bytes. - * - * It just returns with the size of the IAT token. It can be used if the caller - * dynamically allocates memory for the token buffer. - * - * \param[in] challenge_size Size of challenge object in bytes. This must be - * a supported challenge size (as above). - * \param[out] token_size Size of the token in bytes, which is created by - * initial attestation service. - * - * \return Returns error code as specified in \ref psa_status_t - */ -psa_status_t -psa_initial_attest_get_token_size(size_t challenge_size, - size_t *token_size); - -/** - * \brief Get the initial attestation public key. - * - * \param[out] public_key Pointer to the buffer where the public key - * will be stored. - * \param[in] key_buf_size Size of allocated buffer for key, in bytes. - * \param[out] public_key_len Size of public key in bytes. - * \param[out] public_key_curve Type of the elliptic curve which the key - * belongs to. - * - * \note Currently only the ECDSA P-256 over SHA-256 algorithm is supported. - * - * \return Returns error code as specified in \ref psa_status_t - */ -psa_status_t -tfm_initial_attest_get_public_key(uint8_t *public_key, - size_t public_key_buf_size, - size_t *public_key_len, - psa_ecc_curve_t *elliptic_curve_type); - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_INITIAL_ATTESTATION_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/internal_trusted_storage.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/internal_trusted_storage.h deleted file mode 100644 index 3920bc9..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/internal_trusted_storage.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/** This file describes the PSA Internal Trusted Storage API -*/ - -#ifndef PSA_INTERNAL_TRUSTED_STORAGE_H -#define PSA_INTERNAL_TRUSTED_STORAGE_H - -#include -#include - -#include "psa/error.h" -#include "psa/storage_common.h" - -#ifdef __cplusplus -extern "C" { -#endif -#define PSA_ITS_API_VERSION_MAJOR 1 /**< The major version number of the - * PSA ITS API - */ -#define PSA_ITS_API_VERSION_MINOR 0 /**< The minor version number of the - * PSA ITS API - */ -// This version of the header file is associated with 1.0 final release. - -/** - * \brief Create a new, or modify an existing, uid/value pair - * - * Stores data in the internal storage. - * - * \param[in] uid The identifier for the data - * \param[in] data_length The size in bytes of the data in `p_data` - * \param[in] p_data A buffer containing the data - * \param[in] create_flags The flags that the data will be stored with - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the - * provided `uid` value was already - * created with - * PSA_STORAGE_FLAG_WRITE_ONCE - * \retval PSA_ERROR_NOT_SUPPORTED The operation failed because one or - * more of the flags provided in - * `create_flags` is not supported or is - * not valid - * \retval PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because there - * was insufficient space on the - * storage medium - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the - * physical storage has failed (Fatal - * error) - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one - * of the provided pointers(`p_data`) - * is invalid, for example is `NULL` or - * references memory the caller cannot - * access - */ -psa_status_t psa_its_set(psa_storage_uid_t uid, - size_t data_length, - const void *p_data, - psa_storage_create_flags_t create_flags); - -/** - * \brief Retrieve data associated with a provided UID - * - * Retrieves up to `data_size` bytes of the data associated with `uid`, starting - * at `data_offset` bytes from the beginning of the data. Upon successful - * completion, the data will be placed in the `p_data` buffer, which must be at - * least `data_size` bytes in size. The length of the data returned will be in - * `p_data_length`. If `data_size` is 0, the contents of `p_data_length` will - * be set to zero. - * - * \param[in] uid The uid value - * \param[in] data_offset The starting offset of the data requested - * \param[in] data_size The amount of data requested - * \param[out] p_data On success, the buffer where the data will - * be placed - * \param[out] p_data_length On success, this will contain size of the data - * placed in `p_data` - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the - * provided `uid` value was not found in - * the storage - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the - * physical storage has failed (Fatal - * error) - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the - * provided arguments (`p_data`, - * `p_data_length`) is invalid, for example - * is `NULL` or references memory the - * caller cannot access. In addition, this - * can also happen if `data_offset` is - * larger than the size of the data - * associated with `uid` - */ -psa_status_t psa_its_get(psa_storage_uid_t uid, - size_t data_offset, - size_t data_size, - void *p_data, - size_t *p_data_length); - -/** - * \brief Retrieve the metadata about the provided uid - * - * Retrieves the metadata stored for a given `uid` as a `psa_storage_info_t` - * structure. - * - * \param[in] uid The `uid` value - * \param[out] p_info A pointer to the `psa_storage_info_t` struct that will - * be populated with the metadata - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided - * uid value was not found in the storage - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical - * storage has failed (Fatal error) - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the - * provided pointers(`p_info`) - * is invalid, for example is `NULL` or - * references memory the caller cannot - * access - */ -psa_status_t psa_its_get_info(psa_storage_uid_t uid, - struct psa_storage_info_t *p_info); - -/** - * \brief Remove the provided uid and its associated data from the storage - * - * Deletes the data from internal storage. - * - * \param[in] uid The `uid` value - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more - * of the given arguments were invalid (null - * pointer, wrong flags and so on) - * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided - * uid value was not found in the storage - * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the provided - * uid value was created with - * PSA_STORAGE_FLAG_WRITE_ONCE - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical - * storage has failed (Fatal error) - */ -psa_status_t psa_its_remove(psa_storage_uid_t uid); - -#ifdef __cplusplus -} -#endif - -#endif // PSA_INTERNAL_TRUSTED_STORAGE_H diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/protected_storage.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/protected_storage.h deleted file mode 100644 index e76205c..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/protected_storage.h +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright (c) 2019-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/* This file describes the PSA Protected Storage API */ - -#ifndef PSA_PROTECTED_STORAGE_H -#define PSA_PROTECTED_STORAGE_H - -#include -#include - -#include "psa/error.h" -#include "psa/storage_common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief PSA_PS_API_VERSION version - * - * Major and minor PSA_PS_API_VERSION numbers - */ -#define PSA_PS_API_VERSION_MAJOR 1 -#define PSA_PS_API_VERSION_MINOR 0 - -// This version of the header file is associated with 1.0 final release - -/** - * \brief Create a new, or modify an existing, uid/value pair - * - * Stores data in the protected storage. - * - * \param[in] uid The identifier for the data - * \param[in] data_length The size in bytes of the data in `p_data` - * \param[in] p_data A buffer containing the data - * \param[in] create_flags The flags that the data will be stored with - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the - * provided `uid` value was already - * created with - * PSA_STORAGE_FLAG_WRITE_ONCE - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one - * of the provided pointers(`p_data`) - * is invalid, for example is `NULL` or - * references memory the caller cannot - * access - * \retval PSA_ERROR_NOT_SUPPORTED The operation failed because one or - * more of the flags provided in - * `create_flags` is not supported or is - * not valid - * \retval PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because there - * was insufficient space on the - * storage medium - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the - * physical storage has failed (Fatal - * error) - * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an - * unspecified internal failure - */ -psa_status_t psa_ps_set(psa_storage_uid_t uid, - size_t data_length, - const void *p_data, - psa_storage_create_flags_t create_flags); - -/** - * \brief Retrieve data associated with a provided uid - * - * Retrieves up to `data_size` bytes of the data associated with `uid`, starting - * at `data_offset` bytes from the beginning of the data. Upon successful - * completion, the data will be placed in the `p_data` buffer, which must be at - * least `data_size` bytes in size. The length of the data returned will be in - * `p_data_length`. If `data_size` is 0, the contents of `p_data_length` will - * be set to zero. - * - * \param[in] uid The uid value - * \param[in] data_offset The starting offset of the data requested - * \param[in] data_size The amount of data requested - * \param[out] p_data On success, the buffer where the data will - * be placed - * \param[out] p_data_length On success, this will contain size of the data - * placed in `p_data` - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the - * provided arguments (`p_data`, - * `p_data_length`) is invalid, for example - * is `NULL` or references memory the - * caller cannot access. In addition, this - * can also happen if `data_offset` is - * larger than the size of the data - * associated with `uid` - * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the - * provided `uid` value was not found in - * the storage - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the - * physical storage has failed (Fatal - * error) - * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an - * unspecified internal failure - * \retval PSA_ERROR_DATA_CORRUPT The operation failed because the data - * associated with the UID was corrupt - * \retval PSA_ERROR_INVALID_SIGNATURE The operation failed because the data - * associated with the UID failed - * authentication - */ -psa_status_t psa_ps_get(psa_storage_uid_t uid, - size_t data_offset, - size_t data_size, - void *p_data, - size_t *p_data_length); - -/** - * \brief Retrieve the metadata about the provided uid - * - * Retrieves the metadata stored for a given `uid` - * - * \param[in] uid The `uid` value - * \param[out] p_info A pointer to the `psa_storage_info_t` struct that will - * be populated with the metadata - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the - * provided pointers(`p_info`) - * is invalid, for example is `NULL` or - * references memory the caller cannot - * access - * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided - * uid value was not found in the storage - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical - * storage has failed (Fatal error) - * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an - * unspecified internal failure - * \retval PSA_ERROR_DATA_CORRUPT The operation failed because the data - * associated with the UID was corrupt - */ -psa_status_t psa_ps_get_info(psa_storage_uid_t uid, - struct psa_storage_info_t *p_info); - -/** - * \brief Remove the provided uid and its associated data from the storage - * - * Removes previously stored data and any associated metadata, - * including rollback protection data. - * - * \param[in] uid The `uid` value - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more - * of the given arguments were invalid (null - * pointer, wrong flags and so on) - * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided - * uid value was not found in the storage - * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the provided - * uid value was created with - * PSA_STORAGE_FLAG_WRITE_ONCE - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical - * storage has failed (Fatal error) - * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an - * unspecified internal failure - */ -psa_status_t psa_ps_remove(psa_storage_uid_t uid); - -/** - * \brief Reserves storage for the specified uid - * - * Upon success, the capacity of the storage will be capacity, and the size - * will be 0. It is only necessary to call this function for assets that will - * be written with the psa_ps_set_extended function. If only the psa_ps_set - * function is needed, calls to this function are redundant. - * - * \param[in] uid The `uid` value - * \param[in] capacity The capacity to be allocated in bytes - * \param[in] create_flags Flags indicating properties of storage - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The operation completed successfully - * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the - * physical storage has failed - * (Fatal error) - * \retval PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because the - * capacity is bigger than the current - * available space - * \retval PSA_ERROR_NOT_SUPPORTED The operation failed because the - * function is not implemented or one - * or more create_flags are not - * supported. - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because uid was - * 0 or create_flags specified flags - * that are not defined in the API. - * \retval PSA_ERROR_GENERIC_ERROR The operation failed due to an - * unspecified error - * \retval PSA_ERROR_ALREADY_EXISTS Storage for the specified uid - * already exists - */ -psa_status_t psa_ps_create(psa_storage_uid_t uid, - size_t capacity, - psa_storage_create_flags_t create_flags); - -/** - * \brief Sets partial data into an asset - * - * Before calling this function, the storage must have been reserved with a call - * to psa_ps_create. It can also be used to overwrite data in an asset that was - * created with a call to psa_ps_set. Calling this function with data_length = 0 - * is permitted, which will make no change to the stored data.This function can - * overwrite existing data and/or extend it up to the capacity for the uid - * specified in psa_ps_create, but cannot create gaps. - * - * That is, it has preconditions: - * - data_offset <= size - * - data_offset + data_length <= capacity - * and postconditions: - * - size = max(size, data_offset + data_length) - * - capacity unchanged. - * - * \param[in] uid The `uid` value - * \param[in] data_offset Offset within the asset to start the write - * \param[in] data_length The size in bytes of the data in p_data to write - * \param[in] p_data Pointer to a buffer which contains the data to write - * - * \return A status indicating the success/failure of the operation - * - * \retval PSA_SUCCESS The asset exists, the input parameters - * are correct and the data is correctly - * written in the physical storage. - * \retval PSA_ERROR_STORAGE_FAILURE The data was not written correctly in - * the physical storage - * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more - * of the preconditions listed above - * regarding data_offset, size, or - * data_length was violated. - * \retval PSA_ERROR_DOES_NOT_EXIST The specified uid was not found - * \retval PSA_ERROR_NOT_SUPPORTED The implementation of the API does not - * support this function - * \retval PSA_ERROR_GENERIC_ERROR The operation failed due to an - * unspecified error - * \retval PSA_ERROR_DATA_CORRUPT The operation failed because the - * existing data has been corrupted. - * \retval PSA_ERROR_INVALID_SIGNATURE The operation failed because the - * existing data failed authentication - * (MAC check failed). - * \retval PSA_ERROR_NOT_PERMITTED The operation failed because it was - * attempted on an asset which was written - * with the flag - * PSA_STORAGE_FLAG_WRITE_ONCE - */ -psa_status_t psa_ps_set_extended(psa_storage_uid_t uid, - size_t data_offset, - size_t data_length, - const void *p_data); - -/** - * \brief Lists optional features. - * - * \return A bitmask with flags set for all of - * the optional features supported by the - * implementation.Currently defined flags - * are limited to - * PSA_STORAGE_SUPPORT_SET_EXTENDED - */ -uint32_t psa_ps_get_support(void); - -#ifdef __cplusplus -} -#endif - -#endif /* PSA_PROTECTED_STORAGE_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/storage_common.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/storage_common.h deleted file mode 100644 index 3f901c5..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/storage_common.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/* This file includes common definitions for PSA storage -*/ - -#ifndef PSA_STORAGE_COMMON_H -#define PSA_STORAGE_COMMON_H - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef uint32_t psa_storage_create_flags_t; - -typedef uint64_t psa_storage_uid_t; - -/* Flags */ - -#define PSA_STORAGE_FLAG_NONE 0u -#define PSA_STORAGE_FLAG_WRITE_ONCE (1u << 0) -#define PSA_STORAGE_FLAG_NO_CONFIDENTIALITY (1u << 1) -#define PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION (1u << 2) - -/* A container for metadata associated with a specific uid */ - -struct psa_storage_info_t { - size_t capacity; - size_t size; - psa_storage_create_flags_t flags; -}; - -#define PSA_STORAGE_SUPPORT_SET_EXTENDED (1u << 0) - -#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) -#define PSA_ERROR_DATA_CORRUPT ((psa_status_t)-152) - -#ifdef __cplusplus -} -#endif - -#endif // PSA_STORAGE_COMMON_H diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa_manifest/sid.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa_manifest/sid.h deleted file mode 100644 index f9bdf7c..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa_manifest/sid.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2019-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#ifndef __PSA_MANIFEST_SID_H__ -#define __PSA_MANIFEST_SID_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/******** TFM_SP_PS ********/ -#define TFM_PS_SET_SID (0x00000060U) -#define TFM_PS_SET_VERSION (1U) -#define TFM_PS_GET_SID (0x00000061U) -#define TFM_PS_GET_VERSION (1U) -#define TFM_PS_GET_INFO_SID (0x00000062U) -#define TFM_PS_GET_INFO_VERSION (1U) -#define TFM_PS_REMOVE_SID (0x00000063U) -#define TFM_PS_REMOVE_VERSION (1U) -#define TFM_PS_GET_SUPPORT_SID (0x00000064U) -#define TFM_PS_GET_SUPPORT_VERSION (1U) - -/******** TFM_SP_ITS ********/ -#define TFM_ITS_SET_SID (0x00000070U) -#define TFM_ITS_SET_VERSION (1U) -#define TFM_ITS_GET_SID (0x00000071U) -#define TFM_ITS_GET_VERSION (1U) -#define TFM_ITS_GET_INFO_SID (0x00000072U) -#define TFM_ITS_GET_INFO_VERSION (1U) -#define TFM_ITS_REMOVE_SID (0x00000073U) -#define TFM_ITS_REMOVE_VERSION (1U) - -/******** TFM_SP_CRYPTO ********/ -#define TFM_CRYPTO_SID (0x00000080U) -#define TFM_CRYPTO_VERSION (1U) - -/******** TFM_SP_PLATFORM ********/ -#define TFM_SP_PLATFORM_SYSTEM_RESET_SID (0x00000040U) -#define TFM_SP_PLATFORM_SYSTEM_RESET_VERSION (1U) -#define TFM_SP_PLATFORM_IOCTL_SID (0x00000041U) -#define TFM_SP_PLATFORM_IOCTL_VERSION (1U) -#define TFM_SP_PLATFORM_NV_COUNTER_SID (0x00000042U) -#define TFM_SP_PLATFORM_NV_COUNTER_VERSION (1U) - -/******** TFM_SP_INITIAL_ATTESTATION ********/ -#define TFM_ATTEST_GET_TOKEN_SID (0x00000020U) -#define TFM_ATTEST_GET_TOKEN_VERSION (1U) -#define TFM_ATTEST_GET_TOKEN_SIZE_SID (0x00000021U) -#define TFM_ATTEST_GET_TOKEN_SIZE_VERSION (1U) -#define TFM_ATTEST_GET_PUBLIC_KEY_SID (0x00000022U) -#define TFM_ATTEST_GET_PUBLIC_KEY_VERSION (1U) - -/******** TFM_SP_CORE_TEST ********/ -#define SPM_CORE_TEST_INIT_SUCCESS_SID (0x0000F020U) -#define SPM_CORE_TEST_INIT_SUCCESS_VERSION (1U) -#define SPM_CORE_TEST_DIRECT_RECURSION_SID (0x0000F021U) -#define SPM_CORE_TEST_DIRECT_RECURSION_VERSION (1U) -#define SPM_CORE_TEST_SS_TO_SS_SID (0x0000F024U) -#define SPM_CORE_TEST_SS_TO_SS_VERSION (1U) -#define SPM_CORE_TEST_SS_TO_SS_BUFFER_SID (0x0000F025U) -#define SPM_CORE_TEST_SS_TO_SS_BUFFER_VERSION (1U) -#define SPM_CORE_TEST_OUTVEC_WRITE_SID (0x0000F026U) -#define SPM_CORE_TEST_OUTVEC_WRITE_VERSION (1U) -#define SPM_CORE_TEST_PERIPHERAL_ACCESS_SID (0x0000F027U) -#define SPM_CORE_TEST_PERIPHERAL_ACCESS_VERSION (1U) -#define SPM_CORE_TEST_GET_CALLER_CLIENT_ID_SID (0x0000F028U) -#define SPM_CORE_TEST_GET_CALLER_CLIENT_ID_VERSION (1U) -#define SPM_CORE_TEST_SPM_REQUEST_SID (0x0000F029U) -#define SPM_CORE_TEST_SPM_REQUEST_VERSION (1U) -#define SPM_CORE_TEST_BLOCK_SID (0x0000F02AU) -#define SPM_CORE_TEST_BLOCK_VERSION (1U) -#define SPM_CORE_TEST_NS_THREAD_SID (0x0000F02BU) -#define SPM_CORE_TEST_NS_THREAD_VERSION (1U) - -/******** TFM_SP_CORE_TEST_2 ********/ -#define SPM_CORE_TEST_2_SLAVE_SERVICE_SID (0x0000F040U) -#define SPM_CORE_TEST_2_SLAVE_SERVICE_VERSION (1U) -#define SPM_CORE_TEST_2_CHECK_CALLER_CLIENT_ID_SID (0x0000F041U) -#define SPM_CORE_TEST_2_CHECK_CALLER_CLIENT_ID_VERSION (1U) -#define SPM_CORE_TEST_2_GET_EVERY_SECOND_BYTE_SID (0x0000F042U) -#define SPM_CORE_TEST_2_GET_EVERY_SECOND_BYTE_VERSION (1U) -#define SPM_CORE_TEST_2_INVERT_SID (0x0000F043U) -#define SPM_CORE_TEST_2_INVERT_VERSION (1U) -#define SPM_CORE_TEST_2_PREPARE_TEST_SCENARIO_SID (0x0000F044U) -#define SPM_CORE_TEST_2_PREPARE_TEST_SCENARIO_VERSION (1U) -#define SPM_CORE_TEST_2_EXECUTE_TEST_SCENARIO_SID (0x0000F045U) -#define SPM_CORE_TEST_2_EXECUTE_TEST_SCENARIO_VERSION (1U) - -/******** TFM_SP_SECURE_TEST_PARTITION ********/ -#define TFM_SECURE_CLIENT_SFN_RUN_TESTS_SID (0x0000F000U) -#define TFM_SECURE_CLIENT_SFN_RUN_TESTS_VERSION (1U) - -/******** TFM_SP_IPC_SERVICE_TEST ********/ -#define IPC_SERVICE_TEST_BASIC_SID (0x0000F080U) -#define IPC_SERVICE_TEST_BASIC_VERSION (1U) -#define IPC_SERVICE_TEST_PSA_ACCESS_APP_MEM_SID (0x0000F081U) -#define IPC_SERVICE_TEST_PSA_ACCESS_APP_MEM_VERSION (1U) -#define IPC_SERVICE_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_SID (0x0000F082U) -#define IPC_SERVICE_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_VERSION (1U) -#define IPC_SERVICE_TEST_APP_ACCESS_PSA_MEM_SID (0x0000F083U) -#define IPC_SERVICE_TEST_APP_ACCESS_PSA_MEM_VERSION (1U) -#define IPC_SERVICE_TEST_CLIENT_PROGRAMMER_ERROR_SID (0x0000F084U) -#define IPC_SERVICE_TEST_CLIENT_PROGRAMMER_ERROR_VERSION (1U) - -/******** TFM_SP_IPC_CLIENT_TEST ********/ -#define IPC_CLIENT_TEST_BASIC_SID (0x0000F060U) -#define IPC_CLIENT_TEST_BASIC_VERSION (1U) -#define IPC_CLIENT_TEST_PSA_ACCESS_APP_MEM_SID (0x0000F061U) -#define IPC_CLIENT_TEST_PSA_ACCESS_APP_MEM_VERSION (1U) -#define IPC_CLIENT_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_SID (0x0000F062U) -#define IPC_CLIENT_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_VERSION (1U) -#define IPC_CLIENT_TEST_APP_ACCESS_PSA_MEM_SID (0x0000F063U) -#define IPC_CLIENT_TEST_APP_ACCESS_PSA_MEM_VERSION (1U) -#define IPC_CLIENT_TEST_MEM_CHECK_SID (0x0000F064U) -#define IPC_CLIENT_TEST_MEM_CHECK_VERSION (1U) - -/******** TFM_IRQ_TEST_1 ********/ -#define SPM_CORE_IRQ_TEST_1_PREPARE_TEST_SCENARIO_SID (0x0000F0A0U) -#define SPM_CORE_IRQ_TEST_1_PREPARE_TEST_SCENARIO_VERSION (1U) -#define SPM_CORE_IRQ_TEST_1_EXECUTE_TEST_SCENARIO_SID (0x0000F0A1U) -#define SPM_CORE_IRQ_TEST_1_EXECUTE_TEST_SCENARIO_VERSION (1U) - -/******** TFM_SP_PS_TEST ********/ -#define TFM_PS_TEST_PREPARE_SID (0x0000F0C0U) -#define TFM_PS_TEST_PREPARE_VERSION (1U) - -/******** TFM_SP_SECURE_CLIENT_2 ********/ -#define TFM_SECURE_CLIENT_2_SID (0x0000F0E0U) -#define TFM_SECURE_CLIENT_2_VERSION (1U) - -/******** TFM_SP_MULTI_CORE_TEST ********/ -#define MULTI_CORE_MULTI_CLIENT_CALL_TEST_0_SID (0x0000F100U) -#define MULTI_CORE_MULTI_CLIENT_CALL_TEST_0_VERSION (1U) -#define MULTI_CORE_MULTI_CLIENT_CALL_TEST_1_SID (0x0000F101U) -#define MULTI_CORE_MULTI_CLIENT_CALL_TEST_1_VERSION (1U) - -#ifdef __cplusplus -} -#endif - -#endif /* __PSA_MANIFEST_SID_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_api.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_api.h deleted file mode 100644 index 09abc39..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_api.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2017-2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#ifndef __TFM_API_H__ -#define __TFM_API_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "psa/client.h" - -#define TFM_INVALID_CLIENT_ID 0 - -/** - * \brief Checks if the provided client ID is a secure client ID. - * - * \param[in] client_id Client ID to check. - * - * \retval 1 Client ID is secure. - * \retval 0 Client ID is non-secure. - */ -#define TFM_CLIENT_ID_IS_S(client_id) ((client_id)>0) - -/** - * \brief Checks if the provided client ID is a non-secure client ID. - * - * \param[in] client_id Client ID to check. - * - * \retval 1 Client ID is non-secure. - * \retval 0 Client ID is secure. - */ -#define TFM_CLIENT_ID_IS_NS(client_id) ((client_id)<0) - -/* The mask used for timeout values */ -#define PSA_TIMEOUT_MASK PSA_BLOCK - -/* FixMe: sort out DEBUG compile option and limit return value options - * on external interfaces */ -enum tfm_status_e -{ - TFM_SUCCESS = 0, - TFM_PARTITION_BUSY, - TFM_ERROR_SECURE_DOMAIN_LOCKED, - TFM_ERROR_INVALID_PARAMETER, - TFM_ERROR_PARTITION_NON_REENTRANT, - TFM_ERROR_NS_THREAD_MODE_CALL, - TFM_ERROR_NOT_INITIALIZED, - TFM_ERROR_NO_ACTIVE_PARTITION, - TFM_ERROR_INVALID_EXC_MODE, - TFM_SECURE_LOCK_FAILED, - TFM_SECURE_UNLOCK_FAILED, - TFM_ERROR_GENERIC = 0x1F, -}; - -/* - * Structure to package type, in_len and out_len, it is mainly used for - * psa_call. - */ -struct tfm_control_parameter_t { - int32_t type; - size_t in_len; - size_t out_len; -}; - -/********************* Secure function declarations ***************************/ - -/** - * \brief Assign client ID to the current TZ context. - * - * \param[in] ns_client_id The client ID to be assigned to the current - * context. - * \retval TFM_SUCCESS The client ID assigned successfully. - * \retval error code The client ID assignment failed, an error code - * returned according to \ref tfm_status_e. - * \note This function have to be called from handler mode. - */ -enum tfm_status_e tfm_register_client_id (int32_t ns_client_id); - -/** - * \brief Retrieve the version of the PSA Framework API that is implemented. - * - * \return The version of the PSA Framework. - */ -uint32_t tfm_psa_framework_version_veneer(void); - -/** - * \brief Return version of secure function provided by secure binary. - * - * \param[in] sid ID of secure service. - * - * \return Version number of secure function. - */ -uint32_t tfm_psa_version_veneer(uint32_t sid); - -/** - * \brief Connect to secure function. - * - * \param[in] sid ID of secure service. - * \param[in] version Version of SF requested by client. - * - * \return Returns handle to connection. - */ -psa_handle_t tfm_psa_connect_veneer(uint32_t sid, uint32_t version); - -/** - * \brief Call a secure function referenced by a connection handle. - * - * \param[in] handle Handle to connection. - * \param[in] ctrl_param Parameter structure, includes reuqest type, - * in_num and out_num. - * \param[in] in_vec Array of input \ref psa_invec structures. - * \param[in/out] out_vec Array of output \ref psa_outvec structures. - * - * \return Returns \ref psa_status_t status code. - */ -psa_status_t tfm_psa_call_veneer(psa_handle_t handle, - const struct tfm_control_parameter_t *ctrl_param, - const psa_invec *in_vec, - psa_outvec *out_vec); - -/** - * \brief Close connection to secure function referenced by a connection handle. - * - * \param[in] handle Handle to connection - * - * \return void - */ -void tfm_psa_close_veneer(psa_handle_t handle); - -/***************** End Secure function declarations ***************************/ - -#ifdef __cplusplus -} -#endif - -#endif /* __TFM_API_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_crypto_defs.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_crypto_defs.h deleted file mode 100644 index dd45e3b..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_crypto_defs.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (c) 2018-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#ifndef __TFM_CRYPTO_DEFS_H__ -#define __TFM_CRYPTO_DEFS_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include "tfm_api.h" -#include "psa/crypto.h" - -/** - * \brief This type is used to overcome a limitation in the number of maximum - * IOVECs that can be used especially in psa_aead_encrypt and - * psa_aead_decrypt. To be removed in case the AEAD APIs number of - * parameters passed gets restructured - */ -#define TFM_CRYPTO_MAX_NONCE_LENGTH (16u) -struct tfm_crypto_aead_pack_input { - uint8_t nonce[TFM_CRYPTO_MAX_NONCE_LENGTH]; - uint32_t nonce_length; -}; - -/** - * \brief Structure used to pack non-pointer types in a call - * - */ -struct tfm_crypto_pack_iovec { - uint32_t sfn_id; /*!< Secure function ID used to dispatch the - * request - */ - uint16_t step; /*!< Key derivation step */ - psa_key_handle_t key_handle; /*!< Key handle */ - psa_algorithm_t alg; /*!< Algorithm */ - psa_algorithm_t alg2; /*!< Enrollment Algorithm */ - uint32_t op_handle; /*!< Frontend context handle associated to a - * multipart operation - */ - size_t capacity; /*!< Key derivation capacity */ - - struct tfm_crypto_aead_pack_input aead_in; /*!< FixMe: Temporarily used for - * AEAD until the API is - * restructured - */ -}; - -/** - * \brief Define a progressive numerical value for each SID which can be used - * when dispatching the requests to the service - */ -enum { - TFM_CRYPTO_GET_KEY_ATTRIBUTES_SID = (0u), - TFM_CRYPTO_RESET_KEY_ATTRIBUTES_SID, - TFM_CRYPTO_OPEN_KEY_SID, - TFM_CRYPTO_CLOSE_KEY_SID, - TFM_CRYPTO_IMPORT_KEY_SID, - TFM_CRYPTO_DESTROY_KEY_SID, - TFM_CRYPTO_EXPORT_KEY_SID, - TFM_CRYPTO_EXPORT_PUBLIC_KEY_SID, - TFM_CRYPTO_COPY_KEY_SID, - TFM_CRYPTO_HASH_COMPUTE_SID, - TFM_CRYPTO_HASH_COMPARE_SID, - TFM_CRYPTO_HASH_SETUP_SID, - TFM_CRYPTO_HASH_UPDATE_SID, - TFM_CRYPTO_HASH_FINISH_SID, - TFM_CRYPTO_HASH_VERIFY_SID, - TFM_CRYPTO_HASH_ABORT_SID, - TFM_CRYPTO_HASH_CLONE_SID, - TFM_CRYPTO_MAC_COMPUTE_SID, - TFM_CRYPTO_MAC_VERIFY_SID, - TFM_CRYPTO_MAC_SIGN_SETUP_SID, - TFM_CRYPTO_MAC_VERIFY_SETUP_SID, - TFM_CRYPTO_MAC_UPDATE_SID, - TFM_CRYPTO_MAC_SIGN_FINISH_SID, - TFM_CRYPTO_MAC_VERIFY_FINISH_SID, - TFM_CRYPTO_MAC_ABORT_SID, - TFM_CRYPTO_CIPHER_ENCRYPT_SID, - TFM_CRYPTO_CIPHER_DECRYPT_SID, - TFM_CRYPTO_CIPHER_ENCRYPT_SETUP_SID, - TFM_CRYPTO_CIPHER_DECRYPT_SETUP_SID, - TFM_CRYPTO_CIPHER_GENERATE_IV_SID, - TFM_CRYPTO_CIPHER_SET_IV_SID, - TFM_CRYPTO_CIPHER_UPDATE_SID, - TFM_CRYPTO_CIPHER_FINISH_SID, - TFM_CRYPTO_CIPHER_ABORT_SID, - TFM_CRYPTO_AEAD_ENCRYPT_SID, - TFM_CRYPTO_AEAD_DECRYPT_SID, - TFM_CRYPTO_AEAD_ENCRYPT_SETUP_SID, - TFM_CRYPTO_AEAD_DECRYPT_SETUP_SID, - TFM_CRYPTO_AEAD_GENERATE_NONCE_SID, - TFM_CRYPTO_AEAD_SET_NONCE_SID, - TFM_CRYPTO_AEAD_SET_LENGTHS_SID, - TFM_CRYPTO_AEAD_UPDATE_AD_SID, - TFM_CRYPTO_AEAD_UPDATE_SID, - TFM_CRYPTO_AEAD_FINISH_SID, - TFM_CRYPTO_AEAD_VERIFY_SID, - TFM_CRYPTO_AEAD_ABORT_SID, - TFM_CRYPTO_SIGN_HASH_SID, - TFM_CRYPTO_VERIFY_HASH_SID, - TFM_CRYPTO_ASYMMETRIC_ENCRYPT_SID, - TFM_CRYPTO_ASYMMETRIC_DECRYPT_SID, - TFM_CRYPTO_KEY_DERIVATION_SETUP_SID, - TFM_CRYPTO_KEY_DERIVATION_GET_CAPACITY_SID, - TFM_CRYPTO_KEY_DERIVATION_SET_CAPACITY_SID, - TFM_CRYPTO_KEY_DERIVATION_INPUT_BYTES_SID, - TFM_CRYPTO_KEY_DERIVATION_INPUT_KEY_SID, - TFM_CRYPTO_KEY_DERIVATION_KEY_AGREEMENT_SID, - TFM_CRYPTO_KEY_DERIVATION_OUTPUT_BYTES_SID, - TFM_CRYPTO_KEY_DERIVATION_OUTPUT_KEY_SID, - TFM_CRYPTO_KEY_DERIVATION_ABORT_SID, - TFM_CRYPTO_RAW_KEY_AGREEMENT_SID, - TFM_CRYPTO_GENERATE_RANDOM_SID, - TFM_CRYPTO_GENERATE_KEY_SID, - TFM_CRYPTO_SET_KEY_DOMAIN_PARAMETERS_SID, - TFM_CRYPTO_GET_KEY_DOMAIN_PARAMETERS_SID, - TFM_CRYPTO_SID_MAX, -}; - -/** - * \brief Define an invalid value for an SID - * - */ -#define TFM_CRYPTO_SID_INVALID (~0x0u) - -/** - * \brief This value is used to mark an handle as invalid. - * - */ -#define TFM_CRYPTO_INVALID_HANDLE (0x0u) - -/** - * \brief The persistent key identifier that refers to the hardware unique key. - * - */ -#define TFM_CRYPTO_KEY_ID_HUK (0xFFFF815Bu) - -/** - * \brief The algorithm identifier that refers to key derivation from the - * hardware unique key. - * - */ -#define TFM_CRYPTO_ALG_HUK_DERIVATION ((psa_algorithm_t)0xB0000F00) - -/** - * \brief Define miscellaneous literal constants that are used in the service - * - */ -enum { - TFM_CRYPTO_NOT_IN_USE = 0, - TFM_CRYPTO_IN_USE = 1 -}; - -#ifdef __cplusplus -} -#endif - -#endif /* __TFM_CRYPTO_DEFS_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_mailbox.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_mailbox.h deleted file mode 100644 index 3d128f4..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_mailbox.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 2019-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/* - * This is header file of common mailbox objects shared by NSPE and SPE. - * Please refer to tfm_ns_mailbox.h for the definitions only used in NSPE - * mailbox library. - * Please refer to tfm_spe_mailbox.h for the SPE specific definitions and APIs. - */ - -#ifndef __TFM_MAILBOX_H__ -#define __TFM_MAILBOX_H__ - -#include -#include -#include -#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL -#include "device_cfg.h" -#endif -#include "psa/client.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * If multiple outstanding NS PSA Client calls is enabled, multi-core platform - * should define the number of mailbox queue slots NUM_MAILBOX_QUEUE_SLOT in - * platform device_cfg.h. - * Otherwise, NUM_MAILBOX_QUEUE_SLOT is defined as 1. - */ -#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL -#ifndef NUM_MAILBOX_QUEUE_SLOT -#error "Error: Platform doesn't define NUM_MAILBOX_QUEUE_SLOT for mailbox queue" -#endif - -#if (NUM_MAILBOX_QUEUE_SLOT < 2) -#error "Error: Invalid NUM_MAILBOX_QUEUE_SLOT. The value should be more than 1" -#endif - -/* - * The number of slots should be no more than the number of bits in - * mailbox_queue_status_t. - * Here the value is hardcoded. A better way is to define a sizeof() to - * calculate the bits in mailbox_queue_status_t and dump it with pragma message. - */ -#if (NUM_MAILBOX_QUEUE_SLOT > 32) -#error "Error: Invalid NUM_MAILBOX_QUEUE_SLOT. The value should be no more than 32" -#endif -#else /* TFM_MULTI_CORE_MULTI_CLIENT_CALL */ -/* Force the number of mailbox queue slots as 1. */ -#undef NUM_MAILBOX_QUEUE_SLOT -#define NUM_MAILBOX_QUEUE_SLOT (1) -#endif /* TFM_MULTI_CORE_MULTI_CLIENT_CALL */ - -/* PSA client call type value */ -#define MAILBOX_PSA_FRAMEWORK_VERSION (0x1) -#define MAILBOX_PSA_VERSION (0x2) -#define MAILBOX_PSA_CONNECT (0x3) -#define MAILBOX_PSA_CALL (0x4) -#define MAILBOX_PSA_CLOSE (0x5) - -/* Return code of mailbox APIs */ -#define MAILBOX_SUCCESS (0) -#define MAILBOX_QUEUE_FULL (INT32_MIN + 1) -#define MAILBOX_INVAL_PARAMS (INT32_MIN + 2) -#define MAILBOX_NO_PERMS (INT32_MIN + 3) -#define MAILBOX_NO_PEND_EVENT (INT32_MIN + 4) -#define MAILBOX_CHAN_BUSY (INT32_MIN + 5) -#define MAILBOX_CALLBACK_REG_ERROR (INT32_MIN + 6) -#define MAILBOX_INIT_ERROR (INT32_MIN + 7) - -/* - * This structure holds the parameters used in a PSA client call. - */ -struct psa_client_params_t { - union { - struct { - uint32_t sid; - } psa_version_params; - - struct { - uint32_t sid; - uint32_t version; - } psa_connect_params; - - struct { - psa_handle_t handle; - int32_t type; - const psa_invec *in_vec; - size_t in_len; - psa_outvec *out_vec; - size_t out_len; - } psa_call_params; - - struct { - psa_handle_t handle; - } psa_close_params; - }; -}; - -/* Mailbox message passed from NSPE to SPE to deliver a PSA client call */ -struct mailbox_msg_t { - uint32_t call_type; /* PSA client call type */ - struct psa_client_params_t params; /* Contain parameters used in PSA - * client call - */ - - int32_t client_id; /* Optional client ID of the - * non-secure caller. - * It is required to identify the - * non-secure task when NSPE OS - * enforces non-secure task isolation - */ -}; - -/* A handle to a mailbox message in use */ -typedef int32_t mailbox_msg_handle_t; - -#define MAILBOX_MSG_NULL_HANDLE ((mailbox_msg_handle_t)0) - -/* - * Mailbox reply structure in non-secure memory - * to hold the PSA client call return result from SPE - */ -struct mailbox_reply_t { - int32_t return_val; -}; - -/* A single slot structure in NSPE mailbox queue */ -struct ns_mailbox_slot_t { - struct mailbox_msg_t msg; - struct mailbox_reply_t reply; - const void *owner; /* Handle of the owner task of this - * slot - */ - bool is_woken; /* Indicate that owner task has been - * or should be woken up, after the - * replied is received. - */ -}; - -typedef uint32_t mailbox_queue_status_t; - -/* NSPE mailbox queue */ -struct ns_mailbox_queue_t { - mailbox_queue_status_t empty_slots; /* Bitmask of empty slots */ - mailbox_queue_status_t pend_slots; /* Bitmask of slots pending - * for SPE handling - */ - mailbox_queue_status_t replied_slots; /* Bitmask of active slots - * containing PSA client call - * return result - */ - - struct ns_mailbox_slot_t queue[NUM_MAILBOX_QUEUE_SLOT]; - -#ifdef TFM_MULTI_CORE_TEST - uint32_t nr_tx; /* The total number of - * submission of NS PSA Client - * calls from NS task via - * mailbox. - */ - uint32_t nr_used_slots; /* The total number of used - * mailbox queue slots each time - * NS thread requests a mailbox - * queue slot. - */ -#endif -}; - -#ifdef __cplusplus -} -#endif - -#endif /* __TFM_MAILBOX_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_multi_core_api.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_multi_core_api.h deleted file mode 100644 index 7999fa4..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_multi_core_api.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#ifndef __TFM_MULTI_CORE_API__ -#define __TFM_MULTI_CORE_API__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/** - * \brief Called on the non-secure CPU. - * Flags that the non-secure side has completed its initialization. - * Waits, if necessary, for the secure CPU to flag that it has completed - * its initialization. - * - * \return Return 0 if succeeds. - * \return Otherwise, return specific error code. - */ -int32_t tfm_ns_wait_for_s_cpu_ready(void); - -/** - * \brief Synchronisation with secure CPU, platform-specific implementation. - * Flags that the non-secure side has completed its initialization. - * Waits, if necessary, for the secure CPU to flag that it has completed - * its initialization. - * - * \retval Return 0 if succeeds. - * \retval Otherwise, return specific error code. - */ -int32_t tfm_platform_ns_wait_for_s_cpu_ready(void); - -/** - * \brief Acquire the multi-core lock for synchronizing PSA client call(s) - * The actual implementation depends on the use scenario. - * - * \return \ref TFM_SUCCESS on success - * \return \ref TFM_ERROR_GENERIC on error - */ -uint32_t tfm_ns_multi_core_lock_acquire(void); - -/** - * \brief Release the multi-core lock for synchronizing PSA client call(s) - * The actual implementation depends on the use scenario. - * - * \return \ref TFM_SUCCESS on success - * \return \ref TFM_ERROR_GENERIC on error - */ -uint32_t tfm_ns_multi_core_lock_release(void); - -#ifdef __cplusplus -} -#endif - -#endif /* __TFM_MULTI_CORE_API__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_ns_interface.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_ns_interface.h deleted file mode 100644 index 21857be..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_ns_interface.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2017-2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ -#ifndef __TFM_NS_INTERFACE_H__ -#define __TFM_NS_INTERFACE_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "tfm_api.h" - -typedef int32_t (*veneer_fn) (uint32_t arg0, uint32_t arg1, - uint32_t arg2, uint32_t arg3); - -/** - * \brief NS interface, veneer function dispatcher - * - * \details This function implements the dispatching mechanism for the - * desired veneer function, to be called with the parameters - * described from arg0 to arg3. - * - * \param[in] fn Function pointer to the veneer function desired - * \param[in] arg0 Argument 0 - * \param[in] arg1 Argument 1 - * \param[in] arg2 Argument 2 - * \param[in] arg3 Argument 3 - * - * \return Returns the same return value of the requested veneer function - */ -int32_t tfm_ns_interface_dispatch(veneer_fn fn, - uint32_t arg0, uint32_t arg1, - uint32_t arg2, uint32_t arg3); - -/** - * \brief NS interface, Initialise the NS interface - * - * \details This function needs to be called from the NS world to - * properly initialise the NS interface towards TF-M. This - * function will initialise all the objects required for - * runtime dispatching of TF-M requests to services - * - * \return A value according to \ref enum tfm_status_e - */ -enum tfm_status_e tfm_ns_interface_init(void); -#ifdef __cplusplus -} -#endif - -#endif /* __TFM_NS_INTERFACE_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_ns_mailbox.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_ns_mailbox.h deleted file mode 100644 index 2fcb1b6..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_ns_mailbox.h +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (c) 2019-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/* Data types and API definitions in NSPE mailbox library */ - -#ifndef __TFM_NS_MAILBOX_H__ -#define __TFM_NS_MAILBOX_H__ - -#include -#include -#include "tfm_mailbox.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef TFM_MULTI_CORE_TEST -/** - * \brief The structure to hold the statistics result of NSPE mailbox - */ -struct ns_mailbox_stats_res_t { - uint8_t avg_nr_slots; /* The value before the decimal point - * in the average number of NSPE - * mailbox slots in use. - */ - uint8_t avg_nr_slots_tenths; /* The first digit value after the - * decimal point in the average - * number of NSPE mailbox slots in use. - */ -}; -#endif - -/** - * \brief Prepare and send PSA client request to SPE via mailbox. - * - * \param[in] call_type PSA client call type - * \param[in] params Parmaters used for PSA client call - * \param[in] client_id Optional client ID of non-secure caller. - * It is required to identify the non-secure caller - * when NSPE OS enforces non-secure task isolation. - * - * \retval >= 0 The handle to the mailbox message assigned. - * \retval < 0 Operation failed with an error code. - */ -mailbox_msg_handle_t tfm_ns_mailbox_tx_client_req(uint32_t call_type, - const struct psa_client_params_t *params, - int32_t client_id); - -/** - * \brief Fetch PSA client return result. - * - * \param[in] handle The handle to the mailbox message - * \param[out] reply The address to be written with return result. - * - * \retval MAILBOX_SUCCESS Successfully get PSA client call return result. - * \retval Other return code Operation failed with an error code. - */ -int32_t tfm_ns_mailbox_rx_client_reply(mailbox_msg_handle_t handle, - int32_t *reply); - -/** - * \brief Check whether a specific mailbox message has been replied. - * - * \param[in] handle The handle to the mailbox message - * - * \retval true The PSA client call return value is replied. - * \retval false The PSA client call return value is not - * replied yet. - */ -bool tfm_ns_mailbox_is_msg_replied(mailbox_msg_handle_t handle); - -/** - * \brief NSPE mailbox initialization - * - * \param[in] queue The base address of NSPE mailbox queue to be - * initialized. - * - * \retval MAILBOX_SUCCESS Operation succeeded. - * \retval Other return code Operation failed with an error code. - */ -int32_t tfm_ns_mailbox_init(struct ns_mailbox_queue_t *queue); - -/** - * \brief Get the handle of the current non-secure task executing mailbox - * functionalities - * - * \note This function should be implemented according to platform, NS OS - * and actual use scenario. - * This function can be ignored or return NULL if sleep/wake-up mechanism - * is not required in PSA Client API implementation. - * - * \return Return the handle of task. - */ -const void *tfm_ns_mailbox_get_task_handle(void); - -/** - * \brief Fetch the handle to the first replied mailbox message in the NSPE - * mailbox queue. - * This function is intended to be called inside platform specific - * notification IRQ handler. - * - * \note The replied status of the fetched mailbox message will be cleaned after - * the message is fetched. When this function is called again, it fetches - * the next replied mailbox message from the NSPE mailbox queue. - * - * \return Return the handle to the first replied mailbox message in the - * queue. - * Return \ref MAILBOX_MSG_NULL_HANDLE if no mailbox message is replied. - */ -mailbox_msg_handle_t tfm_ns_mailbox_fetch_reply_msg_isr(void); - -/** - * \brief Return the handle of owner task of a mailbox message according to the - * \ref mailbox_msg_handle_t - * - * \param[in] handle The handle of mailbox message. - * - * \return Return the handle value of the owner task. - */ -const void *tfm_ns_mailbox_get_msg_owner(mailbox_msg_handle_t handle); - -#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL -/** - * \brief Wait for the reply returned from SPE to the mailbox message specified - * by handle - * - * \param[in] handle The handle of mailbox message. - * - * \retval MAILBOX_SUCCESS Return from waiting successfully. - * \retval Other return code Failed to wait with an error code. - */ -int32_t tfm_ns_mailbox_wait_reply(mailbox_msg_handle_t handle); -#endif - -/** - * \brief Platform specific NSPE mailbox initialization. - * Invoked by \ref tfm_ns_mailbox_init(). - * - * \param[in] queue The base address of NSPE mailbox queue to be - * initialized. - * - * \retval MAILBOX_SUCCESS Operation succeeded. - * \retval Other return code Operation failed with an error code. - */ -int32_t tfm_ns_mailbox_hal_init(struct ns_mailbox_queue_t *queue); - -/** - * \brief Notify SPE to deal with the PSA client call sent via mailbox - * - * \note The implementation depends on platform specific hardware and use case. - * - * \retval MAILBOX_SUCCESS Operation succeeded. - * \retval Other return code Operation failed with an error code. - */ -int32_t tfm_ns_mailbox_hal_notify_peer(void); - -/** - * \brief Enter critical section of NSPE mailbox. - * - * \note The implementation depends on platform specific hardware and use case. - */ -void tfm_ns_mailbox_hal_enter_critical(void); - -/** - * \brief Exit critical section of NSPE mailbox. - * - * \note The implementation depends on platform specific hardware and use case. - */ -void tfm_ns_mailbox_hal_exit_critical(void); - -/** - * \brief Enter critical section of NSPE mailbox in IRQ handler. - * - * \note The implementation depends on platform specific hardware and use case. - */ -void tfm_ns_mailbox_hal_enter_critical_isr(void); - -/** - * \brief Enter critical section of NSPE mailbox in IRQ handler - * - * \note The implementation depends on platform specific hardware and use case. - */ -void tfm_ns_mailbox_hal_exit_critical_isr(void); - -#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL -/** - * \brief Performs platform and NS OS specific waiting mechanism to wait for - * the reply of the specified mailbox message to be returned from SPE. - * - * \note This function is implemented by platform and NS OS specific waiting - * mechanism accroding to use scenario. - * - * \param[in] handle The handle of mailbox message. - */ -void tfm_ns_mailbox_hal_wait_reply(mailbox_msg_handle_t handle); -#endif - -#ifdef TFM_MULTI_CORE_TEST -/** - * \brief Initialize the statistics module in TF-M NSPE mailbox. - * - * \note This function is only available when multi-core tests are enabled. - */ -void tfm_ns_mailbox_tx_stats_init(void); - -/** - * \brief Calculate the average number of used NS mailbox queue slots each time - * NS task requires a queue slot to submit mailbox message, which is - * recorded in NS mailbox statisitics module. - * - * \note This function is only available when multi-core tests are enabled. - * - * \param[in] stats_res The buffer to be written with - * \ref ns_mailbox_stats_res_t. - * - * \return Return the calculation result. - */ -void tfm_ns_mailbox_stats_avg_slot(struct ns_mailbox_stats_res_t *stats_res); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* __TFM_NS_MAILBOX_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_ns_svc.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_ns_svc.h deleted file mode 100644 index def0c2f..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_ns_svc.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2017-2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#include -#include "cmsis_compiler.h" - -#ifndef __TFM_NS_SVC_H__ -#define __TFM_NS_SVC_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Include all the SVC handler headers - */ -#include "tfm_nspm_svc_handler.h" - -/** - * \brief Macro to encode an svc instruction - * - */ -#define SVC(code) __ASM volatile("svc %0" : : "I" (code)) - -/** - * \def LIST_SVC_NSPM - * - * \brief This is an X macro which lists - * the SVC interface exposed by TF-M - * for the NS OS. - * - */ -#define LIST_SVC_NSPM \ - X(SVC_TFM_NSPM_REGISTER_CLIENT_ID, tfm_nspm_svc_register_client_id) \ - -/** - * \brief Numbers associated to each SVC available - * - * \details Start from 1 as 0 is reserved by RTX - */ -enum tfm_svc_num { - SVC_INVALID = 0, - -#define X(SVC_ENUM, SVC_HANDLER) SVC_ENUM, - - /* SVC API for Services */ -#ifdef TFM_NS_CLIENT_IDENTIFICATION - LIST_SVC_NSPM -#endif - -#undef X - - /* add all the new entries above this line */ - SVC_TFM_MAX, -}; - -/* number of user SVC functions */ -#define USER_SVC_COUNT ((uint32_t)SVC_TFM_MAX - 1) - -#ifdef __cplusplus -} -#endif - -#endif /* __TFM_NS_SVC_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_platform_api.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_platform_api.h deleted file mode 100644 index 8c9b0db..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_platform_api.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2018-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#ifndef __TFM_PLATFORM_API__ -#define __TFM_PLATFORM_API__ - -#include -#include -#include -#include "tfm_api.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief TFM secure partition platform API version - */ -#define TFM_PLATFORM_API_VERSION_MAJOR (0) -#define TFM_PLATFORM_API_VERSION_MINOR (3) - -#define TFM_PLATFORM_API_ID_NV_READ (1010) -#define TFM_PLATFORM_API_ID_NV_INCREMENT (1011) - -/*! - * \enum tfm_platform_err_t - * - * \brief Platform service error types - * - */ -enum tfm_platform_err_t { - TFM_PLATFORM_ERR_SUCCESS = 0, - TFM_PLATFORM_ERR_SYSTEM_ERROR, - TFM_PLATFORM_ERR_INVALID_PARAM, - TFM_PLATFORM_ERR_NOT_SUPPORTED, - - /* Following entry is only to ensure the error code of int size */ - TFM_PLATFORM_ERR_FORCE_INT_SIZE = INT_MAX -}; - -typedef int32_t tfm_platform_ioctl_req_t; - -/*! - * \brief Resets the system. - * - * \return Returns values as specified by the \ref tfm_platform_err_t - */ -enum tfm_platform_err_t tfm_platform_system_reset(void); - -/*! - * \brief Performs a platform-specific service - * - * \param[in] request Request identifier (valid values vary - * based on the platform) - * \param[in] input Input buffer to the requested service (or NULL) - * \param[in,out] output Output buffer to the requested service (or NULL) - * - * \return Returns values as specified by the \ref tfm_platform_err_t - */ -enum tfm_platform_err_t tfm_platform_ioctl(tfm_platform_ioctl_req_t request, - psa_invec *input, - psa_outvec *output); - -/*! - * \brief Increments the given non-volatile (NV) counter by one - * - * \param[in] counter_id NV counter ID. - * - * \return TFM_PLATFORM_ERR_SUCCESS if the value is read correctly. Otherwise, - * it returns TFM_PLATFORM_ERR_SYSTEM_ERROR. - */ -enum tfm_platform_err_t -tfm_platform_nv_counter_increment(uint32_t counter_id); - -/*! - * \brief Reads the given non-volatile (NV) counter - * - * \param[in] counter_id NV counter ID. - * \param[in] size Size of the buffer to store NV counter value - * in bytes. - * \param[out] val Pointer to store the current NV counter value. - * - * \return TFM_PLATFORM_ERR_SUCCESS if the value is read correctly. Otherwise, - * it returns TFM_PLATFORM_ERR_SYSTEM_ERROR. - */ -enum tfm_platform_err_t -tfm_platform_nv_counter_read(uint32_t counter_id, - uint32_t size, uint8_t *val); - -#ifdef __cplusplus -} -#endif - -#endif /* __TFM_PLATFORM_API__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_veneers.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_veneers.h deleted file mode 100644 index c66006a..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_veneers.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 2018-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ - -#ifndef __TFM_VENEERS_H__ -#define __TFM_VENEERS_H__ - -#include "tfm_api.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef TFM_PARTITION_PROTECTED_STORAGE -/******** TFM_SP_PS ********/ -psa_status_t tfm_tfm_ps_set_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_ps_get_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_ps_get_info_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_ps_remove_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_ps_get_support_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_PROTECTED_STORAGE */ - -#ifdef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE -/******** TFM_SP_ITS ********/ -psa_status_t tfm_tfm_its_set_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_its_get_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_its_get_info_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_its_remove_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */ - -#ifdef TFM_PARTITION_AUDIT_LOG -/******** TFM_SP_AUDIT_LOG ********/ -psa_status_t tfm_audit_core_retrieve_record_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_audit_core_add_record_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_audit_core_get_info_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_audit_core_get_record_info_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_audit_core_delete_record_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_AUDIT_LOG */ - -#ifdef TFM_PARTITION_CRYPTO -/******** TFM_SP_CRYPTO ********/ -psa_status_t tfm_tfm_crypto_get_key_attributes_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_open_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_close_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_reset_key_attributes_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_import_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_destroy_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_export_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_export_public_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_copy_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_hash_compute_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_hash_compare_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_hash_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_hash_update_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_hash_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_hash_verify_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_hash_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_hash_clone_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_mac_compute_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_mac_verify_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_mac_sign_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_mac_verify_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_mac_update_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_mac_sign_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_mac_verify_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_mac_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_cipher_encrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_cipher_decrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_cipher_encrypt_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_cipher_decrypt_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_cipher_generate_iv_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_cipher_set_iv_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_cipher_update_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_cipher_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_cipher_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_aead_encrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_aead_decrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_aead_encrypt_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_aead_decrypt_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_aead_generate_nonce_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_aead_set_nonce_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_aead_set_lengths_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_aead_update_ad_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_aead_update_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_aead_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_aead_verify_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_aead_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_sign_hash_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_verify_hash_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_asymmetric_encrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_asymmetric_decrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_key_derivation_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_key_derivation_get_capacity_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_key_derivation_set_capacity_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_key_derivation_input_bytes_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_key_derivation_input_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_key_derivation_key_agreement_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_key_derivation_output_bytes_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_key_derivation_output_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_key_derivation_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_raw_key_agreement_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_generate_random_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_generate_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_CRYPTO */ - -#ifdef TFM_PARTITION_PLATFORM -/******** TFM_SP_PLATFORM ********/ -psa_status_t tfm_platform_sp_system_reset_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_platform_sp_ioctl_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_platform_sp_nv_counter_read_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_platform_sp_nv_counter_increment_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_PLATFORM */ - -#ifdef TFM_PARTITION_INITIAL_ATTESTATION -/******** TFM_SP_INITIAL_ATTESTATION ********/ -psa_status_t tfm_initial_attest_get_token_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_initial_attest_get_token_size_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_initial_attest_get_public_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_INITIAL_ATTESTATION */ - -#ifdef TFM_PARTITION_TEST_CORE -/******** TFM_SP_CORE_TEST ********/ -psa_status_t tfm_spm_core_test_sfn_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_spm_core_test_sfn_init_success_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_spm_core_test_sfn_direct_recursion_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_TEST_CORE */ - -#ifdef TFM_PARTITION_TEST_CORE -/******** TFM_SP_CORE_TEST_2 ********/ -psa_status_t tfm_spm_core_test_2_slave_service_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_spm_core_test_2_sfn_invert_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_spm_core_test_2_check_caller_client_id_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_spm_core_test_2_get_every_second_byte_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_spm_core_test_2_prepare_test_scenario_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_spm_core_test_2_execute_test_scenario_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_TEST_CORE */ - -#ifdef TFM_PARTITION_TEST_SECURE_SERVICES -/******** TFM_SP_SECURE_TEST_PARTITION ********/ -psa_status_t tfm_tfm_secure_client_service_sfn_run_tests_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ - -#ifdef TFM_PARTITION_TEST_CORE_IPC -/******** TFM_SP_IPC_SERVICE_TEST ********/ -#endif /* TFM_PARTITION_TEST_CORE_IPC */ - -#ifdef TFM_PARTITION_TEST_CORE_IPC -/******** TFM_SP_IPC_CLIENT_TEST ********/ -#endif /* TFM_PARTITION_TEST_CORE_IPC */ - -#ifdef TFM_ENABLE_IRQ_TEST -/******** TFM_IRQ_TEST_1 ********/ -psa_status_t tfm_spm_irq_test_1_prepare_test_scenario_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_spm_irq_test_1_execute_test_scenario_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_ENABLE_IRQ_TEST */ - -#ifdef TFM_PARTITION_TEST_PS -/******** TFM_SP_PS_TEST ********/ -psa_status_t tfm_tfm_ps_test_prepare_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_TEST_PS */ - -#ifdef TFM_PARTITION_TEST_SECURE_SERVICES -/******** TFM_SP_SECURE_CLIENT_2 ********/ -psa_status_t tfm_tfm_secure_client_2_call_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ - -#ifdef TFM_MULTI_CORE_TEST -/******** TFM_SP_MULTI_CORE_TEST ********/ -#endif /* TFM_MULTI_CORE_TEST */ - -#ifdef __cplusplus -} -#endif - -#endif /* __TFM_VENEERS_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/src/tfm_crypto_ipc_api.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/src/tfm_crypto_ipc_api.c deleted file mode 100644 index 70b3a0d..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/src/tfm_crypto_ipc_api.c +++ /dev/null @@ -1,1875 +0,0 @@ -/* - * Copyright (c) 2018-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#include "tfm_crypto_defs.h" -#include "psa/crypto.h" -#include "tfm_ns_interface.h" -#include "psa_manifest/sid.h" -#include "psa/client.h" - -#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0])) - -#define PSA_CONNECT(service) \ - psa_handle_t ipc_handle; \ - ipc_handle = psa_connect(service##_SID, service##_VERSION); \ - if (!PSA_HANDLE_IS_VALID(ipc_handle)) { \ - return PSA_ERROR_GENERIC_ERROR; \ - } \ - -#define PSA_CLOSE() psa_close(ipc_handle) - -#define API_DISPATCH(sfn_name, sfn_id) \ - psa_call(ipc_handle, PSA_IPC_CALL, \ - in_vec, ARRAY_SIZE(in_vec), \ - out_vec, ARRAY_SIZE(out_vec)) - -#define API_DISPATCH_NO_OUTVEC(sfn_name, sfn_id) \ - psa_call(ipc_handle, PSA_IPC_CALL, \ - in_vec, ARRAY_SIZE(in_vec), \ - (psa_outvec *)NULL, 0) - -psa_status_t psa_crypto_init(void) -{ - /* Service init is performed during TFM boot up, - * so application level initialisation is empty - */ - return PSA_SUCCESS; -} - -psa_status_t psa_open_key(psa_key_id_t id, - psa_key_handle_t *handle) -{ -#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - const struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_OPEN_KEY_SID, - }; - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = &id, .len = sizeof(psa_key_id_t)}, - }; - psa_outvec out_vec[] = { - {.base = handle, .len = sizeof(psa_key_handle_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_open_key, - TFM_CRYPTO_OPEN_KEY); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ -} - -psa_status_t psa_close_key(psa_key_handle_t handle) -{ -#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - const struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_CLOSE_KEY_SID, - .key_handle = handle, - }; - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH_NO_OUTVEC(tfm_crypto_close_key, - TFM_CRYPTO_CLOSE_KEY);; - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ -} - -psa_status_t psa_import_key(const psa_key_attributes_t *attributes, - const uint8_t *data, - size_t data_length, - psa_key_handle_t *handle) -{ -#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_IMPORT_KEY_SID, - }; - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = attributes, .len = sizeof(psa_key_attributes_t)}, - {.base = data, .len = data_length} - }; - psa_outvec out_vec[] = { - {.base = handle, .len = sizeof(psa_key_handle_t)} - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_import_key, - TFM_CRYPTO_IMPORT_KEY); - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ -} - -psa_status_t psa_destroy_key(psa_key_handle_t handle) -{ -#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_DESTROY_KEY_SID, - .key_handle = handle, - }; - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH_NO_OUTVEC(tfm_crypto_destroy_key, - TFM_CRYPTO_DESTROY_KEY); - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ -} - -psa_status_t psa_get_key_attributes(psa_key_handle_t handle, - psa_key_attributes_t *attributes) -{ -#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_GET_KEY_ATTRIBUTES_SID, - .key_handle = handle, - }; - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = attributes, .len = sizeof(psa_key_attributes_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_get_key_attributes, - TFM_CRYPTO_GET_KEY_ATTRIBUTES); - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ -} - -void psa_reset_key_attributes(psa_key_attributes_t *attributes) -{ -#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED - return; -#else - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_RESET_KEY_ATTRIBUTES_SID, - }; - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = attributes, .len = sizeof(psa_key_attributes_t)}, - }; - - psa_handle_t ipc_handle; - ipc_handle = psa_connect(TFM_CRYPTO_SID, TFM_CRYPTO_VERSION); - if (!PSA_HANDLE_IS_VALID(ipc_handle)) { - return; - } - - (void)API_DISPATCH(tfm_crypto_reset_key_attributes, - TFM_CRYPTO_RESET_KEY_ATTRIBUTES); - PSA_CLOSE(); - - return; -#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ -} - -psa_status_t psa_export_key(psa_key_handle_t handle, - uint8_t *data, - size_t data_size, - size_t *data_length) -{ -#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_EXPORT_KEY_SID, - .key_handle = handle, - }; - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = data, .len = data_size} - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_export_key, - TFM_CRYPTO_EXPORT_KEY); - - *data_length = out_vec[0].len; - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ -} - -psa_status_t psa_export_public_key(psa_key_handle_t handle, - uint8_t *data, - size_t data_size, - size_t *data_length) -{ -#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_EXPORT_PUBLIC_KEY_SID, - .key_handle = handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = data, .len = data_size} - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_export_public_key, - TFM_CRYPTO_EXPORT_PUBLIC_KEY); - - *data_length = out_vec[0].len; - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ -} - -psa_status_t psa_copy_key(psa_key_handle_t source_handle, - const psa_key_attributes_t *attributes, - psa_key_handle_t *target_handle) -{ -#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_COPY_KEY_SID, - .key_handle = source_handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = attributes, .len = sizeof(psa_key_attributes_t)}, - - }; - - psa_outvec out_vec[] = { - {.base = target_handle, .len = sizeof(psa_key_handle_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_copy_key, - TFM_CRYPTO_COPY_KEY); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ -} - -psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation, - unsigned char *iv, - size_t iv_size, - size_t *iv_length) -{ -#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_CIPHER_GENERATE_IV_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - {.base = iv, .len = iv_size}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_cipher_generate_iv, - TFM_CRYPTO_CIPHER_GENERATE_IV); - - *iv_length = out_vec[1].len; - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ -} - -psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, - const unsigned char *iv, - size_t iv_length) -{ -#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_CIPHER_SET_IV_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = iv, .len = iv_length}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_cipher_set_iv, - TFM_CRYPTO_CIPHER_SET_IV); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ -} - -psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg) -{ -#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_CIPHER_ENCRYPT_SETUP_SID, - .key_handle = handle, - .alg = alg, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_cipher_encrypt_setup, - TFM_CRYPTO_CIPHER_ENCRYPT_SETUP); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ -} - -psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg) -{ -#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_CIPHER_DECRYPT_SETUP_SID, - .key_handle = handle, - .alg = alg, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_cipher_decrypt_setup, - TFM_CRYPTO_CIPHER_DECRYPT_SETUP); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ -} - -psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, - const uint8_t *input, - size_t input_length, - unsigned char *output, - size_t output_size, - size_t *output_length) -{ -#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_CIPHER_UPDATE_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = input, .len = input_length}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - {.base = output, .len = output_size} - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_cipher_update, - TFM_CRYPTO_CIPHER_UPDATE); - - *output_length = out_vec[1].len; - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ -} - -psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation) -{ -#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_CIPHER_ABORT_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_cipher_abort, - TFM_CRYPTO_CIPHER_ABORT); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ -} - -psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, - uint8_t *output, - size_t output_size, - size_t *output_length) -{ -#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_CIPHER_FINISH_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - {.base = output, .len = output_size}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_cipher_finish, - TFM_CRYPTO_CIPHER_FINISH); - - *output_length = out_vec[1].len; - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ -} - -psa_status_t psa_hash_setup(psa_hash_operation_t *operation, - psa_algorithm_t alg) -{ -#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_HASH_SETUP_SID, - .alg = alg, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_hash_setup, - TFM_CRYPTO_HASH_SETUP); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_HASH_MODULE_DISABLED */ -} - -psa_status_t psa_hash_update(psa_hash_operation_t *operation, - const uint8_t *input, - size_t input_length) -{ -#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_HASH_UPDATE_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = input, .len = input_length}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_hash_update, - TFM_CRYPTO_HASH_UPDATE); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_HASH_MODULE_DISABLED */ -} - -psa_status_t psa_hash_finish(psa_hash_operation_t *operation, - uint8_t *hash, - size_t hash_size, - size_t *hash_length) -{ -#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_HASH_FINISH_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - {.base = hash, .len = hash_size}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_hash_finish, - TFM_CRYPTO_HASH_FINISH); - - *hash_length = out_vec[1].len; - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_HASH_MODULE_DISABLED */ -} - -psa_status_t psa_hash_verify(psa_hash_operation_t *operation, - const uint8_t *hash, - size_t hash_length) -{ -#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_HASH_VERIFY_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = hash, .len = hash_length}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_hash_verify, - TFM_CRYPTO_HASH_VERIFY); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_HASH_MODULE_DISABLED */ -} - -psa_status_t psa_hash_abort(psa_hash_operation_t *operation) -{ -#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_HASH_ABORT_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_hash_abort, - TFM_CRYPTO_HASH_ABORT); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_HASH_MODULE_DISABLED */ -} - -psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation, - psa_hash_operation_t *target_operation) -{ -#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_HASH_CLONE_SID, - .op_handle = source_operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = target_operation, .len = sizeof(psa_hash_operation_t)}, - }; - - if (target_operation && (target_operation->handle != 0)) { - return PSA_ERROR_BAD_STATE; - } - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_hash_clone, - TFM_CRYPTO_HASH_CLONE); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_HASH_MODULE_DISABLED */ -} - -psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg) -{ -#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_MAC_SIGN_SETUP_SID, - .key_handle = handle, - .alg = alg, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_mac_sign_setup, - TFM_CRYPTO_MAC_SIGN_SETUP); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */ -} - -psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg) -{ -#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_MAC_VERIFY_SETUP_SID, - .key_handle = handle, - .alg = alg, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_mac_verify_setup, - TFM_CRYPTO_MAC_VERIFY_SETUP); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */ -} - -psa_status_t psa_mac_update(psa_mac_operation_t *operation, - const uint8_t *input, - size_t input_length) -{ -#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_MAC_UPDATE_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = input, .len = input_length}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_mac_update, - TFM_CRYPTO_MAC_UPDATE); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */ -} - -psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, - uint8_t *mac, - size_t mac_size, - size_t *mac_length) -{ -#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_MAC_SIGN_FINISH_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - {.base = mac, .len = mac_size}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_mac_sign_finish, - TFM_CRYPTO_MAC_SIGN_FINISH); - - *mac_length = out_vec[1].len; - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */ -} - -psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation, - const uint8_t *mac, - size_t mac_length) -{ -#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_MAC_VERIFY_FINISH_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = mac, .len = mac_length}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_mac_verify_finish, - TFM_CRYPTO_MAC_VERIFY_FINISH); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */ -} - -psa_status_t psa_mac_abort(psa_mac_operation_t *operation) -{ -#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_MAC_ABORT_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_mac_abort, - TFM_CRYPTO_MAC_ABORT); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */ -} - -psa_status_t psa_aead_encrypt(psa_key_handle_t handle, - 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 *ciphertext, - size_t ciphertext_size, - size_t *ciphertext_length) -{ -#ifdef TFM_CRYPTO_AEAD_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_AEAD_ENCRYPT_SID, - .key_handle = handle, - .alg = alg, - .aead_in = {.nonce = {0}, .nonce_length = nonce_length} - }; - - /* Sanitize the optional input */ - if ((additional_data == NULL) && (additional_data_length != 0)) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - size_t idx = 0; - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = plaintext, .len = plaintext_length}, - {.base = additional_data, .len = additional_data_length}, - }; - psa_outvec out_vec[] = { - {.base = ciphertext, .len = ciphertext_size}, - }; - - if (nonce_length > TFM_CRYPTO_MAX_NONCE_LENGTH) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - if (nonce != NULL) { - for (idx = 0; idx < nonce_length; idx++) { - iov.aead_in.nonce[idx] = nonce[idx]; - } - } - - PSA_CONNECT(TFM_CRYPTO); - - size_t in_len = ARRAY_SIZE(in_vec); - if (additional_data == NULL) { - in_len--; - } - status = psa_call(ipc_handle, PSA_IPC_CALL, in_vec, in_len, - out_vec, ARRAY_SIZE(out_vec)); - - *ciphertext_length = out_vec[0].len; - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_AEAD_MODULE_DISABLED */ -} - -psa_status_t psa_aead_decrypt(psa_key_handle_t handle, - 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 *ciphertext, - size_t ciphertext_length, - uint8_t *plaintext, - size_t plaintext_size, - size_t *plaintext_length) -{ -#ifdef TFM_CRYPTO_AEAD_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_AEAD_DECRYPT_SID, - .key_handle = handle, - .alg = alg, - .aead_in = {.nonce = {0}, .nonce_length = nonce_length} - }; - - /* Sanitize the optional input */ - if ((additional_data == NULL) && (additional_data_length != 0)) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - size_t idx = 0; - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = ciphertext, .len = ciphertext_length}, - {.base = additional_data, .len = additional_data_length}, - }; - psa_outvec out_vec[] = { - {.base = plaintext, .len = plaintext_size}, - }; - - if (nonce_length > TFM_CRYPTO_MAX_NONCE_LENGTH) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - if (nonce != NULL) { - for (idx = 0; idx < nonce_length; idx++) { - iov.aead_in.nonce[idx] = nonce[idx]; - } - } - - PSA_CONNECT(TFM_CRYPTO); - - size_t in_len = ARRAY_SIZE(in_vec); - if (additional_data == NULL) { - in_len--; - } - status = psa_call(ipc_handle, PSA_IPC_CALL, in_vec, in_len, - out_vec, ARRAY_SIZE(out_vec)); - - *plaintext_length = out_vec[0].len; - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_AEAD_MODULE_DISABLED */ -} - -psa_status_t psa_asymmetric_sign(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *hash, - size_t hash_length, - uint8_t *signature, - size_t signature_size, - size_t *signature_length) -{ - return psa_sign_hash(handle, alg, hash, hash_length, signature, signature_size, signature_length); -} - -psa_status_t psa_sign_hash(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *hash, - size_t hash_length, - uint8_t *signature, - size_t signature_size, - size_t *signature_length) -{ -#ifdef TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_SIGN_HASH_SID, - .key_handle = handle, - .alg = alg, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = hash, .len = hash_length}, - }; - psa_outvec out_vec[] = { - {.base = signature, .len = signature_size}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_sign_hash, - TFM_CRYPTO_SIGN_HASH); - - *signature_length = out_vec[0].len; - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED */ -} - -psa_status_t psa_asymmetric_verify(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *hash, - size_t hash_length, - const uint8_t *signature, - size_t signature_length) -{ - return psa_verify_hash(handle, alg, hash, hash_length, signature, signature_length); -} - -psa_status_t psa_verify_hash(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *hash, - size_t hash_length, - const uint8_t *signature, - size_t signature_length) -{ -#ifdef TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_VERIFY_HASH_SID, - .key_handle = handle, - .alg = alg - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = hash, .len = hash_length}, - {.base = signature, .len = signature_length} - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH_NO_OUTVEC(tfm_crypto_verify_hash, - TFM_CRYPTO_VERIFY_HASH); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED */ -} - -psa_status_t psa_asymmetric_encrypt(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - const uint8_t *salt, - size_t salt_length, - uint8_t *output, - size_t output_size, - size_t *output_length) -{ -#ifdef TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_ASYMMETRIC_ENCRYPT_SID, - .key_handle = handle, - .alg = alg - }; - - /* Sanitize the optional input */ - if ((salt == NULL) && (salt_length != 0)) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = input, .len = input_length}, - {.base = salt, .len = salt_length} - }; - - psa_outvec out_vec[] = { - {.base = output, .len = output_size}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - size_t in_len = ARRAY_SIZE(in_vec); - if (salt == NULL) { - in_len--; - } - status = psa_call(ipc_handle, PSA_IPC_CALL, in_vec, in_len, - out_vec, ARRAY_SIZE(out_vec)); - - *output_length = out_vec[0].len; - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED */ -} - -psa_status_t psa_asymmetric_decrypt(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - const uint8_t *salt, - size_t salt_length, - uint8_t *output, - size_t output_size, - size_t *output_length) -{ -#ifdef TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_ASYMMETRIC_DECRYPT_SID, - .key_handle = handle, - .alg = alg - }; - - /* Sanitize the optional input */ - if ((salt == NULL) && (salt_length != 0)) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = input, .len = input_length}, - {.base = salt, .len = salt_length} - }; - - psa_outvec out_vec[] = { - {.base = output, .len = output_size}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - size_t in_len = ARRAY_SIZE(in_vec); - if (salt == NULL) { - in_len--; - } - status = psa_call(ipc_handle, PSA_IPC_CALL, in_vec, in_len, - out_vec, ARRAY_SIZE(out_vec)); - - *output_length = out_vec[0].len; - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED */ -} - -psa_status_t psa_key_derivation_get_capacity( - const psa_key_derivation_operation_t *operation, - size_t *capacity) -{ -#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_KEY_DERIVATION_GET_CAPACITY_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - - psa_outvec out_vec[] = { - {.base = capacity, .len = sizeof(size_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_key_derivation_get_capacity, - TFM_CRYPTO_KEY_DERIVATION_GET_CAPACITY); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ -} - -psa_status_t psa_key_derivation_output_bytes( - psa_key_derivation_operation_t *operation, - uint8_t *output, - size_t output_length) -{ -#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_KEY_DERIVATION_OUTPUT_BYTES_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - - psa_outvec out_vec[] = { - {.base = output, .len = output_length}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_key_derivation_output_bytes, - TFM_CRYPTO_KEY_DERIVATION_OUTPUT_BYTES); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ -} - -psa_status_t psa_key_derivation_input_key( - psa_key_derivation_operation_t *operation, - psa_key_derivation_step_t step, - psa_key_handle_t handle) -{ -#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_KEY_DERIVATION_INPUT_KEY_SID, - .key_handle = handle, - .step = step, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH_NO_OUTVEC(tfm_crypto_key_derivation_input_key, - TFM_CRYPTO_KEY_DERIVATION_INPUT_KEY); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ -} - -psa_status_t psa_key_derivation_abort( - psa_key_derivation_operation_t *operation) -{ -#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_KEY_DERIVATION_ABORT_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_key_derivation_abort, - TFM_CRYPTO_KEY_DERIVATION_ABORT); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ -} - -psa_status_t psa_key_derivation_key_agreement( - psa_key_derivation_operation_t *operation, - psa_key_derivation_step_t step, - psa_key_handle_t private_key, - const uint8_t *peer_key, - size_t peer_key_length) -{ -#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_KEY_DERIVATION_KEY_AGREEMENT_SID, - .key_handle = private_key, - .step = step, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = peer_key, .len = peer_key_length}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH_NO_OUTVEC(tfm_crypto_key_derivation_key_agreement, - TFM_CRYPTO_KEY_DERIVATION_KEY_AGREEMENT); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ -} - -psa_status_t psa_generate_random(uint8_t *output, - size_t output_size) -{ -#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_GENERATE_RANDOM_SID, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - - psa_outvec out_vec[] = { - {.base = output, .len = output_size}, - }; - - if (output_size == 0) { - return PSA_SUCCESS; - } - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_generate_random, - TFM_CRYPTO_GENERATE_RANDOM); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ -} - -psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, - psa_key_handle_t *handle) -{ -#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_GENERATE_KEY_SID, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = attributes, .len = sizeof(psa_key_attributes_t)}, - }; - - psa_outvec out_vec[] = { - {.base = handle, .len = sizeof(psa_key_handle_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_generate_key, - TFM_CRYPTO_GENERATE_KEY); - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ -} - -psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes, - psa_key_type_t type, - const uint8_t *data, - size_t data_length) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_get_key_domain_parameters( - const psa_key_attributes_t *attributes, - uint8_t *data, - size_t data_size, - size_t *data_length) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_hash_compare(psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - const uint8_t *hash, - const size_t hash_length) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation, - const uint8_t *input, - size_t input_length) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_aead_finish(psa_aead_operation_t *operation, - uint8_t *ciphertext, - size_t ciphertext_size, - size_t *ciphertext_length, - uint8_t *tag, - size_t tag_size, - size_t *tag_length) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_aead_verify(psa_aead_operation_t *operation, - uint8_t *plaintext, - size_t plaintext_size, - size_t *plaintext_length, - const uint8_t *tag, - size_t tag_length) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_aead_abort(psa_aead_operation_t *operation) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_mac_compute(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - uint8_t *mac, - size_t mac_size, - size_t *mac_length) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_mac_verify(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - const uint8_t *mac, - const size_t mac_length) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_cipher_encrypt(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - uint8_t *output, - size_t output_size, - size_t *output_length) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_cipher_decrypt(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - uint8_t *output, - size_t output_size, - size_t *output_length) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, - psa_key_handle_t private_key, - const uint8_t *peer_key, - size_t peer_key_length, - uint8_t *output, - size_t output_size, - size_t *output_length) -{ -#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_RAW_KEY_AGREEMENT_SID, - .alg = alg, - .key_handle = private_key - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = peer_key, .len = peer_key_length}, - }; - - psa_outvec out_vec[] = { - {.base = output, .len = output_size}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_raw_key_agreement, - TFM_CRYPTO_RAW_KEY_AGREEMENT); - - *output_length = out_vec[0].len; - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ -} - -psa_status_t psa_key_derivation_setup(psa_key_derivation_operation_t *operation, - psa_algorithm_t alg) -{ -#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_KEY_DERIVATION_SETUP_SID, - .alg = alg, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = &(operation->handle), .len = sizeof(uint32_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_key_derivation_setup, - TFM_CRYPTO_KEY_DERIVATION_SETUP); - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ -} - -psa_status_t psa_key_derivation_set_capacity( - psa_key_derivation_operation_t *operation, - size_t capacity) -{ -#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_KEY_DERIVATION_SET_CAPACITY_SID, - .capacity = capacity, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH_NO_OUTVEC(tfm_crypto_key_derivation_set_capacity, - TFM_CRYPTO_KEY_DERIVATION_SET_CAPACITY); - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ -} - -psa_status_t psa_key_derivation_input_bytes( - psa_key_derivation_operation_t *operation, - psa_key_derivation_step_t step, - const uint8_t *data, - size_t data_length) -{ -#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_KEY_DERIVATION_INPUT_BYTES_SID, - .step = step, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = data, .len = data_length}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH_NO_OUTVEC(tfm_crypto_key_derivation_input_bytes, - TFM_CRYPTO_KEY_DERIVATION_INPUT_BYTES); - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ -} - -psa_status_t psa_key_derivation_output_key( - const psa_key_attributes_t *attributes, - psa_key_derivation_operation_t *operation, - psa_key_handle_t *handle) -{ -#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_KEY_DERIVATION_OUTPUT_KEY_SID, - .op_handle = operation->handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = attributes, .len = sizeof(psa_key_attributes_t)}, - }; - - psa_outvec out_vec[] = { - {.base = handle, .len = sizeof(psa_key_handle_t)} - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_key_derivation_output_key, - TFM_CRYPTO_KEY_DERIVATION_OUTPUT_KEY); - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ -} - -psa_status_t psa_hash_compute(psa_algorithm_t alg, - const uint8_t *input, - size_t input_length, - uint8_t *hash, - size_t hash_size, - size_t *hash_length) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation, - psa_key_handle_t handle, - psa_algorithm_t alg) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation, - uint8_t *nonce, - size_t nonce_size, - size_t *nonce_length) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation, - const uint8_t *nonce, - size_t nonce_length) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation, - size_t ad_length, - size_t plaintext_length) -{ - psa_status_t status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} - -psa_status_t psa_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 status; - - status = PSA_ERROR_NOT_SUPPORTED; - - return status; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/src/tfm_initial_attestation_ipc_api.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/src/tfm_initial_attestation_ipc_api.c deleted file mode 100644 index 78f9dec..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/src/tfm_initial_attestation_ipc_api.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2018-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#include "psa/initial_attestation.h" -#include "tfm_ns_interface.h" -#include "psa/client.h" -#include "psa/crypto_types.h" -#include "psa_manifest/sid.h" - -#define IOVEC_LEN(x) (sizeof(x)/sizeof(x[0])) - -psa_status_t -psa_initial_attest_get_token(const uint8_t *auth_challenge, - size_t challenge_size, - uint8_t *token_buf, - size_t token_buf_size, - size_t *token_size) -{ - psa_handle_t handle = PSA_NULL_HANDLE; - psa_status_t status; - - psa_invec in_vec[] = { - {auth_challenge, challenge_size} - }; - psa_outvec out_vec[] = { - {token_buf, token_buf_size} - }; - - handle = psa_connect(TFM_ATTEST_GET_TOKEN_SID, - TFM_ATTEST_GET_TOKEN_VERSION); - if (!PSA_HANDLE_IS_VALID(handle)) { - return PSA_HANDLE_TO_ERROR(handle); - } - - status = psa_call(handle, PSA_IPC_CALL, - in_vec, IOVEC_LEN(in_vec), - out_vec, IOVEC_LEN(out_vec)); - psa_close(handle); - - if (status == PSA_SUCCESS) { - *token_size = out_vec[0].len; - } - - return status; -} - -psa_status_t -psa_initial_attest_get_token_size(size_t challenge_size, - size_t *token_size) -{ - psa_handle_t handle = PSA_NULL_HANDLE; - psa_status_t status; - psa_invec in_vec[] = { - {&challenge_size, sizeof(challenge_size)} - }; - psa_outvec out_vec[] = { - {token_size, sizeof(size_t)} - }; - - handle = psa_connect(TFM_ATTEST_GET_TOKEN_SIZE_SID, - TFM_ATTEST_GET_TOKEN_SIZE_VERSION); - if (!PSA_HANDLE_IS_VALID(handle)) { - return PSA_HANDLE_TO_ERROR(handle); - } - - status = psa_call(handle, PSA_IPC_CALL, - in_vec, IOVEC_LEN(in_vec), - out_vec, IOVEC_LEN(out_vec)); - psa_close(handle); - - return status; -} - -psa_status_t -tfm_initial_attest_get_public_key(uint8_t *public_key, - size_t public_key_buf_size, - size_t *public_key_len, - psa_ecc_curve_t *elliptic_curve_type) -{ - psa_handle_t handle = PSA_NULL_HANDLE; - psa_status_t status; - - psa_outvec out_vec[] = { - {.base = public_key, .len = public_key_buf_size}, - {.base = elliptic_curve_type, .len = sizeof(*elliptic_curve_type)}, - {.base = public_key_len, .len = sizeof(*public_key_len)} - }; - - handle = psa_connect(TFM_ATTEST_GET_PUBLIC_KEY_SID, - TFM_ATTEST_GET_PUBLIC_KEY_VERSION); - if (!PSA_HANDLE_IS_VALID(handle)) { - return PSA_HANDLE_TO_ERROR(handle); - } - - status = psa_call(handle, PSA_IPC_CALL, - NULL, 0, - out_vec, IOVEC_LEN(out_vec)); - psa_close(handle); - - return status; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/src/tfm_its_ipc_api.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/src/tfm_its_ipc_api.c deleted file mode 100644 index 9326f7b..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/src/tfm_its_ipc_api.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#include "psa/internal_trusted_storage.h" -#include "tfm_api.h" - -#include "psa/client.h" -#include "psa_manifest/sid.h" - -#define IOVEC_LEN(x) (sizeof(x)/sizeof(x[0])) - -psa_status_t psa_its_set(psa_storage_uid_t uid, - size_t data_length, - const void *p_data, - psa_storage_create_flags_t create_flags) -{ - psa_status_t status; - psa_handle_t handle; - - psa_invec in_vec[] = { - { .base = &uid, .len = sizeof(uid) }, - { .base = p_data, .len = data_length }, - { .base = &create_flags, .len = sizeof(create_flags) } - }; - - handle = psa_connect(TFM_ITS_SET_SID, TFM_ITS_SET_VERSION); - if (!PSA_HANDLE_IS_VALID(handle)) { - return PSA_ERROR_GENERIC_ERROR; - } - - status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), NULL, 0); - - psa_close(handle); - - if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - return status; -} - -psa_status_t psa_its_get(psa_storage_uid_t uid, - size_t data_offset, - size_t data_size, - void *p_data, - size_t *p_data_length) -{ - psa_status_t status; - psa_handle_t handle; - - psa_invec in_vec[] = { - { .base = &uid, .len = sizeof(uid) }, - { .base = &data_offset, .len = sizeof(data_offset) } - }; - - psa_outvec out_vec[] = { - { .base = p_data, .len = data_size } - }; - - if (p_data_length == NULL) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - handle = psa_connect(TFM_ITS_GET_SID, TFM_ITS_GET_VERSION); - if (!PSA_HANDLE_IS_VALID(handle)) { - return PSA_ERROR_GENERIC_ERROR; - } - - status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), out_vec, - IOVEC_LEN(out_vec)); - - psa_close(handle); - - if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - *p_data_length = out_vec[0].len; - - return status; -} - -psa_status_t psa_its_get_info(psa_storage_uid_t uid, - struct psa_storage_info_t *p_info) -{ - psa_status_t status; - psa_handle_t handle; - - psa_invec in_vec[] = { - { .base = &uid, .len = sizeof(uid) } - }; - - psa_outvec out_vec[] = { - { .base = p_info, .len = sizeof(*p_info) } - }; - - handle = psa_connect(TFM_ITS_GET_INFO_SID, TFM_ITS_GET_INFO_VERSION); - if (!PSA_HANDLE_IS_VALID(handle)) { - return PSA_ERROR_GENERIC_ERROR; - } - - status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), out_vec, - IOVEC_LEN(out_vec)); - - psa_close(handle); - - if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - return status; -} - -psa_status_t psa_its_remove(psa_storage_uid_t uid) -{ - psa_status_t status; - psa_handle_t handle; - - psa_invec in_vec[] = { - { .base = &uid, .len = sizeof(uid) } - }; - - handle = psa_connect(TFM_ITS_REMOVE_SID, TFM_ITS_REMOVE_VERSION); - if (!PSA_HANDLE_IS_VALID(handle)) { - return PSA_ERROR_GENERIC_ERROR; - } - - status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), NULL, 0); - - psa_close(handle); - - return status; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/src/tfm_platform_ipc_api.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/src/tfm_platform_ipc_api.c deleted file mode 100644 index 0c1edf4..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/src/tfm_platform_ipc_api.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#include -#include "tfm_platform_api.h" -#include "psa_manifest/sid.h" - -enum tfm_platform_err_t tfm_platform_system_reset(void) -{ - psa_status_t status = PSA_ERROR_CONNECTION_REFUSED; - psa_handle_t handle = PSA_NULL_HANDLE; - - handle = psa_connect(TFM_SP_PLATFORM_SYSTEM_RESET_SID, - TFM_SP_PLATFORM_SYSTEM_RESET_VERSION); - if (handle <= 0) { - return TFM_PLATFORM_ERR_SYSTEM_ERROR; - } - - status = psa_call(handle, PSA_IPC_CALL, - NULL, 0, NULL, 0); - psa_close(handle); - - if (status < PSA_SUCCESS) { - return TFM_PLATFORM_ERR_SYSTEM_ERROR; - } else { - return (enum tfm_platform_err_t) status; - } - -} - -enum tfm_platform_err_t -tfm_platform_ioctl(tfm_platform_ioctl_req_t request, - psa_invec *input, psa_outvec *output) -{ - tfm_platform_ioctl_req_t req = request; - struct psa_invec in_vec[2] = { {0} }; - size_t inlen, outlen; - psa_status_t status = PSA_ERROR_CONNECTION_REFUSED; - psa_handle_t handle = PSA_NULL_HANDLE; - - in_vec[0].base = &req; - in_vec[0].len = sizeof(req); - if (input != NULL) { - in_vec[1].base = input->base; - in_vec[1].len = input->len; - inlen = 2; - } else { - inlen = 1; - } - - if (output != NULL) { - outlen = 1; - } else { - outlen = 0; - } - - handle = psa_connect(TFM_SP_PLATFORM_IOCTL_SID, - TFM_SP_PLATFORM_IOCTL_VERSION); - if (handle <= 0) { - return TFM_PLATFORM_ERR_SYSTEM_ERROR; - } - - status = psa_call(handle, PSA_IPC_CALL, - in_vec, inlen, - output, outlen); - psa_close(handle); - - if (status < PSA_SUCCESS) { - return TFM_PLATFORM_ERR_SYSTEM_ERROR; - } else { - return (enum tfm_platform_err_t) status; - } -} - diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/src/tfm_ps_ipc_api.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/src/tfm_ps_ipc_api.c deleted file mode 100644 index 7cc3a63..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/src/tfm_ps_ipc_api.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 2017-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#include "psa/protected_storage.h" - -#include "tfm_ns_interface.h" -#include "psa_manifest/sid.h" - -#define IOVEC_LEN(x) (uint32_t)(sizeof(x)/sizeof(x[0])) - -psa_status_t psa_ps_set(psa_storage_uid_t uid, - size_t data_length, - const void *p_data, - psa_storage_create_flags_t create_flags) -{ - psa_status_t status; - psa_handle_t handle; - - psa_invec in_vec[] = { - { .base = &uid, .len = sizeof(uid) }, - { .base = p_data, .len = data_length }, - { .base = &create_flags, .len = sizeof(create_flags) } - }; - - handle = psa_connect(TFM_PS_SET_SID, TFM_PS_SET_VERSION); - if (!PSA_HANDLE_IS_VALID(handle)) { - return PSA_ERROR_GENERIC_ERROR; - } - - status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), - NULL, 0); - - psa_close(handle); - - /* A parameter with a buffer pointer pointer that has data length longer - * than maximum permitted is treated as a secure violation. - * TF-M framework rejects the request with TFM_ERROR_INVALID_PARAMETER. - */ - if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - return status; -} - -psa_status_t psa_ps_get(psa_storage_uid_t uid, - size_t data_offset, - size_t data_size, - void *p_data, - size_t *p_data_length) -{ - psa_status_t status; - psa_handle_t handle; - - psa_invec in_vec[] = { - { .base = &uid, .len = sizeof(uid) }, - { .base = &data_offset, .len = sizeof(data_offset) } - }; - - psa_outvec out_vec[] = { - { .base = p_data, .len = data_size } - }; - - if (p_data_length == NULL) { - return PSA_ERROR_INVALID_ARGUMENT; - } - - handle = psa_connect(TFM_PS_GET_SID, TFM_PS_GET_VERSION); - if (!PSA_HANDLE_IS_VALID(handle)) { - return PSA_ERROR_GENERIC_ERROR; - } - - status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), out_vec, - IOVEC_LEN(out_vec)); - - psa_close(handle); - - *p_data_length = out_vec[0].len; - - return status; -} - -psa_status_t psa_ps_get_info(psa_storage_uid_t uid, - struct psa_storage_info_t *p_info) -{ - psa_status_t status; - psa_handle_t handle; - - psa_invec in_vec[] = { - { .base = &uid, .len = sizeof(uid) } - }; - - psa_outvec out_vec[] = { - { .base = p_info, .len = sizeof(*p_info) } - }; - - handle = psa_connect(TFM_PS_GET_INFO_SID, TFM_PS_GET_INFO_VERSION); - if (!PSA_HANDLE_IS_VALID(handle)) { - return PSA_ERROR_GENERIC_ERROR; - } - - status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), out_vec, - IOVEC_LEN(out_vec)); - - psa_close(handle); - - return status; -} - -psa_status_t psa_ps_remove(psa_storage_uid_t uid) -{ - psa_status_t status; - psa_handle_t handle; - - psa_invec in_vec[] = { - { .base = &uid, .len = sizeof(uid) } - }; - - - handle = psa_connect(TFM_PS_REMOVE_SID, TFM_PS_REMOVE_VERSION); - if (!PSA_HANDLE_IS_VALID(handle)) { - return PSA_ERROR_GENERIC_ERROR; - } - - status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), - NULL, 0); - - psa_close(handle); - - return status; -} - -psa_status_t psa_ps_create(psa_storage_uid_t uid, size_t size, - psa_storage_create_flags_t create_flags) -{ - (void)uid; - (void)size; - (void)create_flags; - - return PSA_ERROR_NOT_SUPPORTED; -} - -psa_status_t psa_ps_set_extended(psa_storage_uid_t uid, size_t data_offset, - size_t data_length, const void *p_data) -{ - (void)uid; - (void)data_offset; - (void)data_length; - (void)p_data; - - return PSA_ERROR_NOT_SUPPORTED; -} - -uint32_t psa_ps_get_support(void) -{ - /* Initialise support_flags to a sensible default, to avoid returning an - * uninitialised value in case the secure function fails. - */ - uint32_t support_flags = 0; - psa_handle_t handle; - - psa_outvec out_vec[] = { - { .base = &support_flags, .len = sizeof(support_flags) } - }; - - /* The PSA API does not return an error, so any error from TF-M is - * ignored. - */ - handle = psa_connect(TFM_PS_GET_SUPPORT_SID, TFM_PS_GET_SUPPORT_VERSION); - if (!PSA_HANDLE_IS_VALID(handle)) { - return support_flags; - } - - (void)psa_call(handle, PSA_IPC_CALL, NULL, 0, out_vec, IOVEC_LEN(out_vec)); - - psa_close(handle); - - return support_flags; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/inc/default_random_seed.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/inc/default_random_seed.h deleted file mode 100644 index 5d15fb4..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/inc/default_random_seed.h +++ /dev/null @@ -1,44 +0,0 @@ - - -#ifndef DEFAULT_RANDOM_SEED_H -#define DEFAULT_RANDOM_SEED_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - - - -/** Read seed from the secure storage. - * - * This function will be the default function for reading the Random seed. - * - * @param buf[out] buffer to hold the seed value from the secure storage - * @param buf_len[in] input buffer length - * - * @returns - * secure storage API return value. - * - */ -int mbed_default_seed_read(unsigned char *buf, size_t buf_len); - -/** Writes seed to the secure storage. - * - * This function will be the default function for writing the Random seed. - * - * @param buf[in] buffer to the seed value - * @param buf_len[in] input buffer length - * - * @returns - * secure storage API return value. - */ -int mbed_default_seed_write(unsigned char *buf, size_t buf_len); - - -#ifdef __cplusplus -} -#endif - -#endif /* DEFAULT_RANDOM_SEED_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/inc/psa/tfm_platform_api.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/inc/psa/tfm_platform_api.h deleted file mode 100644 index 86be961..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/inc/psa/tfm_platform_api.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2018-2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#ifndef __TFM_PLATFORM_API__ -#define __TFM_PLATFORM_API__ - -#include -#include -#include "psa/client.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief TFM secure partition platform API version - */ -#define TFM_PLATFORM_API_VERSION_MAJOR (0) -#define TFM_PLATFORM_API_VERSION_MINOR (3) - -/*! - * \enum tfm_platform_err_t - * - * \brief Platform service error types - * - */ -enum tfm_platform_err_t { - TFM_PLATFORM_ERR_SUCCESS = 0, - TFM_PLATFORM_ERR_SYSTEM_ERROR, - TFM_PLATFORM_ERR_INVALID_PARAM, - TFM_PLATFORM_ERR_NOT_SUPPORTED, - - /* Following entry is only to ensure the error code of int size */ - TFM_PLATFORM_ERR_FORCE_INT_SIZE = INT_MAX -}; - -typedef int32_t tfm_platform_ioctl_req_t; - -/*! - * \brief Performs a platform-specific service - * - * \param[in] request Request identifier (valid values vary - * based on the platform) - * \param[in] input Input buffer to the requested service (or NULL) - * \param[in,out] output Output buffer to the requested service (or NULL) - * - * \return Returns values as specified by the \ref tfm_platform_err_t - */ -enum tfm_platform_err_t tfm_platform_ioctl(tfm_platform_ioctl_req_t request, - psa_invec *input, - psa_outvec *output); - - -#ifdef __cplusplus -} -#endif - -#endif /* __TFM_PLATFORM_API__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/mbed_lib.json b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/mbed_lib.json deleted file mode 100644 index b1087b1..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/mbed_lib.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "psa", - "config": { - "present": 1 - } -} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/src/psa_hrng.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/src/psa_hrng.c deleted file mode 100644 index f5c0a30..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/src/psa_hrng.c +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright (c) 2018-2020 ARM Limited - * - * 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 "trng_api.h" -#include "crypto.h" -#include "mbed_toolchain.h" - -MBED_WEAK void trng_init(trng_t *obj) -{ - (void)(obj); -} - - -MBED_WEAK void trng_free(trng_t *obj) -{ - (void)(obj); -} - -MBED_WEAK int trng_get_bytes(trng_t *obj, uint8_t *output, size_t length, size_t *output_length) -{ - ((void)(obj)); - if (output == NULL || output_length == NULL) { - return -1; - } - - psa_status_t status = psa_crypto_init(); - if (status != PSA_SUCCESS) { - return -1; - } - - status = psa_generate_random(output, length); - if (status != PSA_SUCCESS) { - return -1; - } - - *output_length = length; - - return 0; -} diff --git a/features/FEATURE_EXPERIMENTAL_API/mbed_lib.json b/features/FEATURE_EXPERIMENTAL_API/mbed_lib.json deleted file mode 100644 index d04ec872..0000000 --- a/features/FEATURE_EXPERIMENTAL_API/mbed_lib.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "experimental_api", - "config": { - "present": 1 - } -} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/attestation/main.cpp b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/attestation/main.cpp new file mode 100755 index 0000000..866123c --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/attestation/main.cpp @@ -0,0 +1,164 @@ +/* +* Copyright (c) 2019-2020 ARM Limited. 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. +*/ + +#if !defined(MBED_CONF_RTOS_PRESENT) +#error [NOT_SUPPORTED] PSA attestation test cases require RTOS to run. +#else + +#include "psa/crypto.h" + +#if ((!defined(TARGET_PSA)) || (!defined(MBEDTLS_PSA_CRYPTO_C))) +#error [NOT_SUPPORTED] Mbed Crypto is OFF - skipping. +#else + +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest/utest.h" +#include "psa/lifecycle.h" +#include "psa_initial_attestation_api.h" +#include "psa_attest_inject_key.h" +#include +#include + +#include "entropy.h" +#include "entropy_poll.h" + +/* MAX value support macro */ +#if !defined(MAX) +#define MAX(a,b) (((a)>(b))?(a):(b)) +#endif + +#define MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE \ +MAX(MBEDTLS_ENTROPY_MIN_PLATFORM, MBEDTLS_ENTROPY_BLOCK_SIZE) + +using namespace utest::v1; + +utest::v1::status_t greentea_test_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(60, "default_auto"); + return greentea_test_setup_handler(number_of_cases); +} + +#define PSA_ATTESTATION_PRIVATE_KEY_ID 17 + +static const uint8_t private_key_data[] = { + 0x49, 0xc9, 0xa8, 0xc1, 0x8c, 0x4b, 0x88, 0x56, + 0x38, 0xc4, 0x31, 0xcf, 0x1d, 0xf1, 0xc9, 0x94, + 0x13, 0x16, 0x09, 0xb5, 0x80, 0xd4, 0xfd, 0x43, + 0xa0, 0xca, 0xb1, 0x7d, 0xb2, 0xf1, 0x3e, 0xee +}; + +static const uint8_t public_key_data[] = { + 0x04, 0x77, 0x72, 0x65, 0x6f, 0x81, 0x4b, 0x39, + 0x92, 0x79, 0xd5, 0xe1, 0xf1, 0x78, 0x1f, 0xac, + 0x6f, 0x09, 0x9a, 0x3c, 0x5c, 0xa1, 0xb0, 0xe3, + 0x53, 0x51, 0x83, 0x4b, 0x08, 0xb6, 0x5e, 0x0b, + 0x57, 0x25, 0x90, 0xcd, 0xaf, 0x8f, 0x76, 0x93, + 0x61, 0xbc, 0xf3, 0x4a, 0xcf, 0xc1, 0x1e, 0x5e, + 0x07, 0x4e, 0x84, 0x26, 0xbd, 0xde, 0x04, 0xbe, + 0x6e, 0x65, 0x39, 0x45, 0x44, 0x96, 0x17, 0xde, + 0x45 +}; + +#define TEST_TOKEN_SIZE (0x200) +#define TEST_CHALLENGE_OBJ_SIZE (32u) + +#define CHALLENGE_FOR_TEST 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, \ + 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, \ + 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, \ + 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF + +static uint8_t token_buffer[TEST_TOKEN_SIZE]; +static uint8_t challenge_buffer[TEST_CHALLENGE_OBJ_SIZE] = {CHALLENGE_FOR_TEST}; + +static void check_initial_attestation_get_token() +{ + psa_status_t status = PSA_SUCCESS; + size_t exported_length; + uint8_t exported[sizeof(public_key_data)]; + enum psa_attest_err_t attest_err = PSA_ATTEST_ERR_SUCCESS; + uint32_t token_size; + + status = psa_crypto_init(); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + status = psa_attestation_inject_key(private_key_data, + sizeof(private_key_data), + PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1), + exported, + sizeof(exported), + &exported_length); + + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + TEST_ASSERT_EQUAL(sizeof(public_key_data), exported_length); + TEST_ASSERT_EQUAL(0, memcmp(public_key_data, exported, exported_length)); + + attest_err = psa_initial_attest_get_token_size(TEST_CHALLENGE_OBJ_SIZE, + &token_size); + + TEST_ASSERT_EQUAL(PSA_ATTEST_ERR_SUCCESS, attest_err); + + attest_err = psa_initial_attest_get_token(challenge_buffer, + TEST_CHALLENGE_OBJ_SIZE, + token_buffer, + &token_size); + + TEST_ASSERT_EQUAL(PSA_ATTEST_ERR_SUCCESS, attest_err); +} +/***************************************************************************************/ + +utest::v1::status_t case_teardown_handler(const Case *const source, const size_t passed, const size_t failed, const failure_t reason) +{ + psa_key_handle_t handle; + psa_open_key(PSA_ATTESTATION_PRIVATE_KEY_ID, &handle); + psa_destroy_key(handle); + mbedtls_psa_crypto_free(); + return greentea_case_teardown_handler(source, passed, failed, reason); +} + +utest::v1::status_t case_setup_handler(const Case *const source, const size_t index_of_case) +{ + psa_status_t status; + status = mbed_psa_reboot_and_request_new_security_state(PSA_LIFECYCLE_ASSEMBLY_AND_TEST); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); +#if defined(MBEDTLS_ENTROPY_NV_SEED) + uint8_t seed[MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE] = {0}; + /* inject some seed for test*/ + for (int i = 0; i < MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE; ++i) { + seed[i] = i; + } + + /* don't really care if this succeeds this is just to make crypto init pass*/ + mbedtls_psa_inject_entropy(seed, MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE); +#endif + return greentea_case_setup_handler(source, index_of_case); +} + + +Case cases[] = { + Case("PSA attestation get token", case_setup_handler, check_initial_attestation_get_token, case_teardown_handler), +}; + +Specification specification(greentea_test_setup, cases); + +int main() +{ + return !Harness::run(specification); +} + +#endif // ((!defined(TARGET_PSA)) || (!defined(MBEDTLS_PSA_CRYPTO_C))) +#endif // !defined(MBED_CONF_RTOS_PRESENT) diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/psa_attestation_testlist.md b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/psa_attestation_testlist.md new file mode 100644 index 0000000..d8d7f10 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/psa_attestation_testlist.md @@ -0,0 +1,22 @@ +# PSA Initial Attestation Testcase checklist + +| Test | Return value | API | Test Algorithm | Test Cases | +|-----------|--------------------------------------|-------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| test_a001 | PSA_ATTEST_ERR_SUCCESS | psa_initial_attest_get_token()
psa_initial_attest_get_token_size() | 1. Provide correct inputs to API with described challenge sizes
2. Expect API to return this define as return value each time
3. Verify the token | 1. Challenge_size = 32
2. Challenge_size = 48
3. Challenge_size = 64 | +| | PSA_ATTEST_ERR_INVALID_INPUT | psa_initial_attest_get_token()
psa_initial_attest_get_token_size() | 1. Provide described challenge sizes to the API along with other valid parameters
2. Expect API to return this define as return value each time | 1. Challenge_size is zero
2. Invalid challenge size between 0 and 32
3. Invalid challenge size between 32 and 64
4. Challenge_size is greater than MAX_CHALLENGE_SIZE | +| | PSA_ATTEST_ERR_TOKEN_BUFFER_OVERFLOW | psa_initial_attest_get_token() | 1. Provide described taken size to the API along with other valid parameters
2. Expect API to return this define as return value each time | Pass the token_size which less than actual/required token size | +| | PSA_ATTEST_ERR_INIT_FAILED | psa_initial_attest_get_token()
psa_initial_attest_get_token_size() | Can't simulate. Test can't generate stimulus where attestation initialisation fails | | +| | PSA_ATTEST_ERR_CLAIM_UNAVAILABLE | psa_initial_attest_get_token() | Can't simulate. Test can't generate stimulus where claim can unavailable | | +| | PSA_ATTEST_ERR_GENERAL | psa_initial_attest_get_token()
psa_initial_attest_get_token_size() | Can't simulate. Test can't generate stimulus where unexpected error happened during API operation | | + +## Note + +1. In verifying the token, only the data type of claims and presence of the mandatory claims are checked and the values of the claims are not checked. +2. Checks related to token signature validation will be part of future release + +# License +Arm PSA test suite is distributed under Apache v2.0 License. + +-------------- + +*Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.* diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/test_a001/main.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/test_a001/main.c new file mode 100644 index 0000000..396e1f2 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/test_a001/main.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2020, Arm Limited and affiliates. + * 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 "pal_mbed_os_intf.h" + +#if !defined(MBED_CONF_RTOS_PRESENT) +#error [NOT_SUPPORTED] PSA compliance attestation test cases require RTOS to run. +#else +void test_entry_a001(val_api_t *val_api, psa_api_t *psa_api); + +int main(void) +{ + test_start(test_entry_a001, COMPLIANCE_TEST_ATTESTATION); +} +#endif diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/test_a001/test_a001.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/test_a001/test_a001.c new file mode 100644 index 0000000..230e9ef --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/test_a001/test_a001.c @@ -0,0 +1,104 @@ +/** @file + * Copyright (c) 2019, 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 "val_target.h" +#include "test_a001.h" +#include "test_data.h" + +client_test_t test_a001_attestation_list[] = { + NULL, + psa_initial_attestation_get_token_test, + psa_initial_attestation_get_token_size_test, + NULL, +}; + +static int g_test_count = 1; + +int32_t psa_initial_attestation_get_token_test(caller_security_t caller) +{ + int num_checks = sizeof(check1)/sizeof(check1[0]); + uint32_t i, status, token_size; + uint8_t challenge[PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64+1]; + uint8_t token_buffer[TOKEN_SIZE]; + + for (i = 0; i < num_checks; i++) + { + val->print(PRINT_TEST, "[Check %d] ", g_test_count++); + val->print(PRINT_TEST, check1[i].test_desc, 0); + + memset(challenge, 0x2a, sizeof(challenge)); + memset(token_buffer, 0, sizeof(token_buffer)); + + status = val->attestation_function(VAL_INITIAL_ATTEST_GET_TOKEN_SIZE, + check1[i].challenge_size, &token_size); + if (status != PSA_SUCCESS) + { + if (check1[i].challenge_size != PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32 || + check1[i].challenge_size != PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48 || + check1[i].challenge_size != PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64) + { + token_size = check1[i].token_size; + check1[i].challenge_size = check1[i].actual_challenge_size; + } + else + return status; + } + + status = val->attestation_function(VAL_INITIAL_ATTEST_GET_TOKEN, challenge, + check1[i].challenge_size, token_buffer, &token_size); + TEST_ASSERT_EQUAL(status, check1[i].expected_status, TEST_CHECKPOINT_NUM(1)); + + if (check1[i].expected_status != PSA_SUCCESS) + continue; + + /* Validate the token */ + status = val->attestation_function(VAL_INITIAL_ATTEST_VERIFY_TOKEN, challenge, + check1[i].challenge_size, token_buffer, token_size); + TEST_ASSERT_EQUAL(status, PSA_SUCCESS, TEST_CHECKPOINT_NUM(2)); + } + + return VAL_STATUS_SUCCESS; +} + +int32_t psa_initial_attestation_get_token_size_test(caller_security_t caller) +{ + int num_checks = sizeof(check2)/sizeof(check2[0]); + uint32_t i, status, token_size; + + for (i = 0; i < num_checks; i++) + { + val->print(PRINT_TEST, "[Check %d] ", g_test_count++); + val->print(PRINT_TEST, check2[i].test_desc, 0); + + status = val->attestation_function(VAL_INITIAL_ATTEST_GET_TOKEN_SIZE, + check2[i].challenge_size, &token_size); + + TEST_ASSERT_EQUAL(status, check2[i].expected_status, TEST_CHECKPOINT_NUM(1)); + + if (check2[i].expected_status != PSA_SUCCESS) + continue; + + if (token_size < check2[i].challenge_size) + { + val->print(PRINT_ERROR, "Token size less than challenge size\n", 0); + return VAL_STATUS_INSUFFICIENT_SIZE; + } + } + + return VAL_STATUS_SUCCESS; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/test_a001/test_a001.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/test_a001/test_a001.h new file mode 100644 index 0000000..e066ee8 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/test_a001/test_a001.h @@ -0,0 +1,33 @@ +/** @file + * Copyright (c) 2019, 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_A001_CLIENT_TESTS_H_ +#define _TEST_A001_CLIENT_TESTS_H_ + +#include "val_attestation.h" +#define test_entry CONCAT(test_entry_, a001) +#define val CONCAT(val,test_entry) +#define psa CONCAT(psa,test_entry) + +#define TOKEN_SIZE 512 + +extern val_api_t *val; +extern psa_api_t *psa; +extern client_test_t test_a001_attestation_list[]; + +int32_t psa_initial_attestation_get_token_test(caller_security_t caller); +int32_t psa_initial_attestation_get_token_size_test(caller_security_t caller); +#endif /* _TEST_A001_CLIENT_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/test_a001/test_data.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/test_a001/test_data.h new file mode 100644 index 0000000..bfeba55 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/test_a001/test_data.h @@ -0,0 +1,103 @@ +/** @file + * Copyright (c) 2019, 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_attestation.h" + +typedef struct { + char test_desc[100]; + uint32_t challenge_size; + uint32_t actual_challenge_size; + uint32_t token_size; + psa_status_t expected_status; +} test_data; + + +static test_data check1[] = { +{"Test psa_initial_attestation_get_token with Challenge 32\n", + PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32, TOKEN_SIZE, PSA_SUCCESS +}, + +{"Test psa_initial_attestation_get_token with Challenge 48\n", + PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48, TOKEN_SIZE, PSA_SUCCESS +}, + +{"Test psa_initial_attestation_get_token with Challenge 64\n", + PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64, TOKEN_SIZE, PSA_SUCCESS +}, + +{"Test psa_initial_attestation_get_token with zero challenge size\n", + 0, 0, TOKEN_SIZE, PSA_ATTEST_ERR_INVALID_INPUT +}, + +{"Test psa_initial_attestation_get_token with small challenge size\n", + PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32-1, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32-1, + TOKEN_SIZE, PSA_ATTEST_ERR_INVALID_INPUT +}, + +{"Test psa_initial_attestation_get_token with invalid challenge size\n", + PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32+1, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32+1, + TOKEN_SIZE, PSA_ATTEST_ERR_INVALID_INPUT +}, + +{"Test psa_initial_attestation_get_token with large challenge size\n", + MAX_CHALLENGE_SIZE+1, MAX_CHALLENGE_SIZE+1, TOKEN_SIZE, PSA_ATTEST_ERR_INVALID_INPUT +}, + +{"Test psa_initial_attestation_get_token with zero as token size\n", + PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32-1, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32, + 0, PSA_ATTEST_ERR_INVALID_INPUT +}, + +{"Test psa_initial_attestation_get_token with small token size\n", + PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32-1, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32, + PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32-1, PSA_ATTEST_ERR_TOKEN_BUFFER_OVERFLOW +}, +}; + +static test_data check2[] = { +{"Test psa_initial_attestation_get_token_size with Challenge 32\n", + PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32, TOKEN_SIZE, PSA_SUCCESS +}, + +{"Test psa_initial_attestation_get_token_size with Challenge 48\n", + PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48, TOKEN_SIZE, PSA_SUCCESS +}, + +{"Test psa_initial_attestation_get_token_size with Challenge 64\n", + PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64, TOKEN_SIZE, PSA_SUCCESS +}, + +{"Test psa_initial_attestation_get_token_size with zero challenge size\n", + 0, 0, + TOKEN_SIZE, PSA_ATTEST_ERR_INVALID_INPUT +}, + +{"Test psa_initial_attestation_get_token_size with small challenge size\n", + PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32-1, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32-1, + TOKEN_SIZE, PSA_ATTEST_ERR_INVALID_INPUT +}, + +{"Test psa_initial_attestation_get_token_size with invalid challenge size\n", + PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32+1, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32+1, + TOKEN_SIZE, PSA_ATTEST_ERR_INVALID_INPUT +}, + +{"Test psa_initial_attestation_get_token_size with large challenge size\n", + MAX_CHALLENGE_SIZE+1, MAX_CHALLENGE_SIZE+1, + TOKEN_SIZE, PSA_ATTEST_ERR_INVALID_INPUT +}, +}; diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/test_a001/test_entry.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/test_a001/test_entry.c new file mode 100644 index 0000000..db253b8 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_attestation/test_a001/test_entry.c @@ -0,0 +1,52 @@ +/** @file + * Copyright (c) 2019, 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 "val_target.h" +#include "test_a001.h" + +#define TEST_NUM VAL_CREATE_TEST_ID(VAL_INITIAL_ATTESTATION_BASE, 1) +#define TEST_DESC "Testing initial attestation APIs\n" +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; + + /* test init */ + val->test_init(TEST_NUM, TEST_DESC, TEST_FIELD(TEST_ISOLATION_L1, WD_HIGH_TIMEOUT)); + if (!IS_TEST_START(val->get_status())) + { + goto test_exit; + } + + /* Execute list of tests available in test[num]_attestation_list from Non-secure side*/ + status = val->execute_non_secure_tests(TEST_NUM, test_a001_attestation_list, FALSE); + + if (VAL_ERROR(status)) + { + goto test_exit; + } + +test_exit: + val->test_exit(); +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/psa_its_testlist.md b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/psa_its_testlist.md new file mode 100644 index 0000000..b466a7e --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/psa_its_testlist.md @@ -0,0 +1,30 @@ +# PSA Internal Trusted Storage Testcase checklist + +## Requirements for Storage Test Suite + +Following are the requirements of the Storage Test Suite.
+ +1. Unless described in this document, any behaviour that is defined as IMPLEMENTATION_DEFINED in PSA Storage API document is not verified in this document.
+2. Storage Test Cases use UID value starting from 1 onwards. These UID needs to be free for successfull test execution.
+3. UID values 1 and 2 are reserved as WRITE_ONCE UID.These UID can't be free from testcase. Make sure these are free.
+ + +| Test | Return Value | API Verified | Test Algorithm | UID Usage | +|-----------|--------------------------------------|------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| test_s001 | PSA_ITS_ERROR_UID_NOT_FOUND | psa_its_get
psa_its_get_info
psa_its_remove
| 1. Call get API with UID for which no UID/Data pair is created
2. Call get_info API for which no UID/Data pair is created
3. Call remove API for which no UID/Data pair is created
4. Set valid UID/Data pair with uid1
5. Set one more set of UID/Data pair, with different uid, than previous
6. Remove the uid of step 4.
7. Call get API for removed UID/data pair
8. Call get_info API for removed UID/Data pair
9. Call remove API for removed UID/Data pair
10. Set valid UID/Data pair
11. Call get API for different uid , then created
12. Call get_info API for different uid, then created
13. Call remove API for different uid, then created
14. Remove the created UID/Data pair.
15. Remove the stray uid.
| UID value used are 5,6,7 | +| test_s002 | PSA_ITS_ERROR_WRITE_ONCE | psa_its_set
psa_its_remove
| 1. Set valid UID/data value pair , with create flag value none.2. Call get and get_info API to validate the data, attributes associated with data
3. Call set API again with same uid and create flag PSA_PS_WRITE_ONCE_FLAG
4. Call get and get_info API to validate the data, attributes associated with data is not changed after second set operation
5. try to remove the UID/data pair.
6. Create new UID/data value pair, with create flag PSA_PS_WRITE_ONCE_FLAG
7. Try to remove the created UID.
8. Call get and get_info API to validate the data, attributes associated with data
9. Again call SET with same UID , create flag PSA_PS_WRITE_ONCE_FLAG but different data length
10. Try to remove the UID, PSA_ITS_ERROR_WRITE_ONCE error should be returned
11. Call get and get_info API to validate the data, attributes associated with data
| UID value used are 1 and 2 | +| test_s003 | PSA_ITS_ERROR_INSUFFICIENT_SPACE | psa_its_set
| 1. Create UID/data pairs, with data_len 256 bytes. Do this with incrementing uid values till we have INSUFFICENT_SPACE.
2. Remove all the UID/data pairs created.
3. Repeat the steps once more, to check all previous uid are removed successfully
| UID value starts from 5 and keep on incrementing till all space is exhausted | +| test_s004 | PSA_ITS_SUCCESS | psa_its_set
psa_its_get
psa_its_get_info
psa_its_remove
| 1. Set a valid uid/data pair
2. Validate the data using get api
3. Change the data length to half of previous.
4. Call GET api with original data length , error should be returned and also the return buffer should be empty
5. Call GET api with correct data_len and validate the data received.
6. Check old data cannot be accessed.
7. Call REMOVE api to delete the UID/data pair
| UID value used is 5 | +| test_s005 | PSA_ITS_SUCCESS | psa_its_set
psa_its_get
psa_its_get_info
psa_its_remove
| 1. Set valid UID/data pair with varying uid and data_len
2. Call GET api and validate the set data
3. Call GET info api and validate the data attributes
4. Call REMOVE api to delete the UID/data pair
| UID value used are 4 | +| test_s006 | PSA_ITS_ERROR_FLAGS_NOT_SUPPORTED | psa_its_set
| 1. Call the SET_INFO with minimum flag value to max flag value
2. Call GET_INFO api and validate the flag value
3. Remove the uid/data pair
| UID value used is 5 | +| test_s007 | PSA_ITS_ERROR_INCORRECT_SIZE | psa_its_set
| 1. Create valid uid/data pair.
2. Increase the length of storage.
3. Try to access the old length using get api.
4. Try to access with valid length less than stored size.
5. Decrease the length of storage.
6. Try to access the old length.
7. Remove the uid
| UID value used is 5 | +| test_s008 | PSA_ITS_ERROR_OFFSET_INVALID | psa_its_get
| 1. Set valid UID/data pair
2. Call GET api with valid offset and offset + data_len equal to stored data size.
3. Call GET api with valid offset and offset + data_len less than stored data size.
4. Call get api with invalid offset.
5. Call get api with zero offset , but data len greater than data size.
6. Remove the uid.
| UID value used is 5 | +| test_s009 | PSA_ITS_SUCCESS | psa_its_get
psa_its_set
psa_its_get_info
| 1. Call the SET API with NULL pointer and data_len zero
2. Validate using get_info api storage should be present.
3. Call get API with NULL pointer.
4. Remove the UID.
5. Call get_info API to validate storage is removed.
6. Set storage entity with valid write_buffer , but length zero.
7. Call get_info API to validate storage attributes.
8. Call get_info api with NULL pointer and valid uid.
9. Remove the uid
| UID value used is 5
| +| test_s010 | PSA_ITS_ERROR_STORAGE_FAILURE
| psa_its_set
| 1. Call the SET API with UID value 0.
2. Check that storage creation fails.
| UID value used is 0
| + +## License +Arm PSA test suite is distributed under Apache v2.0 License. + +-------------- + +*Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.* diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/main.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/main.c new file mode 100644 index 0000000..2ab8343 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/main.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020, Arm Limited and affiliates. + * 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 "pal_mbed_os_intf.h" + +#if !defined(MBED_CONF_RTOS_PRESENT) +#error [NOT_SUPPORTED] PSA compliance its test cases require RTOS to run +#else + +#ifdef ITS_TEST +void test_entry_s001(val_api_t *val_api, psa_api_t *psa_api); +#elif PS_TEST +void test_entry_p001(val_api_t *val_api, psa_api_t *psa_api); +#endif + +int main(void) +{ +#ifdef ITS_TEST + test_start(test_entry_s001, COMPLIANCE_TEST_STORAGE); +#elif PS_TEST + test_start(test_entry_p001, COMPLIANCE_TEST_STORAGE); +#endif +} +#endif // !defined(MBED_CONF_RTOS_PRESENT) diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/test_entry.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/test_entry.c new file mode 100644 index 0000000..8b8aed9 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/test_entry.c @@ -0,0 +1,53 @@ +/** @file + * Copyright (c) 2019, 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 "val_target.h" +#include "test_s001.h" + +#define TEST_NUM VAL_CREATE_TEST_ID(VAL_STORAGE_BASE, 1) +#define TEST_DESC "UID not found check\n" + +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; + + /* test init */ + val->test_init(TEST_NUM, TEST_DESC, TEST_FIELD(TEST_ISOLATION_L1, WD_HIGH_TIMEOUT)); + if (!IS_TEST_START(val->get_status())) + { + goto test_exit; + } + + /* Execute list of tests available in test[num]_secure_storage_list from Non-secure side*/ + status = val->execute_non_secure_tests(TEST_NUM, test_s001_sst_list, FALSE); + + if (VAL_ERROR(status)) + { + goto test_exit; + } + +test_exit: + val->test_exit(); +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/test_its_data.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/test_its_data.h new file mode 100644 index 0000000..af95d04 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/test_its_data.h @@ -0,0 +1,81 @@ +/** @file + * Copyright (c) 2019, 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_S001_ITS_DATA_TESTS_H_ +#define _TEST_S001_ITS_DATA_TESTS_H_ + +#include "val_internal_trusted_storage.h" + +#define SST_FUNCTION val->its_function +#define psa_sst_uid_t psa_its_uid_t + +typedef struct { + enum its_function_code api; + psa_its_status_t status; +} test_data; + +static struct psa_its_info_t info; +static const test_data s001_data[] = { +{ + 0, 0 /* Unused Index0 */ +}, +{ + VAL_ITS_GET, PSA_ITS_ERROR_UID_NOT_FOUND /* Call the get API when no UID is set */ +}, +{ + VAL_ITS_GET_INFO, PSA_ITS_ERROR_UID_NOT_FOUND /* Call the get_info API when no UID is set */ +}, +{ + VAL_ITS_REMOVE, PSA_ITS_ERROR_UID_NOT_FOUND /* Call the remove API when no UID is set */ +}, +{ + VAL_ITS_SET, PSA_ITS_SUCCESS /* Create a valid storage entity with UID1 */ +}, +{ + VAL_ITS_SET, PSA_ITS_SUCCESS /* Create a valid storage entity with UID2 */ +}, +{ + VAL_ITS_REMOVE, PSA_ITS_SUCCESS /* Remove UID1 */ +}, +{ + VAL_ITS_GET, PSA_ITS_ERROR_UID_NOT_FOUND /* Call get API for UID1 */ +}, +{ + VAL_ITS_GET_INFO, PSA_ITS_ERROR_UID_NOT_FOUND /* Call get_info API for UID1 */ +}, +{ + VAL_ITS_REMOVE, PSA_ITS_ERROR_UID_NOT_FOUND /* Call remove API for UID1 */ +}, +{ + VAL_ITS_SET, PSA_ITS_SUCCESS /* Create a valid storage entity again with UID1 */ +}, +{ + VAL_ITS_GET, PSA_ITS_ERROR_UID_NOT_FOUND /* Call get API for UID not same as UID1 or UID2 */ +}, +{ + VAL_ITS_GET_INFO, PSA_ITS_ERROR_UID_NOT_FOUND /* Call get_info for UID not same as UID1 or UID2 */ +}, +{ + VAL_ITS_REMOVE, PSA_ITS_ERROR_UID_NOT_FOUND /* Call remove API for UID not same as UID1 or UID2 */ +}, +{ + VAL_ITS_REMOVE, PSA_ITS_SUCCESS /* Remove UID1 */ +}, +{ + VAL_ITS_REMOVE, PSA_ITS_SUCCESS /* Remove UID2 */ +}, +}; +#endif /* _TEST_S001_ITS_DATA_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/test_ps_data.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/test_ps_data.h new file mode 100644 index 0000000..2013058 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/test_ps_data.h @@ -0,0 +1,81 @@ +/** @file + * Copyright (c) 2019, Arm Limited or ps 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_S001_PS_DATA_TESTS_H_ +#define _TEST_S001_PS_DATA_TESTS_H_ + +#include "val_protected_storage.h" + +#define SST_FUNCTION val->ps_function +#define psa_sst_uid_t psa_ps_uid_t + +typedef struct { + enum ps_function_code api; + psa_ps_status_t status; +} test_data; + +static struct psa_ps_info_t info; +static const test_data s001_data[] = { +{ + 0, 0 /* This is dummy for index0 */ +}, +{ + VAL_PS_GET, PSA_PS_ERROR_UID_NOT_FOUND /* Call the get API when no UID is set */ +}, +{ + VAL_PS_GET_INFO, PSA_PS_ERROR_UID_NOT_FOUND /* Call the get_info API when no UID is set */ +}, +{ + VAL_PS_REMOVE, PSA_PS_ERROR_UID_NOT_FOUND /* Call the remove API when no UID is set */ +}, +{ + VAL_PS_SET, PSA_PS_SUCCESS /* Create a valid storage entity with UID1 */ +}, +{ + VAL_PS_SET, PSA_PS_SUCCESS /* Create a valid storage entity with UID2 */ +}, +{ + VAL_PS_REMOVE, PSA_PS_SUCCESS /* Remove UID1 */ +}, +{ + VAL_PS_GET, PSA_PS_ERROR_UID_NOT_FOUND /* Call get API for UID1 */ +}, +{ + VAL_PS_GET_INFO, PSA_PS_ERROR_UID_NOT_FOUND /* Call get_info API for UID1 */ +}, +{ + VAL_PS_REMOVE, PSA_PS_ERROR_UID_NOT_FOUND /* Call remove API for UID1 */ +}, +{ + VAL_PS_SET, PSA_PS_SUCCESS /* Create a valid storage entity again with UID1 */ +}, +{ + VAL_PS_GET, PSA_PS_ERROR_UID_NOT_FOUND /* Call get API for UID not same as UID1 or UID2 */ +}, +{ + VAL_PS_GET_INFO, PSA_PS_ERROR_UID_NOT_FOUND /* Call get_info for UID not same as UID1 or UID2 */ +}, +{ + VAL_PS_REMOVE, PSA_PS_ERROR_UID_NOT_FOUND /* Call remove API for UID not same as UID1 or UID2 */ +}, +{ + VAL_PS_REMOVE, PSA_PS_SUCCESS /* Remove UID1 */ +}, +{ + VAL_PS_REMOVE, PSA_PS_SUCCESS /* Remove UID2 */ +}, +}; +#endif /* _TEST_S001_PS_DATA_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/test_s001.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/test_s001.c new file mode 100644 index 0000000..5e9c26f --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/test_s001.c @@ -0,0 +1,170 @@ +/** @file + * Copyright (c) 2019, 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 "val_target.h" +#include "test_s001.h" +#ifdef ITS_TEST +#include "test_its_data.h" +#elif PS_TEST +#include "test_ps_data.h" +#endif + +#define TEST_BUFF_SIZE 16 + +client_test_t test_s001_sst_list[] = { + NULL, + psa_sst_uid_not_found, + NULL, +}; + +static uint8_t write_buff[TEST_BUFF_SIZE] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}; +static uint8_t read_buff[TEST_BUFF_SIZE] = {0}; + +static int32_t sst_calls_without_set_call(psa_sst_uid_t p_uid) +{ + uint32_t status; + + /* get() without using set() before */ + val->print(PRINT_TEST, "[Check 1] Call get API for UID %d which is not set\n", p_uid); + status = SST_FUNCTION(s001_data[1].api, p_uid, 0, TEST_BUFF_SIZE, read_buff); + TEST_ASSERT_EQUAL(status,s001_data[1].status,TEST_CHECKPOINT_NUM(1)); + + /* get_info() without using set() before */ + val->print(PRINT_TEST, "[Check 2] Call get_info API for UID %d which is not set\n", p_uid); + status = SST_FUNCTION(s001_data[2].api, p_uid, &info); + TEST_ASSERT_EQUAL(status, s001_data[2].status, TEST_CHECKPOINT_NUM(2)); + + /* remove() without using set() before */ + val->print(PRINT_TEST, "[Check 3] Call remove API for UID %d which is not set\n", p_uid); + status = SST_FUNCTION(s001_data[3].api, p_uid); + TEST_ASSERT_EQUAL(status, s001_data[3].status, TEST_CHECKPOINT_NUM(3)); + + return VAL_STATUS_SUCCESS; +} + +static int32_t sst_set_and_remove(psa_sst_uid_t p_uid) +{ + uint32_t status; + + /* set() a UID1 */ + status = SST_FUNCTION(s001_data[4].api, p_uid, TEST_BUFF_SIZE, write_buff, 0); + TEST_ASSERT_EQUAL(status, s001_data[4].status, TEST_CHECKPOINT_NUM(4)); + + /* Also set() with a different UID */ + status = SST_FUNCTION(s001_data[5].api, p_uid + 1, TEST_BUFF_SIZE, write_buff, 0); + TEST_ASSERT_EQUAL(status, s001_data[5].status, TEST_CHECKPOINT_NUM(5)); + + /* remove() UID1 */ + status = SST_FUNCTION(s001_data[6].api, p_uid); + TEST_ASSERT_EQUAL(status, s001_data[6].status, TEST_CHECKPOINT_NUM(6)); + + return VAL_STATUS_SUCCESS; +} + +static int32_t sst_calls_after_uid_remove(psa_sst_uid_t p_uid) +{ + uint32_t status; + + /* get() for UID which is removed */ + val->print(PRINT_TEST, "[Check 4] Call get API for UID %d which is removed\n", p_uid); + status = SST_FUNCTION(s001_data[7].api, p_uid, 0, TEST_BUFF_SIZE, read_buff); + TEST_ASSERT_EQUAL(status, s001_data[7].status, TEST_CHECKPOINT_NUM(7)); + + /* get_info() for UID which is removed */ + val->print(PRINT_TEST, "[Check 5] Call get_info API for UID %d which is removed\n", p_uid); + status = SST_FUNCTION(s001_data[8].api, p_uid, &info); + TEST_ASSERT_EQUAL(status, s001_data[8].status, TEST_CHECKPOINT_NUM(8)); + + /* remove() for UID which is removed */ + val->print(PRINT_TEST, "[Check 6] Call remove API for UID %d which is removed\n", p_uid); + status = SST_FUNCTION(s001_data[9].api, p_uid); + TEST_ASSERT_EQUAL(status, s001_data[9].status, TEST_CHECKPOINT_NUM(9)); + + return VAL_STATUS_SUCCESS; +} + +static int32_t sst_calls_with_different_uid(psa_sst_uid_t p_uid) +{ + uint32_t status; + + /* set() a UID */ + val->print(PRINT_TEST, "Set storage for UID %d\n", p_uid); + status = SST_FUNCTION(s001_data[10].api, p_uid, TEST_BUFF_SIZE, write_buff, 0); + TEST_ASSERT_EQUAL(status, s001_data[10].status, TEST_CHECKPOINT_NUM(10)); + + /* get() for different UID then set UID */ + val->print(PRINT_TEST, "[Check 7] Call get API for different UID %d\n", p_uid); + status = SST_FUNCTION(s001_data[11].api, p_uid-1, 0, TEST_BUFF_SIZE - 1, read_buff); + TEST_ASSERT_EQUAL(status, s001_data[11].status, TEST_CHECKPOINT_NUM(11)); + + /* get_info() for different UID then set UID */ + val->print(PRINT_TEST, "[Check 8] Call get_info API for different UID %d\n", p_uid); + status = SST_FUNCTION(s001_data[12].api, p_uid-1, &info); + TEST_ASSERT_EQUAL(status, s001_data[12].status, TEST_CHECKPOINT_NUM(12)); + + /* remove() for different UID then set UID */ + val->print(PRINT_TEST, "[Check 9] Call remove API for different UID %d\n", p_uid); + status = SST_FUNCTION(s001_data[13].api, p_uid-1); + TEST_ASSERT_EQUAL(status, s001_data[13].status, TEST_CHECKPOINT_NUM(13)); + + /* remove() the set UID */ + status = SST_FUNCTION(s001_data[14].api, p_uid); + TEST_ASSERT_EQUAL(status, s001_data[14].status, TEST_CHECKPOINT_NUM(14)); + + return VAL_STATUS_SUCCESS; +} + +static int32_t sst_remove_stray_uid(psa_sst_uid_t p_uid) +{ + uint32_t status; + + /* Remove UID + 1 */ + status = SST_FUNCTION(s001_data[15].api, p_uid); + TEST_ASSERT_EQUAL(status, s001_data[15].status, TEST_CHECKPOINT_NUM(15)); + + return VAL_STATUS_SUCCESS; +} + +int32_t psa_sst_uid_not_found(caller_security_t caller) +{ + int32_t test_status; + psa_sst_uid_t uid = UID_BASE_VALUE + 6; + + test_status = sst_calls_without_set_call(uid); + if (test_status != VAL_STATUS_SUCCESS) + return test_status; + + test_status = sst_set_and_remove(uid); + if (test_status != VAL_STATUS_SUCCESS) + return test_status; + + test_status = sst_calls_after_uid_remove(uid); + if (test_status != VAL_STATUS_SUCCESS) + return test_status; + + test_status = sst_calls_with_different_uid(uid); + if (test_status != VAL_STATUS_SUCCESS) + return test_status; + + test_status = sst_remove_stray_uid(uid + 1); + if (test_status != VAL_STATUS_SUCCESS) + return test_status; + + return VAL_STATUS_SUCCESS; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/test_s001.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/test_s001.h new file mode 100644 index 0000000..08e5691 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s001/test_s001.h @@ -0,0 +1,35 @@ +/** @file + * Copyright (c) 2019, 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_S001_CLIENT_TESTS_H_ +#define _TEST_S001_CLIENT_TESTS_H_ + +#ifdef ITS_TEST +#define VAL_STORAGE_BASE VAL_INTERNAL_TRUSTED_STORAGE_BASE +#define test_entry CONCAT(test_entry_, s001) +#elif PS_TEST +#define VAL_STORAGE_BASE VAL_PROTECTED_STORAGE_BASE +#define test_entry CONCAT(test_entry_, p001) +#endif +#define val CONCAT(val,test_entry) +#define psa CONCAT(psa,test_entry) + +extern val_api_t *val; +extern psa_api_t *psa; +extern client_test_t test_s001_sst_list[]; + +int32_t psa_sst_uid_not_found(caller_security_t caller); +#endif /* _TEST_S001_CLIENT_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/main.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/main.c new file mode 100644 index 0000000..46729ac --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/main.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020, Arm Limited and affiliates. + * 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 "pal_mbed_os_intf.h" +#include "lifecycle.h" +#if !defined(MBED_CONF_RTOS_PRESENT) +#error [NOT_SUPPORTED] PSA compliance its test cases require RTOS to run +#else + +#ifdef ITS_TEST +void test_entry_s002(val_api_t *val_api, psa_api_t *psa_api); +#elif PS_TEST +void test_entry_p002(val_api_t *val_api, psa_api_t *psa_api); +#endif + +int main(void) +{ +#ifdef ITS_TEST + test_start(test_entry_s002, COMPLIANCE_TEST_STORAGE); +#elif PS_TEST + test_start(test_entry_p002, COMPLIANCE_TEST_STORAGE); +#endif +} +#endif // !defined(MBED_CONF_RTOS_PRESENT) diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/test_entry.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/test_entry.c new file mode 100644 index 0000000..538a41f --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/test_entry.c @@ -0,0 +1,53 @@ +/** @file + * Copyright (c) 2019, 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 "val_target.h" +#include "test_s002.h" + +#define TEST_NUM VAL_CREATE_TEST_ID(VAL_STORAGE_BASE, 2) +#define TEST_DESC "Write once error check\n" + +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; + + /* test init */ + val->test_init(TEST_NUM, TEST_DESC, TEST_FIELD(TEST_ISOLATION_L1, WD_HIGH_TIMEOUT)); + if (!IS_TEST_START(val->get_status())) + { + goto test_exit; + } + + /* Execute list of tests available in test[num]_secure_storage_list from Non-secure side*/ + status = val->execute_non_secure_tests(TEST_NUM, test_s002_sst_list, FALSE); + + if (VAL_ERROR(status)) + { + goto test_exit; + } + +test_exit: + val->test_exit(); +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/test_its_data.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/test_its_data.h new file mode 100644 index 0000000..303b25f --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/test_its_data.h @@ -0,0 +1,134 @@ +/** @file + * Copyright (c) 2019, 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_S002_ITS_DATA_TESTS_H_ +#define _TEST_S002_ITS_DATA_TESTS_H_ + +#include "val_internal_trusted_storage.h" + +#define SST_FUNCTION val->its_function +#define PSA_SST_FLAG_WRITE_ONCE PSA_ITS_FLAG_WRITE_ONCE +#define psa_sst_uid_t psa_its_uid_t + +typedef struct { + enum its_function_code api; + psa_its_status_t status; +} test_data; + +static struct psa_its_info_t orig_info; +static struct psa_its_info_t new_info; +static const test_data s002_data[] = { +{ + 0, 0 /* This is dummy for index0 */ +}, +{ + VAL_ITS_SET, PSA_ITS_SUCCESS /* Create a valid storage with create flag value 0 */ +}, +{ + VAL_ITS_GET_INFO, PSA_ITS_SUCCESS /* Call the get_info API to validate the attributes */ +}, +{ + 0, 0 /* Index not used as check for get info size */ +}, +{ + 0, 0 /* Index not used as check for get info flag */ +}, +{ + VAL_ITS_GET, PSA_ITS_SUCCESS /* Validate the data using get API */ +}, +{ + 0, 0 /* Index not used */ +}, +{ + VAL_ITS_SET, PSA_ITS_SUCCESS /* Change the flag to WRITE_ONCE using set API */ +}, +{ + VAL_ITS_GET_INFO, PSA_ITS_SUCCESS /* Call the get_info API to validate the flag change */ +}, +{ + 0, 0 /* Index not used as check for get info size */ +}, +{ + 0, 0 /* Index not used as check for get info flag */ +}, +{ + VAL_ITS_GET, PSA_ITS_SUCCESS /* Validate the data using get API after flag change */ +}, +{ + 0, 0 /* Index not used */ +}, +{ + VAL_ITS_REMOVE, PSA_ITS_ERROR_WRITE_ONCE /* Storage should not be removed after WRITE_ONCE flag */ +}, +{ + VAL_ITS_SET, PSA_ITS_SUCCESS /* Create a storage with different UID and flag value WRITE_ONCE */ +}, +{ + VAL_ITS_REMOVE, PSA_ITS_ERROR_WRITE_ONCE /* Storage should not be removed */ +}, +{ + VAL_ITS_GET, PSA_ITS_SUCCESS /* Validate the data using get API after flag change */ +}, +{ + 0, 0 /* Index not used */ +}, +{ + VAL_ITS_GET_INFO, PSA_ITS_SUCCESS /* Call the get_info API to validate the flag change */ +}, +{ + 0, 0 /* Index not used as check for get info size */ +}, +{ + 0, 0 /* Index not used as check for get info flag */ +}, +{ + VAL_ITS_SET, PSA_ITS_ERROR_WRITE_ONCE /* Try to set different size for same UID and flag value */ +}, +{ + VAL_ITS_REMOVE, PSA_ITS_ERROR_WRITE_ONCE /* Storage should not be removed */ +}, +{ + VAL_ITS_GET_INFO, PSA_ITS_SUCCESS /* Call the get_info API to validate the flag change */ +}, +{ + 0, 0 /* Index not used as check for get info size */ +}, +{ + 0, 0 /* Index not used as check for get info flag */ +}, +{ + VAL_ITS_GET, PSA_ITS_SUCCESS /* Validate the data using get API after flag change */ +}, +{ + 0, 0 /* Index not used */ +}, +{ + VAL_ITS_SET, PSA_ITS_ERROR_WRITE_ONCE /* Setting flag to zero for UID should fail */ +}, +{ + VAL_ITS_REMOVE, PSA_ITS_ERROR_WRITE_ONCE /* Storage should not be removed */ +}, +{ + VAL_ITS_GET_INFO, PSA_ITS_SUCCESS /* Check that the WRITE_ONCE flag is preserved */ +}, +{ + 0, 0 /* Index not used as check for get info size */ +}, +{ + 0, 0 /* Index not used as check for get info flag */ +}, +}; +#endif /* _TEST_S002_ITS_DATA_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/test_ps_data.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/test_ps_data.h new file mode 100644 index 0000000..19e88b7 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/test_ps_data.h @@ -0,0 +1,134 @@ +/** @file + * Copyright (c) 2019, Arm Limited or ps 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_S002_PS_DATA_TESTS_H_ +#define _TEST_S002_PS_DATA_TESTS_H_ + +#include "val_protected_storage.h" + +#define SST_FUNCTION val->ps_function +#define PSA_SST_FLAG_WRITE_ONCE PSA_PS_FLAG_WRITE_ONCE +#define psa_sst_uid_t psa_ps_uid_t + +typedef struct { + enum ps_function_code api; + psa_ps_status_t status; +} test_data; + +static struct psa_ps_info_t orig_info; +static struct psa_ps_info_t new_info; +static const test_data s002_data[] = { +{ + 0, 0 /* This is dummy for index0 */ +}, +{ + VAL_PS_SET, PSA_PS_SUCCESS /* Create a valid storage with create flag value 0 */ +}, +{ + VAL_PS_GET_INFO, PSA_PS_SUCCESS /* Call the get_info API to validate the attributes */ +}, +{ + 0, 0 /* Index not used as check for get info size */ +}, +{ + 0, 0 /* Index not used as check for get info flag */ +}, +{ + VAL_PS_GET, PSA_PS_SUCCESS /* Validate the data using get API */ +}, +{ + 0, 0 /* Index not used */ +}, +{ + VAL_PS_SET, PSA_PS_SUCCESS /* Change the flag to WRITE_ONCE using set API */ +}, +{ + VAL_PS_GET_INFO, PSA_PS_SUCCESS /* Call the get_info API to validate the flag change */ +}, +{ + 0, 0 /* Index not used as check for get info size */ +}, +{ + 0, 0 /* Index not used as check for get info flag */ +}, +{ + VAL_PS_GET, PSA_PS_SUCCESS /* Validate the data using get API after flag change */ +}, +{ + 0, 0 /* Index not used */ +}, +{ + VAL_PS_REMOVE, PSA_PS_ERROR_WRITE_ONCE /* Storage should not be removed after WRITE_ONCE flag */ +}, +{ + VAL_PS_SET, PSA_PS_SUCCESS /* Create storage with different UID and flag value WRITE_ONCE */ +}, +{ + VAL_PS_REMOVE, PSA_PS_ERROR_WRITE_ONCE /* Storage should not be removed */ +}, +{ + VAL_PS_GET, PSA_PS_SUCCESS /* Validate the data using get API after flag change */ +}, +{ + 0, 0 /* Index not used */ +}, +{ + VAL_PS_GET_INFO, PSA_PS_SUCCESS /* Call the get_info API to validate the flag change */ +}, +{ + 0, 0 /* Index not used as check for get info size */ +}, +{ + 0, 0 /* Index not used as check for get info flag */ +}, +{ + VAL_PS_SET, PSA_PS_ERROR_WRITE_ONCE /* Try to set different size for same UID and flag value */ +}, +{ + VAL_PS_REMOVE, PSA_PS_ERROR_WRITE_ONCE /* Storage should not be removed */ +}, +{ + VAL_PS_GET_INFO, PSA_PS_SUCCESS /* Call the get_info API to validate the flag change */ +}, +{ + 0, 0 /* Index not used as check for get info size */ +}, +{ + 0, 0 /* Index not used as check for get info flag */ +}, +{ + VAL_PS_GET, PSA_PS_SUCCESS /* Validate the data using get API after flag change */ +}, +{ + 0, 0 /* Index not used */ +}, +{ + VAL_PS_SET, PSA_PS_ERROR_WRITE_ONCE /* Setting flag to zero for UID should fail */ +}, +{ + VAL_PS_REMOVE, PSA_PS_ERROR_WRITE_ONCE /* Storage should not be removed */ +}, +{ + VAL_PS_GET_INFO, PSA_PS_SUCCESS /* Check that the WRITE_ONCE flag is preserved */ +}, +{ + 0, 0 /* Index not used as check for get info size */ +}, +{ + 0, 0 /* Index not used as check for get info flag */ +}, +}; +#endif /* _TEST_S002_PS_DATA_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/test_s002.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/test_s002.c new file mode 100644 index 0000000..d46ace1 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/test_s002.c @@ -0,0 +1,161 @@ +/** @file + * Copyright (c) 2019, Arm Limited or sst 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 "val_target.h" +#include "test_s002.h" +#ifdef ITS_TEST +#include "test_its_data.h" +#elif PS_TEST +#include "test_ps_data.h" +#endif + +#define UID_WRITE_ONCE_1 UID_BASE_VALUE + 1 +#define UID_WRITE_ONCE_2 UID_BASE_VALUE + 2 +#define TEST_BUFF_SIZE 16 + +client_test_t test_s002_sst_list[] = { + NULL, + psa_sst_update_write_once_flag_after_create, + psa_sst_create_with_write_once_flag, + NULL, +}; + +int32_t psa_sst_update_write_once_flag_after_create(caller_security_t caller) +{ + uint32_t status; + psa_sst_uid_t uid = UID_WRITE_ONCE_1; + uint8_t write_buff[TEST_BUFF_SIZE/2] = {0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE, 0xBA, 0xBE}; + uint8_t read_buff[TEST_BUFF_SIZE/2] = {0}; + uint8_t write_buff_new[TEST_BUFF_SIZE/4] = {0xFF, 0xFF, 0xFF, 0xFF}; + + /* set() data without a WRITE_ONCE flag */ + status = SST_FUNCTION(s002_data[1].api, uid, TEST_BUFF_SIZE/2, write_buff, 0); + TEST_ASSERT_EQUAL(status, s002_data[1].status, TEST_CHECKPOINT_NUM(1)); + + /* Check that get_info() returns correct attributes; also store for reference for later */ + status = SST_FUNCTION(s002_data[2].api, uid, &orig_info); + TEST_ASSERT_EQUAL(status, s002_data[2].status, TEST_CHECKPOINT_NUM(2)); + TEST_ASSERT_EQUAL(orig_info.size, TEST_BUFF_SIZE/2, TEST_CHECKPOINT_NUM(3)); + TEST_ASSERT_EQUAL(orig_info.flags, 0, TEST_CHECKPOINT_NUM(4)); + + /* Check for data consistency using get() */ + status = SST_FUNCTION(s002_data[5].api, uid, 0, TEST_BUFF_SIZE/2, read_buff); + TEST_ASSERT_EQUAL(status, s002_data[5].status, TEST_CHECKPOINT_NUM(5)); + TEST_ASSERT_MEMCMP(write_buff, read_buff, TEST_BUFF_SIZE/2, TEST_CHECKPOINT_NUM(6)); + + /* set() with WRITE_ONCE_FLAG */ + val->print(PRINT_TEST, "[Check 1] Update the flag of UID %d with WRITE_ONCE flag\n", uid); + status = SST_FUNCTION(s002_data[7].api, uid, TEST_BUFF_SIZE/4, write_buff_new, + PSA_SST_FLAG_WRITE_ONCE); + TEST_ASSERT_EQUAL(status, s002_data[7].status, TEST_CHECKPOINT_NUM(7)); + + /* Check that info is updated, after new set */ + status = SST_FUNCTION(s002_data[8].api, uid, &new_info); + TEST_ASSERT_EQUAL(status, s002_data[8].status, TEST_CHECKPOINT_NUM(8)); + TEST_ASSERT_EQUAL(new_info.size, new_info.size, TEST_CHECKPOINT_NUM(9)); + TEST_ASSERT_EQUAL(new_info.flags, new_info.flags, TEST_CHECKPOINT_NUM(10)); + + /* Check that data contents are preserved which were written with WRITE_ONCE_FLAG originally */ + status = SST_FUNCTION(s002_data[11].api, uid, 0, TEST_BUFF_SIZE/4, read_buff); + TEST_ASSERT_EQUAL(status, s002_data[11].status, TEST_CHECKPOINT_NUM(11)); + TEST_ASSERT_MEMCMP(write_buff_new, read_buff, TEST_BUFF_SIZE/4, TEST_CHECKPOINT_NUM(12)); + + /* remove() the UID */ + val->print(PRINT_TEST, "[Check 2] Try to remove the UID %d having WRITE_ONCE flag\n", uid); + status = SST_FUNCTION(s002_data[13].api, uid); + TEST_ASSERT_EQUAL(status, s002_data[13].status, TEST_CHECKPOINT_NUM(13)); + + return VAL_STATUS_SUCCESS; +} + + +int32_t psa_sst_create_with_write_once_flag(caller_security_t caller) +{ + uint32_t status; + psa_sst_uid_t uid = UID_WRITE_ONCE_2; + uint8_t write_buff[TEST_BUFF_SIZE] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}; + uint8_t read_buff[TEST_BUFF_SIZE] = {0}; + uint8_t write_buff_new[TEST_BUFF_SIZE + 1] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF}; + + /* Set data for a UID using WRITE_ONCE flag */ + val->print(PRINT_TEST, "[Check 3] Create a new UID %d with WRITE_ONCE flag\n", uid); + status = SST_FUNCTION(s002_data[14].api, uid, TEST_BUFF_SIZE, write_buff, + PSA_SST_FLAG_WRITE_ONCE); + TEST_ASSERT_EQUAL(status, s002_data[14].status, TEST_CHECKPOINT_NUM(14)); + + /* Check that remove() fails with PSA_SST_ERROR_WRITE_ONCE */ + val->print(PRINT_TEST, "[Check 4] Try to remove the UID %d having WRITE_ONCE flag\n", uid); + status = SST_FUNCTION(s002_data[15].api, uid); + TEST_ASSERT_EQUAL(status, s002_data[15].status, TEST_CHECKPOINT_NUM(15)); + + /* Check data consistency using get()*/ + status = SST_FUNCTION(s002_data[16].api, uid, 0, TEST_BUFF_SIZE, read_buff); + TEST_ASSERT_EQUAL(status, s002_data[16].status, TEST_CHECKPOINT_NUM(16)); + TEST_ASSERT_MEMCMP(write_buff, read_buff, TEST_BUFF_SIZE, TEST_CHECKPOINT_NUM(17)); + + /* Check that info values is as expected */ + status = SST_FUNCTION(s002_data[18].api, uid, &orig_info); + TEST_ASSERT_EQUAL(status, s002_data[18].status, TEST_CHECKPOINT_NUM(18)); + TEST_ASSERT_EQUAL(orig_info.size, TEST_BUFF_SIZE, TEST_CHECKPOINT_NUM(19)); + TEST_ASSERT_EQUAL(orig_info.flags, PSA_SST_FLAG_WRITE_ONCE, TEST_CHECKPOINT_NUM(20)); + + /* Try to overwrite using set() with same UID as used before with WRITE_ONCE_FLAG */ + val->print(PRINT_TEST, "[Check 5] Try to change the length of write_once UID %d\n", uid); + status = SST_FUNCTION(s002_data[21].api, uid, (TEST_BUFF_SIZE + 1), write_buff_new, + PSA_SST_FLAG_WRITE_ONCE); + TEST_ASSERT_EQUAL(status, s002_data[21].status, TEST_CHECKPOINT_NUM(21)); + + /* Check that remove() still fails with PSA_SST_ERROR_WRITE_ONCE */ + val->print(PRINT_TEST, "[Check 6] Check UID removal still fails\n", 0); + status = SST_FUNCTION(s002_data[22].api, uid); + TEST_ASSERT_EQUAL(status, s002_data[22].status, TEST_CHECKPOINT_NUM(22)); + + /* Check that info is preserved */ + status = SST_FUNCTION(s002_data[23].api, uid, &new_info); + TEST_ASSERT_EQUAL(status, s002_data[23].status, TEST_CHECKPOINT_NUM(23)); + TEST_ASSERT_EQUAL(new_info.size, orig_info.size, TEST_CHECKPOINT_NUM(24)); + TEST_ASSERT_EQUAL(new_info.flags, orig_info.flags, TEST_CHECKPOINT_NUM(25)); + + /* Check that data contents are preserved which were written with WRITE_ONCE_FLAG originally */ + status = SST_FUNCTION(s002_data[26].api, uid, 0, TEST_BUFF_SIZE, read_buff); + TEST_ASSERT_EQUAL(status, s002_data[26].status, TEST_CHECKPOINT_NUM(26)); + TEST_ASSERT_MEMCMP(write_buff, read_buff, TEST_BUFF_SIZE, TEST_CHECKPOINT_NUM(27)); + + /* Try to overwrite using set() with same UID as used before without WRITE_ONCE_FLAG */ + val->print(PRINT_TEST, "[Check 7] Try to change the WRITE_ONCE flag to None for UID %d\n", uid); + new_info.size = 0; + new_info.flags = 0; + status = SST_FUNCTION(s002_data[28].api, uid, (TEST_BUFF_SIZE - 1), write_buff_new, 0); + TEST_ASSERT_EQUAL(status, s002_data[28].status, TEST_CHECKPOINT_NUM(28)); + + /* Check that remove() still fails with PSA_SST_ERROR_WRITE_ONCE */ + val->print(PRINT_TEST, "[Check 8] Check UID removal still fails\n", 0); + status = SST_FUNCTION(s002_data[29].api, uid); + TEST_ASSERT_EQUAL(status, s002_data[29].status, TEST_CHECKPOINT_NUM(29)); + + /* Check that info is preserved */ + status = SST_FUNCTION(s002_data[30].api, uid, &new_info); + TEST_ASSERT_EQUAL(status, s002_data[30].status, TEST_CHECKPOINT_NUM(30)); + TEST_ASSERT_EQUAL(new_info.size, orig_info.size, TEST_CHECKPOINT_NUM(31)); + TEST_ASSERT_EQUAL(new_info.flags, orig_info.flags, TEST_CHECKPOINT_NUM(32)); + + return VAL_STATUS_SUCCESS; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/test_s002.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/test_s002.h new file mode 100644 index 0000000..3a06eb9 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s002/test_s002.h @@ -0,0 +1,36 @@ +/** @file + * Copyright (c) 2019, 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_S002_CLIENT_TESTS_H_ +#define _TEST_S002_CLIENT_TESTS_H_ + +#ifdef ITS_TEST +#define VAL_STORAGE_BASE VAL_INTERNAL_TRUSTED_STORAGE_BASE +#define test_entry CONCAT(test_entry_, s002) +#elif PS_TEST +#define VAL_STORAGE_BASE VAL_PROTECTED_STORAGE_BASE +#define test_entry CONCAT(test_entry_, p002) +#endif +#define val CONCAT(val,test_entry) +#define psa CONCAT(psa,test_entry) + +extern val_api_t *val; +extern psa_api_t *psa; +extern client_test_t test_s002_sst_list[]; + +int32_t psa_sst_update_write_once_flag_after_create(caller_security_t caller); +int32_t psa_sst_create_with_write_once_flag(caller_security_t caller); +#endif /* _TEST_S002_CLIENT_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/main.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/main.c new file mode 100644 index 0000000..fc7328c --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/main.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020, Arm Limited and affiliates. + * 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 "pal_mbed_os_intf.h" +#include "lifecycle.h" + +#ifndef PS_ALLOW_ENTIRE_STORAGE_FILL +#error [NOT_SUPPORTED] Test is too long for CI, thus always fails on timeout. +#endif + +#ifdef ITS_TEST +void test_entry_s003(val_api_t *val_api, psa_api_t *psa_api); +#elif PS_TEST +void test_entry_p003(val_api_t *val_api, psa_api_t *psa_api); +#endif + +int main(void) +{ +#ifdef ITS_TEST + test_start(test_entry_s003, COMPLIANCE_TEST_STORAGE); +#elif PS_TEST + test_start(test_entry_p003, COMPLIANCE_TEST_STORAGE); +#endif + +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/test_entry.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/test_entry.c new file mode 100644 index 0000000..30dcbde --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/test_entry.c @@ -0,0 +1,53 @@ +/** @file + * Copyright (c) 2019, 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 "val_target.h" +#include "test_s003.h" + +#define TEST_NUM VAL_CREATE_TEST_ID(VAL_STORAGE_BASE, 3) +#define TEST_DESC "Insufficient space check\n" + +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; + + /* test init */ + val->test_init(TEST_NUM, TEST_DESC, TEST_FIELD(TEST_ISOLATION_L1, WD_HIGH_TIMEOUT)); + if (!IS_TEST_START(val->get_status())) + { + goto test_exit; + } + + /* Execute list of tests available in test[num]_secure_storage_list from Non-secure side*/ + status = val->execute_non_secure_tests(TEST_NUM, test_s003_sst_list, FALSE); + + if (VAL_ERROR(status)) + { + goto test_exit; + } + +test_exit: + val->test_exit(); +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/test_its_data.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/test_its_data.h new file mode 100644 index 0000000..511e418 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/test_its_data.h @@ -0,0 +1,42 @@ +/** @file + * Copyright (c) 2019, 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_S003_ITS_DATA_TESTS_H_ +#define _TEST_S003_ITS_DATA_TESTS_H_ + +#include "val_internal_trusted_storage.h" + +#define SST_FUNCTION val->its_function +#define PSA_SST_SUCCESS PSA_ITS_SUCCESS +#define psa_sst_uid_t psa_its_uid_t + +typedef struct { + enum its_function_code api; + psa_its_status_t status; +} test_data; + +static const test_data s003_data[] = { +{ + 0, 0 /* This is dummy for index0 */ +}, +{ + VAL_ITS_SET, PSA_ITS_ERROR_INSUFFICIENT_SPACE /* Call set API till insufficent space */ +}, +{ + VAL_ITS_REMOVE, PSA_ITS_SUCCESS /* Remove the UID created */ +}, +}; +#endif /* _TEST_S003_ITS_DATA_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/test_ps_data.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/test_ps_data.h new file mode 100644 index 0000000..db48c35 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/test_ps_data.h @@ -0,0 +1,42 @@ +/** @file + * Copyright (c) 2019, Arm Limited or ps 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_S003_PS_DATA_TESTS_H_ +#define _TEST_S003_PS_DATA_TESTS_H_ + +#include "val_protected_storage.h" + +#define SST_FUNCTION val->ps_function +#define PSA_SST_SUCCESS PSA_PS_SUCCESS +#define psa_sst_uid_t psa_ps_uid_t + +typedef struct { + enum ps_function_code api; + psa_ps_status_t status; +} test_data; + +static const test_data s003_data[] = { +{ + 0, 0 /* This is dummy for index0 */ +}, +{ + VAL_PS_SET, PSA_PS_ERROR_INSUFFICIENT_SPACE /* Call set API till insufficent space */ +}, +{ + VAL_PS_REMOVE, PSA_PS_SUCCESS /* Remove the UID created */ +}, +}; +#endif /* _TEST_S003_PS_DATA_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/test_s003.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/test_s003.c new file mode 100644 index 0000000..3475075 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/test_s003.c @@ -0,0 +1,96 @@ +/** @file + * Copyright (c) 2019, 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 "val_target.h" +#include "test_s003.h" +#if ITS_TEST +#include "test_its_data.h" +#elif PS_TEST +#include "test_ps_data.h" +#endif + +#define TEST_BUFF_SIZE 1024 +#define NUM_ITERATIONS 2 +#define TEST_BASE_UID_VALUE UID_BASE_VALUE + 5 + +client_test_t test_s003_sst_list[] = { + NULL, + psa_sst_insufficient_space, + NULL, +}; + +static uint8_t write_buff[TEST_BUFF_SIZE]; +static char test_desc[2][80] = { + "Overload storage space\n", + "Overload storage again to verify all previous UID removed\n"}; + +int32_t psa_sst_insufficient_space(caller_security_t caller) +{ + uint32_t status = PSA_SST_SUCCESS; + psa_sst_uid_t uid; + uint32_t count = 0, results[NUM_ITERATIONS] = {0}; + int i = 0; + + /* Saturate the storage for NUM_ITERATION times, and remove them after */ + for (i = 0 ; i < NUM_ITERATIONS; i++) + { + val->print(PRINT_TEST, "[Check %d] ", i + 1); + val->print(PRINT_TEST, &test_desc[i][0], 0); + for (uid = TEST_BASE_UID_VALUE; status == PSA_SST_SUCCESS; uid++) + { + val->print(PRINT_INFO, "Setting 0x%x bytes for ", TEST_BUFF_SIZE); + val->print(PRINT_INFO, "UID %d\n", uid); + status = SST_FUNCTION(s003_data[1].api, uid, TEST_BUFF_SIZE, write_buff, 0); + if (status != PSA_SST_SUCCESS) + { + val->print(PRINT_INFO, "UID %d set failed due to insufficient space\n", uid); + break; + } + } + TEST_ASSERT_EQUAL(status, s003_data[1].status, TEST_CHECKPOINT_NUM(1)); + + /* Store number of set()s it took to saturate the storage */ + count = uid - (TEST_BASE_UID_VALUE); + results[i] = uid - (TEST_BASE_UID_VALUE); + + if (count) + val->print(PRINT_TEST, "Remove all registered UIDs\n", 0); + for (uid = TEST_BASE_UID_VALUE; uid < (count + TEST_BASE_UID_VALUE); uid++) + { + val->print(PRINT_INFO, "Removing UID %d\n", uid); + status = SST_FUNCTION(s003_data[2].api, uid); + if (status != PSA_SST_SUCCESS) + break; + } + if (count) + TEST_ASSERT_EQUAL(status, s003_data[2].status, TEST_CHECKPOINT_NUM(2)); + } + + /* Check that it takes equal number of UIDs to fill up the storage each time */ + for (i = 0; i < (NUM_ITERATIONS -1); i++) + { + if (results[i] != results[i+1]) + { + val->print(PRINT_ERROR, "\tERROR : Mismatch between number of UIDs required to\n", 0); + val->print(PRINT_ERROR, "\t fill up the storage between iteration %d", i); + val->print(PRINT_ERROR, " and iteration %d\n", i+1); + return VAL_STATUS_ERROR; + } + } + return VAL_STATUS_SUCCESS; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/test_s003.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/test_s003.h new file mode 100644 index 0000000..9fb4755 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s003/test_s003.h @@ -0,0 +1,35 @@ +/** @file + * Copyright (c) 2019, 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_S003_CLIENT_TESTS_H_ +#define _TEST_S003_CLIENT_TESTS_H_ + +#ifdef ITS_TEST +#define VAL_STORAGE_BASE VAL_INTERNAL_TRUSTED_STORAGE_BASE +#define test_entry CONCAT(test_entry_, s003) +#elif PS_TEST +#define VAL_STORAGE_BASE VAL_PROTECTED_STORAGE_BASE +#define test_entry CONCAT(test_entry_, p003) +#endif +#define val CONCAT(val,test_entry) +#define psa CONCAT(psa,test_entry) + +extern val_api_t *val; +extern psa_api_t *psa; +extern client_test_t test_s003_sst_list[]; + +int32_t psa_sst_insufficient_space(caller_security_t caller); +#endif /* _TEST_S003_CLIENT_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/main.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/main.c new file mode 100644 index 0000000..20a623e --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/main.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020, Arm Limited and affiliates. + * 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 "pal_mbed_os_intf.h" +#if !defined(MBED_CONF_RTOS_PRESENT) +#error [NOT_SUPPORTED] PSA compliance its test cases require RTOS to run +#else + +#ifdef ITS_TEST +void test_entry_s004(val_api_t *val_api, psa_api_t *psa_api); +#elif PS_TEST +void test_entry_p004(val_api_t *val_api, psa_api_t *psa_api); +#endif + +int main(void) +{ +#ifdef ITS_TEST + test_start(test_entry_s004, COMPLIANCE_TEST_STORAGE); +#elif PS_TEST + test_start(test_entry_p004, COMPLIANCE_TEST_STORAGE); +#endif +} +#endif // !defined(MBED_CONF_RTOS_PRESENT) diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/test_entry.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/test_entry.c new file mode 100644 index 0000000..a6afc24 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/test_entry.c @@ -0,0 +1,53 @@ +/** @file + * Copyright (c) 2019, 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 "val_target.h" +#include "test_s004.h" + +#define TEST_NUM VAL_CREATE_TEST_ID(VAL_STORAGE_BASE, 4) +#define TEST_DESC "Data Consistency check\n" + +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; + + /* test init */ + val->test_init(TEST_NUM, TEST_DESC, TEST_FIELD(TEST_ISOLATION_L1, WD_HIGH_TIMEOUT)); + if (!IS_TEST_START(val->get_status())) + { + goto test_exit; + } + + /* Execute list of tests available in test[num]_secure_storage_list from Non-secure side*/ + status = val->execute_non_secure_tests(TEST_NUM, test_s004_sst_list, FALSE); + + if (VAL_ERROR(status)) + { + goto test_exit; + } + +test_exit: + val->test_exit(); +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/test_its_data.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/test_its_data.h new file mode 100644 index 0000000..b41dc1b --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/test_its_data.h @@ -0,0 +1,65 @@ +/** @file + * Copyright (c) 2019, 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_S004_ITS_DATA_TESTS_H_ +#define _TEST_S004_ITS_DATA_TESTS_H_ + +#include "val_internal_trusted_storage.h" + +#define SST_FUNCTION val->its_function +#define psa_sst_uid_t psa_its_uid_t + +typedef struct { + enum its_function_code api; + psa_its_status_t status; +} test_data; + +static const test_data s004_data[] = { +{ + 0, 0 /* This is dummy for index0 */ +}, +{ + VAL_ITS_SET, PSA_ITS_SUCCESS /* Create a valid storage entity */ +}, +{ + VAL_ITS_GET, PSA_ITS_SUCCESS /* Validate the data using get API after set API failure */ +}, +{ + 0, 0 /* Index not used */ +}, +{ + VAL_ITS_SET, PSA_ITS_SUCCESS /* For same UID set the length as half of previous */ +}, +{ + VAL_ITS_GET, PSA_ITS_ERROR_INCORRECT_SIZE /* Call get with incorrect length */ +}, +{ + 0, 0 /* No data should be returned */ +}, +{ + VAL_ITS_GET, PSA_ITS_SUCCESS /* Call get API with correct length */ +}, +{ + 0, 0 /* No data should be returned */ +}, +{ + 0, 0 /* Check that we should not be able to access the old data */ +}, +{ + VAL_ITS_REMOVE, PSA_ITS_SUCCESS /* Remove the valid storage entity */ +}, +}; +#endif /* _TEST_S004_ITS_DATA_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/test_ps_data.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/test_ps_data.h new file mode 100644 index 0000000..baaf194 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/test_ps_data.h @@ -0,0 +1,65 @@ +/** @file + * Copyright (c) 2019, Arm Limited or ps 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_S004_PS_DATA_TESTS_H_ +#define _TEST_S004_PS_DATA_TESTS_H_ + +#include "val_protected_storage.h" + +#define SST_FUNCTION val->ps_function +#define psa_sst_uid_t psa_ps_uid_t + +typedef struct { + enum ps_function_code api; + psa_ps_status_t status; +} test_data; + +static const test_data s004_data[] = { +{ + 0, 0 /* This is dummy for index0 */ +}, +{ + VAL_PS_SET, PSA_PS_SUCCESS /* Create a valid storage entity */ +}, +{ + VAL_PS_GET, PSA_PS_SUCCESS /* Validate the data using get API after set API failure */ +}, +{ + 0, 0 /* Index not used */ +}, +{ + VAL_PS_SET, PSA_PS_SUCCESS /* For same UID set the length as half of previous */ +}, +{ + VAL_PS_GET, PSA_PS_ERROR_INCORRECT_SIZE /* Call get with incorrect length */ +}, +{ + 0, 0 /* No data should be returned */ +}, +{ + VAL_PS_GET, PSA_PS_SUCCESS /* Call get API with correct length */ +}, +{ + 0, 0 /* No data should be returned */ +}, +{ + 0, 0 /* Check that we should not be able to access the old data */ +}, +{ + VAL_PS_REMOVE, PSA_PS_SUCCESS /* Remove the valid storage entity */ +}, +}; +#endif /* _TEST_S004_PS_DATA_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/test_s004.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/test_s004.c new file mode 100644 index 0000000..004ee2f --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/test_s004.c @@ -0,0 +1,84 @@ +/** @file + * Copyright (c) 2019, 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 "val_target.h" +#include "test_s004.h" +#ifdef ITS_TEST +#include "test_its_data.h" +#elif PS_TEST +#include "test_ps_data.h" +#endif + +#define TEST_BUFF_SIZE 20 + +client_test_t test_s004_sst_list[] = { + NULL, + psa_sst_get_data_check, + NULL, +}; + +static psa_sst_uid_t uid = UID_BASE_VALUE + 5; +static uint8_t read_buff[TEST_BUFF_SIZE] = {0}; +static uint8_t write_buff[TEST_BUFF_SIZE] = {0x99, 0x01, 0x30, 0x50, 0x04, 0x23, 0xF6, 0x07, 0x08, \ + 0x0D, 0x70, 0xA1, 0xFF, 0xFF, 0x14, 0x73, 0x46, 0x97, 0xE8, 0xDD}; + +int32_t psa_sst_get_data_check(caller_security_t caller) +{ + uint32_t status,j; + + /* Set data for UID */ + status = SST_FUNCTION(s004_data[1].api, uid, TEST_BUFF_SIZE, write_buff,0); + TEST_ASSERT_EQUAL(status, s004_data[1].status, TEST_CHECKPOINT_NUM(1)); + + /* Call get function and check the data consistency */ + status = SST_FUNCTION(s004_data[2].api, uid, 0, TEST_BUFF_SIZE, read_buff); + TEST_ASSERT_EQUAL(status, s004_data[2].status, TEST_CHECKPOINT_NUM(2)); + TEST_ASSERT_MEMCMP(read_buff, write_buff, TEST_BUFF_SIZE, TEST_CHECKPOINT_NUM(3)); + + /* Call the set again for same uid and set the length as half */ + status = SST_FUNCTION(s004_data[4].api, uid, TEST_BUFF_SIZE/2, write_buff, 0); + TEST_ASSERT_EQUAL(status, s004_data[4].status, TEST_CHECKPOINT_NUM(4)); + + /* Call get function with incorrect buffer length */ + val->print(PRINT_TEST, "[Check 1] Call get API with incorrect length\n", 0); + memset(read_buff, 0, TEST_BUFF_SIZE); + status = SST_FUNCTION(s004_data[5].api, uid, 0, TEST_BUFF_SIZE, read_buff); + TEST_ASSERT_EQUAL(status, s004_data[5].status, TEST_CHECKPOINT_NUM(5)); + for (j = 0; j < TEST_BUFF_SIZE; j++) + { + TEST_ASSERT_EQUAL(read_buff[j], 0, TEST_CHECKPOINT_NUM(6)); + } + + /* Call get function with CORRECT buffer length */ + status = SST_FUNCTION(s004_data[7].api, uid, 0, TEST_BUFF_SIZE/2, read_buff); + TEST_ASSERT_EQUAL(status, s004_data[7].status, TEST_CHECKPOINT_NUM(7)); + TEST_ASSERT_MEMCMP(read_buff, write_buff, TEST_BUFF_SIZE/2, TEST_CHECKPOINT_NUM(8)); + + /* Check we should not be able to access old set data */ + val->print(PRINT_TEST, "[Check 2] Old buffer invalid after length change\n", 0); + for (j = TEST_BUFF_SIZE/2; j < TEST_BUFF_SIZE; j++) + { + TEST_ASSERT_EQUAL(read_buff[j], 0, TEST_CHECKPOINT_NUM(9)); + } + + /* Remove the UID */ + status = SST_FUNCTION(s004_data[10].api, uid); + TEST_ASSERT_EQUAL(status, s004_data[10].status, TEST_CHECKPOINT_NUM(10)); + + return VAL_STATUS_SUCCESS; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/test_s004.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/test_s004.h new file mode 100644 index 0000000..03c6ad1 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s004/test_s004.h @@ -0,0 +1,35 @@ +/** @file + * Copyright (c) 2019, 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_S004_CLIENT_TESTS_H_ +#define _TEST_S004_CLIENT_TESTS_H_ + +#ifdef ITS_TEST +#define VAL_STORAGE_BASE VAL_INTERNAL_TRUSTED_STORAGE_BASE +#define test_entry CONCAT(test_entry_, s004) +#elif PS_TEST +#define VAL_STORAGE_BASE VAL_PROTECTED_STORAGE_BASE +#define test_entry CONCAT(test_entry_, p004) +#endif +#define val CONCAT(val,test_entry) +#define psa CONCAT(psa,test_entry) + +extern val_api_t *val; +extern psa_api_t *psa; +extern client_test_t test_s004_sst_list[]; + +int32_t psa_sst_get_data_check(caller_security_t caller); +#endif /* _TEST_S004_CLIENT_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/main.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/main.c new file mode 100644 index 0000000..b15f531 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/main.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020, Arm Limited and affiliates. + * 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 "pal_mbed_os_intf.h" + +#if !defined(MBED_CONF_RTOS_PRESENT) +#error [NOT_SUPPORTED] PSA compliance its test cases require RTOS to run +#else + +#ifdef ITS_TEST +void test_entry_s005(val_api_t *val_api, psa_api_t *psa_api); +#elif PS_TEST +void test_entry_p005(val_api_t *val_api, psa_api_t *psa_api); +#endif + +int main(void) +{ +#ifdef ITS_TEST + test_start(test_entry_s005, COMPLIANCE_TEST_STORAGE); +#elif PS_TEST + test_start(test_entry_p005, COMPLIANCE_TEST_STORAGE); +#endif +} +#endif // !defined(MBED_CONF_RTOS_PRESENT) diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/test_entry.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/test_entry.c new file mode 100644 index 0000000..36dcbaa --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/test_entry.c @@ -0,0 +1,52 @@ +/** @file + * Copyright (c) 2019, 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 "val_target.h" +#include "test_s005.h" + +#define TEST_NUM VAL_CREATE_TEST_ID(VAL_STORAGE_BASE, 5) +#define TEST_DESC "Success scenarios check\n" + +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; + + /* test init */ + val->test_init(TEST_NUM, TEST_DESC, TEST_FIELD(TEST_ISOLATION_L1, WD_HIGH_TIMEOUT)); + if (!IS_TEST_START(val->get_status())) + { + goto test_exit; + } + + /* Execute list of tests available in test[num]_secure_storage_list from Non-secure side*/ + status = val->execute_non_secure_tests(TEST_NUM, test_s005_sst_list, FALSE); + if (VAL_ERROR(status)) + { + goto test_exit; + } + +test_exit: + val->test_exit(); +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/test_its_data.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/test_its_data.h new file mode 100644 index 0000000..653f7cc --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/test_its_data.h @@ -0,0 +1,58 @@ +/** @file + * Copyright (c) 2019, 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_S005_ITS_DATA_TESTS_H_ +#define _TEST_S005_ITS_DATA_TESTS_H_ + +#include "val_internal_trusted_storage.h" + +#define SST_FUNCTION val->its_function +#define psa_sst_uid_t psa_its_uid_t +#define psa_sst_create_flags_t psa_its_create_flags_t + +typedef struct { + enum its_function_code api; + psa_its_status_t status; +} test_data; + +static struct psa_its_info_t info; +static const test_data s005_data[] = { +{ + 0, 0 /* This is dummy for index0 */ +}, +{ + VAL_ITS_SET, PSA_ITS_SUCCESS /* Create a valid storage entity */ +}, +{ + VAL_ITS_GET, PSA_ITS_SUCCESS /* Validate the data using get API */ +}, +{ + 0, 0 /* Index not used */ +}, +{ + VAL_ITS_GET_INFO, PSA_ITS_SUCCESS /* Validate the data attributes get_info API */ +}, +{ + 0, 0 /* Index not used */ +}, +{ + 0, 0 /* Index not used */ +}, +{ + VAL_ITS_REMOVE, PSA_ITS_SUCCESS /* Remove the valid storage entity */ +}, +}; +#endif /* _TEST_S005_ITS_DATA_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/test_ps_data.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/test_ps_data.h new file mode 100644 index 0000000..a961269 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/test_ps_data.h @@ -0,0 +1,58 @@ +/** @file + * Copyright (c) 2019, Arm Limited or ps 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_S005_PS_DATA_TESTS_H_ +#define _TEST_S005_PS_DATA_TESTS_H_ + +#include "val_protected_storage.h" + +#define SST_FUNCTION val->ps_function +#define psa_sst_uid_t psa_ps_uid_t +#define psa_sst_create_flags_t psa_ps_create_flags_t + +typedef struct { + enum ps_function_code api; + psa_ps_status_t status; +} test_data; + +static struct psa_ps_info_t info; +static const test_data s005_data[] = { +{ + 0, 0 /* This is dummy for index0 */ +}, +{ + VAL_PS_SET, PSA_PS_SUCCESS /* Create a valid storage entity */ +}, +{ + VAL_PS_GET, PSA_PS_SUCCESS /* Validate the data using get API */ +}, +{ + 0, 0 /* Index not used */ +}, +{ + VAL_PS_GET_INFO, PSA_PS_SUCCESS /* Validate the data attributes get_info API */ +}, +{ + 0, 0 /* Index not used */ +}, +{ + 0, 0 /* Index not used */ +}, +{ + VAL_PS_REMOVE, PSA_PS_SUCCESS /* Remove the valid storage entity */ +}, +}; +#endif /* _TEST_S005_PS_DATA_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/test_s005.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/test_s005.c new file mode 100644 index 0000000..c974d04 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/test_s005.c @@ -0,0 +1,89 @@ +/** @file + * Copyright (c) 2019, 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 "val_target.h" +#include "test_s005.h" +#ifdef ITS_TEST +#include "test_its_data.h" +#elif PS_TEST +#include "test_ps_data.h" +#endif + +#define TEST_BUFF_SIZE 30 + +client_test_t test_s005_sst_list[] = { + NULL, + psa_sst_apis_check_success_case, + NULL, +}; + +static uint8_t read_buff[TEST_BUFF_SIZE]; +static uint8_t write_buff[TEST_BUFF_SIZE] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x23, 0xF6, 0x07, 0x08, 0x0D, 0x0A, 0x1B, 0x0C, 0x5D, 0x0E,\ + 0x70, 0xA1, 0xFF, 0xFF, 0x14, 0x73, 0x46, 0x97, 0xE8, 0xDD, 0xCA, 0x0B, 0x3C, 0x0D, 0x2E}; + +static int32_t psa_sst_apis_check(psa_sst_uid_t uid, uint32_t data_len, + uint8_t *data_buff, psa_sst_create_flags_t create_flag) +{ + uint32_t status; + + /* Set the UID with the data_len and data_buff */ + status = SST_FUNCTION(s005_data[1].api, uid, data_len, data_buff, create_flag); + TEST_ASSERT_EQUAL(status, s005_data[1].status, TEST_CHECKPOINT_NUM(1)); + + /* Call the get function to get the data buffer and match the buffer */ + status = SST_FUNCTION(s005_data[2].api, uid, 0, data_len, read_buff); + TEST_ASSERT_EQUAL(status, s005_data[2].status, TEST_CHECKPOINT_NUM(2)); + TEST_ASSERT_MEMCMP(read_buff, data_buff, data_len, TEST_CHECKPOINT_NUM(3)); + + /* Call the get_info function and match the attributes */ + status = SST_FUNCTION(s005_data[4].api, uid, &info); + TEST_ASSERT_EQUAL(status, s005_data[4].status, TEST_CHECKPOINT_NUM(4)); + TEST_ASSERT_EQUAL(info.size, data_len, TEST_CHECKPOINT_NUM(5)); + TEST_ASSERT_EQUAL(info.flags, create_flag, TEST_CHECKPOINT_NUM(6)); + + /* Remove the UID */ + status = SST_FUNCTION(s005_data[7].api, uid); + TEST_ASSERT_EQUAL(status, s005_data[7].status, TEST_CHECKPOINT_NUM(7)); + + return VAL_STATUS_SUCCESS; +} + +int32_t psa_sst_apis_check_success_case(caller_security_t caller) +{ + psa_sst_uid_t uid = UID_BASE_VALUE + 4; + uint32_t data_len = 0, status = VAL_STATUS_SUCCESS; + + /* Calling set function with data_len 1 and valid data pointer */ + val->print(PRINT_TEST, "[Check 1] Set UID with data length zero and call storage APIs\n", 0); + if (psa_sst_apis_check(uid, data_len, write_buff, 0)) + { + val->print(PRINT_ERROR, "Data Len = %d\n", data_len); + return VAL_STATUS_ERROR; + } + + data_len = TEST_BUFF_SIZE/2; + val->print(PRINT_TEST, "[Check 2] Resetting the length check\n", 0); + if (psa_sst_apis_check(uid, data_len, write_buff, 0)) + { + val->print(PRINT_ERROR, "Data Len = %d\n", data_len); + return VAL_STATUS_ERROR; + } + + return status; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/test_s005.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/test_s005.h new file mode 100644 index 0000000..9451737 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s005/test_s005.h @@ -0,0 +1,36 @@ +/** @file + * Copyright (c) 2019, 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_S005_CLIENT_TESTS_H_ +#define _TEST_S005_CLIENT_TESTS_H_ + +#ifdef ITS_TEST +#define VAL_STORAGE_BASE VAL_INTERNAL_TRUSTED_STORAGE_BASE +#define test_entry CONCAT(test_entry_, s005) +#elif PS_TEST +#define VAL_STORAGE_BASE VAL_PROTECTED_STORAGE_BASE +#define test_entry CONCAT(test_entry_, p005) +#endif +#define val CONCAT(val,test_entry) +#define psa CONCAT(psa,test_entry) + +extern val_api_t *val; +extern psa_api_t *psa; +extern client_test_t test_s005_sst_list[]; + +int32_t psa_sst_apis_check_success_case(caller_security_t caller); + +#endif /* _TEST_S005_CLIENT_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/main.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/main.c new file mode 100644 index 0000000..1a24de7 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/main.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020, Arm Limited and affiliates. + * 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 "pal_mbed_os_intf.h" + +#if !defined(MBED_CONF_RTOS_PRESENT) +#error [NOT_SUPPORTED] PSA compliance its test cases require RTOS to run +#else + +#ifdef ITS_TEST +void test_entry_s006(val_api_t *val_api, psa_api_t *psa_api); +#elif PS_TEST +void test_entry_p006(val_api_t *val_api, psa_api_t *psa_api); +#endif + +int main(void) +{ +#ifdef ITS_TEST + test_start(test_entry_s006, COMPLIANCE_TEST_STORAGE); +#elif PS_TEST + test_start(test_entry_p006, COMPLIANCE_TEST_STORAGE); +#endif +} +#endif // !defined(MBED_CONF_RTOS_PRESENT) diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/test_entry.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/test_entry.c new file mode 100644 index 0000000..dda491b --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/test_entry.c @@ -0,0 +1,52 @@ +/** @file + * Copyright (c) 2019, 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 "val_target.h" +#include "test_s006.h" + +#define TEST_NUM VAL_CREATE_TEST_ID(VAL_STORAGE_BASE, 6) +#define TEST_DESC "Flags not supported check\n" + +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; + + /* test init */ + val->test_init(TEST_NUM, TEST_DESC, TEST_FIELD(TEST_ISOLATION_L1, WD_HIGH_TIMEOUT)); + if (!IS_TEST_START(val->get_status())) + { + goto test_exit; + } + + /* Execute list of tests available in test[num]_secure_storage_list from Non-secure side*/ + status = val->execute_non_secure_tests(TEST_NUM, test_s006_sst_list, FALSE); + if (VAL_ERROR(status)) + { + goto test_exit; + } + +test_exit: + val->test_exit(); +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/test_its_data.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/test_its_data.h new file mode 100644 index 0000000..4426f2c --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/test_its_data.h @@ -0,0 +1,53 @@ +/** @file + * Copyright (c) 2019, 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_S006_ITS_DATA_TESTS_H_ +#define _TEST_S006_ITS_DATA_TESTS_H_ + +#include "val_internal_trusted_storage.h" + +#define SST_FUNCTION val->its_function +#define PSA_SST_FLAG_WRITE_ONCE PSA_ITS_FLAG_WRITE_ONCE +#define psa_sst_uid_t psa_its_uid_t +#define psa_sst_create_flags_t psa_its_create_flags_t + +typedef struct { + enum its_function_code api; + psa_its_status_t status; +} test_data; + +static struct psa_its_info_t info; +static const test_data s006_data[] = { +{ + 0, PSA_ITS_ERROR_FLAGS_NOT_SUPPORTED /* This is dummy for index0 */ +}, +{ + VAL_ITS_SET, PSA_ITS_SUCCESS /* Create a valid storage entity with different flag values */ +}, +{ + VAL_ITS_GET_INFO, PSA_ITS_SUCCESS /* Validate the flag value get_info API */ +}, +{ + 0, 0 /* Index not used */ +}, +{ + VAL_ITS_REMOVE, PSA_ITS_SUCCESS /* Remove the storage entity */ +}, +{ + VAL_ITS_REMOVE, PSA_ITS_ERROR_UID_NOT_FOUND /* Storage entity remove fails */ +}, +}; +#endif /* _TEST_S006_ITS_DATA_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/test_ps_data.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/test_ps_data.h new file mode 100644 index 0000000..86e1e30 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/test_ps_data.h @@ -0,0 +1,53 @@ +/** @file + * Copyright (c) 2019, Arm Limited or ps 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_S006_PS_DATA_TESTS_H_ +#define _TEST_S006_PS_DATA_TESTS_H_ + +#include "val_protected_storage.h" + +#define SST_FUNCTION val->ps_function +#define PSA_SST_FLAG_WRITE_ONCE PSA_PS_FLAG_WRITE_ONCE +#define psa_sst_uid_t psa_ps_uid_t +#define psa_sst_create_flags_t psa_ps_create_flags_t + +typedef struct { + enum ps_function_code api; + psa_ps_status_t status; +} test_data; + +static struct psa_ps_info_t info; +static const test_data s006_data[] = { +{ + 0, PSA_PS_ERROR_FLAGS_NOT_SUPPORTED /* This is dummy for index0 */ +}, +{ + VAL_PS_SET, PSA_PS_SUCCESS /* Create a valid storage entity with different flag values */ +}, +{ + VAL_PS_GET_INFO, PSA_PS_SUCCESS /* Validate the flag value get_info API */ +}, +{ + 0, 0 /* Index not used */ +}, +{ + VAL_PS_REMOVE, PSA_PS_SUCCESS /* Remove the storage entity */ +}, +{ + VAL_PS_REMOVE, PSA_PS_ERROR_UID_NOT_FOUND /* Remove the storage entity */ +} +}; +#endif /* _TEST_S006_PS_DATA_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/test_s006.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/test_s006.c new file mode 100644 index 0000000..26b8984 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/test_s006.c @@ -0,0 +1,90 @@ +/** @file + * Copyright (c) 2019, 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 "val_target.h" +#include "test_s006.h" +#ifdef ITS_TEST +#include "test_its_data.h" +#elif PS_TEST +#include "test_ps_data.h" +#endif + +#define TEST_BUFF_SIZE 30 + +client_test_t test_s006_sst_list[] = { + NULL, + psa_sst_flags_not_supported, + NULL, +}; + +static uint8_t write_buff[TEST_BUFF_SIZE] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x23, 0xF6, 0x07, 0x08, 0x0D, 0x0A, 0x1B, 0x0C, 0x5D, 0x0E,\ + 0x70, 0xA1, 0xFF, 0xFF, 0x14, 0x73, 0x46, 0x97, 0xE8, 0xDD, 0xCA, 0x0B, 0x3C, 0x0D, 0x2E}; + +static int32_t psa_sst_remove_api(psa_sst_uid_t uid, uint32_t data_len, + uint8_t *data_buff, psa_sst_create_flags_t create_flag) +{ + uint32_t status; + + /* Call the get_info function and match the attributes */ + status = SST_FUNCTION(s006_data[2].api, uid, &info); + TEST_ASSERT_EQUAL(status, s006_data[2].status, TEST_CHECKPOINT_NUM(2)); + TEST_ASSERT_EQUAL(info.flags, create_flag, TEST_CHECKPOINT_NUM(3)); + + /* Remove the UID */ + status = SST_FUNCTION(s006_data[4].api, uid); + TEST_ASSERT_EQUAL(status, s006_data[4].status, TEST_CHECKPOINT_NUM(4)); + + return VAL_STATUS_SUCCESS; +} + +int32_t psa_sst_flags_not_supported(caller_security_t caller) +{ + psa_sst_create_flags_t flag = 0x80000000; + uint32_t status = VAL_STATUS_SUCCESS; + psa_sst_uid_t uid = UID_BASE_VALUE + 5; + int32_t test_status; + + /* Calling set function with different create flag value */ + + val->print(PRINT_TEST, "[Check 1] Call set API with valid flag values\n", 0); + while (flag) + { + /* Create storage with flag value */ + status = SST_FUNCTION(s006_data[1].api, uid, TEST_BUFF_SIZE, write_buff, + (flag & (~PSA_SST_FLAG_WRITE_ONCE))); + + if (status == s006_data[1].status) + { + test_status = psa_sst_remove_api(uid, TEST_BUFF_SIZE, write_buff, + (flag & (~PSA_SST_FLAG_WRITE_ONCE))); + if (test_status != VAL_STATUS_SUCCESS) + return test_status; + } + else if (status == s006_data[0].status) + { + /* Remove UID should fail */ + status = SST_FUNCTION(s006_data[5].api, uid); + TEST_ASSERT_EQUAL(status, s006_data[5].status, TEST_CHECKPOINT_NUM(5)); + } + + flag = flag >> 1; + }; + + return status; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/test_s006.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/test_s006.h new file mode 100644 index 0000000..9e79324 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s006/test_s006.h @@ -0,0 +1,36 @@ +/** @file + * Copyright (c) 2019, 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_S006_CLIENT_TESTS_H_ +#define _TEST_S006_CLIENT_TESTS_H_ + +#ifdef ITS_TEST +#define VAL_STORAGE_BASE VAL_INTERNAL_TRUSTED_STORAGE_BASE +#define test_entry CONCAT(test_entry_, s006) +#elif PS_TEST +#define VAL_STORAGE_BASE VAL_PROTECTED_STORAGE_BASE +#define test_entry CONCAT(test_entry_, p006) +#endif +#define val CONCAT(val,test_entry) +#define psa CONCAT(psa,test_entry) + +extern val_api_t *val; +extern psa_api_t *psa; +extern client_test_t test_s006_sst_list[]; + +int32_t psa_sst_flags_not_supported(caller_security_t caller); + +#endif /* _TEST_S006_CLIENT_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/main.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/main.c new file mode 100644 index 0000000..a63001e --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/main.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020, Arm Limited and affiliates. + * 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 "pal_mbed_os_intf.h" + +#if !defined(MBED_CONF_RTOS_PRESENT) +#error [NOT_SUPPORTED] PSA compliance its test cases require RTOS to run +#else + +#ifdef ITS_TEST +void test_entry_s007(val_api_t *val_api, psa_api_t *psa_api); +#elif PS_TEST +void test_entry_p007(val_api_t *val_api, psa_api_t *psa_api); +#endif + +int main(void) +{ +#ifdef ITS_TEST + test_start(test_entry_s007, COMPLIANCE_TEST_STORAGE); +#elif PS_TEST + test_start(test_entry_p007, COMPLIANCE_TEST_STORAGE); +#endif +} +#endif // !defined(MBED_CONF_RTOS_PRESENT) diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/test_entry.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/test_entry.c new file mode 100644 index 0000000..f6005a1 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/test_entry.c @@ -0,0 +1,52 @@ +/** @file + * Copyright (c) 2019, 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 "val_target.h" +#include "test_s007.h" + +#define TEST_NUM VAL_CREATE_TEST_ID(VAL_STORAGE_BASE, 7) +#define TEST_DESC "Incorrect Size check\n" + +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; + + /* test init */ + val->test_init(TEST_NUM, TEST_DESC, TEST_FIELD(TEST_ISOLATION_L1, WD_HIGH_TIMEOUT)); + if (!IS_TEST_START(val->get_status())) + { + goto test_exit; + } + + /* Execute list of tests available in test[num]_secure_storage_list from Non-secure side*/ + status = val->execute_non_secure_tests(TEST_NUM, test_s007_sst_list, FALSE); + if (VAL_ERROR(status)) + { + goto test_exit; + } + +test_exit: + val->test_exit(); +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/test_its_data.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/test_its_data.h new file mode 100644 index 0000000..550dffb --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/test_its_data.h @@ -0,0 +1,65 @@ +/** @file + * Copyright (c) 2019, 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_S007_ITS_DATA_TESTS_H_ +#define _TEST_S007_ITS_DATA_TESTS_H_ + +#include "val_internal_trusted_storage.h" + +#define SST_FUNCTION val->its_function +#define psa_sst_uid_t psa_its_uid_t + +typedef struct { + enum its_function_code api; + psa_its_status_t status; +} test_data; + +static const test_data s007_data[] = { +{ + 0, 0 /* This is dummy for index0 */ +}, +{ + VAL_ITS_SET, PSA_ITS_SUCCESS /* Create a valid storage entity */ +}, +{ + VAL_ITS_SET, PSA_ITS_SUCCESS /* Increase the length of storage */ +}, +{ + VAL_ITS_GET, PSA_ITS_SUCCESS /* Try to access old length */ +}, +{ + VAL_ITS_GET, PSA_ITS_SUCCESS /* Try to access valid length less than set length */ +}, +{ + 0, 0 /* This is dummy for index5 */ +}, +{ + VAL_ITS_SET, PSA_ITS_SUCCESS /* Decrease the length of storage */ +}, +{ + VAL_ITS_GET, PSA_ITS_ERROR_INCORRECT_SIZE /* Try to access old length */ +}, +{ + VAL_ITS_GET, PSA_ITS_ERROR_INCORRECT_SIZE /* Try to access old length */ +}, +{ + VAL_ITS_GET, PSA_ITS_SUCCESS /* Try to access data with correct length */ +}, +{ + VAL_ITS_REMOVE, PSA_ITS_SUCCESS /* Remove the storage entity */ +}, +}; +#endif /* _TEST_S007_ITS_DATA_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/test_ps_data.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/test_ps_data.h new file mode 100644 index 0000000..fa032c1 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/test_ps_data.h @@ -0,0 +1,65 @@ +/** @file + * Copyright (c) 2019, Arm Limited or ps 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_S007_PS_DATA_TESTS_H_ +#define _TEST_S007_PS_DATA_TESTS_H_ + +#include "val_protected_storage.h" + +#define SST_FUNCTION val->ps_function +#define psa_sst_uid_t psa_ps_uid_t + +typedef struct { + enum ps_function_code api; + psa_ps_status_t status; +} test_data; + +static const test_data s007_data[] = { +{ + 0, 0 /* This is dummy for index0 */ +}, +{ + VAL_PS_SET, PSA_PS_SUCCESS /* Create a valid storage entity */ +}, +{ + VAL_PS_SET, PSA_PS_SUCCESS /* Increase the length of storage */ +}, +{ + VAL_PS_GET, PSA_PS_SUCCESS /* Try to access old length */ +}, +{ + VAL_PS_GET, PSA_PS_SUCCESS /* Try to access valid length less than set length */ +}, +{ + 0, 0 /* This is dummy for index5 */ +}, +{ + VAL_PS_SET, PSA_PS_SUCCESS /* Decrease the length of storage */ +}, +{ + VAL_PS_GET, PSA_PS_ERROR_INCORRECT_SIZE /* Try to access old length */ +}, +{ + VAL_PS_GET, PSA_PS_ERROR_INCORRECT_SIZE /* Try to access old length */ +}, +{ + VAL_PS_GET, PSA_PS_SUCCESS /* Try to access data with correct length */ +}, +{ + VAL_PS_REMOVE, PSA_PS_SUCCESS /* Remove the storage entity */ +}, +}; +#endif /* _TEST_S007_PS_DATA_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/test_s007.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/test_s007.c new file mode 100644 index 0000000..b17143c --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/test_s007.c @@ -0,0 +1,89 @@ +/** @file + * Copyright (c) 2019, 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 "val_target.h" +#include "test_s007.h" +#ifdef ITS_TEST +#include "test_its_data.h" +#elif PS_TEST +#include "test_ps_data.h" +#endif + +#define TEST_BUFF_SIZE 30 + +client_test_t test_s007_sst_list[] = { + NULL, + psa_sst_get_incorrect_size, + NULL, +}; + +static uint8_t write_buff[TEST_BUFF_SIZE] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x23, 0xF6, 0x07, 0x08, 0x0D, 0x0A, 0x1B, 0x0C, 0x5D, 0x0E,\ + 0x70, 0xA1, 0xFF, 0xFF, 0x14, 0x73, 0x46, 0x97, 0xE8, 0xDD, 0xCA, 0x0B, 0x3C, 0x0D, 0x2E}; +static uint8_t read_buff[TEST_BUFF_SIZE]; + +int32_t psa_sst_get_incorrect_size(caller_security_t caller) +{ + psa_sst_uid_t uid = UID_BASE_VALUE + 5; + uint32_t status = VAL_STATUS_SUCCESS; + + /* Set the UID with the data_len and data_buff */ + val->print(PRINT_TEST, "Create a valid Storage\n", 0); + status = SST_FUNCTION(s007_data[1].api, uid, TEST_BUFF_SIZE/2, write_buff, 0); + TEST_ASSERT_EQUAL(status, s007_data[1].status, TEST_CHECKPOINT_NUM(1)); + + /* Call set for same UID and increase the length */ + val->print(PRINT_TEST, "Increase the length of storage\n", 0); + status = SST_FUNCTION(s007_data[2].api, uid, TEST_BUFF_SIZE, write_buff, 0); + TEST_ASSERT_EQUAL(status, s007_data[2].status, TEST_CHECKPOINT_NUM(2)); + + /* Access data using get API and old length */ + val->print(PRINT_TEST, "[Check 1] Call get API with old length\n", 0); + status = SST_FUNCTION(s007_data[3].api, uid, 0, TEST_BUFF_SIZE/2, read_buff); + TEST_ASSERT_EQUAL(status, s007_data[3].status, TEST_CHECKPOINT_NUM(3)); + + /* Access data using get API and valid length */ + status = SST_FUNCTION(s007_data[4].api, uid, 0, TEST_BUFF_SIZE/4, read_buff); + TEST_ASSERT_EQUAL(status, s007_data[4].status, TEST_CHECKPOINT_NUM(4)); + TEST_ASSERT_MEMCMP(read_buff, write_buff, TEST_BUFF_SIZE/4, TEST_CHECKPOINT_NUM(5)); + + /* Decrease the length again */ + val->print(PRINT_TEST, "Decrease the length of storage\n", 0); + status = SST_FUNCTION(s007_data[6].api, uid, TEST_BUFF_SIZE/4, write_buff, 0); + TEST_ASSERT_EQUAL(status, s007_data[6].status, TEST_CHECKPOINT_NUM(6)); + + /* Access data using get API and old length */ + status = SST_FUNCTION(s007_data[7].api, uid, 0, TEST_BUFF_SIZE/2, read_buff); + TEST_ASSERT_EQUAL(status, s007_data[7].status, TEST_CHECKPOINT_NUM(7)); + + /* Access data using get API and old length */ + val->print(PRINT_TEST, "[Check 2] Call get API with old length\n", 0); + status = SST_FUNCTION(s007_data[8].api, uid, 0, TEST_BUFF_SIZE, read_buff); + TEST_ASSERT_EQUAL(status, s007_data[8].status, TEST_CHECKPOINT_NUM(8)); + + /* Access data using correct length */ + val->print(PRINT_TEST, "[Check 3] Call get API with valid length\n", 0); + status = SST_FUNCTION(s007_data[9].api, uid, 0, TEST_BUFF_SIZE/4, read_buff); + TEST_ASSERT_EQUAL(status, s007_data[9].status, TEST_CHECKPOINT_NUM(9)); + + /* Remove the UID */ + status = SST_FUNCTION(s007_data[10].api, uid); + TEST_ASSERT_EQUAL(status, s007_data[10].status, TEST_CHECKPOINT_NUM(10)); + + return status; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/test_s007.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/test_s007.h new file mode 100644 index 0000000..b663980 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s007/test_s007.h @@ -0,0 +1,36 @@ +/** @file + * Copyright (c) 2019, 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_S007_CLIENT_TESTS_H_ +#define _TEST_S007_CLIENT_TESTS_H_ + +#ifdef ITS_TEST +#define VAL_STORAGE_BASE VAL_INTERNAL_TRUSTED_STORAGE_BASE +#define test_entry CONCAT(test_entry_, s007) +#elif PS_TEST +#define VAL_STORAGE_BASE VAL_PROTECTED_STORAGE_BASE +#define test_entry CONCAT(test_entry_, p007) +#endif +#define val CONCAT(val,test_entry) +#define psa CONCAT(psa,test_entry) + +extern val_api_t *val; +extern psa_api_t *psa; +extern client_test_t test_s007_sst_list[]; + +int32_t psa_sst_get_incorrect_size(caller_security_t caller); + +#endif /* _TEST_S007_CLIENT_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/main.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/main.c new file mode 100644 index 0000000..b17f6cf --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/main.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020, Arm Limited and affiliates. + * 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 "pal_mbed_os_intf.h" + +#if !defined(MBED_CONF_RTOS_PRESENT) +#error [NOT_SUPPORTED] PSA compliance its test cases require RTOS to run +#else + +#ifdef ITS_TEST +void test_entry_s008(val_api_t *val_api, psa_api_t *psa_api); +#elif PS_TEST +void test_entry_p008(val_api_t *val_api, psa_api_t *psa_api); +#endif + +int main(void) +{ +#ifdef ITS_TEST + test_start(test_entry_s008, COMPLIANCE_TEST_STORAGE); +#elif PS_TEST + test_start(test_entry_p008, COMPLIANCE_TEST_STORAGE); +#endif +} +#endif // !defined(MBED_CONF_RTOS_PRESENT) diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/test_entry.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/test_entry.c new file mode 100644 index 0000000..f531881 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/test_entry.c @@ -0,0 +1,53 @@ +/** @file + * Copyright (c) 2019, 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 "val_target.h" +#include "test_s008.h" + +#define TEST_NUM VAL_CREATE_TEST_ID(VAL_STORAGE_BASE, 8) +#define TEST_DESC "Invalid offset check\n" + +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; + + /* test init */ + val->test_init(TEST_NUM, TEST_DESC, TEST_FIELD(TEST_ISOLATION_L1, WD_HIGH_TIMEOUT)); + if (!IS_TEST_START(val->get_status())) + { + goto test_exit; + } + + /* Execute list of tests available in test[num]_secure_storage_list from Non-secure side*/ + status = val->execute_non_secure_tests(TEST_NUM, test_s008_sst_list, FALSE); + + if (VAL_ERROR(status)) + { + goto test_exit; + } + +test_exit: + val->test_exit(); +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/test_its_data.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/test_its_data.h new file mode 100644 index 0000000..89093d4 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/test_its_data.h @@ -0,0 +1,74 @@ +/** @file + * Copyright (c) 2019, 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_S008_ITS_DATA_TESTS_H_ +#define _TEST_S008_ITS_DATA_TESTS_H_ + +#include "val_internal_trusted_storage.h" + +#define SST_FUNCTION val->its_function +#define psa_sst_uid_t psa_its_uid_t + +typedef struct { + enum its_function_code api; + psa_its_status_t status; +} test_data; + +static const test_data s008_data[] = { +{ + 0, 0 /* This is dummy for index0 */ +}, +{ + VAL_ITS_SET, PSA_ITS_SUCCESS /* Create a valid storage entity with zero flag value */ +}, +{ + VAL_ITS_GET, PSA_ITS_SUCCESS /* Call get API with offset + data_len = total_size */ +}, +{ + 0, 0 /* This is dummy for index3 */ +}, +{ + VAL_ITS_GET, PSA_ITS_SUCCESS /* Call get API with offset + data_len < total_size */ +}, +{ + 0, 0 /* This is dummy for index5 */ +}, +{ + VAL_ITS_GET, PSA_ITS_SUCCESS /* Call get API with offset = total data_size + 1 */ +}, +{ + 0, 0 /* This is dummy for index7 */ +}, +{ + VAL_ITS_GET, PSA_ITS_ERROR_INCORRECT_SIZE /* get API with offset + data_len > total data_size */ +}, +{ + 0, 0 /* This is dummy for index9 */ +}, +{ + VAL_ITS_GET, PSA_ITS_ERROR_INCORRECT_SIZE /* Call get API with invalid data len and offset zero */ +}, +{ + 0, 0 /* This is dummy for index11 */ +}, +{ + VAL_ITS_GET, PSA_ITS_SUCCESS /* Call get API with offset = MAX_UINT32 */ +}, +{ + VAL_ITS_REMOVE, PSA_ITS_SUCCESS /* Remove the storage entity */ +}, +}; +#endif /* _TEST_S008_ITS_DATA_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/test_ps_data.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/test_ps_data.h new file mode 100644 index 0000000..2b15d35 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/test_ps_data.h @@ -0,0 +1,74 @@ +/** @file + * Copyright (c) 2019, Arm Limited or ps 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_S008_PS_DATA_TESTS_H_ +#define _TEST_S008_PS_DATA_TESTS_H_ + +#include "val_protected_storage.h" + +#define SST_FUNCTION val->ps_function +#define psa_sst_uid_t psa_ps_uid_t + +typedef struct { + enum ps_function_code api; + psa_ps_status_t status; +} test_data; + +static const test_data s008_data[] = { +{ + 0, 0 /* This is dummy for index0 */ +}, +{ + VAL_PS_SET, PSA_PS_SUCCESS /* Create a valid storage entity with zero flag value */ +}, +{ + VAL_PS_GET, PSA_PS_SUCCESS /* Call get API with offset + data_len = total_size */ +}, +{ + 0, 0 /* This is dummy for index3 */ +}, +{ + VAL_PS_GET, PSA_PS_SUCCESS /* Call get API with offset + data_len < total_size */ +}, +{ + 0, 0 /* This is dummy for index5 */ +}, +{ + VAL_PS_GET, PSA_PS_SUCCESS/* Call get API with offset = total data_size + 1 */ +}, +{ + 0, 0 /* This is dummy for index7 */ +}, +{ + VAL_PS_GET, PSA_PS_ERROR_INCORRECT_SIZE /* Call get API with offset + data_len > total data_size */ +}, +{ + 0, 0 /* This is dummy for index9 */ +}, +{ + VAL_PS_GET, PSA_PS_ERROR_INCORRECT_SIZE /* Call get API with invalid data len and offset zero */ +}, +{ + 0, 0 /* This is dummy for index11 */ +}, +{ + VAL_PS_GET, PSA_PS_SUCCESS /* Call get API with offset = MAX_UINT32 */ +}, +{ + VAL_PS_REMOVE, PSA_PS_SUCCESS /* Remove the storage entity */ +}, +}; +#endif /* _TEST_S008_PS_DATA_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/test_s008.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/test_s008.c new file mode 100644 index 0000000..7a2536e --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/test_s008.c @@ -0,0 +1,116 @@ +/** @file + * Copyright (c) 2019, 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 "val_target.h" +#include "test_s008.h" +#ifdef ITS_TEST +#include "test_its_data.h" +#elif PS_TEST +#include "test_ps_data.h" +#endif + +#define TEST_BUFF_SIZE 20 +#define TEST_MAX_UINT32 0xFFFFFFFF + +client_test_t test_s008_sst_list[] = { + NULL, + psa_sst_valid_offset_success, + psa_sst_invalid_offset_failure, + NULL, +}; + +static psa_sst_uid_t uid = UID_BASE_VALUE + 5; +static uint8_t read_buff[TEST_BUFF_SIZE]; +static uint8_t write_buff[TEST_BUFF_SIZE] = {0x99, 0x01, 0x02, 0x03, 0x04, 0x23, 0xF6, 0x07, 0x08, \ + 0x0D, 0x70, 0xA1, 0xFF, 0xFF, 0x14, 0x73, 0x46, 0x97, 0xE8, 0xDD}; + +int32_t psa_sst_invalid_offset_failure(caller_security_t caller) +{ + uint32_t status, j; + + /* Case where offset = data_size +1 , data_len 0. Also check nothing is returned in read buff*/ + val->print(PRINT_TEST, "[Check 2] Try to access data with varying invalid offset\n", 0); + memset(read_buff, 0, TEST_BUFF_SIZE); + status = SST_FUNCTION(s008_data[6].api, uid, TEST_BUFF_SIZE+1, 0, read_buff); + TEST_ASSERT_NOT_EQUAL(status, s008_data[6].status, TEST_CHECKPOINT_NUM(6)); + for (j = 0; j < TEST_BUFF_SIZE; j++) + { + TEST_ASSERT_EQUAL(read_buff[j], 0x00, TEST_CHECKPOINT_NUM(7)); + } + + /* Case where offset = data_size , data_len= 1 Also check nothing is returned in read buff*/ + status = SST_FUNCTION(s008_data[8].api, uid, TEST_BUFF_SIZE, 1, read_buff); + TEST_ASSERT_EQUAL(status, s008_data[8].status, TEST_CHECKPOINT_NUM(8)); + for (j = 0; j < TEST_BUFF_SIZE; j++) + { + TEST_ASSERT_EQUAL(read_buff[j], 0x00, TEST_CHECKPOINT_NUM(9)); + } + + /* Case where offset = 0 , data_len > data_size Also check nothing is returned in read buff*/ + status = SST_FUNCTION(s008_data[10].api, uid, 0, TEST_BUFF_SIZE+1, read_buff); + TEST_ASSERT_EQUAL(status, s008_data[10].status, TEST_CHECKPOINT_NUM(10)); + for (j = 0; j < TEST_BUFF_SIZE; j++) + { + TEST_ASSERT_EQUAL(read_buff[j], 0x00, TEST_CHECKPOINT_NUM(11)); + } + + /* Try to access data with offset as MAX_UINT32 and length less than buffer size */ + status = SST_FUNCTION(s008_data[12].api, uid, TEST_MAX_UINT32, TEST_BUFF_SIZE/2, read_buff); + TEST_ASSERT_NOT_EQUAL(status, s008_data[12].status, TEST_CHECKPOINT_NUM(12)); + + /* Remove the UID */ + status = SST_FUNCTION(s008_data[13].api, uid); + TEST_ASSERT_EQUAL(status, s008_data[13].status, TEST_CHECKPOINT_NUM(13)); + + return VAL_STATUS_SUCCESS; +} + +int32_t psa_sst_valid_offset_success(caller_security_t caller) +{ + uint32_t status, data_len, offset = TEST_BUFF_SIZE; + + /* Set data for UID */ + status = SST_FUNCTION(s008_data[1].api, uid, TEST_BUFF_SIZE, write_buff, 0); + TEST_ASSERT_EQUAL(status, s008_data[1].status, TEST_CHECKPOINT_NUM(1)); + + /* Case where offset + datalen = data_size */ + val->print(PRINT_TEST, "[Check 1] Try to access data with varying valid offset\n", 0); + while (offset > 0) + { + data_len = TEST_BUFF_SIZE - offset; + memset(read_buff, 0, TEST_BUFF_SIZE); + status = SST_FUNCTION(s008_data[2].api, uid, offset, data_len, read_buff); + TEST_ASSERT_EQUAL(status, s008_data[2].status, TEST_CHECKPOINT_NUM(2)); + TEST_ASSERT_MEMCMP(read_buff, write_buff + offset, data_len, TEST_CHECKPOINT_NUM(3)); + offset >>= 1; + } + + offset = TEST_BUFF_SIZE - 2; + data_len = 1; + /* Case where offset + datalen < data_size */ + while (offset > 0) + { + status = SST_FUNCTION(s008_data[4].api, uid, offset, data_len, read_buff); + TEST_ASSERT_EQUAL(status, s008_data[4].status, TEST_CHECKPOINT_NUM(4)); + TEST_ASSERT_MEMCMP(read_buff, write_buff + offset, data_len, TEST_CHECKPOINT_NUM(5)); + offset >>= 1; + data_len <<= 1; + } + + return VAL_STATUS_SUCCESS; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/test_s008.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/test_s008.h new file mode 100644 index 0000000..d036b4a --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s008/test_s008.h @@ -0,0 +1,37 @@ +/** @file + * Copyright (c) 2019, 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_S008_CLIENT_TESTS_H_ +#define _TEST_S008_CLIENT_TESTS_H_ + +#ifdef ITS_TEST +#define VAL_STORAGE_BASE VAL_INTERNAL_TRUSTED_STORAGE_BASE +#define test_entry CONCAT(test_entry_, s008) +#elif PS_TEST +#define VAL_STORAGE_BASE VAL_PROTECTED_STORAGE_BASE +#define test_entry CONCAT(test_entry_, p008) +#endif +#define val CONCAT(val,test_entry) +#define psa CONCAT(psa,test_entry) + +extern val_api_t *val; +extern psa_api_t *psa; +extern client_test_t test_s008_sst_list[]; + +int32_t psa_sst_valid_offset_success(caller_security_t caller); +int32_t psa_sst_invalid_offset_failure(caller_security_t caller); + +#endif /* _TEST_S008_CLIENT_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/main.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/main.c new file mode 100644 index 0000000..74a6ddb --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/main.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020, Arm Limited and affiliates. + * 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 "pal_mbed_os_intf.h" + +#if !defined(MBED_CONF_RTOS_PRESENT) +#error [NOT_SUPPORTED] PSA compliance its test cases require RTOS to run +#else + +#ifdef ITS_TEST +void test_entry_s009(val_api_t *val_api, psa_api_t *psa_api); +#elif PS_TEST +void test_entry_p009(val_api_t *val_api, psa_api_t *psa_api); +#endif + +int main(void) +{ +#ifdef ITS_TEST + test_start(test_entry_s009, COMPLIANCE_TEST_STORAGE); +#elif PS_TEST + test_start(test_entry_p009, COMPLIANCE_TEST_STORAGE); +#endif +} +#endif // !defined(MBED_CONF_RTOS_PRESENT) diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/test_entry.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/test_entry.c new file mode 100644 index 0000000..37883fb --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/test_entry.c @@ -0,0 +1,53 @@ +/** @file + * Copyright (c) 2019, 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 "val_target.h" +#include "test_s009.h" + +#define TEST_NUM VAL_CREATE_TEST_ID(VAL_STORAGE_BASE, 9) +#define TEST_DESC "Invalid Arguments check\n" + +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; + + /* test init */ + val->test_init(TEST_NUM, TEST_DESC, TEST_FIELD(TEST_ISOLATION_L1, WD_HIGH_TIMEOUT)); + if (!IS_TEST_START(val->get_status())) + { + goto test_exit; + } + + /* Execute list of tests available in test[num]_secure_storage_list from Non-secure side*/ + status = val->execute_non_secure_tests(TEST_NUM, test_s009_sst_list, FALSE); + + if (VAL_ERROR(status)) + { + goto test_exit; + } + +test_exit: + val->test_exit(); +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/test_its_data.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/test_its_data.h new file mode 100644 index 0000000..80e7fb1 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/test_its_data.h @@ -0,0 +1,69 @@ +/** @file + * Copyright (c) 2019, 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_S009_ITS_DATA_TESTS_H_ +#define _TEST_S009_ITS_DATA_TESTS_H_ + +#include "val_internal_trusted_storage.h" + +#define SST_FUNCTION val->its_function +#define psa_sst_uid_t psa_its_uid_t + +typedef struct { + enum its_function_code api; + psa_its_status_t status; +} test_data; + +static struct psa_its_info_t info; +static const test_data s009_data[] = { +{ + 0, 0 /* This is dummy for index0 */ +}, +{ + VAL_ITS_SET, PSA_ITS_SUCCESS /* Call set API with NULL write buffer and 0 length */ +}, +{ + VAL_ITS_GET_INFO, PSA_ITS_SUCCESS /* Verify UID is created */ +}, +{ + VAL_ITS_GET, PSA_ITS_SUCCESS /* Call get API with NULL write buffer and 0 length */ +}, +{ + VAL_ITS_REMOVE, PSA_ITS_SUCCESS /* Remove the storage entity */ +}, +{ + VAL_ITS_GET_INFO, PSA_ITS_ERROR_UID_NOT_FOUND /* Verify UID is removed */ +}, +{ + VAL_ITS_SET, PSA_ITS_SUCCESS /* Create storage of zero size and valid write buffer */ +}, +{ + VAL_ITS_GET_INFO, PSA_ITS_SUCCESS /* Call get_info API to check data size */ +}, +{ + 0, 0 /* This is dummy for index8 */ +}, +{ + VAL_ITS_GET, PSA_ITS_SUCCESS /* Call get API with 0 length and NULL read buffer */ +}, +{ + VAL_ITS_SET, PSA_ITS_SUCCESS /* Increase the asset size */ +}, +{ + VAL_ITS_REMOVE, PSA_ITS_SUCCESS /* Remove the storage entity */ +}, +}; +#endif /* _TEST_S009_ITS_DATA_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/test_ps_data.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/test_ps_data.h new file mode 100644 index 0000000..129bca0 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/test_ps_data.h @@ -0,0 +1,69 @@ +/** @file + * Copyright (c) 2019, Arm Limited or ps 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_S009_PS_DATA_TESTS_H_ +#define _TEST_S009_PS_DATA_TESTS_H_ + +#include "val_protected_storage.h" + +#define SST_FUNCTION val->ps_function +#define psa_sst_uid_t psa_ps_uid_t + +typedef struct { + enum ps_function_code api; + psa_ps_status_t status; +} test_data; + +static struct psa_ps_info_t info; +static const test_data s009_data[] = { +{ + 0, 0 /* This is dummy for index0 */ +}, +{ + VAL_PS_SET, PSA_PS_SUCCESS /* Call set API with NULL write buffer and 0 length */ +}, +{ + VAL_PS_GET_INFO, PSA_PS_SUCCESS /* Verify UID is created */ +}, +{ + VAL_PS_GET, PSA_PS_SUCCESS /* Call get API with NULL write buffer and 0 length */ +}, +{ + VAL_PS_REMOVE, PSA_PS_SUCCESS /* Remove the storage entity */ +}, +{ + VAL_PS_GET_INFO, PSA_PS_ERROR_UID_NOT_FOUND /* Verify UID is removed */ +}, +{ + VAL_PS_SET, PSA_PS_SUCCESS /* Create storage of zero size and valid write buffer */ +}, +{ + VAL_PS_GET_INFO, PSA_PS_SUCCESS /* Call get_info API to check data size */ +}, +{ + 0, 0 /* This is dummy for index8 */ +}, +{ + VAL_PS_GET, PSA_PS_SUCCESS /* Call get API with 0 length and NULL read buffer */ +}, +{ + VAL_PS_SET, PSA_PS_SUCCESS /* Increase the asset size */ +}, +{ + VAL_PS_REMOVE, PSA_PS_SUCCESS /* Remove the storage entity */ +}, +}; +#endif /* _TEST_S009_PS_DATA_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/test_s009.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/test_s009.c new file mode 100644 index 0000000..c54fa02 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/test_s009.c @@ -0,0 +1,92 @@ +/** @file + * Copyright (c) 2019, 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 "val_target.h" +#include "test_s009.h" +#ifdef ITS_TEST +#include "test_its_data.h" +#elif PS_TEST +#include "test_ps_data.h" +#endif + +#define TEST_BUFF_SIZE 20 + +client_test_t test_s009_sst_list[] = { + NULL, + psa_sst_zero_length_check, + NULL, +}; + +static psa_sst_uid_t uid = UID_BASE_VALUE + 5; +static uint8_t write_buff[TEST_BUFF_SIZE] = {0x99, 0x01, 0x02, 0x03, 0x04, 0x23, 0xF6, 0x07, 0x08, \ + 0x0D, 0x70, 0xA1, 0xFF, 0xFF, 0x14, 0x73, 0x46, 0x97, 0xE8, 0xDD}; + +int32_t psa_sst_zero_length_check(caller_security_t caller) +{ + uint32_t status; + + /* Set data for UID with length 0 and NULL pointer */ + val->print(PRINT_TEST, "[Check 1] Call set API with NULL pointer and data length 0\n", 0); + status = SST_FUNCTION(s009_data[1].api, uid, 0, NULL, 0); + TEST_ASSERT_EQUAL(status, s009_data[1].status, TEST_CHECKPOINT_NUM(1)); + + /* Call the get_info function to verify UID created */ + status = SST_FUNCTION(s009_data[2].api, uid, &info); + TEST_ASSERT_EQUAL(status, s009_data[2].status, TEST_CHECKPOINT_NUM(2)); + + /* Call get API with NULL read buffer */ + val->print(PRINT_TEST, "[Check 2] Call get API with NULL read buffer and data length 0\n", 0); + status = SST_FUNCTION(s009_data[3].api, uid, 0, 0, NULL); + TEST_ASSERT_EQUAL(status, s009_data[3].status, TEST_CHECKPOINT_NUM(3)); + + /* Remove the UID */ + val->print(PRINT_TEST, "[Check 3] Remove the UID\n", 0); + status = SST_FUNCTION(s009_data[4].api, uid); + TEST_ASSERT_EQUAL(status, s009_data[4].status, TEST_CHECKPOINT_NUM(4)); + + /* Call the get_info function to verify UID is removed */ + val->print(PRINT_TEST, "[Check 4] Call get_info API to verify UID removed\n", 0); + status = SST_FUNCTION(s009_data[5].api, uid, &info); + TEST_ASSERT_EQUAL(status, s009_data[5].status, TEST_CHECKPOINT_NUM(5)); + + /* Create UID with length 0 and valid write buffer */ + val->print(PRINT_TEST, "[Check 5] Create UID with zero data_len and valid write buffer\n", 0); + status = SST_FUNCTION(s009_data[6].api, uid, 0, write_buff, 0); + TEST_ASSERT_EQUAL(status, s009_data[6].status, TEST_CHECKPOINT_NUM(6)); + + /* Call the get_info function and match the attributes */ + status = SST_FUNCTION(s009_data[7].api, uid, &info); + TEST_ASSERT_EQUAL(status, s009_data[7].status, TEST_CHECKPOINT_NUM(7)); + TEST_ASSERT_EQUAL(info.size, 0, TEST_CHECKPOINT_NUM(8)); + + /* Call get API with NULL read buffer and valid UID */ + val->print(PRINT_TEST, "[Check 8] Call get API with NULL read buffer and data length 0\n", 0); + status = SST_FUNCTION(s009_data[9].api, uid, 0, 0, NULL); + TEST_ASSERT_EQUAL(status, s009_data[9].status, TEST_CHECKPOINT_NUM(9)); + + /* Change the length to test_buff_size */ + val->print(PRINT_TEST, "[Check 9] Increase the length\n", 0); + status = SST_FUNCTION(s009_data[10].api, uid, TEST_BUFF_SIZE, write_buff, 0); + TEST_ASSERT_EQUAL(status, s009_data[10].status, TEST_CHECKPOINT_NUM(10)); + + /* Remove the UID */ + status = SST_FUNCTION(s009_data[11].api, uid); + TEST_ASSERT_EQUAL(status, s009_data[11].status, TEST_CHECKPOINT_NUM(11)); + + return VAL_STATUS_SUCCESS; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/test_s009.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/test_s009.h new file mode 100644 index 0000000..49a5de0 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s009/test_s009.h @@ -0,0 +1,36 @@ +/** @file + * Copyright (c) 2019, 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_S009_CLIENT_TESTS_H_ +#define _TEST_S009_CLIENT_TESTS_H_ + +#ifdef ITS_TEST +#define VAL_STORAGE_BASE VAL_INTERNAL_TRUSTED_STORAGE_BASE +#define test_entry CONCAT(test_entry_, s009) +#elif PS_TEST +#define VAL_STORAGE_BASE VAL_PROTECTED_STORAGE_BASE +#define test_entry CONCAT(test_entry_, p009) +#endif +#define val CONCAT(val,test_entry) +#define psa CONCAT(psa,test_entry) + +extern val_api_t *val; +extern psa_api_t *psa; +extern client_test_t test_s009_sst_list[]; + +int32_t psa_sst_zero_length_check(caller_security_t caller); + +#endif /* _TEST_S009_CLIENT_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/main.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/main.c new file mode 100644 index 0000000..c9f0728 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/main.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020, Arm Limited and affiliates. + * 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 "pal_mbed_os_intf.h" + +#if !defined(MBED_CONF_RTOS_PRESENT) +#error [NOT_SUPPORTED] PSA compliance its test cases require RTOS to run +#else + +#ifdef ITS_TEST +void test_entry_s010(val_api_t *val_api, psa_api_t *psa_api); +#elif PS_TEST +void test_entry_p010(val_api_t *val_api, psa_api_t *psa_api); +#endif + +int main(void) +{ +#ifdef ITS_TEST + test_start(test_entry_s010, COMPLIANCE_TEST_STORAGE); +#elif PS_TEST + test_start(test_entry_p010, COMPLIANCE_TEST_STORAGE); +#endif +} +#endif // !defined(MBED_CONF_RTOS_PRESENT) diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/test_entry.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/test_entry.c new file mode 100644 index 0000000..82623c6 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/test_entry.c @@ -0,0 +1,53 @@ +/** @file + * Copyright (c) 2019, 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 "val_target.h" +#include "test_s010.h" + +#define TEST_NUM VAL_CREATE_TEST_ID(VAL_STORAGE_BASE, 10) +#define TEST_DESC "UID value zero check\n" + +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; + + /* test init */ + val->test_init(TEST_NUM, TEST_DESC, TEST_FIELD(TEST_ISOLATION_L1, WD_HIGH_TIMEOUT)); + if (!IS_TEST_START(val->get_status())) + { + goto test_exit; + } + + /* Execute list of tests available in test[num]_secure_storage_list from Non-secure side*/ + status = val->execute_non_secure_tests(TEST_NUM, test_s010_sst_list, FALSE); + + if (VAL_ERROR(status)) + { + goto test_exit; + } + +test_exit: + val->test_exit(); +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/test_its_data.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/test_its_data.h new file mode 100644 index 0000000..7b1b6d3 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/test_its_data.h @@ -0,0 +1,35 @@ +/** @file + * Copyright (c) 2019, 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_S010_ITS_DATA_TESTS_H_ +#define _TEST_S010_ITS_DATA_TESTS_H_ + +#include "val_internal_trusted_storage.h" + +#define SST_FUNCTION val->its_function +#define psa_sst_uid_t psa_its_uid_t + +typedef struct { + enum its_function_code api; + psa_its_status_t status; +} test_data; + +static const test_data s010_data[] = { +{ + VAL_ITS_SET, PSA_ITS_SUCCESS /* Create with UID value zero should fail */ +}, +}; +#endif /* _TEST_S010_ITS_DATA_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/test_ps_data.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/test_ps_data.h new file mode 100644 index 0000000..e88ed9b --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/test_ps_data.h @@ -0,0 +1,35 @@ +/** @file + * Copyright (c) 2019, Arm Limited or ps 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_S010_PS_DATA_TESTS_H_ +#define _TEST_S010_PS_DATA_TESTS_H_ + +#include "val_protected_storage.h" + +#define SST_FUNCTION val->ps_function +#define psa_sst_uid_t psa_ps_uid_t + +typedef struct { + enum ps_function_code api; + psa_ps_status_t status; +} test_data; + +static const test_data s010_data[] = { +{ + VAL_PS_SET, PSA_PS_SUCCESS /* Create with UID value zero should fail */ +}, +}; +#endif /* _TEST_S010_PS_DATA_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/test_s010.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/test_s010.c new file mode 100644 index 0000000..16fbedd --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/test_s010.c @@ -0,0 +1,48 @@ +/** @file + * Copyright (c) 2019, 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 "val_target.h" +#include "test_s010.h" +#ifdef ITS_TEST +#include "test_its_data.h" +#elif PS_TEST +#include "test_ps_data.h" +#endif + +#define TEST_BUFF_SIZE 1 + +client_test_t test_s010_sst_list[] = { + NULL, + psa_sst_uid_value_zero_check, + NULL, +}; + +static uint8_t write_buff[TEST_BUFF_SIZE] = {0xFF}; + +int32_t psa_sst_uid_value_zero_check(caller_security_t caller) +{ + int32_t status; + psa_sst_uid_t uid = 0; + + /* Set with UID value zero should fail */ + val->print(PRINT_TEST, "[Check 1] Creating storage with UID 0 should fail\n", 0 ); + status = SST_FUNCTION(s010_data[0].api, uid, TEST_BUFF_SIZE, write_buff, 0); + TEST_ASSERT_NOT_EQUAL(status, s010_data[0].status, TEST_CHECKPOINT_NUM(1)); + + return VAL_STATUS_SUCCESS; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/test_s010.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/test_s010.h new file mode 100644 index 0000000..35dfb7c --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/compliance_its/test_s010/test_s010.h @@ -0,0 +1,35 @@ +/** @file + * Copyright (c) 2019, 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_S010_CLIENT_TESTS_H_ +#define _TEST_S010_CLIENT_TESTS_H_ + +#ifdef ITS_TEST +#define VAL_STORAGE_BASE VAL_INTERNAL_TRUSTED_STORAGE_BASE +#define test_entry CONCAT(test_entry_, s010) +#elif PS_TEST +#define VAL_STORAGE_BASE VAL_PROTECTED_STORAGE_BASE +#define test_entry CONCAT(test_entry_, p010) +#endif +#define val CONCAT(val,test_entry) +#define psa CONCAT(psa,test_entry) + +extern val_api_t *val; +extern psa_api_t *psa; +extern client_test_t test_s010_sst_list[]; + +int32_t psa_sst_uid_value_zero_check(caller_security_t caller); +#endif /* _TEST_S010_CLIENT_TESTS_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/crypto_init/main.cpp b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/crypto_init/main.cpp new file mode 100644 index 0000000..778b0fb --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/crypto_init/main.cpp @@ -0,0 +1,90 @@ +/* +* Copyright (c) 2018-2020 ARM Limited. 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 "psa/crypto.h" + +#if ((!defined(TARGET_PSA)) || (!defined(MBEDTLS_PSA_CRYPTO_C))) +#error [NOT_SUPPORTED] Mbed Crypto is OFF - skipping. +#else + +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest/utest.h" +#include "entropy.h" +#include "entropy_poll.h" + +#define TEST_RANDOM_SIZE 64 + +#if !defined(MAX) +#define MAX(a,b) (((a)>(b))?(a):(b)) +#endif + +/* Calculating the minimum allowed entropy size in bytes */ +#define MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE \ + MAX(MBEDTLS_ENTROPY_MIN_PLATFORM, MBEDTLS_ENTROPY_BLOCK_SIZE) + +using namespace utest::v1; + +utest::v1::status_t greentea_test_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(60, "default_auto"); + return greentea_test_setup_handler(number_of_cases); +} + +static void check_crypto_init_deinit() +{ + psa_status_t status; + uint8_t output[TEST_RANDOM_SIZE] = {0}; + + // Should fail as init is required first + status = psa_generate_random(output, sizeof(output)); + TEST_ASSERT_EQUAL(PSA_ERROR_BAD_STATE, status); + + status = psa_crypto_init(); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + + status = psa_generate_random(output, sizeof(output)); + TEST_ASSERT_NOT_EQUAL(PSA_ERROR_BAD_STATE, status); + + mbedtls_psa_crypto_free(); + status = psa_generate_random(output, sizeof(output)); + TEST_ASSERT_EQUAL(PSA_ERROR_BAD_STATE, status); +} + +Case cases[] = { + Case("PSA crypto-init De-init", check_crypto_init_deinit), +}; + +Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); + +int main() +{ +#if defined(MBEDTLS_ENTROPY_NV_SEED) + uint8_t seed[MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE] = {0}; + /* inject some a seed for test*/ + for (int i = 0; i < MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE; ++i) { + seed[i] = i; + } + + /* don't really care if this succeed this is just to make crypto init pass*/ + mbedtls_psa_inject_entropy(seed, MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE); +#endif + return !Harness::run(specification); +} + +#endif // ((!defined(TARGET_PSA)) || (!defined(MBEDTLS_PSA_CRYPTO_C))) diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/entropy_inject/main.cpp b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/entropy_inject/main.cpp new file mode 100644 index 0000000..0098e8e --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/entropy_inject/main.cpp @@ -0,0 +1,187 @@ +/* +* Copyright (c) 2018 ARM Limited. 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. +*/ + +#if ((!defined(TARGET_PSA) || (!defined(COMPONENT_PSA_SRV_IPC)) && !defined(MBEDTLS_ENTROPY_NV_SEED))) +#error [NOT_SUPPORTED] PSA entropy injection tests can run only on PSA-enabled targets. +#else + +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest/utest.h" +#include "psa/internal_trusted_storage.h" +#include "psa/lifecycle.h" +#include "entropy.h" +#include "entropy_poll.h" +#include "psa/crypto.h" +#include + +/* MAX value support macro */ +#if !defined(MAX) +#define MAX(a,b) (((a)>(b))?(a):(b)) +#endif + +/* Calculating the minimum allowed entropy size in bytes */ +#define MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE \ + MAX(MBEDTLS_ENTROPY_MIN_PLATFORM, MBEDTLS_ENTROPY_BLOCK_SIZE) + +using namespace utest::v1; + +uint8_t seed[MBEDTLS_ENTROPY_MAX_SEED_SIZE + 2] = {0}; +bool skip_tests = false; + +void validate_entropy_seed_injection(int seed_length_a, + int expected_status_a, + int seed_length_b, + int expected_status_b) +{ + psa_status_t status; + uint8_t output[32] = { 0 }; + uint8_t zeros[32] = { 0 }; + int memcmp_res = 0; + status = mbedtls_psa_inject_entropy(seed, seed_length_a); + TEST_ASSERT_EQUAL_INT(expected_status_a, status); + + status = mbedtls_psa_inject_entropy(seed, seed_length_b); + TEST_ASSERT_EQUAL_INT(expected_status_b, status); + + status = psa_crypto_init(); + TEST_ASSERT_EQUAL_INT(PSA_SUCCESS, status); + + status = psa_generate_random(output, sizeof(output)); + TEST_ASSERT_EQUAL_INT(PSA_SUCCESS, status); + + memcmp_res = memcmp(output, zeros, sizeof(output)); + TEST_ASSERT_NOT_EQUAL(0, memcmp_res); +} + +void run_entropy_inject_with_crypto_init() +{ + psa_status_t status; + status = psa_crypto_init(); + TEST_ASSERT_EQUAL_INT(PSA_ERROR_INSUFFICIENT_ENTROPY, status); + + status = mbedtls_psa_inject_entropy(seed, MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE); + TEST_ASSERT_EQUAL_INT(PSA_SUCCESS, status); + + status = psa_crypto_init(); + TEST_ASSERT_EQUAL_INT(PSA_SUCCESS, status); + + status = mbedtls_psa_inject_entropy(seed, MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE); + TEST_ASSERT_EQUAL_INT(PSA_ERROR_NOT_PERMITTED, status); + + mbedtls_psa_crypto_free(); + /* The seed is written by nv_seed callback functions therefore the injection will fail */ + status = mbedtls_psa_inject_entropy(seed, MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE); + TEST_ASSERT_EQUAL_INT(PSA_ERROR_NOT_PERMITTED, status); +} + + +utest::v1::status_t greentea_test_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(60, "default_auto"); + + /* fill seed in some data */ + for (size_t i = 0; i < sizeof(seed); ++i) { + seed[i] = i; + } + + psa_status_t status = mbed_psa_reboot_and_request_new_security_state(PSA_LIFECYCLE_ASSEMBLY_AND_TEST); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + + if (mbedtls_psa_inject_entropy(seed, MBEDTLS_ENTROPY_MAX_SEED_SIZE) == PSA_ERROR_NOT_SUPPORTED) { + skip_tests = true; + } + + return greentea_test_setup_handler(number_of_cases); +} + +static void injection_small_good() +{ + TEST_SKIP_UNLESS(!skip_tests); + validate_entropy_seed_injection( + MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE, PSA_SUCCESS, + MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE, PSA_ERROR_NOT_PERMITTED); +} + +static void injection_big_good() +{ + TEST_SKIP_UNLESS(!skip_tests); + validate_entropy_seed_injection( + MBEDTLS_ENTROPY_MAX_SEED_SIZE, PSA_SUCCESS, + MBEDTLS_ENTROPY_MAX_SEED_SIZE, PSA_ERROR_NOT_PERMITTED); +} + +static void injection_too_small() +{ + TEST_SKIP_UNLESS(!skip_tests); + validate_entropy_seed_injection( + (MBEDTLS_ENTROPY_MIN_PLATFORM - 1), PSA_ERROR_INVALID_ARGUMENT, + MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE, PSA_SUCCESS); +} + +static void injection_too_big() +{ + TEST_SKIP_UNLESS(!skip_tests); + validate_entropy_seed_injection( + (MBEDTLS_ENTROPY_MAX_SEED_SIZE + 1), PSA_ERROR_INVALID_ARGUMENT, + MBEDTLS_ENTROPY_MAX_SEED_SIZE, PSA_SUCCESS); +} + +static void injection_and_init_deinit() +{ + TEST_SKIP_UNLESS(!skip_tests); + run_entropy_inject_with_crypto_init(); +} + + + +/***************************************************************************************/ + +utest::v1::status_t case_teardown_handler(const Case *const source, const size_t passed, const size_t failed, const failure_t reason) +{ + psa_status_t status; + status = mbed_psa_reboot_and_request_new_security_state(PSA_LIFECYCLE_ASSEMBLY_AND_TEST); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + mbedtls_psa_crypto_free(); + return greentea_case_teardown_handler(source, passed, failed, reason); +} + +utest::v1::status_t case_setup_handler(const Case *const source, const size_t index_of_case) +{ + psa_status_t status; + status = mbed_psa_reboot_and_request_new_security_state(PSA_LIFECYCLE_ASSEMBLY_AND_TEST); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + return greentea_case_setup_handler(source, index_of_case); +} + +Case cases[] = { + Case("PSA entropy injection small good", case_setup_handler, injection_small_good, case_teardown_handler), + Case("PSA entropy injection big good", case_setup_handler, injection_big_good, case_teardown_handler), + Case("PSA entropy injection too big", case_setup_handler, injection_too_big, case_teardown_handler), + Case("PSA entropy injection too small", case_setup_handler, injection_too_small, case_teardown_handler), + Case("PSA entropy injection before and after init", case_setup_handler, injection_and_init_deinit, case_teardown_handler), +}; + +Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); + +int main() +{ + return !Harness::run(specification); +} + +#endif // ((!defined(TARGET_PSA) || (!defined(COMPONENT_PSA_SRV_IPC)) && !defined(MBEDTLS_ENTROPY_NV_SEED))) diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/its_ps/main.cpp b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/its_ps/main.cpp new file mode 100644 index 0000000..ee2c510 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/its_ps/main.cpp @@ -0,0 +1,251 @@ +/* +* Copyright (c) 2019 ARM Limited. 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. +*/ + +#if !defined(MBED_CONF_RTOS_PRESENT) +#error [NOT_SUPPORTED] ITS/PS test cases require RTOS to run. +#else + +#ifndef TARGET_PSA +#error [NOT_SUPPORTED] ITS/PS tests can run only on PSA-enabled targets. +#else + +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest/utest.h" +#include "psa/error.h" +#include "psa/storage_common.h" +#include "psa/internal_trusted_storage.h" +#include "psa/protected_storage.h" +#include "psa/lifecycle.h" +#include "KVMap.h" +#include "KVStore.h" +#include "kv_config.h" +#include "psa_storage_common_impl.h" +#include "DeviceKey.h" + +using namespace utest::v1; +using namespace mbed; + +#define TEST_BUFF_SIZE 16 +#define STR_EXPAND(tok) #tok + +typedef enum { + its, + ps +} storage_type_t; + +extern "C" psa_status_t psa_ps_reset(); + +static psa_status_t set_func(storage_type_t stype, psa_storage_uid_t uid, size_t data_length, + const void *p_data, psa_storage_create_flags_t create_flags) +{ + return (stype == its) ? + psa_its_set(uid, data_length, p_data, create_flags) : + psa_ps_set(uid, data_length, p_data, create_flags); +} + +static psa_status_t get_func(storage_type_t stype, psa_storage_uid_t uid, size_t data_offset, + size_t data_length, void *p_data, size_t *actual_length) +{ + return (stype == its) ? + psa_its_get(uid, data_offset, data_length, p_data, actual_length) : + psa_ps_get(uid, data_offset, data_length, p_data, actual_length); +} + +static psa_status_t get_info_func(storage_type_t stype, psa_storage_uid_t uid, + struct psa_storage_info_t *p_info) +{ + return (stype == its) ? + psa_its_get_info(uid, p_info) : + psa_ps_get_info(uid, p_info); +} + +static psa_status_t remove_func(storage_type_t stype, psa_storage_uid_t uid) +{ + return (stype == its) ? + psa_its_remove(uid) : + psa_ps_remove(uid); +} + + +template +void pits_ps_test() +{ + psa_status_t status = PSA_SUCCESS; + uint8_t write_buff[TEST_BUFF_SIZE] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}; + uint8_t read_buff[TEST_BUFF_SIZE] = {0}; + size_t actual_size; + psa_storage_create_flags_t flags; + struct psa_storage_info_t info = {0, PSA_STORAGE_FLAG_WRITE_ONCE}; + memset(read_buff, 0, TEST_BUFF_SIZE); + + status = get_info_func(stype, 5, &info); + TEST_ASSERT_EQUAL(PSA_ERROR_DOES_NOT_EXIST, status); + + status = set_func(stype, 5, TEST_BUFF_SIZE, write_buff, 0); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + + status = get_info_func(stype, 5, &info); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + TEST_ASSERT_EQUAL(TEST_BUFF_SIZE, info.size); + TEST_ASSERT_EQUAL(0, info.flags); + + status = get_func(stype, 5, 0, TEST_BUFF_SIZE, read_buff, &actual_size); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + TEST_ASSERT_EQUAL_MEMORY(write_buff, read_buff, TEST_BUFF_SIZE); + + memset(read_buff, 0, TEST_BUFF_SIZE); + status = get_func(stype, 5, 1, TEST_BUFF_SIZE, read_buff, &actual_size); + TEST_ASSERT_NOT_EQUAL(PSA_SUCCESS, status); + + status = get_func(stype, 5, 1, TEST_BUFF_SIZE - 1, read_buff, &actual_size); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + TEST_ASSERT_EQUAL_MEMORY(write_buff + 1, read_buff, TEST_BUFF_SIZE - 1); + + status = remove_func(stype, 5); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + + status = get_info_func(stype, 5, &info); + TEST_ASSERT_EQUAL(PSA_ERROR_DOES_NOT_EXIST, status); + + if (stype == its) { + return; + } + + mbed::KVMap &kv_map = mbed::KVMap::get_instance(); + mbed::KVStore *kvstore = kv_map.get_main_kv_instance(STR_EXPAND(MBED_CONF_STORAGE_DEFAULT_KV)); + uint32_t kv_get_flags; + + flags = PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION; + status = set_func(stype, 6, TEST_BUFF_SIZE, write_buff, flags); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + + status = get_info_func(stype, 6, &info); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + TEST_ASSERT_EQUAL(flags, info.flags); + + status = psa_storage_get_info_impl(kvstore, 1, 6, &info, &kv_get_flags); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + TEST_ASSERT_EQUAL(kv_get_flags, mbed::KVStore::REQUIRE_CONFIDENTIALITY_FLAG); + + flags = PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION | PSA_STORAGE_FLAG_NO_CONFIDENTIALITY | PSA_STORAGE_FLAG_WRITE_ONCE; + status = set_func(stype, 6, TEST_BUFF_SIZE, write_buff, flags); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + + status = get_info_func(stype, 6, &info); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + TEST_ASSERT_EQUAL(flags, info.flags); + + status = psa_storage_get_info_impl(kvstore, 1, 6, &info, &kv_get_flags); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + TEST_ASSERT_EQUAL(kv_get_flags, mbed::KVStore::WRITE_ONCE_FLAG); +} + +template +void pits_ps_write_once_test() +{ + psa_status_t status = PSA_SUCCESS; + uint8_t write_buff[TEST_BUFF_SIZE] = {0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00}; + uint8_t read_buff[TEST_BUFF_SIZE] = {0}; + size_t actual_size; + struct psa_storage_info_t info = {0, 0}; + + status = get_info_func(stype, 5, &info); + TEST_ASSERT_EQUAL(PSA_ERROR_DOES_NOT_EXIST, status); + + status = set_func(stype, 5, TEST_BUFF_SIZE, write_buff, PSA_STORAGE_FLAG_WRITE_ONCE); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + + info.size = 0; + info.flags = PSA_STORAGE_FLAG_WRITE_ONCE; + status = get_info_func(stype, 5, &info); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + TEST_ASSERT_EQUAL(TEST_BUFF_SIZE, info.size); + TEST_ASSERT_EQUAL(PSA_STORAGE_FLAG_WRITE_ONCE, info.flags); + + status = get_func(stype, 5, 0, TEST_BUFF_SIZE, read_buff, &actual_size); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + TEST_ASSERT_EQUAL(TEST_BUFF_SIZE, actual_size); + TEST_ASSERT_EQUAL_MEMORY(write_buff, read_buff, TEST_BUFF_SIZE); + + status = set_func(stype, 5, TEST_BUFF_SIZE, write_buff, PSA_STORAGE_FLAG_WRITE_ONCE); + TEST_ASSERT_EQUAL(PSA_ERROR_NOT_PERMITTED, status); + + status = set_func(stype, 5, TEST_BUFF_SIZE, write_buff, 0); + TEST_ASSERT_EQUAL(PSA_ERROR_NOT_PERMITTED, status); + + status = remove_func(stype, 5); + TEST_ASSERT_EQUAL(PSA_ERROR_NOT_PERMITTED, status); + + info.size = 0; + info.flags = PSA_STORAGE_FLAG_WRITE_ONCE; + status = get_info_func(stype, 5, &info); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + TEST_ASSERT_EQUAL(TEST_BUFF_SIZE, info.size); + TEST_ASSERT_EQUAL(PSA_STORAGE_FLAG_WRITE_ONCE, info.flags); +} + +utest::v1::status_t case_its_teardown_handler(const Case *const source, const size_t passed, const size_t failed, const failure_t reason) +{ + psa_status_t status; + status = mbed_psa_reboot_and_request_new_security_state(PSA_LIFECYCLE_ASSEMBLY_AND_TEST); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + return greentea_case_teardown_handler(source, passed, failed, reason); +} + +template +utest::v1::status_t case_its_setup_handler(const Case *const source, const size_t index_of_case) +{ + psa_status_t status; + if (stype == its) { + status = mbed_psa_reboot_and_request_new_security_state(PSA_LIFECYCLE_ASSEMBLY_AND_TEST); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + } else { + status = psa_ps_reset(); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + } +#if DEVICEKEY_ENABLED + DeviceKey::get_instance().generate_root_of_trust(); +#endif + return greentea_case_setup_handler(source, index_of_case); +} + +Case cases[] = { + Case("PSA prot internal storage - Basic", case_its_setup_handler, pits_ps_test, case_its_teardown_handler), + Case("PSA prot internal storage - Write-once", case_its_setup_handler, pits_ps_write_once_test, case_its_teardown_handler), +#if COMPONENT_FLASHIAP + Case("PSA protected storage - Basic", case_its_setup_handler, pits_ps_test), + Case("PSA protected storage - Write-once", case_its_setup_handler, pits_ps_write_once_test) +#endif +}; + +utest::v1::status_t greentea_test_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(60, "default_auto"); + return greentea_test_setup_handler(number_of_cases); +} + +Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); + +int main() +{ + return !Harness::run(specification); +} + +#endif // TARGET_PSA +#endif // !defined(MBED_CONF_RTOS_PRESENT) diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/client.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/client.h new file mode 100644 index 0000000..de1c520 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/client.h @@ -0,0 +1,155 @@ +/* Copyright (c) 2017-2020 ARM Limited + * + * 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. + */ + +#if defined(FEATURE_TFM) +#include "interface/include/psa_client.h" +#else + +#ifndef __MBED_OS_DEFAULT_PSA_CLIENT_API_H__ +#define __MBED_OS_DEFAULT_PSA_CLIENT_API_H__ + +#include +#include "psa/error.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(UINT32_MAX) +#define UINT32_MAX ((uint32_t)-1) +#endif + +#if !defined(INT32_MIN) +#define INT32_MIN (-0x7fffffff - 1) +#endif + +#define PSA_FRAMEWORK_VERSION (0x0100) /**< Version of the PSA Framework API. */ +#define PSA_VERSION_NONE (0L) /**< Identifier for an unimplemented Root of Trust (RoT) Service. */ +#define PSA_CONNECTION_REFUSED (INT32_MIN + 1) /**< The return value from psa_connect() if the RoT Service or SPM was unable to establish a connection.*/ +#define PSA_CONNECTION_BUSY (INT32_MIN + 2) /**< The return value from psa_connect() if the RoT Service rejects the connection for a transient reason.*/ +#define PSA_DROP_CONNECTION (INT32_MIN) /**< The result code in a call to psa_reply() to indicate a nonrecoverable error in the client.*/ +#define PSA_NULL_HANDLE ((psa_handle_t)0) /**< Denotes an invalid handle.*/ + +typedef int32_t psa_handle_t; + +typedef struct psa_invec { + const void *base; /**< Starting address of the buffer.*/ + size_t len; /**< Length in bytes of the buffer.*/ +} psa_invec; + + +typedef struct psa_outvec { + void *base; /**< Starting address of the buffer.*/ + size_t len; /**< Length in bytes of the buffer.*/ +} psa_outvec; + +/** + * \brief Retrieve the version of the PSA Framework API that is implemented. + * + * \return version The version of the PSA Framework implementation + * that is providing the runtime services to the + * caller. The major and minor version are encoded + * as follows: + * \arg version[15:8] -- major version number. + * \arg version[7:0] -- minor version number. + */ +uint32_t psa_framework_version(void); + +/** + * \brief Retrieve the version of an RoT Service or indicate that it is not + * present on this system. + * + * \param[in] sid ID of the RoT Service to query. + * + * \retval PSA_VERSION_NONE The RoT Service is not implemented, or the + * caller is not permitted to access the service. + * \retval > 0 The version of the implemented RoT Service. + */ +uint32_t psa_version(uint32_t sid); + +/** + * \brief Connect to an RoT Service by its SID. + * + * \param[in] sid ID of the RoT Service to connect to. + * \param[in] version Requested version of the RoT Service. + * + * \retval > 0 A handle for the connection. + * \retval PSA_ERROR_CONNECTION_REFUSED The SPM or RoT Service has refused the + * connection. + * \retval PSA_ERROR_CONNECTION_BUSY The SPM or RoT Service cannot make the + * connection at the moment. + * \retval "PROGRAMMER ERROR" The call is a PROGRAMMER ERROR if one or more + * of the following are true: + * \arg The RoT Service ID is not present. + * \arg The RoT Service version is not supported. + * \arg The caller is not allowed to access the RoT + * service. + */ +psa_handle_t psa_connect(uint32_t sid, uint32_t version); + +/** + * \brief Call an RoT Service on an established connection. + * + * \param[in] handle A handle to an established connection. + * \param[in] type The reuqest type. + * Must be zero( \ref PSA_IPC_CALL) or positive. + * \param[in] in_vec Array of input \ref psa_invec structures. + * \param[in] in_len Number of input \ref psa_invec structures. + * \param[in/out] out_vec Array of output \ref psa_outvec structures. + * \param[in] out_len Number of output \ref psa_outvec structures. + * + * \retval >=0 RoT Service-specific status value. + * \retval <0 RoT Service-specific error code. + * \retval PSA_ERROR_PROGRAMMER_ERROR The connection has been terminated by the + * RoT Service. The call is a PROGRAMMER ERROR if + * one or more of the following are true: + * \arg An invalid handle was passed. + * \arg The connection is already handling a request. + * \arg type < 0. + * \arg An invalid memory reference was provided. + * \arg in_len + out_len > PSA_MAX_IOVEC. + * \arg The message is unrecognized by the RoT + * Service or incorrectly formatted. + */ +psa_status_t psa_call(psa_handle_t handle, int32_t type, + const psa_invec *in_vec, + size_t in_len, + psa_outvec *out_vec, + size_t out_len); + +/** + * \brief Close a connection to an RoT Service. + * + * \param[in] handle A handle to an established connection, or the + * null handle. + * + * \retval void Success. + * \retval "PROGRAMMER ERROR" The call is a PROGRAMMER ERROR if one or more + * of the following are true: + * \arg An invalid handle was provided that is not + * the null handle. + * \arg The connection is currently handling a + * request. + */ +void psa_close(psa_handle_t handle); + +#ifdef __cplusplus +} +#endif + +#endif // __MBED_OS_DEFAULT_PSA_CLIENT_API_H__ +#endif diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto.h new file mode 100644 index 0000000..2b07b74 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto.h @@ -0,0 +1,3780 @@ +/** + * \file psa/crypto.h + * \brief Platform Security Architecture cryptography module + */ +/* + * Copyright (C) 2018, ARM Limited, 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 PSA_CRYPTO_H +#define PSA_CRYPTO_H + +#include "crypto_platform.h" + +#include + +#ifdef __DOXYGEN_ONLY__ +/* This __DOXYGEN_ONLY__ block contains mock definitions for things that + * must be defined in the crypto_platform.h header. These mock definitions + * are present in this file as a convenience to generate pretty-printed + * documentation that includes those definitions. */ + +/** \defgroup platform Implementation-specific definitions + * @{ + */ + +/** \brief Key handle. + * + * This type represents open handles to keys. It must be an unsigned integral + * type. The choice of type is implementation-dependent. + * + * 0 is not a valid key handle. How other handle values are assigned is + * implementation-dependent. + */ +typedef _unsigned_integral_type_ psa_key_handle_t; + +/**@}*/ +#endif /* __DOXYGEN_ONLY__ */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* The file "crypto_types.h" declares types that encode errors, + * algorithms, key types, policies, etc. */ +#include "crypto_types.h" + +/** \defgroup version API version + * @{ + */ + +/** + * The major version of this implementation of the PSA Crypto API + */ +#define PSA_CRYPTO_API_VERSION_MAJOR 1 + +/** + * The minor version of this implementation of the PSA Crypto API + */ +#define PSA_CRYPTO_API_VERSION_MINOR 0 + +/**@}*/ + +/* The file "crypto_values.h" declares macros to build and analyze values + * of integral types defined in "crypto_types.h". */ +#include "crypto_values.h" + +/** \defgroup initialization Library initialization + * @{ + */ + +/** + * \brief Library initialization. + * + * Applications must call this function before calling any other + * function in this module. + * + * Applications may call this function more than once. Once a call + * succeeds, subsequent calls are guaranteed to succeed. + * + * If the application calls other functions before calling psa_crypto_init(), + * the behavior is undefined. Implementations are encouraged to either perform + * the operation as if the library had been initialized or to return + * #PSA_ERROR_BAD_STATE or some other applicable error. In particular, + * implementations should not return a success status if the lack of + * initialization may have security implications, for example due to improper + * seeding of the random number generator. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + */ +psa_status_t psa_crypto_init(void); + +/**@}*/ + +/** \addtogroup attributes + * @{ + */ + +/** \def PSA_KEY_ATTRIBUTES_INIT + * + * This macro returns a suitable initializer for a key attribute structure + * of type #psa_key_attributes_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_KEY_ATTRIBUTES_INIT {0} +#endif + +/** Return an initial value for a key attributes structure. + */ +static psa_key_attributes_t psa_key_attributes_init(void); + +/** Declare a key as persistent and set its key identifier. + * + * If the attribute structure currently declares the key as volatile (which + * is the default content of an attribute structure), this function sets + * the lifetime attribute to #PSA_KEY_LIFETIME_PERSISTENT. + * + * This function does not access storage, it merely stores the given + * value in the structure. + * The persistent key will be written to storage when the attribute + * structure is passed to a key creation function such as + * psa_import_key(), psa_generate_key(), + * psa_key_derivation_output_key() or psa_copy_key(). + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param id The persistent identifier for the key. + */ +static void psa_set_key_id(psa_key_attributes_t *attributes, + psa_key_id_t id); + +/** Set the location of a persistent key. + * + * To make a key persistent, you must give it a persistent key identifier + * with psa_set_key_id(). By default, a key that has a persistent identifier + * is stored in the default storage area identifier by + * #PSA_KEY_LIFETIME_PERSISTENT. Call this function to choose a storage + * area, or to explicitly declare the key as volatile. + * + * This function does not access storage, it merely stores the given + * value in the structure. + * The persistent key will be written to storage when the attribute + * structure is passed to a key creation function such as + * psa_import_key(), psa_generate_key(), + * psa_key_derivation_output_key() or psa_copy_key(). + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param lifetime The lifetime for the key. + * If this is #PSA_KEY_LIFETIME_VOLATILE, the + * key will be volatile, and the key identifier + * attribute is reset to 0. + */ +static void psa_set_key_lifetime(psa_key_attributes_t *attributes, + psa_key_lifetime_t lifetime); + +/** Retrieve the key identifier from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The persistent identifier stored in the attribute structure. + * This value is unspecified if the attribute structure declares + * the key as volatile. + */ +static psa_key_id_t psa_get_key_id(const psa_key_attributes_t *attributes); + +/** Retrieve the lifetime from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The lifetime value stored in the attribute structure. + */ +static psa_key_lifetime_t psa_get_key_lifetime( + const psa_key_attributes_t *attributes); + +/** Declare usage flags for a key. + * + * Usage flags are part of a key's usage policy. They encode what + * kind of operations are permitted on the key. For more details, + * refer to the documentation of the type #psa_key_usage_t. + * + * This function overwrites any usage flags + * previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param usage_flags The usage flags to write. + */ +static void psa_set_key_usage_flags(psa_key_attributes_t *attributes, + psa_key_usage_t usage_flags); + +/** Retrieve the usage flags from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The usage flags stored in the attribute structure. + */ +static psa_key_usage_t psa_get_key_usage_flags( + const psa_key_attributes_t *attributes); + +/** Declare the permitted algorithm policy for a key. + * + * The permitted algorithm policy of a key encodes which algorithm or + * algorithms are permitted to be used with this key. The following + * algorithm policies are supported: + * - 0 does not allow any cryptographic operation with the key. The key + * may be used for non-cryptographic actions such as exporting (if + * permitted by the usage flags). + * - An algorithm value permits this particular algorithm. + * - An algorithm wildcard built from #PSA_ALG_ANY_HASH allows the specified + * signature scheme with any hash algorithm. + * + * This function overwrites any algorithm policy + * previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param alg The permitted algorithm policy to write. + */ +static void psa_set_key_algorithm(psa_key_attributes_t *attributes, + psa_algorithm_t alg); + + +/** Retrieve the algorithm policy from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The algorithm stored in the attribute structure. + */ +static psa_algorithm_t psa_get_key_algorithm( + const psa_key_attributes_t *attributes); + +/** Declare the type of a key. + * + * This function overwrites any key type + * previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param type The key type to write. + * If this is 0, the key type in \p attributes + * becomes unspecified. + */ +static void psa_set_key_type(psa_key_attributes_t *attributes, + psa_key_type_t type); + + +/** Declare the size of a key. + * + * This function overwrites any key size previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param bits The key size in bits. + * If this is 0, the key size in \p attributes + * becomes unspecified. Keys of size 0 are + * not supported. + */ +static void psa_set_key_bits(psa_key_attributes_t *attributes, + size_t bits); + +/** Retrieve the key type from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The key type stored in the attribute structure. + */ +static psa_key_type_t psa_get_key_type(const psa_key_attributes_t *attributes); + +/** Retrieve the key size from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The key size stored in the attribute structure, in bits. + */ +static size_t psa_get_key_bits(const psa_key_attributes_t *attributes); + +/** Retrieve the attributes of a key. + * + * This function first resets the attribute structure as with + * psa_reset_key_attributes(). It then copies the attributes of + * the given key into the given attribute structure. + * + * \note This function may allocate memory or other resources. + * Once you have called this function on an attribute structure, + * you must call psa_reset_key_attributes() to free these resources. + * + * \param[in] handle Handle to the key to query. + * \param[in,out] attributes On success, the attributes of the key. + * On failure, equivalent to a + * freshly-initialized structure. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_get_key_attributes(psa_key_handle_t handle, + psa_key_attributes_t *attributes); + +/** Reset a key attribute structure to a freshly initialized state. + * + * You must initialize the attribute structure as described in the + * documentation of the type #psa_key_attributes_t before calling this + * function. Once the structure has been initialized, you may call this + * function at any time. + * + * This function frees any auxiliary resources that the structure + * may contain. + * + * \param[in,out] attributes The attribute structure to reset. + */ +void psa_reset_key_attributes(psa_key_attributes_t *attributes); + +/**@}*/ + +/** \defgroup key_management Key management + * @{ + */ + +/** Open a handle to an existing persistent key. + * + * Open a handle to a persistent key. A key is persistent if it was created + * with a lifetime other than #PSA_KEY_LIFETIME_VOLATILE. A persistent key + * always has a nonzero key identifier, set with psa_set_key_id() when + * creating the key. Implementations may provide additional pre-provisioned + * keys that can be opened with psa_open_key(). Such keys have a key identifier + * in the vendor range, as documented in the description of #psa_key_id_t. + * + * The application must eventually close the handle with psa_close_key() or + * psa_destroy_key() to release associated resources. If the application dies + * without calling one of these functions, the implementation should perform + * the equivalent of a call to psa_close_key(). + * + * Some implementations permit an application to open the same key multiple + * times. If this is successful, each call to psa_open_key() will return a + * different key handle. + * + * \note Applications that rely on opening a key multiple times will not be + * portable to implementations that only permit a single key handle to be + * opened. See also :ref:\`key-handles\`. + * + * \param id The persistent identifier of the key. + * \param[out] handle On success, a handle to the key. + * + * \retval #PSA_SUCCESS + * Success. The application can now use the value of `*handle` + * to access the key. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * The implementation does not have sufficient resources to open the + * key. This can be due to reaching an implementation limit on the + * number of open keys, the number of open key handles, or available + * memory. + * \retval #PSA_ERROR_DOES_NOT_EXIST + * There is no persistent key with key identifier \p id. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p id is not a valid persistent key identifier. + * \retval #PSA_ERROR_NOT_PERMITTED + * The specified key exists, but the application does not have the + * permission to access it. Note that this specification does not + * define any way to create such a key, but it may be possible + * through implementation-specific means. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_open_key(psa_key_id_t id, + psa_key_handle_t *handle); + + +/** Close a key handle. + * + * If the handle designates a volatile key, this will destroy the key material + * and free all associated resources, just like psa_destroy_key(). + * + * If this is the last open handle to a persistent key, then closing the handle + * will free all resources associated with the key in volatile memory. The key + * data in persistent storage is not affected and can be opened again later + * with a call to psa_open_key(). + * + * Closing the key handle makes the handle invalid, and the key handle + * must not be used again by the application. + * + * \note If the key handle was used to set up an active + * :ref:\`multipart operation \`, then closing the + * key handle can cause the multipart operation to fail. Applications should + * maintain the key handle until after the multipart operation has finished. + * + * \param handle The key handle to close. + * If this is \c 0, do nothing and return \c PSA_SUCCESS. + * + * \retval #PSA_SUCCESS + * \p handle was a valid handle or \c 0. It is now closed. + * \retval #PSA_ERROR_INVALID_HANDLE + * \p handle is not a valid handle nor \c 0. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_close_key(psa_key_handle_t handle); + +/** Make a copy of a key. + * + * Copy key material from one location to another. + * + * This function is primarily useful to copy a key from one location + * to another, since it populates a key using the material from + * another key which may have a different lifetime. + * + * This function may be used to share a key with a different party, + * subject to implementation-defined restrictions on key sharing. + * + * The policy on the source key must have the usage flag + * #PSA_KEY_USAGE_COPY set. + * This flag is sufficient to permit the copy if the key has the lifetime + * #PSA_KEY_LIFETIME_VOLATILE or #PSA_KEY_LIFETIME_PERSISTENT. + * Some secure elements do not provide a way to copy a key without + * making it extractable from the secure element. If a key is located + * in such a secure element, then the key must have both usage flags + * #PSA_KEY_USAGE_COPY and #PSA_KEY_USAGE_EXPORT in order to make + * a copy of the key outside the secure element. + * + * The resulting key may only be used in a way that conforms to + * both the policy of the original key and the policy specified in + * the \p attributes parameter: + * - The usage flags on the resulting key are the bitwise-and of the + * usage flags on the source policy and the usage flags in \p attributes. + * - If both allow the same algorithm or wildcard-based + * algorithm policy, the resulting key has the same algorithm policy. + * - If either of the policies allows an algorithm and the other policy + * allows a wildcard-based algorithm policy that includes this algorithm, + * the resulting key allows the same algorithm. + * - If the policies do not allow any algorithm in common, this function + * fails with the status #PSA_ERROR_INVALID_ARGUMENT. + * + * The effect of this function on implementation-defined attributes is + * implementation-defined. + * + * \param source_handle The key to copy. It must be a valid key handle. + * \param[in] attributes The attributes for the new key. + * They are used as follows: + * - The key type and size may be 0. If either is + * nonzero, it must match the corresponding + * attribute of the source key. + * - The key location (the lifetime and, for + * persistent keys, the key identifier) is + * used directly. + * - The policy constraints (usage flags and + * algorithm policy) are combined from + * the source key and \p attributes so that + * both sets of restrictions apply, as + * described in the documentation of this function. + * \param[out] target_handle On success, a handle to the newly created key. + * \c 0 on failure. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \p source_handle is invalid. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The lifetime or identifier in \p attributes are invalid. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The policy constraints on the source and specified in + * \p attributes are incompatible. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p attributes specifies a key type or key size + * which does not match the attributes of the source key. + * \retval #PSA_ERROR_NOT_PERMITTED + * The source key does not have the #PSA_KEY_USAGE_COPY usage flag. + * \retval #PSA_ERROR_NOT_PERMITTED + * The source key is not exportable and its lifetime does not + * allow copying it to the target's lifetime. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_copy_key(psa_key_handle_t source_handle, + const psa_key_attributes_t *attributes, + psa_key_handle_t *target_handle); + + +/** + * \brief Destroy a key. + * + * This function destroys a key from both volatile + * memory and, if applicable, non-volatile storage. Implementations shall + * make a best effort to ensure that that the key material cannot be recovered. + * + * This function also erases any metadata such as policies and frees + * resources associated with the key. To free all resources associated with + * the key, all handles to the key must be closed or destroyed. + * + * Destroying the key makes the handle invalid, and the key handle + * must not be used again by the application. Using other open handles to the + * destroyed key in a cryptographic operation will result in an error. + * + * If a key is currently in use in a multipart operation, then destroying the + * key will cause the multipart operation to fail. + * + * \param handle Handle to the key to erase. + * If this is \c 0, do nothing and return \c PSA_SUCCESS. + * + * \retval #PSA_SUCCESS + * \p handle was a valid handle and the key material that it + * referred to has been erased. + * Alternatively, \p handle is \c 0. + * \retval #PSA_ERROR_NOT_PERMITTED + * The key cannot be erased because it is + * read-only, either due to a policy or due to physical restrictions. + * \retval #PSA_ERROR_INVALID_HANDLE + * \p handle is not a valid handle nor \c 0. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * There was an failure in communication with the cryptoprocessor. + * The key material may still be present in the cryptoprocessor. + * \retval #PSA_ERROR_STORAGE_FAILURE + * The storage is corrupted. Implementations shall make a best effort + * to erase key material even in this stage, however applications + * should be aware that it may be impossible to guarantee that the + * key material is not recoverable in such cases. + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * An unexpected condition which is not a storage corruption or + * a communication failure occurred. The cryptoprocessor may have + * been compromised. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_destroy_key(psa_key_handle_t handle); + +/**@}*/ + +/** \defgroup import_export Key import and export + * @{ + */ + +/** + * \brief Import a key in binary format. + * + * This function supports any output from psa_export_key(). Refer to the + * documentation of psa_export_public_key() for the format of public keys + * and to the documentation of psa_export_key() for the format for + * other key types. + * + * The key data determines the key size. The attributes may optionally + * specify a key size; in this case it must match the size determined + * from the key data. A key size of 0 in \p attributes indicates that + * the key size is solely determined by the key data. + * + * Implementations must reject an attempt to import a key of size 0. + * + * This specification supports a single format for each key type. + * Implementations may support other formats as long as the standard + * format is supported. Implementations that support other formats + * should ensure that the formats are clearly unambiguous so as to + * minimize the risk that an invalid input is accidentally interpreted + * according to a different format. + * + * \param[in] attributes The attributes for the new key. + * The key size is always determined from the + * \p data buffer. + * If the key size in \p attributes is nonzero, + * it must be equal to the size from \p data. + * \param[out] handle On success, a handle to the newly created key. + * \c 0 on failure. + * \param[in] data Buffer containing the key data. The content of this + * buffer is interpreted according to the type declared + * in \p attributes. + * All implementations must support at least the format + * described in the documentation + * of psa_export_key() or psa_export_public_key() for + * the chosen type. Implementations may allow other + * formats, but should be conservative: implementations + * should err on the side of rejecting content if it + * may be erroneous (e.g. wrong type or truncated data). + * \param data_length Size of the \p data buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The key type or key size is not supported, either by the + * implementation in general or in this particular persistent location. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key attributes, as a whole, are invalid. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key data is not correctly formatted. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size in \p attributes is nonzero and does not match the size + * of the key data. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_import_key(const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + psa_key_handle_t *handle); + + + +/** + * \brief Export a key in binary format. + * + * The output of this function can be passed to psa_import_key() to + * create an equivalent object. + * + * If the implementation of psa_import_key() supports other formats + * beyond the format specified here, the output from psa_export_key() + * must use the representation specified here, not the original + * representation. + * + * For standard key types, the output format is as follows: + * + * - For symmetric keys (including MAC keys), the format is the + * raw bytes of the key. + * - For DES, the key data consists of 8 bytes. The parity bits must be + * correct. + * - For Triple-DES, the format is the concatenation of the + * two or three DES keys. + * - For RSA key pairs (#PSA_KEY_TYPE_RSA_KEY_PAIR), the format + * is the non-encrypted DER encoding of the representation defined by + * PKCS\#1 (RFC 8017) as `RSAPrivateKey`, version 0. + * ``` + * RSAPrivateKey ::= SEQUENCE { + * version INTEGER, -- must be 0 + * modulus INTEGER, -- n + * publicExponent INTEGER, -- e + * privateExponent INTEGER, -- d + * prime1 INTEGER, -- p + * prime2 INTEGER, -- q + * exponent1 INTEGER, -- d mod (p-1) + * exponent2 INTEGER, -- d mod (q-1) + * coefficient INTEGER, -- (inverse of q) mod p + * } + * ``` + * - For elliptic curve key pairs (key types for which + * #PSA_KEY_TYPE_IS_ECC_KEY_PAIR is true), the format is + * a representation of the private value as a `ceiling(m/8)`-byte string + * where `m` is the bit size associated with the curve, i.e. the bit size + * of the order of the curve's coordinate field. This byte string is + * in little-endian order for Montgomery curves (curve types + * `PSA_ECC_CURVE_CURVEXXX`), and in big-endian order for Weierstrass + * curves (curve types `PSA_ECC_CURVE_SECTXXX`, `PSA_ECC_CURVE_SECPXXX` + * and `PSA_ECC_CURVE_BRAINPOOL_PXXX`). + * This is the content of the `privateKey` field of the `ECPrivateKey` + * format defined by RFC 5915. + * - For Diffie-Hellman key exchange key pairs (key types for which + * #PSA_KEY_TYPE_IS_DH_KEY_PAIR is true), the + * format is the representation of the private key `x` as a big-endian byte + * string. The length of the byte string is the private key size in bytes + * (leading zeroes are not stripped). + * - For public keys (key types for which #PSA_KEY_TYPE_IS_PUBLIC_KEY is + * true), the format is the same as for psa_export_public_key(). + * + * The policy on the key must have the usage flag #PSA_KEY_USAGE_EXPORT set. + * + * \param handle Handle to the key to export. + * \param[out] data Buffer where the key data is to be written. + * \param data_size Size of the \p data buffer in bytes. + * \param[out] data_length On success, the number of bytes + * that make up the key data. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * The key does not have the #PSA_KEY_USAGE_EXPORT flag. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p data buffer is too small. You can determine a + * sufficient buffer size by calling + * #PSA_KEY_EXPORT_MAX_SIZE(\c type, \c bits) + * where \c type is the key type + * and \c bits is the key size in bits. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_export_key(psa_key_handle_t handle, + uint8_t *data, + size_t data_size, + size_t *data_length); + +/** + * \brief Export a public key or the public part of a key pair in binary format. + * + * The output of this function can be passed to psa_import_key() to + * create an object that is equivalent to the public key. + * + * This specification supports a single format for each key type. + * Implementations may support other formats as long as the standard + * format is supported. Implementations that support other formats + * should ensure that the formats are clearly unambiguous so as to + * minimize the risk that an invalid input is accidentally interpreted + * according to a different format. + * + * For standard key types, the output format is as follows: + * - For RSA public keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY), the DER encoding of + * the representation defined by RFC 3279 §2.3.1 as `RSAPublicKey`. + * ``` + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER } -- e + * ``` + * - For elliptic curve public keys (key types for which + * #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true), the format is the uncompressed + * representation defined by SEC1 §2.3.3 as the content of an ECPoint. + * Let `m` be the bit size associated with the curve, i.e. the bit size of + * `q` for a curve over `F_q`. The representation consists of: + * - The byte 0x04; + * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; + * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. + * - For Diffie-Hellman key exchange public keys (key types for which + * #PSA_KEY_TYPE_IS_DH_PUBLIC_KEY is true), + * the format is the representation of the public key `y = g^x mod p` as a + * big-endian byte string. The length of the byte string is the length of the + * base prime `p` in bytes. + * + * Exporting a public key object or the public part of a key pair is + * always permitted, regardless of the key's usage flags. + * + * \param handle Handle to the key to export. + * \param[out] data Buffer where the key data is to be written. + * \param data_size Size of the \p data buffer in bytes. + * \param[out] data_length On success, the number of bytes + * that make up the key data. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key is neither a public key nor a key pair. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p data buffer is too small. You can determine a + * sufficient buffer size by calling + * #PSA_KEY_EXPORT_MAX_SIZE(#PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(\c type), \c bits) + * where \c type is the key type + * and \c bits is the key size in bits. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_export_public_key(psa_key_handle_t handle, + uint8_t *data, + size_t data_size, + size_t *data_length); + + + +/**@}*/ + +/** \defgroup hash Message digests + * @{ + */ + +/** Calculate the hash (digest) of a message. + * + * \note To verify the hash of a message against an + * expected value, use psa_hash_compare() instead. + * + * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_HASH(\p alg) is true). + * \param[in] input Buffer containing the message to hash. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] hash Buffer where the hash is to be written. + * \param hash_size Size of the \p hash buffer in bytes. + * \param[out] hash_length On success, the number of bytes + * that make up the hash value. This is always + * #PSA_HASH_SIZE(\p alg). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a hash algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p hash_size is too small + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_compute(psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *hash, + size_t hash_size, + size_t *hash_length); + +/** Calculate the hash (digest) of a message and compare it with a + * reference value. + * + * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_HASH(\p alg) is true). + * \param[in] input Buffer containing the message to hash. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] hash Buffer containing the expected hash value. + * \param hash_length Size of the \p hash buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected hash is identical to the actual hash of the input. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The hash of the message was calculated successfully, but it + * differs from the expected hash. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a hash algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p input_length or \p hash_length do not match the hash size for \p alg + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_compare(psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *hash, + size_t hash_length); + +/** The type of the state data structure for multipart hash operations. + * + * Before calling any function on a hash operation object, the application must + * initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_hash_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_hash_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_HASH_OPERATION_INIT, + * for example: + * \code + * psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_hash_operation_init() + * to the structure, for example: + * \code + * psa_hash_operation_t operation; + * operation = psa_hash_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure except + * as directed by the documentation of a specific implementation. */ +typedef struct psa_hash_operation_s psa_hash_operation_t; + +/** \def PSA_HASH_OPERATION_INIT + * + * This macro returns a suitable initializer for a hash operation object + * of type #psa_hash_operation_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_HASH_OPERATION_INIT {0} +#endif + +/** Return an initial value for a hash operation object. + */ +static psa_hash_operation_t psa_hash_operation_init(void); + +/** Set up a multipart hash operation. + * + * The sequence of operations to calculate a hash (message digest) + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_hash_operation_t, e.g. #PSA_HASH_OPERATION_INIT. + * -# Call psa_hash_setup() to specify the algorithm. + * -# Call psa_hash_update() zero, one or more times, passing a fragment + * of the message each time. The hash that is calculated is the hash + * of the concatenation of these messages in order. + * -# To calculate the hash, call psa_hash_finish(). + * To compare the hash with an expected value, call psa_hash_verify(). + * + * If an error occurs at any step after a call to psa_hash_setup(), the + * operation will need to be reset by a call to psa_hash_abort(). The + * application may call psa_hash_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_hash_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_hash_finish() or psa_hash_verify(). + * - A call to psa_hash_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_hash_operation_t and not yet in use. + * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_HASH(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not a supported hash algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p alg is not a hash algorithm. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_setup(psa_hash_operation_t *operation, + psa_algorithm_t alg); + +/** Add a message fragment to a multipart hash operation. + * + * The application must call psa_hash_setup() before calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_hash_abort(). + * + * \param[in,out] operation Active hash operation. + * \param[in] input Buffer containing the message fragment to hash. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it muct be active). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_update(psa_hash_operation_t *operation, + const uint8_t *input, + size_t input_length); + +/** Finish the calculation of the hash of a message. + * + * The application must call psa_hash_setup() before calling this function. + * This function calculates the hash of the message formed by concatenating + * the inputs passed to preceding calls to psa_hash_update(). + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_hash_abort(). + * + * \warning Applications should not call this function if they expect + * a specific value for the hash. Call psa_hash_verify() instead. + * Beware that comparing integrity or authenticity data such as + * hash values with a function such as \c memcmp is risky + * because the time taken by the comparison may leak information + * about the hashed data which could allow an attacker to guess + * a valid hash and thereby bypass security controls. + * + * \param[in,out] operation Active hash operation. + * \param[out] hash Buffer where the hash is to be written. + * \param hash_size Size of the \p hash buffer in bytes. + * \param[out] hash_length On success, the number of bytes + * that make up the hash value. This is always + * #PSA_HASH_SIZE(\c alg) where \c alg is the + * hash algorithm that is calculated. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p hash buffer is too small. You can determine a + * sufficient buffer size by calling #PSA_HASH_SIZE(\c alg) + * where \c alg is the hash algorithm that is calculated. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_finish(psa_hash_operation_t *operation, + uint8_t *hash, + size_t hash_size, + size_t *hash_length); + +/** Finish the calculation of the hash of a message and compare it with + * an expected value. + * + * The application must call psa_hash_setup() before calling this function. + * This function calculates the hash of the message formed by concatenating + * the inputs passed to preceding calls to psa_hash_update(). It then + * compares the calculated hash with the expected hash passed as a + * parameter to this function. + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_hash_abort(). + * + * \note Implementations shall make the best effort to ensure that the + * comparison between the actual hash and the expected hash is performed + * in constant time. + * + * \param[in,out] operation Active hash operation. + * \param[in] hash Buffer containing the expected hash value. + * \param hash_length Size of the \p hash buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected hash is identical to the actual hash of the message. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The hash of the message was calculated successfully, but it + * differs from the expected hash. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_verify(psa_hash_operation_t *operation, + const uint8_t *hash, + size_t hash_length); + +/** Abort a hash operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_hash_setup() again. + * + * You may call this function any time after the operation object has + * been initialized by one of the methods described in #psa_hash_operation_t. + * + * In particular, calling psa_hash_abort() after the operation has been + * terminated by a call to psa_hash_abort(), psa_hash_finish() or + * psa_hash_verify() is safe and has no effect. + * + * \param[in,out] operation Initialized hash operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_abort(psa_hash_operation_t *operation); + +/** Clone a hash operation. + * + * This function copies the state of an ongoing hash operation to + * a new operation object. In other words, this function is equivalent + * to calling psa_hash_setup() on \p target_operation with the same + * algorithm that \p source_operation was set up for, then + * psa_hash_update() on \p target_operation with the same input that + * that was passed to \p source_operation. After this function returns, the + * two objects are independent, i.e. subsequent calls involving one of + * the objects do not affect the other object. + * + * \param[in] source_operation The active hash operation to clone. + * \param[in,out] target_operation The operation object to set up. + * It must be initialized but not active. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_BAD_STATE + * The \p source_operation state is not valid (it must be active). + * \retval #PSA_ERROR_BAD_STATE + * The \p target_operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation, + psa_hash_operation_t *target_operation); + +/**@}*/ + +/** \defgroup MAC Message authentication codes + * @{ + */ + +/** Calculate the MAC (message authentication code) of a message. + * + * \note To verify the MAC of a message against an + * expected value, use psa_mac_verify() instead. + * Beware that comparing integrity or authenticity data such as + * MAC values with a function such as \c memcmp is risky + * because the time taken by the comparison may leak information + * about the MAC value which could allow an attacker to guess + * a valid MAC and thereby bypass security controls. + * + * \param handle Handle to the key to use for the operation. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * \param[in] input Buffer containing the input message. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] mac Buffer where the MAC value is to be written. + * \param mac_size Size of the \p mac buffer in bytes. + * \param[out] mac_length On success, the number of bytes + * that make up the MAC value. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p mac_size is too small + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_compute(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *mac, + size_t mac_size, + size_t *mac_length); + +/** Calculate the MAC of a message and compare it with a reference value. + * + * \param handle Handle to the key to use for the operation. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * \param[in] input Buffer containing the input message. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] mac Buffer containing the expected MAC value. + * \param mac_length Size of the \p mac buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected MAC is identical to the actual MAC of the input. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The MAC of the message was calculated successfully, but it + * differs from the expected value. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_verify(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *mac, + size_t mac_length); + +/** The type of the state data structure for multipart MAC operations. + * + * Before calling any function on a MAC operation object, the application must + * initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_mac_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_mac_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_MAC_OPERATION_INIT, + * for example: + * \code + * psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_mac_operation_init() + * to the structure, for example: + * \code + * psa_mac_operation_t operation; + * operation = psa_mac_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure except + * as directed by the documentation of a specific implementation. */ +typedef struct psa_mac_operation_s psa_mac_operation_t; + +/** \def PSA_MAC_OPERATION_INIT + * + * This macro returns a suitable initializer for a MAC operation object of type + * #psa_mac_operation_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_MAC_OPERATION_INIT {0} +#endif + +/** Return an initial value for a MAC operation object. + */ +static psa_mac_operation_t psa_mac_operation_init(void); + +/** Set up a multipart MAC calculation operation. + * + * This function sets up the calculation of the MAC + * (message authentication code) of a byte string. + * To verify the MAC of a message against an + * expected value, use psa_mac_verify_setup() instead. + * + * The sequence of operations to calculate a MAC is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT. + * -# Call psa_mac_sign_setup() to specify the algorithm and key. + * -# Call psa_mac_update() zero, one or more times, passing a fragment + * of the message each time. The MAC that is calculated is the MAC + * of the concatenation of these messages in order. + * -# At the end of the message, call psa_mac_sign_finish() to finish + * calculating the MAC value and retrieve it. + * + * If an error occurs at any step after a call to psa_mac_sign_setup(), the + * operation will need to be reset by a call to psa_mac_abort(). The + * application may call psa_mac_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_mac_sign_setup(), the application must + * eventually terminate the operation through one of the following methods: + * - A successful call to psa_mac_sign_finish(). + * - A call to psa_mac_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_mac_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Set up a multipart MAC verification operation. + * + * This function sets up the verification of the MAC + * (message authentication code) of a byte string against an expected value. + * + * The sequence of operations to verify a MAC is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT. + * -# Call psa_mac_verify_setup() to specify the algorithm and key. + * -# Call psa_mac_update() zero, one or more times, passing a fragment + * of the message each time. The MAC that is calculated is the MAC + * of the concatenation of these messages in order. + * -# At the end of the message, call psa_mac_verify_finish() to finish + * calculating the actual MAC of the message and verify it against + * the expected value. + * + * If an error occurs at any step after a call to psa_mac_verify_setup(), the + * operation will need to be reset by a call to psa_mac_abort(). The + * application may call psa_mac_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_mac_verify_setup(), the application must + * eventually terminate the operation through one of the following methods: + * - A successful call to psa_mac_verify_finish(). + * - A call to psa_mac_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_mac_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c key is not compatible with \c alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \c alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Add a message fragment to a multipart MAC operation. + * + * The application must call psa_mac_sign_setup() or psa_mac_verify_setup() + * before calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_mac_abort(). + * + * \param[in,out] operation Active MAC operation. + * \param[in] input Buffer containing the message fragment to add to + * the MAC calculation. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_update(psa_mac_operation_t *operation, + const uint8_t *input, + size_t input_length); + +/** Finish the calculation of the MAC of a message. + * + * The application must call psa_mac_sign_setup() before calling this function. + * This function calculates the MAC of the message formed by concatenating + * the inputs passed to preceding calls to psa_mac_update(). + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_mac_abort(). + * + * \warning Applications should not call this function if they expect + * a specific value for the MAC. Call psa_mac_verify_finish() instead. + * Beware that comparing integrity or authenticity data such as + * MAC values with a function such as \c memcmp is risky + * because the time taken by the comparison may leak information + * about the MAC value which could allow an attacker to guess + * a valid MAC and thereby bypass security controls. + * + * \param[in,out] operation Active MAC operation. + * \param[out] mac Buffer where the MAC value is to be written. + * \param mac_size Size of the \p mac buffer in bytes. + * \param[out] mac_length On success, the number of bytes + * that make up the MAC value. This is always + * #PSA_MAC_FINAL_SIZE(\c key_type, \c key_bits, \c alg) + * where \c key_type and \c key_bits are the type and + * bit-size respectively of the key and \c alg is the + * MAC algorithm that is calculated. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active mac sign + * operation). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p mac buffer is too small. You can determine a + * sufficient buffer size by calling PSA_MAC_FINAL_SIZE(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, + uint8_t *mac, + size_t mac_size, + size_t *mac_length); + +/** Finish the calculation of the MAC of a message and compare it with + * an expected value. + * + * The application must call psa_mac_verify_setup() before calling this function. + * This function calculates the MAC of the message formed by concatenating + * the inputs passed to preceding calls to psa_mac_update(). It then + * compares the calculated MAC with the expected MAC passed as a + * parameter to this function. + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_mac_abort(). + * + * \note Implementations shall make the best effort to ensure that the + * comparison between the actual MAC and the expected MAC is performed + * in constant time. + * + * \param[in,out] operation Active MAC operation. + * \param[in] mac Buffer containing the expected MAC value. + * \param mac_length Size of the \p mac buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected MAC is identical to the actual MAC of the message. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The MAC of the message was calculated successfully, but it + * differs from the expected MAC. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active mac verify + * operation). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation, + const uint8_t *mac, + size_t mac_length); + +/** Abort a MAC operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_mac_sign_setup() or psa_mac_verify_setup() again. + * + * You may call this function any time after the operation object has + * been initialized by one of the methods described in #psa_mac_operation_t. + * + * In particular, calling psa_mac_abort() after the operation has been + * terminated by a call to psa_mac_abort(), psa_mac_sign_finish() or + * psa_mac_verify_finish() is safe and has no effect. + * + * \param[in,out] operation Initialized MAC operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_abort(psa_mac_operation_t *operation); + +/**@}*/ + +/** \defgroup cipher Symmetric ciphers + * @{ + */ + +/** Encrypt a message using a symmetric cipher. + * + * This function encrypts a message with a random IV (initialization + * vector). Use the multipart operation interface with a + * #psa_cipher_operation_t object to provide other forms of IV. + * + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * \param[in] input Buffer containing the message to encrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the output is to be written. + * The output contains the IV followed by + * the ciphertext proper. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_encrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Decrypt a message using a symmetric cipher. + * + * This function decrypts a message encrypted with a symmetric cipher. + * + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * \param[in] input Buffer containing the message to decrypt. + * This consists of the IV followed by the + * ciphertext proper. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the plaintext is to be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_decrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** The type of the state data structure for multipart cipher operations. + * + * Before calling any function on a cipher operation object, the application + * must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_cipher_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_cipher_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_CIPHER_OPERATION_INIT, + * for example: + * \code + * psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_cipher_operation_init() + * to the structure, for example: + * \code + * psa_cipher_operation_t operation; + * operation = psa_cipher_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure except + * as directed by the documentation of a specific implementation. */ +typedef struct psa_cipher_operation_s psa_cipher_operation_t; + +/** \def PSA_CIPHER_OPERATION_INIT + * + * This macro returns a suitable initializer for a cipher operation object of + * type #psa_cipher_operation_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_CIPHER_OPERATION_INIT {0} +#endif + +/** Return an initial value for a cipher operation object. + */ +static psa_cipher_operation_t psa_cipher_operation_init(void); + +/** Set the key for a multipart symmetric encryption operation. + * + * The sequence of operations to encrypt a message with a symmetric cipher + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_cipher_operation_t, e.g. + * #PSA_CIPHER_OPERATION_INIT. + * -# Call psa_cipher_encrypt_setup() to specify the algorithm and key. + * -# Call either psa_cipher_generate_iv() or psa_cipher_set_iv() to + * generate or set the IV (initialization vector). You should use + * psa_cipher_generate_iv() unless the protocol you are implementing + * requires a specific IV value. + * -# Call psa_cipher_update() zero, one or more times, passing a fragment + * of the message each time. + * -# Call psa_cipher_finish(). + * + * If an error occurs at any step after a call to psa_cipher_encrypt_setup(), + * the operation will need to be reset by a call to psa_cipher_abort(). The + * application may call psa_cipher_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_cipher_encrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_cipher_finish(). + * - A call to psa_cipher_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_cipher_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Set the key for a multipart symmetric decryption operation. + * + * The sequence of operations to decrypt a message with a symmetric cipher + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_cipher_operation_t, e.g. + * #PSA_CIPHER_OPERATION_INIT. + * -# Call psa_cipher_decrypt_setup() to specify the algorithm and key. + * -# Call psa_cipher_set_iv() with the IV (initialization vector) for the + * decryption. If the IV is prepended to the ciphertext, you can call + * psa_cipher_update() on a buffer containing the IV followed by the + * beginning of the message. + * -# Call psa_cipher_update() zero, one or more times, passing a fragment + * of the message each time. + * -# Call psa_cipher_finish(). + * + * If an error occurs at any step after a call to psa_cipher_decrypt_setup(), + * the operation will need to be reset by a call to psa_cipher_abort(). The + * application may call psa_cipher_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_cipher_decrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_cipher_finish(). + * - A call to psa_cipher_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_cipher_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Generate an IV for a symmetric encryption operation. + * + * This function generates a random IV (initialization vector), nonce + * or initial counter value for the encryption operation as appropriate + * for the chosen algorithm, key type and key size. + * + * The application must call psa_cipher_encrypt_setup() before + * calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \param[in,out] operation Active cipher operation. + * \param[out] iv Buffer where the generated IV is to be written. + * \param iv_size Size of the \p iv buffer in bytes. + * \param[out] iv_length On success, the number of bytes of the + * generated IV. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with no IV set). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p iv buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation, + uint8_t *iv, + size_t iv_size, + size_t *iv_length); + +/** Set the IV for a symmetric encryption or decryption operation. + * + * This function sets the IV (initialization vector), nonce + * or initial counter value for the encryption or decryption operation. + * + * The application must call psa_cipher_encrypt_setup() before + * calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \note When encrypting, applications should use psa_cipher_generate_iv() + * instead of this function, unless implementing a protocol that requires + * a non-random IV. + * + * \param[in,out] operation Active cipher operation. + * \param[in] iv Buffer containing the IV to use. + * \param iv_length Size of the IV in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active cipher + * encrypt operation, with no IV set). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size of \p iv is not acceptable for the chosen algorithm, + * or the chosen algorithm does not use an IV. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, + const uint8_t *iv, + size_t iv_length); + +/** Encrypt or decrypt a message fragment in an active cipher operation. + * + * Before calling this function, you must: + * 1. Call either psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup(). + * The choice of setup function determines whether this function + * encrypts or decrypts its input. + * 2. If the algorithm requires an IV, call psa_cipher_generate_iv() + * (recommended when encrypting) or psa_cipher_set_iv(). + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \param[in,out] operation Active cipher operation. + * \param[in] input Buffer containing the message fragment to + * encrypt or decrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the output is to be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with an IV set + * if required for the algorithm). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Finish encrypting or decrypting a message in a cipher operation. + * + * The application must call psa_cipher_encrypt_setup() or + * psa_cipher_decrypt_setup() before calling this function. The choice + * of setup function determines whether this function encrypts or + * decrypts its input. + * + * This function finishes the encryption or decryption of the message + * formed by concatenating the inputs passed to preceding calls to + * psa_cipher_update(). + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \param[in,out] operation Active cipher operation. + * \param[out] output Buffer where the output is to be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total input size passed to this operation is not valid for + * this particular algorithm. For example, the algorithm is a based + * on block cipher and requires a whole number of blocks, but the + * total input size is not a multiple of the block size. + * \retval #PSA_ERROR_INVALID_PADDING + * This is a decryption operation for an algorithm that includes + * padding, and the ciphertext does not contain valid padding. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with an IV set + * if required for the algorithm). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Abort a cipher operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup() again. + * + * You may call this function any time after the operation object has + * been initialized as described in #psa_cipher_operation_t. + * + * In particular, calling psa_cipher_abort() after the operation has been + * terminated by a call to psa_cipher_abort() or psa_cipher_finish() + * is safe and has no effect. + * + * \param[in,out] operation Initialized cipher operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation); + +/**@}*/ + +/** \defgroup aead Authenticated encryption with associated data (AEAD) + * @{ + */ + +/** Process an authenticated encryption operation. + * + * \param handle Handle to the key to use for the operation. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param[in] nonce Nonce or IV to use. + * \param nonce_length Size of the \p nonce buffer in bytes. + * \param[in] additional_data Additional data that will be authenticated + * but not encrypted. + * \param additional_data_length Size of \p additional_data in bytes. + * \param[in] plaintext Data that will be authenticated and + * encrypted. + * \param plaintext_length Size of \p plaintext in bytes. + * \param[out] ciphertext Output buffer for the authenticated and + * encrypted data. The additional data is not + * part of this output. For algorithms where the + * encrypted data and the authentication tag + * are defined as separate outputs, the + * authentication tag is appended to the + * encrypted data. + * \param ciphertext_size Size of the \p ciphertext buffer in bytes. + * This must be at least + * #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\p alg, + * \p plaintext_length). + * \param[out] ciphertext_length On success, the size of the output + * in the \p ciphertext buffer. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not an AEAD algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p ciphertext_size is too small + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_encrypt(psa_key_handle_t handle, + 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 *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length); + +/** Process an authenticated decryption operation. + * + * \param handle Handle to the key to use for the operation. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param[in] nonce Nonce or IV to use. + * \param nonce_length Size of the \p nonce buffer in bytes. + * \param[in] additional_data Additional data that has been authenticated + * but not encrypted. + * \param additional_data_length Size of \p additional_data in bytes. + * \param[in] ciphertext Data that has been authenticated and + * encrypted. For algorithms where the + * encrypted data and the authentication tag + * are defined as separate inputs, the buffer + * must contain the encrypted data followed + * by the authentication tag. + * \param ciphertext_length Size of \p ciphertext in bytes. + * \param[out] plaintext Output buffer for the decrypted data. + * \param plaintext_size Size of the \p plaintext buffer in bytes. + * This must be at least + * #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\p alg, + * \p ciphertext_length). + * \param[out] plaintext_length On success, the size of the output + * in the \p plaintext buffer. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The ciphertext is not authentic. + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not an AEAD algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p plaintext_size or \p nonce_length is too small + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_decrypt(psa_key_handle_t handle, + 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 *ciphertext, + size_t ciphertext_length, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length); + +/** The type of the state data structure for multipart AEAD operations. + * + * Before calling any function on an AEAD operation object, the application + * must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_aead_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_aead_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_AEAD_OPERATION_INIT, + * for example: + * \code + * psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_aead_operation_init() + * to the structure, for example: + * \code + * psa_aead_operation_t operation; + * operation = psa_aead_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure except + * as directed by the documentation of a specific implementation. */ +typedef struct psa_aead_operation_s psa_aead_operation_t; + +/** \def PSA_AEAD_OPERATION_INIT + * + * This macro returns a suitable initializer for an AEAD operation object of + * type #psa_aead_operation_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_AEAD_OPERATION_INIT {0} +#endif + +/** Return an initial value for an AEAD operation object. + */ +static psa_aead_operation_t psa_aead_operation_init(void); + +/** Set the key for a multipart authenticated encryption operation. + * + * The sequence of operations to encrypt a message with authentication + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_aead_operation_t, e.g. + * #PSA_AEAD_OPERATION_INIT. + * -# Call psa_aead_encrypt_setup() to specify the algorithm and key. + * -# If needed, call psa_aead_set_lengths() to specify the length of the + * inputs to the subsequent calls to psa_aead_update_ad() and + * psa_aead_update(). See the documentation of psa_aead_set_lengths() + * for details. + * -# Call either psa_aead_generate_nonce() or psa_aead_set_nonce() to + * generate or set the nonce. You should use + * psa_aead_generate_nonce() unless the protocol you are implementing + * requires a specific nonce value. + * -# Call psa_aead_update_ad() zero, one or more times, passing a fragment + * of the non-encrypted additional authenticated data each time. + * -# Call psa_aead_update() zero, one or more times, passing a fragment + * of the message to encrypt each time. + * -# Call psa_aead_finish(). + * + * If an error occurs at any step after a call to psa_aead_encrypt_setup(), + * the operation will need to be reset by a call to psa_aead_abort(). The + * application may call psa_aead_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_aead_encrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_aead_finish(). + * - A call to psa_aead_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_aead_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not an AEAD algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Set the key for a multipart authenticated decryption operation. + * + * The sequence of operations to decrypt a message with authentication + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_aead_operation_t, e.g. + * #PSA_AEAD_OPERATION_INIT. + * -# Call psa_aead_decrypt_setup() to specify the algorithm and key. + * -# If needed, call psa_aead_set_lengths() to specify the length of the + * inputs to the subsequent calls to psa_aead_update_ad() and + * psa_aead_update(). See the documentation of psa_aead_set_lengths() + * for details. + * -# Call psa_aead_set_nonce() with the nonce for the decryption. + * -# Call psa_aead_update_ad() zero, one or more times, passing a fragment + * of the non-encrypted additional authenticated data each time. + * -# Call psa_aead_update() zero, one or more times, passing a fragment + * of the ciphertext to decrypt each time. + * -# Call psa_aead_verify(). + * + * If an error occurs at any step after a call to psa_aead_decrypt_setup(), + * the operation will need to be reset by a call to psa_aead_abort(). The + * application may call psa_aead_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_aead_decrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_aead_verify(). + * - A call to psa_aead_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_aead_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not an AEAD algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Generate a random nonce for an authenticated encryption operation. + * + * This function generates a random nonce for the authenticated encryption + * operation with an appropriate size for the chosen algorithm, key type + * and key size. + * + * The application must call psa_aead_encrypt_setup() before + * calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \param[in,out] operation Active AEAD operation. + * \param[out] nonce Buffer where the generated nonce is to be + * written. + * \param nonce_size Size of the \p nonce buffer in bytes. + * \param[out] nonce_length On success, the number of bytes of the + * generated nonce. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active aead encrypt + operation, with no nonce set). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p nonce buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation, + uint8_t *nonce, + size_t nonce_size, + size_t *nonce_length); + +/** Set the nonce for an authenticated encryption or decryption operation. + * + * This function sets the nonce for the authenticated + * encryption or decryption operation. + * + * The application must call psa_aead_encrypt_setup() or + * psa_aead_decrypt_setup() before calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \note When encrypting, applications should use psa_aead_generate_nonce() + * instead of this function, unless implementing a protocol that requires + * a non-random IV. + * + * \param[in,out] operation Active AEAD operation. + * \param[in] nonce Buffer containing the nonce to use. + * \param nonce_length Size of the nonce in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with no nonce + * set). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size of \p nonce is not acceptable for the chosen algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation, + const uint8_t *nonce, + size_t nonce_length); + +/** Declare the lengths of the message and additional data for AEAD. + * + * The application must call this function before calling + * psa_aead_update_ad() or psa_aead_update() if the algorithm for + * the operation requires it. If the algorithm does not require it, + * calling this function is optional, but if this function is called + * then the implementation must enforce the lengths. + * + * You may call this function before or after setting the nonce with + * psa_aead_set_nonce() or psa_aead_generate_nonce(). + * + * - For #PSA_ALG_CCM, calling this function is required. + * - For the other AEAD algorithms defined in this specification, calling + * this function is not required. + * - For vendor-defined algorithm, refer to the vendor documentation. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \param[in,out] operation Active AEAD operation. + * \param ad_length Size of the non-encrypted additional + * authenticated data in bytes. + * \param plaintext_length Size of the plaintext to encrypt in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, and + * psa_aead_update_ad() and psa_aead_update() must not have been + * called yet). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * At least one of the lengths is not acceptable for the chosen + * algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation, + size_t ad_length, + size_t plaintext_length); + +/** Pass additional data to an active AEAD operation. + * + * Additional data is authenticated, but not encrypted. + * + * You may call this function multiple times to pass successive fragments + * of the additional data. You may not call this function after passing + * data to encrypt or decrypt with psa_aead_update(). + * + * Before calling this function, you must: + * 1. Call either psa_aead_encrypt_setup() or psa_aead_decrypt_setup(). + * 2. Set the nonce with psa_aead_generate_nonce() or psa_aead_set_nonce(). + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \warning When decrypting, until psa_aead_verify() has returned #PSA_SUCCESS, + * there is no guarantee that the input is valid. Therefore, until + * you have called psa_aead_verify() and it has returned #PSA_SUCCESS, + * treat the input as untrusted and prepare to undo any action that + * depends on the input if psa_aead_verify() returns an error status. + * + * \param[in,out] operation Active AEAD operation. + * \param[in] input Buffer containing the fragment of + * additional data. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, have a nonce + * set, have lengths set if required by the algorithm, and + * psa_aead_update() must not have been called yet). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total input length overflows the additional data length that + * was previously specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length); + +/** Encrypt or decrypt a message fragment in an active AEAD operation. + * + * Before calling this function, you must: + * 1. Call either psa_aead_encrypt_setup() or psa_aead_decrypt_setup(). + * The choice of setup function determines whether this function + * encrypts or decrypts its input. + * 2. Set the nonce with psa_aead_generate_nonce() or psa_aead_set_nonce(). + * 3. Call psa_aead_update_ad() to pass all the additional data. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \warning When decrypting, until psa_aead_verify() has returned #PSA_SUCCESS, + * there is no guarantee that the input is valid. Therefore, until + * you have called psa_aead_verify() and it has returned #PSA_SUCCESS: + * - Do not use the output in any way other than storing it in a + * confidential location. If you take any action that depends + * on the tentative decrypted data, this action will need to be + * undone if the input turns out not to be valid. Furthermore, + * if an adversary can observe that this action took place + * (for example through timing), they may be able to use this + * fact as an oracle to decrypt any message encrypted with the + * same key. + * - In particular, do not copy the output anywhere but to a + * memory or storage space that you have exclusive access to. + * + * This function does not require the input to be aligned to any + * particular block boundary. If the implementation can only process + * a whole block at a time, it must consume all the input provided, but + * it may delay the end of the corresponding output until a subsequent + * call to psa_aead_update(), psa_aead_finish() or psa_aead_verify() + * provides sufficient input. The amount of data that can be delayed + * in this way is bounded by #PSA_AEAD_UPDATE_OUTPUT_SIZE. + * + * \param[in,out] operation Active AEAD operation. + * \param[in] input Buffer containing the message fragment to + * encrypt or decrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the output is to be written. + * \param output_size Size of the \p output buffer in bytes. + * This must be at least + * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c alg, + * \p input_length) where \c alg is the + * algorithm that is being calculated. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, have a nonce + * set, and have lengths set if required by the algorithm). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * You can determine a sufficient buffer size by calling + * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c alg, \p input_length) + * where \c alg is the algorithm that is being calculated. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update_ad() so far is + * less than the additional data length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total input length overflows the plaintext length that + * was previously specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_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); + +/** Finish encrypting a message in an AEAD operation. + * + * The operation must have been set up with psa_aead_encrypt_setup(). + * + * This function finishes the authentication of the additional data + * formed by concatenating the inputs passed to preceding calls to + * psa_aead_update_ad() with the plaintext formed by concatenating the + * inputs passed to preceding calls to psa_aead_update(). + * + * This function has two output buffers: + * - \p ciphertext contains trailing ciphertext that was buffered from + * preceding calls to psa_aead_update(). + * - \p tag contains the authentication tag. Its length is always + * #PSA_AEAD_TAG_LENGTH(\c alg) where \c alg is the AEAD algorithm + * that the operation performs. + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \param[in,out] operation Active AEAD operation. + * \param[out] ciphertext Buffer where the last part of the ciphertext + * is to be written. + * \param ciphertext_size Size of the \p ciphertext buffer in bytes. + * This must be at least + * #PSA_AEAD_FINISH_OUTPUT_SIZE(\c alg) where + * \c alg is the algorithm that is being + * calculated. + * \param[out] ciphertext_length On success, the number of bytes of + * returned ciphertext. + * \param[out] tag Buffer where the authentication tag is + * to be written. + * \param tag_size Size of the \p tag buffer in bytes. + * This must be at least + * #PSA_AEAD_TAG_LENGTH(\c alg) where \c alg is + * the algorithm that is being calculated. + * \param[out] tag_length On success, the number of bytes + * that make up the returned tag. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active encryption + * operation with a nonce set). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p ciphertext or \p tag buffer is too small. + * You can determine a sufficient buffer size for \p ciphertext by + * calling #PSA_AEAD_FINISH_OUTPUT_SIZE(\c alg) + * where \c alg is the algorithm that is being calculated. + * You can determine a sufficient buffer size for \p tag by + * calling #PSA_AEAD_TAG_LENGTH(\c alg). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update_ad() so far is + * less than the additional data length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update() so far is + * less than the plaintext length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_finish(psa_aead_operation_t *operation, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length, + uint8_t *tag, + size_t tag_size, + size_t *tag_length); + +/** Finish authenticating and decrypting a message in an AEAD operation. + * + * The operation must have been set up with psa_aead_decrypt_setup(). + * + * This function finishes the authenticated decryption of the message + * components: + * + * - The additional data consisting of the concatenation of the inputs + * passed to preceding calls to psa_aead_update_ad(). + * - The ciphertext consisting of the concatenation of the inputs passed to + * preceding calls to psa_aead_update(). + * - The tag passed to this function call. + * + * If the authentication tag is correct, this function outputs any remaining + * plaintext and reports success. If the authentication tag is not correct, + * this function returns #PSA_ERROR_INVALID_SIGNATURE. + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \note Implementations shall make the best effort to ensure that the + * comparison between the actual tag and the expected tag is performed + * in constant time. + * + * \param[in,out] operation Active AEAD operation. + * \param[out] plaintext Buffer where the last part of the plaintext + * is to be written. This is the remaining data + * from previous calls to psa_aead_update() + * that could not be processed until the end + * of the input. + * \param plaintext_size Size of the \p plaintext buffer in bytes. + * This must be at least + * #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c alg) where + * \c alg is the algorithm that is being + * calculated. + * \param[out] plaintext_length On success, the number of bytes of + * returned plaintext. + * \param[in] tag Buffer containing the authentication tag. + * \param tag_length Size of the \p tag buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The calculations were successful, but the authentication tag is + * not correct. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active decryption + * operation with a nonce set). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p plaintext buffer is too small. + * You can determine a sufficient buffer size for \p plaintext by + * calling #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c alg) + * where \c alg is the algorithm that is being calculated. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update_ad() so far is + * less than the additional data length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update() so far is + * less than the plaintext length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_verify(psa_aead_operation_t *operation, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length, + const uint8_t *tag, + size_t tag_length); + +/** Abort an AEAD operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_aead_encrypt_setup() or psa_aead_decrypt_setup() again. + * + * You may call this function any time after the operation object has + * been initialized as described in #psa_aead_operation_t. + * + * In particular, calling psa_aead_abort() after the operation has been + * terminated by a call to psa_aead_abort(), psa_aead_finish() or + * psa_aead_verify() is safe and has no effect. + * + * \param[in,out] operation Initialized AEAD operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_abort(psa_aead_operation_t *operation); + +/**@}*/ + +/** \defgroup asymmetric Asymmetric cryptography + * @{ + */ + +/** + * \brief Sign a hash or short message with a private key. + * + * Note that to perform a hash-and-sign signature algorithm, you must + * first calculate the hash by calling psa_hash_setup(), psa_hash_update() + * and psa_hash_finish(). Then pass the resulting hash as the \p hash + * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) + * to determine the hash algorithm to use. + * + * \param handle Handle to the key to use for the operation. + * It must be an asymmetric key pair. + * \param alg A signature algorithm that is compatible with + * the type of \p handle. + * \param[in] hash The hash or message to sign. + * \param hash_length Size of the \p hash buffer in bytes. + * \param[out] signature Buffer where the signature is to be written. + * \param signature_size Size of the \p signature buffer in bytes. + * \param[out] signature_length On success, the number of bytes + * that make up the returned signature value. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p signature buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p handle. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_sign_hash(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length); + +/** + * \brief Verify the signature a hash or short message using a public key. + * + * Note that to perform a hash-and-sign signature algorithm, you must + * first calculate the hash by calling psa_hash_setup(), psa_hash_update() + * and psa_hash_finish(). Then pass the resulting hash as the \p hash + * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) + * to determine the hash algorithm to use. + * + * \param handle Handle to the key to use for the operation. + * It must be a public key or an asymmetric key pair. + * \param alg A signature algorithm that is compatible with + * the type of \p handle. + * \param[in] hash The hash or message whose signature is to be + * verified. + * \param hash_length Size of the \p hash buffer in bytes. + * \param[in] signature Buffer containing the signature to verify. + * \param signature_length Size of the \p signature buffer in bytes. + * + * \retval #PSA_SUCCESS + * The signature is valid. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The calculation was perfomed successfully, but the passed + * signature is not a valid signature. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_verify_hash(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length); + +/** + * \brief Encrypt a short message with a public key. + * + * \param handle Handle to the key to use for the operation. + * It must be a public key or an asymmetric + * key pair. + * \param alg An asymmetric encryption algorithm that is + * compatible with the type of \p handle. + * \param[in] input The message to encrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[in] salt A salt or label, if supported by the + * encryption algorithm. + * If the algorithm does not support a + * salt, pass \c NULL. + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass \c NULL. + * + * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported. + * \param salt_length Size of the \p salt buffer in bytes. + * If \p salt is \c NULL, pass 0. + * \param[out] output Buffer where the encrypted message is to + * be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p handle. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_asymmetric_encrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** + * \brief Decrypt a short message with a private key. + * + * \param handle Handle to the key to use for the operation. + * It must be an asymmetric key pair. + * \param alg An asymmetric encryption algorithm that is + * compatible with the type of \p handle. + * \param[in] input The message to decrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[in] salt A salt or label, if supported by the + * encryption algorithm. + * If the algorithm does not support a + * salt, pass \c NULL. + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass \c NULL. + * + * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported. + * \param salt_length Size of the \p salt buffer in bytes. + * If \p salt is \c NULL, pass 0. + * \param[out] output Buffer where the decrypted message is to + * be written. + * \param output_size Size of the \c output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p handle. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_INVALID_PADDING + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_asymmetric_decrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/**@}*/ + +/** \defgroup key_derivation Key derivation and pseudorandom generation + * @{ + */ + +/** The type of the state data structure for key derivation operations. + * + * Before calling any function on a key derivation operation object, the + * application must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_key_derivation_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_key_derivation_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_KEY_DERIVATION_OPERATION_INIT, + * for example: + * \code + * psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_key_derivation_operation_init() + * to the structure, for example: + * \code + * psa_key_derivation_operation_t operation; + * operation = psa_key_derivation_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure except + * as directed by the documentation of a specific implementation. + */ +typedef struct psa_key_derivation_s psa_key_derivation_operation_t; + +/** \def PSA_KEY_DERIVATION_OPERATION_INIT + * + * This macro returns a suitable initializer for a key derivation operation + * object of type #psa_key_derivation_operation_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_KEY_DERIVATION_OPERATION_INIT {0} +#endif + +/** Return an initial value for a key derivation operation object. + */ +static psa_key_derivation_operation_t psa_key_derivation_operation_init(void); + +/** Set up a key derivation operation. + * + * A key derivation algorithm takes some inputs and uses them to generate + * a byte stream in a deterministic way. + * This byte stream can be used to produce keys and other + * cryptographic material. + * + * To derive a key: + * -# Start with an initialized object of type #psa_key_derivation_operation_t. + * -# Call psa_key_derivation_setup() to select the algorithm. + * -# Provide the inputs for the key derivation by calling + * psa_key_derivation_input_bytes() or psa_key_derivation_input_key() + * as appropriate. Which inputs are needed, in what order, and whether + * they may be keys and if so of what type depends on the algorithm. + * -# Optionally set the operation's maximum capacity with + * psa_key_derivation_set_capacity(). You may do this before, in the middle + * of or after providing inputs. For some algorithms, this step is mandatory + * because the output depends on the maximum capacity. + * -# To derive a key, call psa_key_derivation_output_key(). + * To derive a byte string for a different purpose, call + * psa_key_derivation_output_bytes(). + * Successive calls to these functions use successive output bytes + * calculated by the key derivation algorithm. + * -# Clean up the key derivation operation object with + * psa_key_derivation_abort(). + * + * If this function returns an error, the key derivation operation object is + * not changed. + * + * If an error occurs at any step after a call to psa_key_derivation_setup(), + * the operation will need to be reset by a call to psa_key_derivation_abort(). + * + * Implementations must reject an attempt to derive a key of size 0. + * + * \param[in,out] operation The key derivation operation object + * to set up. It must + * have been initialized but not set up yet. + * \param alg The key derivation algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_KEY_DERIVATION(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c alg is not a key derivation algorithm. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \c alg is not supported or is not a key derivation algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_setup( + psa_key_derivation_operation_t *operation, + psa_algorithm_t alg); + +/** Retrieve the current capacity of a key derivation operation. + * + * The capacity of a key derivation is the maximum number of bytes that it can + * return. When you get *N* bytes of output from a key derivation operation, + * this reduces its capacity by *N*. + * + * \param[in] operation The operation to query. + * \param[out] capacity On success, the capacity of the operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_get_capacity( + const psa_key_derivation_operation_t *operation, + size_t *capacity); + +/** Set the maximum capacity of a key derivation operation. + * + * The capacity of a key derivation operation is the maximum number of bytes + * that the key derivation operation can return from this point onwards. + * + * \param[in,out] operation The key derivation operation object to modify. + * \param capacity The new capacity of the operation. + * It must be less or equal to the operation's + * current capacity. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p capacity is larger than the operation's current capacity. + * In this case, the operation object remains valid and its capacity + * remains unchanged. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_set_capacity( + psa_key_derivation_operation_t *operation, + size_t capacity); + +/** Use the maximum possible capacity for a key derivation operation. + * + * Use this value as the capacity argument when setting up a key derivation + * to indicate that the operation should have the maximum possible capacity. + * The value of the maximum possible capacity depends on the key derivation + * algorithm. + */ +#define PSA_KEY_DERIVATION_UNLIMITED_CAPACITY ((size_t)(-1)) + +/** Provide an input for key derivation or key agreement. + * + * Which inputs are required and in what order depends on the algorithm. + * Refer to the documentation of each key derivation or key agreement + * algorithm for information. + * + * This function passes direct inputs, which is usually correct for + * non-secret inputs. To pass a secret input, which should be in a key + * object, call psa_key_derivation_input_key() instead of this function. + * Refer to the documentation of individual step types + * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t) + * for more information. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() and must not + * have produced any output yet. + * \param step Which step the input data is for. + * \param[in] data Input data to use. + * \param data_length Size of the \p data buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step is not compatible with the operation's algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step does not allow direct inputs. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this input \p step. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_input_bytes( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length); + +/** Provide an input for key derivation in the form of a key. + * + * Which inputs are required and in what order depends on the algorithm. + * Refer to the documentation of each key derivation or key agreement + * algorithm for information. + * + * This function obtains input from a key object, which is usually correct for + * secret inputs or for non-secret personalization strings kept in the key + * store. To pass a non-secret parameter which is not in the key store, + * call psa_key_derivation_input_bytes() instead of this function. + * Refer to the documentation of individual step types + * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t) + * for more information. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() and must not + * have produced any output yet. + * \param step Which step the input data is for. + * \param handle Handle to the key. It must have an + * appropriate type for \p step and must + * allow the usage #PSA_KEY_USAGE_DERIVE. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step is not compatible with the operation's algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step does not allow key inputs of the given type + * or does not allow key inputs at all. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this input \p step. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_input_key( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_handle_t handle); + +/** Perform a key agreement and use the shared secret as input to a key + * derivation. + * + * A key agreement algorithm takes two inputs: a private key \p private_key + * a public key \p peer_key. + * The result of this function is passed as input to a key derivation. + * The output of this key derivation can be extracted by reading from the + * resulting operation to produce keys and other cryptographic material. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() with a + * key agreement and derivation algorithm + * \c alg (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_KEY_AGREEMENT(\c alg) is true + * and #PSA_ALG_IS_RAW_KEY_AGREEMENT(\c alg) + * is false). + * The operation must be ready for an + * input of the type given by \p step. + * \param step Which step the input data is for. + * \param private_key Handle to the private key to use. + * \param[in] peer_key Public key of the peer. The peer key must be in the + * same format that psa_import_key() accepts for the + * public key type corresponding to the type of + * private_key. That is, this function performs the + * equivalent of + * #psa_import_key(..., + * `peer_key`, `peer_key_length`) where + * with key attributes indicating the public key + * type corresponding to the type of `private_key`. + * For example, for EC keys, this means that peer_key + * is interpreted as a point on the curve that the + * private key is on. The standard formats for public + * keys are documented in the documentation of + * psa_export_public_key(). + * \param peer_key_length Size of \p peer_key in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this key agreement \p step. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c private_key is not compatible with \c alg, + * or \p peer_key is not valid for \c alg or not compatible with + * \c private_key. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \c alg is not supported or is not a key derivation algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step does not allow an input resulting from a key agreement. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_key_agreement( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_handle_t private_key, + const uint8_t *peer_key, + size_t peer_key_length); + +/** Read some data from a key derivation operation. + * + * This function calculates output bytes from a key derivation algorithm and + * return those bytes. + * If you view the key derivation's output as a stream of bytes, this + * function destructively reads the requested number of bytes from the + * stream. + * The operation's capacity decreases by the number of bytes read. + * + * If this function returns an error status other than + * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to read from. + * \param[out] output Buffer where the output will be written. + * \param output_length Number of bytes to output. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INSUFFICIENT_DATA + * The operation's capacity was less than + * \p output_length bytes. Note that in this case, + * no output is written to the output buffer. + * The operation's capacity is set to 0, thus + * subsequent calls to this function will not + * succeed, even with a smaller output buffer. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active and completed + * all required input steps). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_output_bytes( + psa_key_derivation_operation_t *operation, + uint8_t *output, + size_t output_length); + +/** Derive a key from an ongoing key derivation operation. + * + * This function calculates output bytes from a key derivation algorithm + * and uses those bytes to generate a key deterministically. + * The key's location, usage policy, type and size are taken from + * \p attributes. + * + * If you view the key derivation's output as a stream of bytes, this + * function destructively reads as many bytes as required from the + * stream. + * The operation's capacity decreases by the number of bytes read. + * + * If this function returns an error status other than + * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * How much output is produced and consumed from the operation, and how + * the key is derived, depends on the key type: + * + * - For key types for which the key is an arbitrary sequence of bytes + * of a given size, this function is functionally equivalent to + * calling #psa_key_derivation_output_bytes + * and passing the resulting output to #psa_import_key. + * However, this function has a security benefit: + * if the implementation provides an isolation boundary then + * the key material is not exposed outside the isolation boundary. + * As a consequence, for these key types, this function always consumes + * exactly (\p bits / 8) bytes from the operation. + * The following key types defined in this specification follow this scheme: + * + * - #PSA_KEY_TYPE_AES; + * - #PSA_KEY_TYPE_ARC4; + * - #PSA_KEY_TYPE_CAMELLIA; + * - #PSA_KEY_TYPE_DERIVE; + * - #PSA_KEY_TYPE_HMAC. + * + * - For ECC keys on a Montgomery elliptic curve + * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a + * Montgomery curve), this function always draws a byte string whose + * length is determined by the curve, and sets the mandatory bits + * accordingly. That is: + * + * - Curve25519 (#PSA_ECC_CURVE_MONTGOMERY, 255 bits): draw a 32-byte + * string and process it as specified in RFC 7748 §5. + * - Curve448 (#PSA_ECC_CURVE_MONTGOMERY, 448 bits): draw a 56-byte + * string and process it as specified in RFC 7748 §5. + * + * - For key types for which the key is represented by a single sequence of + * \p bits bits with constraints as to which bit sequences are acceptable, + * this function draws a byte string of length (\p bits / 8) bytes rounded + * up to the nearest whole number of bytes. If the resulting byte string + * is acceptable, it becomes the key, otherwise the drawn bytes are discarded. + * This process is repeated until an acceptable byte string is drawn. + * The byte string drawn from the operation is interpreted as specified + * for the output produced by psa_export_key(). + * The following key types defined in this specification follow this scheme: + * + * - #PSA_KEY_TYPE_DES. + * Force-set the parity bits, but discard forbidden weak keys. + * For 2-key and 3-key triple-DES, the three keys are generated + * successively (for example, for 3-key triple-DES, + * if the first 8 bytes specify a weak key and the next 8 bytes do not, + * discard the first 8 bytes, use the next 8 bytes as the first key, + * and continue reading output from the operation to derive the other + * two keys). + * - Finite-field Diffie-Hellman keys (#PSA_KEY_TYPE_DH_KEY_PAIR(\c group) + * where \c group designates any Diffie-Hellman group) and + * ECC keys on a Weierstrass elliptic curve + * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a + * Weierstrass curve). + * For these key types, interpret the byte string as integer + * in big-endian order. Discard it if it is not in the range + * [0, *N* - 2] where *N* is the boundary of the private key domain + * (the prime *p* for Diffie-Hellman, the subprime *q* for DSA, + * or the order of the curve's base point for ECC). + * Add 1 to the resulting integer and use this as the private key *x*. + * This method allows compliance to NIST standards, specifically + * the methods titled "key-pair generation by testing candidates" + * in NIST SP 800-56A §5.6.1.1.4 for Diffie-Hellman, + * in FIPS 186-4 §B.1.2 for DSA, and + * in NIST SP 800-56A §5.6.1.2.2 or + * FIPS 186-4 §B.4.2 for elliptic curve keys. + * + * - For other key types, including #PSA_KEY_TYPE_RSA_KEY_PAIR, + * the way in which the operation output is consumed is + * implementation-defined. + * + * In all cases, the data that is read is discarded from the operation. + * The operation's capacity is decreased by the number of bytes read. + * + * For algorithms that take an input step #PSA_KEY_DERIVATION_INPUT_SECRET, + * the input to that step must be provided with psa_key_derivation_input_key(). + * Future versions of this specification may include additional restrictions + * on the derived key based on the attributes and strength of the secret key. + * + * \param[in] attributes The attributes for the new key. + * \param[in,out] operation The key derivation operation object to read from. + * \param[out] handle On success, a handle to the newly created key. + * \c 0 on failure. + * + * \retval #PSA_SUCCESS + * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_INSUFFICIENT_DATA + * There was not enough data to create the desired key. + * Note that in this case, no output is written to the output buffer. + * The operation's capacity is set to 0, thus subsequent calls to + * this function will not succeed, even with a smaller output buffer. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The key type or key size is not supported, either by the + * implementation in general or in this particular location. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The provided key attributes are not valid for the operation. + * \retval #PSA_ERROR_NOT_PERMITTED + * The #PSA_KEY_DERIVATION_INPUT_SECRET input was not provided through + * a key. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active and completed + * all required input steps). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_output_key( + const psa_key_attributes_t *attributes, + psa_key_derivation_operation_t *operation, + psa_key_handle_t *handle); + +/** Abort a key derivation operation. + * + * Aborting an operation frees all associated resources except for the \c + * operation structure itself. Once aborted, the operation object can be reused + * for another operation by calling psa_key_derivation_setup() again. + * + * This function may be called at any time after the operation + * object has been initialized as described in #psa_key_derivation_operation_t. + * + * In particular, it is valid to call psa_key_derivation_abort() twice, or to + * call psa_key_derivation_abort() on an operation that has not been set up. + * + * \param[in,out] operation The operation to abort. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_abort( + psa_key_derivation_operation_t *operation); + +/** Perform a key agreement and return the raw shared secret. + * + * \warning The raw result of a key agreement algorithm such as finite-field + * Diffie-Hellman or elliptic curve Diffie-Hellman has biases and should + * not be used directly as key material. It should instead be passed as + * input to a key derivation algorithm. To chain a key agreement with + * a key derivation, use psa_key_derivation_key_agreement() and other + * functions from the key derivation interface. + * + * \param alg The key agreement algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_RAW_KEY_AGREEMENT(\p alg) + * is true). + * \param private_key Handle to the private key to use. + * \param[in] peer_key Public key of the peer. It must be + * in the same format that psa_import_key() + * accepts. The standard formats for public + * keys are documented in the documentation + * of psa_export_public_key(). + * \param peer_key_length Size of \p peer_key in bytes. + * \param[out] output Buffer where the decrypted message is to + * be written. + * \param output_size Size of the \c output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p alg is not a key agreement algorithm + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p private_key is not compatible with \p alg, + * or \p peer_key is not valid for \p alg or not compatible with + * \p private_key. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p output_size is too small + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not a supported key agreement algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, + psa_key_handle_t private_key, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/**@}*/ + +/** \defgroup random Random generation + * @{ + */ + +/** + * \brief Generate random bytes. + * + * \warning This function **can** fail! Callers MUST check the return status + * and MUST NOT use the content of the output buffer if the return + * status is not #PSA_SUCCESS. + * + * \note To generate a key, use psa_generate_key() instead. + * + * \param[out] output Output buffer for the generated data. + * \param output_size Number of bytes to generate and output. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_generate_random(uint8_t *output, + size_t output_size); + +/** + * \brief Generate a key or key pair. + * + * The key is generated randomly. + * Its location, usage policy, type and size are taken from \p attributes. + * + * Implementations must reject an attempt to generate a key of size 0. + * + * The following type-specific considerations apply: + * - For RSA keys (#PSA_KEY_TYPE_RSA_KEY_PAIR), + * the public exponent is 65537. + * The modulus is a product of two probabilistic primes + * between 2^{n-1} and 2^n where n is the bit size specified in the + * attributes. + * + * \param[in] attributes The attributes for the new key. + * \param[out] handle On success, a handle to the newly created key. + * \c 0 on failure. + * + * \retval #PSA_SUCCESS + * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, + psa_key_handle_t *handle); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +/* The file "crypto_sizes.h" contains definitions for size calculation + * macros whose definitions are implementation-specific. */ +#include "crypto_sizes.h" + +/* The file "crypto_struct.h" contains definitions for + * implementation-specific structs that are declared above. */ +#include "crypto_struct.h" + +/* The file "crypto_extra.h" contains vendor-specific definitions. This + * can include vendor-defined algorithms, extra functions, etc. */ +#include "crypto_extra.h" + +#endif /* PSA_CRYPTO_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_accel_driver.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_accel_driver.h new file mode 100644 index 0000000..4a540f0 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_accel_driver.h @@ -0,0 +1,823 @@ +/** + * \file psa/crypto_accel_driver.h + * \brief PSA cryptography accelerator driver module + * + * This header declares types and function signatures for cryptography + * drivers that access key material directly. This is meant for + * on-chip cryptography accelerators. + * + * This file is part of the PSA Crypto Driver Model, containing functions for + * driver developers to implement to enable hardware to be called in a + * standardized way by a PSA Cryptographic API implementation. The functions + * comprising the driver model, which driver authors implement, are not + * intended to be called by application developers. + */ + +/* + * Copyright (C) 2018, ARM Limited, 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 PSA_CRYPTO_ACCEL_DRIVER_H +#define PSA_CRYPTO_ACCEL_DRIVER_H + +#include "crypto_driver_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup driver_digest Hardware-Accelerated Message Digests + * + * Generation and authentication of Message Digests (aka hashes) must be done + * in parts using the following sequence: + * - `psa_drv_hash_setup_t` + * - `psa_drv_hash_update_t` + * - `psa_drv_hash_update_t` + * - ... + * - `psa_drv_hash_finish_t` + * + * If a previously started Message Digest operation needs to be terminated + * before the `psa_drv_hash_finish_t` operation is complete, it should be aborted + * by the `psa_drv_hash_abort_t`. Failure to do so may result in allocated + * resources not being freed or in other undefined behavior. + */ +/**@{*/ + +/** \brief The hardware-specific hash context structure + * + * The contents of this structure are implementation dependent and are + * therefore not described here + */ +typedef struct psa_drv_hash_context_s psa_drv_hash_context_t; + +/** \brief The function prototype for the start operation of a hash (message + * digest) operation + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_hash__setup + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying hash function + * + * \param[in,out] p_context A structure that will contain the + * hardware-specific hash context + * + * \retval PSA_SUCCESS Success. + */ +typedef psa_status_t (*psa_drv_hash_setup_t)(psa_drv_hash_context_t *p_context); + +/** \brief The function prototype for the update operation of a hash (message + * digest) operation + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_hash__update + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying algorithm + * + * \param[in,out] p_context A hardware-specific structure for the + * previously-established hash operation to be + * continued + * \param[in] p_input A buffer containing the message to be appended + * to the hash operation + * \param[in] input_length The size in bytes of the input message buffer + */ +typedef psa_status_t (*psa_drv_hash_update_t)(psa_drv_hash_context_t *p_context, + const uint8_t *p_input, + size_t input_length); + +/** \brief The function prototype for the finish operation of a hash (message + * digest) operation + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_hash__finish + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying algorithm + * + * \param[in,out] p_context A hardware-specific structure for the + * previously started hash operation to be + * fiinished + * \param[out] p_output A buffer where the generated digest will be + * placed + * \param[in] output_size The size in bytes of the buffer that has been + * allocated for the `p_output` buffer + * \param[out] p_output_length The number of bytes placed in `p_output` after + * success + * + * \retval PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_hash_finish_t)(psa_drv_hash_context_t *p_context, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** \brief The function prototype for the abort operation of a hash (message + * digest) operation + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_hash__abort + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying algorithm + * + * \param[in,out] p_context A hardware-specific structure for the previously + * started hash operation to be aborted + */ +typedef void (*psa_drv_hash_abort_t)(psa_drv_hash_context_t *p_context); + +/**@}*/ + +/** \defgroup accel_mac Hardware-Accelerated Message Authentication Code + * Generation and authentication of Message Authentication Codes (MACs) using + * cryptographic accelerators can be done either as a single function call (via the + * `psa_drv_accel_mac_generate_t` or `psa_drv_accel_mac_verify_t` + * functions), or in parts using the following sequence: + * - `psa_drv_accel_mac_setup_t` + * - `psa_drv_accel_mac_update_t` + * - `psa_drv_accel_mac_update_t` + * - ... + * - `psa_drv_accel_mac_finish_t` or `psa_drv_accel_mac_finish_verify_t` + * + * If a previously started MAC operation needs to be terminated, it + * should be done so by the `psa_drv_accel_mac_abort_t`. Failure to do so may + * result in allocated resources not being freed or in other undefined + * behavior. + * + */ +/**@{*/ + +/** \brief The hardware-accelerator-specific MAC context structure + * + * The contents of this structure are implementation dependent and are + * therefore not described here. + */ +typedef struct psa_drv_accel_mac_context_s psa_drv_accel_mac_context_t; + +/** \brief The function prototype for the setup operation of a + * hardware-accelerated MAC operation + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_mac___setup + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying primitive, and `MAC_VARIANT` + * is the specific variant of a MAC operation (such as HMAC or CMAC) + * + * \param[in,out] p_context A structure that will contain the + * hardware-specific MAC context + * \param[in] p_key A buffer containing the cleartext key material + * to be used in the operation + * \param[in] key_length The size in bytes of the key material + * + * \retval PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_accel_mac_setup_t)(psa_drv_accel_mac_context_t *p_context, + const uint8_t *p_key, + size_t key_length); + +/** \brief The function prototype for the update operation of a + * hardware-accelerated MAC operation + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_mac___update + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` + * is the specific variant of a MAC operation (such as HMAC or CMAC) + * + * \param[in,out] p_context A hardware-specific structure for the + * previously-established MAC operation to be + * continued + * \param[in] p_input A buffer containing the message to be appended + * to the MAC operation + * \param[in] input_length The size in bytes of the input message buffer + */ +typedef psa_status_t (*psa_drv_accel_mac_update_t)(psa_drv_accel_mac_context_t *p_context, + const uint8_t *p_input, + size_t input_length); + +/** \brief The function prototype for the finish operation of a + * hardware-accelerated MAC operation + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_mac___finish + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` is + * the specific variant of a MAC operation (such as HMAC or CMAC) + * + * \param[in,out] p_context A hardware-specific structure for the + * previously started MAC operation to be + * finished + * \param[out] p_mac A buffer where the generated MAC will be placed + * \param[in] mac_length The size in bytes of the buffer that has been + * allocated for the `p_mac` buffer + * + * \retval PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_accel_mac_finish_t)(psa_drv_accel_mac_context_t *p_context, + uint8_t *p_mac, + size_t mac_length); + +/** \brief The function prototype for the finish and verify operation of a + * hardware-accelerated MAC operation + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_mac___finish_verify + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` is + * the specific variant of a MAC operation (such as HMAC or CMAC) + * + * \param[in,out] p_context A hardware-specific structure for the + * previously started MAC operation to be + * verified and finished + * \param[in] p_mac A buffer containing the MAC that will be used + * for verification + * \param[in] mac_length The size in bytes of the data in the `p_mac` + * buffer + * + * \retval PSA_SUCCESS + * The operation completed successfully and the comparison matched + */ +typedef psa_status_t (*psa_drv_accel_mac_finish_verify_t)(psa_drv_accel_mac_context_t *p_context, + const uint8_t *p_mac, + size_t mac_length); + +/** \brief The function prototype for the abort operation for a previously + * started hardware-accelerated MAC operation + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_mac___abort + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` is + * the specific variant of a MAC operation (such as HMAC or CMAC) + * + * \param[in,out] p_context A hardware-specific structure for the + * previously started MAC operation to be + * aborted + * + */ +typedef psa_status_t (*psa_drv_accel_mac_abort_t)(psa_drv_accel_mac_context_t *p_context); + +/** \brief The function prototype for the one-shot operation of a + * hardware-accelerated MAC operation + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_mac__ + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` is + * the specific variant of a MAC operation (such as HMAC or CMAC) + * + * \param[in] p_input A buffer containing the data to be MACed + * \param[in] input_length The length in bytes of the `p_input` data + * \param[in] p_key A buffer containing the key material to be used + * for the MAC operation + * \param[in] key_length The length in bytes of the `p_key` data + * \param[in] alg The algorithm to be performed + * \param[out] p_mac The buffer where the resulting MAC will be placed + * upon success + * \param[in] mac_length The length in bytes of the `p_mac` buffer + */ +typedef psa_status_t (*psa_drv_accel_mac_t)(const uint8_t *p_input, + size_t input_length, + const uint8_t *p_key, + size_t key_length, + psa_algorithm_t alg, + uint8_t *p_mac, + size_t mac_length); + +/** \brief The function prototype for the one-shot hardware-accelerated MAC + * Verify operation + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_mac___verify + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` is + * the specific variant of a MAC operation (such as HMAC or CMAC) + * + * \param[in] p_input A buffer containing the data to be MACed + * \param[in] input_length The length in bytes of the `p_input` data + * \param[in] p_key A buffer containing the key material to be used + * for the MAC operation + * \param[in] key_length The length in bytes of the `p_key` data + * \param[in] alg The algorithm to be performed + * \param[in] p_mac The MAC data to be compared + * \param[in] mac_length The length in bytes of the `p_mac` buffer + * + * \retval PSA_SUCCESS + * The operation completed successfully and the comparison matched + */ +typedef psa_status_t (*psa_drv_accel_mac_verify_t)(const uint8_t *p_input, + size_t input_length, + const uint8_t *p_key, + size_t key_length, + psa_algorithm_t alg, + const uint8_t *p_mac, + size_t mac_length); +/**@}*/ + +/** \defgroup accel_cipher Hardware-Accelerated Block Ciphers + * Encryption and Decryption using hardware-acceleration in block modes other + * than ECB must be done in multiple parts, using the following flow: + * - `psa_drv_accel_ciphersetup_t` + * - `psa_drv_accel_cipher_set_iv_t` (optional depending upon block mode) + * - `psa_drv_accel_cipher_update_t` + * - `psa_drv_accel_cipher_update_t` + * - ... + * - `psa_drv_accel_cipher_finish_t` + * + * If a previously started hardware-accelerated Cipher operation needs to be + * terminated, it should be done so by the `psa_drv_accel_cipher_abort_t`. + * Failure to do so may result in allocated resources not being freed or in + * other undefined behavior. + */ +/**@{*/ + +/** \brief The hardware-accelerator-specific cipher context structure + * + * The contents of this structure are implementation dependent and are + * therefore not described here. + */ +typedef struct psa_drv_accel_cipher_context_s psa_drv_accel_cipher_context_t; + +/** \brief The function prototype for the setup operation of + * hardware-accelerated block cipher operations. + * Functions that implement this prototype should be named in the following + * conventions: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_cipher_setup__ + * ~~~~~~~~~~~~~ + * Where + * - `CIPHER_NAME` is the name of the underlying block cipher (i.e. AES or DES) + * - `MODE` is the block mode of the cipher operation (i.e. CBC or CTR) + * + * For stream ciphers: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_cipher_setup_ + * ~~~~~~~~~~~~~ + * Where `CIPHER_NAME` is the name of a stream cipher (i.e. RC4) + * + * \param[in,out] p_context A structure that will contain the + * hardware-specific cipher context + * \param[in] direction Indicates if the operation is an encrypt or a + * decrypt + * \param[in] p_key_data A buffer containing the cleartext key material + * to be used in the operation + * \param[in] key_data_size The size in bytes of the key material + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_accel_cipher_setup_t)(psa_drv_accel_cipher_context_t *p_context, + psa_encrypt_or_decrypt_t direction, + const uint8_t *p_key_data, + size_t key_data_size); + +/** \brief The function prototype for the set initialization vector operation + * of hardware-accelerated block cipher operations + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_cipher_set_iv__ + * ~~~~~~~~~~~~~ + * Where + * - `CIPHER_NAME` is the name of the underlying block cipher (i.e. AES or DES) + * - `MODE` is the block mode of the cipher operation (i.e. CBC or CTR) + * + * \param[in,out] p_context A structure that contains the previously setup + * hardware-specific cipher context + * \param[in] p_iv A buffer containing the initialization vecotr + * \param[in] iv_length The size in bytes of the contents of `p_iv` + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_accel_cipher_set_iv_t)(psa_drv_accel_cipher_context_t *p_context, + const uint8_t *p_iv, + size_t iv_length); + +/** \brief The function prototype for the update operation of + * hardware-accelerated block cipher operations. + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_cipher_update__ + * ~~~~~~~~~~~~~ + * Where + * - `CIPHER_NAME` is the name of the underlying block cipher (i.e. AES or DES) + * - `MODE` is the block mode of the cipher operation (i.e. CBC or CTR) + * + * \param[in,out] p_context A hardware-specific structure for the + * previously started cipher operation + * \param[in] p_input A buffer containing the data to be + * encrypted or decrypted + * \param[in] input_size The size in bytes of the `p_input` buffer + * \param[out] p_output A caller-allocated buffer where the + * generated output will be placed + * \param[in] output_size The size in bytes of the `p_output` buffer + * \param[out] p_output_length After completion, will contain the number + * of bytes placed in the `p_output` buffer + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_accel_cipher_update_t)(psa_drv_accel_cipher_context_t *p_context, + const uint8_t *p_input, + size_t input_size, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** \brief The function prototype for the finish operation of + * hardware-accelerated block cipher operations. + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_cipher_finish__ + * ~~~~~~~~~~~~~ + * Where + * - `CIPHER_NAME` is the name of the underlying block cipher (i.e. AES or DES) + * - `MODE` is the block mode of the cipher operation (i.e. CBC or CTR) + * + * \param[in,out] p_context A hardware-specific structure for the + * previously started cipher operation + * \param[out] p_output A caller-allocated buffer where the generated + * output will be placed + * \param[in] output_size The size in bytes of the `p_output` buffer + * \param[out] p_output_length After completion, will contain the number of + * bytes placed in the `p_output` buffer + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_accel_cipher_finish_t)(psa_drv_accel_cipher_context_t *p_context, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** \brief The function prototype for the abort operation of + * hardware-accelerated block cipher operations. + * + * Functions that implement the following prototype should be named in the + * following convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_cipher_abort__ + * ~~~~~~~~~~~~~ + * Where + * - `CIPHER_NAME` is the name of the underlying block cipher (i.e. AES or DES) + * - `MODE` is the block mode of the cipher operation (i.e. CBC or CTR) + * + * \param[in,out] p_context A hardware-specific structure for the + * previously started cipher operation + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_accel_cipher_abort_t)(psa_drv_accel_cipher_context_t *p_context); + +/**@}*/ + +/** \defgroup accel_aead Hardware-Accelerated Authenticated Encryption with Additional Data + * + * Hardware-accelerated Authenticated Encryption with Additional Data (AEAD) + * operations must be done in one function call. While this creates a burden + * for implementers as there must be sufficient space in memory for the entire + * message, it prevents decrypted data from being made available before the + * authentication operation is complete and the data is known to be authentic. + */ +/**@{*/ + +/** \brief The function prototype for the hardware-accelerated authenticated + * encryption operation. + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_aead__encrypt + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the AEAD algorithm + * + * \param[in] p_key A pointer to the key material + * \param[in] key_length The size in bytes of the key material + * \param[in] alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(`alg`) is true) + * \param[in] nonce Nonce or IV to use + * \param[in] nonce_length Size of the `nonce` buffer in bytes + * \param[in] additional_data Additional data that will be MACed + * but not encrypted. + * \param[in] additional_data_length Size of `additional_data` in bytes + * \param[in] plaintext Data that will be MACed and + * encrypted. + * \param[in] plaintext_length Size of `plaintext` in bytes + * \param[out] ciphertext Output buffer for the authenticated and + * encrypted data. The additional data is + * not part of this output. For algorithms + * where the encrypted data and the + * authentication tag are defined as + * separate outputs, the authentication + * tag is appended to the encrypted data. + * \param[in] ciphertext_size Size of the `ciphertext` buffer in + * bytes + * This must be at least + * #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(`alg`, + * `plaintext_length`). + * \param[out] ciphertext_length On success, the size of the output in + * the `ciphertext` buffer + * + * \retval #PSA_SUCCESS + * + */ +typedef psa_status_t (*psa_drv_accel_aead_encrypt_t)(const uint8_t *p_key, + size_t key_length, + 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 *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length); + +/** \brief The function prototype for the hardware-accelerated authenticated + * decryption operation. + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_aead__decrypt + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the AEAD algorithm + * \param[in] p_key A pointer to the key material + * \param[in] key_length The size in bytes of the key material + * \param[in] alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(`alg`) is true) + * \param[in] nonce Nonce or IV to use + * \param[in] nonce_length Size of the `nonce` buffer in bytes + * \param[in] additional_data Additional data that has been MACed + * but not encrypted + * \param[in] additional_data_length Size of `additional_data` in bytes + * \param[in] ciphertext Data that has been MACed and + * encrypted + * For algorithms where the encrypted data + * and the authentication tag are defined + * as separate inputs, the buffer must + * contain the encrypted data followed by + * the authentication tag. + * \param[in] ciphertext_length Size of `ciphertext` in bytes + * \param[out] plaintext Output buffer for the decrypted data + * \param[in] plaintext_size Size of the `plaintext` buffer in + * bytes + * This must be at least + * #PSA_AEAD_DECRYPT_OUTPUT_SIZE(`alg`, + * `ciphertext_length`). + * \param[out] plaintext_length On success, the size of the output + * in the \b plaintext buffer + * + * \retval #PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_accel_aead_decrypt_t)(const uint8_t *p_key, + size_t key_length, + 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 *ciphertext, + size_t ciphertext_length, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length); + +/**@}*/ + +/** \defgroup accel_asymmetric Hardware-Accelerated Asymmetric Cryptography + * + * Since the amount of data that can (or should) be encrypted or signed using + * asymmetric keys is limited by the key size, hardware-accelerated asymmetric + * key operations must be done in single function calls. + */ +/**@{*/ + + +/** + * \brief The function prototype for the hardware-accelerated asymmetric sign + * operation. + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_asymmetric__sign + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the signing algorithm + * + * This function supports any asymmetric-key output from psa_export_key() as + * the buffer in \p p_key. Refer to the documentation of \ref + * psa_export_key() for the formats. + * + * \param[in] p_key A buffer containing the private key + * material + * \param[in] key_size The size in bytes of the `p_key` data + * \param[in] alg A signature algorithm that is compatible + * with the type of `p_key` + * \param[in] p_hash The hash or message to sign + * \param[in] hash_length Size of the `p_hash` buffer in bytes + * \param[out] p_signature Buffer where the signature is to be written + * \param[in] signature_size Size of the `p_signature` buffer in bytes + * \param[out] p_signature_length On success, the number of bytes + * that make up the returned signature value + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_accel_asymmetric_sign_t)(const uint8_t *p_key, + size_t key_size, + psa_algorithm_t alg, + psa_key_type_t key_type, + const uint8_t *p_hash, + size_t hash_length, + uint8_t *p_signature, + size_t signature_size, + size_t *p_signature_length); + +/** + * \brief The function prototype for the hardware-accelerated signature verify + * operation + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_asymmetric__verify + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the signing algorithm + * + * This function supports any output from \ref psa_export_public_key() as the + * buffer in \p p_key. Refer to the documentation of \ref + * psa_export_public_key() for the format of public keys and to the + * documentation of \ref psa_export_key() for the format for other key types. + * + * \param[in] p_key A buffer containing the public key material + * \param[in] key_size The size in bytes of the `p_key` data + * \param[in] alg A signature algorithm that is compatible with + * the type of `key` + * \param[in] p_hash The hash or message whose signature is to be + * verified + * \param[in] hash_length Size of the `p_hash` buffer in bytes + * \param[in] p_signature Buffer containing the signature to verify + * \param[in] signature_length Size of the `p_signature` buffer in bytes + * + * \retval PSA_SUCCESS + * The signature is valid. + */ +typedef psa_status_t (*psa_drv_accel_asymmetric_verify_t)(const uint8_t *p_key, + size_t key_size, + psa_algorithm_t alg, + psa_key_type_t key_type, + const uint8_t *p_hash, + size_t hash_length, + const uint8_t *p_signature, + size_t signature_length); + +/** + * \brief The function prototype for the hardware-accelerated asymmetric + * encrypt operation + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_asymmetric__encrypt + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the encryption algorithm + * + * This function supports any output from \ref psa_export_public_key() as the + * buffer in \p p_key. Refer to the documentation of \ref + * psa_export_public_key() for the format of public keys and to the + * documentation of \ref psa_export_key() for the format for other key types. + * + * \param[in] p_key A buffer containing the public key material + * \param[in] key_size The size in bytes of the `p_key` data + * \param[in] alg An asymmetric encryption algorithm that is + * compatible with the type of `key` + * \param[in] p_input The message to encrypt + * \param[in] input_length Size of the `p_input` buffer in bytes + * \param[in] p_salt A salt or label, if supported by the + * encryption algorithm + * If the algorithm does not support a + * salt, pass `NULL` + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass `NULL`. + * For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported. + * \param[in] salt_length Size of the `p_salt` buffer in bytes + * If `p_salt` is `NULL`, pass 0. + * \param[out] p_output Buffer where the encrypted message is to + * be written + * \param[in] output_size Size of the `p_output` buffer in bytes + * \param[out] p_output_length On success, the number of bytes + * that make up the returned output + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_accel_asymmetric_encrypt_t)(const uint8_t *p_key, + size_t key_size, + psa_algorithm_t alg, + psa_key_type_t key_type, + const uint8_t *p_input, + size_t input_length, + const uint8_t *p_salt, + size_t salt_length, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** + * \brief The function prototype for the hardware=acce;erated asymmetric + * decrypt operation + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_asymmetric__decrypt + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the encryption algorithm + * + * This function supports any asymmetric-key output from psa_export_key() as + * the buffer in \p p_key. Refer to the documentation of \ref + * psa_export_key() for the formats. + * + * \param[in] p_key A buffer containing the private key material + * \param[in] key_size The size in bytes of the `p_key` data + * \param[in] alg An asymmetric encryption algorithm that is + * compatible with the type of `key` + * \param[in] p_input The message to decrypt + * \param[in] input_length Size of the `p_input` buffer in bytes + * \param[in] p_salt A salt or label, if supported by the + * encryption algorithm + * If the algorithm does not support a + * salt, pass `NULL`. + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass `NULL`. + * For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported + * \param[in] salt_length Size of the `p_salt` buffer in bytes + * If `p_salt` is `NULL`, pass 0 + * \param[out] p_output Buffer where the decrypted message is to + * be written + * \param[in] output_size Size of the `p_output` buffer in bytes + * \param[out] p_output_length On success, the number of bytes + * that make up the returned output + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_accel_asymmetric_decrypt_t)(const uint8_t *p_key, + size_t key_size, + psa_algorithm_t alg, + psa_key_type_t key_type, + const uint8_t *p_input, + size_t input_length, + const uint8_t *p_salt, + size_t salt_length, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_ACCEL_DRIVER_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_compat.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_compat.h new file mode 100644 index 0000000..1ed5f05 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_compat.h @@ -0,0 +1,196 @@ +/** + * \file psa/crypto_compat.h + * + * \brief PSA cryptography module: Backward compatibility aliases + * + * This header declares alternative names for macro and functions. + * New application code should not use these names. + * These names may be removed in a future version of Mbed Crypto. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + */ +/* + * Copyright (C) 2019, ARM Limited, 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef PSA_CRYPTO_COMPAT_H +#define PSA_CRYPTO_COMPAT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +/* + * Mechanism for declaring deprecated values + */ +#if defined(MBEDTLS_DEPRECATED_WARNING) && !defined(MBEDTLS_PSA_DEPRECATED) +#define MBEDTLS_PSA_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_PSA_DEPRECATED +#endif + +typedef MBEDTLS_PSA_DEPRECATED size_t mbedtls_deprecated_size_t; +typedef MBEDTLS_PSA_DEPRECATED psa_status_t mbedtls_deprecated_psa_status_t; +typedef MBEDTLS_PSA_DEPRECATED psa_key_usage_t mbedtls_deprecated_psa_key_usage_t; +typedef MBEDTLS_PSA_DEPRECATED psa_ecc_curve_t mbedtls_deprecated_psa_ecc_curve_t; +typedef MBEDTLS_PSA_DEPRECATED psa_dh_group_t mbedtls_deprecated_psa_dh_group_t; + +#define MBEDTLS_DEPRECATED_CONSTANT( type, value ) \ + ( (mbedtls_deprecated_##type) ( value ) ) + +/* + * Deprecated PSA Crypto error code definitions (PSA Crypto API <= 1.0 beta2) + */ +#define PSA_ERROR_UNKNOWN_ERROR \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_GENERIC_ERROR ) +#define PSA_ERROR_OCCUPIED_SLOT \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_ALREADY_EXISTS ) +#define PSA_ERROR_EMPTY_SLOT \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_DOES_NOT_EXIST ) +#define PSA_ERROR_INSUFFICIENT_CAPACITY \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_INSUFFICIENT_DATA ) +#define PSA_ERROR_TAMPERING_DETECTED \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_CORRUPTION_DETECTED ) + +/* + * Deprecated PSA Crypto numerical encodings (PSA Crypto API <= 1.0 beta3) + */ +#define PSA_KEY_USAGE_SIGN \ + MBEDTLS_DEPRECATED_CONSTANT( psa_key_usage_t, PSA_KEY_USAGE_SIGN_HASH ) +#define PSA_KEY_USAGE_VERIFY \ + MBEDTLS_DEPRECATED_CONSTANT( psa_key_usage_t, PSA_KEY_USAGE_VERIFY_HASH ) + +/* + * Deprecated PSA Crypto size calculation macros (PSA Crypto API <= 1.0 beta3) + */ +#define PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE \ + MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_SIGNATURE_MAX_SIZE ) +#define PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE( key_type, key_bits, alg ) \ + MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_SIGN_OUTPUT_SIZE( key_type, key_bits, alg ) ) + +/* + * Deprecated PSA Crypto function names (PSA Crypto API <= 1.0 beta3) + */ +MBEDTLS_PSA_DEPRECATED static inline psa_status_t psa_asymmetric_sign( psa_key_handle_t key, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length ) +{ + return psa_sign_hash( key, alg, hash, hash_length, signature, signature_size, signature_length ); +} + +MBEDTLS_PSA_DEPRECATED static inline psa_status_t psa_asymmetric_verify( psa_key_handle_t key, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length ) +{ + return psa_verify_hash( key, alg, hash, hash_length, signature, signature_length ); +} + + + +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/* + * Size-specific elliptic curve and Diffie-Hellman group names + */ +#define PSA_ECC_CURVE_SECP160K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_K1 ) +#define PSA_ECC_CURVE_SECP192K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_K1 ) +#define PSA_ECC_CURVE_SECP224K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_K1 ) +#define PSA_ECC_CURVE_SECP256K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_K1 ) +#define PSA_ECC_CURVE_SECP160R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_R1 ) +#define PSA_ECC_CURVE_SECP192R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_R1 ) +#define PSA_ECC_CURVE_SECP224R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_R1 ) +#define PSA_ECC_CURVE_SECP256R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_R1 ) +#define PSA_ECC_CURVE_SECP384R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_R1 ) +#define PSA_ECC_CURVE_SECP521R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_R1 ) +#define PSA_ECC_CURVE_SECP160R2 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_R2 ) +#define PSA_ECC_CURVE_SECT163K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_K1 ) +#define PSA_ECC_CURVE_SECT233K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_K1 ) +#define PSA_ECC_CURVE_SECT239K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_K1 ) +#define PSA_ECC_CURVE_SECT283K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_K1 ) +#define PSA_ECC_CURVE_SECT409K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_K1 ) +#define PSA_ECC_CURVE_SECT571K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_K1 ) +#define PSA_ECC_CURVE_SECT163R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R1 ) +#define PSA_ECC_CURVE_SECT193R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R1 ) +#define PSA_ECC_CURVE_SECT233R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R1 ) +#define PSA_ECC_CURVE_SECT283R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R1 ) +#define PSA_ECC_CURVE_SECT409R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R1 ) +#define PSA_ECC_CURVE_SECT571R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R1 ) +#define PSA_ECC_CURVE_SECT163R2 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R2 ) +#define PSA_ECC_CURVE_SECT193R2 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R2 ) +#define PSA_ECC_CURVE_BRAINPOOL_P256R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_BRAINPOOL_P_R1 ) +#define PSA_ECC_CURVE_BRAINPOOL_P384R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_BRAINPOOL_P_R1 ) +#define PSA_ECC_CURVE_BRAINPOOL_P512R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_BRAINPOOL_P_R1 ) +#define PSA_ECC_CURVE_CURVE25519 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_MONTGOMERY ) +#define PSA_ECC_CURVE_CURVE448 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_MONTGOMERY ) + +#define PSA_DH_GROUP_FFDHE2048 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_dh_group_t, PSA_DH_GROUP_RFC7919 ) +#define PSA_DH_GROUP_FFDHE3072 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_dh_group_t, PSA_DH_GROUP_RFC7919 ) +#define PSA_DH_GROUP_FFDHE4096 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_dh_group_t, PSA_DH_GROUP_RFC7919 ) +#define PSA_DH_GROUP_FFDHE6144 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_dh_group_t, PSA_DH_GROUP_RFC7919 ) +#define PSA_DH_GROUP_FFDHE8192 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_dh_group_t, PSA_DH_GROUP_RFC7919 ) + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_COMPAT_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_driver_common.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_driver_common.h new file mode 100644 index 0000000..6f1a5d5 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_driver_common.h @@ -0,0 +1,54 @@ +/** + * \file psa/crypto_driver_common.h + * \brief Definitions for all PSA crypto drivers + * + * This file contains common definitions shared by all PSA crypto drivers. + * Do not include it directly: instead, include the header file(s) for + * the type(s) of driver that you are implementing. For example, if + * you are writing a driver for a chip that provides both a hardware + * random generator and an accelerator for some cryptographic algorithms, + * include `psa/crypto_entropy_driver.h` and `psa/crypto_accel_driver.h`. + * + * This file is part of the PSA Crypto Driver Model, containing functions for + * driver developers to implement to enable hardware to be called in a + * standardized way by a PSA Cryptographic API implementation. The functions + * comprising the driver model, which driver authors implement, are not + * intended to be called by application developers. + */ + +/* + * Copyright (C) 2018, ARM Limited, 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 PSA_CRYPTO_DRIVER_COMMON_H +#define PSA_CRYPTO_DRIVER_COMMON_H + +#include +#include + +/* Include type definitions (psa_status_t, psa_algorithm_t, + * psa_key_type_t, etc.) and macros to build and analyze values + * of these types. */ +#include "crypto_types.h" +#include "crypto_values.h" + +/** For encrypt-decrypt functions, whether the operation is an encryption + * or a decryption. */ +typedef enum { + PSA_CRYPTO_DRIVER_DECRYPT, + PSA_CRYPTO_DRIVER_ENCRYPT +} psa_encrypt_or_decrypt_t; + +#endif /* PSA_CRYPTO_DRIVER_COMMON_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_entropy_driver.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_entropy_driver.h new file mode 100644 index 0000000..f596b6b --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_entropy_driver.h @@ -0,0 +1,108 @@ +/** + * \file psa/crypto_entropy_driver.h + * \brief PSA entropy source driver module + * + * This header declares types and function signatures for entropy sources. + * + * This file is part of the PSA Crypto Driver Model, containing functions for + * driver developers to implement to enable hardware to be called in a + * standardized way by a PSA Cryptographic API implementation. The functions + * comprising the driver model, which driver authors implement, are not + * intended to be called by application developers. + */ + +/* + * Copyright (C) 2018, ARM Limited, 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 PSA_CRYPTO_ENTROPY_DRIVER_H +#define PSA_CRYPTO_ENTROPY_DRIVER_H + +#include "crypto_driver_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup driver_rng Entropy Generation + */ +/**@{*/ + +/** \brief Initialize an entropy driver + * + * + * \param[in,out] p_context A hardware-specific structure + * containing any context information for + * the implementation + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_entropy_init_t)(void *p_context); + +/** \brief Get a specified number of bits from the entropy source + * + * It retrives `buffer_size` bytes of data from the entropy source. The entropy + * source will always fill the provided buffer to its full size, however, most + * entropy sources have biases, and the actual amount of entropy contained in + * the buffer will be less than the number of bytes. + * The driver will return the actual number of bytes of entropy placed in the + * buffer in `p_received_entropy_bytes`. + * A PSA Crypto API implementation will likely feed the output of this function + * into a Digital Random Bit Generator (DRBG), and typically has a minimum + * amount of entropy that it needs. + * To accomplish this, the PSA Crypto implementation should be designed to call + * this function multiple times until it has received the required amount of + * entropy from the entropy source. + * + * \param[in,out] p_context A hardware-specific structure + * containing any context information + * for the implementation + * \param[out] p_buffer A caller-allocated buffer for the + * retrieved entropy to be placed in + * \param[in] buffer_size The allocated size of `p_buffer` + * \param[out] p_received_entropy_bits The amount of entropy (in bits) + * actually provided in `p_buffer` + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_entropy_get_bits_t)(void *p_context, + uint8_t *p_buffer, + uint32_t buffer_size, + uint32_t *p_received_entropy_bits); + +/** + * \brief A struct containing all of the function pointers needed to interface + * to an entropy source + * + * PSA Crypto API implementations should populate instances of the table as + * appropriate upon startup. + * + * If one of the functions is not implemented, it should be set to NULL. + */ +typedef struct { + /** The driver-specific size of the entropy context */ + const size_t context_size; + /** Function that performs initialization for the entropy source */ + psa_drv_entropy_init_t p_init; + /** Function that performs the get_bits operation for the entropy source */ + psa_drv_entropy_get_bits_t p_get_bits; +} psa_drv_entropy_t; +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_ENTROPY_DRIVER_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_extra.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_extra.h new file mode 100644 index 0000000..64ab1bf --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_extra.h @@ -0,0 +1,655 @@ +/** + * \file psa/crypto_extra.h + * + * \brief PSA cryptography module: Mbed TLS vendor extensions + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * This file is reserved for vendor-specific definitions. + */ +/* + * Copyright (C) 2018, ARM Limited, 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef PSA_CRYPTO_EXTRA_H +#define PSA_CRYPTO_EXTRA_H + +#include "mbedtls/platform_util.h" + +#include "crypto_compat.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* UID for secure storage seed */ +#define PSA_CRYPTO_ITS_RANDOM_SEED_UID 0xFFFFFF52 + + +/** \addtogroup attributes + * @{ + */ + +/** \brief Declare the enrollment algorithm for a key. + * + * An operation on a key may indifferently use the algorithm set with + * psa_set_key_algorithm() or with this function. + * + * \param[out] attributes The attribute structure to write to. + * \param alg2 A second algorithm that the key may be used + * for, in addition to the algorithm set with + * psa_set_key_algorithm(). + * + * \warning Setting an enrollment algorithm is not recommended, because + * using the same key with different algorithms can allow some + * attacks based on arithmetic relations between different + * computations made with the same key, or can escalate harmless + * side channels into exploitable ones. Use this function only + * if it is necessary to support a protocol for which it has been + * verified that the usage of the key with multiple algorithms + * is safe. + */ +static inline void psa_set_key_enrollment_algorithm( + psa_key_attributes_t *attributes, + psa_algorithm_t alg2) +{ + attributes->core.policy.alg2 = alg2; +} + +/** Retrieve the enrollment algorithm policy from key attributes. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The enrollment algorithm stored in the attribute structure. + */ +static inline psa_algorithm_t psa_get_key_enrollment_algorithm( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.policy.alg2 ); +} + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + +/** Retrieve the slot number where a key is stored. + * + * A slot number is only defined for keys that are stored in a secure + * element. + * + * This information is only useful if the secure element is not entirely + * managed through the PSA Cryptography API. It is up to the secure + * element driver to decide how PSA slot numbers map to any other interface + * that the secure element may have. + * + * \param[in] attributes The key attribute structure to query. + * \param[out] slot_number On success, the slot number containing the key. + * + * \retval #PSA_SUCCESS + * The key is located in a secure element, and \p *slot_number + * indicates the slot number that contains it. + * \retval #PSA_ERROR_NOT_PERMITTED + * The caller is not permitted to query the slot number. + * Mbed Crypto currently does not return this error. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key is not located in a secure element. + */ +psa_status_t psa_get_key_slot_number( + const psa_key_attributes_t *attributes, + psa_key_slot_number_t *slot_number ); + +/** Choose the slot number where a key is stored. + * + * This function declares a slot number in the specified attribute + * structure. + * + * A slot number is only meaningful for keys that are stored in a secure + * element. It is up to the secure element driver to decide how PSA slot + * numbers map to any other interface that the secure element may have. + * + * \note Setting a slot number in key attributes for a key creation can + * cause the following errors when creating the key: + * - #PSA_ERROR_NOT_SUPPORTED if the selected secure element does + * not support choosing a specific slot number. + * - #PSA_ERROR_NOT_PERMITTED if the caller is not permitted to + * choose slot numbers in general or to choose this specific slot. + * - #PSA_ERROR_INVALID_ARGUMENT if the chosen slot number is not + * valid in general or not valid for this specific key. + * - #PSA_ERROR_ALREADY_EXISTS if there is already a key in the + * selected slot. + * + * \param[out] attributes The attribute structure to write to. + * \param slot_number The slot number to set. + */ +static inline void psa_set_key_slot_number( + psa_key_attributes_t *attributes, + psa_key_slot_number_t slot_number ) +{ + attributes->core.flags |= MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER; + attributes->slot_number = slot_number; +} + +/** Remove the slot number attribute from a key attribute structure. + * + * This function undoes the action of psa_set_key_slot_number(). + * + * \param[out] attributes The attribute structure to write to. + */ +static inline void psa_clear_key_slot_number( + psa_key_attributes_t *attributes ) +{ + attributes->core.flags &= ~MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER; +} + +/** Register a key that is already present in a secure element. + * + * The key must be located in a secure element designated by the + * lifetime field in \p attributes, in the slot set with + * psa_set_key_slot_number() in the attribute structure. + * This function makes the key available through the key identifier + * specified in \p attributes. + * + * \param[in] attributes The attributes of the existing key. + * + * \retval #PSA_SUCCESS + * The key was successfully registered. + * Note that depending on the design of the driver, this may or may + * not guarantee that a key actually exists in the designated slot + * and is compatible with the specified attributes. + * \retval #PSA_ERROR_ALREADY_EXISTS + * There is already a key with the identifier specified in + * \p attributes. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The secure element driver for the specified lifetime does not + * support registering a key. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p attributes specifies a lifetime which is not located + * in a secure element. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * No slot number is specified in \p attributes, + * or the specified slot number is not valid. + * \retval #PSA_ERROR_NOT_PERMITTED + * The caller is not authorized to register the specified key slot. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t mbedtls_psa_register_se_key( + const psa_key_attributes_t *attributes); + +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + +/**@}*/ + +/** + * \brief Library deinitialization. + * + * This function clears all data associated with the PSA layer, + * including the whole key store. + * + * This is an Mbed TLS extension. + */ +void mbedtls_psa_crypto_free( void ); + +/** \brief Statistics about + * resource consumption related to the PSA keystore. + * + * \note The content of this structure is not part of the stable API and ABI + * of Mbed Crypto and may change arbitrarily from version to version. + */ +typedef struct mbedtls_psa_stats_s +{ + /** Number of slots containing key material for a volatile key. */ + size_t volatile_slots; + /** Number of slots containing key material for a key which is in + * internal persistent storage. */ + size_t persistent_slots; + /** Number of slots containing a reference to a key in a + * secure element. */ + size_t external_slots; + /** Number of slots which are occupied, but do not contain + * key material yet. */ + size_t half_filled_slots; + /** Number of slots that contain cache data. */ + size_t cache_slots; + /** Number of slots that are not used for anything. */ + size_t empty_slots; + /** Largest key id value among open keys in internal persistent storage. */ + psa_app_key_id_t max_open_internal_key_id; + /** Largest key id value among open keys in secure elements. */ + psa_app_key_id_t max_open_external_key_id; +} mbedtls_psa_stats_t; + +/** \brief Get statistics about + * resource consumption related to the PSA keystore. + * + * \note When Mbed Crypto is built as part of a service, with isolation + * between the application and the keystore, the service may or + * may not expose this function. + */ +void mbedtls_psa_get_stats( mbedtls_psa_stats_t *stats ); + +/** + * \brief Inject an initial entropy seed for the random generator into + * secure storage. + * + * This function injects data to be used as a seed for the random generator + * used by the PSA Crypto implementation. On devices that lack a trusted + * entropy source (preferably a hardware random number generator), + * the Mbed PSA Crypto implementation uses this value to seed its + * random generator. + * + * On devices without a trusted entropy source, this function must be + * called exactly once in the lifetime of the device. On devices with + * a trusted entropy source, calling this function is optional. + * In all cases, this function may only be called before calling any + * other function in the PSA Crypto API, including psa_crypto_init(). + * + * When this function returns successfully, it populates a file in + * persistent storage. Once the file has been created, this function + * can no longer succeed. + * + * If any error occurs, this function does not change the system state. + * You can call this function again after correcting the reason for the + * error if possible. + * + * \warning This function **can** fail! Callers MUST check the return status. + * + * \warning If you use this function, you should use it as part of a + * factory provisioning process. The value of the injected seed + * is critical to the security of the device. It must be + * *secret*, *unpredictable* and (statistically) *unique per device*. + * You should be generate it randomly using a cryptographically + * secure random generator seeded from trusted entropy sources. + * You should transmit it securely to the device and ensure + * that its value is not leaked or stored anywhere beyond the + * needs of transmitting it from the point of generation to + * the call of this function, and erase all copies of the value + * once this function returns. + * + * This is an Mbed TLS extension. + * + * \note This function is only available on the following platforms: + * * If the compile-time option MBEDTLS_PSA_INJECT_ENTROPY is enabled. + * Note that you must provide compatible implementations of + * mbedtls_nv_seed_read and mbedtls_nv_seed_write. + * * In a client-server integration of PSA Cryptography, on the client side, + * if the server supports this feature. + * \param[in] seed Buffer containing the seed value to inject. + * \param[in] seed_size Size of the \p seed buffer. + * The size of the seed in bytes must be greater + * or equal to both #MBEDTLS_ENTROPY_MIN_PLATFORM + * and #MBEDTLS_ENTROPY_BLOCK_SIZE. + * It must be less or equal to + * #MBEDTLS_ENTROPY_MAX_SEED_SIZE. + * + * \retval #PSA_SUCCESS + * The seed value was injected successfully. The random generator + * of the PSA Crypto implementation is now ready for use. + * You may now call psa_crypto_init() and use the PSA Crypto + * implementation. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p seed_size is out of range. + * \retval #PSA_ERROR_STORAGE_FAILURE + * There was a failure reading or writing from storage. + * \retval #PSA_ERROR_NOT_PERMITTED + * The library has already been initialized. It is no longer + * possible to call this function. + */ +psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed, + size_t seed_size); + +/** \addtogroup crypto_types + * @{ + */ + +/** DSA public key. + * + * The import and export format is the + * representation of the public key `y = g^x mod p` as a big-endian byte + * string. The length of the byte string is the length of the base prime `p` + * in bytes. + */ +#define PSA_KEY_TYPE_DSA_PUBLIC_KEY ((psa_key_type_t)0x4002) + +/** DSA key pair (private and public key). + * + * The import and export format is the + * representation of the private key `x` as a big-endian byte string. The + * length of the byte string is the private key size in bytes (leading zeroes + * are not stripped). + * + * Determinstic DSA key derivation with psa_generate_derived_key follows + * FIPS 186-4 §B.1.2: interpret the byte string as integer + * in big-endian order. Discard it if it is not in the range + * [0, *N* - 2] where *N* is the boundary of the private key domain + * (the prime *p* for Diffie-Hellman, the subprime *q* for DSA, + * or the order of the curve's base point for ECC). + * Add 1 to the resulting integer and use this as the private key *x*. + * + */ +#define PSA_KEY_TYPE_DSA_KEY_PAIR ((psa_key_type_t)0x7002) + +/** Whether a key type is an DSA key (pair or public-only). */ +#define PSA_KEY_TYPE_IS_DSA(type) \ + (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY) + +#define PSA_ALG_DSA_BASE ((psa_algorithm_t)0x10040000) +/** DSA signature with hashing. + * + * This is the signature scheme defined by FIPS 186-4, + * with a random per-message secret number (*k*). + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding DSA signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_DSA(hash_alg) \ + (PSA_ALG_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_DETERMINISTIC_DSA_BASE ((psa_algorithm_t)0x10050000) +#define PSA_ALG_DSA_DETERMINISTIC_FLAG PSA_ALG_ECDSA_DETERMINISTIC_FLAG +/** Deterministic DSA signature with hashing. + * + * This is the deterministic variant defined by RFC 6979 of + * the signature scheme defined by FIPS 186-4. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding DSA signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_DETERMINISTIC_DSA(hash_alg) \ + (PSA_ALG_DETERMINISTIC_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_IS_DSA(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_DSA_DETERMINISTIC_FLAG) == \ + PSA_ALG_DSA_BASE) +#define PSA_ALG_DSA_IS_DETERMINISTIC(alg) \ + (((alg) & PSA_ALG_DSA_DETERMINISTIC_FLAG) != 0) +#define PSA_ALG_IS_DETERMINISTIC_DSA(alg) \ + (PSA_ALG_IS_DSA(alg) && PSA_ALG_DSA_IS_DETERMINISTIC(alg)) +#define PSA_ALG_IS_RANDOMIZED_DSA(alg) \ + (PSA_ALG_IS_DSA(alg) && !PSA_ALG_DSA_IS_DETERMINISTIC(alg)) + + +/* We need to expand the sample definition of this macro from + * the API definition. */ +#undef PSA_ALG_IS_HASH_AND_SIGN +#define PSA_ALG_IS_HASH_AND_SIGN(alg) \ + (PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || \ + PSA_ALG_IS_DSA(alg) || PSA_ALG_IS_ECDSA(alg)) + +/**@}*/ + +/** \addtogroup attributes + * @{ + */ + +/** Custom Diffie-Hellman group. + * + * For keys of type #PSA_KEY_TYPE_DH_PUBLIC_KEY(#PSA_DH_GROUP_CUSTOM) or + * #PSA_KEY_TYPE_DH_KEY_PAIR(#PSA_DH_GROUP_CUSTOM), the group data comes + * from domain parameters set by psa_set_key_domain_parameters(). + */ +#define PSA_DH_GROUP_CUSTOM ((psa_dh_group_t) 0x7e) + + +/** + * \brief Set domain parameters for a key. + * + * Some key types require additional domain parameters in addition to + * the key type identifier and the key size. Use this function instead + * of psa_set_key_type() when you need to specify domain parameters. + * + * The format for the required domain parameters varies based on the key type. + * + * - For RSA keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY or #PSA_KEY_TYPE_RSA_KEY_PAIR), + * the domain parameter data consists of the public exponent, + * represented as a big-endian integer with no leading zeros. + * This information is used when generating an RSA key pair. + * When importing a key, the public exponent is read from the imported + * key data and the exponent recorded in the attribute structure is ignored. + * As an exception, the public exponent 65537 is represented by an empty + * byte string. + * - For DSA keys (#PSA_KEY_TYPE_DSA_PUBLIC_KEY or #PSA_KEY_TYPE_DSA_KEY_PAIR), + * the `Dss-Parms` format as defined by RFC 3279 §2.3.2. + * ``` + * Dss-Parms ::= SEQUENCE { + * p INTEGER, + * q INTEGER, + * g INTEGER + * } + * ``` + * - For Diffie-Hellman key exchange keys + * (#PSA_KEY_TYPE_DH_PUBLIC_KEY(#PSA_DH_GROUP_CUSTOM) or + * #PSA_KEY_TYPE_DH_KEY_PAIR(#PSA_DH_GROUP_CUSTOM)), the + * `DomainParameters` format as defined by RFC 3279 §2.3.3. + * ``` + * DomainParameters ::= SEQUENCE { + * p INTEGER, -- odd prime, p=jq +1 + * g INTEGER, -- generator, g + * q INTEGER, -- factor of p-1 + * j INTEGER OPTIONAL, -- subgroup factor + * validationParms ValidationParms OPTIONAL + * } + * ValidationParms ::= SEQUENCE { + * seed BIT STRING, + * pgenCounter INTEGER + * } + * ``` + * + * \note This function may allocate memory or other resources. + * Once you have called this function on an attribute structure, + * you must call psa_reset_key_attributes() to free these resources. + * + * \note This is an experimental extension to the interface. It may change + * in future versions of the library. + * + * \param[in,out] attributes Attribute structure where the specified domain + * parameters will be stored. + * If this function fails, the content of + * \p attributes is not modified. + * \param type Key type (a \c PSA_KEY_TYPE_XXX value). + * \param[in] data Buffer containing the key domain parameters. + * The content of this buffer is interpreted + * according to \p type as described above. + * \param data_length Size of the \p data buffer in bytes. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + */ +psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes, + psa_key_type_t type, + const uint8_t *data, + size_t data_length); + +/** + * \brief Get domain parameters for a key. + * + * Get the domain parameters for a key with this function, if any. The format + * of the domain parameters written to \p data is specified in the + * documentation for psa_set_key_domain_parameters(). + * + * \note This is an experimental extension to the interface. It may change + * in future versions of the library. + * + * \param[in] attributes The key attribute structure to query. + * \param[out] data On success, the key domain parameters. + * \param data_size Size of the \p data buffer in bytes. + * The buffer is guaranteed to be large + * enough if its size in bytes is at least + * the value given by + * PSA_KEY_DOMAIN_PARAMETERS_SIZE(). + * \param[out] data_length On success, the number of bytes + * that make up the key domain parameters data. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + */ +psa_status_t psa_get_key_domain_parameters( + const psa_key_attributes_t *attributes, + uint8_t *data, + size_t data_size, + size_t *data_length); + +/** Safe output buffer size for psa_get_key_domain_parameters(). + * + * This macro returns a compile-time constant if its arguments are + * compile-time constants. + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \note This is an experimental extension to the interface. It may change + * in future versions of the library. + * + * \param key_type A supported key type. + * \param key_bits The size of the key in bits. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_get_key_domain_parameters() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported + * by the implementation, this macro shall return either a + * sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_KEY_DOMAIN_PARAMETERS_SIZE(key_type, key_bits) \ + (PSA_KEY_TYPE_IS_RSA(key_type) ? sizeof(int) : \ + PSA_KEY_TYPE_IS_DH(key_type) ? PSA_DH_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) : \ + PSA_KEY_TYPE_IS_DSA(key_type) ? PSA_DSA_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) : \ + 0) +#define PSA_DH_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) \ + (4 + (PSA_BITS_TO_BYTES(key_bits) + 5) * 3 /*without optional parts*/) +#define PSA_DSA_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) \ + (4 + (PSA_BITS_TO_BYTES(key_bits) + 5) * 2 /*p, g*/ + 34 /*q*/) + +/**@}*/ + +/** \defgroup psa_tls_helpers TLS helper functions + * @{ + */ + +#if defined(MBEDTLS_ECP_C) +#include + +/** Convert an ECC curve identifier from the Mbed TLS encoding to PSA. + * + * \note This function is provided solely for the convenience of + * Mbed TLS and may be removed at any time without notice. + * + * \param grpid An Mbed TLS elliptic curve identifier + * (`MBEDTLS_ECP_DP_xxx`). + * \param[out] bits On success, the bit size of the curve. + * + * \return The corresponding PSA elliptic curve identifier + * (`PSA_ECC_CURVE_xxx`). + * \return \c 0 on failure (\p grpid is not recognized). + */ +static inline psa_ecc_curve_t mbedtls_ecc_group_to_psa( mbedtls_ecp_group_id grpid, + size_t *bits ) +{ + switch( grpid ) + { + case MBEDTLS_ECP_DP_SECP192R1: + *bits = 192; + return( PSA_ECC_CURVE_SECP_R1 ); + case MBEDTLS_ECP_DP_SECP224R1: + *bits = 224; + return( PSA_ECC_CURVE_SECP_R1 ); + case MBEDTLS_ECP_DP_SECP256R1: + *bits = 256; + return( PSA_ECC_CURVE_SECP_R1 ); + case MBEDTLS_ECP_DP_SECP384R1: + *bits = 384; + return( PSA_ECC_CURVE_SECP_R1 ); + case MBEDTLS_ECP_DP_SECP521R1: + *bits = 521; + return( PSA_ECC_CURVE_SECP_R1 ); + case MBEDTLS_ECP_DP_BP256R1: + *bits = 256; + return( PSA_ECC_CURVE_BRAINPOOL_P_R1 ); + case MBEDTLS_ECP_DP_BP384R1: + *bits = 384; + return( PSA_ECC_CURVE_BRAINPOOL_P_R1 ); + case MBEDTLS_ECP_DP_BP512R1: + *bits = 512; + return( PSA_ECC_CURVE_BRAINPOOL_P_R1 ); + case MBEDTLS_ECP_DP_CURVE25519: + *bits = 255; + return( PSA_ECC_CURVE_MONTGOMERY ); + case MBEDTLS_ECP_DP_SECP192K1: + *bits = 192; + return( PSA_ECC_CURVE_SECP_K1 ); + case MBEDTLS_ECP_DP_SECP224K1: + *bits = 224; + return( PSA_ECC_CURVE_SECP_K1 ); + case MBEDTLS_ECP_DP_SECP256K1: + *bits = 256; + return( PSA_ECC_CURVE_SECP_K1 ); + case MBEDTLS_ECP_DP_CURVE448: + *bits = 448; + return( PSA_ECC_CURVE_MONTGOMERY ); + default: + return( 0 ); + } +} + +/** Convert an ECC curve identifier from the PSA encoding to Mbed TLS. + * + * \note This function is provided solely for the convenience of + * Mbed TLS and may be removed at any time without notice. + * + * \param curve A PSA elliptic curve identifier + * (`PSA_ECC_CURVE_xxx`). + * \param byte_length The byte-length of a private key on \p curve. + * + * \return The corresponding Mbed TLS elliptic curve identifier + * (`MBEDTLS_ECP_DP_xxx`). + * \return #MBEDTLS_ECP_DP_NONE if \c curve is not recognized. + * \return #MBEDTLS_ECP_DP_NONE if \p byte_length is not + * correct for \p curve. + */ +mbedtls_ecp_group_id mbedtls_ecc_group_of_psa( psa_ecc_curve_t curve, + size_t byte_length ); +#endif /* MBEDTLS_ECP_C */ + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_EXTRA_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_platform.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_platform.h new file mode 100644 index 0000000..d85a719 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_platform.h @@ -0,0 +1,102 @@ +/** + * \file psa/crypto_platform.h + * + * \brief PSA cryptography module: Mbed TLS platform definitions + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * This file contains platform-dependent type definitions. + * + * In implementations with isolation between the application and the + * cryptography module, implementers should take care to ensure that + * the definitions that are exposed to applications match what the + * module implements. + */ +/* + * Copyright (C) 2018, ARM Limited, 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef PSA_CRYPTO_PLATFORM_H +#define PSA_CRYPTO_PLATFORM_H + +/* Include the Mbed TLS configuration file, the way Mbed TLS does it + * in each of its header files. */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +/* PSA requires several types which C99 provides in stdint.h. */ +#include + +/* Integral type representing a key handle. */ +typedef uint16_t psa_key_handle_t; + +/* This implementation distinguishes *application key identifiers*, which + * are the key identifiers specified by the application, from + * *key file identifiers*, which are the key identifiers that the library + * sees internally. The two types can be different if there is a remote + * call layer between the application and the library which supports + * multiple client applications that do not have access to each others' + * keys. The point of having different types is that the key file + * identifier may encode not only the key identifier specified by the + * application, but also the the identity of the application. + * + * Note that this is an internal concept of the library and the remote + * call layer. The application itself never sees anything other than + * #psa_app_key_id_t with its standard definition. + */ + +/* The application key identifier is always what the application sees as + * #psa_key_id_t. */ +typedef uint32_t psa_app_key_id_t; + +#if defined(MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER) + +#if defined(PSA_CRYPTO_SECURE) +/* Building for the PSA Crypto service on a PSA platform. */ +/* A key owner is a PSA partition identifier. */ +typedef int32_t psa_key_owner_id_t; +#endif + +typedef struct +{ + uint32_t key_id; + psa_key_owner_id_t owner; +} psa_key_file_id_t; +#define PSA_KEY_FILE_GET_KEY_ID( file_id ) ( ( file_id ).key_id ) + +/* Since crypto.h is used as part of the PSA Cryptography API specification, + * it must use standard types for things like the argument of psa_open_key(). + * If it wasn't for that constraint, psa_open_key() would take a + * `psa_key_file_id_t` argument. As a workaround, make `psa_key_id_t` an + * alias for `psa_key_file_id_t` when building for a multi-client service. */ +typedef psa_key_file_id_t psa_key_id_t; +#define PSA_KEY_ID_INIT {0, 0} + +#else /* !MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER */ + +/* By default, a key file identifier is just the application key identifier. */ +typedef psa_app_key_id_t psa_key_file_id_t; +#define PSA_KEY_FILE_GET_KEY_ID( id ) ( id ) + +#endif /* !MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER */ + +#endif /* PSA_CRYPTO_PLATFORM_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_se_driver.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_se_driver.h new file mode 100644 index 0000000..7ac1ed1 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_se_driver.h @@ -0,0 +1,1388 @@ +/** + * \file psa/crypto_se_driver.h + * \brief PSA external cryptoprocessor driver module + * + * This header declares types and function signatures for cryptography + * drivers that access key material via opaque references. + * This is meant for cryptoprocessors that have a separate key storage from the + * space in which the PSA Crypto implementation runs, typically secure + * elements (SEs). + * + * This file is part of the PSA Crypto Driver HAL (hardware abstraction layer), + * containing functions for driver developers to implement to enable hardware + * to be called in a standardized way by a PSA Cryptography API + * implementation. The functions comprising the driver HAL, which driver + * authors implement, are not intended to be called by application developers. + */ + +/* + * Copyright (C) 2018, ARM Limited, 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 PSA_CRYPTO_SE_DRIVER_H +#define PSA_CRYPTO_SE_DRIVER_H + +#include "crypto_driver_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup se_init Secure element driver initialization + */ +/**@{*/ + +/** \brief Driver context structure + * + * Driver functions receive a pointer to this structure. + * Each registered driver has one instance of this structure. + * + * Implementations must include the fields specified here and + * may include other fields. + */ +typedef struct { + /** A read-only pointer to the driver's persistent data. + * + * Drivers typically use this persistent data to keep track of + * which slot numbers are available. This is only a guideline: + * drivers may use the persistent data for any purpose, keeping + * in mind the restrictions on when the persistent data is saved + * to storage: the persistent data is only saved after calling + * certain functions that receive a writable pointer to the + * persistent data. + * + * The core allocates a memory buffer for the persistent data. + * The pointer is guaranteed to be suitably aligned for any data type, + * like a pointer returned by `malloc` (but the core can use any + * method to allocate the buffer, not necessarily `malloc`). + * + * The size of this buffer is in the \c persistent_data_size field of + * this structure. + * + * Before the driver is initialized for the first time, the content of + * the persistent data is all-bits-zero. After a driver upgrade, if the + * size of the persistent data has increased, the original data is padded + * on the right with zeros; if the size has decreased, the original data + * is truncated to the new size. + * + * This pointer is to read-only data. Only a few driver functions are + * allowed to modify the persistent data. These functions receive a + * writable pointer. These functions are: + * - psa_drv_se_t::p_init + * - psa_drv_se_key_management_t::p_allocate + * - psa_drv_se_key_management_t::p_destroy + * + * The PSA Cryptography core saves the persistent data from one + * session to the next. It does this before returning from API functions + * that call a driver method that is allowed to modify the persistent + * data, specifically: + * - psa_crypto_init() causes a call to psa_drv_se_t::p_init, and may call + * psa_drv_se_key_management_t::p_destroy to complete an action + * that was interrupted by a power failure. + * - Key creation functions cause a call to + * psa_drv_se_key_management_t::p_allocate, and may cause a call to + * psa_drv_se_key_management_t::p_destroy in case an error occurs. + * - psa_destroy_key() causes a call to + * psa_drv_se_key_management_t::p_destroy. + */ + const void *const persistent_data; + + /** The size of \c persistent_data in bytes. + * + * This is always equal to the value of the `persistent_data_size` field + * of the ::psa_drv_se_t structure when the driver is registered. + */ + const size_t persistent_data_size; + + /** Driver transient data. + * + * The core initializes this value to 0 and does not read or modify it + * afterwards. The driver may store whatever it wants in this field. + */ + uintptr_t transient_data; +} psa_drv_se_context_t; + +/** \brief A driver initialization function. + * + * \param[in,out] drv_context The driver context structure. + * \param[in,out] persistent_data A pointer to the persistent data + * that allows writing. + * \param lifetime The lifetime value for which this driver + * is registered. + * + * \retval #PSA_SUCCESS + * The driver is operational. + * The core will update the persistent data in storage. + * \return + * Any other return value prevents the driver from being used in + * this session. + * The core will NOT update the persistent data in storage. + */ +typedef psa_status_t (*psa_drv_se_init_t)(psa_drv_se_context_t *drv_context, + void *persistent_data, + psa_key_lifetime_t lifetime); + +#if defined(__DOXYGEN_ONLY__) || !defined(MBEDTLS_PSA_CRYPTO_SE_C) +/* Mbed Crypto with secure element support enabled defines this type in + * crypto_types.h because it is also visible to applications through an + * implementation-specific extension. + * For the PSA Cryptography specification, this type is only visible + * via crypto_se_driver.h. */ +/** An internal designation of a key slot between the core part of the + * PSA Crypto implementation and the driver. The meaning of this value + * is driver-dependent. */ +typedef uint64_t psa_key_slot_number_t; +#endif /* __DOXYGEN_ONLY__ || !MBEDTLS_PSA_CRYPTO_SE_C */ + +/**@}*/ + +/** \defgroup se_mac Secure Element Message Authentication Codes + * Generation and authentication of Message Authentication Codes (MACs) using + * a secure element can be done either as a single function call (via the + * `psa_drv_se_mac_generate_t` or `psa_drv_se_mac_verify_t` functions), or in + * parts using the following sequence: + * - `psa_drv_se_mac_setup_t` + * - `psa_drv_se_mac_update_t` + * - `psa_drv_se_mac_update_t` + * - ... + * - `psa_drv_se_mac_finish_t` or `psa_drv_se_mac_finish_verify_t` + * + * If a previously started secure element MAC operation needs to be terminated, + * it should be done so by the `psa_drv_se_mac_abort_t`. Failure to do so may + * result in allocated resources not being freed or in other undefined + * behavior. + */ +/**@{*/ +/** \brief A function that starts a secure element MAC operation for a PSA + * Crypto Driver implementation + * + * \param[in,out] drv_context The driver context structure. + * \param[in,out] op_context A structure that will contain the + * hardware-specific MAC context + * \param[in] key_slot The slot of the key to be used for the + * operation + * \param[in] algorithm The algorithm to be used to underly the MAC + * operation + * + * \retval PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_se_mac_setup_t)(psa_drv_se_context_t *drv_context, + void *op_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t algorithm); + +/** \brief A function that continues a previously started secure element MAC + * operation + * + * \param[in,out] op_context A hardware-specific structure for the + * previously-established MAC operation to be + * updated + * \param[in] p_input A buffer containing the message to be appended + * to the MAC operation + * \param[in] input_length The size in bytes of the input message buffer + */ +typedef psa_status_t (*psa_drv_se_mac_update_t)(void *op_context, + const uint8_t *p_input, + size_t input_length); + +/** \brief a function that completes a previously started secure element MAC + * operation by returning the resulting MAC. + * + * \param[in,out] op_context A hardware-specific structure for the + * previously started MAC operation to be + * finished + * \param[out] p_mac A buffer where the generated MAC will be + * placed + * \param[in] mac_size The size in bytes of the buffer that has been + * allocated for the `output` buffer + * \param[out] p_mac_length After completion, will contain the number of + * bytes placed in the `p_mac` buffer + * + * \retval PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_se_mac_finish_t)(void *op_context, + uint8_t *p_mac, + size_t mac_size, + size_t *p_mac_length); + +/** \brief A function that completes a previously started secure element MAC + * operation by comparing the resulting MAC against a provided value + * + * \param[in,out] op_context A hardware-specific structure for the previously + * started MAC operation to be fiinished + * \param[in] p_mac The MAC value against which the resulting MAC + * will be compared against + * \param[in] mac_length The size in bytes of the value stored in `p_mac` + * + * \retval PSA_SUCCESS + * The operation completed successfully and the MACs matched each + * other + * \retval PSA_ERROR_INVALID_SIGNATURE + * The operation completed successfully, but the calculated MAC did + * not match the provided MAC + */ +typedef psa_status_t (*psa_drv_se_mac_finish_verify_t)(void *op_context, + const uint8_t *p_mac, + size_t mac_length); + +/** \brief A function that aborts a previous started secure element MAC + * operation + * + * \param[in,out] op_context A hardware-specific structure for the previously + * started MAC operation to be aborted + */ +typedef psa_status_t (*psa_drv_se_mac_abort_t)(void *op_context); + +/** \brief A function that performs a secure element MAC operation in one + * command and returns the calculated MAC + * + * \param[in,out] drv_context The driver context structure. + * \param[in] p_input A buffer containing the message to be MACed + * \param[in] input_length The size in bytes of `p_input` + * \param[in] key_slot The slot of the key to be used + * \param[in] alg The algorithm to be used to underlie the MAC + * operation + * \param[out] p_mac A buffer where the generated MAC will be + * placed + * \param[in] mac_size The size in bytes of the `p_mac` buffer + * \param[out] p_mac_length After completion, will contain the number of + * bytes placed in the `output` buffer + * + * \retval PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_se_mac_generate_t)(psa_drv_se_context_t *drv_context, + const uint8_t *p_input, + size_t input_length, + psa_key_slot_number_t key_slot, + psa_algorithm_t alg, + uint8_t *p_mac, + size_t mac_size, + size_t *p_mac_length); + +/** \brief A function that performs a secure element MAC operation in one + * command and compares the resulting MAC against a provided value + * + * \param[in,out] drv_context The driver context structure. + * \param[in] p_input A buffer containing the message to be MACed + * \param[in] input_length The size in bytes of `input` + * \param[in] key_slot The slot of the key to be used + * \param[in] alg The algorithm to be used to underlie the MAC + * operation + * \param[in] p_mac The MAC value against which the resulting MAC will + * be compared against + * \param[in] mac_length The size in bytes of `mac` + * + * \retval PSA_SUCCESS + * The operation completed successfully and the MACs matched each + * other + * \retval PSA_ERROR_INVALID_SIGNATURE + * The operation completed successfully, but the calculated MAC did + * not match the provided MAC + */ +typedef psa_status_t (*psa_drv_se_mac_verify_t)(psa_drv_se_context_t *drv_context, + const uint8_t *p_input, + size_t input_length, + psa_key_slot_number_t key_slot, + psa_algorithm_t alg, + const uint8_t *p_mac, + size_t mac_length); + +/** \brief A struct containing all of the function pointers needed to + * perform secure element MAC operations + * + * PSA Crypto API implementations should populate the table as appropriate + * upon startup. + * + * If one of the functions is not implemented (such as + * `psa_drv_se_mac_generate_t`), it should be set to NULL. + * + * Driver implementers should ensure that they implement all of the functions + * that make sense for their hardware, and that they provide a full solution + * (for example, if they support `p_setup`, they should also support + * `p_update` and at least one of `p_finish` or `p_finish_verify`). + * + */ +typedef struct { + /**The size in bytes of the hardware-specific secure element MAC context + * structure + */ + size_t context_size; + /** Function that performs a MAC setup operation + */ + psa_drv_se_mac_setup_t p_setup; + /** Function that performs a MAC update operation + */ + psa_drv_se_mac_update_t p_update; + /** Function that completes a MAC operation + */ + psa_drv_se_mac_finish_t p_finish; + /** Function that completes a MAC operation with a verify check + */ + psa_drv_se_mac_finish_verify_t p_finish_verify; + /** Function that aborts a previoustly started MAC operation + */ + psa_drv_se_mac_abort_t p_abort; + /** Function that performs a MAC operation in one call + */ + psa_drv_se_mac_generate_t p_mac; + /** Function that performs a MAC and verify operation in one call + */ + psa_drv_se_mac_verify_t p_mac_verify; +} psa_drv_se_mac_t; +/**@}*/ + +/** \defgroup se_cipher Secure Element Symmetric Ciphers + * + * Encryption and Decryption using secure element keys in block modes other + * than ECB must be done in multiple parts, using the following flow: + * - `psa_drv_se_cipher_setup_t` + * - `psa_drv_se_cipher_set_iv_t` (optional depending upon block mode) + * - `psa_drv_se_cipher_update_t` + * - `psa_drv_se_cipher_update_t` + * - ... + * - `psa_drv_se_cipher_finish_t` + * + * If a previously started secure element Cipher operation needs to be + * terminated, it should be done so by the `psa_drv_se_cipher_abort_t`. Failure + * to do so may result in allocated resources not being freed or in other + * undefined behavior. + * + * In situations where a PSA Cryptographic API implementation is using a block + * mode not-supported by the underlying hardware or driver, it can construct + * the block mode itself, while calling the `psa_drv_se_cipher_ecb_t` function + * for the cipher operations. + */ +/**@{*/ + +/** \brief A function that provides the cipher setup function for a + * secure element driver + * + * \param[in,out] drv_context The driver context structure. + * \param[in,out] op_context A structure that will contain the + * hardware-specific cipher context. + * \param[in] key_slot The slot of the key to be used for the + * operation + * \param[in] algorithm The algorithm to be used in the cipher + * operation + * \param[in] direction Indicates whether the operation is an encrypt + * or decrypt + * + * \retval PSA_SUCCESS + * \retval PSA_ERROR_NOT_SUPPORTED + */ +typedef psa_status_t (*psa_drv_se_cipher_setup_t)(psa_drv_se_context_t *drv_context, + void *op_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t algorithm, + psa_encrypt_or_decrypt_t direction); + +/** \brief A function that sets the initialization vector (if + * necessary) for an secure element cipher operation + * + * Rationale: The `psa_se_cipher_*` operation in the PSA Cryptographic API has + * two IV functions: one to set the IV, and one to generate it internally. The + * generate function is not necessary for the drivers to implement as the PSA + * Crypto implementation can do the generation using its RNG features. + * + * \param[in,out] op_context A structure that contains the previously set up + * hardware-specific cipher context + * \param[in] p_iv A buffer containing the initialization vector + * \param[in] iv_length The size (in bytes) of the `p_iv` buffer + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_se_cipher_set_iv_t)(void *op_context, + const uint8_t *p_iv, + size_t iv_length); + +/** \brief A function that continues a previously started secure element cipher + * operation + * + * \param[in,out] op_context A hardware-specific structure for the + * previously started cipher operation + * \param[in] p_input A buffer containing the data to be + * encrypted/decrypted + * \param[in] input_size The size in bytes of the buffer pointed to + * by `p_input` + * \param[out] p_output The caller-allocated buffer where the + * output will be placed + * \param[in] output_size The allocated size in bytes of the + * `p_output` buffer + * \param[out] p_output_length After completion, will contain the number + * of bytes placed in the `p_output` buffer + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_se_cipher_update_t)(void *op_context, + const uint8_t *p_input, + size_t input_size, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** \brief A function that completes a previously started secure element cipher + * operation + * + * \param[in,out] op_context A hardware-specific structure for the + * previously started cipher operation + * \param[out] p_output The caller-allocated buffer where the output + * will be placed + * \param[in] output_size The allocated size in bytes of the `p_output` + * buffer + * \param[out] p_output_length After completion, will contain the number of + * bytes placed in the `p_output` buffer + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_se_cipher_finish_t)(void *op_context, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** \brief A function that aborts a previously started secure element cipher + * operation + * + * \param[in,out] op_context A hardware-specific structure for the + * previously started cipher operation + */ +typedef psa_status_t (*psa_drv_se_cipher_abort_t)(void *op_context); + +/** \brief A function that performs the ECB block mode for secure element + * cipher operations + * + * Note: this function should only be used with implementations that do not + * provide a needed higher-level operation. + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key_slot The slot of the key to be used for the operation + * \param[in] algorithm The algorithm to be used in the cipher operation + * \param[in] direction Indicates whether the operation is an encrypt or + * decrypt + * \param[in] p_input A buffer containing the data to be + * encrypted/decrypted + * \param[in] input_size The size in bytes of the buffer pointed to by + * `p_input` + * \param[out] p_output The caller-allocated buffer where the output + * will be placed + * \param[in] output_size The allocated size in bytes of the `p_output` + * buffer + * + * \retval PSA_SUCCESS + * \retval PSA_ERROR_NOT_SUPPORTED + */ +typedef psa_status_t (*psa_drv_se_cipher_ecb_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t algorithm, + psa_encrypt_or_decrypt_t direction, + const uint8_t *p_input, + size_t input_size, + uint8_t *p_output, + size_t output_size); + +/** + * \brief A struct containing all of the function pointers needed to implement + * cipher operations using secure elements. + * + * PSA Crypto API implementations should populate instances of the table as + * appropriate upon startup or at build time. + * + * If one of the functions is not implemented (such as + * `psa_drv_se_cipher_ecb_t`), it should be set to NULL. + */ +typedef struct { + /** The size in bytes of the hardware-specific secure element cipher + * context structure + */ + size_t context_size; + /** Function that performs a cipher setup operation */ + psa_drv_se_cipher_setup_t p_setup; + /** Function that sets a cipher IV (if necessary) */ + psa_drv_se_cipher_set_iv_t p_set_iv; + /** Function that performs a cipher update operation */ + psa_drv_se_cipher_update_t p_update; + /** Function that completes a cipher operation */ + psa_drv_se_cipher_finish_t p_finish; + /** Function that aborts a cipher operation */ + psa_drv_se_cipher_abort_t p_abort; + /** Function that performs ECB mode for a cipher operation + * (Danger: ECB mode should not be used directly by clients of the PSA + * Crypto Client API) + */ + psa_drv_se_cipher_ecb_t p_ecb; +} psa_drv_se_cipher_t; + +/**@}*/ + +/** \defgroup se_asymmetric Secure Element Asymmetric Cryptography + * + * Since the amount of data that can (or should) be encrypted or signed using + * asymmetric keys is limited by the key size, asymmetric key operations using + * keys in a secure element must be done in single function calls. + */ +/**@{*/ + +/** + * \brief A function that signs a hash or short message with a private key in + * a secure element + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key_slot Key slot of an asymmetric key pair + * \param[in] alg A signature algorithm that is compatible + * with the type of `key` + * \param[in] p_hash The hash to sign + * \param[in] hash_length Size of the `p_hash` buffer in bytes + * \param[out] p_signature Buffer where the signature is to be written + * \param[in] signature_size Size of the `p_signature` buffer in bytes + * \param[out] p_signature_length On success, the number of bytes + * that make up the returned signature value + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_se_asymmetric_sign_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t alg, + const uint8_t *p_hash, + size_t hash_length, + uint8_t *p_signature, + size_t signature_size, + size_t *p_signature_length); + +/** + * \brief A function that verifies the signature a hash or short message using + * an asymmetric public key in a secure element + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key_slot Key slot of a public key or an asymmetric key + * pair + * \param[in] alg A signature algorithm that is compatible with + * the type of `key` + * \param[in] p_hash The hash whose signature is to be verified + * \param[in] hash_length Size of the `p_hash` buffer in bytes + * \param[in] p_signature Buffer containing the signature to verify + * \param[in] signature_length Size of the `p_signature` buffer in bytes + * + * \retval PSA_SUCCESS + * The signature is valid. + */ +typedef psa_status_t (*psa_drv_se_asymmetric_verify_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t alg, + const uint8_t *p_hash, + size_t hash_length, + const uint8_t *p_signature, + size_t signature_length); + +/** + * \brief A function that encrypts a short message with an asymmetric public + * key in a secure element + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key_slot Key slot of a public key or an asymmetric key + * pair + * \param[in] alg An asymmetric encryption algorithm that is + * compatible with the type of `key` + * \param[in] p_input The message to encrypt + * \param[in] input_length Size of the `p_input` buffer in bytes + * \param[in] p_salt A salt or label, if supported by the + * encryption algorithm + * If the algorithm does not support a + * salt, pass `NULL`. + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass `NULL`. + * For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported. + * \param[in] salt_length Size of the `p_salt` buffer in bytes + * If `p_salt` is `NULL`, pass 0. + * \param[out] p_output Buffer where the encrypted message is to + * be written + * \param[in] output_size Size of the `p_output` buffer in bytes + * \param[out] p_output_length On success, the number of bytes that make up + * the returned output + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_se_asymmetric_encrypt_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t alg, + const uint8_t *p_input, + size_t input_length, + const uint8_t *p_salt, + size_t salt_length, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** + * \brief A function that decrypts a short message with an asymmetric private + * key in a secure element. + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key_slot Key slot of an asymmetric key pair + * \param[in] alg An asymmetric encryption algorithm that is + * compatible with the type of `key` + * \param[in] p_input The message to decrypt + * \param[in] input_length Size of the `p_input` buffer in bytes + * \param[in] p_salt A salt or label, if supported by the + * encryption algorithm + * If the algorithm does not support a + * salt, pass `NULL`. + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass `NULL`. + * For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported. + * \param[in] salt_length Size of the `p_salt` buffer in bytes + * If `p_salt` is `NULL`, pass 0. + * \param[out] p_output Buffer where the decrypted message is to + * be written + * \param[in] output_size Size of the `p_output` buffer in bytes + * \param[out] p_output_length On success, the number of bytes + * that make up the returned output + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_se_asymmetric_decrypt_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t alg, + const uint8_t *p_input, + size_t input_length, + const uint8_t *p_salt, + size_t salt_length, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** + * \brief A struct containing all of the function pointers needed to implement + * asymmetric cryptographic operations using secure elements. + * + * PSA Crypto API implementations should populate instances of the table as + * appropriate upon startup or at build time. + * + * If one of the functions is not implemented, it should be set to NULL. + */ +typedef struct { + /** Function that performs an asymmetric sign operation */ + psa_drv_se_asymmetric_sign_t p_sign; + /** Function that performs an asymmetric verify operation */ + psa_drv_se_asymmetric_verify_t p_verify; + /** Function that performs an asymmetric encrypt operation */ + psa_drv_se_asymmetric_encrypt_t p_encrypt; + /** Function that performs an asymmetric decrypt operation */ + psa_drv_se_asymmetric_decrypt_t p_decrypt; +} psa_drv_se_asymmetric_t; + +/**@}*/ + +/** \defgroup se_aead Secure Element Authenticated Encryption with Additional Data + * Authenticated Encryption with Additional Data (AEAD) operations with secure + * elements must be done in one function call. While this creates a burden for + * implementers as there must be sufficient space in memory for the entire + * message, it prevents decrypted data from being made available before the + * authentication operation is complete and the data is known to be authentic. + */ +/**@{*/ + +/** \brief A function that performs a secure element authenticated encryption + * operation + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key_slot Slot containing the key to use. + * \param[in] algorithm The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(`alg`) is true) + * \param[in] p_nonce Nonce or IV to use + * \param[in] nonce_length Size of the `p_nonce` buffer in bytes + * \param[in] p_additional_data Additional data that will be + * authenticated but not encrypted + * \param[in] additional_data_length Size of `p_additional_data` in bytes + * \param[in] p_plaintext Data that will be authenticated and + * encrypted + * \param[in] plaintext_length Size of `p_plaintext` in bytes + * \param[out] p_ciphertext Output buffer for the authenticated and + * encrypted data. The additional data is + * not part of this output. For algorithms + * where the encrypted data and the + * authentication tag are defined as + * separate outputs, the authentication + * tag is appended to the encrypted data. + * \param[in] ciphertext_size Size of the `p_ciphertext` buffer in + * bytes + * \param[out] p_ciphertext_length On success, the size of the output in + * the `p_ciphertext` buffer + * + * \retval #PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_se_aead_encrypt_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t algorithm, + const uint8_t *p_nonce, + size_t nonce_length, + const uint8_t *p_additional_data, + size_t additional_data_length, + const uint8_t *p_plaintext, + size_t plaintext_length, + uint8_t *p_ciphertext, + size_t ciphertext_size, + size_t *p_ciphertext_length); + +/** A function that peforms a secure element authenticated decryption operation + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key_slot Slot containing the key to use + * \param[in] algorithm The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(`alg`) is true) + * \param[in] p_nonce Nonce or IV to use + * \param[in] nonce_length Size of the `p_nonce` buffer in bytes + * \param[in] p_additional_data Additional data that has been + * authenticated but not encrypted + * \param[in] additional_data_length Size of `p_additional_data` in bytes + * \param[in] p_ciphertext Data that has been authenticated and + * encrypted. + * For algorithms where the encrypted data + * and the authentication tag are defined + * as separate inputs, the buffer must + * contain the encrypted data followed by + * the authentication tag. + * \param[in] ciphertext_length Size of `p_ciphertext` in bytes + * \param[out] p_plaintext Output buffer for the decrypted data + * \param[in] plaintext_size Size of the `p_plaintext` buffer in + * bytes + * \param[out] p_plaintext_length On success, the size of the output in + * the `p_plaintext` buffer + * + * \retval #PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_se_aead_decrypt_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t algorithm, + const uint8_t *p_nonce, + size_t nonce_length, + const uint8_t *p_additional_data, + size_t additional_data_length, + const uint8_t *p_ciphertext, + size_t ciphertext_length, + uint8_t *p_plaintext, + size_t plaintext_size, + size_t *p_plaintext_length); + +/** + * \brief A struct containing all of the function pointers needed to implement + * secure element Authenticated Encryption with Additional Data operations + * + * PSA Crypto API implementations should populate instances of the table as + * appropriate upon startup. + * + * If one of the functions is not implemented, it should be set to NULL. + */ +typedef struct { + /** Function that performs the AEAD encrypt operation */ + psa_drv_se_aead_encrypt_t p_encrypt; + /** Function that performs the AEAD decrypt operation */ + psa_drv_se_aead_decrypt_t p_decrypt; +} psa_drv_se_aead_t; +/**@}*/ + +/** \defgroup se_key_management Secure Element Key Management + * Currently, key management is limited to importing keys in the clear, + * destroying keys, and exporting keys in the clear. + * Whether a key may be exported is determined by the key policies in place + * on the key slot. + */ +/**@{*/ + +/** An enumeration indicating how a key is created. + */ +typedef enum +{ + PSA_KEY_CREATION_IMPORT, /**< During psa_import_key() */ + PSA_KEY_CREATION_GENERATE, /**< During psa_generate_key() */ + PSA_KEY_CREATION_DERIVE, /**< During psa_key_derivation_output_key() */ + PSA_KEY_CREATION_COPY, /**< During psa_copy_key() */ + +#ifndef __DOXYGEN_ONLY__ + /** A key is being registered with mbedtls_psa_register_se_key(). + * + * The core only passes this value to + * psa_drv_se_key_management_t::p_validate_slot_number, not to + * psa_drv_se_key_management_t::p_allocate. The call to + * `p_validate_slot_number` is not followed by any other call to the + * driver: the key is considered successfully registered if the call to + * `p_validate_slot_number` succeeds, or if `p_validate_slot_number` is + * null. + * + * With this creation method, the driver must return #PSA_SUCCESS if + * the given attributes are compatible with the existing key in the slot, + * and #PSA_ERROR_DOES_NOT_EXIST if the driver can determine that there + * is no key with the specified slot number. + * + * This is an Mbed Crypto extension. + */ + PSA_KEY_CREATION_REGISTER, +#endif +} psa_key_creation_method_t; + +/** \brief A function that allocates a slot for a key. + * + * To create a key in a specific slot in a secure element, the core + * first calls this function to determine a valid slot number, + * then calls a function to create the key material in that slot. + * In nominal conditions (that is, if no error occurs), + * the effect of a call to a key creation function in the PSA Cryptography + * API with a lifetime that places the key in a secure element is the + * following: + * -# The core calls psa_drv_se_key_management_t::p_allocate + * (or in some implementations + * psa_drv_se_key_management_t::p_validate_slot_number). The driver + * selects (or validates) a suitable slot number given the key attributes + * and the state of the secure element. + * -# The core calls a key creation function in the driver. + * + * The key creation functions in the PSA Cryptography API are: + * - psa_import_key(), which causes + * a call to `p_allocate` with \p method = #PSA_KEY_CREATION_IMPORT + * then a call to psa_drv_se_key_management_t::p_import. + * - psa_generate_key(), which causes + * a call to `p_allocate` with \p method = #PSA_KEY_CREATION_GENERATE + * then a call to psa_drv_se_key_management_t::p_import. + * - psa_key_derivation_output_key(), which causes + * a call to `p_allocate` with \p method = #PSA_KEY_CREATION_DERIVE + * then a call to psa_drv_se_key_derivation_t::p_derive. + * - psa_copy_key(), which causes + * a call to `p_allocate` with \p method = #PSA_KEY_CREATION_COPY + * then a call to psa_drv_se_key_management_t::p_export. + * + * In case of errors, other behaviors are possible. + * - If the PSA Cryptography subsystem dies after the first step, + * for example because the device has lost power abruptly, + * the second step may never happen, or may happen after a reset + * and re-initialization. Alternatively, after a reset and + * re-initialization, the core may call + * psa_drv_se_key_management_t::p_destroy on the slot number that + * was allocated (or validated) instead of calling a key creation function. + * - If an error occurs, the core may call + * psa_drv_se_key_management_t::p_destroy on the slot number that + * was allocated (or validated) instead of calling a key creation function. + * + * Errors and system resets also have an impact on the driver's persistent + * data. If a reset happens before the overall key creation process is + * completed (before or after the second step above), it is unspecified + * whether the persistent data after the reset is identical to what it + * was before or after the call to `p_allocate` (or `p_validate_slot_number`). + * + * \param[in,out] drv_context The driver context structure. + * \param[in,out] persistent_data A pointer to the persistent data + * that allows writing. + * \param[in] attributes Attributes of the key. + * \param method The way in which the key is being created. + * \param[out] key_slot Slot where the key will be stored. + * This must be a valid slot for a key of the + * chosen type. It must be unoccupied. + * + * \retval #PSA_SUCCESS + * Success. + * The core will record \c *key_slot as the key slot where the key + * is stored and will update the persistent data in storage. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + */ +typedef psa_status_t (*psa_drv_se_allocate_key_t)( + psa_drv_se_context_t *drv_context, + void *persistent_data, + const psa_key_attributes_t *attributes, + psa_key_creation_method_t method, + psa_key_slot_number_t *key_slot); + +/** \brief A function that determines whether a slot number is valid + * for a key. + * + * To create a key in a specific slot in a secure element, the core + * first calls this function to validate the choice of slot number, + * then calls a function to create the key material in that slot. + * See the documentation of #psa_drv_se_allocate_key_t for more details. + * + * As of the PSA Cryptography API specification version 1.0, there is no way + * for applications to trigger a call to this function. However some + * implementations offer the capability to create or declare a key in + * a specific slot via implementation-specific means, generally for the + * sake of initial device provisioning or onboarding. Such a mechanism may + * be added to a future version of the PSA Cryptography API specification. + * + * This function may update the driver's persistent data through + * \p persistent_data. The core will save the updated persistent data at the + * end of the key creation process. See the description of + * ::psa_drv_se_allocate_key_t for more information. + * + * \param[in,out] drv_context The driver context structure. + * \param[in,out] persistent_data A pointer to the persistent data + * that allows writing. + * \param[in] attributes Attributes of the key. + * \param method The way in which the key is being created. + * \param[in] key_slot Slot where the key is to be stored. + * + * \retval #PSA_SUCCESS + * The given slot number is valid for a key with the given + * attributes. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The given slot number is not valid for a key with the + * given attributes. This includes the case where the slot + * number is not valid at all. + * \retval #PSA_ERROR_ALREADY_EXISTS + * There is already a key with the specified slot number. + * Drivers may choose to return this error from the key + * creation function instead. + */ +typedef psa_status_t (*psa_drv_se_validate_slot_number_t)( + psa_drv_se_context_t *drv_context, + void *persistent_data, + const psa_key_attributes_t *attributes, + psa_key_creation_method_t method, + psa_key_slot_number_t key_slot); + +/** \brief A function that imports a key into a secure element in binary format + * + * This function can support any output from psa_export_key(). Refer to the + * documentation of psa_export_key() for the format for each key type. + * + * \param[in,out] drv_context The driver context structure. + * \param key_slot Slot where the key will be stored. + * This must be a valid slot for a key of the + * chosen type. It must be unoccupied. + * \param[in] attributes The key attributes, including the lifetime, + * the key type and the usage policy. + * Drivers should not access the key size stored + * in the attributes: it may not match the + * data passed in \p data. + * Drivers can call psa_get_key_lifetime(), + * psa_get_key_type(), + * psa_get_key_usage_flags() and + * psa_get_key_algorithm() to access this + * information. + * \param[in] data Buffer containing the key data. + * \param[in] data_length Size of the \p data buffer in bytes. + * \param[out] bits On success, the key size in bits. The driver + * must determine this value after parsing the + * key according to the key type. + * This value is not used if the function fails. + * + * \retval #PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_se_import_key_t)( + psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + size_t *bits); + +/** + * \brief A function that destroys a secure element key and restore the slot to + * its default state + * + * This function destroys the content of the key from a secure element. + * Implementations shall make a best effort to ensure that any previous content + * of the slot is unrecoverable. + * + * This function returns the specified slot to its default state. + * + * \param[in,out] drv_context The driver context structure. + * \param[in,out] persistent_data A pointer to the persistent data + * that allows writing. + * \param key_slot The key slot to erase. + * + * \retval #PSA_SUCCESS + * The slot's content, if any, has been erased. + */ +typedef psa_status_t (*psa_drv_se_destroy_key_t)( + psa_drv_se_context_t *drv_context, + void *persistent_data, + psa_key_slot_number_t key_slot); + +/** + * \brief A function that exports a secure element key in binary format + * + * The output of this function can be passed to psa_import_key() to + * create an equivalent object. + * + * If a key is created with `psa_import_key()` and then exported with + * this function, it is not guaranteed that the resulting data is + * identical: the implementation may choose a different representation + * of the same key if the format permits it. + * + * This function should generate output in the same format that + * `psa_export_key()` does. Refer to the + * documentation of `psa_export_key()` for the format for each key type. + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key Slot whose content is to be exported. This must + * be an occupied key slot. + * \param[out] p_data Buffer where the key data is to be written. + * \param[in] data_size Size of the `p_data` buffer in bytes. + * \param[out] p_data_length On success, the number of bytes + * that make up the key data. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_DOES_NOT_EXIST + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + */ +typedef psa_status_t (*psa_drv_se_export_key_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key, + uint8_t *p_data, + size_t data_size, + size_t *p_data_length); + +/** + * \brief A function that generates a symmetric or asymmetric key on a secure + * element + * + * If \p type is asymmetric (#PSA_KEY_TYPE_IS_ASYMMETRIC(\p type) = 1), + * the driver may export the public key at the time of generation, + * in the format documented for psa_export_public_key() by writing it + * to the \p pubkey buffer. + * This is optional, intended for secure elements that output the + * public key at generation time and that cannot export the public key + * later. Drivers that do not need this feature should leave + * \p *pubkey_length set to 0 and should + * implement the psa_drv_key_management_t::p_export_public function. + * Some implementations do not support this feature, in which case + * \p pubkey is \c NULL and \p pubkey_size is 0. + * + * \param[in,out] drv_context The driver context structure. + * \param key_slot Slot where the key will be stored. + * This must be a valid slot for a key of the + * chosen type. It must be unoccupied. + * \param[in] attributes The key attributes, including the lifetime, + * the key type and size, and the usage policy. + * Drivers can call psa_get_key_lifetime(), + * psa_get_key_type(), psa_get_key_bits(), + * psa_get_key_usage_flags() and + * psa_get_key_algorithm() to access this + * information. + * \param[out] pubkey A buffer where the driver can write the + * public key, when generating an asymmetric + * key pair. + * This is \c NULL when generating a symmetric + * key or if the core does not support + * exporting the public key at generation time. + * \param pubkey_size The size of the `pubkey` buffer in bytes. + * This is 0 when generating a symmetric + * key or if the core does not support + * exporting the public key at generation time. + * \param[out] pubkey_length On entry, this is always 0. + * On success, the number of bytes written to + * \p pubkey. If this is 0 or unchanged on return, + * the core will not read the \p pubkey buffer, + * and will instead call the driver's + * psa_drv_key_management_t::p_export_public + * function to export the public key when needed. + */ +typedef psa_status_t (*psa_drv_se_generate_key_t)( + psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + const psa_key_attributes_t *attributes, + uint8_t *pubkey, size_t pubkey_size, size_t *pubkey_length); + +/** + * \brief A struct containing all of the function pointers needed to for secure + * element key management + * + * PSA Crypto API implementations should populate instances of the table as + * appropriate upon startup or at build time. + * + * If one of the functions is not implemented, it should be set to NULL. + */ +typedef struct { + /** Function that allocates a slot for a key. */ + psa_drv_se_allocate_key_t p_allocate; + /** Function that checks the validity of a slot for a key. */ + psa_drv_se_validate_slot_number_t p_validate_slot_number; + /** Function that performs a key import operation */ + psa_drv_se_import_key_t p_import; + /** Function that performs a generation */ + psa_drv_se_generate_key_t p_generate; + /** Function that performs a key destroy operation */ + psa_drv_se_destroy_key_t p_destroy; + /** Function that performs a key export operation */ + psa_drv_se_export_key_t p_export; + /** Function that performs a public key export operation */ + psa_drv_se_export_key_t p_export_public; +} psa_drv_se_key_management_t; + +/**@}*/ + +/** \defgroup driver_derivation Secure Element Key Derivation and Agreement + * Key derivation is the process of generating new key material using an + * existing key and additional parameters, iterating through a basic + * cryptographic function, such as a hash. + * Key agreement is a part of cryptographic protocols that allows two parties + * to agree on the same key value, but starting from different original key + * material. + * The flows are similar, and the PSA Crypto Driver Model uses the same functions + * for both of the flows. + * + * There are two different final functions for the flows, + * `psa_drv_se_key_derivation_derive` and `psa_drv_se_key_derivation_export`. + * `psa_drv_se_key_derivation_derive` is used when the key material should be + * placed in a slot on the hardware and not exposed to the caller. + * `psa_drv_se_key_derivation_export` is used when the key material should be + * returned to the PSA Cryptographic API implementation. + * + * Different key derivation algorithms require a different number of inputs. + * Instead of having an API that takes as input variable length arrays, which + * can be problemmatic to manage on embedded platforms, the inputs are passed + * to the driver via a function, `psa_drv_se_key_derivation_collateral`, that + * is called multiple times with different `collateral_id`s. Thus, for a key + * derivation algorithm that required 3 paramter inputs, the flow would look + * something like: + * ~~~~~~~~~~~~~{.c} + * psa_drv_se_key_derivation_setup(kdf_algorithm, source_key, dest_key_size_bytes); + * psa_drv_se_key_derivation_collateral(kdf_algorithm_collateral_id_0, + * p_collateral_0, + * collateral_0_size); + * psa_drv_se_key_derivation_collateral(kdf_algorithm_collateral_id_1, + * p_collateral_1, + * collateral_1_size); + * psa_drv_se_key_derivation_collateral(kdf_algorithm_collateral_id_2, + * p_collateral_2, + * collateral_2_size); + * psa_drv_se_key_derivation_derive(); + * ~~~~~~~~~~~~~ + * + * key agreement example: + * ~~~~~~~~~~~~~{.c} + * psa_drv_se_key_derivation_setup(alg, source_key. dest_key_size_bytes); + * psa_drv_se_key_derivation_collateral(DHE_PUBKEY, p_pubkey, pubkey_size); + * psa_drv_se_key_derivation_export(p_session_key, + * session_key_size, + * &session_key_length); + * ~~~~~~~~~~~~~ + */ +/**@{*/ + +/** \brief A function that Sets up a secure element key derivation operation by + * specifying the algorithm and the source key sot + * + * \param[in,out] drv_context The driver context structure. + * \param[in,out] op_context A hardware-specific structure containing any + * context information for the implementation + * \param[in] kdf_alg The algorithm to be used for the key derivation + * \param[in] source_key The key to be used as the source material for + * the key derivation + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_se_key_derivation_setup_t)(psa_drv_se_context_t *drv_context, + void *op_context, + psa_algorithm_t kdf_alg, + psa_key_slot_number_t source_key); + +/** \brief A function that provides collateral (parameters) needed for a secure + * element key derivation or key agreement operation + * + * Since many key derivation algorithms require multiple parameters, it is + * expeced that this function may be called multiple times for the same + * operation, each with a different algorithm-specific `collateral_id` + * + * \param[in,out] op_context A hardware-specific structure containing any + * context information for the implementation + * \param[in] collateral_id An ID for the collateral being provided + * \param[in] p_collateral A buffer containing the collateral data + * \param[in] collateral_size The size in bytes of the collateral + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_se_key_derivation_collateral_t)(void *op_context, + uint32_t collateral_id, + const uint8_t *p_collateral, + size_t collateral_size); + +/** \brief A function that performs the final secure element key derivation + * step and place the generated key material in a slot + * + * \param[in,out] op_context A hardware-specific structure containing any + * context information for the implementation + * \param[in] dest_key The slot where the generated key material + * should be placed + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_se_key_derivation_derive_t)(void *op_context, + psa_key_slot_number_t dest_key); + +/** \brief A function that performs the final step of a secure element key + * agreement and place the generated key material in a buffer + * + * \param[out] p_output Buffer in which to place the generated key + * material + * \param[in] output_size The size in bytes of `p_output` + * \param[out] p_output_length Upon success, contains the number of bytes of + * key material placed in `p_output` + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_se_key_derivation_export_t)(void *op_context, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** + * \brief A struct containing all of the function pointers needed to for secure + * element key derivation and agreement + * + * PSA Crypto API implementations should populate instances of the table as + * appropriate upon startup. + * + * If one of the functions is not implemented, it should be set to NULL. + */ +typedef struct { + /** The driver-specific size of the key derivation context */ + size_t context_size; + /** Function that performs a key derivation setup */ + psa_drv_se_key_derivation_setup_t p_setup; + /** Function that sets key derivation collateral */ + psa_drv_se_key_derivation_collateral_t p_collateral; + /** Function that performs a final key derivation step */ + psa_drv_se_key_derivation_derive_t p_derive; + /** Function that perforsm a final key derivation or agreement and + * exports the key */ + psa_drv_se_key_derivation_export_t p_export; +} psa_drv_se_key_derivation_t; + +/**@}*/ + +/** \defgroup se_registration Secure element driver registration + */ +/**@{*/ + +/** A structure containing pointers to all the entry points of a + * secure element driver. + * + * Future versions of this specification may add extra substructures at + * the end of this structure. + */ +typedef struct { + /** The version of the driver HAL that this driver implements. + * This is a protection against loading driver binaries built against + * a different version of this specification. + * Use #PSA_DRV_SE_HAL_VERSION. + */ + uint32_t hal_version; + + /** The size of the driver's persistent data in bytes. + * + * This can be 0 if the driver does not need persistent data. + * + * See the documentation of psa_drv_se_context_t::persistent_data + * for more information about why and how a driver can use + * persistent data. + */ + size_t persistent_data_size; + + /** The driver initialization function. + * + * This function is called once during the initialization of the + * PSA Cryptography subsystem, before any other function of the + * driver is called. If this function returns a failure status, + * the driver will be unusable, at least until the next system reset. + * + * If this field is \c NULL, it is equivalent to a function that does + * nothing and returns #PSA_SUCCESS. + */ + psa_drv_se_init_t p_init; + + const psa_drv_se_key_management_t *key_management; + const psa_drv_se_mac_t *mac; + const psa_drv_se_cipher_t *cipher; + const psa_drv_se_aead_t *aead; + const psa_drv_se_asymmetric_t *asymmetric; + const psa_drv_se_key_derivation_t *derivation; +} psa_drv_se_t; + +/** The current version of the secure element driver HAL. + */ +/* 0.0.0 patchlevel 5 */ +#define PSA_DRV_SE_HAL_VERSION 0x00000005 + +/** Register an external cryptoprocessor (secure element) driver. + * + * This function is only intended to be used by driver code, not by + * application code. In implementations with separation between the + * PSA cryptography module and applications, this function should + * only be available to callers that run in the same memory space as + * the cryptography module, and should not be exposed to applications + * running in a different memory space. + * + * This function may be called before psa_crypto_init(). It is + * implementation-defined whether this function may be called + * after psa_crypto_init(). + * + * \note Implementations store metadata about keys including the lifetime + * value. Therefore, from one instantiation of the PSA Cryptography + * library to the next one, if there is a key in storage with a certain + * lifetime value, you must always register the same driver (or an + * updated version that communicates with the same secure element) + * with the same lifetime value. + * + * \param lifetime The lifetime value through which this driver will + * be exposed to applications. + * The values #PSA_KEY_LIFETIME_VOLATILE and + * #PSA_KEY_LIFETIME_PERSISTENT are reserved and + * may not be used for drivers. Implementations + * may reserve other values. + * \param[in] methods The method table of the driver. This structure must + * remain valid for as long as the cryptography + * module keeps running. It is typically a global + * constant. + * + * \return PSA_SUCCESS + * The driver was successfully registered. Applications can now + * use \p lifetime to access keys through the methods passed to + * this function. + * \return PSA_ERROR_BAD_STATE + * This function was called after the initialization of the + * cryptography module, and this implementation does not support + * driver registration at this stage. + * \return PSA_ERROR_ALREADY_EXISTS + * There is already a registered driver for this value of \p lifetime. + * \return PSA_ERROR_INVALID_ARGUMENT + * \p lifetime is a reserved value. + * \return PSA_ERROR_NOT_SUPPORTED + * `methods->hal_version` is not supported by this implementation. + * \return PSA_ERROR_INSUFFICIENT_MEMORY + * \return PSA_ERROR_NOT_PERMITTED + */ +psa_status_t psa_register_se_driver( + psa_key_lifetime_t lifetime, + const psa_drv_se_t *methods); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_SE_DRIVER_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_sizes.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_sizes.h new file mode 100644 index 0000000..1f04222 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_sizes.h @@ -0,0 +1,662 @@ +/** + * \file psa/crypto_sizes.h + * + * \brief PSA cryptography module: Mbed TLS buffer size macros + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * This file contains the definitions of macros that are useful to + * compute buffer sizes. The signatures and semantics of these macros + * are standardized, but the definitions are not, because they depend on + * the available algorithms and, in some cases, on permitted tolerances + * on buffer sizes. + * + * In implementations with isolation between the application and the + * cryptography module, implementers should take care to ensure that + * the definitions that are exposed to applications match what the + * module implements. + * + * Macros that compute sizes whose values do not depend on the + * implementation are in crypto.h. + */ +/* + * Copyright (C) 2018, ARM Limited, 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef PSA_CRYPTO_SIZES_H +#define PSA_CRYPTO_SIZES_H + +/* Include the Mbed TLS configuration file, the way Mbed TLS does it + * in each of its header files. */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#define PSA_BITS_TO_BYTES(bits) (((bits) + 7) / 8) +#define PSA_BYTES_TO_BITS(bytes) ((bytes) * 8) + +#define PSA_ROUND_UP_TO_MULTIPLE(block_size, length) \ + (((length) + (block_size) - 1) / (block_size) * (block_size)) + +/** The size of the output of psa_hash_finish(), in bytes. + * + * This is also the hash size that psa_hash_verify() expects. + * + * \param alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p alg) is true), or an HMAC algorithm + * (#PSA_ALG_HMAC(\c hash_alg) where \c hash_alg is a + * hash algorithm). + * + * \return The hash size for the specified hash algorithm. + * If the hash algorithm is not recognized, return 0. + * An implementation may return either 0 or the correct size + * for a hash algorithm that it recognizes, but does not support. + */ +#define PSA_HASH_SIZE(alg) \ + ( \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD2 ? 16 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD4 ? 16 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 16 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 20 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 20 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_224 ? 28 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_256 ? 32 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_384 ? 48 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512 ? 64 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 28 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 32 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 28 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 32 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 48 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 64 : \ + 0) + +/** \def PSA_HASH_MAX_SIZE + * + * Maximum size of a hash. + * + * This macro must expand to a compile-time constant integer. This value + * should be the maximum size of a hash supported by the implementation, + * in bytes, and must be no smaller than this maximum. + */ +/* Note: for HMAC-SHA-3, the block size is 144 bytes for HMAC-SHA3-226, + * 136 bytes for HMAC-SHA3-256, 104 bytes for SHA3-384, 72 bytes for + * HMAC-SHA3-512. */ +#if defined(MBEDTLS_SHA512_C) +#define PSA_HASH_MAX_SIZE 64 +#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 128 +#else +#define PSA_HASH_MAX_SIZE 32 +#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 64 +#endif + +/** \def PSA_MAC_MAX_SIZE + * + * Maximum size of a MAC. + * + * This macro must expand to a compile-time constant integer. This value + * should be the maximum size of a MAC supported by the implementation, + * in bytes, and must be no smaller than this maximum. + */ +/* All non-HMAC MACs have a maximum size that's smaller than the + * minimum possible value of PSA_HASH_MAX_SIZE in this implementation. */ +/* Note that the encoding of truncated MAC algorithms limits this value + * to 64 bytes. + */ +#define PSA_MAC_MAX_SIZE PSA_HASH_MAX_SIZE + +/** The tag size for an AEAD algorithm, in bytes. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return The tag size for the specified algorithm. + * If the AEAD algorithm does not have an identified + * tag that can be distinguished from the rest of + * the ciphertext, return 0. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +#define PSA_AEAD_TAG_LENGTH(alg) \ + (PSA_ALG_IS_AEAD(alg) ? \ + (((alg) & PSA_ALG_AEAD_TAG_LENGTH_MASK) >> PSA_AEAD_TAG_LENGTH_OFFSET) : \ + 0) + +/* The maximum size of an RSA key on this implementation, in bits. + * This is a vendor-specific macro. + * + * Mbed TLS does not set a hard limit on the size of RSA keys: any key + * whose parameters fit in a bignum is accepted. However large keys can + * induce a large memory usage and long computation times. Unlike other + * auxiliary macros in this file and in crypto.h, which reflect how the + * library is configured, this macro defines how the library is + * configured. This implementation refuses to import or generate an + * RSA key whose size is larger than the value defined here. + * + * Note that an implementation may set different size limits for different + * operations, and does not need to accept all key sizes up to the limit. */ +#define PSA_VENDOR_RSA_MAX_KEY_BITS 4096 + +/* The maximum size of an ECC key on this implementation, in bits. + * This is a vendor-specific macro. */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 521 +#elif defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 512 +#elif defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 448 +#elif defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 384 +#elif defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 384 +#elif defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256 +#elif defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256 +#elif defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256 +#elif defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 255 +#elif defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 224 +#elif defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 224 +#elif defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 192 +#elif defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 192 +#else +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 0 +#endif + +/** \def PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN + * + * This macro returns the maximum length of the PSK supported + * by the TLS-1.2 PSK-to-MS key derivation. + * + * Quoting RFC 4279, Sect 5.3: + * TLS implementations supporting these ciphersuites MUST support + * arbitrary PSK identities up to 128 octets in length, and arbitrary + * PSKs up to 64 octets in length. Supporting longer identities and + * keys is RECOMMENDED. + * + * Therefore, no implementation should define a value smaller than 64 + * for #PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN. + */ +#define PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN 128 + +/** The maximum size of a block cipher supported by the implementation. */ +#define PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE 16 + +/** The size of the output of psa_mac_sign_finish(), in bytes. + * + * This is also the MAC size that psa_mac_verify_finish() expects. + * + * \param key_type The type of the MAC key. + * \param key_bits The size of the MAC key in bits. + * \param alg A MAC algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_MAC(\p alg) is true). + * + * \return The MAC size for the specified algorithm with + * the specified key parameters. + * \return 0 if the MAC algorithm is not recognized. + * \return Either 0 or the correct size for a MAC algorithm that + * the implementation recognizes, but does not support. + * \return Unspecified if the key parameters are not consistent + * with the algorithm. + */ +#define PSA_MAC_FINAL_SIZE(key_type, key_bits, alg) \ + ((alg) & PSA_ALG_MAC_TRUNCATION_MASK ? PSA_MAC_TRUNCATED_LENGTH(alg) : \ + PSA_ALG_IS_HMAC(alg) ? PSA_HASH_SIZE(PSA_ALG_HMAC_GET_HASH(alg)) : \ + PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) ? PSA_BLOCK_CIPHER_BLOCK_SIZE(key_type) : \ + ((void)(key_type), (void)(key_bits), 0)) + +/** The maximum size of the output of psa_aead_encrypt(), in bytes. + * + * If the size of the ciphertext buffer is at least this large, it is + * guaranteed that psa_aead_encrypt() will not fail due to an + * insufficient buffer size. Depending on the algorithm, the actual size of + * the ciphertext may be smaller. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param plaintext_length Size of the plaintext in bytes. + * + * \return The AEAD ciphertext size for the specified + * algorithm. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +#define PSA_AEAD_ENCRYPT_OUTPUT_SIZE(alg, plaintext_length) \ + (PSA_AEAD_TAG_LENGTH(alg) != 0 ? \ + (plaintext_length) + PSA_AEAD_TAG_LENGTH(alg) : \ + 0) + +/** The maximum size of the output of psa_aead_decrypt(), in bytes. + * + * If the size of the plaintext buffer is at least this large, it is + * guaranteed that psa_aead_decrypt() will not fail due to an + * insufficient buffer size. Depending on the algorithm, the actual size of + * the plaintext may be smaller. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param ciphertext_length Size of the plaintext in bytes. + * + * \return The AEAD ciphertext size for the specified + * algorithm. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +#define PSA_AEAD_DECRYPT_OUTPUT_SIZE(alg, ciphertext_length) \ + (PSA_AEAD_TAG_LENGTH(alg) != 0 ? \ + (ciphertext_length) - PSA_AEAD_TAG_LENGTH(alg) : \ + 0) + +/** A sufficient output buffer size for psa_aead_update(). + * + * If the size of the output buffer is at least this large, it is + * guaranteed that psa_aead_update() will not fail due to an + * insufficient buffer size. The actual size of the output may be smaller + * in any given call. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param input_length Size of the input in bytes. + * + * \return A sufficient output buffer size for the specified + * algorithm. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +/* For all the AEAD modes defined in this specification, it is possible + * to emit output without delay. However, hardware may not always be + * capable of this. So for modes based on a block cipher, allow the + * implementation to delay the output until it has a full block. */ +#define PSA_AEAD_UPDATE_OUTPUT_SIZE(alg, input_length) \ + (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ + PSA_ROUND_UP_TO_MULTIPLE(PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE, (input_length)) : \ + (input_length)) + +/** A sufficient ciphertext buffer size for psa_aead_finish(). + * + * If the size of the ciphertext buffer is at least this large, it is + * guaranteed that psa_aead_finish() will not fail due to an + * insufficient ciphertext buffer size. The actual size of the output may + * be smaller in any given call. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return A sufficient ciphertext buffer size for the + * specified algorithm. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +#define PSA_AEAD_FINISH_OUTPUT_SIZE(alg) \ + (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ + PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE : \ + 0) + +/** A sufficient plaintext buffer size for psa_aead_verify(). + * + * If the size of the plaintext buffer is at least this large, it is + * guaranteed that psa_aead_verify() will not fail due to an + * insufficient plaintext buffer size. The actual size of the output may + * be smaller in any given call. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return A sufficient plaintext buffer size for the + * specified algorithm. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +#define PSA_AEAD_VERIFY_OUTPUT_SIZE(alg) \ + (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ + PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE : \ + 0) + +#define PSA_RSA_MINIMUM_PADDING_SIZE(alg) \ + (PSA_ALG_IS_RSA_OAEP(alg) ? \ + 2 * PSA_HASH_SIZE(PSA_ALG_RSA_OAEP_GET_HASH(alg)) + 1 : \ + 11 /*PKCS#1v1.5*/) + +/** + * \brief ECDSA signature size for a given curve bit size + * + * \param curve_bits Curve size in bits. + * \return Signature size in bytes. + * + * \note This macro returns a compile-time constant if its argument is one. + */ +#define PSA_ECDSA_SIGNATURE_SIZE(curve_bits) \ + (PSA_BITS_TO_BYTES(curve_bits) * 2) + +/** Sufficient signature buffer size for psa_sign_hash(). + * + * This macro returns a sufficient buffer size for a signature using a key + * of the specified type and size, with the specified algorithm. + * Note that the actual size of the signature may be smaller + * (some algorithms produce a variable-size signature). + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type An asymmetric key type (this may indifferently be a + * key pair type or a public key type). + * \param key_bits The size of the key in bits. + * \param alg The signature algorithm. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_sign_hash() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported + * by the implementation, this macro shall return either a + * sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_SIGN_OUTPUT_SIZE(key_type, key_bits, alg) \ + (PSA_KEY_TYPE_IS_RSA(key_type) ? ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \ + PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_ECDSA_SIGNATURE_SIZE(key_bits) : \ + ((void)alg, 0)) + +#define PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE \ + PSA_ECDSA_SIGNATURE_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) + +/** \def PSA_SIGNATURE_MAX_SIZE + * + * Maximum size of an asymmetric signature. + * + * This macro must expand to a compile-time constant integer. This value + * should be the maximum size of a signature supported by the implementation, + * in bytes, and must be no smaller than this maximum. + */ +#define PSA_SIGNATURE_MAX_SIZE \ + (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) > PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE ? \ + PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) : \ + PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE) + +/** Sufficient output buffer size for psa_asymmetric_encrypt(). + * + * This macro returns a sufficient buffer size for a ciphertext produced using + * a key of the specified type and size, with the specified algorithm. + * Note that the actual size of the ciphertext may be smaller, depending + * on the algorithm. + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type An asymmetric key type (this may indifferently be a + * key pair type or a public key type). + * \param key_bits The size of the key in bits. + * \param alg The signature algorithm. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_asymmetric_encrypt() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported + * by the implementation, this macro shall return either a + * sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \ + (PSA_KEY_TYPE_IS_RSA(key_type) ? \ + ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \ + 0) + +/** Sufficient output buffer size for psa_asymmetric_decrypt(). + * + * This macro returns a sufficient buffer size for a ciphertext produced using + * a key of the specified type and size, with the specified algorithm. + * Note that the actual size of the ciphertext may be smaller, depending + * on the algorithm. + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type An asymmetric key type (this may indifferently be a + * key pair type or a public key type). + * \param key_bits The size of the key in bits. + * \param alg The signature algorithm. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_asymmetric_decrypt() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported + * by the implementation, this macro shall return either a + * sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \ + (PSA_KEY_TYPE_IS_RSA(key_type) ? \ + PSA_BITS_TO_BYTES(key_bits) - PSA_RSA_MINIMUM_PADDING_SIZE(alg) : \ + 0) + +/* Maximum size of the ASN.1 encoding of an INTEGER with the specified + * number of bits. + * + * This definition assumes that bits <= 2^19 - 9 so that the length field + * is at most 3 bytes. The length of the encoding is the length of the + * bit string padded to a whole number of bytes plus: + * - 1 type byte; + * - 1 to 3 length bytes; + * - 0 to 1 bytes of leading 0 due to the sign bit. + */ +#define PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(bits) \ + ((bits) / 8 + 5) + +/* Maximum size of the export encoding of an RSA public key. + * Assumes that the public exponent is less than 2^32. + * + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER } -- e + * + * - 4 bytes of SEQUENCE overhead; + * - n : INTEGER; + * - 7 bytes for the public exponent. + */ +#define PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) \ + (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) + 11) + +/* Maximum size of the export encoding of an RSA key pair. + * Assumes thatthe public exponent is less than 2^32 and that the size + * difference between the two primes is at most 1 bit. + * + * RSAPrivateKey ::= SEQUENCE { + * version Version, -- 0 + * modulus INTEGER, -- N-bit + * publicExponent INTEGER, -- 32-bit + * privateExponent INTEGER, -- N-bit + * prime1 INTEGER, -- N/2-bit + * prime2 INTEGER, -- N/2-bit + * exponent1 INTEGER, -- N/2-bit + * exponent2 INTEGER, -- N/2-bit + * coefficient INTEGER, -- N/2-bit + * } + * + * - 4 bytes of SEQUENCE overhead; + * - 3 bytes of version; + * - 7 half-size INTEGERs plus 2 full-size INTEGERs, + * overapproximated as 9 half-size INTEGERS; + * - 7 bytes for the public exponent. + */ +#define PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits) \ + (9 * PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE((key_bits) / 2 + 1) + 14) + +/* Maximum size of the export encoding of a DSA public key. + * + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } -- contains DSAPublicKey + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters Dss-Parms } -- SEQUENCE of 3 INTEGERs + * DSAPublicKey ::= INTEGER -- public key, Y + * + * - 3 * 4 bytes of SEQUENCE overhead; + * - 1 + 1 + 7 bytes of algorithm (DSA OID); + * - 4 bytes of BIT STRING overhead; + * - 3 full-size INTEGERs (p, g, y); + * - 1 + 1 + 32 bytes for 1 sub-size INTEGER (q <= 256 bits). + */ +#define PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) \ + (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3 + 59) + +/* Maximum size of the export encoding of a DSA key pair. + * + * DSAPrivateKey ::= SEQUENCE { + * version Version, -- 0 + * prime INTEGER, -- p + * subprime INTEGER, -- q + * generator INTEGER, -- g + * public INTEGER, -- y + * private INTEGER, -- x + * } + * + * - 4 bytes of SEQUENCE overhead; + * - 3 bytes of version; + * - 3 full-size INTEGERs (p, g, y); + * - 2 * (1 + 1 + 32) bytes for 2 sub-size INTEGERs (q, x <= 256 bits). + */ +#define PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits) \ + (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3 + 75) + +/* Maximum size of the export encoding of an ECC public key. + * + * The representation of an ECC public key is: + * - The byte 0x04; + * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; + * - `y_P` as a `ceiling(m/8)`-byte string, big-endian; + * - where m is the bit size associated with the curve. + * + * - 1 byte + 2 * point size. + */ +#define PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) \ + (2 * PSA_BITS_TO_BYTES(key_bits) + 1) + +/* Maximum size of the export encoding of an ECC key pair. + * + * An ECC key pair is represented by the secret value. + */ +#define PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) \ + (PSA_BITS_TO_BYTES(key_bits)) + +/** Sufficient output buffer size for psa_export_key() or psa_export_public_key(). + * + * This macro returns a compile-time constant if its arguments are + * compile-time constants. + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * The following code illustrates how to allocate enough memory to export + * a key by querying the key type and size at runtime. + * \code{c} + * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + * psa_status_t status; + * status = psa_get_key_attributes(key, &attributes); + * if (status != PSA_SUCCESS) handle_error(...); + * psa_key_type_t key_type = psa_get_key_type(&attributes); + * size_t key_bits = psa_get_key_bits(&attributes); + * size_t buffer_size = PSA_KEY_EXPORT_MAX_SIZE(key_type, key_bits); + * psa_reset_key_attributes(&attributes); + * uint8_t *buffer = malloc(buffer_size); + * if (buffer == NULL) handle_error(...); + * size_t buffer_length; + * status = psa_export_key(key, buffer, buffer_size, &buffer_length); + * if (status != PSA_SUCCESS) handle_error(...); + * \endcode + * + * For psa_export_public_key(), calculate the buffer size from the + * public key type. You can use the macro #PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR + * to convert a key pair type to the corresponding public key type. + * \code{c} + * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + * psa_status_t status; + * status = psa_get_key_attributes(key, &attributes); + * if (status != PSA_SUCCESS) handle_error(...); + * psa_key_type_t key_type = psa_get_key_type(&attributes); + * psa_key_type_t public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(key_type); + * size_t key_bits = psa_get_key_bits(&attributes); + * size_t buffer_size = PSA_KEY_EXPORT_MAX_SIZE(public_key_type, key_bits); + * psa_reset_key_attributes(&attributes); + * uint8_t *buffer = malloc(buffer_size); + * if (buffer == NULL) handle_error(...); + * size_t buffer_length; + * status = psa_export_public_key(key, buffer, buffer_size, &buffer_length); + * if (status != PSA_SUCCESS) handle_error(...); + * \endcode + * + * \param key_type A supported key type. + * \param key_bits The size of the key in bits. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_sign_hash() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported + * by the implementation, this macro shall return either a + * sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_KEY_EXPORT_MAX_SIZE(key_type, key_bits) \ + (PSA_KEY_TYPE_IS_UNSTRUCTURED(key_type) ? PSA_BITS_TO_BYTES(key_bits) : \ + (key_type) == PSA_KEY_TYPE_RSA_KEY_PAIR ? PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits) : \ + (key_type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY ? PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ + (key_type) == PSA_KEY_TYPE_DSA_KEY_PAIR ? PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits) : \ + (key_type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY ? PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ + PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) ? PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) : \ + PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type) ? PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) : \ + 0) + +#endif /* PSA_CRYPTO_SIZES_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_types.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_types.h new file mode 100644 index 0000000..d96c66e --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_types.h @@ -0,0 +1,287 @@ +/** + * \file psa/crypto_types.h + * + * \brief PSA cryptography module: type aliases. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. Drivers must include the appropriate driver + * header file. + * + * This file contains portable definitions of integral types for properties + * of cryptographic keys, designations of cryptographic algorithms, and + * error codes returned by the library. + * + * This header file does not declare any function. + */ +/* + * Copyright (C) 2018, ARM Limited, 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef PSA_CRYPTO_TYPES_H +#define PSA_CRYPTO_TYPES_H + +#include + +/** \defgroup error Error codes + * @{ + */ + +/** + * \brief Function return status. + * + * This is either #PSA_SUCCESS (which is zero), indicating success, + * or a small negative value indicating that an error occurred. Errors are + * encoded as one of the \c PSA_ERROR_xxx values defined here. */ +/* If #PSA_SUCCESS is already defined, it means that #psa_status_t + * is also defined in an external header, so prevent its multiple + * definition. + */ +#ifndef PSA_SUCCESS +typedef int32_t psa_status_t; +#endif + +/**@}*/ + +/** \defgroup crypto_types Key and algorithm types + * @{ + */ + +/** \brief Encoding of a key type. + */ +typedef uint16_t psa_key_type_t; + +/** The type of PSA elliptic curve family identifiers. + * + * The curve identifier is required to create an ECC key using the + * PSA_KEY_TYPE_ECC_KEY_PAIR() or PSA_KEY_TYPE_ECC_PUBLIC_KEY() + * macros. + * + * Values defined by this standard will never be in the range 0x80-0xff. + * Vendors who define additional families must use an encoding in this range. + */ +typedef uint8_t psa_ecc_curve_t; + +/** The type of PSA Diffie-Hellman group family identifiers. + * + * The group identifier is required to create an Diffie-Hellman key using the + * PSA_KEY_TYPE_DH_KEY_PAIR() or PSA_KEY_TYPE_DH_PUBLIC_KEY() + * macros. + * + * Values defined by this standard will never be in the range 0x80-0xff. + * Vendors who define additional families must use an encoding in this range. + */ +typedef uint8_t psa_dh_group_t; + +/** \brief Encoding of a cryptographic algorithm. + * + * For algorithms that can be applied to multiple key types, this type + * does not encode the key type. For example, for symmetric ciphers + * based on a block cipher, #psa_algorithm_t encodes the block cipher + * mode and the padding mode while the block cipher itself is encoded + * via #psa_key_type_t. + */ +typedef uint32_t psa_algorithm_t; + +/**@}*/ + +/** \defgroup key_lifetimes Key lifetimes + * @{ + */ + +/** Encoding of key lifetimes. + * + * The lifetime of a key indicates where it is stored and what system actions + * may create and destroy it. + * + * Keys with the lifetime #PSA_KEY_LIFETIME_VOLATILE are automatically + * destroyed when the application terminates or on a power reset. + * + * Keys with a lifetime other than #PSA_KEY_LIFETIME_VOLATILE are said + * to be _persistent_. + * Persistent keys are preserved if the application or the system restarts. + * Persistent keys have a key identifier of type #psa_key_id_t. + * The application can call psa_open_key() to open a persistent key that + * it created previously. + */ +typedef uint32_t psa_key_lifetime_t; + +/** Encoding of identifiers of persistent keys. + * + * - Applications may freely choose key identifiers in the range + * #PSA_KEY_ID_USER_MIN to #PSA_KEY_ID_USER_MAX. + * - Implementations may define additional key identifiers in the range + * #PSA_KEY_ID_VENDOR_MIN to #PSA_KEY_ID_VENDOR_MAX. + * - 0 is reserved as an invalid key identifier. + * - Key identifiers outside these ranges are reserved for future use. + */ +/* Implementation-specific quirk: The Mbed Crypto library can be built as + * part of a multi-client service that exposes the PSA Crypto API in each + * client and encodes the client identity in the key id argument of functions + * such as psa_open_key(). In this build configuration, we define + * psa_key_id_t in crypto_platform.h instead of here. */ +#if !defined(MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER) +typedef uint32_t psa_key_id_t; +#define PSA_KEY_ID_INIT 0 +#endif + +/**@}*/ + +/** \defgroup policy Key policies + * @{ + */ + +/** \brief Encoding of permitted usage on a key. */ +typedef uint32_t psa_key_usage_t; + +/**@}*/ + +/** \defgroup attributes Key attributes + * @{ + */ + +/** The type of a structure containing key attributes. + * + * This is an opaque structure that can represent the metadata of a key + * object. Metadata that can be stored in attributes includes: + * - The location of the key in storage, indicated by its key identifier + * and its lifetime. + * - The key's policy, comprising usage flags and a specification of + * the permitted algorithm(s). + * - Information about the key itself: the key type and its size. + * - Implementations may define additional attributes. + * + * The actual key material is not considered an attribute of a key. + * Key attributes do not contain information that is generally considered + * highly confidential. + * + * An attribute structure can be a simple data structure where each function + * `psa_set_key_xxx` sets a field and the corresponding function + * `psa_get_key_xxx` retrieves the value of the corresponding field. + * However, implementations may report values that are equivalent to the + * original one, but have a different encoding. For example, an + * implementation may use a more compact representation for types where + * many bit-patterns are invalid or not supported, and store all values + * that it does not support as a special marker value. In such an + * implementation, after setting an invalid value, the corresponding + * get function returns an invalid value which may not be the one that + * was originally stored. + * + * An attribute structure may contain references to auxiliary resources, + * for example pointers to allocated memory or indirect references to + * pre-calculated values. In order to free such resources, the application + * must call psa_reset_key_attributes(). As an exception, calling + * psa_reset_key_attributes() on an attribute structure is optional if + * the structure has only been modified by the following functions + * since it was initialized or last reset with psa_reset_key_attributes(): + * - psa_set_key_id() + * - psa_set_key_lifetime() + * - psa_set_key_type() + * - psa_set_key_bits() + * - psa_set_key_usage_flags() + * - psa_set_key_algorithm() + * + * Before calling any function on a key attribute structure, the application + * must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_key_attributes_t attributes; + * memset(&attributes, 0, sizeof(attributes)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_key_attributes_t attributes = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_KEY_ATTRIBUTES_INIT, + * for example: + * \code + * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + * \endcode + * - Assign the result of the function psa_key_attributes_init() + * to the structure, for example: + * \code + * psa_key_attributes_t attributes; + * attributes = psa_key_attributes_init(); + * \endcode + * + * A freshly initialized attribute structure contains the following + * values: + * + * - lifetime: #PSA_KEY_LIFETIME_VOLATILE. + * - key identifier: 0 (which is not a valid key identifier). + * - type: \c 0 (meaning that the type is unspecified). + * - key size: \c 0 (meaning that the size is unspecified). + * - usage flags: \c 0 (which allows no usage except exporting a public key). + * - algorithm: \c 0 (which allows no cryptographic usage, but allows + * exporting). + * + * A typical sequence to create a key is as follows: + * -# Create and initialize an attribute structure. + * -# If the key is persistent, call psa_set_key_id(). + * Also call psa_set_key_lifetime() to place the key in a non-default + * location. + * -# Set the key policy with psa_set_key_usage_flags() and + * psa_set_key_algorithm(). + * -# Set the key type with psa_set_key_type(). + * Skip this step if copying an existing key with psa_copy_key(). + * -# When generating a random key with psa_generate_key() or deriving a key + * with psa_key_derivation_output_key(), set the desired key size with + * psa_set_key_bits(). + * -# Call a key creation function: psa_import_key(), psa_generate_key(), + * psa_key_derivation_output_key() or psa_copy_key(). This function reads + * the attribute structure, creates a key with these attributes, and + * outputs a handle to the newly created key. + * -# The attribute structure is now no longer necessary. + * You may call psa_reset_key_attributes(), although this is optional + * with the workflow presented here because the attributes currently + * defined in this specification do not require any additional resources + * beyond the structure itself. + * + * A typical sequence to query a key's attributes is as follows: + * -# Call psa_get_key_attributes(). + * -# Call `psa_get_key_xxx` functions to retrieve the attribute(s) that + * you are interested in. + * -# Call psa_reset_key_attributes() to free any resources that may be + * used by the attribute structure. + * + * Once a key has been created, it is impossible to change its attributes. + */ +typedef struct psa_key_attributes_s psa_key_attributes_t; + + +#ifndef __DOXYGEN_ONLY__ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +/* Mbed Crypto defines this type in crypto_types.h because it is also + * visible to applications through an implementation-specific extension. + * For the PSA Cryptography specification, this type is only visible + * via crypto_se_driver.h. */ +typedef uint64_t psa_key_slot_number_t; +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ +#endif /* !__DOXYGEN_ONLY__ */ + +/**@}*/ + +/** \defgroup derivation Key derivation + * @{ + */ + +/** \brief Encoding of the step of a key derivation. */ +typedef uint16_t psa_key_derivation_step_t; + +/**@}*/ + +#endif /* PSA_CRYPTO_TYPES_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_values.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_values.h new file mode 100644 index 0000000..baaabff --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/crypto_values.h @@ -0,0 +1,1705 @@ +/** + * \file psa/crypto_values.h + * + * \brief PSA cryptography module: macros to build and analyze integer values. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. Drivers must include the appropriate driver + * header file. + * + * This file contains portable definitions of macros to build and analyze + * values of integral types that encode properties of cryptographic keys, + * designations of cryptographic algorithms, and error codes returned by + * the library. + * + * This header file only defines preprocessor macros. + */ +/* + * Copyright (C) 2018, ARM Limited, 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef PSA_CRYPTO_VALUES_H +#define PSA_CRYPTO_VALUES_H + +/** \defgroup error Error codes + * @{ + */ + +/* PSA error codes */ + +/** The action was completed successfully. */ +#define PSA_SUCCESS ((psa_status_t)0) + +/** An error occurred that does not correspond to any defined + * failure cause. + * + * Implementations may use this error code if none of the other standard + * error codes are applicable. */ +#define PSA_ERROR_GENERIC_ERROR ((psa_status_t)-132) + +/** The requested operation or a parameter is not supported + * by this implementation. + * + * Implementations should return this error code when an enumeration + * parameter such as a key type, algorithm, etc. is not recognized. + * If a combination of parameters is recognized and identified as + * not valid, return #PSA_ERROR_INVALID_ARGUMENT instead. */ +#define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)-134) + +/** The requested action is denied by a policy. + * + * Implementations should return this error code when the parameters + * are recognized as valid and supported, and a policy explicitly + * denies the requested operation. + * + * If a subset of the parameters of a function call identify a + * forbidden operation, and another subset of the parameters are + * not valid or not supported, it is unspecified whether the function + * returns #PSA_ERROR_NOT_PERMITTED, #PSA_ERROR_NOT_SUPPORTED or + * #PSA_ERROR_INVALID_ARGUMENT. */ +#define PSA_ERROR_NOT_PERMITTED ((psa_status_t)-133) + +/** An output buffer is too small. + * + * Applications can call the \c PSA_xxx_SIZE macro listed in the function + * description to determine a sufficient buffer size. + * + * Implementations should preferably return this error code only + * in cases when performing the operation with a larger output + * buffer would succeed. However implementations may return this + * error if a function has invalid or unsupported parameters in addition + * to the parameters that determine the necessary output buffer size. */ +#define PSA_ERROR_BUFFER_TOO_SMALL ((psa_status_t)-138) + +/** Asking for an item that already exists + * + * Implementations should return this error, when attempting + * to write an item (like a key) that already exists. */ +#define PSA_ERROR_ALREADY_EXISTS ((psa_status_t)-139) + +/** Asking for an item that doesn't exist + * + * Implementations should return this error, if a requested item (like + * a key) does not exist. */ +#define PSA_ERROR_DOES_NOT_EXIST ((psa_status_t)-140) + +/** The requested action cannot be performed in the current state. + * + * Multipart operations return this error when one of the + * functions is called out of sequence. Refer to the function + * descriptions for permitted sequencing of functions. + * + * Implementations shall not return this error code to indicate + * that a key either exists or not, + * but shall instead return #PSA_ERROR_ALREADY_EXISTS or #PSA_ERROR_DOES_NOT_EXIST + * as applicable. + * + * Implementations shall not return this error code to indicate that a + * key handle is invalid, but shall return #PSA_ERROR_INVALID_HANDLE + * instead. */ +#define PSA_ERROR_BAD_STATE ((psa_status_t)-137) + +/** The parameters passed to the function are invalid. + * + * Implementations may return this error any time a parameter or + * combination of parameters are recognized as invalid. + * + * Implementations shall not return this error code to indicate that a + * key handle is invalid, but shall return #PSA_ERROR_INVALID_HANDLE + * instead. + */ +#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)-135) + +/** There is not enough runtime memory. + * + * If the action is carried out across multiple security realms, this + * error can refer to available memory in any of the security realms. */ +#define PSA_ERROR_INSUFFICIENT_MEMORY ((psa_status_t)-141) + +/** There is not enough persistent storage. + * + * Functions that modify the key storage return this error code if + * there is insufficient storage space on the host media. In addition, + * many functions that do not otherwise access storage may return this + * error code if the implementation requires a mandatory log entry for + * the requested action and the log storage space is full. */ +#define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)-142) + +/** There was a communication failure inside the implementation. + * + * This can indicate a communication failure between the application + * and an external cryptoprocessor or between the cryptoprocessor and + * an external volatile or persistent memory. A communication failure + * may be transient or permanent depending on the cause. + * + * \warning If a function returns this error, it is undetermined + * whether the requested action has completed or not. Implementations + * should return #PSA_SUCCESS on successful completion whenever + * possible, however functions may return #PSA_ERROR_COMMUNICATION_FAILURE + * if the requested action was completed successfully in an external + * cryptoprocessor but there was a breakdown of communication before + * the cryptoprocessor could report the status to the application. + */ +#define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t)-145) + +/** There was a storage failure that may have led to data loss. + * + * This error indicates that some persistent storage is corrupted. + * It should not be used for a corruption of volatile memory + * (use #PSA_ERROR_CORRUPTION_DETECTED), for a communication error + * between the cryptoprocessor and its external storage (use + * #PSA_ERROR_COMMUNICATION_FAILURE), or when the storage is + * in a valid state but is full (use #PSA_ERROR_INSUFFICIENT_STORAGE). + * + * Note that a storage failure does not indicate that any data that was + * previously read is invalid. However this previously read data may no + * longer be readable from storage. + * + * When a storage failure occurs, it is no longer possible to ensure + * the global integrity of the keystore. Depending on the global + * integrity guarantees offered by the implementation, access to other + * data may or may not fail even if the data is still readable but + * its integrity cannot be guaranteed. + * + * Implementations should only use this error code to report a + * permanent storage corruption. However application writers should + * keep in mind that transient errors while reading the storage may be + * reported using this error code. */ +#define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)-146) + +/** A hardware failure was detected. + * + * A hardware failure may be transient or permanent depending on the + * cause. */ +#define PSA_ERROR_HARDWARE_FAILURE ((psa_status_t)-147) + +/** A tampering attempt was detected. + * + * If an application receives this error code, there is no guarantee + * that previously accessed or computed data was correct and remains + * confidential. Applications should not perform any security function + * and should enter a safe failure state. + * + * Implementations may return this error code if they detect an invalid + * state that cannot happen during normal operation and that indicates + * that the implementation's security guarantees no longer hold. Depending + * on the implementation architecture and on its security and safety goals, + * the implementation may forcibly terminate the application. + * + * This error code is intended as a last resort when a security breach + * is detected and it is unsure whether the keystore data is still + * protected. Implementations shall only return this error code + * to report an alarm from a tampering detector, to indicate that + * the confidentiality of stored data can no longer be guaranteed, + * or to indicate that the integrity of previously returned data is now + * considered compromised. Implementations shall not use this error code + * to indicate a hardware failure that merely makes it impossible to + * perform the requested operation (use #PSA_ERROR_COMMUNICATION_FAILURE, + * #PSA_ERROR_STORAGE_FAILURE, #PSA_ERROR_HARDWARE_FAILURE, + * #PSA_ERROR_INSUFFICIENT_ENTROPY or other applicable error code + * instead). + * + * This error indicates an attack against the application. Implementations + * shall not return this error code as a consequence of the behavior of + * the application itself. */ +#define PSA_ERROR_CORRUPTION_DETECTED ((psa_status_t)-151) + +/** There is not enough entropy to generate random data needed + * for the requested action. + * + * This error indicates a failure of a hardware random generator. + * Application writers should note that this error can be returned not + * only by functions whose purpose is to generate random data, such + * as key, IV or nonce generation, but also by functions that execute + * an algorithm with a randomized result, as well as functions that + * use randomization of intermediate computations as a countermeasure + * to certain attacks. + * + * Implementations should avoid returning this error after psa_crypto_init() + * has succeeded. Implementations should generate sufficient + * entropy during initialization and subsequently use a cryptographically + * secure pseudorandom generator (PRNG). However implementations may return + * this error at any time if a policy requires the PRNG to be reseeded + * during normal operation. */ +#define PSA_ERROR_INSUFFICIENT_ENTROPY ((psa_status_t)-148) + +/** The signature, MAC or hash is incorrect. + * + * Verification functions return this error if the verification + * calculations completed successfully, and the value to be verified + * was determined to be incorrect. + * + * If the value to verify has an invalid size, implementations may return + * either #PSA_ERROR_INVALID_ARGUMENT or #PSA_ERROR_INVALID_SIGNATURE. */ +#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) + +/** The decrypted padding is incorrect. + * + * \warning In some protocols, when decrypting data, it is essential that + * the behavior of the application does not depend on whether the padding + * is correct, down to precise timing. Applications should prefer + * protocols that use authenticated encryption rather than plain + * encryption. If the application must perform a decryption of + * unauthenticated data, the application writer should take care not + * to reveal whether the padding is invalid. + * + * Implementations should strive to make valid and invalid padding + * as close as possible to indistinguishable to an external observer. + * In particular, the timing of a decryption operation should not + * depend on the validity of the padding. */ +#define PSA_ERROR_INVALID_PADDING ((psa_status_t)-150) + +/** Return this error when there's insufficient data when attempting + * to read from a resource. */ +#define PSA_ERROR_INSUFFICIENT_DATA ((psa_status_t)-143) + +/** The key handle is not valid. See also :ref:\`key-handles\`. + */ +#define PSA_ERROR_INVALID_HANDLE ((psa_status_t)-136) + +/**@}*/ + +/** \defgroup crypto_types Key and algorithm types + * @{ + */ + +/** An invalid key type value. + * + * Zero is not the encoding of any key type. + */ +#define PSA_KEY_TYPE_NONE ((psa_key_type_t)0x0000) + +/** Vendor-defined key type flag. + * + * Key types defined by this standard will never have the + * #PSA_KEY_TYPE_VENDOR_FLAG bit set. Vendors who define additional key types + * must use an encoding with the #PSA_KEY_TYPE_VENDOR_FLAG bit set and should + * respect the bitwise structure used by standard encodings whenever practical. + */ +#define PSA_KEY_TYPE_VENDOR_FLAG ((psa_key_type_t)0x8000) + +#define PSA_KEY_TYPE_CATEGORY_MASK ((psa_key_type_t)0x7000) +#define PSA_KEY_TYPE_CATEGORY_RAW ((psa_key_type_t)0x1000) +#define PSA_KEY_TYPE_CATEGORY_SYMMETRIC ((psa_key_type_t)0x2000) +#define PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY ((psa_key_type_t)0x4000) +#define PSA_KEY_TYPE_CATEGORY_KEY_PAIR ((psa_key_type_t)0x7000) + +#define PSA_KEY_TYPE_CATEGORY_FLAG_PAIR ((psa_key_type_t)0x3000) + +/** Whether a key type is vendor-defined. + * + * See also #PSA_KEY_TYPE_VENDOR_FLAG. + */ +#define PSA_KEY_TYPE_IS_VENDOR_DEFINED(type) \ + (((type) & PSA_KEY_TYPE_VENDOR_FLAG) != 0) + +/** Whether a key type is an unstructured array of bytes. + * + * This encompasses both symmetric keys and non-key data. + */ +#define PSA_KEY_TYPE_IS_UNSTRUCTURED(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_RAW || \ + ((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_SYMMETRIC) + +/** Whether a key type is asymmetric: either a key pair or a public key. */ +#define PSA_KEY_TYPE_IS_ASYMMETRIC(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK \ + & ~PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) == \ + PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY) +/** Whether a key type is the public part of a key pair. */ +#define PSA_KEY_TYPE_IS_PUBLIC_KEY(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY) +/** Whether a key type is a key pair containing a private part and a public + * part. */ +#define PSA_KEY_TYPE_IS_KEY_PAIR(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_KEY_PAIR) +/** The key pair type corresponding to a public key type. + * + * You may also pass a key pair type as \p type, it will be left unchanged. + * + * \param type A public key type or key pair type. + * + * \return The corresponding key pair type. + * If \p type is not a public key or a key pair, + * the return value is undefined. + */ +#define PSA_KEY_TYPE_KEY_PAIR_OF_PUBLIC_KEY(type) \ + ((type) | PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) +/** The public key type corresponding to a key pair type. + * + * You may also pass a key pair type as \p type, it will be left unchanged. + * + * \param type A public key type or key pair type. + * + * \return The corresponding public key type. + * If \p type is not a public key or a key pair, + * the return value is undefined. + */ +#define PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) \ + ((type) & ~PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) + +/** Raw data. + * + * A "key" of this type cannot be used for any cryptographic operation. + * Applications may use this type to store arbitrary data in the keystore. */ +#define PSA_KEY_TYPE_RAW_DATA ((psa_key_type_t)0x1001) + +/** HMAC key. + * + * The key policy determines which underlying hash algorithm the key can be + * used for. + * + * HMAC keys should generally have the same size as the underlying hash. + * This size can be calculated with #PSA_HASH_SIZE(\c alg) where + * \c alg is the HMAC algorithm or the underlying hash algorithm. */ +#define PSA_KEY_TYPE_HMAC ((psa_key_type_t)0x1100) + +/** A secret for key derivation. + * + * The key policy determines which key derivation algorithm the key + * can be used for. + */ +#define PSA_KEY_TYPE_DERIVE ((psa_key_type_t)0x1200) + +/** Key for a cipher, AEAD or MAC algorithm based on the AES block cipher. + * + * The size of the key can be 16 bytes (AES-128), 24 bytes (AES-192) or + * 32 bytes (AES-256). + */ +#define PSA_KEY_TYPE_AES ((psa_key_type_t)0x2400) + +/** Key for a cipher or MAC algorithm based on DES or 3DES (Triple-DES). + * + * The size of the key can be 8 bytes (single DES), 16 bytes (2-key 3DES) or + * 24 bytes (3-key 3DES). + * + * Note that single DES and 2-key 3DES are weak and strongly + * deprecated and should only be used to decrypt legacy data. 3-key 3DES + * is weak and deprecated and should only be used in legacy protocols. + */ +#define PSA_KEY_TYPE_DES ((psa_key_type_t)0x2301) + +/** Key for a cipher, AEAD or MAC algorithm based on the + * Camellia block cipher. */ +#define PSA_KEY_TYPE_CAMELLIA ((psa_key_type_t)0x2403) + +/** Key for the RC4 stream cipher. + * + * Note that RC4 is weak and deprecated and should only be used in + * legacy protocols. */ +#define PSA_KEY_TYPE_ARC4 ((psa_key_type_t)0x2002) + +/** Key for the ChaCha20 stream cipher or the Chacha20-Poly1305 AEAD algorithm. + * + * ChaCha20 and the ChaCha20_Poly1305 construction are defined in RFC 7539. + * + * Implementations must support 12-byte nonces, may support 8-byte nonces, + * and should reject other sizes. + */ +#define PSA_KEY_TYPE_CHACHA20 ((psa_key_type_t)0x2004) + +/** RSA public key. */ +#define PSA_KEY_TYPE_RSA_PUBLIC_KEY ((psa_key_type_t)0x4001) +/** RSA key pair (private and public key). */ +#define PSA_KEY_TYPE_RSA_KEY_PAIR ((psa_key_type_t)0x7001) +/** Whether a key type is an RSA key (pair or public-only). */ +#define PSA_KEY_TYPE_IS_RSA(type) \ + (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY) + +#define PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE ((psa_key_type_t)0x4100) +#define PSA_KEY_TYPE_ECC_KEY_PAIR_BASE ((psa_key_type_t)0x7100) +#define PSA_KEY_TYPE_ECC_CURVE_MASK ((psa_key_type_t)0x00ff) +/** Elliptic curve key pair. + * + * \param curve A value of type ::psa_ecc_curve_t that identifies the + * ECC curve to be used. + */ +#define PSA_KEY_TYPE_ECC_KEY_PAIR(curve) \ + (PSA_KEY_TYPE_ECC_KEY_PAIR_BASE | (curve)) +/** Elliptic curve public key. + * + * \param curve A value of type ::psa_ecc_curve_t that identifies the + * ECC curve to be used. + */ +#define PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve) \ + (PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE | (curve)) + +/** Whether a key type is an elliptic curve key (pair or public-only). */ +#define PSA_KEY_TYPE_IS_ECC(type) \ + ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) & \ + ~PSA_KEY_TYPE_ECC_CURVE_MASK) == PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE) +/** Whether a key type is an elliptic curve key pair. */ +#define PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type) \ + (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \ + PSA_KEY_TYPE_ECC_KEY_PAIR_BASE) +/** Whether a key type is an elliptic curve public key. */ +#define PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(type) \ + (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \ + PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE) + +/** Extract the curve from an elliptic curve key type. */ +#define PSA_KEY_TYPE_GET_CURVE(type) \ + ((psa_ecc_curve_t) (PSA_KEY_TYPE_IS_ECC(type) ? \ + ((type) & PSA_KEY_TYPE_ECC_CURVE_MASK) : \ + 0)) + +/** SEC Koblitz curves over prime fields. + * + * This family comprises the following curves: + * secp192k1, secp224k1, secp256k1. + * They are defined in _Standards for Efficient Cryptography_, + * _SEC 2: Recommended Elliptic Curve Domain Parameters_. + * https://www.secg.org/sec2-v2.pdf + */ +#define PSA_ECC_CURVE_SECP_K1 ((psa_ecc_curve_t) 0x17) + +/** SEC random curves over prime fields. + * + * This family comprises the following curves: + * secp192k1, secp224r1, secp256r1, secp384r1, secp521r1. + * They are defined in _Standards for Efficient Cryptography_, + * _SEC 2: Recommended Elliptic Curve Domain Parameters_. + * https://www.secg.org/sec2-v2.pdf + */ +#define PSA_ECC_CURVE_SECP_R1 ((psa_ecc_curve_t) 0x12) +/* SECP160R2 (SEC2 v1, obsolete) */ +#define PSA_ECC_CURVE_SECP_R2 ((psa_ecc_curve_t) 0x1b) + +/** SEC Koblitz curves over binary fields. + * + * This family comprises the following curves: + * sect163k1, sect233k1, sect239k1, sect283k1, sect409k1, sect571k1. + * They are defined in _Standards for Efficient Cryptography_, + * _SEC 2: Recommended Elliptic Curve Domain Parameters_. + * https://www.secg.org/sec2-v2.pdf + */ +#define PSA_ECC_CURVE_SECT_K1 ((psa_ecc_curve_t) 0x27) + +/** SEC random curves over binary fields. + * + * This family comprises the following curves: + * sect163r1, sect233r1, sect283r1, sect409r1, sect571r1. + * They are defined in _Standards for Efficient Cryptography_, + * _SEC 2: Recommended Elliptic Curve Domain Parameters_. + * https://www.secg.org/sec2-v2.pdf + */ +#define PSA_ECC_CURVE_SECT_R1 ((psa_ecc_curve_t) 0x22) + +/** SEC additional random curves over binary fields. + * + * This family comprises the following curve: + * sect163r2. + * It is defined in _Standards for Efficient Cryptography_, + * _SEC 2: Recommended Elliptic Curve Domain Parameters_. + * https://www.secg.org/sec2-v2.pdf + */ +#define PSA_ECC_CURVE_SECT_R2 ((psa_ecc_curve_t) 0x2b) + +/** Brainpool P random curves. + * + * This family comprises the following curves: + * brainpoolP160r1, brainpoolP192r1, brainpoolP224r1, brainpoolP256r1, + * brainpoolP320r1, brainpoolP384r1, brainpoolP512r1. + * It is defined in RFC 5639. + */ +#define PSA_ECC_CURVE_BRAINPOOL_P_R1 ((psa_ecc_curve_t) 0x30) + +/** Curve25519 and Curve448. + * + * This family comprises the following Montgomery curves: + * - 255-bit: Bernstein et al., + * _Curve25519: new Diffie-Hellman speed records_, LNCS 3958, 2006. + * The algorithm #PSA_ALG_ECDH performs X25519 when used with this curve. + * - 448-bit: Hamburg, + * _Ed448-Goldilocks, a new elliptic curve_, NIST ECC Workshop, 2015. + * The algorithm #PSA_ALG_ECDH performs X448 when used with this curve. + */ +#define PSA_ECC_CURVE_MONTGOMERY ((psa_ecc_curve_t) 0x41) + +#define PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE ((psa_key_type_t)0x4200) +#define PSA_KEY_TYPE_DH_KEY_PAIR_BASE ((psa_key_type_t)0x7200) +#define PSA_KEY_TYPE_DH_GROUP_MASK ((psa_key_type_t)0x00ff) +/** Diffie-Hellman key pair. + * + * \param group A value of type ::psa_dh_group_t that identifies the + * Diffie-Hellman group to be used. + */ +#define PSA_KEY_TYPE_DH_KEY_PAIR(group) \ + (PSA_KEY_TYPE_DH_KEY_PAIR_BASE | (group)) +/** Diffie-Hellman public key. + * + * \param group A value of type ::psa_dh_group_t that identifies the + * Diffie-Hellman group to be used. + */ +#define PSA_KEY_TYPE_DH_PUBLIC_KEY(group) \ + (PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE | (group)) + +/** Whether a key type is a Diffie-Hellman key (pair or public-only). */ +#define PSA_KEY_TYPE_IS_DH(type) \ + ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) & \ + ~PSA_KEY_TYPE_DH_GROUP_MASK) == PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE) +/** Whether a key type is a Diffie-Hellman key pair. */ +#define PSA_KEY_TYPE_IS_DH_KEY_PAIR(type) \ + (((type) & ~PSA_KEY_TYPE_DH_GROUP_MASK) == \ + PSA_KEY_TYPE_DH_KEY_PAIR_BASE) +/** Whether a key type is a Diffie-Hellman public key. */ +#define PSA_KEY_TYPE_IS_DH_PUBLIC_KEY(type) \ + (((type) & ~PSA_KEY_TYPE_DH_GROUP_MASK) == \ + PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE) + +/** Extract the group from a Diffie-Hellman key type. */ +#define PSA_KEY_TYPE_GET_GROUP(type) \ + ((psa_dh_group_t) (PSA_KEY_TYPE_IS_DH(type) ? \ + ((type) & PSA_KEY_TYPE_DH_GROUP_MASK) : \ + 0)) + +/** Diffie-Hellman groups defined in RFC 7919 Appendix A. + * + * This family includes groups with the following key sizes (in bits): + * 2048, 3072, 4096, 6144, 8192. A given implementation may support + * all of these sizes or only a subset. + */ +#define PSA_DH_GROUP_RFC7919 ((psa_dh_group_t) 0x03) + +#define PSA_GET_KEY_TYPE_BLOCK_SIZE_EXPONENT(type) \ + (((type) >> 8) & 7) +/** The block size of a block cipher. + * + * \param type A cipher key type (value of type #psa_key_type_t). + * + * \return The block size for a block cipher, or 1 for a stream cipher. + * The return value is undefined if \p type is not a supported + * cipher key type. + * + * \note It is possible to build stream cipher algorithms on top of a block + * cipher, for example CTR mode (#PSA_ALG_CTR). + * This macro only takes the key type into account, so it cannot be + * used to determine the size of the data that #psa_cipher_update() + * might buffer for future processing in general. + * + * \note This macro returns a compile-time constant if its argument is one. + * + * \warning This macro may evaluate its argument multiple times. + */ +#define PSA_BLOCK_CIPHER_BLOCK_SIZE(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_SYMMETRIC ? \ + 1u << PSA_GET_KEY_TYPE_BLOCK_SIZE_EXPONENT(type) : \ + 0u) + +/** Vendor-defined algorithm flag. + * + * Algorithms defined by this standard will never have the #PSA_ALG_VENDOR_FLAG + * bit set. Vendors who define additional algorithms must use an encoding with + * the #PSA_ALG_VENDOR_FLAG bit set and should respect the bitwise structure + * used by standard encodings whenever practical. + */ +#define PSA_ALG_VENDOR_FLAG ((psa_algorithm_t)0x80000000) + +#define PSA_ALG_CATEGORY_MASK ((psa_algorithm_t)0x7f000000) +#define PSA_ALG_CATEGORY_HASH ((psa_algorithm_t)0x01000000) +#define PSA_ALG_CATEGORY_MAC ((psa_algorithm_t)0x02000000) +#define PSA_ALG_CATEGORY_CIPHER ((psa_algorithm_t)0x04000000) +#define PSA_ALG_CATEGORY_AEAD ((psa_algorithm_t)0x06000000) +#define PSA_ALG_CATEGORY_SIGN ((psa_algorithm_t)0x10000000) +#define PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION ((psa_algorithm_t)0x12000000) +#define PSA_ALG_CATEGORY_KEY_DERIVATION ((psa_algorithm_t)0x20000000) +#define PSA_ALG_CATEGORY_KEY_AGREEMENT ((psa_algorithm_t)0x30000000) + +/** Whether an algorithm is vendor-defined. + * + * See also #PSA_ALG_VENDOR_FLAG. + */ +#define PSA_ALG_IS_VENDOR_DEFINED(alg) \ + (((alg) & PSA_ALG_VENDOR_FLAG) != 0) + +/** Whether the specified algorithm is a hash algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a hash algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_HASH(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_HASH) + +/** Whether the specified algorithm is a MAC algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a MAC algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_MAC(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_MAC) + +/** Whether the specified algorithm is a symmetric cipher algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a symmetric cipher algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_CIPHER(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_CIPHER) + +/** Whether the specified algorithm is an authenticated encryption + * with associated data (AEAD) algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is an AEAD algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_AEAD(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_AEAD) + +/** Whether the specified algorithm is a public-key signature algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a public-key signature algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_SIGN(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_SIGN) + +/** Whether the specified algorithm is a public-key encryption algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a public-key encryption algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION) + +/** Whether the specified algorithm is a key agreement algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a key agreement algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_KEY_AGREEMENT(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_AGREEMENT) + +/** Whether the specified algorithm is a key derivation algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a key derivation algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_KEY_DERIVATION(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_DERIVATION) + +#define PSA_ALG_HASH_MASK ((psa_algorithm_t)0x000000ff) +/** MD2 */ +#define PSA_ALG_MD2 ((psa_algorithm_t)0x01000001) +/** MD4 */ +#define PSA_ALG_MD4 ((psa_algorithm_t)0x01000002) +/** MD5 */ +#define PSA_ALG_MD5 ((psa_algorithm_t)0x01000003) +/** PSA_ALG_RIPEMD160 */ +#define PSA_ALG_RIPEMD160 ((psa_algorithm_t)0x01000004) +/** SHA1 */ +#define PSA_ALG_SHA_1 ((psa_algorithm_t)0x01000005) +/** SHA2-224 */ +#define PSA_ALG_SHA_224 ((psa_algorithm_t)0x01000008) +/** SHA2-256 */ +#define PSA_ALG_SHA_256 ((psa_algorithm_t)0x01000009) +/** SHA2-384 */ +#define PSA_ALG_SHA_384 ((psa_algorithm_t)0x0100000a) +/** SHA2-512 */ +#define PSA_ALG_SHA_512 ((psa_algorithm_t)0x0100000b) +/** SHA2-512/224 */ +#define PSA_ALG_SHA_512_224 ((psa_algorithm_t)0x0100000c) +/** SHA2-512/256 */ +#define PSA_ALG_SHA_512_256 ((psa_algorithm_t)0x0100000d) +/** SHA3-224 */ +#define PSA_ALG_SHA3_224 ((psa_algorithm_t)0x01000010) +/** SHA3-256 */ +#define PSA_ALG_SHA3_256 ((psa_algorithm_t)0x01000011) +/** SHA3-384 */ +#define PSA_ALG_SHA3_384 ((psa_algorithm_t)0x01000012) +/** SHA3-512 */ +#define PSA_ALG_SHA3_512 ((psa_algorithm_t)0x01000013) + +/** In a hash-and-sign algorithm policy, allow any hash algorithm. + * + * This value may be used to form the algorithm usage field of a policy + * for a signature algorithm that is parametrized by a hash. The key + * may then be used to perform operations using the same signature + * algorithm parametrized with any supported hash. + * + * That is, suppose that `PSA_xxx_SIGNATURE` is one of the following macros: + * - #PSA_ALG_RSA_PKCS1V15_SIGN, #PSA_ALG_RSA_PSS, + * - #PSA_ALG_ECDSA, #PSA_ALG_DETERMINISTIC_ECDSA. + * Then you may create and use a key as follows: + * - Set the key usage field using #PSA_ALG_ANY_HASH, for example: + * ``` + * psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); // or VERIFY + * psa_set_key_algorithm(&attributes, PSA_xxx_SIGNATURE(PSA_ALG_ANY_HASH)); + * ``` + * - Import or generate key material. + * - Call psa_sign_hash() or psa_verify_hash(), passing + * an algorithm built from `PSA_xxx_SIGNATURE` and a specific hash. Each + * call to sign or verify a message may use a different hash. + * ``` + * psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA_256), ...); + * psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA_512), ...); + * psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA3_256), ...); + * ``` + * + * This value may not be used to build other algorithms that are + * parametrized over a hash. For any valid use of this macro to build + * an algorithm \c alg, #PSA_ALG_IS_HASH_AND_SIGN(\c alg) is true. + * + * This value may not be used to build an algorithm specification to + * perform an operation. It is only valid to build policies. + */ +#define PSA_ALG_ANY_HASH ((psa_algorithm_t)0x010000ff) + +#define PSA_ALG_MAC_SUBCATEGORY_MASK ((psa_algorithm_t)0x00c00000) +#define PSA_ALG_HMAC_BASE ((psa_algorithm_t)0x02800000) +/** Macro to build an HMAC algorithm. + * + * For example, #PSA_ALG_HMAC(#PSA_ALG_SHA_256) is HMAC-SHA-256. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding HMAC algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_HMAC(hash_alg) \ + (PSA_ALG_HMAC_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) + +#define PSA_ALG_HMAC_GET_HASH(hmac_alg) \ + (PSA_ALG_CATEGORY_HASH | ((hmac_alg) & PSA_ALG_HASH_MASK)) + +/** Whether the specified algorithm is an HMAC algorithm. + * + * HMAC is a family of MAC algorithms that are based on a hash function. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is an HMAC algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_HMAC(alg) \ + (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \ + PSA_ALG_HMAC_BASE) + +/* In the encoding of a MAC algorithm, the bits corresponding to + * PSA_ALG_MAC_TRUNCATION_MASK encode the length to which the MAC is + * truncated. As an exception, the value 0 means the untruncated algorithm, + * whatever its length is. The length is encoded in 6 bits, so it can + * reach up to 63; the largest MAC is 64 bytes so its trivial truncation + * to full length is correctly encoded as 0 and any non-trivial truncation + * is correctly encoded as a value between 1 and 63. */ +#define PSA_ALG_MAC_TRUNCATION_MASK ((psa_algorithm_t)0x00003f00) +#define PSA_MAC_TRUNCATION_OFFSET 8 + +/** Macro to build a truncated MAC algorithm. + * + * A truncated MAC algorithm is identical to the corresponding MAC + * algorithm except that the MAC value for the truncated algorithm + * consists of only the first \p mac_length bytes of the MAC value + * for the untruncated algorithm. + * + * \note This macro may allow constructing algorithm identifiers that + * are not valid, either because the specified length is larger + * than the untruncated MAC or because the specified length is + * smaller than permitted by the implementation. + * + * \note It is implementation-defined whether a truncated MAC that + * is truncated to the same length as the MAC of the untruncated + * algorithm is considered identical to the untruncated algorithm + * for policy comparison purposes. + * + * \param mac_alg A MAC algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg) + * is true). This may be a truncated or untruncated + * MAC algorithm. + * \param mac_length Desired length of the truncated MAC in bytes. + * This must be at most the full length of the MAC + * and must be at least an implementation-specified + * minimum. The implementation-specified minimum + * shall not be zero. + * + * \return The corresponding MAC algorithm with the specified + * length. + * \return Unspecified if \p alg is not a supported + * MAC algorithm or if \p mac_length is too small or + * too large for the specified MAC algorithm. + */ +#define PSA_ALG_TRUNCATED_MAC(mac_alg, mac_length) \ + (((mac_alg) & ~PSA_ALG_MAC_TRUNCATION_MASK) | \ + ((mac_length) << PSA_MAC_TRUNCATION_OFFSET & PSA_ALG_MAC_TRUNCATION_MASK)) + +/** Macro to build the base MAC algorithm corresponding to a truncated + * MAC algorithm. + * + * \param mac_alg A MAC algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg) + * is true). This may be a truncated or untruncated + * MAC algorithm. + * + * \return The corresponding base MAC algorithm. + * \return Unspecified if \p alg is not a supported + * MAC algorithm. + */ +#define PSA_ALG_FULL_LENGTH_MAC(mac_alg) \ + ((mac_alg) & ~PSA_ALG_MAC_TRUNCATION_MASK) + +/** Length to which a MAC algorithm is truncated. + * + * \param mac_alg A MAC algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg) + * is true). + * + * \return Length of the truncated MAC in bytes. + * \return 0 if \p alg is a non-truncated MAC algorithm. + * \return Unspecified if \p alg is not a supported + * MAC algorithm. + */ +#define PSA_MAC_TRUNCATED_LENGTH(mac_alg) \ + (((mac_alg) & PSA_ALG_MAC_TRUNCATION_MASK) >> PSA_MAC_TRUNCATION_OFFSET) + +#define PSA_ALG_CIPHER_MAC_BASE ((psa_algorithm_t)0x02c00000) +/** The CBC-MAC construction over a block cipher + * + * \warning CBC-MAC is insecure in many cases. + * A more secure mode, such as #PSA_ALG_CMAC, is recommended. + */ +#define PSA_ALG_CBC_MAC ((psa_algorithm_t)0x02c00001) +/** The CMAC construction over a block cipher */ +#define PSA_ALG_CMAC ((psa_algorithm_t)0x02c00002) + +/** Whether the specified algorithm is a MAC algorithm based on a block cipher. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a MAC algorithm based on a block cipher, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) \ + (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \ + PSA_ALG_CIPHER_MAC_BASE) + +#define PSA_ALG_CIPHER_STREAM_FLAG ((psa_algorithm_t)0x00800000) +#define PSA_ALG_CIPHER_FROM_BLOCK_FLAG ((psa_algorithm_t)0x00400000) + +/** Whether the specified algorithm is a stream cipher. + * + * A stream cipher is a symmetric cipher that encrypts or decrypts messages + * by applying a bitwise-xor with a stream of bytes that is generated + * from a key. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a stream cipher algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier or if it is not a symmetric cipher algorithm. + */ +#define PSA_ALG_IS_STREAM_CIPHER(alg) \ + (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_CIPHER_STREAM_FLAG)) == \ + (PSA_ALG_CATEGORY_CIPHER | PSA_ALG_CIPHER_STREAM_FLAG)) + +/** The ARC4 stream cipher algorithm. + */ +#define PSA_ALG_ARC4 ((psa_algorithm_t)0x04800001) + +/** The ChaCha20 stream cipher. + * + * ChaCha20 is defined in RFC 7539. + * + * The nonce size for psa_cipher_set_iv() or psa_cipher_generate_iv() + * must be 12. + * + * The initial block counter is always 0. + * + */ +#define PSA_ALG_CHACHA20 ((psa_algorithm_t)0x04800005) + +/** The CTR stream cipher mode. + * + * CTR is a stream cipher which is built from a block cipher. + * The underlying block cipher is determined by the key type. + * For example, to use AES-128-CTR, use this algorithm with + * a key of type #PSA_KEY_TYPE_AES and a length of 128 bits (16 bytes). + */ +#define PSA_ALG_CTR ((psa_algorithm_t)0x04c00001) + +/** The CFB stream cipher mode. + * + * The underlying block cipher is determined by the key type. + */ +#define PSA_ALG_CFB ((psa_algorithm_t)0x04c00002) + +/** The OFB stream cipher mode. + * + * The underlying block cipher is determined by the key type. + */ +#define PSA_ALG_OFB ((psa_algorithm_t)0x04c00003) + +/** The XTS cipher mode. + * + * XTS is a cipher mode which is built from a block cipher. It requires at + * least one full block of input, but beyond this minimum the input + * does not need to be a whole number of blocks. + */ +#define PSA_ALG_XTS ((psa_algorithm_t)0x044000ff) + +/** The CBC block cipher chaining mode, with no padding. + * + * The underlying block cipher is determined by the key type. + * + * This symmetric cipher mode can only be used with messages whose lengths + * are whole number of blocks for the chosen block cipher. + */ +#define PSA_ALG_CBC_NO_PADDING ((psa_algorithm_t)0x04600100) + +/** The CBC block cipher chaining mode with PKCS#7 padding. + * + * The underlying block cipher is determined by the key type. + * + * This is the padding method defined by PKCS#7 (RFC 2315) §10.3. + */ +#define PSA_ALG_CBC_PKCS7 ((psa_algorithm_t)0x04600101) + +#define PSA_ALG_AEAD_FROM_BLOCK_FLAG ((psa_algorithm_t)0x00400000) + +/** Whether the specified algorithm is an AEAD mode on a block cipher. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is an AEAD algorithm which is an AEAD mode based on + * a block cipher, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) \ + (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_AEAD_FROM_BLOCK_FLAG)) == \ + (PSA_ALG_CATEGORY_AEAD | PSA_ALG_AEAD_FROM_BLOCK_FLAG)) + +/** The CCM authenticated encryption algorithm. + * + * The underlying block cipher is determined by the key type. + */ +#define PSA_ALG_CCM ((psa_algorithm_t)0x06401001) + +/** The GCM authenticated encryption algorithm. + * + * The underlying block cipher is determined by the key type. + */ +#define PSA_ALG_GCM ((psa_algorithm_t)0x06401002) + +/** The Chacha20-Poly1305 AEAD algorithm. + * + * The ChaCha20_Poly1305 construction is defined in RFC 7539. + * + * Implementations must support 12-byte nonces, may support 8-byte nonces, + * and should reject other sizes. + * + * Implementations must support 16-byte tags and should reject other sizes. + */ +#define PSA_ALG_CHACHA20_POLY1305 ((psa_algorithm_t)0x06001005) + +/* In the encoding of a AEAD algorithm, the bits corresponding to + * PSA_ALG_AEAD_TAG_LENGTH_MASK encode the length of the AEAD tag. + * The constants for default lengths follow this encoding. + */ +#define PSA_ALG_AEAD_TAG_LENGTH_MASK ((psa_algorithm_t)0x00003f00) +#define PSA_AEAD_TAG_LENGTH_OFFSET 8 + +/** Macro to build a shortened AEAD algorithm. + * + * A shortened AEAD algorithm is similar to the corresponding AEAD + * algorithm, but has an authentication tag that consists of fewer bytes. + * Depending on the algorithm, the tag length may affect the calculation + * of the ciphertext. + * + * \param aead_alg An AEAD algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_AEAD(\p alg) + * is true). + * \param tag_length Desired length of the authentication tag in bytes. + * + * \return The corresponding AEAD algorithm with the specified + * length. + * \return Unspecified if \p alg is not a supported + * AEAD algorithm or if \p tag_length is not valid + * for the specified AEAD algorithm. + */ +#define PSA_ALG_AEAD_WITH_TAG_LENGTH(aead_alg, tag_length) \ + (((aead_alg) & ~PSA_ALG_AEAD_TAG_LENGTH_MASK) | \ + ((tag_length) << PSA_AEAD_TAG_LENGTH_OFFSET & \ + PSA_ALG_AEAD_TAG_LENGTH_MASK)) + +/** Calculate the corresponding AEAD algorithm with the default tag length. + * + * \param aead_alg An AEAD algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return The corresponding AEAD algorithm with the default + * tag length for that algorithm. + */ +#define PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH(aead_alg) \ + ( \ + PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, PSA_ALG_CCM) \ + PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, PSA_ALG_GCM) \ + PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, PSA_ALG_CHACHA20_POLY1305) \ + 0) +#define PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, ref) \ + PSA_ALG_AEAD_WITH_TAG_LENGTH(aead_alg, 0) == \ + PSA_ALG_AEAD_WITH_TAG_LENGTH(ref, 0) ? \ + ref : + +#define PSA_ALG_RSA_PKCS1V15_SIGN_BASE ((psa_algorithm_t)0x10020000) +/** RSA PKCS#1 v1.5 signature with hashing. + * + * This is the signature scheme defined by RFC 8017 + * (PKCS#1: RSA Cryptography Specifications) under the name + * RSASSA-PKCS1-v1_5. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding RSA PKCS#1 v1.5 signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_RSA_PKCS1V15_SIGN(hash_alg) \ + (PSA_ALG_RSA_PKCS1V15_SIGN_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +/** Raw PKCS#1 v1.5 signature. + * + * The input to this algorithm is the DigestInfo structure used by + * RFC 8017 (PKCS#1: RSA Cryptography Specifications), §9.2 + * steps 3–6. + */ +#define PSA_ALG_RSA_PKCS1V15_SIGN_RAW PSA_ALG_RSA_PKCS1V15_SIGN_BASE +#define PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PKCS1V15_SIGN_BASE) + +#define PSA_ALG_RSA_PSS_BASE ((psa_algorithm_t)0x10030000) +/** RSA PSS signature with hashing. + * + * This is the signature scheme defined by RFC 8017 + * (PKCS#1: RSA Cryptography Specifications) under the name + * RSASSA-PSS, with the message generation function MGF1, and with + * a salt length equal to the length of the hash. The specified + * hash algorithm is used to hash the input message, to create the + * salted hash, and for the mask generation. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding RSA PSS signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_RSA_PSS(hash_alg) \ + (PSA_ALG_RSA_PSS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_IS_RSA_PSS(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PSS_BASE) + +#define PSA_ALG_ECDSA_BASE ((psa_algorithm_t)0x10060000) +/** ECDSA signature with hashing. + * + * This is the ECDSA signature scheme defined by ANSI X9.62, + * with a random per-message secret number (*k*). + * + * The representation of the signature as a byte string consists of + * the concatentation of the signature values *r* and *s*. Each of + * *r* and *s* is encoded as an *N*-octet string, where *N* is the length + * of the base point of the curve in octets. Each value is represented + * in big-endian order (most significant octet first). + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding ECDSA signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_ECDSA(hash_alg) \ + (PSA_ALG_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +/** ECDSA signature without hashing. + * + * This is the same signature scheme as #PSA_ALG_ECDSA(), but + * without specifying a hash algorithm. This algorithm may only be + * used to sign or verify a sequence of bytes that should be an + * already-calculated hash. Note that the input is padded with + * zeros on the left or truncated on the left as required to fit + * the curve size. + */ +#define PSA_ALG_ECDSA_ANY PSA_ALG_ECDSA_BASE +#define PSA_ALG_DETERMINISTIC_ECDSA_BASE ((psa_algorithm_t)0x10070000) +/** Deterministic ECDSA signature with hashing. + * + * This is the deterministic ECDSA signature scheme defined by RFC 6979. + * + * The representation of a signature is the same as with #PSA_ALG_ECDSA(). + * + * Note that when this algorithm is used for verification, signatures + * made with randomized ECDSA (#PSA_ALG_ECDSA(\p hash_alg)) with the + * same private key are accepted. In other words, + * #PSA_ALG_DETERMINISTIC_ECDSA(\p hash_alg) differs from + * #PSA_ALG_ECDSA(\p hash_alg) only for signature, not for verification. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding deterministic ECDSA signature + * algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_DETERMINISTIC_ECDSA(hash_alg) \ + (PSA_ALG_DETERMINISTIC_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_ECDSA_DETERMINISTIC_FLAG ((psa_algorithm_t)0x00010000) +#define PSA_ALG_IS_ECDSA(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_ECDSA_DETERMINISTIC_FLAG) == \ + PSA_ALG_ECDSA_BASE) +#define PSA_ALG_ECDSA_IS_DETERMINISTIC(alg) \ + (((alg) & PSA_ALG_ECDSA_DETERMINISTIC_FLAG) != 0) +#define PSA_ALG_IS_DETERMINISTIC_ECDSA(alg) \ + (PSA_ALG_IS_ECDSA(alg) && PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) +#define PSA_ALG_IS_RANDOMIZED_ECDSA(alg) \ + (PSA_ALG_IS_ECDSA(alg) && !PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) + +/** Whether the specified algorithm is a hash-and-sign algorithm. + * + * Hash-and-sign algorithms are public-key signature algorithms structured + * in two parts: first the calculation of a hash in a way that does not + * depend on the key, then the calculation of a signature from the + * hash value and the key. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a hash-and-sign algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_HASH_AND_SIGN(alg) \ + (PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || \ + PSA_ALG_IS_ECDSA(alg)) + +/** Get the hash used by a hash-and-sign signature algorithm. + * + * A hash-and-sign algorithm is a signature algorithm which is + * composed of two phases: first a hashing phase which does not use + * the key and produces a hash of the input message, then a signing + * phase which only uses the hash and the key and not the message + * itself. + * + * \param alg A signature algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_SIGN(\p alg) is true). + * + * \return The underlying hash algorithm if \p alg is a hash-and-sign + * algorithm. + * \return 0 if \p alg is a signature algorithm that does not + * follow the hash-and-sign structure. + * \return Unspecified if \p alg is not a signature algorithm or + * if it is not supported by the implementation. + */ +#define PSA_ALG_SIGN_GET_HASH(alg) \ + (PSA_ALG_IS_HASH_AND_SIGN(alg) ? \ + ((alg) & PSA_ALG_HASH_MASK) == 0 ? /*"raw" algorithm*/ 0 : \ + ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ + 0) + +/** RSA PKCS#1 v1.5 encryption. + */ +#define PSA_ALG_RSA_PKCS1V15_CRYPT ((psa_algorithm_t)0x12020000) + +#define PSA_ALG_RSA_OAEP_BASE ((psa_algorithm_t)0x12030000) +/** RSA OAEP encryption. + * + * This is the encryption scheme defined by RFC 8017 + * (PKCS#1: RSA Cryptography Specifications) under the name + * RSAES-OAEP, with the message generation function MGF1. + * + * \param hash_alg The hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true) to use + * for MGF1. + * + * \return The corresponding RSA OAEP signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_RSA_OAEP(hash_alg) \ + (PSA_ALG_RSA_OAEP_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_IS_RSA_OAEP(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_OAEP_BASE) +#define PSA_ALG_RSA_OAEP_GET_HASH(alg) \ + (PSA_ALG_IS_RSA_OAEP(alg) ? \ + ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ + 0) + +#define PSA_ALG_HKDF_BASE ((psa_algorithm_t)0x20000100) +/** Macro to build an HKDF algorithm. + * + * For example, `PSA_ALG_HKDF(PSA_ALG_SHA256)` is HKDF using HMAC-SHA-256. + * + * This key derivation algorithm uses the following inputs: + * - #PSA_KEY_DERIVATION_INPUT_SALT is the salt used in the "extract" step. + * It is optional; if omitted, the derivation uses an empty salt. + * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key used in the "extract" step. + * - #PSA_KEY_DERIVATION_INPUT_INFO is the info string used in the "expand" step. + * You must pass #PSA_KEY_DERIVATION_INPUT_SALT before #PSA_KEY_DERIVATION_INPUT_SECRET. + * You may pass #PSA_KEY_DERIVATION_INPUT_INFO at any time after steup and before + * starting to generate output. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding HKDF algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_HKDF(hash_alg) \ + (PSA_ALG_HKDF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +/** Whether the specified algorithm is an HKDF algorithm. + * + * HKDF is a family of key derivation algorithms that are based on a hash + * function and the HMAC construction. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is an HKDF algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_HKDF(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_BASE) +#define PSA_ALG_HKDF_GET_HASH(hkdf_alg) \ + (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) + +#define PSA_ALG_TLS12_PRF_BASE ((psa_algorithm_t)0x20000200) +/** Macro to build a TLS-1.2 PRF algorithm. + * + * TLS 1.2 uses a custom pseudorandom function (PRF) for key schedule, + * specified in Section 5 of RFC 5246. It is based on HMAC and can be + * used with either SHA-256 or SHA-384. + * + * This key derivation algorithm uses the following inputs, which must be + * passed in the order given here: + * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed. + * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key. + * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label. + * + * For the application to TLS-1.2 key expansion, the seed is the + * concatenation of ServerHello.Random + ClientHello.Random, + * and the label is "key expansion". + * + * For example, `PSA_ALG_TLS12_PRF(PSA_ALG_SHA256)` represents the + * TLS 1.2 PRF using HMAC-SHA-256. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding TLS-1.2 PRF algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_TLS12_PRF(hash_alg) \ + (PSA_ALG_TLS12_PRF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) + +/** Whether the specified algorithm is a TLS-1.2 PRF algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a TLS-1.2 PRF algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_TLS12_PRF(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_TLS12_PRF_BASE) +#define PSA_ALG_TLS12_PRF_GET_HASH(hkdf_alg) \ + (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) + +#define PSA_ALG_TLS12_PSK_TO_MS_BASE ((psa_algorithm_t)0x20000300) +/** Macro to build a TLS-1.2 PSK-to-MasterSecret algorithm. + * + * In a pure-PSK handshake in TLS 1.2, the master secret is derived + * from the PreSharedKey (PSK) through the application of padding + * (RFC 4279, Section 2) and the TLS-1.2 PRF (RFC 5246, Section 5). + * The latter is based on HMAC and can be used with either SHA-256 + * or SHA-384. + * + * This key derivation algorithm uses the following inputs, which must be + * passed in the order given here: + * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed. + * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key. + * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label. + * + * For the application to TLS-1.2, the seed (which is + * forwarded to the TLS-1.2 PRF) is the concatenation of the + * ClientHello.Random + ServerHello.Random, + * and the label is "master secret" or "extended master secret". + * + * For example, `PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA256)` represents the + * TLS-1.2 PSK to MasterSecret derivation PRF using HMAC-SHA-256. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding TLS-1.2 PSK to MS algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_TLS12_PSK_TO_MS(hash_alg) \ + (PSA_ALG_TLS12_PSK_TO_MS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) + +/** Whether the specified algorithm is a TLS-1.2 PSK to MS algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a TLS-1.2 PSK to MS algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_TLS12_PSK_TO_MS(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_TLS12_PSK_TO_MS_BASE) +#define PSA_ALG_TLS12_PSK_TO_MS_GET_HASH(hkdf_alg) \ + (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) + +#define PSA_ALG_KEY_DERIVATION_MASK ((psa_algorithm_t)0x0803ffff) +#define PSA_ALG_KEY_AGREEMENT_MASK ((psa_algorithm_t)0x10fc0000) + +/** Macro to build a combined algorithm that chains a key agreement with + * a key derivation. + * + * \param ka_alg A key agreement algorithm (\c PSA_ALG_XXX value such + * that #PSA_ALG_IS_KEY_AGREEMENT(\p ka_alg) is true). + * \param kdf_alg A key derivation algorithm (\c PSA_ALG_XXX value such + * that #PSA_ALG_IS_KEY_DERIVATION(\p kdf_alg) is true). + * + * \return The corresponding key agreement and derivation + * algorithm. + * \return Unspecified if \p ka_alg is not a supported + * key agreement algorithm or \p kdf_alg is not a + * supported key derivation algorithm. + */ +#define PSA_ALG_KEY_AGREEMENT(ka_alg, kdf_alg) \ + ((ka_alg) | (kdf_alg)) + +#define PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) \ + (((alg) & PSA_ALG_KEY_DERIVATION_MASK) | PSA_ALG_CATEGORY_KEY_DERIVATION) + +#define PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) \ + (((alg) & PSA_ALG_KEY_AGREEMENT_MASK) | PSA_ALG_CATEGORY_KEY_AGREEMENT) + +/** Whether the specified algorithm is a raw key agreement algorithm. + * + * A raw key agreement algorithm is one that does not specify + * a key derivation function. + * Usually, raw key agreement algorithms are constructed directly with + * a \c PSA_ALG_xxx macro while non-raw key agreement algorithms are + * constructed with PSA_ALG_KEY_AGREEMENT(). + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a raw key agreement algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_RAW_KEY_AGREEMENT(alg) \ + (PSA_ALG_IS_KEY_AGREEMENT(alg) && \ + PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) == PSA_ALG_CATEGORY_KEY_DERIVATION) + +#define PSA_ALG_IS_KEY_DERIVATION_OR_AGREEMENT(alg) \ + ((PSA_ALG_IS_KEY_DERIVATION(alg) || PSA_ALG_IS_KEY_AGREEMENT(alg))) + +/** The finite-field Diffie-Hellman (DH) key agreement algorithm. + * + * The shared secret produced by key agreement is + * `g^{ab}` in big-endian format. + * It is `ceiling(m / 8)` bytes long where `m` is the size of the prime `p` + * in bits. + */ +#define PSA_ALG_FFDH ((psa_algorithm_t)0x30100000) + +/** Whether the specified algorithm is a finite field Diffie-Hellman algorithm. + * + * This includes the raw finite field Diffie-Hellman algorithm as well as + * finite-field Diffie-Hellman followed by any supporter key derivation + * algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a finite field Diffie-Hellman algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key agreement algorithm identifier. + */ +#define PSA_ALG_IS_FFDH(alg) \ + (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_FFDH) + +/** The elliptic curve Diffie-Hellman (ECDH) key agreement algorithm. + * + * The shared secret produced by key agreement is the x-coordinate of + * the shared secret point. It is always `ceiling(m / 8)` bytes long where + * `m` is the bit size associated with the curve, i.e. the bit size of the + * order of the curve's coordinate field. When `m` is not a multiple of 8, + * the byte containing the most significant bit of the shared secret + * is padded with zero bits. The byte order is either little-endian + * or big-endian depending on the curve type. + * + * - For Montgomery curves (curve types `PSA_ECC_CURVE_CURVEXXX`), + * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` + * in little-endian byte order. + * The bit size is 448 for Curve448 and 255 for Curve25519. + * - For Weierstrass curves over prime fields (curve types + * `PSA_ECC_CURVE_SECPXXX` and `PSA_ECC_CURVE_BRAINPOOL_PXXX`), + * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` + * in big-endian byte order. + * The bit size is `m = ceiling(log_2(p))` for the field `F_p`. + * - For Weierstrass curves over binary fields (curve types + * `PSA_ECC_CURVE_SECTXXX`), + * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` + * in big-endian byte order. + * The bit size is `m` for the field `F_{2^m}`. + */ +#define PSA_ALG_ECDH ((psa_algorithm_t)0x30200000) + +/** Whether the specified algorithm is an elliptic curve Diffie-Hellman + * algorithm. + * + * This includes the raw elliptic curve Diffie-Hellman algorithm as well as + * elliptic curve Diffie-Hellman followed by any supporter key derivation + * algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is an elliptic curve Diffie-Hellman algorithm, + * 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key agreement algorithm identifier. + */ +#define PSA_ALG_IS_ECDH(alg) \ + (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_ECDH) + +/** Whether the specified algorithm encoding is a wildcard. + * + * Wildcard values may only be used to set the usage algorithm field in + * a policy, not to perform an operation. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a wildcard algorithm encoding. + * \return 0 if \c alg is a non-wildcard algorithm encoding (suitable for + * an operation). + * \return This macro may return either 0 or 1 if \c alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_WILDCARD(alg) \ + (PSA_ALG_IS_HASH_AND_SIGN(alg) ? \ + PSA_ALG_SIGN_GET_HASH(alg) == PSA_ALG_ANY_HASH : \ + (alg) == PSA_ALG_ANY_HASH) + +/**@}*/ + +/** \defgroup key_lifetimes Key lifetimes + * @{ + */ + +/** A volatile key only exists as long as the handle to it is not closed. + * The key material is guaranteed to be erased on a power reset. + */ +#define PSA_KEY_LIFETIME_VOLATILE ((psa_key_lifetime_t)0x00000000) + +/** The default storage area for persistent keys. + * + * A persistent key remains in storage until it is explicitly destroyed or + * until the corresponding storage area is wiped. This specification does + * not define any mechanism to wipe a storage area, but implementations may + * provide their own mechanism (for example to perform a factory reset, + * to prepare for device refurbishment, or to uninstall an application). + * + * This lifetime value is the default storage area for the calling + * application. Implementations may offer other storage areas designated + * by other lifetime values as implementation-specific extensions. + */ +#define PSA_KEY_LIFETIME_PERSISTENT ((psa_key_lifetime_t)0x00000001) + +/** The minimum value for a key identifier chosen by the application. + */ +#define PSA_KEY_ID_USER_MIN ((psa_app_key_id_t)0x00000001) +/** The maximum value for a key identifier chosen by the application. + */ +#define PSA_KEY_ID_USER_MAX ((psa_app_key_id_t)0x3fffffff) +/** The minimum value for a key identifier chosen by the implementation. + */ +#define PSA_KEY_ID_VENDOR_MIN ((psa_app_key_id_t)0x40000000) +/** The maximum value for a key identifier chosen by the implementation. + */ +#define PSA_KEY_ID_VENDOR_MAX ((psa_app_key_id_t)0x7fffffff) + +/**@}*/ + +/** \defgroup policy Key policies + * @{ + */ + +/** Whether the key may be exported. + * + * A public key or the public part of a key pair may always be exported + * regardless of the value of this permission flag. + * + * If a key does not have export permission, implementations shall not + * allow the key to be exported in plain form from the cryptoprocessor, + * whether through psa_export_key() or through a proprietary interface. + * The key may however be exportable in a wrapped form, i.e. in a form + * where it is encrypted by another key. + */ +#define PSA_KEY_USAGE_EXPORT ((psa_key_usage_t)0x00000001) + +/** Whether the key may be copied. + * + * This flag allows the use of psa_copy_key() to make a copy of the key + * with the same policy or a more restrictive policy. + * + * For lifetimes for which the key is located in a secure element which + * enforce the non-exportability of keys, copying a key outside the secure + * element also requires the usage flag #PSA_KEY_USAGE_EXPORT. + * Copying the key inside the secure element is permitted with just + * #PSA_KEY_USAGE_COPY if the secure element supports it. + * For keys with the lifetime #PSA_KEY_LIFETIME_VOLATILE or + * #PSA_KEY_LIFETIME_PERSISTENT, the usage flag #PSA_KEY_USAGE_COPY + * is sufficient to permit the copy. + */ +#define PSA_KEY_USAGE_COPY ((psa_key_usage_t)0x00000002) + +/** Whether the key may be used to encrypt a message. + * + * This flag allows the key to be used for a symmetric encryption operation, + * for an AEAD encryption-and-authentication operation, + * or for an asymmetric encryption operation, + * if otherwise permitted by the key's type and policy. + * + * For a key pair, this concerns the public key. + */ +#define PSA_KEY_USAGE_ENCRYPT ((psa_key_usage_t)0x00000100) + +/** Whether the key may be used to decrypt a message. + * + * This flag allows the key to be used for a symmetric decryption operation, + * for an AEAD decryption-and-verification operation, + * or for an asymmetric decryption operation, + * if otherwise permitted by the key's type and policy. + * + * For a key pair, this concerns the private key. + */ +#define PSA_KEY_USAGE_DECRYPT ((psa_key_usage_t)0x00000200) + +/** Whether the key may be used to sign a message. + * + * This flag allows the key to be used for a MAC calculation operation + * or for an asymmetric signature operation, + * if otherwise permitted by the key's type and policy. + * + * For a key pair, this concerns the private key. + */ +#define PSA_KEY_USAGE_SIGN_HASH ((psa_key_usage_t)0x00000400) + +/** Whether the key may be used to verify a message signature. + * + * This flag allows the key to be used for a MAC verification operation + * or for an asymmetric signature verification operation, + * if otherwise permitted by by the key's type and policy. + * + * For a key pair, this concerns the public key. + */ +#define PSA_KEY_USAGE_VERIFY_HASH ((psa_key_usage_t)0x00000800) + +/** Whether the key may be used to derive other keys. + */ +#define PSA_KEY_USAGE_DERIVE ((psa_key_usage_t)0x00001000) + +/**@}*/ + +/** \defgroup derivation Key derivation + * @{ + */ + +/** A secret input for key derivation. + * + * This should be a key of type #PSA_KEY_TYPE_DERIVE + * (passed to psa_key_derivation_input_key()) + * or the shared secret resulting from a key agreement + * (obtained via psa_key_derivation_key_agreement()). + * + * The secret can also be a direct input (passed to + * key_derivation_input_bytes()). In this case, the derivation operation + * may not be used to derive keys: the operation will only allow + * psa_key_derivation_output_bytes(), not psa_key_derivation_output_key(). + */ +#define PSA_KEY_DERIVATION_INPUT_SECRET ((psa_key_derivation_step_t)0x0101) + +/** A label for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + */ +#define PSA_KEY_DERIVATION_INPUT_LABEL ((psa_key_derivation_step_t)0x0201) + +/** A salt for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + */ +#define PSA_KEY_DERIVATION_INPUT_SALT ((psa_key_derivation_step_t)0x0202) + +/** An information string for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + */ +#define PSA_KEY_DERIVATION_INPUT_INFO ((psa_key_derivation_step_t)0x0203) + +/** A seed for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + */ +#define PSA_KEY_DERIVATION_INPUT_SEED ((psa_key_derivation_step_t)0x0204) + +/**@}*/ + +#endif /* PSA_CRYPTO_VALUES_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/error.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/error.h new file mode 100644 index 0000000..ba0e0e3 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/error.h @@ -0,0 +1,56 @@ +/* +* Copyright (c) 2019 ARM Limited. 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. +*/ + +/* psa/error.h +Standard error codes for the SPM and RoT Services +As defined in PSA Firmware Framework v1.0 +*/ + +#ifndef __PSA_ERROR__ +#define __PSA_ERROR__ + +#include +#include + +typedef int32_t psa_status_t; + +#define PSA_SUCCESS ((psa_status_t)0) + +#define PSA_ERROR_PROGRAMMER_ERROR ((psa_status_t)-129) +#define PSA_ERROR_CONNECTION_REFUSED ((psa_status_t)-130) +#define PSA_ERROR_CONNECTION_BUSY ((psa_status_t)-131) +#define PSA_ERROR_GENERIC_ERROR ((psa_status_t)-132) +#define PSA_ERROR_NOT_PERMITTED ((psa_status_t)-133) +#define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)-134) +#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)-135) +#define PSA_ERROR_INVALID_HANDLE ((psa_status_t)-136) +#define PSA_ERROR_BAD_STATE ((psa_status_t)-137) +#define PSA_ERROR_BUFFER_TOO_SMALL ((psa_status_t)-138) +#define PSA_ERROR_ALREADY_EXISTS ((psa_status_t)-139) +#define PSA_ERROR_DOES_NOT_EXIST ((psa_status_t)-140) +#define PSA_ERROR_INSUFFICIENT_MEMORY ((psa_status_t)-141) +#define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)-142) +#define PSA_ERROR_INSUFFICIENT_DATA ((psa_status_t)-143) +#define PSA_ERROR_SERVICE_FAILURE ((psa_status_t)-144) +#define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t)-145) +#define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)-146) +#define PSA_ERROR_HARDWARE_FAILURE ((psa_status_t)-147) +#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) +#define PSA_ERROR_DATA_CORRUPT ((psa_status_t)-152) + +#endif // __PSA_ERROR__ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/internal_trusted_storage.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/internal_trusted_storage.h new file mode 100644 index 0000000..7b3b6a9 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/internal_trusted_storage.h @@ -0,0 +1,23 @@ +/* Copyright (c) 2017-2018 ARM Limited + * + * 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 __MBED_INTERNAL_TRUSTED_STORAGE_H__ +#define __MBED_INTERNAL_TRUSTED_STORAGE_H__ + +#include "psa_prot_internal_storage.h" + +#endif // __MBED_INTERNAL_TRUSTED_STORAGE_H__ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/lifecycle.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/lifecycle.h new file mode 100644 index 0000000..1afa44f --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/lifecycle.h @@ -0,0 +1,79 @@ +/* Copyright (c) 2018 ARM Limited + * + * 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 __LIFECYCLE_H__ +#define __LIFECYCLE_H__ + +/** @file +@brief This file describes the PSA RoT Lifecycle API +*/ + +#include +#include +#include "mbed_toolchain.h" +#include "psa/error.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define PSA_LIFECYCLE_STATE_MASK (0xff00u) /**< A mask value that extracts the main lifecycle state */ +#define PSA_LIFECYCLE_SUBSTATE_MASK (0x00ffu) /**< A mask value that extracts the IMPLEMENTATION DEFINED lifecycle sub-state */ + +#define PSA_LIFECYCLE_UNKNOWN (0x0000u) /**< State is unknown */ +#define PSA_LIFECYCLE_ASSEMBLY_AND_TEST (0x1000u) /**< Assembly and Test state */ +#define PSA_LIFECYCLE_PSA_ROT_PROVISIONING (0x2000u) /**< PSA RoT Provisioning state */ +#define PSA_LIFECYCLE_SECURED (0x3000u) /**< Secured state */ +#define PSA_LIFECYCLE_NON_PSA_ROT_DEBUG (0x4000u) /**< Non PSA RoT debug state */ +#define PSA_LIFECYCLE_RECOVERABLE_PSA_ROT_DEBUG (0x5000u) /**< Recoverable PSA RoT Debug state */ +#define PSA_LIFECYCLE_DECOMMISSIONED (0x6000u) /**< Decommissioned state */ + +/** \brief Get PSA RoT lifecycle state + * + * \retval The main state and sub-state are encoded as follows:@n + @a version[15:8] – main lifecycle state + @a version[7:0] – IMPLEMENTATION DEFINED sub-state + */ +uint32_t psa_security_lifecycle_state(void); + +/** \brief Request state change + * + * State change requested and the reset the system. + * \note System reset will not be performed when switching from PSA_LIFECYCLE_ASSEMBLY_AND_TEST + * to PSA_LIFECYCLE_ASSEMBLY_AND_TEST. + * + * \note state change to follwing states will delete PSA internal storage: + * - PSA_LIFECYCLE_ASSEMBLY_AND_TEST + * - PSA_LIFECYCLE_PSA_ROT_PROVISIONING + * - PSA_LIFECYCLE_DECOMMISSIONED + */ +psa_status_t mbed_psa_reboot_and_request_new_security_state(uint32_t new_state); + + +/** \brief Resets the system + * + * PSA targets do not allow NSPE to access system power domain. + * This API requests system reset to be carried out by SPE once all critical secure tasks are finished. + */ +MBED_NORETURN void mbed_psa_system_reset(); + +#ifdef __cplusplus +} +#endif + +#endif // __LIFECYCLE_H__ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/protected_storage.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/protected_storage.h new file mode 100644 index 0000000..6b299a3 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/protected_storage.h @@ -0,0 +1,202 @@ +/* Copyright (C) 2019, ARM Limited, 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. + */ + +/** @file +@brief This file describes the PSA Protected Storage API +*/ + +#ifndef __PSA_PROTECTED_STORAGE_H__ +#define __PSA_PROTECTED_STORAGE_H__ + +#include +#include + +#include "psa/error.h" +#include "psa/storage_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define PSA_PS_API_VERSION_MAJOR 1 /**< The major version number of the PSA PS API. It will be incremented on significant updates that may include breaking changes */ +#define PSA_PS_API_VERSION_MINOR 1 /**< The minor version number of the PSA PS API. It will be incremented in small updates that are unlikely to include breaking changes */ + + +/** + * \brief create a new or modify an existing key/value pair + * + * \param[in] uid the identifier for the data + * \param[in] data_length The size in bytes of the data in `p_data` + * \param[in] p_data A buffer containing the data + * \param[in] create_flags The flags indicating the properties of the data + * + * \return A status indicating the success/failure of the operation + + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the provided uid value was already created with PSA_STORAGE_WRITE_ONCE_FLAG + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more of the given arguments were invalid. + * \retval PSA_ERROR_NOT_SUPPORTED The operation failed because one or more of the flags provided in `create_flags` is not supported or is not valid + * \retval PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because there was insufficient space on the storage medium + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an unspecified internal failure + */ +psa_status_t psa_ps_set(psa_storage_uid_t uid, + size_t data_length, + const void *p_data, + psa_storage_create_flags_t create_flags); + +/** + * \brief Retrieve the value for a provided uid + * + * \param[in] uid The identifier for the data + * \param[in] data_offset The offset within the data associated with the `uid` to start retrieving data + * \param[in] data_length The amount of data to read (and the minimum allocated size of the `p_data` buffer) + * \param[out] p_data The buffer where the data will be placed upon successful completion + * \param[out] p_data_length The actual amount of data returned + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more of the given arguments were invalid (null pointer, wrong flags etc.) + * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided uid value was not found in the storage + * \retval PSA_ERROR_BUFFER_TOO_SMALL The operation failed because the data associated with provided uid does not fit `data_size` + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an unspecified internal failure + * \retval PSA_ERROR_DATA_CORRUPT The operation failed because of an authentication failure when attempting to get the key + * \retval PSA_ERROR_INVALID_SIGNATURE The operation failed because the data associated with the UID failed authentication + */ +psa_status_t psa_ps_get(psa_storage_uid_t uid, + size_t data_offset, + size_t data_length, + void *p_data, + size_t *p_data_length); + +/** + * \brief Retrieve the metadata about the provided uid + * + * \param[in] uid The identifier for the data + * \param[out] p_info A pointer to the `psa_storage_info_t` struct that will be populated with the metadata + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more of the given arguments were invalid (null pointer, wrong flags etc.) + * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided uid value was not found in the storage + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an unspecified internal failure + * \retval PSA_ERROR_DATA_CORRUPT The operation failed because of an authentication failure when attempting to get the key + * \retval PSA_ERROR_INVALID_SIGNATURE The operation failed because the data associated with the UID failed authentication + */ +psa_status_t psa_ps_get_info(psa_storage_uid_t uid, struct psa_storage_info_t *p_info); + +/** + * \brief Remove the provided uid and its associated data from the storage + * + * \param[in] uid The identifier for the data to be removed + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more of the given arguments were invalid (null pointer, wrong flags etc.) + * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided uid value was not found in the storage + * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the provided uid value was created with psa_eps_WRITE_ONCE_FLAG + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an unspecified internal failure + */ +psa_status_t psa_ps_remove(psa_storage_uid_t uid); + +/** + * Creates an asset based on the given identifier, the maximum size and + * creation flags. This create allocates the space in the secure storage + * area without setting any data in the asset. + * + * It is only necessary to call this function for items that will be written + * with the \ref psa_ps_set_extended function. If only the \ref psa_ps_set function + * is needed, calls to this function are redundant. + * + * If the \ref PSA_STORAGE_FLAG_WRITE_ONCE flag is passed, implementations should + * return \ref PSA_ERROR_NOT_SUPPORTED. + * + * This function is optional. Not all PSA Protected Storage Implementations + * will implement this function. Consult the documentation of your chosen + * platform to determine if it is present. + * + * \param[in] uid A unique identifier for the asset. + * \param[in] size The maximum size in bytes of the asset. + * \param[in] create_flags Create flags \ref psa_storage_create_flags_t. + * + * \retval PSA_SUCCESS The assest does not exist and the input parameters are correct or + * the asset already exists, the input parameters are the same that + * have been used to create the asset and the owner is the same and the current asset content is kept + * TDB: "Owner is the same" doesn't really make sense from a PSA perspective, as each partition + * has its own UID space, making other partitions' data unadressable + * \retval PSA_ERROR_STORAGE_FAILURE The create action has a physical storage error + * \retval PSA_ERROR_INSUFFICIENT_STORAGE The maximum size is bigger of the current available space + * \retval PSA_ERROR_NOT_SUPPORTED One or more create_flags are not valid or supported + * \retval PSA_ERROR_INVALID_ARGUMENT The asset exists and the input paramters are not the same as the existing asset + * \retval PSA_ERROR_NOT_SUPPORTED The implementation of the API does not support this function + * \retval PSA_ERROR_GENERIC_ERROR The operation has failed due to an unspecified error + */ +psa_status_t psa_ps_create(psa_storage_uid_t uid, + size_t size, + psa_storage_create_flags_t create_flags); + +/** + * Sets partial data into an asset based on the given identifier, data_offset, + * data length and p_data. + * + * Before calling this function, the asset must have been created with a call + * to \ref psa_ps_create. + * + * This function is optional. Not all PSA Protected Storage Implementations + * will implement this function. Consult the documentation of your chosen + * platform to determine if it is present. + * + * \param[in] uid The unique identifier for the asset. + * \param[in] data_offset Offset within the asset to start the write. + * \param[in] data_length The size in bytes of the data in p_data to write. + * \param[in] p_data Pointer to a buffer which contains the data to write. + * + * \retval PSA_SUCCESS If the asset exists, the input parameters are correct and the data + * is correctly written in the physical storage + * \retval PSA_ERROR_STORAGE_FAILURE If the data is not written correctly in the physical storage + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more of the given arguments were invalid (null pointer, wrong flags, etc) + * \retval PSA_ERROR_DOES_NOT_EXIST The specified UID was not found + * \retval PSA_ERROR_NOT_SUPPORTED The implementation of the API does not support this function + * \retval PSA_ERROR_GENERIC_ERROR The operation failed due to an unspecified error + * \retval PSA_ERROR_DATA_CORRUPT The operation failed because the existing data has been corrupted + * \retval PSA_ERROR_INVALID_SIGNATURE The operation failed because the existing data failed authentication (MAC check failed) + */ +psa_status_t psa_ps_set_extended(psa_storage_uid_t uid, + size_t data_offset, + size_t data_length, + const void *p_data); + +/** + * Returns a bitmask with flags set for all of the optional features supported + * by the implementation. + * + * Currently defined flags are limited to: + * - \ref PSA_STORAGE_SUPPORT_SET_EXTENDED + */ +uint32_t psa_ps_get_support(void); + +#ifdef __cplusplus +} +#endif + + +#endif // __PSA_PROTECTED_STORAGE_H__ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/service.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/service.h new file mode 100644 index 0000000..ff54f1c --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/service.h @@ -0,0 +1,28 @@ +/* Copyright (c) 2017-2020 ARM Limited + * + * 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. + */ + +#if defined(FEATURE_TFM) + +#include "interface/include/psa_service.h" +#include "secure_fw/core/ipc/include/tfm_utils.h" +#define SPM_PANIC(format, ...) tfm_panic() + +#else + +#error "Compiling psa service header on non-secure target is not allowed" + +#endif diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/storage_common.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/storage_common.h new file mode 100644 index 0000000..1747f14 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/inc/psa/storage_common.h @@ -0,0 +1,64 @@ +/* Copyright (C) 2019, ARM Limited, 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. + */ + +/** @file +@brief This file includes common definitions for PSA storage +*/ + +#ifndef __PSA_STORAGE_COMMON_H__ +#define __PSA_STORAGE_COMMON_H__ + +#include +#include +#include "psa/error.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \brief Flags used when creating a data entry + */ +typedef uint32_t psa_storage_create_flags_t; + +#define PSA_STORAGE_FLAG_NONE 0 /**< No flags to pass */ +#define PSA_STORAGE_FLAG_WRITE_ONCE (1 << 0) /**< The data associated with the uid will not be able to be modified or deleted. Intended to be used to set bits in `psa_storage_create_flags_t`*/ +#define PSA_STORAGE_FLAG_NO_CONFIDENTIALITY (1 << 1) /**< The data associated with the uid is public and therefore does not require confidentiality. It therefore only needs to be integrity protected */ +#define PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION (1 << 2) /**< The data associated with the uid does not require replay protection. This may permit faster storage - but it permits an attecker with physical access to revert to an earlier version of the data. */ + +/** \brief A type for UIDs used for identifying data + */ +typedef uint64_t psa_storage_uid_t; + +/** + * \brief A container for metadata associated with a specific uid + */ +struct psa_storage_info_t { + size_t capacity; /**< The allocated capacity of the storage associated with a UID **/ + size_t size; /**< The size of the data associated with a uid **/ + psa_storage_create_flags_t flags; /**< The flags set when the uid was created **/ +}; + +/** \brief Flag indicating that \ref psa_storage_create and \ref psa_storage_set_extended are supported */ +#define PSA_STORAGE_SUPPORT_SET_EXTENDED (1 << 0) + +/** \brief PSA storage specific error codes */ +#define PSA_ERROR_DATA_CORRUPT ((psa_status_t)-152) + +#ifdef __cplusplus +} +#endif + +#endif // __PSA_STORAGE_COMMON_H__ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbed_lib.json b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbed_lib.json new file mode 100644 index 0000000..e8e5047 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbed_lib.json @@ -0,0 +1,12 @@ +{ + "name": "psa-services", + "requires": [ + "drivers", + "platform", + "mbedtls", + "storage", + "flashiap-block-device", + "kv-global-api", + "storage_tdb_internal" + ] +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/crypto_struct.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/crypto_struct.h new file mode 100644 index 0000000..938abd0 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/crypto_struct.h @@ -0,0 +1,473 @@ +/** + * \file psa/crypto_struct.h + * + * \brief PSA cryptography module: Mbed TLS structured type implementations + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * This file contains the definitions of some data structures with + * implementation-specific definitions. + * + * In implementations with isolation between the application and the + * cryptography module, it is expected that the front-end and the back-end + * would have different versions of this file. + * + *

Design notes about multipart operation structures

+ * + * Each multipart operation structure contains a `psa_algorithm_t alg` + * field which indicates which specific algorithm the structure is for. + * When the structure is not in use, `alg` is 0. Most of the structure + * consists of a union which is discriminated by `alg`. + * + * Note that when `alg` is 0, the content of other fields is undefined. + * In particular, it is not guaranteed that a freshly-initialized structure + * is all-zero: we initialize structures to something like `{0, 0}`, which + * is only guaranteed to initializes the first member of the union; + * GCC and Clang initialize the whole structure to 0 (at the time of writing), + * but MSVC and CompCert don't. + * + * In Mbed Crypto, multipart operation structures live independently from + * the key. This allows Mbed Crypto to free the key objects when destroying + * a key slot. If a multipart operation needs to remember the key after + * the setup function returns, the operation structure needs to contain a + * copy of the key. + */ +/* + * Copyright (C) 2018, ARM Limited, 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef PSA_CRYPTO_STRUCT_H +#define PSA_CRYPTO_STRUCT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Include the Mbed TLS configuration file, the way Mbed TLS does it + * in each of its header files. */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/cipher.h" +#include "mbedtls/cmac.h" +#include "mbedtls/gcm.h" +#include "mbedtls/md.h" +#include "mbedtls/md2.h" +#include "mbedtls/md4.h" +#include "mbedtls/md5.h" +#include "mbedtls/ripemd160.h" +#include "mbedtls/sha1.h" +#include "mbedtls/sha256.h" +#include "mbedtls/sha512.h" + +struct psa_hash_operation_s +{ + psa_algorithm_t alg; + union + { + unsigned dummy; /* Make the union non-empty even with no supported algorithms. */ +#if defined(MBEDTLS_MD2_C) + mbedtls_md2_context md2; +#endif +#if defined(MBEDTLS_MD4_C) + mbedtls_md4_context md4; +#endif +#if defined(MBEDTLS_MD5_C) + mbedtls_md5_context md5; +#endif +#if defined(MBEDTLS_RIPEMD160_C) + mbedtls_ripemd160_context ripemd160; +#endif +#if defined(MBEDTLS_SHA1_C) + mbedtls_sha1_context sha1; +#endif +#if defined(MBEDTLS_SHA256_C) + mbedtls_sha256_context sha256; +#endif +#if defined(MBEDTLS_SHA512_C) + mbedtls_sha512_context sha512; +#endif + } ctx; +}; + +#define PSA_HASH_OPERATION_INIT {0, {0}} +static inline struct psa_hash_operation_s psa_hash_operation_init( void ) +{ + const struct psa_hash_operation_s v = PSA_HASH_OPERATION_INIT; + return( v ); +} + +#if defined(MBEDTLS_MD_C) +typedef struct +{ + /** The hash context. */ + struct psa_hash_operation_s hash_ctx; + /** The HMAC part of the context. */ + uint8_t opad[PSA_HMAC_MAX_HASH_BLOCK_SIZE]; +} psa_hmac_internal_data; +#endif /* MBEDTLS_MD_C */ + +struct psa_mac_operation_s +{ + psa_algorithm_t alg; + unsigned int key_set : 1; + unsigned int iv_required : 1; + unsigned int iv_set : 1; + unsigned int has_input : 1; + unsigned int is_sign : 1; + uint8_t mac_size; + union + { + unsigned dummy; /* Make the union non-empty even with no supported algorithms. */ +#if defined(MBEDTLS_MD_C) + psa_hmac_internal_data hmac; +#endif +#if defined(MBEDTLS_CMAC_C) + mbedtls_cipher_context_t cmac; +#endif + } ctx; +}; + +#define PSA_MAC_OPERATION_INIT {0, 0, 0, 0, 0, 0, 0, {0}} +static inline struct psa_mac_operation_s psa_mac_operation_init( void ) +{ + const struct psa_mac_operation_s v = PSA_MAC_OPERATION_INIT; + return( v ); +} + +struct psa_cipher_operation_s +{ + psa_algorithm_t alg; + unsigned int key_set : 1; + unsigned int iv_required : 1; + unsigned int iv_set : 1; + uint8_t iv_size; + uint8_t block_size; + union + { + unsigned dummy; /* Enable easier initializing of the union. */ + mbedtls_cipher_context_t cipher; + } ctx; +}; + +#define PSA_CIPHER_OPERATION_INIT {0, 0, 0, 0, 0, 0, {0}} +static inline struct psa_cipher_operation_s psa_cipher_operation_init( void ) +{ + const struct psa_cipher_operation_s v = PSA_CIPHER_OPERATION_INIT; + return( v ); +} + +struct psa_aead_operation_s +{ + psa_algorithm_t alg; + unsigned int key_set : 1; + unsigned int iv_set : 1; + uint8_t iv_size; + uint8_t block_size; + union + { + unsigned dummy; /* Enable easier initializing of the union. */ + mbedtls_cipher_context_t cipher; + } ctx; +}; + +#define PSA_AEAD_OPERATION_INIT {0, 0, 0, 0, 0, {0}} +static inline struct psa_aead_operation_s psa_aead_operation_init( void ) +{ + const struct psa_aead_operation_s v = PSA_AEAD_OPERATION_INIT; + return( v ); +} + +#if defined(MBEDTLS_MD_C) +typedef struct +{ + uint8_t *info; + size_t info_length; + psa_hmac_internal_data hmac; + uint8_t prk[PSA_HASH_MAX_SIZE]; + uint8_t output_block[PSA_HASH_MAX_SIZE]; +#if PSA_HASH_MAX_SIZE > 0xff +#error "PSA_HASH_MAX_SIZE does not fit in uint8_t" +#endif + uint8_t offset_in_block; + uint8_t block_number; + unsigned int state : 2; + unsigned int info_set : 1; +} psa_hkdf_key_derivation_t; +#endif /* MBEDTLS_MD_C */ + +#if defined(MBEDTLS_MD_C) +typedef enum +{ + TLS12_PRF_STATE_INIT, /* no input provided */ + TLS12_PRF_STATE_SEED_SET, /* seed has been set */ + TLS12_PRF_STATE_KEY_SET, /* key has been set */ + TLS12_PRF_STATE_LABEL_SET, /* label has been set */ + TLS12_PRF_STATE_OUTPUT /* output has been started */ +} psa_tls12_prf_key_derivation_state_t; + +typedef struct psa_tls12_prf_key_derivation_s +{ +#if PSA_HASH_MAX_SIZE > 0xff +#error "PSA_HASH_MAX_SIZE does not fit in uint8_t" +#endif + + /* Indicates how many bytes in the current HMAC block have + * not yet been read by the user. */ + uint8_t left_in_block; + + /* The 1-based number of the block. */ + uint8_t block_number; + + psa_tls12_prf_key_derivation_state_t state; + + uint8_t *seed; + size_t seed_length; + uint8_t *label; + size_t label_length; + psa_hmac_internal_data hmac; + uint8_t Ai[PSA_HASH_MAX_SIZE]; + + /* `HMAC_hash( prk, A(i) + seed )` in the notation of RFC 5246, Sect. 5. */ + uint8_t output_block[PSA_HASH_MAX_SIZE]; +} psa_tls12_prf_key_derivation_t; +#endif /* MBEDTLS_MD_C */ + +struct psa_key_derivation_s +{ + psa_algorithm_t alg; + unsigned int can_output_key : 1; + size_t capacity; + union + { + /* Make the union non-empty even with no supported algorithms. */ + uint8_t dummy; +#if defined(MBEDTLS_MD_C) + psa_hkdf_key_derivation_t hkdf; + psa_tls12_prf_key_derivation_t tls12_prf; +#endif + } ctx; +}; + +/* This only zeroes out the first byte in the union, the rest is unspecified. */ +#define PSA_KEY_DERIVATION_OPERATION_INIT {0, 0, 0, {0}} +static inline struct psa_key_derivation_s psa_key_derivation_operation_init( void ) +{ + const struct psa_key_derivation_s v = PSA_KEY_DERIVATION_OPERATION_INIT; + return( v ); +} + +struct psa_key_policy_s +{ + psa_key_usage_t usage; + psa_algorithm_t alg; + psa_algorithm_t alg2; +}; +typedef struct psa_key_policy_s psa_key_policy_t; + +#define PSA_KEY_POLICY_INIT {0, 0, 0} +static inline struct psa_key_policy_s psa_key_policy_init( void ) +{ + const struct psa_key_policy_s v = PSA_KEY_POLICY_INIT; + return( v ); +} + +/* The type used internally for key sizes. + * Public interfaces use size_t, but internally we use a smaller type. */ +typedef uint16_t psa_key_bits_t; +/* The maximum value of the type used to represent bit-sizes. + * This is used to mark an invalid key size. */ +#define PSA_KEY_BITS_TOO_LARGE ( (psa_key_bits_t) ( -1 ) ) +/* The maximum size of a key in bits. + * Currently defined as the maximum that can be represented, rounded down + * to a whole number of bytes. + * This is an uncast value so that it can be used in preprocessor + * conditionals. */ +#define PSA_MAX_KEY_BITS 0xfff8 + +/** A mask of flags that can be stored in key attributes. + * + * This type is also used internally to store flags in slots. Internal + * flags are defined in library/psa_crypto_core.h. Internal flags may have + * the same value as external flags if they are properly handled during + * key creation and in psa_get_key_attributes. + */ +typedef uint16_t psa_key_attributes_flag_t; + +#define MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER \ + ( (psa_key_attributes_flag_t) 0x0001 ) + +/* A mask of key attribute flags used externally only. + * Only meant for internal checks inside the library. */ +#define MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY ( \ + MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER | \ + 0 ) + +/* A mask of key attribute flags used both internally and externally. + * Currently there aren't any. */ +#define MBEDTLS_PSA_KA_MASK_DUAL_USE ( \ + 0 ) + +typedef struct +{ + psa_key_type_t type; + psa_key_bits_t bits; + psa_key_lifetime_t lifetime; + psa_key_id_t id; + psa_key_policy_t policy; + psa_key_attributes_flag_t flags; +} psa_core_key_attributes_t; + +#define PSA_CORE_KEY_ATTRIBUTES_INIT {PSA_KEY_TYPE_NONE, 0, PSA_KEY_LIFETIME_VOLATILE, PSA_KEY_ID_INIT, PSA_KEY_POLICY_INIT, 0} + +struct psa_key_attributes_s +{ + psa_core_key_attributes_t core; +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + psa_key_slot_number_t slot_number; +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + void *domain_parameters; + size_t domain_parameters_size; +}; + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +#define PSA_KEY_ATTRIBUTES_INIT {PSA_CORE_KEY_ATTRIBUTES_INIT, 0, NULL, 0} +#else +#define PSA_KEY_ATTRIBUTES_INIT {PSA_CORE_KEY_ATTRIBUTES_INIT, NULL, 0} +#endif + +static inline struct psa_key_attributes_s psa_key_attributes_init( void ) +{ + const struct psa_key_attributes_s v = PSA_KEY_ATTRIBUTES_INIT; + return( v ); +} + +static inline void psa_set_key_id(psa_key_attributes_t *attributes, + psa_key_id_t id) +{ + attributes->core.id = id; + if( attributes->core.lifetime == PSA_KEY_LIFETIME_VOLATILE ) + attributes->core.lifetime = PSA_KEY_LIFETIME_PERSISTENT; +} + +static inline psa_key_id_t psa_get_key_id( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.id ); +} + +static inline void psa_set_key_lifetime(psa_key_attributes_t *attributes, + psa_key_lifetime_t lifetime) +{ + attributes->core.lifetime = lifetime; + if( lifetime == PSA_KEY_LIFETIME_VOLATILE ) + { +#ifdef MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER + attributes->core.id.key_id = 0; + attributes->core.id.owner = 0; +#else + attributes->core.id = 0; +#endif + } +} + +static inline psa_key_lifetime_t psa_get_key_lifetime( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.lifetime ); +} + +static inline void psa_set_key_usage_flags(psa_key_attributes_t *attributes, + psa_key_usage_t usage_flags) +{ + attributes->core.policy.usage = usage_flags; +} + +static inline psa_key_usage_t psa_get_key_usage_flags( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.policy.usage ); +} + +static inline void psa_set_key_algorithm(psa_key_attributes_t *attributes, + psa_algorithm_t alg) +{ + attributes->core.policy.alg = alg; +} + +static inline psa_algorithm_t psa_get_key_algorithm( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.policy.alg ); +} + +/* This function is declared in crypto_extra.h, which comes after this + * header file, but we need the function here, so repeat the declaration. */ +psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes, + psa_key_type_t type, + const uint8_t *data, + size_t data_length); + +static inline void psa_set_key_type(psa_key_attributes_t *attributes, + psa_key_type_t type) +{ + if( attributes->domain_parameters == NULL ) + { + /* Common case: quick path */ + attributes->core.type = type; + } + else + { + /* Call the bigger function to free the old domain paramteres. + * Ignore any errors which may arise due to type requiring + * non-default domain parameters, since this function can't + * report errors. */ + (void) psa_set_key_domain_parameters( attributes, type, NULL, 0 ); + } +} + +static inline psa_key_type_t psa_get_key_type( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.type ); +} + +static inline void psa_set_key_bits(psa_key_attributes_t *attributes, + size_t bits) +{ + if( bits > PSA_MAX_KEY_BITS ) + attributes->core.bits = PSA_KEY_BITS_TOO_LARGE; + else + attributes->core.bits = (psa_key_bits_t) bits; +} + +static inline size_t psa_get_key_bits( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.bits ); +} + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_STRUCT_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto.c new file mode 100644 index 0000000..6932318 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto.c @@ -0,0 +1,5805 @@ +/* + * PSA crypto layer on top of Mbed TLS crypto + */ +/* Copyright (C) 2018, ARM Limited, 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +#include "psa_crypto_service_integration.h" +#include "psa/crypto.h" + +#include "psa_crypto_core.h" +#include "psa_crypto_invasive.h" +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +#include "psa_crypto_se.h" +#endif +#include "psa_crypto_slot_management.h" +/* Include internal declarations that are useful for implementing persistently + * stored keys. */ +#include "psa_crypto_storage.h" + +#include +#include +#include +#include "mbedtls/platform.h" +#if !defined(MBEDTLS_PLATFORM_C) +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/arc4.h" +#include "mbedtls/asn1.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/bignum.h" +#include "mbedtls/blowfish.h" +#include "mbedtls/camellia.h" +#include "mbedtls/chacha20.h" +#include "mbedtls/chachapoly.h" +#include "mbedtls/cipher.h" +#include "mbedtls/ccm.h" +#include "mbedtls/cmac.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/des.h" +#include "mbedtls/ecdh.h" +#include "mbedtls/ecp.h" +#include "mbedtls/entropy.h" +#include "mbedtls/error.h" +#include "mbedtls/gcm.h" +#include "mbedtls/md2.h" +#include "mbedtls/md4.h" +#include "mbedtls/md5.h" +#include "mbedtls/md.h" +#include "mbedtls/md_internal.h" +#include "mbedtls/pk.h" +#include "mbedtls/pk_internal.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" +#include "mbedtls/ripemd160.h" +#include "mbedtls/rsa.h" +#include "mbedtls/sha1.h" +#include "mbedtls/sha256.h" +#include "mbedtls/sha512.h" +#include "mbedtls/xtea.h" + +#define ARRAY_LENGTH( array ) ( sizeof( array ) / sizeof( *( array ) ) ) + +/* constant-time buffer comparison */ +static inline int safer_memcmp( const uint8_t *a, const uint8_t *b, size_t n ) +{ + size_t i; + unsigned char diff = 0; + + for( i = 0; i < n; i++ ) + diff |= a[i] ^ b[i]; + + return( diff ); +} + + + +/****************************************************************/ +/* Global data, support functions and library management */ +/****************************************************************/ + +static int key_type_is_raw_bytes( psa_key_type_t type ) +{ + return( PSA_KEY_TYPE_IS_UNSTRUCTURED( type ) ); +} + +/* Values for psa_global_data_t::rng_state */ +#define RNG_NOT_INITIALIZED 0 +#define RNG_INITIALIZED 1 +#define RNG_SEEDED 2 + +typedef struct +{ + void (* entropy_init )( mbedtls_entropy_context *ctx ); + void (* entropy_free )( mbedtls_entropy_context *ctx ); + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + unsigned initialized : 1; + unsigned rng_state : 2; +} psa_global_data_t; + +static psa_global_data_t global_data; + +#define GUARD_MODULE_INITIALIZED \ + if( global_data.initialized == 0 ) \ + return( PSA_ERROR_BAD_STATE ); + +static psa_status_t mbedtls_to_psa_error( int ret ) +{ + /* If there's both a high-level code and low-level code, dispatch on + * the high-level code. */ + switch( ret < -0x7f ? - ( -ret & 0x7f80 ) : ret ) + { + case 0: + return( PSA_SUCCESS ); + + case MBEDTLS_ERR_AES_INVALID_KEY_LENGTH: + case MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH: + case MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_AES_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + + case MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + + case MBEDTLS_ERR_ASN1_OUT_OF_DATA: + case MBEDTLS_ERR_ASN1_UNEXPECTED_TAG: + case MBEDTLS_ERR_ASN1_INVALID_LENGTH: + case MBEDTLS_ERR_ASN1_LENGTH_MISMATCH: + case MBEDTLS_ERR_ASN1_INVALID_DATA: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_ASN1_ALLOC_FAILED: + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + case MBEDTLS_ERR_ASN1_BUF_TOO_SMALL: + return( PSA_ERROR_BUFFER_TOO_SMALL ); + +#if defined(MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA) + case MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA: +#elif defined(MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH) + case MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH: +#endif + case MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + +#if defined(MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA) + case MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA: +#elif defined(MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH) + case MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH: +#endif + case MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + + case MBEDTLS_ERR_CCM_BAD_INPUT: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_CCM_AUTH_FAILED: + return( PSA_ERROR_INVALID_SIGNATURE ); + case MBEDTLS_ERR_CCM_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + + case MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA: + return( PSA_ERROR_INVALID_ARGUMENT ); + + case MBEDTLS_ERR_CHACHAPOLY_BAD_STATE: + return( PSA_ERROR_BAD_STATE ); + case MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED: + return( PSA_ERROR_INVALID_SIGNATURE ); + + case MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_CIPHER_ALLOC_FAILED: + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + case MBEDTLS_ERR_CIPHER_INVALID_PADDING: + return( PSA_ERROR_INVALID_PADDING ); + case MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED: + return( PSA_ERROR_BAD_STATE ); + case MBEDTLS_ERR_CIPHER_AUTH_FAILED: + return( PSA_ERROR_INVALID_SIGNATURE ); + case MBEDTLS_ERR_CIPHER_INVALID_CONTEXT: + return( PSA_ERROR_CORRUPTION_DETECTED ); + case MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + + case MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + + case MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED: + return( PSA_ERROR_INSUFFICIENT_ENTROPY ); + case MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG: + case MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR: + return( PSA_ERROR_INSUFFICIENT_ENTROPY ); + + case MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_DES_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + + case MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED: + case MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE: + case MBEDTLS_ERR_ENTROPY_SOURCE_FAILED: + return( PSA_ERROR_INSUFFICIENT_ENTROPY ); + + case MBEDTLS_ERR_GCM_AUTH_FAILED: + return( PSA_ERROR_INVALID_SIGNATURE ); + case MBEDTLS_ERR_GCM_BAD_INPUT: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_GCM_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + + case MBEDTLS_ERR_MD2_HW_ACCEL_FAILED: + case MBEDTLS_ERR_MD4_HW_ACCEL_FAILED: + case MBEDTLS_ERR_MD5_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + + case MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_MD_BAD_INPUT_DATA: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_MD_ALLOC_FAILED: + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + case MBEDTLS_ERR_MD_FILE_IO_ERROR: + return( PSA_ERROR_STORAGE_FAILURE ); + case MBEDTLS_ERR_MD_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + + case MBEDTLS_ERR_MPI_FILE_IO_ERROR: + return( PSA_ERROR_STORAGE_FAILURE ); + case MBEDTLS_ERR_MPI_BAD_INPUT_DATA: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_MPI_INVALID_CHARACTER: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL: + return( PSA_ERROR_BUFFER_TOO_SMALL ); + case MBEDTLS_ERR_MPI_NEGATIVE_VALUE: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_MPI_DIVISION_BY_ZERO: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_MPI_ALLOC_FAILED: + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + + case MBEDTLS_ERR_PK_ALLOC_FAILED: + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + case MBEDTLS_ERR_PK_TYPE_MISMATCH: + case MBEDTLS_ERR_PK_BAD_INPUT_DATA: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_PK_FILE_IO_ERROR: + return( PSA_ERROR_STORAGE_FAILURE ); + case MBEDTLS_ERR_PK_KEY_INVALID_VERSION: + case MBEDTLS_ERR_PK_KEY_INVALID_FORMAT: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_PK_UNKNOWN_PK_ALG: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_PK_PASSWORD_REQUIRED: + case MBEDTLS_ERR_PK_PASSWORD_MISMATCH: + return( PSA_ERROR_NOT_PERMITTED ); + case MBEDTLS_ERR_PK_INVALID_PUBKEY: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_PK_INVALID_ALG: + case MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE: + case MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_PK_SIG_LEN_MISMATCH: + return( PSA_ERROR_INVALID_SIGNATURE ); + case MBEDTLS_ERR_PK_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + + case MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + case MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED: + return( PSA_ERROR_NOT_SUPPORTED ); + + case MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + + case MBEDTLS_ERR_RSA_BAD_INPUT_DATA: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_RSA_INVALID_PADDING: + return( PSA_ERROR_INVALID_PADDING ); + case MBEDTLS_ERR_RSA_KEY_GEN_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + case MBEDTLS_ERR_RSA_KEY_CHECK_FAILED: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_RSA_PUBLIC_FAILED: + case MBEDTLS_ERR_RSA_PRIVATE_FAILED: + return( PSA_ERROR_CORRUPTION_DETECTED ); + case MBEDTLS_ERR_RSA_VERIFY_FAILED: + return( PSA_ERROR_INVALID_SIGNATURE ); + case MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE: + return( PSA_ERROR_BUFFER_TOO_SMALL ); + case MBEDTLS_ERR_RSA_RNG_FAILED: + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + case MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_RSA_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + + case MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED: + case MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED: + case MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + + case MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + + case MBEDTLS_ERR_ECP_BAD_INPUT_DATA: + case MBEDTLS_ERR_ECP_INVALID_KEY: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL: + return( PSA_ERROR_BUFFER_TOO_SMALL ); + case MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH: + case MBEDTLS_ERR_ECP_VERIFY_FAILED: + return( PSA_ERROR_INVALID_SIGNATURE ); + case MBEDTLS_ERR_ECP_ALLOC_FAILED: + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + case MBEDTLS_ERR_ECP_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + case MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED: + return( PSA_ERROR_CORRUPTION_DETECTED ); + + default: + return( PSA_ERROR_GENERIC_ERROR ); + } +} + + + + +/****************************************************************/ +/* Key management */ +/****************************************************************/ + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +static inline int psa_key_slot_is_external( const psa_key_slot_t *slot ) +{ + return( psa_key_lifetime_is_external( slot->attr.lifetime ) ); +} +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + +#if defined(MBEDTLS_ECP_C) +mbedtls_ecp_group_id mbedtls_ecc_group_of_psa( psa_ecc_curve_t curve, + size_t byte_length ) +{ + switch( curve ) + { + case PSA_ECC_CURVE_SECP_R1: + switch( byte_length ) + { + case PSA_BITS_TO_BYTES( 192 ): + return( MBEDTLS_ECP_DP_SECP192R1 ); + case PSA_BITS_TO_BYTES( 224 ): + return( MBEDTLS_ECP_DP_SECP224R1 ); + case PSA_BITS_TO_BYTES( 256 ): + return( MBEDTLS_ECP_DP_SECP256R1 ); + case PSA_BITS_TO_BYTES( 384 ): + return( MBEDTLS_ECP_DP_SECP384R1 ); + case PSA_BITS_TO_BYTES( 521 ): + return( MBEDTLS_ECP_DP_SECP521R1 ); + default: + return( MBEDTLS_ECP_DP_NONE ); + } + break; + + case PSA_ECC_CURVE_BRAINPOOL_P_R1: + switch( byte_length ) + { + case PSA_BITS_TO_BYTES( 256 ): + return( MBEDTLS_ECP_DP_BP256R1 ); + case PSA_BITS_TO_BYTES( 384 ): + return( MBEDTLS_ECP_DP_BP384R1 ); + case PSA_BITS_TO_BYTES( 512 ): + return( MBEDTLS_ECP_DP_BP512R1 ); + default: + return( MBEDTLS_ECP_DP_NONE ); + } + break; + + case PSA_ECC_CURVE_MONTGOMERY: + switch( byte_length ) + { + case PSA_BITS_TO_BYTES( 255 ): + return( MBEDTLS_ECP_DP_CURVE25519 ); + case PSA_BITS_TO_BYTES( 448 ): + return( MBEDTLS_ECP_DP_CURVE448 ); + default: + return( MBEDTLS_ECP_DP_NONE ); + } + break; + + case PSA_ECC_CURVE_SECP_K1: + switch( byte_length ) + { + case PSA_BITS_TO_BYTES( 192 ): + return( MBEDTLS_ECP_DP_SECP192K1 ); + case PSA_BITS_TO_BYTES( 224 ): + return( MBEDTLS_ECP_DP_SECP224K1 ); + case PSA_BITS_TO_BYTES( 256 ): + return( MBEDTLS_ECP_DP_SECP256K1 ); + default: + return( MBEDTLS_ECP_DP_NONE ); + } + break; + + default: + return( MBEDTLS_ECP_DP_NONE ); + } +} +#endif /* defined(MBEDTLS_ECP_C) */ + +static psa_status_t prepare_raw_data_slot( psa_key_type_t type, + size_t bits, + struct raw_data *raw ) +{ + /* Check that the bit size is acceptable for the key type */ + switch( type ) + { + case PSA_KEY_TYPE_RAW_DATA: +#if defined(MBEDTLS_MD_C) + case PSA_KEY_TYPE_HMAC: +#endif + case PSA_KEY_TYPE_DERIVE: + break; +#if defined(MBEDTLS_AES_C) + case PSA_KEY_TYPE_AES: + if( bits != 128 && bits != 192 && bits != 256 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + break; +#endif +#if defined(MBEDTLS_CAMELLIA_C) + case PSA_KEY_TYPE_CAMELLIA: + if( bits != 128 && bits != 192 && bits != 256 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + break; +#endif +#if defined(MBEDTLS_DES_C) + case PSA_KEY_TYPE_DES: + if( bits != 64 && bits != 128 && bits != 192 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + break; +#endif +#if defined(MBEDTLS_ARC4_C) + case PSA_KEY_TYPE_ARC4: + if( bits < 8 || bits > 2048 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + break; +#endif +#if defined(MBEDTLS_CHACHA20_C) + case PSA_KEY_TYPE_CHACHA20: + if( bits != 256 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + break; +#endif + default: + return( PSA_ERROR_NOT_SUPPORTED ); + } + if( bits % 8 != 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + /* Allocate memory for the key */ + raw->bytes = PSA_BITS_TO_BYTES( bits ); + raw->data = mbedtls_calloc( 1, raw->bytes ); + if( raw->data == NULL ) + { + raw->bytes = 0; + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + } + return( PSA_SUCCESS ); +} + +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_PARSE_C) +/* Mbed TLS doesn't support non-byte-aligned key sizes (i.e. key sizes + * that are not a multiple of 8) well. For example, there is only + * mbedtls_rsa_get_len(), which returns a number of bytes, and no + * way to return the exact bit size of a key. + * To keep things simple, reject non-byte-aligned key sizes. */ +static psa_status_t psa_check_rsa_key_byte_aligned( + const mbedtls_rsa_context *rsa ) +{ + mbedtls_mpi n; + psa_status_t status; + mbedtls_mpi_init( &n ); + status = mbedtls_to_psa_error( + mbedtls_rsa_export( rsa, &n, NULL, NULL, NULL, NULL ) ); + if( status == PSA_SUCCESS ) + { + if( mbedtls_mpi_bitlen( &n ) % 8 != 0 ) + status = PSA_ERROR_NOT_SUPPORTED; + } + mbedtls_mpi_free( &n ); + return( status ); +} + +static psa_status_t psa_import_rsa_key( psa_key_type_t type, + const uint8_t *data, + size_t data_length, + mbedtls_rsa_context **p_rsa ) +{ + psa_status_t status; + mbedtls_pk_context pk; + mbedtls_rsa_context *rsa; + size_t bits; + + mbedtls_pk_init( &pk ); + + /* Parse the data. */ + if( PSA_KEY_TYPE_IS_KEY_PAIR( type ) ) + status = mbedtls_to_psa_error( + mbedtls_pk_parse_key( &pk, data, data_length, NULL, 0 ) ); + else + status = mbedtls_to_psa_error( + mbedtls_pk_parse_public_key( &pk, data, data_length ) ); + if( status != PSA_SUCCESS ) + goto exit; + + /* We have something that the pkparse module recognizes. If it is a + * valid RSA key, store it. */ + if( mbedtls_pk_get_type( &pk ) != MBEDTLS_PK_RSA ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + rsa = mbedtls_pk_rsa( pk ); + /* The size of an RSA key doesn't have to be a multiple of 8. Mbed TLS + * supports non-byte-aligned key sizes, but not well. For example, + * mbedtls_rsa_get_len() returns the key size in bytes, not in bits. */ + bits = PSA_BYTES_TO_BITS( mbedtls_rsa_get_len( rsa ) ); + if( bits > PSA_VENDOR_RSA_MAX_KEY_BITS ) + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + status = psa_check_rsa_key_byte_aligned( rsa ); + +exit: + /* Free the content of the pk object only on error. */ + if( status != PSA_SUCCESS ) + { + mbedtls_pk_free( &pk ); + return( status ); + } + + /* On success, store the content of the object in the RSA context. */ + *p_rsa = rsa; + + return( PSA_SUCCESS ); +} +#endif /* defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_PARSE_C) */ + +#if defined(MBEDTLS_ECP_C) +static psa_status_t psa_prepare_import_ec_key( psa_ecc_curve_t curve, + size_t data_length, + int is_public, + mbedtls_ecp_keypair **p_ecp ) +{ + mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE; + *p_ecp = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) ); + if( *p_ecp == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + mbedtls_ecp_keypair_init( *p_ecp ); + + if( is_public ) + { + /* A public key is represented as: + * - The byte 0x04; + * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; + * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. + * So its data length is 2m+1 where n is the key size in bits. + */ + if( ( data_length & 1 ) == 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + data_length = data_length / 2; + } + + /* Load the group. */ + grp_id = mbedtls_ecc_group_of_psa( curve, data_length ); + if( grp_id == MBEDTLS_ECP_DP_NONE ) + return( PSA_ERROR_INVALID_ARGUMENT ); + return( mbedtls_to_psa_error( + mbedtls_ecp_group_load( &( *p_ecp )->grp, grp_id ) ) ); +} + +/* Import a public key given as the uncompressed representation defined by SEC1 + * 2.3.3 as the content of an ECPoint. */ +static psa_status_t psa_import_ec_public_key( psa_ecc_curve_t curve, + const uint8_t *data, + size_t data_length, + mbedtls_ecp_keypair **p_ecp ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_keypair *ecp = NULL; + + status = psa_prepare_import_ec_key( curve, data_length, 1, &ecp ); + if( status != PSA_SUCCESS ) + goto exit; + + /* Load the public value. */ + status = mbedtls_to_psa_error( + mbedtls_ecp_point_read_binary( &ecp->grp, &ecp->Q, + data, data_length ) ); + if( status != PSA_SUCCESS ) + goto exit; + + /* Check that the point is on the curve. */ + status = mbedtls_to_psa_error( + mbedtls_ecp_check_pubkey( &ecp->grp, &ecp->Q ) ); + if( status != PSA_SUCCESS ) + goto exit; + + *p_ecp = ecp; + return( PSA_SUCCESS ); + +exit: + if( ecp != NULL ) + { + mbedtls_ecp_keypair_free( ecp ); + mbedtls_free( ecp ); + } + return( status ); +} + +/* Import a private key given as a byte string which is the private value + * in big-endian order. */ +static psa_status_t psa_import_ec_private_key( psa_ecc_curve_t curve, + const uint8_t *data, + size_t data_length, + mbedtls_ecp_keypair **p_ecp ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_keypair *ecp = NULL; + + status = psa_prepare_import_ec_key( curve, data_length, 0, &ecp ); + if( status != PSA_SUCCESS ) + goto exit; + + /* Load the secret value. */ + status = mbedtls_to_psa_error( + mbedtls_mpi_read_binary( &ecp->d, data, data_length ) ); + if( status != PSA_SUCCESS ) + goto exit; + /* Validate the private key. */ + status = mbedtls_to_psa_error( + mbedtls_ecp_check_privkey( &ecp->grp, &ecp->d ) ); + if( status != PSA_SUCCESS ) + goto exit; + /* Calculate the public key from the private key. */ + status = mbedtls_to_psa_error( + mbedtls_ecp_mul( &ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G, + mbedtls_ctr_drbg_random, &global_data.ctr_drbg ) ); + if( status != PSA_SUCCESS ) + goto exit; + + *p_ecp = ecp; + return( PSA_SUCCESS ); + +exit: + if( ecp != NULL ) + { + mbedtls_ecp_keypair_free( ecp ); + mbedtls_free( ecp ); + } + return( status ); +} +#endif /* defined(MBEDTLS_ECP_C) */ + + +/** Return the size of the key in the given slot, in bits. + * + * \param[in] slot A key slot. + * + * \return The key size in bits, read from the metadata in the slot. + */ +static inline size_t psa_get_key_slot_bits( const psa_key_slot_t *slot ) +{ + return( slot->attr.bits ); +} + +/** Calculate the size of the key in the given slot, in bits. + * + * \param[in] slot A key slot containing a transparent key. + * + * \return The key size in bits, calculated from the key data. + */ +static psa_key_bits_t psa_calculate_key_bits( const psa_key_slot_t *slot ) +{ + size_t bits = 0; /* return 0 on an empty slot */ + + if( key_type_is_raw_bytes( slot->attr.type ) ) + bits = PSA_BYTES_TO_BITS( slot->data.raw.bytes ); +#if defined(MBEDTLS_RSA_C) + else if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) + bits = PSA_BYTES_TO_BITS( mbedtls_rsa_get_len( slot->data.rsa ) ); +#endif /* defined(MBEDTLS_RSA_C) */ +#if defined(MBEDTLS_ECP_C) + else if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) + bits = slot->data.ecp->grp.pbits; +#endif /* defined(MBEDTLS_ECP_C) */ + + /* We know that the size fits in psa_key_bits_t thanks to checks + * when the key was created. */ + return( (psa_key_bits_t) bits ); +} + +/** Import key data into a slot. `slot->attr.type` must have been set + * previously. This function assumes that the slot does not contain + * any key material yet. On failure, the slot content is unchanged. */ +psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, + const uint8_t *data, + size_t data_length ) +{ + psa_status_t status = PSA_SUCCESS; + + if( key_type_is_raw_bytes( slot->attr.type ) ) + { + size_t bit_size = PSA_BYTES_TO_BITS( data_length ); + /* Ensure that the bytes-to-bit conversion didn't overflow. */ + if( data_length > SIZE_MAX / 8 ) + return( PSA_ERROR_NOT_SUPPORTED ); + /* Enforce a size limit, and in particular ensure that the bit + * size fits in its representation type. */ + if( bit_size > PSA_MAX_KEY_BITS ) + return( PSA_ERROR_NOT_SUPPORTED ); + status = prepare_raw_data_slot( slot->attr.type, bit_size, + &slot->data.raw ); + if( status != PSA_SUCCESS ) + return( status ); + if( data_length != 0 ) + memcpy( slot->data.raw.data, data, data_length ); + } + else +#if defined(MBEDTLS_ECP_C) + if( PSA_KEY_TYPE_IS_ECC_KEY_PAIR( slot->attr.type ) ) + { + status = psa_import_ec_private_key( PSA_KEY_TYPE_GET_CURVE( slot->attr.type ), + data, data_length, + &slot->data.ecp ); + } + else if( PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY( slot->attr.type ) ) + { + status = psa_import_ec_public_key( + PSA_KEY_TYPE_GET_CURVE( slot->attr.type ), + data, data_length, + &slot->data.ecp ); + } + else +#endif /* MBEDTLS_ECP_C */ +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_PARSE_C) + if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) + { + status = psa_import_rsa_key( slot->attr.type, + data, data_length, + &slot->data.rsa ); + } + else +#endif /* defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_PARSE_C) */ + { + return( PSA_ERROR_NOT_SUPPORTED ); + } + + if( status == PSA_SUCCESS ) + { + /* Write the actual key size to the slot. + * psa_start_key_creation() wrote the size declared by the + * caller, which may be 0 (meaning unspecified) or wrong. */ + slot->attr.bits = psa_calculate_key_bits( slot ); + } + return( status ); +} + +/** Calculate the intersection of two algorithm usage policies. + * + * Return 0 (which allows no operation) on incompatibility. + */ +static psa_algorithm_t psa_key_policy_algorithm_intersection( + psa_algorithm_t alg1, + psa_algorithm_t alg2 ) +{ + /* Common case: both sides actually specify the same policy. */ + if( alg1 == alg2 ) + return( alg1 ); + /* If the policies are from the same hash-and-sign family, check + * if one is a wildcard. If so the other has the specific algorithm. */ + if( PSA_ALG_IS_HASH_AND_SIGN( alg1 ) && + PSA_ALG_IS_HASH_AND_SIGN( alg2 ) && + ( alg1 & ~PSA_ALG_HASH_MASK ) == ( alg2 & ~PSA_ALG_HASH_MASK ) ) + { + if( PSA_ALG_SIGN_GET_HASH( alg1 ) == PSA_ALG_ANY_HASH ) + return( alg2 ); + if( PSA_ALG_SIGN_GET_HASH( alg2 ) == PSA_ALG_ANY_HASH ) + return( alg1 ); + } + /* If the policies are incompatible, allow nothing. */ + return( 0 ); +} + +static int psa_key_algorithm_permits( psa_algorithm_t policy_alg, + psa_algorithm_t requested_alg ) +{ + /* Common case: the policy only allows requested_alg. */ + if( requested_alg == policy_alg ) + return( 1 ); + /* If policy_alg is a hash-and-sign with a wildcard for the hash, + * and requested_alg is the same hash-and-sign family with any hash, + * then requested_alg is compliant with policy_alg. */ + if( PSA_ALG_IS_HASH_AND_SIGN( requested_alg ) && + PSA_ALG_SIGN_GET_HASH( policy_alg ) == PSA_ALG_ANY_HASH ) + { + return( ( policy_alg & ~PSA_ALG_HASH_MASK ) == + ( requested_alg & ~PSA_ALG_HASH_MASK ) ); + } + /* If it isn't permitted, it's forbidden. */ + return( 0 ); +} + +/** Test whether a policy permits an algorithm. + * + * The caller must test usage flags separately. + */ +static int psa_key_policy_permits( const psa_key_policy_t *policy, + psa_algorithm_t alg ) +{ + return( psa_key_algorithm_permits( policy->alg, alg ) || + psa_key_algorithm_permits( policy->alg2, alg ) ); +} + +/** Restrict a key policy based on a constraint. + * + * \param[in,out] policy The policy to restrict. + * \param[in] constraint The policy constraint to apply. + * + * \retval #PSA_SUCCESS + * \c *policy contains the intersection of the original value of + * \c *policy and \c *constraint. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c *policy and \c *constraint are incompatible. + * \c *policy is unchanged. + */ +static psa_status_t psa_restrict_key_policy( + psa_key_policy_t *policy, + const psa_key_policy_t *constraint ) +{ + psa_algorithm_t intersection_alg = + psa_key_policy_algorithm_intersection( policy->alg, constraint->alg ); + psa_algorithm_t intersection_alg2 = + psa_key_policy_algorithm_intersection( policy->alg2, constraint->alg2 ); + if( intersection_alg == 0 && policy->alg != 0 && constraint->alg != 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + if( intersection_alg2 == 0 && policy->alg2 != 0 && constraint->alg2 != 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + policy->usage &= constraint->usage; + policy->alg = intersection_alg; + policy->alg2 = intersection_alg2; + return( PSA_SUCCESS ); +} + +/** Retrieve a slot which must contain a key. The key must have allow all the + * usage flags set in \p usage. If \p alg is nonzero, the key must allow + * operations with this algorithm. */ +static psa_status_t psa_get_key_from_slot( psa_key_handle_t handle, + psa_key_slot_t **p_slot, + psa_key_usage_t usage, + psa_algorithm_t alg ) +{ + psa_status_t status; + psa_key_slot_t *slot = NULL; + + *p_slot = NULL; + + status = psa_get_key_slot( handle, &slot ); + if( status != PSA_SUCCESS ) + return( status ); + + /* Enforce that usage policy for the key slot contains all the flags + * required by the usage parameter. There is one exception: public + * keys can always be exported, so we treat public key objects as + * if they had the export flag. */ + if( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->attr.type ) ) + usage &= ~PSA_KEY_USAGE_EXPORT; + if( ( slot->attr.policy.usage & usage ) != usage ) + return( PSA_ERROR_NOT_PERMITTED ); + + /* Enforce that the usage policy permits the requested algortihm. */ + if( alg != 0 && ! psa_key_policy_permits( &slot->attr.policy, alg ) ) + return( PSA_ERROR_NOT_PERMITTED ); + + *p_slot = slot; + return( PSA_SUCCESS ); +} + +/** Retrieve a slot which must contain a transparent key. + * + * A transparent key is a key for which the key material is directly + * available, as opposed to a key in a secure element. + * + * This is a temporary function to use instead of psa_get_key_from_slot() + * until secure element support is fully implemented. + */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +static psa_status_t psa_get_transparent_key( psa_key_handle_t handle, + psa_key_slot_t **p_slot, + psa_key_usage_t usage, + psa_algorithm_t alg ) +{ + psa_status_t status = psa_get_key_from_slot( handle, p_slot, usage, alg ); + if( status != PSA_SUCCESS ) + return( status ); + if( psa_key_slot_is_external( *p_slot ) ) + { + *p_slot = NULL; + return( PSA_ERROR_NOT_SUPPORTED ); + } + return( PSA_SUCCESS ); +} +#else /* MBEDTLS_PSA_CRYPTO_SE_C */ +/* With no secure element support, all keys are transparent. */ +#define psa_get_transparent_key( handle, p_slot, usage, alg ) \ + psa_get_key_from_slot( handle, p_slot, usage, alg ) +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + +/** Wipe key data from a slot. Preserve metadata such as the policy. */ +static psa_status_t psa_remove_key_data_from_memory( psa_key_slot_t *slot ) +{ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if( psa_key_slot_is_external( slot ) ) + { + /* No key material to clean. */ + } + else +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + if( slot->attr.type == PSA_KEY_TYPE_NONE ) + { + /* No key material to clean. */ + } + else if( key_type_is_raw_bytes( slot->attr.type ) ) + { + mbedtls_free( slot->data.raw.data ); + } + else +#if defined(MBEDTLS_RSA_C) + if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) + { + mbedtls_rsa_free( slot->data.rsa ); + mbedtls_free( slot->data.rsa ); + } + else +#endif /* defined(MBEDTLS_RSA_C) */ +#if defined(MBEDTLS_ECP_C) + if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) + { + mbedtls_ecp_keypair_free( slot->data.ecp ); + mbedtls_free( slot->data.ecp ); + } + else +#endif /* defined(MBEDTLS_ECP_C) */ + { + /* Shouldn't happen: the key type is not any type that we + * put in. */ + return( PSA_ERROR_CORRUPTION_DETECTED ); + } + + return( PSA_SUCCESS ); +} + +/** Completely wipe a slot in memory, including its policy. + * Persistent storage is not affected. */ +psa_status_t psa_wipe_key_slot( psa_key_slot_t *slot ) +{ + psa_status_t status = psa_remove_key_data_from_memory( slot ); + /* Multipart operations may still be using the key. This is safe + * because all multipart operation objects are independent from + * the key slot: if they need to access the key after the setup + * phase, they have a copy of the key. Note that this means that + * key material can linger until all operations are completed. */ + /* At this point, key material and other type-specific content has + * been wiped. Clear remaining metadata. We can call memset and not + * zeroize because the metadata is not particularly sensitive. */ + memset( slot, 0, sizeof( *slot ) ); + return( status ); +} + +psa_status_t psa_destroy_key( psa_key_handle_t handle ) +{ + psa_key_slot_t *slot; + psa_status_t status; /* status of the last operation */ + psa_status_t overall_status = PSA_SUCCESS; +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + psa_se_drv_table_entry_t *driver; +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + if( handle == 0 ) + return( PSA_SUCCESS ); + + status = psa_get_key_slot( handle, &slot ); + if( status != PSA_SUCCESS ) + return( status ); + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + driver = psa_get_se_driver_entry( slot->attr.lifetime ); + if( driver != NULL ) + { + /* For a key in a secure element, we need to do three things: + * remove the key file in internal storage, destroy the + * key inside the secure element, and update the driver's + * persistent data. Start a transaction that will encompass these + * three actions. */ + psa_crypto_prepare_transaction( PSA_CRYPTO_TRANSACTION_DESTROY_KEY ); + psa_crypto_transaction.key.lifetime = slot->attr.lifetime; + psa_crypto_transaction.key.slot = slot->data.se.slot_number; + psa_crypto_transaction.key.id = slot->attr.id; + status = psa_crypto_save_transaction( ); + if( status != PSA_SUCCESS ) + { + (void) psa_crypto_stop_transaction( ); + /* We should still try to destroy the key in the secure + * element and the key metadata in storage. This is especially + * important if the error is that the storage is full. + * But how to do it exactly without risking an inconsistent + * state after a reset? + * https://github.com/ARMmbed/mbed-crypto/issues/215 + */ + overall_status = status; + goto exit; + } + + status = psa_destroy_se_key( driver, slot->data.se.slot_number ); + if( overall_status == PSA_SUCCESS ) + overall_status = status; + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) + if( slot->attr.lifetime != PSA_KEY_LIFETIME_VOLATILE ) + { + status = psa_destroy_persistent_key( slot->attr.id ); + if( overall_status == PSA_SUCCESS ) + overall_status = status; + + /* TODO: other slots may have a copy of the same key. We should + * invalidate them. + * https://github.com/ARMmbed/mbed-crypto/issues/214 + */ + } +#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if( driver != NULL ) + { + status = psa_save_se_persistent_data( driver ); + if( overall_status == PSA_SUCCESS ) + overall_status = status; + status = psa_crypto_stop_transaction( ); + if( overall_status == PSA_SUCCESS ) + overall_status = status; + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +exit: +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + status = psa_wipe_key_slot( slot ); + /* Prioritize CORRUPTION_DETECTED from wiping over a storage error */ + if( overall_status == PSA_SUCCESS ) + overall_status = status; + return( overall_status ); +} + +void psa_reset_key_attributes( psa_key_attributes_t *attributes ) +{ + mbedtls_free( attributes->domain_parameters ); + memset( attributes, 0, sizeof( *attributes ) ); +} + +psa_status_t psa_set_key_domain_parameters( psa_key_attributes_t *attributes, + psa_key_type_t type, + const uint8_t *data, + size_t data_length ) +{ + uint8_t *copy = NULL; + + if( data_length != 0 ) + { + copy = mbedtls_calloc( 1, data_length ); + if( copy == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + memcpy( copy, data, data_length ); + } + /* After this point, this function is guaranteed to succeed, so it + * can start modifying `*attributes`. */ + + if( attributes->domain_parameters != NULL ) + { + mbedtls_free( attributes->domain_parameters ); + attributes->domain_parameters = NULL; + attributes->domain_parameters_size = 0; + } + + attributes->domain_parameters = copy; + attributes->domain_parameters_size = data_length; + attributes->core.type = type; + return( PSA_SUCCESS ); +} + +psa_status_t psa_get_key_domain_parameters( + const psa_key_attributes_t *attributes, + uint8_t *data, size_t data_size, size_t *data_length ) +{ + if( attributes->domain_parameters_size > data_size ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + *data_length = attributes->domain_parameters_size; + if( attributes->domain_parameters_size != 0 ) + memcpy( data, attributes->domain_parameters, + attributes->domain_parameters_size ); + return( PSA_SUCCESS ); +} + +#if defined(MBEDTLS_RSA_C) +static psa_status_t psa_get_rsa_public_exponent( + const mbedtls_rsa_context *rsa, + psa_key_attributes_t *attributes ) +{ + mbedtls_mpi mpi; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint8_t *buffer = NULL; + size_t buflen; + mbedtls_mpi_init( &mpi ); + + ret = mbedtls_rsa_export( rsa, NULL, NULL, NULL, NULL, &mpi ); + if( ret != 0 ) + goto exit; + if( mbedtls_mpi_cmp_int( &mpi, 65537 ) == 0 ) + { + /* It's the default value, which is reported as an empty string, + * so there's nothing to do. */ + goto exit; + } + + buflen = mbedtls_mpi_size( &mpi ); + buffer = mbedtls_calloc( 1, buflen ); + if( buffer == NULL ) + { + ret = MBEDTLS_ERR_MPI_ALLOC_FAILED; + goto exit; + } + ret = mbedtls_mpi_write_binary( &mpi, buffer, buflen ); + if( ret != 0 ) + goto exit; + attributes->domain_parameters = buffer; + attributes->domain_parameters_size = buflen; + +exit: + mbedtls_mpi_free( &mpi ); + if( ret != 0 ) + mbedtls_free( buffer ); + return( mbedtls_to_psa_error( ret ) ); +} +#endif /* MBEDTLS_RSA_C */ + +/** Retrieve all the publicly-accessible attributes of a key. + */ +psa_status_t psa_get_key_attributes( psa_key_handle_t handle, + psa_key_attributes_t *attributes ) +{ + psa_key_slot_t *slot; + psa_status_t status; + + psa_reset_key_attributes( attributes ); + + status = psa_get_key_from_slot( handle, &slot, 0, 0 ); + if( status != PSA_SUCCESS ) + return( status ); + + attributes->core = slot->attr; + attributes->core.flags &= ( MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY | + MBEDTLS_PSA_KA_MASK_DUAL_USE ); + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if( psa_key_slot_is_external( slot ) ) + psa_set_key_slot_number( attributes, slot->data.se.slot_number ); +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + switch( slot->attr.type ) + { +#if defined(MBEDTLS_RSA_C) + case PSA_KEY_TYPE_RSA_KEY_PAIR: + case PSA_KEY_TYPE_RSA_PUBLIC_KEY: +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + /* TODO: reporting the public exponent for opaque keys + * is not yet implemented. + * https://github.com/ARMmbed/mbed-crypto/issues/216 + */ + if( psa_key_slot_is_external( slot ) ) + break; +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + status = psa_get_rsa_public_exponent( slot->data.rsa, attributes ); + break; +#endif /* MBEDTLS_RSA_C */ + default: + /* Nothing else to do. */ + break; + } + + if( status != PSA_SUCCESS ) + psa_reset_key_attributes( attributes ); + return( status ); +} + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +psa_status_t psa_get_key_slot_number( + const psa_key_attributes_t *attributes, + psa_key_slot_number_t *slot_number ) +{ + if( attributes->core.flags & MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER ) + { + *slot_number = attributes->slot_number; + return( PSA_SUCCESS ); + } + else + return( PSA_ERROR_INVALID_ARGUMENT ); +} +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + +#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECP_C) +static int pk_write_pubkey_simple( mbedtls_pk_context *key, + unsigned char *buf, size_t size ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *c; + size_t len = 0; + + c = buf + size; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, key ) ); + + return( (int) len ); +} +#endif /* defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECP_C) */ + +static psa_status_t psa_internal_export_key( const psa_key_slot_t *slot, + uint8_t *data, + size_t data_size, + size_t *data_length, + int export_public_key ) +{ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + *data_length = 0; + + if( export_public_key && ! PSA_KEY_TYPE_IS_ASYMMETRIC( slot->attr.type ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + /* Reject a zero-length output buffer now, since this can never be a + * valid key representation. This way we know that data must be a valid + * pointer and we can do things like memset(data, ..., data_size). */ + if( data_size == 0 ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) ) + { + psa_drv_se_export_key_t method; + if( drv->key_management == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + method = ( export_public_key ? + drv->key_management->p_export_public : + drv->key_management->p_export ); + if( method == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + return( method( drv_context, + slot->data.se.slot_number, + data, data_size, data_length ) ); + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + if( key_type_is_raw_bytes( slot->attr.type ) ) + { + if( slot->data.raw.bytes > data_size ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + memcpy( data, slot->data.raw.data, slot->data.raw.bytes ); + memset( data + slot->data.raw.bytes, 0, + data_size - slot->data.raw.bytes ); + *data_length = slot->data.raw.bytes; + return( PSA_SUCCESS ); + } +#if defined(MBEDTLS_ECP_C) + if( PSA_KEY_TYPE_IS_ECC_KEY_PAIR( slot->attr.type ) && !export_public_key ) + { + psa_status_t status; + + size_t bytes = PSA_BITS_TO_BYTES( slot->attr.bits ); + if( bytes > data_size ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + status = mbedtls_to_psa_error( + mbedtls_mpi_write_binary( &slot->data.ecp->d, data, bytes ) ); + if( status != PSA_SUCCESS ) + return( status ); + memset( data + bytes, 0, data_size - bytes ); + *data_length = bytes; + return( PSA_SUCCESS ); + } +#endif + else + { +#if defined(MBEDTLS_PK_WRITE_C) + if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) || + PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) + { + mbedtls_pk_context pk; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) + { +#if defined(MBEDTLS_RSA_C) + mbedtls_pk_init( &pk ); + pk.pk_info = &mbedtls_rsa_info; + pk.pk_ctx = slot->data.rsa; +#else + return( PSA_ERROR_NOT_SUPPORTED ); +#endif + } + else + { +#if defined(MBEDTLS_ECP_C) + mbedtls_pk_init( &pk ); + pk.pk_info = &mbedtls_eckey_info; + pk.pk_ctx = slot->data.ecp; +#else + return( PSA_ERROR_NOT_SUPPORTED ); +#endif + } + if( export_public_key || PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->attr.type ) ) + { + ret = pk_write_pubkey_simple( &pk, data, data_size ); + } + else + { + ret = mbedtls_pk_write_key_der( &pk, data, data_size ); + } + if( ret < 0 ) + { + memset( data, 0, data_size ); + return( mbedtls_to_psa_error( ret ) ); + } + /* The mbedtls_pk_xxx functions write to the end of the buffer. + * Move the data to the beginning and erase remaining data + * at the original location. */ + if( 2 * (size_t) ret <= data_size ) + { + memcpy( data, data + data_size - ret, ret ); + memset( data + data_size - ret, 0, ret ); + } + else if( (size_t) ret < data_size ) + { + memmove( data, data + data_size - ret, ret ); + memset( data + ret, 0, data_size - ret ); + } + *data_length = ret; + return( PSA_SUCCESS ); + } + else +#endif /* defined(MBEDTLS_PK_WRITE_C) */ + { + /* This shouldn't happen in the reference implementation, but + it is valid for a special-purpose implementation to omit + support for exporting certain key types. */ + return( PSA_ERROR_NOT_SUPPORTED ); + } + } +} + +psa_status_t psa_export_key( psa_key_handle_t handle, + uint8_t *data, + size_t data_size, + size_t *data_length ) +{ + psa_key_slot_t *slot; + psa_status_t status; + + /* Set the key to empty now, so that even when there are errors, we always + * set data_length to a value between 0 and data_size. On error, setting + * the key to empty is a good choice because an empty key representation is + * unlikely to be accepted anywhere. */ + *data_length = 0; + + /* Export requires the EXPORT flag. There is an exception for public keys, + * which don't require any flag, but psa_get_key_from_slot takes + * care of this. */ + status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_EXPORT, 0 ); + if( status != PSA_SUCCESS ) + return( status ); + return( psa_internal_export_key( slot, data, data_size, + data_length, 0 ) ); +} + +psa_status_t psa_export_public_key( psa_key_handle_t handle, + uint8_t *data, + size_t data_size, + size_t *data_length ) +{ + psa_key_slot_t *slot; + psa_status_t status; + + /* Set the key to empty now, so that even when there are errors, we always + * set data_length to a value between 0 and data_size. On error, setting + * the key to empty is a good choice because an empty key representation is + * unlikely to be accepted anywhere. */ + *data_length = 0; + + /* Exporting a public key doesn't require a usage flag. */ + status = psa_get_key_from_slot( handle, &slot, 0, 0 ); + if( status != PSA_SUCCESS ) + return( status ); + return( psa_internal_export_key( slot, data, data_size, + data_length, 1 ) ); +} + +#if defined(static_assert) +static_assert( ( MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_DUAL_USE ) == 0, + "One or more key attribute flag is listed as both external-only and dual-use" ); +static_assert( ( PSA_KA_MASK_INTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_DUAL_USE ) == 0, + "One or more key attribute flag is listed as both internal-only and dual-use" ); +static_assert( ( PSA_KA_MASK_INTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY ) == 0, + "One or more key attribute flag is listed as both internal-only and external-only" ); +#endif + +/** Validate that a key policy is internally well-formed. + * + * This function only rejects invalid policies. It does not validate the + * consistency of the policy with respect to other attributes of the key + * such as the key type. + */ +static psa_status_t psa_validate_key_policy( const psa_key_policy_t *policy ) +{ + if( ( policy->usage & ~( PSA_KEY_USAGE_EXPORT | + PSA_KEY_USAGE_COPY | + PSA_KEY_USAGE_ENCRYPT | + PSA_KEY_USAGE_DECRYPT | + PSA_KEY_USAGE_SIGN_HASH | + PSA_KEY_USAGE_VERIFY_HASH | + PSA_KEY_USAGE_DERIVE ) ) != 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + return( PSA_SUCCESS ); +} + +/** Validate the internal consistency of key attributes. + * + * This function only rejects invalid attribute values. If does not + * validate the consistency of the attributes with any key data that may + * be involved in the creation of the key. + * + * Call this function early in the key creation process. + * + * \param[in] attributes Key attributes for the new key. + * \param[out] p_drv On any return, the driver for the key, if any. + * NULL for a transparent key. + * + */ +static psa_status_t psa_validate_key_attributes( + const psa_key_attributes_t *attributes, + psa_se_drv_table_entry_t **p_drv ) +{ + psa_status_t status; + + if( attributes->core.lifetime != PSA_KEY_LIFETIME_VOLATILE ) + { + status = psa_validate_persistent_key_parameters( + attributes->core.lifetime, attributes->core.id, + p_drv, 1 ); + if( status != PSA_SUCCESS ) + return( status ); + } + + status = psa_validate_key_policy( &attributes->core.policy ); + if( status != PSA_SUCCESS ) + return( status ); + + /* Refuse to create overly large keys. + * Note that this doesn't trigger on import if the attributes don't + * explicitly specify a size (so psa_get_key_bits returns 0), so + * psa_import_key() needs its own checks. */ + if( psa_get_key_bits( attributes ) > PSA_MAX_KEY_BITS ) + return( PSA_ERROR_NOT_SUPPORTED ); + + /* Reject invalid flags. These should not be reachable through the API. */ + if( attributes->core.flags & ~ ( MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY | + MBEDTLS_PSA_KA_MASK_DUAL_USE ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + return( PSA_SUCCESS ); +} + +/** Prepare a key slot to receive key material. + * + * This function allocates a key slot and sets its metadata. + * + * If this function fails, call psa_fail_key_creation(). + * + * This function is intended to be used as follows: + * -# Call psa_start_key_creation() to allocate a key slot, prepare + * it with the specified attributes, and assign it a handle. + * -# Populate the slot with the key material. + * -# Call psa_finish_key_creation() to finalize the creation of the slot. + * In case of failure at any step, stop the sequence and call + * psa_fail_key_creation(). + * + * \param method An identification of the calling function. + * \param[in] attributes Key attributes for the new key. + * \param[out] handle On success, a handle for the allocated slot. + * \param[out] p_slot On success, a pointer to the prepared slot. + * \param[out] p_drv On any return, the driver for the key, if any. + * NULL for a transparent key. + * + * \retval #PSA_SUCCESS + * The key slot is ready to receive key material. + * \return If this function fails, the key slot is an invalid state. + * You must call psa_fail_key_creation() to wipe and free the slot. + */ +static psa_status_t psa_start_key_creation( + psa_key_creation_method_t method, + const psa_key_attributes_t *attributes, + psa_key_handle_t *handle, + psa_key_slot_t **p_slot, + psa_se_drv_table_entry_t **p_drv ) +{ + psa_status_t status; + psa_key_slot_t *slot; + + (void) method; + *p_drv = NULL; + + status = psa_validate_key_attributes( attributes, p_drv ); + if( status != PSA_SUCCESS ) + return( status ); + + status = psa_get_empty_key_slot( handle, p_slot ); + if( status != PSA_SUCCESS ) + return( status ); + slot = *p_slot; + + /* We're storing the declared bit-size of the key. It's up to each + * creation mechanism to verify that this information is correct. + * It's automatically correct for mechanisms that use the bit-size as + * an input (generate, device) but not for those where the bit-size + * is optional (import, copy). */ + + slot->attr = attributes->core; + + /* Erase external-only flags from the internal copy. To access + * external-only flags, query `attributes`. Thanks to the check + * in psa_validate_key_attributes(), this leaves the dual-use + * flags and any internal flag that psa_get_empty_key_slot() + * may have set. */ + slot->attr.flags &= ~MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY; + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + /* For a key in a secure element, we need to do three things + * when creating or registering a key: + * create the key file in internal storage, create the + * key inside the secure element, and update the driver's + * persistent data. Start a transaction that will encompass these + * three actions. */ + /* The first thing to do is to find a slot number for the new key. + * We save the slot number in persistent storage as part of the + * transaction data. It will be needed to recover if the power + * fails during the key creation process, to clean up on the secure + * element side after restarting. Obtaining a slot number from the + * secure element driver updates its persistent state, but we do not yet + * save the driver's persistent state, so that if the power fails, + * we can roll back to a state where the key doesn't exist. */ + if( *p_drv != NULL ) + { + status = psa_find_se_slot_for_key( attributes, method, *p_drv, + &slot->data.se.slot_number ); + if( status != PSA_SUCCESS ) + return( status ); + psa_crypto_prepare_transaction( PSA_CRYPTO_TRANSACTION_CREATE_KEY ); + psa_crypto_transaction.key.lifetime = slot->attr.lifetime; + psa_crypto_transaction.key.slot = slot->data.se.slot_number; + psa_crypto_transaction.key.id = slot->attr.id; + status = psa_crypto_save_transaction( ); + if( status != PSA_SUCCESS ) + { + (void) psa_crypto_stop_transaction( ); + return( status ); + } + } + + if( *p_drv == NULL && method == PSA_KEY_CREATION_REGISTER ) + { + /* Key registration only makes sense with a secure element. */ + return( PSA_ERROR_INVALID_ARGUMENT ); + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + return( status ); +} + +/** Finalize the creation of a key once its key material has been set. + * + * This entails writing the key to persistent storage. + * + * If this function fails, call psa_fail_key_creation(). + * See the documentation of psa_start_key_creation() for the intended use + * of this function. + * + * \param[in,out] slot Pointer to the slot with key material. + * \param[in] driver The secure element driver for the key, + * or NULL for a transparent key. + * + * \retval #PSA_SUCCESS + * The key was successfully created. The handle is now valid. + * \return If this function fails, the key slot is an invalid state. + * You must call psa_fail_key_creation() to wipe and free the slot. + */ +static psa_status_t psa_finish_key_creation( + psa_key_slot_t *slot, + psa_se_drv_table_entry_t *driver ) +{ + psa_status_t status = PSA_SUCCESS; + (void) slot; + (void) driver; + +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) + if( slot->attr.lifetime != PSA_KEY_LIFETIME_VOLATILE ) + { +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if( driver != NULL ) + { + psa_se_key_data_storage_t data; +#if defined(static_assert) + static_assert( sizeof( slot->data.se.slot_number ) == + sizeof( data.slot_number ), + "Slot number size does not match psa_se_key_data_storage_t" ); + static_assert( sizeof( slot->attr.bits ) == sizeof( data.bits ), + "Bit-size size does not match psa_se_key_data_storage_t" ); +#endif + memcpy( &data.slot_number, &slot->data.se.slot_number, + sizeof( slot->data.se.slot_number ) ); + memcpy( &data.bits, &slot->attr.bits, + sizeof( slot->attr.bits ) ); + status = psa_save_persistent_key( &slot->attr, + (uint8_t*) &data, + sizeof( data ) ); + } + else +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + { + size_t buffer_size = + PSA_KEY_EXPORT_MAX_SIZE( slot->attr.type, + slot->attr.bits ); + uint8_t *buffer = mbedtls_calloc( 1, buffer_size ); + size_t length = 0; + if( buffer == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + status = psa_internal_export_key( slot, + buffer, buffer_size, &length, + 0 ); + if( status == PSA_SUCCESS ) + status = psa_save_persistent_key( &slot->attr, + buffer, length ); + + mbedtls_platform_zeroize( buffer, buffer_size ); + mbedtls_free( buffer ); + } + } +#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + /* Finish the transaction for a key creation. This does not + * happen when registering an existing key. Detect this case + * by checking whether a transaction is in progress (actual + * creation of a key in a secure element requires a transaction, + * but registration doesn't use one). */ + if( driver != NULL && + psa_crypto_transaction.unknown.type == PSA_CRYPTO_TRANSACTION_CREATE_KEY ) + { + status = psa_save_se_persistent_data( driver ); + if( status != PSA_SUCCESS ) + { + psa_destroy_persistent_key( slot->attr.id ); + return( status ); + } + status = psa_crypto_stop_transaction( ); + if( status != PSA_SUCCESS ) + return( status ); + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + return( status ); +} + +/** Abort the creation of a key. + * + * You may call this function after calling psa_start_key_creation(), + * or after psa_finish_key_creation() fails. In other circumstances, this + * function may not clean up persistent storage. + * See the documentation of psa_start_key_creation() for the intended use + * of this function. + * + * \param[in,out] slot Pointer to the slot with key material. + * \param[in] driver The secure element driver for the key, + * or NULL for a transparent key. + */ +static void psa_fail_key_creation( psa_key_slot_t *slot, + psa_se_drv_table_entry_t *driver ) +{ + (void) driver; + + if( slot == NULL ) + return; + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + /* TODO: If the key has already been created in the secure + * element, and the failure happened later (when saving metadata + * to internal storage), we need to destroy the key in the secure + * element. + * https://github.com/ARMmbed/mbed-crypto/issues/217 + */ + + /* Abort the ongoing transaction if any (there may not be one if + * the creation process failed before starting one, or if the + * key creation is a registration of a key in a secure element). + * Earlier functions must already have done what it takes to undo any + * partial creation. All that's left is to update the transaction data + * itself. */ + (void) psa_crypto_stop_transaction( ); +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + psa_wipe_key_slot( slot ); +} + +/** Validate optional attributes during key creation. + * + * Some key attributes are optional during key creation. If they are + * specified in the attributes structure, check that they are consistent + * with the data in the slot. + * + * This function should be called near the end of key creation, after + * the slot in memory is fully populated but before saving persistent data. + */ +static psa_status_t psa_validate_optional_attributes( + const psa_key_slot_t *slot, + const psa_key_attributes_t *attributes ) +{ + if( attributes->core.type != 0 ) + { + if( attributes->core.type != slot->attr.type ) + return( PSA_ERROR_INVALID_ARGUMENT ); + } + + if( attributes->domain_parameters_size != 0 ) + { +#if defined(MBEDTLS_RSA_C) + if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) + { + mbedtls_mpi actual, required; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi_init( &actual ); + mbedtls_mpi_init( &required ); + ret = mbedtls_rsa_export( slot->data.rsa, + NULL, NULL, NULL, NULL, &actual ); + if( ret != 0 ) + goto rsa_exit; + ret = mbedtls_mpi_read_binary( &required, + attributes->domain_parameters, + attributes->domain_parameters_size ); + if( ret != 0 ) + goto rsa_exit; + if( mbedtls_mpi_cmp_mpi( &actual, &required ) != 0 ) + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + rsa_exit: + mbedtls_mpi_free( &actual ); + mbedtls_mpi_free( &required ); + if( ret != 0) + return( mbedtls_to_psa_error( ret ) ); + } + else +#endif + { + return( PSA_ERROR_INVALID_ARGUMENT ); + } + } + + if( attributes->core.bits != 0 ) + { + if( attributes->core.bits != slot->attr.bits ) + return( PSA_ERROR_INVALID_ARGUMENT ); + } + + return( PSA_SUCCESS ); +} + +psa_status_t psa_import_key( const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + psa_key_handle_t *handle ) +{ + psa_status_t status; + psa_key_slot_t *slot = NULL; + psa_se_drv_table_entry_t *driver = NULL; + + /* Reject zero-length symmetric keys (including raw data key objects). + * This also rejects any key which might be encoded as an empty string, + * which is never valid. */ + if( data_length == 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + status = psa_start_key_creation( PSA_KEY_CREATION_IMPORT, attributes, + handle, &slot, &driver ); + if( status != PSA_SUCCESS ) + goto exit; + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if( driver != NULL ) + { + const psa_drv_se_t *drv = psa_get_se_driver_methods( driver ); + /* The driver should set the number of key bits, however in + * case it doesn't, we initialize bits to an invalid value. */ + size_t bits = PSA_MAX_KEY_BITS + 1; + if( drv->key_management == NULL || + drv->key_management->p_import == NULL ) + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + status = drv->key_management->p_import( + psa_get_se_driver_context( driver ), + slot->data.se.slot_number, attributes, data, data_length, + &bits ); + if( status != PSA_SUCCESS ) + goto exit; + if( bits > PSA_MAX_KEY_BITS ) + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + slot->attr.bits = (psa_key_bits_t) bits; + } + else +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + { + status = psa_import_key_into_slot( slot, data, data_length ); + if( status != PSA_SUCCESS ) + goto exit; + } + status = psa_validate_optional_attributes( slot, attributes ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_finish_key_creation( slot, driver ); +exit: + if( status != PSA_SUCCESS ) + { + psa_fail_key_creation( slot, driver ); + *handle = 0; + } + return( status ); +} + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +psa_status_t mbedtls_psa_register_se_key( + const psa_key_attributes_t *attributes ) +{ + psa_status_t status; + psa_key_slot_t *slot = NULL; + psa_se_drv_table_entry_t *driver = NULL; + psa_key_handle_t handle = 0; + + /* Leaving attributes unspecified is not currently supported. + * It could make sense to query the key type and size from the + * secure element, but not all secure elements support this + * and the driver HAL doesn't currently support it. */ + if( psa_get_key_type( attributes ) == PSA_KEY_TYPE_NONE ) + return( PSA_ERROR_NOT_SUPPORTED ); + if( psa_get_key_bits( attributes ) == 0 ) + return( PSA_ERROR_NOT_SUPPORTED ); + + status = psa_start_key_creation( PSA_KEY_CREATION_REGISTER, attributes, + &handle, &slot, &driver ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_finish_key_creation( slot, driver ); + +exit: + if( status != PSA_SUCCESS ) + { + psa_fail_key_creation( slot, driver ); + } + /* Registration doesn't keep the key in RAM. */ + psa_close_key( handle ); + return( status ); +} +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + +static psa_status_t psa_copy_key_material( const psa_key_slot_t *source, + psa_key_slot_t *target ) +{ + psa_status_t status; + uint8_t *buffer = NULL; + size_t buffer_size = 0; + size_t length; + + buffer_size = PSA_KEY_EXPORT_MAX_SIZE( source->attr.type, + psa_get_key_slot_bits( source ) ); + buffer = mbedtls_calloc( 1, buffer_size ); + if( buffer == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + status = psa_internal_export_key( source, buffer, buffer_size, &length, 0 ); + if( status != PSA_SUCCESS ) + goto exit; + target->attr.type = source->attr.type; + status = psa_import_key_into_slot( target, buffer, length ); + +exit: + mbedtls_platform_zeroize( buffer, buffer_size ); + mbedtls_free( buffer ); + return( status ); +} + +psa_status_t psa_copy_key( psa_key_handle_t source_handle, + const psa_key_attributes_t *specified_attributes, + psa_key_handle_t *target_handle ) +{ + psa_status_t status; + psa_key_slot_t *source_slot = NULL; + psa_key_slot_t *target_slot = NULL; + psa_key_attributes_t actual_attributes = *specified_attributes; + psa_se_drv_table_entry_t *driver = NULL; + + status = psa_get_transparent_key( source_handle, &source_slot, + PSA_KEY_USAGE_COPY, 0 ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_validate_optional_attributes( source_slot, + specified_attributes ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_restrict_key_policy( &actual_attributes.core.policy, + &source_slot->attr.policy ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_start_key_creation( PSA_KEY_CREATION_COPY, + &actual_attributes, + target_handle, &target_slot, &driver ); + if( status != PSA_SUCCESS ) + goto exit; + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if( driver != NULL ) + { + /* Copying to a secure element is not implemented yet. */ + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + status = psa_copy_key_material( source_slot, target_slot ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_finish_key_creation( target_slot, driver ); +exit: + if( status != PSA_SUCCESS ) + { + psa_fail_key_creation( target_slot, driver ); + *target_handle = 0; + } + return( status ); +} + + + +/****************************************************************/ +/* Message digests */ +/****************************************************************/ + +#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_DETERMINISTIC) +static const mbedtls_md_info_t *mbedtls_md_info_from_psa( psa_algorithm_t alg ) +{ + switch( alg ) + { +#if defined(MBEDTLS_MD2_C) + case PSA_ALG_MD2: + return( &mbedtls_md2_info ); +#endif +#if defined(MBEDTLS_MD4_C) + case PSA_ALG_MD4: + return( &mbedtls_md4_info ); +#endif +#if defined(MBEDTLS_MD5_C) + case PSA_ALG_MD5: + return( &mbedtls_md5_info ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case PSA_ALG_RIPEMD160: + return( &mbedtls_ripemd160_info ); +#endif +#if defined(MBEDTLS_SHA1_C) + case PSA_ALG_SHA_1: + return( &mbedtls_sha1_info ); +#endif +#if defined(MBEDTLS_SHA256_C) + case PSA_ALG_SHA_224: + return( &mbedtls_sha224_info ); + case PSA_ALG_SHA_256: + return( &mbedtls_sha256_info ); +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case PSA_ALG_SHA_384: + return( &mbedtls_sha384_info ); +#endif + case PSA_ALG_SHA_512: + return( &mbedtls_sha512_info ); +#endif + default: + return( NULL ); + } +} +#endif + +psa_status_t psa_hash_abort( psa_hash_operation_t *operation ) +{ + switch( operation->alg ) + { + case 0: + /* The object has (apparently) been initialized but it is not + * in use. It's ok to call abort on such an object, and there's + * nothing to do. */ + break; +#if defined(MBEDTLS_MD2_C) + case PSA_ALG_MD2: + mbedtls_md2_free( &operation->ctx.md2 ); + break; +#endif +#if defined(MBEDTLS_MD4_C) + case PSA_ALG_MD4: + mbedtls_md4_free( &operation->ctx.md4 ); + break; +#endif +#if defined(MBEDTLS_MD5_C) + case PSA_ALG_MD5: + mbedtls_md5_free( &operation->ctx.md5 ); + break; +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case PSA_ALG_RIPEMD160: + mbedtls_ripemd160_free( &operation->ctx.ripemd160 ); + break; +#endif +#if defined(MBEDTLS_SHA1_C) + case PSA_ALG_SHA_1: + mbedtls_sha1_free( &operation->ctx.sha1 ); + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case PSA_ALG_SHA_224: + case PSA_ALG_SHA_256: + mbedtls_sha256_free( &operation->ctx.sha256 ); + break; +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case PSA_ALG_SHA_384: +#endif + case PSA_ALG_SHA_512: + mbedtls_sha512_free( &operation->ctx.sha512 ); + break; +#endif + default: + return( PSA_ERROR_BAD_STATE ); + } + operation->alg = 0; + return( PSA_SUCCESS ); +} + +psa_status_t psa_hash_setup( psa_hash_operation_t *operation, + psa_algorithm_t alg ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* A context must be freshly initialized before it can be set up. */ + if( operation->alg != 0 ) + { + return( PSA_ERROR_BAD_STATE ); + } + + switch( alg ) + { +#if defined(MBEDTLS_MD2_C) + case PSA_ALG_MD2: + mbedtls_md2_init( &operation->ctx.md2 ); + ret = mbedtls_md2_starts_ret( &operation->ctx.md2 ); + break; +#endif +#if defined(MBEDTLS_MD4_C) + case PSA_ALG_MD4: + mbedtls_md4_init( &operation->ctx.md4 ); + ret = mbedtls_md4_starts_ret( &operation->ctx.md4 ); + break; +#endif +#if defined(MBEDTLS_MD5_C) + case PSA_ALG_MD5: + mbedtls_md5_init( &operation->ctx.md5 ); + ret = mbedtls_md5_starts_ret( &operation->ctx.md5 ); + break; +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case PSA_ALG_RIPEMD160: + mbedtls_ripemd160_init( &operation->ctx.ripemd160 ); + ret = mbedtls_ripemd160_starts_ret( &operation->ctx.ripemd160 ); + break; +#endif +#if defined(MBEDTLS_SHA1_C) + case PSA_ALG_SHA_1: + mbedtls_sha1_init( &operation->ctx.sha1 ); + ret = mbedtls_sha1_starts_ret( &operation->ctx.sha1 ); + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case PSA_ALG_SHA_224: + mbedtls_sha256_init( &operation->ctx.sha256 ); + ret = mbedtls_sha256_starts_ret( &operation->ctx.sha256, 1 ); + break; + case PSA_ALG_SHA_256: + mbedtls_sha256_init( &operation->ctx.sha256 ); + ret = mbedtls_sha256_starts_ret( &operation->ctx.sha256, 0 ); + break; +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case PSA_ALG_SHA_384: + mbedtls_sha512_init( &operation->ctx.sha512 ); + ret = mbedtls_sha512_starts_ret( &operation->ctx.sha512, 1 ); + break; +#endif + case PSA_ALG_SHA_512: + mbedtls_sha512_init( &operation->ctx.sha512 ); + ret = mbedtls_sha512_starts_ret( &operation->ctx.sha512, 0 ); + break; +#endif + default: + return( PSA_ALG_IS_HASH( alg ) ? + PSA_ERROR_NOT_SUPPORTED : + PSA_ERROR_INVALID_ARGUMENT ); + } + if( ret == 0 ) + operation->alg = alg; + else + psa_hash_abort( operation ); + return( mbedtls_to_psa_error( ret ) ); +} + +psa_status_t psa_hash_update( psa_hash_operation_t *operation, + const uint8_t *input, + size_t input_length ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* Don't require hash implementations to behave correctly on a + * zero-length input, which may have an invalid pointer. */ + if( input_length == 0 ) + return( PSA_SUCCESS ); + + switch( operation->alg ) + { +#if defined(MBEDTLS_MD2_C) + case PSA_ALG_MD2: + ret = mbedtls_md2_update_ret( &operation->ctx.md2, + input, input_length ); + break; +#endif +#if defined(MBEDTLS_MD4_C) + case PSA_ALG_MD4: + ret = mbedtls_md4_update_ret( &operation->ctx.md4, + input, input_length ); + break; +#endif +#if defined(MBEDTLS_MD5_C) + case PSA_ALG_MD5: + ret = mbedtls_md5_update_ret( &operation->ctx.md5, + input, input_length ); + break; +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case PSA_ALG_RIPEMD160: + ret = mbedtls_ripemd160_update_ret( &operation->ctx.ripemd160, + input, input_length ); + break; +#endif +#if defined(MBEDTLS_SHA1_C) + case PSA_ALG_SHA_1: + ret = mbedtls_sha1_update_ret( &operation->ctx.sha1, + input, input_length ); + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case PSA_ALG_SHA_224: + case PSA_ALG_SHA_256: + ret = mbedtls_sha256_update_ret( &operation->ctx.sha256, + input, input_length ); + break; +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case PSA_ALG_SHA_384: +#endif + case PSA_ALG_SHA_512: + ret = mbedtls_sha512_update_ret( &operation->ctx.sha512, + input, input_length ); + break; +#endif + default: + return( PSA_ERROR_BAD_STATE ); + } + + if( ret != 0 ) + psa_hash_abort( operation ); + return( mbedtls_to_psa_error( ret ) ); +} + +psa_status_t psa_hash_finish( psa_hash_operation_t *operation, + uint8_t *hash, + size_t hash_size, + size_t *hash_length ) +{ + psa_status_t status; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t actual_hash_length = PSA_HASH_SIZE( operation->alg ); + + /* Fill the output buffer with something that isn't a valid hash + * (barring an attack on the hash and deliberately-crafted input), + * in case the caller doesn't check the return status properly. */ + *hash_length = hash_size; + /* If hash_size is 0 then hash may be NULL and then the + * call to memset would have undefined behavior. */ + if( hash_size != 0 ) + memset( hash, '!', hash_size ); + + if( hash_size < actual_hash_length ) + { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + + switch( operation->alg ) + { +#if defined(MBEDTLS_MD2_C) + case PSA_ALG_MD2: + ret = mbedtls_md2_finish_ret( &operation->ctx.md2, hash ); + break; +#endif +#if defined(MBEDTLS_MD4_C) + case PSA_ALG_MD4: + ret = mbedtls_md4_finish_ret( &operation->ctx.md4, hash ); + break; +#endif +#if defined(MBEDTLS_MD5_C) + case PSA_ALG_MD5: + ret = mbedtls_md5_finish_ret( &operation->ctx.md5, hash ); + break; +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case PSA_ALG_RIPEMD160: + ret = mbedtls_ripemd160_finish_ret( &operation->ctx.ripemd160, hash ); + break; +#endif +#if defined(MBEDTLS_SHA1_C) + case PSA_ALG_SHA_1: + ret = mbedtls_sha1_finish_ret( &operation->ctx.sha1, hash ); + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case PSA_ALG_SHA_224: + case PSA_ALG_SHA_256: + ret = mbedtls_sha256_finish_ret( &operation->ctx.sha256, hash ); + break; +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case PSA_ALG_SHA_384: +#endif + case PSA_ALG_SHA_512: + ret = mbedtls_sha512_finish_ret( &operation->ctx.sha512, hash ); + break; +#endif + default: + return( PSA_ERROR_BAD_STATE ); + } + status = mbedtls_to_psa_error( ret ); + +exit: + if( status == PSA_SUCCESS ) + { + *hash_length = actual_hash_length; + return( psa_hash_abort( operation ) ); + } + else + { + psa_hash_abort( operation ); + return( status ); + } +} + +psa_status_t psa_hash_verify( psa_hash_operation_t *operation, + const uint8_t *hash, + size_t hash_length ) +{ + uint8_t actual_hash[MBEDTLS_MD_MAX_SIZE]; + size_t actual_hash_length; + psa_status_t status = psa_hash_finish( operation, + actual_hash, sizeof( actual_hash ), + &actual_hash_length ); + if( status != PSA_SUCCESS ) + return( status ); + if( actual_hash_length != hash_length ) + return( PSA_ERROR_INVALID_SIGNATURE ); + if( safer_memcmp( hash, actual_hash, actual_hash_length ) != 0 ) + return( PSA_ERROR_INVALID_SIGNATURE ); + return( PSA_SUCCESS ); +} + +psa_status_t psa_hash_compute( psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + uint8_t *hash, size_t hash_size, + size_t *hash_length ) +{ + psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + *hash_length = hash_size; + status = psa_hash_setup( &operation, alg ); + if( status != PSA_SUCCESS ) + goto exit; + status = psa_hash_update( &operation, input, input_length ); + if( status != PSA_SUCCESS ) + goto exit; + status = psa_hash_finish( &operation, hash, hash_size, hash_length ); + if( status != PSA_SUCCESS ) + goto exit; + +exit: + if( status == PSA_SUCCESS ) + status = psa_hash_abort( &operation ); + else + psa_hash_abort( &operation ); + return( status ); +} + +psa_status_t psa_hash_compare( psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + const uint8_t *hash, size_t hash_length ) +{ + psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + status = psa_hash_setup( &operation, alg ); + if( status != PSA_SUCCESS ) + goto exit; + status = psa_hash_update( &operation, input, input_length ); + if( status != PSA_SUCCESS ) + goto exit; + status = psa_hash_verify( &operation, hash, hash_length ); + if( status != PSA_SUCCESS ) + goto exit; + +exit: + if( status == PSA_SUCCESS ) + status = psa_hash_abort( &operation ); + else + psa_hash_abort( &operation ); + return( status ); +} + +psa_status_t psa_hash_clone( const psa_hash_operation_t *source_operation, + psa_hash_operation_t *target_operation ) +{ + if( target_operation->alg != 0 ) + return( PSA_ERROR_BAD_STATE ); + + switch( source_operation->alg ) + { + case 0: + return( PSA_ERROR_BAD_STATE ); +#if defined(MBEDTLS_MD2_C) + case PSA_ALG_MD2: + mbedtls_md2_clone( &target_operation->ctx.md2, + &source_operation->ctx.md2 ); + break; +#endif +#if defined(MBEDTLS_MD4_C) + case PSA_ALG_MD4: + mbedtls_md4_clone( &target_operation->ctx.md4, + &source_operation->ctx.md4 ); + break; +#endif +#if defined(MBEDTLS_MD5_C) + case PSA_ALG_MD5: + mbedtls_md5_clone( &target_operation->ctx.md5, + &source_operation->ctx.md5 ); + break; +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case PSA_ALG_RIPEMD160: + mbedtls_ripemd160_clone( &target_operation->ctx.ripemd160, + &source_operation->ctx.ripemd160 ); + break; +#endif +#if defined(MBEDTLS_SHA1_C) + case PSA_ALG_SHA_1: + mbedtls_sha1_clone( &target_operation->ctx.sha1, + &source_operation->ctx.sha1 ); + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case PSA_ALG_SHA_224: + case PSA_ALG_SHA_256: + mbedtls_sha256_clone( &target_operation->ctx.sha256, + &source_operation->ctx.sha256 ); + break; +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case PSA_ALG_SHA_384: +#endif + case PSA_ALG_SHA_512: + mbedtls_sha512_clone( &target_operation->ctx.sha512, + &source_operation->ctx.sha512 ); + break; +#endif + default: + return( PSA_ERROR_NOT_SUPPORTED ); + } + + target_operation->alg = source_operation->alg; + return( PSA_SUCCESS ); +} + + +/****************************************************************/ +/* MAC */ +/****************************************************************/ + +static const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa( + psa_algorithm_t alg, + psa_key_type_t key_type, + size_t key_bits, + mbedtls_cipher_id_t* cipher_id ) +{ + mbedtls_cipher_mode_t mode; + mbedtls_cipher_id_t cipher_id_tmp; + + if( PSA_ALG_IS_AEAD( alg ) ) + alg = PSA_ALG_AEAD_WITH_TAG_LENGTH( alg, 0 ); + + if( PSA_ALG_IS_CIPHER( alg ) || PSA_ALG_IS_AEAD( alg ) ) + { + switch( alg ) + { + case PSA_ALG_ARC4: + case PSA_ALG_CHACHA20: + mode = MBEDTLS_MODE_STREAM; + break; + case PSA_ALG_CTR: + mode = MBEDTLS_MODE_CTR; + break; + case PSA_ALG_CFB: + mode = MBEDTLS_MODE_CFB; + break; + case PSA_ALG_OFB: + mode = MBEDTLS_MODE_OFB; + break; + case PSA_ALG_CBC_NO_PADDING: + mode = MBEDTLS_MODE_CBC; + break; + case PSA_ALG_CBC_PKCS7: + mode = MBEDTLS_MODE_CBC; + break; + case PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, 0 ): + mode = MBEDTLS_MODE_CCM; + break; + case PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_GCM, 0 ): + mode = MBEDTLS_MODE_GCM; + break; + case PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CHACHA20_POLY1305, 0 ): + mode = MBEDTLS_MODE_CHACHAPOLY; + break; + default: + return( NULL ); + } + } + else if( alg == PSA_ALG_CMAC ) + mode = MBEDTLS_MODE_ECB; + else + return( NULL ); + + switch( key_type ) + { + case PSA_KEY_TYPE_AES: + cipher_id_tmp = MBEDTLS_CIPHER_ID_AES; + break; + case PSA_KEY_TYPE_DES: + /* key_bits is 64 for Single-DES, 128 for two-key Triple-DES, + * and 192 for three-key Triple-DES. */ + if( key_bits == 64 ) + cipher_id_tmp = MBEDTLS_CIPHER_ID_DES; + else + cipher_id_tmp = MBEDTLS_CIPHER_ID_3DES; + /* mbedtls doesn't recognize two-key Triple-DES as an algorithm, + * but two-key Triple-DES is functionally three-key Triple-DES + * with K1=K3, so that's how we present it to mbedtls. */ + if( key_bits == 128 ) + key_bits = 192; + break; + case PSA_KEY_TYPE_CAMELLIA: + cipher_id_tmp = MBEDTLS_CIPHER_ID_CAMELLIA; + break; + case PSA_KEY_TYPE_ARC4: + cipher_id_tmp = MBEDTLS_CIPHER_ID_ARC4; + break; + case PSA_KEY_TYPE_CHACHA20: + cipher_id_tmp = MBEDTLS_CIPHER_ID_CHACHA20; + break; + default: + return( NULL ); + } + if( cipher_id != NULL ) + *cipher_id = cipher_id_tmp; + + return( mbedtls_cipher_info_from_values( cipher_id_tmp, + (int) key_bits, mode ) ); +} + +#if defined(MBEDTLS_MD_C) +static size_t psa_get_hash_block_size( psa_algorithm_t alg ) +{ + switch( alg ) + { + case PSA_ALG_MD2: + return( 16 ); + case PSA_ALG_MD4: + return( 64 ); + case PSA_ALG_MD5: + return( 64 ); + case PSA_ALG_RIPEMD160: + return( 64 ); + case PSA_ALG_SHA_1: + return( 64 ); + case PSA_ALG_SHA_224: + return( 64 ); + case PSA_ALG_SHA_256: + return( 64 ); + case PSA_ALG_SHA_384: + return( 128 ); + case PSA_ALG_SHA_512: + return( 128 ); + default: + return( 0 ); + } +} +#endif /* MBEDTLS_MD_C */ + +/* Initialize the MAC operation structure. Once this function has been + * called, psa_mac_abort can run and will do the right thing. */ +static psa_status_t psa_mac_init( psa_mac_operation_t *operation, + psa_algorithm_t alg ) +{ + psa_status_t status = PSA_ERROR_NOT_SUPPORTED; + + operation->alg = alg; + operation->key_set = 0; + operation->iv_set = 0; + operation->iv_required = 0; + operation->has_input = 0; + operation->is_sign = 0; + +#if defined(MBEDTLS_CMAC_C) + if( alg == PSA_ALG_CMAC ) + { + operation->iv_required = 0; + mbedtls_cipher_init( &operation->ctx.cmac ); + status = PSA_SUCCESS; + } + else +#endif /* MBEDTLS_CMAC_C */ +#if defined(MBEDTLS_MD_C) + if( PSA_ALG_IS_HMAC( operation->alg ) ) + { + /* We'll set up the hash operation later in psa_hmac_setup_internal. */ + operation->ctx.hmac.hash_ctx.alg = 0; + status = PSA_SUCCESS; + } + else +#endif /* MBEDTLS_MD_C */ + { + if( ! PSA_ALG_IS_MAC( alg ) ) + status = PSA_ERROR_INVALID_ARGUMENT; + } + + if( status != PSA_SUCCESS ) + memset( operation, 0, sizeof( *operation ) ); + return( status ); +} + +#if defined(MBEDTLS_MD_C) +static psa_status_t psa_hmac_abort_internal( psa_hmac_internal_data *hmac ) +{ + mbedtls_platform_zeroize( hmac->opad, sizeof( hmac->opad ) ); + return( psa_hash_abort( &hmac->hash_ctx ) ); +} +#endif /* MBEDTLS_MD_C */ + +psa_status_t psa_mac_abort( psa_mac_operation_t *operation ) +{ + if( operation->alg == 0 ) + { + /* The object has (apparently) been initialized but it is not + * in use. It's ok to call abort on such an object, and there's + * nothing to do. */ + return( PSA_SUCCESS ); + } + else +#if defined(MBEDTLS_CMAC_C) + if( operation->alg == PSA_ALG_CMAC ) + { + mbedtls_cipher_free( &operation->ctx.cmac ); + } + else +#endif /* MBEDTLS_CMAC_C */ +#if defined(MBEDTLS_MD_C) + if( PSA_ALG_IS_HMAC( operation->alg ) ) + { + psa_hmac_abort_internal( &operation->ctx.hmac ); + } + else +#endif /* MBEDTLS_MD_C */ + { + /* Sanity check (shouldn't happen: operation->alg should + * always have been initialized to a valid value). */ + goto bad_state; + } + + operation->alg = 0; + operation->key_set = 0; + operation->iv_set = 0; + operation->iv_required = 0; + operation->has_input = 0; + operation->is_sign = 0; + + return( PSA_SUCCESS ); + +bad_state: + /* If abort is called on an uninitialized object, we can't trust + * anything. Wipe the object in case it contains confidential data. + * This may result in a memory leak if a pointer gets overwritten, + * but it's too late to do anything about this. */ + memset( operation, 0, sizeof( *operation ) ); + return( PSA_ERROR_BAD_STATE ); +} + +#if defined(MBEDTLS_CMAC_C) +static int psa_cmac_setup( psa_mac_operation_t *operation, + size_t key_bits, + psa_key_slot_t *slot, + const mbedtls_cipher_info_t *cipher_info ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + operation->mac_size = cipher_info->block_size; + + ret = mbedtls_cipher_setup( &operation->ctx.cmac, cipher_info ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_cipher_cmac_starts( &operation->ctx.cmac, + slot->data.raw.data, + key_bits ); + return( ret ); +} +#endif /* MBEDTLS_CMAC_C */ + +#if defined(MBEDTLS_MD_C) +static psa_status_t psa_hmac_setup_internal( psa_hmac_internal_data *hmac, + const uint8_t *key, + size_t key_length, + psa_algorithm_t hash_alg ) +{ + uint8_t ipad[PSA_HMAC_MAX_HASH_BLOCK_SIZE]; + size_t i; + size_t hash_size = PSA_HASH_SIZE( hash_alg ); + size_t block_size = psa_get_hash_block_size( hash_alg ); + psa_status_t status; + + /* Sanity checks on block_size, to guarantee that there won't be a buffer + * overflow below. This should never trigger if the hash algorithm + * is implemented correctly. */ + /* The size checks against the ipad and opad buffers cannot be written + * `block_size > sizeof( ipad ) || block_size > sizeof( hmac->opad )` + * because that triggers -Wlogical-op on GCC 7.3. */ + if( block_size > sizeof( ipad ) ) + return( PSA_ERROR_NOT_SUPPORTED ); + if( block_size > sizeof( hmac->opad ) ) + return( PSA_ERROR_NOT_SUPPORTED ); + if( block_size < hash_size ) + return( PSA_ERROR_NOT_SUPPORTED ); + + if( key_length > block_size ) + { + status = psa_hash_compute( hash_alg, key, key_length, + ipad, sizeof( ipad ), &key_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + } + /* A 0-length key is not commonly used in HMAC when used as a MAC, + * but it is permitted. It is common when HMAC is used in HKDF, for + * example. Don't call `memcpy` in the 0-length because `key` could be + * an invalid pointer which would make the behavior undefined. */ + else if( key_length != 0 ) + memcpy( ipad, key, key_length ); + + /* ipad contains the key followed by garbage. Xor and fill with 0x36 + * to create the ipad value. */ + for( i = 0; i < key_length; i++ ) + ipad[i] ^= 0x36; + memset( ipad + key_length, 0x36, block_size - key_length ); + + /* Copy the key material from ipad to opad, flipping the requisite bits, + * and filling the rest of opad with the requisite constant. */ + for( i = 0; i < key_length; i++ ) + hmac->opad[i] = ipad[i] ^ 0x36 ^ 0x5C; + memset( hmac->opad + key_length, 0x5C, block_size - key_length ); + + status = psa_hash_setup( &hmac->hash_ctx, hash_alg ); + if( status != PSA_SUCCESS ) + goto cleanup; + + status = psa_hash_update( &hmac->hash_ctx, ipad, block_size ); + +cleanup: + mbedtls_platform_zeroize( ipad, sizeof(ipad) ); + + return( status ); +} +#endif /* MBEDTLS_MD_C */ + +static psa_status_t psa_mac_setup( psa_mac_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg, + int is_sign ) +{ + psa_status_t status; + psa_key_slot_t *slot; + size_t key_bits; + psa_key_usage_t usage = + is_sign ? PSA_KEY_USAGE_SIGN_HASH : PSA_KEY_USAGE_VERIFY_HASH; + uint8_t truncated = PSA_MAC_TRUNCATED_LENGTH( alg ); + psa_algorithm_t full_length_alg = PSA_ALG_FULL_LENGTH_MAC( alg ); + + /* A context must be freshly initialized before it can be set up. */ + if( operation->alg != 0 ) + { + return( PSA_ERROR_BAD_STATE ); + } + + status = psa_mac_init( operation, full_length_alg ); + if( status != PSA_SUCCESS ) + return( status ); + if( is_sign ) + operation->is_sign = 1; + + status = psa_get_transparent_key( handle, &slot, usage, alg ); + if( status != PSA_SUCCESS ) + goto exit; + key_bits = psa_get_key_slot_bits( slot ); + +#if defined(MBEDTLS_CMAC_C) + if( full_length_alg == PSA_ALG_CMAC ) + { + const mbedtls_cipher_info_t *cipher_info = + mbedtls_cipher_info_from_psa( full_length_alg, + slot->attr.type, key_bits, NULL ); + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + if( cipher_info == NULL ) + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + operation->mac_size = cipher_info->block_size; + ret = psa_cmac_setup( operation, key_bits, slot, cipher_info ); + status = mbedtls_to_psa_error( ret ); + } + else +#endif /* MBEDTLS_CMAC_C */ +#if defined(MBEDTLS_MD_C) + if( PSA_ALG_IS_HMAC( full_length_alg ) ) + { + psa_algorithm_t hash_alg = PSA_ALG_HMAC_GET_HASH( alg ); + if( hash_alg == 0 ) + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + + operation->mac_size = PSA_HASH_SIZE( hash_alg ); + /* Sanity check. This shouldn't fail on a valid configuration. */ + if( operation->mac_size == 0 || + operation->mac_size > sizeof( operation->ctx.hmac.opad ) ) + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + + if( slot->attr.type != PSA_KEY_TYPE_HMAC ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + status = psa_hmac_setup_internal( &operation->ctx.hmac, + slot->data.raw.data, + slot->data.raw.bytes, + hash_alg ); + } + else +#endif /* MBEDTLS_MD_C */ + { + (void) key_bits; + status = PSA_ERROR_NOT_SUPPORTED; + } + + if( truncated == 0 ) + { + /* The "normal" case: untruncated algorithm. Nothing to do. */ + } + else if( truncated < 4 ) + { + /* A very short MAC is too short for security since it can be + * brute-forced. Ancient protocols with 32-bit MACs do exist, + * so we make this our minimum, even though 32 bits is still + * too small for security. */ + status = PSA_ERROR_NOT_SUPPORTED; + } + else if( truncated > operation->mac_size ) + { + /* It's impossible to "truncate" to a larger length. */ + status = PSA_ERROR_INVALID_ARGUMENT; + } + else + operation->mac_size = truncated; + +exit: + if( status != PSA_SUCCESS ) + { + psa_mac_abort( operation ); + } + else + { + operation->key_set = 1; + } + return( status ); +} + +psa_status_t psa_mac_sign_setup( psa_mac_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg ) +{ + return( psa_mac_setup( operation, handle, alg, 1 ) ); +} + +psa_status_t psa_mac_verify_setup( psa_mac_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg ) +{ + return( psa_mac_setup( operation, handle, alg, 0 ) ); +} + +psa_status_t psa_mac_update( psa_mac_operation_t *operation, + const uint8_t *input, + size_t input_length ) +{ + psa_status_t status = PSA_ERROR_BAD_STATE; + if( ! operation->key_set ) + return( PSA_ERROR_BAD_STATE ); + if( operation->iv_required && ! operation->iv_set ) + return( PSA_ERROR_BAD_STATE ); + operation->has_input = 1; + +#if defined(MBEDTLS_CMAC_C) + if( operation->alg == PSA_ALG_CMAC ) + { + int ret = mbedtls_cipher_cmac_update( &operation->ctx.cmac, + input, input_length ); + status = mbedtls_to_psa_error( ret ); + } + else +#endif /* MBEDTLS_CMAC_C */ +#if defined(MBEDTLS_MD_C) + if( PSA_ALG_IS_HMAC( operation->alg ) ) + { + status = psa_hash_update( &operation->ctx.hmac.hash_ctx, input, + input_length ); + } + else +#endif /* MBEDTLS_MD_C */ + { + /* This shouldn't happen if `operation` was initialized by + * a setup function. */ + return( PSA_ERROR_BAD_STATE ); + } + + if( status != PSA_SUCCESS ) + psa_mac_abort( operation ); + return( status ); +} + +#if defined(MBEDTLS_MD_C) +static psa_status_t psa_hmac_finish_internal( psa_hmac_internal_data *hmac, + uint8_t *mac, + size_t mac_size ) +{ + uint8_t tmp[MBEDTLS_MD_MAX_SIZE]; + psa_algorithm_t hash_alg = hmac->hash_ctx.alg; + size_t hash_size = 0; + size_t block_size = psa_get_hash_block_size( hash_alg ); + psa_status_t status; + + status = psa_hash_finish( &hmac->hash_ctx, tmp, sizeof( tmp ), &hash_size ); + if( status != PSA_SUCCESS ) + return( status ); + /* From here on, tmp needs to be wiped. */ + + status = psa_hash_setup( &hmac->hash_ctx, hash_alg ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_hash_update( &hmac->hash_ctx, hmac->opad, block_size ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_hash_update( &hmac->hash_ctx, tmp, hash_size ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_hash_finish( &hmac->hash_ctx, tmp, sizeof( tmp ), &hash_size ); + if( status != PSA_SUCCESS ) + goto exit; + + memcpy( mac, tmp, mac_size ); + +exit: + mbedtls_platform_zeroize( tmp, hash_size ); + return( status ); +} +#endif /* MBEDTLS_MD_C */ + +static psa_status_t psa_mac_finish_internal( psa_mac_operation_t *operation, + uint8_t *mac, + size_t mac_size ) +{ + if( ! operation->key_set ) + return( PSA_ERROR_BAD_STATE ); + if( operation->iv_required && ! operation->iv_set ) + return( PSA_ERROR_BAD_STATE ); + + if( mac_size < operation->mac_size ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + +#if defined(MBEDTLS_CMAC_C) + if( operation->alg == PSA_ALG_CMAC ) + { + uint8_t tmp[PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE]; + int ret = mbedtls_cipher_cmac_finish( &operation->ctx.cmac, tmp ); + if( ret == 0 ) + memcpy( mac, tmp, operation->mac_size ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + return( mbedtls_to_psa_error( ret ) ); + } + else +#endif /* MBEDTLS_CMAC_C */ +#if defined(MBEDTLS_MD_C) + if( PSA_ALG_IS_HMAC( operation->alg ) ) + { + return( psa_hmac_finish_internal( &operation->ctx.hmac, + mac, operation->mac_size ) ); + } + else +#endif /* MBEDTLS_MD_C */ + { + /* This shouldn't happen if `operation` was initialized by + * a setup function. */ + return( PSA_ERROR_BAD_STATE ); + } +} + +psa_status_t psa_mac_sign_finish( psa_mac_operation_t *operation, + uint8_t *mac, + size_t mac_size, + size_t *mac_length ) +{ + psa_status_t status; + + if( operation->alg == 0 ) + { + return( PSA_ERROR_BAD_STATE ); + } + + /* Fill the output buffer with something that isn't a valid mac + * (barring an attack on the mac and deliberately-crafted input), + * in case the caller doesn't check the return status properly. */ + *mac_length = mac_size; + /* If mac_size is 0 then mac may be NULL and then the + * call to memset would have undefined behavior. */ + if( mac_size != 0 ) + memset( mac, '!', mac_size ); + + if( ! operation->is_sign ) + { + return( PSA_ERROR_BAD_STATE ); + } + + status = psa_mac_finish_internal( operation, mac, mac_size ); + + if( status == PSA_SUCCESS ) + { + status = psa_mac_abort( operation ); + if( status == PSA_SUCCESS ) + *mac_length = operation->mac_size; + else + memset( mac, '!', mac_size ); + } + else + psa_mac_abort( operation ); + return( status ); +} + +psa_status_t psa_mac_verify_finish( psa_mac_operation_t *operation, + const uint8_t *mac, + size_t mac_length ) +{ + uint8_t actual_mac[PSA_MAC_MAX_SIZE]; + psa_status_t status; + + if( operation->alg == 0 ) + { + return( PSA_ERROR_BAD_STATE ); + } + + if( operation->is_sign ) + { + return( PSA_ERROR_BAD_STATE ); + } + if( operation->mac_size != mac_length ) + { + status = PSA_ERROR_INVALID_SIGNATURE; + goto cleanup; + } + + status = psa_mac_finish_internal( operation, + actual_mac, sizeof( actual_mac ) ); + if( status != PSA_SUCCESS ) + goto cleanup; + + if( safer_memcmp( mac, actual_mac, mac_length ) != 0 ) + status = PSA_ERROR_INVALID_SIGNATURE; + +cleanup: + if( status == PSA_SUCCESS ) + status = psa_mac_abort( operation ); + else + psa_mac_abort( operation ); + + mbedtls_platform_zeroize( actual_mac, sizeof( actual_mac ) ); + + return( status ); +} + + + +/****************************************************************/ +/* Asymmetric cryptography */ +/****************************************************************/ + +#if defined(MBEDTLS_RSA_C) +/* Decode the hash algorithm from alg and store the mbedtls encoding in + * md_alg. Verify that the hash length is acceptable. */ +static psa_status_t psa_rsa_decode_md_type( psa_algorithm_t alg, + size_t hash_length, + mbedtls_md_type_t *md_alg ) +{ + psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg ); + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_psa( hash_alg ); + *md_alg = mbedtls_md_get_type( md_info ); + + /* The Mbed TLS RSA module uses an unsigned int for hash length + * parameters. Validate that it fits so that we don't risk an + * overflow later. */ +#if SIZE_MAX > UINT_MAX + if( hash_length > UINT_MAX ) + return( PSA_ERROR_INVALID_ARGUMENT ); +#endif + +#if defined(MBEDTLS_PKCS1_V15) + /* For PKCS#1 v1.5 signature, if using a hash, the hash length + * must be correct. */ + if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) && + alg != PSA_ALG_RSA_PKCS1V15_SIGN_RAW ) + { + if( md_info == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + if( mbedtls_md_get_size( md_info ) != hash_length ) + return( PSA_ERROR_INVALID_ARGUMENT ); + } +#endif /* MBEDTLS_PKCS1_V15 */ + +#if defined(MBEDTLS_PKCS1_V21) + /* PSS requires a hash internally. */ + if( PSA_ALG_IS_RSA_PSS( alg ) ) + { + if( md_info == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + } +#endif /* MBEDTLS_PKCS1_V21 */ + + return( PSA_SUCCESS ); +} + +static psa_status_t psa_rsa_sign( mbedtls_rsa_context *rsa, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length ) +{ + psa_status_t status; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md_type_t md_alg; + + status = psa_rsa_decode_md_type( alg, hash_length, &md_alg ); + if( status != PSA_SUCCESS ) + return( status ); + + if( signature_size < mbedtls_rsa_get_len( rsa ) ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + +#if defined(MBEDTLS_PKCS1_V15) + if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) ) + { + mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V15, + MBEDTLS_MD_NONE ); + ret = mbedtls_rsa_pkcs1_sign( rsa, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg, + MBEDTLS_RSA_PRIVATE, + md_alg, + (unsigned int) hash_length, + hash, + signature ); + } + else +#endif /* MBEDTLS_PKCS1_V15 */ +#if defined(MBEDTLS_PKCS1_V21) + if( PSA_ALG_IS_RSA_PSS( alg ) ) + { + mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V21, md_alg ); + ret = mbedtls_rsa_rsassa_pss_sign( rsa, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg, + MBEDTLS_RSA_PRIVATE, + MBEDTLS_MD_NONE, + (unsigned int) hash_length, + hash, + signature ); + } + else +#endif /* MBEDTLS_PKCS1_V21 */ + { + return( PSA_ERROR_INVALID_ARGUMENT ); + } + + if( ret == 0 ) + *signature_length = mbedtls_rsa_get_len( rsa ); + return( mbedtls_to_psa_error( ret ) ); +} + +static psa_status_t psa_rsa_verify( mbedtls_rsa_context *rsa, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length ) +{ + psa_status_t status; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md_type_t md_alg; + + status = psa_rsa_decode_md_type( alg, hash_length, &md_alg ); + if( status != PSA_SUCCESS ) + return( status ); + + if( signature_length != mbedtls_rsa_get_len( rsa ) ) + return( PSA_ERROR_INVALID_SIGNATURE ); + +#if defined(MBEDTLS_PKCS1_V15) + if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) ) + { + mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V15, + MBEDTLS_MD_NONE ); + ret = mbedtls_rsa_pkcs1_verify( rsa, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg, + MBEDTLS_RSA_PUBLIC, + md_alg, + (unsigned int) hash_length, + hash, + signature ); + } + else +#endif /* MBEDTLS_PKCS1_V15 */ +#if defined(MBEDTLS_PKCS1_V21) + if( PSA_ALG_IS_RSA_PSS( alg ) ) + { + mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V21, md_alg ); + ret = mbedtls_rsa_rsassa_pss_verify( rsa, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg, + MBEDTLS_RSA_PUBLIC, + MBEDTLS_MD_NONE, + (unsigned int) hash_length, + hash, + signature ); + } + else +#endif /* MBEDTLS_PKCS1_V21 */ + { + return( PSA_ERROR_INVALID_ARGUMENT ); + } + + /* Mbed TLS distinguishes "invalid padding" from "valid padding but + * the rest of the signature is invalid". This has little use in + * practice and PSA doesn't report this distinction. */ + if( ret == MBEDTLS_ERR_RSA_INVALID_PADDING ) + return( PSA_ERROR_INVALID_SIGNATURE ); + return( mbedtls_to_psa_error( ret ) ); +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECDSA_C) +/* `ecp` cannot be const because `ecp->grp` needs to be non-const + * for mbedtls_ecdsa_sign() and mbedtls_ecdsa_sign_det() + * (even though these functions don't modify it). */ +static psa_status_t psa_ecdsa_sign( mbedtls_ecp_keypair *ecp, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi r, s; + size_t curve_bytes = PSA_BITS_TO_BYTES( ecp->grp.pbits ); + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &s ); + + if( signature_size < 2 * curve_bytes ) + { + ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + goto cleanup; + } + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + if( PSA_ALG_DSA_IS_DETERMINISTIC( alg ) ) + { + psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg ); + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_psa( hash_alg ); + mbedtls_md_type_t md_alg = mbedtls_md_get_type( md_info ); + MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det_ext( &ecp->grp, &r, &s, + &ecp->d, hash, + hash_length, md_alg, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg ) ); + } + else +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + { + (void) alg; + MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ecp->grp, &r, &s, &ecp->d, + hash, hash_length, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &r, + signature, + curve_bytes ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &s, + signature + curve_bytes, + curve_bytes ) ); + +cleanup: + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &s ); + if( ret == 0 ) + *signature_length = 2 * curve_bytes; + return( mbedtls_to_psa_error( ret ) ); +} + +static psa_status_t psa_ecdsa_verify( mbedtls_ecp_keypair *ecp, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi r, s; + size_t curve_bytes = PSA_BITS_TO_BYTES( ecp->grp.pbits ); + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &s ); + + if( signature_length != 2 * curve_bytes ) + return( PSA_ERROR_INVALID_SIGNATURE ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, + signature, + curve_bytes ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &s, + signature + curve_bytes, + curve_bytes ) ); + + ret = mbedtls_ecdsa_verify( &ecp->grp, hash, hash_length, + &ecp->Q, &r, &s ); + +cleanup: + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &s ); + return( mbedtls_to_psa_error( ret ) ); +} +#endif /* MBEDTLS_ECDSA_C */ + +psa_status_t psa_sign_hash( psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length ) +{ + psa_key_slot_t *slot; + psa_status_t status; +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + *signature_length = signature_size; + /* Immediately reject a zero-length signature buffer. This guarantees + * that signature must be a valid pointer. (On the other hand, the hash + * buffer can in principle be empty since it doesn't actually have + * to be a hash.) */ + if( signature_size == 0 ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + + status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_SIGN_HASH, alg ); + if( status != PSA_SUCCESS ) + goto exit; + if( ! PSA_KEY_TYPE_IS_KEY_PAIR( slot->attr.type ) ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) ) + { + if( drv->asymmetric == NULL || + drv->asymmetric->p_sign == NULL ) + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + status = drv->asymmetric->p_sign( drv_context, + slot->data.se.slot_number, + alg, + hash, hash_length, + signature, signature_size, + signature_length ); + } + else +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ +#if defined(MBEDTLS_RSA_C) + if( slot->attr.type == PSA_KEY_TYPE_RSA_KEY_PAIR ) + { + status = psa_rsa_sign( slot->data.rsa, + alg, + hash, hash_length, + signature, signature_size, + signature_length ); + } + else +#endif /* defined(MBEDTLS_RSA_C) */ +#if defined(MBEDTLS_ECP_C) + if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) + { +#if defined(MBEDTLS_ECDSA_C) + if( +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + PSA_ALG_IS_ECDSA( alg ) +#else + PSA_ALG_IS_RANDOMIZED_ECDSA( alg ) +#endif + ) + status = psa_ecdsa_sign( slot->data.ecp, + alg, + hash, hash_length, + signature, signature_size, + signature_length ); + else +#endif /* defined(MBEDTLS_ECDSA_C) */ + { + status = PSA_ERROR_INVALID_ARGUMENT; + } + } + else +#endif /* defined(MBEDTLS_ECP_C) */ + { + status = PSA_ERROR_NOT_SUPPORTED; + } + +exit: + /* Fill the unused part of the output buffer (the whole buffer on error, + * the trailing part on success) with something that isn't a valid mac + * (barring an attack on the mac and deliberately-crafted input), + * in case the caller doesn't check the return status properly. */ + if( status == PSA_SUCCESS ) + memset( signature + *signature_length, '!', + signature_size - *signature_length ); + else + memset( signature, '!', signature_size ); + /* If signature_size is 0 then we have nothing to do. We must not call + * memset because signature may be NULL in this case. */ + return( status ); +} + +psa_status_t psa_verify_hash( psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length ) +{ + psa_key_slot_t *slot; + psa_status_t status; +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_VERIFY_HASH, alg ); + if( status != PSA_SUCCESS ) + return( status ); + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) ) + { + if( drv->asymmetric == NULL || + drv->asymmetric->p_verify == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + return( drv->asymmetric->p_verify( drv_context, + slot->data.se.slot_number, + alg, + hash, hash_length, + signature, signature_length ) ); + } + else +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ +#if defined(MBEDTLS_RSA_C) + if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) + { + return( psa_rsa_verify( slot->data.rsa, + alg, + hash, hash_length, + signature, signature_length ) ); + } + else +#endif /* defined(MBEDTLS_RSA_C) */ +#if defined(MBEDTLS_ECP_C) + if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) + { +#if defined(MBEDTLS_ECDSA_C) + if( PSA_ALG_IS_ECDSA( alg ) ) + return( psa_ecdsa_verify( slot->data.ecp, + hash, hash_length, + signature, signature_length ) ); + else +#endif /* defined(MBEDTLS_ECDSA_C) */ + { + return( PSA_ERROR_INVALID_ARGUMENT ); + } + } + else +#endif /* defined(MBEDTLS_ECP_C) */ + { + return( PSA_ERROR_NOT_SUPPORTED ); + } +} + +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) +static void psa_rsa_oaep_set_padding_mode( psa_algorithm_t alg, + mbedtls_rsa_context *rsa ) +{ + psa_algorithm_t hash_alg = PSA_ALG_RSA_OAEP_GET_HASH( alg ); + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_psa( hash_alg ); + mbedtls_md_type_t md_alg = mbedtls_md_get_type( md_info ); + mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V21, md_alg ); +} +#endif /* defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) */ + +psa_status_t psa_asymmetric_encrypt( psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ + psa_key_slot_t *slot; + psa_status_t status; + + (void) input; + (void) input_length; + (void) salt; + (void) output; + (void) output_size; + + *output_length = 0; + + if( ! PSA_ALG_IS_RSA_OAEP( alg ) && salt_length != 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + status = psa_get_transparent_key( handle, &slot, PSA_KEY_USAGE_ENCRYPT, alg ); + if( status != PSA_SUCCESS ) + return( status ); + if( ! ( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->attr.type ) || + PSA_KEY_TYPE_IS_KEY_PAIR( slot->attr.type ) ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + +#if defined(MBEDTLS_RSA_C) + if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) + { + mbedtls_rsa_context *rsa = slot->data.rsa; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + if( output_size < mbedtls_rsa_get_len( rsa ) ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); +#if defined(MBEDTLS_PKCS1_V15) + if( alg == PSA_ALG_RSA_PKCS1V15_CRYPT ) + { + ret = mbedtls_rsa_pkcs1_encrypt( rsa, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg, + MBEDTLS_RSA_PUBLIC, + input_length, + input, + output ); + } + else +#endif /* MBEDTLS_PKCS1_V15 */ +#if defined(MBEDTLS_PKCS1_V21) + if( PSA_ALG_IS_RSA_OAEP( alg ) ) + { + psa_rsa_oaep_set_padding_mode( alg, rsa ); + ret = mbedtls_rsa_rsaes_oaep_encrypt( rsa, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg, + MBEDTLS_RSA_PUBLIC, + salt, salt_length, + input_length, + input, + output ); + } + else +#endif /* MBEDTLS_PKCS1_V21 */ + { + return( PSA_ERROR_INVALID_ARGUMENT ); + } + if( ret == 0 ) + *output_length = mbedtls_rsa_get_len( rsa ); + return( mbedtls_to_psa_error( ret ) ); + } + else +#endif /* defined(MBEDTLS_RSA_C) */ + { + return( PSA_ERROR_NOT_SUPPORTED ); + } +} + +psa_status_t psa_asymmetric_decrypt( psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ + psa_key_slot_t *slot; + psa_status_t status; + + (void) input; + (void) input_length; + (void) salt; + (void) output; + (void) output_size; + + *output_length = 0; + + if( ! PSA_ALG_IS_RSA_OAEP( alg ) && salt_length != 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + status = psa_get_transparent_key( handle, &slot, PSA_KEY_USAGE_DECRYPT, alg ); + if( status != PSA_SUCCESS ) + return( status ); + if( ! PSA_KEY_TYPE_IS_KEY_PAIR( slot->attr.type ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + +#if defined(MBEDTLS_RSA_C) + if( slot->attr.type == PSA_KEY_TYPE_RSA_KEY_PAIR ) + { + mbedtls_rsa_context *rsa = slot->data.rsa; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( input_length != mbedtls_rsa_get_len( rsa ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + +#if defined(MBEDTLS_PKCS1_V15) + if( alg == PSA_ALG_RSA_PKCS1V15_CRYPT ) + { + ret = mbedtls_rsa_pkcs1_decrypt( rsa, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg, + MBEDTLS_RSA_PRIVATE, + output_length, + input, + output, + output_size ); + } + else +#endif /* MBEDTLS_PKCS1_V15 */ +#if defined(MBEDTLS_PKCS1_V21) + if( PSA_ALG_IS_RSA_OAEP( alg ) ) + { + psa_rsa_oaep_set_padding_mode( alg, rsa ); + ret = mbedtls_rsa_rsaes_oaep_decrypt( rsa, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg, + MBEDTLS_RSA_PRIVATE, + salt, salt_length, + output_length, + input, + output, + output_size ); + } + else +#endif /* MBEDTLS_PKCS1_V21 */ + { + return( PSA_ERROR_INVALID_ARGUMENT ); + } + + return( mbedtls_to_psa_error( ret ) ); + } + else +#endif /* defined(MBEDTLS_RSA_C) */ + { + return( PSA_ERROR_NOT_SUPPORTED ); + } +} + + + +/****************************************************************/ +/* Symmetric cryptography */ +/****************************************************************/ + +/* Initialize the cipher operation structure. Once this function has been + * called, psa_cipher_abort can run and will do the right thing. */ +static psa_status_t psa_cipher_init( psa_cipher_operation_t *operation, + psa_algorithm_t alg ) +{ + if( ! PSA_ALG_IS_CIPHER( alg ) ) + { + memset( operation, 0, sizeof( *operation ) ); + return( PSA_ERROR_INVALID_ARGUMENT ); + } + + operation->alg = alg; + operation->key_set = 0; + operation->iv_set = 0; + operation->iv_required = 1; + operation->iv_size = 0; + operation->block_size = 0; + mbedtls_cipher_init( &operation->ctx.cipher ); + return( PSA_SUCCESS ); +} + +static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg, + mbedtls_operation_t cipher_operation ) +{ + int ret = 0; + psa_status_t status = PSA_ERROR_GENERIC_ERROR; + psa_key_slot_t *slot; + size_t key_bits; + const mbedtls_cipher_info_t *cipher_info = NULL; + psa_key_usage_t usage = ( cipher_operation == MBEDTLS_ENCRYPT ? + PSA_KEY_USAGE_ENCRYPT : + PSA_KEY_USAGE_DECRYPT ); + + /* A context must be freshly initialized before it can be set up. */ + if( operation->alg != 0 ) + { + return( PSA_ERROR_BAD_STATE ); + } + + status = psa_cipher_init( operation, alg ); + if( status != PSA_SUCCESS ) + return( status ); + + status = psa_get_transparent_key( handle, &slot, usage, alg); + if( status != PSA_SUCCESS ) + goto exit; + key_bits = psa_get_key_slot_bits( slot ); + + cipher_info = mbedtls_cipher_info_from_psa( alg, slot->attr.type, key_bits, NULL ); + if( cipher_info == NULL ) + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + + ret = mbedtls_cipher_setup( &operation->ctx.cipher, cipher_info ); + if( ret != 0 ) + goto exit; + +#if defined(MBEDTLS_DES_C) + if( slot->attr.type == PSA_KEY_TYPE_DES && key_bits == 128 ) + { + /* Two-key Triple-DES is 3-key Triple-DES with K1=K3 */ + uint8_t keys[24]; + memcpy( keys, slot->data.raw.data, 16 ); + memcpy( keys + 16, slot->data.raw.data, 8 ); + ret = mbedtls_cipher_setkey( &operation->ctx.cipher, + keys, + 192, cipher_operation ); + } + else +#endif + { + ret = mbedtls_cipher_setkey( &operation->ctx.cipher, + slot->data.raw.data, + (int) key_bits, cipher_operation ); + } + if( ret != 0 ) + goto exit; + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) + switch( alg ) + { + case PSA_ALG_CBC_NO_PADDING: + ret = mbedtls_cipher_set_padding_mode( &operation->ctx.cipher, + MBEDTLS_PADDING_NONE ); + break; + case PSA_ALG_CBC_PKCS7: + ret = mbedtls_cipher_set_padding_mode( &operation->ctx.cipher, + MBEDTLS_PADDING_PKCS7 ); + break; + default: + /* The algorithm doesn't involve padding. */ + ret = 0; + break; + } + if( ret != 0 ) + goto exit; +#endif //MBEDTLS_CIPHER_MODE_WITH_PADDING + + operation->key_set = 1; + operation->block_size = ( PSA_ALG_IS_STREAM_CIPHER( alg ) ? 1 : + PSA_BLOCK_CIPHER_BLOCK_SIZE( slot->attr.type ) ); + if( alg & PSA_ALG_CIPHER_FROM_BLOCK_FLAG ) + { + operation->iv_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( slot->attr.type ); + } +#if defined(MBEDTLS_CHACHA20_C) + else + if( alg == PSA_ALG_CHACHA20 ) + operation->iv_size = 12; +#endif + +exit: + if( status == 0 ) + status = mbedtls_to_psa_error( ret ); + if( status != 0 ) + psa_cipher_abort( operation ); + return( status ); +} + +psa_status_t psa_cipher_encrypt_setup( psa_cipher_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg ) +{ + return( psa_cipher_setup( operation, handle, alg, MBEDTLS_ENCRYPT ) ); +} + +psa_status_t psa_cipher_decrypt_setup( psa_cipher_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg ) +{ + return( psa_cipher_setup( operation, handle, alg, MBEDTLS_DECRYPT ) ); +} + +psa_status_t psa_cipher_generate_iv( psa_cipher_operation_t *operation, + uint8_t *iv, + size_t iv_size, + size_t *iv_length ) +{ + psa_status_t status; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + if( operation->iv_set || ! operation->iv_required ) + { + return( PSA_ERROR_BAD_STATE ); + } + if( iv_size < operation->iv_size ) + { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + ret = mbedtls_ctr_drbg_random( &global_data.ctr_drbg, + iv, operation->iv_size ); + if( ret != 0 ) + { + status = mbedtls_to_psa_error( ret ); + goto exit; + } + + *iv_length = operation->iv_size; + status = psa_cipher_set_iv( operation, iv, *iv_length ); + +exit: + if( status != PSA_SUCCESS ) + psa_cipher_abort( operation ); + return( status ); +} + +psa_status_t psa_cipher_set_iv( psa_cipher_operation_t *operation, + const uint8_t *iv, + size_t iv_length ) +{ + psa_status_t status; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + if( operation->iv_set || ! operation->iv_required ) + { + return( PSA_ERROR_BAD_STATE ); + } + if( iv_length != operation->iv_size ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + ret = mbedtls_cipher_set_iv( &operation->ctx.cipher, iv, iv_length ); + status = mbedtls_to_psa_error( ret ); +exit: + if( status == PSA_SUCCESS ) + operation->iv_set = 1; + else + psa_cipher_abort( operation ); + return( status ); +} + +psa_status_t psa_cipher_update( psa_cipher_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 status; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t expected_output_size; + + if( operation->alg == 0 ) + { + return( PSA_ERROR_BAD_STATE ); + } + + if( ! PSA_ALG_IS_STREAM_CIPHER( operation->alg ) ) + { + /* Take the unprocessed partial block left over from previous + * update calls, if any, plus the input to this call. Remove + * the last partial block, if any. You get the data that will be + * output in this call. */ + expected_output_size = + ( operation->ctx.cipher.unprocessed_len + input_length ) + / operation->block_size * operation->block_size; + } + else + { + expected_output_size = input_length; + } + + if( output_size < expected_output_size ) + { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + + ret = mbedtls_cipher_update( &operation->ctx.cipher, input, + input_length, output, output_length ); + status = mbedtls_to_psa_error( ret ); +exit: + if( status != PSA_SUCCESS ) + psa_cipher_abort( operation ); + return( status ); +} + +psa_status_t psa_cipher_finish( psa_cipher_operation_t *operation, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ + psa_status_t status = PSA_ERROR_GENERIC_ERROR; + int cipher_ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH]; + + if( ! operation->key_set ) + { + return( PSA_ERROR_BAD_STATE ); + } + if( operation->iv_required && ! operation->iv_set ) + { + return( PSA_ERROR_BAD_STATE ); + } + + if( operation->ctx.cipher.operation == MBEDTLS_ENCRYPT && + operation->alg == PSA_ALG_CBC_NO_PADDING && + operation->ctx.cipher.unprocessed_len != 0 ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto error; + } + + cipher_ret = mbedtls_cipher_finish( &operation->ctx.cipher, + temp_output_buffer, + output_length ); + if( cipher_ret != 0 ) + { + status = mbedtls_to_psa_error( cipher_ret ); + goto error; + } + + if( *output_length == 0 ) + ; /* Nothing to copy. Note that output may be NULL in this case. */ + else if( output_size >= *output_length ) + memcpy( output, temp_output_buffer, *output_length ); + else + { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto error; + } + + mbedtls_platform_zeroize( temp_output_buffer, sizeof( temp_output_buffer ) ); + status = psa_cipher_abort( operation ); + + return( status ); + +error: + + *output_length = 0; + + mbedtls_platform_zeroize( temp_output_buffer, sizeof( temp_output_buffer ) ); + (void) psa_cipher_abort( operation ); + + return( status ); +} + +psa_status_t psa_cipher_abort( psa_cipher_operation_t *operation ) +{ + if( operation->alg == 0 ) + { + /* The object has (apparently) been initialized but it is not + * in use. It's ok to call abort on such an object, and there's + * nothing to do. */ + return( PSA_SUCCESS ); + } + + /* Sanity check (shouldn't happen: operation->alg should + * always have been initialized to a valid value). */ + if( ! PSA_ALG_IS_CIPHER( operation->alg ) ) + return( PSA_ERROR_BAD_STATE ); + + mbedtls_cipher_free( &operation->ctx.cipher ); + + operation->alg = 0; + operation->key_set = 0; + operation->iv_set = 0; + operation->iv_size = 0; + operation->block_size = 0; + operation->iv_required = 0; + + return( PSA_SUCCESS ); +} + + + + +/****************************************************************/ +/* AEAD */ +/****************************************************************/ + +typedef struct +{ + psa_key_slot_t *slot; + const mbedtls_cipher_info_t *cipher_info; + union + { +#if defined(MBEDTLS_CCM_C) + mbedtls_ccm_context ccm; +#endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_GCM_C) + mbedtls_gcm_context gcm; +#endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) + mbedtls_chachapoly_context chachapoly; +#endif /* MBEDTLS_CHACHAPOLY_C */ + } ctx; + psa_algorithm_t core_alg; + uint8_t full_tag_length; + uint8_t tag_length; +} aead_operation_t; + +static void psa_aead_abort_internal( aead_operation_t *operation ) +{ + switch( operation->core_alg ) + { +#if defined(MBEDTLS_CCM_C) + case PSA_ALG_CCM: + mbedtls_ccm_free( &operation->ctx.ccm ); + break; +#endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_GCM_C) + case PSA_ALG_GCM: + mbedtls_gcm_free( &operation->ctx.gcm ); + break; +#endif /* MBEDTLS_GCM_C */ + } +} + +static psa_status_t psa_aead_setup( aead_operation_t *operation, + psa_key_handle_t handle, + psa_key_usage_t usage, + psa_algorithm_t alg ) +{ + psa_status_t status; + size_t key_bits; + mbedtls_cipher_id_t cipher_id; + + status = psa_get_transparent_key( handle, &operation->slot, usage, alg ); + if( status != PSA_SUCCESS ) + return( status ); + + key_bits = psa_get_key_slot_bits( operation->slot ); + + operation->cipher_info = + mbedtls_cipher_info_from_psa( alg, operation->slot->attr.type, key_bits, + &cipher_id ); + if( operation->cipher_info == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + + switch( PSA_ALG_AEAD_WITH_TAG_LENGTH( alg, 0 ) ) + { +#if defined(MBEDTLS_CCM_C) + case PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, 0 ): + operation->core_alg = PSA_ALG_CCM; + operation->full_tag_length = 16; + /* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16. + * The call to mbedtls_ccm_encrypt_and_tag or + * mbedtls_ccm_auth_decrypt will validate the tag length. */ + if( PSA_BLOCK_CIPHER_BLOCK_SIZE( operation->slot->attr.type ) != 16 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + mbedtls_ccm_init( &operation->ctx.ccm ); + status = mbedtls_to_psa_error( + mbedtls_ccm_setkey( &operation->ctx.ccm, cipher_id, + operation->slot->data.raw.data, + (unsigned int) key_bits ) ); + if( status != 0 ) + goto cleanup; + break; +#endif /* MBEDTLS_CCM_C */ + +#if defined(MBEDTLS_GCM_C) + case PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_GCM, 0 ): + operation->core_alg = PSA_ALG_GCM; + operation->full_tag_length = 16; + /* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16. + * The call to mbedtls_gcm_crypt_and_tag or + * mbedtls_gcm_auth_decrypt will validate the tag length. */ + if( PSA_BLOCK_CIPHER_BLOCK_SIZE( operation->slot->attr.type ) != 16 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + mbedtls_gcm_init( &operation->ctx.gcm ); + status = mbedtls_to_psa_error( + mbedtls_gcm_setkey( &operation->ctx.gcm, cipher_id, + operation->slot->data.raw.data, + (unsigned int) key_bits ) ); + if( status != 0 ) + goto cleanup; + break; +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CHACHAPOLY_C) + case PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CHACHA20_POLY1305, 0 ): + operation->core_alg = PSA_ALG_CHACHA20_POLY1305; + operation->full_tag_length = 16; + /* We only support the default tag length. */ + if( alg != PSA_ALG_CHACHA20_POLY1305 ) + return( PSA_ERROR_NOT_SUPPORTED ); + mbedtls_chachapoly_init( &operation->ctx.chachapoly ); + status = mbedtls_to_psa_error( + mbedtls_chachapoly_setkey( &operation->ctx.chachapoly, + operation->slot->data.raw.data ) ); + if( status != 0 ) + goto cleanup; + break; +#endif /* MBEDTLS_CHACHAPOLY_C */ + + default: + return( PSA_ERROR_NOT_SUPPORTED ); + } + + if( PSA_AEAD_TAG_LENGTH( alg ) > operation->full_tag_length ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto cleanup; + } + operation->tag_length = PSA_AEAD_TAG_LENGTH( alg ); + + return( PSA_SUCCESS ); + +cleanup: + psa_aead_abort_internal( operation ); + return( status ); +} + +psa_status_t psa_aead_encrypt( psa_key_handle_t handle, + 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 *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length ) +{ + psa_status_t status; + aead_operation_t operation; + uint8_t *tag; + + *ciphertext_length = 0; + + status = psa_aead_setup( &operation, handle, PSA_KEY_USAGE_ENCRYPT, alg ); + if( status != PSA_SUCCESS ) + return( status ); + + /* For all currently supported modes, the tag is at the end of the + * ciphertext. */ + if( ciphertext_size < ( plaintext_length + operation.tag_length ) ) + { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + tag = ciphertext + plaintext_length; + +#if defined(MBEDTLS_GCM_C) + if( operation.core_alg == PSA_ALG_GCM ) + { + status = mbedtls_to_psa_error( + mbedtls_gcm_crypt_and_tag( &operation.ctx.gcm, + MBEDTLS_GCM_ENCRYPT, + plaintext_length, + nonce, nonce_length, + additional_data, additional_data_length, + plaintext, ciphertext, + operation.tag_length, tag ) ); + } + else +#endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_CCM_C) + if( operation.core_alg == PSA_ALG_CCM ) + { + status = mbedtls_to_psa_error( + mbedtls_ccm_encrypt_and_tag( &operation.ctx.ccm, + plaintext_length, + nonce, nonce_length, + additional_data, + additional_data_length, + plaintext, ciphertext, + tag, operation.tag_length ) ); + } + else +#endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) + if( operation.core_alg == PSA_ALG_CHACHA20_POLY1305 ) + { + if( nonce_length != 12 || operation.tag_length != 16 ) + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + status = mbedtls_to_psa_error( + mbedtls_chachapoly_encrypt_and_tag( &operation.ctx.chachapoly, + plaintext_length, + nonce, + additional_data, + additional_data_length, + plaintext, + ciphertext, + tag ) ); + } + else +#endif /* MBEDTLS_CHACHAPOLY_C */ + { + return( PSA_ERROR_NOT_SUPPORTED ); + } + + if( status != PSA_SUCCESS && ciphertext_size != 0 ) + memset( ciphertext, 0, ciphertext_size ); + +exit: + psa_aead_abort_internal( &operation ); + if( status == PSA_SUCCESS ) + *ciphertext_length = plaintext_length + operation.tag_length; + return( status ); +} + +/* Locate the tag in a ciphertext buffer containing the encrypted data + * followed by the tag. Return the length of the part preceding the tag in + * *plaintext_length. This is the size of the plaintext in modes where + * the encrypted data has the same size as the plaintext, such as + * CCM and GCM. */ +static psa_status_t psa_aead_unpadded_locate_tag( size_t tag_length, + const uint8_t *ciphertext, + size_t ciphertext_length, + size_t plaintext_size, + const uint8_t **p_tag ) +{ + size_t payload_length; + if( tag_length > ciphertext_length ) + return( PSA_ERROR_INVALID_ARGUMENT ); + payload_length = ciphertext_length - tag_length; + if( payload_length > plaintext_size ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + *p_tag = ciphertext + payload_length; + return( PSA_SUCCESS ); +} + +psa_status_t psa_aead_decrypt( psa_key_handle_t handle, + 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 *ciphertext, + size_t ciphertext_length, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length ) +{ + psa_status_t status; + aead_operation_t operation; + const uint8_t *tag = NULL; + + *plaintext_length = 0; + + status = psa_aead_setup( &operation, handle, PSA_KEY_USAGE_DECRYPT, alg ); + if( status != PSA_SUCCESS ) + return( status ); + + status = psa_aead_unpadded_locate_tag( operation.tag_length, + ciphertext, ciphertext_length, + plaintext_size, &tag ); + if( status != PSA_SUCCESS ) + goto exit; + +#if defined(MBEDTLS_GCM_C) + if( operation.core_alg == PSA_ALG_GCM ) + { + status = mbedtls_to_psa_error( + mbedtls_gcm_auth_decrypt( &operation.ctx.gcm, + ciphertext_length - operation.tag_length, + nonce, nonce_length, + additional_data, + additional_data_length, + tag, operation.tag_length, + ciphertext, plaintext ) ); + } + else +#endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_CCM_C) + if( operation.core_alg == PSA_ALG_CCM ) + { + status = mbedtls_to_psa_error( + mbedtls_ccm_auth_decrypt( &operation.ctx.ccm, + ciphertext_length - operation.tag_length, + nonce, nonce_length, + additional_data, + additional_data_length, + ciphertext, plaintext, + tag, operation.tag_length ) ); + } + else +#endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) + if( operation.core_alg == PSA_ALG_CHACHA20_POLY1305 ) + { + if( nonce_length != 12 || operation.tag_length != 16 ) + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + status = mbedtls_to_psa_error( + mbedtls_chachapoly_auth_decrypt( &operation.ctx.chachapoly, + ciphertext_length - operation.tag_length, + nonce, + additional_data, + additional_data_length, + tag, + ciphertext, + plaintext ) ); + } + else +#endif /* MBEDTLS_CHACHAPOLY_C */ + { + return( PSA_ERROR_NOT_SUPPORTED ); + } + + if( status != PSA_SUCCESS && plaintext_size != 0 ) + memset( plaintext, 0, plaintext_size ); + +exit: + psa_aead_abort_internal( &operation ); + if( status == PSA_SUCCESS ) + *plaintext_length = ciphertext_length - operation.tag_length; + return( status ); +} + + + +/****************************************************************/ +/* Generators */ +/****************************************************************/ + +#define HKDF_STATE_INIT 0 /* no input yet */ +#define HKDF_STATE_STARTED 1 /* got salt */ +#define HKDF_STATE_KEYED 2 /* got key */ +#define HKDF_STATE_OUTPUT 3 /* output started */ + +static psa_algorithm_t psa_key_derivation_get_kdf_alg( + const psa_key_derivation_operation_t *operation ) +{ + if ( PSA_ALG_IS_KEY_AGREEMENT( operation->alg ) ) + return( PSA_ALG_KEY_AGREEMENT_GET_KDF( operation->alg ) ); + else + return( operation->alg ); +} + + +psa_status_t psa_key_derivation_abort( psa_key_derivation_operation_t *operation ) +{ + psa_status_t status = PSA_SUCCESS; + psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg( operation ); + if( kdf_alg == 0 ) + { + /* The object has (apparently) been initialized but it is not + * in use. It's ok to call abort on such an object, and there's + * nothing to do. */ + } + else +#if defined(MBEDTLS_MD_C) + if( PSA_ALG_IS_HKDF( kdf_alg ) ) + { + mbedtls_free( operation->ctx.hkdf.info ); + status = psa_hmac_abort_internal( &operation->ctx.hkdf.hmac ); + } + else if( PSA_ALG_IS_TLS12_PRF( kdf_alg ) || + /* TLS-1.2 PSK-to-MS KDF uses the same core as TLS-1.2 PRF */ + PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) ) + { + if( operation->ctx.tls12_prf.seed != NULL ) + { + mbedtls_platform_zeroize( operation->ctx.tls12_prf.seed, + operation->ctx.tls12_prf.seed_length ); + mbedtls_free( operation->ctx.tls12_prf.seed ); + } + + if( operation->ctx.tls12_prf.label != NULL ) + { + mbedtls_platform_zeroize( operation->ctx.tls12_prf.label, + operation->ctx.tls12_prf.label_length ); + mbedtls_free( operation->ctx.tls12_prf.label ); + } + + status = psa_hmac_abort_internal( &operation->ctx.tls12_prf.hmac ); + + /* We leave the fields Ai and output_block to be erased safely by the + * mbedtls_platform_zeroize() in the end of this function. */ + } + else +#endif /* MBEDTLS_MD_C */ + { + status = PSA_ERROR_BAD_STATE; + } + mbedtls_platform_zeroize( operation, sizeof( *operation ) ); + return( status ); +} + +psa_status_t psa_key_derivation_get_capacity(const psa_key_derivation_operation_t *operation, + size_t *capacity) +{ + if( operation->alg == 0 ) + { + /* This is a blank key derivation operation. */ + return PSA_ERROR_BAD_STATE; + } + + *capacity = operation->capacity; + return( PSA_SUCCESS ); +} + +psa_status_t psa_key_derivation_set_capacity( psa_key_derivation_operation_t *operation, + size_t capacity ) +{ + if( operation->alg == 0 ) + return( PSA_ERROR_BAD_STATE ); + if( capacity > operation->capacity ) + return( PSA_ERROR_INVALID_ARGUMENT ); + operation->capacity = capacity; + return( PSA_SUCCESS ); +} + +#if defined(MBEDTLS_MD_C) +/* Read some bytes from an HKDF-based operation. This performs a chunk + * of the expand phase of the HKDF algorithm. */ +static psa_status_t psa_key_derivation_hkdf_read( psa_hkdf_key_derivation_t *hkdf, + psa_algorithm_t hash_alg, + uint8_t *output, + size_t output_length ) +{ + uint8_t hash_length = PSA_HASH_SIZE( hash_alg ); + psa_status_t status; + + if( hkdf->state < HKDF_STATE_KEYED || ! hkdf->info_set ) + return( PSA_ERROR_BAD_STATE ); + hkdf->state = HKDF_STATE_OUTPUT; + + while( output_length != 0 ) + { + /* Copy what remains of the current block */ + uint8_t n = hash_length - hkdf->offset_in_block; + if( n > output_length ) + n = (uint8_t) output_length; + memcpy( output, hkdf->output_block + hkdf->offset_in_block, n ); + output += n; + output_length -= n; + hkdf->offset_in_block += n; + if( output_length == 0 ) + break; + /* We can't be wanting more output after block 0xff, otherwise + * the capacity check in psa_key_derivation_output_bytes() would have + * prevented this call. It could happen only if the operation + * object was corrupted or if this function is called directly + * inside the library. */ + if( hkdf->block_number == 0xff ) + return( PSA_ERROR_BAD_STATE ); + + /* We need a new block */ + ++hkdf->block_number; + hkdf->offset_in_block = 0; + status = psa_hmac_setup_internal( &hkdf->hmac, + hkdf->prk, hash_length, + hash_alg ); + if( status != PSA_SUCCESS ) + return( status ); + if( hkdf->block_number != 1 ) + { + status = psa_hash_update( &hkdf->hmac.hash_ctx, + hkdf->output_block, + hash_length ); + if( status != PSA_SUCCESS ) + return( status ); + } + status = psa_hash_update( &hkdf->hmac.hash_ctx, + hkdf->info, + hkdf->info_length ); + if( status != PSA_SUCCESS ) + return( status ); + status = psa_hash_update( &hkdf->hmac.hash_ctx, + &hkdf->block_number, 1 ); + if( status != PSA_SUCCESS ) + return( status ); + status = psa_hmac_finish_internal( &hkdf->hmac, + hkdf->output_block, + sizeof( hkdf->output_block ) ); + if( status != PSA_SUCCESS ) + return( status ); + } + + return( PSA_SUCCESS ); +} + +static psa_status_t psa_key_derivation_tls12_prf_generate_next_block( + psa_tls12_prf_key_derivation_t *tls12_prf, + psa_algorithm_t alg ) +{ + psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH( alg ); + uint8_t hash_length = PSA_HASH_SIZE( hash_alg ); + psa_hash_operation_t backup = PSA_HASH_OPERATION_INIT; + psa_status_t status, cleanup_status; + + /* We can't be wanting more output after block 0xff, otherwise + * the capacity check in psa_key_derivation_output_bytes() would have + * prevented this call. It could happen only if the operation + * object was corrupted or if this function is called directly + * inside the library. */ + if( tls12_prf->block_number == 0xff ) + return( PSA_ERROR_CORRUPTION_DETECTED ); + + /* We need a new block */ + ++tls12_prf->block_number; + tls12_prf->left_in_block = hash_length; + + /* Recall the definition of the TLS-1.2-PRF from RFC 5246: + * + * PRF(secret, label, seed) = P_(secret, label + seed) + * + * P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + + * HMAC_hash(secret, A(2) + seed) + + * HMAC_hash(secret, A(3) + seed) + ... + * + * A(0) = seed + * A(i) = HMAC_hash(secret, A(i-1)) + * + * The `psa_tls12_prf_key_derivation` structure saves the block + * `HMAC_hash(secret, A(i) + seed)` from which the output + * is currently extracted as `output_block` and where i is + * `block_number`. + */ + + /* Save the hash context before using it, to preserve the hash state with + * only the inner padding in it. We need this, because inner padding depends + * on the key (secret in the RFC's terminology). */ + status = psa_hash_clone( &tls12_prf->hmac.hash_ctx, &backup ); + if( status != PSA_SUCCESS ) + goto cleanup; + + /* Calculate A(i) where i = tls12_prf->block_number. */ + if( tls12_prf->block_number == 1 ) + { + /* A(1) = HMAC_hash(secret, A(0)), where A(0) = seed. (The RFC overloads + * the variable seed and in this instance means it in the context of the + * P_hash function, where seed = label + seed.) */ + status = psa_hash_update( &tls12_prf->hmac.hash_ctx, + tls12_prf->label, tls12_prf->label_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + status = psa_hash_update( &tls12_prf->hmac.hash_ctx, + tls12_prf->seed, tls12_prf->seed_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + } + else + { + /* A(i) = HMAC_hash(secret, A(i-1)) */ + status = psa_hash_update( &tls12_prf->hmac.hash_ctx, + tls12_prf->Ai, hash_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + } + + status = psa_hmac_finish_internal( &tls12_prf->hmac, + tls12_prf->Ai, hash_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + status = psa_hash_clone( &backup, &tls12_prf->hmac.hash_ctx ); + if( status != PSA_SUCCESS ) + goto cleanup; + + /* Calculate HMAC_hash(secret, A(i) + label + seed). */ + status = psa_hash_update( &tls12_prf->hmac.hash_ctx, + tls12_prf->Ai, hash_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + status = psa_hash_update( &tls12_prf->hmac.hash_ctx, + tls12_prf->label, tls12_prf->label_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + status = psa_hash_update( &tls12_prf->hmac.hash_ctx, + tls12_prf->seed, tls12_prf->seed_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + status = psa_hmac_finish_internal( &tls12_prf->hmac, + tls12_prf->output_block, hash_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + status = psa_hash_clone( &backup, &tls12_prf->hmac.hash_ctx ); + if( status != PSA_SUCCESS ) + goto cleanup; + + +cleanup: + + cleanup_status = psa_hash_abort( &backup ); + if( status == PSA_SUCCESS && cleanup_status != PSA_SUCCESS ) + status = cleanup_status; + + return( status ); +} + +static psa_status_t psa_key_derivation_tls12_prf_read( + psa_tls12_prf_key_derivation_t *tls12_prf, + psa_algorithm_t alg, + uint8_t *output, + size_t output_length ) +{ + psa_algorithm_t hash_alg = PSA_ALG_TLS12_PRF_GET_HASH( alg ); + uint8_t hash_length = PSA_HASH_SIZE( hash_alg ); + psa_status_t status; + uint8_t offset, length; + + while( output_length != 0 ) + { + /* Check if we have fully processed the current block. */ + if( tls12_prf->left_in_block == 0 ) + { + status = psa_key_derivation_tls12_prf_generate_next_block( tls12_prf, + alg ); + if( status != PSA_SUCCESS ) + return( status ); + + continue; + } + + if( tls12_prf->left_in_block > output_length ) + length = (uint8_t) output_length; + else + length = tls12_prf->left_in_block; + + offset = hash_length - tls12_prf->left_in_block; + memcpy( output, tls12_prf->output_block + offset, length ); + output += length; + output_length -= length; + tls12_prf->left_in_block -= length; + } + + return( PSA_SUCCESS ); +} +#endif /* MBEDTLS_MD_C */ + +psa_status_t psa_key_derivation_output_bytes( + psa_key_derivation_operation_t *operation, + uint8_t *output, + size_t output_length ) +{ + psa_status_t status; + psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg( operation ); + + if( operation->alg == 0 ) + { + /* This is a blank operation. */ + return PSA_ERROR_BAD_STATE; + } + + if( output_length > operation->capacity ) + { + operation->capacity = 0; + /* Go through the error path to wipe all confidential data now + * that the operation object is useless. */ + status = PSA_ERROR_INSUFFICIENT_DATA; + goto exit; + } + if( output_length == 0 && operation->capacity == 0 ) + { + /* Edge case: this is a finished operation, and 0 bytes + * were requested. The right error in this case could + * be either INSUFFICIENT_CAPACITY or BAD_STATE. Return + * INSUFFICIENT_CAPACITY, which is right for a finished + * operation, for consistency with the case when + * output_length > 0. */ + return( PSA_ERROR_INSUFFICIENT_DATA ); + } + operation->capacity -= output_length; + +#if defined(MBEDTLS_MD_C) + if( PSA_ALG_IS_HKDF( kdf_alg ) ) + { + psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH( kdf_alg ); + status = psa_key_derivation_hkdf_read( &operation->ctx.hkdf, hash_alg, + output, output_length ); + } + else + if( PSA_ALG_IS_TLS12_PRF( kdf_alg ) || + PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) ) + { + status = psa_key_derivation_tls12_prf_read( &operation->ctx.tls12_prf, + kdf_alg, output, + output_length ); + } + else +#endif /* MBEDTLS_MD_C */ + { + return( PSA_ERROR_BAD_STATE ); + } + +exit: + if( status != PSA_SUCCESS ) + { + /* Preserve the algorithm upon errors, but clear all sensitive state. + * This allows us to differentiate between exhausted operations and + * blank operations, so we can return PSA_ERROR_BAD_STATE on blank + * operations. */ + psa_algorithm_t alg = operation->alg; + psa_key_derivation_abort( operation ); + operation->alg = alg; + memset( output, '!', output_length ); + } + return( status ); +} + +#if defined(MBEDTLS_DES_C) +static void psa_des_set_key_parity( uint8_t *data, size_t data_size ) +{ + if( data_size >= 8 ) + mbedtls_des_key_set_parity( data ); + if( data_size >= 16 ) + mbedtls_des_key_set_parity( data + 8 ); + if( data_size >= 24 ) + mbedtls_des_key_set_parity( data + 16 ); +} +#endif /* MBEDTLS_DES_C */ + +static psa_status_t psa_generate_derived_key_internal( + psa_key_slot_t *slot, + size_t bits, + psa_key_derivation_operation_t *operation ) +{ + uint8_t *data = NULL; + size_t bytes = PSA_BITS_TO_BYTES( bits ); + psa_status_t status; + + if( ! key_type_is_raw_bytes( slot->attr.type ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + if( bits % 8 != 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + data = mbedtls_calloc( 1, bytes ); + if( data == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + + status = psa_key_derivation_output_bytes( operation, data, bytes ); + if( status != PSA_SUCCESS ) + goto exit; +#if defined(MBEDTLS_DES_C) + if( slot->attr.type == PSA_KEY_TYPE_DES ) + psa_des_set_key_parity( data, bytes ); +#endif /* MBEDTLS_DES_C */ + status = psa_import_key_into_slot( slot, data, bytes ); + +exit: + mbedtls_free( data ); + return( status ); +} + +psa_status_t psa_key_derivation_output_key( const psa_key_attributes_t *attributes, + psa_key_derivation_operation_t *operation, + psa_key_handle_t *handle ) +{ + psa_status_t status; + psa_key_slot_t *slot = NULL; + psa_se_drv_table_entry_t *driver = NULL; + + /* Reject any attempt to create a zero-length key so that we don't + * risk tripping up later, e.g. on a malloc(0) that returns NULL. */ + if( psa_get_key_bits( attributes ) == 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + if( ! operation->can_output_key ) + return( PSA_ERROR_NOT_PERMITTED ); + + status = psa_start_key_creation( PSA_KEY_CREATION_DERIVE, + attributes, handle, &slot, &driver ); +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if( driver != NULL ) + { + /* Deriving a key in a secure element is not implemented yet. */ + status = PSA_ERROR_NOT_SUPPORTED; + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + if( status == PSA_SUCCESS ) + { + status = psa_generate_derived_key_internal( slot, + attributes->core.bits, + operation ); + } + if( status == PSA_SUCCESS ) + status = psa_finish_key_creation( slot, driver ); + if( status != PSA_SUCCESS ) + { + psa_fail_key_creation( slot, driver ); + *handle = 0; + } + return( status ); +} + + + +/****************************************************************/ +/* Key derivation */ +/****************************************************************/ + +static psa_status_t psa_key_derivation_setup_kdf( + psa_key_derivation_operation_t *operation, + psa_algorithm_t kdf_alg ) +{ + /* Make sure that operation->ctx is properly zero-initialised. (Macro + * initialisers for this union leave some bytes unspecified.) */ + memset( &operation->ctx, 0, sizeof( operation->ctx ) ); + + /* Make sure that kdf_alg is a supported key derivation algorithm. */ +#if defined(MBEDTLS_MD_C) + if( PSA_ALG_IS_HKDF( kdf_alg ) || + PSA_ALG_IS_TLS12_PRF( kdf_alg ) || + PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) ) + { + psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH( kdf_alg ); + size_t hash_size = PSA_HASH_SIZE( hash_alg ); + if( hash_size == 0 ) + return( PSA_ERROR_NOT_SUPPORTED ); + if( ( PSA_ALG_IS_TLS12_PRF( kdf_alg ) || + PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) ) && + ! ( hash_alg == PSA_ALG_SHA_256 || hash_alg == PSA_ALG_SHA_384 ) ) + { + return( PSA_ERROR_NOT_SUPPORTED ); + } + operation->capacity = 255 * hash_size; + return( PSA_SUCCESS ); + } +#endif /* MBEDTLS_MD_C */ + else + return( PSA_ERROR_NOT_SUPPORTED ); +} + +psa_status_t psa_key_derivation_setup( psa_key_derivation_operation_t *operation, + psa_algorithm_t alg ) +{ + psa_status_t status; + + if( operation->alg != 0 ) + return( PSA_ERROR_BAD_STATE ); + + if( PSA_ALG_IS_RAW_KEY_AGREEMENT( alg ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + else if( PSA_ALG_IS_KEY_AGREEMENT( alg ) ) + { + psa_algorithm_t kdf_alg = PSA_ALG_KEY_AGREEMENT_GET_KDF( alg ); + status = psa_key_derivation_setup_kdf( operation, kdf_alg ); + } + else if( PSA_ALG_IS_KEY_DERIVATION( alg ) ) + { + status = psa_key_derivation_setup_kdf( operation, alg ); + } + else + return( PSA_ERROR_INVALID_ARGUMENT ); + + if( status == PSA_SUCCESS ) + operation->alg = alg; + return( status ); +} + +#if defined(MBEDTLS_MD_C) +static psa_status_t psa_hkdf_input( psa_hkdf_key_derivation_t *hkdf, + psa_algorithm_t hash_alg, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length ) +{ + psa_status_t status; + switch( step ) + { + case PSA_KEY_DERIVATION_INPUT_SALT: + if( hkdf->state != HKDF_STATE_INIT ) + return( PSA_ERROR_BAD_STATE ); + status = psa_hmac_setup_internal( &hkdf->hmac, + data, data_length, + hash_alg ); + if( status != PSA_SUCCESS ) + return( status ); + hkdf->state = HKDF_STATE_STARTED; + return( PSA_SUCCESS ); + case PSA_KEY_DERIVATION_INPUT_SECRET: + /* If no salt was provided, use an empty salt. */ + if( hkdf->state == HKDF_STATE_INIT ) + { + status = psa_hmac_setup_internal( &hkdf->hmac, + NULL, 0, + hash_alg ); + if( status != PSA_SUCCESS ) + return( status ); + hkdf->state = HKDF_STATE_STARTED; + } + if( hkdf->state != HKDF_STATE_STARTED ) + return( PSA_ERROR_BAD_STATE ); + status = psa_hash_update( &hkdf->hmac.hash_ctx, + data, data_length ); + if( status != PSA_SUCCESS ) + return( status ); + status = psa_hmac_finish_internal( &hkdf->hmac, + hkdf->prk, + sizeof( hkdf->prk ) ); + if( status != PSA_SUCCESS ) + return( status ); + hkdf->offset_in_block = PSA_HASH_SIZE( hash_alg ); + hkdf->block_number = 0; + hkdf->state = HKDF_STATE_KEYED; + return( PSA_SUCCESS ); + case PSA_KEY_DERIVATION_INPUT_INFO: + if( hkdf->state == HKDF_STATE_OUTPUT ) + return( PSA_ERROR_BAD_STATE ); + if( hkdf->info_set ) + return( PSA_ERROR_BAD_STATE ); + hkdf->info_length = data_length; + if( data_length != 0 ) + { + hkdf->info = mbedtls_calloc( 1, data_length ); + if( hkdf->info == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + memcpy( hkdf->info, data, data_length ); + } + hkdf->info_set = 1; + return( PSA_SUCCESS ); + default: + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +static psa_status_t psa_tls12_prf_set_seed( psa_tls12_prf_key_derivation_t *prf, + const uint8_t *data, + size_t data_length ) +{ + if( prf->state != TLS12_PRF_STATE_INIT ) + return( PSA_ERROR_BAD_STATE ); + + if( data_length != 0 ) + { + prf->seed = mbedtls_calloc( 1, data_length ); + if( prf->seed == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + + memcpy( prf->seed, data, data_length ); + prf->seed_length = data_length; + } + + prf->state = TLS12_PRF_STATE_SEED_SET; + + return( PSA_SUCCESS ); +} + +static psa_status_t psa_tls12_prf_set_key( psa_tls12_prf_key_derivation_t *prf, + psa_algorithm_t hash_alg, + const uint8_t *data, + size_t data_length ) +{ + psa_status_t status; + if( prf->state != TLS12_PRF_STATE_SEED_SET ) + return( PSA_ERROR_BAD_STATE ); + + status = psa_hmac_setup_internal( &prf->hmac, data, data_length, hash_alg ); + if( status != PSA_SUCCESS ) + return( status ); + + prf->state = TLS12_PRF_STATE_KEY_SET; + + return( PSA_SUCCESS ); +} + +static psa_status_t psa_tls12_prf_psk_to_ms_set_key( + psa_tls12_prf_key_derivation_t *prf, + psa_algorithm_t hash_alg, + const uint8_t *data, + size_t data_length ) +{ + psa_status_t status; + uint8_t pms[ 4 + 2 * PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN ]; + uint8_t *cur = pms; + + if( data_length > PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + /* Quoting RFC 4279, Section 2: + * + * The premaster secret is formed as follows: if the PSK is N octets + * long, concatenate a uint16 with the value N, N zero octets, a second + * uint16 with the value N, and the PSK itself. + */ + + *cur++ = ( data_length >> 8 ) & 0xff; + *cur++ = ( data_length >> 0 ) & 0xff; + memset( cur, 0, data_length ); + cur += data_length; + *cur++ = pms[0]; + *cur++ = pms[1]; + memcpy( cur, data, data_length ); + cur += data_length; + + status = psa_tls12_prf_set_key( prf, hash_alg, pms, cur - pms ); + + mbedtls_platform_zeroize( pms, sizeof( pms ) ); + return( status ); +} + +static psa_status_t psa_tls12_prf_set_label( psa_tls12_prf_key_derivation_t *prf, + const uint8_t *data, + size_t data_length ) +{ + if( prf->state != TLS12_PRF_STATE_KEY_SET ) + return( PSA_ERROR_BAD_STATE ); + + if( data_length != 0 ) + { + prf->label = mbedtls_calloc( 1, data_length ); + if( prf->label == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + + memcpy( prf->label, data, data_length ); + prf->label_length = data_length; + } + + prf->state = TLS12_PRF_STATE_LABEL_SET; + + return( PSA_SUCCESS ); +} + +static psa_status_t psa_tls12_prf_input( psa_tls12_prf_key_derivation_t *prf, + psa_algorithm_t hash_alg, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length ) +{ + switch( step ) + { + case PSA_KEY_DERIVATION_INPUT_SEED: + return( psa_tls12_prf_set_seed( prf, data, data_length ) ); + case PSA_KEY_DERIVATION_INPUT_SECRET: + return( psa_tls12_prf_set_key( prf, hash_alg, data, data_length ) ); + case PSA_KEY_DERIVATION_INPUT_LABEL: + return( psa_tls12_prf_set_label( prf, data, data_length ) ); + default: + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +static psa_status_t psa_tls12_prf_psk_to_ms_input( + psa_tls12_prf_key_derivation_t *prf, + psa_algorithm_t hash_alg, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length ) +{ + if( step == PSA_KEY_DERIVATION_INPUT_SECRET ) + { + return( psa_tls12_prf_psk_to_ms_set_key( prf, hash_alg, + data, data_length ) ); + } + + return( psa_tls12_prf_input( prf, hash_alg, step, data, data_length ) ); +} +#endif /* MBEDTLS_MD_C */ + +/** Check whether the given key type is acceptable for the given + * input step of a key derivation. + * + * Secret inputs must have the type #PSA_KEY_TYPE_DERIVE. + * Non-secret inputs must have the type #PSA_KEY_TYPE_RAW_DATA. + * Both secret and non-secret inputs can alternatively have the type + * #PSA_KEY_TYPE_NONE, which is never the type of a key object, meaning + * that the input was passed as a buffer rather than via a key object. + */ +static int psa_key_derivation_check_input_type( + psa_key_derivation_step_t step, + psa_key_type_t key_type ) +{ + switch( step ) + { + case PSA_KEY_DERIVATION_INPUT_SECRET: + if( key_type == PSA_KEY_TYPE_DERIVE ) + return( PSA_SUCCESS ); + if( key_type == PSA_KEY_TYPE_NONE ) + return( PSA_SUCCESS ); + break; + case PSA_KEY_DERIVATION_INPUT_LABEL: + case PSA_KEY_DERIVATION_INPUT_SALT: + case PSA_KEY_DERIVATION_INPUT_INFO: + case PSA_KEY_DERIVATION_INPUT_SEED: + if( key_type == PSA_KEY_TYPE_RAW_DATA ) + return( PSA_SUCCESS ); + if( key_type == PSA_KEY_TYPE_NONE ) + return( PSA_SUCCESS ); + break; + } + return( PSA_ERROR_INVALID_ARGUMENT ); +} + +static psa_status_t psa_key_derivation_input_internal( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_type_t key_type, + const uint8_t *data, + size_t data_length ) +{ + psa_status_t status; + psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg( operation ); + + status = psa_key_derivation_check_input_type( step, key_type ); + if( status != PSA_SUCCESS ) + goto exit; + +#if defined(MBEDTLS_MD_C) + if( PSA_ALG_IS_HKDF( kdf_alg ) ) + { + status = psa_hkdf_input( &operation->ctx.hkdf, + PSA_ALG_HKDF_GET_HASH( kdf_alg ), + step, data, data_length ); + } + else if( PSA_ALG_IS_TLS12_PRF( kdf_alg ) ) + { + status = psa_tls12_prf_input( &operation->ctx.tls12_prf, + PSA_ALG_HKDF_GET_HASH( kdf_alg ), + step, data, data_length ); + } + else if( PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) ) + { + status = psa_tls12_prf_psk_to_ms_input( &operation->ctx.tls12_prf, + PSA_ALG_HKDF_GET_HASH( kdf_alg ), + step, data, data_length ); + } + else +#endif /* MBEDTLS_MD_C */ + { + /* This can't happen unless the operation object was not initialized */ + return( PSA_ERROR_BAD_STATE ); + } + +exit: + if( status != PSA_SUCCESS ) + psa_key_derivation_abort( operation ); + return( status ); +} + +psa_status_t psa_key_derivation_input_bytes( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length ) +{ + return( psa_key_derivation_input_internal( operation, step, + PSA_KEY_TYPE_NONE, + data, data_length ) ); +} + +psa_status_t psa_key_derivation_input_key( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_handle_t handle ) +{ + psa_key_slot_t *slot; + psa_status_t status; + + status = psa_get_transparent_key( handle, &slot, + PSA_KEY_USAGE_DERIVE, + operation->alg ); + if( status != PSA_SUCCESS ) + { + psa_key_derivation_abort( operation ); + return( status ); + } + + /* Passing a key object as a SECRET input unlocks the permission + * to output to a key object. */ + if( step == PSA_KEY_DERIVATION_INPUT_SECRET ) + operation->can_output_key = 1; + + return( psa_key_derivation_input_internal( operation, + step, slot->attr.type, + slot->data.raw.data, + slot->data.raw.bytes ) ); +} + + + +/****************************************************************/ +/* Key agreement */ +/****************************************************************/ + +#if defined(MBEDTLS_ECDH_C) +static psa_status_t psa_key_agreement_ecdh( const uint8_t *peer_key, + size_t peer_key_length, + const mbedtls_ecp_keypair *our_key, + uint8_t *shared_secret, + size_t shared_secret_size, + size_t *shared_secret_length ) +{ + mbedtls_ecp_keypair *their_key = NULL; + mbedtls_ecdh_context ecdh; + psa_status_t status; + size_t bits = 0; + psa_ecc_curve_t curve = mbedtls_ecc_group_to_psa( our_key->grp.id, &bits ); + mbedtls_ecdh_init( &ecdh ); + + status = psa_import_ec_public_key( curve, + peer_key, peer_key_length, + &their_key ); + if( status != PSA_SUCCESS ) + goto exit; + + status = mbedtls_to_psa_error( + mbedtls_ecdh_get_params( &ecdh, their_key, MBEDTLS_ECDH_THEIRS ) ); + if( status != PSA_SUCCESS ) + goto exit; + status = mbedtls_to_psa_error( + mbedtls_ecdh_get_params( &ecdh, our_key, MBEDTLS_ECDH_OURS ) ); + if( status != PSA_SUCCESS ) + goto exit; + + status = mbedtls_to_psa_error( + mbedtls_ecdh_calc_secret( &ecdh, + shared_secret_length, + shared_secret, shared_secret_size, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg ) ); + if( status != PSA_SUCCESS ) + goto exit; + if( PSA_BITS_TO_BYTES( bits ) != *shared_secret_length ) + status = PSA_ERROR_CORRUPTION_DETECTED; + +exit: + if( status != PSA_SUCCESS ) + mbedtls_platform_zeroize( shared_secret, shared_secret_size ); + mbedtls_ecdh_free( &ecdh ); + mbedtls_ecp_keypair_free( their_key ); + mbedtls_free( their_key ); + return( status ); +} +#endif /* MBEDTLS_ECDH_C */ + +#define PSA_KEY_AGREEMENT_MAX_SHARED_SECRET_SIZE MBEDTLS_ECP_MAX_BYTES + +static psa_status_t psa_key_agreement_raw_internal( psa_algorithm_t alg, + psa_key_slot_t *private_key, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *shared_secret, + size_t shared_secret_size, + size_t *shared_secret_length ) +{ + switch( alg ) + { +#if defined(MBEDTLS_ECDH_C) + case PSA_ALG_ECDH: + if( ! PSA_KEY_TYPE_IS_ECC_KEY_PAIR( private_key->attr.type ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + return( psa_key_agreement_ecdh( peer_key, peer_key_length, + private_key->data.ecp, + shared_secret, shared_secret_size, + shared_secret_length ) ); +#endif /* MBEDTLS_ECDH_C */ + default: + (void) private_key; + (void) peer_key; + (void) peer_key_length; + (void) shared_secret; + (void) shared_secret_size; + (void) shared_secret_length; + return( PSA_ERROR_NOT_SUPPORTED ); + } +} + +/* Note that if this function fails, you must call psa_key_derivation_abort() + * to potentially free embedded data structures and wipe confidential data. + */ +static psa_status_t psa_key_agreement_internal( psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_slot_t *private_key, + const uint8_t *peer_key, + size_t peer_key_length ) +{ + psa_status_t status; + uint8_t shared_secret[PSA_KEY_AGREEMENT_MAX_SHARED_SECRET_SIZE]; + size_t shared_secret_length = 0; + psa_algorithm_t ka_alg = PSA_ALG_KEY_AGREEMENT_GET_BASE( operation->alg ); + + /* Step 1: run the secret agreement algorithm to generate the shared + * secret. */ + status = psa_key_agreement_raw_internal( ka_alg, + private_key, + peer_key, peer_key_length, + shared_secret, + sizeof( shared_secret ), + &shared_secret_length ); + if( status != PSA_SUCCESS ) + goto exit; + + /* Step 2: set up the key derivation to generate key material from + * the shared secret. A shared secret is permitted wherever a key + * of type DERIVE is permitted. */ + status = psa_key_derivation_input_internal( operation, step, + PSA_KEY_TYPE_DERIVE, + shared_secret, + shared_secret_length ); + +exit: + mbedtls_platform_zeroize( shared_secret, shared_secret_length ); + return( status ); +} + +psa_status_t psa_key_derivation_key_agreement( psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_handle_t private_key, + const uint8_t *peer_key, + size_t peer_key_length ) +{ + psa_key_slot_t *slot; + psa_status_t status; + if( ! PSA_ALG_IS_KEY_AGREEMENT( operation->alg ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + status = psa_get_transparent_key( private_key, &slot, + PSA_KEY_USAGE_DERIVE, operation->alg ); + if( status != PSA_SUCCESS ) + return( status ); + status = psa_key_agreement_internal( operation, step, + slot, + peer_key, peer_key_length ); + if( status != PSA_SUCCESS ) + psa_key_derivation_abort( operation ); + return( status ); +} + +psa_status_t psa_raw_key_agreement( psa_algorithm_t alg, + psa_key_handle_t private_key, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ + psa_key_slot_t *slot; + psa_status_t status; + + if( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + status = psa_get_transparent_key( private_key, &slot, + PSA_KEY_USAGE_DERIVE, alg ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_key_agreement_raw_internal( alg, slot, + peer_key, peer_key_length, + output, output_size, + output_length ); + +exit: + if( status != PSA_SUCCESS ) + { + /* If an error happens and is not handled properly, the output + * may be used as a key to protect sensitive data. Arrange for such + * a key to be random, which is likely to result in decryption or + * verification errors. This is better than filling the buffer with + * some constant data such as zeros, which would result in the data + * being protected with a reproducible, easily knowable key. + */ + psa_generate_random( output, output_size ); + *output_length = output_size; + } + return( status ); +} + + +/****************************************************************/ +/* Random generation */ +/****************************************************************/ + +psa_status_t psa_generate_random( uint8_t *output, + size_t output_size ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + GUARD_MODULE_INITIALIZED; + + while( output_size > MBEDTLS_CTR_DRBG_MAX_REQUEST ) + { + ret = mbedtls_ctr_drbg_random( &global_data.ctr_drbg, + output, + MBEDTLS_CTR_DRBG_MAX_REQUEST ); + if( ret != 0 ) + return( mbedtls_to_psa_error( ret ) ); + output += MBEDTLS_CTR_DRBG_MAX_REQUEST; + output_size -= MBEDTLS_CTR_DRBG_MAX_REQUEST; + } + + ret = mbedtls_ctr_drbg_random( &global_data.ctr_drbg, output, output_size ); + return( mbedtls_to_psa_error( ret ) ); +} + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) +#include "mbedtls/entropy_poll.h" + +psa_status_t mbedtls_psa_inject_entropy( const uint8_t *seed, + size_t seed_size ) +{ + if( global_data.initialized ) + return( PSA_ERROR_NOT_PERMITTED ); + + if( ( ( seed_size < MBEDTLS_ENTROPY_MIN_PLATFORM ) || + ( seed_size < MBEDTLS_ENTROPY_BLOCK_SIZE ) ) || + ( seed_size > MBEDTLS_ENTROPY_MAX_SEED_SIZE ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + return( mbedtls_psa_storage_inject_entropy( seed, seed_size ) ); +} +#endif /* MBEDTLS_PSA_INJECT_ENTROPY */ + +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_GENPRIME) +static psa_status_t psa_read_rsa_exponent( const uint8_t *domain_parameters, + size_t domain_parameters_size, + int *exponent ) +{ + size_t i; + uint32_t acc = 0; + + if( domain_parameters_size == 0 ) + { + *exponent = 65537; + return( PSA_SUCCESS ); + } + + /* Mbed TLS encodes the public exponent as an int. For simplicity, only + * support values that fit in a 32-bit integer, which is larger than + * int on just about every platform anyway. */ + if( domain_parameters_size > sizeof( acc ) ) + return( PSA_ERROR_NOT_SUPPORTED ); + for( i = 0; i < domain_parameters_size; i++ ) + acc = ( acc << 8 ) | domain_parameters[i]; + if( acc > INT_MAX ) + return( PSA_ERROR_NOT_SUPPORTED ); + *exponent = acc; + return( PSA_SUCCESS ); +} +#endif /* MBEDTLS_RSA_C && MBEDTLS_GENPRIME */ + +static psa_status_t psa_generate_key_internal( + psa_key_slot_t *slot, size_t bits, + const uint8_t *domain_parameters, size_t domain_parameters_size ) +{ + psa_key_type_t type = slot->attr.type; + + if( domain_parameters == NULL && domain_parameters_size != 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + if( key_type_is_raw_bytes( type ) ) + { + psa_status_t status; + status = prepare_raw_data_slot( type, bits, &slot->data.raw ); + if( status != PSA_SUCCESS ) + return( status ); + status = psa_generate_random( slot->data.raw.data, + slot->data.raw.bytes ); + if( status != PSA_SUCCESS ) + return( status ); +#if defined(MBEDTLS_DES_C) + if( type == PSA_KEY_TYPE_DES ) + psa_des_set_key_parity( slot->data.raw.data, + slot->data.raw.bytes ); +#endif /* MBEDTLS_DES_C */ + } + else + +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_GENPRIME) + if ( type == PSA_KEY_TYPE_RSA_KEY_PAIR ) + { + mbedtls_rsa_context *rsa; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int exponent; + psa_status_t status; + if( bits > PSA_VENDOR_RSA_MAX_KEY_BITS ) + return( PSA_ERROR_NOT_SUPPORTED ); + /* Accept only byte-aligned keys, for the same reasons as + * in psa_import_rsa_key(). */ + if( bits % 8 != 0 ) + return( PSA_ERROR_NOT_SUPPORTED ); + status = psa_read_rsa_exponent( domain_parameters, + domain_parameters_size, + &exponent ); + if( status != PSA_SUCCESS ) + return( status ); + rsa = mbedtls_calloc( 1, sizeof( *rsa ) ); + if( rsa == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + mbedtls_rsa_init( rsa, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE ); + ret = mbedtls_rsa_gen_key( rsa, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg, + (unsigned int) bits, + exponent ); + if( ret != 0 ) + { + mbedtls_rsa_free( rsa ); + mbedtls_free( rsa ); + return( mbedtls_to_psa_error( ret ) ); + } + slot->data.rsa = rsa; + } + else +#endif /* MBEDTLS_RSA_C && MBEDTLS_GENPRIME */ + +#if defined(MBEDTLS_ECP_C) + if ( PSA_KEY_TYPE_IS_ECC( type ) && PSA_KEY_TYPE_IS_KEY_PAIR( type ) ) + { + psa_ecc_curve_t curve = PSA_KEY_TYPE_GET_CURVE( type ); + mbedtls_ecp_group_id grp_id = + mbedtls_ecc_group_of_psa( curve, PSA_BITS_TO_BYTES( bits ) ); + const mbedtls_ecp_curve_info *curve_info = + mbedtls_ecp_curve_info_from_grp_id( grp_id ); + mbedtls_ecp_keypair *ecp; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + if( domain_parameters_size != 0 ) + return( PSA_ERROR_NOT_SUPPORTED ); + if( grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + if( curve_info->bit_size != bits ) + return( PSA_ERROR_INVALID_ARGUMENT ); + ecp = mbedtls_calloc( 1, sizeof( *ecp ) ); + if( ecp == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + mbedtls_ecp_keypair_init( ecp ); + ret = mbedtls_ecp_gen_key( grp_id, ecp, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg ); + if( ret != 0 ) + { + mbedtls_ecp_keypair_free( ecp ); + mbedtls_free( ecp ); + return( mbedtls_to_psa_error( ret ) ); + } + slot->data.ecp = ecp; + } + else +#endif /* MBEDTLS_ECP_C */ + + return( PSA_ERROR_NOT_SUPPORTED ); + + return( PSA_SUCCESS ); +} + +psa_status_t psa_generate_key( const psa_key_attributes_t *attributes, + psa_key_handle_t *handle ) +{ + psa_status_t status; + psa_key_slot_t *slot = NULL; + psa_se_drv_table_entry_t *driver = NULL; + + /* Reject any attempt to create a zero-length key so that we don't + * risk tripping up later, e.g. on a malloc(0) that returns NULL. */ + if( psa_get_key_bits( attributes ) == 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + status = psa_start_key_creation( PSA_KEY_CREATION_GENERATE, + attributes, handle, &slot, &driver ); + if( status != PSA_SUCCESS ) + goto exit; + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if( driver != NULL ) + { + const psa_drv_se_t *drv = psa_get_se_driver_methods( driver ); + size_t pubkey_length = 0; /* We don't support this feature yet */ + if( drv->key_management == NULL || + drv->key_management->p_generate == NULL ) + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + status = drv->key_management->p_generate( + psa_get_se_driver_context( driver ), + slot->data.se.slot_number, attributes, + NULL, 0, &pubkey_length ); + } + else +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + { + status = psa_generate_key_internal( + slot, attributes->core.bits, + attributes->domain_parameters, attributes->domain_parameters_size ); + } + +exit: + if( status == PSA_SUCCESS ) + status = psa_finish_key_creation( slot, driver ); + if( status != PSA_SUCCESS ) + { + psa_fail_key_creation( slot, driver ); + *handle = 0; + } + return( status ); +} + + + +/****************************************************************/ +/* Module setup */ +/****************************************************************/ + +psa_status_t mbedtls_psa_crypto_configure_entropy_sources( + void (* entropy_init )( mbedtls_entropy_context *ctx ), + void (* entropy_free )( mbedtls_entropy_context *ctx ) ) +{ + if( global_data.rng_state != RNG_NOT_INITIALIZED ) + return( PSA_ERROR_BAD_STATE ); + global_data.entropy_init = entropy_init; + global_data.entropy_free = entropy_free; + return( PSA_SUCCESS ); +} + +void mbedtls_psa_crypto_free( void ) +{ + psa_wipe_all_key_slots( ); + if( global_data.rng_state != RNG_NOT_INITIALIZED ) + { + mbedtls_ctr_drbg_free( &global_data.ctr_drbg ); + global_data.entropy_free( &global_data.entropy ); + } + /* Wipe all remaining data, including configuration. + * In particular, this sets all state indicator to the value + * indicating "uninitialized". */ + mbedtls_platform_zeroize( &global_data, sizeof( global_data ) ); +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + /* Unregister all secure element drivers, so that we restart from + * a pristine state. */ + psa_unregister_all_se_drivers( ); +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ +} + +#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) +/** Recover a transaction that was interrupted by a power failure. + * + * This function is called during initialization, before psa_crypto_init() + * returns. If this function returns a failure status, the initialization + * fails. + */ +static psa_status_t psa_crypto_recover_transaction( + const psa_crypto_transaction_t *transaction ) +{ + switch( transaction->unknown.type ) + { + case PSA_CRYPTO_TRANSACTION_CREATE_KEY: + case PSA_CRYPTO_TRANSACTION_DESTROY_KEY: + /* TODO - fall through to the failure case until this + * is implemented. + * https://github.com/ARMmbed/mbed-crypto/issues/218 + */ + default: + /* We found an unsupported transaction in the storage. + * We don't know what state the storage is in. Give up. */ + return( PSA_ERROR_STORAGE_FAILURE ); + } +} +#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */ + +psa_status_t psa_crypto_init( void ) +{ + psa_status_t status; + const unsigned char drbg_seed[] = "PSA"; + + /* Double initialization is explicitly allowed. */ + if( global_data.initialized != 0 ) + return( PSA_SUCCESS ); + + /* Set default configuration if + * mbedtls_psa_crypto_configure_entropy_sources() hasn't been called. */ + if( global_data.entropy_init == NULL ) + global_data.entropy_init = mbedtls_entropy_init; + if( global_data.entropy_free == NULL ) + global_data.entropy_free = mbedtls_entropy_free; + + /* Initialize the random generator. */ + global_data.entropy_init( &global_data.entropy ); +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ + defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) + /* The PSA entropy injection feature depends on using NV seed as an entropy + * source. Add NV seed as an entropy source for PSA entropy injection. */ + mbedtls_entropy_add_source( &global_data.entropy, + mbedtls_nv_seed_poll, NULL, + MBEDTLS_ENTROPY_BLOCK_SIZE, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif + mbedtls_ctr_drbg_init( &global_data.ctr_drbg ); + global_data.rng_state = RNG_INITIALIZED; + status = mbedtls_to_psa_error( + mbedtls_ctr_drbg_seed( &global_data.ctr_drbg, + mbedtls_entropy_func, + &global_data.entropy, + drbg_seed, sizeof( drbg_seed ) - 1 ) ); + if( status != PSA_SUCCESS ) + goto exit; + global_data.rng_state = RNG_SEEDED; + + status = psa_initialize_key_slots( ); + if( status != PSA_SUCCESS ) + goto exit; + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + status = psa_init_all_se_drivers( ); + if( status != PSA_SUCCESS ) + goto exit; +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + +#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) + status = psa_crypto_load_transaction( ); + if( status == PSA_SUCCESS ) + { + status = psa_crypto_recover_transaction( &psa_crypto_transaction ); + if( status != PSA_SUCCESS ) + goto exit; + status = psa_crypto_stop_transaction( ); + } + else if( status == PSA_ERROR_DOES_NOT_EXIST ) + { + /* There's no transaction to complete. It's all good. */ + status = PSA_SUCCESS; + } +#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */ + + /* All done. */ + global_data.initialized = 1; + +exit: + if( status != PSA_SUCCESS ) + mbedtls_psa_crypto_free( ); + return( status ); +} + +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_core.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_core.h new file mode 100644 index 0000000..edf3ab6 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_core.h @@ -0,0 +1,175 @@ +/* + * PSA crypto core internal interfaces + */ +/* Copyright (C) 2018, ARM Limited, 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef PSA_CRYPTO_CORE_H +#define PSA_CRYPTO_CORE_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "psa/crypto.h" +#include "psa/crypto_se_driver.h" + +#include "mbedtls/ecp.h" +#include "mbedtls/rsa.h" + +/** The data structure representing a key slot, containing key material + * and metadata for one key. + */ +typedef struct +{ + psa_core_key_attributes_t attr; + union + { + /* Raw-data key (key_type_is_raw_bytes() in psa_crypto.c) */ + struct raw_data + { + uint8_t *data; + size_t bytes; + } raw; +#if defined(MBEDTLS_RSA_C) + /* RSA public key or key pair */ + mbedtls_rsa_context *rsa; +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_C) + /* EC public key or key pair */ + mbedtls_ecp_keypair *ecp; +#endif /* MBEDTLS_ECP_C */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + /* Any key type in a secure element */ + struct se + { + psa_key_slot_number_t slot_number; + } se; +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + } data; +} psa_key_slot_t; + +/* A mask of key attribute flags used only internally. + * Currently there aren't any. */ +#define PSA_KA_MASK_INTERNAL_ONLY ( \ + 0 ) + +/** Test whether a key slot is occupied. + * + * A key slot is occupied iff the key type is nonzero. This works because + * no valid key can have 0 as its key type. + * + * \param[in] slot The key slot to test. + * + * \return 1 if the slot is occupied, 0 otherwise. + */ +static inline int psa_is_key_slot_occupied( const psa_key_slot_t *slot ) +{ + return( slot->attr.type != 0 ); +} + +/** Retrieve flags from psa_key_slot_t::attr::core::flags. + * + * \param[in] slot The key slot to query. + * \param mask The mask of bits to extract. + * + * \return The key attribute flags in the given slot, + * bitwise-anded with \p mask. + */ +static inline uint16_t psa_key_slot_get_flags( const psa_key_slot_t *slot, + uint16_t mask ) +{ + return( slot->attr.flags & mask ); +} + +/** Set flags in psa_key_slot_t::attr::core::flags. + * + * \param[in,out] slot The key slot to modify. + * \param mask The mask of bits to modify. + * \param value The new value of the selected bits. + */ +static inline void psa_key_slot_set_flags( psa_key_slot_t *slot, + uint16_t mask, + uint16_t value ) +{ + slot->attr.flags = ( ( ~mask & slot->attr.flags ) | + ( mask & value ) ); +} + +/** Turn on flags in psa_key_slot_t::attr::core::flags. + * + * \param[in,out] slot The key slot to modify. + * \param mask The mask of bits to set. + */ +static inline void psa_key_slot_set_bits_in_flags( psa_key_slot_t *slot, + uint16_t mask ) +{ + slot->attr.flags |= mask; +} + +/** Turn off flags in psa_key_slot_t::attr::core::flags. + * + * \param[in,out] slot The key slot to modify. + * \param mask The mask of bits to clear. + */ +static inline void psa_key_slot_clear_bits( psa_key_slot_t *slot, + uint16_t mask ) +{ + slot->attr.flags &= ~mask; +} + +/** Completely wipe a slot in memory, including its policy. + * + * Persistent storage is not affected. + * + * \param[in,out] slot The key slot to wipe. + * + * \retval PSA_SUCCESS + * Success. This includes the case of a key slot that was + * already fully wiped. + * \retval PSA_ERROR_CORRUPTION_DETECTED + */ +psa_status_t psa_wipe_key_slot( psa_key_slot_t *slot ); + +/** Import key data into a slot. + * + * `slot->type` must have been set previously. + * This function assumes that the slot does not contain any key material yet. + * On failure, the slot content is unchanged. + * + * Persistent storage is not affected. + * + * \param[in,out] slot The key slot to import data into. + * Its `type` field must have previously been set to + * the desired key type. + * It must not contain any key material yet. + * \param[in] data Buffer containing the key material to parse and import. + * \param data_length Size of \p data in bytes. + * + * \retval PSA_SUCCESS + * \retval PSA_ERROR_INVALID_ARGUMENT + * \retval PSA_ERROR_NOT_SUPPORTED + * \retval PSA_ERROR_INSUFFICIENT_MEMORY + */ +psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, + const uint8_t *data, + size_t data_length ); + +#endif /* PSA_CRYPTO_CORE_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_invasive.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_invasive.h new file mode 100644 index 0000000..642652a --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_invasive.h @@ -0,0 +1,79 @@ +/** + * \file psa_crypto_invasive.h + * + * \brief PSA cryptography module: invasive interfaces for test only. + * + * The interfaces in this file are intended for testing purposes only. + * They MUST NOT be made available to clients over IPC in integrations + * with isolation, and they SHOULD NOT be made available in library + * integrations except when building the library for testing. + */ +/* + * Copyright (C) 2018, ARM Limited, 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef PSA_CRYPTO_INVASIVE_H +#define PSA_CRYPTO_INVASIVE_H + +#if defined(MBEDTLS_CONFIG_FILE) +#include MBEDTLS_CONFIG_FILE +#else +#include "mbedtls/config.h" +#endif + +#include "psa/crypto.h" + +#include "mbedtls/entropy.h" + +/** \brief Configure entropy sources. + * + * This function may only be called before a call to psa_crypto_init(), + * or after a call to mbedtls_psa_crypto_free() and before any + * subsequent call to psa_crypto_init(). + * + * This function is only intended for test purposes. The functionality + * it provides is also useful for system integrators, but + * system integrators should configure entropy drivers instead of + * breaking through to the Mbed TLS API. + * + * \param entropy_init Function to initialize the entropy context + * and set up the desired entropy sources. + * It is called by psa_crypto_init(). + * By default this is mbedtls_entropy_init(). + * This function cannot report failures directly. + * To indicate a failure, set the entropy context + * to a state where mbedtls_entropy_func() will + * return an error. + * \param entropy_free Function to free the entropy context + * and associated resources. + * It is called by mbedtls_psa_crypto_free(). + * By default this is mbedtls_entropy_free(). + * + * \retval PSA_SUCCESS + * Success. + * \retval PSA_ERROR_NOT_PERMITTED + * The caller does not have the permission to configure + * entropy sources. + * \retval PSA_ERROR_BAD_STATE + * The library has already been initialized. + */ +psa_status_t mbedtls_psa_crypto_configure_entropy_sources( + void (* entropy_init )( mbedtls_entropy_context *ctx ), + void (* entropy_free )( mbedtls_entropy_context *ctx ) ); + +#endif /* PSA_CRYPTO_INVASIVE_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_its.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_its.h new file mode 100644 index 0000000..3809787 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_its.h @@ -0,0 +1,144 @@ +/** \file psa_crypto_its.h + * \brief Interface of trusted storage that crypto is built on. + */ +/* Copyright (C) 2019, ARM Limited, 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 PSA_CRYPTO_ITS_H +#define PSA_CRYPTO_ITS_H + +#include +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \brief Flags used when creating a data entry + */ +typedef uint32_t psa_storage_create_flags_t; + +/** \brief A type for UIDs used for identifying data + */ +typedef uint64_t psa_storage_uid_t; + +#define PSA_STORAGE_FLAG_NONE 0 /**< No flags to pass */ +#define PSA_STORAGE_FLAG_WRITE_ONCE (1 << 0) /**< The data associated with the uid will not be able to be modified or deleted. Intended to be used to set bits in `psa_storage_create_flags_t`*/ + +/** + * \brief A container for metadata associated with a specific uid + */ +struct psa_storage_info_t +{ + uint32_t size; /**< The size of the data associated with a uid **/ + psa_storage_create_flags_t flags; /**< The flags set when the uid was created **/ +}; + +/** Flag indicating that \ref psa_storage_create and \ref psa_storage_set_extended are supported */ +#define PSA_STORAGE_SUPPORT_SET_EXTENDED (1 << 0) + +/** \brief PSA storage specific error codes + */ +#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) +#define PSA_ERROR_DATA_CORRUPT ((psa_status_t)-152) + +#define PSA_ITS_API_VERSION_MAJOR 1 /**< The major version number of the PSA ITS API. It will be incremented on significant updates that may include breaking changes */ +#define PSA_ITS_API_VERSION_MINOR 1 /**< The minor version number of the PSA ITS API. It will be incremented in small updates that are unlikely to include breaking changes */ + +/** + * \brief create a new or modify an existing uid/value pair + * + * \param[in] uid the identifier for the data + * \param[in] data_length The size in bytes of the data in `p_data` + * \param[in] p_data A buffer containing the data + * \param[in] create_flags The flags that the data will be stored with + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the provided `uid` value was already created with PSA_STORAGE_WRITE_ONCE_FLAG + * \retval PSA_ERROR_NOT_SUPPORTED The operation failed because one or more of the flags provided in `create_flags` is not supported or is not valid + * \retval PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because there was insufficient space on the storage medium + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_data`) + * is invalid, for example is `NULL` or references memory the caller cannot access + */ +psa_status_t psa_its_set(psa_storage_uid_t uid, + uint32_t data_length, + const void *p_data, + psa_storage_create_flags_t create_flags); + +/** + * \brief Retrieve the value associated with a provided uid + * + * \param[in] uid The uid value + * \param[in] data_offset The starting offset of the data requested + * \param[in] data_length the amount of data requested (and the minimum allocated size of the `p_data` buffer) + * \param[out] p_data The buffer where the data will be placed upon successful completion + * \param[out] p_data_length The amount of data returned in the p_data buffer + * + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided `uid` value was not found in the storage + * \retval PSA_ERROR_INVALID_SIZE The operation failed because the data associated with provided uid is larger than `data_size` + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_data`, `p_data_length`) + * is invalid. For example is `NULL` or references memory the caller cannot access. + * In addition, this can also happen if an invalid offset was provided. + */ +psa_status_t psa_its_get(psa_storage_uid_t uid, + uint32_t data_offset, + uint32_t data_length, + void *p_data, + size_t *p_data_length ); + +/** + * \brief Retrieve the metadata about the provided uid + * + * \param[in] uid The uid value + * \param[out] p_info A pointer to the `psa_storage_info_t` struct that will be populated with the metadata + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided uid value was not found in the storage + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_info`) + * is invalid, for example is `NULL` or references memory the caller cannot access + */ +psa_status_t psa_its_get_info(psa_storage_uid_t uid, + struct psa_storage_info_t *p_info); + +/** + * \brief Remove the provided key and its associated data from the storage + * + * \param[in] uid The uid value + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided key value was not found in the storage + * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the provided key value was created with PSA_STORAGE_WRITE_ONCE_FLAG + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + */ +psa_status_t psa_its_remove(psa_storage_uid_t uid); + +#endif /* PSA_CRYPTO_ITS_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_se.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_se.c new file mode 100644 index 0000000..b7fa0c5 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_se.c @@ -0,0 +1,388 @@ +/* + * PSA crypto support for secure element drivers + */ +/* Copyright (C) 2019, ARM Limited, 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. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + +#include +#include +#include + +#include "psa/crypto_se_driver.h" + +#include "psa_crypto_se.h" + +#if defined(MBEDTLS_PSA_ITS_FILE_C) +#include "psa_crypto_its.h" +#else /* Native ITS implementation */ +#include "psa/error.h" +#include "psa/internal_trusted_storage.h" +#endif + +#include "mbedtls/platform.h" +#if !defined(MBEDTLS_PLATFORM_C) +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + + + +/****************************************************************/ +/* Driver lookup */ +/****************************************************************/ + +/* This structure is identical to psa_drv_se_context_t declared in + * `crypto_se_driver.h`, except that some parts are writable here + * (non-const, or pointer to non-const). */ +typedef struct +{ + void *persistent_data; + size_t persistent_data_size; + uintptr_t transient_data; +} psa_drv_se_internal_context_t; + +typedef struct psa_se_drv_table_entry_s +{ + psa_key_lifetime_t lifetime; + const psa_drv_se_t *methods; + union + { + psa_drv_se_internal_context_t internal; + psa_drv_se_context_t context; + }; +} psa_se_drv_table_entry_t; + +static psa_se_drv_table_entry_t driver_table[PSA_MAX_SE_DRIVERS]; + +psa_se_drv_table_entry_t *psa_get_se_driver_entry( + psa_key_lifetime_t lifetime ) +{ + size_t i; + /* In the driver table, lifetime=0 means an entry that isn't used. + * No driver has a lifetime of 0 because it's a reserved value + * (which designates volatile keys). Make sure we never return + * a driver entry for lifetime 0. */ + if( lifetime == 0 ) + return( NULL ); + for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ ) + { + if( driver_table[i].lifetime == lifetime ) + return( &driver_table[i] ); + } + return( NULL ); +} + +const psa_drv_se_t *psa_get_se_driver_methods( + const psa_se_drv_table_entry_t *driver ) +{ + return( driver->methods ); +} + +psa_drv_se_context_t *psa_get_se_driver_context( + psa_se_drv_table_entry_t *driver ) +{ + return( &driver->context ); +} + +int psa_get_se_driver( psa_key_lifetime_t lifetime, + const psa_drv_se_t **p_methods, + psa_drv_se_context_t **p_drv_context) +{ + psa_se_drv_table_entry_t *driver = psa_get_se_driver_entry( lifetime ); + if( p_methods != NULL ) + *p_methods = ( driver ? driver->methods : NULL ); + if( p_drv_context != NULL ) + *p_drv_context = ( driver ? &driver->context : NULL ); + return( driver != NULL ); +} + + + +/****************************************************************/ +/* Persistent data management */ +/****************************************************************/ + +static psa_status_t psa_get_se_driver_its_file_uid( + const psa_se_drv_table_entry_t *driver, + psa_storage_uid_t *uid ) +{ + if( driver->lifetime > PSA_MAX_SE_LIFETIME ) + return( PSA_ERROR_NOT_SUPPORTED ); + +#if SIZE_MAX > UINT32_MAX + /* ITS file sizes are limited to 32 bits. */ + if( driver->internal.persistent_data_size > UINT32_MAX ) + return( PSA_ERROR_NOT_SUPPORTED ); +#endif + + /* See the documentation of PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE. */ + *uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + driver->lifetime; + return( PSA_SUCCESS ); +} + +psa_status_t psa_load_se_persistent_data( + const psa_se_drv_table_entry_t *driver ) +{ + psa_status_t status; + psa_storage_uid_t uid; + size_t length; + + status = psa_get_se_driver_its_file_uid( driver, &uid ); + if( status != PSA_SUCCESS ) + return( status ); + + /* Read the amount of persistent data that the driver requests. + * If the data in storage is larger, it is truncated. If the data + * in storage is smaller, silently keep what is already at the end + * of the output buffer. */ + /* psa_get_se_driver_its_file_uid ensures that the size_t + * persistent_data_size is in range, but compilers don't know that, + * so cast to reassure them. */ + return( psa_its_get( uid, 0, + (uint32_t) driver->internal.persistent_data_size, + driver->internal.persistent_data, + &length ) ); +} + +psa_status_t psa_save_se_persistent_data( + const psa_se_drv_table_entry_t *driver ) +{ + psa_status_t status; + psa_storage_uid_t uid; + + status = psa_get_se_driver_its_file_uid( driver, &uid ); + if( status != PSA_SUCCESS ) + return( status ); + + /* psa_get_se_driver_its_file_uid ensures that the size_t + * persistent_data_size is in range, but compilers don't know that, + * so cast to reassure them. */ + return( psa_its_set( uid, + (uint32_t) driver->internal.persistent_data_size, + driver->internal.persistent_data, + 0 ) ); +} + +psa_status_t psa_destroy_se_persistent_data( psa_key_lifetime_t lifetime ) +{ + psa_storage_uid_t uid; + if( lifetime > PSA_MAX_SE_LIFETIME ) + return( PSA_ERROR_NOT_SUPPORTED ); + uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + lifetime; + return( psa_its_remove( uid ) ); +} + +psa_status_t psa_find_se_slot_for_key( + const psa_key_attributes_t *attributes, + psa_key_creation_method_t method, + psa_se_drv_table_entry_t *driver, + psa_key_slot_number_t *slot_number ) +{ + psa_status_t status; + + /* If the lifetime is wrong, it's a bug in the library. */ + if( driver->lifetime != psa_get_key_lifetime( attributes ) ) + return( PSA_ERROR_CORRUPTION_DETECTED ); + + /* If the driver doesn't support key creation in any way, give up now. */ + if( driver->methods->key_management == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + + if( psa_get_key_slot_number( attributes, slot_number ) == PSA_SUCCESS ) + { + /* The application wants to use a specific slot. Allow it if + * the driver supports it. On a system with isolation, + * the crypto service must check that the application is + * permitted to request this slot. */ + psa_drv_se_validate_slot_number_t p_validate_slot_number = + driver->methods->key_management->p_validate_slot_number; + if( p_validate_slot_number == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + status = p_validate_slot_number( &driver->context, + driver->internal.persistent_data, + attributes, method, + *slot_number ); + } + else if( method == PSA_KEY_CREATION_REGISTER ) + { + /* The application didn't specify a slot number. This doesn't + * make sense when registering a slot. */ + return( PSA_ERROR_INVALID_ARGUMENT ); + } + else + { + /* The application didn't tell us which slot to use. Let the driver + * choose. This is the normal case. */ + psa_drv_se_allocate_key_t p_allocate = + driver->methods->key_management->p_allocate; + if( p_allocate == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + status = p_allocate( &driver->context, + driver->internal.persistent_data, + attributes, method, + slot_number ); + } + return( status ); +} + +psa_status_t psa_destroy_se_key( psa_se_drv_table_entry_t *driver, + psa_key_slot_number_t slot_number ) +{ + psa_status_t status; + psa_status_t storage_status; + /* Normally a missing method would mean that the action is not + * supported. But psa_destroy_key() is not supposed to return + * PSA_ERROR_NOT_SUPPORTED: if you can create a key, you should + * be able to destroy it. The only use case for a driver that + * does not have a way to destroy keys at all is if the keys are + * locked in a read-only state: we can use the keys but not + * destroy them. Hence, if the driver doesn't support destroying + * keys, it's really a lack of permission. */ + if( driver->methods->key_management == NULL || + driver->methods->key_management->p_destroy == NULL ) + return( PSA_ERROR_NOT_PERMITTED ); + status = driver->methods->key_management->p_destroy( + &driver->context, + driver->internal.persistent_data, + slot_number ); + storage_status = psa_save_se_persistent_data( driver ); + return( status == PSA_SUCCESS ? storage_status : status ); +} + +psa_status_t psa_init_all_se_drivers( void ) +{ + size_t i; + for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ ) + { + psa_se_drv_table_entry_t *driver = &driver_table[i]; + if( driver->lifetime == 0 ) + continue; /* skipping unused entry */ + const psa_drv_se_t *methods = psa_get_se_driver_methods( driver ); + if( methods->p_init != NULL ) + { + psa_status_t status = methods->p_init( + &driver->context, + driver->internal.persistent_data, + driver->lifetime ); + if( status != PSA_SUCCESS ) + return( status ); + status = psa_save_se_persistent_data( driver ); + if( status != PSA_SUCCESS ) + return( status ); + } + } + return( PSA_SUCCESS ); +} + + + +/****************************************************************/ +/* Driver registration */ +/****************************************************************/ + +psa_status_t psa_register_se_driver( + psa_key_lifetime_t lifetime, + const psa_drv_se_t *methods) +{ + size_t i; + psa_status_t status; + + if( methods->hal_version != PSA_DRV_SE_HAL_VERSION ) + return( PSA_ERROR_NOT_SUPPORTED ); + /* Driver table entries are 0-initialized. 0 is not a valid driver + * lifetime because it means a volatile key. */ +#if defined(static_assert) + static_assert( PSA_KEY_LIFETIME_VOLATILE == 0, + "Secure element support requires 0 to mean a volatile key" ); +#endif + if( lifetime == PSA_KEY_LIFETIME_VOLATILE || + lifetime == PSA_KEY_LIFETIME_PERSISTENT ) + { + return( PSA_ERROR_INVALID_ARGUMENT ); + } + if( lifetime > PSA_MAX_SE_LIFETIME ) + return( PSA_ERROR_NOT_SUPPORTED ); + + for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ ) + { + if( driver_table[i].lifetime == 0 ) + break; + /* Check that lifetime isn't already in use up to the first free + * entry. Since entries are created in order and never deleted, + * there can't be a used entry after the first free entry. */ + if( driver_table[i].lifetime == lifetime ) + return( PSA_ERROR_ALREADY_EXISTS ); + } + if( i == PSA_MAX_SE_DRIVERS ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + + driver_table[i].lifetime = lifetime; + driver_table[i].methods = methods; + driver_table[i].internal.persistent_data_size = + methods->persistent_data_size; + + if( methods->persistent_data_size != 0 ) + { + driver_table[i].internal.persistent_data = + mbedtls_calloc( 1, methods->persistent_data_size ); + if( driver_table[i].internal.persistent_data == NULL ) + { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto error; + } + /* Load the driver's persistent data. On first use, the persistent + * data does not exist in storage, and is initialized to + * all-bits-zero by the calloc call just above. */ + status = psa_load_se_persistent_data( &driver_table[i] ); + if( status != PSA_SUCCESS && status != PSA_ERROR_DOES_NOT_EXIST ) + goto error; + } + + return( PSA_SUCCESS ); + +error: + memset( &driver_table[i], 0, sizeof( driver_table[i] ) ); + return( status ); +} + +void psa_unregister_all_se_drivers( void ) +{ + size_t i; + for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ ) + { + if( driver_table[i].internal.persistent_data != NULL ) + mbedtls_free( driver_table[i].internal.persistent_data ); + } + memset( driver_table, 0, sizeof( driver_table ) ); +} + + + +/****************************************************************/ +/* The end */ +/****************************************************************/ + +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_se.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_se.h new file mode 100644 index 0000000..86bf7a7 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_se.h @@ -0,0 +1,190 @@ +/* + * PSA crypto support for secure element drivers + */ +/* Copyright (C) 2019, ARM Limited, 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. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef PSA_CRYPTO_SE_H +#define PSA_CRYPTO_SE_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "psa/crypto.h" +#include "psa/crypto_se_driver.h" + +/** The maximum lifetime value that this implementation supports + * for a secure element. + * + * This is not a characteristic that each PSA implementation has, but a + * limitation of the current implementation due to the constraints imposed + * by storage. See #PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE. + * + * The minimum lifetime value for a secure element is 2, like on any + * PSA implementation (0=volatile and 1=internal-storage are taken). + */ +#define PSA_MAX_SE_LIFETIME 255 + +/** The base of the range of ITS file identifiers for secure element + * driver persistent data. + * + * We use a slice of the implemenation reserved range 0xffff0000..0xffffffff, + * specifically the range 0xfffffe00..0xfffffeff. The length of this range + * drives the value of #PSA_MAX_SE_LIFETIME. + * The identifiers 0xfffffe00 and 0xfffffe01 are actually not used since + * they correspond to #PSA_KEY_LIFETIME_VOLATILE and + * #PSA_KEY_LIFETIME_PERSISTENT which don't have a driver. + */ +#define PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE ( (psa_key_id_t) 0xfffffe00 ) + +/** The maximum number of registered secure element driver lifetimes. */ +#define PSA_MAX_SE_DRIVERS 4 + +/** Unregister all secure element drivers. + * + * \warning Do not call this function while the library is in the initialized + * state. This function is only intended to be called at the end + * of mbedtls_psa_crypto_free(). + */ +void psa_unregister_all_se_drivers( void ); + +/** Initialize all secure element drivers. + * + * Called from psa_crypto_init(). + */ +psa_status_t psa_init_all_se_drivers( void ); + +/** A structure that describes a registered secure element driver. + * + * A secure element driver table entry contains a pointer to the + * driver's method table as well as the driver context structure. + */ +typedef struct psa_se_drv_table_entry_s psa_se_drv_table_entry_t; + +/** Return the secure element driver information for a lifetime value. + * + * \param lifetime The lifetime value to query. + * \param[out] p_methods On output, if there is a driver, + * \c *methods points to its method table. + * Otherwise \c *methods is \c NULL. + * \param[out] p_drv_context On output, if there is a driver, + * \c *drv_context points to its context + * structure. + * Otherwise \c *drv_context is \c NULL. + * + * \retval 1 + * \p lifetime corresponds to a registered driver. + * \retval 0 + * \p lifetime does not correspond to a registered driver. + */ +int psa_get_se_driver( psa_key_lifetime_t lifetime, + const psa_drv_se_t **p_methods, + psa_drv_se_context_t **p_drv_context); + +/** Return the secure element driver table entry for a lifetime value. + * + * \param lifetime The lifetime value to query. + * + * \return The driver table entry for \p lifetime, or + * \p NULL if \p lifetime does not correspond to a registered driver. + */ +psa_se_drv_table_entry_t *psa_get_se_driver_entry( + psa_key_lifetime_t lifetime ); + +/** Return the method table for a secure element driver. + * + * \param[in] driver The driver table entry to access, or \c NULL. + * + * \return The driver's method table. + * \c NULL if \p driver is \c NULL. + */ +const psa_drv_se_t *psa_get_se_driver_methods( + const psa_se_drv_table_entry_t *driver ); + +/** Return the context of a secure element driver. + * + * \param[in] driver The driver table entry to access, or \c NULL. + * + * \return A pointer to the driver context. + * \c NULL if \p driver is \c NULL. + */ +psa_drv_se_context_t *psa_get_se_driver_context( + psa_se_drv_table_entry_t *driver ); + +/** Find a free slot for a key that is to be created. + * + * This function calls the relevant method in the driver to find a suitable + * slot for a key with the given attributes. + * + * \param[in] attributes Metadata about the key that is about to be created. + * \param[in] driver The driver table entry to query. + * \param[out] slot_number On success, a slot number that is free in this + * secure element. + */ +psa_status_t psa_find_se_slot_for_key( + const psa_key_attributes_t *attributes, + psa_key_creation_method_t method, + psa_se_drv_table_entry_t *driver, + psa_key_slot_number_t *slot_number ); + +/** Destoy a key in a secure element. + * + * This function calls the relevant driver method to destroy a key + * and updates the driver's persistent data. + */ +psa_status_t psa_destroy_se_key( psa_se_drv_table_entry_t *driver, + psa_key_slot_number_t slot_number ); + +/** Load the persistent data of a secure element driver. + * + * \param driver The driver table entry containing the persistent + * data to load from storage. + */ +psa_status_t psa_load_se_persistent_data( + const psa_se_drv_table_entry_t *driver ); + +/** Save the persistent data of a secure element driver. + * + * \param[in] driver The driver table entry containing the persistent + * data to save to storage. + */ +psa_status_t psa_save_se_persistent_data( + const psa_se_drv_table_entry_t *driver ); + +/** Destroy the persistent data of a secure element driver. + * + * This is currently only used for testing. + * + * \param[in] lifetime The driver lifetime whose persistent data should + * be erased. + */ +psa_status_t psa_destroy_se_persistent_data( psa_key_lifetime_t lifetime ); + + +/** The storage representation of a key whose data is in a secure element. + */ +typedef struct +{ + uint8_t slot_number[sizeof( psa_key_slot_number_t )]; + uint8_t bits[sizeof( psa_key_bits_t )]; +} psa_se_key_data_storage_t; + +#endif /* PSA_CRYPTO_SE_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_service_integration.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_service_integration.h new file mode 100644 index 0000000..938bfe1 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_service_integration.h @@ -0,0 +1,40 @@ +/* Copyright (C) 2019, ARM Limited, 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef PSA_CRYPTO_SERVICE_INTEGRATION_H +#define PSA_CRYPTO_SERVICE_INTEGRATION_H + +/* + * When MBEDTLS_PSA_CRYPTO_SPM is defined, the code is being built for SPM + * (Secure Partition Manager) integration which separates the code into two + * parts: NSPE (Non-Secure Processing Environment) and SPE (Secure Processing + * Environment). When building for the SPE, an additional header file should be + * included. + */ +#if defined(MBEDTLS_PSA_CRYPTO_SPM) +/* + * PSA_CRYPTO_SECURE means that the file which included this file is being + * compiled for SPE. The files crypto_structs.h and crypto_types.h have + * different implementations for NSPE and SPE and are compiled according to this + * flag. + */ +#define PSA_CRYPTO_SECURE 1 +#include "crypto_spe.h" +#endif // MBEDTLS_PSA_CRYPTO_SPM + +#endif // PSA_CRYPTO_SERVICE_INTEGRATION_H diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_slot_management.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_slot_management.c new file mode 100644 index 0000000..6cd6a11 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_slot_management.c @@ -0,0 +1,299 @@ +/* + * PSA crypto layer on top of Mbed TLS crypto + */ +/* Copyright (C) 2018, ARM Limited, 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +#include "psa_crypto_service_integration.h" +#include "psa/crypto.h" + +#include "psa_crypto_core.h" +#include "psa_crypto_slot_management.h" +#include "psa_crypto_storage.h" +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +#include "psa_crypto_se.h" +#endif + +#include +#include +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#define ARRAY_LENGTH( array ) ( sizeof( array ) / sizeof( *( array ) ) ) + +typedef struct +{ + psa_key_slot_t key_slots[PSA_KEY_SLOT_COUNT]; + unsigned key_slots_initialized : 1; +} psa_global_data_t; + +static psa_global_data_t global_data; + +/* Access a key slot at the given handle. The handle of a key slot is + * the index of the slot in the global slot array, plus one so that handles + * start at 1 and not 0. */ +psa_status_t psa_get_key_slot( psa_key_handle_t handle, + psa_key_slot_t **p_slot ) +{ + psa_key_slot_t *slot = NULL; + + if( ! global_data.key_slots_initialized ) + return( PSA_ERROR_BAD_STATE ); + + /* 0 is not a valid handle under any circumstance. This + * implementation provides slots number 1 to N where N is the + * number of available slots. */ + if( handle == 0 || handle > ARRAY_LENGTH( global_data.key_slots ) ) + return( PSA_ERROR_INVALID_HANDLE ); + slot = &global_data.key_slots[handle - 1]; + + /* If the slot isn't occupied, the handle is invalid. */ + if( ! psa_is_key_slot_occupied( slot ) ) + return( PSA_ERROR_INVALID_HANDLE ); + + *p_slot = slot; + return( PSA_SUCCESS ); +} + +psa_status_t psa_initialize_key_slots( void ) +{ + /* Nothing to do: program startup and psa_wipe_all_key_slots() both + * guarantee that the key slots are initialized to all-zero, which + * means that all the key slots are in a valid, empty state. */ + global_data.key_slots_initialized = 1; + return( PSA_SUCCESS ); +} + +void psa_wipe_all_key_slots( void ) +{ + psa_key_handle_t key; + for( key = 1; key <= PSA_KEY_SLOT_COUNT; key++ ) + { + psa_key_slot_t *slot = &global_data.key_slots[key - 1]; + (void) psa_wipe_key_slot( slot ); + } + global_data.key_slots_initialized = 0; +} + +psa_status_t psa_get_empty_key_slot( psa_key_handle_t *handle, + psa_key_slot_t **p_slot ) +{ + if( ! global_data.key_slots_initialized ) + return( PSA_ERROR_BAD_STATE ); + + for( *handle = PSA_KEY_SLOT_COUNT; *handle != 0; --( *handle ) ) + { + *p_slot = &global_data.key_slots[*handle - 1]; + if( ! psa_is_key_slot_occupied( *p_slot ) ) + return( PSA_SUCCESS ); + } + *p_slot = NULL; + return( PSA_ERROR_INSUFFICIENT_MEMORY ); +} + +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) +static psa_status_t psa_load_persistent_key_into_slot( psa_key_slot_t *slot ) +{ + psa_status_t status = PSA_SUCCESS; + uint8_t *key_data = NULL; + size_t key_data_length = 0; + + status = psa_load_persistent_key( &slot->attr, + &key_data, &key_data_length ); + if( status != PSA_SUCCESS ) + goto exit; + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if( psa_key_lifetime_is_external( slot->attr.lifetime ) ) + { + psa_se_key_data_storage_t *data; + if( key_data_length != sizeof( *data ) ) + { + status = PSA_ERROR_STORAGE_FAILURE; + goto exit; + } + data = (psa_se_key_data_storage_t *) key_data; + memcpy( &slot->data.se.slot_number, &data->slot_number, + sizeof( slot->data.se.slot_number ) ); + memcpy( &slot->attr.bits, &data->bits, + sizeof( slot->attr.bits ) ); + } + else +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + { + status = psa_import_key_into_slot( slot, key_data, key_data_length ); + } + +exit: + psa_free_persistent_key_data( key_data, key_data_length ); + return( status ); +} + +/** Check whether a key identifier is acceptable. + * + * For backward compatibility, key identifiers that were valid in a + * past released version must remain valid, unless a migration path + * is provided. + * + * \param file_id The key identifier to check. + * \param vendor_ok Nonzero to allow key ids in the vendor range. + * 0 to allow only key ids in the application range. + * + * \return 1 if \p file_id is acceptable, otherwise 0. + */ +static int psa_is_key_id_valid( psa_key_file_id_t file_id, + int vendor_ok ) +{ + psa_app_key_id_t key_id = PSA_KEY_FILE_GET_KEY_ID( file_id ); + if( PSA_KEY_ID_USER_MIN <= key_id && key_id <= PSA_KEY_ID_USER_MAX ) + return( 1 ); + else if( vendor_ok && + PSA_KEY_ID_VENDOR_MIN <= key_id && + key_id <= PSA_KEY_ID_VENDOR_MAX ) + return( 1 ); + else + return( 0 ); +} +#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ + +psa_status_t psa_validate_persistent_key_parameters( + psa_key_lifetime_t lifetime, + psa_key_file_id_t id, + psa_se_drv_table_entry_t **p_drv, + int creating ) +{ + if( p_drv != NULL ) + *p_drv = NULL; +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if( psa_key_lifetime_is_external( lifetime ) ) + { + *p_drv = psa_get_se_driver_entry( lifetime ); + if( *p_drv == NULL ) + return( PSA_ERROR_INVALID_ARGUMENT ); + } + else +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + if( lifetime != PSA_KEY_LIFETIME_PERSISTENT ) + return( PSA_ERROR_INVALID_ARGUMENT ); + +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) + if( ! psa_is_key_id_valid( id, ! creating ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + return( PSA_SUCCESS ); + +#else /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ + (void) id; + (void) creating; + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* !MBEDTLS_PSA_CRYPTO_STORAGE_C */ +} + +psa_status_t psa_open_key( psa_key_file_id_t id, psa_key_handle_t *handle ) +{ +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) + psa_status_t status; + psa_key_slot_t *slot; + + *handle = 0; + + status = psa_validate_persistent_key_parameters( + PSA_KEY_LIFETIME_PERSISTENT, id, NULL, 0 ); + if( status != PSA_SUCCESS ) + return( status ); + + status = psa_get_empty_key_slot( handle, &slot ); + if( status != PSA_SUCCESS ) + return( status ); + + slot->attr.lifetime = PSA_KEY_LIFETIME_PERSISTENT; + slot->attr.id = id; + + status = psa_load_persistent_key_into_slot( slot ); + if( status != PSA_SUCCESS ) + { + psa_wipe_key_slot( slot ); + *handle = 0; + } + return( status ); + +#else /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ + (void) id; + *handle = 0; + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* !defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ +} + +psa_status_t psa_close_key( psa_key_handle_t handle ) +{ + psa_status_t status; + psa_key_slot_t *slot; + + if( handle == 0 ) + return( PSA_SUCCESS ); + + status = psa_get_key_slot( handle, &slot ); + if( status != PSA_SUCCESS ) + return( status ); + + return( psa_wipe_key_slot( slot ) ); +} + +void mbedtls_psa_get_stats( mbedtls_psa_stats_t *stats ) +{ + psa_key_handle_t key; + memset( stats, 0, sizeof( *stats ) ); + for( key = 1; key <= PSA_KEY_SLOT_COUNT; key++ ) + { + const psa_key_slot_t *slot = &global_data.key_slots[key - 1]; + if( ! psa_is_key_slot_occupied( slot ) ) + { + ++stats->empty_slots; + continue; + } + if( slot->attr.lifetime == PSA_KEY_LIFETIME_VOLATILE ) + ++stats->volatile_slots; + else if( slot->attr.lifetime == PSA_KEY_LIFETIME_PERSISTENT ) + { + psa_app_key_id_t id = PSA_KEY_FILE_GET_KEY_ID(slot->attr.id); + ++stats->persistent_slots; + if( id > stats->max_open_internal_key_id ) + stats->max_open_internal_key_id = id; + } + else + { + psa_app_key_id_t id = PSA_KEY_FILE_GET_KEY_ID(slot->attr.id); + ++stats->external_slots; + if( id > stats->max_open_external_key_id ) + stats->max_open_external_key_id = id; + } + } +} + +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_slot_management.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_slot_management.h new file mode 100644 index 0000000..472253d --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_slot_management.h @@ -0,0 +1,129 @@ +/* + * PSA crypto layer on top of Mbed TLS crypto + */ +/* Copyright (C) 2018, ARM Limited, 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef PSA_CRYPTO_SLOT_MANAGEMENT_H +#define PSA_CRYPTO_SLOT_MANAGEMENT_H + +#include "psa/crypto.h" +#include "psa_crypto_se.h" + +/* Number of key slots (plus one because 0 is not used). + * The value is a compile-time constant for now, for simplicity. */ +#define PSA_KEY_SLOT_COUNT 32 + +/** Access a key slot at the given handle. + * + * \param handle Key handle to query. + * \param[out] p_slot On success, `*p_slot` contains a pointer to the + * key slot in memory designated by \p handle. + * + * \retval PSA_SUCCESS + * Success: \p handle is a handle to `*p_slot`. Note that `*p_slot` + * may be empty or occupied. + * \retval PSA_ERROR_INVALID_HANDLE + * \p handle is out of range or is not in use. + * \retval PSA_ERROR_BAD_STATE + * The library has not been initialized. + */ +psa_status_t psa_get_key_slot( psa_key_handle_t handle, + psa_key_slot_t **p_slot ); + +/** Initialize the key slot structures. + * + * \retval PSA_SUCCESS + * Currently this function always succeeds. + */ +psa_status_t psa_initialize_key_slots( void ); + +/** Delete all data from key slots in memory. + * + * This does not affect persistent storage. */ +void psa_wipe_all_key_slots( void ); + +/** Find a free key slot. + * + * This function returns a key slot that is available for use and is in its + * ground state (all-bits-zero). + * + * \param[out] handle On success, a slot number that can be used as a + * handle to the slot. + * \param[out] p_slot On success, a pointer to the slot. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BAD_STATE + */ +psa_status_t psa_get_empty_key_slot( psa_key_handle_t *handle, + psa_key_slot_t **p_slot ); + +/** Test whether a lifetime designates a key in an external cryptoprocessor. + * + * \param lifetime The lifetime to test. + * + * \retval 1 + * The lifetime designates an external key. There should be a + * registered driver for this lifetime, otherwise the key cannot + * be created or manipulated. + * \retval 0 + * The lifetime designates a key that is volatile or in internal + * storage. + */ +static inline int psa_key_lifetime_is_external( psa_key_lifetime_t lifetime ) +{ + return( lifetime != PSA_KEY_LIFETIME_VOLATILE && + lifetime != PSA_KEY_LIFETIME_PERSISTENT ); +} + +/** Test whether the given parameters are acceptable for a persistent key. + * + * This function does not access the storage in any way. It only tests + * whether the parameters are meaningful and permitted by general policy. + * It does not test whether the a file by the given id exists or could be + * created. + * + * If the key is in external storage, this function returns the corresponding + * driver. + * + * \param lifetime The lifetime to test. + * \param id The key id to test. + * \param[out] p_drv On output, if \p lifetime designates a key + * in an external processor, \c *p_drv is a pointer + * to the driver table entry fot this lifetime. + * If \p lifetime designates a transparent key, + * \c *p_drv is \c NULL. + * \param creating 0 if attempting to open an existing key. + * Nonzero if attempting to create a key. + * + * \retval PSA_SUCCESS + * The given parameters are valid. + * \retval PSA_ERROR_INVALID_ARGUMENT + * \p lifetime is volatile or is invalid. + * \retval PSA_ERROR_INVALID_ARGUMENT + * \p id is invalid. + */ +psa_status_t psa_validate_persistent_key_parameters( + psa_key_lifetime_t lifetime, + psa_key_file_id_t id, + psa_se_drv_table_entry_t **p_drv, + int creating ); + + +#endif /* PSA_CRYPTO_SLOT_MANAGEMENT_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_storage.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_storage.c new file mode 100644 index 0000000..fa1214c --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_storage.c @@ -0,0 +1,504 @@ +/* + * PSA persistent key storage + */ +/* Copyright (C) 2018, ARM Limited, 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if defined(MBEDTLS_CONFIG_FILE) +#include MBEDTLS_CONFIG_FILE +#else +#include "mbedtls/config.h" +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) + +#include +#include + +#include "psa_crypto_service_integration.h" +#include "psa/crypto.h" +#include "psa_crypto_storage.h" +#include "mbedtls/platform_util.h" + +#if defined(MBEDTLS_PSA_ITS_FILE_C) +#include "psa_crypto_its.h" +#else /* Native ITS implementation */ +#include "psa/error.h" +#include "psa/internal_trusted_storage.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + + + +/****************************************************************/ +/* Key storage */ +/****************************************************************/ + +/* Determine a file name (ITS file identifier) for the given key file + * identifier. The file name must be distinct from any file that is used + * for a purpose other than storing a key. Currently, the only such file + * is the random seed file whose name is PSA_CRYPTO_ITS_RANDOM_SEED_UID + * and whose value is 0xFFFFFF52. */ +static psa_storage_uid_t psa_its_identifier_of_slot( psa_key_file_id_t file_id ) +{ +#if defined(MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER) && \ + defined(PSA_CRYPTO_SECURE) + /* Encode the owner in the upper 32 bits. This means that if + * owner values are nonzero (as they are on a PSA platform), + * no key file will ever have a value less than 0x100000000, so + * the whole range 0..0xffffffff is available for non-key files. */ + uint32_t unsigned_owner = (uint32_t) file_id.owner; + return( (uint64_t) unsigned_owner << 32 | file_id.key_id ); +#else + /* Use the key id directly as a file name. + * psa_is_key_file_id_valid() in psa_crypto_slot_management.c + * is responsible for ensuring that key identifiers do not have a + * value that is reserved for non-key files. */ + return( file_id ); +#endif +} + +/** + * \brief Load persistent data for the given key slot number. + * + * This function reads data from a storage backend and returns the data in a + * buffer. + * + * \param key Persistent identifier of the key to be loaded. This + * should be an occupied storage location. + * \param[out] data Buffer where the data is to be written. + * \param data_size Size of the \c data buffer in bytes. + * + * \retval PSA_SUCCESS + * \retval PSA_ERROR_STORAGE_FAILURE + * \retval PSA_ERROR_DOES_NOT_EXIST + */ +static psa_status_t psa_crypto_storage_load( const psa_key_file_id_t key, + uint8_t *data, + size_t data_size ) +{ + psa_status_t status; + psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key ); + struct psa_storage_info_t data_identifier_info; + size_t data_length = 0; + + status = psa_its_get_info( data_identifier, &data_identifier_info ); + if( status != PSA_SUCCESS ) + return( status ); + + status = psa_its_get( data_identifier, 0, (uint32_t) data_size, data, &data_length ); + if( data_size != data_length ) + return( PSA_ERROR_STORAGE_FAILURE ); + + return( status ); +} + +int psa_is_key_present_in_storage( const psa_key_file_id_t key ) +{ + psa_status_t ret; + psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key ); + struct psa_storage_info_t data_identifier_info; + + ret = psa_its_get_info( data_identifier, &data_identifier_info ); + + if( ret == PSA_ERROR_DOES_NOT_EXIST ) + return( 0 ); + return( 1 ); +} + +/** + * \brief Store persistent data for the given key slot number. + * + * This function stores the given data buffer to a persistent storage. + * + * \param key Persistent identifier of the key to be stored. This + * should be an unoccupied storage location. + * \param[in] data Buffer containing the data to be stored. + * \param data_length The number of bytes + * that make up the data. + * + * \retval PSA_SUCCESS + * \retval PSA_ERROR_INSUFFICIENT_STORAGE + * \retval PSA_ERROR_STORAGE_FAILURE + * \retval PSA_ERROR_ALREADY_EXISTS + */ +static psa_status_t psa_crypto_storage_store( const psa_key_file_id_t key, + const uint8_t *data, + size_t data_length ) +{ + psa_status_t status; + psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key ); + struct psa_storage_info_t data_identifier_info; + + if( psa_is_key_present_in_storage( key ) == 1 ) + return( PSA_ERROR_ALREADY_EXISTS ); + + status = psa_its_set( data_identifier, (uint32_t) data_length, data, 0 ); + if( status != PSA_SUCCESS ) + { + return( PSA_ERROR_STORAGE_FAILURE ); + } + + status = psa_its_get_info( data_identifier, &data_identifier_info ); + if( status != PSA_SUCCESS ) + { + goto exit; + } + + if( data_identifier_info.size != data_length ) + { + status = PSA_ERROR_STORAGE_FAILURE; + goto exit; + } + +exit: + if( status != PSA_SUCCESS ) + psa_its_remove( data_identifier ); + return( status ); +} + +psa_status_t psa_destroy_persistent_key( const psa_key_file_id_t key ) +{ + psa_status_t ret; + psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key ); + struct psa_storage_info_t data_identifier_info; + + ret = psa_its_get_info( data_identifier, &data_identifier_info ); + if( ret == PSA_ERROR_DOES_NOT_EXIST ) + return( PSA_SUCCESS ); + + if( psa_its_remove( data_identifier ) != PSA_SUCCESS ) + return( PSA_ERROR_STORAGE_FAILURE ); + + ret = psa_its_get_info( data_identifier, &data_identifier_info ); + if( ret != PSA_ERROR_DOES_NOT_EXIST ) + return( PSA_ERROR_STORAGE_FAILURE ); + + return( PSA_SUCCESS ); +} + +/** + * \brief Get data length for given key slot number. + * + * \param key Persistent identifier whose stored data length + * is to be obtained. + * \param[out] data_length The number of bytes that make up the data. + * + * \retval PSA_SUCCESS + * \retval PSA_ERROR_STORAGE_FAILURE + */ +static psa_status_t psa_crypto_storage_get_data_length( + const psa_key_file_id_t key, + size_t *data_length ) +{ + psa_status_t status; + psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key ); + struct psa_storage_info_t data_identifier_info; + + status = psa_its_get_info( data_identifier, &data_identifier_info ); + if( status != PSA_SUCCESS ) + return( status ); + + *data_length = (size_t) data_identifier_info.size; + + return( PSA_SUCCESS ); +} + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE( n, b, i ) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE( n, b, i ) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +/** + * Persistent key storage magic header. + */ +#define PSA_KEY_STORAGE_MAGIC_HEADER "PSA\0KEY" +#define PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH ( sizeof( PSA_KEY_STORAGE_MAGIC_HEADER ) ) + +typedef struct { + uint8_t magic[PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH]; + uint8_t version[4]; + uint8_t lifetime[sizeof( psa_key_lifetime_t )]; + uint8_t type[4]; /* Size=4 for a 2-byte type to keep the structure more + * regular and aligned and to make potential future + * extensibility easier. */ + uint8_t policy[sizeof( psa_key_policy_t )]; + uint8_t data_len[4]; + uint8_t key_data[]; +} psa_persistent_key_storage_format; + +void psa_format_key_data_for_storage( const uint8_t *data, + const size_t data_length, + const psa_core_key_attributes_t *attr, + uint8_t *storage_data ) +{ + psa_persistent_key_storage_format *storage_format = + (psa_persistent_key_storage_format *) storage_data; + + memcpy( storage_format->magic, PSA_KEY_STORAGE_MAGIC_HEADER, PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH ); + PUT_UINT32_LE( 0, storage_format->version, 0 ); + PUT_UINT32_LE( attr->lifetime, storage_format->lifetime, 0 ); + PUT_UINT32_LE( (uint32_t) attr->type, storage_format->type, 0 ); + PUT_UINT32_LE( attr->policy.usage, storage_format->policy, 0 ); + PUT_UINT32_LE( attr->policy.alg, storage_format->policy, sizeof( uint32_t ) ); + PUT_UINT32_LE( attr->policy.alg2, storage_format->policy, 2 * sizeof( uint32_t ) ); + PUT_UINT32_LE( data_length, storage_format->data_len, 0 ); + memcpy( storage_format->key_data, data, data_length ); +} + +static psa_status_t check_magic_header( const uint8_t *data ) +{ + if( memcmp( data, PSA_KEY_STORAGE_MAGIC_HEADER, + PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH ) != 0 ) + return( PSA_ERROR_STORAGE_FAILURE ); + return( PSA_SUCCESS ); +} + +psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data, + size_t storage_data_length, + uint8_t **key_data, + size_t *key_data_length, + psa_core_key_attributes_t *attr ) +{ + psa_status_t status; + const psa_persistent_key_storage_format *storage_format = + (const psa_persistent_key_storage_format *)storage_data; + uint32_t version; + uint32_t type; + + if( storage_data_length < sizeof(*storage_format) ) + return( PSA_ERROR_STORAGE_FAILURE ); + + status = check_magic_header( storage_data ); + if( status != PSA_SUCCESS ) + return( status ); + + GET_UINT32_LE( version, storage_format->version, 0 ); + if( version != 0 ) + return( PSA_ERROR_STORAGE_FAILURE ); + + GET_UINT32_LE( *key_data_length, storage_format->data_len, 0 ); + if( *key_data_length > ( storage_data_length - sizeof(*storage_format) ) || + *key_data_length > PSA_CRYPTO_MAX_STORAGE_SIZE ) + return( PSA_ERROR_STORAGE_FAILURE ); + + if( *key_data_length == 0 ) + { + *key_data = NULL; + } + else + { + *key_data = mbedtls_calloc( 1, *key_data_length ); + if( *key_data == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + memcpy( *key_data, storage_format->key_data, *key_data_length ); + } + + GET_UINT32_LE( attr->lifetime, storage_format->lifetime, 0 ); + GET_UINT32_LE( type, storage_format->type, 0 ); + if( type <= (psa_key_type_t) -1 ) + attr->type = (psa_key_type_t) type; + else + return( PSA_ERROR_STORAGE_FAILURE ); + GET_UINT32_LE( attr->policy.usage, storage_format->policy, 0 ); + GET_UINT32_LE( attr->policy.alg, storage_format->policy, sizeof( uint32_t ) ); + GET_UINT32_LE( attr->policy.alg2, storage_format->policy, 2 * sizeof( uint32_t ) ); + + return( PSA_SUCCESS ); +} + +psa_status_t psa_save_persistent_key( const psa_core_key_attributes_t *attr, + const uint8_t *data, + const size_t data_length ) +{ + size_t storage_data_length; + uint8_t *storage_data; + psa_status_t status; + + if( data_length > PSA_CRYPTO_MAX_STORAGE_SIZE ) + return PSA_ERROR_INSUFFICIENT_STORAGE; + storage_data_length = data_length + sizeof( psa_persistent_key_storage_format ); + + storage_data = mbedtls_calloc( 1, storage_data_length ); + if( storage_data == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + + psa_format_key_data_for_storage( data, data_length, attr, storage_data ); + + status = psa_crypto_storage_store( attr->id, + storage_data, storage_data_length ); + + mbedtls_free( storage_data ); + + return( status ); +} + +void psa_free_persistent_key_data( uint8_t *key_data, size_t key_data_length ) +{ + if( key_data != NULL ) + { + mbedtls_platform_zeroize( key_data, key_data_length ); + } + mbedtls_free( key_data ); +} + +psa_status_t psa_load_persistent_key( psa_core_key_attributes_t *attr, + uint8_t **data, + size_t *data_length ) +{ + psa_status_t status = PSA_SUCCESS; + uint8_t *loaded_data; + size_t storage_data_length = 0; + psa_key_id_t key = attr->id; + + status = psa_crypto_storage_get_data_length( key, &storage_data_length ); + if( status != PSA_SUCCESS ) + return( status ); + + loaded_data = mbedtls_calloc( 1, storage_data_length ); + + if( loaded_data == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + + status = psa_crypto_storage_load( key, loaded_data, storage_data_length ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_parse_key_data_from_storage( loaded_data, storage_data_length, + data, data_length, attr ); + +exit: + mbedtls_free( loaded_data ); + return( status ); +} + + + +/****************************************************************/ +/* Transactions */ +/****************************************************************/ + +#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) + +psa_crypto_transaction_t psa_crypto_transaction; + +psa_status_t psa_crypto_save_transaction( void ) +{ + struct psa_storage_info_t p_info; + psa_status_t status; + status = psa_its_get_info( PSA_CRYPTO_ITS_TRANSACTION_UID, &p_info ); + if( status == PSA_SUCCESS ) + { + /* This shouldn't happen: we're trying to start a transaction while + * there is still a transaction that hasn't been replayed. */ + return( PSA_ERROR_CORRUPTION_DETECTED ); + } + else if( status != PSA_ERROR_DOES_NOT_EXIST ) + return( status ); + return( psa_its_set( PSA_CRYPTO_ITS_TRANSACTION_UID, + sizeof( psa_crypto_transaction ), + &psa_crypto_transaction, + 0 ) ); +} + +psa_status_t psa_crypto_load_transaction( void ) +{ + psa_status_t status; + size_t length; + status = psa_its_get( PSA_CRYPTO_ITS_TRANSACTION_UID, 0, + sizeof( psa_crypto_transaction ), + &psa_crypto_transaction, &length ); + if( status != PSA_SUCCESS ) + return( status ); + if( length != sizeof( psa_crypto_transaction ) ) + return( PSA_ERROR_STORAGE_FAILURE ); + return( PSA_SUCCESS ); +} + +psa_status_t psa_crypto_stop_transaction( void ) +{ + psa_status_t status = psa_its_remove( PSA_CRYPTO_ITS_TRANSACTION_UID ); + /* Whether or not updating the storage succeeded, the transaction is + * finished now. It's too late to go back, so zero out the in-memory + * data. */ + memset( &psa_crypto_transaction, 0, sizeof( psa_crypto_transaction ) ); + return( status ); +} + +#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */ + + + +/****************************************************************/ +/* Random generator state */ +/****************************************************************/ + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) +psa_status_t mbedtls_psa_storage_inject_entropy( const unsigned char *seed, + size_t seed_size ) +{ + psa_status_t status; + struct psa_storage_info_t p_info; + + status = psa_its_get_info( PSA_CRYPTO_ITS_RANDOM_SEED_UID, &p_info ); + + if( PSA_ERROR_DOES_NOT_EXIST == status ) /* No seed exists */ + { + status = psa_its_set( PSA_CRYPTO_ITS_RANDOM_SEED_UID, seed_size, seed, 0 ); + } + else if( PSA_SUCCESS == status ) + { + /* You should not be here. Seed needs to be injected only once */ + status = PSA_ERROR_NOT_PERMITTED; + } + return( status ); +} +#endif /* MBEDTLS_PSA_INJECT_ENTROPY */ + + + +/****************************************************************/ +/* The end */ +/****************************************************************/ + +#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_storage.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_storage.h new file mode 100644 index 0000000..1b7dbd6 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_crypto_storage.h @@ -0,0 +1,390 @@ +/** + * \file psa_crypto_storage.h + * + * \brief PSA cryptography module: Mbed TLS key storage + */ +/* + * Copyright (C) 2018, ARM Limited, 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef PSA_CRYPTO_STORAGE_H +#define PSA_CRYPTO_STORAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "psa/crypto.h" +#include "psa/crypto_se_driver.h" + +#include +#include + +/* Limit the maximum key size in storage. This should have no effect + * since the key size is limited in memory. */ +#define PSA_CRYPTO_MAX_STORAGE_SIZE ( PSA_BITS_TO_BYTES( PSA_MAX_KEY_BITS ) ) +/* Sanity check: a file size must fit in 32 bits. Allow a generous + * 64kB of metadata. */ +#if PSA_CRYPTO_MAX_STORAGE_SIZE > 0xffff0000 +#error PSA_CRYPTO_MAX_STORAGE_SIZE > 0xffff0000 +#endif + +/** The maximum permitted persistent slot number. + * + * In Mbed Crypto 0.1.0b: + * - Using the file backend, all key ids are ok except 0. + * - Using the ITS backend, all key ids are ok except 0xFFFFFF52 + * (#PSA_CRYPTO_ITS_RANDOM_SEED_UID) for which the file contains the + * device's random seed (if this feature is enabled). + * - Only key ids from 1 to #PSA_KEY_SLOT_COUNT are actually used. + * + * Since we need to preserve the random seed, avoid using that key slot. + * Reserve a whole range of key slots just in case something else comes up. + * + * This limitation will probably become moot when we implement client + * separation for key storage. + */ +#define PSA_MAX_PERSISTENT_KEY_IDENTIFIER PSA_KEY_ID_VENDOR_MAX + +/** + * \brief Checks if persistent data is stored for the given key slot number + * + * This function checks if any key data or metadata exists for the key slot in + * the persistent storage. + * + * \param key Persistent identifier to check. + * + * \retval 0 + * No persistent data present for slot number + * \retval 1 + * Persistent data present for slot number + */ +int psa_is_key_present_in_storage( const psa_key_file_id_t key ); + +/** + * \brief Format key data and metadata and save to a location for given key + * slot. + * + * This function formats the key data and metadata and saves it to a + * persistent storage backend. The storage location corresponding to the + * key slot must be empty, otherwise this function will fail. This function + * should be called after psa_import_key_into_slot() to ensure the + * persistent key is not saved into a storage location corresponding to an + * already occupied non-persistent key, as well as validating the key data. + * + * + * \param[in] attr The attributes of the key to save. + * The key identifier field in the attributes + * determines the key's location. + * \param[in] data Buffer containing the key data. + * \param data_length The number of bytes that make up the key data. + * + * \retval PSA_SUCCESS + * \retval PSA_ERROR_INSUFFICIENT_MEMORY + * \retval PSA_ERROR_INSUFFICIENT_STORAGE + * \retval PSA_ERROR_STORAGE_FAILURE + * \retval PSA_ERROR_ALREADY_EXISTS + */ +psa_status_t psa_save_persistent_key( const psa_core_key_attributes_t *attr, + const uint8_t *data, + const size_t data_length ); + +/** + * \brief Parses key data and metadata and load persistent key for given + * key slot number. + * + * This function reads from a storage backend, parses the key data and + * metadata and writes them to the appropriate output parameters. + * + * Note: This function allocates a buffer and returns a pointer to it through + * the data parameter. psa_free_persistent_key_data() must be called after + * this function to zeroize and free this buffer, regardless of whether this + * function succeeds or fails. + * + * \param[in,out] attr On input, the key identifier field identifies + * the key to load. Other fields are ignored. + * On success, the attribute structure contains + * the key metadata that was loaded from storage. + * \param[out] data Pointer to an allocated key data buffer on return. + * \param[out] data_length The number of bytes that make up the key data. + * + * \retval PSA_SUCCESS + * \retval PSA_ERROR_INSUFFICIENT_MEMORY + * \retval PSA_ERROR_STORAGE_FAILURE + * \retval PSA_ERROR_DOES_NOT_EXIST + */ +psa_status_t psa_load_persistent_key( psa_core_key_attributes_t *attr, + uint8_t **data, + size_t *data_length ); + +/** + * \brief Remove persistent data for the given key slot number. + * + * \param key Persistent identifier of the key to remove + * from persistent storage. + * + * \retval PSA_SUCCESS + * The key was successfully removed, + * or the key did not exist. + * \retval PSA_ERROR_STORAGE_FAILURE + */ +psa_status_t psa_destroy_persistent_key( const psa_key_file_id_t key ); + +/** + * \brief Free the temporary buffer allocated by psa_load_persistent_key(). + * + * This function must be called at some point after psa_load_persistent_key() + * to zeroize and free the memory allocated to the buffer in that function. + * + * \param key_data Buffer for the key data. + * \param key_data_length Size of the key data buffer. + * + */ +void psa_free_persistent_key_data( uint8_t *key_data, size_t key_data_length ); + +/** + * \brief Formats key data and metadata for persistent storage + * + * \param[in] data Buffer containing the key data. + * \param data_length Length of the key data buffer. + * \param[in] attr The core attributes of the key. + * \param[out] storage_data Output buffer for the formatted data. + * + */ +void psa_format_key_data_for_storage( const uint8_t *data, + const size_t data_length, + const psa_core_key_attributes_t *attr, + uint8_t *storage_data ); + +/** + * \brief Parses persistent storage data into key data and metadata + * + * \param[in] storage_data Buffer for the storage data. + * \param storage_data_length Length of the storage data buffer + * \param[out] key_data On output, pointer to a newly allocated buffer + * containing the key data. This must be freed + * using psa_free_persistent_key_data() + * \param[out] key_data_length Length of the key data buffer + * \param[out] attr On success, the attribute structure is filled + * with the loaded key metadata. + * + * \retval PSA_SUCCESS + * \retval PSA_ERROR_INSUFFICIENT_STORAGE + * \retval PSA_ERROR_INSUFFICIENT_MEMORY + * \retval PSA_ERROR_STORAGE_FAILURE + */ +psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data, + size_t storage_data_length, + uint8_t **key_data, + size_t *key_data_length, + psa_core_key_attributes_t *attr ); + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +/** This symbol is defined if transaction support is required. */ +#define PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS +#endif + +#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) + +/** The type of transaction that is in progress. + */ +/* This is an integer type rather than an enum for two reasons: to support + * unknown values when loading a transaction file, and to ensure that the + * type has a known size. + */ +typedef uint16_t psa_crypto_transaction_type_t; + +/** No transaction is in progress. + * + * This has the value 0, so zero-initialization sets a transaction's type to + * this value. + */ +#define PSA_CRYPTO_TRANSACTION_NONE ( (psa_crypto_transaction_type_t) 0x0000 ) + +/** A key creation transaction. + * + * This is only used for keys in an external cryptoprocessor (secure element). + * Keys in RAM or in internal storage are created atomically in storage + * (simple file creation), so they do not need a transaction mechanism. + */ +#define PSA_CRYPTO_TRANSACTION_CREATE_KEY ( (psa_crypto_transaction_type_t) 0x0001 ) + +/** A key destruction transaction. + * + * This is only used for keys in an external cryptoprocessor (secure element). + * Keys in RAM or in internal storage are destroyed atomically in storage + * (simple file deletion), so they do not need a transaction mechanism. + */ +#define PSA_CRYPTO_TRANSACTION_DESTROY_KEY ( (psa_crypto_transaction_type_t) 0x0002 ) + +/** Transaction data. + * + * This type is designed to be serialized by writing the memory representation + * and reading it back on the same device. + * + * \note The transaction mechanism is designed for a single active transaction + * at a time. The transaction object is #psa_crypto_transaction. + * + * \note If an API call starts a transaction, it must complete this transaction + * before returning to the application. + * + * The lifetime of a transaction is the following (note that only one + * transaction may be active at a time): + * + * -# Call psa_crypto_prepare_transaction() to initialize the transaction + * object in memory and declare the type of transaction that is starting. + * -# Fill in the type-specific fields of #psa_crypto_transaction. + * -# Call psa_crypto_save_transaction() to start the transaction. This + * saves the transaction data to internal storage. + * -# Perform the work of the transaction by modifying files, contacting + * external entities, or whatever needs doing. Note that the transaction + * may be interrupted by a power failure, so you need to have a way + * recover from interruptions either by undoing what has been done + * so far or by resuming where you left off. + * -# If there are intermediate stages in the transaction, update + * the fields of #psa_crypto_transaction and call + * psa_crypto_save_transaction() again when each stage is reached. + * -# When the transaction is over, call psa_crypto_stop_transaction() to + * remove the transaction data in storage and in memory. + * + * If the system crashes while a transaction is in progress, psa_crypto_init() + * calls psa_crypto_load_transaction() and takes care of completing or + * rewinding the transaction. This is done in psa_crypto_recover_transaction() + * in psa_crypto.c. If you add a new type of transaction, be + * sure to add code for it in psa_crypto_recover_transaction(). + */ +typedef union +{ + /* Each element of this union must have the following properties + * to facilitate serialization and deserialization: + * + * - The element is a struct. + * - The first field of the struct is `psa_crypto_transaction_type_t type`. + * - Elements of the struct are arranged such a way that there is + * no padding. + */ + struct psa_crypto_transaction_unknown_s + { + psa_crypto_transaction_type_t type; + uint16_t unused1; + uint32_t unused2; + uint64_t unused3; + uint64_t unused4; + } unknown; + /* ::type is #PSA_CRYPTO_TRANSACTION_CREATE_KEY or + * #PSA_CRYPTO_TRANSACTION_DESTROY_KEY. */ + struct psa_crypto_transaction_key_s + { + psa_crypto_transaction_type_t type; + uint16_t unused1; + psa_key_lifetime_t lifetime; + psa_key_slot_number_t slot; + psa_key_id_t id; + } key; +} psa_crypto_transaction_t; + +/** The single active transaction. + */ +extern psa_crypto_transaction_t psa_crypto_transaction; + +/** Prepare for a transaction. + * + * There must not be an ongoing transaction. + * + * \param type The type of transaction to start. + */ +static inline void psa_crypto_prepare_transaction( + psa_crypto_transaction_type_t type ) +{ + psa_crypto_transaction.unknown.type = type; +} + +/** Save the transaction data to storage. + * + * You may call this function multiple times during a transaction to + * atomically update the transaction state. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_STORAGE_FAILURE + */ +psa_status_t psa_crypto_save_transaction( void ); + +/** Load the transaction data from storage, if any. + * + * This function is meant to be called from psa_crypto_init() to recover + * in case a transaction was interrupted by a system crash. + * + * \retval #PSA_SUCCESS + * The data about the ongoing transaction has been loaded to + * #psa_crypto_transaction. + * \retval #PSA_ERROR_DOES_NOT_EXIST + * There is no ongoing transaction. + * \retval #PSA_ERROR_STORAGE_FAILURE + */ +psa_status_t psa_crypto_load_transaction( void ); + +/** Indicate that the current transaction is finished. + * + * Call this function at the very end of transaction processing. + * This function does not "commit" or "abort" the transaction: the storage + * subsystem has no concept of "commit" and "abort", just saving and + * removing the transaction information in storage. + * + * This function erases the transaction data in storage (if any) and + * resets the transaction data in memory. + * + * \retval #PSA_SUCCESS + * There was transaction data in storage. + * \retval #PSA_ERROR_DOES_NOT_EXIST + * There was no transaction data in storage. + * \retval #PSA_ERROR_STORAGE_FAILURE + * It was impossible to determine whether there was transaction data + * in storage, or the transaction data could not be erased. + */ +psa_status_t psa_crypto_stop_transaction( void ); + +/** The ITS file identifier for the transaction data. + * + * 0xffffffNN = special file; 0x74 = 't' for transaction. + */ +#define PSA_CRYPTO_ITS_TRANSACTION_UID ( (psa_key_id_t) 0xffffff74 ) + +#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */ + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) +/** Backend side of mbedtls_psa_inject_entropy(). + * + * This function stores the supplied data into the entropy seed file. + * + * \retval #PSA_SUCCESS + * Success + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_NOT_PERMITTED + * The entropy seed file already exists. + */ +psa_status_t mbedtls_psa_storage_inject_entropy( const unsigned char *seed, + size_t seed_size ); +#endif /* MBEDTLS_PSA_INJECT_ENTROPY */ + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_STORAGE_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_its_file.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_its_file.c new file mode 100644 index 0000000..0935b27 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbedtls/psa_its_file.c @@ -0,0 +1,255 @@ +/* + * PSA ITS simulator over stdio files. + */ +/* Copyright (C) 2018, ARM Limited, 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if defined(MBEDTLS_CONFIG_FILE) +#include MBEDTLS_CONFIG_FILE +#else +#include "mbedtls/config.h" +#endif + +#if defined(MBEDTLS_PSA_ITS_FILE_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_snprintf snprintf +#endif + +#if defined(_WIN32) +#include +#endif + +#include "psa_crypto_its.h" + +#include +#include +#include +#include + +#if !defined(PSA_ITS_STORAGE_PREFIX) +#define PSA_ITS_STORAGE_PREFIX "" +#endif + +#define PSA_ITS_STORAGE_FILENAME_PATTERN "%08lx%08lx" +#define PSA_ITS_STORAGE_SUFFIX ".psa_its" +#define PSA_ITS_STORAGE_FILENAME_LENGTH \ + ( sizeof( PSA_ITS_STORAGE_PREFIX ) - 1 + /*prefix without terminating 0*/ \ + 16 + /*UID (64-bit number in hex)*/ \ + sizeof( PSA_ITS_STORAGE_SUFFIX ) - 1 + /*suffix without terminating 0*/ \ + 1 /*terminating null byte*/ ) +#define PSA_ITS_STORAGE_TEMP \ + PSA_ITS_STORAGE_PREFIX "tempfile" PSA_ITS_STORAGE_SUFFIX + +/* The maximum value of psa_storage_info_t.size */ +#define PSA_ITS_MAX_SIZE 0xffffffff + +#define PSA_ITS_MAGIC_STRING "PSA\0ITS\0" +#define PSA_ITS_MAGIC_LENGTH 8 + +/* As rename fails on Windows if the new filepath already exists, + * use MoveFileExA with the MOVEFILE_REPLACE_EXISTING flag instead. + * Returns 0 on success, nonzero on failure. */ +#if defined(_WIN32) +#define rename_replace_existing( oldpath, newpath ) \ + ( ! MoveFileExA( oldpath, newpath, MOVEFILE_REPLACE_EXISTING ) ) +#else +#define rename_replace_existing( oldpath, newpath ) rename( oldpath, newpath ) +#endif + +typedef struct +{ + uint8_t magic[PSA_ITS_MAGIC_LENGTH]; + uint8_t size[sizeof( uint32_t )]; + uint8_t flags[sizeof( psa_storage_create_flags_t )]; +} psa_its_file_header_t; + +static void psa_its_fill_filename( psa_storage_uid_t uid, char *filename ) +{ + /* Break up the UID into two 32-bit pieces so as not to rely on + * long long support in snprintf. */ + mbedtls_snprintf( filename, PSA_ITS_STORAGE_FILENAME_LENGTH, + "%s" PSA_ITS_STORAGE_FILENAME_PATTERN "%s", + PSA_ITS_STORAGE_PREFIX, + (unsigned long) ( uid >> 32 ), + (unsigned long) ( uid & 0xffffffff ), + PSA_ITS_STORAGE_SUFFIX ); +} + +static psa_status_t psa_its_read_file( psa_storage_uid_t uid, + struct psa_storage_info_t *p_info, + FILE **p_stream ) +{ + char filename[PSA_ITS_STORAGE_FILENAME_LENGTH]; + psa_its_file_header_t header; + size_t n; + + *p_stream = NULL; + psa_its_fill_filename( uid, filename ); + *p_stream = fopen( filename, "rb" ); + if( *p_stream == NULL ) + return( PSA_ERROR_DOES_NOT_EXIST ); + + n = fread( &header, 1, sizeof( header ), *p_stream ); + if( n != sizeof( header ) ) + return( PSA_ERROR_DATA_CORRUPT ); + if( memcmp( header.magic, PSA_ITS_MAGIC_STRING, + PSA_ITS_MAGIC_LENGTH ) != 0 ) + return( PSA_ERROR_DATA_CORRUPT ); + + p_info->size = ( header.size[0] | + header.size[1] << 8 | + header.size[2] << 16 | + header.size[3] << 24 ); + p_info->flags = ( header.flags[0] | + header.flags[1] << 8 | + header.flags[2] << 16 | + header.flags[3] << 24 ); + return( PSA_SUCCESS ); +} + +psa_status_t psa_its_get_info( psa_storage_uid_t uid, + struct psa_storage_info_t *p_info ) +{ + psa_status_t status; + FILE *stream = NULL; + status = psa_its_read_file( uid, p_info, &stream ); + if( stream != NULL ) + fclose( stream ); + return( status ); +} + +psa_status_t psa_its_get( psa_storage_uid_t uid, + uint32_t data_offset, + uint32_t data_length, + void *p_data, + size_t *p_data_length ) +{ + psa_status_t status; + FILE *stream = NULL; + size_t n; + struct psa_storage_info_t info; + + status = psa_its_read_file( uid, &info, &stream ); + if( status != PSA_SUCCESS ) + goto exit; + status = PSA_ERROR_INVALID_ARGUMENT; + if( data_offset + data_length < data_offset ) + goto exit; +#if SIZE_MAX < 0xffffffff + if( data_offset + data_length > SIZE_MAX ) + goto exit; +#endif + if( data_offset + data_length > info.size ) + goto exit; + + status = PSA_ERROR_STORAGE_FAILURE; +#if LONG_MAX < 0xffffffff + while( data_offset > LONG_MAX ) + { + if( fseek( stream, LONG_MAX, SEEK_CUR ) != 0 ) + goto exit; + data_offset -= LONG_MAX; + } +#endif + if( fseek( stream, data_offset, SEEK_CUR ) != 0 ) + goto exit; + n = fread( p_data, 1, data_length, stream ); + if( n != data_length ) + goto exit; + status = PSA_SUCCESS; + if( p_data_length != NULL ) + *p_data_length = n; + +exit: + if( stream != NULL ) + fclose( stream ); + return( status ); +} + +psa_status_t psa_its_set( psa_storage_uid_t uid, + uint32_t data_length, + const void *p_data, + psa_storage_create_flags_t create_flags ) +{ + psa_status_t status = PSA_ERROR_STORAGE_FAILURE; + char filename[PSA_ITS_STORAGE_FILENAME_LENGTH]; + FILE *stream = NULL; + psa_its_file_header_t header; + size_t n; + + memcpy( header.magic, PSA_ITS_MAGIC_STRING, PSA_ITS_MAGIC_LENGTH ); + header.size[0] = data_length & 0xff; + header.size[1] = ( data_length >> 8 ) & 0xff; + header.size[2] = ( data_length >> 16 ) & 0xff; + header.size[3] = ( data_length >> 24 ) & 0xff; + header.flags[0] = create_flags & 0xff; + header.flags[1] = ( create_flags >> 8 ) & 0xff; + header.flags[2] = ( create_flags >> 16 ) & 0xff; + header.flags[3] = ( create_flags >> 24 ) & 0xff; + + psa_its_fill_filename( uid, filename ); + stream = fopen( PSA_ITS_STORAGE_TEMP, "wb" ); + if( stream == NULL ) + goto exit; + + status = PSA_ERROR_INSUFFICIENT_STORAGE; + n = fwrite( &header, 1, sizeof( header ), stream ); + if( n != sizeof( header ) ) + goto exit; + if( data_length != 0 ) + { + n = fwrite( p_data, 1, data_length, stream ); + if( n != data_length ) + goto exit; + } + status = PSA_SUCCESS; + +exit: + if( stream != NULL ) + { + int ret = fclose( stream ); + if( status == PSA_SUCCESS && ret != 0 ) + status = PSA_ERROR_INSUFFICIENT_STORAGE; + } + if( status == PSA_SUCCESS ) + { + if( rename_replace_existing( PSA_ITS_STORAGE_TEMP, filename ) != 0 ) + status = PSA_ERROR_STORAGE_FAILURE; + } + remove( PSA_ITS_STORAGE_TEMP ); + return( status ); +} + +psa_status_t psa_its_remove( psa_storage_uid_t uid ) +{ + char filename[PSA_ITS_STORAGE_FILENAME_LENGTH]; + FILE *stream; + psa_its_fill_filename( uid, filename ); + stream = fopen( filename, "rb" ); + if( stream == NULL ) + return( PSA_ERROR_DOES_NOT_EXIST ); + fclose( stream ); + if( remove( filename ) != 0 ) + return( PSA_ERROR_STORAGE_FAILURE ); + return( PSA_SUCCESS ); +} + +#endif /* MBEDTLS_PSA_ITS_FILE_C */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_attestation_eat.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_attestation_eat.c new file mode 100644 index 0000000..8683680 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_attestation_eat.c @@ -0,0 +1,365 @@ +/** @file + * Copyright (c) 2019, 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 "pal_attestation_eat.h" + +uint32_t mandatory_claims = 0, mandaroty_sw_components = 0; +bool_t sw_component_present = 0; + +static int get_items_in_map(QCBORDecodeContext *decode_context, + struct items_to_get_t *item_list) +{ + int item_index; + QCBORItem item; + struct items_to_get_t *item_ptr = item_list; + + /* initialize the data type of all items in the list */ + while (item_ptr->label != 0) { + item_ptr->item.uDataType = QCBOR_TYPE_NONE; + item_ptr++; + } + + QCBORDecode_GetNext(decode_context, &item); + if (item.uDataType != QCBOR_TYPE_MAP) { + return PAL_ATTEST_ERROR; + } + + for (item_index = item.val.uCount; item_index != 0; item_index--) { + if (QCBORDecode_GetNext(decode_context, &item) != QCBOR_SUCCESS) { + return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; + } + if (item.uLabelType != QCBOR_TYPE_INT64) { + continue; + } + + item_ptr = item_list; + while (item_ptr->label != 0) { + if (item.label.int64 == item_ptr->label) { + item_ptr->item = item; + } + item_ptr++; + } + } + + return PAL_ATTEST_SUCCESS; +} + +static int get_item_in_map(QCBORDecodeContext *decode_context, + int32_t label, + QCBORItem *item) +{ + struct items_to_get_t item_list[2]; + + item_list[0].label = label; + item_list[1].label = 0; + + if (get_items_in_map(decode_context, item_list)) { + return PAL_ATTEST_ERROR; + } + + if (item_list[0].item.uDataType == QCBOR_TYPE_NONE) { + return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; + } + + *item = item_list[0].item; + + return PAL_ATTEST_SUCCESS; +} + +static int parse_unprotected_headers(QCBORDecodeContext *decode_context, + struct useful_buf_c *child, + bool *loop_back) +{ + struct items_to_get_t item_list[3]; + + item_list[0].label = COSE_HEADER_PARAM_KID; + item_list[1].label = T_COSE_SHORT_CIRCUIT_LABEL; + item_list[2].label = 0; + *loop_back = false; + + if (get_items_in_map(decode_context, item_list)) { + return PAL_ATTEST_ERROR; + } + + if (item_list[1].item.uDataType == QCBOR_TYPE_TRUE) { + *loop_back = true; + } + + if (item_list[0].item.uDataType != QCBOR_TYPE_BYTE_STRING) { + return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; + } + + *child = item_list[0].item.val.string; + + return PAL_ATTEST_SUCCESS; +} + +static int parse_protected_headers(struct useful_buf_c protected_headers, + int32_t *alg_id) +{ + QCBORDecodeContext decode_context; + QCBORItem item; + + QCBORDecode_Init(&decode_context, protected_headers, 0); + + if (get_item_in_map(&decode_context, COSE_HEADER_PARAM_ALG, &item)) { + return PAL_ATTEST_ERROR; + } + + if (QCBORDecode_Finish(&decode_context)) { + return PAL_ATTEST_ERROR; + } + + if ((item.uDataType != QCBOR_TYPE_INT64) || (item.val.int64 > INT32_MAX)) { + return PAL_ATTEST_ERROR; + } + + *alg_id = (int32_t)item.val.int64; + + return PAL_ATTEST_SUCCESS; +} + +/** + @brief - This API will verify the claims + @param - decode_context : The buffer containing the challenge + item : context for decoding the data items + completed_challenge : Buffer containing the challenge + @return - error status +**/ +static int parse_claims(QCBORDecodeContext *decode_context, QCBORItem item, + struct useful_buf_c completed_challenge) +{ + int i, count = 0; + int status = PAL_ATTEST_SUCCESS; + + /* Parse each claim and validate their data type */ + while (status == PAL_ATTEST_SUCCESS) { + status = QCBORDecode_GetNext(decode_context, &item); + if (status != PAL_ATTEST_SUCCESS) { + break; + } + + mandatory_claims |= 1 << (EAT_CBOR_ARM_RANGE_BASE - item.label.int64); + if (item.uLabelType == QCBOR_TYPE_INT64) { + if (item.label.int64 == EAT_CBOR_ARM_LABEL_NONCE) { + if (item.uDataType == QCBOR_TYPE_BYTE_STRING) { + /* Given challenge vs challenge in token */ + if (UsefulBuf_Compare(item.val.string, completed_challenge)) { + return PAL_ATTEST_TOKEN_CHALLENGE_MISMATCH; + } + } else { + return PAL_ATTEST_TOKEN_NOT_SUPPORTED; + } + } else if (item.label.int64 == EAT_CBOR_ARM_LABEL_BOOT_SEED || + item.label.int64 == EAT_CBOR_ARM_LABEL_IMPLEMENTATION_ID || + item.label.int64 == EAT_CBOR_ARM_LABEL_UEID) { + if (item.uDataType != QCBOR_TYPE_BYTE_STRING) { + return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; + } + } else if (item.label.int64 == EAT_CBOR_ARM_LABEL_ORIGINATION || + item.label.int64 == EAT_CBOR_ARM_LABEL_PROFILE_DEFINITION || + item.label.int64 == EAT_CBOR_ARM_LABEL_HW_VERSION) { + if (item.uDataType != QCBOR_TYPE_TEXT_STRING) { + return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; + } + } else if (item.label.int64 == EAT_CBOR_ARM_LABEL_CLIENT_ID || + item.label.int64 == EAT_CBOR_ARM_LABEL_SECURITY_LIFECYCLE) { + if (item.uDataType != QCBOR_TYPE_INT64) { + return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; + } + } else if (item.label.int64 == EAT_CBOR_ARM_LABEL_SW_COMPONENTS) { + if (item.uDataType != QCBOR_TYPE_ARRAY) { + return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; + } + + sw_component_present = 1; + status = QCBORDecode_GetNext(decode_context, &item); + if (status != PAL_ATTEST_SUCCESS) { + continue; + } + + count = item.val.uCount; + for (i = 0; i <= count; i++) { + mandaroty_sw_components |= 1 << item.label.int64; + + if (item.label.int64 == EAT_CBOR_SW_COMPONENT_MEASUREMENT) { + if (item.uDataType != QCBOR_TYPE_BYTE_STRING) { + return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; + } + } else if (item.label.int64 == EAT_CBOR_SW_COMPONENT_MEASUREMENT_DESC) { + if (item.uDataType != QCBOR_TYPE_TEXT_STRING) { + return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; + } + } else if (item.label.int64 == EAT_CBOR_SW_COMPONENT_VERSION) { + if (item.uDataType != QCBOR_TYPE_TEXT_STRING) { + return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; + } + } else if (item.label.int64 == EAT_CBOR_SW_COMPONENT_SIGNER_ID) { + if (item.uDataType != QCBOR_TYPE_BYTE_STRING) { + return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; + } + } else if (item.label.int64 == EAT_CBOR_SW_COMPONENT_EPOCH) { + if (item.uDataType != QCBOR_TYPE_INT64) { + return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; + } + } else if (item.label.int64 == EAT_CBOR_SW_COMPONENT_TYPE) { + if (item.uDataType != QCBOR_TYPE_TEXT_STRING) { + return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; + } + } + + if (i < count) { + status = QCBORDecode_GetNext(decode_context, &item); + if (status != PAL_ATTEST_SUCCESS) { + return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; + } + } + } + + } + } else { + /* ToDo: Add other claim types */ + } + } + + if (status == QCBOR_ERR_HIT_END) { + return PAL_ATTEST_SUCCESS; + } else { + return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; + } +} + +/** + @brief - This API will verify the attestation token + @param - challenge : The buffer containing the challenge + challenge_size : Size of the challenge buffer + token : The buffer containing the attestation token + token_size : Size of the token buffer + @return - error status +**/ +int32_t pal_initial_attest_verify_token(uint8_t *challenge, uint32_t challenge_size, + uint8_t *token, uint32_t token_size) +{ + int status = PAL_ATTEST_SUCCESS; + bool short_circuit; + int32_t cose_algorithm_id; + QCBORItem item; + QCBORDecodeContext decode_context; + struct useful_buf_c completed_challenge; + struct useful_buf_c completed_token; + struct useful_buf_c payload; + struct useful_buf_c protected_headers; + struct useful_buf_c kid; + + /* Construct the token buffer for validation */ + completed_token.ptr = token; + completed_token.len = token_size; + + /* Construct the challenge buffer for validation */ + completed_challenge.ptr = challenge; + completed_challenge.len = challenge_size; + + /* + ------------------------- + | CBOR Array Type | + ------------------------- + | Protected Headers | + ------------------------- + | Unprotected Headers | + ------------------------- + | Payload | + ------------------------- + | Signature | + ------------------------- + */ + + /* Initialize the decorder */ + QCBORDecode_Init(&decode_context, completed_token, QCBOR_DECODE_MODE_NORMAL); + + /* Get the Header */ + QCBORDecode_GetNext(&decode_context, &item); + + /* Check the CBOR Array type. Check if the count is 4. + * Only COSE_SIGN1 is supported now. + */ + if (item.uDataType != QCBOR_TYPE_ARRAY || item.val.uCount != 4 || + !QCBORDecode_IsTagged(&decode_context, &item, CBOR_TAG_COSE_SIGN1)) { + return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; + } + + /* Get the next headers */ + QCBORDecode_GetNext(&decode_context, &item); + if (item.uDataType != QCBOR_TYPE_BYTE_STRING) { + return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; + } + + protected_headers = item.val.string; + + /* Parse the protected headers and check the data type and value*/ + status = parse_protected_headers(protected_headers, &cose_algorithm_id); + if (status != PAL_ATTEST_SUCCESS) { + return status; + } + + /* Parse the unprotected headers and check the data type and value */ + short_circuit = false; + status = parse_unprotected_headers(&decode_context, &kid, &short_circuit); + if (status != PAL_ATTEST_SUCCESS) { + return status; + } + + /* Get the payload */ + QCBORDecode_GetNext(&decode_context, &item); + if (item.uDataType != QCBOR_TYPE_BYTE_STRING) { + return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; + } + + payload = item.val.string; + + /* Get the digital signature */ + QCBORDecode_GetNext(&decode_context, &item); + if (item.uDataType != QCBOR_TYPE_BYTE_STRING) { + return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; + } + + /* Initialize the Decoder and validate the payload format */ + QCBORDecode_Init(&decode_context, payload, QCBOR_DECODE_MODE_NORMAL); + status = QCBORDecode_GetNext(&decode_context, &item); + if (status != PAL_ATTEST_SUCCESS) { + return status; + } + + if (item.uDataType != QCBOR_TYPE_MAP) { + return PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING; + } + + /* Parse the payload and check the data type of each claim */ + status = parse_claims(&decode_context, item, completed_challenge); + if (status != PAL_ATTEST_SUCCESS) { + return status; + } + + if ((mandatory_claims & MANDATORY_CLAIM_WITH_SW_COMP) == MANDATORY_CLAIM_WITH_SW_COMP) { + if ((mandaroty_sw_components & MANDATORY_SW_COMP) != MANDATORY_SW_COMP) { + return PAL_ATTEST_TOKEN_NOT_ALL_MANDATORY_CLAIMS; + } + } else if ((mandatory_claims & MANDATORY_CLAIM_NO_SW_COMP) != MANDATORY_CLAIM_NO_SW_COMP) { + return PAL_ATTEST_TOKEN_NOT_ALL_MANDATORY_CLAIMS; + } + + return PAL_ATTEST_SUCCESS; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_attestation_eat.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_attestation_eat.h new file mode 100644 index 0000000..9f435fb --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_attestation_eat.h @@ -0,0 +1,73 @@ +/** @file + * Copyright (c) 2019, 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 "qcbor.h" +#include "pal_common.h" + +#define PAL_ATTEST_MIN_ERROR 30 + +#define COSE_HEADER_PARAM_ALG 1 +#define COSE_HEADER_PARAM_KID 4 + +#define MANDATORY_CLAIM_WITH_SW_COMP 862 +#define MANDATORY_CLAIM_NO_SW_COMP 926 +#define MANDATORY_SW_COMP 36 +#define CBOR_ARM_TOTAL_CLAIM_INSTANCE 10 + +/* + CBOR Label for proprietary header indicating short-circuit + signing was used. Just a random number in the proprietary + label space */ +#define T_COSE_SHORT_CIRCUIT_LABEL (-8675309) + +#define EAT_CBOR_ARM_RANGE_BASE (-75000) +#define EAT_CBOR_ARM_LABEL_PROFILE_DEFINITION (EAT_CBOR_ARM_RANGE_BASE - 0) +#define EAT_CBOR_ARM_LABEL_CLIENT_ID (EAT_CBOR_ARM_RANGE_BASE - 1) +#define EAT_CBOR_ARM_LABEL_SECURITY_LIFECYCLE (EAT_CBOR_ARM_RANGE_BASE - 2) +#define EAT_CBOR_ARM_LABEL_IMPLEMENTATION_ID (EAT_CBOR_ARM_RANGE_BASE - 3) +#define EAT_CBOR_ARM_LABEL_BOOT_SEED (EAT_CBOR_ARM_RANGE_BASE - 4) +#define EAT_CBOR_ARM_LABEL_HW_VERSION (EAT_CBOR_ARM_RANGE_BASE - 5) +#define EAT_CBOR_ARM_LABEL_SW_COMPONENTS (EAT_CBOR_ARM_RANGE_BASE - 6) +#define EAT_CBOR_ARM_LABEL_NO_SW_COMPONENTS (EAT_CBOR_ARM_RANGE_BASE - 7) +#define EAT_CBOR_ARM_LABEL_NONCE (EAT_CBOR_ARM_RANGE_BASE - 8) +#define EAT_CBOR_ARM_LABEL_UEID (EAT_CBOR_ARM_RANGE_BASE - 9) +#define EAT_CBOR_ARM_LABEL_ORIGINATION (EAT_CBOR_ARM_RANGE_BASE - 10) + +#define EAT_CBOR_SW_COMPONENT_TYPE (1u) +#define EAT_CBOR_SW_COMPONENT_MEASUREMENT (2u) +#define EAT_CBOR_SW_COMPONENT_EPOCH (3u) +#define EAT_CBOR_SW_COMPONENT_VERSION (4u) +#define EAT_CBOR_SW_COMPONENT_SIGNER_ID (5u) +#define EAT_CBOR_SW_COMPONENT_MEASUREMENT_DESC (6u) + + +enum attestation_error_code { + PAL_ATTEST_SUCCESS = 0, + PAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING = PAL_ATTEST_MIN_ERROR, + PAL_ATTEST_TOKEN_CHALLENGE_MISMATCH, + PAL_ATTEST_TOKEN_NOT_SUPPORTED, + PAL_ATTEST_TOKEN_NOT_ALL_MANDATORY_CLAIMS, + PAL_ATTEST_ERROR, +}; + +struct items_to_get_t { + int64_t label; + QCBORItem item; +}; + +int32_t pal_initial_attest_verify_token(uint8_t *challenge, uint32_t challenge_size, + uint8_t *token, uint32_t token_size); diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_attestation_intf.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_attestation_intf.c new file mode 100644 index 0000000..66b3ab4 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_attestation_intf.c @@ -0,0 +1,53 @@ +/** @file + * Copyright (c) 2019, 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 "pal_attestation_intf.h" + +/** + @brief - This API will call the requested attestation function + @param - type : function code + valist : variable argument list + @return - error status +**/ +int32_t pal_attestation_function(int type, va_list valist) +{ + uint8_t *challenge, *token; + uint32_t challenge_size, *token_size, verify_token_size; + + switch (type) { + case PAL_INITIAL_ATTEST_GET_TOKEN: + challenge = va_arg(valist, uint8_t *); + challenge_size = va_arg(valist, uint32_t); + token = va_arg(valist, uint8_t *); + token_size = va_arg(valist, uint32_t *); + return psa_initial_attest_get_token(challenge, challenge_size, token, token_size); + case PAL_INITIAL_ATTEST_GET_TOKEN_SIZE: + challenge_size = va_arg(valist, uint32_t); + token_size = va_arg(valist, uint32_t *); + return psa_initial_attest_get_token_size(challenge_size, token_size); + case PAL_INITIAL_ATTEST_VERIFY_TOKEN: + challenge = va_arg(valist, uint8_t *); + challenge_size = va_arg(valist, uint32_t); + token = va_arg(valist, uint8_t *); + verify_token_size = va_arg(valist, uint32_t); + return pal_initial_attest_verify_token(challenge, challenge_size, + token, verify_token_size); + default: + return PAL_STATUS_UNSUPPORTED_FUNC; + } +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_attestation_intf.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_attestation_intf.h new file mode 100644 index 0000000..fdefc83 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_attestation_intf.h @@ -0,0 +1,31 @@ +/** @file + * Copyright (c) 2019, 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 _PAL_INITIAL_ATTESTATION_H_ +#define _PAL_INITIAL_ATTESTATION_H_ + +#include "psa_initial_attestation_api.h" +#include "pal_attestation_eat.h" + +enum attestation_function_code { + PAL_INITIAL_ATTEST_GET_TOKEN = 0x1, + PAL_INITIAL_ATTEST_GET_TOKEN_SIZE = 0x2, + PAL_INITIAL_ATTEST_VERIFY_TOKEN = 0x3, +}; + +int32_t pal_attestation_function(int type, va_list valist); +#endif /* _PAL_INITIAL_ATTESTATION_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_client_api_empty_intf.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_client_api_empty_intf.c new file mode 100644 index 0000000..8e9b90d --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_client_api_empty_intf.c @@ -0,0 +1,94 @@ +/** @file + * Copyright (c) 2018-2020, 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 "pal_common.h" +#include "pal_client_api_intf.h" + + +/** + * @brief - Retrieve the version of the PSA Framework API that is implemented. + * This is a wrapper API for psa_framework_version API. + * @param - void + * @return - The PSA Framework API version. + */ + +uint32_t pal_ipc_framework_version(void) +{ + return 0; +} + +/** + * @brief - Retrieve the minor version of a Root of Trust Service by its SID. + * This is a wrapper API for the psa_version API. + * @param - sid The Root of Trust Service ID + * @return - Minor version of Root of Trust Service or PSA_VERSION_NONE if Root of Trust + * Service not present on the system. + */ + +uint32_t pal_ipc_version(uint32_t sid) +{ + return PSA_VERSION_NONE; +} + +/** + * @brief - Connect to given sid. + * This is a wrapper API for the psa_connect API. + * @param - sid : RoT service id + * @param - minor_version : minor_version of RoT service + * @return - psa_handle_t : return connection handle + */ + +psa_handle_t pal_ipc_connect(uint32_t sid, uint32_t minor_version) +{ + return PSA_NULL_HANDLE; +} + +/** + * @brief Call a connected Root of Trust Service. + * This is a wrapper API for the psa_call API. + * The caller must provide an array of ::psa_invec_t structures as the input payload. + * + * @param -handle Handle for the connection. + * @param -in_vec Array of psa_invec structures. + * @param -in_len Number of psa_invec structures in in_vec. + * @param -out_vec Array of psa_outvec structures for optional Root of Trust Service response. + * @param -out_len Number of psa_outvec structures in out_vec. + * @return -psa_status_t + */ + +psa_status_t pal_ipc_call(psa_handle_t handle, + const psa_invec *in_vec, + size_t in_len, + psa_outvec *out_vec, + size_t out_len) +{ + return (PSA_SUCCESS - 1); +} + +/** + * @brief Close a connection to a Root of Trust Service. + * This is a wrapper API for the psa_close API. + * Sends the PSA_IPC_DISCONNECT message to the Root of Trust Service so it can clean up resources. + * + * @param handle Handle for the connection. + * @return void + */ + +void pal_ipc_close(psa_handle_t handle) +{ + return; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_client_api_intf.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_client_api_intf.c new file mode 100644 index 0000000..73ca73c --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_client_api_intf.c @@ -0,0 +1,101 @@ +/** @file + * Copyright (c) 2018, 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. +**/ + +#ifdef COMPONENT_PSA_SRV_IPC + +#include "pal_common.h" +#include "pal_client_api_intf.h" + +/** + * @brief - Retrieve the version of the PSA Framework API that is implemented. + * This is a wrapper API for psa_framework_version API. + * @param - void + * @return - The PSA Framework API version. + * Note - Return PAL_STATUS_ERROR if PSA IPC is not implemented. + */ + +uint32_t pal_ipc_framework_version(void) +{ + return (psa_framework_version()); +} + +/** + * @brief - Retrieve the minor version of a Root of Trust Service by its SID. + * This is a wrapper API for the psa_version API. + * @param - sid The Root of Trust Service ID + * @return - Minor version of Root of Trust Service or PSA_VERSION_NONE if Root of Trust + * Service not present on the system. + * Note - Return PAL_STATUS_ERROR if PSA IPC is not implemented. + */ + +uint32_t pal_ipc_version(uint32_t sid) +{ + return (psa_version(sid)); +} + +/** + * @brief - Connect to given sid. + * This is a wrapper API for the psa_connect API. + * @param - sid : RoT service id + * @param - minor_version : minor_version of RoT service + * @return - psa_handle_t : return connection handle + * Note - Return PSA_NULL_HANDLE if PSA IPC is not implemented. + */ + +psa_handle_t pal_ipc_connect(uint32_t sid, uint32_t minor_version) +{ + return (psa_connect(sid, minor_version)); +} + +/** + * @brief Call a connected Root of Trust Service. + * This is a wrapper API for the psa_call API. + * The caller must provide an array of ::psa_invec_t structures as the input payload. + * + * @param -handle Handle for the connection. + * @param -in_vec Array of psa_invec structures. + * @param -in_len Number of psa_invec structures in in_vec. + * @param -out_vec Array of psa_outvec structures for optional Root of Trust Service response. + * @param -out_len Number of psa_outvec structures in out_vec. + * @return -psa_status_t + * Note - Return -1 if PSA IPC is not implemented. + */ + +psa_status_t pal_ipc_call(psa_handle_t handle, + const psa_invec *in_vec, + size_t in_len, + psa_outvec *out_vec, + size_t out_len) +{ + return (psa_call(handle, in_vec, in_len, out_vec, out_len)); +} + +/** + * @brief Close a connection to a Root of Trust Service. + * This is a wrapper API for the psa_close API. + * Sends the PSA_IPC_DISCONNECT message to the Root of Trust Service so it can clean up resources. + * + * @param - handle Handle for the connection. + * @return - void + */ + +void pal_ipc_close(psa_handle_t handle) +{ + psa_close(handle); +} + +#endif diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_client_api_intf.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_client_api_intf.h new file mode 100644 index 0000000..3c53f5e --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_client_api_intf.h @@ -0,0 +1,61 @@ +/** @file + * Copyright (c) 2018-2020, 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 _PAL_CLIENT_API_H_ +#define _PAL_CLIENT_API_H_ + +#include "pal_common.h" + +#define PSA_VERSION_NONE (0) +#define PSA_CONNECTION_REFUSED (INT32_MIN + 1) +#define PSA_CONNECTION_BUSY (INT32_MIN + 2) +#define PSA_DROP_CONNECTION (INT32_MIN) +#define PSA_NULL_HANDLE ((psa_handle_t)0) + +typedef int32_t psa_status_t; +typedef int32_t psa_handle_t; + +typedef struct psa_invec { + const void *base; + size_t len; +} psa_invec; + +typedef struct psa_outvec { + void *base; + size_t len; +} psa_outvec; + +uint32_t psa_framework_version(void); +uint32_t psa_version(uint32_t sid); +psa_handle_t psa_connect(uint32_t sid, uint32_t minor_version); +psa_status_t psa_call(psa_handle_t handle, + const psa_invec *in_vec, + size_t in_len, + psa_outvec *out_vec, + size_t out_len); +void psa_close(psa_handle_t handle); + +uint32_t pal_ipc_framework_version(void); +uint32_t pal_ipc_version(uint32_t sid); +psa_handle_t pal_ipc_connect(uint32_t sid, uint32_t minor_version); +psa_status_t pal_ipc_call(psa_handle_t handle, + const psa_invec *in_vec, + size_t in_len, + psa_outvec *out_vec, + size_t out_len); +void pal_ipc_close(psa_handle_t handle); +#endif /* _PAL_CLIENT_API_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_common.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_common.h new file mode 100644 index 0000000..eaa6b4a --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_common.h @@ -0,0 +1,106 @@ +/** @file + * Copyright (c) 2018, 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 _PAL_COMMON_H_ +#define _PAL_COMMON_H_ + +#include +#include +#include +#include +#include + +#ifndef PSA_PROTECTED_STORAGE_IMPLEMENTED +#define PSA_INTERNAL_TRUSTED_STORAGE_IMPLEMENTED 1 /* Use ITS by default */ +#define ITS_TEST 1 +#endif + +#include "internal_trusted_storage.h" + +/* typedef's */ +typedef uint8_t bool_t; +typedef uint32_t addr_t; +typedef uint32_t test_id_t; +typedef uint32_t block_id_t; +typedef char char8_t; +typedef uint32_t cfg_id_t; + +#define PAL_STATUS_UNSUPPORTED_FUNC 0xFF + +typedef enum { + PAL_STATUS_SUCCESS = 0x0, + PAL_STATUS_ERROR = 0x80 +} pal_status_t; + +typedef enum { + NVMEM_READ = 0x1, + NVMEM_WRITE = 0x2, +} nvmem_fn_type_t; + +typedef struct { + nvmem_fn_type_t nvmem_fn_type; + addr_t base; + uint32_t offset; + int size; +} nvmem_param_t; + +typedef enum { + WD_INIT_SEQ = 0x1, + WD_ENABLE_SEQ = 0x2, + WD_DISABLE_SEQ = 0x3, + WD_STATUS_SEQ = 0x4, +} wd_fn_type_t; + +typedef enum { + WD_LOW_TIMEOUT = 0x1, + WD_MEDIUM_TIMEOUT = 0x2, + WD_HIGH_TIMEOUT = 0x3, + WD_CRYPTO_TIMEOUT = 0x4, +} wd_timeout_type_t; + +typedef struct { + wd_fn_type_t wd_fn_type; + addr_t wd_base_addr; + uint32_t wd_time_us; + uint32_t wd_timer_tick_us; +} wd_param_t; + +typedef enum { + UART_INIT = 0x1, + UART_PRINT = 0x2, +} uart_fn_type_t; + +/* + * Redefining some of the client.h elements for compilation to go through + * when PSA IPC APIs are not implemented. + */ +#if (PSA_IPC_IMPLEMENTED == 0) + +#ifndef PSA_VERSION_NONE +#define PSA_VERSION_NONE (0) +#endif + +typedef int32_t psa_handle_t; + +#ifndef PSA_NULL_HANDLE +#define PSA_NULL_HANDLE ((psa_handle_t)0) +#endif + + +#endif /* PSA_IPC_IMPLEMENTED */ + +#endif /* _PAL_COMMON_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_interfaces_ns.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_interfaces_ns.h new file mode 100644 index 0000000..6393a47 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_interfaces_ns.h @@ -0,0 +1,187 @@ +/** @file + * Copyright (c) 2018-2019, 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 _PAL_INTERFACES_NS_H_ +#define _PAL_INTERFACES_NS_H_ + +#include "val.h" +#include "val_client_defs.h" +#include + +/** + @brief - This function will read peripherals using SPI commands + @param - addr : address of the peripheral + - data : read buffer + - len : length of the read buffer in bytes + @return - error status +**/ +int pal_spi_read(addr_t addr, uint8_t *data, uint32_t len); + +/** + * @brief - Retrieve the version of the PSA Framework API that is implemented. + * This is a wrapper API for psa_framework_version API. + * @param - void + * @return - The PSA Framework API version. + * Note - Return PAL_STATUS_ERROR if PSA IPC is not implemented. + */ +uint32_t pal_ipc_framework_version(void); + +/** + * @brief - Retrieve the minor version of a Root of Trust Service by its SID. + * This is a wrapper API for the psa_version API. + * @param - sid The Root of Trust Service ID + * @return - Minor version of Root of Trust Service or PSA_VERSION_NONE if Root of Trust Service + * not present on the system. + * Note - Return PAL_STATUS_ERROR if PSA IPC is not implemented. + */ +uint32_t pal_ipc_version(uint32_t sid); + +/** + * @brief - Connect to given sid. + * This is a wrapper API for the psa_connect API. + * @param - sid : RoT service id + * - minor_version : minor_version of RoT service + * @return - psa_handle_t : return connection handle + * Note - Return PSA_NULL_HANDLE if PSA IPC is not implemented. + */ +psa_handle_t pal_ipc_connect(uint32_t sid, uint32_t minor_version); + +/** + * @brief - Call a connected Root of Trust Service. + * This is a wrapper API for the psa_call API. The caller must provide an array of + * psa_invec_t structures as the input payload. + * @param - handle: Handle for the connection. + * - in_vec: Array of psa_invec structures. + * - in_len: Number of psa_invec structures in in_vec. + * - out_vec: Array of psa_outvec structures for optional Root of Trust Service response. + * - out_len: Number of psa_outvec structures in out_vec. + * @return - psa_status_t + */ + +psa_status_t pal_ipc_call(psa_handle_t handle, + const psa_invec *in_vec, + size_t in_len, + psa_outvec *out_vec, + size_t out_len); + +/** + * @brief - Close a connection to a Root of Trust Service. + * This is a wrapper API for the psa_close API. + * Sends the PSA_IPC_DISCONNECT message to the Root of Trust Service + * so it can clean up resources. + * @param - handle Handle for the connection. + * @return - void + */ +void pal_ipc_close(psa_handle_t handle); +/** + @brief - This function initializes the UART + @param - uart base addr + @return - SUCCESS/FAILURE +**/ +int pal_uart_init_ns(uint32_t uart_base_addr); + +/** + * @brief - This function parses the input string and writes bytes into UART TX FIFO + * @param - str : Input String + * - data : Value for format specifier + * @return - SUCCESS/FAILURE +**/ + +int pal_print_ns(char *str, uint32_t data); + +/** + * @brief - Initializes an hardware watchdog timer + * @param - base_addr : Base address of the watchdog module + * - time_us : Time in micro seconds + * - timer_tick_us : Number of ticks per micro second + * @return - SUCCESS/FAILURE +**/ +int pal_wd_timer_init_ns(addr_t base_addr, uint32_t time_us, uint32_t timer_tick_us); + +/** + * @brief - Enables a hardware watchdog timer + * @param - base_addr : Base address of the watchdog module + * @return - SUCCESS/FAILURE +**/ +int pal_wd_timer_enable_ns(addr_t base_addr); + +/** + * @brief - Disables a hardware watchdog timer + * @param - base_addr : Base address of the watchdog module + * @return - SUCCESS/FAILURE +**/ +int pal_wd_timer_disable_ns(addr_t base_addr); + +/** + * @brief - Reads from given non-volatile address. + * @param - base : Base address of nvmem + * offset : Offset + * buffer : Pointer to source address + * size : Number of bytes + * @return - SUCCESS/FAILURE +**/ +int pal_nvmem_read_ns(addr_t base, uint32_t offset, void *buffer, int size); + +/** + * @brief - Writes into given non-volatile address. + * @param - base : Base address of nvmem + * offset : Offset + * buffer : Pointer to source address + * size : Number of bytes + * @return - SUCCESS/FAILURE +**/ +int pal_nvmem_write_ns(addr_t base, uint32_t offset, void *buffer, int size); + +/** + * @brief - This API will call the requested crypto function + * @param - type : function code + * valist : variable argument list + * @return - error status +**/ +int32_t pal_crypto_function(int type, va_list valist); + +/** + * @brief - This API will call the requested internal trusted storage function + * @param - type : function code + * valist : variable argument list + * @return - error status +**/ +uint32_t pal_its_function(int type, va_list valist); + +/** + * @brief - This API will call the requested protected storage function + * @param - type : function code + * valist : variable argument list + * @return - error status +**/ +uint32_t pal_ps_function(int type, va_list valist); + +/** + * @brief - This API will call the requested attestation function + * @param - type : function code + * valist : variable argument list + * @return - error status +**/ +int32_t pal_attestation_function(int type, va_list valist); + +/** + * @brief - Terminates the simulation at the end of all tests completion. + * By default, it put cpus into power down mode. + * @param - void + * @return - void +**/ +void pal_terminate_simulation(void); +#endif diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_internal_trusted_storage_intf.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_internal_trusted_storage_intf.c new file mode 100644 index 0000000..2e9de8c --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_internal_trusted_storage_intf.c @@ -0,0 +1,92 @@ +/** @file + * Copyright (c) 2018, 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 "pal_internal_trusted_storage_intf.h" + +/** + @brief - This API will call the requested internal trusted storage function + @param - type : function code + valist : variable argument list + @return - error status +**/ +uint32_t pal_its_function(int type, va_list valist) +{ +#if PSA_INTERNAL_TRUSTED_STORAGE_IMPLEMENTED + uint32_t uid, data_length, offset; + const void *p_write_data; + void *p_read_data; + psa_storage_create_flags_t its_create_flags; + //psa_ps_create_flags_t ps_create_flags; + struct psa_its_info_t *its_p_info; + //struct psa_eps_info_t *ps_p_info; + /* TODO: Actual size argument is currently not supported by the testing framework. + * Changes need to be implemented in the actual tests. + * Should be fixed by the next import of the tests. + */ + size_t actual_size; + + switch (type) { + case PAL_ITS_SET: + uid = va_arg(valist, psa_storage_uid_t); + data_length = va_arg(valist, uint32_t); + p_write_data = va_arg(valist, const void *); + its_create_flags = va_arg(valist, psa_storage_create_flags_t); + return psa_its_set(uid, data_length, p_write_data, its_create_flags); + case PAL_ITS_GET: + uid = va_arg(valist, psa_storage_uid_t); + offset = va_arg(valist, uint32_t); + data_length = va_arg(valist, uint32_t); + p_read_data = va_arg(valist, void *); + /* TODO: Actual size argument is currently not supported by the testing framework. + * Changes need to be implemented in the actual tests. + * Should be fixed by the next import of the tests. + */ + return psa_its_get(uid, offset, data_length, p_read_data, &actual_size); + case PAL_ITS_GET_INFO: + uid = va_arg(valist, psa_storage_uid_t); + its_p_info = va_arg(valist, struct psa_its_info_t *); + return psa_its_get_info(uid, (struct psa_storage_info_t *)its_p_info); + case PAL_ITS_REMOVE: + uid = va_arg(valist, psa_storage_uid_t); + return psa_its_remove(uid); + /* case PAL_PS_SET: */ + /* uid = va_arg(valist, uint32_t); */ + /* data_length = va_arg(valist, uint32_t); */ + /* p_write_data = va_arg(valist, const void*); */ + /* ps_create_flags = va_arg(valist, psa_ps_create_flags_t); */ + /* return psa_ps_set(uid, data_length, p_write_data, ps_create_flags); */ + /* case PAL_PS_GET: */ + /* uid = va_arg(valist, uint32_t); */ + /* offset = va_arg(valist, uint32_t); */ + /* data_length = va_arg(valist, uint32_t); */ + /* p_read_data = va_arg(valist, void*); */ + /* return psa_ps_get(uid, offset, data_length, p_read_data); */ + /* case PAL_PS_GET_INFO: */ + /* uid = va_arg(valist, uint32_t); */ + /* ps_p_info = va_arg(valist, struct psa_eps_info_t*); */ + /* return psa_ps_get_info(uid, ps_p_info); */ + /* case PAL_PS_REMOVE: */ + /* uid = va_arg(valist, uint32_t); */ + /* return psa_ps_remove(uid); */ + default: + return PAL_STATUS_UNSUPPORTED_FUNC; + } +#else + return PAL_STATUS_ERROR; +#endif +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_internal_trusted_storage_intf.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_internal_trusted_storage_intf.h new file mode 100644 index 0000000..c40aa43 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_internal_trusted_storage_intf.h @@ -0,0 +1,36 @@ +/** @file + * Copyright (c) 2018, 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 _PAL_INTERNAL_TRUSTED_STORAGE_INTF_H_ +#define _PAL_INTERNAL_TRUSTED_STORAGE_INTF_H_ + +#include +#include "pal_common.h" + +#if PSA_INTERNAL_TRUSTED_STORAGE_IMPLEMENTED +#include "psa/internal_trusted_storage.h" +#endif + +enum its_function_code { + PAL_ITS_SET = 0x1, + PAL_ITS_GET = 0x2, + PAL_ITS_GET_INFO = 0x3, + PAL_ITS_REMOVE = 0x4, +}; + +uint32_t pal_its_function(int type, va_list valist); +#endif /* _PAL_INTERNAL_TRUSTED_STORAGE_INTF_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_mbed_os_intf.cpp b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_mbed_os_intf.cpp new file mode 100644 index 0000000..be1c70e --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_mbed_os_intf.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2019-2020 Arm Limited. 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 "rtos.h" +#include "mbed_assert.h" +#include "val_interfaces.h" +#include "pal_common.h" + +#include "psa/crypto.h" +#include "entropy_poll.h" + +#include "psa_attest_inject_key.h" +#include "psa_initial_attestation_api.h" + +#include "pal_mbed_os_intf.h" + +#include "lifecycle.h" + +#define TEST_STACK_SIZE 8192 +#define TEST_KEY_ID_VALUE 17 + +extern val_api_t val_api; +extern psa_api_t psa_api; +#ifdef PS_TEST +extern "C" psa_status_t psa_ps_reset(); +#endif + +test_entry_f test_g = NULL; +compliance_test_type type_g = COMPLIANCE_TEST_UNDEFINED; + +// randomly generated attestation key used for testing the attestation feature. +// The specific key chosen shouldn't matter to the attestation test +// the test just needs a key to be injected before it is run. +static const uint8_t private_key_data[] = { + 0x49, 0xc9, 0xa8, 0xc1, 0x8c, 0x4b, 0x88, 0x56, + 0x38, 0xc4, 0x31, 0xcf, 0x1d, 0xf1, 0xc9, 0x94, + 0x13, 0x16, 0x09, 0xb5, 0x80, 0xd4, 0xfd, 0x43, + 0xa0, 0xca, 0xb1, 0x7d, 0xb2, 0xf1, 0x3e, 0xee +}; + +static const uint8_t public_key_data[] = { + 0x04, 0x77, 0x72, 0x65, 0x6f, 0x81, 0x4b, 0x39, + 0x92, 0x79, 0xd5, 0xe1, 0xf1, 0x78, 0x1f, 0xac, + 0x6f, 0x09, 0x9a, 0x3c, 0x5c, 0xa1, 0xb0, 0xe3, + 0x53, 0x51, 0x83, 0x4b, 0x08, 0xb6, 0x5e, 0x0b, + 0x57, 0x25, 0x90, 0xcd, 0xaf, 0x8f, 0x76, 0x93, + 0x61, 0xbc, 0xf3, 0x4a, 0xcf, 0xc1, 0x1e, 0x5e, + 0x07, 0x4e, 0x84, 0x26, 0xbd, 0xde, 0x04, 0xbe, + 0x6e, 0x65, 0x39, 0x45, 0x44, 0x96, 0x17, 0xde, + 0x45 +}; + +static void psa_attestation_destroy_key_for_test() +{ + psa_key_handle_t handle = 0; + psa_open_key(TEST_KEY_ID_VALUE, &handle); + psa_destroy_key(handle); +} + +static void psa_attestation_inject_key_for_test(void) +{ + size_t exported_length; + uint8_t exported[sizeof(public_key_data)]; + + psa_attestation_destroy_key_for_test(); + psa_attestation_inject_key(private_key_data, + sizeof(private_key_data), + PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1), + exported, + sizeof(exported), + &exported_length); +} + + + +static void reset_storage_for_compliance_test() +{ +#ifdef ITS_TEST + mbed_psa_reboot_and_request_new_security_state(PSA_LIFECYCLE_ASSEMBLY_AND_TEST); +#elif PS_TEST + psa_ps_reset(); +#endif +} + +#if !defined(MAX) +#define MAX(a,b) (((a)>(b))?(a):(b)) +#endif + +#define MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE \ + MAX(MBEDTLS_ENTROPY_MIN_PLATFORM, MBEDTLS_ENTROPY_BLOCK_SIZE) + +static void inject_entropy() +{ +#if defined(MBEDTLS_ENTROPY_NV_SEED) + uint8_t seed[MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE] = { 0 }; + for (int i = 0; i < MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE; ++i) { + seed[i] = i; + } + mbedtls_psa_inject_entropy(seed, MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE); +#endif // defined(MBEDTLS_ENTROPY_NV_SEED) +} + + + +void main_wrapper(void) +{ + test_g(&val_api, &psa_api); +} + + +void pal_mbed_os_compliance_test_initialize(void) +{ + if (COMPLIANCE_TEST_CRYPTO == type_g) { + inject_entropy(); + } else if (COMPLIANCE_TEST_STORAGE == type_g) { + reset_storage_for_compliance_test(); + } else if (COMPLIANCE_TEST_ATTESTATION == type_g) { + reset_storage_for_compliance_test(); + inject_entropy(); + psa_crypto_init(); + psa_attestation_inject_key_for_test(); // inject key in case needed + } + +} + +void pal_mbed_os_compliance_test_destroy(void) +{ + reset_storage_for_compliance_test(); +} + +int test_start(test_entry_f test_f, compliance_test_type type) +{ + test_g = test_f; + type_g = type; +#if defined(MBED_CONF_RTOS_PRESENT) + MBED_ASSERT((type > COMPLIANCE_TEST_START) && (type < COMPLIANCE_TEST_END)); + Thread thread(osPriorityNormal, TEST_STACK_SIZE, NULL); + thread.start(main_wrapper); + thread.join(); +#endif + return 0; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_mbed_os_intf.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_mbed_os_intf.h new file mode 100644 index 0000000..5308bf9 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_mbed_os_intf.h @@ -0,0 +1,26 @@ +#ifndef PAL_MBED_OS_CRYPTO_H_ +#define PAL_MBED_OS_CRYPTO_H_ + +#include "val_interfaces.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum _compliance_test_type { + COMPLIANCE_TEST_UNDEFINED, + COMPLIANCE_TEST_START = COMPLIANCE_TEST_UNDEFINED, + COMPLIANCE_TEST_CRYPTO, + COMPLIANCE_TEST_ATTESTATION, + COMPLIANCE_TEST_STORAGE, + COMPLIANCE_TEST_END +} compliance_test_type; + +typedef void (*test_entry_f)(val_api_t *val_api, psa_api_t *psa_api); +int test_start(test_entry_f test_f, compliance_test_type type); + +#ifdef __cplusplus +} +#endif + +#endif /* PAL_MBED_OS_CRYPTO_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_protected_storage_intf.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_protected_storage_intf.c new file mode 100644 index 0000000..893e5f3 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_protected_storage_intf.c @@ -0,0 +1,63 @@ +/** @file + * Copyright (c) 2018, 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 "pal_protected_storage_intf.h" + +/** + @brief - This API will call the requested protected storage function + @param - type : function code + valist : variable argument list + @return - error status +**/ +uint32_t pal_ps_function(int type, va_list valist) +{ +#if PSA_PROTECTED_STORAGE_IMPLEMENTED + uint32_t uid, data_length, offset; + size_t actual_length; + const void *p_write_data; + void *p_read_data; + psa_storage_create_flags_t ps_create_flags; + struct psa_ps_info_t *ps_p_info; + + switch (type) { + case PAL_PS_SET: + uid = va_arg(valist, psa_storage_uid_t); + data_length = va_arg(valist, uint32_t); + p_write_data = va_arg(valist, const void *); + ps_create_flags = va_arg(valist, psa_storage_create_flags_t); + return psa_ps_set(uid, data_length, p_write_data, ps_create_flags); + case PAL_PS_GET: + uid = va_arg(valist, psa_storage_uid_t); + offset = va_arg(valist, uint32_t); + data_length = va_arg(valist, uint32_t); + p_read_data = va_arg(valist, void *); + return psa_ps_get(uid, offset, data_length, p_read_data, &actual_length); + case PAL_PS_GET_INFO: + uid = va_arg(valist, psa_storage_uid_t); + ps_p_info = va_arg(valist, struct psa_ps_info_t *); + return psa_ps_get_info(uid, ps_p_info); + case PAL_PS_REMOVE: + uid = va_arg(valist, psa_storage_uid_t); + return psa_ps_remove(uid); + default: + return PAL_STATUS_UNSUPPORTED_FUNC; + } +#else + return PAL_STATUS_ERROR; +#endif +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_protected_storage_intf.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_protected_storage_intf.h new file mode 100644 index 0000000..3ebe86a --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/pal/pal_protected_storage_intf.h @@ -0,0 +1,36 @@ +/** @file + * Copyright (c) 2018, 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 _PAL_PROTECTED_STORAGE_INTF_H_ +#define _PAL_PROTECTED_STORAGE_INTF_H_ + +#include +#include "pal_common.h" + +#if PSA_PROTECTED_STORAGE_IMPLEMENTED +#include "psa/protected_storage.h" +#endif + +enum ps_function_code { + PAL_PS_SET = 0x1, + PAL_PS_GET = 0x2, + PAL_PS_GET_INFO = 0x3, + PAL_PS_REMOVE = 0x4, +}; + +uint32_t pal_ps_function(int type, va_list valist); +#endif /* _PAL_PROTECTED_STORAGE_INTF_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/LICENSE b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/LICENSE new file mode 100644 index 0000000..96810fd --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/LICENSE @@ -0,0 +1,2 @@ +Unless specifically indicated otherwise in a file, TF-M files in this directory are licensed under the BSD-3-Clause license, +as can be found in: LICENSE-bsd-3-clause.txt diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/LICENSE-BSD-3-Clause b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/LICENSE-BSD-3-Clause new file mode 100644 index 0000000..476769c --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/LICENSE-BSD-3-Clause @@ -0,0 +1,26 @@ +Copyright 2019 Arm Limited and affiliates. +SPDX-License-Identifier: BSD-3-Clause + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name of the copyright holder nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attest_boot_status_loader.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attest_boot_status_loader.c new file mode 100755 index 0000000..8413a67 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attest_boot_status_loader.c @@ -0,0 +1,95 @@ +/* +* Copyright (c) 2018-2019 ARM Limited. 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 +#include +#include "attestation.h" +#include "attestation_bootloader_data.h" +#include "tfm_impl/tfm_boot_status.h" +#ifdef TARGET_TFM +#include "region_defs.h" +#endif + +/*! + * \def SHARED_DATA_INITIALZED and SHARED_DATA_UNNITIALZED + * + * \brief Indicates that shared data was already initialized. + */ +#define SHARED_DATA_UNNITIALZED (0u) +#define SHARED_DATA_INITIALZED (1u) + +/*! + * \var shared_data_init_done + * + * \brief Indicates whether shared data area was already initialized. + * + */ +static uint32_t shared_data_init_done = SHARED_DATA_UNNITIALZED; + +enum psa_attest_err_t +attest_get_boot_data(uint8_t major_type, void *ptr, uint32_t len) { + if (shared_data_init_done == SHARED_DATA_INITIALZED) + { + return PSA_ATTEST_ERR_SUCCESS; + } + struct shared_data_tlv_header *tlv_header; + struct shared_data_tlv_header *ptr_tlv_header; + struct shared_data_tlv_entry *tlv_entry; + uintptr_t tlv_end, offset; + + /* Get the boundaries of TLV section */ + tlv_header = (struct shared_data_tlv_header *)BOOT_TFM_SHARED_DATA_BASE; + if (tlv_header->tlv_magic != SHARED_DATA_TLV_INFO_MAGIC) + { + return PSA_ATTEST_ERR_INIT_FAILED; + } + tlv_end = (uintptr_t)BOOT_TFM_SHARED_DATA_BASE + (uintptr_t)tlv_header->tlv_tot_len; + offset = (uintptr_t)BOOT_TFM_SHARED_DATA_BASE + (uintptr_t)SHARED_DATA_HEADER_SIZE; + + /* Add header to output buffer as well */ + if (len < SHARED_DATA_HEADER_SIZE) + { + return PSA_ATTEST_ERR_INIT_FAILED; + } + ptr_tlv_header = (struct shared_data_tlv_header *)ptr; + ptr_tlv_header->tlv_magic = SHARED_DATA_TLV_INFO_MAGIC; + ptr_tlv_header->tlv_tot_len = SHARED_DATA_HEADER_SIZE; + + ptr = (uint8_t *)ptr + SHARED_DATA_HEADER_SIZE; + /* Iterates over the TLV section and copy TLVs with requested major + * type to the provided buffer. + */ + for (; offset < tlv_end; offset += tlv_entry->tlv_len) + { + tlv_entry = (struct shared_data_tlv_entry *)offset; + if (GET_MAJOR(tlv_entry->tlv_type) == major_type) { + if (len < ptr_tlv_header->tlv_tot_len + tlv_entry->tlv_len) { + return PSA_ATTEST_ERR_INIT_FAILED; + } + memcpy(ptr, (const void *)tlv_entry, tlv_entry->tlv_len); + ptr = (uint8_t *)ptr + tlv_entry->tlv_len; + ptr_tlv_header->tlv_tot_len += tlv_entry->tlv_len; + } + if (tlv_entry->tlv_len == 0) { + break; + } + } + + shared_data_init_done = SHARED_DATA_INITIALZED; + return PSA_ATTEST_ERR_SUCCESS; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attest_crypto.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attest_crypto.c new file mode 100755 index 0000000..f92fc18 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attest_crypto.c @@ -0,0 +1,275 @@ +/* + * attest_crypto.c + * + * Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * See BSD-3-Clause license in README.md + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "t_cose_crypto.h" +#include "tfm_plat_defs.h" +#include "psa/crypto.h" +#include "tfm_plat_crypto_keys.h" +#include + +#define PSA_ATTESTATION_PRIVATE_KEY_ID 17 + +/** + * \brief Context for PSA hash adaptation. + * + * Hash context for PSA hash implementation. This is fit into and cast + * to/from struct \ref t_cose_crypto_hash. + */ +struct t_cose_psa_crypto_hash { + psa_status_t status; + psa_hash_operation_t operation; +}; + +enum t_cose_err_t +t_cose_crypto_pub_key_sign(int32_t cose_alg_id, + int32_t key_select, + struct useful_buf_c hash_to_sign, + struct useful_buf signature_buffer, + struct useful_buf_c *signature) { + enum t_cose_err_t cose_ret = T_COSE_SUCCESS; + psa_status_t crypto_ret; + const size_t sig_size = t_cose_signature_size(cose_alg_id); + + (void)key_select; + + psa_key_handle_t handle; + + if (sig_size > signature_buffer.len) + { + return T_COSE_ERR_SIG_BUFFER_SIZE; + } + + crypto_ret = psa_open_key(PSA_ATTESTATION_PRIVATE_KEY_ID, &handle); + if (crypto_ret != PSA_SUCCESS) + { + return T_COSE_ERR_NO_KID; + } + + crypto_ret = psa_sign_hash(handle, + PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256), + hash_to_sign.ptr, + hash_to_sign.len, + signature_buffer.ptr, + signature_buffer.len, + &(signature->len)); + + + if (crypto_ret != PSA_SUCCESS) + { + psa_close_key(handle); + cose_ret = T_COSE_ERR_UNSUPPORTED_SIGNING_ALG; + } else + { + signature->ptr = signature_buffer.ptr; + } + + psa_close_key(handle); + return cose_ret; +} + +enum t_cose_err_t +t_cose_crypto_get_ec_pub_key(int32_t key_select, + struct useful_buf_c kid, + int32_t *cose_curve_id, + struct useful_buf buf_to_hold_x_coord, + struct useful_buf buf_to_hold_y_coord, + struct useful_buf_c *x_coord, + struct useful_buf_c *y_coord) { + + enum tfm_plat_err_t err; + enum ecc_curve_t cose_curve; + struct ecc_key_t attest_key = {0}; + uint8_t key_buf[ECC_P_256_KEY_SIZE] = {0}; + + (void)key_select; + + /* Get the initial attestation key */ + err = tfm_plat_get_initial_attest_key(key_buf, sizeof(key_buf), + &attest_key, &cose_curve); + + /* Check the availability of the private key */ + if (err != TFM_PLAT_ERR_SUCCESS || + attest_key.pubx_key == NULL || + attest_key.puby_key == NULL) + { + return T_COSE_ERR_KEY_BUFFER_SIZE; + } + + *cose_curve_id = (int32_t)cose_curve; + + /* Check buffer size to avoid overflow */ + if (buf_to_hold_x_coord.len < attest_key.pubx_key_size) + { + return T_COSE_ERR_KEY_BUFFER_SIZE; + } + + /* Copy the X coordinate of the public key to the buffer */ + memcpy(buf_to_hold_x_coord.ptr, + (const void *)attest_key.pubx_key, + attest_key.pubx_key_size); + + /* Update size */ + buf_to_hold_x_coord.len = attest_key.pubx_key_size; + + /* Check buffer size to avoid overflow */ + if (buf_to_hold_y_coord.len < attest_key.puby_key_size) + { + return T_COSE_ERR_KEY_BUFFER_SIZE; + } + + /* Copy the Y coordinate of the public key to the buffer */ + memcpy(buf_to_hold_y_coord.ptr, + (const void *)attest_key.puby_key, + attest_key.puby_key_size); + + /* Update size */ + buf_to_hold_y_coord.len = attest_key.puby_key_size; + + x_coord->ptr = buf_to_hold_x_coord.ptr; + x_coord->len = buf_to_hold_x_coord.len; + y_coord->ptr = buf_to_hold_y_coord.ptr; + y_coord->len = buf_to_hold_y_coord.len; + + return T_COSE_SUCCESS; +} + +/** + * \brief Check some of the sizes for hash implementation. + * + * \return Value from \ref t_cose_err_t error if sizes are not correct. + * + * It makes sure the constants in the header file match the local + * implementation. This gets evaluated at compile time and will + * optimize out to nothing when all checks pass. + */ +static inline enum t_cose_err_t check_hash_sizes() +{ + if (T_COSE_CRYPTO_SHA256_SIZE != PSA_HASH_SIZE(PSA_ALG_SHA_256)) { + return T_COSE_ERR_HASH_GENERAL_FAIL; + } + + return T_COSE_SUCCESS; +} + +/** + * \brief Convert COSE algorithm ID to a PSA algorithm ID + * + * \param[in] cose_hash_alg_id The COSE-based ID for the + * + * \return PSA-based hash algorithm ID, or MD4 in the case of error. + * + */ +static inline psa_algorithm_t cose_hash_alg_id_to_psa(int32_t cose_hash_alg_id) +{ + psa_algorithm_t return_value; + + switch (cose_hash_alg_id) { + case COSE_ALG_SHA256_PROPRIETARY: + return_value = PSA_ALG_SHA_256; + break; + default: + return_value = PSA_ALG_MD4; + break; + } + + return return_value; +} + +enum t_cose_err_t +t_cose_crypto_hash_start(struct t_cose_crypto_hash *hash_ctx, + int32_t cose_hash_alg_id) { + enum t_cose_err_t cose_ret = T_COSE_SUCCESS; + psa_status_t psa_ret; + struct t_cose_psa_crypto_hash *psa_hash_ctx; + + /* These next 3 lines optimize to nothing except when there is + * failure. + */ + cose_ret = check_hash_sizes(); + if (cose_ret != T_COSE_SUCCESS) + { + return cose_ret; + } + + psa_hash_ctx = (struct t_cose_psa_crypto_hash *)hash_ctx; + memset(&psa_hash_ctx->operation, 0, sizeof(psa_hash_operation_t)); + + psa_ret = psa_hash_setup(&psa_hash_ctx->operation, + cose_hash_alg_id_to_psa(cose_hash_alg_id)); + + if (psa_ret == PSA_SUCCESS) + { + psa_hash_ctx->status = PSA_SUCCESS; + cose_ret = T_COSE_SUCCESS; + } else if (psa_ret == PSA_ERROR_NOT_SUPPORTED) + { + cose_ret = T_COSE_ERR_UNSUPPORTED_HASH; + } else + { + cose_ret = T_COSE_ERR_HASH_GENERAL_FAIL; + } + + return cose_ret; +} + +void t_cose_crypto_hash_update(struct t_cose_crypto_hash *hash_ctx, + struct useful_buf_c data_to_hash) +{ + struct t_cose_psa_crypto_hash *psa_hash_ctx; + + psa_hash_ctx = (struct t_cose_psa_crypto_hash *)hash_ctx; + + if (psa_hash_ctx->status == PSA_SUCCESS) { + if (data_to_hash.ptr != NULL) { + psa_hash_ctx->status = psa_hash_update(&psa_hash_ctx->operation, + data_to_hash.ptr, + data_to_hash.len); + } + } +} + +enum t_cose_err_t +t_cose_crypto_hash_finish(struct t_cose_crypto_hash *hash_ctx, + struct useful_buf buffer_to_hold_result, + struct useful_buf_c *hash_result) { + enum t_cose_err_t cose_ret = T_COSE_SUCCESS; + psa_status_t psa_ret; + struct t_cose_psa_crypto_hash *psa_hash_ctx; + + psa_hash_ctx = (struct t_cose_psa_crypto_hash *)hash_ctx; + + if (psa_hash_ctx->status == PSA_SUCCESS) + { + psa_ret = psa_hash_finish(&psa_hash_ctx->operation, + buffer_to_hold_result.ptr, + buffer_to_hold_result.len, + &(hash_result->len)); + + if (psa_ret == PSA_SUCCESS) { + hash_result->ptr = buffer_to_hold_result.ptr; + cose_ret = T_COSE_SUCCESS; + } else if (psa_ret == PSA_ERROR_BUFFER_TOO_SMALL) { + cose_ret = T_COSE_ERR_HASH_BUFFER_SIZE; + } else { + cose_ret = T_COSE_ERR_HASH_GENERAL_FAIL; + } + } else + { + cose_ret = T_COSE_ERR_HASH_GENERAL_FAIL; + } + + return cose_ret; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attest_crypto_keys.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attest_crypto_keys.c new file mode 100755 index 0000000..e67227c --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attest_crypto_keys.c @@ -0,0 +1,182 @@ +/* +* Copyright (c) 2018-2019 ARM Limited. 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 "tfm_plat_crypto_keys.h" +#include "psa/crypto.h" + +#include +#include + + +#define ONE_BYTE (1u) +#define PSA_ATTESTATION_PRIVATE_KEY_ID 17 + +/** + * \brief Copy the key to the destination buffer + * + * \param[out] p_dst Pointer to buffer where to store the key + * \param[in] p_src Pointer to the key + * \param[in] size Length of the key + */ +static inline void copy_key(uint8_t *p_dst, const uint8_t *p_src, size_t size) +{ + uint32_t i; + + for (i = size; i > 0; i--) { + *p_dst = *p_src; + p_src++; + p_dst++; + } +} + +static psa_status_t get_curve(psa_key_type_t type, enum ecc_curve_t *curve_type) +{ + psa_ecc_curve_t curve = PSA_KEY_TYPE_GET_CURVE(type); + switch (curve) { + case PSA_ECC_CURVE_SECP_R1: + *curve_type = P_256; + break; + case PSA_ECC_CURVE_MONTGOMERY: + *curve_type = X25519; + break; + default: + return (PSA_ERROR_NOT_SUPPORTED); + } + + return PSA_SUCCESS; +} + +enum tfm_plat_err_t +tfm_plat_get_initial_attest_key(uint8_t *key_buf, + uint32_t size, + struct ecc_key_t *ecc_key, + enum ecc_curve_t *curve_type) + +{ + uint8_t *key_dst = NULL; + uint8_t *key_src; + uint32_t key_size; + + psa_status_t crypto_ret; + + uint8_t *public_key = NULL; + psa_key_type_t type; + psa_key_type_t public_type; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + size_t bits; + size_t public_key_size = 0; + size_t public_key_length = 0; + + uint32_t initial_attestation_public_x_key_size = 0; + uint32_t initial_attestation_public_y_key_size = 0; + + psa_key_handle_t handle; + + crypto_ret = psa_open_key(PSA_ATTESTATION_PRIVATE_KEY_ID, &handle); + if (crypto_ret != PSA_SUCCESS) + { + return TFM_PLAT_ERR_SYSTEM_ERR; + } + + crypto_ret = psa_get_key_attributes(handle, &attributes); + if (crypto_ret != PSA_SUCCESS) + { + psa_close_key(handle); + return TFM_PLAT_ERR_SYSTEM_ERR; + } + type = psa_get_key_type(&attributes); + if (!PSA_KEY_TYPE_IS_ECC(type)) + { + psa_close_key(handle); + return TFM_PLAT_ERR_SYSTEM_ERR; + } + public_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type); + bits = psa_get_key_bits(&attributes); + public_key_size = PSA_KEY_EXPORT_MAX_SIZE(public_type, bits); + public_key = (uint8_t *) malloc(public_key_size); + if (public_key == NULL) + { + psa_close_key(handle); + return TFM_PLAT_ERR_SYSTEM_ERR; + } + + crypto_ret = psa_export_public_key(handle, + public_key, public_key_size, + &public_key_length); + if (crypto_ret != PSA_SUCCESS) + { + free(public_key); + psa_close_key(handle); + return TFM_PLAT_ERR_SYSTEM_ERR; + } + + /* Set the EC curve type which the key belongs to */ + crypto_ret = get_curve(type, curve_type); + if (crypto_ret != PSA_SUCCESS) + { + free(public_key); + psa_close_key(handle); + return TFM_PLAT_ERR_SYSTEM_ERR; + } + + key_src = public_key; + key_dst = key_buf; + + /* The representation of an ECC public key is: + ** -The byte 0x04 + ** - `x_P` as a `ceiling(m/8)`-byte string, big-endian + ** - `y_P` as a `ceiling(m/8)`-byte string, big-endian + ** - where m is the bit size associated with the curve + ** - 1 byte + 2 * point size + */ + initial_attestation_public_x_key_size = ceil((public_key_length - 1) / 2); + initial_attestation_public_y_key_size = ceil((public_key_length - 1) / 2); + + /* Copy the x-coordinate of public key to the buffer */ + if (initial_attestation_public_x_key_size != 0) + { + key_src = key_src + ONE_BYTE; + key_size = initial_attestation_public_x_key_size; + copy_key(key_dst, key_src, key_size); + ecc_key->pubx_key = key_dst; + ecc_key->pubx_key_size = key_size; + key_dst = key_dst + key_size; + } else + { + ecc_key->pubx_key = NULL; + ecc_key->pubx_key_size = 0; + } + + /* Copy the y-coordinate of public key to the buffer */ + if (initial_attestation_public_y_key_size != 0) + { + key_src += initial_attestation_public_x_key_size; + key_size = initial_attestation_public_y_key_size; + copy_key(key_dst, key_src, key_size); + ecc_key->puby_key = key_dst; + ecc_key->puby_key_size = key_size; + } else + { + ecc_key->puby_key = NULL; + ecc_key->puby_key_size = 0; + } + + free(public_key); + psa_close_key(handle); + return TFM_PLAT_ERR_SUCCESS; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attest_iat_claims_loader.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attest_iat_claims_loader.c new file mode 100755 index 0000000..cfabfef --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attest_iat_claims_loader.c @@ -0,0 +1,220 @@ +/* +* Copyright (c) 2018-2019 ARM Limited. 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 +#include +#include +#include +#include "tfm_plat_boot_seed.h" +#include "attestation_bootloader_data.h" +#include "tfm_attest_hal.h" +#include "psa_initial_attestation_api.h" +#include "attestation.h" +#include "psa/crypto.h" +#include "psa/lifecycle.h" + +extern int32_t g_caller_id; + +#define ATTEST_PUB_KEY_SHA_256_SIZE (32u) +#define PSA_ATTESTATION_PRIVATE_KEY_ID 17 + +static enum tfm_security_lifecycle_t security_lifecycle_psa_to_tfm(void) +{ + uint32_t lc = psa_security_lifecycle_state(); + switch (lc) { + case PSA_LIFECYCLE_UNKNOWN: + return TFM_SLC_UNKNOWN; + case PSA_LIFECYCLE_ASSEMBLY_AND_TEST: + return TFM_SLC_ASSEMBLY_AND_TEST; + case PSA_LIFECYCLE_PSA_ROT_PROVISIONING: + return TFM_SLC_PSA_ROT_PROVISIONING; + case PSA_LIFECYCLE_SECURED: + return TFM_SLC_SECURED; + case PSA_LIFECYCLE_NON_PSA_ROT_DEBUG: + return TFM_SLC_NON_PSA_ROT_DEBUG; + case PSA_LIFECYCLE_RECOVERABLE_PSA_ROT_DEBUG: + return TFM_SLC_RECOVERABLE_PSA_ROT_DEBUG; + case PSA_LIFECYCLE_DECOMMISSIONED: + return TFM_SLC_DECOMMISSIONED; + default: + return TFM_SLC_UNKNOWN; + } +} + +/* Hash of attestation public key */ +static enum tfm_plat_err_t attest_public_key_sha256(uint32_t *size, uint8_t *buf) +{ + psa_key_handle_t handle = 0; + + uint8_t *public_key = NULL; + psa_key_type_t type; + psa_key_type_t public_type; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + size_t bits; + size_t public_key_size = 0; + size_t public_key_length = 0; + + psa_status_t crypto_ret; + enum tfm_plat_err_t status = TFM_PLAT_ERR_SUCCESS; + psa_hash_operation_t hash_handle = {0}; + + crypto_ret = psa_open_key(PSA_ATTESTATION_PRIVATE_KEY_ID, &handle); + if (crypto_ret != PSA_SUCCESS) { + return TFM_PLAT_ERR_SYSTEM_ERR; + } + + crypto_ret = psa_get_key_attributes(handle, &attributes); + if (crypto_ret != PSA_SUCCESS) { + status = TFM_PLAT_ERR_SYSTEM_ERR; + goto exit; + } + type = psa_get_key_type(&attributes); + if (!PSA_KEY_TYPE_IS_ECC(type)) { + status = TFM_PLAT_ERR_SYSTEM_ERR; + goto exit; + } + public_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type); + bits = psa_get_key_bits(&attributes); + public_key_size = PSA_KEY_EXPORT_MAX_SIZE(public_type, bits); + public_key = (uint8_t *) malloc(public_key_size); + if (public_key == NULL) { + status = TFM_PLAT_ERR_SYSTEM_ERR; + goto exit; + } + + crypto_ret = psa_export_public_key(handle, + public_key, public_key_size, + &public_key_length); + if (crypto_ret != PSA_SUCCESS) { + status = TFM_PLAT_ERR_SYSTEM_ERR; + goto exit; + } + + crypto_ret = psa_hash_setup(&hash_handle, PSA_ALG_SHA_256); + if (crypto_ret != PSA_SUCCESS) { + status = TFM_PLAT_ERR_SYSTEM_ERR; + goto exit; + } + + psa_hash_update(&hash_handle, public_key, public_key_length); + + crypto_ret = psa_hash_finish(&hash_handle, + buf, + ATTEST_PUB_KEY_SHA_256_SIZE, + (size_t *) size); + if (crypto_ret != PSA_SUCCESS) { + status = TFM_PLAT_ERR_SYSTEM_ERR; + goto exit; + } + +exit: + if (public_key != NULL) { + free(public_key); + } + psa_close_key(handle); + return status; +} + +/** + * \brief Copy the device specific ID to the destination buffer + * + * \param[out] p_dst Pointer to buffer where to store ID + * \param[in] p_src Pointer to the ID + * \param[in] size Length of the ID + */ +static inline void copy_id(uint8_t *p_dst, uint8_t *p_src, size_t size) +{ + uint32_t i; + + for (i = size; i > 0; i--) { + *p_dst = *p_src; + p_src++; + p_dst++; + } +} + +enum psa_attest_err_t attest_get_caller_client_id(int32_t *caller_id) +{ + *caller_id = g_caller_id; + return PSA_ATTEST_ERR_SUCCESS; +} + +/* Boot seed data is part of bootloader status*/ +enum tfm_plat_err_t tfm_plat_get_boot_seed(uint32_t size, uint8_t *buf) +{ + return (enum tfm_plat_err_t)PSA_ATTEST_ERR_CLAIM_UNAVAILABLE; +} + +/** + * Instance ID is mapped to EAT Universal Entity ID (UEID) + * This implementation creates the instance ID as follows: + * - byte 0: 0x01 indicates the type of UEID to be GUID + * - byte 1-32: Hash of attestation public key. Public key is hashed in raw + * format without any encoding. + */ +enum tfm_plat_err_t tfm_plat_get_instance_id(uint32_t *size, uint8_t *buf) +{ + enum tfm_plat_err_t status; + + buf[0] = 0x01; /* First byte is type byte: 0x01 indicates GUID */ + + status = attest_public_key_sha256(size, &buf[1]); + + /* Instance ID size: 1 type byte + size of public key hash */ + *size = *size + 1; + + return status; +} + +/* HW version data is part of bootloader status*/ +enum tfm_plat_err_t tfm_plat_get_hw_version(uint32_t *size, uint8_t *buf) +{ + return (enum tfm_plat_err_t)PSA_ATTEST_ERR_CLAIM_UNAVAILABLE; +} + +enum tfm_plat_err_t tfm_plat_get_implementation_id(uint32_t *size, uint8_t *buf) +{ + memcpy(buf, impl_id_data, *size); + return (enum tfm_plat_err_t)PSA_ATTEST_ERR_SUCCESS; +} + +/* Temporary Implementation of security lifecycle data: mandatory claim. +** tfm_attest_hal_get_security_lifecycle function should return +** 'PSA_ATTEST_ERR_CLAIM_UNAVAILABLE' if been called. +** Security lifecycle data is part of bootloader status data. +** Temp implementation of using psa_security_lifecycle_state */ + +enum tfm_security_lifecycle_t tfm_attest_hal_get_security_lifecycle(void) +{ + return security_lifecycle_psa_to_tfm(); +} + + +const char * +tfm_attest_hal_get_verification_service(uint32_t *size) +{ + *size = sizeof(verification_service_url) - 1; + return verification_service_url; +} + +const char * +tfm_attest_hal_get_profile_definition(uint32_t *size) +{ + *size = sizeof(attestation_profile_definition) - 1; + return attestation_profile_definition; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attestation.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attestation.h new file mode 100755 index 0000000..b2b8d1b --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attestation.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2018-2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/** @addtogroup PSA-Attestation + * @{ + */ + + +#ifndef __ATTESTATION_H__ +#define __ATTESTATION_H__ + +#include "psa_initial_attestation_api.h" +#include "tfm_client.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Type of memory access + */ +enum attest_memory_access_t { + TFM_ATTEST_ACCESS_RO = 1, + TFM_ATTEST_ACCESS_RW = 2, +}; + +/** + * \brief Copy the boot data (coming from boot loader) from shared memory area + * to service memory area + * + * \param[in] major_type Major type of TLV entries to copy + * \param[out] ptr Pointer to the buffer to store the boot data + * \parma[in] len Size of the buffer to store the boot data + * + * \return Returns error code as specified in \ref psa_attest_err_t + */ +enum psa_attest_err_t +attest_get_boot_data(uint8_t major_type, void *ptr, uint32_t len); + +/** + * \brief Get the ID of the caller thread. + * + * \param[out] caller_id Pointer where to store caller ID + * + * \return Returns error code as specified in \ref psa_attest_err_t + */ +enum psa_attest_err_t +attest_get_caller_client_id(int32_t *caller_id); + +/** + * \brief Verify memory access rights + * + * \param[in] addr Pointer to the base of the address range to check + * \param[in] size Size of the address range to check + * \param[in] access Type of memory access as specified in + * \ref attest_memory_access + * + * \return Returns error code as specified in \ref psa_attest_err_t + */ +enum psa_attest_err_t +attest_check_memory_access(void *addr, + uint32_t size, + enum attest_memory_access_t access); + +/** + * \brief Initialise the initial attestation service during the TF-M boot up + * process. + * + * \return Returns PSA_ATTEST_ERR_SUCCESS if init has been completed, + * otherwise error as specified in \ref psa_attest_err_t + */ +enum psa_attest_err_t attest_init(void); + +/** + * \brief Get initial attestation token + * + * \param[in] in_vec Pointer to in_vec array, which contains input data + * to attestation service + * \param[in] num_invec Number of elements in in_vec array + * \param[in/out] out_vec Pointer out_vec array, which contains output data + * to attestation service + * \param[in] num_outvec Number of elements in out_vec array + * + * \return Returns error code as specified in \ref psa_attest_err_t + */ +enum psa_attest_err_t +initial_attest_get_token(const psa_invec *in_vec, uint32_t num_invec, + psa_outvec *out_vec, uint32_t num_outvec); + +/** + * \brief Get the size of the initial attestation token + * + * \param[in] in_vec Pointer to in_vec array, which contains input data + * to attestation service + * \param[in] num_invec Number of elements in in_vec array + * \param[out] out_vec Pointer to out_vec array, which contains pointer + * where to store the output data + * \param[in] num_outvec Number of elements in out_vec array + * + * \return Returns error code as specified in \ref psa_attest_err_t + */ +enum psa_attest_err_t +initial_attest_get_token_size(const psa_invec *in_vec, uint32_t num_invec, + psa_outvec *out_vec, uint32_t num_outvec); +#ifdef __cplusplus +} +#endif + +/** @}*/ // PSA-Attestation + +#endif /* __ATTESTATION_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attestation_bootloader_data.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attestation_bootloader_data.c new file mode 100755 index 0000000..797ecea --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attestation_bootloader_data.c @@ -0,0 +1,64 @@ +/* +* Copyright (c) 2018-2019 ARM Limited. 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 "attestation_bootloader_data.h" + +/* Temporary Boodloader data - contains temp mandatory claims */ +__attribute__((aligned(4))) +const uint8_t temp_ram_page_data[] = { + 0x16, 0x20, 0xAC, 0x00, //shared_data_tlv_header + 0x83, 0x11, 0x0C, 0x00, // SW_TYPE + 0x4E, 0x53, 0x50, 0x45, 0x5F, 0x53, 0x50, 0x45, + 0x80, 0x11, 0x0A, 0x00, //SW_VERSION + 0x31, 0x2E, 0x31, 0x2E, 0x31, 0x31, + 0x82, 0x11, 0x06, 0x00, //SW_EPOCH + 0x00, 0x00, + 0x88, 0x11, 0x24, 0x00, //SW_MEASURE_VALUE + 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, + 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, + 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, + 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, + 0x81, 0x11, 0x24, 0x00, //SW_SIGNER_ID + 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, + 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, + 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, + 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, + 0x89, 0x11, 0x0A, 0x00, //SW_MEASURE_TYPE + 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, + 0x00, 0x10, 0x24, 0x00, //TLV_MINOR_IAS_BOOT_SEED + 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, + 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, + 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, + 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, + 0x01, 0x10, 0x16, 0x00, //TLV_MINOR_IAS_HW_VERSION + 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, + 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, + 0x31, 0x32 +}; + +/* Temporary Implementation ID data: mandatory claim represents the original +** implementation signer of the attestation key and identifies the contract +** between the report and verification */ +#define TEMP_IMPL_ID_DATA_SIZE (32u) + +#define TEMP_IMPL_ID_DATA 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, \ + 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, \ + 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, \ + 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF + +const uint8_t impl_id_data[TEMP_IMPL_ID_DATA_SIZE] = {TEMP_IMPL_ID_DATA}; diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attestation_bootloader_data.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attestation_bootloader_data.h new file mode 100755 index 0000000..6f0c560 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/attestation_bootloader_data.h @@ -0,0 +1,48 @@ +/* +* Copyright (c) 2018-2019 ARM Limited. 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 __ATTESTATION_BOOTLOADER_DATA_H__ +#define __ATTESTATION_BOOTLOADER_DATA_H__ + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Temp Shared data area between bootloader and runtime firmware */ +extern const uint8_t temp_ram_page_data[]; + +#define S_RAM_ALIAS_BASE (temp_ram_page_data) + +#define BOOT_TFM_SHARED_DATA_BASE S_RAM_ALIAS_BASE + +extern const uint8_t impl_id_data[]; + +/* Example verification service URL for initial attestation token - temporary data*/ +static const char verification_service_url[] = "www.mbed.com"; +/* Example profile definition document for initial attestation token - temporary data*/ +static const char attestation_profile_definition[] = "psa-attest.md"; + +#ifdef __cplusplus +} +#endif + +#endif /* __ATTESTATION_BOOTLOADER_DATA_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_attest_inject_key.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_attest_inject_key.c new file mode 100755 index 0000000..acb93a6 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_attest_inject_key.c @@ -0,0 +1,38 @@ +/* +* Copyright (c) 2018-2019 ARM Limited. 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 "psa_attest_inject_key.h" +#include "psa_inject_attestation_key_impl.h" + +psa_status_t +psa_attestation_inject_key(const uint8_t *key_data, + size_t key_data_length, + psa_key_type_t type, + uint8_t *public_key_data, + size_t public_key_data_size, + size_t *public_key_data_length) +{ + psa_status_t status = PSA_SUCCESS; + status = psa_attestation_inject_key_impl(key_data, + key_data_length, + type, + public_key_data, + public_key_data_size, + public_key_data_length); + return (status); +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_attest_inject_key.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_attest_inject_key.h new file mode 100644 index 0000000..3e934d3 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_attest_inject_key.h @@ -0,0 +1,87 @@ +/* +* Copyright (c) 2018-2019 ARM Limited. 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. +*/ + +/** @addtogroup PSA-Attestation + * @{ + */ + +#ifndef __PSA_INJECT_KEY_H__ +#define __PSA_INJECT_KEY_H__ + +#include "psa/crypto.h" +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * \brief Generate or import a given key pair and export the public part in a binary format. + * Initial attestation key: Private key for ECDSA-P256 to sign initial attestation token. + * Attestation private key is a persistent key that saved to + * persistent storage with persistent storage id = 17. + * + * \param[in] key_data Buffer containing the private key data if given. + * It must conain the format described in the documentation + * of psa_export_public_key() for + * the chosen type. + * In case of generate the private key - NULL will pass. + * \param key_data_length Size of the \p data buffer in bytes - must be 256 bits. in case key_data isn't NULL. + * In case of private key generation - 0 will pass. + * \param type Key type - must be a ECC key type + * (a \c PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_XXX) value). + * \param[out] data Buffer where the key data is to be written. + * \param data_size Size of the \p data buffer in bytes - + * needs to be bigger then the max size of the public part. + * \param[out] data_length On success, the number of bytes + * that make up the key data. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_OCCUPIED_SLOT + * There is already a key in the specified slot. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t +psa_attestation_inject_key(const uint8_t *key_data, + size_t key_data_length, + psa_key_type_t type, + uint8_t *public_key_data, + size_t public_key_data_size, + size_t *public_key_data_length); + +#ifdef __cplusplus +} +#endif + +/** @}*/ // PSA-Attestation + +#endif /* __PSA_INJECT_KEY_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_attestation_stubs.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_attestation_stubs.c new file mode 100755 index 0000000..b36c64a --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_attestation_stubs.c @@ -0,0 +1,31 @@ +/* +* Copyright (c) 2018-2019 ARM Limited. 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 +#include "attestation.h" + +enum psa_attest_err_t +attest_check_memory_access(void *addr, + uint32_t size, + enum attest_memory_access_t access) { + if (size == 0) + { + return PSA_ATTEST_ERR_INVALID_INPUT; + } + return PSA_ATTEST_ERR_SUCCESS; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_initial_attestation_api.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_initial_attestation_api.c new file mode 100755 index 0000000..c4eb017 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_initial_attestation_api.c @@ -0,0 +1,70 @@ +/* +* Copyright (c) 2018-2019 ARM Limited. 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 "psa_initial_attestation_api.h" +#include "psa/client.h" +#include "attestation.h" +#include + +int32_t g_caller_id = 0; + +enum psa_attest_err_t +psa_initial_attest_get_token(const uint8_t *challenge_obj, + uint32_t challenge_size, + uint8_t *token, + uint32_t *token_size) { + enum psa_attest_err_t err; + + err = attest_init(); + if (err != PSA_ATTEST_ERR_SUCCESS) + { + return err; + } + + psa_invec in_vec[1] = { { challenge_obj, challenge_size } }; + psa_outvec out_vec[1] = { { token, *token_size } }; + + err = initial_attest_get_token(in_vec, 1, out_vec, 1); + if (err != PSA_ATTEST_ERR_SUCCESS) + { + return err; + } + + *token_size = out_vec[0].len; + + return err; +} + +enum psa_attest_err_t +psa_initial_attest_get_token_size(uint32_t challenge_size, + uint32_t *token_size) { + enum psa_attest_err_t err; + + err = attest_init(); + if (err != PSA_ATTEST_ERR_SUCCESS) + { + return err; + } + + psa_invec in_vec[1] = { { &challenge_size, sizeof(challenge_size) } }; + psa_outvec out_vec[1] = { { token_size, sizeof(*token_size) } }; + + err = initial_attest_get_token_size(in_vec, 1, out_vec, 1); + + return err; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_initial_attestation_api.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_initial_attestation_api.h new file mode 100644 index 0000000..0b56499 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_initial_attestation_api.h @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2018-2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/***************************************************************************/ +/* DRAFT UNDER REVIEW */ +/* These APIs are still evolving and are meant as a prototype for review.*/ +/* The APIs will change depending on feedback and will be firmed up */ +/* to a stable set of APIs once all the feedback has been considered. */ +/***************************************************************************/ + +/** @addtogroup PSA-Attestation + * @{ + */ + + +#ifndef __PSA_INITIAL_ATTESTATION_API_H__ +#define __PSA_INITIAL_ATTESTATION_API_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief PSA INITIAL ATTESTATION API version + */ +#define PSA_INITIAL_ATTEST_API_VERSION_MAJOR (0) +#define PSA_INITIAL_ATTEST_API_VERSION_MINOR (9) + +/** + * \enum psa_attest_err_t + * + * \brief Initial attestation service error types + * + */ +enum psa_attest_err_t { + /** Action was performed successfully */ + PSA_ATTEST_ERR_SUCCESS = 0, + /** Boot status data is unavailable or malformed */ + PSA_ATTEST_ERR_INIT_FAILED, + /** Token buffer is too small to store the created token there */ + PSA_ATTEST_ERR_TOKEN_BUFFER_OVERFLOW, + /** Some of the mandatory claims are unavailable*/ + PSA_ATTEST_ERR_CLAIM_UNAVAILABLE, + /** Some parameter or combination of parameters are recognised as invalid: + * - challenge size is not allowed + * - challenge object is unavailable + * - token buffer is unavailable + */ + PSA_ATTEST_ERR_INVALID_INPUT, + /** Unexpected error happened during operation */ + PSA_ATTEST_ERR_GENERAL, + /** Following entry is only to ensure the error code of integer size */ + PSA_ATTEST_ERR_FORCE_INT_SIZE = INT_MAX +}; + +/** + * The allowed size of input challenge in bytes: 32, 48, 64 + * Challenge can be a nonce from server + * or the hash of some combined data : nonce + attested data by caller. + */ +#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32 (32u) +#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48 (48u) +#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64 (64u) + +/** + * The list of fixed claims in the initial attestation token is still evolving, + * you can expect slight changes in the future. + * + * The initial attestation token is planned to be aligned with future version of + * Entity Attestation Token format: + * https://tools.ietf.org/html/draft-mandyam-eat-01 + * + * Current list of claims: + * - Challenge: Input object from caller. Can be a single nonce from server + * or hash of nonce and attested data. It is intended to provide + * freshness to reports and the caller has responsibility to + * arrange this. Allowed length: 32, 48, 64 bytes. The claim is + * modeled to be eventually represented by the EAT standard + * claim nonce. Until such a time as that standard exists, + * the claim will be represented by a custom claim. Value + * is encoded as byte string. + * + * - Instance ID: It represents the unique identifier of the instance. In the + * PSA definition it is a hash of the public attestation key + * of the instance. The claim is modeled to be eventually + * represented by the EAT standard claim UEID of type GUID. + * Until such a time as that standard exists, the claim will be + * represented by a custom claim Value is encoded as byte + * string. + * + * - Verification service indicator: Optional, recommended claim. It is used by + * a Relying Party to locate a validation service for the token. + * The value is a text string that can be used to locate the + * service or a URL specifying the address of the service. The + * claim is modeled to be eventually represented by the EAT + * standard claim origination. Until such a time as that + * standard exists, the claim will be represented by a custom + * claim. Value is encoded as text string. + * + * - Profile definition: Optional, recommended claim. It contains the name of + * a document that describes the 'profile' of the token, being + * a full description of the claims, their usage, verification + * and token signing. The document name may include versioning. + * Custom claim with a value encoded as text string. + * + * - Implementation ID: It represents the original implementation signer of the + * attestation key and identifies the contract between the + * report and verification. A verification service will use this + * claim to locate the details of the verification process. + * Custom claim with a value encoded as byte string. + * + * - Security lifecycle: It represents the current lifecycle state of the + * instance. Custom claim with a value encoded as integer that + * is divided to convey a major state and a minor state. The + * PSA state and implementation state are encoded as follows: + * - version[15:8] - PSA lifecycle state - major + * - version[7:0] - IMPLEMENTATION DEFINED state - minor + * Possible PSA lifecycle states: + * - Unknown (0x1000u), + * - PSA_RoT_Provisioning (0x2000u), + * - Secured (0x3000u), + * - Non_PSA_RoT_Debug(0x4000u), + * - Recoverable_PSA_RoT_Debug (0x5000u), + * - Decommissioned (0x6000u) + * + * - Client ID: The partition ID of that secure partition or non-secure + * thread who called the initial attestation API. Custom claim + * with a value encoded as a *signed* integer. Negative number + * represents non-secure caller, positive numbers represents + * secure callers, zero is invalid. + * + * - HW version: Optional claim. Globally unique number in EAN-13 format + * identifying the GDSII that went to fabrication, HW and ROM. + * It can be used to reference the security level of the PSA-ROT + * via a certification website. Custom claim with a value is + * encoded as text string. + + * - Boot seed: It represents a random value created at system boot time that + * will allow differentiation of reports from different system + * sessions. The size is 32 bytes. Custom claim with a value is + * encoded as byte string. + * + * - Software components: Recommended claim. It represents the software state + * of the system. The value of the claim is an array of CBOR map + * entries, with one entry per software component within the + * device. Each map contains multiple claims that describe + * evidence about the details of the software component. + * + * - Measurement type: Optional claim. It represents the role of the + * software component. Value is encoded as short(!) text + * string. + * + * - Measurement value: It represents a hash of the invariant software + * component in memory at start-up time. The value must be a + * cryptographic hash of 256 bits or stronger.Value is + * encoded as byte string. + * + * - Security epoch: Optional claim. It represents the security control + * point of the software component. Value is encoded as + * unsigned integer. + * + * - Version: Optional claim. It represents the issued software version. + * Value is encoded as text string. + * + * - Signer ID: It represents the hash of a signing authority public key. + * Value is encoded as byte string. + * + * - Measurement description: Optional claim. It represents the way in which + * the measurement value of the software component is + * computed. Value is encoded as text string containing an + * abbreviated description (name) of the measurement method. + * + * - No software measurements: In the event that the implementation does not + * contain any software measurements then the software + * components claim above can be omitted but instead + * it is mandatory to include this claim to indicate this is a + * deliberate state. Custom claim a value is encoded as unsigned + * integer set to 1. + */ + +/** + * \brief Get initial attestation token + * + * \param[in] challenge_obj Pointer to buffer where challenge input is + * stored. Nonce and / or hash of attested data. + * Must be always + * \ref PSA_INITIAL_ATTEST_CHALLENGE_SIZE bytes + * long. + * \param[in] challenge_size Size of challenge object in bytes. + * \param[out] token Pointer to the buffer where attestation token + * must be stored. + * \param[in/out] token_size Size of allocated buffer for token, which + * updated by initial attestation service with + * final token size. + * + * \return Returns error code as specified in \ref psa_attest_err_t + */ +enum psa_attest_err_t +psa_initial_attest_get_token(const uint8_t *challenge_obj, + uint32_t challenge_size, + uint8_t *token, + uint32_t *token_size); + +/** + * \brief Get the exact size of initial attestation token in bytes. + * + * It just returns with the size of the IAT token. It can be used if the caller + * dynamically allocates memory for the token buffer. + * + * \param[in] challenge_size Size of challenge object in bytes. + * \param[out] token_size Size of the token in bytes, which is created by + * initial attestation service. + * + * \return Returns error code as specified in \ref psa_attest_err_t + */ +enum psa_attest_err_t +psa_initial_attest_get_token_size(uint32_t challenge_size, + uint32_t *token_size); + +#ifdef __cplusplus +} +#endif + +/** @}*/ // PSA-Attestation + +#endif /* __PSA_INITIAL_ATTESTATION_API_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_inject_attestation_key_impl.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_inject_attestation_key_impl.c new file mode 100755 index 0000000..c63d93e --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_inject_attestation_key_impl.c @@ -0,0 +1,108 @@ +/* +* Copyright (c) 2018-2019 ARM Limited. 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 "psa_inject_attestation_key_impl.h" + +#define ECDSA_P256_KEY_SIZE_IN_BYTES 32 +#define PSA_ATTESTATION_PRIVATE_KEY_ID 17 + +psa_status_t +psa_attestation_inject_key_impl(const uint8_t *key_data, + size_t key_data_length, + psa_key_type_t type, + uint8_t *public_key_data, + size_t public_key_data_size, + size_t *public_key_data_length) +{ + psa_status_t status = PSA_SUCCESS; + size_t key_data_bits = ECDSA_P256_KEY_SIZE_IN_BYTES * 8; + psa_key_handle_t handle = 0; + psa_key_id_t key_id = PSA_ATTESTATION_PRIVATE_KEY_ID; + psa_key_lifetime_t lifetime = PSA_KEY_LIFETIME_PERSISTENT; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_usage_t usage = PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY; + psa_key_type_t public_type; + size_t bits; + size_t exported_size = 0; + psa_key_type_t type_key; + +#if defined(MBEDTLS_ECP_C) + + status = psa_open_key(key_id, &handle); + if (status == PSA_SUCCESS) { + /* The key already has been injected */ + goto exit; + } + + psa_set_key_usage_flags(&attributes, usage); + psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)); + psa_set_key_type(&attributes, type); + psa_set_key_bits(&attributes, key_data_bits); + psa_set_key_lifetime(&attributes, lifetime); + psa_set_key_id(&attributes, key_id); + + if (! PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) { + return (PSA_ERROR_INVALID_ARGUMENT); + } + + if (key_data != NULL) { + if (key_data_length != ECDSA_P256_KEY_SIZE_IN_BYTES) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + status = psa_import_key(&attributes, key_data, key_data_length, &handle); + if (status != PSA_SUCCESS) { + goto exit; + } + } else { + /* generating key pair */ + key_data_bits = ECDSA_P256_KEY_SIZE_IN_BYTES * 8; + status = psa_generate_key(&attributes, &handle); + if (status != PSA_SUCCESS) { + goto exit; + } + } + + status = psa_get_key_attributes(handle, &attributes); + if (status != PSA_SUCCESS) { + goto exit; + } + + type_key = psa_get_key_type(&attributes); + public_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type_key); + bits = psa_get_key_bits(&attributes); + exported_size = PSA_KEY_EXPORT_MAX_SIZE(public_type, bits); + + status = psa_export_public_key(handle, + public_key_data, + public_key_data_size, + public_key_data_length); + if (status != PSA_SUCCESS) { + goto exit; + } + if (*public_key_data_length > exported_size) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + +exit: + psa_close_key(handle); + return (status); +#endif /* MBEDTLS_ECP_C */ + + return (PSA_ERROR_NOT_SUPPORTED); +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_inject_attestation_key_impl.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_inject_attestation_key_impl.h new file mode 100755 index 0000000..de6e1bb --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/psa_inject_attestation_key_impl.h @@ -0,0 +1,43 @@ +/* +* Copyright (c) 2018-2019 ARM Limited. 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 __PSA_INITIAL_ATTESTATION_IMPL_H__ +#define __PSA_INITIAL_ATTESTATION_IMPL_H__ + +#include "psa/crypto.h" +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +psa_status_t +psa_attestation_inject_key_impl(const uint8_t *key_data, + size_t key_data_length, + psa_key_type_t type, + uint8_t *public_key_data, + size_t public_key_data_size, + size_t *public_key_data_length); + +#ifdef __cplusplus +} +#endif + +#endif /* __PSA_INITIAL_ATTESTATION_IMPL_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/.mbedignore b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/.mbedignore new file mode 100644 index 0000000..ab1cfb4 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/.mbedignore @@ -0,0 +1 @@ +test/* diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/CMakeLists.txt b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/CMakeLists.txt new file mode 100644 index 0000000..060462a --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/CMakeLists.txt @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------- +# Copyright (c) 2019, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +#------------------------------------------------------------------------------- + +cmake_minimum_required(VERSION 3.7) + +#Tell cmake where our modules can be found +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/../../../cmake) + +#Include common stuff to control cmake. +include("Common/BuildSys") + +#Start an embedded project. +embedded_project_start(CONFIG "${CMAKE_CURRENT_LIST_DIR}/../../../ConfigDefault.cmake") +project(tfm_qcbor LANGUAGES C) +embedded_project_fixup() + +#Some project global settings +set (QCBOR_DIR "${CMAKE_CURRENT_LIST_DIR}") + +#Append all our source files to global lists. +list(APPEND ALL_SRC_C + "${QCBOR_DIR}/src/ieee754.c" + "${QCBOR_DIR}/src/qcbor_decode.c" + "${QCBOR_DIR}/src/qcbor_encode.c" + "${QCBOR_DIR}/src/UsefulBuf.c" + ) + +#Setting include directories +embedded_include_directories(PATH ${QCBOR_DIR}/inc ABSOLUTE) + +#Specify what we build (for the QCBOR, build as an object library) +add_library(${PROJECT_NAME} OBJECT ${ALL_SRC_C}) + +#Set common compiler flags +config_setting_shared_compiler_flags(${PROJECT_NAME}) + +embedded_project_end(${PROJECT_NAME}) diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/README.md b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/README.md new file mode 100644 index 0000000..a514bab --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/README.md @@ -0,0 +1,172 @@ +# QCBOR + +QCBOR encodes and decodes [RFC 7049](https://tools.ietf.org/html/rfc7049) CBOR. + +## Characteristics + +**Implemented in C with minimal dependency** – Only dependencies are + C99, , , and making it + highly portable. There are no #ifdefs to be configured at all. + +**Focused on C / native data representation** – Simpler code because + there is no support for encoding/decoding to/from JSON, pretty + printing, diagnostic notation... Only encoding from native C + representations and decoding to native C representations is supported. + +**Small simple memory model** – Malloc is not needed. The encode + context is 136 bytes, decode context is 104 bytes and the + description of decoded data item is 56 bytes. Stack use is light and + there is no recursion. The caller supplies the memory to hold the + encoded CBOR and encode/decode contexts so caller has full control + of memory usage making it good for embedded implementations that + have to run in small fixed memory. + +**Supports nearly all of RFC 7049** – Only minor, corner-case parts of + RFC 7049 are not directly supported (canonicalization, decimal + fractions, big floats). Decoding indefinite length strings is supported, + but requires a string allocator (see documentation). Encoding indefinite + length strings is not supported, but is also not necessary or + preferred. + +**Extensible and general** – Provides a way to handle data types that + are not directly supported. + +**Secure coding style** – Uses a construct called UsefulBuf as a + discipline for very safe coding the handling of binary data. + +**Small code size** – When optimized for size using the compiler -Os + option, x86 code is about 4KB (~1.1KB encode, ~2.5KB decode, + ~0.4KB common). Other decoders may be smaller, but they may + also do less for you, so overall size of the implementation may + be larger. For example, QCBOR internally tracks error status + so you don't have to check a return code on every operation. + +**Clear documented public interface** – The public interface is + separated from the implementation. It can be put to use without + reading the source. + +**Comprehensive test suite** – Easy to verify on a new platform + or OS with the test suite. The test suite dependencies are also + minimal, only additionally requiring for floating point + tests. + +## Code Status + +QCBOR was originally developed by Qualcomm. It was [open sourced +through CAF](https://source.codeaurora.org/quic/QCBOR/QCBOR/) with a +permissive Linux license, September 2018 (thanks Qualcomm!). + +This code in [Laurence's +GitHub](https://github.com/laurencelundblade/QCBOR) has diverged from +the CAF source with some small simplifications and tidying up. + +From Nov 3, 2018, the interface and code are fairly stable. Large +changes are not planned or expected, particularly in the +interface. The test coverage is pretty good. + +## Building + +There is a simple makefile for the UNIX style command line binary that +compiles everything to run the tests. + +These seven files, the contents of the src and inc directories, make +up the entire implementation. + +* inc + * UsefulBuf.h + * qcbor.h +* src + * UsefulBuf.c + * qcbor_encode.c + * qcbor_decode.c + * ieee754.h + * ieee754.c + +For most use cases you should just be able to add them to your +project. Hopefully the easy portability of this implementation makes +this work straight away, whatever your development environment is. + +The files ieee754.c and ieee754.h are support for half-precision +floating point. The encoding side of the floating point functionality +is about 500 bytes. If it is never called because no floating point +numbers are ever encoded, all 500 bytes will be dead stripped and not +impact code size. The decoding side is about 150 bytes of object +code. It is never dead stripped because it directly referenced by the +core decoder, however it doesn't add very much to the size. + +The test directory includes some tests that are nearly as portable as +the main implementation. If your development environment doesn't +support UNIX style command line and make, you should be able to make a +simple project and add the test files to it. Then just call +RunTests() to invoke them all. + + +## Changes from CAF Version +* Float support is restored +* Minimal length float encoding is added +* indefinite length arrays/maps are supported +* indefinite length strings are supported +* Tag decoding is changed; unlimited number of tags supported, any tag +value supported, tag utility function for easier tag checking +* Addition functions in UsefulBuf +* QCBOREncode_Init takes a UsefulBuf instead of a pointer and size +* QCBOREncode_Finish takes a UsefulBufC and EncodedCBOR is remove +* bstr wrapping of arrays/maps is replaced with OpenBstrwrap +* AddRaw renamed to AddEncoded and can now only add whole arrays or maps, +not partial maps and arrays (simplification; was a dangerous feature) +* Finish cannot be called repeatedly on a partial decode (some tests used +this, but it is not really a good thing to use in the first place) +* UsefulOutBuf_OutUBuf changed to work differently +* UsefulOutBuf_Init works differently +* The "_3" functions are replaced with a small number of simpler functions +* There is a new AddTag functon instead of the "_3" functions, making +the interface simpler and saving some code +* QCBOREncode_AddRawSimple_2 is removed (the macros that referenced +still exist and work the same) + +## Credits +* Ganesh Kanike for porting to QSEE +* Mark Bapst for sponsorship and release as open source by Qualcomm +* Sachin Sharma for release through CAF +* Tamas Ban for porting to TF-M and 32-bit ARM + +## Copyright and License + +QCBOR is available under what is essentially the 3-Clause BSD License. + +Files created inside Qualcomm and open-sourced through CAF (The Code +Aurora Forum) have a slightly modified 3-Clause BSD License. The +modification additionally disclaims NON-INFRINGEMENT. + +Files created after release to CAF use the standard 3-Clause BSD +License with no modification. These files have the SPDX license +identifier, "SPDX-License-Identifier: BSD-3-Clause" in them. + +### BSD-3-Clause license + +* Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +### Copyright for this README + +Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/inc/UsefulBuf.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/inc/UsefulBuf.h new file mode 100644 index 0000000..453f016 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/inc/UsefulBuf.h @@ -0,0 +1,1534 @@ +/*============================================================================== + Copyright (c) 2016-2018, The Linux Foundation. + Copyright (c) 2018-2019, Laurence Lundblade. + All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors, nor the name "Laurence Lundblade" may be used to + endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ==============================================================================*/ + +/*=================================================================================== + FILE: UsefulBuf.h + + DESCRIPTION: General purpose input and output buffers + + EDIT HISTORY FOR FILE: + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + when who what, where, why + -------- ---- --------------------------------------------------- + 12/17/2018 llundblade Remove const from UsefulBuf and UsefulBufC .len + 12/13/2018 llundblade Documentation improvements + 09/18/2018 llundblade Cleaner distinction between UsefulBuf and UsefulBufC + 02/02/18 llundbla Full support for integers in and out; fix pointer + alignment bug. Incompatible change: integers in/out + are now in network byte order. + 08/12/17 llundbla Added UsefulOutBuf_AtStart and UsefulBuf_Find + 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected comparison + for < or > for unequal length buffers. Added + UsefulBuf_Set() function. + 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst + 11/13/16 llundbla Initial Version. + + + =====================================================================================*/ + +#ifndef _UsefulBuf_h +#define _UsefulBuf_h + + +#include // for uint8_t, uint16_t.... +#include // for strlen, memcpy, memmove, memset +#include // for size_t + +/** + @file UsefulBuf.h + + The goal of this code is to make buffer and pointer manipulation + easier and safer when working with binary data. + + You use the UsefulBuf, UsefulOutBuf and UsefulInputBuf + structures to represent buffers rather than ad hoc pointers and lengths. + + With these it will often be possible to write code that does little or no + direct pointer manipulation for copying and formatting data. For example + the QCBOR encoder was rewritten using these and has no direct pointer + manipulation. + + While it is true that object code using these functions will be a little + larger and slower than a white-knuckle clever use of pointers might be, but + not by that much or enough to have an affect for most use cases. For + security-oriented code this is highly worthwhile. Clarity, simplicity, + reviewability and are more important. + + There are some extra sanity and double checks in this code to help catch + coding errors and simple memory corruption. They are helpful, but not a + substitute for proper code review, input validation and such. + + This code consists of a lot of inline functions and a few that are not. + It should not generate very much object code, especially with the + optimizer turned up to -Os or -O3. The idea is that the inline + functions are easier to review and understand and the optimizer does + the work of making the code small. + */ + + +/*...... This is a ruler that is 80 characters long...........................*/ + +/** + UsefulBufC and UsefulBuf are simple data structures to hold a pointer and + length for a binary data. In C99 this data structure can be passed on the + stack making a lot of code cleaner than carrying around a pointer and + length as two parameters. + + This is also conducive to secure code practice as the lengths are + always carried with the pointer and the convention for handling a + pointer and a length is clear. + + While it might be possible to write buffer and pointer code more + efficiently in some use cases, the thought is that unless there is an + extreme need for performance (e.g., you are building a gigabit-per-second + IP router), it is probably better to have cleaner code you can be most + certain about the security of. + + The non-const UsefulBuf is usually used to refer a buffer to be filled in. + The length is the size of the buffer. + + The const UsefulBufC is usually used to refer to some data that has been + filled in. The length is amount of valid data pointed to. + + A common use is to pass a UsefulBuf to a function, the function fills it + in, the function returns a UsefulBufC. The pointer is the same in both. + + A UsefulBuf is NULL, it has no value, when the ptr in it is NULL. + + There are utility functions for the following: + - Checking for UsefulBufs that are NULL, empty or both + - Copying, copying with offset, copying head or tail + - Comparing and finding substrings + - Initializating + - Create initialized const UsefulBufC from compiler literals + - Create initialized const UsefulBufC from NULL-terminated string + - Make an empty UsefulBuf on the stack + + See also UsefulOutBuf. It is a richer structure that has both the size of + the valid data and the size of the buffer. + + UsefulBuf is only 16 or 8 bytes on a 64- or 32-bit machine so it can go + on the stack and be a function parameter or return value. + + UsefulBuf is kind of like the Useful Pot Pooh gave Eeyore on his birthday. + Eeyore's balloon fits beautifully, "it goes in and out like anything". + +*/ +typedef struct useful_buf_c { + const void *ptr; + size_t len; +} UsefulBufC; + + +/** + The non-const UsefulBuf typically used for some allocated memory + that is to be filled in. The len is the amount of memory, + not the length of the valid data in the buffer. + */ +typedef struct useful_buf { + void *ptr; + size_t len; +} UsefulBuf; + + +/** + A "NULL" UsefulBufC is one that has no value in the same way a NULL pointer has no value. + A UsefulBuf is NULL when the ptr field is NULL. It doesn't matter what len is. + See UsefulBuf_IsEmpty() for the distinction between NULL and empty. + */ +#define NULLUsefulBufC ((UsefulBufC) {NULL, 0}) + +/** A NULL UsefulBuf is one that has no memory associated the say way + NULL points to nothing. It does not matter what len is. + */ +#define NULLUsefulBuf ((UsefulBuf) {NULL, 0}) + + +/** + @brief Check if a UsefulBuf is NULL or not + + @param[in] UB The UsefulBuf to check + + @return 1 if it is NULL, 0 if not. + */ +static inline int UsefulBuf_IsNULL(UsefulBuf UB) { + return !UB.ptr; +} + + +/** + @brief Check if a UsefulBufC is NULL or not + + @param[in] UB The UsefulBufC to check + + @return 1 if it is NULL, 0 if not. + */ +static inline int UsefulBuf_IsNULLC(UsefulBufC UB) { + return !UB.ptr; +} + + +/** + @brief Check if a UsefulBuf is empty or not + + @param[in] UB The UsefulBuf to check + + @return 1 if it is empty, 0 if not. + + An "Empty" UsefulBuf is one that has a value and can be considered to be set, + but that value is of zero length. It is empty when len is zero. It + doesn't matter what the ptr is. + + A lot of uses will not need to clearly distinguish a NULL UsefulBuf + from an empty one and can have the ptr NULL and the len 0. However + if a use of UsefulBuf needs to make a distinction then ptr should + not be NULL when the UsefulBuf is considered empty, but not NULL. + + */ +static inline int UsefulBuf_IsEmpty(UsefulBuf UB) { + return !UB.len; +} + + +/** + @brief Check if a UsefulBufC is empty or not + + @param[in] UB The UsefulBufC to check + + @return 1 if it is empty, 0 if not. + */ +static inline int UsefulBuf_IsEmptyC(UsefulBufC UB) { + return !UB.len; +} + + +/** + @brief Check if a UsefulBuf is NULL or empty + + @param[in] UB The UsefulBuf to check + + @return 1 if it is either NULL or empty, 0 if not. + */ +static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB) { + return UsefulBuf_IsEmpty(UB) || UsefulBuf_IsNULL(UB); +} + + +/** + @brief Check if a UsefulBufC is NULL or empty + + @param[in] UB The UsefulBufC to check + + @return 1 if it is either NULL or empty, 0 if not. + */ +static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB) { + return UsefulBuf_IsEmptyC(UB) || UsefulBuf_IsNULLC(UB); +} + + +/** + @brief Convert a non const UsefulBuf to a const UsefulBufC + + @param[in] UB The UsefulBuf to convert + + Returns: a UsefulBufC struct + */ + +static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB) +{ + return (UsefulBufC){UB.ptr, UB.len}; +} + + +/** + @brief Convert a const UsefulBufC to a non-const UsefulBuf + + @param[in] UBC The UsefulBuf to convert + + Returns: a non const UsefulBuf struct + */ +static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC) +{ + return (UsefulBuf){(void *)UBC.ptr, UBC.len}; +} + + +/** + Convert a literal string to a UsefulBufC. + + szString must be a literal string that you can take sizeof. + This is better for literal strings than UsefulBuf_FromSZ() + because it generates less code. It will not work on + non-literal strings. + + The terminating \0 (NULL) is NOT included in the length! + + */ +#define UsefulBuf_FROM_SZ_LITERAL(szString) \ + ((UsefulBufC) {(szString), sizeof(szString)-1}) + + +/** + Convert a literal byte array to a UsefulBufC. + + pBytes must be a literal string that you can take sizeof. + It will not work on non-literal arrays. + + */ +#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) \ + ((UsefulBufC) {(pBytes), sizeof(pBytes)}) + + +/** + Make an automatic variable with name of type UsefulBuf and point it to a stack + variable of the give size + */ +#define UsefulBuf_MAKE_STACK_UB(name, size) \ + uint8_t __pBuf##name[(size)];\ + UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )} + + +/** + Make a byte array in to a UsefulBuf + */ +#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) \ + ((UsefulBuf) {(pBytes), sizeof(pBytes)}) + +/** + @brief Convert a NULL terminated string to a UsefulBufC. + + @param[in] szString The string to convert + + @return a UsefulBufC struct + + UsefulBufC.ptr points to the string so it's lifetime + must be maintained. + + The terminating \0 (NULL) is NOT included in the length! + + */ +static inline UsefulBufC UsefulBuf_FromSZ(const char *szString){ + return ((UsefulBufC) {szString, strlen(szString)}); +} + + +/** + @brief Copy one UsefulBuf into another at an offset + + @param[in] Dest Destiation buffer to copy into + @param[in] uOffset The byte offset in Dest at which to copy to + @param[in] Src The bytes to copy + + @return Pointer and length of the copy + + This fails and returns NULLUsefulBufC Src.len + uOffset > Dest.len. + + Like memcpy, there is no check for NULL. If NULL is passed + this will crash. + + There is an assumption that there is valid data in Dest up to + uOffset as the resulting UsefulBufC returned starts + at the beginning of Dest and goes to Src.len + uOffset. + + */ +UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src); + + +/** + @brief Copy one UsefulBuf into another + + @param[in] Dest The destination buffer to copy into + @param[out] Src The source to copy from + + @return filled in UsefulBufC on success, NULLUsefulBufC on failure + + This fails if Src.len is greater than Dest.len. + + Note that like memcpy, the pointers are not checked and + this will crash, rather than return NULLUsefulBufC if + they are NULL or invalid. + + Results are undefined if Dest and Src overlap. + + */ +static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src) { + return UsefulBuf_CopyOffset(Dest, 0, Src); +} + + +/** + @brief Set all bytes in a UsefulBuf to a value, for example 0 + + @param[in] pDest The destination buffer to copy into + @param[in] value The value to set the bytes to + + Note that like memset, the pointer in pDest is not checked and + this will crash if NULL or invalid. + + */ +static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value) +{ + memset(pDest.ptr, value, pDest.len); + return (UsefulBufC){pDest.ptr, pDest.len}; +} + + +/** + @brief Copy a pointer into a UsefulBuf + + @param[in,out] Dest The destination buffer to copy into + @param[in] ptr The source to copy from + @param[in] len Length of the source; amoutn to copy + + @return 0 on success, 1 on failure + + This fails and returns NULLUsefulBufC if len is greater than + pDest->len. + + Note that like memcpy, the pointers are not checked and + this will crash, rather than return 1 if they are NULL + or invalid. + + */ +inline static UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest, const void *ptr, size_t len) +{ + return UsefulBuf_Copy(Dest, (UsefulBufC){ptr, len}); +} + + +/** + @brief Returns a truncation of a UsefulBufC + + @param[in] UB The buffer to get the head of + @param[in] uAmount The number of bytes in the head + + @return A UsefulBufC that is the head of UB + + */ +static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount) +{ + if(uAmount > UB.len) { + return NULLUsefulBufC; + } + return (UsefulBufC){UB.ptr, uAmount}; +} + + +/** + @brief Returns bytes from the end of a UsefulBufC + + @param[in] UB The buffer to get the tail of + @param[in] uAmount The offset from the start where the tail is to begin + + @return A UsefulBufC that is the tail of UB or NULLUsefulBufC if + uAmount is greater than the length of the UsefulBufC + + If the input UsefulBufC is NULL, but the len is not, then the + length of the tail will be calculated and returned along + with a NULL ptr. + */ +static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount) +{ + UsefulBufC ReturnValue; + + if(uAmount > UB.len) { + ReturnValue = NULLUsefulBufC; + } else if(UB.ptr == NULL) { + ReturnValue = (UsefulBufC){NULL, UB.len - uAmount}; + } else { + ReturnValue = (UsefulBufC){(uint8_t *)UB.ptr + uAmount, UB.len - uAmount}; + } + + return ReturnValue; +} + + +/** + @brief Compare two UsefulBufCs + + @param[in] UB1 The destination buffer to copy into + @param[in] UB2 The source to copy from + + @return 0 if equal... + + Returns a negative value if UB1 if is less than UB2. UB1 is + less than UB2 if it is shorter or the first byte that is not + the same is less. + + Returns 0 if the UsefulBufs are the same. + + Returns a positive value if UB2 is less than UB1. + + All that is of significance is that the result is positive, + negative or 0. (This doesn't return the difference between + the first non-matching byte like memcmp). + + */ +int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2); + + +/** + @brief Find one UsefulBuf in another + + @param[in] BytesToSearch UsefulBuf to search through + @param[in] BytesToFind UsefulBuf with bytes to be found + + @return position of found bytes or SIZE_MAX if not found. + + */ +size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind); + + + + +#if 0 // NOT_DEPRECATED +/** Deprecated macro; use UsefulBuf_FROM_SZ_LITERAL instead */ +#define SZLiteralToUsefulBufC(szString) \ + ((UsefulBufC) {(szString), sizeof(szString)-1}) + +/** Deprecated macro; use UsefulBuf_MAKE_STACK_UB instead */ +#define MakeUsefulBufOnStack(name, size) \ + uint8_t __pBuf##name[(size)];\ + UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )} + +/** Deprecated macro; use UsefulBuf_FROM_BYTE_ARRAY_LITERAL instead */ +#define ByteArrayLiteralToUsefulBufC(pBytes) \ + ((UsefulBufC) {(pBytes), sizeof(pBytes)}) + +/** Deprecated function; use UsefulBuf_Unconst() instead */ +static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC) +{ + return (UsefulBuf){(void *)UBC.ptr, UBC.len}; +} +#endif + + + +/* + Convenient functions to avoid type punning, compiler warnings and such + The optimizer reduces them to a simple assignment + This is a crusty corner of C. It shouldn't be this hard. + */ +static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f) +{ + uint32_t u32; + memcpy(&u32, &f, sizeof(uint32_t)); + return u32; +} + +static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d) +{ + uint64_t u64; + memcpy(&u64, &d, sizeof(uint64_t)); + return u64; +} + +static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64) +{ + double d; + memcpy(&d, &u64, sizeof(uint64_t)); + return d; +} + +static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32) +{ + float f; + memcpy(&f, &u32, sizeof(uint32_t)); + return f; +} + + + + + +/** + UsefulOutBuf is a structure and functions (an object) that are good + for serializing data into a buffer such as is often done with network + protocols or data written to files. + + The main idea is that all the pointer manipulation for adding data is + done by UsefulOutBuf functions so the caller doesn't have to do any. + All the pointer manipulation is centralized here. This code will + have been reviewed and written carefully so it spares the caller of + much of this work and results in much safer code with much less work. + + The functions to add data to the output buffer always check the + length and will never write off the end of the output buffer. If an + attempt to add data that will not fit is made, an internal error flag + will be set and further attempts to add data will not do anything. + + Basically, if you initialized with the correct buffer, there is no + way to ever write off the end of that buffer when calling the Add + and Insert functions here. + + The functions to add data do not return an error. The working model + is that the caller just makes all the calls to add data without any + error checking on each one. The error is instead checked after all the + data is added when the result is to be used. This makes the caller's + code cleaner. + + There is a utility function to get the error status anytime along the + way if the caller wants. There are functions to see how much room is + left and see if some data will fit too, but their use is generally + not necessary. + + The general call flow is like this: + + - Initialize the UsefulOutBuf with the buffer that is to have the + data added. The caller allocates the buffer. It can be heap + or stack or shared memory (or other). + + - Make calls to add data to the output buffer. Insert and append + are both supported. The append and insert calls will never write + off the end of the buffer. + + - When all data is added, check the error status to make sure + everything fit. + + - Get the resulting serialized data either as a UsefulBuf (a + pointer and length) or have it copied to another buffer. + + UsefulOutBuf can be initialized with just a buffer length by passing + NULL as the pointer to the output buffer. This is useful if you want + to go through the whole serialization process to either see if it + will fit into a given buffer or compute the size of the buffer + needed. Pass a very large buffer size when calling Init, if you want + just to compute the size. + + Some inexpensive simple sanity checks are performed before every data + addition to guard against use of an uninitialized or corrupted + UsefulOutBuf. + + This has been used to create a CBOR encoder. The CBOR encoder has + almost no pointer manipulation in it, is much easier to read, and + easier to review. + + A UsefulOutBuf is 27 bytes or 15 bytes on 64- or 32-bit machines so it + can go on the stack or be a C99 function parameter. + */ + +typedef struct useful_out_buf { + UsefulBuf UB; // Memory that is being output to + size_t data_len; // length of the data + uint16_t magic; // Used to detect corruption and lack of initialization + uint8_t err; +} UsefulOutBuf; + + +/** + @brief Initialize and supply the actual output buffer + + @param[out] me The UsefulOutBuf to initialize + @param[in] Storage Buffer to output into + + Intializes the UsefulOutBuf with storage. Sets the current position + to the beginning of the buffer clears the error. + + This must be called before the UsefulOutBuf is used. + */ +void UsefulOutBuf_Init(UsefulOutBuf *me, UsefulBuf Storage); + + + + +/** Convenience marco to make a UsefulOutBuf on the stack and + initialize it with stack buffer + */ +#define UsefulOutBuf_MakeOnStack(name, size) \ + uint8_t __pBuf##name[(size)];\ + UsefulOutBuf name;\ + UsefulOutBuf_Init(&(name), (UsefulBuf){__pBuf##name, (size)}); + + + +/** + @brief Reset a UsefulOutBuf for re use + + @param[in] me Pointer to the UsefulOutBuf + + This sets the amount of data in the output buffer to none and + clears the error state. + + The output buffer is still the same one and size as from the + UsefulOutBuf_Init() call. + + It doesn't zero the data, just resets to 0 bytes of valid data. + */ +static inline void UsefulOutBuf_Reset(UsefulOutBuf *me) +{ + me->data_len = 0; + me->err = 0; +} + + +/** + @brief Returns position of end of data in the UsefulOutBuf + + @param[in] me Pointer to the UsefulOutBuf + + @return position of end of data + + On a freshly initialized UsefulOutBuf with no data added, this will + return 0. After ten bytes have been added, it will return 10 and so + on. + + Generally callers will not need this function for most uses of + UsefulOutBuf. + + */ +static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *me) +{ + return me->data_len; +} + + +/** + @brief Returns whether any data has been added to the UsefulOutBuf + + @param[in] me Pointer to the UsefulOutBuf + + @return 1 if output position is at start + + */ +static inline int UsefulOutBuf_AtStart(UsefulOutBuf *me) +{ + return 0 == me->data_len; +} + + +/** + @brief Inserts bytes into the UsefulOutBuf + + @param[in] me Pointer to the UsefulOutBuf + @param[in] NewData UsefulBuf with the bytes to insert + @param[in] uPos Index in output buffer at which to insert + + NewData is the pointer and length for the bytes to be added to the + output buffer. There must be room in the output buffer for all of + NewData or an error will occur. + + The insertion point must be between 0 and the current valid data. If + not an error will occur. Appending data to the output buffer is + achieved by inserting at the end of the valid data. This can be + retrieved by calling UsefulOutBuf_GetEndPosition(). + + When insertion is performed, the bytes between the insertion point and + the end of data previously added to the output buffer is slid to the + right to make room for the new data. + + Overlapping buffers are OK. NewData can point to data in the output + buffer. + + If an error occurs an error state is set in the UsefulOutBuf. No + error is returned. All subsequent attempts to add data will do + nothing. + + Call UsefulOutBuf_GetError() to find out if there is an error. This + is usually not needed until all additions of data are complete. + + */ +void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *me, UsefulBufC NewData, size_t uPos); + + +/** + @brief Insert a data buffer into the UsefulOutBuf + + @param[in] me Pointer to the UsefulOutBul + @param[in] pBytes Pointer to the bytes to insert + @param[in] uLen Length of the bytes to insert + @param[in] uPos Index in output buffer at which to insert + + See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with + the difference being a pointer and length is passed in rather than an + UsefulBuf. + + */ +static inline void UsefulOutBuf_InsertData(UsefulOutBuf *me, const void *pBytes, size_t uLen, size_t uPos) +{ + UsefulBufC Data = {pBytes, uLen}; + UsefulOutBuf_InsertUsefulBuf(me, Data, uPos); +} + + +/** + @brief Insert a NULL-terminated string into the UsefulOutBuf + + @param[in] me Pointer to the UsefulOutBuf + @param[in] szString string to append + + */ +static inline void UsefulOutBuf_InsertString(UsefulOutBuf *me, const char *szString, size_t uPos) +{ + UsefulOutBuf_InsertUsefulBuf(me, (UsefulBufC){szString, strlen(szString)}, uPos); +} + + +/** + @brief Insert a byte into the UsefulOutBuf + + @param[in] me Pointer to the UsefulOutBul + @param[in] byte Bytes to insert + @param[in] uPos Index in output buffer at which to insert + + See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with + the difference being a single byte is to be inserted. + */ +static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *me, uint8_t byte, size_t uPos) +{ + UsefulOutBuf_InsertData(me, &byte, 1, uPos); +} + + +/** + @brief Insert a 16-bit integer into the UsefulOutBuf + + @param[in] me Pointer to the UsefulOutBul + @param[in] uInteger16 Integer to insert + @param[in] uPos Index in output buffer at which to insert + + See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with + the difference being a single byte is to be inserted. + + The integer will be inserted in network byte order (big endian) + */ +static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *me, uint16_t uInteger16, size_t uPos) +{ + // Converts native integer format to network byte order (big endian) + uint8_t tmp[2]; + tmp[0] = (uInteger16 & 0xff00) >> 8; + tmp[1] = (uInteger16 & 0xff); + UsefulOutBuf_InsertData(me, tmp, 2, uPos); +} + + +/** + @brief Insert a 32-bit integer into the UsefulOutBuf + + @param[in] me Pointer to the UsefulOutBul + @param[in] uInteger32 Integer to insert + @param[in] uPos Index in output buffer at which to insert + + See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with + the difference being a single byte is to be inserted. + + The integer will be inserted in network byte order (big endian) + */ +static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *me, uint32_t uInteger32, size_t uPos) +{ + // Converts native integer format to network byte order (big endian) + uint8_t tmp[4]; + tmp[0] = (uInteger32 & 0xff000000) >> 24; + tmp[1] = (uInteger32 & 0xff0000) >> 16; + tmp[2] = (uInteger32 & 0xff00) >> 8; + tmp[3] = (uInteger32 & 0xff); + UsefulOutBuf_InsertData(me, tmp, 4, uPos); +} + + +/** + @brief Insert a 64-bit integer into the UsefulOutBuf + + @param[in] me Pointer to the UsefulOutBul + @param[in] uInteger64 Integer to insert + @param[in] uPos Index in output buffer at which to insert + + See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with + the difference being a single byte is to be inserted. + + The integer will be inserted in network byte order (big endian) + */ +static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *me, uint64_t uInteger64, size_t uPos) +{ + // Converts native integer format to network byte order (big endian) + uint8_t tmp[8]; + tmp[0] = (uInteger64 & 0xff00000000000000) >> 56; + tmp[1] = (uInteger64 & 0xff000000000000) >> 48; + tmp[2] = (uInteger64 & 0xff0000000000) >> 40; + tmp[3] = (uInteger64 & 0xff00000000) >> 32; + tmp[4] = (uInteger64 & 0xff000000) >> 24; + tmp[5] = (uInteger64 & 0xff0000) >> 16; + tmp[6] = (uInteger64 & 0xff00) >> 8; + tmp[7] = (uInteger64 & 0xff); + UsefulOutBuf_InsertData(me, tmp, 8, uPos); +} + + +/** + @brief Insert a float into the UsefulOutBuf + + @param[in] me Pointer to the UsefulOutBul + @param[in] f Integer to insert + @param[in] uPos Index in output buffer at which to insert + + See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with + the difference being a single byte is to be inserted. + + The float will be inserted in network byte order (big endian) + */ +static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *me, float f, size_t uPos) +{ + UsefulOutBuf_InsertUint32(me, UsefulBufUtil_CopyFloatToUint32(f), uPos); +} + + +/** + @brief Insert a double into the UsefulOutBuf + + @param[in] me Pointer to the UsefulOutBul + @param[in] d Integer to insert + @param[in] uPos Index in output buffer at which to insert + + See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with + the difference being a single byte is to be inserted. + + The double will be inserted in network byte order (big endian) + */ +static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *me, double d, size_t uPos) +{ + UsefulOutBuf_InsertUint64(me, UsefulBufUtil_CopyDoubleToUint64(d), uPos); +} + + + +/** + Append a UsefulBuf into the UsefulOutBuf + + @param[in] me Pointer to the UsefulOutBuf + @param[in] NewData UsefulBuf with the bytes to append + + See UsefulOutBuf_InsertUsefulBuf() for details. This does the same + with the insertion point at the end of the valid data. + +*/ +static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *me, UsefulBufC NewData) +{ + // An append is just a insert at the end + UsefulOutBuf_InsertUsefulBuf(me, NewData, UsefulOutBuf_GetEndPosition(me)); +} + + +/** + Append bytes to the UsefulOutBuf + + @param[in] me Pointer to the UsefulOutBuf + @param[in] pBytes Pointer to bytes to append + @param[in] uLen Index in output buffer at which to append + + See UsefulOutBuf_InsertUsefulBuf() for details. This does the same + with the insertion point at the end of the valid data. + */ + +static inline void UsefulOutBuf_AppendData(UsefulOutBuf *me, const void *pBytes, size_t uLen) +{ + UsefulBufC Data = {pBytes, uLen}; + UsefulOutBuf_AppendUsefulBuf(me, Data); +} + + +/** + Append a NULL-terminated string to the UsefulOutBuf + + @param[in] me Pointer to the UsefulOutBuf + @param[in] szString string to append + + */ +static inline void UsefulOutBuf_AppendString(UsefulOutBuf *me, const char *szString) +{ + UsefulOutBuf_AppendUsefulBuf(me, (UsefulBufC){szString, strlen(szString)}); +} + + +/** + @brief Append a byte to the UsefulOutBuf + + @param[in] me Pointer to the UsefulOutBuf + @param[in] byte Bytes to append + + See UsefulOutBuf_InsertUsefulBuf() for details. This does the same + with the insertion point at the end of the valid data. + */ +static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *me, uint8_t byte) +{ + UsefulOutBuf_AppendData(me, &byte, 1); +} + +/** + @brief Append an integer to the UsefulOutBuf + + @param[in] me Pointer to the UsefulOutBuf + @param[in] uInteger16 Integer to append + + See UsefulOutBuf_InsertUsefulBuf() for details. This does the same + with the insertion point at the end of the valid data. + + The integer will be appended in network byte order (big endian). + */ +static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *me, uint16_t uInteger16){ + UsefulOutBuf_InsertUint16(me, uInteger16, UsefulOutBuf_GetEndPosition(me)); +} + +/** + @brief Append an integer to the UsefulOutBuf + + @param[in] me Pointer to the UsefulOutBuf + @param[in] uInteger32 Integer to append + + See UsefulOutBuf_InsertUsefulBuf() for details. This does the same + with the insertion point at the end of the valid data. + + The integer will be appended in network byte order (big endian). + */ +static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *me, uint32_t uInteger32){ + UsefulOutBuf_InsertUint32(me, uInteger32, UsefulOutBuf_GetEndPosition(me)); +} + +/** + @brief Append an integer to the UsefulOutBuf + + @param[in] me Pointer to the UsefulOutBuf + @param[in] uInteger64 Integer to append + + See UsefulOutBuf_InsertUsefulBuf() for details. This does the same + with the insertion point at the end of the valid data. + + The integer will be appended in network byte order (big endian). + */ +static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *me, uint64_t uInteger64){ + UsefulOutBuf_InsertUint64(me, uInteger64, UsefulOutBuf_GetEndPosition(me)); +} + + +/** + @brief Append a float to the UsefulOutBuf + + @param[in] me Pointer to the UsefulOutBuf + @param[in] f Float to append + + See UsefulOutBuf_InsertUsefulBuf() for details. This does the same + with the insertion point at the end of the valid data. + + The float will be appended in network byte order (big endian). + */ +static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *me, float f){ + UsefulOutBuf_InsertFloat(me, f, UsefulOutBuf_GetEndPosition(me)); +} + +/** + @brief Append a float to the UsefulOutBuf + + @param[in] me Pointer to the UsefulOutBuf + @param[in] d Double to append + + See UsefulOutBuf_InsertUsefulBuf() for details. This does the same + with the insertion point at the end of the valid data. + + The double will be appended in network byte order (big endian). + */ +static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *me, double d){ + UsefulOutBuf_InsertDouble(me, d, UsefulOutBuf_GetEndPosition(me)); +} + +/** + @brief Returns the current error status + + @param[in] me Pointer to the UsefulOutBuf + + @return 0 if all OK, 1 on error + + This is the error status since the call to either + UsefulOutBuf_Reset() of UsefulOutBuf_Init(). Once it goes into error + state it will stay until one of those functions is called. + + Possible error conditions are: + - bytes to be inserted will not fit + - insertion point is out of buffer or past valid data + - current position is off end of buffer (probably corruption or uninitialized) + - detect corruption / uninitialized by bad magic number + */ + +static inline int UsefulOutBuf_GetError(UsefulOutBuf *me) +{ + return me->err; +} + + +/** + @brief Returns number of bytes unused used in the output buffer + + @param[in] me Pointer to the UsefulOutBuf + + @return Number of unused bytes or zero + + Because of the error handling strategy and checks in UsefulOutBuf_InsertUsefulBuf() + it is usually not necessary to use this. + */ + +static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *me) +{ + return me->UB.len - me->data_len; +} + + +/** + @brief Returns true / false if some number of bytes will fit in the UsefulOutBuf + + @param[in] me Pointer to the UsefulOutBuf + @param[in] uLen Number of bytes for which to check + + @return 1 or 0 if nLen bytes would fit + + Because of the error handling strategy and checks in UsefulOutBuf_InsertUsefulBuf() + it is usually not necessary to use this. + */ + +static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *me, size_t uLen) +{ + return uLen <= UsefulOutBuf_RoomLeft(me); +} + + +/** + @brief Returns the resulting valid data in a UsefulOutBuf + + @param[in] me Pointer to the UsefulOutBuf. + + @return The valid data in UsefulOutBuf. + + The storage for the returned data is Storage parameter passed + to UsefulOutBuf_Init(). See also UsefulOutBuf_CopyOut(). + + This can be called anytime and many times to get intermediate + results. It doesn't change the data or reset the current position + so you can keep adding data. + */ + +UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *me); + + +/** + @brief Copies the valid data out into a supplied buffer + + @param[in] me Pointer to the UsefulOutBuf + @param[out] Dest The destination buffer to copy into + + @return Pointer and length of copied data. + + This is the same as UsefulOutBuf_OutUBuf() except it copies the data. +*/ + +UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *me, UsefulBuf Dest); + + + + + + + + + + + + + +/** + UsefulInputBuf is the counterpart to UsefulOutBuf and is for parsing + data read or received. Initialize it with the data + from the network and its length. Then use the functions + here to get the various data types out of it. It maintains a position + for getting the next item. This means you don't have to track a + pointer as you get each object. UsefulInputBuf does that for you and + makes sure it never goes off the end of the buffer. The QCBOR + implementation parser makes use of this for all its pointer math and + length checking. + + UsefulInputBuf also maintains an internal error state so you do not have + to. Once data has been requested off the end of the buffer, it goes + into an error state. You can keep calling functions to get more data + but they will either return 0 or NULL. As long as you don't + dereference the NULL, you can wait until all data items have been + fetched before checking for the error and this can simplify your + code. + + The integer and float parsing expects network byte order (big endian). + Network byte order is what is used by TCP/IP, CBOR and most internet + protocols. + + Lots of inlining is used to keep code size down. The code optimizer, + particularly with the -Os, also reduces code size a lot. The only + non-inline code is UsefulInputBuf_GetBytes() which is less than 100 + bytes so use of UsefulInputBuf doesn't add much code for all the messy + hard-to-get right issues with parsing in C that is solves. + + The parse context size is: + 64-bit machine: 16 + 8 + 2 + 1 (5 bytes padding to align) = 32 bytes + 32-bit machine: 8 + 4 + 2 + 1 (1 byte padding to align) = 16 bytes + + */ + +#define UIB_MAGIC (0xB00F) + +typedef struct useful_input_buf { + // Private data structure + UsefulBufC UB; // Data being parsed + size_t cursor; // Current offset in data being parse + uint16_t magic; // Check for corrupted or uninitialized UsefulInputBuf + uint8_t err; // Set request goes off end or magic number is bad +} UsefulInputBuf; + + + +/** + @brief Initialize the UsefulInputBuf structure before use. + + @param[in] me Pointer to the UsefulInputBuf instance. + @param[in] UB Pointer to the data to parse. + + */ +static inline void UsefulInputBuf_Init(UsefulInputBuf *me, UsefulBufC UB) +{ + me->cursor = 0; + me->err = 0; + me->magic = UIB_MAGIC; + me->UB = UB; +} + + +/** + @brief Returns current position in input buffer + + @param[in] me Pointer to the UsefulInputBuf. + + @return Integer position of the cursor + + The position that the next bytes will be returned from. + + */ +static inline size_t UsefulInputBuf_Tell(UsefulInputBuf *me) +{ + return me->cursor; +} + + +/** + @brief Sets current position in input buffer + + @param[in] me Pointer to the UsefulInputBuf. + @param[in] uPos Position to set to + + If the position is off the end of the input buffer, the error state + is entered and all functions will do nothing. + + Seeking to a valid position in the buffer will not reset the error + state. Only re initialization will do that. + + */ +static inline void UsefulInputBuf_Seek(UsefulInputBuf *me, size_t uPos) +{ + if(uPos > me->UB.len) { + me->err = 1; + } else { + me->cursor = uPos; + } +} + + +/** + @brief Returns the number of bytes from the cursor to the end of the buffer, + the uncomsummed bytes. + + @param[in] me Pointer to the UsefulInputBuf. + + @return number of bytes unconsumed or 0 on error. + + This is a critical function for input length validation. This does + some pointer / offset math. + + Returns 0 if the cursor it invalid or corruption of the structure is + detected. + + Code Reviewers: THIS FUNCTION DOES POINTER MATH + */ +static inline size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *me) +{ + // Magic number is messed up. Either the structure got overwritten + // or was never initialized. + if(me->magic != UIB_MAGIC) { + return 0; + } + + // The cursor is off the end of the input buffer given + // Presuming there are no bugs in this code, this should never happen. + // If it so, the struct was corrupted. The check is retained as + // as a defense in case there is a bug in this code or the struct is corrupted. + if(me->cursor > me->UB.len) { + return 0; + } + + // subtraction can't go neative because of check above + return me->UB.len - me->cursor; +} + + +/** + @brief Check if there are any unconsumed bytes + + @param[in] me Pointer to the UsefulInputBuf. + + @return 1 if len bytes are available after the cursor, and 0 if not + + */ +static inline int UsefulInputBuf_BytesAvailable(UsefulInputBuf *me, size_t uLen) +{ + return UsefulInputBuf_BytesUnconsumed(me) >= uLen ? 1 : 0; +} + + +/** + @brief Get pointer to bytes out of the input buffer + + @param[in] me Pointer to the UsefulInputBuf. + @param[in] uNum Number of bytes to get + + @return Pointer to bytes. + + This consumes n bytes from the input buffer. It returns a pointer to + the start of the n bytes. + + If there are not n bytes in the input buffer, NULL will be returned + and an error will be set. + + It advances the current position by n bytes. + */ +const void * UsefulInputBuf_GetBytes(UsefulInputBuf *me, size_t uNum); + + +/** + @brief Get UsefulBuf out of the input buffer + + @param[in] me Pointer to the UsefulInputBuf. + @param[in] uNum Number of bytes to get + + @return UsefulBufC with ptr and length for bytes consumed. + + This consumes n bytes from the input buffer and returns the pointer + and len to them as a UsefulBufC. The len returned will always be n. + + If there are not n bytes in the input buffer, UsefulBufC.ptr will be + NULL and UsefulBufC.len will be 0. An error will be set. + + It advances the current position by n bytes. + */ +static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *me, size_t uNum) +{ + const void *pResult = UsefulInputBuf_GetBytes(me, uNum); + if(!pResult) { + return NULLUsefulBufC; + } else { + return (UsefulBufC){pResult, uNum}; + } +} + + +/** + @brief Get a byte out of the input buffer. + + @param[in] me Pointer to the UsefulInputBuf. + + @return The byte + + This consumes 1 byte from the input buffer. It returns the byte. + + If there is not 1 byte in the buffer, 0 will be returned for the byte + and an error set internally. You must check the error at some point + to know whether the 0 was the real value or just returned in error, + but you may not have to do that right away. Check the error state + with UsefulInputBuf_GetError(). You can also know you are in the + error state if UsefulInputBuf_GetBytes() returns NULL or the ptr from + UsefulInputBuf_GetUsefulBuf() is NULL. + + It advances the current position by 1 byte. + */ +static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *me) +{ + const void *pResult = UsefulInputBuf_GetBytes(me, sizeof(uint8_t)); + + return pResult ? *(uint8_t *)pResult : 0; +} + + +/** + @brief Get a uint16_t out of the input buffer + + @param[in] me Pointer to the UsefulInputBuf. + + @return The uint16_t + + See UsefulInputBuf_GetByte(). This works the same, except it returns + a uint16_t and two bytes are consumed. + + The input bytes must be in network order (big endian). + */ +static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *me) +{ + const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(me, sizeof(uint16_t)); + + if(!pResult) { + return 0; + } + + return ((uint16_t)pResult[0] << 8) + (uint16_t)pResult[1]; +} + + +/** + @brief Get a uint32_t out of the input buffer + + @param[in] me Pointer to the UsefulInputBuf. + + @return The uint32_t + + See UsefulInputBuf_GetByte(). This works the same, except it returns + a uint32_t and four bytes are consumed. + + The input bytes must be in network order (big endian). + */ +static inline uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *me) +{ + const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(me, sizeof(uint32_t)); + + if(!pResult) { + return 0; + } + + return ((uint32_t)pResult[0]<<24) + + ((uint32_t)pResult[1]<<16) + + ((uint32_t)pResult[2]<<8) + + (uint32_t)pResult[3]; +} + + +/** + @brief Get a uint64_t out of the input buffer + + @param[in] me Pointer to the UsefulInputBuf. + + @return The uint64_t + + See UsefulInputBuf_GetByte(). This works the same, except it returns + a uint64_t and eight bytes are consumed. + + The input bytes must be in network order (big endian). + */ +static inline uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *me) +{ + const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(me, sizeof(uint64_t)); + + if(!pResult) { + return 0; + } + + return ((uint64_t)pResult[0]<<56) + + ((uint64_t)pResult[1]<<48) + + ((uint64_t)pResult[2]<<40) + + ((uint64_t)pResult[3]<<32) + + ((uint64_t)pResult[4]<<24) + + ((uint64_t)pResult[5]<<16) + + ((uint64_t)pResult[6]<<8) + + (uint64_t)pResult[7]; +} + + +/** + @brief Get a float out of the input buffer + + @param[in] me Pointer to the UsefulInputBuf. + + @return The float + + See UsefulInputBuf_GetByte(). This works the same, except it returns + a float and four bytes are consumed. + + The input bytes must be in network order (big endian). + */ +static inline float UsefulInputBuf_GetFloat(UsefulInputBuf *me) +{ + uint32_t uResult = UsefulInputBuf_GetUint32(me); + + return uResult ? UsefulBufUtil_CopyUint32ToFloat(uResult) : 0; +} + +/** + @brief Get a double out of the input buffer + + @param[in] me Pointer to the UsefulInputBuf. + + @return The double + + See UsefulInputBuf_GetByte(). This works the same, except it returns + a double and eight bytes are consumed. + + The input bytes must be in network order (big endian). + */ +static inline double UsefulInputBuf_GetDouble(UsefulInputBuf *me) +{ + uint64_t uResult = UsefulInputBuf_GetUint64(me); + + return uResult ? UsefulBufUtil_CopyUint64ToDouble(uResult) : 0; +} + + +/** + @brief Get the error status + + @param[in] me Pointer to the UsefulInputBuf. + + @return The error. + + Zero is success, non-zero is error. Once in the error state, the only + way to clear it is to call Init again. + + You may be able to only check the error state at the end after all + the Get()'s have been done, but if what you get later depends on what + you get sooner you cannot. For example if you get a length or count + of following items you will have to check the error. + + */ +static inline int UsefulInputBuf_GetError(UsefulInputBuf *me) +{ + return me->err; +} + + +#endif // _UsefulBuf_h diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/inc/qcbor.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/inc/qcbor.h new file mode 100644 index 0000000..8f061fb --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/inc/qcbor.h @@ -0,0 +1,2597 @@ +/*============================================================================== + Copyright (c) 2016-2018, The Linux Foundation. + Copyright (c) 2018-2019, Laurence Lundblade. + All rights reserved. + SPDX-License-Identifier: BSD-3-Clause + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors, nor the name "Laurence Lundblade" may be used to + endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ==============================================================================*/ + + +/*=================================================================================== + FILE: qcbor.h + + DESCRIPTION: This is the full public API and data structures for QCBOR + + EDIT HISTORY FOR FILE: + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + when who what, where, why + -------- ---- --------------------------------------------------- + 12/18/18 llundblade Move decode malloc optional code to separate repository + 12/13/18 llundblade Documentatation improvements + 11/29/18 llundblade Rework to simpler handling of tags and labels. + 11/9/18 llundblade Error codes are now enums. + 11/1/18 llundblade Floating support. + 10/31/18 llundblade Switch to one license that is almost BSD-3. + 10/15/18 llundblade Indefinite length maps and arrays supported + 10/8/18 llundblade Indefinite length strings supported + 09/28/18 llundblade Added bstr wrapping feature for COSE implementation. + 07/05/17 llundbla Add bstr wrapping of maps/arrays for COSE. + 03/01/17 llundbla More data types; decoding improvements and fixes. + 11/13/16 llundbla Integrate most TZ changes back into github version. + 09/30/16 gkanike Porting to TZ. + 03/15/16 llundbla Initial Version. + + =====================================================================================*/ + +#ifndef __QCBOR__qcbor__ +#define __QCBOR__qcbor__ + +/*...... This is a ruler that is 80 characters long...........................*/ + +/* =========================================================================== + BEGINNING OF PRIVATE PART OF THIS FILE + + Caller of QCBOR should not reference any of the details below up until + the start of the public part. + =========================================================================== */ + +/* + Standard integer types are used in the interface to be precise about + sizes to be better at preventing underflow/overflow errors. + */ +#include +#include +#include "UsefulBuf.h" + + +/* + The maxium nesting of arrays and maps when encoding or decoding. + (Further down in the file there is a definition that refers to this + that is public. This is done this way so there can be a nice + separation of public and private parts in this file. +*/ +#define QCBOR_MAX_ARRAY_NESTING1 15 // Do not increase this over 255 + + +/* The largest offset to the start of an array or map. It is slightly + less than UINT32_MAX so the error condition can be tests on 32-bit machines. + UINT32_MAX comes from uStart in QCBORTrackNesting being a uin32_t. + + This will cause trouble on a machine where size_t is less than 32-bits. + */ +#define QCBOR_MAX_ARRAY_OFFSET (UINT32_MAX - 100) + +/* + PRIVATE DATA STRUCTURE + + Holds the data for tracking array and map nesting during encoding. Pairs up with + the Nesting_xxx functions to make an "object" to handle nesting encoding. + + uStart is a uint32_t instead of a size_t to keep the size of this + struct down so it can be on the stack without any concern. It would be about + double if size_t was used instead. + + Size approximation (varies with CPU/compiler): + 64-bit machine: (15 + 1) * (4 + 2 + 1 + 1 pad) + 8 = 136 bytes + 32-bit machine: (15 + 1) * (4 + 2 + 1 + 1 pad) + 4 = 132 bytes +*/ +typedef struct __QCBORTrackNesting { + // PRIVATE DATA STRUCTURE + struct { + // See function OpenArrayInternal() for detailed comments on how this works + uint32_t uStart; // uStart is the byte position where the array starts + uint16_t uCount; // Number of items in the arrary or map; counts items in a map, not pairs of items + uint8_t uMajorType; // Indicates if item is a map or an array + } pArrays[QCBOR_MAX_ARRAY_NESTING1+1], // stored state for the nesting levels + *pCurrentNesting; // the current nesting level +} QCBORTrackNesting; + + +/* + PRIVATE DATA STRUCTURE + + Context / data object for encoding some CBOR. Used by all encode functions to + form a public "object" that does the job of encdoing. + + Size approximation (varies with CPU/compiler): + 64-bit machine: 27 + 1 (+ 4 padding) + 136 = 32 + 136 = 168 bytes + 32-bit machine: 15 + 1 + 132 = 148 bytes +*/ +struct _QCBOREncodeContext { + // PRIVATE DATA STRUCTURE + UsefulOutBuf OutBuf; // Pointer to output buffer, its length and position in it + uint8_t uError; // Error state + QCBORTrackNesting nesting; // Keep track of array and map nesting +}; + + +/* + PRIVATE DATA STRUCTURE + + Holds the data for array and map nesting for decoding work. This structure + and the DecodeNesting_xxx functions form an "object" that does the work + for arrays and maps. + + Size approximation (varies with CPU/compiler): + 64-bit machine: 4 * 16 + 8 = 72 + 32-bit machine: 4 * 16 + 4 = 68 + */ +typedef struct __QCBORDecodeNesting { + // PRIVATE DATA STRUCTURE + struct { + uint16_t uCount; + uint8_t uMajorType; + } pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING1+1], + *pCurrent; +} QCBORDecodeNesting; + + +/* + PRIVATE DATA STRUCTURE + + The decode context. This data structure plus the public QCBORDecode_xxx + functions form an "object" that does CBOR decoding. + + Size approximation (varies with CPU/compiler): + 64-bit machine: 32 + 1 + 1 + 6 bytes padding + 72 + 16 = 128 bytes + 32-bit machine: 16 + 1 + 1 + 2 bytes padding + 68 + 8 = 68 bytes + */ +struct _QCBORDecodeContext { + // PRIVATE DATA STRUCTURE + UsefulInputBuf InBuf; + + uint8_t uDecodeMode; + uint8_t bStringAllocateAll; + + QCBORDecodeNesting nesting; + + // This is NULL or points to a QCBORStringAllocator. It is void + // here because _QCBORDecodeContext is defined early in the + // private part of this file and QCBORStringAllocat is defined + // later in the public part of this file. + void *pStringAllocator; + + // This is NULL or points to QCBORTagList. + // It is type void for the same reason as above. + const void *pCallerConfiguredTagList; +}; + +// Used internally in the impementation here +// Must not conflict with any of the official CBOR types +#define CBOR_MAJOR_NONE_TYPE_RAW 9 +#define CBOR_MAJOR_NONE_TAG_LABEL_REORDER 10 + + +/* =========================================================================== + END OF PRIVATE PART OF THIS FILE + + BEGINNING OF PUBLIC PART OF THIS FILE + =========================================================================== */ + + + +/* =========================================================================== + BEGINNING OF CONSTANTS THAT COME FROM THE CBOR STANDARD, RFC 7049 + + It is not necessary to use these directly when encoding or decoding + CBOR with this implementation. + =========================================================================== */ + +/* Standard CBOR Major type for positive integers of various lengths */ +#define CBOR_MAJOR_TYPE_POSITIVE_INT 0 + +/* Standard CBOR Major type for negative integer of various lengths */ +#define CBOR_MAJOR_TYPE_NEGATIVE_INT 1 + +/* Standard CBOR Major type for an array of arbitrary 8-bit bytes. */ +#define CBOR_MAJOR_TYPE_BYTE_STRING 2 + +/* Standard CBOR Major type for a UTF-8 string. Note this is true 8-bit UTF8 + with no encoding and no NULL termination */ +#define CBOR_MAJOR_TYPE_TEXT_STRING 3 + +/* Standard CBOR Major type for an ordered array of other CBOR data items */ +#define CBOR_MAJOR_TYPE_ARRAY 4 + +/* Standard CBOR Major type for CBOR MAP. Maps an array of pairs. The + first item in the pair is the "label" (key, name or identfier) and the second + item is the value. */ +#define CBOR_MAJOR_TYPE_MAP 5 + +/* Standard CBOR optional tagging. This tags things like dates and URLs */ +#define CBOR_MAJOR_TYPE_OPTIONAL 6 + +/* Standard CBOR extra simple types like floats and the values true and false */ +#define CBOR_MAJOR_TYPE_SIMPLE 7 + + +/* + These are special values for the AdditionalInfo bits that are part of the first byte. + Mostly they encode the length of the data item. + */ +#define LEN_IS_ONE_BYTE 24 +#define LEN_IS_TWO_BYTES 25 +#define LEN_IS_FOUR_BYTES 26 +#define LEN_IS_EIGHT_BYTES 27 +#define ADDINFO_RESERVED1 28 +#define ADDINFO_RESERVED2 29 +#define ADDINFO_RESERVED3 30 +#define LEN_IS_INDEFINITE 31 + + +/* + 24 is a special number for CBOR. Integers and lengths + less than it are encoded in the same byte as the major type + */ +#define CBOR_TWENTY_FOUR 24 + + +/* + Tags that are used with CBOR_MAJOR_TYPE_OPTIONAL. These are + the ones defined in the CBOR spec. + */ +/** See QCBOREncode_AddDateString() below */ +#define CBOR_TAG_DATE_STRING 0 +/** See QCBOREncode_AddDateEpoch_2() */ +#define CBOR_TAG_DATE_EPOCH 1 +#define CBOR_TAG_POS_BIGNUM 2 +#define CBOR_TAG_NEG_BIGNUM 3 +#define CBOR_TAG_FRACTION 4 +#define CBOR_TAG_BIGFLOAT 5 + +#define CBOR_TAG_COSE_ENCRYPTO 16 +#define CBOR_TAG_COSE_MAC0 17 +#define CBOR_TAG_COSE_SIGN1 18 + +/* The data in byte string should be converted in base 64 URL when encoding in JSON or similar text-based representations */ +#define CBOR_TAG_ENC_AS_B64URL 21 +/* The data in byte string should be encoded in base 64 when encoding in JSON */ +#define CBOR_TAG_ENC_AS_B64 22 +/* The data in byte string should be encoded in base 16 when encoding in JSON */ +#define CBOR_TAG_ENC_AS_B16 23 +#define CBOR_TAG_CBOR 24 +/** The data in the string is a URIs, as defined in RFC3986 */ +#define CBOR_TAG_URI 32 +/** The data in the string is a base 64'd URL */ +#define CBOR_TAG_B64URL 33 +/** The data in the string is base 64'd */ +#define CBOR_TAG_B64 34 +/** regular expressions in Perl Compatible Regular Expressions (PCRE) / JavaScript syntax ECMA262. */ +#define CBOR_TAG_REGEX 35 +/** MIME messages (including all headers), as defined in RFC2045 */ +#define CBOR_TAG_MIME 36 +/** Binary UUID */ +#define CBOR_TAG_BIN_UUID 37 + +#define CBOR_TAG_CWT 61 + +#define CBOR_TAG_ENCRYPT 96 +#define CBOR_TAG_MAC 97 +#define CBOR_TAG_SIGN 98 + +#define CBOR_TAG_GEO_COORD 103 + + +/** The data is CBOR data */ +#define CBOR_TAG_CBOR_MAGIC 55799 +#define CBOR_TAG_NONE UINT64_MAX + + +/* + Values for the 5 bits for items of major type 7 + */ +#define CBOR_SIMPLEV_FALSE 20 +#define CBOR_SIMPLEV_TRUE 21 +#define CBOR_SIMPLEV_NULL 22 +#define CBOR_SIMPLEV_UNDEF 23 +#define CBOR_SIMPLEV_ONEBYTE 24 +#define HALF_PREC_FLOAT 25 +#define SINGLE_PREC_FLOAT 26 +#define DOUBLE_PREC_FLOAT 27 +#define CBOR_SIMPLE_BREAK 31 + + + +/* =========================================================================== + + END OF CONSTANTS THAT COME FROM THE CBOR STANDARD, RFC 7049 + + BEGINNING OF PUBLIC INTERFACE FOR QCBOR ENCODER / DECODER + + =========================================================================== */ + +/** + + @file qcbor.h + + Q C B O R E n c o d e / D e c o d e + + This implements CBOR -- Concise Binary Object Representation as defined + in RFC 7049. More info is at http://cbor.io. This is a near-complete + implementation of the specification. Limitations are listed further down. + + CBOR is intentionally designed to be translatable to JSON, but not + all CBOR can convert to JSON. See RFC 7049 for more info on how to + construct CBOR that is the most JSON friendly. + + The memory model for encoding and decoding is that encoded CBOR + must be in a contiguous buffer in memory. During encoding the + caller must supply an output buffer and if the encoding would go + off the end of the buffer an error is returned. During decoding + the caller supplies the encoded CBOR in a contiguous buffer + and the decoder returns pointers and lengths into that buffer + for strings. + + This implementation does not require malloc. All data structures + passed in/out of the APIs can fit on the stack. + + Decoding of indefinite length strings is a special case that requires + a "string allocator" to allocate memory into which the segments of + the string are coalesced. Without this, decoding will error out if + an indefinite length string is encountered (indefinite length maps + and arrays do not require the string allocator). A simple string + allocator called MemPool is built-in and will work if supplied with + a block of memory to allocate. The string allocator can optionally + use malloc() or some other custom scheme. + + Here are some terms and definitions: + + - "Item", "Data Item": An integer or string or such. The basic "thing" that + CBOR is about. An array is an item itself that contains some items. + + - "Array": An ordered sequence of items, the same as JSON. + + - "Map": A collection of label/value pairs. Each pair is a data + item. A JSON "object" is the same as a CBOR "map". + + - "Label": The data item in a pair in a map that names or identifies the + pair, not the value. This implementation refers to it as a "label". + JSON refers to it as the "name". The CBOR RFC refers to it this as a "key". + This implementation chooses label instead because key is too easily confused + with a cryptographic key. The COSE standard, which uses CBOR, has also + chosen to use the term "label" rather than "key" for this same reason. + + - "Key": See "Label" above. + + - "Tag": Optional info that can be added before each data item. This is always + CBOR major type 6. + + - "Initial Byte": The first byte of an encoded item. Encoding and decoding of + this byte is taken care of by the implementation. + + - "Additional Info": In addition to the major type, all data items have some + other info. This is usually the length of the data, but can be several + other things. Encoding and decoding of this is taken care of by the + implementation. + + CBOR has two mechanisms for tagging and labeling the data + values like integers and strings. For example, an integer that + represents someone's birthday in epoch seconds since Jan 1, 1970 + could be encoded like this: + + - First it is CBOR_MAJOR_TYPE_POSITIVE_INT, the primitive positive + integer. + - Next it has a "tag" CBOR_TAG_DATE_EPOCH indicating the integer + represents a date in the form of the number of seconds since + Jan 1, 1970. + - Last it has a string "label" like "BirthDate" indicating + the meaning of the data. + + The encoded binary looks like this: + a1 # Map of 1 item + 69 # Indicates text string of 9 bytes + 426972746844617465 # The text "BirthDate" + c1 # Tags next int as epoch date + 1a # Indicates 4 byte integer + 580d4172 # unsigned integer date 1477263730 + + Implementors using this API will primarily work with labels. Generally + tags are only needed for making up new data types. This implementation + covers most of the data types defined in the RFC using tags. It also, + allows for the creation of news tags if necessary. + + This implementation explicitly supports labels that are text strings + and integers. Text strings translate nicely into JSON objects and + are very readable. Integer labels are much less readable, but + can be very compact. If they are in the range of -23 to + 23 they take up only one byte. + + CBOR allows a label to be any type of data including an array or + a map. It is possible to use this API to construct and + parse such labels, but it is not explicitly supported. + + A common encoding usage mode is to invoke the encoding twice. First + with no output buffer to compute the length of the needed output + buffer. Then the correct sized output buffer is allocated. Last the + encoder is invoked again, this time with the output buffer. + + The double invocation is not required if the max output buffer size + can be predicted. This is usually possible for simple CBOR structures. + If the double invocation is implemented, it can be + in a loop or function as in the example code so that the code doesn't + have to actually be written twice, saving code size. + + If a buffer too small to hold the encoded output is given, the error + QCBOR_ERR_BUFFER_TOO_SMALL will be returned. Data will never be + written off the end of the output buffer no matter which functions + here are called or what parameters are passed to them. + + The error handling is simple. The only possible errors are trying to + encode structures that are too large or too complex. There are no + internal malloc calls so there will be no failures for out of memory. + Only the final call, QCBOREncode_Finish(), returns an error code. + Once an error happens, the encoder goes into an error state and calls + to it will do nothing so the encoding can just go on. An error + check is not needed after every data item is added. + + Encoding generally proceeds by calling QCBOREncode_Init(), calling + lots of "Add" functions and calling QCBOREncode_Finish(). There + are many "Add" functions for various data types. The input + buffers need only to be valid during the "Add" calls. The + data is copied into the output buf during the "Add" call. + + There are three `Add` functions for each data type. The first + / main one for the type is for adding the data item to an array. + The second one's name ends in `ToMap`, is used for adding + data items to maps and takes a string + argument that is its label in the map. The third one ends in + `ToMapN`, is also used for adding data items to maps, and + takes an integer argument that is its label in the map. + + The simplest aggregate type is an array, which is a simple ordered + set of items without labels the same as JSON arrays. Call + QCBOREncode_OpenArray() to open a new array, then "Add" to + put items in the array and then QCBOREncode_CloseArray(). Nesting + to a limit is allowed. All opens must be matched by closes or an + encoding error will be returned. + + The other aggregate type is a map which does use labels. The + `Add` functions that end in `ToMap` and `ToMapN` are convenient + ways to add labeled data items to a map. You can also call + any type of `Add` function once to add a label of any time and + then call any type of `Add` again to add its value. + + Note that when you nest arrays or maps in a map, the nested + array or map has a label. + + Usually it is not necessary to add tags explicitly as most + tagged types have functions here, but they can be added by + calling QCBOREncode_AddTag(). There is an IANA registry for new tags that are + for broad use and standardization as per RFC 7049. It is also + allowed for protocols to make up new tags in the range above 256. + Note that even arrays and maps can be tagged. + + Summary Limits of this implementation: + - The entire encoded CBOR must fit into contiguous memory. + - Max size of encoded / decoded CBOR data is UINT32_MAX (4GB). + - Max array / map nesting level when encoding / decoding is + QCBOR_MAX_ARRAY_NESTING (this is typically 15). + - Max items in an array or map when encoding / decoding is + QCBOR_MAX_ITEMS_IN_ARRAY (typically 65,536). + - Does not support encoding indefinite lengths (decoding is supported). + - Does not directly support some tagged types: decimal fractions, big floats + - Does not directly support labels in maps other than text strings and ints. + - Does not directly support int labels greater than INT64_MAX + - Epoch dates limited to INT64_MAX (+/- 292 billion years) + - Tags on labels are ignored during decoding + + This implementation is intended to run on 32 and 64-bit CPUs. Minor + modifications are needed for it to work on 16-bit CPUs. + + The public interface uses size_t for all lengths. Internally the + implementation uses 32-bit lengths by design to use less memory and + fit structures on the stack. This limits the encoded + CBOR it can work with to size UINT32_MAX (4GB) which should be + enough. + + This implementation assumes two's compliment integer + machines. Stdint.h also requires this. It of course would be easy to + fix this implementation for another integer representation, but all + modern machines seem to be two's compliment. + + */ + + +/** + The maximum number of items in a single array or map when encoding of decoding. +*/ +// -1 is because the value UINT16_MAX is used to track indefinite length arraysUINT16_MAX +#define QCBOR_MAX_ITEMS_IN_ARRAY (UINT16_MAX-1) + +/** + The maximum nesting of arrays and maps when encoding or decoding. The + error QCBOR_ERR_ARRAY_NESTING_TOO_DEEP will be returned on encoding + of decoding if it is exceeded +*/ +#define QCBOR_MAX_ARRAY_NESTING QCBOR_MAX_ARRAY_NESTING1 + +/** + The maximum number of tags that can be in QCBORTagListIn and passed to + QCBORDecode_SetCallerConfiguredTagList() + */ +#define QCBOR_MAX_CUSTOM_TAGS 16 + + +typedef enum { + /** The encode or decode completely correctly. */ + QCBOR_SUCCESS = 0, + + /** The buffer provided for the encoded output when doing encoding was + too small and the encoded output will not fit. Also, when the buffer + given to QCBORDecode_SetMemPool() is too small. */ + QCBOR_ERR_BUFFER_TOO_SMALL, + + /** During encoding or decoding, the array or map nesting was deeper than + this implementation can handle. Note that in the interest of code size + and memory use, this implementation has a hard limit on array nesting. The + limit is defined as the constant QCBOR_MAX_ARRAY_NESTING. */ + QCBOR_ERR_ARRAY_NESTING_TOO_DEEP, + + /** During decoding or encoding, the array or map had too many items in it. + This limit QCBOR_MAX_ITEMS_IN_ARRAY, typically 65,535. */ + QCBOR_ERR_ARRAY_TOO_LONG, + + /** During encoding, more arrays or maps were closed than opened. This is a + coding error on the part of the caller of the encoder. */ + QCBOR_ERR_TOO_MANY_CLOSES, + + /** During decoding, some CBOR construct was encountered that this decoder + doesn't support, primarily this is the reserved additional info values, + 28 through 30. */ + QCBOR_ERR_UNSUPPORTED, + + /** During decoding, hit the end of the given data to decode. For example, + a byte string of 100 bytes was expected, but the end of the input was + hit before finding those 100 bytes. Corrupted CBOR input will often + result in this error. */ + QCBOR_ERR_HIT_END, + + /** During encoding, the length of the encoded CBOR exceeded UINT32_MAX. + */ + QCBOR_ERR_BUFFER_TOO_LARGE, + + /** During decoding, an integer smaller than INT64_MIN was received (CBOR + can represent integers smaller than INT64_MIN, but C cannot). */ + QCBOR_ERR_INT_OVERFLOW, + + /** During decoding, the label for a map entry is bad. What causes this + error depends on the decoding mode. */ + QCBOR_ERR_MAP_LABEL_TYPE, + + /** During encoding or decoding, the number of array or map opens was not + matched by the number of closes. */ + QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN, + + /** During encoding, the simple value is not between CBOR_SIMPLEV_FALSE + and CBOR_SIMPLEV_UNDEF. */ + QCBOR_ERR_BAD_SIMPLE, + + /** During decoding, a date greater than +- 292 billion years from Jan 1 + 1970 encountered during parsing. */ + QCBOR_ERR_DATE_OVERFLOW, + + /** During decoding, the CBOR is not valid, primarily a simple type is encoded in + a prohibited way. */ + QCBOR_ERR_INVALID_CBOR, + + /** Optional tagging that doesn't make sense (an int is tagged as a + date string) or can't be handled. */ + QCBOR_ERR_BAD_OPT_TAG, + + /** Returned by QCBORDecode_Finish() if all the inputs bytes have not + been consumed. */ + QCBOR_ERR_EXTRA_BYTES, + + /** During encoding, QCBOREncode_Close() call with a different type than + is currently open. */ + QCBOR_ERR_CLOSE_MISMATCH, + + /** Unable to decode an indefinite length string because no string + allocator was configured. */ + QCBOR_ERR_NO_STRING_ALLOCATOR, + + /** One of the chunks in an indefinite length string is not of the type of + the string. */ + QCBOR_ERR_INDEFINITE_STRING_CHUNK, + + /** Error allocating space for a string, usually for an indefinite length + string. */ + QCBOR_ERR_STRING_ALLOCATE, + + /** During decoding, a break occurred outside an indefinite length item. */ + QCBOR_ERR_BAD_BREAK, + + /** During decoding, too many tags in the caller-configured tag list, or not + enough space in QCBORTagListOut. */ + QCBOR_ERR_TOO_MANY_TAGS, + + /** Returned by QCBORDecode_SetMemPool() when xx is too small. This should + never happen on a machine with 64-bit or smaller pointers. Fixing + it is probably by increasing QCBOR_DECODE_MIN_MEM_POOL_SIZE. */ + QCBOR_ERR_MEM_POOL_INTERNAL + +} QCBORError; + + +typedef enum { + /** See QCBORDecode_Init() */ + QCBOR_DECODE_MODE_NORMAL = 0, + /** See QCBORDecode_Init() */ + QCBOR_DECODE_MODE_MAP_STRINGS_ONLY = 1, + /** See QCBORDecode_Init() */ + QCBOR_DECODE_MODE_MAP_AS_ARRAY = 2 +} QCBORDecodeMode; + + + + + +/* Do not renumber these. Code depends on some of these values. */ +/** The type is unknown, unset or invalid */ +#define QCBOR_TYPE_NONE 0 +/** Type for an integer that decoded either between INT64_MIN and INT32_MIN or INT32_MAX and INT64_MAX; val.int64 */ +#define QCBOR_TYPE_INT64 2 +/** Type for an integer that decoded to a more than INT64_MAX and UINT64_MAX; val.uint64 */ +#define QCBOR_TYPE_UINT64 3 +/** Type for an array. The number of items in the array is in val.uCount. */ +#define QCBOR_TYPE_ARRAY 4 +/** Type for a map; number of items in map is in val.uCount */ +#define QCBOR_TYPE_MAP 5 +/** Type for a buffer full of bytes. Data is in val.string. */ +#define QCBOR_TYPE_BYTE_STRING 6 +/** Type for a UTF-8 string. It is not NULL terminated. Data is in val.string. */ +#define QCBOR_TYPE_TEXT_STRING 7 +/** Type for a positive big number. Data is in val.bignum, a pointer and a length. */ +#define QCBOR_TYPE_POSBIGNUM 9 +/** Type for a negative big number. Data is in val.bignum, a pointer and a length. */ +#define QCBOR_TYPE_NEGBIGNUM 10 +/** Type for RFC 3339 date string, possibly with time zone. Data is in val.dateString */ +#define QCBOR_TYPE_DATE_STRING 11 +/** Type for integer seconds since Jan 1970 + floating point fraction. Data is in val.epochDate */ +#define QCBOR_TYPE_DATE_EPOCH 12 +/** A simple type that this CBOR implementation doesn't know about; Type is in val.uSimple. */ +#define QCBOR_TYPE_UKNOWN_SIMPLE 13 +/** Type for the simple value false; nothing more; nothing in val union. */ +#define QCBOR_TYPE_FALSE 20 +/** Type for the simple value true; nothing more; nothing in val union. */ +#define QCBOR_TYPE_TRUE 21 +/** Type for the simple value null; nothing more; nothing in val union. */ +#define QCBOR_TYPE_NULL 22 +/** Type for the simple value undef; nothing more; nothing in val union. */ +#define QCBOR_TYPE_UNDEF 23 +/** Type for a floating point number. Data is in val.float. */ +#define QCBOR_TYPE_FLOAT 26 +/** Type for a double floating point number. Data is in val.double. */ +#define QCBOR_TYPE_DOUBLE 27 +/** For QCBOR_DECODE_MODE_MAP_AS_ARRAY decode mode, a map that is being traversed as an array. See QCBORDecode_Init() */ +#define QCBOR_TYPE_MAP_AS_ARRAY 32 + +#define QCBOR_TYPE_BREAK 31 // Used internally; never returned + +#define QCBOR_TYPE_OPTTAG 254 // Used internally; never returned + + + +/* + Approx Size of this: + 8 + 8 + 1 + 1 + 1 + (1 padding) + (4 padding on 64-bit machine) = 24 for first part (20 on a 32-bit machine) + 16 bytes for the val union + 16 bytes for label union + total = 56 bytes (52 bytes on 32-bit machine) + */ + +/** + QCBORItem holds the type, value and other info for a decoded item returned by GetNextItem(). + */ +typedef struct _QCBORItem { + uint8_t uDataType; /** Tells what element of the val union to use. One of QCBOR_TYPE_XXXX */ + uint8_t uNestingLevel; /** How deep the nesting from arrays and maps are. 0 is the top level with no arrays or maps entered */ + uint8_t uLabelType; /** Tells what element of the label union to use */ + uint8_t uDataAlloc; /** 1 if allocated with string allocator, 0 if not. See QCBORDecode_MakeMallocStringAllocator() */ + uint8_t uLabelAlloc; /** Like uDataAlloc, but for label */ + uint8_t uNextNestLevel; /** If not equal to uNestingLevel, this item closed out at least one map/array */ + + union { + int64_t int64; /** The value for uDataType QCBOR_TYPE_INT64 */ + uint64_t uint64; /** The value for uDataType QCBOR_TYPE_UINT64 */ + + UsefulBufC string; /** The value for uDataType QCBOR_TYPE_BYTE_STRING and QCBOR_TYPE_TEXT_STRING */ + uint16_t uCount; /** The "value" for uDataType QCBOR_TYPE_ARRAY or QCBOR_TYPE_MAP -- the number of items in the array or map + UINT16_MAX when decoding indefinite lengths maps and arrays. */ + double dfnum; /** The value for uDataType QCBOR_TYPE_DOUBLE */ + struct { + int64_t nSeconds; + double fSecondsFraction; + } epochDate; /** The value for uDataType QCBOR_TYPE_DATE_EPOCH */ + UsefulBufC dateString; /** The value for uDataType QCBOR_TYPE_DATE_STRING */ + UsefulBufC bigNum; /** The value for uDataType QCBOR_TYPE_BIGNUM */ + uint8_t uSimple; /** The integer value for unknown simple types */ + uint64_t uTagV; + + } val; /** The union holding the item's value. Select union member based on uDataType */ + + union { + UsefulBufC string; /** The label for uLabelType QCBOR_TYPE_BYTE_STRING and QCBOR_TYPE_TEXT_STRING */ + int64_t int64; /** The label for uLabelType for QCBOR_TYPE_INT64 */ + uint64_t uint64; /** The label for uLabelType for QCBOR_TYPE_UINT64 */ + } label; /** Union holding the different label types selected based on uLabelType */ + + uint64_t uTagBits; /** Bit indicating which tags (major type 6) on this item. */ + +} QCBORItem; + + +/** + This is a set of functions and pointer context (in object-oriented parlance, + an "object") used to allocate memory for coalescing the segments of an indefinite + length string into one. + + The fAllocate function works as an initial allocator and a reallocator to + expand the string for each new segment. When it is an initial allocator + pOldMem is NULL. + + The fFree function is called to clean up an individual allocation when an error occurs. + + The fDesctructor function is called when QCBORDecode_Finish is called. + + Any memory allocated with this will be marked by setting uDataAlloc + or uLabelAlloc in the QCBORItem structure so the caller knows they + have to free it. + + fAllocate is only ever called to increase the single most recent + allocation made, making implementation of a memory pool very simple. + + fFree is also only called on the single most recent allocation. + */ +typedef struct { + void *pAllocaterContext; + UsefulBuf (*fAllocate)(void *pAllocaterContext, void *pOldMem, size_t uNewSize); + void (*fFree)(void *pAllocaterContext, void *pMem); + void (*fDestructor)(void *pAllocaterContext); +} QCBORStringAllocator; + + +/** + This only matters if you use a string allocator + and and set it up with QCBORDecode_SetMemPool(). It is + the size of the overhead needed needed by + QCBORDecode_SetMemPool(). If you write your own + string allocator or use the separately available malloc + based string allocator, this size will not apply + */ +#define QCBOR_DECODE_MIN_MEM_POOL_SIZE 72 + + +/** + This is used to tell the decoder about tags that it should + record in uTagBits in QCBORItem beyond the built-in + tags. puTags points to an + array of uint64_t integers that are the tags. uNumTags + is the number of integers in the array. The maximum + size is QCBOR_MAX_CUSTOM_TAGS. See QCBORDecode_IsTagged() + and QCBORDecode_SetCallerAddedTagMap(). + */ +typedef struct { + uint8_t uNumTags; + const uint64_t *puTags; +} QCBORTagListIn; + + +/** + This is for QCBORDecode_GetNextWithTags() to be able to return the + full list of tags on an item. It not needed for most CBOR protocol + implementations. Its primary use is for pretty-printing CBOR or + protocol conversion to another format. + + On input, puTags points to a buffer to be filled in + and uNumAllocated is the number of uint64_t values + in the buffer. + + On output the buffer contains the tags for the item. + uNumUsed tells how many there are. + */ +typedef struct { + uint8_t uNumUsed; + uint8_t uNumAllocated; + uint64_t *puTags; +} QCBORTagListOut; + + +/** + QCBOREncodeContext is the data type that holds context for all the + encoding functions. It is less than 200 bytes, so it can go on + the stack. The contents are opaque, and the caller should not access + any internal items. A context may be re used serially as long as + it is re initialized. + */ +typedef struct _QCBOREncodeContext QCBOREncodeContext; + + +/** + Initialize the the encoder to prepare to encode some CBOR. + + @param[in,out] pCtx The encoder context to initialize. + @param[in] Storage The buffer into which this encoded result will be placed. + + Call this once at the start of an encoding of a CBOR structure. Then + call the various QCBOREncode_AddXXX() functions to add the data + items. Then call QCBOREncode_Finish(). + + The maximum output buffer is UINT32_MAX (4GB). This is not a practical + limit in any way and reduces the memory needed by the implementation. + The error QCBOR_ERR_BUFFER_TOO_LARGE will be returned by QCBOR_Finish() + if a larger buffer length is passed in. + + If this is called with pBuf as NULL and uBufLen a large value like + UINT32_MAX, all the QCBOREncode_AddXXXX() functions and + QCBORE_Encode_Finish() can still be called. No data will be encoded, + but the length of what would be encoded will be calculated. The + length of the encoded structure will be handed back in the call to + QCBOREncode_Finish(). You can then allocate a buffer of that size + and call all the encoding again, this time to fill in the buffer. + + A QCBORContext can be reused over and over as long as + QCBOREncode_Init() is called. + */ +void QCBOREncode_Init(QCBOREncodeContext *pCtx, UsefulBuf Storage); + + +/** + @brief Add a signed 64-bit integer to the encoded output. + + @param[in] pCtx The encoding context to add the integer to. + @param[in] nNum The integer to add. + + The integer will be encoded and added to the CBOR output. + + This function figures out the size and the sign and encodes in the + correct minimal CBOR. Specifically, it will select CBOR major type 0 or 1 + based on sign and will encode to 1, 2, 4 or 8 bytes depending on the + value of the integer. Values less than 24 effectively encode to one + byte because they are encoded in with the CBOR major type. This is + a neat and efficient characteristic of CBOR that can be taken + advantage of when designing CBOR-based protocols. If integers like + tags can be kept between -23 and 23 they will be encoded in one byte + including the major type. + + If you pass a smaller int, say an int16_t or a small value, say 100, + the encoding will still be CBOR's most compact that can represent the + value. For example, CBOR always encodes the value 0 as one byte, + 0x00. The representation as 0x00 includes identification of the type + as an integer too as the major type for an integer is 0. See RFC 7049 + Appendix A for more examples of CBOR encoding. This compact encoding + is also canonical CBOR as per section 3.9 in RFC 7049. + + There are no functions to add int16_t or int32_t because they are + not necessary because this always encodes to the smallest number + of bytes based on the value (If this code is running on a 32-bit + machine having a way to add 32-bit integers would reduce code size some). + + If the encoding context is in an error state, this will do + nothing. If an error occurs when adding this integer, the internal + error flag will be set, and the error will be returned when + QCBOREncode_Finish() is called. + + See also QCBOREncode_AddUInt64(). + */ +void QCBOREncode_AddInt64(QCBOREncodeContext *pCtx, int64_t nNum); + +static void QCBOREncode_AddInt64ToMap(QCBOREncodeContext *pCtx, const char *szLabel, int64_t uNum); + +static void QCBOREncode_AddInt64ToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, int64_t uNum); + + +/** + @brief Add an unsigned 64-bit integer to the encoded output. + + @param[in] pCtx The encoding context to add the integer to. + @param[in] uNum The integer to add. + + The integer will be encoded and added to the CBOR output. + + The only reason so use this function is for integers larger than + INT64_MAX and smaller than UINT64_MAX. Otherwise QCBOREncode_AddInt64() + will work fine. + + Error handling is the same as for QCBOREncode_AddInt64(). + */ +void QCBOREncode_AddUInt64(QCBOREncodeContext *pCtx, uint64_t uNum); + +static void QCBOREncode_AddUInt64ToMap(QCBOREncodeContext *pCtx, const char *szLabel, uint64_t uNum); + +static void QCBOREncode_AddUInt64ToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, uint64_t uNum); + + +/** + + @brief Add a UTF-8 text string to the encoded output + + @param[in] pCtx The context to initialize. + @param[in] Text Pointer and length of text to add. + + The text passed in must be unencoded UTF-8 according to RFC + 3629. There is no NULL termination. The text is added as CBOR + major type 3. + + If called with nBytesLen equal to 0, an empty string will be + added. When nBytesLen is 0, pBytes may be NULL. + + Note that the restriction of the buffer length to an uint32_t is + entirely intentional as this encoder is not capable of encoding + lengths greater. This limit to 4GB for a text string should not be a + problem. + + Error handling is the same as QCBOREncode_AddInt64(). + */ +static void QCBOREncode_AddText(QCBOREncodeContext *pCtx, UsefulBufC Text); + +static void QCBOREncode_AddTextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Text); + +static void QCBOREncode_AddTextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Text); + + +/** + @brief Add a UTF-8 text string to the encoded output + + @param[in] pCtx The context to initialize. + @param[in] szString Null-terminated text to add. + + This works the same as QCBOREncode_AddText(). + */ +static void QCBOREncode_AddSZString(QCBOREncodeContext *pCtx, const char *szString); + +static void QCBOREncode_AddSZStringToMap(QCBOREncodeContext *pCtx, const char *szLabel, const char *szString); + +static void QCBOREncode_AddSZStringToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, const char *szString); + + +/** + @brief Add a floating-point number to the encoded output + + @param[in] pCtx The encoding context to add the float to. + @param[in] dNum The double precision number to add. + + This outputs a floating-point number with CBOR major type 7. + + This will selectively encode the double-precision floating point + number as either double-precision, single-precision or + half-precision. It will always encode infinity, NaN and 0 has half + precision. If no precision will be lost in the conversion to + half-precision then it will be converted and encoded. If not and no + precision will be lost in conversion to single-precision, then it + will be converted and encoded. If not, then no conversion is + performed, and it encoded as a double. + + Half-precision floating point numbers take up 2 bytes, half that of + single-precision, one quarter of double-precision + + This automatically reduces the size of encoded messages a lot, maybe + even by four if most of values are 0, infinity or NaN. + + On decode, these will always be returned as a double. + + Error handling is the same as QCBOREncode_AddInt64(). + */ +void QCBOREncode_AddDouble(QCBOREncodeContext *pCtx, double dNum); + +static void QCBOREncode_AddDoubleToMap(QCBOREncodeContext *pCtx, const char *szLabel, double dNum); + +static void QCBOREncode_AddDoubleToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, double dNum); + + +/** + @brief[in] Add an optional tag + + @param[in] pCtx The encoding context to add the integer to. + @param[in] uTag The tag to add + + This outputs a CBOR major type 6 optional tag. + + The tag is applied to the next data item added to the encoded + output. That data item that is to be tagged can be of any major + CBOR type. Any number of tags can be added to a data item by calling + this multiple times before the data item is added. + + For many of the common standard tags a function to encode + data using it already exists and this is not needed. For example, + QCBOREncode_AddDateEpoch() already exists to output + integers representing dates with the right tag. +*/ +void QCBOREncode_AddTag(QCBOREncodeContext *pCtx,uint64_t uTag); + + +/** + @brief Add an epoch-based date + + @param[in] pCtx The encoding context to add the simple value to. + @param[in] date Number of seconds since 1970-01-01T00:00Z in UTC time. + + As per RFC 7049 this is similar to UNIX/Linux/POSIX dates. This is + the most compact way to specify a date and time in CBOR. Note that this + is always UTC and does not include the time zone. Use + QCBOREncode_AddDateString() if you want to include the time zone. + + The integer encoding rules apply here so the date will be encoded in a + minimal number of 1, 2 4 or 8 bytes. Until about the year 2106 these + dates should encode in 6 bytes -- one byte for the tag, one byte for the type + and 4 bytes for the integer. + + If you care about leap-seconds and that level of accuracy, make sure the + system you are running this code on does it correctly. This code just takes + the value passed in. + + This implementation cannot encode fractional seconds using float or double + even though that is allowed by CBOR, but you can encode them if you + want to by calling QCBOREncode_AddDouble() + with the right parameters. + + Error handling is the same as QCBOREncode_AddInt64(). + */ +static void QCBOREncode_AddDateEpoch(QCBOREncodeContext *pCtx, int64_t date); + +static void QCBOREncode_AddDateEpochToMap(QCBOREncodeContext *pCtx, const char *szLabel, int64_t date); + +static void QCBOREncode_AddDateEpochToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, int64_t date); + + +/** + @brief Add a byte string to the encoded output. + + @param[in] pCtx The context to initialize. + @param[in] Bytes Pointer and length of the input data. + + Simply adds the bytes to the encoded output as CBOR major type 2. + + If called with Bytes.len equal to 0, an empty string will be + added. When Bytes.len is 0, Bytes.ptr may be NULL. + + Error handling is the same as QCBOREncode_AddInt64(). + */ +static void QCBOREncode_AddBytes(QCBOREncodeContext *pCtx, UsefulBufC Bytes); + +static void QCBOREncode_AddBytesToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes); + +static void QCBOREncode_AddBytesToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes); + + + +/** + @brief Add a binary UUID to the encoded output. + + @param[in] pCtx The context to initialize. + @param[in] Bytes Pointer and length of the binary UUID. + + A binary UUID as defined in RFC 4122 is added to the ouput. + + It is output as CBOR major type 2, a binary string, with + optional tag 36 indicating the binary string is a UUID. + */ +static void QCBOREncode_AddBinaryUUID(QCBOREncodeContext *pCtx, UsefulBufC Bytes); + +static void QCBOREncode_AddBinaryUUIDToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes); + +static void QCBOREncode_AddBinaryUUIDToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes); + + +/** + @brief Add a positive big number to the encoded output. + + @param[in] pCtx The context to initialize. + @param[in] Bytes Pointer and length of the big number. + + Big numbers are integers larger than 64-bits. Their format + is described in RFC 7049. + + It is output as CBOR major type 2, a binary string, with + optional tag 2 indicating the binary string is a positive big + number. + + Often big numbers are used to represent cryptographic keys, + however, COSE which defines representations for keys chose not + to use this particular type. + */ +static void QCBOREncode_AddPositiveBignum(QCBOREncodeContext *pCtx, UsefulBufC Bytes); + +static void QCBOREncode_AddPositiveBignumToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes); + +static void QCBOREncode_AddPositiveBignumToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes); + + +/** + @brief Add a negative big number to the encoded output. + + @param[in] pCtx The context to initialize. + @param[in] Bytes Pointer and length of the big number. + + Big numbers are integers larger than 64-bits. Their format + is described in RFC 7049. + + It is output as CBOR major type 2, a binary string, with + optional tag 2 indicating the binary string is a negative big + number. + + Often big numbers are used to represent cryptographic keys, + however, COSE which defines representations for keys chose not + to use this particular type. + */ +static void QCBOREncode_AddNegativeBignum(QCBOREncodeContext *pCtx, UsefulBufC Bytes); + +static void QCBOREncode_AddNegativeBignumToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes); + +static void QCBOREncode_AddNegativeBignumToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes); + + +/** + @brief Add a text URI to the encoded output. + + @param[in] pCtx The context to initialize. + @param[in] URI Pointer and length of the URI. + + The format of URI is RFC 3986. + + It is output as CBOR major type 3, a text string, with + optional tag 32 indicating the text string is a URI. + */ +static void QCBOREncode_AddURI(QCBOREncodeContext *pCtx, UsefulBufC URI); + +static void QCBOREncode_AddURIToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC URI); + +static void QCBOREncode_AddURIToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC URI); + + +/** + @brief Add base 64-encoded text to encoded output. + + @param[in] pCtx The context to initialize. + @param[in] B64Text Pointer and length of the base-64 encoded text. + + The text content is base 64 encoded data per RFC 4648. + + It is output as CBOR major type 3, a text string, with + optional tag 34 indicating the text string is a URI. + */ +static void QCBOREncode_AddB64Text(QCBOREncodeContext *pCtx, UsefulBufC B64Text); + +static void QCBOREncode_AddB64TextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC B64Text); + +static void QCBOREncode_AddB64TextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC B64Text); + + +/** + @brief Add base 64URL -encoded URL to encoded output. + + @param[in] pCtx The context to initialize. + @param[in] B64Text Pointer and length of the base-64 encoded text. + + The text content is base 64 URL format encoded text as per RFC 4648. + + It is output as CBOR major type 3, a text string, with + optional tag 33 indicating the text string is a URI. + */ +static void QCBOREncode_AddB64URLText(QCBOREncodeContext *pCtx, UsefulBufC B64Text); + +static void QCBOREncode_AddB64URLTextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC B64Text); + +static void QCBOREncode_AddB64URLTextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC B64Text); + + +/** + @brief Add Perl Compatible Regular Expression + + @param[in] pCtx The context to initialize. + @param[in] Regex Pointer and length of the regular expression. + + The text content is Perl Compatible Regular + Expressions (PCRE) / JavaScript syntax [ECMA262]. + + It is output as CBOR major type 3, a text string, with + optional tag 35 indicating the text string is a regular expression. + */ +static void QCBOREncode_AddRegex(QCBOREncodeContext *pCtx, UsefulBufC Regex); + +static void QCBOREncode_AddRegexToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Regex); + +static void QCBOREncode_AddRegexToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Regex); + + +/** + @brief MIME encoded text to the encoded output. + + @param[in] pCtx The context to initialize. + @param[in] MIMEData Pointer and length of the regular expression. + + The text content is in MIME format per RFC 2045 including the headers. + + It is output as CBOR major type 3, a text string, with + optional tag 36 indicating the text string is MIME data. + */ +static void QCBOREncode_AddMIMEData(QCBOREncodeContext *pCtx, UsefulBufC MIMEData); + +static void QCBOREncode_AddMIMEDataToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC MIMEData); + +static void QCBOREncode_AddMIMEDataToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC MIMEData); + + +/** + @brief Add an RFC 3339 date string + + @param[in] pCtx The encoding context to add the simple value to. + @param[in] szDate Null-terminated string with date to add + + The string szDate should be in the form of RFC 3339 as defined by section + 3.3 in RFC 4287. This is as described in section 2.4.1 in RFC 7049. + + Note that this function doesn't validate the format of the date string + at all. If you add an incorrect format date string, the generated + CBOR will be incorrect and the receiver may not be able to handle it. + + Error handling is the same as QCBOREncode_AddInt64(). + */ +static void QCBOREncode_AddDateString(QCBOREncodeContext *pCtx, const char *szDate); + +static void QCBOREncode_AddDateStringToMap(QCBOREncodeContext *pCtx, const char *szLabel, const char *szDate); + +static void QCBOREncode_AddDateStringToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, const char *szDate); + + +/** + @brief Add a standard boolean. + + @param[in] pCtx The encoding context to add the simple value to. + @param[in] b true or false from stdbool. Anything will result in an error. + + Adds a boolean value as CBOR major type 7. + + Error handling is the same as QCBOREncode_AddInt64(). + */ +static void QCBOREncode_AddBool(QCBOREncodeContext *pCtx, bool b); + +static void QCBOREncode_AddBoolToMap(QCBOREncodeContext *pCtx, const char *szLabel, bool b); + +static void QCBOREncode_AddBoolToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, bool b); + + + +/** + @brief Add a NULL to the encoded output. + + @param[in] pCtx The encoding context to add the simple value to. + + Adds the NULL value as CBOR major type 7. + + This NULL doesn't have any special meaning in CBOR such as a terminating + value for a string or an empty value. + + Error handling is the same as QCBOREncode_AddInt64(). + */ +static void QCBOREncode_AddNULL(QCBOREncodeContext *pCtx); + +static void QCBOREncode_AddNULLToMap(QCBOREncodeContext *pCtx, const char *szLabel); + +static void QCBOREncode_AddNULLToMapN(QCBOREncodeContext *pCtx, int64_t nLabel); + + +/** + @brief Add an "undef" to the encoded output. + + @param[in] pCtx The encoding context to add the simple value to. + + Adds the undef value as CBOR major type 7. + + Note that this value will not translate to JSON. + + This Undef doesn't have any special meaning in CBOR such as a terminating + value for a string or an empty value. + + Error handling is the same as QCBOREncode_AddInt64(). + */ +static void QCBOREncode_AddUndef(QCBOREncodeContext *pCtx); + +static void QCBOREncode_AddUndefToMap(QCBOREncodeContext *pCtx, const char *szLabel); + +static void QCBOREncode_AddUndefToMapN(QCBOREncodeContext *pCtx, int64_t nLabel); + + +/** + @brief Indicates that the next items added are in an array. + + @param[in] pCtx The encoding context to open the array in. + + Arrays are the basic CBOR aggregate or structure type. Call this + function to start or open an array. Then call the various AddXXX + functions to add the items that go into the array. Then call + QCBOREncode_CloseArray() when all items have been added. The data + items in the array can be of any type and can be of mixed types. + + Nesting of arrays and maps is allowed and supported just by calling + QCBOREncode_OpenArray() again before calling CloseArray. While CBOR + has no limit on nesting, this implementation does in order to keep it + smaller and simpler. The limit is QCBOR_MAX_ARRAY_NESTING. This is + the max number of times this can be called without calling + QCBOREncode_CloseArray(). QCBOREncode_Finish() will return + QCBOR_ERR_ARRAY_NESTING_TOO_DEEP when it is called as this function + just sets an error state and returns no value when this occurs. + + If you try to add more than QCBOR_MAX_ITEMS_IN_ARRAY items to a + single array or map, QCBOR_ERR_ARRAY_TOO_LONG will be returned when + QCBOREncode_Finish() is called. + + An array itself must have a label if it is being added to a map. + Note that array elements do not have labels (but map elements do). + + An array itself may be tagged. + */ +static void QCBOREncode_OpenArray(QCBOREncodeContext *pCtx); + +static void QCBOREncode_OpenArrayInMap(QCBOREncodeContext *pCtx, const char *szLabel); + +static void QCBOREncode_OpenArrayInMapN(QCBOREncodeContext *pCtx, int64_t nLabel); + + +/** + @brief Close an open array. + + @param[in] pCtx The context to add to. + + The closes an array opened by QCBOREncode_OpenArray(). It reduces + nesting level by one. All arrays (and maps) must be closed before + calling QCBOREncode_Finish(). + + When an error occurs as a result of this call, the encoder records + the error and enters the error state. The error will be returned when + QCBOREncode_Finish() is called. + + If this has been called more times than QCBOREncode_OpenArray(), then + QCBOR_ERR_TOO_MANY_CLOSES will be returned when QCBOREncode_Finish() + is called. + + If this is called and it is not an array that is currently open, + QCBOR_ERR_CLOSE_MISMATCH will be returned when QCBOREncode_Finish() + is called. + */ +static void QCBOREncode_CloseArray(QCBOREncodeContext *pCtx); + + +/** + @brief Indicates that the next items added are in a map. + + @param[in] pCtx The context to add to. + + See QCBOREncode_OpenArray() for more information, particularly error + handling. + + CBOR maps are an aggregate type where each item in the map consists + of a label and a value. They are similar to JSON objects. + + The value can be any CBOR type including another map. + + The label can also be any CBOR type, but in practice they are + typically, integers as this gives the most compact output. They might + also be text strings which gives readability and translation to JSON. + + Every QCBOREncode_AddXXX() call has once version that is "InMap" for + adding items to maps with string labels and on that is "InMapN" that + is for adding with integer labels. + + RFC 7049 uses the term "key" instead of "label". + + If you wish to use map labels that are neither integer labels or + text strings, then just call the QCBOREncode_AddXXX() function + explicitly to add the label. Then call it again to add the value. + + See the RFC7049 for a lot more information on creating maps. + */ +static void QCBOREncode_OpenMap(QCBOREncodeContext *pCtx); + +static void QCBOREncode_OpenMapInMap(QCBOREncodeContext *pCtx, const char *szLabel); + +static void QCBOREncode_OpenMapInMapN(QCBOREncodeContext *pCtx, int64_t nLabel); + + + +/** + @brief Close an open map. + + @param[in] pCtx The context to add to. + + The closes a map opened by QCBOREncode_OpenMap(). It reduces nesting + level by one. + + When an error occurs as a result of this call, the encoder records + the error and enters the error state. The error will be returned when + QCBOREncode_Finish() is called. + + If this has been called more times than QCBOREncode_OpenMap(), + then QCBOR_ERR_TOO_MANY_CLOSES will be returned when + QCBOREncode_Finish() is called. + + If this is called and it is not a map that is currently + open, QCBOR_ERR_CLOSE_MISMATCH will be returned when QCBOREncode_Finish() + is called. + */ +static void QCBOREncode_CloseMap(QCBOREncodeContext *pCtx); + + +/** + @brief Indicate start of encoded CBOR to be wrapped in a bstr. + + @param[in] pCtx The context to add to. + + All added encoded items between this call and a call to + QCBOREncode_CloseBstrWrap() will be wrapped in a bstr. They will + appear in the final output as a byte string. That byte string will + contain encoded CBOR. + + The typical use case is for encoded CBOR that is to be + cryptographically hashed, as part of a COSE (RFC 8152) + implementation. This avoids having to encode the items first in one + buffer (e.g., the COSE payload) and then add that buffer as a bstr to + another encoding (e.g. the COSE to-be-signed bytes, the + Sig_structure) potentially saving a lot of memory. + + When constructing cryptographically signed CBOR objects, maps or + arrays, they typically are encoded normally and then wrapped as a + byte string. The COSE standard for example does this. The wrapping is + simply treating the encoded CBOR map as a byte string. + + The stated purpose of this wrapping is to prevent code relaying the + signed data but not verifying it from tampering with the signed data + thus making the signature unverifiable. It is also quite beneficial + for the signature verification code. Standard CBOR parsers usually do + not give access to partially parsed CBOR as would be need to check + the signature of some CBOR. With this wrapping, standard CBOR parsers + can be used to get to all the data needed for a signature + verification. + */ +static void QCBOREncode_BstrWrap(QCBOREncodeContext *pCtx); + +static void QCBOREncode_BstrWrapInMap(QCBOREncodeContext *pCtx, const char *szLabel); + +static void QCBOREncode_BstrWrapInMapN(QCBOREncodeContext *pCtx, int64_t nLabel); + + +/** + @brief Close a wrapping bstr. + + @param[in] pCtx The context to add to. + @param[out] pWrappedCBOR UsefulBufC containing wrapped bytes + + The closes a wrapping bstr opened by QCBOREncode_BstrWrap(). It reduces + nesting level by one. + + A pointer and length of the enclosed encoded CBOR is returned in + *pWrappedCBOR if it is not NULL. The main purpose of this is so this + data can be hashed (e.g., with SHA-256) as part of a COSE (RFC 8152) + implementation. **WARNING**, this pointer and length should be used + right away before any other calls to QCBOREncode_xxxx() as they will + move data around and the pointer and length will no longer be to the + correct encoded CBOR. + + When an error occurs as a result of this call, the encoder records + the error and enters the error state. The error will be returned when + QCBOREncode_Finish() is called. + + If this has been called more times then QCBOREncode_BstrWrap(), + then QCBOR_ERR_TOO_MANY_CLOSES will be returned when + QCBOREncode_Finish() is called. + + If this is called and it is not a wrapping bstr that is currently + open, QCBOR_ERR_CLOSE_MISMATCH will be returned when QCBOREncode_Finish() + is called. + */ +static void QCBOREncode_CloseBstrWrap(QCBOREncodeContext *pCtx, UsefulBufC *pWrappedCBOR); + + +/** + @brief Add some already-encoded CBOR bytes. + + @param[in] pCtx The context to add to. + @param[in] Encoded The already-encoded CBOR to add to the context. + + The encoded CBOR being added must be fully conforming CBOR. It must + be complete with no arrays or maps that are incomplete. While this + encoder doesn't ever produce indefinite lengths, it is OK for the + raw CBOR added here to have indefinite lengths. + + The raw CBOR added here is not checked in anyway. If it is not + conforming or has open arrays or such, the final encoded CBOR + will probably be wrong or not what was intended. + + If the encoded CBOR being added here contains multiple items, they + must be enclosed in a map or array. At the top level the raw + CBOR must be a single data item. + */ +static void QCBOREncode_AddEncoded(QCBOREncodeContext *pCtx, UsefulBufC Encoded); + +static void QCBOREncode_AddEncodedToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Encoded); + +static void QCBOREncode_AddEncodedToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Encoded); + + +/** + @brief Get the encoded result. + + @param[in] pCtx The context to finish encoding with. + @param[out] pEncodedCBOR Pointer and length of encoded CBOR. + + @return + One of the CBOR error codes. + + If this returns success QCBOR_SUCCESS the encoding was a success and + the return length is correct and complete. + + If no buffer was passed to QCBOR_Init(), then only the length and + number of items was computed. The length is in + pEncodedCBOR->Bytes.len. pEncodedCBOR->Bytes.ptr is NULL. + + If a buffer was passed, then pEncodedCBOR->Bytes.ptr is the same as + the buffer passed to QCBOR_Init() and contains the encoded CBOR + and the length is filled in. + + If an error is returned, the buffer may have partially encoded + incorrect CBOR in it and it should not be used. Likewise, the length + may be incorrect and should not be used. + + Note that the error could have occurred in one of the many + QCBOR_AddXXX calls long before QCBOREncode_Finish() was called. This + error handling approach reduces the CBOR implementation size, but makes + debugging a problem a little more difficult. + */ +QCBORError QCBOREncode_Finish(QCBOREncodeContext *pCtx, UsefulBufC *pEncodedCBOR); + + +/** + @brief Get the encoded CBOR and error status. + + @param[in] pCtx The context to finish encoding with. + @param[out] uEncodedLen The length of the encoded or potentially encoded CBOR in bytes. + + @return + One of the CBOR error codes. + + If this returns success QCBOR_SUCCESS the encoding was a success and + the return length is correct and complete. + + If no buffer was passed to QCBOR_Init(), then only the length was + computed. If a buffer was passed, then the encoded CBOR is in the + buffer. + + If an error is returned, the buffer may have partially encoded + incorrect CBOR in it and it should not be used. Likewise, the length + may be incorrect and should not be used. + + Note that the error could have occurred in one of the many + QCBOR_AddXXX calls long before QCBOREncode_Finish() was called. This + error handling reduces the CBOR implementation size, but makes + debugging harder. + */ +QCBORError QCBOREncode_FinishGetSize(QCBOREncodeContext *pCtx, size_t *uEncodedLen); + + + + + + +/** + QCBORDecodeContext is the data type that holds context decoding the + data items for some received CBOR. It is about 100 bytes, so it can go + on the stack. The contents are opaque, and the caller should not + access any internal items. A context may be re used serially as long + as it is re initialized. + */ +typedef struct _QCBORDecodeContext QCBORDecodeContext; + + +/** + Initialize the CBOR decoder context. + + @param[in] pCtx The context to initialize. + @param[in] EncodedCBOR The buffer with CBOR encoded bytes to be decoded. + @param[in] nMode One of QCBOR_DECODE_MODE_xxx + + Initialize context for a pre-order travesal of the encoded CBOR tree. + + Most CBOR decoding can be completed by calling this function to start + and QCBORDecode_GetNext() in a loop. + + If indefinite length strings are to be decoded, then + QCBORDecode_SetMemPool() or QCBORDecode_SetUpAllocator() must be + called to set up a string allocator. + + If tags other than built-in tags are to be recognized, then + QCBORDecode_SetCallerAddedTagMap() must be called. The built-in tags + are those for which a macro of the form CBOR_TAG_XXX is defined. + + Three decoding modes are supported. In normal mode, + QCBOR_DECODE_MODE_NORMAL, maps are decoded and strings and ints are + accepted as map labels. If a label is other than these, the error + QCBOR_ERR_MAP_LABEL_TYPE is returned by QCBORDecode_GetNext(). + + In strings-only mode, QCBOR_DECODE_MODE_MAP_STRINGS_ONLY, only text + strings are accepted for map labels. This lines up with CBOR that + converts to JSON. The error QCBOR_ERR_MAP_LABEL_TYPE is returned by + QCBORDecode_GetNext() if anything but a text string label is + encountered. + + In QCBOR_DECODE_MODE_MAP_AS_ARRAY maps are treated as special arrays. + They will be return with special uDataType QCBOR_TYPE_MAP_AS_ARRAY + and uCount, the number of items, will be double what it would be + for a normal map because the labels are also counted. This mode + is useful for decoding CBOR that has labels that are not + integers or text strings, but the caller must manage much of + the map decoding. + */ +void QCBORDecode_Init(QCBORDecodeContext *pCtx, UsefulBufC EncodedCBOR, QCBORDecodeMode nMode); + + +/** + @brief Set up the MemPool string allocator for indefinite length strings. + + @param[in] pCtx The decode context. + @param[in] MemPool The pointer and length of the memory pool. + @param[in] bAllStrings true means to put even definite length strings in the pool. + + @return error if the MemPool was less than QCBOR_DECODE_MIN_MEM_POOL_SIZE. + + Indefinite length strings (text and byte) cannot be decoded unless + there is a string allocator configured. MemPool is a simple built-in + string allocator that allocates bytes from a memory pool handed to it + by calling this function. The memory pool is just a pointer and + length for some block of memory that is to be used for string + allocation. It can come from the stack, heap or other. + + The memory pool must be QCBOR_DECODE_MIN_MEM_POOL_SIZE plus space for + all the strings allocated. There is no overhead per string allocated + + This memory pool is used for all indefinite length strings that are + text strings or byte strings, including strings used as labels. + + The pointers to strings in QCBORItem will point into the memory pool set + here. They do not need to be individually freed. Just discard the buffer + when they are no longer needed. + + If bAllStrings is set, then the size will be the overhead plus the + space to hold **all** strings, definite and indefinite length, value + or label. The advantage of this is that after the decode is complete, + the original memory holding the encoded CBOR does not need to remain + valid. + + If this function is never called because there is no need to support + indefinite length strings, the MemPool implementation should be + dead-stripped by the loader and not add to code size. + */ +QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pCtx, UsefulBuf MemPool, bool bAllStrings); + + +/** + @brief Sets up a custom string allocator for indefinite length strings + + @param[in] pCtx The decoder context to set up an allocator for + @param[in] pAllocator The string allocator "object" + + See QCBORStringAllocator for the requirements of the string allocator. + + Typically, this is used if the simple MemPool allocator isn't desired. + + A malloc based string allocator can be obtained by calling + QCBOR_DMalloc(). This function is supply separately from qcbor + to keep qcbor smaller and neater. It is in a separate + GitHub repository. + + You can also write your own allocator. Create the allocate, free, + and destroy functions and put pointers to them in a QCBORStringAllocator. + */ +void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pCtx, const QCBORStringAllocator *pAllocator, bool bAllStrings); + + +/** + @brief Configure list of caller selected tags to be recognized + + @param[in] pCtx The decode context. + @param[out] pTagList Structure holding the list of tags to configure + + This is used to tell the decoder about tags beyond those that are + built-in that should be recognized. The built-in tags are those + with macros of the form CBOR_TAG_XXX. + + See description of QCBORTagListIn. + */ +void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pCtx, const QCBORTagListIn *pTagList); + + +/** + @brief Gets the next item (integer, byte string, array...) in pre order traversal of CBOR tree + + @param[in] pCtx The decoder context. + @param[out] pDecodedItem Holds the CBOR item just decoded. + + @return 0 or error. All errors except QCBOR_ERR_TOO_MANY_TAGS + and QCBOR_ERR_STRING_ALLOCATE indicate that the CBOR input + could not be decoded. In most cases + this is because the CBOR is invalid. In a few cases + (QCBOR_ERR_ARRAY_NESTING_TOO_DEEP, QCBOR_ERR_INT_OVERFLOW, + QCBOR_ERR_DATE_OVERFLOW) it is because the CBOR is beyond + the limits of what this implementation can handle. + QCBOR_ERR_NO_STRING_ALLOCATOR indicates CBOR that cannot + be handled unless a string allocator is configured. + QCBOR_ERR_MAP_LABEL_TYPE is in a way a limitation of + this implementation, but can be avoided by decoding + in QCBOR_DECODE_MODE_MAP_AS_ARRAY mode. + + pDecodedItem is filled in with the value parsed. Generally, the + following data is returned in the structure. + + - The data type in uDataType which indicates which member of the val + union the data is in. This decoder figures out the type based on the + CBOR major type, the CBOR "additionalInfo", the CBOR optional tags + and the value of the integer. + + - The value of the item, which might be an integer, a pointer and a + length, the count of items in an array, a floating-point number or + other. + + - The nesting level for maps and arrays. + + - The label for an item in a map, which may be a text or byte string or an integer. + + - The CBOR optional tag or tags. + + See documentation on in the data type QCBORItem for all the details + on what is returned. + + This function also handles arrays and maps. When first encountered a + QCBORItem will be returned with major type CBOR_MAJOR_TYPE_ARRAY or + CBOR_MAJOR_TYPE_ARRAY_MAP. QCBORItem.val.uCount will indicate the number + of Items in the array or map. Typically, an implementation will call + QCBORDecode_GetNext() in a for loop to fetch them all. When decoding + indefinite length maps and arrays, QCBORItem.val.uCount is UINT16_MAX + and uNextNestLevel must be used to know when the end of a map + or array is reached. + + Nesting level 0 is the outside top-most nesting level. For example, in + a CBOR structure with two items, an integer and a byte string only, + both would be at nesting level 0. A CBOR structure with an array + open, an integer and a byte string, would have the integer and byte + string as nesting level 1. + + Here is an example of how the nesting level is reported with no arrays + or maps at all + + @verbatim + CBOR Structure Nesting Level + Integer 0 + Byte String 0 + @endverbatim + + Here is an example of how the nesting level is reported with an a simple + array and some top-level items. + + @verbatim + Integer 0 + Array (with 2 items) 0 + Byte String 1 + Byte string 1 + Integer 0 + @endverbatim + + + Here's a more complex example + @verbatim + + Map with 2 items 0 + Text string 1 + Array with 3 integers 1 + integer 2 + integer 2 + integer 2 + text string 1 + byte string 1 + @endverbatim + + In QCBORItem, uNextNestLevel is the nesting level for the next call + to QCBORDecode_GetNext(). It indicates if any maps or arrays were closed + out during the processing of the just-fecthed QCBORItem. This processing + includes a look-ahead for any breaks that close out indefinite length + arrays or maps. This value is needed to be able to understand the + hierarchical structure. If uNextNestLevel is not equal to uNestLevel + the end of the current map or array has been encountered. This + works the same for both definite and indefinite length arrays. + + Most uses of this decoder will not need to do anything extra for + tag handling. The built-in tags, those with a macro of the form + CBOR_TAG_XXXX, will be enough. + + If tags beyond built-in tags are to be recognized, they must be + configured by calling QCBORDecode_SetCallerConfiguredTags(). If + a tag is not recognized it is silently ignored. + + Several tagged types are automatically recognized and decoded and + returned in their decoded form. + + To find out if a QCBORItem was tagged with a particular tag + call QCBORDecode_IsTagged(). This works only for built-in + tags and caller-configured tags. + + To get the full list of tags on an Item without having to + pre-configure any predetermined list of tags use + QCBORDecode_GetNextWithTags(). + */ +QCBORError QCBORDecode_GetNext(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem); + + +/** + @brief Gets the next item including full list of tags for item + + @param[in] pCtx The decoder context. + @param[out] pDecodedItem Holds the CBOR item just decoded. + @param[in,out] pTagList On input array to put tags in; on output the tags on this item. + + @return 0 or error. + + This works the same as QCBORDecode_GetNext() except that it also returns + the full list of tags for the data item. This function should only + be needed when parsing CBOR to print it out or convert it to some other + format. It should not be needed in an actual CBOR protocol implementation. + + Tags will be returned here whether or not they are in the built-in or + caller-configured tag lists. + + CBOR has no upper bound of limit on the number of tags that can be + associated with a data item. In practice the number of tags on an item + will usually be small, perhaps less than five. This will return an error + if the array in pTagList is too small to hold all the tags for an item. + + (This function is separate from QCBORDecode_GetNext() so as to not have to + make QCBORItem large enough to be able to hold a full list of tags. Even a list of + five tags would nearly double its size because tags can be a uint64_t). + */ +QCBORError QCBORDecode_GetNextWithTags(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem, QCBORTagListOut *pTagList); + + +/** + @brief Determine if a CBOR item was tagged with a particular tag + + @param[in] pCtx The decoder context. + @param[in] pItem The CBOR item to check + @param[in] uTag The tag to check + + @return 1 if it was tagged, 0 if not + + QCBORDecode_GetNext() processes tags by looking them up + in two lists and setting a bit corresponding to the tag + in uTagBits in the QCBORItem. To find out if a + QCBORItem was tagged with a particular tag, call + this function. It handles the mapping between + the two lists of tags and the bits set for it. + + The first tag list is the built-in tags, those + with a macro of the form CBOR_TAG_XXX in this + header file. There are up to 48 of these, + corresponding to the lower 48 tag bits. + + The other optional tag list is the ones + the caller configured using QCBORDecode_SetCallerConfiguredTagList() + There are QCBOR_MAX_CUSTOM_TAGS (16) of these corresponding to the + upper 16 tag bits. + + See also QCBORDecode_GetTags() and QCBORDecode_GetNextWithTags(). + */ +int QCBORDecode_IsTagged(QCBORDecodeContext *pCtx, const QCBORItem *pItem, uint64_t uTag); + + +/** + Check whether all the bytes have been decoded and maps and arrays closed. + + @param[in] pCtx The context to check + + @return QCBOR_SUCCESS or error + + This tells you if all the bytes given to QCBORDecode_Init() have + been consumed and whether all maps and arrays were closed. + The decode is considered to be incorrect or incomplete if not + and an error will be returned. + */ +QCBORError QCBORDecode_Finish(QCBORDecodeContext *pCtx); + + + + +/** + Convert int64_t to smaller int's safely + + @param [in] src An int64_t + @param [out] dest A smaller sized int to convert to + + @return 0 on success -1 if not + + When decoding an integer, the CBOR decoder will return the value as an + int64_t unless the integer is in the range of INT64_MAX and + UINT64_MAX. That is, unless the value is so large that it can only be + represented as a uint64_t, it will be an int64_t. + + CBOR itself doesn't size the individual integers it carries at + all. The only limits it puts on the major integer types is that they + are 8 bytes or less in length. Then encoders like this one use the + smallest number of 1, 2, 4 or 8 bytes to represent the integer based + on its value. There is thus no notion that one data item in CBOR is + an 1 byte integer and another is a 4 byte integer. + + The interface to this CBOR encoder only uses 64-bit integers. Some + CBOR protocols or implementations of CBOR protocols may not want to + work with something smaller than a 64-bit integer. Perhaps an array + of 1000 integers needs to be sent and none has a value larger than + 50,000 and are represented as uint16_t. + + The sending / encoding side is easy. Integers are temporarily widened + to 64-bits as a parameter passing through QCBOREncode_AddInt64() and + encoded in the smallest way possible for their value, possibly in + less than an uint16_t. + + On the decoding side the integers will be returned at int64_t even if + they are small and were represented by only 1 or 2 bytes in the + encoded CBOR. The functions here will convert integers to a small + representation with an overflow check. + + (The decoder could have support 8 different integer types and + represented the integer with the smallest type automatically, but + this would have made the decoder more complex and code calling the + decoder more complex in most use cases. In most use cases on 64-bit + machines it is no burden to carry around even small integers as + 64-bit values). + */ +static inline int QCBOR_Int64ToInt32(int64_t src, int32_t *dest) +{ + if(src > INT32_MAX || src < INT32_MIN) { + return -1; + } else { + *dest = (int32_t) src; + } + return 0; +} + +static inline int QCBOR_Int64ToInt16(int64_t src, int16_t *dest) +{ + if(src > INT16_MAX || src < INT16_MIN) { + return -1; + } else { + *dest = (int16_t) src; + } + return 0; +} + +static inline int QCBOR_Int64ToInt8(int64_t src, int8_t *dest) +{ + if(src > INT8_MAX || src < INT8_MIN) { + return -1; + } else { + *dest = (int8_t) src; + } + return 0; +} + +static inline int QCBOR_Int64ToUInt32(int64_t src, uint32_t *dest) +{ + if(src > UINT32_MAX || src < 0) { + return -1; + } else { + *dest = (uint32_t) src; + } + return 0; +} + +static inline int QCBOR_Int64UToInt16(int64_t src, uint16_t *dest) +{ + if(src > UINT16_MAX || src < 0) { + return -1; + } else { + *dest = (uint16_t) src; + } + return 0; +} + +static inline int QCBOR_Int64ToUInt8(int64_t src, uint8_t *dest) +{ + if(src > UINT8_MAX || src < 0) { + return -1; + } else { + *dest = (uint8_t) src; + } + return 0; +} + +static inline int QCBOR_Int64ToUInt64(int64_t src, uint64_t *dest) +{ + if(src > 0) { + return -1; + } else { + *dest = (uint64_t) src; + } + return 0; +} + + + + + +/* =========================================================================== + BEGINNING OF PRIVATE INLINE IMPLEMENTATION + + =========================================================================== */ + +/** + @brief Semi-private method to add a buffer full of bytes to encoded output + + @param[in] pCtx The encoding context to add the integer to. + @param[in] uMajorType The CBOR major type of the bytes. + @param[in] Bytes The bytes to add. + + Use QCBOREncode_AddText() or QCBOREncode_AddBytes() or + QCBOREncode_AddEncoded() instead. They are inline functions + that call this and supply the correct major type. This function + is public to make the inline functions work to keep the overall + code size down and because the C language has no way to make + it private. + + If this is called the major type should be CBOR_MAJOR_TYPE_TEXT_STRING, + CBOR_MAJOR_TYPE_BYTE_STRING or CBOR_MAJOR_NONE_TYPE_RAW. The last + one is special for adding already-encoded CBOR. + */ +void QCBOREncode_AddBuffer(QCBOREncodeContext *pCtx, uint8_t uMajorType, UsefulBufC Bytes); + + +/** + @brief Semi-private method to open a map, array or bstr wrapped CBOR + + @param[in] pCtx The context to add to. + @param[in] uMajorType The major CBOR type to close + + Call QCBOREncode_OpenArray(), QCBOREncode_OpenMap() or + QCBOREncode_BstrWrap() instead of this. + */ +void QCBOREncode_OpenMapOrArray(QCBOREncodeContext *pCtx, uint8_t uMajorType); + + +/** + @brief Semi-private method to close a map, array or bstr wrapped CBOR + + @param[in] pCtx The context to add to. + @param[in] uMajorType The major CBOR type to close + @param[out] pWrappedCBOR UsefulBufC containing wrapped bytes + + Call QCBOREncode_CloseArray(), QCBOREncode_CloseMap() or + QCBOREncode_CloseBstrWrap() instead of this. + */ +void QCBOREncode_CloseMapOrArray(QCBOREncodeContext *pCtx, uint8_t uMajorType, UsefulBufC *pWrappedCBOR); + + +/** + @brief Semi-private method to add simple types. + + @param[in] pCtx The encoding context to add the simple value to. + @param[in] uSize Minimum encoding size for uNum. Usually 0. + @param[in] uNum One of CBOR_SIMPLEV_FALSE through _UNDEF or other. + + This is used to add simple types like true and false. + + Call QCBOREncode_AddBool(), QCBOREncode_AddNULL(), QCBOREncode_AddUndef() + instead of this. + + This function can add simple values that are not defined by CBOR yet. This expansion + point in CBOR should not be used unless they are standardized. + + Error handling is the same as QCBOREncode_AddInt64(). + */ +void QCBOREncode_AddType7(QCBOREncodeContext *pCtx, size_t uSize, uint64_t uNum); + + +static inline void QCBOREncode_AddInt64ToMap(QCBOREncodeContext *pCtx, const char *szLabel, int64_t uNum) +{ + QCBOREncode_AddBuffer(pCtx, CBOR_MAJOR_TYPE_TEXT_STRING, UsefulBuf_FromSZ(szLabel)); // AddSZString not defined yet + QCBOREncode_AddInt64(pCtx, uNum); +} + +static inline void QCBOREncode_AddInt64ToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, int64_t uNum) +{ + QCBOREncode_AddInt64(pCtx, nLabel); + QCBOREncode_AddInt64(pCtx, uNum); +} + + +static inline void QCBOREncode_AddUInt64ToMap(QCBOREncodeContext *pCtx, const char *szLabel, uint64_t uNum) +{ + QCBOREncode_AddBuffer(pCtx, CBOR_MAJOR_TYPE_TEXT_STRING, UsefulBuf_FromSZ(szLabel)); // AddSZString not defined yet + QCBOREncode_AddUInt64(pCtx, uNum); +} + +static inline void QCBOREncode_AddUInt64ToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, uint64_t uNum) +{ + QCBOREncode_AddInt64(pCtx, nLabel); + QCBOREncode_AddUInt64(pCtx, uNum); +} + + +static inline void QCBOREncode_AddText(QCBOREncodeContext *pCtx, UsefulBufC Text) +{ + QCBOREncode_AddBuffer(pCtx, CBOR_MAJOR_TYPE_TEXT_STRING, Text); +} + +static inline void QCBOREncode_AddTextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Text) +{ + QCBOREncode_AddText(pCtx, UsefulBuf_FromSZ(szLabel)); // AddSZString not defined yet + QCBOREncode_AddText(pCtx, Text); +} + +static inline void QCBOREncode_AddTextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Text) +{ + QCBOREncode_AddInt64(pCtx, nLabel); + QCBOREncode_AddText(pCtx, Text); +} + + +inline static void QCBOREncode_AddSZString(QCBOREncodeContext *pCtx, const char *szString) +{ + QCBOREncode_AddText(pCtx, UsefulBuf_FromSZ(szString)); +} + +static inline void QCBOREncode_AddSZStringToMap(QCBOREncodeContext *pCtx, const char *szLabel, const char *szString) +{ + QCBOREncode_AddSZString(pCtx, szLabel); + QCBOREncode_AddSZString(pCtx, szString); +} + +static inline void QCBOREncode_AddSZStringToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, const char *szString) +{ + QCBOREncode_AddInt64(pCtx, nLabel); + QCBOREncode_AddSZString(pCtx, szString); +} + + +static inline void QCBOREncode_AddDoubleToMap(QCBOREncodeContext *pCtx, const char *szLabel, double dNum) +{ + QCBOREncode_AddSZString(pCtx, szLabel); + QCBOREncode_AddDouble(pCtx, dNum); +} + +static inline void QCBOREncode_AddDoubleToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, double dNum) +{ + QCBOREncode_AddInt64(pCtx, nLabel); + QCBOREncode_AddDouble(pCtx, dNum); +} + + +static inline void QCBOREncode_AddDateEpoch(QCBOREncodeContext *pCtx, int64_t date) +{ + QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_EPOCH); + QCBOREncode_AddInt64(pCtx, date); +} + +static inline void QCBOREncode_AddDateEpochToMap(QCBOREncodeContext *pCtx, const char *szLabel, int64_t date) +{ + QCBOREncode_AddSZString(pCtx, szLabel); + QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_EPOCH); + QCBOREncode_AddInt64(pCtx, date); +} + +static inline void QCBOREncode_AddDateEpochToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, int64_t date) +{ + QCBOREncode_AddInt64(pCtx, nLabel); + QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_EPOCH); + QCBOREncode_AddInt64(pCtx, date); +} + + +static inline void QCBOREncode_AddBytes(QCBOREncodeContext *pCtx, UsefulBufC Bytes) +{ + QCBOREncode_AddBuffer(pCtx, CBOR_MAJOR_TYPE_BYTE_STRING, Bytes); +} + +static inline void QCBOREncode_AddBytesToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes) +{ + QCBOREncode_AddSZString(pCtx, szLabel); + QCBOREncode_AddBytes(pCtx, Bytes); +} + +static inline void QCBOREncode_AddBytesToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes) +{ + QCBOREncode_AddInt64(pCtx, nLabel); + QCBOREncode_AddBytes(pCtx, Bytes); +} + + +static inline void QCBOREncode_AddBinaryUUID(QCBOREncodeContext *pCtx, UsefulBufC Bytes) +{ + QCBOREncode_AddTag(pCtx, CBOR_TAG_BIN_UUID); + QCBOREncode_AddBytes(pCtx, Bytes); +} + +static inline void QCBOREncode_AddBinaryUUIDToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes) +{ + QCBOREncode_AddSZString(pCtx, szLabel); + QCBOREncode_AddTag(pCtx, CBOR_TAG_BIN_UUID); + QCBOREncode_AddBytes(pCtx, Bytes); +} + +static inline void QCBOREncode_AddBinaryUUIDToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes) +{ + QCBOREncode_AddInt64(pCtx, nLabel); + QCBOREncode_AddTag(pCtx, CBOR_TAG_BIN_UUID); + QCBOREncode_AddBytes(pCtx, Bytes); +} + + +static inline void QCBOREncode_AddPositiveBignum(QCBOREncodeContext *pCtx, UsefulBufC Bytes) +{ + QCBOREncode_AddTag(pCtx, CBOR_TAG_POS_BIGNUM); + QCBOREncode_AddBytes(pCtx, Bytes); +} + +static inline void QCBOREncode_AddPositiveBignumToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes) +{ + QCBOREncode_AddSZString(pCtx, szLabel); + QCBOREncode_AddTag(pCtx, CBOR_TAG_POS_BIGNUM); + QCBOREncode_AddBytes(pCtx, Bytes); +} + +static inline void QCBOREncode_AddPositiveBignumToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes) +{ + QCBOREncode_AddInt64(pCtx, nLabel); + QCBOREncode_AddTag(pCtx, CBOR_TAG_POS_BIGNUM); + QCBOREncode_AddBytes(pCtx, Bytes); +} + + +static inline void QCBOREncode_AddNegativeBignum(QCBOREncodeContext *pCtx, UsefulBufC Bytes) +{ + QCBOREncode_AddTag(pCtx, CBOR_TAG_NEG_BIGNUM); + QCBOREncode_AddBytes(pCtx, Bytes); +} + +static inline void QCBOREncode_AddNegativeBignumToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes) +{ + QCBOREncode_AddSZString(pCtx, szLabel); + QCBOREncode_AddTag(pCtx, CBOR_TAG_NEG_BIGNUM); + QCBOREncode_AddBytes(pCtx, Bytes); +} + +static inline void QCBOREncode_AddNegativeBignumToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes) +{ + QCBOREncode_AddInt64(pCtx, nLabel); + QCBOREncode_AddTag(pCtx, CBOR_TAG_NEG_BIGNUM); + QCBOREncode_AddBytes(pCtx, Bytes); +} + + +static inline void QCBOREncode_AddURI(QCBOREncodeContext *pCtx, UsefulBufC URI) +{ + QCBOREncode_AddTag(pCtx, CBOR_TAG_URI); + QCBOREncode_AddText(pCtx, URI); +} + +static inline void QCBOREncode_AddURIToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC URI) +{ + QCBOREncode_AddSZString(pCtx, szLabel); + QCBOREncode_AddTag(pCtx, CBOR_TAG_URI); + QCBOREncode_AddText(pCtx, URI); +} + +static inline void QCBOREncode_AddURIToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC URI) +{ + QCBOREncode_AddInt64(pCtx, nLabel); + QCBOREncode_AddTag(pCtx, CBOR_TAG_URI); + QCBOREncode_AddText(pCtx, URI); +} + + + +static inline void QCBOREncode_AddB64Text(QCBOREncodeContext *pCtx, UsefulBufC B64Text) +{ + QCBOREncode_AddTag(pCtx, CBOR_TAG_B64); + QCBOREncode_AddText(pCtx, B64Text); +} + +static inline void QCBOREncode_AddB64TextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC B64Text) +{ + QCBOREncode_AddSZString(pCtx, szLabel); + QCBOREncode_AddTag(pCtx, CBOR_TAG_B64); + QCBOREncode_AddText(pCtx, B64Text); +} + +static inline void QCBOREncode_AddB64TextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC B64Text) +{ + QCBOREncode_AddInt64(pCtx, nLabel); + QCBOREncode_AddTag(pCtx, CBOR_TAG_B64); + QCBOREncode_AddText(pCtx, B64Text); +} + + +static inline void QCBOREncode_AddB64URLText(QCBOREncodeContext *pCtx, UsefulBufC B64Text) +{ + QCBOREncode_AddTag(pCtx, CBOR_TAG_B64URL); + QCBOREncode_AddText(pCtx, B64Text); +} + +static inline void QCBOREncode_AddB64URLTextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC B64Text) +{ + QCBOREncode_AddSZString(pCtx, szLabel); + QCBOREncode_AddTag(pCtx, CBOR_TAG_B64URL); + QCBOREncode_AddText(pCtx, B64Text); +} + +static inline void QCBOREncode_AddB64URLTextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC B64Text) +{ + QCBOREncode_AddInt64(pCtx, nLabel); + QCBOREncode_AddTag(pCtx, CBOR_TAG_B64URL); + QCBOREncode_AddText(pCtx, B64Text); +} + + +static inline void QCBOREncode_AddRegex(QCBOREncodeContext *pCtx, UsefulBufC Bytes) +{ + QCBOREncode_AddTag(pCtx, CBOR_TAG_REGEX); + QCBOREncode_AddText(pCtx, Bytes); +} + +static inline void QCBOREncode_AddRegexToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes) +{ + QCBOREncode_AddSZString(pCtx, szLabel); + QCBOREncode_AddTag(pCtx, CBOR_TAG_REGEX); + QCBOREncode_AddText(pCtx, Bytes); +} + +static inline void QCBOREncode_AddRegexToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes) +{ + QCBOREncode_AddInt64(pCtx, nLabel); + QCBOREncode_AddTag(pCtx, CBOR_TAG_REGEX); + QCBOREncode_AddText(pCtx, Bytes); +} + + +static inline void QCBOREncode_AddMIMEData(QCBOREncodeContext *pCtx, UsefulBufC MIMEData) +{ + QCBOREncode_AddTag(pCtx, CBOR_TAG_MIME); + QCBOREncode_AddText(pCtx, MIMEData); +} + +static inline void QCBOREncode_AddMIMEDataToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC MIMEData) +{ + QCBOREncode_AddSZString(pCtx, szLabel); + QCBOREncode_AddTag(pCtx, CBOR_TAG_MIME); + QCBOREncode_AddText(pCtx, MIMEData); +} + +static inline void QCBOREncode_AddMIMEDataToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC MIMEData) +{ + QCBOREncode_AddInt64(pCtx, nLabel); + QCBOREncode_AddTag(pCtx, CBOR_TAG_MIME); + QCBOREncode_AddText(pCtx, MIMEData); +} + + +static inline void QCBOREncode_AddDateString(QCBOREncodeContext *pCtx, const char *szDate) +{ + QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_STRING); + QCBOREncode_AddSZString(pCtx, szDate); +} + +static inline void QCBOREncode_AddDateStringToMap(QCBOREncodeContext *pCtx, const char *szLabel, const char *szDate) +{ + QCBOREncode_AddSZString(pCtx, szLabel); + QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_STRING); + QCBOREncode_AddSZString(pCtx, szDate); +} + +static inline void QCBOREncode_AddDateStringToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, const char *szDate) +{ + QCBOREncode_AddInt64(pCtx, nLabel); + QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_STRING); + QCBOREncode_AddSZString(pCtx, szDate); +} + + +static inline void QCBOREncode_AddSimple(QCBOREncodeContext *pCtx, uint64_t uNum) +{ + QCBOREncode_AddType7(pCtx, 0, uNum); +} + +static inline void QCBOREncode_AddSimpleToMap(QCBOREncodeContext *pCtx, const char *szLabel, uint8_t uSimple) +{ + QCBOREncode_AddSZString(pCtx, szLabel); + QCBOREncode_AddSimple(pCtx, uSimple); +} + +static inline void QCBOREncode_AddSimpleToMapN(QCBOREncodeContext *pCtx, int nLabel, uint8_t uSimple) +{ + QCBOREncode_AddInt64(pCtx, nLabel); + QCBOREncode_AddSimple(pCtx, uSimple); +} + + +static inline void QCBOREncode_AddBool(QCBOREncodeContext *pCtx, bool b) +{ + uint8_t uSimple = CBOR_SIMPLEV_FALSE; + if(b) { + uSimple = CBOR_SIMPLEV_TRUE; + } + QCBOREncode_AddSimple(pCtx, uSimple); +} + +static inline void QCBOREncode_AddBoolToMap(QCBOREncodeContext *pCtx, const char *szLabel, bool b) +{ + QCBOREncode_AddSZString(pCtx, szLabel); + QCBOREncode_AddBool(pCtx, b); +} + +static inline void QCBOREncode_AddBoolToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, bool b) +{ + QCBOREncode_AddInt64(pCtx, nLabel); + QCBOREncode_AddBool(pCtx, b); +} + + +static inline void QCBOREncode_AddNULL(QCBOREncodeContext *pCtx) +{ + QCBOREncode_AddSimple(pCtx, CBOR_SIMPLEV_NULL); +} + +static inline void QCBOREncode_AddNULLToMap(QCBOREncodeContext *pCtx, const char *szLabel) +{ + QCBOREncode_AddSZString(pCtx, szLabel); + QCBOREncode_AddNULL(pCtx); +} + +static inline void QCBOREncode_AddNULLToMapN(QCBOREncodeContext *pCtx, int64_t nLabel) +{ + QCBOREncode_AddInt64(pCtx, nLabel); + QCBOREncode_AddNULL(pCtx); +} + + +static inline void QCBOREncode_AddUndef(QCBOREncodeContext *pCtx) +{ + QCBOREncode_AddSimple(pCtx, CBOR_SIMPLEV_UNDEF); +} + +static inline void QCBOREncode_AddUndefToMap(QCBOREncodeContext *pCtx, const char *szLabel) +{ + QCBOREncode_AddSZString(pCtx, szLabel); + QCBOREncode_AddUndef(pCtx); +} + +static inline void QCBOREncode_AddUndefToMapN(QCBOREncodeContext *pCtx, int64_t nLabel) +{ + QCBOREncode_AddInt64(pCtx, nLabel); + QCBOREncode_AddUndef(pCtx); +} + + +static inline void QCBOREncode_OpenArray(QCBOREncodeContext *pCtx) +{ + QCBOREncode_OpenMapOrArray(pCtx, CBOR_MAJOR_TYPE_ARRAY); +} + +static inline void QCBOREncode_OpenArrayInMap(QCBOREncodeContext *pCtx, const char *szLabel) +{ + QCBOREncode_AddSZString(pCtx, szLabel); + QCBOREncode_OpenArray(pCtx); +} + +static inline void QCBOREncode_OpenArrayInMapN(QCBOREncodeContext *pCtx, int64_t nLabel) +{ + QCBOREncode_AddInt64(pCtx, nLabel); + QCBOREncode_OpenArray(pCtx); +} + +static inline void QCBOREncode_CloseArray(QCBOREncodeContext *pCtx) +{ + QCBOREncode_CloseMapOrArray(pCtx, CBOR_MAJOR_TYPE_ARRAY, NULL); +} + + +static inline void QCBOREncode_OpenMap(QCBOREncodeContext *pCtx) +{ + QCBOREncode_OpenMapOrArray(pCtx, CBOR_MAJOR_TYPE_MAP); +} + +static inline void QCBOREncode_OpenMapInMap(QCBOREncodeContext *pCtx, const char *szLabel) +{ + QCBOREncode_AddSZString(pCtx, szLabel); + QCBOREncode_OpenMap(pCtx); +} + +static inline void QCBOREncode_OpenMapInMapN(QCBOREncodeContext *pCtx, int64_t nLabel) +{ + QCBOREncode_AddInt64(pCtx, nLabel); + QCBOREncode_OpenMap(pCtx); +} + +static inline void QCBOREncode_CloseMap(QCBOREncodeContext *pCtx) +{ + QCBOREncode_CloseMapOrArray(pCtx, CBOR_MAJOR_TYPE_MAP, NULL); +} + + +static inline void QCBOREncode_BstrWrap(QCBOREncodeContext *pCtx) +{ + QCBOREncode_OpenMapOrArray(pCtx, CBOR_MAJOR_TYPE_BYTE_STRING); +} + +static inline void QCBOREncode_BstrWrapInMap(QCBOREncodeContext *pCtx, const char *szLabel) +{ + QCBOREncode_AddSZString(pCtx, szLabel); + QCBOREncode_BstrWrap(pCtx); +} + +static inline void QCBOREncode_BstrWrapInMapN(QCBOREncodeContext *pCtx, int64_t nLabel) +{ + QCBOREncode_AddInt64(pCtx, nLabel); + QCBOREncode_BstrWrap(pCtx); +} + +static inline void QCBOREncode_CloseBstrWrap(QCBOREncodeContext *pCtx, UsefulBufC *pWrappedCBOR) +{ + QCBOREncode_CloseMapOrArray(pCtx, CBOR_MAJOR_TYPE_BYTE_STRING, pWrappedCBOR); +} + + +static inline void QCBOREncode_AddEncoded(QCBOREncodeContext *pCtx, UsefulBufC Encoded) +{ + QCBOREncode_AddBuffer(pCtx, CBOR_MAJOR_NONE_TYPE_RAW, Encoded); +} + +static inline void QCBOREncode_AddEncodedToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Encoded) +{ + QCBOREncode_AddSZString(pCtx, szLabel); + QCBOREncode_AddEncoded(pCtx, Encoded); +} + +static inline void QCBOREncode_AddEncodedToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Encoded) +{ + QCBOREncode_AddInt64(pCtx, nLabel); + QCBOREncode_AddEncoded(pCtx, Encoded); +} + + +/* =========================================================================== + END OF PRIVATE INLINE IMPLEMENTATION + + =========================================================================== */ + +#endif /* defined(__QCBOR__qcbor__) */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/inc/useful_buf.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/inc/useful_buf.h new file mode 100644 index 0000000..dcb88b8 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/inc/useful_buf.h @@ -0,0 +1,143 @@ +/* + * useful_buf.h + * + * Copyright 2019, Laurence Lundblade + * + * SPDX-License-Identifier: BSD-3-Clause + * + * See BSD-3-Clause license in README.mdE. + */ + + +#ifndef __USEFUL_BUF_H__ +#define __USEFUL_BUF_H__ + +#include "UsefulBuf.h" + + +/** + * \file useful_buf.h + * + * \brief This is a TF-M coding style version of UsefulBuf. + * See UsefulBuf for documentation of these functions. + */ + + +#define NULL_USEFUL_BUF_C NULLUsefulBufC + +#define NULL_USEFUL_BUF NULLUsefulBuf + + +static inline int useful_buf_c_is_null(struct useful_buf_c in) +{ + return UsefulBuf_IsNULLC(in); +} + + +static inline int useful_buf_is_null(struct useful_buf in) +{ + return UsefulBuf_IsNULL(in); +} + + +static inline int useful_buf_c_is_empty(struct useful_buf_c in) +{ + return UsefulBuf_IsEmptyC(in); +} + +static inline int useful_buf_is_empty(struct useful_buf in) +{ + return UsefulBuf_IsEmpty(in); +} + + +static inline int useful_buf_is_null_or_empty(struct useful_buf in) +{ + return UsefulBuf_IsNULLOrEmpty(in); +} + + +static inline int useful_buf_c_is_null_or_empty(struct useful_buf_c in) +{ + return UsefulBuf_IsNULLOrEmptyC(in); +} + + +static inline struct useful_buf useful_buf_unconst(struct useful_buf_c in) +{ + return UsefulBuf_Unconst(in); +} + +#define USEFUL_BUF_FROM_SZ_LITERAL UsefulBuf_FROM_SZ_LITERAL + +#define USEFUL_BUF_FROM_BYTE_ARRAY_LITERAL UsefulBuf_FROM_BYTE_ARRAY_LITERAL + +#define USEFUL_BUF_MAKE_STACK_UB UsefulBuf_MAKE_STACK_UB + +#define USEFUL_BUF_FROM_BYTE_ARRAY UsefulBuf_FROM_BYTE_ARRAY + + +static inline struct useful_buf_c useful_buf_from_sz(const char *string) +{ + return UsefulBuf_FromSZ(string); +} + +static inline struct +useful_buf_c useful_buf_copy_offset(struct useful_buf dest, + size_t offset, + struct useful_buf_c src) +{ + return UsefulBuf_CopyOffset(dest, offset, src); +} + + + +static inline struct useful_buf_c useful_buf_copy(struct useful_buf dest, + struct useful_buf_c src) +{ + return UsefulBuf_Copy(dest, src); +} + + +static inline struct useful_buf_c useful_buf_set(struct useful_buf dest, + uint8_t value) +{ + return UsefulBuf_Set(dest, value); +} + + +static inline struct useful_buf_c useful_buf_copy_ptr(struct useful_buf dest, + const void *ptr, + size_t len) +{ + return UsefulBuf_CopyPtr(dest, ptr, len); +} + + +static inline struct useful_buf_c useful_buf_head(struct useful_buf_c buf, + size_t amount) +{ + return UsefulBuf_Head(buf, amount); +} + +static inline struct useful_buf_c useful_buf_tail(struct useful_buf_c buf, + size_t amount) +{ + return UsefulBuf_Tail(buf, amount); +} + +static inline int useful_buf_compare(const struct useful_buf_c buf1, + const struct useful_buf_c buf2) +{ + return UsefulBuf_Compare(buf1, buf2); +} + +static inline size_t +useful_buf_find_bytes(const struct useful_buf_c bytes_to_search, + const struct useful_buf_c bytes_to_find) +{ + return UsefulBuf_FindBytes(bytes_to_search, bytes_to_find); +} + + +#endif /* __USEFUL_BUF_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/src/UsefulBuf.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/src/UsefulBuf.c new file mode 100644 index 0000000..0e69ff4 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/src/UsefulBuf.c @@ -0,0 +1,329 @@ +/*============================================================================== + Copyright (c) 2016-2018, The Linux Foundation. + Copyright (c) 2018-2019, Laurence Lundblade. + All rights reserved. + SPDX-License-Identifier: BSD-3-Clause + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors, nor the name "Laurence Lundblade" may be used to + endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ==============================================================================*/ + +/*=================================================================================== + FILE: UsefulBuf.c + + DESCRIPTION: General purpose input and output buffers + + EDIT HISTORY FOR FILE: + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + when who what, where, why + -------- ---- --------------------------------------------------- + 09/07/17 llundbla Fix critical bug in UsefulBuf_Find() -- a read off + the end of memory when the bytes to find is longer + than the bytes to search. + 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected comparison + for < or > for unequal length buffers. Added + UsefulBuf_Set() function. + 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst + 11/13/16 llundbla Initial Version. + + =====================================================================================*/ + +#include "UsefulBuf.h" + +#define USEFUL_OUT_BUF_MAGIC (0x0B0F) // used to catch use of uninitialized or corrupted UOBs + + +/* + Public function -- see UsefulBuf.h + */ +UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src) +{ + // Do this with subtraction so it doesn't give erroneous result if uOffset + Src.len overflows + if(uOffset > Dest.len || Src.len > Dest.len - uOffset) { // uOffset + Src.len > Dest.len + return NULLUsefulBufC; + } + + memcpy((uint8_t *)Dest.ptr + uOffset, Src.ptr, Src.len); + + return (UsefulBufC){Dest.ptr, Src.len + uOffset}; +} + + +/* + Public function -- see UsefulBuf.h + */ +int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2) +{ + // use the comparisons rather than subtracting lengths to + // return an int instead of a size_t + if(UB1.len < UB2.len) { + return -1; + } else if (UB1.len > UB2.len) { + return 1; + } // else UB1.len == UB2.len + + return memcmp(UB1.ptr, UB2.ptr, UB1.len); +} + + + +/* + Public function -- see UsefulBuf.h + */ +size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind) +{ + if(BytesToSearch.len < BytesToFind.len) { + return SIZE_MAX; + } + + for(size_t uPos = 0; uPos <= BytesToSearch.len - BytesToFind.len; uPos++) { + if(!UsefulBuf_Compare((UsefulBufC){((uint8_t *)BytesToSearch.ptr) + uPos, BytesToFind.len}, BytesToFind)) { + return uPos; + } + } + + return SIZE_MAX; +} + + +/* + Public function -- see UsefulBuf.h + + Code Reviewers: THIS FUNCTION DOES POINTER MATH + */ +void UsefulOutBuf_Init(UsefulOutBuf *me, UsefulBuf Storage) +{ + me->magic = USEFUL_OUT_BUF_MAGIC; + UsefulOutBuf_Reset(me); + me->UB = Storage; + +#if 0 + // This check is off by default. + + // The following check fails on ThreadX + + // Sanity check on the pointer and size to be sure we are not + // passed a buffer that goes off the end of the address space. + // Given this test, we know that all unsigned lengths less than + // me->size are valid and won't wrap in any pointer additions + // based off of pStorage in the rest of this code. + const uintptr_t ptrM = UINTPTR_MAX - Storage.len; + if(Storage.ptr && (uintptr_t)Storage.ptr > ptrM) // Check #0 + me->err = 1; +#endif +} + + + +/* + Public function -- see UsefulBuf.h + + The core of UsefulOutBuf -- put some bytes in the buffer without writing off the end of it. + + Code Reviewers: THIS FUNCTION DOES POINTER MATH + + This function inserts the source buffer, NewData, into the destination buffer, me->UB.ptr. + + Destination is represented as: + me->UB.ptr -- start of the buffer + me->UB.len -- size of the buffer UB.ptr + me->data_len -- length of value data in UB + + Source is data: + NewData.ptr -- start of source buffer + NewData.len -- length of source buffer + + Insertion point: + uInsertionPos. + + Steps: + + 0. Corruption checks on UsefulOutBuf + + 1. Figure out if the new data will fit or not + + 2. Is insertion position in the range of valid data? + + 3. If insertion point is not at the end, slide data to the right of the insertion point to the right + + 4. Put the new data in at the insertion position. + + */ +void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *me, UsefulBufC NewData, size_t uInsertionPos) +{ + if(me->err) { + // Already in error state. + return; + } + + /* 0. Sanity check the UsefulOutBuf structure */ + // A "counter measure". If magic number is not the right number it + // probably means me was not initialized or it was corrupted. Attackers + // can defeat this, but it is a hurdle and does good with very + // little code. + if(me->magic != USEFUL_OUT_BUF_MAGIC) { + me->err = 1; + return; // Magic number is wrong due to uninitalization or corrption + } + + // Make sure valid data is less than buffer size. This would only occur + // if there was corruption of me, but it is also part of the checks to + // be sure there is no pointer arithmatic under/overflow. + if(me->data_len > me->UB.len) { // Check #1 + me->err = 1; + return; // Offset of valid data is off the end of the UsefulOutBuf due to uninitialization or corruption + } + + /* 1. Will it fit? */ + // WillItFit() is the same as: NewData.len <= (me->size - me->data_len) + // Check #1 makes sure subtraction in RoomLeft will not wrap around + if(! UsefulOutBuf_WillItFit(me, NewData.len)) { // Check #2 + // The new data will not fit into the the buffer. + me->err = 1; + return; + } + + /* 2. Check the Insertion Position */ + // This, with Check #1, also confirms that uInsertionPos <= me->data_len + if(uInsertionPos > me->data_len) { // Check #3 + // Off the end of the valid data in the buffer. + me->err = 1; + return; + } + + /* 3. Slide existing data to the right */ + uint8_t *pSourceOfMove = ((uint8_t *)me->UB.ptr) + uInsertionPos; // PtrMath #1 + size_t uNumBytesToMove = me->data_len - uInsertionPos; // PtrMath #2 + uint8_t *pDestinationOfMove = pSourceOfMove + NewData.len; // PtrMath #3 + + if(uNumBytesToMove && me->UB.ptr) { + // To know memmove won't go off end of destination, see PtrMath #4 + memmove(pDestinationOfMove, pSourceOfMove, uNumBytesToMove); + } + + /* 4. Put the new data in */ + uint8_t *pInsertionPoint = ((uint8_t *)me->UB.ptr) + uInsertionPos; // PtrMath #5 + if(me->UB.ptr) { + // To know memmove won't go off end of destination, see PtrMath #6 + memmove(pInsertionPoint, NewData.ptr, NewData.len); + } + me->data_len += NewData.len ; +} + + +/* + Rationale that describes why the above pointer math is safe + + PtrMath #1 will never wrap around over because + Check #0 in UsefulOutBuf_Init makes sure me->UB.ptr + me->UB.len doesn't wrap + Check #1 makes sure me->data_len is less than me->UB.len + Check #3 makes sure uInsertionPos is less than me->data_len + + PtrMath #2 will never wrap around under because + Check #3 makes sure uInsertionPos is less than me->data_len + + PtrMath #3 will never wrap around over because todo + PtrMath #1 is checked resulting in pSourceOfMove being between me->UB.ptr and a maximum valid ptr + Check #2 that NewData.len will fit + + PtrMath #4 will never wrap under because + Calculation for extent or memmove is uRoomInDestination = me->UB.len - (uInsertionPos + NewData.len) + Check #3 makes sure uInsertionPos is less than me->data_len + Check #3 allows Check #2 to be refactored as NewData.Len > (me->size - uInsertionPos) + This algebraically rearranges to me->size > uInsertionPos + NewData.len + + PtrMath #5 is exactly the same as PtrMath #1 + + PtrMath #6 will never wrap under because + Calculation for extent of memove is uRoomInDestination = me->UB.len - uInsertionPos; + Check #1 makes sure me->data_len is less than me->size + Check #3 makes sure uInsertionPos is less than me->data_len + */ + + +/* + Public function -- see UsefulBuf.h + */ +UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *me) +{ + if(me->err) { + return NULLUsefulBufC; + } + + if(me->magic != USEFUL_OUT_BUF_MAGIC) { + me->err = 1; + return NULLUsefulBufC; + } + + return (UsefulBufC){me->UB.ptr,me->data_len}; +} + + +/* + Public function -- see UsefulBuf.h + + Copy out the data accumulated in to the output buffer. + */ +UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *me, UsefulBuf pDest) +{ + const UsefulBufC Tmp = UsefulOutBuf_OutUBuf(me); + if(UsefulBuf_IsNULLC(Tmp)) { + return NULLUsefulBufC; + } + return UsefulBuf_Copy(pDest, Tmp); +} + + + + +/* + Public function -- see UsefulBuf.h + + The core of UsefulInputBuf -- consume some bytes without going off the end of the buffer. + + Code Reviewers: THIS FUNCTION DOES POINTER MATH + */ +const void * UsefulInputBuf_GetBytes(UsefulInputBuf *me, size_t uAmount) +{ + // Already in error state. Do nothing. + if(me->err) { + return NULL; + } + + if(!UsefulInputBuf_BytesAvailable(me, uAmount)) { + // The number of bytes asked for at current position are more than available + me->err = 1; + return NULL; + } + + // This is going to succeed + const void * const result = ((uint8_t *)me->UB.ptr) + me->cursor; + me->cursor += uAmount; // this will not overflow because of check using UsefulInputBuf_BytesAvailable() + return result; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/src/ieee754.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/src/ieee754.c new file mode 100644 index 0000000..b0be7f0 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/src/ieee754.c @@ -0,0 +1,496 @@ +/*============================================================================== + ieee754.c -- floating point conversion between half, double and single precision + + Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. + + SPDX-License-Identifier: BSD-3-Clause + + See BSD-3-Clause license in README.md + + Created on 7/23/18 + ==============================================================================*/ + +#include "ieee754.h" +#include // For memcpy() + + +/* + This code is written for clarity and verifiability, not for size, on the assumption + that the optimizer will do a good job. The LLVM optimizer, -Os, does seem to do the + job and the resulting object code is smaller from combining code for the many different + cases (normal, subnormal, infinity, zero...) for the conversions. + + Dead stripping is also really helpful to get code size down when floating point + encoding is not needed. + + This code works solely using shifts and masks and thus has no dependency on + any math libraries. It can even work if the CPU doesn't have any floating + point support, though that isn't the most useful thing to do. + + The memcpy() dependency is only for CopyFloatToUint32() and friends which only + is needed to avoid type punning when converting the actual float bits to + an unsigned value so the bit shifts and masks can work. + */ + +/* + The references used to write this code: + + - IEEE 754-2008, particularly section 3.6 and 6.2.1 + + - https://en.wikipedia.org/wiki/IEEE_754 and subordinate pages + + - https://stackoverflow.com/questions/19800415/why-does-ieee-754-reserve-so-many-nan-values + */ + + +// ----- Half Precsion ----------- +#define HALF_NUM_SIGNIFICAND_BITS (10) +#define HALF_NUM_EXPONENT_BITS (5) +#define HALF_NUM_SIGN_BITS (1) + +#define HALF_SIGNIFICAND_SHIFT (0) +#define HALF_EXPONENT_SHIFT (HALF_NUM_SIGNIFICAND_BITS) +#define HALF_SIGN_SHIFT (HALF_NUM_SIGNIFICAND_BITS + HALF_NUM_EXPONENT_BITS) + +#define HALF_SIGNIFICAND_MASK (0x3ff) // The lower 10 bits // 0x03ff +#define HALF_EXPONENT_MASK (0x1f << HALF_EXPONENT_SHIFT) // 0x7c00 5 bits of exponent +#define HALF_SIGN_MASK (0x01 << HALF_SIGN_SHIFT) // // 0x80001 bit of sign +#define HALF_QUIET_NAN_BIT (0x01 << (HALF_NUM_SIGNIFICAND_BITS-1)) // 0x0200 + +/* Biased Biased Unbiased Use + 0x00 0 -15 0 and subnormal + 0x01 1 -14 Smallest normal exponent + 0x1e 30 15 Largest normal exponent + 0x1F 31 16 NaN and Infinity */ +#define HALF_EXPONENT_BIAS (15) +#define HALF_EXPONENT_MAX (HALF_EXPONENT_BIAS) // 15 Unbiased +#define HALF_EXPONENT_MIN (-HALF_EXPONENT_BIAS+1) // -14 Unbiased +#define HALF_EXPONENT_ZERO (-HALF_EXPONENT_BIAS) // -15 Unbiased +#define HALF_EXPONENT_INF_OR_NAN (HALF_EXPONENT_BIAS+1) // 16 Unbiased + + +// ------ Single Precision -------- +#define SINGLE_NUM_SIGNIFICAND_BITS (23) +#define SINGLE_NUM_EXPONENT_BITS (8) +#define SINGLE_NUM_SIGN_BITS (1) + +#define SINGLE_SIGNIFICAND_SHIFT (0) +#define SINGLE_EXPONENT_SHIFT (SINGLE_NUM_SIGNIFICAND_BITS) +#define SINGLE_SIGN_SHIFT (SINGLE_NUM_SIGNIFICAND_BITS + SINGLE_NUM_EXPONENT_BITS) + +#define SINGLE_SIGNIFICAND_MASK (0x7fffffUL) // The lower 23 bits +#define SINGLE_EXPONENT_MASK (0xffUL << SINGLE_EXPONENT_SHIFT) // 8 bits of exponent +#define SINGLE_SIGN_MASK (0x01UL << SINGLE_SIGN_SHIFT) // 1 bit of sign +#define SINGLE_QUIET_NAN_BIT (0x01UL << (SINGLE_NUM_SIGNIFICAND_BITS-1)) + +/* Biased Biased Unbiased Use + 0x0000 0 -127 0 and subnormal + 0x0001 1 -126 Smallest normal exponent + 0x7f 127 0 1 + 0xfe 254 127 Largest normal exponent + 0xff 255 128 NaN and Infinity */ +#define SINGLE_EXPONENT_BIAS (127) +#define SINGLE_EXPONENT_MAX (SINGLE_EXPONENT_BIAS) // 127 unbiased +#define SINGLE_EXPONENT_MIN (-SINGLE_EXPONENT_BIAS+1) // -126 unbiased +#define SINGLE_EXPONENT_ZERO (-SINGLE_EXPONENT_BIAS) // -127 unbiased +#define SINGLE_EXPONENT_INF_OR_NAN (SINGLE_EXPONENT_BIAS+1) // 128 unbiased + + +// --------- Double Precision ---------- +#define DOUBLE_NUM_SIGNIFICAND_BITS (52) +#define DOUBLE_NUM_EXPONENT_BITS (11) +#define DOUBLE_NUM_SIGN_BITS (1) + +#define DOUBLE_SIGNIFICAND_SHIFT (0) +#define DOUBLE_EXPONENT_SHIFT (DOUBLE_NUM_SIGNIFICAND_BITS) +#define DOUBLE_SIGN_SHIFT (DOUBLE_NUM_SIGNIFICAND_BITS + DOUBLE_NUM_EXPONENT_BITS) + +#define DOUBLE_SIGNIFICAND_MASK (0xfffffffffffffULL) // The lower 52 bits +#define DOUBLE_EXPONENT_MASK (0x7ffULL << DOUBLE_EXPONENT_SHIFT) // 11 bits of exponent +#define DOUBLE_SIGN_MASK (0x01ULL << DOUBLE_SIGN_SHIFT) // 1 bit of sign +#define DOUBLE_QUIET_NAN_BIT (0x01ULL << (DOUBLE_NUM_SIGNIFICAND_BITS-1)) + + +/* Biased Biased Unbiased Use + 0x00000000 0 -1023 0 and subnormal + 0x00000001 1 -1022 Smallest normal exponent + 0x000007fe 2046 1023 Largest normal exponent + 0x000007ff 2047 1024 NaN and Infinity */ +#define DOUBLE_EXPONENT_BIAS (1023) +#define DOUBLE_EXPONENT_MAX (DOUBLE_EXPONENT_BIAS) // unbiased +#define DOUBLE_EXPONENT_MIN (-DOUBLE_EXPONENT_BIAS+1) // unbiased +#define DOUBLE_EXPONENT_ZERO (-DOUBLE_EXPONENT_BIAS) // unbiased +#define DOUBLE_EXPONENT_INF_OR_NAN (DOUBLE_EXPONENT_BIAS+1) // unbiased + + + +/* + Convenient functions to avoid type punning, compiler warnings and such + The optimizer reduces them to a simple assignment. + This is a crusty corner of C. It shouldn't be this hard. + + These are also in UsefulBuf.h under a different name. They are copied + here to avoid a dependency on UsefulBuf.h. There is no + object code size impact because these always optimze down to a + simple assignment. + */ +static inline uint32_t CopyFloatToUint32(float f) +{ + uint32_t u32; + memcpy(&u32, &f, sizeof(uint32_t)); + return u32; +} + +static inline uint64_t CopyDoubleToUint64(double d) +{ + uint64_t u64; + memcpy(&u64, &d, sizeof(uint64_t)); + return u64; +} + +static inline float CopyUint32ToFloat(uint32_t u32) +{ + float f; + memcpy(&f, &u32, sizeof(uint32_t)); + return f; +} + +static inline double CopyUint64ToDouble(uint64_t u64) +{ + double d; + memcpy(&d, &u64, sizeof(uint64_t)); + return d; +} + + +// Public function; see ieee754.h +uint16_t IEEE754_FloatToHalf(float f) +{ + // Pull the three parts out of the single-precision float + const uint32_t uSingle = CopyFloatToUint32(f); + const int32_t nSingleUnbiasedExponent = ((uSingle & SINGLE_EXPONENT_MASK) >> SINGLE_EXPONENT_SHIFT) - SINGLE_EXPONENT_BIAS; + const uint32_t uSingleSign = (uSingle & SINGLE_SIGN_MASK) >> SINGLE_SIGN_SHIFT; + const uint32_t uSingleSignificand = uSingle & SINGLE_SIGNIFICAND_MASK; + + + // Now convert the three parts to half-precision. + uint16_t uHalfSign, uHalfSignificand, uHalfBiasedExponent; + if(nSingleUnbiasedExponent == SINGLE_EXPONENT_INF_OR_NAN) { + // +/- Infinity and NaNs -- single biased exponent is 0xff + uHalfBiasedExponent = HALF_EXPONENT_INF_OR_NAN + HALF_EXPONENT_BIAS; + if(!uSingleSignificand) { + // Infinity + uHalfSignificand = 0; + } else { + // Copy the LBSs of the NaN payload that will fit from the single to the half + uHalfSignificand = uSingleSignificand & (HALF_SIGNIFICAND_MASK & ~HALF_QUIET_NAN_BIT); + if(uSingleSignificand & SINGLE_QUIET_NAN_BIT) { + // It's a qNaN; copy the qNaN bit + uHalfSignificand |= HALF_QUIET_NAN_BIT; + } else { + // It's a sNaN; make sure the significand is not zero so it stays a NaN + // This is needed because not all significand bits are copied from single + if(!uHalfSignificand) { + // Set the LSB. This is what wikipedia shows for sNAN. + uHalfSignificand |= 0x01; + } + } + } + } else if(nSingleUnbiasedExponent == SINGLE_EXPONENT_ZERO) { + // 0 or a subnormal number -- singled biased exponent is 0 + uHalfBiasedExponent = 0; + uHalfSignificand = 0; // Any subnormal single will be too small to express as a half precision + } else if(nSingleUnbiasedExponent > HALF_EXPONENT_MAX) { + // Exponent is too large to express in half-precision; round up to infinity + uHalfBiasedExponent = HALF_EXPONENT_INF_OR_NAN + HALF_EXPONENT_BIAS; + uHalfSignificand = 0; + } else if(nSingleUnbiasedExponent < HALF_EXPONENT_MIN) { + // Exponent is too small to express in half-precision normal; make it a half-precision subnormal + uHalfBiasedExponent = (uint16_t)(HALF_EXPONENT_ZERO + HALF_EXPONENT_BIAS); + // Difference between single normal exponent and the base exponent of a half subnormal + const uint32_t nExpDiff = -(nSingleUnbiasedExponent - HALF_EXPONENT_MIN); + // Also have to shift the significand by the difference in number of bits between a single and a half significand + const int32_t nSignificandBitsDiff = SINGLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS; + // Add in the 1 that is implied in the significand of a normal number; it needs to be present in a subnormal + const uint32_t uSingleSignificandSubnormal = uSingleSignificand + (0x01L << SINGLE_NUM_SIGNIFICAND_BITS); + uHalfSignificand = uSingleSignificandSubnormal >> (nExpDiff + nSignificandBitsDiff); + } else { + // The normal case + uHalfBiasedExponent = nSingleUnbiasedExponent + HALF_EXPONENT_BIAS; + uHalfSignificand = uSingleSignificand >> (SINGLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS); + } + uHalfSign = uSingleSign; + + // Put the 3 values in the right place for a half precision + const uint16_t uHalfPrecision = uHalfSignificand | + (uHalfBiasedExponent << HALF_EXPONENT_SHIFT) | + (uHalfSign << HALF_SIGN_SHIFT); + return uHalfPrecision; +} + + +// Public function; see ieee754.h +uint16_t IEEE754_DoubleToHalf(double d) +{ + // Pull the three parts out of the double-precision float + const uint64_t uDouble = CopyDoubleToUint64(d); + const int64_t nDoubleUnbiasedExponent = ((uDouble & DOUBLE_EXPONENT_MASK) >> DOUBLE_EXPONENT_SHIFT) - DOUBLE_EXPONENT_BIAS; + const uint64_t uDoubleSign = (uDouble & DOUBLE_SIGN_MASK) >> DOUBLE_SIGN_SHIFT; + const uint64_t uDoubleSignificand = uDouble & DOUBLE_SIGNIFICAND_MASK; + + + // Now convert the three parts to half-precision. + uint16_t uHalfSign, uHalfSignificand, uHalfBiasedExponent; + if(nDoubleUnbiasedExponent == DOUBLE_EXPONENT_INF_OR_NAN) { + // +/- Infinity and NaNs -- single biased exponent is 0xff + uHalfBiasedExponent = HALF_EXPONENT_INF_OR_NAN + HALF_EXPONENT_BIAS; + if(!uDoubleSignificand) { + // Infinity + uHalfSignificand = 0; + } else { + // Copy the LBSs of the NaN payload that will fit from the double to the half + uHalfSignificand = uDoubleSignificand & (HALF_SIGNIFICAND_MASK & ~HALF_QUIET_NAN_BIT); + if(uDoubleSignificand & DOUBLE_QUIET_NAN_BIT) { + // It's a qNaN; copy the qNaN bit + uHalfSignificand |= HALF_QUIET_NAN_BIT; + } else { + // It's an sNaN; make sure the significand is not zero so it stays a NaN + // This is needed because not all significand bits are copied from single + if(!uHalfSignificand) { + // Set the LSB. This is what wikipedia shows for sNAN. + uHalfSignificand |= 0x01; + } + } + } + } else if(nDoubleUnbiasedExponent == DOUBLE_EXPONENT_ZERO) { + // 0 or a subnormal number -- double biased exponent is 0 + uHalfBiasedExponent = 0; + uHalfSignificand = 0; // Any subnormal single will be too small to express as a half precision; TODO, is this really true? + } else if(nDoubleUnbiasedExponent > HALF_EXPONENT_MAX) { + // Exponent is too large to express in half-precision; round up to infinity; TODO, is this really true? + uHalfBiasedExponent = HALF_EXPONENT_INF_OR_NAN + HALF_EXPONENT_BIAS; + uHalfSignificand = 0; + } else if(nDoubleUnbiasedExponent < HALF_EXPONENT_MIN) { + // Exponent is too small to express in half-precision; round down to zero + uHalfBiasedExponent = (uint16_t)(HALF_EXPONENT_ZERO + HALF_EXPONENT_BIAS); + // Difference between double normal exponent and the base exponent of a half subnormal + const uint64_t nExpDiff = -(nDoubleUnbiasedExponent - HALF_EXPONENT_MIN); + // Also have to shift the significand by the difference in number of bits between a double and a half significand + const int64_t nSignificandBitsDiff = DOUBLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS; + // Add in the 1 that is implied in the significand of a normal number; it needs to be present in a subnormal + const uint64_t uDoubleSignificandSubnormal = uDoubleSignificand + (0x01ULL << DOUBLE_NUM_SIGNIFICAND_BITS); + uHalfSignificand = uDoubleSignificandSubnormal >> (nExpDiff + nSignificandBitsDiff); + } else { + // The normal case + uHalfBiasedExponent = nDoubleUnbiasedExponent + HALF_EXPONENT_BIAS; + uHalfSignificand = uDoubleSignificand >> (DOUBLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS); + } + uHalfSign = uDoubleSign; + + + // Put the 3 values in the right place for a half precision + const uint16_t uHalfPrecision = uHalfSignificand | + (uHalfBiasedExponent << HALF_EXPONENT_SHIFT) | + (uHalfSign << HALF_SIGN_SHIFT); + return uHalfPrecision; +} + + +// Public function; see ieee754.h +float IEEE754_HalfToFloat(uint16_t uHalfPrecision) +{ + // Pull out the three parts of the half-precision float + const uint16_t uHalfSignificand = uHalfPrecision & HALF_SIGNIFICAND_MASK; + const int16_t nHalfUnBiasedExponent = ((uHalfPrecision & HALF_EXPONENT_MASK) >> HALF_EXPONENT_SHIFT) - HALF_EXPONENT_BIAS; + const uint16_t uHalfSign = (uHalfPrecision & HALF_SIGN_MASK) >> HALF_SIGN_SHIFT; + + + // Make the three parts of the single-precision number + uint32_t uSingleSignificand, uSingleSign, uSingleBiasedExponent; + if(nHalfUnBiasedExponent == HALF_EXPONENT_ZERO) { + // 0 or subnormal + if(uHalfSignificand) { + // Subnormal case + uSingleBiasedExponent = -HALF_EXPONENT_BIAS + SINGLE_EXPONENT_BIAS +1; + // A half-precision subnormal can always be converted to a normal single-precision float because the ranges line up + uSingleSignificand = uHalfSignificand; + // Shift bits from right of the decimal to left, reducing the exponent by 1 each time + do { + uSingleSignificand <<= 1; + uSingleBiasedExponent--; + } while ((uSingleSignificand & 0x400) == 0); + uSingleSignificand &= HALF_SIGNIFICAND_MASK; + uSingleSignificand <<= (SINGLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS); + } else { + // Just zero + uSingleBiasedExponent = SINGLE_EXPONENT_ZERO + SINGLE_EXPONENT_BIAS; + uSingleSignificand = 0; + } + } else if(nHalfUnBiasedExponent == HALF_EXPONENT_INF_OR_NAN) { + // NaN or Inifinity + uSingleBiasedExponent = SINGLE_EXPONENT_INF_OR_NAN + SINGLE_EXPONENT_BIAS; + if(uHalfSignificand) { + // NaN + // First preserve the NaN payload from half to single + uSingleSignificand = uHalfSignificand & ~HALF_QUIET_NAN_BIT; + if(uHalfSignificand & HALF_QUIET_NAN_BIT) { + // Next, set qNaN if needed since half qNaN bit is not copied above + uSingleSignificand |= SINGLE_QUIET_NAN_BIT; + } + } else { + // Infinity + uSingleSignificand = 0; + } + } else { + // Normal number + uSingleBiasedExponent = nHalfUnBiasedExponent + SINGLE_EXPONENT_BIAS; + uSingleSignificand = uHalfSignificand << (SINGLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS); + } + uSingleSign = uHalfSign; + + + // Shift the three parts of the single precision into place + const uint32_t uSinglePrecision = uSingleSignificand | + (uSingleBiasedExponent << SINGLE_EXPONENT_SHIFT) | + (uSingleSign << SINGLE_SIGN_SHIFT); + + return CopyUint32ToFloat(uSinglePrecision); +} + + +// Public function; see ieee754.h +double IEEE754_HalfToDouble(uint16_t uHalfPrecision) +{ + // Pull out the three parts of the half-precision float + const uint16_t uHalfSignificand = uHalfPrecision & HALF_SIGNIFICAND_MASK; + const int16_t nHalfUnBiasedExponent = ((uHalfPrecision & HALF_EXPONENT_MASK) >> HALF_EXPONENT_SHIFT) - HALF_EXPONENT_BIAS; + const uint16_t uHalfSign = (uHalfPrecision & HALF_SIGN_MASK) >> HALF_SIGN_SHIFT; + + + // Make the three parts of hte single-precision number + uint64_t uDoubleSignificand, uDoubleSign, uDoubleBiasedExponent; + if(nHalfUnBiasedExponent == HALF_EXPONENT_ZERO) { + // 0 or subnormal + uDoubleBiasedExponent = DOUBLE_EXPONENT_ZERO + DOUBLE_EXPONENT_BIAS; + if(uHalfSignificand) { + // Subnormal case + uDoubleBiasedExponent = -HALF_EXPONENT_BIAS + DOUBLE_EXPONENT_BIAS +1; + // A half-precision subnormal can always be converted to a normal double-precision float because the ranges line up + uDoubleSignificand = uHalfSignificand; + // Shift bits from right of the decimal to left, reducing the exponent by 1 each time + do { + uDoubleSignificand <<= 1; + uDoubleBiasedExponent--; + } while ((uDoubleSignificand & 0x400) == 0); + uDoubleSignificand &= HALF_SIGNIFICAND_MASK; + uDoubleSignificand <<= (DOUBLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS); + } else { + // Just zero + uDoubleSignificand = 0; + } + } else if(nHalfUnBiasedExponent == HALF_EXPONENT_INF_OR_NAN) { + // NaN or Inifinity + uDoubleBiasedExponent = DOUBLE_EXPONENT_INF_OR_NAN + DOUBLE_EXPONENT_BIAS; + if(uHalfSignificand) { + // NaN + // First preserve the NaN payload from half to single + uDoubleSignificand = uHalfSignificand & ~HALF_QUIET_NAN_BIT; + if(uHalfSignificand & HALF_QUIET_NAN_BIT) { + // Next, set qNaN if needed since half qNaN bit is not copied above + uDoubleSignificand |= DOUBLE_QUIET_NAN_BIT; + } + } else { + // Infinity + uDoubleSignificand = 0; + } + } else { + // Normal number + uDoubleBiasedExponent = nHalfUnBiasedExponent + DOUBLE_EXPONENT_BIAS; + uDoubleSignificand = (uint64_t)uHalfSignificand << (DOUBLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS); + } + uDoubleSign = uHalfSign; + + + // Shift the 3 parts into place as a double-precision + const uint64_t uDouble = uDoubleSignificand | + (uDoubleBiasedExponent << DOUBLE_EXPONENT_SHIFT) | + (uDoubleSign << DOUBLE_SIGN_SHIFT); + return CopyUint64ToDouble(uDouble); +} + + +// Public function; see ieee754.h +IEEE754_union IEEE754_FloatToSmallest(float f) +{ + IEEE754_union result; + + // Pull the neeed two parts out of the single-precision float + const uint32_t uSingle = CopyFloatToUint32(f); + const int32_t nSingleExponent = ((uSingle & SINGLE_EXPONENT_MASK) >> SINGLE_EXPONENT_SHIFT) - SINGLE_EXPONENT_BIAS; + const uint32_t uSingleSignificand = uSingle & SINGLE_SIGNIFICAND_MASK; + + // Bit mask that is the significand bits that would be lost when converting + // from single-precision to half-precision + const uint64_t uDroppedSingleBits = SINGLE_SIGNIFICAND_MASK >> HALF_NUM_SIGNIFICAND_BITS; + + // Optimizer will re organize so there is only one call to IEEE754_FloatToHalf() + if(uSingle == 0) { + // Value is 0.0000, not a a subnormal + result.uSize = IEEE754_UNION_IS_HALF; + result.uValue = IEEE754_FloatToHalf(f); + } else if(nSingleExponent == SINGLE_EXPONENT_INF_OR_NAN) { + // NaN, +/- infinity + result.uSize = IEEE754_UNION_IS_HALF; + result.uValue = IEEE754_FloatToHalf(f); + } else if((nSingleExponent >= HALF_EXPONENT_MIN) && nSingleExponent <= HALF_EXPONENT_MAX && (!(uSingleSignificand & uDroppedSingleBits))) { + // Normal number in exponent range and precision won't be lost + result.uSize = IEEE754_UNION_IS_HALF; + result.uValue = IEEE754_FloatToHalf(f); + } else { + // Subnormal, exponent out of range, or precision will be lost + result.uSize = IEEE754_UNION_IS_SINGLE; + result.uValue = uSingle; + } + + return result; +} + +// Public function; see ieee754.h +IEEE754_union IEEE754_DoubleToSmallestInternal(double d, int bAllowHalfPrecision) +{ + IEEE754_union result; + + // Pull the needed two parts out of the double-precision float + const uint64_t uDouble = CopyDoubleToUint64(d); + const int64_t nDoubleExponent = ((uDouble & DOUBLE_EXPONENT_MASK) >> DOUBLE_EXPONENT_SHIFT) - DOUBLE_EXPONENT_BIAS; + const uint64_t uDoubleSignificand = uDouble & DOUBLE_SIGNIFICAND_MASK; + + // Masks to check whether dropped significand bits are zero or not + const uint64_t uDroppedDoubleBits = DOUBLE_SIGNIFICAND_MASK >> HALF_NUM_SIGNIFICAND_BITS; + const uint64_t uDroppedSingleBits = DOUBLE_SIGNIFICAND_MASK >> SINGLE_NUM_SIGNIFICAND_BITS; + + // The various cases + if(d == 0.0) { // Take care of positive and negative zero + // Value is 0.0000, not a a subnormal + result.uSize = IEEE754_UNION_IS_HALF; + result.uValue = IEEE754_DoubleToHalf(d); + } else if(nDoubleExponent == DOUBLE_EXPONENT_INF_OR_NAN) { + // NaN, +/- infinity + result.uSize = IEEE754_UNION_IS_HALF; + result.uValue = IEEE754_DoubleToHalf(d); + } else if(bAllowHalfPrecision && (nDoubleExponent >= HALF_EXPONENT_MIN) && nDoubleExponent <= HALF_EXPONENT_MAX && (!(uDoubleSignificand & uDroppedDoubleBits))) { + // Can convert to half without precision loss + result.uSize = IEEE754_UNION_IS_HALF; + result.uValue = IEEE754_DoubleToHalf(d); + } else if((nDoubleExponent >= SINGLE_EXPONENT_MIN) && nDoubleExponent <= SINGLE_EXPONENT_MAX && (!(uDoubleSignificand & uDroppedSingleBits))) { + // Can convert to single without precision loss + result.uSize = IEEE754_UNION_IS_SINGLE; + result.uValue = CopyFloatToUint32((float)d); + } else { + // Can't convert without precision loss + result.uSize = IEEE754_UNION_IS_DOUBLE; + result.uValue = uDouble; + } + + return result; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/src/ieee754.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/src/ieee754.h new file mode 100644 index 0000000..f0e0a22 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/src/ieee754.h @@ -0,0 +1,161 @@ +/*============================================================================== + ieee754.c -- floating point conversion between half, double and single precision + + Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. + + SPDX-License-Identifier: BSD-3-Clause + + See BSD-3-Clause license in README.md + + Created on 7/23/18 + ==============================================================================*/ + +#ifndef ieee754_h +#define ieee754_h + +#include + + + +/* + General comments + + This is a complete in that it handles all conversion cases + including +/- infinity, +/- zero, subnormal numbers, qNaN, sNaN + and NaN payloads. + + This confirms to IEEE 754-2008, but note that this doesn't + specify conversions, just the encodings. + + NaN payloads are preserved with alignment on the LSB. The + qNaN bit is handled differently and explicity copied. It + is always the MSB of the significand. The NaN payload MSBs + (except the qNaN bit) are truncated when going from + double or single to half. + + TODO: what does the C cast do with NaN payloads from + double to single? + + + + */ + +/* + Most simply just explicilty encode the type you want, single or double. + This works easily everywhere since standard C supports both + these types and so does qcbor. This encoder also supports + half precision and there's a few ways to use it to encode + floating point numbers in less space. + + Without losing precision, you can encode a single or double + such that the special values of 0, NaN and Infinity encode + as half-precision. This CBOR decodoer and most others + should handle this properly. + + If you don't mind losing precision, then you can use half-precision. + One way to do this is to set up your environment to use + ___fp_16. Some compilers and CPUs support it even though it is not + standard C. What is nice about this is that your program + will use less memory and floating point operations like + multiplying, adding and such will be faster. + + Another way to make use of half-precision is to represent + the values in your program as single or double, but encode + them in CBOR as half-precision. This cuts the size + of the encoded messages by 2 or 4, but doesn't reduce + memory needs or speed because you are still using + single or double in your code. + + + encode: + - float as float + - double as double + - half as half + - float as half_precision, for environments that don't support a half-precision type + - double as half_precision, for environments that don't support a half-precision type + - float with NaN, Infinity and 0 as half + - double with NaN, Infinity and 0 as half + + + + + */ + + + +/* + Convert single precision float to half-precision float. + Precision and NaN payload bits will be lost. Too large + values will round up to infinity and too small to zero. + */ +uint16_t IEEE754_FloatToHalf(float f); + + +/* + Convert half precision float to single precision float. + This is a loss-less conversion. + */ +float IEEE754_HalfToFloat(uint16_t uHalfPrecision); + + +/* + Convert double precision float to half-precision float. + Precision and NaN payload bits will be lost. Too large + values will round up to infinity and too small to zero. + */ +uint16_t IEEE754_DoubleToHalf(double d); + + +/* + Convert half precision float to double precision float. + This is a loss-less conversion. + */ +double IEEE754_HalfToDouble(uint16_t uHalfPrecision); + + + +// Both tags the value and gives the size +#define IEEE754_UNION_IS_HALF 2 +#define IEEE754_UNION_IS_SINGLE 4 +#define IEEE754_UNION_IS_DOUBLE 8 + +typedef struct { + uint8_t uSize; // One of IEEE754_IS_xxxx + uint64_t uValue; +} IEEE754_union; + + +/* + Converts double-precision to single-precision or half-precision if possible without + loss of precisions. If not, leaves it as a double. Only converts to single-precision + unless bAllowHalfPrecision is set. + */ +IEEE754_union IEEE754_DoubleToSmallestInternal(double d, int bAllowHalfPrecision); + +/* + Converts double-precision to single-precision if possible without + loss of precision. If not, leaves it as a double. + */ +static inline IEEE754_union IEEE754_DoubleToSmall(double d) +{ + return IEEE754_DoubleToSmallestInternal(d, 0); +} + + +/* + Converts double-precision to single-precision or half-precision if possible without + loss of precisions. If not, leaves it as a double. + */ +static inline IEEE754_union IEEE754_DoubleToSmallest(double d) +{ + return IEEE754_DoubleToSmallestInternal(d, 1); +} + +/* + Converts single-precision to half-precision if possible without + loss of precision. If not leaves as single-precision. + */ +IEEE754_union IEEE754_FloatToSmallest(float f); + + +#endif /* ieee754_h */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/src/qcbor_decode.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/src/qcbor_decode.c new file mode 100644 index 0000000..1fa2624 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/src/qcbor_decode.c @@ -0,0 +1,1319 @@ +/*============================================================================== + Copyright (c) 2016-2018, The Linux Foundation. + Copyright (c) 2018-2019, Laurence Lundblade. + All rights reserved. + SPDX-License-Identifier: BSD-3-Clause + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors, nor the name "Laurence Lundblade" may be used to + endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ==============================================================================*/ + +/*=================================================================================== + FILE: qcbor_decode.c + + DESCRIPTION: This file contains the implementation of QCBOR. + + EDIT HISTORY FOR FILE: + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + when who what, where, why + -------- ---- --------------------------------------------------- + 01/10/19 llundblade Clever type and argument decoder is 250 bytes smaller + 11/9/18 llundblade Error codes are now enums. + 11/2/18 llundblade Simplify float decoding and align with preferred + float encoding + 10/31/18 llundblade Switch to one license that is almost BSD-3. + 10/28/18 llundblade Reworked tag decoding + 10/15/18 llundblade Indefinite length maps and arrays supported + 10/8/18 llundblade Indefinite length strings supported + 02/04/17 llundbla Work on CPUs that don's require pointer alignment + by making use of changes in UsefulBuf + 03/01/17 llundbla More data types; decoding improvements and fixes + 11/13/16 llundbla Integrate most TZ changes back into github version. + 09/30/16 gkanike Porting to TZ. + 03/15/16 llundbla Initial Version. + + =====================================================================================*/ + +#include "qcbor.h" +#include "ieee754.h" + + +/* + This casts away the const-ness of a pointer, usually so it can be + freed or realloced. + */ +#define UNCONST_POINTER(ptr) ((void *)(ptr)) + + +/* + Collection of functions to track the map/array nesting for decoding + */ + +inline static int IsMapOrArray(uint8_t uDataType) +{ + return uDataType == QCBOR_TYPE_MAP || uDataType == QCBOR_TYPE_ARRAY; +} + +inline static int DecodeNesting_IsNested(const QCBORDecodeNesting *pNesting) +{ + return pNesting->pCurrent != &(pNesting->pMapsAndArrays[0]); +} + +inline static int DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting) +{ + return pNesting->pCurrent->uCount == UINT16_MAX; +} + +inline static uint8_t DecodeNesting_GetLevel(QCBORDecodeNesting *pNesting) +{ + return pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]); +} + +inline static int DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting) +{ + if(!DecodeNesting_IsNested(pNesting)) { + return 0; + } + + return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType; +} + +// Process a break. This will either ascend the nesting or error out +inline static QCBORError DecodeNesting_BreakAscend(QCBORDecodeNesting *pNesting) +{ + // breaks must always occur when there is nesting + if(!DecodeNesting_IsNested(pNesting)) { + return QCBOR_ERR_BAD_BREAK; + } + + // breaks can only occur when the map/array is indefinite length + if(!DecodeNesting_IsIndefiniteLength(pNesting)) { + return QCBOR_ERR_BAD_BREAK; + } + + // if all OK, the break reduces the level of nesting + pNesting->pCurrent--; + + return QCBOR_SUCCESS; +} + +// Called on every single item except breaks including the opening of a map/array +inline static void DecodeNesting_DecrementCount(QCBORDecodeNesting *pNesting) +{ + if(!DecodeNesting_IsNested(pNesting)) { + // at top level where there is no tracking + return; + } + + if(DecodeNesting_IsIndefiniteLength(pNesting)) { + // There is no count for indefinite length arrays/maps + return; + } + + // Decrement the count of items in this array/map + pNesting->pCurrent->uCount--; + + // Pop up nesting levels if the counts at the levels are zero + while(DecodeNesting_IsNested(pNesting) && 0 == pNesting->pCurrent->uCount) { + pNesting->pCurrent--; + if(!DecodeNesting_IsIndefiniteLength(pNesting)) { + pNesting->pCurrent->uCount--; + } + } +} + +// Called on every map/array +inline static QCBORError DecodeNesting_Descend(QCBORDecodeNesting *pNesting, QCBORItem *pItem) +{ + QCBORError nReturn = QCBOR_SUCCESS; + + if(pItem->val.uCount == 0) { + // Nothing to do for empty definite lenth arrays. They are just are + // effectively the same as an item that is not a map or array + goto Done; + // Empty indefinite length maps and arrays are handled elsewhere + } + + // Error out if arrays is too long to handle + if(pItem->val.uCount != UINT16_MAX && pItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY) { + nReturn = QCBOR_ERR_ARRAY_TOO_LONG; + goto Done; + } + + // Error out if nesting is too deep + if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) { + nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP; + goto Done; + } + + // The actual descend + pNesting->pCurrent++; + + // Record a few details for this nesting level + pNesting->pCurrent->uMajorType = pItem->uDataType; + pNesting->pCurrent->uCount = pItem->val.uCount; + +Done: + return nReturn;; +} + +inline static void DecodeNesting_Init(QCBORDecodeNesting *pNesting) +{ + pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]); +} + + + +/* + This list of built-in tags. Only add tags here that are + clearly established and useful. Once a tag is added here + it can't be taken out as that would break backwards compatibility. + There are only 48 slots available forever. + */ +static const uint16_t spBuiltInTagMap[] = { + CBOR_TAG_DATE_STRING, // See TAG_MAPPER_FIRST_FOUR + CBOR_TAG_DATE_EPOCH, // See TAG_MAPPER_FIRST_FOUR + CBOR_TAG_POS_BIGNUM, // See TAG_MAPPER_FIRST_FOUR + CBOR_TAG_NEG_BIGNUM, // See TAG_MAPPER_FIRST_FOUR + CBOR_TAG_FRACTION, + CBOR_TAG_BIGFLOAT, + CBOR_TAG_COSE_ENCRYPTO, + CBOR_TAG_COSE_MAC0, + CBOR_TAG_COSE_SIGN1, + CBOR_TAG_ENC_AS_B64URL, + CBOR_TAG_ENC_AS_B64, + CBOR_TAG_ENC_AS_B16, + CBOR_TAG_CBOR, + CBOR_TAG_URI, + CBOR_TAG_B64URL, + CBOR_TAG_B64, + CBOR_TAG_REGEX, + CBOR_TAG_MIME, + CBOR_TAG_BIN_UUID, + CBOR_TAG_CWT, + CBOR_TAG_ENCRYPT, + CBOR_TAG_MAC, + CBOR_TAG_SIGN, + CBOR_TAG_GEO_COORD, + CBOR_TAG_CBOR_MAGIC +}; + +// This is used in a bit of cleverness in GetNext_TaggedItem() to +// keep code size down and switch for the internal processing of +// these types. This will break if the first four items in +// spBuiltInTagMap don't have values 0,1,2,3. That is the +// mapping is 0 to 0, 1 to 1, 2 to 2 and 3 to 3. +#define QCBOR_TAGFLAG_DATE_STRING (0x01LL << CBOR_TAG_DATE_STRING) +#define QCBOR_TAGFLAG_DATE_EPOCH (0x01LL << CBOR_TAG_DATE_EPOCH) +#define QCBOR_TAGFLAG_POS_BIGNUM (0x01LL << CBOR_TAG_POS_BIGNUM) +#define QCBOR_TAGFLAG_NEG_BIGNUM (0x01LL << CBOR_TAG_NEG_BIGNUM) + +#define TAG_MAPPER_FIRST_FOUR (QCBOR_TAGFLAG_DATE_STRING |\ + QCBOR_TAGFLAG_DATE_EPOCH |\ + QCBOR_TAGFLAG_POS_BIGNUM |\ + QCBOR_TAGFLAG_NEG_BIGNUM) + +#define TAG_MAPPER_TOTAL_TAG_BITS 64 // Number of bits in a uint64_t +#define TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS) // 48 +#define TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS ) // 48 + +static inline int TagMapper_LookupBuiltIn(uint64_t uTag) +{ + if(sizeof(spBuiltInTagMap)/sizeof(uint16_t) > TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS) { + // This is a cross-check to make sure the above array doesn't + // accidentally get made too big. + // In normal conditions the above test should optimize out + // as all the values are known at compile time. + return -1; + } + + if(uTag > UINT16_MAX) { + // This tag map works only on 16-bit tags + return -1; + } + + for(int nTagBitIndex = 0; nTagBitIndex < (int)(sizeof(spBuiltInTagMap)/sizeof(uint16_t)); nTagBitIndex++) { + if(spBuiltInTagMap[nTagBitIndex] == uTag) { + return nTagBitIndex; + } + } + return -1; // Indicates no match +} + +static inline int TagMapper_LookupCallerConfigured(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag) +{ + for(int nTagBitIndex = 0; nTagBitIndex < pCallerConfiguredTagMap->uNumTags; nTagBitIndex++) { + if(pCallerConfiguredTagMap->puTags[nTagBitIndex] == uTag) { + return nTagBitIndex + TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX; + } + } + + return -1; // Indicates no match +} + +/* + Find the tag bit index for a given tag value, or error out + + This and the above functions could probably be optimized and made + clearer and neater. + */ +static QCBORError TagMapper_Lookup(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag, uint8_t *puTagBitIndex) +{ + int nTagBitIndex = TagMapper_LookupBuiltIn(uTag); + if(nTagBitIndex >= 0) { + // Cast is safe because TagMapper_LookupBuiltIn never returns > 47 + *puTagBitIndex = (uint8_t)nTagBitIndex; + return QCBOR_SUCCESS; + } + + if(pCallerConfiguredTagMap) { + if(pCallerConfiguredTagMap->uNumTags > QCBOR_MAX_CUSTOM_TAGS) { + return QCBOR_ERR_TOO_MANY_TAGS; + } + nTagBitIndex = TagMapper_LookupCallerConfigured(pCallerConfiguredTagMap, uTag); + if(nTagBitIndex >= 0) { + // Cast is safe because TagMapper_LookupBuiltIn never returns > 63 + + *puTagBitIndex = (uint8_t)nTagBitIndex; + return QCBOR_SUCCESS; + } + } + + return QCBOR_ERR_BAD_OPT_TAG; +} + + + + +/* + Public function, see header file + */ +void QCBORDecode_Init(QCBORDecodeContext *me, UsefulBufC EncodedCBOR, QCBORDecodeMode nDecodeMode) +{ + memset(me, 0, sizeof(QCBORDecodeContext)); + UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR); + // Don't bother with error check on decode mode. If a bad value is passed it will just act as + // if the default normal mode of 0 was set. + me->uDecodeMode = nDecodeMode; + DecodeNesting_Init(&(me->nesting)); +} + + +/* + Public function, see header file + */ +void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pCtx, const QCBORStringAllocator *pAllocator, bool bAllocAll) +{ + pCtx->pStringAllocator = (void *)pAllocator; + pCtx->bStringAllocateAll = bAllocAll; +} + +void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me, const QCBORTagListIn *pTagList) +{ + me->pCallerConfiguredTagList = pTagList; +} + + +/* + This decodes the fundamental part of a CBOR data item, the type and number + + This is the Counterpart to InsertEncodedTypeAndNumber(). + + This does the network->host byte order conversion. The conversion here + also results in the conversion for floats in addition to that for + lengths, tags and integer values. + + This returns: + pnMajorType -- the major type for the item + puNumber -- the "number" which is used a the value for integers, tags and floats and length for strings and arrays + puAdditionalInfo -- Pass this along to know what kind of float or if length is indefinite + + */ +inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf, + int *pnMajorType, + uint64_t *puArgument, + uint8_t *puAdditionalInfo) +{ + QCBORError nReturn; + + // Get the initial byte that every CBOR data item has + const uint8_t uInitialByte = UsefulInputBuf_GetByte(pUInBuf); + + // Break down the initial byte + const uint8_t uTmpMajorType = uInitialByte >> 5; + const uint8_t uAdditionalInfo = uInitialByte & 0x1f; + + // Where the number or argument accumulates + uint64_t uArgument; + + if(uAdditionalInfo >= LEN_IS_ONE_BYTE && uAdditionalInfo <= LEN_IS_EIGHT_BYTES) { + // Need to get 1,2,4 or 8 additional argument bytes + // Map LEN_IS_ONE_BYTE.. LEN_IS_EIGHT_BYTES to actual length + static const uint8_t aIterate[] = {1,2,4,8}; + + // Loop getting all the bytes in the argument + uArgument = 0; + for(int i = aIterate[uAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) { + // This shift and add gives the endian conversion + uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf); + } + } else if(uAdditionalInfo >= ADDINFO_RESERVED1 && uAdditionalInfo <= ADDINFO_RESERVED3) { + // The reserved and thus-far unused additional info values + nReturn = QCBOR_ERR_UNSUPPORTED; + goto Done; + } else { + // Less than 24, additional info is argument or 31, an indefinite length + // No more bytes to get + uArgument = uAdditionalInfo; + } + + if(UsefulInputBuf_GetError(pUInBuf)) { + nReturn = QCBOR_ERR_HIT_END; + goto Done; + } + + // All successful if we got here. + nReturn = QCBOR_SUCCESS; + *pnMajorType = uTmpMajorType; + *puArgument = uArgument; + *puAdditionalInfo = uAdditionalInfo; + +Done: + return nReturn; +} + +/* + CBOR doesn't explicitly specify two's compliment for integers but all CPUs + use it these days and the test vectors in the RFC are so. All integers in the CBOR + structure are positive and the major type indicates positive or negative. + CBOR can express positive integers up to 2^x - 1 where x is the number of bits + and negative integers down to 2^x. Note that negative numbers can be one + more away from zero than positive. + Stdint, as far as I can tell, uses two's compliment to represent + negative integers. + + See http://www.unix.org/whitepapers/64bit.html for reasons int isn't + used here in any way including in the interface + */ +inline static QCBORError DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem) +{ + // Stack usage: int/ptr 1 -- 8 + QCBORError nReturn = QCBOR_SUCCESS; + + if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) { + if (uNumber <= INT64_MAX) { + pDecodedItem->val.int64 = (int64_t)uNumber; + pDecodedItem->uDataType = QCBOR_TYPE_INT64; + + } else { + pDecodedItem->val.uint64 = uNumber; + pDecodedItem->uDataType = QCBOR_TYPE_UINT64; + + } + } else { + if(uNumber <= INT64_MAX) { + pDecodedItem->val.int64 = -uNumber-1; + pDecodedItem->uDataType = QCBOR_TYPE_INT64; + + } else { + // C can't represent a negative integer in this range + // so it is an error. todo -- test this condition + nReturn = QCBOR_ERR_INT_OVERFLOW; + } + } + + return nReturn; +} + +// Make sure #define value line up as DecodeSimple counts on this. +#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE +#error QCBOR_TYPE_FALSE macro value wrong +#endif + +#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE +#error QCBOR_TYPE_TRUE macro value wrong +#endif + +#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL +#error QCBOR_TYPE_NULL macro value wrong +#endif + +#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF +#error QCBOR_TYPE_UNDEF macro value wrong +#endif + +#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK +#error QCBOR_TYPE_BREAK macro value wrong +#endif + +#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT +#error QCBOR_TYPE_DOUBLE macro value wrong +#endif + +#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT +#error QCBOR_TYPE_FLOAT macro value wrong +#endif + +/* + Decode true, false, floats, break... + */ + +inline static QCBORError DecodeSimple(uint8_t uAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem) +{ + // Stack usage: 0 + QCBORError nReturn = QCBOR_SUCCESS; + + // uAdditionalInfo is 5 bits from the initial byte + // compile time checks above make sure uAdditionalInfo values line up with uDataType values + pDecodedItem->uDataType = uAdditionalInfo; + + switch(uAdditionalInfo) { + case ADDINFO_RESERVED1: // 28 + case ADDINFO_RESERVED2: // 29 + case ADDINFO_RESERVED3: // 30 + nReturn = QCBOR_ERR_UNSUPPORTED; + break; + + case HALF_PREC_FLOAT: + pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber); + pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE; + break; + case SINGLE_PREC_FLOAT: + pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber); + pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE; + break; + case DOUBLE_PREC_FLOAT: + pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber); + pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE; + break; + + case CBOR_SIMPLEV_FALSE: // 20 + case CBOR_SIMPLEV_TRUE: // 21 + case CBOR_SIMPLEV_NULL: // 22 + case CBOR_SIMPLEV_UNDEF: // 23 + case CBOR_SIMPLE_BREAK: // 31 + break; // nothing to do + + case CBOR_SIMPLEV_ONEBYTE: // 24 + if(uNumber <= CBOR_SIMPLE_BREAK) { + // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7 + nReturn = QCBOR_ERR_INVALID_CBOR; + goto Done; + } + /* FALLTHROUGH */ + // fall through intentionally + + default: // 0-19 + pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE; + // DecodeTypeAndNumber will make uNumber equal to uAdditionalInfo when uAdditionalInfo is < 24 + // This cast is safe because the 2, 4 and 8 byte lengths of uNumber are in the double/float cases above + pDecodedItem->val.uSimple = (uint8_t)uNumber; + break; + } + +Done: + return nReturn; +} + + + +/* + Decode text and byte strings. Call the string allocator if asked to. + */ +inline static QCBORError DecodeBytes(const QCBORStringAllocator *pAlloc, int nMajorType, uint64_t uStrLen, UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem) +{ + // Stack usage: UsefulBuf 2, int/ptr 1 40 + QCBORError nReturn = QCBOR_SUCCESS; + + const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, uStrLen); + if(UsefulBuf_IsNULLC(Bytes)) { + // Failed to get the bytes for this string item + nReturn = QCBOR_ERR_HIT_END; + goto Done; + } + + if(pAlloc) { + // We are asked to use string allocator to make a copy + UsefulBuf NewMem = pAlloc->fAllocate(pAlloc->pAllocaterContext, NULL, uStrLen); + if(UsefulBuf_IsNULL(NewMem)) { + nReturn = QCBOR_ERR_STRING_ALLOCATE; + goto Done; + } + pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes); + } else { + // Normal case with no string allocator + pDecodedItem->val.string = Bytes; + } + pDecodedItem->uDataType = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING; + +Done: + return nReturn; +} + + +/* + Mostly just assign the right data type for the date string. + */ +inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem) +{ + // Stack Use: UsefulBuf 1 16 + if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) { + return QCBOR_ERR_BAD_OPT_TAG; + } + + const UsefulBufC Temp = pDecodedItem->val.string; + pDecodedItem->val.dateString = Temp; + pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING; + return QCBOR_SUCCESS; +} + + +/* + Mostly just assign the right data type for the bignum. + */ +inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem) +{ + // Stack Use: UsefulBuf 1 -- 16 + if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) { + return QCBOR_ERR_BAD_OPT_TAG; + } + const UsefulBufC Temp = pDecodedItem->val.string; + pDecodedItem->val.bigNum = Temp; + pDecodedItem->uDataType = pDecodedItem->uTagBits & QCBOR_TAGFLAG_POS_BIGNUM ? QCBOR_TYPE_POSBIGNUM : QCBOR_TYPE_NEGBIGNUM; + return QCBOR_SUCCESS; +} + + +/* + The epoch formatted date. Turns lots of different forms of encoding date into uniform one + */ +static int DecodeDateEpoch(QCBORItem *pDecodedItem) +{ + // Stack usage: 1 + QCBORError nReturn = QCBOR_SUCCESS; + + pDecodedItem->val.epochDate.fSecondsFraction = 0; + + switch (pDecodedItem->uDataType) { + + case QCBOR_TYPE_INT64: + pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64; + break; + + case QCBOR_TYPE_UINT64: + if(pDecodedItem->val.uint64 > INT64_MAX) { + nReturn = QCBOR_ERR_DATE_OVERFLOW; + goto Done; + } + pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.uint64; + break; + + case QCBOR_TYPE_DOUBLE: + { + const double d = pDecodedItem->val.dfnum; + if(d > INT64_MAX) { + nReturn = QCBOR_ERR_DATE_OVERFLOW; + goto Done; + } + pDecodedItem->val.epochDate.nSeconds = d; // Float to integer conversion happening here. + pDecodedItem->val.epochDate.fSecondsFraction = d - pDecodedItem->val.epochDate.nSeconds; + } + break; + + default: + nReturn = QCBOR_ERR_BAD_OPT_TAG; + goto Done; + } + pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH; + +Done: + return nReturn; +} + + + + +// Make sure the constants align as this is assumed by the GetAnItem() implementation +#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY +#error QCBOR_TYPE_ARRAY value not lined up with major type +#endif +#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP +#error QCBOR_TYPE_MAP value not lined up with major type +#endif + +/* + This gets a single data item and decodes it including preceding optional tagging. This does not + deal with arrays and maps and nesting except to decode the data item introducing them. Arrays and + maps are handled at the next level up in GetNext(). + + Errors detected here include: an array that is too long to decode, hit end of buffer unexpectedly, + a few forms of invalid encoded CBOR + */ +static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem, const QCBORStringAllocator *pAlloc) +{ + // Stack usage: int/ptr 3 -- 24 + QCBORError nReturn; + + // Get the major type and the number. Number could be length of more bytes or the value depending on the major type + // nAdditionalInfo is an encoding of the length of the uNumber and is needed to decode floats and doubles + int uMajorType; + uint64_t uNumber; + uint8_t uAdditionalInfo; + + nReturn = DecodeTypeAndNumber(pUInBuf, &uMajorType, &uNumber, &uAdditionalInfo); + + // Error out here if we got into trouble on the type and number. + // The code after this will not work if the type and number is not good. + if(nReturn) + goto Done; + + memset(pDecodedItem, 0, sizeof(QCBORItem)); + + // At this point the major type and the value are valid. We've got the type and the number that + // starts every CBOR data item. + switch (uMajorType) { + case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0 + case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1 + nReturn = DecodeInteger(uMajorType, uNumber, pDecodedItem); + break; + + case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2 + case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3 + if(uAdditionalInfo == LEN_IS_INDEFINITE) { + pDecodedItem->uDataType = (uMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING; + pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX}; + } else { + nReturn = DecodeBytes(pAlloc, uMajorType, uNumber, pUInBuf, pDecodedItem); + } + break; + + case CBOR_MAJOR_TYPE_ARRAY: // Major type 4 + case CBOR_MAJOR_TYPE_MAP: // Major type 5 + // Record the number of items in the array or map + if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) { + nReturn = QCBOR_ERR_ARRAY_TOO_LONG; + goto Done; + } + if(uAdditionalInfo == LEN_IS_INDEFINITE) { + pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length + } else { + pDecodedItem->val.uCount = (uint16_t)uNumber; // type conversion OK because of check above + } + pDecodedItem->uDataType = uMajorType; // C preproc #if above makes sure constants align + break; + + case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags + pDecodedItem->val.uTagV = uNumber; + pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG; + break; + + case CBOR_MAJOR_TYPE_SIMPLE: // Major type 7, float, double, true, false, null... + nReturn = DecodeSimple(uAdditionalInfo, uNumber, pDecodedItem); + break; + + default: // Should never happen because DecodeTypeAndNumber() should never return > 7 + nReturn = QCBOR_ERR_UNSUPPORTED; + break; + } + +Done: + return nReturn; +} + + + +/* + This layer deals with indefinite length strings. It pulls all the + individual chunk items together into one QCBORItem using the + string allocator. + + Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH + */ +static inline QCBORError GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem) +{ + // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96 + QCBORError nReturn; + QCBORStringAllocator *pAlloc = (QCBORStringAllocator *)me->pStringAllocator; + UsefulBufC FullString = NULLUsefulBufC; + + nReturn = GetNext_Item(&(me->InBuf), pDecodedItem, me->bStringAllocateAll ? pAlloc: NULL); + if(nReturn) { + goto Done; + } + + // To reduce code size by removing support for indefinite length strings, the + // code in this function from here down can be eliminated. Run tests, except + // indefinite length string tests, to be sure all is OK if this is removed. + + // Only do indefinite length processing on strings + if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING && pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) { + goto Done; // no need to do any work here on non-string types + } + + // Is this a string with an indefinite length? + if(pDecodedItem->val.string.len != SIZE_MAX) { + goto Done; // length is not indefinite, so no work to do here + } + + // Can't do indefinite length strings without a string allocator + if(pAlloc == NULL) { + nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR; + goto Done; + } + + // There is an indefinite length string to work on... + // Track which type of string it is + const uint8_t uStringType = pDecodedItem->uDataType; + + // Loop getting chunk of indefinite string + for(;;) { + // Get item for next chunk + QCBORItem StringChunkItem; + // NULL passed to never string alloc chunk of indefinite length strings + nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL); + if(nReturn) { + break; // Error getting the next chunk + } + + // See if it is a marker at end of indefinite length string + if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) { + // String is complete + pDecodedItem->val.string = FullString; + pDecodedItem->uDataAlloc = 1; + break; + } + + // Match data type of chunk to type at beginning. + // Also catches error of other non-string types that don't belong. + if(StringChunkItem.uDataType != uStringType) { + nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK; + break; + } + + // Alloc new buffer or expand previously allocated buffer so it can fit + UsefulBuf NewMem = (*pAlloc->fAllocate)(pAlloc->pAllocaterContext, + UNCONST_POINTER(FullString.ptr), + FullString.len + StringChunkItem.val.string.len); + if(UsefulBuf_IsNULL(NewMem)) { + // Allocation of memory for the string failed + nReturn = QCBOR_ERR_STRING_ALLOCATE; + break; + } + + // Copy new string chunk at the end of string so far. + FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string); + } + +Done: + if(pAlloc && nReturn && !UsefulBuf_IsNULLC(FullString)) { + // Getting item failed, clean up the allocated memory + (pAlloc->fFree)(pAlloc->pAllocaterContext, UNCONST_POINTER(FullString.ptr)); + } + + return nReturn; +} + + +/* + Returns an error if there was something wrong with the optional item or it couldn't + be handled. + */ +static QCBORError GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem, QCBORTagListOut *pTags) +{ + // Stack usage: int/ptr: 3 -- 24 + QCBORError nReturn; + uint64_t uTagBits = 0; + if(pTags) { + pTags->uNumUsed = 0; + } + + for(;;) { + nReturn = GetNext_FullItem(me, pDecodedItem); + if(nReturn) { + goto Done; // Error out of the loop + } + + if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) { + // Successful exit from loop; maybe got some tags, maybe not + pDecodedItem->uTagBits = uTagBits; + break; + } + + uint8_t uTagBitIndex; + // Tag was mapped, tag was not mapped, error with tag list + switch(TagMapper_Lookup(me->pCallerConfiguredTagList, pDecodedItem->val.uTagV, &uTagBitIndex)) { + + case QCBOR_SUCCESS: + // Successfully mapped the tag + uTagBits |= 0x01ULL << uTagBitIndex; + break; + + case QCBOR_ERR_BAD_OPT_TAG: + // Tag is not recognized. Do nothing + break; + + default: + // Error Condition + goto Done; + } + + if(pTags) { + // Caller wants all tags recorded in the provided buffer + if(pTags->uNumUsed >= pTags->uNumAllocated) { + nReturn = QCBOR_ERR_TOO_MANY_TAGS; + goto Done; + } + pTags->puTags[pTags->uNumUsed] = pDecodedItem->val.uTagV; + pTags->uNumUsed++; + } + } + + switch(pDecodedItem->uTagBits & TAG_MAPPER_FIRST_FOUR) { + case 0: + // No tags at all or none we know about. Nothing to do. + // This is part of the pass-through path of this function + // that will mostly be taken when decoding any item. + break; + + case QCBOR_TAGFLAG_DATE_STRING: + nReturn = DecodeDateString(pDecodedItem); + break; + + case QCBOR_TAGFLAG_DATE_EPOCH: + nReturn = DecodeDateEpoch(pDecodedItem); + break; + + case QCBOR_TAGFLAG_POS_BIGNUM: + case QCBOR_TAGFLAG_NEG_BIGNUM: + nReturn = DecodeBigNum(pDecodedItem); + break; + + default: + // Encountering some mixed up CBOR like something that + // is tagged as both a string and integer date. + nReturn = QCBOR_ERR_BAD_OPT_TAG; + } + +Done: + return nReturn; +} + + +/* + This layer takes care of map entries. It combines the label and data items into one QCBORItem. + */ +static inline QCBORError GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem, QCBORTagListOut *pTags) +{ + // Stack use: int/ptr 1, QCBORItem -- 56 + QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags); + if(nReturn) + goto Done; + + if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) { + // Break can't be a map entry + goto Done; + } + + if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) { + // In a map and caller wants maps decoded, not treated as arrays + + if(DecodeNesting_TypeIsMap(&(me->nesting))) { + // If in a map and the right decoding mode, get the label + + // Get the next item which will be the real data; Item will be the label + QCBORItem LabelItem = *pDecodedItem; + nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags); + if(nReturn) + goto Done; + + pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc; + + if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) { + // strings are always good labels + pDecodedItem->label.string = LabelItem.val.string; + pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING; + } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) { + // It's not a string and we only want strings, probably for easy translation to JSON + nReturn = QCBOR_ERR_MAP_LABEL_TYPE; + goto Done; + } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) { + pDecodedItem->label.int64 = LabelItem.val.int64; + pDecodedItem->uLabelType = QCBOR_TYPE_INT64; + } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) { + pDecodedItem->label.uint64 = LabelItem.val.uint64; + pDecodedItem->uLabelType = QCBOR_TYPE_UINT64; + } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) { + pDecodedItem->label.string = LabelItem.val.string; + pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc; + pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING; + } else { + // label is not an int or a string. It is an arrray + // or a float or such and this implementation doesn't handle that. + // Also, tags on labels are ignored. + nReturn = QCBOR_ERR_MAP_LABEL_TYPE; + goto Done; + } + } + } else { + if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) { + // Decoding a map as an array + pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY; + pDecodedItem->val.uCount *= 2; + } + } + +Done: + return nReturn; +} + + +/* + Public function, see header qcbor.h file + */ +QCBORError QCBORDecode_GetNextWithTags(QCBORDecodeContext *me, QCBORItem *pDecodedItem, QCBORTagListOut *pTags) +{ + // Stack ptr/int: 2, QCBORItem : 64 + + // The public entry point for fetching and parsing the next QCBORItem. + // All the CBOR parsing work is here and in subordinate calls. + QCBORError nReturn; + + nReturn = GetNext_MapEntry(me, pDecodedItem, pTags); + if(nReturn) { + goto Done; + } + + // Break ending arrays/maps are always processed at the end of this function. + // They should never show up here. + if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) { + nReturn = QCBOR_ERR_BAD_BREAK; + goto Done; + } + + // Record the nesting level for this data item before processing any of + // decrementing and descending. + pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting)); + + // Process the item just received for descent or decrement, and + // ascent if decrements are enough to close out a definite length array/map + if(IsMapOrArray(pDecodedItem->uDataType)) { + // If the new item is array or map, the nesting level descends + nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem); + // Maps and arrays do count in as items in the map/array that encloses + // them so a decrement needs to be done for them too, but that is done + // only when all the items in them have been processed, not when they + // are opened. + } else { + // Decrement the count of items in the enclosing map/array + // If the count in the enclosing map/array goes to zero, that + // triggers a decrement in the map/array above that and + // an ascend in nesting level. + DecodeNesting_DecrementCount(&(me->nesting)); + } + if(nReturn) { + goto Done; + } + + // For indefinite length maps/arrays, looking at any and + // all breaks that might terminate them. The equivalent + // for definite length maps/arrays happens in + // DecodeNesting_DecrementCount(). + if(DecodeNesting_IsNested(&(me->nesting)) && DecodeNesting_IsIndefiniteLength(&(me->nesting))) { + while(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) { + // Peek forward one item to see if it is a break. + QCBORItem Peek; + size_t uPeek = UsefulInputBuf_Tell(&(me->InBuf)); + nReturn = GetNext_Item(&(me->InBuf), &Peek, NULL); + if(nReturn) { + goto Done; + } + if(Peek.uDataType != QCBOR_TYPE_BREAK) { + // It is not a break, rewind so it can be processed normally. + UsefulInputBuf_Seek(&(me->InBuf), uPeek); + break; + } + // It is a break. Ascend one nesting level. + // The break is consumed. + nReturn = DecodeNesting_BreakAscend(&(me->nesting)); + if(nReturn) { + // break occured outside of an indefinite length array/map + goto Done; + } + } + } + + // Tell the caller what level is next. This tells them what maps/arrays + // were closed out and makes it possible for them to reconstruct + // the tree with just the information returned by GetNext + pDecodedItem->uNextNestLevel = DecodeNesting_GetLevel(&(me->nesting)); + +Done: + return nReturn; +} + + +QCBORError QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem) +{ + return QCBORDecode_GetNextWithTags(me, pDecodedItem, NULL); +} + + +/* + Decoding items is done in 5 layered functions, one calling the + next one down. If a layer has no work to do for a particular item + it returns quickly. + + - QCBORDecode_GetNext -- The top layer manages the beginnings and + ends of maps and arrays. It tracks descending into and ascending + out of maps/arrays. It processes all breaks that terminate + maps and arrays. + + - GetNext_MapEntry -- This handles the combining of two + items, the label and the data, that make up a map entry. + It only does work on maps. It combines the label and data + items into one labeled item. + + - GetNext_TaggedItem -- This handles the type 6 tagged items. + It accumulates all the tags and combines them with the following + non-tagged item. If the tagged item is something that is understood + like a date, the decoding of that item is invoked. + + - GetNext_FullItem -- This assembles the sub items that make up + an indefinte length string into one string item. It uses the + string allocater to create contiguous space for the item. It + processes all breaks that are part of indefinite length strings. + + - GetNext_Item -- This gets and decodes the most atomic + item in CBOR, the thing with an initial byte containing + the major type. + + Roughly this takes 300 bytes of stack for vars. Need to + evaluate this more carefully and correctly. + + */ + + +/* + Public function, see header qcbor.h file + */ +int QCBORDecode_IsTagged(QCBORDecodeContext *me, const QCBORItem *pItem, uint64_t uTag) +{ + const QCBORTagListIn *pCallerConfiguredTagMap = me->pCallerConfiguredTagList; + + uint8_t uTagBitIndex; + // Do not care about errors in pCallerConfiguredTagMap here. They are + // caught during GetNext() before this is called. + if(TagMapper_Lookup(pCallerConfiguredTagMap, uTag, &uTagBitIndex)) { + return 0; + } + + const uint64_t uTagBit = 0x01ULL << uTagBitIndex; + return (uTagBit & pItem->uTagBits) != 0; +} + + +/* + Public function, see header qcbor.h file + */ +QCBORError QCBORDecode_Finish(QCBORDecodeContext *me) +{ + int nReturn = QCBOR_SUCCESS; + + // Error out if all the maps/arrays are not closed out + if(DecodeNesting_IsNested(&(me->nesting))) { + nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN; + goto Done; + } + + // Error out if not all the bytes are consumed + if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) { + nReturn = QCBOR_ERR_EXTRA_BYTES; + } + +Done: + // Call the destructor for the string allocator if there is one. + // Always called, even if there are errors; always have to clean up + if(me->pStringAllocator) { + QCBORStringAllocator *pAllocator = (QCBORStringAllocator *)me->pStringAllocator; + if(pAllocator->fDestructor) { + (pAllocator->fDestructor)(pAllocator->pAllocaterContext); + } + } + + return nReturn; +} + + + +/* + +Decoder errors handled in this file + + - Hit end of input before it was expected while decoding type and number QCBOR_ERR_HIT_END + + - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW + + - Hit end of input while decoding a text or byte string QCBOR_ERR_HIT_END + + - Encountered conflicting tags -- e.g., an item is tagged both a date string and an epoch date QCBOR_ERR_UNSUPPORTED + + - Encontered an array or mapp that has too many items QCBOR_ERR_ARRAY_TOO_LONG + + - Encountered array/map nesting that is too deep QCBOR_ERR_ARRAY_NESTING_TOO_DEEP + + - An epoch date > INT64_MAX or < INT64_MIN was encountered QCBOR_ERR_DATE_OVERFLOW + + - The type of a map label is not a string or int QCBOR_ERR_MAP_LABEL_TYPE + + - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES + + */ + + + + +/* + This is a very primitive memory allocator. It does not track individual + allocations, only a high-water mark. A free or reallotcation must be of + the last chunk allocated. + + All of this following code will get dead-stripped if QCBORDecode_SetMemPool() + is not called. + */ + +typedef struct { + QCBORStringAllocator StringAllocator; + uint8_t *pStart; // First byte that can be allocated + uint8_t *pEnd; // One past the last byte that can be allocated + uint8_t *pFree; // Where the next free chunk is +} MemPool; + + +/* + Internal function for an allocation + + Code Reviewers: THIS FUNCTION DOES POINTER MATH + */ +static UsefulBuf MemPool_Alloc(void *ctx, void *pMem, size_t uNewSize) +{ + MemPool *me = (MemPool *)ctx; + void *pReturn = NULL; + + if(pMem) { + // Realloc case + // This check will work even if uNewSize is a super-large value like UINT64_MAX + if((uNewSize <= (size_t)(me->pEnd - (uint8_t *)pMem)) && ((uint8_t *)pMem >= me->pStart)) { + me->pFree = (uint8_t *)pMem + uNewSize; + pReturn = pMem; + } + } else { + // New chunk case + // This check will work even if uNewSize is a super large value like UINT64_MAX + if(uNewSize <= (size_t)(me->pEnd - me->pFree)) { + pReturn = me->pFree; + me->pFree += uNewSize; + } + } + + return (UsefulBuf){pReturn, uNewSize}; +} + +/* + Internal function to free memory + */ +static void MemPool_Free(void *ctx, void *pOldMem) +{ + MemPool *me = (MemPool *)ctx; + me->pFree = pOldMem; +} + +/* + Public function, see header qcbor.h file + */ +QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *me, UsefulBuf Pool, bool bAllStrings) +{ + // The idea behind QCBOR_MIN_MEM_POOL_SIZE is + // that the caller knows exactly what size to + // allocate and that the tests can run conclusively + // no matter what size MemPool is + // even though it wastes some memory. MemPool + // will vary depending on pointer size of the + // the machine. QCBOR_MIN_MEM_POOL_SIZE is + // set for pointers up to 64-bits. This + // wastes about 50 bytes on a 32-bit machine. + // This check makes sure things don't go + // horribly wrong. It should optimize out + // when there is no problem as the sizes are + // known at compile time. + if(sizeof(MemPool) > QCBOR_DECODE_MIN_MEM_POOL_SIZE) { + return QCBOR_ERR_MEM_POOL_INTERNAL; + } + + // The first bytes of the Pool passed in are used + // as the context (vtable of sorts) for the memory pool + // allocator. + if(Pool.len < QCBOR_DECODE_MIN_MEM_POOL_SIZE) { + return QCBOR_ERR_BUFFER_TOO_SMALL; + } + MemPool *pMP = (MemPool *)Pool.ptr; + + // Fill in the "vtable" + pMP->StringAllocator.fAllocate = MemPool_Alloc; + pMP->StringAllocator.fFree = MemPool_Free; + pMP->StringAllocator.fDestructor = NULL; + + // Set up the pointers to the memory to be allocated + pMP->pStart = (uint8_t *)Pool.ptr + QCBOR_DECODE_MIN_MEM_POOL_SIZE; + pMP->pFree = pMP->pStart; + pMP->pEnd = (uint8_t *)Pool.ptr + Pool.len; + + // More book keeping of context + pMP->StringAllocator.pAllocaterContext = pMP; + me->pStringAllocator = pMP; + + // The flag indicating when to use the allocator + me->bStringAllocateAll = bAllStrings; + + return QCBOR_SUCCESS; +} + + +/* + Extra little hook to make MemPool testing work right + without adding any code size or overhead to non-test + uses. This will get dead-stripped for non-test use. + + This is not a public function. + */ +size_t MemPoolTestHook_GetPoolSize(void *ctx) +{ + MemPool *me = (MemPool *)ctx; + + return me->pEnd - me->pStart; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/src/qcbor_encode.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/src/qcbor_encode.c new file mode 100644 index 0000000..de22c6c --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/src/qcbor_encode.c @@ -0,0 +1,650 @@ +/*============================================================================== + Copyright (c) 2016-2018, The Linux Foundation. + Copyright (c) 2018-2019, Laurence Lundblade. + All rights reserved. + SPDX-License-Identifier: BSD-3-Clause + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors, nor the name "Laurence Lundblade" may be used to + endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ==============================================================================*/ + +/*=================================================================================== + FILE: qcbor_encode.c + + DESCRIPTION: This file contains the implementation of QCBOR. + + EDIT HISTORY FOR FILE: + + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. + + when who what, where, why + -------- ---- --------------------------------------------------- + 12/30/18 llundblade Small efficient clever encode of type & argument. + 11/29/18 llundblade Rework to simpler handling of tags and labels. + 11/9/18 llundblade Error codes are now enums. + 11/1/18 llundblade Floating support. + 10/31/18 llundblade Switch to one license that is almost BSD-3. + 09/28/18 llundblade Added bstr wrapping feature for COSE implementation. + 02/05/18 llundbla Works on CPUs which require integer alignment. + Requires new version of UsefulBuf. + 07/05/17 llundbla Add bstr wrapping of maps/arrays for COSE + 03/01/17 llundbla More data types + 11/13/16 llundbla Integrate most TZ changes back into github version. + 09/30/16 gkanike Porting to TZ. + 03/15/16 llundbla Initial Version. + + =====================================================================================*/ + +#include "qcbor.h" +#include "ieee754.h" + + +/*...... This is a ruler that is 80 characters long...........................*/ + + +/* + CBOR's two nesting types, arrays and maps, are tracked here. There is a + limit of QCBOR_MAX_ARRAY_NESTING to the number of arrays and maps + that can be nested in one encoding so the encoding context stays + small enough to fit on the stack. + + When an array / map is opened, pCurrentNesting points to the element + in pArrays that records the type, start position and accumluates a + count of the number of items added. When closed the start position is + used to go back and fill in the type and number of items in the array + / map. + + Encoded output be just items like ints and strings that are + not part of any array / map. That is, the first thing encoded + does not have to be an array or a map. + */ +inline static void Nesting_Init(QCBORTrackNesting *pNesting) +{ + // assumes pNesting has been zeroed + pNesting->pCurrentNesting = &pNesting->pArrays[0]; + // Implied CBOR array at the top nesting level. This is never returned, + // but makes the item count work correctly. + pNesting->pCurrentNesting->uMajorType = CBOR_MAJOR_TYPE_ARRAY; +} + +inline static QCBORError Nesting_Increase(QCBORTrackNesting *pNesting, + uint8_t uMajorType, + uint32_t uPos) +{ + QCBORError nReturn = QCBOR_SUCCESS; + + if(pNesting->pCurrentNesting == &pNesting->pArrays[QCBOR_MAX_ARRAY_NESTING]) { + // trying to open one too many + nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP; + } else { + pNesting->pCurrentNesting++; + pNesting->pCurrentNesting->uCount = 0; + pNesting->pCurrentNesting->uStart = uPos; + pNesting->pCurrentNesting->uMajorType = uMajorType; + } + return nReturn; +} + +inline static void Nesting_Decrease(QCBORTrackNesting *pNesting) +{ + pNesting->pCurrentNesting--; +} + +inline static QCBORError Nesting_Increment(QCBORTrackNesting *pNesting) +{ + if(1 >= QCBOR_MAX_ITEMS_IN_ARRAY - pNesting->pCurrentNesting->uCount) { + return QCBOR_ERR_ARRAY_TOO_LONG; + } + + pNesting->pCurrentNesting->uCount += 1; + + return QCBOR_SUCCESS; +} + +inline static uint16_t Nesting_GetCount(QCBORTrackNesting *pNesting) +{ + // The nesting count recorded is always the actual number of individiual + // data items in the array or map. For arrays CBOR uses the actual item + // count. For maps, CBOR uses the number of pairs. This function returns + // the number needed for the CBOR encoding, so it divides the number of + // items by two for maps to get the number of pairs. This implementation + // takes advantage of the map major type being one larger the array major + // type, hence uDivisor is either 1 or 2. + const uint16_t uDivisor = pNesting->pCurrentNesting->uMajorType - CBOR_MAJOR_TYPE_ARRAY+1; + + return pNesting->pCurrentNesting->uCount / uDivisor; +} + +inline static uint32_t Nesting_GetStartPos(QCBORTrackNesting *pNesting) +{ + return pNesting->pCurrentNesting->uStart; +} + +inline static uint8_t Nesting_GetMajorType(QCBORTrackNesting *pNesting) +{ + return pNesting->pCurrentNesting->uMajorType; +} + +inline static int Nesting_IsInNest(QCBORTrackNesting *pNesting) +{ + return pNesting->pCurrentNesting == &pNesting->pArrays[0] ? 0 : 1; +} + + + + +/* + Error tracking plan -- Errors are tracked internally and not returned + until Finish is called. The CBOR errors are in me->uError. + UsefulOutBuf also tracks whether the buffer is full or not in its + context. Once either of these errors is set they are never + cleared. Only QCBOREncode_Init() resets them. Or said another way, they must + never be cleared or we'll tell the caller all is good when it is not. + + Only one error code is reported by QCBOREncode_Finish() even if there are + multiple errors. The last one set wins. The caller might have to fix + one error to reveal the next one they have to fix. This is OK. + + The buffer full error tracked by UsefulBuf is only pulled out of + UsefulBuf in Finish() so it is the one that usually wins. UsefulBuf + will never go off the end of the buffer even if it is called again + and again when full. + + It is really tempting to not check for overflow on the count in the + number of items in an array. It would save a lot of code, it is + extremely unlikely that any one will every put 65,000 items in an + array, and the only bad thing that would happen is the CBOR would be + bogus. + + Since this does not parse any input, you could in theory remove all + error checks in this code if you knew the caller called it + correctly. Maybe someday CDDL or some such language will be able to + generate the code to call this and the calling code would always be + correct. This could also automatically size some of the data + structures like array/map nesting resulting in some stack memory + savings. + + Errors returned here fall into two categories: + + Sizes + QCBOR_ERR_BUFFER_TOO_LARGE -- Encoded output exceeded UINT32_MAX + QCBOR_ERR_BUFFER_TOO_SMALL -- output buffer too small + + QCBOR_ERR_ARRAY_NESTING_TOO_DEEP -- Array/map nesting > QCBOR_MAX_ARRAY_NESTING1 + QCBOR_ERR_ARRAY_TOO_LONG -- Too many things added to an array/map + + Nesting constructed incorrectly + QCBOR_ERR_TOO_MANY_CLOSES -- more close calls than opens + QCBOR_ERR_CLOSE_MISMATCH -- Type of close does not match open + QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN -- Finish called without enough closes + */ + + + + +/* + Public function for initialization. See header qcbor.h + */ +void QCBOREncode_Init(QCBOREncodeContext *me, UsefulBuf Storage) +{ + memset(me, 0, sizeof(QCBOREncodeContext)); + UsefulOutBuf_Init(&(me->OutBuf), Storage); + Nesting_Init(&(me->nesting)); +} + + + + +/* + All CBOR data items have a type and an "argument". The argument is + either the value of the item for integer types, the length of the + content for string, byte, array and map types, a tag for major type + 6, and has several uses for major type 7. + + This function encodes the type and the argument. There are several + encodings for the argument depending on how large it is and how it is + used. + + Every encoding of the type and argument has at least one byte, the + "initial byte". + + The top three bits of the initial byte are the major type for the + CBOR data item. The eight major types defined by the standard are + defined as CBOR_MAJOR_TYPE_xxxx in qcbor.h. + + The remaining five bits, known as "additional information", and + possibly more bytes encode the argument. If the argument is less than + 24, then it is encoded entirely in the five bits. This is neat + because it allows you to encode an entire CBOR data item in 1 byte + for many values and types (integers 0-23, true, false, and tags). + + If the argument is larger than 24, then it is encoded in 1,2,4 or 8 + additional bytes, with the number of these bytes indicated by the + values of the 5 bits 24, 25, 25 and 27. + + It is possible to encode a particular argument in many ways with this + representation. This implementation always uses the smallest + possible representation. This conforms with CBOR preferred encoding. + + This function inserts them into the output buffer at the specified + position. AppendEncodedTypeAndNumber() appends to the end. + + This function takes care of converting to network byte order. + + This function is also used to insert floats and doubles. Before this + function is called the float or double must be copied into a + uint64_t. That is how they are passed in. They are then converted to + network byte order correctly. The uMinLen param makes sure that even + + if all the digits of a half, float or double are 0 it is still + correctly encoded in 2, 4 or 8 bytes. + */ + +static void InsertEncodedTypeAndNumber(QCBOREncodeContext *me, + uint8_t uMajorType, + int nMinLen, + uint64_t uNumber, + size_t uPos) +{ + /* + This code does endian conversion without hton or knowing the + endianness of the machine using masks and shifts. This avoids the + dependency on hton and the mess of figuring out how to find the + machine's endianness. + + This is a good efficient implementation on little-endian machines. + A faster and small implementation is possible on big-endian + machines because CBOR/network byte order is big endian. However + big endian machines are uncommon. + + On x86, it is about 200 bytes instead of 500 bytes for the more + formal unoptimized code. + + This also does the CBOR preferred shortest encoding for integers + and is called to do endian conversion for floats. + + It works backwards from the LSB to the MSB as needed. + + Code Reviewers: THIS FUNCTION DOES POINTER MATH + */ + // Holds up to 9 bytes of type and argument + // plus one extra so pointer always points to + // valid bytes. + uint8_t bytes[sizeof(uint64_t)+2]; + // Point to the last bytes and work backwards + uint8_t *pByte = &bytes[sizeof(bytes)-1]; + // This is the 5 bits in the initial byte that is not the major type + uint8_t uAdditionalInfo; + + if(uNumber < CBOR_TWENTY_FOUR && nMinLen == 0) { + // Simple case where argument is < 24 + uAdditionalInfo = uNumber; + } else { + /* + Encode argument in 1,2,4 or 8 bytes. Outer loop + runs once for 1 byte and 4 times for 8 bytes. + Inner loop runs 1, 2 or 4 times depending on + outer loop counter. This works backwards taking + 8 bits off the argument being encoded at a time + until all bits from uNumber have been encoded + and the minimum encoding size is reached. + Minimum encoding size is for floating point + numbers with zero bytes. + */ + static const uint8_t aIterate[] = {1,1,2,4}; + uint8_t i; + for(i = 0; uNumber || nMinLen > 0; i++) { + const uint8_t uIterations = aIterate[i]; + for(int j = 0; j < uIterations; j++) { + *--pByte = uNumber & 0xff; + uNumber = uNumber >> 8; + } + nMinLen -= uIterations; + } + // Additional info is the encoding of the + // number of additional bytes to encode + // argument. + uAdditionalInfo = LEN_IS_ONE_BYTE-1 + i; + } + *--pByte = (uMajorType << 5) + uAdditionalInfo; + + UsefulOutBuf_InsertData(&(me->OutBuf), pByte, &bytes[sizeof(bytes)-1] - pByte, uPos); +} + + +/* + Append the type and number info to the end of the buffer. + + See InsertEncodedTypeAndNumber() function above for details +*/ +inline static void AppendEncodedTypeAndNumber(QCBOREncodeContext *me, + uint8_t uMajorType, + uint64_t uNumber) +{ + // An append is an insert at the end. + InsertEncodedTypeAndNumber(me, + uMajorType, + 0, + uNumber, + UsefulOutBuf_GetEndPosition(&(me->OutBuf))); +} + + + + +/* + Public functions for closing arrays and maps. See header qcbor.h + */ +void QCBOREncode_AddUInt64(QCBOREncodeContext *me, uint64_t uValue) +{ + if(me->uError == QCBOR_SUCCESS) { + AppendEncodedTypeAndNumber(me, CBOR_MAJOR_TYPE_POSITIVE_INT, uValue); + me->uError = Nesting_Increment(&(me->nesting)); + } +} + + +/* + Public functions for closing arrays and maps. See header qcbor.h + */ +void QCBOREncode_AddInt64(QCBOREncodeContext *me, int64_t nNum) +{ + if(me->uError == QCBOR_SUCCESS) { + uint8_t uMajorType; + uint64_t uValue; + + if(nNum < 0) { + // In CBOR -1 encodes as 0x00 with major type negative int. + uValue = (uint64_t)(-nNum - 1); + uMajorType = CBOR_MAJOR_TYPE_NEGATIVE_INT; + } else { + uValue = (uint64_t)nNum; + uMajorType = CBOR_MAJOR_TYPE_POSITIVE_INT; + } + + AppendEncodedTypeAndNumber(me, uMajorType, uValue); + me->uError = Nesting_Increment(&(me->nesting)); + } +} + + +/* + Semi-private function. It is exposed to user of the interface, + but they will usually call one of the inline wrappers rather than this. + + See header qcbor.h + + Does the work of adding some bytes to the CBOR output. Works for a + byte and text strings, which are the same in in CBOR though they have + different major types. This is also used to insert raw + pre-encoded CBOR. + */ +void QCBOREncode_AddBuffer(QCBOREncodeContext *me, uint8_t uMajorType, UsefulBufC Bytes) +{ + if(me->uError == QCBOR_SUCCESS) { + // If it is not Raw CBOR, add the type and the length + if(uMajorType != CBOR_MAJOR_NONE_TYPE_RAW) { + AppendEncodedTypeAndNumber(me, uMajorType, Bytes.len); + } + + // Actually add the bytes + UsefulOutBuf_AppendUsefulBuf(&(me->OutBuf), Bytes); + + // Update the array counting if there is any nesting at all + me->uError = Nesting_Increment(&(me->nesting)); + } +} + + +/* + Public functions for closing arrays and maps. See header qcbor.h + */ +void QCBOREncode_AddTag(QCBOREncodeContext *me, uint64_t uTag) +{ + AppendEncodedTypeAndNumber(me, CBOR_MAJOR_TYPE_OPTIONAL, uTag); +} + + +/* + Semi-private function. It is exposed to user of the interface, + but they will usually call one of the inline wrappers rather than this. + + See header qcbor.h + */ +void QCBOREncode_AddType7(QCBOREncodeContext *me, size_t uSize, uint64_t uNum) +{ + if(me->uError == QCBOR_SUCCESS) { + // This function call takes care of endian swapping for the float / double + InsertEncodedTypeAndNumber(me, + // The major type for floats and doubles + CBOR_MAJOR_TYPE_SIMPLE, + // size makes sure floats with zeros encode correctly + (int)uSize, + // Bytes of the floating point number as a uint + uNum, + // end position because this is append + UsefulOutBuf_GetEndPosition(&(me->OutBuf))); + + me->uError = Nesting_Increment(&(me->nesting)); + } +} + + +/* + Public functions for closing arrays and maps. See header qcbor.h + */ +void QCBOREncode_AddDouble(QCBOREncodeContext *me, double dNum) +{ + const IEEE754_union uNum = IEEE754_DoubleToSmallest(dNum); + + QCBOREncode_AddType7(me, uNum.uSize, uNum.uValue); +} + + +/* + Semi-public function. It is exposed to user of the interface, + but they will usually call one of the inline wrappers rather than this. + + See header qcbor.h +*/ +void QCBOREncode_OpenMapOrArray(QCBOREncodeContext *me, uint8_t uMajorType) +{ + // Add one item to the nesting level we are in for the new map or array + me->uError = Nesting_Increment(&(me->nesting)); + if(me->uError == QCBOR_SUCCESS) { + // The offset where the length of an array or map will get written + // is stored in a uint32_t, not a size_t to keep stack usage smaller. This + // checks to be sure there is no wrap around when recording the offset. + // Note that on 64-bit machines CBOR larger than 4GB can be encoded as long as no + // array / map offsets occur past the 4GB mark, but the public interface + // says that the maximum is 4GB to keep the discussion simpler. + size_t uEndPosition = UsefulOutBuf_GetEndPosition(&(me->OutBuf)); + + // QCBOR_MAX_ARRAY_OFFSET is slightly less than UINT32_MAX so this + // code can run on a 32-bit machine and tests can pass on a 32-bit + // machine. If it was exactly UINT32_MAX, then this code would + // not compile or run on a 32-bit machine and an #ifdef or some + // machine size detection would be needed reducing portability. + if(uEndPosition >= QCBOR_MAX_ARRAY_OFFSET) { + me->uError = QCBOR_ERR_BUFFER_TOO_LARGE; + + } else { + // Increase nesting level because this is a map or array. + // Cast from size_t to uin32_t is safe because of check above + me->uError = Nesting_Increase(&(me->nesting), uMajorType, (uint32_t)uEndPosition); + } + } +} + + +/* + Public functions for closing arrays and maps. See header qcbor.h + */ +void QCBOREncode_CloseMapOrArray(QCBOREncodeContext *me, + uint8_t uMajorType, + UsefulBufC *pWrappedCBOR) +{ + if(me->uError == QCBOR_SUCCESS) { + if(!Nesting_IsInNest(&(me->nesting))) { + me->uError = QCBOR_ERR_TOO_MANY_CLOSES; + } else if(Nesting_GetMajorType(&(me->nesting)) != uMajorType) { + me->uError = QCBOR_ERR_CLOSE_MISMATCH; + } else { + // When the array, map or bstr wrap was started, nothing was done + // except note the position of the start of it. This code goes back + // and inserts the actual CBOR array, map or bstr and its length. + // That means all the data that is in the array, map or wrapped + // needs to be slid to the right. This is done by UsefulOutBuf's + // insert function that is called from inside + // InsertEncodedTypeAndNumber() + const size_t uInsertPosition = Nesting_GetStartPos(&(me->nesting)); + const size_t uEndPosition = UsefulOutBuf_GetEndPosition(&(me->OutBuf)); + // This can't go negative because the UsefulOutBuf always only grows + // and never shrinks. UsefulOutBut itself also has defenses such that + // it won't write were it should not even if given hostile input lengths + const size_t uLenOfEncodedMapOrArray = uEndPosition - uInsertPosition; + + // Length is number of bytes for a bstr and number of items a for map & array + const size_t uLength = uMajorType == CBOR_MAJOR_TYPE_BYTE_STRING ? + uLenOfEncodedMapOrArray : Nesting_GetCount(&(me->nesting)); + + // Actually insert + InsertEncodedTypeAndNumber(me, + uMajorType, // major type bstr, array or map + 0, // no minimum length for encoding + uLength, // either len of bstr or num map / array items + uInsertPosition); // position in out buffer + + // Return pointer and length to the enclosed encoded CBOR. The intended + // use is for it to be hashed (e.g., SHA-256) in a COSE implementation. + // This must be used right away, as the pointer and length go invalid + // on any subsequent calls to this function because of the + // InsertEncodedTypeAndNumber() call that slides data to the right. + if(pWrappedCBOR) { + const UsefulBufC PartialResult = UsefulOutBuf_OutUBuf(&(me->OutBuf)); + const size_t uBstrLen = UsefulOutBuf_GetEndPosition(&(me->OutBuf)) - uEndPosition; + *pWrappedCBOR = UsefulBuf_Tail(PartialResult, uInsertPosition+uBstrLen); + } + Nesting_Decrease(&(me->nesting)); + } + } +} + + + + +/* + Public functions to finish and get the encoded result. See header qcbor.h + */ +QCBORError QCBOREncode_Finish(QCBOREncodeContext *me, UsefulBufC *pEncodedCBOR) +{ + QCBORError uReturn = me->uError; + + if(uReturn != QCBOR_SUCCESS) { + goto Done; + } + + if (Nesting_IsInNest(&(me->nesting))) { + uReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN; + goto Done; + } + + if(UsefulOutBuf_GetError(&(me->OutBuf))) { + // Stuff didn't fit in the buffer. + // This check catches this condition for all the appends and inserts + // so checks aren't needed when the appends and inserts are performed. + // And of course UsefulBuf will never overrun the input buffer given + // to it. No complex analysis of the error handling in this file is + // needed to know that is true. Just read the UsefulBuf code. + uReturn = QCBOR_ERR_BUFFER_TOO_SMALL; + goto Done; + } + + *pEncodedCBOR = UsefulOutBuf_OutUBuf(&(me->OutBuf)); + +Done: + return uReturn; +} + + +/* + Public functions to finish and get the encoded result. See header qcbor.h + */ +QCBORError QCBOREncode_FinishGetSize(QCBOREncodeContext *me, size_t *puEncodedLen) +{ + UsefulBufC Enc; + + QCBORError nReturn = QCBOREncode_Finish(me, &Enc); + + if(nReturn == QCBOR_SUCCESS) { + *puEncodedLen = Enc.len; + } + + return nReturn; +} + + + + +/* + Notes on the code + + CBOR Major Type Public Function + 0 QCBOREncode_AddUInt64 + 0, 1 QCBOREncode_AddUInt64, QCBOREncode_AddInt64 + 2, 3 QCBOREncode_AddBuffer, Also QCBOREncode_OpenMapOrArray + 4, 5 QCBOREncode_OpenMapOrArray + 6 QCBOREncode_AddTag + 7 QCBOREncode_AddDouble, QCBOREncode_AddType7 + + Object code sizes on X86 with LLVM compiler and -Os (Dec 30, 2018) + + _QCBOREncode_Init 69 + _QCBOREncode_AddUInt64 76 + _QCBOREncode_AddInt64 87 + _QCBOREncode_AddBuffer 113 + _QCBOREncode_AddTag 27 + _QCBOREncode_AddType7 87 + _QCBOREncode_AddDouble 36 + _QCBOREncode_OpenMapOrArray 103 + _QCBOREncode_CloseMapOrArray 181 + _InsertEncodedTypeAndNumber 190 + _QCBOREncode_Finish 72 + _QCBOREncode_FinishGetSize 70 + + Total is about 1.1KB + + _QCBOREncode_CloseMapOrArray is larger because it has a lot + of nesting tracking to do and much of Nesting_ inlines + into it. It probably can't be reduced much. + + If the error returned by Nesting_Increment() can be ignored + because the limit is so high and the consequence of exceeding + is proved to be inconsequential, then a lot of if(me->uError) + instance can be removed, saving some code. + + */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/UsefulBuf_Tests.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/UsefulBuf_Tests.c new file mode 100644 index 0000000..bacaac5 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/UsefulBuf_Tests.c @@ -0,0 +1,698 @@ +/*============================================================================== + Copyright (c) 2016-2018, The Linux Foundation. + Copyright (c) 2018-2019, Laurence Lundblade. + All rights reserved. + SPDX-License-Identifier: BSD-3-Clause + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors, nor the name "Laurence Lundblade" may be used to + endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ==============================================================================*/ + +#include "UsefulBuf.h" + + +/* Basic exercise... + + Call all the main public functions. + + Binary compare the result to the expected. + + There is nothing adversarial in this test + */ +const char * UOBTest_NonAdversarial() +{ + const char *szReturn = NULL; + + UsefulBuf_MAKE_STACK_UB(outbuf,50); + + UsefulOutBuf UOB; + + UsefulOutBuf_Init(&UOB, outbuf); + + if(!UsefulOutBuf_AtStart(&UOB)) { + szReturn = "Not at start"; + goto Done; + } + + // Put 7 bytes at beginning of buf + UsefulOutBuf_AppendData(&UOB, "bluster", 7); + + if(UsefulOutBuf_AtStart(&UOB)) { + szReturn = "At start"; + goto Done; + } + + // add a space to end + UsefulOutBuf_AppendByte(&UOB, ' '); + + // Add 5 bytes to the end + UsefulBufC UBC = {"hunny", 5}; + UsefulOutBuf_AppendUsefulBuf(&UOB, UBC); + + // Insert 9 bytes at the beginning, slide the previous stuff right + UsefulOutBuf_InsertData(&UOB, "heffalump", 9, 0); + UsefulOutBuf_InsertByte(&UOB, ' ', 9); + + // Put 9 bytes in at position 10 -- just after "heffalump " + UsefulBufC UBC2 = {"unbounce ", 9}; + UsefulOutBuf_InsertUsefulBuf(&UOB, UBC2, 10); + + // Make it a null terminated string (because all the appends and inserts above not strcpy !) + UsefulOutBuf_AppendByte(&UOB, '\0'); + + + UsefulBufC U = UsefulOutBuf_OutUBuf(&UOB); + + const char *expected = "heffalump unbounce bluster hunny"; + + if(UsefulBuf_IsNULLC(U) || U.len-1 != strlen(expected) || strcmp(expected, U.ptr) || UsefulOutBuf_GetError(&UOB)) { + szReturn = "OutUBuf"; + } + + UsefulBuf_MAKE_STACK_UB(buf, 50); + UsefulBufC Out = UsefulOutBuf_CopyOut(&UOB, buf); + + if(UsefulBuf_IsNULLC(Out) || Out.len-1 != strlen(expected) || strcmp(expected, Out.ptr)) { + szReturn = "CopyOut"; + } + +Done: + return szReturn; +} + + +/* + Append test utility. + pUOB is the buffer to append too + num is the amount to append + expected is the expected return code, 0 or 1 + + returns 0 if test passed + + */ +static int AppendTest(UsefulOutBuf *pUOB, size_t num, int expected) +{ + //reset + UsefulOutBuf_Reset(pUOB); + + // check status first + if(UsefulOutBuf_GetError(pUOB)) + return 1; + + // append the bytes + UsefulOutBuf_AppendData(pUOB, (const uint8_t *)"bluster", num); + + // check error status after + if(UsefulOutBuf_GetError(pUOB) != expected) + return 1; + + return 0; +} + + +/* + Same as append, but takes a position param too + */ +static int InsertTest(UsefulOutBuf *pUOB, size_t num, size_t pos, int expected) +{ + // reset + UsefulOutBuf_Reset(pUOB); + + // check + if(UsefulOutBuf_GetError(pUOB)) + return 1; + + UsefulOutBuf_InsertData(pUOB, (const uint8_t *)"bluster", num, pos); + + if(UsefulOutBuf_GetError(pUOB) != expected) + return 1; + + return 0; +} + + +/* + Boundary conditions to test + - around 0 + - around the buffer size + - around MAX size_t + + + Test these for the buffer size and the cursor, the insert amount, the append amount and the insert position + + */ + +const char *UOBTest_BoundaryConditionsTest() +{ + UsefulBuf_MAKE_STACK_UB(outbuf,2); + + UsefulOutBuf UOB; + + UsefulOutBuf_Init(&UOB, outbuf); + + // append 0 byte to a 2 byte buffer --> success + if(AppendTest(&UOB, 0, 0)) + return "Append 0 bytes failed"; + + // append 1 byte to a 2 byte buffer --> success + if(AppendTest(&UOB, 1, 0)) + return "Append of 1 byte failed"; + + // append 2 byte to a 2 byte buffer --> success + if(AppendTest(&UOB, 2, 0)) + return "Append to fill buffer failed"; + + // append 3 bytes to a 2 byte buffer --> failure + if(AppendTest(&UOB, 3, 1)) + return "Overflow of buffer not caught"; + + // append max size_t to a 2 byte buffer --> failure + if(AppendTest(&UOB, SIZE_MAX, 1)) + return "Append of SIZE_MAX error not caught"; + + if(InsertTest(&UOB, 1, 0, 0)) + return "Insert 1 byte at start failed"; + + if(InsertTest(&UOB, 2, 0, 0)) + return "Insert 2 bytes at start failed"; + + if(InsertTest(&UOB, 3, 0, 1)) + return "Insert overflow not caught"; + + if(InsertTest(&UOB, 1, 1, 1)) + return "Bad insertion point not caught"; + + + UsefulBuf_MAKE_STACK_UB(outBuf2,10); + + UsefulOutBuf_Init(&UOB, outBuf2); + + UsefulOutBuf_Reset(&UOB); + // put data in the buffer + UsefulOutBuf_AppendString(&UOB, "abc123"); + + UsefulOutBuf_InsertString(&UOB, "xyz*&^", 0); + + if(!UsefulOutBuf_GetError(&UOB)) { + return "insert with data should have failed"; + } + + + UsefulOutBuf_Init(&UOB, (UsefulBuf){NULL, SIZE_MAX - 5}); + UsefulOutBuf_AppendData(&UOB, "123456789", SIZE_MAX -6); + if(UsefulOutBuf_GetError(&UOB)) { + return "insert in huge should have succeeded"; + } + + UsefulOutBuf_Init(&UOB, (UsefulBuf){NULL, SIZE_MAX - 5}); + UsefulOutBuf_AppendData(&UOB, "123456789", SIZE_MAX -5); + if(UsefulOutBuf_GetError(&UOB)) { + return "insert in huge should have succeeded"; + } + + UsefulOutBuf_Init(&UOB, (UsefulBuf){NULL, SIZE_MAX - 5}); + UsefulOutBuf_AppendData(&UOB, "123456789", SIZE_MAX - 4); + if(!UsefulOutBuf_GetError(&UOB)) { + return "lengths near max size"; + } + + return NULL; +} + + + + + +// Test function to get size and magic number check + +const char *TestBasicSanity() +{ + UsefulBuf_MAKE_STACK_UB(outbuf,10); + + UsefulOutBuf UOB; + + // First -- make sure that the room left function returns the right amount + UsefulOutBuf_Init(&UOB, outbuf); + + if(UsefulOutBuf_RoomLeft(&UOB) != 10) + return "room left failed"; + + if(!UsefulOutBuf_WillItFit(&UOB, 9)) { + return "it did not fit"; + } + + if(UsefulOutBuf_WillItFit(&UOB, 11)) { + return "it should have not fit"; + } + + + // Next -- make sure that the magic number checking is working right + UOB.magic = 8888; // make magic bogus + + UsefulOutBuf_AppendData(&UOB, (const uint8_t *)"bluster", 7); + + if(!UsefulOutBuf_GetError(&UOB)) + return "magic corruption check failed"; + + + + // Next make sure that the valid data length check is working right + UsefulOutBuf_Init(&UOB, outbuf); + + UOB.data_len = UOB.UB.len+1; // make size bogus + + UsefulOutBuf_AppendData(&UOB, (const uint8_t *)"bluster", 7); + if(!UsefulOutBuf_GetError(&UOB)) + return "valid data check failed"; + + return NULL; +} + + + +const char *UBMacroConversionsTest() +{ + char *szFoo = "foo"; + + UsefulBufC Foo = UsefulBuf_FromSZ(szFoo); + if(Foo.len != 3 || strncmp(Foo.ptr, szFoo, 3)) + return "SZToUsefulBufC failed"; + + UsefulBufC Too = UsefulBuf_FROM_SZ_LITERAL("Toooo"); + if(Too.len != 5 || strncmp(Too.ptr, "Toooo", 5)) + return "UsefulBuf_FROM_SZ_LITERAL failed"; + + uint8_t pB[] = {0x42, 0x6f, 0x6f}; + UsefulBufC Boo = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pB); + if(Boo.len != 3 || strncmp(Boo.ptr, "Boo", 3)) + return "UsefulBuf_FROM_BYTE_ARRAY_LITERAL failed"; + + char *sz = "not const"; // some data for the test + UsefulBuf B = (UsefulBuf){sz, sizeof(sz)}; + UsefulBufC BC = UsefulBuf_Const(B); + if(BC.len != sizeof(sz) || BC.ptr != sz) + return "UsefulBufConst failed"; + + return NULL; +} + + +const char *UBUtilTests() +{ + UsefulBuf UB = NULLUsefulBuf; + + if(!UsefulBuf_IsNULL(UB)){ + return "IsNull failed"; + } + + if(!UsefulBuf_IsEmpty(UB)){ + return "IsEmpty failed"; + } + + if(!UsefulBuf_IsNULLOrEmpty(UB)) { + return "IsNULLOrEmpty failed"; + } + + const UsefulBufC UBC = UsefulBuf_Const(UB); + + if(!UsefulBuf_IsNULLC(UBC)){ + return "IsNull const failed"; + } + + if(!UsefulBuf_IsEmptyC(UBC)){ + return "IsEmptyC failed"; + } + + if(!UsefulBuf_IsNULLOrEmptyC(UBC)){ + return "IsNULLOrEmptyC failed"; + } + + const UsefulBuf UB2 = UsefulBuf_Unconst(UBC); + if(!UsefulBuf_IsEmpty(UB2)) { + return "Back to UB is Empty failed"; + } + + UB.ptr = "x"; // just some valid pointer + + if(UsefulBuf_IsNULL(UB)){ + return "IsNull failed"; + } + + if(!UsefulBuf_IsEmptyC(UBC)){ + return "IsEmpty failed"; + } + + // test the Unconst. + if(UsefulBuf_Unconst(UBC).ptr != NULL) { + return "Unconst failed"; + } + + // Set 100 bytes of '+'; validated a few tests later + UsefulBuf_MAKE_STACK_UB(Temp, 100); + const UsefulBufC TempC = UsefulBuf_Set(Temp, '+'); + + // Try to copy into a buf that is too small and see failure + UsefulBuf_MAKE_STACK_UB(Temp2, 99); + if(!UsefulBuf_IsNULLC(UsefulBuf_Copy(Temp2, TempC))) { + return "Copy should have failed"; + } + + if(UsefulBuf_IsNULLC(UsefulBuf_CopyPtr(Temp2, "xx", 2))) { + return "CopyPtr failed"; + } + + UsefulBufC xxyy = UsefulBuf_CopyOffset(Temp2, 2, UsefulBuf_FROM_SZ_LITERAL("yy")); + if(UsefulBuf_IsNULLC(xxyy)) { + return "CopyOffset Failed"; + } + + if(UsefulBuf_Compare(UsefulBuf_Head(xxyy, 3), UsefulBuf_FROM_SZ_LITERAL("xxy"))) { + return "head failed"; + } + + if(UsefulBuf_Compare(UsefulBuf_Tail(xxyy, 1), UsefulBuf_FROM_SZ_LITERAL("xyy"))) { + return "tail failed"; + } + + if(!UsefulBuf_IsNULLC(UsefulBuf_Head(xxyy, 5))) { + return "head should have failed"; + } + + if(!UsefulBuf_IsNULLC(UsefulBuf_Tail(xxyy, 5))) { + return "tail should have failed"; + } + + if(!UsefulBuf_IsNULLC(UsefulBuf_Tail(NULLUsefulBufC, 0))) { + return "tail of NULLUsefulBufC is not NULLUsefulBufC"; + } + + const UsefulBufC TailResult = UsefulBuf_Tail((UsefulBufC){NULL, 100}, 99); + if(TailResult.ptr != NULL || TailResult.len != 1) { + return "tail of NULL and length incorrect"; + } + + if(!UsefulBuf_IsNULLC(UsefulBuf_CopyOffset(Temp2, 100, UsefulBuf_FROM_SZ_LITERAL("yy")))) { + return "Copy Offset should have failed"; + } + + // Try to copy into a NULL/empty buf and see failure + const UsefulBuf UBNull = NULLUsefulBuf; + if(!UsefulBuf_IsNULLC(UsefulBuf_Copy(UBNull, TempC))) { + return "Copy to NULL should have failed"; + } + + + // Try to set a NULL/empty buf; nothing should happen + UsefulBuf_Set(UBNull, '+'); // This will crash on failure + + // Copy successfully to a buffer + UsefulBuf_MAKE_STACK_UB(Temp3, 101); + if(UsefulBuf_IsNULLC(UsefulBuf_Copy(Temp3, TempC))) { + return "Copy should not have failed"; + } + + static const uint8_t pExpected[] = { + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + }; + UsefulBufC Expected = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExpected); + // This validates comparison for equality and the UsefulBuf_Set + if(UsefulBuf_Compare(Expected, TempC)) { + return "Set / Copy / Compare failed"; + } + + // Compare two empties and expect success + if(UsefulBuf_Compare(NULLUsefulBufC, NULLUsefulBufC)){ + return "Compare Empties failed"; + } + + // Compare with empty and expect the first to be larger + if(UsefulBuf_Compare(Expected, NULLUsefulBufC) <= 0){ + return "Compare with empty failed"; + } + + + static const uint8_t pExpectedBigger[] = { + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', ',', + }; + const UsefulBufC ExpectedBigger = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExpectedBigger); + + // Expect -1 when the first arg is smaller + if(UsefulBuf_Compare(Expected, ExpectedBigger) >= 0){ + return "Compare with bigger"; + } + + + static const uint8_t pExpectedSmaller[] = { + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '*', + }; + const UsefulBufC ExpectedSmaller = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExpectedSmaller); + // Expect +1 when the first arg is larger + if(UsefulBuf_Compare(Expected, ExpectedSmaller) <= 0){ + return "Compare with smaller"; + } + + + static const uint8_t pExpectedLonger[] = { + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+' + }; + const UsefulBufC ExpectedLonger = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExpectedLonger); + + // Expect -1 when the first arg is smaller + if(UsefulBuf_Compare(Expected, ExpectedLonger) >= 0){ + return "Compare with longer"; + } + + + static const uint8_t pExpectedShorter[] = { + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', + '+', '+', '+', '+', '+', '+', '+', '+', '+', + }; + const UsefulBufC ExpectedShorter = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExpectedShorter); + // Expect +1 with the first arg is larger + if(UsefulBuf_Compare(Expected, ExpectedShorter) <= 0){ + return "Compare with shorter"; + } + + + if(UsefulBuf_IsNULLC(UsefulBuf_Copy(Temp, NULLUsefulBufC))) { + return "Copy null/empty failed"; + } + + // Look for +++++... in +++++... and find it at the beginning + if(0 != UsefulBuf_FindBytes(ExpectedLonger, ExpectedShorter)){ + return "Failed to find"; + } + + // look for ++* in ....++* and find it at the end + static const uint8_t pToFind[] = {'+', '+', '*'}; + const UsefulBufC ToBeFound = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pToFind); + + if(97 != UsefulBuf_FindBytes(ExpectedSmaller, ToBeFound)){ + return "Failed to find 2"; + } + + // look for ++* in ....++, and find it near the end + if(SIZE_MAX != UsefulBuf_FindBytes(ExpectedBigger, ToBeFound)){ + return "Failed to not find"; + } + + // Look for the whole buffer in itself and succeed. + if(0 != UsefulBuf_FindBytes(ExpectedLonger, ExpectedLonger)){ + return "Failed to find 3"; + } + + return NULL; +} + + +const char * UIBTest_IntegerFormat() +{ + UsefulOutBuf_MakeOnStack(UOB,100); + + const uint32_t u32 = 0x0A0B0C0D; // from https://en.wikipedia.org/wiki/Endianness + const uint64_t u64 = 1984738472938472; + const uint16_t u16 = 40000; + const uint8_t u8 = 9; + const float f = (float)314.15; + const double d = 2.1e10; + + + UsefulOutBuf_AppendUint32(&UOB, u32); // Also tests UsefulOutBuf_InsertUint64 and UsefulOutBuf_GetEndPosition + UsefulOutBuf_AppendUint64(&UOB, u64); // Also tests UsefulOutBuf_InsertUint32 + UsefulOutBuf_AppendUint16(&UOB, u16); // Also tests UsefulOutBuf_InsertUint16 + UsefulOutBuf_AppendByte(&UOB, u8); + UsefulOutBuf_AppendFloat(&UOB, f); // Also tests UsefulOutBuf_InsertFloat + UsefulOutBuf_AppendDouble(&UOB, d); // Also tests UsefulOutBuf_InsertDouble + + const UsefulBufC O = UsefulOutBuf_OutUBuf(&UOB); + if(UsefulBuf_IsNULLC(O)) + return "Couldn't output integers"; + + // from https://en.wikipedia.org/wiki/Endianness + const uint8_t pExpectedNetworkOrder[4] = {0x0A, 0x0B, 0x0C, 0x0D}; + if(memcmp(O.ptr, pExpectedNetworkOrder, 4)) { + return "not in network order"; + } + + UsefulInputBuf UIB; + + UsefulInputBuf_Init(&UIB, O); + + if(UsefulInputBuf_Tell(&UIB) != 0) { + return "UsefulInputBuf_Tell failed"; + } + + if(UsefulInputBuf_GetUint32(&UIB) != u32) { + return "u32 out then in failed"; + } + if(UsefulInputBuf_GetUint64(&UIB) != u64) { + return "u64 out then in failed"; + } + if(UsefulInputBuf_GetUint16(&UIB) != u16) { + return "u16 out then in failed"; + } + if(UsefulInputBuf_GetByte(&UIB) != u8) { + return "u8 out then in failed"; + } + if(UsefulInputBuf_GetFloat(&UIB) != f) { + return "float out then in failed"; + } + if(UsefulInputBuf_GetDouble(&UIB) != d) { + return "double out then in failed"; + } + + // Reset and go again for a few more tests + UsefulInputBuf_Init(&UIB, O); + + const UsefulBufC Four = UsefulInputBuf_GetUsefulBuf(&UIB, 4); + if(UsefulBuf_IsNULLC(Four)) { + return "Four is NULL"; + } + if(UsefulBuf_Compare(Four, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExpectedNetworkOrder))) { + return "Four compare failed"; + } + + if(UsefulInputBuf_BytesUnconsumed(&UIB) != 23){ + return "Wrong number of unconsumed bytes"; + } + + if(!UsefulInputBuf_BytesAvailable(&UIB, 23)){ + return "Wrong number of bytes available I"; + } + + if(UsefulInputBuf_BytesAvailable(&UIB, 24)){ + return "Wrong number of bytes available II"; + } + + UsefulInputBuf_Seek(&UIB, 0); + + if(UsefulInputBuf_GetError(&UIB)) { + return "unexpected error after seek"; + } + + const uint8_t *pGetBytes = (const uint8_t *)UsefulInputBuf_GetBytes(&UIB, 4); + if(pGetBytes == NULL) { + return "GetBytes returns NULL"; + } + + if(memcmp(pGetBytes, pExpectedNetworkOrder, 4)) { + return "Got wrong bytes"; + } + + UsefulInputBuf_Seek(&UIB, 28); + + if(!UsefulInputBuf_GetError(&UIB)) { + return "expected error after seek"; + } + + return NULL; +} + + +const char *UBUTest_CopyUtil() +{ + if(UsefulBufUtil_CopyFloatToUint32(65536.0F) != 0x47800000) { + return "CopyFloatToUint32 failed"; + } + + if(UsefulBufUtil_CopyDoubleToUint64(4e-40L) != 0X37C16C2800000000ULL) { + return "CopyDoubleToUint64 failed"; + } + + if(UsefulBufUtil_CopyUint64ToDouble(0X37C16C2800000000ULL) != 4e-40L) { + return "CopyUint64ToDouble failed"; + } + + if(UsefulBufUtil_CopyUint32ToFloat(0x47800000) != 65536.0F) { + return "CopyUint32ToFloat failed"; + } + + return NULL; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/UsefulBuf_Tests.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/UsefulBuf_Tests.h new file mode 100644 index 0000000..d85b951 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/UsefulBuf_Tests.h @@ -0,0 +1,51 @@ +/*============================================================================== + Copyright (c) 2016-2018, The Linux Foundation. + Copyright (c) 2018, Laurence Lundblade. + All rights reserved. + SPDX-License-Identifier: BSD-3-Clause + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors, nor the name "Laurence Lundblade" may be used to + endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ==============================================================================*/ + +#ifndef UsefulBuf_UsefulBuf_Tests_h +#define UsefulBuf_UsefulBuf_Tests_h + +const char * UOBTest_NonAdversarial(void); + +const char * TestBasicSanity(void); + +const char * UOBTest_BoundaryConditionsTest(void); + +const char * UBMacroConversionsTest(void); + +const char * UBUtilTests(void); + +const char * UIBTest_IntegerFormat(void); + +const char * UBUTest_CopyUtil(void); + +#endif diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/float_tests.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/float_tests.c new file mode 100644 index 0000000..06f7415 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/float_tests.c @@ -0,0 +1,471 @@ +/*============================================================================== + float_tests.c -- tests for float and conversion to/from half-precision + + Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. + + SPDX-License-Identifier: BSD-3-Clause + + See BSD-3-Clause license in README.md + + Created on 9/19/18 + ==============================================================================*/ + +#include "float_tests.h" +#include "qcbor.h" +#include "half_to_double_from_rfc7049.h" +#include // For INFINITY and NAN and isnan() + + + +static const uint8_t spExpectedHalf[] = { + 0xB1, + 0x64, + 0x7A, 0x65, 0x72, 0x6F, + 0xF9, 0x00, 0x00, // 0.000 + 0x6A, + 0x69, 0x6E, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79, + 0xF9, 0x7C, 0x00, // Infinity + 0x73, + 0x6E, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x69, 0x6E, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79, + 0xF9, 0xFC, 0x00, // -Inifinity + 0x63, + 0x4E, 0x61, 0x4E, + 0xF9, 0x7E, 0x00, // NaN + 0x63, + 0x6F, 0x6E, 0x65, + 0xF9, 0x3C, 0x00, // 1.0 + 0x69, + 0x6F, 0x6E, 0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64, + 0xF9, 0x35, 0x55, // 0.333251953125 + 0x76, + 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x68, 0x61, 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6F, 0x6E, + 0xF9, 0x7B, 0xFF, // 65504.0 + 0x78, 0x18, 0x74, 0x6F, 0x6F, 0x2D, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x20, 0x68, 0x61, 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6F, 0x6E, + 0xF9, 0x7C, 0x00, // Infinity + 0x72, + 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x73, 0x75, 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, + 0xF9, 0x00, 0x01, // 0.000000059604 + 0x6F, + 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, + 0xF9, 0x03, 0xFF, // 0.0000609755516 + 0x71, + 0x62, 0x69, 0x67, 0x67, 0x65, 0x73, 0x74, 0x20, 0x73, 0x75, 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, + 0xF9, 0x04, 0x00, // 0.000061988 + 0x70, + 0x73, 0x75, 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x20, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, + 0xF9, 0x00, 0x00, + 0x03, + 0xF9, 0xC0, 0x00, // -2 + 0x04, + 0xF9, 0x7E, 0x00, // qNaN + 0x05, + 0xF9, 0x7C, 0x01, // sNaN + 0x06, + 0xF9, 0x7E, 0x0F, // qNaN with payload 0x0f + 0x07, + 0xF9, 0x7C, 0x0F, // sNaN with payload 0x0f + +}; + + +int HalfPrecisionDecodeBasicTests() +{ + UsefulBufC HalfPrecision = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedHalf); + + QCBORDecodeContext DC; + QCBORDecode_Init(&DC, HalfPrecision, 0); + + QCBORItem Item; + + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_MAP) { + return -1; + } + + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.0F) { + return -2; + } + + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != INFINITY) { + return -3; + } + + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != -INFINITY) { + return -4; + } + + QCBORDecode_GetNext(&DC, &Item); // TODO, is this really converting right? It is carrying payload, but this confuses things. + if(Item.uDataType != QCBOR_TYPE_DOUBLE || !isnan(Item.val.dfnum)) { + return -5; + } + + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 1.0F) { + return -6; + } + + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.333251953125F) { + return -7; + } + + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 65504.0F) { + return -8; + } + + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != INFINITY) { + return -9; + } + + QCBORDecode_GetNext(&DC, &Item); // TODO: check this + if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.0000000596046448F) { + return -10; + } + + QCBORDecode_GetNext(&DC, &Item); // TODO: check this + if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.0000609755516F) { + return -11; + } + + QCBORDecode_GetNext(&DC, &Item); // TODO check this + if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.0000610351563F) { + return -12; + } + + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0) { + return -13; + } + + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != -2.0F) { + return -14; + } + + // TODO: double check these four tests + QCBORDecode_GetNext(&DC, &Item); // qNaN + if(Item.uDataType != QCBOR_TYPE_DOUBLE || UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum) != 0x7ff8000000000000ULL) { + return -15; + } + QCBORDecode_GetNext(&DC, &Item); // sNaN + if(Item.uDataType != QCBOR_TYPE_DOUBLE || UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum) != 0x7ff0000000000001ULL) { + return -16; + } + QCBORDecode_GetNext(&DC, &Item); // qNaN with payload 0x0f + if(Item.uDataType != QCBOR_TYPE_DOUBLE || UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum) != 0x7ff800000000000fULL) { + return -17; + } + QCBORDecode_GetNext(&DC, &Item); // sNaN with payload 0x0f + if(Item.uDataType != QCBOR_TYPE_DOUBLE || UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum) != 0x7ff000000000000fULL) { + return -18; + } + + if(QCBORDecode_Finish(&DC)) { + return -19; + } + + return 0; +} + + + + +int HalfPrecisionAgainstRFCCodeTest() +{ + for(uint32_t uHalfP = 0; uHalfP < 0xffff; uHalfP += 60) { + unsigned char x[2]; + x[1] = uHalfP & 0xff; + x[0] = uHalfP >> 8; + double d = decode_half(x); + + // Contruct the CBOR for the half-precision float by hand + UsefulBuf_MAKE_STACK_UB(__xx, 3); + UsefulOutBuf UOB; + UsefulOutBuf_Init(&UOB, __xx); + + const uint8_t uHalfPrecInitialByte = HALF_PREC_FLOAT + (CBOR_MAJOR_TYPE_SIMPLE << 5); // 0xf9 + UsefulOutBuf_AppendByte(&UOB, uHalfPrecInitialByte); // The initial byte for a half-precision float + UsefulOutBuf_AppendUint16(&UOB, (uint16_t)uHalfP); + + // Now parse the hand-constructed CBOR. This will invoke the conversion to a float + QCBORDecodeContext DC; + QCBORDecode_Init(&DC, UsefulOutBuf_OutUBuf(&UOB), 0); + + QCBORItem Item; + + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_DOUBLE) { + return -1; + } + + //printf("%04x QCBOR:%15.15f RFC: %15.15f (%8x)\n", uHalfP,Item.val.fnum, d , UsefulBufUtil_CopyFloatToUint32(d)); + + if(isnan(d)) { + // The RFC code uses the native instructions which may or may not + // handle sNaN, qNaN and NaN payloads correctly. This test just + // makes sure it is a NaN and doesn't worry about the type of NaN + if(!isnan(Item.val.dfnum)) { + return -3; + } + } else { + if(Item.val.dfnum != d) { + return -2; + } + } + } + return 0; +} + + +/* + {"zero": 0.0, + "negative zero": -0.0, + "infinitity": Infinity, + "negative infinitity": -Infinity, + "NaN": NaN, + "one": 1.0, + "one third": 0.333251953125, + "largest half-precision": 65504.0, + "largest half-precision point one": 65504.1, + "too-large half-precision": 65536.0, + "smallest subnormal": 5.96046448e-8, + "smallest normal": 0.00006103515261202119, + "biggest subnormal": 0.00006103515625, + "subnormal single": 4.00000646641519e-40, + 3: -2.0, + "large single exp": 2.5521177519070385e+38, + "too-large single exp": 5.104235503814077e+38, + "biggest single with prec": 16777216.0, + "first single with prec loss": 16777217.0, + 1: "fin"} + */ +static const uint8_t spExpectedSmallest[] = { + 0xB4, 0x64, 0x7A, 0x65, 0x72, 0x6F, 0xF9, 0x00, 0x00, 0x6D, + 0x6E, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x7A, + 0x65, 0x72, 0x6F, 0xF9, 0x80, 0x00, 0x6A, 0x69, 0x6E, 0x66, + 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79, 0xF9, 0x7C, 0x00, + 0x73, 0x6E, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, + 0x69, 0x6E, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79, + 0xF9, 0xFC, 0x00, 0x63, 0x4E, 0x61, 0x4E, 0xF9, 0x7E, 0x00, + 0x63, 0x6F, 0x6E, 0x65, 0xF9, 0x3C, 0x00, 0x69, 0x6F, 0x6E, + 0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64, 0xF9, 0x35, 0x55, + 0x76, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x68, + 0x61, 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, + 0x69, 0x6F, 0x6E, 0xF9, 0x7B, 0xFF, 0x78, 0x20, 0x6C, 0x61, + 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x68, 0x61, 0x6C, 0x66, + 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6F, 0x6E, + 0x20, 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x20, 0x6F, 0x6E, 0x65, + 0xFB, 0x40, 0xEF, 0xFC, 0x03, 0x33, 0x33, 0x33, 0x33, 0x78, + 0x18, 0x74, 0x6F, 0x6F, 0x2D, 0x6C, 0x61, 0x72, 0x67, 0x65, + 0x20, 0x68, 0x61, 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, + 0x69, 0x73, 0x69, 0x6F, 0x6E, 0xFA, 0x47, 0x80, 0x00, 0x00, + 0x72, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, + 0x73, 0x75, 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0xFB, + 0x3E, 0x70, 0x00, 0x00, 0x00, 0x1C, 0x5F, 0x68, 0x6F, 0x73, + 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x6E, 0x6F, + 0x72, 0x6D, 0x61, 0x6C, 0xFA, 0x38, 0x7F, 0xFF, 0xFF, 0x71, + 0x62, 0x69, 0x67, 0x67, 0x65, 0x73, 0x74, 0x20, 0x73, 0x75, + 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0xF9, 0x04, 0x00, + 0x70, 0x73, 0x75, 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, + 0x20, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0xFB, 0x37, 0xC1, + 0x6C, 0x28, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF9, 0xC0, 0x00, + 0x70, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x20, 0x73, 0x69, 0x6E, + 0x67, 0x6C, 0x65, 0x20, 0x65, 0x78, 0x70, 0xFA, 0x7F, 0x40, + 0x00, 0x00, 0x74, 0x74, 0x6F, 0x6F, 0x2D, 0x6C, 0x61, 0x72, + 0x67, 0x65, 0x20, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, + 0x65, 0x78, 0x70, 0xFB, 0x47, 0xF8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x78, 0x18, 0x62, 0x69, 0x67, 0x67, 0x65, 0x73, + 0x74, 0x20, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x77, + 0x69, 0x74, 0x68, 0x20, 0x70, 0x72, 0x65, 0x63, 0xFA, 0x4B, + 0x80, 0x00, 0x00, 0x78, 0x1B, 0x66, 0x69, 0x72, 0x73, 0x74, + 0x20, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x20, 0x70, 0x72, 0x65, 0x63, 0x20, 0x6C, 0x6F, + 0x73, 0x73, 0xFB, 0x41, 0x70, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x01, 0x63, 0x66, 0x69, 0x6E +}; + + +int DoubleAsSmallestTest() +{ + UsefulBuf_MAKE_STACK_UB(EncodedHalfsMem, 420); + +#define QCBOREncode_AddDoubleAsSmallestToMap QCBOREncode_AddDoubleToMap +#define QCBOREncode_AddDoubleAsSmallestToMapN QCBOREncode_AddDoubleToMapN + + + QCBOREncodeContext EC; + QCBOREncode_Init(&EC, EncodedHalfsMem); + // These are mostly from https://en.wikipedia.org/wiki/Half-precision_floating-point_format + QCBOREncode_OpenMap(&EC); + // 64 # text(4) + // 7A65726F # "zero" + // F9 0000 # primitive(0) + QCBOREncode_AddDoubleAsSmallestToMap(&EC, "zero", 0.00); + + // 64 # text(4) + // 7A65726F # "negative zero" + // F9 8000 # primitive(0) + QCBOREncode_AddDoubleAsSmallestToMap(&EC, "negative zero", -0.00); + + // 6A # text(10) + // 696E66696E6974697479 # "infinitity" + // F9 7C00 # primitive(31744) + QCBOREncode_AddDoubleAsSmallestToMap(&EC, "infinitity", INFINITY); + + // 73 # text(19) + // 6E6567617469766520696E66696E6974697479 # "negative infinitity" + // F9 FC00 # primitive(64512) + QCBOREncode_AddDoubleAsSmallestToMap(&EC, "negative infinitity", -INFINITY); + + // 63 # text(3) + // 4E614E # "NaN" + // F9 7E00 # primitive(32256) + QCBOREncode_AddDoubleAsSmallestToMap(&EC, "NaN", NAN); + + // TODO: test a few NaN variants + + // 63 # text(3) + // 6F6E65 # "one" + // F9 3C00 # primitive(15360) + QCBOREncode_AddDoubleAsSmallestToMap(&EC, "one", 1.0); + + // 69 # text(9) + // 6F6E65207468697264 # "one third" + // F9 3555 # primitive(13653) + QCBOREncode_AddDoubleAsSmallestToMap(&EC, "one third", 0.333251953125); + + // 76 # text(22) + // 6C6172676573742068616C662D707265636973696F6E # "largest half-precision" + // F9 7BFF # primitive(31743) + QCBOREncode_AddDoubleAsSmallestToMap(&EC, "largest half-precision",65504.0); + + // 76 # text(22) + // 6C6172676573742068616C662D707265636973696F6E # "largest half-precision" + // F9 7BFF # primitive(31743) + QCBOREncode_AddDoubleAsSmallestToMap(&EC, "largest half-precision point one",65504.1); + + // Float 65536.0F is 0x47800000 in hex. It has an exponent of 16, which is larger than 15, the largest half-precision exponent + // 78 18 # text(24) + // 746F6F2D6C617267652068616C662D707265636973696F6E # "too-large half-precision" + // FA 47800000 # primitive(31743) + QCBOREncode_AddDoubleAsSmallestToMap(&EC, "too-large half-precision", 65536.0); + + // The smallest possible half-precision subnormal, but digitis are lost converting + // to half, so this turns into a double + // 72 # text(18) + // 736D616C6C657374207375626E6F726D616C # "smallest subnormal" + // FB 3E700000001C5F68 # primitive(4499096027744984936) + QCBOREncode_AddDoubleAsSmallestToMap(&EC, "smallest subnormal", 0.0000000596046448); + + // The smallest possible half-precision snormal, but digitis are lost converting + // to half, so this turns into a single TODO: confirm this is right + // 6F # text(15) + // 736D616C6C657374206E6F726D616C # "smallest normal" + // FA 387FFFFF # primitive(947912703) + // in hex single is 0x387fffff, exponent -15, significand 7fffff + QCBOREncode_AddDoubleAsSmallestToMap(&EC, "smallest normal", 0.0000610351526F); + + // 71 # text(17) + // 62696767657374207375626E6F726D616C # "biggest subnormal" + // F9 0400 # primitive(1024) + // in hex single is 0x38800000, exponent -14, significand 0 + QCBOREncode_AddDoubleAsSmallestToMap(&EC, "biggest subnormal", 0.0000610351563F); + + // 70 # text(16) + // 7375626E6F726D616C2073696E676C65 # "subnormal single" + // FB 37C16C2800000000 # primitive(4017611261645684736) + QCBOREncode_AddDoubleAsSmallestToMap(&EC, "subnormal single", 4e-40L); + + // 03 # unsigned(3) + // F9 C000 # primitive(49152) + QCBOREncode_AddDoubleAsSmallestToMapN(&EC, 3, -2.0); + + // 70 # text(16) + // 6C617267652073696E676C6520657870 # "large single exp" + // FA 7F400000 # primitive(2134900736) + // (0x01LL << (DOUBLE_NUM_SIGNIFICAND_BITS-1)) | ((127LL + DOUBLE_EXPONENT_BIAS) << DOUBLE_EXPONENT_SHIFT); + QCBOREncode_AddDoubleAsSmallestToMap(&EC, "large single exp", 2.5521177519070385E+38); // Exponent fits single + + // 74 # text(20) + // 746F6F2D6C617267652073696E676C6520657870 # "too-large single exp" + // FB 47F8000000000000 # primitive(5185894970917126144) + // (0x01LL << (DOUBLE_NUM_SIGNIFICAND_BITS-1)) | ((128LL + DOUBLE_EXPONENT_BIAS) << DOUBLE_EXPONENT_SHIFT); + QCBOREncode_AddDoubleAsSmallestToMap(&EC, "too-large single exp", 5.104235503814077E+38); // Exponent too large for single + + // 66 # text(6) + // 646664666465 # "dfdfde" + // FA 4B800000 # primitive(1266679808) + QCBOREncode_AddDoubleAsSmallestToMap(&EC, "biggest single with prec",16777216); // Single with no precision loss + + // 78 18 # text(24) + // 626967676573742073696E676C6520776974682070726563 # "biggest single with prec" + // FA 4B800000 # primitive(1266679808) + QCBOREncode_AddDoubleAsSmallestToMap(&EC, "first single with prec loss",16777217); // Double becuase of precision loss + + // Just a convenient marker when cutting and pasting encoded CBOR + QCBOREncode_AddSZStringToMapN(&EC, 1, "fin"); + + QCBOREncode_CloseMap(&EC); + + UsefulBufC EncodedHalfs; + int nReturn = QCBOREncode_Finish(&EC, &EncodedHalfs); + if(nReturn) { + return -1; + } + + if(UsefulBuf_Compare(EncodedHalfs, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedSmallest))) { + return -3; + } + + return 0; +} + + + +#ifdef NAN_EXPERIMENT +/* + Code for checking what the double to float cast does with + NaNs. Not run as part of tests. Keep it around to + be able to check various platforms and CPUs. + */ + +#define DOUBLE_NUM_SIGNIFICAND_BITS (52) +#define DOUBLE_NUM_EXPONENT_BITS (11) +#define DOUBLE_NUM_SIGN_BITS (1) + +#define DOUBLE_SIGNIFICAND_SHIFT (0) +#define DOUBLE_EXPONENT_SHIFT (DOUBLE_NUM_SIGNIFICAND_BITS) +#define DOUBLE_SIGN_SHIFT (DOUBLE_NUM_SIGNIFICAND_BITS + DOUBLE_NUM_EXPONENT_BITS) + +#define DOUBLE_SIGNIFICAND_MASK (0xfffffffffffffULL) // The lower 52 bits +#define DOUBLE_EXPONENT_MASK (0x7ffULL << DOUBLE_EXPONENT_SHIFT) // 11 bits of exponent +#define DOUBLE_SIGN_MASK (0x01ULL << DOUBLE_SIGN_SHIFT) // 1 bit of sign +#define DOUBLE_QUIET_NAN_BIT (0x01ULL << (DOUBLE_NUM_SIGNIFICAND_BITS-1)) + + +static int NaNExperiments() { + double dqNaN = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | DOUBLE_QUIET_NAN_BIT); + double dsNaN = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | 0x01); + double dqNaNPayload = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | DOUBLE_QUIET_NAN_BIT | 0xf00f); + + float f1 = (float)dqNaN; + float f2 = (float)dsNaN; + float f3 = (float)dqNaNPayload; + + + uint32_t uqNaN = UsefulBufUtil_CopyFloatToUint32((float)dqNaN); + uint32_t usNaN = UsefulBufUtil_CopyFloatToUint32((float)dsNaN); + uint32_t uqNaNPayload = UsefulBufUtil_CopyFloatToUint32((float)dqNaNPayload); + + // Result of this on x86 is that every NaN is a qNaN. The intel + // CVTSD2SS instruction ignores the NaN payload and even converts + // a sNaN to a qNaN. + + return 0; +} +#endif diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/float_tests.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/float_tests.h new file mode 100644 index 0000000..b7174c8 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/float_tests.h @@ -0,0 +1,23 @@ +/*============================================================================== + float_tests.h -- tests for float and conversion to/from half-precision + + Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. + + SPDX-License-Identifier: BSD-3-Clause + + See BSD-3-Clause license in README.md + + Created on 9/19/18 + ==============================================================================*/ + +#ifndef float_tests_h +#define float_tests_h + +int HalfPrecisionDecodeBasicTests(void); + +int DoubleAsSmallestTest(void); + +int HalfPrecisionAgainstRFCCodeTest(void); + + +#endif /* float_tests_h */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/half_to_double_from_rfc7049.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/half_to_double_from_rfc7049.c new file mode 100644 index 0000000..4d8fb67 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/half_to_double_from_rfc7049.c @@ -0,0 +1,46 @@ +/* + SPDX-License-Identifier: BSD-2-Clause + + Copyright (c) 2013 IETF Trust and the persons identified as the + document authors. All rights reserved. + + This document is subject to BCP 78 and the IETF Trust's Legal + Provisions Relating to IETF Documents + (http://trustee.ietf.org/license-info) in effect on the date of + publication of this document. Please review these documents + carefully, as they describe your rights and restrictions with respect + to this document. Code Components extracted from this document must + include Simplified BSD License text as described in Section 4.e of + the Trust Legal Provisions and are provided without warranty as + described in the Simplified BSD License. + + */ + +/* + This code is from RFC 7049. It is not used in the main implementation + because: + a) it adds a dependency on and ldexp(). + b) the license may be an issue + + QCBOR does support half-precision, but rather than using + floating point math like this, it does it with bit shifting + and masking. + + This code is here to test that code. + + */ + +#include "half_to_double_from_rfc7049.h" + +#include + +double decode_half(unsigned char *halfp) { + int half = (halfp[0] << 8) + halfp[1]; + int exp = (half >> 10) & 0x1f; + int mant = half & 0x3ff; + double val; + if (exp == 0) val = ldexp(mant, -24); + else if (exp != 31) val = ldexp(mant + 1024, exp - 25); + else val = mant == 0 ? INFINITY : NAN; + return half & 0x8000 ? -val : val; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/half_to_double_from_rfc7049.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/half_to_double_from_rfc7049.h new file mode 100644 index 0000000..9f69e35 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/half_to_double_from_rfc7049.h @@ -0,0 +1,18 @@ +/*============================================================================== + half_to_double_from_rfc7049.h -- interface to IETF float conversion code. + + Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. + + SPDX-License-Identifier: BSD-3-Clause + + See BSD-3-Clause license in README.md + + Created on 9/23/18 + ==============================================================================*/ + +#ifndef half_to_double_from_rfc7049_h +#define half_to_double_from_rfc7049_h + +double decode_half(unsigned char *halfp); + +#endif /* half_to_double_from_rfc7049_h */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/qcbor_decode_tests.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/qcbor_decode_tests.c new file mode 100644 index 0000000..5742daf --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/qcbor_decode_tests.c @@ -0,0 +1,2836 @@ +/*============================================================================== + Copyright (c) 2016-2018, The Linux Foundation. + Copyright (c) 2018-2019, Laurence Lundblade. + All rights reserved. + SPDX-License-Identifier: BSD-3-Clause + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors, nor the name "Laurence Lundblade" may be used to + endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ==============================================================================*/ + +#include "qcbor_decode_tests.h" +#include "qcbor.h" +#include +#include // for fabs() + + +#ifdef PRINT_FUNCTIONS_FOR_DEBUGGING +#include + +static void PrintUsefulBufC(const char *szLabel, UsefulBufC Buf) +{ + if(szLabel) { + printf("%s ", szLabel); + } + + size_t i; + for(i = 0; i < Buf.len; i++) { + uint8_t Z = ((uint8_t *)Buf.ptr)[i]; + printf("%02x ", Z); + } + printf("\n"); + + fflush(stdout); +} + +/*static void printencoded(const char *szLabel, const uint8_t *pEncoded, size_t nLen) +{ + PrintUsefulBufC(szLabel, (UsefulBufC){pEncoded, nLen}); +}*/ +#endif + + +static const uint8_t spExpectedEncodedInts[] = { + 0x98, 0x2f, 0x3b, 0x7f, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x3b, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x3a, 0xff, 0xff, 0xff, + 0xff, 0x3a, 0xff, 0xff, 0xff, 0xfe, 0x3a, 0xff, + 0xff, 0xff, 0xfd, 0x3a, 0x7f, 0xff, 0xff, 0xff, + 0x3a, 0x7f, 0xff, 0xff, 0xfe, 0x3a, 0x00, 0x01, + 0x00, 0x01, 0x3a, 0x00, 0x01, 0x00, 0x00, 0x39, + 0xff, 0xff, 0x39, 0xff, 0xfe, 0x39, 0xff, 0xfd, + 0x39, 0x01, 0x00, 0x38, 0xff, 0x38, 0xfe, 0x38, + 0xfd, 0x38, 0x18, 0x37, 0x36, 0x20, 0x00, 0x00, + 0x01, 0x16, 0x17, 0x18, 0x18, 0x18, 0x19, 0x18, + 0x1a, 0x18, 0xfe, 0x18, 0xff, 0x19, 0x01, 0x00, + 0x19, 0x01, 0x01, 0x19, 0xff, 0xfe, 0x19, 0xff, + 0xff, 0x1a, 0x00, 0x01, 0x00, 0x00, 0x1a, 0x00, + 0x01, 0x00, 0x01, 0x1a, 0x00, 0x01, 0x00, 0x02, + 0x1a, 0x7f, 0xff, 0xff, 0xff, 0x1a, 0x7f, 0xff, + 0xff, 0xff, 0x1a, 0x80, 0x00, 0x00, 0x00, 0x1a, + 0x80, 0x00, 0x00, 0x01, 0x1a, 0xff, 0xff, 0xff, + 0xfe, 0x1a, 0xff, 0xff, 0xff, 0xff, 0x1b, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1b, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x1b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff}; + + +// return CBOR error or -1 if type of value doesn't match + +static int IntegerValuesParseTestInternal(QCBORDecodeContext *pDCtx) +{ + QCBORItem Item; + int nCBORError; + + if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_ARRAY) + return -1; + + if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || // Todo; fix this for 32-bit machines + Item.val.int64 != -9223372036854775807LL - 1) + return -1; + + if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != -4294967297) + return -1; + + if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != -4294967296) + return -1; + + if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != -4294967295) + return -1; + + if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != -4294967294) + return -1; + + + if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != -2147483648) + return -1; + + if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != -2147483647) + return -1; + + if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != -65538) + return -1; + + if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != -65537) + return -1; + + if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != -65536) + return -1; + + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != -65535) + return -1; + + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != -65534) + return -1; + + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != -257) + return -1; + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != -256) + return -1; + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != -255) + return -1; + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != -254) + return -1; + + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != -25) + return -1; + + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != -24) + return -1; + + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != -23) + return -1; + + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != -1) + return -1; + + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 0) + return -1; + + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 0) + return -1; + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 1) + return -1; + + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 22) + return -1; + + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 23) + return -1; + + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 24) + return -1; + + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 25) + return -1; + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 26) + return -1; + + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 254) + return -1; + + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 255) + return -1; + + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 256) + return -1; + + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 257) + return -1; + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 65534) + return -1; + + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 65535) + return -1; + + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 65536) + return -1; + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 65537) + return -1; + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 65538) + return -1; + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 2147483647) + return -1; + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 2147483647) + return -1; + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 2147483648) + return -1; + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 2147483649) + return -1; + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 4294967294) + return -1; + + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 4294967295) + return -1; + + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 4294967296) + return -1; + + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 4294967297) + return -1; + + + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 9223372036854775807LL) + return -1; + + + if(( nCBORError = QCBORDecode_GetNext(pDCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_UINT64 || + Item.val.uint64 != 18446744073709551615ULL) + return -1; + + + if(QCBORDecode_Finish(pDCtx) != QCBOR_SUCCESS) { + return -1; + } + + return 0; +} + + +/* + Tests the decoding of lots of different integers sizes + and values. + */ + +int IntegerValuesParseTest() +{ + int n; + QCBORDecodeContext DCtx; + + QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedEncodedInts), QCBOR_DECODE_MODE_NORMAL); + + n = IntegerValuesParseTestInternal(&DCtx); + + return(n); +} + + +/* + Creates a simple CBOR array and returns it in *pEncoded. The array is malloced + and needs to be freed. This is used by several tests. + + Two of the inputs can be set. Two other items in the array are fixed. + + */ + +static uint8_t spSimpleArrayBuffer[50]; + +static int CreateSimpleArray(int nInt1, int nInt2, uint8_t **pEncoded, size_t *pEncodedLen) +{ + QCBOREncodeContext ECtx; + int nReturn = -1; + + *pEncoded = NULL; + *pEncodedLen = INT32_MAX; + + // loop runs CBOR encoding twice. First with no buffer to + // calculate the length so buffer can be allocated correctly, + // and last with the buffer to do the actual encoding + do { + QCBOREncode_Init(&ECtx, (UsefulBuf){*pEncoded, *pEncodedLen}); + QCBOREncode_OpenArray(&ECtx); + QCBOREncode_AddInt64(&ECtx, nInt1); + QCBOREncode_AddInt64(&ECtx, nInt2); + QCBOREncode_AddBytes(&ECtx, ((UsefulBufC) {"galactic", 8})); + QCBOREncode_AddBytes(&ECtx, ((UsefulBufC) {"haven token", 11})); + QCBOREncode_CloseArray(&ECtx); + + if(QCBOREncode_FinishGetSize(&ECtx, pEncodedLen)) + goto Done; + + if(*pEncoded != NULL) { + nReturn = 0; + goto Done; + } + + // Use static buffer to avoid dependency on malloc() + if(*pEncodedLen > sizeof(spSimpleArrayBuffer)) { + goto Done; + } + *pEncoded = spSimpleArrayBuffer; + + } while(1); + +Done: + return nReturn; +} + + +/* + {"first integer": 42, + "an array of two strings": [ + "string1", "string2" + ], + "map in a map": { + "bytes 1": h'78787878', + "bytes 2": h'79797979', + "another int": 98, + "text 2": "lies, damn lies and statistics" + } + } + */ + +static uint8_t pValidMapEncoded[] = { + 0xa3, 0x6d, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x69, 0x6e, + 0x74, 0x65, 0x67, 0x65, 0x72, 0x18, 0x2a, 0x77, 0x61, 0x6e, + 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, + 0x74, 0x77, 0x6f, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0x73, 0x82, 0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x31, + 0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x32, 0x6c, 0x6d, + 0x61, 0x70, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x6d, 0x61, + 0x70, 0xa4, 0x67, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x31, + 0x44, 0x78, 0x78, 0x78, 0x78, 0x67, 0x62, 0x79, 0x74, 0x65, + 0x73, 0x20, 0x32, 0x44, 0x79, 0x79, 0x79, 0x79, 0x6b, 0x61, + 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x74, + 0x18, 0x62, 0x66, 0x74, 0x65, 0x78, 0x74, 0x20, 0x32, 0x78, + 0x1e, 0x6c, 0x69, 0x65, 0x73, 0x2c, 0x20, 0x64, 0x61, 0x6d, + 0x6e, 0x20, 0x6c, 0x69, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, + 0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, + 0x73 } ; + +static int ParseOrderedArray(const uint8_t *pEncoded, size_t nLen, int64_t *pInt1, int64_t *pInt2, const uint8_t **pBuf3, size_t *pBuf3Len, const uint8_t **pBuf4, size_t *pBuf4Len) +{ + QCBORDecodeContext DCtx; + QCBORItem Item; + int nReturn = -1; // assume error until success + + QCBORDecode_Init(&DCtx, (UsefulBufC){pEncoded, nLen}, QCBOR_DECODE_MODE_NORMAL); + + // Make sure the first thing is a map + if(QCBORDecode_GetNext(&DCtx, &Item) != 0 || Item.uDataType != QCBOR_TYPE_ARRAY) + goto Done; + + // First integer + if(QCBORDecode_GetNext(&DCtx, &Item) != 0 || Item.uDataType != QCBOR_TYPE_INT64) + goto Done; + *pInt1 = Item.val.int64; + + // Second integer + if(QCBORDecode_GetNext(&DCtx, &Item) != 0 || Item.uDataType != QCBOR_TYPE_INT64) + goto Done; + *pInt2 = Item.val.int64; + + // First string + if(QCBORDecode_GetNext(&DCtx, &Item) != 0 || Item.uDataType != QCBOR_TYPE_BYTE_STRING) + goto Done; + *pBuf3 = Item.val.string.ptr; + *pBuf3Len = Item.val.string.len; + + // Second string + if(QCBORDecode_GetNext(&DCtx, &Item) != 0 || Item.uDataType != QCBOR_TYPE_BYTE_STRING) + goto Done; + *pBuf4 = Item.val.string.ptr; + *pBuf4Len = Item.val.string.len; + + nReturn = 0; + +Done: + return(nReturn); +} + + + + +int SimpleArrayTest() +{ + uint8_t *pEncoded; + size_t nEncodedLen; + + int64_t i1=0, i2=0; + size_t i3=0, i4=0; + const uint8_t *s3= (uint8_t *)""; + const uint8_t *s4= (uint8_t *)""; + + + if(CreateSimpleArray(23, 6000, &pEncoded, &nEncodedLen) < 0) { + return(-1); + } + + ParseOrderedArray(pEncoded, nEncodedLen, &i1, &i2, &s3, &i3, &s4, &i4); + + if(i1 != 23 || + i2 != 6000 || + i3 != 8 || + i4 != 11 || + memcmp("galactic", s3, 8) !=0 || + memcmp("haven token", s4, 11) !=0) { + return(-1); + } + + return(0); +} + + + +static uint8_t spDeepArrays[] = {0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80}; + +int ParseDeepArrayTest() +{ + QCBORDecodeContext DCtx; + int nReturn = 0; + int i; + + QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spDeepArrays), QCBOR_DECODE_MODE_NORMAL); + + for(i = 0; i < 10; i++) { + QCBORItem Item; + + if(QCBORDecode_GetNext(&DCtx, &Item) != 0 || + Item.uDataType != QCBOR_TYPE_ARRAY || + Item.uNestingLevel != i) { + nReturn = -1; + break; + } + } + + return(nReturn); +} + +// Big enough to test nesting to the depth of 24 +static uint8_t spTooDeepArrays[] = {0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x80}; + +int ParseTooDeepArrayTest() +{ + QCBORDecodeContext DCtx; + int nReturn = 0; + int i; + QCBORItem Item; + + + QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spTooDeepArrays), QCBOR_DECODE_MODE_NORMAL); + + for(i = 0; i < QCBOR_MAX_ARRAY_NESTING1; i++) { + + if(QCBORDecode_GetNext(&DCtx, &Item) != 0 || + Item.uDataType != QCBOR_TYPE_ARRAY || + Item.uNestingLevel != i) { + nReturn = -1; + break; + } + } + + if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_ARRAY_NESTING_TOO_DEEP) + nReturn = -1; + + return(nReturn); +} + + + + +int ShortBufferParseTest() +{ + int nResult = 0; + QCBORDecodeContext DCtx; + int num; + + for(num = sizeof(spExpectedEncodedInts)-1; num; num--) { + int n; + + QCBORDecode_Init(&DCtx, (UsefulBufC){spExpectedEncodedInts, num}, QCBOR_DECODE_MODE_NORMAL); + + n = IntegerValuesParseTestInternal(&DCtx); + + //printf("Len %d, result: %d\n", num, n); + + if(n != QCBOR_ERR_HIT_END) { + nResult = -1; + goto Done; + } + } +Done: + return nResult; +} + + + +int ShortBufferParseTest2() +{ + uint8_t *pEncoded; + int nReturn; + size_t nEncodedLen; + + int64_t i1, i2; + size_t i3, i4; + const uint8_t *s3, *s4; + + nReturn = 0; + + if(CreateSimpleArray(23, 6000, &pEncoded, &nEncodedLen) < 0) { + return(-1); + } + + for(nEncodedLen--; nEncodedLen; nEncodedLen--) { + int nResult = ParseOrderedArray(pEncoded, (uint32_t)nEncodedLen, &i1, &i2, &s3, &i3, &s4, &i4); + if(nResult == 0) { + nReturn = -1; + } + } + + return(nReturn); +} + +/* + Decode and thoroughly check a moderately complex + set of maps + */ +static int ParseMapTest1(QCBORDecodeMode nMode) +{ + QCBORDecodeContext DCtx; + QCBORItem Item; + int nCBORError; + + QCBORDecode_Init(&DCtx, (UsefulBufC){pValidMapEncoded, sizeof(pValidMapEncoded)}, nMode); + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uDataType != QCBOR_TYPE_MAP || + Item.val.uCount != 3) + return -1; + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || + Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 42 || + Item.uDataAlloc || + Item.uLabelAlloc || + UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("first integer"))) { + return -1; + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || + Item.uDataAlloc || + Item.uLabelAlloc || + UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("an array of two strings")) || + Item.uDataType != QCBOR_TYPE_ARRAY || + Item.val.uCount != 2) + return -1; + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || + Item.uDataAlloc || + Item.uLabelAlloc || + UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("string1"))) { + return -1; + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || + Item.uDataAlloc || + Item.uLabelAlloc || + UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("string2"))) { + return -1; + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || + Item.uDataAlloc || + Item.uLabelAlloc || + UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("map in a map")) || + Item.uDataType != QCBOR_TYPE_MAP || + Item.val.uCount != 4) { + return -1; + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || + UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("bytes 1"))|| + Item.uDataType != QCBOR_TYPE_BYTE_STRING || + Item.uDataAlloc || + Item.uLabelAlloc || + UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("xxxx"))) { + return -1; + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || + UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("bytes 2")) || + Item.uDataType != QCBOR_TYPE_BYTE_STRING || + Item.uDataAlloc || + Item.uLabelAlloc || + UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("yyyy"))) { + return -1; + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || + Item.uDataAlloc || + Item.uLabelAlloc || + UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("another int")) || + Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 98) + return -1; + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || + UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("text 2"))|| + Item.uDataType != QCBOR_TYPE_TEXT_STRING || + Item.uDataAlloc || + Item.uLabelAlloc || + UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("lies, damn lies and statistics"))) { + return -1; + } + + return 0; +} + + +/* + Decode and thoroughly check a moderately complex + set of maps + */ +int ParseMapAsArrayTest() +{ + QCBORDecodeContext DCtx; + QCBORItem Item; + int nCBORError; + + QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded), QCBOR_DECODE_MODE_MAP_AS_ARRAY); + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uDataType != QCBOR_TYPE_MAP_AS_ARRAY || + Item.val.uCount != 6) { + return -1; + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || + Item.uDataAlloc || + Item.uLabelAlloc || + Item.uLabelType != QCBOR_TYPE_NONE || + UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("first integer"))) { + return -2; + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uLabelType != QCBOR_TYPE_NONE || + Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 42 || + Item.uDataAlloc || + Item.uLabelAlloc) { + return -3; + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uLabelType != QCBOR_TYPE_NONE || + Item.uDataAlloc || + Item.uLabelAlloc || + UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("an array of two strings")) || + Item.uDataType != QCBOR_TYPE_TEXT_STRING) { + return -4; + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uLabelType != QCBOR_TYPE_NONE || + Item.uDataAlloc || + Item.uLabelAlloc || + Item.uDataType != QCBOR_TYPE_ARRAY || + Item.val.uCount != 2) { + return -5; + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || + Item.val.string.len != 7 || + Item.uDataAlloc || + Item.uLabelAlloc || + UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("string1"))) { + return -6; + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || + Item.uDataAlloc || + Item.uLabelAlloc || + UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("string2"))) { + return -7; + } + + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uLabelType != QCBOR_TYPE_NONE || + Item.uDataAlloc || + Item.uLabelAlloc || + UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("map in a map"))) { + return -8; + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uLabelType != QCBOR_TYPE_NONE || + Item.uDataAlloc || + Item.uLabelAlloc || + Item.uDataType != QCBOR_TYPE_MAP_AS_ARRAY || + Item.val.uCount != 8) { + return -9; + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uLabelType != QCBOR_TYPE_NONE || + UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("bytes 1"))|| + Item.uDataType != QCBOR_TYPE_TEXT_STRING || + Item.uDataAlloc || + Item.uLabelAlloc) { + return -10; + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uLabelType != QCBOR_TYPE_NONE || + Item.uDataType != QCBOR_TYPE_BYTE_STRING || + Item.uDataAlloc || + Item.uLabelAlloc || + UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("xxxx"))) { + return -11; + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uLabelType != QCBOR_TYPE_NONE || + UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("bytes 2")) || + Item.uDataType != QCBOR_TYPE_TEXT_STRING || + Item.uDataAlloc || + Item.uLabelAlloc) { + return -12; + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uLabelType != QCBOR_TYPE_NONE || + Item.uDataType != QCBOR_TYPE_BYTE_STRING || + Item.uDataAlloc || + Item.uLabelAlloc || + UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("yyyy"))) { + return -13; + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uLabelType != QCBOR_TYPE_NONE || + Item.uDataAlloc || + Item.uLabelAlloc || + UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("another int")) || + Item.uDataType != QCBOR_TYPE_TEXT_STRING) { + return -14; + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uLabelType != QCBOR_TYPE_NONE || + Item.uDataAlloc || + Item.uLabelAlloc || + Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 98) { + return -15; + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uLabelType != QCBOR_TYPE_NONE || + UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("text 2"))|| + Item.uDataType != QCBOR_TYPE_TEXT_STRING || + Item.uDataAlloc || + Item.uLabelAlloc) { + return -16; + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uLabelType != QCBOR_TYPE_NONE || + Item.uDataType != QCBOR_TYPE_TEXT_STRING || + Item.uDataAlloc || + Item.uLabelAlloc || + UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("lies, damn lies and statistics"))) { + return -17; + } + + return 0; +} + + +/* + Fully or partially decode pValidMapEncoded. When + partially decoding check for the right error code. + How much partial decoding depends on nLevel. + + The partial decodes test error conditions of + incomplete encoded input. + + This could be combined with the above test + and made prettier and maybe a little more + thorough. + */ +static int ExtraBytesTest(int nLevel) +{ + QCBORDecodeContext DCtx; + QCBORItem Item; + int nCBORError; + + QCBORDecode_Init(&DCtx, (UsefulBufC){pValidMapEncoded, sizeof(pValidMapEncoded)}, QCBOR_DECODE_MODE_NORMAL); + + if(nLevel < 1) { + if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_EXTRA_BYTES) { + return -1; + } else { + return 0; + } + } + + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uDataType != QCBOR_TYPE_MAP || + Item.val.uCount != 3) + return -1; + + if(nLevel < 2) { + if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN) { + return -1; + } else { + return 0; + } + } + + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || + Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.uCount != 42 || + UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("first integer"))) { + return -1; + } + + if(nLevel < 3) { + if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN) { + return -1; + } else { + return 0; + } + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || + UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("an array of two strings")) || + Item.uDataType != QCBOR_TYPE_ARRAY || + Item.val.uCount != 2) { + return -1; + } + + + if(nLevel < 4) { + if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN) { + return -1; + } else { + return 0; + } + } + + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || + UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("string1"))) { + return -1; + } + + if(nLevel < 5) { + if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN) { + return -1; + } else { + return 0; + } + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || + UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("string2"))) { + return -1; + } + + if(nLevel < 6) { + if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN) { + return -1; + } else { + return 0; + } + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || + UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("map in a map")) || + Item.uDataType != QCBOR_TYPE_MAP || + Item.val.uCount != 4) + return -1; + + if(nLevel < 7) { + if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN) { + return -1; + } else { + return 0; + } + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || + UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("bytes 1")) || + Item.uDataType != QCBOR_TYPE_BYTE_STRING || + UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("xxxx"))) { + return -1; + } + + if(nLevel < 8) { + if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN) { + return -1; + } else { + return 0; + } + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || + UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("bytes 2")) || + Item.uDataType != QCBOR_TYPE_BYTE_STRING || + UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("yyyy"))) { + return -1; + } + + if(nLevel < 9) { + if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN) { + return -1; + } else { + return 0; + } + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || + UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("another int")) || + Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != 98) + return -1; + + if(nLevel < 10) { + if(QCBORDecode_Finish(&DCtx) != QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN) { + return -1; + } else { + return 0; + } + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) { + return nCBORError; + } + if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || + UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("text 2"))|| + Item.uDataType != QCBOR_TYPE_TEXT_STRING || + UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("lies, damn lies and statistics"))) { + return -1; + } + + if(QCBORDecode_Finish(&DCtx)) { + return -1; + } + + return 0; +} + + + + +int ParseMapTest() +{ + // Parse a moderatly complex map structure very thoroughl + int n = ParseMapTest1(QCBOR_DECODE_MODE_NORMAL); + + n = ParseMapTest1(QCBOR_DECODE_MODE_MAP_STRINGS_ONLY); + + if(!n) { + for(int i = 0; i < 10; i++) { + n = ExtraBytesTest(i); + if(n) { + break; + } + } + } + + return(n); +} + + +static uint8_t spSimpleValues[] = {0x8a, 0xf4, 0xf5, 0xf6, 0xf7, 0xff, 0xe0, 0xf3, 0xf8, 0x00, 0xf8, 0x13, 0xf8, 0x1f, 0xf8, 0x20, 0xf8, 0xff}; + +int ParseSimpleTest() +{ + QCBORDecodeContext DCtx; + QCBORItem Item; + int nCBORError; + + + QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSimpleValues), QCBOR_DECODE_MODE_NORMAL); + + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_ARRAY || + Item.val.uCount != 10) + return -1; + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_FALSE) + return -1; + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_TRUE) + return -1; + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_NULL) + return -1; + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_UNDEF) + return -1; + + // A break + if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_BAD_BREAK) + return -1; + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_UKNOWN_SIMPLE || Item.val.uSimple != 0) + return -1; + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_UKNOWN_SIMPLE || Item.val.uSimple != 19) + return -1; + + if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_INVALID_CBOR) + return -1; + + if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_INVALID_CBOR) + return -1; + + if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_INVALID_CBOR) + return -1; + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_UKNOWN_SIMPLE || Item.val.uSimple != 32) + return -1; + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_UKNOWN_SIMPLE || Item.val.uSimple != 255) + return -1; + + return 0; + +} + + +struct FailInput { + UsefulBufC Input; + int nError; +}; + + +struct FailInput Failures[] = { + { {(uint8_t[]){0x18}, 1}, QCBOR_ERR_HIT_END }, // 1 byte integer missing the byte + { {(uint8_t[]){0x1c}, 1}, QCBOR_ERR_UNSUPPORTED }, // Reserved additional info = 28 + { {(uint8_t[]){0x1d}, 1}, QCBOR_ERR_UNSUPPORTED }, // Reserved additional info = 29 + { {(uint8_t[]){0x1e}, 1}, QCBOR_ERR_UNSUPPORTED }, // Reserved additional info = 30 + { {(uint8_t[]){0x1f}, 1}, QCBOR_ERR_UNSUPPORTED }, // Indefinite length integer + { {(uint8_t[]){0x3c}, 1}, QCBOR_ERR_UNSUPPORTED }, // 1 byte integer missing the byte + { {(uint8_t[]){0x3d}, 1}, QCBOR_ERR_UNSUPPORTED }, // 1 byte integer missing the byte + { {(uint8_t[]){0x3e}, 1}, QCBOR_ERR_UNSUPPORTED }, // 1 byte integer missing the byte + { {(uint8_t[]){0x3f}, 1}, QCBOR_ERR_UNSUPPORTED }, // Indefinite length negative integer + { {(uint8_t[]){0x41}, 1}, QCBOR_ERR_HIT_END }, // Short byte string + { {(uint8_t[]){0x5c}, 1}, QCBOR_ERR_UNSUPPORTED }, // Reserved additional info = 28 + { {(uint8_t[]){0x5f}, 1}, QCBOR_ERR_UNSUPPORTED }, // Indefinite length byte string + { {(uint8_t[]){0x61}, 1}, QCBOR_ERR_HIT_END }, // Short UTF-8 string + { {(uint8_t[]){0x7c}, 1}, QCBOR_ERR_UNSUPPORTED }, // Reserved additional info = 28 + { {(uint8_t[]){0x7f}, 1}, QCBOR_ERR_UNSUPPORTED }, // Indefinite length UTF-8 string + { {(uint8_t[]){0xff}, 1}, QCBOR_ERR_UNSUPPORTED } , // break + { {(uint8_t[]){0xf8, 0x00}, 2}, QCBOR_ERR_INVALID_CBOR }, // An invalid encoding of a simple type + { {(uint8_t[]){0xf8, 0x1f}, 2}, QCBOR_ERR_INVALID_CBOR }, // An invalid encoding of a simple type + { {(uint8_t[]){0xc0, 0x00}, 2}, QCBOR_ERR_BAD_OPT_TAG }, // Text-based date, with an integer + { {(uint8_t[]){0xc1, 0x41, 0x33}, 3}, QCBOR_ERR_BAD_OPT_TAG }, // Epoch date, with an byte string + { {(uint8_t[]){0xc1, 0xc0, 0x00}, 3}, QCBOR_ERR_BAD_OPT_TAG }, // tagged as both epoch and string dates + { {(uint8_t[]){0xc2, 0x00}, 2}, QCBOR_ERR_BAD_OPT_TAG } // big num tagged an int, not a byte string + +}; + + +int FailureTests() +{ + int nResult = 0; + + struct FailInput *pFEnd = &Failures[0] + sizeof(Failures)/sizeof(struct FailInput); + + for(struct FailInput *pF = &Failures[0]; pF < pFEnd ;pF++) { + QCBORDecodeContext DCtx; + QCBORItem Item; + int nCBORError; + + QCBORDecode_Init(&DCtx, pF->Input, QCBOR_DECODE_MODE_NORMAL); + + while(1) { + nCBORError = QCBORDecode_GetNext(&DCtx, &Item); + if(QCBOR_ERR_HIT_END == nCBORError) { + break; + } + if(nCBORError != pF->nError) { + nResult = 1; + break; + } + } + } + + { + QCBORDecodeContext DCtx; + QCBORItem Item; + int nCBORError; + + QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSimpleValues), QCBOR_DECODE_MODE_NORMAL); + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) + return nCBORError; + if(Item.uDataType != QCBOR_TYPE_ARRAY || + Item.val.uCount != 10) + return -1; + + DCtx.InBuf.magic = 0; // Corrupt the UsefulInputBuf + + nCBORError = QCBORDecode_GetNext(&DCtx, &Item); + if(nCBORError != QCBOR_ERR_HIT_END) + return -1; + } + + + return nResult; +} + + +/* Try all 256 values of the byte at nLen including recursing for + each of the values to try values at nLen+1 ... up to nLenMax + */ +static void ComprehensiveInputRecurser(uint8_t *pBuf, int nLen, int nLenMax) +{ + if(nLen >= nLenMax) { + return; + } + + for(int inputByte = 0; inputByte < 256; inputByte++) { + // Set up the input + pBuf[nLen] = inputByte; + const UsefulBufC Input = {pBuf, nLen+1}; + + // Get ready to parse + QCBORDecodeContext DCtx; + QCBORDecode_Init(&DCtx, Input, QCBOR_DECODE_MODE_NORMAL); + + // Parse by getting the next item until an error occurs + // Just about every possible decoder error can occur here + // The goal of this test is not to check for the correct + // error since that is not really possible. It is to + // see that there is no crash on hostile input. + while(1) { + QCBORItem Item; + QCBORError nCBORError = QCBORDecode_GetNext(&DCtx, &Item); + if(nCBORError != QCBOR_SUCCESS) { + break; + } + } + + ComprehensiveInputRecurser(pBuf, nLen+1, nLenMax); + } +} + + +/* + Public function for initialization. See header qcbor.h + */ +int ComprehensiveInputTest() +{ + // Size 2 tests 64K inputs and runs quickly + uint8_t pBuf[2]; + + ComprehensiveInputRecurser(pBuf, 0, sizeof(pBuf)); + + return 0; +} + + +/* + Public function for initialization. See header qcbor.h + */ +int BigComprehensiveInputTest() +{ + // size 3 tests 16 million inputs and runs OK + // in seconds on fast machines. Size 4 takes + // 10+ minutes and 5 half a day on fast + // machines. This test is kept separate from + // the others so as to no slow down the use + // of them as a very frequent regression. + uint8_t pBuf[3]; // + + ComprehensiveInputRecurser(pBuf, 0, sizeof(pBuf)); + + return 0; +} + + +static uint8_t spDateTestInput[] = { + 0xc0, // tag for string date + 0x6a, '1','9','8','5','-','0','4','-','1','2', // Date string + + 0xc1, // tag for epoch date + 0x1a, 0x53, 0x72, 0x4E, 0x00, // Epoch date 1400000000; Tue, 13 May 2014 16:53:20 GMT + + // CBOR_TAG_B64 + 0xc1, 0xcf, 0xd8, 0x22, // 0xee, // Epoch date with extra tags TODO: fix this test + 0x1a, 0x53, 0x72, 0x4E, 0x01, + + 0xc1, // tag for epoch date + 0x1b, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // Too large integer + + 0xc1, // tag for epoch date + 0xfa, 0x3f, 0x8c, 0xcc, 0xcd, // double with value 1.1 + + 0xc1, // tag for epoch date + 0xfa, 0x7f, 0x7f, 0xff, 0xff // 3.4028234663852886e+38 too large + +}; + + +// have to check float expected only to within an epsilon +int CHECK_EXPECTED_DOUBLE(double val, double expected) { + + double diff = val - expected; + + diff = fabs(diff); + + return diff > 0.0000001; +} + + +int DateParseTest() +{ + QCBORDecodeContext DCtx; + QCBORItem Item; + int nCBORError; + + QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spDateTestInput), QCBOR_DECODE_MODE_NORMAL); + + const uint64_t uTags[] = {15}; + QCBORTagListIn TagList = {1, uTags}; + + QCBORDecode_SetCallerConfiguredTagList(&DCtx, &TagList); + + // String date + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) + return -1; + if(Item.uDataType != QCBOR_TYPE_DATE_STRING || + UsefulBuf_Compare(Item.val.dateString, UsefulBuf_FromSZ("1985-04-12"))){ + return -2; + } + + // Epoch date + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) + return -3; + if(Item.uDataType != QCBOR_TYPE_DATE_EPOCH || + Item.val.epochDate.nSeconds != 1400000000 || + Item.val.epochDate.fSecondsFraction != 0 ) { + return -4; + } + + // Epoch date with extra CBOR_TAG_B64 tag that doesn't really mean anything + // but want to be sure extra tag doesn't cause a problem + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) + return -5; + if(Item.uDataType != QCBOR_TYPE_DATE_EPOCH || + Item.val.epochDate.nSeconds != 1400000001 || + Item.val.epochDate.fSecondsFraction != 0 || + !QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_B64)) { + return -6; + } + + // Epoch date that is too large for our representation + if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_DATE_OVERFLOW) { + return -7; + } + + // Epoch date in float format with fractional seconds + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) + return -8; + if(Item.uDataType != QCBOR_TYPE_DATE_EPOCH || + Item.val.epochDate.nSeconds != 1 || + CHECK_EXPECTED_DOUBLE(Item.val.epochDate.fSecondsFraction, 0.1 )) { + return -9; + } + + // Epoch date float that is too large for our representation + if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_DATE_OVERFLOW) { + return -10; + } + + // TODO: could use a few more tests with float, double, and half precsion and negative (but coverage is still pretty good) + + return 0; +} + +// Really simple basic input for tagging test +static uint8_t spOptTestInput[] = { + 0xd9, 0xd9, 0xf7, // CBOR magic number + 0x81, // Array of one + 0xd8, 0x04, // non-preferred serialization of tag 4 + 0x82, 0x01, 0x03}; // fraction 1/3 + +static uint8_t spEncodedLargeTag[] = {0xdb, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x80}; + +// 0x9192939495969798, 0x88, 0x01, 0x04 +static uint8_t spLotsOfTags[] = {0xdb, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0xd8, 0x88, 0xc5, 0xc4, 0x80}; + +/* + The cbor.me parse of this. + 55799(55799(55799({6(7(-23)): 5859837686836516696(7({7(-20): 11({17(-18): 17(17(17("Organization"))), + 9(-17): 773("SSG"), -15: 4(5(6(7(8(9(10(11(12(13(14(15("Confusion")))))))))))), 17(-16): 17("San Diego"), + 17(-14): 17("US")}), 23(-19): 19({-11: 9({-9: -7}), + 90599561(90599561(90599561(-10))): 12(h'0102030405060708090A')})})), + 16(-22): 23({11(8(7(-5))): 8(-3)})}))) + */ +static uint8_t spCSRWithTags[] = { + 0xd9, 0xd9, 0xf7, 0xd9, 0xd9, 0xf7, 0xd9, 0xd9, 0xf7, 0xa2, + 0xc6, 0xc7, 0x36, + 0xdb, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0xc7, 0xa2, + 0xda, 0x00, 0x00, 0x00, 0x07, 0x33, + 0xcb, 0xa5, + 0xd1, 0x31, + 0xd1, 0xd1, 0xd1, 0x6c, + 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0xc9, 0x30, + 0xd9, 0x03, 0x05, 0x63, + 0x53, 0x53, 0x47, + 0x2e, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0x69, + 0x43, 0x6f, 0x6e, 0x66, 0x75, 0x73, 0x69, 0x6f, 0x6e, + 0xd1, 0x2f, + 0xd1, 0x69, + 0x53, 0x61, 0x6e, 0x20, 0x44, 0x69, 0x65, 0x67, 0x6f, + 0xd1, 0x2d, + 0xd1, 0x62, + 0x55, 0x53, + 0xd7, 0x32, + 0xd3, 0xa2, + 0x2a, + 0xc9, 0xa1, + 0x28, + 0x26, + 0xda, 0x05, 0x66, 0x70, 0x89, 0xda, 0x05, 0x66, 0x70, 0x89, 0xda, 0x05, 0x66, 0x70, 0x89, 0x29, + 0xcc, 0x4a, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,0x07, 0x08, 0x09, 0x0a, + 0xd0, 0x35, + 0xd7, 0xa1, + 0xcb, 0xc8, 0xc7, 0x24, + 0xc8, 0x22}; + +static int CheckCSRMaps(QCBORDecodeContext *pDC); + + +int OptTagParseTest() +{ + QCBORDecodeContext DCtx; + QCBORItem Item; + + QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spOptTestInput), QCBOR_DECODE_MODE_NORMAL); + + //------------------------- + // This text matches the magic number tag and the fraction tag + if(QCBORDecode_GetNext(&DCtx, &Item)) { + return -2; + } + if(Item.uDataType != QCBOR_TYPE_ARRAY || + !QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_CBOR_MAGIC)) { + return -3; + } + + if(QCBORDecode_GetNext(&DCtx, &Item)) { + return -4; + } + if(Item.uDataType != QCBOR_TYPE_ARRAY || + !QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_FRACTION) || + Item.val.uCount != 2) { + return -5; + } + + // -------------------------------- + // This test decodes the very large tag, but it is not in + // any list so it is ignored. + QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spEncodedLargeTag), QCBOR_DECODE_MODE_NORMAL); + if(QCBORDecode_GetNext(&DCtx, &Item)) { + return -6; + } + if(Item.uTagBits) { + return -7; + } + + // ---------------------------------- + // This test sets up a caller-config list that includes the very large tage and then matches it. + QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spEncodedLargeTag), QCBOR_DECODE_MODE_NORMAL); + const uint64_t puList[] = {0x9192939495969798, 257}; + const QCBORTagListIn TL = {2, puList}; + QCBORDecode_SetCallerConfiguredTagList(&DCtx, &TL); + + if(QCBORDecode_GetNext(&DCtx, &Item)) { + return -8; + } + if(Item.uDataType != QCBOR_TYPE_ARRAY || + !QCBORDecode_IsTagged(&DCtx, &Item, 0x9192939495969798) || + QCBORDecode_IsTagged(&DCtx, &Item, 257) || + QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_BIGFLOAT) || + Item.val.uCount != 0) { + return -9; + } + + //------------------------ + // This test sets up a caller-configured list, and looks up something not in it + const uint64_t puLongList[17] = {1,2,1}; + const QCBORTagListIn TLLong = {17, puLongList}; + QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spEncodedLargeTag), QCBOR_DECODE_MODE_NORMAL); + QCBORDecode_SetCallerConfiguredTagList(&DCtx, &TLLong); + if(QCBORDecode_GetNext(&DCtx, &Item)) { + return -11; + } + + // ----------------------- + // This tests retrievel of the full tag list + QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spLotsOfTags), QCBOR_DECODE_MODE_NORMAL); + uint64_t puTags[16]; + QCBORTagListOut Out = {0, 4, puTags}; + if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { + return -12; + } + if(puTags[0] != 0x9192939495969798 || + puTags[1] != 0x88 || + puTags[2] != 0x05 || + puTags[3] != 0x04) { + return -13; + } + + // ---------------------- + // This text if too small of an out list + QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spLotsOfTags), QCBOR_DECODE_MODE_NORMAL); + QCBORTagListOut OutSmall = {0, 3, puTags}; + if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &OutSmall) != QCBOR_ERR_TOO_MANY_TAGS) { + return -14; + } + + // --------------- + // Parse a version of the "CSR" that has had a ton of tags randomly inserted + QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spCSRWithTags), QCBOR_DECODE_MODE_NORMAL); + int n = CheckCSRMaps(&DCtx); + if(n) { + return n-2000; + } + + Out = (QCBORTagListOut){0,16, puTags}; + QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spCSRWithTags), QCBOR_DECODE_MODE_NORMAL); + + const uint64_t puTagList[] = {773, 1, 90599561}; + const QCBORTagListIn TagList = {3, puTagList}; + QCBORDecode_SetCallerConfiguredTagList(&DCtx, &TagList); + + + if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { + return -100; + } + if(Item.uDataType != QCBOR_TYPE_MAP || + !QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_CBOR_MAGIC) || + QCBORDecode_IsTagged(&DCtx, &Item, 90599561) || + QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_DATE_EPOCH) || + Item.val.uCount != 2 || + puTags[0] != CBOR_TAG_CBOR_MAGIC || + puTags[1] != CBOR_TAG_CBOR_MAGIC || + puTags[2] != CBOR_TAG_CBOR_MAGIC || + Out.uNumUsed != 3) { + return -101; + } + + if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { + return -102; + } + if(Item.uDataType != QCBOR_TYPE_MAP || + QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_CBOR_MAGIC) || + QCBORDecode_IsTagged(&DCtx, &Item, 6) || + QCBORDecode_IsTagged(&DCtx, &Item, 7) || // item is tagged 7, but 7 is not configured to be recognized + Item.val.uCount != 2 || + puTags[0] != 5859837686836516696 || + puTags[1] != 7 || + Out.uNumUsed != 2) { + return -103; + } + + if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { + return -104; + } + if(Item.uDataType != QCBOR_TYPE_MAP || + Item.uTagBits || + Item.val.uCount != 5 || + puTags[0] != 0x0b || + Out.uNumUsed != 1) { + return -105; + } + + if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { + return -106; + } + if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || + !QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_COSE_MAC0) || + Item.val.string.len != 12 || + puTags[0] != CBOR_TAG_COSE_MAC0 || + puTags[1] != CBOR_TAG_COSE_MAC0 || + puTags[2] != CBOR_TAG_COSE_MAC0 || + Out.uNumUsed != 3) { + return -105; + } + + if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { + return -107; + } + if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || + !QCBORDecode_IsTagged(&DCtx, &Item, 773) || + Item.val.string.len != 3 || + puTags[0] != 773 || + Out.uNumUsed != 1) { + return -108; + } + + if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { + return -109; + } + if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || + !QCBORDecode_IsTagged(&DCtx, &Item, 4) || + Item.val.string.len != 9 || + puTags[0] != 4 || + puTags[11] != 0x0f || + Out.uNumUsed != 12) { + return -110; + } + + if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { + return -111; + } + if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || + !QCBORDecode_IsTagged(&DCtx, &Item, 17) || + Item.val.string.len != 9 || + puTags[0] != 17 || + Out.uNumUsed != 1) { + return -112; + } + + if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { + return -111; + } + if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || + !QCBORDecode_IsTagged(&DCtx, &Item, 17) || + Item.val.string.len != 2 || + puTags[0] != 17 || + Out.uNumUsed != 1) { + return -112; + } + + if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { + return -113; + } + if(Item.uDataType != QCBOR_TYPE_MAP || + QCBORDecode_IsTagged(&DCtx, &Item, 19) || + Item.val.uCount != 2 || + puTags[0] != 19 || + Out.uNumUsed != 1) { + return -114; + } + + if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { + return -115; + } + if(Item.uDataType != QCBOR_TYPE_MAP || + QCBORDecode_IsTagged(&DCtx, &Item, 9) || + Item.uTagBits || + Item.val.uCount != 1 || + puTags[0] != 9 || + Out.uNumUsed != 1) { + return -116; + } + + if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { + return -116; + } + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.val.int64 != -7 || + Item.uTagBits || + Out.uNumUsed != 0) { + return -117; + } + + if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { + return -118; + } + if(Item.uDataType != QCBOR_TYPE_BYTE_STRING || + Item.val.string.len != 10 || + Item.uTagBits || + puTags[0] != 12 || + Out.uNumUsed != 1) { + return -119; + } + + if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { + return -120; + } + if(Item.uDataType != QCBOR_TYPE_MAP || + !QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_ENC_AS_B16) || + Item.val.uCount != 1 || + puTags[0] != 0x17 || + Out.uNumUsed != 1) { + return -121; + } + + if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) { + return -122; + } + if(Item.uDataType != QCBOR_TYPE_INT64 || + QCBORDecode_IsTagged(&DCtx, &Item, 8) || + Item.val.int64 != -3 || + puTags[0] != 8 || + Out.uNumUsed != 1) { + return -123; + } + + if(QCBORDecode_Finish(&DCtx)) { + return -124; + } + + return 0; +} + + + + +static uint8_t spBigNumInput[] = { + 0x83, + 0xC2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xA4, + 0x63, 0x42, 0x4E, 0x2B, + 0xC2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x40, + 0xC2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x63, 0x42, 0x4E, 0x2D, + 0xC3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x38, 0x3F, + 0xC3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + +static uint8_t spBigNum[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + +int BignumParseTest() +{ + QCBORDecodeContext DCtx; + QCBORItem Item; + int nCBORError; + + QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNumInput), QCBOR_DECODE_MODE_NORMAL); + + + // + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) + return -1; + if(Item.uDataType != QCBOR_TYPE_ARRAY) { + return -1; + } + + // + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) + return -1; + if(Item.uDataType != QCBOR_TYPE_POSBIGNUM || + UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){ + return -1; + } + + // + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) + return -1; + if(Item.uDataType != QCBOR_TYPE_NEGBIGNUM || + UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){ + return -1; + } + + // + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) + return -1; + if(Item.uDataType != QCBOR_TYPE_MAP) { + return -1; + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) + return -1; + if(Item.uDataType != QCBOR_TYPE_POSBIGNUM || + Item.uLabelType != QCBOR_TYPE_TEXT_STRING || + UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){ + return -1; + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) + return -1; + if(Item.uDataType != QCBOR_TYPE_POSBIGNUM || + Item.uLabelType != QCBOR_TYPE_INT64 || + Item.label.int64 != 64 || + UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){ + return -1; + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) + return -1; + if(Item.uDataType != QCBOR_TYPE_NEGBIGNUM || + Item.uLabelType != QCBOR_TYPE_TEXT_STRING || + UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){ + return -1; + } + + if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) + return -1; + if(Item.uDataType != QCBOR_TYPE_NEGBIGNUM || + Item.uLabelType != QCBOR_TYPE_INT64 || + Item.label.int64 != -64 || + UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){ + return -1; + } + + return 0; +} + + + +static int CheckItemWithIntLabel(QCBORDecodeContext *pCtx, uint8_t uDataType, uint8_t uNestingLevel, uint8_t uNextNest, int64_t nLabel, QCBORItem *pItem) +{ + QCBORItem Item; + int nCBORError; + + if((nCBORError = QCBORDecode_GetNext(pCtx, &Item))) return -1; + if(Item.uDataType != uDataType) return -1; + if(uNestingLevel > 0) { + if(Item.uLabelType != QCBOR_TYPE_INT64 && Item.uLabelType != QCBOR_TYPE_UINT64) return -1; + if(Item.uLabelType == QCBOR_TYPE_INT64) { + if(Item.label.int64 != nLabel) return -1; + } else { + if(Item.label.uint64 != (uint64_t)nLabel) return -1; + } + } + if(Item.uNestingLevel != uNestingLevel) return -1; + if(Item.uNextNestLevel != uNextNest) return -1; + + if(pItem) { + *pItem = Item; + } + return 0; +} + + +// Same code checks definite and indefinite length versions of the map +static int CheckCSRMaps(QCBORDecodeContext *pDC) +{ + if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_MAP, 0, 1, 0, NULL)) return -1; + + if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_MAP, 1, 2, -23, NULL)) return -1; + + if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_MAP, 2, 3, -20, NULL)) return -1; + + if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_TEXT_STRING, 3, 3, -18, NULL)) return -1; + if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_TEXT_STRING, 3, 3, -17, NULL)) return -1; + if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_TEXT_STRING, 3, 3, -15, NULL)) return -1; + if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_TEXT_STRING, 3, 3, -16, NULL)) return -1; + if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_TEXT_STRING, 3, 2, -14, NULL)) return -1; + + if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_MAP, 2, 3, -19, NULL)) return -1; + if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_MAP, 3, 4, -11, NULL)) return -1; + + if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_INT64, 4, 3, -9, NULL)) return -1; + if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_BYTE_STRING, 3, 1, -10, NULL)) return -1; + + if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_MAP, 1, 2, -22, NULL)) return -1; + if(CheckItemWithIntLabel(pDC, QCBOR_TYPE_INT64, 2, 0, -5, NULL)) return -1; + + if(QCBORDecode_Finish(pDC)) return -2; + + return 0; +} + + +/* +// cbor.me decoded output +{ + -23: { + -20: { + -18: "Organization", + -17: "SSG", + -15: "Confusion", + -16: "San Diego", + -14: "US" + }, + -19: { + -11: { + -9: -7 + }, + -10: '\u0001\u0002\u0003\u0004\u0005\u0006\a\b\t\n' + } + }, + -22: { + -5: -3 + } +} + */ + + +static uint8_t spCSRInput[] = { + 0xa2, 0x36, 0xa2, 0x33, 0xa5, 0x31, 0x6c, 0x4f, + 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x30, 0x63, 0x53, 0x53, 0x47, + 0x2e, 0x69, 0x43, 0x6f, 0x6e, 0x66, 0x75, 0x73, + 0x69, 0x6f, 0x6e, 0x2f, 0x69, 0x53, 0x61, 0x6e, + 0x20, 0x44, 0x69, 0x65, 0x67, 0x6f, 0x2d, 0x62, + 0x55, 0x53, 0x32, 0xa2, 0x2a, 0xa1, 0x28, 0x26, + 0x29, 0x4a, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x09, 0x0a, 0x35, 0xa1, 0x24, 0x22}; + +int NestedMapTest() +{ + QCBORDecodeContext DCtx; + + QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spCSRInput), QCBOR_DECODE_MODE_NORMAL); + + return CheckCSRMaps(&DCtx); +} + + + +int StringDecoderModeFailTest() +{ + QCBORDecodeContext DCtx; + + QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spCSRInput), QCBOR_DECODE_MODE_MAP_STRINGS_ONLY); + + QCBORItem Item; + QCBORError nCBORError; + + if(QCBORDecode_GetNext(&DCtx, &Item)) { + return -1; + } + if(Item.uDataType != QCBOR_TYPE_MAP) { + return -2; + } + + nCBORError = QCBORDecode_GetNext(&DCtx, &Item); + if(nCBORError != QCBOR_ERR_MAP_LABEL_TYPE) { + return -3; + } + + return 0; +} + + +// Same map as above, but using indefinite lengths +static uint8_t spCSRInputIndefLen[] = { + 0xbf, 0x36, 0xbf, 0x33, 0xbf, 0x31, 0x6c, 0x4f, + 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x30, 0x63, 0x53, 0x53, 0x47, + 0x2e, 0x69, 0x43, 0x6f, 0x6e, 0x66, 0x75, 0x73, + 0x69, 0x6f, 0x6e, 0x2f, 0x69, 0x53, 0x61, 0x6e, + 0x20, 0x44, 0x69, 0x65, 0x67, 0x6f, 0x2d, 0x62, + 0x55, 0x53, 0xff, 0x32, 0xbf, 0x2a, 0xbf, 0x28, + 0x26, 0xff, 0x29, 0x4a, 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0xff, 0xff, + 0x35, 0xbf, 0x24, 0x22, 0xff, 0xff}; + +int NestedMapTestIndefLen() +{ + QCBORDecodeContext DCtx; + + QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spCSRInputIndefLen), QCBOR_DECODE_MODE_NORMAL); + + return CheckCSRMaps(&DCtx); +} + + + +static UsefulBufC make_nested_indefinite_arrays(int n, UsefulBuf Storage) +{ + UsefulOutBuf UOB; + UsefulOutBuf_Init(&UOB, Storage); + + int i; + for(i = 0; i < n; i++) { + UsefulOutBuf_AppendByte(&UOB, 0x9f); + } + + for(i = 0; i < n; i++) { + UsefulOutBuf_AppendByte(&UOB, 0xff); + } + return UsefulOutBuf_OutUBuf(&UOB); +} + + +static int parse_indeflen_nested(UsefulBufC Nested, int nNestLevel) +{ + QCBORDecodeContext DC; + QCBORDecode_Init(&DC, Nested, 0); + + int j; + for(j = 0; j < nNestLevel; j++) { + QCBORItem Item; + int nReturn = QCBORDecode_GetNext(&DC, &Item); + if(j >= QCBOR_MAX_ARRAY_NESTING) { + // Should be in error + if(nReturn != QCBOR_ERR_ARRAY_NESTING_TOO_DEEP) { + return -4; + } else { + return 0; // Decoding doesn't recover after an error + } + } else { + // Should be no error + if(nReturn) { + return -9; // Should not have got an error + } + } + if(Item.uDataType != QCBOR_TYPE_ARRAY) { + return -7; + } + } + int nReturn = QCBORDecode_Finish(&DC); + if(nReturn) { + return -3; + } + return 0; +} + + +int IndefiniteLengthNestTest() +{ + UsefulBuf_MAKE_STACK_UB(Storage, 50); + int i; + for(i=1; i < QCBOR_MAX_ARRAY_NESTING+4; i++) { + const UsefulBufC Nested = make_nested_indefinite_arrays(i, Storage); + int nReturn = parse_indeflen_nested(Nested, i); + if(nReturn) { + return nReturn; + } + } + return 0; +} + + + +static const uint8_t spIndefiniteArray[] = {0x9f, 0x01, 0x82, 0x02, 0x03, 0xff}; // [1, [2, 3]] +static const uint8_t spIndefiniteArrayBad1[] = {0x9f}; // No closing break +static const uint8_t spIndefiniteArrayBad2[] = {0x9f, 0x9f, 0x02, 0xff}; // Not enough closing breaks +static const uint8_t spIndefiniteArrayBad3[] = {0x9f, 0x02, 0xff, 0xff}; // Too many closing breaks +static const uint8_t spIndefiniteArrayBad4[] = {0x81, 0x9f}; // Unclosed indeflen inside def len +static const uint8_t spIndefiniteArrayBad5[] = {0x9f, 0xd1, 0xff}; // confused tag + +int IndefiniteLengthArrayMapTest() +{ + int nResult; + // --- first test ----- + UsefulBufC IndefLen = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteArray); + + // Decode it and see if it is OK + UsefulBuf_MAKE_STACK_UB(MemPool, 150); + QCBORDecodeContext DC; + QCBORItem Item; + QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL); + + QCBORDecode_SetMemPool(&DC, MemPool, false); + + QCBORDecode_GetNext(&DC, &Item); + + if(Item.uDataType != QCBOR_TYPE_ARRAY || + Item.uNestingLevel != 0 || + Item.uNextNestLevel != 1) { + return -111; + } + + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.uNestingLevel != 1 || + Item.uNextNestLevel != 1) { + return -2; + } + + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_ARRAY || + Item.uNestingLevel != 1 || + Item.uNextNestLevel != 2) { + return -3; + } + + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.uNestingLevel != 2 || + Item.uNextNestLevel != 2) { + return -4; + } + + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_INT64 || + Item.uNestingLevel != 2 || + Item.uNextNestLevel != 0) { + return -5; + } + + if(QCBORDecode_Finish(&DC)) { + return -6; + } + + // --- next test ----- + IndefLen = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteArrayBad1); + + QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL); + + QCBORDecode_SetMemPool(&DC, MemPool, false); + + nResult = QCBORDecode_GetNext(&DC, &Item); + if(nResult || Item.uDataType != QCBOR_TYPE_ARRAY) { + return -7; + } + + nResult = QCBORDecode_Finish(&DC); + if(nResult != QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN) { + return -8; + } + + + // --- next test ----- + IndefLen = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteArrayBad2); + + QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL); + + QCBORDecode_SetMemPool(&DC, MemPool, false); + + nResult = QCBORDecode_GetNext(&DC, &Item); + if(nResult || Item.uDataType != QCBOR_TYPE_ARRAY) { + return -9; + } + + nResult = QCBORDecode_GetNext(&DC, &Item); + if(nResult || Item.uDataType != QCBOR_TYPE_ARRAY) { + return -10; + } + + nResult = QCBORDecode_GetNext(&DC, &Item); + if(nResult || Item.uDataType != QCBOR_TYPE_INT64) { + return -11; + } + + nResult = QCBORDecode_Finish(&DC); + if(nResult != QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN) { + return -12; + } + + + // --- next test ----- + IndefLen = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteArrayBad3); + + QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL); + + QCBORDecode_SetMemPool(&DC, MemPool, false); + + nResult = QCBORDecode_GetNext(&DC, &Item); + if(nResult || Item.uDataType != QCBOR_TYPE_ARRAY) { + return -13; + } + + nResult = QCBORDecode_GetNext(&DC, &Item); + if(nResult != QCBOR_ERR_BAD_BREAK) { + return -14; + } + + + // --- next test ----- + IndefLen = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteArrayBad4); + + QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL); + + QCBORDecode_SetMemPool(&DC, MemPool, false); + + nResult = QCBORDecode_GetNext(&DC, &Item); + if(nResult || Item.uDataType != QCBOR_TYPE_ARRAY) { + return -15; + } + + nResult = QCBORDecode_GetNext(&DC, &Item); + if(nResult || Item.uDataType != QCBOR_TYPE_ARRAY) { + return -16; + } + + nResult = QCBORDecode_Finish(&DC); + if(nResult != QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN) { + return -17; + } + + // --- next test ----- + IndefLen = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteArrayBad5); + + QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL); + + QCBORDecode_SetMemPool(&DC, MemPool, false); + + nResult = QCBORDecode_GetNext(&DC, &Item); + if(nResult || Item.uDataType != QCBOR_TYPE_ARRAY) { + return -18; + } + + nResult = QCBORDecode_GetNext(&DC, &Item); + if(nResult != QCBOR_ERR_BAD_BREAK) { + return -19; + } + + return 0; +} + + +static const uint8_t spIndefiniteLenString[] = { + 0x81, // Array of length one + 0x7f, // text string marked with indefinite length + 0x65, 0x73, 0x74, 0x72, 0x65, 0x61, // first segment + 0x64, 0x6d, 0x69, 0x6e, 0x67, // second segment + 0xff // ending break +}; + +static const uint8_t spIndefiniteLenStringBad2[] = { + 0x81, // Array of length one + 0x7f, // text string marked with indefinite length + 0x65, 0x73, 0x74, 0x72, 0x65, 0x61, // first segment + 0x44, 0x6d, 0x69, 0x6e, 0x67, // second segment of wrong type + 0xff // ending break +}; + +static const uint8_t spIndefiniteLenStringBad3[] = { + 0x81, // Array of length one + 0x7f, // text string marked with indefinite length + 0x01, 0x02, // Not a string + 0xff // ending break +}; + +static const uint8_t spIndefiniteLenStringBad4[] = { + 0x81, // Array of length one + 0x7f, // text string marked with indefinite length + 0x65, 0x73, 0x74, 0x72, 0x65, 0x61, // first segment + 0x64, 0x6d, 0x69, 0x6e, 0x67, // second segment + // missing end of string +}; + +static const uint8_t spIndefiniteLenStringLabel[] = { + 0xa1, // Array of length one + 0x7f, // text string marked with indefinite length + 0x65, 0x73, 0x74, 0x72, 0x75, 0x75, // first segment + 0x64, 0x6d, 0x69, 0x6e, 0x67, // second segment + 0xff, // ending break + 0x01 // integer being labeled. +}; + +static UsefulBufC MakeIndefiniteBigBstr(UsefulBuf Storage) // TODO: size this +{ + UsefulOutBuf UOB; + + UsefulOutBuf_Init(&UOB, Storage); + UsefulOutBuf_AppendByte(&UOB, 0x81); + UsefulOutBuf_AppendByte(&UOB, 0x5f); + + int i = 0; + for(int nChunkSize = 1; nChunkSize <= 128; nChunkSize *= 2) { + UsefulOutBuf_AppendByte(&UOB, 0x58); + UsefulOutBuf_AppendByte(&UOB, (uint8_t)nChunkSize); + for(int j = 0; j < nChunkSize; j++ ) { + UsefulOutBuf_AppendByte(&UOB, i); + i++; + } + } + UsefulOutBuf_AppendByte(&UOB, 0xff); + + return UsefulOutBuf_OutUBuf(&UOB); +} + +static int CheckBigString(UsefulBufC BigString) +{ + if(BigString.len != 255) { + return 1; + } + + for(uint8_t i = 0; i < 255; i++){ + if(((const uint8_t *)BigString.ptr)[i] != i) { + return 1; + } + } + return 0; +} + + +int IndefiniteLengthStringTest() +{ + QCBORDecodeContext DC; + QCBORItem Item; + // big enough for MakeIndefiniteBigBstr() + MemPool overhead + UsefulBuf_MAKE_STACK_UB(MemPool, 350); + + // --- Simple normal indefinite length string ------ + UsefulBufC IndefLen = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteLenString); + QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL); + + if(QCBORDecode_SetMemPool(&DC, MemPool, false)) { + return -1; + } + + if(QCBORDecode_GetNext(&DC, &Item)) { + return -2; + } + if(Item.uDataType != QCBOR_TYPE_ARRAY || Item.uDataAlloc) { + return -3; + } + + if(QCBORDecode_GetNext(&DC, &Item)) { + return -4; + } + if(Item.uDataType != QCBOR_TYPE_TEXT_STRING || !Item.uDataAlloc) { + return -5; + } + if(QCBORDecode_Finish(&DC)) { + return -6; + } + + // ----- types mismatch --- + QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteLenStringBad2), QCBOR_DECODE_MODE_NORMAL); + + if(QCBORDecode_SetMemPool(&DC, MemPool, false)) { + return -7; + } + + if(QCBORDecode_GetNext(&DC, &Item)) { + return -8; + } + if(Item.uDataType != QCBOR_TYPE_ARRAY) { + return -9; + } + + if(QCBORDecode_GetNext(&DC, &Item) != QCBOR_ERR_INDEFINITE_STRING_CHUNK) { + return -10; + } + + // ----- not a string --- + QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteLenStringBad3), QCBOR_DECODE_MODE_NORMAL); + + if(QCBORDecode_SetMemPool(&DC, MemPool, false)) { + return -11; + } + + if(QCBORDecode_GetNext(&DC, &Item)) { + return -12; + } + if(Item.uDataType != QCBOR_TYPE_ARRAY) { + return -13; + } + + if(QCBORDecode_GetNext(&DC, &Item) != QCBOR_ERR_INDEFINITE_STRING_CHUNK) { + return -14; + } + + // ----- no end ----- + QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteLenStringBad4), QCBOR_DECODE_MODE_NORMAL); + + if(QCBORDecode_SetMemPool(&DC, MemPool, false)) { + return -15; + } + + if(QCBORDecode_GetNext(&DC, &Item)) { + return -16; + } + if(Item.uDataType != QCBOR_TYPE_ARRAY) { + return -17; + } + + if(QCBORDecode_GetNext(&DC, &Item) != QCBOR_ERR_HIT_END) { + return -18; + } + + // ------ Don't set a string allocator and see an error ----- + QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL); + + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_ARRAY) { + return -19; + } + + if(QCBORDecode_GetNext(&DC, &Item) != QCBOR_ERR_NO_STRING_ALLOCATOR) { + return -20; + } + + // ----- Mempool is way too small ----- + UsefulBuf_MAKE_STACK_UB(MemPoolTooSmall, 20); // 20 is too small no matter what + + QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL); + if(!QCBORDecode_SetMemPool(&DC, MemPoolTooSmall, false)) { + return -21; + } + + // ----- Mempool is way too small ----- + UsefulBuf_MAKE_STACK_UB(BigIndefBStrStorage, 290); + const UsefulBufC BigIndefBStr = MakeIndefiniteBigBstr(BigIndefBStrStorage); + + UsefulBuf_MAKE_STACK_UB(MemPoolSmall, 80); // 80 is big enough for MemPool overhead, but not BigIndefBStr + + QCBORDecode_Init(&DC, BigIndefBStr, QCBOR_DECODE_MODE_NORMAL); + if(QCBORDecode_SetMemPool(&DC, MemPoolSmall, false)) { + return -22; + } + + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_ARRAY) { + return -23; + } + if(QCBORDecode_GetNext(&DC, &Item) != QCBOR_ERR_STRING_ALLOCATE) { + return -24; + } + + // ---- big bstr ----- + QCBORDecode_Init(&DC, BigIndefBStr, QCBOR_DECODE_MODE_NORMAL); + + if(QCBORDecode_SetMemPool(&DC, MemPool, false)) { + return -25; + } + + if(QCBORDecode_GetNext(&DC, &Item)) { + return -26; + } + if(Item.uDataType != QCBOR_TYPE_ARRAY || Item.uDataAlloc) { + return -26; + } + + if(QCBORDecode_GetNext(&DC, &Item)) { + return -27; + } + if(Item.uDataType != QCBOR_TYPE_BYTE_STRING || !Item.uDataAlloc || Item.uNestingLevel != 1) { + return -28; + } + if(CheckBigString(Item.val.string)) { + return -3; + } + if(QCBORDecode_Finish(&DC)) { + return -29; + } + + // --- label is an indefinite length string ------ + QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteLenStringLabel), QCBOR_DECODE_MODE_NORMAL); + + if(QCBORDecode_SetMemPool(&DC, MemPool, false)) { + return -30; + } + + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_MAP) { + return -31; + } + + if(QCBORDecode_GetNext(&DC, &Item)){ + return -32; + } + if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING || Item.uDataType != QCBOR_TYPE_INT64 || + Item.uDataAlloc || !Item.uLabelAlloc || + UsefulBuf_Compare(Item.label.string, UsefulBuf_FromSZ("struuming"))) { + return -33; + } + + if(QCBORDecode_Finish(&DC)) { + return -34; + } + + return 0; +} + + +int AllocAllStringsTest() +{ + QCBORDecodeContext DC; + QCBORError nCBORError; + + + // First test, use the "CSRMap" as easy input and checking + QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spCSRInput), QCBOR_DECODE_MODE_NORMAL); + + UsefulBuf_MAKE_STACK_UB(Pool, sizeof(spCSRInput) + QCBOR_DECODE_MIN_MEM_POOL_SIZE); + + nCBORError = QCBORDecode_SetMemPool(&DC, Pool, 1); // Turn on copying. + if(nCBORError) { + return -1; + } + + if(CheckCSRMaps(&DC)) { + return -2; + } + + // Next parse, save pointers to a few strings, destroy original and see all is OK. + UsefulBuf_MAKE_STACK_UB(CopyOfStorage, sizeof(pValidMapEncoded) + QCBOR_DECODE_MIN_MEM_POOL_SIZE); + const UsefulBufC CopyOf = UsefulBuf_Copy(CopyOfStorage, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded)); + + QCBORDecode_Init(&DC, CopyOf, QCBOR_DECODE_MODE_NORMAL); + UsefulBuf_Set(Pool, '/'); + QCBORDecode_SetMemPool(&DC, Pool, 1); // Turn on copying. + + QCBORItem Item1, Item2, Item3, Item4; + if((nCBORError = QCBORDecode_GetNext(&DC, &Item1))) + return nCBORError; + if(Item1.uDataType != QCBOR_TYPE_MAP || + Item1.val.uCount != 3) + return -3; + if((nCBORError = QCBORDecode_GetNext(&DC, &Item1))) + return nCBORError; + if((nCBORError = QCBORDecode_GetNext(&DC, &Item2))) + return nCBORError; + if((nCBORError = QCBORDecode_GetNext(&DC, &Item3))) + return nCBORError; + if((nCBORError = QCBORDecode_GetNext(&DC, &Item4))) + return nCBORError; + + UsefulBuf_Set(CopyOfStorage, '_'); + + if(Item1.uLabelType != QCBOR_TYPE_TEXT_STRING || + Item1.uDataType != QCBOR_TYPE_INT64 || + Item1.val.int64 != 42 || + UsefulBuf_Compare(Item1.label.string, UsefulBuf_FromSZ("first integer"))) { + return -4; + } + + + if(Item2.uLabelType != QCBOR_TYPE_TEXT_STRING || + UsefulBuf_Compare(Item2.label.string, UsefulBuf_FromSZ("an array of two strings")) || + Item2.uDataType != QCBOR_TYPE_ARRAY || + Item2.val.uCount != 2) + return -5; + + if(Item3.uDataType != QCBOR_TYPE_TEXT_STRING || + UsefulBuf_Compare(Item3.val.string, UsefulBuf_FromSZ("string1"))) { + return -6; + } + + if(Item4.uDataType != QCBOR_TYPE_TEXT_STRING || + UsefulBuf_Compare(Item4.val.string, UsefulBuf_FromSZ("string2"))) { + return -7; + } + + // Next parse with a pool that is too small + UsefulBuf_MAKE_STACK_UB(SmallPool, QCBOR_DECODE_MIN_MEM_POOL_SIZE + 1); + QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded), QCBOR_DECODE_MODE_NORMAL); + QCBORDecode_SetMemPool(&DC, SmallPool, 1); // Turn on copying. + if((nCBORError = QCBORDecode_GetNext(&DC, &Item1))) + return -8; + if(Item1.uDataType != QCBOR_TYPE_MAP || + Item1.val.uCount != 3) { + return -9; + } + if(!(nCBORError = QCBORDecode_GetNext(&DC, &Item1))){ + if(!(nCBORError = QCBORDecode_GetNext(&DC, &Item2))) { + if(!(nCBORError = QCBORDecode_GetNext(&DC, &Item3))) { + nCBORError = QCBORDecode_GetNext(&DC, &Item4); + } + } + } + if(nCBORError != QCBOR_ERR_STRING_ALLOCATE) { + return -10; + } + + return 0; +} + +// Cheating declaration to get to the special test hook +size_t MemPoolTestHook_GetPoolSize(void *ctx); + + +int MemPoolTest(void) +{ + // Set up the decoder with a tiny bit of CBOR to parse + QCBORDecodeContext DC; + const uint8_t pMinimalCBOR[] = {0xa0}; // One empty map + QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pMinimalCBOR),0); + + // Set up an memory pool of 100 bytes + UsefulBuf_MAKE_STACK_UB(Pool, 100); + QCBORError nError = QCBORDecode_SetMemPool(&DC, Pool, 0); + if(nError) { + return -9; + } + + // Cheat a little to get to the string allocator object + // so we can call it directly to test it + QCBORStringAllocator *pAlloc = (QCBORStringAllocator *)DC.pStringAllocator; + // Cheat some more to know exactly the + size_t uAvailPool = MemPoolTestHook_GetPoolSize(pAlloc); + + // First test -- ask for too much in one go + UsefulBuf Allocated = (*pAlloc->fAllocate)(pAlloc->pAllocaterContext, NULL, uAvailPool+1); + if(!UsefulBuf_IsNULL(Allocated)) { + return -1; + } + + + // Re do the set up for the next test that will do a successful alloc, + // a fail, a free and then success + // This test should work on 32 and 64-bit machines if the compiler + // does the expected thing with pointer sizes for the internal + // MemPool implementation leaving 44 or 72 bytes of pool memory. + QCBORDecode_SetMemPool(&DC, Pool, 0); + + // Cheat a little to get to the string allocator object + // so we can call it directly to test it + pAlloc = (QCBORStringAllocator *)DC.pStringAllocator; + // Cheat some more to know exactly the + uAvailPool = MemPoolTestHook_GetPoolSize(pAlloc); + + Allocated = (*pAlloc->fAllocate)(pAlloc->pAllocaterContext, NULL, uAvailPool-1); + if(UsefulBuf_IsNULL(Allocated)) { // expected to succeed + return -2; + } + UsefulBuf Allocated2 = (*pAlloc->fAllocate)(pAlloc->pAllocaterContext, NULL, uAvailPool/2); + if(!UsefulBuf_IsNULL(Allocated2)) { // expected to fail + return -3; + } + (*pAlloc->fFree)(pAlloc->pAllocaterContext, Allocated.ptr); + Allocated = (*pAlloc->fAllocate)(pAlloc->pAllocaterContext, NULL, uAvailPool/2); + if(UsefulBuf_IsNULL(Allocated)) { // succeed because of the free + return -4; + } + + + // Re do set up for next test that involves a successful alloc, + // and a successful realloc and a failed realloc + QCBORDecode_SetMemPool(&DC, Pool, 0); + + // Cheat a little to get to the string allocator object + // so we can call it directly to test it + pAlloc = (QCBORStringAllocator *)DC.pStringAllocator; + Allocated = (*pAlloc->fAllocate)(pAlloc->pAllocaterContext, NULL, uAvailPool/2); + if(UsefulBuf_IsNULL(Allocated)) { // expected to succeed + return -5; + } + Allocated2 = (*pAlloc->fAllocate)(pAlloc->pAllocaterContext, Allocated.ptr, uAvailPool); + if(UsefulBuf_IsNULL(Allocated2)) { + return -6; + } + if(Allocated2.ptr != Allocated.ptr || Allocated2.len != uAvailPool) { + return -7; + } + UsefulBuf Allocated3 = (*pAlloc->fAllocate)(pAlloc->pAllocaterContext, Allocated.ptr, uAvailPool+1); + if(!UsefulBuf_IsNULL(Allocated3)) { // expected to fail + return -8; + } + + return 0; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/qcbor_decode_tests.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/qcbor_decode_tests.h new file mode 100644 index 0000000..cbd352e --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/qcbor_decode_tests.h @@ -0,0 +1,230 @@ +/*============================================================================== + Copyright (c) 2016-2018, The Linux Foundation. + Copyright (c) 2018-2019, Laurence Lundblade. + All rights reserved. + SPDX-License-Identifier: BSD-3-Clause + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors, nor the name "Laurence Lundblade" may be used to + endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ==============================================================================*/ + +#ifndef __QCBOR__qcbort_decode_tests__ +#define __QCBOR__qcbort_decode_tests__ + +#include "qcbor.h" + + +/* + Notes: + + - All the functions in qcbor.h are called once in the aggregation of all the tests below. + + - All the types that are supported are given as input and parsed by these tests + + - There is some hostile input such as invalid lengths and CBOR too complex + and types this parser doesn't handle + + */ + + + + +/* + Parse a well-known set of integers including those around the boundaries and + make sure the expected values come out + */ +int IntegerValuesParseTest(void); + + + + + +/* + Decode a simple CBOR encoded array and make sure it returns all the correct values. + This is a decode test. + */ +int SimpleArrayTest(void); + + +/* + Make sure a maximally deep array can be parsed and that the + reported nesting level is correct. This uses test vector + of CBOR encoded data with a depth of 10. This a parse test. + */ +int ParseDeepArrayTest(void); + + +/* + See that the correct error is reported when parsing + an array of depth 11, one too large. + */ +int ParseTooDeepArrayTest(void); + + +/* + Try to parse some legit CBOR types that this parsers + doesn't support. + */ +int UnsupportedCBORDecodeTest(void); + + +/* + This takes the encoded CBOR integers used in the above test and parses + it over and over with one more byte less each time. It should fail + every time on incorrect CBOR input. This is a hostile input decode test. + */ +int ShortBufferParseTest(void); + + +/* + Same as ShortBufferParseTest, but with a different encoded CBOR input. + It is another hostile input test + */ +int ShortBufferParseTest2(void); + + +/* + Parses the somewhat complicated CBOR MAP and makes sure all the correct + values parse out. About 15 values are tested. This is a decode test. + */ +int ParseMapTest(void); + + + +int FloatValuesTest1(void); + + + +int SimpleValuesTest1(void); + + +/* + + */ +int ParseMapAsArrayTest(void); + + + +int ParseSimpleTest(void); + + + +/* + Tests a number of failure cases on bad CBOR to get the right error code + */ +int FailureTests(void); + + +/* + Parses all possible inputs that are two bytes long. Main point + is that the test doesn't crash as it doesn't evaluate the + input for correctness in any way. + + (Parsing all possible 3 byte strings takes too long on all but + very fast machines). + */ +int ComprehensiveInputTest(void); + + +/* + Parses all possible inputs that are four bytes long. Main point + is that the test doesn't crash as it doesn't evaluate the + input for correctness in any way. This runs very slow, so it + is only practical as a once-in-a-while regression test on + fast machines. + */ +int BigComprehensiveInputTest(void); + + +/* + Thest the date types -- epoch and strings + */ +int DateParseTest(void); + + +/* + Test optional tags like the CBOR magic number. + */ +int OptTagParseTest(void); + + +/* + Parse some big numbers, positive and negative + */ +int BignumParseTest(void); + + +int StringDecoderModeFailTest(void); + + +/* + Parse some nested maps + */ +int NestedMapTest(void); + + +/* + Parse maps with indefinite lengths + */ +int NestedMapTestIndefLen(void); + + +/* + Parse some maps and arrays with indefinite lengths. + Includes some error cases. + */ +int IndefiniteLengthArrayMapTest(void); + + +/* + Parse indefinite length strings. Uses + MemPool. Includes error cases. + */ +int IndefiniteLengthStringTest(void); + + +/* + Test deep nesting of indefinite length + maps and arrays including too deep. + */ +int IndefiniteLengthNestTest(void); + + +/* + Test parsing strings were all strings, not + just indefinite length strings, are + allocated. Includes error test cases. + */ +int AllocAllStringsTest(void); + + +/* + Direct test of MemPool string allocator + */ +int MemPoolTest(void); + + +#endif /* defined(__QCBOR__qcbort_decode_tests__) */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/qcbor_encode_tests.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/qcbor_encode_tests.c new file mode 100644 index 0000000..8d75119 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/qcbor_encode_tests.c @@ -0,0 +1,2007 @@ +/*============================================================================== + Copyright (c) 2016-2018, The Linux Foundation. + Copyright (c) 2018-2019, Laurence Lundblade. + All rights reserved. + SPDX-License-Identifier: BSD-3-Clause + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors, nor the name "Laurence Lundblade" may be used to + endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ==============================================================================*/ + +#include "qcbor.h" +#include "qcbor_encode_tests.h" + + +/* + This is the test set for CBOR encoding. + + This is largely complete for the implemented. + + A few more things to do include: + - Add a test for counting the top level items and adding it back in with AddRaw() + - Run on some different CPUs like 32-bit and maybe even 16-bit + - Test the large array count limit + - Add the CBOR diagnostic output for every expected + + */ + +//#define PRINT_FUNCTIONS_FOR_DEBUGGINGXX + +#ifdef PRINT_FUNCTIONS_FOR_DEBUGGINGXX +#include + +// ifdef these out to not have compiler warnings +static void printencoded(const uint8_t *pEncoded, size_t nLen) +{ + size_t i; + for(i = 0; i < nLen; i++) { + uint8_t Z = pEncoded[i]; + printf("%02x ", Z); + } + printf("\n"); + + fflush(stdout); +} + + +// Do the comparison and print out where it fails +static int UsefulBuf_Compare_Print(UsefulBufC U1, UsefulBufC U2) { + size_t i; + for(i = 0; i < U1.len; i++) { + if(((uint8_t *)U1.ptr)[i] != ((uint8_t *)U2.ptr)[i]) { + printf("Position: %d Actual: 0x%x Expected: 0x%x\n", i, ((uint8_t *)U1.ptr)[i], ((uint8_t *)U2.ptr)[i]); + return 1; + } + } + return 0; + +} + +#define CheckResults(Enc, Expected) \ + UsefulBuf_Compare_Print(Enc, (UsefulBufC){Expected, sizeof(Expected)}) + +#else + +#define CheckResults(Enc, Expected) \ + UsefulBuf_Compare(Enc, (UsefulBufC){Expected, sizeof(Expected)}) + +#endif + + + +// One big buffer that is used by all the tests to encode into +// Putting it in uninitialized data is better than using a lot +// of stack. The tests should run on small devices too. +static uint8_t spBigBuf[2200]; + + + +/* + Some very minimal tests. + */ +int BasicEncodeTest() +{ + // Very simple CBOR, a map with one boolean that is true in it + QCBOREncodeContext EC; + + QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); + + QCBOREncode_OpenMap(&EC); + QCBOREncode_AddBoolToMapN(&EC, 66, true); + QCBOREncode_CloseMap(&EC); + + UsefulBufC Encoded; + if(QCBOREncode_Finish(&EC, &Encoded)) { + return -1; + } + + + // Decode it and see that is right + QCBORDecodeContext DC; + QCBORItem Item; + QCBORDecode_Init(&DC, Encoded, QCBOR_DECODE_MODE_NORMAL); + + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_MAP) { + return -2; + } + + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_TRUE) { + return -3; + } + + if(QCBORDecode_Finish(&DC)) { + return -4; + } + + + // Make another encoded message with the CBOR from the previous put into this one + UsefulBuf_MAKE_STACK_UB(MemoryForEncoded2, 20); + QCBOREncode_Init(&EC, MemoryForEncoded2); + QCBOREncode_OpenArray(&EC); + QCBOREncode_AddUInt64(&EC, 451); + QCBOREncode_AddEncoded(&EC, Encoded); + QCBOREncode_OpenMap(&EC); + QCBOREncode_AddEncodedToMapN(&EC, -70000, Encoded); + QCBOREncode_CloseMap(&EC); + QCBOREncode_CloseArray(&EC); + + UsefulBufC Encoded2; + if(QCBOREncode_Finish(&EC, &Encoded2)) { + return -5; + } + /* + [ // 0 1:3 + 451, // 1 1:2 + { // 1 1:2 2:1 + 66: true // 2 1:1 + }, + { // 1 1:1 2:1 + -70000: { // 2 1:1 2:1 3:1 + 66: true // 3 XXXXXX + } + } + ] + + + + 83 # array(3) + 19 01C3 # unsigned(451) + A1 # map(1) + 18 42 # unsigned(66) + F5 # primitive(21) + A1 # map(1) + 3A 0001116F # negative(69999) + A1 # map(1) + 18 42 # unsigned(66) + F5 # primitive(21) + */ + + // Decode it and see if it is OK + QCBORDecode_Init(&DC, Encoded2, QCBOR_DECODE_MODE_NORMAL); + + // 0 1:3 + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_ARRAY || Item.val.uCount != 3) { + return -6; + } + + // 1 1:2 + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_INT64 || Item.val.uint64 != 451) { + return -7; + } + + // 1 1:2 2:1 + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_MAP || Item.val.uCount != 1) { + return -8; + } + + // 2 1:1 + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_TRUE) { + return -9; + } + + // 1 1:1 2:1 + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_MAP || Item.val.uCount != 1) { + return -10; + } + + // 2 1:1 2:1 3:1 + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_MAP || Item.val.uCount != 1 || Item.uLabelType != QCBOR_TYPE_INT64 || Item.label.int64 != -70000) { + return -11; + } + + // 3 XXXXXX + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_TRUE || Item.uLabelType != QCBOR_TYPE_INT64 || Item.label.int64 != 66) { + return -12; + } + + if(QCBORDecode_Finish(&DC)) { + return -13; + } + + return 0; +} + + + +static const uint8_t spExpectedEncodedAll[] = { + 0x98, 0x22, 0x66, 0x55, 0x49, 0x4e, 0x54, 0x36, 0x32, 0xd8, + 0x64, 0x1a, 0x05, 0x5d, 0x23, 0x15, 0x65, 0x49, 0x4e, 0x54, + 0x36, 0x34, 0xd8, 0x4c, 0x1b, 0x00, 0x00, 0x00, 0x12, 0x16, + 0xaf, 0x2b, 0x15, 0x00, 0x38, 0x2b, 0xa4, 0x63, 0x4c, 0x42, + 0x4c, 0x18, 0x4d, 0x23, 0x18, 0x58, 0x78, 0x1a, 0x4e, 0x45, + 0x47, 0x4c, 0x42, 0x4c, 0x54, 0x48, 0x41, 0x54, 0x20, 0x49, + 0x53, 0x20, 0x4b, 0x49, 0x4e, 0x44, 0x20, 0x4f, 0x46, 0x20, + 0x4c, 0x4f, 0x4e, 0x47, 0x3b, 0x00, 0x00, 0x02, 0x2d, 0x9a, + 0xc6, 0x94, 0x55, 0x3a, 0x05, 0xf5, 0xe0, 0xff, 0x3a, 0x2f, + 0xaf, 0x07, 0xff, 0xc1, 0x1a, 0x8e, 0x15, 0x1c, 0x8a, + 0xa3, 0x74, 0x4c, 0x6f, 0x6e, 0x67, 0x4c, 0x69, 0x76, 0x65, + 0x44, 0x65, 0x6e, 0x69, 0x73, 0x52, 0x69, 0x74, 0x63, 0x68, + 0x69, 0x65, 0xc1, 0x1a, 0x53, 0x72, 0x4e, 0x00, 0x66, 0x74, + 0x69, 0x6d, 0x65, 0x28, 0x29, 0xc1, 0x1a, 0x58, 0x0d, 0x41, + 0x72, 0x39, 0x07, 0xb0, 0xc1, 0x1a, 0x58, 0x0d, 0x3f, 0x76, + 0x42, 0xff, 0x00, 0xa3, 0x66, 0x62, 0x69, 0x6e, 0x62, 0x69, + 0x6e, 0xda, 0x00, 0x01, 0x86, 0xa0, 0x41, 0x00, 0x66, 0x62, + 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x43, 0x01, 0x02, 0x03, 0x00, + 0x44, 0x04, 0x02, 0x03, 0xfe, 0x6f, 0x62, 0x61, 0x72, 0x20, + 0x62, 0x61, 0x72, 0x20, 0x66, 0x6f, 0x6f, 0x20, 0x62, 0x61, + 0x72, 0x64, 0x6f, 0x6f, 0x66, 0x0a, 0xd8, 0x20, 0x78, 0x6b, + 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x73, 0x74, 0x61, + 0x63, 0x6b, 0x6f, 0x76, 0x65, 0x72, 0x66, 0x6c, 0x6f, 0x77, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x32, 0x38, 0x30, 0x35, 0x39, + 0x36, 0x39, 0x37, 0x2f, 0x68, 0x6f, 0x77, 0x2d, 0x64, 0x6f, + 0x2d, 0x69, 0x2d, 0x74, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x2d, + 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x2d, 0x64, 0x65, + 0x62, 0x75, 0x67, 0x2d, 0x61, 0x6e, 0x64, 0x2d, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2d, 0x62, 0x75, 0x69, 0x6c, + 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x2d, 0x78, 0x63, 0x6f, 0x64, + 0x65, 0x2d, 0x36, 0x2d, 0x37, 0x2d, 0x38, 0xd8, 0x22, 0x78, + 0x1c, 0x59, 0x57, 0x35, 0x35, 0x49, 0x47, 0x4e, 0x68, 0x63, + 0x6d, 0x35, 0x68, 0x62, 0x43, 0x42, 0x77, 0x62, 0x47, 0x56, + 0x68, 0x63, 0x33, 0x56, 0x79, 0x5a, 0x51, 0x3d, 0x3d, 0xd8, + 0x23, 0x67, 0x5b, 0x5e, 0x61, 0x62, 0x63, 0x5d, 0x2b, 0xd8, + 0x24, 0x79, 0x01, 0x57, 0x4d, 0x49, 0x4d, 0x45, 0x2d, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x2e, + 0x30, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, + 0x54, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x6d, 0x75, 0x6c, 0x74, + 0x69, 0x70, 0x61, 0x72, 0x74, 0x2f, 0x6d, 0x69, 0x78, 0x65, + 0x64, 0x3b, 0x0a, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, + 0x79, 0x3d, 0x22, 0x58, 0x58, 0x58, 0x58, 0x62, 0x6f, 0x75, + 0x6e, 0x64, 0x61, 0x72, 0x79, 0x20, 0x74, 0x65, 0x78, 0x74, + 0x22, 0x0a, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, + 0x20, 0x61, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, + 0x72, 0x74, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x20, 0x69, 0x6e, 0x20, 0x4d, 0x49, 0x4d, 0x45, 0x20, 0x66, + 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x2e, 0x0a, 0x0a, 0x2d, 0x2d, + 0x58, 0x58, 0x58, 0x58, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, + 0x72, 0x79, 0x20, 0x74, 0x65, 0x78, 0x74, 0x0a, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, 0x70, 0x65, + 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, 0x61, + 0x69, 0x6e, 0x0a, 0x0a, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, + 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6f, 0x64, 0x79, + 0x20, 0x74, 0x65, 0x78, 0x74, 0x0a, 0x0a, 0x2d, 0x2d, 0x58, + 0x58, 0x58, 0x58, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, + 0x79, 0x20, 0x74, 0x65, 0x78, 0x74, 0x0a, 0x43, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, 0x70, 0x65, 0x3a, + 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, 0x61, 0x69, + 0x6e, 0x3b, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x2d, 0x44, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x3a, 0x20, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, + 0x6d, 0x65, 0x6e, 0x74, 0x3b, 0x0a, 0x66, 0x69, 0x6c, 0x65, + 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x65, 0x73, 0x74, + 0x2e, 0x74, 0x78, 0x74, 0x22, 0x0a, 0x0a, 0x74, 0x68, 0x69, + 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, + 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x20, + 0x74, 0x65, 0x78, 0x74, 0x0a, 0x0a, 0x2d, 0x2d, 0x58, 0x58, + 0x58, 0x58, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, + 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x2d, 0xae, 0x65, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x6f, 0x66, 0x6f, 0x6f, 0x20, 0x62, + 0x61, 0x72, 0x20, 0x66, 0x6f, 0x6f, 0x20, 0x66, 0x6f, 0x6f, + 0x64, 0x5f, 0x5f, 0x5f, 0x5f, 0x67, 0x66, 0x6f, 0x6f, 0x20, + 0x62, 0x61, 0x72, 0x66, 0x28, 0x29, 0x28, 0x29, 0x28, 0x29, + 0xd9, 0x03, 0xe8, 0x6b, 0x72, 0x61, 0x62, 0x20, 0x72, 0x61, + 0x62, 0x20, 0x6f, 0x6f, 0x66, 0x16, 0x6f, 0x66, 0x6f, 0x6f, + 0x20, 0x66, 0x6f, 0x6f, 0x20, 0x66, 0x6f, 0x6f, 0x20, 0x66, + 0x6f, 0x6f, 0x62, 0x5e, 0x5e, 0x69, 0x6f, 0x6f, 0x6f, 0x6f, + 0x6f, 0x6f, 0x6f, 0x6f, 0x66, 0x18, 0x63, 0x6d, 0x66, 0x66, + 0x66, 0x66, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, + 0x66, 0x63, 0x52, 0x46, 0x43, 0xd8, 0x20, 0x78, 0x31, 0x68, + 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x74, 0x6f, 0x6f, + 0x6c, 0x73, 0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e, 0x6f, 0x72, + 0x67, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x2f, 0x72, 0x66, 0x63, + 0x37, 0x30, 0x34, 0x39, 0x23, 0x73, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x2d, 0x32, 0x2e, 0x34, 0x2e, 0x35, 0x18, 0x89, + 0xd8, 0x20, 0x6f, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, + 0x63, 0x62, 0x6f, 0x72, 0x2e, 0x6d, 0x65, 0x2f, 0x68, 0x77, + 0x68, 0x65, 0x6e, 0x69, 0x6d, 0x36, 0x34, 0xd8, 0x22, 0x6c, + 0x63, 0x47, 0x78, 0x6c, 0x59, 0x58, 0x4e, 0x31, 0x63, 0x6d, + 0x55, 0x75, 0x18, 0x40, 0xd8, 0x22, 0x68, 0x63, 0x33, 0x56, + 0x79, 0x5a, 0x53, 0x34, 0x3d, 0x64, 0x70, 0x6f, 0x70, 0x6f, + 0xd8, 0x23, 0x68, 0x31, 0x30, 0x30, 0x5c, 0x73, 0x2a, 0x6d, + 0x6b, 0x38, 0x32, 0xd8, 0x23, 0x66, 0x70, 0x65, 0x72, 0x6c, + 0x5c, 0x42, 0x63, 0x4e, 0x65, 0x64, 0xd8, 0x24, 0x79, 0x01, + 0x57, 0x4d, 0x49, 0x4d, 0x45, 0x2d, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x2e, 0x30, 0x0a, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, 0x70, + 0x65, 0x3a, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, + 0x72, 0x74, 0x2f, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x3b, 0x0a, + 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x3d, 0x22, + 0x58, 0x58, 0x58, 0x58, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, + 0x72, 0x79, 0x20, 0x74, 0x65, 0x78, 0x74, 0x22, 0x0a, 0x0a, + 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, + 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74, 0x20, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x69, 0x6e, + 0x20, 0x4d, 0x49, 0x4d, 0x45, 0x20, 0x66, 0x6f, 0x72, 0x6d, + 0x61, 0x74, 0x2e, 0x0a, 0x0a, 0x2d, 0x2d, 0x58, 0x58, 0x58, + 0x58, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x20, + 0x74, 0x65, 0x78, 0x74, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x2d, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, + 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x0a, + 0x0a, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x74, 0x65, + 0x78, 0x74, 0x0a, 0x0a, 0x2d, 0x2d, 0x58, 0x58, 0x58, 0x58, + 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x20, 0x74, + 0x65, 0x78, 0x74, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x2d, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, + 0x78, 0x74, 0x2f, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x3b, 0x0a, + 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x44, 0x69, + 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, + 0x20, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, + 0x74, 0x3b, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, + 0x65, 0x3d, 0x22, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74, 0x78, + 0x74, 0x22, 0x0a, 0x0a, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, + 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x74, 0x74, 0x61, + 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x65, 0x78, + 0x74, 0x0a, 0x0a, 0x2d, 0x2d, 0x58, 0x58, 0x58, 0x58, 0x62, + 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x20, 0x74, 0x65, + 0x78, 0x74, 0x2d, 0x2d, 0x0a, 0xd8, 0x24, 0x79, 0x01, 0x57, + 0x4d, 0x49, 0x4d, 0x45, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x2e, 0x30, 0x0a, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, 0x70, 0x65, + 0x3a, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, + 0x74, 0x2f, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x3b, 0x0a, 0x62, + 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x3d, 0x22, 0x58, + 0x58, 0x58, 0x58, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, + 0x79, 0x20, 0x74, 0x65, 0x78, 0x74, 0x22, 0x0a, 0x0a, 0x54, + 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x6d, + 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x69, 0x6e, 0x20, + 0x4d, 0x49, 0x4d, 0x45, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, + 0x74, 0x2e, 0x0a, 0x0a, 0x2d, 0x2d, 0x58, 0x58, 0x58, 0x58, + 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x20, 0x74, + 0x65, 0x78, 0x74, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x2d, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, + 0x78, 0x74, 0x2f, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x0a, 0x0a, + 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x74, 0x65, 0x78, + 0x74, 0x0a, 0x0a, 0x2d, 0x2d, 0x58, 0x58, 0x58, 0x58, 0x62, + 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x20, 0x74, 0x65, + 0x78, 0x74, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x2d, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, + 0x74, 0x2f, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x3b, 0x0a, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x44, 0x69, 0x73, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, + 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, + 0x3b, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, + 0x3d, 0x22, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74, 0x78, 0x74, + 0x22, 0x0a, 0x0a, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x74, 0x74, 0x61, 0x63, + 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x65, 0x78, 0x74, + 0x0a, 0x0a, 0x2d, 0x2d, 0x58, 0x58, 0x58, 0x58, 0x62, 0x6f, + 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x20, 0x74, 0x65, 0x78, + 0x74, 0x2d, 0x2d, 0xc0, 0x74, 0x32, 0x30, 0x30, 0x33, 0x2d, + 0x31, 0x32, 0x2d, 0x31, 0x33, 0x54, 0x31, 0x38, 0x3a, 0x33, + 0x30, 0x3a, 0x30, 0x32, 0x5a, 0xa2, 0x68, 0x42, 0x65, 0x64, + 0x20, 0x74, 0x69, 0x6d, 0x65, 0xc0, 0x78, 0x1c, 0x32, 0x30, + 0x30, 0x33, 0x2d, 0x31, 0x32, 0x2d, 0x31, 0x33, 0x54, 0x31, + 0x38, 0x3a, 0x33, 0x30, 0x3a, 0x30, 0x32, 0x2e, 0x32, 0x35, + 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0x18, 0x58, 0xc0, 0x78, + 0x1c, 0x32, 0x30, 0x30, 0x33, 0x2d, 0x31, 0x32, 0x2d, 0x31, + 0x33, 0x54, 0x31, 0x38, 0x3a, 0x33, 0x30, 0x3a, 0x30, 0x32, + 0x2e, 0x32, 0x35, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0xf7, + 0xa3, 0x64, 0x64, 0x61, 0x72, 0x65, 0xd8, 0x42, 0xf5, 0x62, + 0x75, 0x75, 0xf4, 0x1a, 0x00, 0x0b, 0x41, 0x62, 0xf6, 0x80, + 0xa3, 0x78, 0x1c, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x74, 0x61, 0x67, 0x67, 0x65, 0x64, 0x20, + 0x65, 0x6d, 0x70, 0x74, 0x79, 0x20, 0x61, 0x72, 0x72, 0x61, + 0x79, 0xd9, 0x04, 0x45, 0x80, 0x65, 0x61, 0x6c, 0x61, 0x62, + 0x6c, 0x80, 0x18, 0x2a, 0x80, 0xa1, 0x68, 0x69, 0x6e, 0x20, + 0x61, 0x20, 0x6d, 0x61, 0x70, 0xa1, 0x19, 0x15, 0xb4, 0xa1, + 0x6e, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x69, 0x6e, 0x20, 0x61, + 0x20, 0x69, 0x6e, 0x20, 0x61, 0xd9, 0x23, 0x7f, 0xa0, 0xa5, + 0x62, 0x73, 0x31, 0xd8, 0x58, 0xf8, 0xff, 0x62, 0x73, 0x32, + 0xe0, 0x62, 0x73, 0x33, 0xd8, 0x58, 0xf8, 0x21, 0x1a, 0x05, + 0x44, 0x8c, 0x06, 0xd8, 0x58, 0xf8, 0xff, 0x18, 0x59, 0xd8, + 0x58, 0xf3, 0xd8, 0x25, 0x50, 0x53, 0x4d, 0x41, 0x52, 0x54, + 0x43, 0x53, 0x4c, 0x54, 0x54, 0x43, 0x46, 0x49, 0x43, 0x41, + 0x32, 0xa2, 0x64, 0x55, 0x55, 0x55, 0x55, 0xd8, 0x25, 0x50, + 0x53, 0x4d, 0x41, 0x52, 0x54, 0x43, 0x53, 0x4c, 0x54, 0x54, + 0x43, 0x46, 0x49, 0x43, 0x41, 0x32, 0x18, 0x63, 0xd8, 0x25, + 0x50, 0x53, 0x4d, 0x41, 0x52, 0x54, 0x43, 0x53, 0x4c, 0x54, + 0x54, 0x43, 0x46, 0x49, 0x43, 0x41, 0x32, 0xf5, 0xf4, 0xa2, + 0x71, 0x47, 0x65, 0x6f, 0x72, 0x67, 0x65, 0x20, 0x69, 0x73, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0xf5, 0x19, + 0x10, 0x41, 0xf5, 0xC2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC3, 0x49, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0x63, 0x42, 0x4E, 0x2B, + 0xC2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x40, 0xC2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x63, 0x42, 0x4E, 0x2D, 0xC3, 0x49, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, + 0x3F, 0xC3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 +}; + + +static const char *szMIME = "\ +MIME-Version: 1.0\n\ +Content-Type: multipart/mixed;\n\ +boundary=\"XXXXboundary text\"\n\ +\n\ +This is a multipart message in MIME format.\n\ +\n\ +--XXXXboundary text\n\ +Content-Type: text/plain\n\ +\n\ +this is the body text\n\ +\n\ +--XXXXboundary text\n\ +Content-Type: text/plain;\n\ +Content-Disposition: attachment;\n\ +filename=\"test.txt\"\n\ +\n\ +this is the attachment text\n\ +\n\ +--XXXXboundary text--"; + + +int AllAddMethodsTest() +{ + // TODO: this test should be broken down into several so it is more managable. Tags and labels could be more sensible + QCBOREncodeContext ECtx; + int nReturn = 0; + + QCBOREncode_Init(&ECtx, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); + + QCBOREncode_OpenArray(&ECtx); + + // Some ints that are tagged and have strings preceeding them (not labels becase it is not a map) + QCBOREncode_AddSZString(&ECtx, "UINT62"); + QCBOREncode_AddTag(&ECtx, 100); + QCBOREncode_AddUInt64(&ECtx, 89989909); + QCBOREncode_AddSZString(&ECtx, "INT64"); + QCBOREncode_AddTag(&ECtx, 76); + QCBOREncode_AddInt64(&ECtx, 77689989909); + QCBOREncode_AddUInt64(&ECtx,0); + QCBOREncode_AddInt64(&ECtx, -44); + + // ints that go in maps + QCBOREncode_OpenMap(&ECtx); + QCBOREncode_AddUInt64ToMap(&ECtx, "LBL", 77); + QCBOREncode_AddUInt64ToMapN(&ECtx, -4, 88); + QCBOREncode_AddInt64ToMap(&ECtx, "NEGLBLTHAT IS KIND OF LONG", -2394893489238); + QCBOREncode_AddInt64ToMapN(&ECtx, -100000000, -800000000); + QCBOREncode_CloseMap(&ECtx); + + // Epoch Date + QCBOREncode_AddDateEpoch(&ECtx, 2383748234); + + // Epoch date with labels + QCBOREncode_OpenMap(&ECtx); + QCBOREncode_AddDateEpochToMap(&ECtx, "LongLiveDenisRitchie", 1400000000); + QCBOREncode_AddDateEpochToMap(&ECtx, "time()", 1477263730); + QCBOREncode_AddDateEpochToMapN(&ECtx, -1969, 1477263222); + QCBOREncode_CloseMap(&ECtx); + + // Binary blobs + QCBOREncode_AddBytes(&ECtx, ((UsefulBufC) {(uint8_t []){0xff, 0x00}, 2})); + + // binary blobs in maps + QCBOREncode_OpenMap(&ECtx); + QCBOREncode_AddSZString(&ECtx, "binbin"); + QCBOREncode_AddTag(&ECtx, 100000); + QCBOREncode_AddBytes(&ECtx, ((UsefulBufC) {(uint8_t []){0x00}, 1})); + QCBOREncode_AddBytesToMap(&ECtx, "blabel", ((UsefulBufC) {(uint8_t []){0x01, 0x02, 0x03}, 3})); + QCBOREncode_AddBytesToMapN(&ECtx, 0, ((UsefulBufC){(uint8_t []){0x04, 0x02, 0x03, 0xfe}, 4})); + QCBOREncode_CloseMap(&ECtx); + + // text blobs + QCBOREncode_AddText(&ECtx, UsefulBuf_FROM_SZ_LITERAL("bar bar foo bar")); + QCBOREncode_AddSZString(&ECtx, "oof\n"); + QCBOREncode_AddURI(&ECtx, UsefulBuf_FROM_SZ_LITERAL("http://stackoverflow.com/questions/28059697/how-do-i-toggle-between-debug-and-release-builds-in-xcode-6-7-8")); + QCBOREncode_AddB64Text(&ECtx, UsefulBuf_FROM_SZ_LITERAL("YW55IGNhcm5hbCBwbGVhc3VyZQ==")); + QCBOREncode_AddRegex(&ECtx, UsefulBuf_FROM_SZ_LITERAL("[^abc]+")); + QCBOREncode_AddMIMEData(&ECtx, UsefulBuf_FromSZ(szMIME)); + + // text blobs in maps + QCBOREncode_OpenMap(&ECtx); + QCBOREncode_AddTextToMap(&ECtx, "#####", UsefulBuf_FROM_SZ_LITERAL("foo bar foo foo")); + QCBOREncode_AddTextToMap(&ECtx, "____", UsefulBuf_FROM_SZ_LITERAL("foo bar")); + QCBOREncode_AddSZString(&ECtx, "()()()"); + QCBOREncode_AddTag(&ECtx, 1000); + QCBOREncode_AddSZString(&ECtx, "rab rab oof"); + QCBOREncode_AddTextToMapN(&ECtx,22, UsefulBuf_FROM_SZ_LITERAL("foo foo foo foo")); + QCBOREncode_AddSZStringToMap(&ECtx, "^^", "oooooooof"); + QCBOREncode_AddSZStringToMapN(&ECtx, 99, "ffffoooooooof"); + QCBOREncode_AddURIToMap(&ECtx, "RFC", UsefulBuf_FROM_SZ_LITERAL("https://tools.ietf.org/html/rfc7049#section-2.4.5")); + QCBOREncode_AddURIToMapN(&ECtx, 0x89, UsefulBuf_FROM_SZ_LITERAL("http://cbor.me/")); + QCBOREncode_AddB64TextToMap(&ECtx, "whenim64", UsefulBuf_FROM_SZ_LITERAL("cGxlYXN1cmUu")); + QCBOREncode_AddB64TextToMapN(&ECtx, 64, UsefulBuf_FROM_SZ_LITERAL("c3VyZS4=")); + QCBOREncode_AddRegexToMap(&ECtx, "popo", UsefulBuf_FROM_SZ_LITERAL("100\\s*mk")); // x code string literal bug + QCBOREncode_AddRegexToMapN(&ECtx, -51, UsefulBuf_FROM_SZ_LITERAL("perl\\B")); // x code string literal bug + QCBOREncode_AddMIMEDataToMap(&ECtx, "Ned", UsefulBuf_FromSZ(szMIME)); + QCBOREncode_AddMIMEDataToMapN(&ECtx, 10, UsefulBuf_FromSZ(szMIME)); + QCBOREncode_CloseMap(&ECtx); + + // Date strings + QCBOREncode_AddDateString(&ECtx, "2003-12-13T18:30:02Z"); + QCBOREncode_OpenMap(&ECtx); + QCBOREncode_AddDateStringToMap(&ECtx, "Bed time", "2003-12-13T18:30:02.25+01:00"); + QCBOREncode_AddDateStringToMapN(&ECtx, 88, "2003-12-13T18:30:02.25+01:00"); + QCBOREncode_CloseMap(&ECtx); + + // true / false ... + QCBOREncode_AddSimple(&ECtx, CBOR_SIMPLEV_UNDEF); + QCBOREncode_OpenMap(&ECtx); + QCBOREncode_AddSZString(&ECtx, "dare"); + QCBOREncode_AddTag(&ECtx, 66); + QCBOREncode_AddBool(&ECtx, true); + QCBOREncode_AddBoolToMap(&ECtx, "uu", false); + QCBOREncode_AddSimpleToMapN(&ECtx, 737634, CBOR_SIMPLEV_NULL); + QCBOREncode_CloseMap(&ECtx); + + // opening an array + QCBOREncode_OpenArray(&ECtx); + QCBOREncode_CloseArray(&ECtx); + + // opening arrays in a map + QCBOREncode_OpenMap(&ECtx); + QCBOREncode_AddSZString(&ECtx, "label and tagged empty array"); + QCBOREncode_AddTag(&ECtx, 1093); + QCBOREncode_OpenArray(&ECtx); + QCBOREncode_CloseArray(&ECtx); + QCBOREncode_OpenArrayInMap(&ECtx, "alabl"); + QCBOREncode_CloseArray(&ECtx); + QCBOREncode_OpenArrayInMapN(&ECtx, 42); + QCBOREncode_CloseArray(&ECtx); + QCBOREncode_CloseMap(&ECtx); + + // opening maps with labels and tagging + QCBOREncode_OpenMap(&ECtx); + QCBOREncode_OpenMapInMap(&ECtx, "in a map"); + QCBOREncode_OpenMapInMapN(&ECtx, 5556); + QCBOREncode_AddSZString(&ECtx, "in a in a in a"); + QCBOREncode_AddTag(&ECtx, 9087); + QCBOREncode_OpenMap(&ECtx); + QCBOREncode_CloseMap(&ECtx); + QCBOREncode_CloseMap(&ECtx); + QCBOREncode_CloseMap(&ECtx); + QCBOREncode_CloseMap(&ECtx); + + + // Extended simple values (these are not standard...) + QCBOREncode_OpenMap(&ECtx); + QCBOREncode_AddSZString(&ECtx, "s1"); + QCBOREncode_AddTag(&ECtx, 88); + QCBOREncode_AddSimple(&ECtx, 255); + QCBOREncode_AddSimpleToMap(&ECtx, "s2", 0); + QCBOREncode_AddSZString(&ECtx, "s3"); + QCBOREncode_AddTag(&ECtx, 88); + QCBOREncode_AddSimple(&ECtx, 33); + QCBOREncode_AddInt64(&ECtx, 88378374); // label before tag + QCBOREncode_AddTag(&ECtx, 88); + QCBOREncode_AddSimple(&ECtx, 255); + QCBOREncode_AddInt64(&ECtx, 89); // label before tag + QCBOREncode_AddTag(&ECtx, 88); + QCBOREncode_AddSimple(&ECtx, 19); + QCBOREncode_CloseMap(&ECtx); + + // UUIDs + static const uint8_t ppppUUID[] = {0x53, 0x4D, 0x41, 0x52, 0x54, 0x43, 0x53, 0x4C, 0x54, 0x54, 0x43, 0x46, 0x49, 0x43, 0x41, 0x32}; + const UsefulBufC XXUUID = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(ppppUUID); + QCBOREncode_AddBinaryUUID(&ECtx, XXUUID); + QCBOREncode_OpenMap(&ECtx); + QCBOREncode_AddBinaryUUIDToMap(&ECtx, "UUUU", XXUUID); + QCBOREncode_AddBinaryUUIDToMapN(&ECtx, 99, XXUUID); + QCBOREncode_CloseMap(&ECtx); + + // Bool + QCBOREncode_AddBool(&ECtx, true); + QCBOREncode_AddBool(&ECtx, false); + QCBOREncode_OpenMap(&ECtx); + QCBOREncode_AddBoolToMap(&ECtx, "George is the man", true); + QCBOREncode_AddBoolToMapN(&ECtx, 010101, true); + QCBOREncode_CloseMap(&ECtx); + + + static const uint8_t pBignum[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + const UsefulBufC BIGNUM = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBignum); + QCBOREncode_AddPositiveBignum(&ECtx, BIGNUM); + QCBOREncode_AddNegativeBignum(&ECtx, BIGNUM); + QCBOREncode_OpenMap(&ECtx); + QCBOREncode_AddPositiveBignumToMap(&ECtx, "BN+", BIGNUM); + QCBOREncode_AddPositiveBignumToMapN(&ECtx, 64, BIGNUM); + QCBOREncode_AddNegativeBignumToMap(&ECtx, "BN-", BIGNUM); + QCBOREncode_AddNegativeBignumToMapN(&ECtx, -64, BIGNUM); + QCBOREncode_CloseMap(&ECtx); + + QCBOREncode_CloseArray(&ECtx); + + UsefulBufC Enc; + + if(QCBOREncode_Finish(&ECtx, &Enc)) { + nReturn = -1; + goto Done; + } + + if(CheckResults(Enc, spExpectedEncodedAll)) + nReturn = -2; + +Done: + return nReturn; +} + +/* + 98 2F # array(47) + 3B 7FFFFFFFFFFFFFFF # negative(9223372036854775807) + 3B 0000000100000000 # negative(4294967296) + 3A FFFFFFFF # negative(4294967295) + 3A FFFFFFFE # negative(4294967294) + 3A FFFFFFFD # negative(4294967293) + 3A 7FFFFFFF # negative(2147483647) + 3A 7FFFFFFE # negative(2147483646) + 3A 00010001 # negative(65537) + 3A 00010000 # negative(65536) + 39 FFFF # negative(65535) + 39 FFFE # negative(65534) + 39 FFFD # negative(65533) + 39 0100 # negative(256) + 38 FF # negative(255) + 38 FE # negative(254) + 38 FD # negative(253) + 38 18 # negative(24) + 37 # negative(23) + 36 # negative(22) + 20 # negative(0) + 00 # unsigned(0) + 00 # unsigned(0) + 01 # unsigned(1) + 16 # unsigned(22) + 17 # unsigned(23) + 18 18 # unsigned(24) + 18 19 # unsigned(25) + 18 1A # unsigned(26) + 18 FE # unsigned(254) + 18 FF # unsigned(255) + 19 0100 # unsigned(256) + 19 0101 # unsigned(257) + 19 FFFE # unsigned(65534) + 19 FFFF # unsigned(65535) + 1A 00010000 # unsigned(65536) + 1A 00010001 # unsigned(65537) + 1A 00010002 # unsigned(65538) + 1A 7FFFFFFF # unsigned(2147483647) + 1A 7FFFFFFF # unsigned(2147483647) + 1A 80000000 # unsigned(2147483648) + 1A 80000001 # unsigned(2147483649) + 1A FFFFFFFE # unsigned(4294967294) + 1A FFFFFFFF # unsigned(4294967295) + 1B 0000000100000000 # unsigned(4294967296) + 1B 0000000100000001 # unsigned(4294967297) + 1B 7FFFFFFFFFFFFFFF # unsigned(9223372036854775807) + 1B FFFFFFFFFFFFFFFF # unsigned(18446744073709551615) + */ +static const uint8_t spExpectedEncodedInts[] = { + 0x98, 0x2f, 0x3b, 0x7f, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x3b, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x3a, 0xff, 0xff, 0xff, + 0xff, 0x3a, 0xff, 0xff, 0xff, 0xfe, 0x3a, 0xff, + 0xff, 0xff, 0xfd, 0x3a, 0x7f, 0xff, 0xff, 0xff, + 0x3a, 0x7f, 0xff, 0xff, 0xfe, 0x3a, 0x00, 0x01, + 0x00, 0x01, 0x3a, 0x00, 0x01, 0x00, 0x00, 0x39, + 0xff, 0xff, 0x39, 0xff, 0xfe, 0x39, 0xff, 0xfd, + 0x39, 0x01, 0x00, 0x38, 0xff, 0x38, 0xfe, 0x38, + 0xfd, 0x38, 0x18, 0x37, 0x36, 0x20, 0x00, 0x00, + 0x01, 0x16, 0x17, 0x18, 0x18, 0x18, 0x19, 0x18, + 0x1a, 0x18, 0xfe, 0x18, 0xff, 0x19, 0x01, 0x00, + 0x19, 0x01, 0x01, 0x19, 0xff, 0xfe, 0x19, 0xff, + 0xff, 0x1a, 0x00, 0x01, 0x00, 0x00, 0x1a, 0x00, + 0x01, 0x00, 0x01, 0x1a, 0x00, 0x01, 0x00, 0x02, + 0x1a, 0x7f, 0xff, 0xff, 0xff, 0x1a, 0x7f, 0xff, + 0xff, 0xff, 0x1a, 0x80, 0x00, 0x00, 0x00, 0x1a, + 0x80, 0x00, 0x00, 0x01, 0x1a, 0xff, 0xff, 0xff, + 0xfe, 0x1a, 0xff, 0xff, 0xff, 0xff, 0x1b, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1b, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x1b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff}; + +/* + + Test the generation of integers. This also ends up testing + encoding of all the different lengths. It encodes integers + of many lengths and values, especially around the boundaries + for different types of integers. It compares the output + to expected values generated from http://cbor.me. + + */ +int IntegerValuesTest1() +{ + QCBOREncodeContext ECtx; + int nReturn = 0; + + QCBOREncode_Init(&ECtx, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); + QCBOREncode_OpenArray(&ECtx); + + QCBOREncode_AddInt64(&ECtx, -9223372036854775807LL - 1); + QCBOREncode_AddInt64(&ECtx, -4294967297); + QCBOREncode_AddInt64(&ECtx, -4294967296); + QCBOREncode_AddInt64(&ECtx, -4294967295); + QCBOREncode_AddInt64(&ECtx, -4294967294); + QCBOREncode_AddInt64(&ECtx, -2147483648); + QCBOREncode_AddInt64(&ECtx, -2147483647); + QCBOREncode_AddInt64(&ECtx, -65538); + QCBOREncode_AddInt64(&ECtx, -65537); + QCBOREncode_AddInt64(&ECtx, -65536); + QCBOREncode_AddInt64(&ECtx, -65535); + QCBOREncode_AddInt64(&ECtx, -65534); + QCBOREncode_AddInt64(&ECtx, -257); + QCBOREncode_AddInt64(&ECtx, -256); + QCBOREncode_AddInt64(&ECtx, -255); + QCBOREncode_AddInt64(&ECtx, -254); + QCBOREncode_AddInt64(&ECtx, -25); + QCBOREncode_AddInt64(&ECtx, -24); + QCBOREncode_AddInt64(&ECtx, -23); + QCBOREncode_AddInt64(&ECtx, -1); + QCBOREncode_AddInt64(&ECtx, 0); + QCBOREncode_AddUInt64(&ECtx, 0ULL); + QCBOREncode_AddInt64(&ECtx, 1); + QCBOREncode_AddInt64(&ECtx, 22); + QCBOREncode_AddInt64(&ECtx, 23); + QCBOREncode_AddInt64(&ECtx, 24); + QCBOREncode_AddInt64(&ECtx, 25); + QCBOREncode_AddInt64(&ECtx, 26); + QCBOREncode_AddInt64(&ECtx, 254); + QCBOREncode_AddInt64(&ECtx, 255); + QCBOREncode_AddInt64(&ECtx, 256); + QCBOREncode_AddInt64(&ECtx, 257); + QCBOREncode_AddInt64(&ECtx, 65534); + QCBOREncode_AddInt64(&ECtx, 65535); + QCBOREncode_AddInt64(&ECtx, 65536); + QCBOREncode_AddInt64(&ECtx, 65537); + QCBOREncode_AddInt64(&ECtx, 65538); + QCBOREncode_AddInt64(&ECtx, 2147483647); + QCBOREncode_AddInt64(&ECtx, 2147483647); + QCBOREncode_AddInt64(&ECtx, 2147483648); + QCBOREncode_AddInt64(&ECtx, 2147483649); + QCBOREncode_AddInt64(&ECtx, 4294967294); + QCBOREncode_AddInt64(&ECtx, 4294967295); + QCBOREncode_AddInt64(&ECtx, 4294967296); + QCBOREncode_AddInt64(&ECtx, 4294967297); + QCBOREncode_AddInt64(&ECtx, 9223372036854775807LL); + QCBOREncode_AddUInt64(&ECtx, 18446744073709551615ULL); + + QCBOREncode_CloseArray(&ECtx); + + UsefulBufC Enc; + if(QCBOREncode_Finish(&ECtx, &Enc)) { + nReturn = -1; + } + + if(CheckResults(Enc, spExpectedEncodedInts)) + return -2; + + return(nReturn); +} + + +/* + 85 # array(5) + F5 # primitive(21) + F4 # primitive(20) + F6 # primitive(22) + F7 # primitive(23) + A1 # map(1) + 65 # text(5) + 554E446566 # "UNDef" + F7 # primitive(23) + */ +static const uint8_t spExpectedEncodedSimple[] = { + 0x85, 0xf5, 0xf4, 0xf6, 0xf7, 0xa1, 0x65, 0x55, 0x4e, 0x44, 0x65, 0x66, 0xf7}; + +int SimpleValuesTest1() +{ + QCBOREncodeContext ECtx; + int nReturn = 0; + + QCBOREncode_Init(&ECtx, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); + QCBOREncode_OpenArray(&ECtx); + + QCBOREncode_AddSimple(&ECtx, CBOR_SIMPLEV_TRUE); + QCBOREncode_AddSimple(&ECtx, CBOR_SIMPLEV_FALSE); + QCBOREncode_AddSimple(&ECtx, CBOR_SIMPLEV_NULL); + QCBOREncode_AddSimple(&ECtx, CBOR_SIMPLEV_UNDEF); + + QCBOREncode_OpenMap(&ECtx); + + QCBOREncode_AddSimpleToMap(&ECtx, "UNDef", CBOR_SIMPLEV_UNDEF); + QCBOREncode_CloseMap(&ECtx); + + QCBOREncode_CloseArray(&ECtx); + + UsefulBufC ECBOR; + if(QCBOREncode_Finish(&ECtx, &ECBOR)) { + nReturn = -1; + } + + if(CheckResults(ECBOR, spExpectedEncodedSimple)) + return -2; + + return(nReturn); +} + + +/* + 83 # array(3) + C0 # tag(0) + 74 # text(20) + 323031332D30332D32315432303A30343A30305A # "2013-03-21T20:04:00Z" + C1 # tag(1) + 1A 514B67B0 # unsigned(1363896240) + A2 # map(2) + 78 19 # text(25) + 53616D706C6520446174652066726F6D205246432033333339 # "Sample Date from RFC 3339" + C0 # tag(0) + 77 # text(23) + 313938352D30342D31325432333A32303A35302E35325A # "1985-04-12T23:20:50.52Z" + 62 # text(2) + 5344 # "SD" + C1 # tag(1) + 19 03E7 # unsigned(999) + */ +static const uint8_t spExpectedEncodedDates[] = { + 0x83, 0xc0, 0x74, 0x32, 0x30, 0x31, 0x33, 0x2d, 0x30, 0x33, + 0x2d, 0x32, 0x31, 0x54, 0x32, 0x30, 0x3a, 0x30, 0x34, 0x3a, + 0x30, 0x30, 0x5a, 0xc1, 0x1a, 0x51, 0x4b, 0x67, 0xb0, 0xa2, + 0x78, 0x19, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x44, + 0x61, 0x74, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x52, + 0x46, 0x43, 0x20, 0x33, 0x33, 0x33, 0x39, 0xc0, 0x77, 0x31, + 0x39, 0x38, 0x35, 0x2d, 0x30, 0x34, 0x2d, 0x31, 0x32, 0x54, + 0x32, 0x33, 0x3a, 0x32, 0x30, 0x3a, 0x35, 0x30, 0x2e, 0x35, + 0x32, 0x5a, 0x62, 0x53, 0x44, 0xc1, 0x19, 0x03, 0xe7 +}; + +int EncodeDateTest() +{ + QCBOREncodeContext ECtx; + int nReturn = 0; + + QCBOREncode_Init(&ECtx, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); + + QCBOREncode_OpenArray(&ECtx); + + + QCBOREncode_AddDateString(&ECtx, "2013-03-21T20:04:00Z"); // from CBOR RFC + QCBOREncode_AddDateEpoch(&ECtx, 1363896240); // from CBOR RFC + + + QCBOREncode_OpenMap(&ECtx); + + QCBOREncode_AddDateStringToMap(&ECtx, "Sample Date from RFC 3339", "1985-04-12T23:20:50.52Z"); + + QCBOREncode_AddDateEpochToMap(&ECtx, "SD", 999); + + QCBOREncode_CloseMap(&ECtx); + + QCBOREncode_CloseArray(&ECtx); + + UsefulBufC ECBOR; + + if(QCBOREncode_Finish(&ECtx, &ECBOR)) { + nReturn = -1; + } + + if(CheckResults(ECBOR, spExpectedEncodedDates)) + return -2; + + return(nReturn); +} + + +int ArrayNestingTest1() +{ + QCBOREncodeContext ECtx; + int i; + int nReturn = 0; + + QCBOREncode_Init(&ECtx, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); + for(i = QCBOR_MAX_ARRAY_NESTING; i; i--) { + QCBOREncode_OpenArray(&ECtx); + } + for(i = QCBOR_MAX_ARRAY_NESTING; i; i--) { + QCBOREncode_CloseArray(&ECtx); + } + UsefulBufC Encoded; + if(QCBOREncode_Finish(&ECtx, &Encoded)) { + nReturn = -1; + } + + return(nReturn); +} + + + +int ArrayNestingTest2() +{ + QCBOREncodeContext ECtx; + int i; + int nReturn = 0; + + QCBOREncode_Init(&ECtx, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); + for(i = QCBOR_MAX_ARRAY_NESTING+1; i; i--) { + QCBOREncode_OpenArray(&ECtx); + } + for(i = QCBOR_MAX_ARRAY_NESTING; i; i--) { + QCBOREncode_CloseArray(&ECtx); + } + + UsefulBufC Encoded; + if(QCBOREncode_Finish(&ECtx, &Encoded) != QCBOR_ERR_ARRAY_NESTING_TOO_DEEP) { + nReturn = -1; + } + + return(nReturn); +} + + + +int ArrayNestingTest3() +{ + QCBOREncodeContext ECtx; + int i; + int nReturn = 0; + + QCBOREncode_Init(&ECtx, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); + for(i = QCBOR_MAX_ARRAY_NESTING; i; i--) { + QCBOREncode_OpenArray(&ECtx); + } + for(i = QCBOR_MAX_ARRAY_NESTING+1 ; i; i--) { + QCBOREncode_CloseArray(&ECtx); + } + UsefulBufC Encoded; + if(QCBOREncode_Finish(&ECtx, &Encoded) != QCBOR_ERR_TOO_MANY_CLOSES) { + nReturn = -1; + } + + return(nReturn); +} + + +/* + 81 # array(1) + 81 # array(1) + 81 # array(1) + 81 # array(1) + 80 # array(0) +*/ +static const uint8_t spFiveArrarys[] = {0x81, 0x81, 0x81, 0x81, 0x80}; + +// Validated at http://cbor.me and by manually examining its output +/* + 82 # array(2) + 81 # array(1) + 81 # array(1) + 81 # array(1) + 81 # array(1) + 80 # array(0) + 98 2F # array(47) + 3B 7FFFFFFFFFFFFFFF # negative(9223372036854775807) + 3B 0000000100000000 # negative(4294967296) + 3A FFFFFFFF # negative(4294967295) + 3A FFFFFFFE # negative(4294967294) + 3A FFFFFFFD # negative(4294967293) + 3A 7FFFFFFF # negative(2147483647) + 3A 7FFFFFFE # negative(2147483646) + 3A 00010001 # negative(65537) + 3A 00010000 # negative(65536) + 39 FFFF # negative(65535) + 39 FFFE # negative(65534) + 39 FFFD # negative(65533) + 39 0100 # negative(256) + 38 FF # negative(255) + 38 FE # negative(254) + 38 FD # negative(253) + 38 18 # negative(24) + 37 # negative(23) + 36 # negative(22) + 20 # negative(0) + 00 # unsigned(0) + 00 # unsigned(0) + 01 # unsigned(1) + 16 # unsigned(22) + 17 # unsigned(23) + 18 18 # unsigned(24) + 18 19 # unsigned(25) + 18 1A # unsigned(26) + 18 FE # unsigned(254) + 18 FF # unsigned(255) + 19 0100 # unsigned(256) + 19 0101 # unsigned(257) + 19 FFFE # unsigned(65534) + 19 FFFF # unsigned(65535) + 1A 00010000 # unsigned(65536) + 1A 00010001 # unsigned(65537) + 1A 00010002 # unsigned(65538) + 1A 7FFFFFFF # unsigned(2147483647) + 1A 7FFFFFFF # unsigned(2147483647) + 1A 80000000 # unsigned(2147483648) + 1A 80000001 # unsigned(2147483649) + 1A FFFFFFFE # unsigned(4294967294) + 1A FFFFFFFF # unsigned(4294967295) + 1B 0000000100000000 # unsigned(4294967296) + 1B 0000000100000001 # unsigned(4294967297) + 1B 7FFFFFFFFFFFFFFF # unsigned(9223372036854775807) + 1B FFFFFFFFFFFFFFFF # unsigned(18446744073709551615) + */ +static const uint8_t spEncodeRawExpected[] = { + 0x82, 0x81, 0x81, 0x81, 0x81, 0x80, 0x98, 0x2f, + 0x3b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x3b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x3a, 0xff, 0xff, 0xff, 0xff, 0x3a, + 0xff, 0xff, 0xff, 0xfe, 0x3a, 0xff, 0xff, 0xff, + 0xfd, 0x3a, 0x7f, 0xff, 0xff, 0xff, 0x3a, 0x7f, + 0xff, 0xff, 0xfe, 0x3a, 0x00, 0x01, 0x00, 0x01, + 0x3a, 0x00, 0x01, 0x00, 0x00, 0x39, 0xff, 0xff, + 0x39, 0xff, 0xfe, 0x39, 0xff, 0xfd, 0x39, 0x01, + 0x00, 0x38, 0xff, 0x38, 0xfe, 0x38, 0xfd, 0x38, + 0x18, 0x37, 0x36, 0x20, 0x00, 0x00, 0x01, 0x16, + 0x17, 0x18, 0x18, 0x18, 0x19, 0x18, 0x1a, 0x18, + 0xfe, 0x18, 0xff, 0x19, 0x01, 0x00, 0x19, 0x01, + 0x01, 0x19, 0xff, 0xfe, 0x19, 0xff, 0xff, 0x1a, + 0x00, 0x01, 0x00, 0x00, 0x1a, 0x00, 0x01, 0x00, + 0x01, 0x1a, 0x00, 0x01, 0x00, 0x02, 0x1a, 0x7f, + 0xff, 0xff, 0xff, 0x1a, 0x7f, 0xff, 0xff, 0xff, + 0x1a, 0x80, 0x00, 0x00, 0x00, 0x1a, 0x80, 0x00, + 0x00, 0x01, 0x1a, 0xff, 0xff, 0xff, 0xfe, 0x1a, + 0xff, 0xff, 0xff, 0xff, 0x1b, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x1b, 0x7f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1b, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + +int EncodeRawTest() +{ + QCBOREncodeContext ECtx; + + QCBOREncode_Init(&ECtx, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); + QCBOREncode_OpenArray(&ECtx); + QCBOREncode_AddEncoded(&ECtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spFiveArrarys)); + QCBOREncode_AddEncoded(&ECtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedEncodedInts)); + QCBOREncode_CloseArray(&ECtx); + + UsefulBufC EncodedRawTest; + + if(QCBOREncode_Finish(&ECtx, &EncodedRawTest)) { + return -4; + } + + if(CheckResults(EncodedRawTest, spEncodeRawExpected)) { + return -5; + } + + return 0; +} + +/* + This returns a pointer to spBigBuf + */ +static int CreateMap(uint8_t **pEncoded, size_t *pEncodedLen) +{ + QCBOREncodeContext ECtx; + int nReturn = -1; + + *pEncoded = NULL; + *pEncodedLen = INT32_MAX; + size_t uFirstSizeEstimate = 0; + + // loop runs CBOR encoding twice. First with no buffer to + // calucate the length so buffer can be allocated correctly, + // and last with the buffer to do the actual encoding + do { + QCBOREncode_Init(&ECtx, (UsefulBuf){*pEncoded, *pEncodedLen}); + QCBOREncode_OpenMap(&ECtx); + QCBOREncode_AddInt64ToMap(&ECtx, "first integer", 42); + QCBOREncode_OpenArrayInMap(&ECtx, "an array of two strings"); + QCBOREncode_AddText(&ECtx, ((UsefulBufC) {"string1", 7})); + QCBOREncode_AddText(&ECtx, ((UsefulBufC) {"string2", 7})); + QCBOREncode_CloseArray(&ECtx); + QCBOREncode_OpenMapInMap(&ECtx, "map in a map"); + QCBOREncode_AddBytesToMap(&ECtx,"bytes 1", ((UsefulBufC) { "xxxx", 4})); + QCBOREncode_AddBytesToMap(&ECtx, "bytes 2",((UsefulBufC) { "yyyy", 4})); + QCBOREncode_AddInt64ToMap(&ECtx, "another int", 98); + QCBOREncode_AddTextToMap(&ECtx, "text 2", ((UsefulBufC) {"lies, damn lies and statistics", 30})); + QCBOREncode_CloseMap(&ECtx); + QCBOREncode_CloseMap(&ECtx); + + if(QCBOREncode_FinishGetSize(&ECtx, pEncodedLen)) + goto Done; + if(*pEncoded != NULL) { + if(uFirstSizeEstimate != *pEncodedLen) { + nReturn = 1; + } else { + nReturn = 0; + } + goto Done; + } + *pEncoded = spBigBuf; + uFirstSizeEstimate = *pEncodedLen; + + } while(1); + + Done: + return(nReturn); +} + +/* + A3 # map(3) + 6D # text(13) + 666972737420696E7465676572 # "first integer" + 18 2A # unsigned(42) + 77 # text(23) + 616E206172726179206F662074776F20737472696E6773 # "an array of two strings" + 82 # array(2) + 67 # text(7) + 737472696E6731 # "string1" + 67 # text(7) + 737472696E6732 # "string2" + 6C # text(12) + 6D617020696E2061206D6170 # "map in a map" + A4 # map(4) + 67 # text(7) + 62797465732031 # "bytes 1" + 44 # bytes(4) + 78787878 # "xxxx" + 67 # text(7) + 62797465732032 # "bytes 2" + 44 # bytes(4) + 79797979 # "yyyy" + 6B # text(11) + 616E6F7468657220696E74 # "another int" + 18 62 # unsigned(98) + 66 # text(6) + 746578742032 # "text 2" + 78 1E # text(30) + 6C6965732C2064616D6E206C69657320616E642073746174697374696373 # "lies, damn lies and statistics" + */ +static const uint8_t spValidMapEncoded[] = { + 0xa3, 0x6d, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x69, 0x6e, + 0x74, 0x65, 0x67, 0x65, 0x72, 0x18, 0x2a, 0x77, 0x61, 0x6e, + 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, + 0x74, 0x77, 0x6f, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0x73, 0x82, 0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x31, + 0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x32, 0x6c, 0x6d, + 0x61, 0x70, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x6d, 0x61, + 0x70, 0xa4, 0x67, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x31, + 0x44, 0x78, 0x78, 0x78, 0x78, 0x67, 0x62, 0x79, 0x74, 0x65, + 0x73, 0x20, 0x32, 0x44, 0x79, 0x79, 0x79, 0x79, 0x6b, 0x61, + 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x74, + 0x18, 0x62, 0x66, 0x74, 0x65, 0x78, 0x74, 0x20, 0x32, 0x78, + 0x1e, 0x6c, 0x69, 0x65, 0x73, 0x2c, 0x20, 0x64, 0x61, 0x6d, + 0x6e, 0x20, 0x6c, 0x69, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, + 0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, + 0x73 } ; + + +int MapEncodeTest() +{ + uint8_t *pEncodedMaps; + size_t nEncodedMapLen; + + if(CreateMap(&pEncodedMaps, &nEncodedMapLen)) { + return -1; + } + + int nReturn = 0; + if(memcmp(spValidMapEncoded, pEncodedMaps, sizeof(spValidMapEncoded))) + nReturn = 2; + + return(nReturn); +} + + +/* + @brief Encode the RTIC results + + @param[in] nRResult CBOR_SIMPLEV_TRUE, CBOR_SIMPLEV_FALSE or CBOR_SIMPLEV_NULL + @param[in] time Time stamp in UNIX epoch time or 0 for no time stamp + @param[in] szAlexString Diagnostic code. + @param[in[ pOut Buffer to put the result in + @param[in/out] pnLen Size of pOut buffer when called; length of data output in buffer on return + + @return + One of the CBOR encoder errors. QCBOR_SUCCESS, which is has value 0, if no error. + + The size of pOut should be 30 bytes plus the length of pnLen. If you make it too + short an error will be returned. This function will never write off the end + of the buffer passed to it. + + If the result is 0, then the correct encoded CBOR is in pOut and *pnLen is the + length of the encoded CBOR. + + */ + +static UsefulBufC FormatRTICResults(int nRResult, uint64_t time, const char *szType, const char *szAlexString, UsefulBuf Storage) +{ + // Buffer that the result will be written in to + // It is fixed size and small that a stack variable will be fine + // QCBOREncode will never write off the end of this buffer. If it won't fit QCBOREncode_Finish will return an error. + + // Context for the encoder + QCBOREncodeContext ECtx; + QCBOREncode_Init(&ECtx, Storage); + + // All the RTIC results are grouped in a CBOR Map which will get turned into a JSON Object + // Contents are label / value pairs + QCBOREncode_OpenMap(&ECtx); + + { // Brace / indention just to show CBOR encoding nesting + + // The result: 0 if scan happened and found nothing; 1 if it happened and found something wrong; 2 if it didn't happen + QCBOREncode_AddSimpleToMap(&ECtx, "integrity", nRResult); + + // Add the diagnostic code + QCBOREncode_AddSZStringToMap(&ECtx, "type", szType); + + // Add a time stamp + if(time) { + QCBOREncode_AddDateEpochToMap(&ECtx, "time", time); + } + + // Add the diagnostic code + QCBOREncode_AddSZStringToMap(&ECtx, "diag", szAlexString); + + // Open a subordinate map for telemtry data + QCBOREncode_OpenMapInMap(&ECtx, "telemetry"); + + { // Brace / indention just to show CBOR encoding nesting + + // Add a few fake integers and buffers for now. + QCBOREncode_AddInt64ToMap(&ECtx, "Shoe Size", 12); + + // Add a few fake integers and buffers for now. + QCBOREncode_AddInt64ToMap(&ECtx, "IQ", 0xffffffff); + + // Add a few fake integers and buffers for now. + static const uint8_t pPV[] = {0x66, 0x67, 0x00, 0x56, 0xaa, 0xbb, 0x01, 0x01}; + const UsefulBufC WSPV = {pPV, sizeof(pPV)}; + + QCBOREncode_AddBytesToMap(&ECtx, "WhaleSharkPatternVector", WSPV); + } + } + + // Close the telemetry map + QCBOREncode_CloseMap(&ECtx); + + // Close the map + QCBOREncode_CloseMap(&ECtx); + + UsefulBufC Result; + + QCBOREncode_Finish(&ECtx, &Result); + + return Result; +} + + +/* + A5 # map(5) + 69 # text(9) + 696E74656772697479 # "integrity" + F4 # primitive(20) + 64 # text(4) + 74797065 # "type" + 66 # text(6) + 726563656E74 # "recent" + 64 # text(4) + 74696D65 # "time" + C1 # tag(1) + 1A 580D4172 # unsigned(1477263730) + 64 # text(4) + 64696167 # "diag" + 6A # text(10) + 30784131654335303031 # "0xA1eC5001" + 69 # text(9) + 74656C656D65747279 # "telemetry" + A3 # map(3) + 69 # text(9) + 53686F652053697A65 # "Shoe Size" + 0C # unsigned(12) + 62 # text(2) + 4951 # "IQ" + 1A FFFFFFFF # unsigned(4294967295) + 77 # text(23) + 5768616C65536861726B5061747465726E566563746F72 # "WhaleSharkPatternVector" + 48 # bytes(8) + 66670056AABB0101 # "fg\x00V\xAA\xBB\x01\x01" + */ +static const uint8_t spExpectedRTIC[] = { + 0xa5, 0x69, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x69, 0x74, + 0x79, 0xf4, 0x64, 0x74, 0x79, 0x70, 0x65, 0x66, 0x72, 0x65, + 0x63, 0x65, 0x6e, 0x74, 0x64, 0x74, 0x69, 0x6d, 0x65, 0xc1, + 0x1a, 0x58, 0x0d, 0x41, 0x72, 0x64, 0x64, 0x69, 0x61, 0x67, + 0x6a, 0x30, 0x78, 0x41, 0x31, 0x65, 0x43, 0x35, 0x30, 0x30, + 0x31, 0x69, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, + 0x79, 0xa3, 0x69, 0x53, 0x68, 0x6f, 0x65, 0x20, 0x53, 0x69, + 0x7a, 0x65, 0x0c, 0x62, 0x49, 0x51, 0x1a, 0xff, 0xff, 0xff, + 0xff, 0x77, 0x57, 0x68, 0x61, 0x6c, 0x65, 0x53, 0x68, 0x61, + 0x72, 0x6b, 0x50, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x56, + 0x65, 0x63, 0x74, 0x6f, 0x72, 0x48, 0x66, 0x67, 0x00, 0x56, + 0xaa, 0xbb, 0x01, 0x01}; + + +int RTICResultsTest() +{ + const UsefulBufC Encoded = FormatRTICResults(CBOR_SIMPLEV_FALSE, 1477263730, + "recent", "0xA1eC5001", + UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); + if(UsefulBuf_IsNULLC(Encoded)) { + return -1; + } + + if(CheckResults(Encoded, spExpectedRTIC)) { + return -2; + } + + return 0; +} + + +/* + 82 # array(2) + 19 01C3 # unsigned(451) + 43 # bytes(3) + 1901D2 # "\x19\x01\xD2" +*/ +static const uint8_t spExpectedBstrWrap[] = {0x82, 0x19, 0x01, 0xC3, 0x43, 0x19, 0x01, 0xD2}; + +/* + Very basic bstr wrapping test + */ +int BstrWrapTest() +{ + QCBOREncodeContext EC; + + QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); + + QCBOREncode_OpenArray(&EC); + QCBOREncode_AddUInt64(&EC, 451); + + QCBOREncode_BstrWrap(&EC); + QCBOREncode_AddUInt64(&EC, 466); + + UsefulBufC Wrapped; + QCBOREncode_CloseBstrWrap(&EC, &Wrapped); + + QCBOREncode_CloseArray(&EC); + + UsefulBufC Encoded; + if(QCBOREncode_Finish(&EC, &Encoded)) { + return -1; + } + + if(CheckResults(Encoded, spExpectedBstrWrap)) { + return -2; + } + + /* Another test; see about handling length calculation */ + QCBOREncode_Init(&EC, (UsefulBuf){NULL, INT32_MAX}); + QCBOREncode_OpenArray(&EC); + QCBOREncode_BstrWrap(&EC); + QCBOREncode_OpenArray(&EC); + QCBOREncode_AddNULL(&EC); + QCBOREncode_CloseArray(&EC); + UsefulBufC BStr; + QCBOREncode_CloseBstrWrap(&EC, &BStr); + // 2 is one byte for an array of length 1 and 1 byte for a NULL + if(BStr.ptr != NULL || BStr.len != 2) { + return -5; + } + + return 0; +} + + + +int BstrWrapErrorTest() +{ + // -------------- Test closing a bstrwrap when it is an array that is open ----------- + QCBOREncodeContext EC; + + QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); + + QCBOREncode_OpenArray(&EC); + QCBOREncode_AddUInt64(&EC, 451); + + QCBOREncode_BstrWrap(&EC); + QCBOREncode_AddUInt64(&EC, 466); + QCBOREncode_OpenArray(&EC); + + UsefulBufC Wrapped; + QCBOREncode_CloseBstrWrap(&EC, &Wrapped); + + QCBOREncode_CloseArray(&EC); + + UsefulBufC Encoded2; + if(QCBOREncode_Finish(&EC, &Encoded2) != QCBOR_ERR_CLOSE_MISMATCH) { + return -1; + } + + // ----------- test closing a bstrwrap when nothing is open --------------------- + QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); + QCBOREncode_CloseBstrWrap(&EC, &Wrapped); + if(QCBOREncode_Finish(&EC, &Encoded2) != QCBOR_ERR_TOO_MANY_CLOSES) { + return -2; + } + + // --------------- test nesting too deep ---------------------------------- + QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); + for(int i = 1; i < 18; i++) { + QCBOREncode_BstrWrap(&EC); + } + QCBOREncode_AddBool(&EC, true); + + for(int i = 1; i < 18; i++) { + QCBOREncode_CloseBstrWrap(&EC, &Wrapped); + } + + if(QCBOREncode_Finish(&EC, &Encoded2) != QCBOR_ERR_ARRAY_NESTING_TOO_DEEP) { + return -3; + } + + return 0; +} + + + +// Part of bstr_wrap_nest_test +/* + 83 array with three + 53 byte string with 19 bytes + 01 #1 + 50 byte string with 16 bytes + 02 + 4D byte string with 13 bytes + 03 + 4A byte string with 10 bytes + 04 + 47 byte string with 7 bytes + 05 + 44 byte string with 4 bytes + 06 + 41 byte string with 1 byte + 07 + 01 + 02 + 03 + 04 + 05 + 06 + 07 + A2 map with two items + 18 20 label for byte string + 54 byte string of length 20 + 82 Array with two items + 10 The integer value 10 + A2 map with two items + 18 21 label for byte string + 44 byte string with 4 bytes + 81 array with 1 item + 11 integer value 11 + 18 30 integer value 30 + 18 40 integer label 40 + 65 68 65 6C 6C 6F text string hello + 18 31 integer value 31 + 18 41 integer label 41 + 65 68 65 6C 6C 6F text string hello + + + */ + + +/* + 83 # array(3) + 56 # bytes(22) + 00530150024D034A0447054406410700010203040506 # "\x00S\x01P\x02M\x03J\x04G\x05D\x06A\a\x00\x01\x02\x03\x04\x05\x06" + 07 # unsigned(7) + A2 # map(2) + 18 20 # unsigned(32) + 54 # bytes(20) + 8210A21821448111183018406568656C6C6F1831 # "\x82\x10\xA2\x18!D\x81\x11\x180\x18@ehello\x181" + 18 41 # unsigned(65) + 65 # text(5) + 68656C6C6F # "hello" + */ +static const uint8_t spExpectedDeepBstr[] = +{ + 0x83, 0x56, 0x00, 0x53, 0x01, 0x50, 0x02, 0x4D, + 0x03, 0x4A, 0x04, 0x47, 0x05, 0x44, 0x06, 0x41, + 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0xA2, 0x18, 0x20, 0x54, 0x82, 0x10, 0xA2, + 0x18, 0x21, 0x44, 0x81, 0x11, 0x18, 0x30, 0x18, + 0x40, 0x65, 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x18, + 0x31, 0x18, 0x41, 0x65, 0x68, 0x65, 0x6C, 0x6C, + 0x6F +}; + +// Part of bstr_wrap_nest_test +static int DecodeNextNested(UsefulBufC Wrapped) +{ + int nReturn; + QCBORDecodeContext DC; + QCBORDecode_Init(&DC, Wrapped, QCBOR_DECODE_MODE_NORMAL); + + QCBORItem Item; + nReturn = QCBORDecode_GetNext(&DC, &Item); + if(nReturn) { + return -11; + } + if(Item.uDataType != QCBOR_TYPE_INT64) { + return -12; + } + + nReturn = QCBORDecode_GetNext(&DC, &Item); + if(nReturn == QCBOR_ERR_HIT_END) { + return 0; + } + if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) { + return -13; + } + nReturn = DecodeNextNested(Item.val.string); + if(nReturn) { + return nReturn; + } + + nReturn = QCBORDecode_GetNext(&DC, &Item); + if(nReturn) { + return -14; + } + if(Item.uDataType != QCBOR_TYPE_INT64) { + return -15; + } + + if(QCBORDecode_Finish(&DC)) { + return -16; + } + + return 0; +} + +// Part of bstr_wrap_nest_test +static int DecodeNextNested2(UsefulBufC Wrapped) +{ + int nReturn; + QCBORDecodeContext DC; + QCBORDecode_Init(&DC, Wrapped, QCBOR_DECODE_MODE_NORMAL); + + QCBORItem Item; + nReturn = QCBORDecode_GetNext(&DC, &Item); + if(nReturn) { + return -11; + } + if(Item.uDataType != QCBOR_TYPE_ARRAY) { + return -12; + } + + nReturn = QCBORDecode_GetNext(&DC, &Item); + if(nReturn) { + return -11; + } + if(Item.uDataType != QCBOR_TYPE_INT64) { + return -12; + } + + nReturn = QCBORDecode_GetNext(&DC, &Item); + if(nReturn) { + return -11; + } + if(Item.uDataType != QCBOR_TYPE_MAP) { + return 0; + } + + nReturn = QCBORDecode_GetNext(&DC, &Item); + if(nReturn) { + return -11; + } + if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) { + return -13; + } + nReturn = DecodeNextNested2(Item.val.string); + if(nReturn) { + return nReturn; + } + + nReturn = QCBORDecode_GetNext(&DC, &Item); + if(nReturn) { + return -11; + } + if(Item.uDataType != QCBOR_TYPE_TEXT_STRING) { + return -12; + } + nReturn = QCBORDecode_GetNext(&DC, &Item); + if(nReturn) { + return -11; + } + if(Item.uDataType != QCBOR_TYPE_INT64) { + return -12; + } + + if(QCBORDecode_Finish(&DC)) { + return -16; + } + + return 0; +} + + +int BstrWrapNestTest() +{ + QCBOREncodeContext EC; + QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); + + // ---- Make a complicated nested CBOR structure --- +#define BSTR_TEST_DEPTH 10 + + QCBOREncode_OpenArray(&EC); + + for(int i = 0; i < BSTR_TEST_DEPTH-2; i++) { + QCBOREncode_BstrWrap(&EC); + QCBOREncode_AddUInt64(&EC, i); + } + + for(int i = 0; i < BSTR_TEST_DEPTH-2; i++) { + QCBOREncode_CloseBstrWrap(&EC, NULL); + QCBOREncode_AddUInt64(&EC, i); + } + + for(int i = 0; i < (BSTR_TEST_DEPTH-2)/3; i++) { + QCBOREncode_OpenMap(&EC); + QCBOREncode_BstrWrapInMapN(&EC, i+0x20); + QCBOREncode_OpenArray(&EC); + QCBOREncode_AddUInt64(&EC, i+0x10); + } + + for(int i = 0; i < (BSTR_TEST_DEPTH-2)/3; i++) { + QCBOREncode_CloseArray(&EC); + QCBOREncode_AddUInt64(&EC, i+0x30); + QCBOREncode_CloseBstrWrap(&EC, NULL); + QCBOREncode_AddSZStringToMapN(&EC, i+0x40, "hello"); + QCBOREncode_CloseMap(&EC); + } + QCBOREncode_CloseArray(&EC); + + UsefulBufC Encoded; + if(QCBOREncode_Finish(&EC, &Encoded)) { + return -1; + } + + // ---Compare it to expected. Expected was hand checked with use of CBOR playground ---- + if(UsefulBuf_Compare(UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedDeepBstr), Encoded)) { + return -25; + } + + + // ---- Decode it and see if it is OK ------ + QCBORDecodeContext DC; + QCBORDecode_Init(&DC, Encoded, QCBOR_DECODE_MODE_NORMAL); + + QCBORItem Item; + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_ARRAY || Item.val.uCount != 3) { + return -2; + } + + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) { + return -3; + } + + int nReturn = DecodeNextNested(Item.val.string); + if(nReturn) { + return nReturn; + } + + nReturn = QCBORDecode_GetNext(&DC, &Item); + if(nReturn) { + return -11; + } + if(Item.uDataType != QCBOR_TYPE_INT64) { + return -12; + } + + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_MAP || Item.val.uCount != 2) { + return -2; + } + + QCBORDecode_GetNext(&DC, &Item); + if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) { + return -3; + } + nReturn = DecodeNextNested2(Item.val.string); + if(nReturn) { + return nReturn; + } + + nReturn = QCBORDecode_GetNext(&DC, &Item); + if(nReturn) { + return -11; + } + if(Item.uDataType != QCBOR_TYPE_TEXT_STRING) { + return -12; + } + + if(QCBORDecode_Finish(&DC)) { + return -16; + } + + return 0; +} + + +static const uint8_t spSignature[] = { + 0x8e, 0xb3, 0x3e, 0x4c, 0xa3, 0x1d, 0x1c, 0x46, 0x5a, 0xb0, + 0x5a, 0xac, 0x34, 0xcc, 0x6b, 0x23, 0xd5, 0x8f, 0xef, 0x5c, + 0x08, 0x31, 0x06, 0xc4, 0xd2, 0x5a, 0x91, 0xae, 0xf0, 0xb0, + 0x11, 0x7e, 0x2a, 0xf9, 0xa2, 0x91, 0xaa, 0x32, 0xe1, 0x4a, + 0xb8, 0x34, 0xdc, 0x56, 0xed, 0x2a, 0x22, 0x34, 0x44, 0x54, + 0x7e, 0x01, 0xf1, 0x1d, 0x3b, 0x09, 0x16, 0xe5, 0xa4, 0xc3, + 0x45, 0xca, 0xcb, 0x36}; + +/* + D2 # tag(18) + 84 # array(4) + 43 # bytes(3) + A10126 # "\xA1\x01&" + A1 # map(1) + 04 # unsigned(4) + 42 # bytes(2) + 3131 # "11" + 54 # bytes(20) + 546869732069732074686520636F6E74656E742E # "This is the content." + 58 40 # bytes(64) + 8EB33E4CA31D1C465AB05AAC34CC6B23D58FEF5C083106C4D25A91AEF0B0117E2AF9A291AA32E14AB834DC56ED2A223444547E01F11D3B0916E5A4C345CACB36 # "\x8E\xB3>L\xA3\x1D\x1CFZ\xB0Z\xAC4\xCCk#\xD5\x8F\xEF\\\b1\x06\xC4\xD2Z\x91\xAE\xF0\xB0\x11~*\xF9\xA2\x91\xAA2\xE1J\xB84\xDCV\xED*\"4DT~\x01\xF1\x1D;\t\x16\xE5\xA4\xC3E\xCA\xCB6" + */ +static const uint8_t spExpected[] = { + 0xD2, 0x84, 0x43, 0xA1, 0x01, 0x26, 0xA1, 0x04, 0x42, 0x31, + 0x31, 0x54, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, + 0x74, 0x2E, 0x58, 0x40, 0x8E, 0xB3, 0x3E, 0x4C, 0xA3, 0x1D, + 0x1C, 0x46, 0x5A, 0xB0, 0x5A, 0xAC, 0x34, 0xCC, 0x6B, 0x23, + 0xD5, 0x8F, 0xEF, 0x5C, 0x08, 0x31, 0x06, 0xC4, 0xD2, 0x5A, + 0x91, 0xAE, 0xF0, 0xB0, 0x11, 0x7E, 0x2A, 0xF9, 0xA2, 0x91, + 0xAA, 0x32, 0xE1, 0x4A, 0xB8, 0x34, 0xDC, 0x56, 0xED, 0x2A, + 0x22, 0x34, 0x44, 0x54, 0x7E, 0x01, 0xF1, 0x1D, 0x3B, 0x09, + 0x16, 0xE5, 0xA4, 0xC3, 0x45, 0xCA, 0xCB, 0x36}; + +/* + this corresponds exactly to the example in RFC 8152 + section C.2.1. This doesn't actually verify the signature + though that would be nice as it would make the test + really good. That would require bring in ECDSA crypto + to this test. + */ +int CoseSign1TBSTest() +{ + // All of this is from RFC 8152 C.2.1 + const char *szKid = "11"; + const UsefulBufC Kid = UsefulBuf_FromSZ(szKid); + const char *szPayload = "This is the content."; + const UsefulBufC Payload = UsefulBuf_FromSZ(szPayload); + static const uint8_t pProtectedHeaders[] = {0xa1, 0x01, 0x26}; + const UsefulBufC ProtectedHeaders = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pProtectedHeaders); + + // It would be good to compare this to the output from + // a COSE implementation like COSE-C. It has been checked + // against the CBOR playground. + const UsefulBufC Signature = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSignature); + + QCBOREncodeContext EC; + QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); + + // top level array for cose sign1, 18 is the tag for COSE sign + QCBOREncode_AddTag(&EC, CBOR_TAG_COSE_SIGN1); + QCBOREncode_OpenArray(&EC); + + // Add protected headers + QCBOREncode_AddBytes(&EC, ProtectedHeaders); + + // Empty map with unprotected headers + QCBOREncode_OpenMap(&EC); + QCBOREncode_AddBytesToMapN(&EC, 4, Kid); + QCBOREncode_CloseMap(&EC); + + // The payload + UsefulBufC WrappedPayload; + QCBOREncode_BstrWrap(&EC); + QCBOREncode_AddEncoded(&EC, Payload); // Payload is not actually CBOR in example C.2.1 + QCBOREncode_CloseBstrWrap(&EC, &WrappedPayload); + + // Check we got back the actual payload expected + if(UsefulBuf_Compare(WrappedPayload, Payload)) { + return -1; + } + + // The signature + QCBOREncode_AddBytes(&EC, Signature); + QCBOREncode_CloseArray(&EC); + + // Finish and check the results + UsefulBufC COSE_Sign1; + if(QCBOREncode_Finish(&EC, &COSE_Sign1)) { + return -2; + } + + // 98 is the size from RFC 8152 C.2.1 + if(COSE_Sign1.len != 98) { + return -3; + } + + if(CheckResults(COSE_Sign1, spExpected)) { + return -4; + } + + return 0; +} + + +int EncodeErrorTests() +{ + QCBOREncodeContext EC; + + + // ------ Test for QCBOR_ERR_BUFFER_TOO_LARGE ------ + // Do all of these tests with NULL buffers so no actual large allocations are neccesary + UsefulBuf Buffer = (UsefulBuf){NULL, UINT32_MAX}; + + // First verify no error from a big buffer + QCBOREncode_Init(&EC, Buffer); + QCBOREncode_OpenArray(&EC); + // 6 is the CBOR overhead for opening the array and encodng the length + // This exactly fills the buffer. + QCBOREncode_AddBytes(&EC, (UsefulBufC){NULL, UINT32_MAX-6}); + QCBOREncode_CloseArray(&EC); + size_t xx; + if(QCBOREncode_FinishGetSize(&EC, &xx) != QCBOR_SUCCESS) { + return -1; + } + + // Second verify error from an array in encoded output too large + QCBOREncode_Init(&EC, Buffer); + QCBOREncode_OpenArray(&EC); + QCBOREncode_AddBytes(&EC, (UsefulBufC){NULL, UINT32_MAX-6}); + QCBOREncode_OpenArray(&EC); // Where QCBOR internally encounters and records error + QCBOREncode_CloseArray(&EC); + QCBOREncode_CloseArray(&EC); + if(QCBOREncode_FinishGetSize(&EC, &xx) != QCBOR_ERR_BUFFER_TOO_LARGE) { + return -2; + } + + // Third, fit an array in exactly at max position allowed + QCBOREncode_Init(&EC, Buffer); + QCBOREncode_OpenArray(&EC); + QCBOREncode_AddBytes(&EC, (UsefulBufC){NULL, QCBOR_MAX_ARRAY_OFFSET-6}); + QCBOREncode_OpenArray(&EC); + QCBOREncode_CloseArray(&EC); + QCBOREncode_CloseArray(&EC); + if(QCBOREncode_FinishGetSize(&EC, &xx) != QCBOR_SUCCESS) { + return -10; + } + + + // ----- QCBOR_ERR_BUFFER_TOO_SMALL -------------- + // Work close to the 4GB size limit for a better test + const uint32_t uLargeSize = UINT32_MAX - 1024; + UsefulBuf Large = (UsefulBuf){NULL,uLargeSize}; + + QCBOREncode_Init(&EC, Large); + QCBOREncode_OpenArray(&EC); + QCBOREncode_AddBytes(&EC, (UsefulBufC){NULL, uLargeSize/2 + 1}); + QCBOREncode_CloseArray(&EC); + if(QCBOREncode_FinishGetSize(&EC, &xx) != QCBOR_SUCCESS) { + // Making sure it succeeds when it should first + return -3; + } + + QCBOREncode_Init(&EC, Large); + QCBOREncode_OpenArray(&EC); + QCBOREncode_AddBytes(&EC, (UsefulBufC){NULL, uLargeSize/2 + 1}); + QCBOREncode_AddBytes(&EC, (UsefulBufC){NULL, uLargeSize/2}); + QCBOREncode_CloseArray(&EC); + if(QCBOREncode_FinishGetSize(&EC, &xx) != QCBOR_ERR_BUFFER_TOO_SMALL) { + // Now just 1 byte over, see that it fails + return -4; + } + + + // ----- QCBOR_ERR_ARRAY_NESTING_TOO_DEEP ------- + QCBOREncode_Init(&EC, Large); + for(int i = QCBOR_MAX_ARRAY_NESTING; i > 0; i--) { + QCBOREncode_OpenArray(&EC); + } + for(int i = QCBOR_MAX_ARRAY_NESTING; i > 0; i--) { + QCBOREncode_CloseArray(&EC); + } + if(QCBOREncode_FinishGetSize(&EC, &xx) != QCBOR_SUCCESS) { + // Making sure it succeeds when it should first + return -5; + } + + QCBOREncode_Init(&EC, Large); + for(int i = QCBOR_MAX_ARRAY_NESTING+1; i > 0; i--) { + QCBOREncode_OpenArray(&EC); + } + for(int i = QCBOR_MAX_ARRAY_NESTING+1; i > 0; i--) { + QCBOREncode_CloseArray(&EC); + } + if(QCBOREncode_FinishGetSize(&EC, &xx) != QCBOR_ERR_ARRAY_NESTING_TOO_DEEP) { + // One more level to cause error + return -6; + } + + + // ------ QCBOR_ERR_TOO_MANY_CLOSES -------- + QCBOREncode_Init(&EC, Large); + for(int i = QCBOR_MAX_ARRAY_NESTING; i > 0; i--) { + QCBOREncode_OpenArray(&EC); + } + for(int i = QCBOR_MAX_ARRAY_NESTING+1; i > 0; i--) { + QCBOREncode_CloseArray(&EC); + } + if(QCBOREncode_FinishGetSize(&EC, &xx) != QCBOR_ERR_TOO_MANY_CLOSES) { + // One more level to cause error + return -7; + } + + + // ------ QCBOR_ERR_CLOSE_MISMATCH -------- + QCBOREncode_Init(&EC, Large); + QCBOREncode_OpenArray(&EC); + UsefulBufC Wrap; + QCBOREncode_CloseBstrWrap(&EC, &Wrap); + if(QCBOREncode_FinishGetSize(&EC, &xx) != QCBOR_ERR_CLOSE_MISMATCH) { + return -8; + } + + + // ------ QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN --------- + QCBOREncode_Init(&EC, Large); + for(int i = QCBOR_MAX_ARRAY_NESTING; i > 0; i--) { + QCBOREncode_OpenArray(&EC); + } + for(int i = QCBOR_MAX_ARRAY_NESTING-1; i > 0; i--) { + QCBOREncode_CloseArray(&EC); + } + if(QCBOREncode_FinishGetSize(&EC, &xx) != QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN) { + // One more level to cause error + return -9; + } + + /* QCBOR_ERR_ARRAY_TOO_LONG is not tested here as + it would require a 64KB of RAM to test */ + + return 0; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/qcbor_encode_tests.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/qcbor_encode_tests.h new file mode 100644 index 0000000..49362c6 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/qcbor_encode_tests.h @@ -0,0 +1,146 @@ +/*============================================================================== + Copyright (c) 2016-2018, The Linux Foundation. + Copyright (c) 2018-2019, Laurence Lundblade. + All rights reserved. + SPDX-License-Identifier: BSD-3-Clause + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors, nor the name "Laurence Lundblade" may be used to + endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ==============================================================================*/ + +#ifndef __QCBOR__qcbor_encode_tests__ +#define __QCBOR__qcbor_encode_tests__ + +#include "qcbor.h" + + +/* + Notes: + + - All the functions in qcbor.h are called once in the aggregation of all the tests below. + + - All the types that are supported are given as input and parsed by these tests + + - There is some hostile input such as invalid lengths and CBOR too complex + and types this parser doesn't handle + + */ + + +/* + Most basic test. + */ +int BasicEncodeTest(void); + + +/* + Encode lots of integer values, particularly around the boundary and make sure they + Match the expected binary output. Primarily an encoding test. + */ +int IntegerValuesTest1(void); + + + +/* + Create nested arrays to the max depth allowed and make sure it succeeds. + This is an encoding test. + */ +int ArrayNestingTest1(void); + + +/* + Create nested arrays to one more than the meax depth and make sure it fails. + This is an encoding test. + */ +int ArrayNestingTest2(void); + + +/* + Encoding test. + Create arrays to max depth and close one extra time and look for correct error code + */ +int ArrayNestingTest3(void); + + +/* + This tests the QCBOREncode_AddRaw() function by adding two chunks or RAWCBOR to an + array and comparing with expected values. This is an encoding test. + */ +int EncodeRawTest(void); + + +/* + This creates a somewhat complicated CBOR MAP and verifies it against expected + data. This is an encoding test. + */ +int MapEncodeTest(void); + + + +/* + Encodes a goodly number of floats and doubles and checks encoding is right + */ +int FloatValuesTest1(void); + + +/* + Encodes true, false and the like + */ +int SimpleValuesTest1(void); + + +/* + Encodes most data formats that are supported */ +int EncodeDateTest(void); + + +/* + Encodes particular data structure that a particular app will need... + */ +int RTICResultsTest(void); + + +/* + Calls all public encode methods in qcbor.h once. + */ +int AllAddMethodsTest(void); + +/* + The binary string wrapping of maps and arrays used by COSE + */ +int BstrWrapTest(void); + +int BstrWrapErrorTest(void); + +int BstrWrapNestTest(void); + +int CoseSign1TBSTest(void); + +int EncodeErrorTests(void); + + + +#endif /* defined(__QCBOR__qcbor_encode_tests__) */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/run_tests.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/run_tests.c new file mode 100644 index 0000000..6e35620 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/run_tests.c @@ -0,0 +1,285 @@ +/*============================================================================== + run_tests.c -- test aggregator and results reporting + + Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. + + SPDX-License-Identifier: BSD-3-Clause + + See BSD-3-Clause license in README.md + + Created on 9/30/18 + ==============================================================================*/ + +#include "run_tests.h" +#include "UsefulBuf.h" +#include + +#include "float_tests.h" +#include "qcbor_decode_tests.h" +#include "qcbor_encode_tests.h" +#include "UsefulBuf_Tests.h" + + + +// Used to test RunTests +int fail_test() +{ + return -44; +} + + + + +/* + Convert a number up to 999999999 to a string. This is so sprintf doesn't + have to be linked in so as to minimized dependencies even in test code. + */ +const char *NumToString(int32_t nNum, UsefulBuf StringMem) +{ + const int32_t nMax = 1000000000; + + UsefulOutBuf OutBuf; + UsefulOutBuf_Init(&OutBuf, StringMem); + + if(nNum < 0) { + UsefulOutBuf_AppendByte(&OutBuf, '-'); + nNum = -nNum; + } + if(nNum > nMax-1) { + return "XXX"; + } + + bool bDidSomeOutput = false; + for(int n = nMax; n > 0; n/=10) { + int x = nNum/n; + if(x || bDidSomeOutput){ + bDidSomeOutput = true; + UsefulOutBuf_AppendByte(&OutBuf, '0' + x); + nNum -= x * n; + } + } + if(!bDidSomeOutput){ + UsefulOutBuf_AppendByte(&OutBuf, '0'); + } + UsefulOutBuf_AppendByte(&OutBuf, '\0'); + + return UsefulOutBuf_GetError(&OutBuf) ? "" : StringMem.ptr; +} + + + + +typedef int (test_fun_t)(void); +typedef const char * (test_fun2_t)(void); + + +#define TEST_ENTRY(test_name) {#test_name, test_name, true} +#define TEST_ENTRY_DISABLED(test_name) {#test_name, test_name, false} + +typedef struct { + const char *szTestName; + test_fun_t *test_fun; + bool bEnabled; +} test_entry; + +typedef struct { + const char *szTestName; + test_fun2_t *test_fun; + bool bEnabled; +} test_entry2; + +test_entry2 s_tests2[] = { + TEST_ENTRY(UBUTest_CopyUtil), + TEST_ENTRY(UOBTest_NonAdversarial), + TEST_ENTRY(TestBasicSanity), + TEST_ENTRY(UOBTest_BoundaryConditionsTest), + TEST_ENTRY(UBMacroConversionsTest), + TEST_ENTRY(UBUtilTests), + TEST_ENTRY(UIBTest_IntegerFormat) +}; + + +test_entry s_tests[] = { + TEST_ENTRY(ParseMapAsArrayTest), + TEST_ENTRY_DISABLED(AllocAllStringsTest), + TEST_ENTRY(IndefiniteLengthNestTest), + TEST_ENTRY(NestedMapTestIndefLen), + TEST_ENTRY(ParseSimpleTest), + TEST_ENTRY(EncodeRawTest), + TEST_ENTRY(RTICResultsTest), + TEST_ENTRY(MapEncodeTest), + TEST_ENTRY(ArrayNestingTest1), + TEST_ENTRY(ArrayNestingTest2), + TEST_ENTRY(ArrayNestingTest3), + TEST_ENTRY(EncodeDateTest), + TEST_ENTRY(SimpleValuesTest1), + TEST_ENTRY(IntegerValuesTest1), + TEST_ENTRY(AllAddMethodsTest), + TEST_ENTRY(ParseTooDeepArrayTest), + TEST_ENTRY(ComprehensiveInputTest), + TEST_ENTRY(ParseMapTest), + TEST_ENTRY_DISABLED(IndefiniteLengthArrayMapTest), + TEST_ENTRY(BasicEncodeTest), + TEST_ENTRY(NestedMapTest), + TEST_ENTRY(BignumParseTest), + TEST_ENTRY(OptTagParseTest), + TEST_ENTRY(DateParseTest), + TEST_ENTRY(ShortBufferParseTest2), + TEST_ENTRY(ShortBufferParseTest), + TEST_ENTRY(ParseDeepArrayTest), + TEST_ENTRY(SimpleArrayTest), + TEST_ENTRY(IntegerValuesParseTest), + TEST_ENTRY_DISABLED(MemPoolTest), + TEST_ENTRY_DISABLED(IndefiniteLengthStringTest), + TEST_ENTRY(HalfPrecisionDecodeBasicTests), + TEST_ENTRY(DoubleAsSmallestTest), + TEST_ENTRY(HalfPrecisionAgainstRFCCodeTest), + TEST_ENTRY(BstrWrapTest), + TEST_ENTRY(BstrWrapErrorTest), + TEST_ENTRY(BstrWrapNestTest), + TEST_ENTRY(CoseSign1TBSTest), + TEST_ENTRY(StringDecoderModeFailTest), + TEST_ENTRY_DISABLED(BigComprehensiveInputTest), + TEST_ENTRY(EncodeErrorTests), + //TEST_ENTRY(fail_test), +}; + + +int RunTests(const char *szTestNames[], OutputStringCB pfOutput, void *poutCtx, int *pNumTestsRun) +{ + int nTestsFailed = 0; + int nTestsRun = 0; + UsefulBuf_MAKE_STACK_UB(StringStorage, 5); + + test_entry2 *t2; + const test_entry2 *s_tests2_end = s_tests2 + sizeof(s_tests2)/sizeof(test_entry2); + + for(t2 = s_tests2; t2 < s_tests2_end; t2++) { + if(szTestNames[0]) { + // Some tests have been named + const char **szRequestedNames; + for(szRequestedNames = szTestNames; *szRequestedNames; szRequestedNames++) { + if(!strcmp(t2->szTestName, *szRequestedNames)) { + break; // Name matched + } + } + if(*szRequestedNames == NULL) { + // Didn't match this test + continue; + } + } else { + // no tests named, but don't run "disabled" tests + if(!t2->bEnabled) { + // Don't run disabled tests when all tests are being run + // as indicated by no specific test names being given + continue; + } + } + + const char * szTestResult = (t2->test_fun)(); + nTestsRun++; + if(pfOutput) { + (*pfOutput)(t2->szTestName, poutCtx, 0); + } + + if(szTestResult) { + if(pfOutput) { + (*pfOutput)(" FAILED (returned ", poutCtx, 0); + (*pfOutput)(szTestResult, poutCtx, 0); + (*pfOutput)(")", poutCtx, 1); + } + nTestsFailed++; + } else { + if(pfOutput) { + (*pfOutput)( " PASSED", poutCtx, 1); + } + } + } + + + test_entry *t; + const test_entry *s_tests_end = s_tests + sizeof(s_tests)/sizeof(test_entry); + + for(t = s_tests; t < s_tests_end; t++) { + if(szTestNames[0]) { + // Some tests have been named + const char **szRequestedNames; + for(szRequestedNames = szTestNames; *szRequestedNames; szRequestedNames++) { + if(!strcmp(t->szTestName, *szRequestedNames)) { + break; // Name matched + } + } + if(*szRequestedNames == NULL) { + // Didn't match this test + continue; + } + } else { + // no tests named, but don't run "disabled" tests + if(!t->bEnabled) { + // Don't run disabled tests when all tests are being run + // as indicated by no specific test names being given + continue; + } + } + + int nTestResult = (t->test_fun)(); + nTestsRun++; + if(pfOutput) { + (*pfOutput)(t->szTestName, poutCtx, 0); + } + + if(nTestResult) { + if(pfOutput) { + (*pfOutput)(" FAILED (returned ", poutCtx, 0); + (*pfOutput)(NumToString(nTestResult, StringStorage), poutCtx, 0); + (*pfOutput)(")", poutCtx, 1); + } + nTestsFailed++; + } else { + if(pfOutput) { + (*pfOutput)( " PASSED", poutCtx, 1); + } + } + } + + if(pNumTestsRun) { + *pNumTestsRun = nTestsRun; + } + + if(pfOutput) { + (*pfOutput)( "SUMMARY: ", poutCtx, 0); + (*pfOutput)( NumToString(nTestsRun, StringStorage), poutCtx, 0); + (*pfOutput)( " tests run; ", poutCtx, 0); + (*pfOutput)( NumToString(nTestsFailed, StringStorage), poutCtx, 0); + (*pfOutput)( " tests failed", poutCtx, 1); + } + + return nTestsFailed; +} + + + + +static void PrintSize(const char *szWhat, uint32_t uSize, OutputStringCB pfOutput, void *pOutCtx) +{ + UsefulBuf_MAKE_STACK_UB(buffer, 20); + + (*pfOutput)(szWhat, pOutCtx, 0); + (*pfOutput)(" ", pOutCtx, 0); + (*pfOutput)(NumToString(uSize, buffer), pOutCtx, 0); + (*pfOutput)("", pOutCtx, 1); +} + +void PrintSizes(OutputStringCB pfOutput, void *pOutCtx) +{ + // Type and size of return from sizeof() varies. These will never be large so cast is safe + PrintSize("sizeof(QCBORTrackNesting)", (uint32_t)sizeof(QCBORTrackNesting), pfOutput, pOutCtx); + PrintSize("sizeof(QCBOREncodeContext)", (uint32_t)sizeof(QCBOREncodeContext), pfOutput, pOutCtx); + PrintSize("sizeof(QCBORDecodeNesting)", (uint32_t)sizeof(QCBORDecodeNesting), pfOutput, pOutCtx); + PrintSize("sizeof(QCBORDecodeContext)", (uint32_t)sizeof(QCBORDecodeContext), pfOutput, pOutCtx); + PrintSize("sizeof(QCBORItem)", (uint32_t)sizeof(QCBORItem), pfOutput, pOutCtx); + PrintSize("sizeof(QCBORStringAllocator)",(uint32_t)sizeof(QCBORStringAllocator), pfOutput, pOutCtx); + PrintSize("sizeof(QCBORTagListIn)", (uint32_t)sizeof(QCBORTagListIn), pfOutput, pOutCtx); + PrintSize("sizeof(QCBORTagListOut)", (uint32_t)sizeof(QCBORTagListOut), pfOutput, pOutCtx); + (*pfOutput)("", pOutCtx, 1); +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/run_tests.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/run_tests.h new file mode 100644 index 0000000..62c9f5a --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/qcbor/test/run_tests.h @@ -0,0 +1,65 @@ +/*============================================================================== + run_tests.h -- test aggregator and results reporting + + Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. + + SPDX-License-Identifier: BSD-3-Clause + + See BSD-3-Clause license in README.md + + Created 9/30/18 + ==============================================================================*/ + +/** + @file run_tests.h +*/ + +/** + @brief Type for function to output a text string + + @param[in] szString The string to output + @param[in] pOutCtx A context pointer; NULL if not needed + @param[in] bNewline If non-zero, output a newline after the string + + This is a prototype of a function to be passed to RunTests() to + output text strings. + + This can be implemented with stdio (if available) using a straight + call to fputs() where the FILE * is passed as the pOutCtx as shown in + the example code below. This code is for Linux where the newline is + a \\n. Windows usually prefers \\r\\n. + + @code + static void fputs_wrapper(const char *szString, void *pOutCtx, int bNewLine) + { + fputs(szString, (FILE *)pOutCtx); + if(bNewLine) { + fputs("\n", pOutCtx); + } + } + @endcode +*/ +typedef void (*OutputStringCB)(const char *szString, void *pOutCtx, int bNewline); + + +/** + @brief Runs the QCBOR tests. + + @param[in] szTestNames An argv-style list of test names to run. If + empty, all are run. + @param[in] pfOutput Function that is called to output text strings. + @param[in] pOutCtx Context pointer passed to output function. + @param[out] pNumTestsRun Returns the number of tests run. May be NULL. + + @return The number of tests that failed. Zero means overall success. + */ +int RunTests(const char *szTestNames[], OutputStringCB pfOutput, void *pOutCtx, int *pNumTestsRun); + + +/** + @brief Print sizes of encoder / decoder contexts. + + @param[in] pfOutput Function that is called to output text strings. + @param[in] pOutCtx Context pointer passed to output function. + */ +void PrintSizes(OutputStringCB pfOutput, void *pOutCtx); diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_client.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_client.h new file mode 100755 index 0000000..ee2645d --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_client.h @@ -0,0 +1,32 @@ +/* +* Copyright (c) 2018-2019 ARM Limited. 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 __TFM_CLIENT_H__ +#define __TFM_CLIENT_H__ + +#include "psa/client.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_CLIENT_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/attest_eat_defines.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/attest_eat_defines.h new file mode 100755 index 0000000..002e2a1 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/attest_eat_defines.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __ATTEST_EAT_DEFINES_H__ +#define __ATTEST_EAT_DEFINES_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define EAT_CBOR_ARM_RANGE_BASE (-75000) +#define EAT_CBOR_ARM_LABEL_PROFILE_DEFINITION (EAT_CBOR_ARM_RANGE_BASE - 0) +#define EAT_CBOR_ARM_LABEL_CLIENT_ID (EAT_CBOR_ARM_RANGE_BASE - 1) +#define EAT_CBOR_ARM_LABEL_SECURITY_LIFECYCLE (EAT_CBOR_ARM_RANGE_BASE - 2) +#define EAT_CBOR_ARM_LABEL_IMPLEMENTATION_ID (EAT_CBOR_ARM_RANGE_BASE - 3) +#define EAT_CBOR_ARM_LABEL_BOOT_SEED (EAT_CBOR_ARM_RANGE_BASE - 4) +#define EAT_CBOR_ARM_LABEL_HW_VERSION (EAT_CBOR_ARM_RANGE_BASE - 5) +#define EAT_CBOR_ARM_LABEL_SW_COMPONENTS (EAT_CBOR_ARM_RANGE_BASE - 6) +#define EAT_CBOR_ARM_LABEL_NO_SW_COMPONENTS (EAT_CBOR_ARM_RANGE_BASE - 7) +#define EAT_CBOR_ARM_LABEL_CHALLENGE (EAT_CBOR_ARM_RANGE_BASE - 8) +#define EAT_CBOR_ARM_LABEL_UEID (EAT_CBOR_ARM_RANGE_BASE - 9) +#define EAT_CBOR_ARM_LABEL_ORIGINATION (EAT_CBOR_ARM_RANGE_BASE - 10) + +#define EAT_CBOR_SW_COMPONENT_MEASUREMENT_TYPE (1) +#define EAT_CBOR_SW_COMPONENT_MEASUREMENT_VALUE (2) +#define EAT_CBOR_SW_COMPONENT_SECURITY_EPOCH (3) +#define EAT_CBOR_SW_COMPONENT_VERSION (4) +#define EAT_CBOR_SW_COMPONENT_SIGNER_ID (5) +#define EAT_CBOR_SW_COMPONENT_MEASUREMENT_DESC (6) + +#ifdef __cplusplus +} +#endif + +#endif /* __ATTEST_EAT_DEFINES_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/attest_token.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/attest_token.c new file mode 100755 index 0000000..3be2d56 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/attest_token.c @@ -0,0 +1,227 @@ +/* + * attest_token.c + * + * Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * See BSD-3-Clause license in README.md + */ + +#include "attest_token.h" +#include "qcbor.h" +#include "t_cose_sign1_sign.h" + + +/** + * \file attest_token.c + * + * \brief Attestation token creation implementation + * + * Outline of token creation. Much of this occurs inside + * t_cose_sign1_init() and t_cose_sign1_finish(). + * + * - Create encoder context + * - Open the CBOR array that hold the \c COSE_Sign1 + * - Write COSE Headers + * - Protected Header + * - Algorithm ID + * - Unprotected Headers + * - Key ID + * - Open payload bstr + * - Write payload data… lots of it… + * - Get bstr that is the encoded payload + * - Compute signature + * - Create a separate encoder context for \c Sig_structure + * - Encode CBOR context identifier + * - Encode protected headers + * - Encode two empty bstr + * - Add one more empty bstr that is a "fake payload" + * - Close off \c Sig_structure + * - Hash all but "fake payload" of \c Sig_structure + * - Get payload bstr ptr and length + * - Continue hash of the real encoded payload + * - Run ECDSA + * - Write signature into the CBOR output + * - Close CBOR array holding the \c COSE_Sign1 + */ + +/* + * \brief Map t_cose error to attestation token error. + * + * \param[in] err The t_cose error to map. + * + * \return the attestation token error. + * + */ +static enum attest_token_err_t t_cose_err_to_attest_err(enum t_cose_err_t err) +{ + switch(err) { + + case T_COSE_SUCCESS: + return ATTEST_TOKEN_ERR_SUCCESS; + + case T_COSE_ERR_UNSUPPORTED_HASH: + return ATTEST_TOKEN_ERR_HASH_UNAVAILABLE; + + default: + /* A lot of the errors are not mapped because they are + * primarily internal errors that should never happen. They + * end up here. + */ + return ATTEST_TOKEN_ERR_GENERAL; + } +} + + +/* + Public function. See attest_token.h + */ +enum attest_token_err_t attest_token_start(struct attest_token_ctx *me, + uint32_t opt_flags, + int32_t key_select, + int32_t cose_alg_id, + const struct useful_buf *out_buf) +{ + /* approximate stack usage on 32-bit machine: 4 bytes */ + enum t_cose_err_t cose_return_value; + enum attest_token_err_t return_value; + + /* Remember some of the configuration values */ + me->opt_flags = opt_flags; + me->key_select = key_select; + + /* Spin up the CBOR encoder */ + QCBOREncode_Init(&(me->cbor_enc_ctx), *out_buf); + + + /* Initialize COSE signer. This will cause the cose headers to be + * encoded and written into out_buf using me->cbor_enc_ctx + */ + cose_return_value = t_cose_sign1_init(&(me->signer_ctx), + opt_flags & + TOKEN_OPT_SHORT_CIRCUIT_SIGN, + cose_alg_id, + key_select, + &(me->cbor_enc_ctx)); + if(cose_return_value) { + return_value = t_cose_err_to_attest_err(cose_return_value); + goto Done; + } + + /* Open the payload-wrapping bstr */ + QCBOREncode_BstrWrap(&(me->cbor_enc_ctx)); + + QCBOREncode_OpenMap(&(me->cbor_enc_ctx)); + + return_value = ATTEST_TOKEN_ERR_SUCCESS; + +Done: + return return_value; +} + + +/* + Public function. See attest_token.h + */ +QCBOREncodeContext *attest_token_borrow_cbor_cntxt(struct attest_token_ctx *me) +{ + return &(me->cbor_enc_ctx); +} + + +/* + Public function. See attest_token.h + */ +void attest_token_add_integer(struct attest_token_ctx *me, + int32_t label, + int64_t Value) +{ + QCBOREncode_AddInt64ToMapN(&(me->cbor_enc_ctx), label, Value); +} + + +/* + Public function. See attest_token.h + */ +void attest_token_add_bstr(struct attest_token_ctx *me, + int32_t label, + const struct useful_buf_c *bstr) +{ + QCBOREncode_AddBytesToMapN(&(me->cbor_enc_ctx), + label, + *bstr); +} + + +/* + Public function. See attest_token.h + */ +void attest_token_add_tstr(struct attest_token_ctx *me, + int32_t label, + const struct useful_buf_c *tstr) +{ + QCBOREncode_AddTextToMapN(&(me->cbor_enc_ctx), label, *tstr); +} + + +/* + See attest_token.h + */ +void attest_token_add_encoded(struct attest_token_ctx *me, + int32_t label, + const struct useful_buf_c *encoded) +{ + QCBOREncode_AddEncodedToMapN(&(me->cbor_enc_ctx), label, *encoded); +} + + +/* + Public function. See attest_token.h + */ +enum attest_token_err_t +attest_token_finish(struct attest_token_ctx *me, + struct useful_buf_c *completed_token) +{ + /* approximate stack usage on 32-bit machine: 4 + 4 + 8 + 8 = 24 */ + enum attest_token_err_t return_value = ATTEST_TOKEN_ERR_SUCCESS; + /* The payload with all the claims that is signed */ + struct useful_buf_c token_payload_ub; + /* The completed and signed encoded cose_sign1 */ + struct useful_buf_c completed_token_ub; + QCBORError qcbor_result; + enum t_cose_err_t cose_return_value; + + QCBOREncode_CloseMap(&(me->cbor_enc_ctx)); + + /* Close off the payload-wrapping bstr. This gives us back the + * pointer and length of the payload that needs to be hashed as + * part of the signature + */ + QCBOREncode_CloseBstrWrap(&(me->cbor_enc_ctx), &token_payload_ub); + + /* Finish off the cose signature. This does all the interesting work of + hashing and signing */ + cose_return_value = + t_cose_sign1_finish(&(me->signer_ctx), token_payload_ub); + if(cose_return_value) { + /* Main errors are invoking the hash or signature */ + return_value = t_cose_err_to_attest_err(cose_return_value); + goto Done; + } + + /* Close off the CBOR encoding and return the completed token */ + qcbor_result = QCBOREncode_Finish(&(me->cbor_enc_ctx), + &completed_token_ub); + if(qcbor_result == QCBOR_ERR_BUFFER_TOO_SMALL) { + return_value = ATTEST_TOKEN_ERR_TOO_SMALL; + } else if (qcbor_result != QCBOR_SUCCESS) { + /* likely from array not closed, too many closes, ... */ + return_value = ATTEST_TOKEN_ERR_CBOR_FORMATTING; + } else { + *completed_token = completed_token_ub; + } + +Done: + return return_value; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/attest_token.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/attest_token.h new file mode 100755 index 0000000..903c42b --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/attest_token.h @@ -0,0 +1,241 @@ +/* + * attest_token.h + * + * Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * See BSD-3-Clause license in README.md + */ + +#ifndef __ATTEST_TOKEN_H__ +#define __ATTEST_TOKEN_H__ + +#include +#include "qcbor.h" +#include "t_cose_sign1_sign.h" + + +/** + * \file attest_token.h + * + * \brief Attestation Token Creation Interface + * + * The context and functions here are the way to create an attestation + * token. The steps are roughly: + * + * -# Creation and initialize an attest_token_ctx indicating the + * options, key and such using attest_token_start(). + * + * -# Use various add methods to fill in the payload with claims. The + * encoding context can also be borrowed for more rich payloads. + * + * -# Call attest_token_finish() to create the signature and finish + * formatting the COSE signed output. + */ + + +/** + Error codes returned from attestation token creation. + */ +enum attest_token_err_t { + /** Success */ + ATTEST_TOKEN_ERR_SUCCESS = 0, + /** The buffer passed in to receive the output is too small. */ + ATTEST_TOKEN_ERR_TOO_SMALL, + /** Something went wrong formatting the CBOR, most likely the + payload has maps or arrays that are not closed. */ + ATTEST_TOKEN_ERR_CBOR_FORMATTING, + /** A general, unspecific error when creating or decoding the + token. */ + ATTEST_TOKEN_ERR_GENERAL, + /** A hash function that is needed to make the token is not + available. */ + ATTEST_TOKEN_ERR_HASH_UNAVAILABLE, + /** CBOR Syntax not well-formed -- a CBOR syntax error. */ + ATTEST_TOKEN_ERR_CBOR_NOT_WELL_FORMED, + /** Bad CBOR structure, for example not a map when was is + required. */ + ATTEST_TOKEN_ERR_CBOR_STRUCTURE, + /** Bad CBOR type, for example an not a text string, when a text + string is required. */ + ATTETST_TOKEN_ERR_CBOR_TYPE, + /** Integer too large, for example an \c int32_t is required, but + value only fits in \c int64_t */ + ATTEST_TOKEN_ERR_INTEGER_VALUE, + /** Something is wrong with the COSE signing structure, missing + headers or such. */ + ATTEST_TOKEN_ERR_COSE_SIGN1_FORMAT, + /** COSE signature is invalid, data is corrupted. */ + ATTEST_TOKEN_ERR_COSE_SIGN1_VALIDATION, + /** The signing algorithm is not supported. */ + ATTEST_TOKEN_ERR_UNSUPPORTED_SIG_ALG, + /** Out of memory. */ + ATTEST_TOKEN_ERR_INSUFFICIENT_MEMORY, + /** Tampering detected in cryptographic function. */ + ATTEST_TOKEN_ERR_TAMPERING_DETECTED, + /** Verification key is not found or of wrong type. */ + ATTEST_TOKEN_ERR_VERIFICATION_KEY +}; + + + +/** + * Request that the claims internally generated not be added to the + * token. This is a test mode that results in a static token that + * never changes. Only the nonce is included. The nonce is under + * the callers control unlike the other claims. + */ +#define TOKEN_OPT_OMIT_CLAIMS 0x40000000 + + +/** + * A special test mode where a proper signature is not produced. In + * its place there is a concatenation of hashes of the payload to be + * the same size as the signature. This works and can be used to + * verify all of the SW stack except the public signature part. The + * token has no security value in this mode because anyone can + * replicate it. */ +#define TOKEN_OPT_SHORT_CIRCUIT_SIGN 0x80000000 + + +/** + * The context for creating an attestation token. The caller of + * attest_token must create one of these and pass it to the functions + * here. It is small enough that it can go on the stack. It is most of + * the memory needed to create a token except the output buffer and + * any memory requirements for the cryptographic operations. + * + * The structure is opaque for the caller. + * + * This is roughly 148 + 8 + 32 = 188 bytes + */ +struct attest_token_ctx { + /* Private data structure */ + QCBOREncodeContext cbor_enc_ctx; + uint32_t opt_flags; + int32_t key_select; + struct t_cose_sign1_ctx signer_ctx; +}; + + +/** + * \brief Initialize a token creation context. + * + * \param[in] me The token creation context to be initialized. + * \param[in] opt_flags Flags to select different custom options, + for example \ref TOKEN_OPT_OMIT_CLAIMS. + * \param[in] key_select Selects which attestation key to sign with. + * \param[in] cose_alg_id The algorithm to sign with. The IDs are + * defined in [COSE (RFC 8152)] + * (https://tools.ietf.org/html/rfc8152) or + * in the [IANA COSE Registry] + * (https://www.iana.org/assignments/cose/cose.xhtml). + * \param[out] out_buffer The output buffer to write the encoded token into. + * + * \return one of the \ref attest_token_err_t errors. + * + * The size of the buffer in \c out_buffer->len + * determines the size of the token that can be created. It must be + * able to hold the final encoded and signed token. The data encoding + * overhead is just that of CBOR. The signing overhead depends on the + * signing key size. It is about 150 bytes for 256-bit ECDSA. + * + * If \c out_buffer->ptr is \c NULL and \c out_buffer_ptr->len is + * large like \c UINT32_MAX no token will be created but the length of + * the token that would be created will be in \c completed_token as + * returned by attest_token_finish(). None of the cryptographic + * functions run during this, but the sizes of what they would output + * is taken into account. + */ +enum attest_token_err_t +attest_token_start(struct attest_token_ctx *me, + uint32_t opt_flags, + int32_t key_select, + int32_t cose_alg_id, + const struct useful_buf *out_buffer); + + + +/** + * \brief Get a copy of the CBOR encoding context + * + * \param[in] me Token creation context. + * + * \return The CBOR encoding context + * + * Allows the caller to encode CBOR right into the output buffer using + * any of the \c QCBOREncode_AddXXXX() methods. Anything added here + * will be part of the payload that gets hashed. This can be used to + * make complex CBOR structures. All open arrays and maps must be + * close before calling any other \c attest_token methods. \c + * QCBOREncode_Finish() should not be closed on this context. + */ +QCBOREncodeContext *attest_token_borrow_cbor_cntxt(struct attest_token_ctx *me); + +/** + * \brief Add a 64-bit signed integer claim + * + * \param[in] me Token creation context. + * \param[in] label Integer label for claim. + * \param[in] value The integer claim data. + */ +void attest_token_add_integer(struct attest_token_ctx *me, + int32_t label, + int64_t value); + +/** + * \brief Add a binary string claim + * + * \param[in] me Token creation context. + * \param[in] label Integer label for claim. + * \param[in] value The binary claim data. + */ +void attest_token_add_bstr(struct attest_token_ctx *me, + int32_t label, + const struct useful_buf_c *value); + +/** + * \brief Add a text string claim + * + * \param[in] me Token creation context. + * \param[in] label Integer label for claim. + * \param[in] value The text claim data. + */ +void attest_token_add_tstr(struct attest_token_ctx *me, + int32_t label, + const struct useful_buf_c *value); + +/** + * \brief Add some already-encoded CBOR to payload + * + * \param[in] me Token creation context. + * \param[in] label Integer label for claim. + * \param[in] encoded The already-encoded CBOR. + * + * Encoded CBOR must be a full map or full array or a non-aggregate + * type. It cannot be a partial map or array. It can be nested maps + * and arrays, but they must all be complete. + */ +void attest_token_add_encoded(struct attest_token_ctx *me, + int32_t label, + const struct useful_buf_c *encoded); + + +/** + * \brief Finish the token, complete the signing and get the result + * + * \param[in] me Token Creation Context. + * \param[out] completed_token Pointer and length to completed token. + * + * \return one of the \ref attest_token_err_t errors. + * + * This completes the token after the payload has been added. When + * this is called the signing algorithm is run and the final + * formatting of the token is completed. + */ +enum attest_token_err_t +attest_token_finish(struct attest_token_ctx *me, + struct useful_buf_c *completed_token); + +#endif /* __ATTEST_TOKEN_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/attestation_core.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/attestation_core.c new file mode 100755 index 0000000..a7e46da --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/attestation_core.c @@ -0,0 +1,1032 @@ +/* + * Copyright (c) 2018-2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include "tfm_client.h" +#include "attestation.h" +#include "tfm_impl/tfm_boot_status.h" +#include "tfm_plat_defs.h" +#include "tfm_plat_device_id.h" +#include "tfm_plat_boot_seed.h" +#include "tfm_attest_hal.h" +#include "attest_token.h" +#include "attest_eat_defines.h" +#include "t_cose_defines.h" +#include "tfm_memory_utils.h" + +#define MAX_BOOT_STATUS 512 + +/* Indicates how to encode SW components' measurements in the CBOR map */ +#define EAT_SW_COMPONENT_NESTED 1 /* Nested map */ +#define EAT_SW_COMPONENT_NOT_NESTED 0 /* Flat structure */ + +/* Indicates that the boot status does not contain any SW components' + * measurement + */ +#define NO_SW_COMPONENT_FIXED_VALUE 1 + +/*! + * \var boot_status + * + * \brief Array variable to store the boot status in service's memory. + * + * \details Boot status comes from the secure bootloader and primarily stored + * on a memory area which is shared between bootloader and SPM. + * SPM provides the \ref tfm_core_get_boot_data() API to retrieve + * the service related data from shared area. + */ + +/* Enforcement of 4 byte alignment, which is checked by TF-M SPM */ +__attribute__ ((aligned(4))) +static uint8_t boot_status[MAX_BOOT_STATUS]; + +enum psa_attest_err_t attest_init(void) +{ + enum psa_attest_err_t res; + + res = attest_get_boot_data(TLV_MAJOR_IAS, boot_status, MAX_BOOT_STATUS); + + return res; +} + +/*! + * \brief Static function to map return values between \ref attest_token_err_t + * and \ref psa_attest_err_t + * + * \param[in] token_err Token encoding return value + * + * \return Returns error code as specified in \ref psa_attest_err_t + */ +static inline enum psa_attest_err_t +error_mapping(enum attest_token_err_t token_err) +{ + switch (token_err) { + case ATTEST_TOKEN_ERR_SUCCESS: + return PSA_ATTEST_ERR_SUCCESS; + break; + case ATTEST_TOKEN_ERR_TOO_SMALL: + return PSA_ATTEST_ERR_TOKEN_BUFFER_OVERFLOW; + break; + default: + return PSA_ATTEST_ERR_GENERAL; + } +} + +/*! + * \brief Static function to convert a pointer and size info to unsigned + * integer number. Max 32bits unsigned integers are supported. + * + * This implementation assumes that the endianness of the sender and receiver + * of the data is the same because they are actually running on the same CPU + * instance. If this assumption is not true than this function must be + * refactored accordingly. + * + * \param[in] int_ptr Pointer to the unsigned integer + * \param[in] len Size of the unsigned integers in bytes + * \param[in] value Pointer where to store the converted value + * + * \return Returns 0 on success and -1 on error. + */ +static inline int32_t get_uint(const void *int_ptr, + size_t len, + uint32_t *value) +{ + uint16_t uint16; + + switch (len) { + case 1: + *value = (uint32_t)(*(uint8_t *)(int_ptr)); + break; + case 2: + /* Avoid unaligned access */ + tfm_memcpy(&uint16, int_ptr, sizeof(uint16)); + *value = (uint32_t)uint16; + break; + case 4: + /* Avoid unaligned access */ + tfm_memcpy(value, int_ptr, sizeof(uint32_t)); + break; + default: + return -1; + } + + return 0; +} +/*! + * \brief Static function to look up all entires in the shared data area + * (boot status) which belong to a specific module. + * + * \param[in] module The identifier of SW module to look up based on this + * \param[out] claim The type of SW module's attribute + * \param[out] tlv_len Length of the shared data entry + * \param[in/out] tlv_ptr Pointer to the shared data entry. If its value NULL as + * input then it will starts the look up from the + * beginning of the shared data section. If not NULL then + * it continue look up from the next entry. It returns + * the address of next found entry which belongs to + * module. + * + * \retval -1 Error, boot status is malformed + * \retval 0 Entry not found + * \retval 1 Entry found + */ +static int32_t attest_get_tlv_by_module(uint8_t module, + uint8_t *claim, + uint16_t *tlv_len, + uint8_t **tlv_ptr) +{ + struct shared_data_tlv_header *tlv_header; + struct shared_data_tlv_entry tlv_entry; + uint8_t *tlv_end; + uint8_t *tlv_curr; + + tlv_header = (struct shared_data_tlv_header *)boot_status; + if (tlv_header->tlv_magic != SHARED_DATA_TLV_INFO_MAGIC) { + return -1; + } + + /* Get the boundaries of TLV section where to lookup*/ + tlv_end = (uint8_t *)boot_status + tlv_header->tlv_tot_len; + if (*tlv_ptr == NULL) { + /* At first call set to the beginning of the TLV section */ + tlv_curr = (uint8_t *)boot_status + SHARED_DATA_HEADER_SIZE; + } else { + /* Any subsequent call set to the next TLV entry */ + tfm_memcpy(&tlv_entry, *tlv_ptr, SHARED_DATA_ENTRY_HEADER_SIZE); + tlv_curr = (*tlv_ptr) + tlv_entry.tlv_len; + } + + /* Iterates over the TLV section and returns the address and size of TLVs + * with requested module identifier + */ + for (; tlv_curr < tlv_end; tlv_curr += tlv_entry.tlv_len) { + /* Create local copy to avoid unaligned access */ + tfm_memcpy(&tlv_entry, tlv_curr, SHARED_DATA_ENTRY_HEADER_SIZE); + if (GET_IAS_MODULE(tlv_entry.tlv_type) == module) { + *claim = GET_IAS_CLAIM(tlv_entry.tlv_type); + *tlv_ptr = tlv_curr; + *tlv_len = tlv_entry.tlv_len; + return 1; + } + } + + return 0; +} + +/*! + * \brief Static function to look up specific claim belongs to SW_GENERAL module + * + * \param[in] claim The claim ID to look for + * \param[out] tlv_len Length of the shared data entry + * \param[out] tlv_ptr Pointer to a shared data entry which belongs to the + * SW_GENERAL module. + * + * \retval -1 Error, boot status is malformed + * \retval 0 Entry not found + * \retval 1 Entry found + */ +static int32_t attest_get_tlv_by_id(uint8_t claim, + uint16_t *tlv_len, + uint8_t **tlv_ptr) +{ + uint8_t tlv_id; + uint8_t module = SW_GENERAL; + int32_t found; + + /* Ensure that look up starting from the beginning of the boot status */ + *tlv_ptr = NULL; + + /* Look up specific TLV entry which belongs to SW_GENERAL module */ + do { + /* Look up next entry */ + found = attest_get_tlv_by_module(module, &tlv_id, + tlv_len, tlv_ptr); + if (found != 1) { + break; + } + /* At least one entry was found which belongs to SW_GENERAL, + * check whether this one is looked for + */ + if (claim == tlv_id) { + break; + } + } while (found == 1); + + return found; +} + +/*! + * \brief Static function to add SW component related claims to attestation + * token in CBOR format. + * + * This function translates between TLV and CBOR encoding. + * + * \param[in] token_ctx Attestation token encoding context + * \param[in] tlv_id The ID of claim + * \param[in] claim_value A structure which carries a pointer and size about + * the data item to be added to the token + * + * \return Returns error code as specified in \ref psa_attest_err_t + */ +static enum psa_attest_err_t +attest_add_sw_component_claim(struct attest_token_ctx *token_ctx, + uint8_t tlv_id, + const struct useful_buf_c *claim_value) +{ + int32_t res; + uint32_t value; + + switch (tlv_id) { + case SW_MEASURE_VALUE: + attest_token_add_bstr(token_ctx, + EAT_CBOR_SW_COMPONENT_MEASUREMENT_VALUE, + claim_value); + break; + case SW_MEASURE_TYPE: + attest_token_add_tstr(token_ctx, + EAT_CBOR_SW_COMPONENT_MEASUREMENT_DESC, + claim_value); + break; + case SW_VERSION: + attest_token_add_tstr(token_ctx, + EAT_CBOR_SW_COMPONENT_VERSION, + claim_value); + break; + case SW_SIGNER_ID: + attest_token_add_bstr(token_ctx, + EAT_CBOR_SW_COMPONENT_SIGNER_ID, + claim_value); + break; + case SW_EPOCH: + res = get_uint(claim_value->ptr, claim_value->len, &value); + if (res) { + return PSA_ATTEST_ERR_GENERAL; + } + attest_token_add_integer(token_ctx, + EAT_CBOR_SW_COMPONENT_SECURITY_EPOCH, + (int64_t)value); + break; + case SW_TYPE: + attest_token_add_tstr(token_ctx, + EAT_CBOR_SW_COMPONENT_MEASUREMENT_TYPE, + claim_value); + break; + default: + return PSA_ATTEST_ERR_GENERAL; + } + + return PSA_ATTEST_ERR_SUCCESS; +} + +/*! + * \brief Static function to add the measurement data of a single SW components + * to the attestation token. + * + * \param[in] token_ctx Token encoding context + * \param[in] module SW component identifier + * \param[in] tlv_address Address of the first TLV entry in the boot status, + * which belongs to this SW component. + * \param[in] nested_map Flag to indicate that how to encode the SW component + * measurement data: nested map or non-nested map. + * + * \return Returns error code as specified in \ref psa_attest_err_t + */ +static enum psa_attest_err_t +attest_add_single_sw_measurment(struct attest_token_ctx *token_ctx, + uint32_t module, + uint8_t *tlv_address, + uint32_t nested_map) +{ + struct shared_data_tlv_entry tlv_entry; + uint16_t tlv_len; + uint8_t tlv_id; + uint8_t *tlv_ptr = tlv_address; + int32_t found = 1; + struct useful_buf_c claim_value; + enum psa_attest_err_t res; + QCBOREncodeContext *cbor_encode_ctx; + + /* Create local copy to avoid unaligned access */ + tfm_memcpy(&tlv_entry, tlv_address, SHARED_DATA_ENTRY_HEADER_SIZE); + tlv_len = tlv_entry.tlv_len; + tlv_id = GET_IAS_CLAIM(tlv_entry.tlv_type); + + cbor_encode_ctx = attest_token_borrow_cbor_cntxt(token_ctx); + + /* Open nested map for SW component measurement claims */ + if (nested_map) { + QCBOREncode_OpenMapInMapN(cbor_encode_ctx, + EAT_CBOR_SW_COMPONENT_MEASUREMENT_VALUE); + } + + /* Look up all measurement TLV entry which belongs to the SW component */ + while (found) { + /* Here only measurement claims are added to the token */ + if (GET_IAS_MEASUREMENT_CLAIM(tlv_id)) { + claim_value.ptr = tlv_ptr + SHARED_DATA_ENTRY_HEADER_SIZE; + claim_value.len = tlv_len - SHARED_DATA_ENTRY_HEADER_SIZE; + res = attest_add_sw_component_claim(token_ctx, + tlv_id, + &claim_value); + if (res != PSA_ATTEST_ERR_SUCCESS) { + return res; + } + } + + /* Look up next entry it can be non-measurement claim*/ + found = attest_get_tlv_by_module(module, &tlv_id, + &tlv_len, &tlv_ptr); + if (found == -1) { + return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE; + } + } + + if (nested_map) { + QCBOREncode_CloseMap(cbor_encode_ctx); + } + + return PSA_ATTEST_ERR_SUCCESS; +} + +/*! + * \brief Static function to add the claims of a single SW components to the + * attestation token. + * + * \param[in] token_ctx Token encoding context + * \param[in] module SW component identifier + * \param[in] tlv_address Address of the first TLV entry in the boot status, + * which belongs to this SW component. + * + * \return Returns error code as specified in \ref psa_attest_err_t + */ +static enum psa_attest_err_t +attest_add_single_sw_component(struct attest_token_ctx *token_ctx, + uint32_t module, + uint8_t *tlv_address) +{ + struct shared_data_tlv_entry tlv_entry; + uint16_t tlv_len; + uint8_t tlv_id; + uint8_t *tlv_ptr = tlv_address; + int32_t found = 1; + uint32_t measurement_claim_cnt = 0; + struct useful_buf_c claim_value; + QCBOREncodeContext *cbor_encode_ctx; + + /* Create local copy to avoid unaligned access */ + tfm_memcpy(&tlv_entry, tlv_address, SHARED_DATA_ENTRY_HEADER_SIZE); + tlv_len = tlv_entry.tlv_len; + tlv_id = GET_IAS_CLAIM(tlv_entry.tlv_type); + + /* Open map which stores claims belong to a SW component */ + cbor_encode_ctx = attest_token_borrow_cbor_cntxt(token_ctx); + QCBOREncode_OpenMap(cbor_encode_ctx); + + /*Look up all TLV entry which belongs to the same SW component */ + while (found) { + /* Check whether claim is measurement claim */ + if (GET_IAS_MEASUREMENT_CLAIM(tlv_id)) { + if (measurement_claim_cnt == 0) { + /* Call only once when first measurement claim found */ + measurement_claim_cnt++; + attest_add_single_sw_measurment(token_ctx, + module, + tlv_ptr, + EAT_SW_COMPONENT_NOT_NESTED); + } + } else { + /* Adding top level claims */ + claim_value.ptr = tlv_ptr + SHARED_DATA_ENTRY_HEADER_SIZE; + claim_value.len = tlv_len - SHARED_DATA_ENTRY_HEADER_SIZE; + attest_add_sw_component_claim(token_ctx, tlv_id, &claim_value); + } + + /* Look up next entry which belongs to SW component */ + found = attest_get_tlv_by_module(module, &tlv_id, + &tlv_len, &tlv_ptr); + if (found == -1) { + return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE; + } + } + + /* Close map which stores claims belong to a SW component */ + QCBOREncode_CloseMap(cbor_encode_ctx); + + return PSA_ATTEST_ERR_SUCCESS; +} + +/*! + * \brief Static function to add the claims of all SW components to the + * attestation token. + * + * \param[in] token_ctx Token encoding context + * + * \return Returns error code as specified in \ref psa_attest_err_t + */ +static enum psa_attest_err_t +attest_add_all_sw_components(struct attest_token_ctx *token_ctx) +{ + uint16_t tlv_len; + uint8_t *tlv_ptr; + uint8_t tlv_id; + int32_t found; + uint32_t cnt = 0; + uint32_t module; + QCBOREncodeContext *cbor_encode_ctx; + + /* Starting from module 1, because module 0 contains general claims which + * are not related to SW module(i.e: boot_seed, etc.) + */ + for (module = 1; module < SW_MAX; ++module) { + /* Indicates to restart the look up from the beginning of the shared + * data section + */ + tlv_ptr = NULL; + + /* Look up the first TLV entry which belongs to the SW module */ + found = attest_get_tlv_by_module(module, &tlv_id, + &tlv_len, &tlv_ptr); + if (found == -1) { + return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE; + } + + if (found == 1) { + cnt++; + if (cnt == 1) { + /* Open array which stores SW components claims */ + cbor_encode_ctx = attest_token_borrow_cbor_cntxt(token_ctx); + QCBOREncode_OpenArrayInMapN(cbor_encode_ctx, + EAT_CBOR_ARM_LABEL_SW_COMPONENTS); + } + attest_add_single_sw_component(token_ctx, module, tlv_ptr); + } + } + + if (cnt != 0) { + /* Close array which stores SW components claims*/ + QCBOREncode_CloseArray(cbor_encode_ctx); + } else { + /* If there is not any SW components' measurement in the boot status + * then include this claim to indicate that this state is intentional + */ + attest_token_add_integer(token_ctx, + EAT_CBOR_ARM_LABEL_NO_SW_COMPONENTS, + (int64_t)NO_SW_COMPONENT_FIXED_VALUE); + } + + return PSA_ATTEST_ERR_SUCCESS; +} + +/*! + * \brief Static function to add boot seed claim to attestation token. + * + * \param[in] token_ctx Token encoding context + * + * \return Returns error code as specified in \ref psa_attest_err_t + */ +static enum psa_attest_err_t +attest_add_boot_seed_claim(struct attest_token_ctx *token_ctx) +{ + /* FixMe: Enforcement of 4 byte alignment can be removed as soon as memory + * type is configured in the MPU to be normal, instead of device, + * which prohibits unaligned access. + */ + __attribute__ ((aligned(4))) + uint8_t boot_seed[BOOT_SEED_SIZE]; + enum tfm_plat_err_t res; + struct useful_buf_c claim_value = {0}; + uint16_t tlv_len; + uint8_t *tlv_ptr = NULL; + int32_t found = 0; + + /* First look up BOOT_SEED in boot status, it might comes from bootloader */ + found = attest_get_tlv_by_id(BOOT_SEED, &tlv_len, &tlv_ptr); + if (found == 1) { + claim_value.ptr = tlv_ptr + SHARED_DATA_ENTRY_HEADER_SIZE; + claim_value.len = tlv_len - SHARED_DATA_ENTRY_HEADER_SIZE; + } else { + /* If not found in boot status then use callback function to get it + * from runtime SW + */ + res = tfm_plat_get_boot_seed(sizeof(boot_seed), boot_seed); + if (res != TFM_PLAT_ERR_SUCCESS) { + return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE; + } + claim_value.ptr = boot_seed; + claim_value.len = BOOT_SEED_SIZE; + } + + attest_token_add_bstr(token_ctx, + EAT_CBOR_ARM_LABEL_BOOT_SEED, + &claim_value); + + return PSA_ATTEST_ERR_SUCCESS; +} + +/* FixMe: Remove this #if when MPU will be configured properly. Currently + * in case of TFM_LVL == 3 unaligned access triggers a usage fault + * exception. + */ +#if !defined(TFM_LVL) || (TFM_LVL == 1) +/*! + * \brief Static function to add instance id claim to attestation token. + * + * \param[in] token_ctx Token encoding context + * + * \return Returns error code as specified in \ref psa_attest_err_t + */ +static enum psa_attest_err_t +attest_add_instance_id_claim(struct attest_token_ctx *token_ctx) +{ + /* FixMe: Enforcement of 4 byte alignment can be removed as soon as memory + * type is configured in the MPU to be normal, instead of device, + * which prohibits unaligned access. + */ + __attribute__ ((aligned(4))) + uint8_t instance_id[INSTANCE_ID_MAX_SIZE]; + enum tfm_plat_err_t res_plat; + uint32_t size = sizeof(instance_id); + struct useful_buf_c claim_value; + + res_plat = tfm_plat_get_instance_id(&size, instance_id); + if (res_plat != TFM_PLAT_ERR_SUCCESS) { + return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE; + } + + claim_value.ptr = instance_id; + claim_value.len = size; + attest_token_add_bstr(token_ctx, + EAT_CBOR_ARM_LABEL_UEID, + &claim_value); + + return PSA_ATTEST_ERR_SUCCESS; +} + +/*! + * \brief Static function to add implementation id claim to attestation token. + * + * \param[in] token_ctx Token encoding context + * + * \return Returns error code as specified in \ref psa_attest_err_t + */ +static enum psa_attest_err_t +attest_add_implementation_id_claim(struct attest_token_ctx *token_ctx) +{ + /* FixMe: Enforcement of 4 byte alignment can be removed as soon as memory + * type is configured in the MPU to be normal, instead of device, + * which prohibits unaligned access. + */ + __attribute__ ((aligned(4))) + uint8_t implementation_id[IMPLEMENTATION_ID_MAX_SIZE]; + enum tfm_plat_err_t res_plat; + uint32_t size = sizeof(implementation_id); + struct useful_buf_c claim_value; + + res_plat = tfm_plat_get_implementation_id(&size, implementation_id); + if (res_plat != TFM_PLAT_ERR_SUCCESS) { + return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE; + } + + claim_value.ptr = implementation_id; + claim_value.len = size; + attest_token_add_bstr(token_ctx, + EAT_CBOR_ARM_LABEL_IMPLEMENTATION_ID, + &claim_value); + + return PSA_ATTEST_ERR_SUCCESS; +} + +/*! + * \brief Static function to add hardware version claim to attestation token. + * + * \param[in] token_ctx Token encoding context + * + * \return Returns error code as specified in \ref psa_attest_err_t + */ +static enum psa_attest_err_t +attest_add_hw_version_claim(struct attest_token_ctx *token_ctx) +{ + /* FixMe: Enforcement of 4 byte alignment can be removed as soon as memory + * type is configured in the MPU to be normal, instead of device, + * which prohibits unaligned access. + */ + __attribute__ ((aligned(4))) + uint8_t hw_version[HW_VERSION_MAX_SIZE]; + enum tfm_plat_err_t res_plat; + uint32_t size = sizeof(hw_version); + struct useful_buf_c claim_value = {0}; + uint16_t tlv_len; + uint8_t *tlv_ptr = NULL; + int32_t found = 0; + + /* First look up HW version in boot status, it might comes + * from bootloader + */ + found = attest_get_tlv_by_id(HW_VERSION, &tlv_len, &tlv_ptr); + if (found == 1) { + claim_value.ptr = tlv_ptr + SHARED_DATA_ENTRY_HEADER_SIZE; + claim_value.len = tlv_len - SHARED_DATA_ENTRY_HEADER_SIZE; + } else { + /* If not found in boot status then use callback function to get it + * from runtime SW + */ + res_plat = tfm_plat_get_hw_version(&size, hw_version); + if (res_plat != TFM_PLAT_ERR_SUCCESS) { + return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE; + } + claim_value.ptr = hw_version; + claim_value.len = size; + } + + attest_token_add_tstr(token_ctx, + EAT_CBOR_ARM_LABEL_HW_VERSION, + &claim_value); + + return PSA_ATTEST_ERR_SUCCESS; +} +#endif + +/*! + * \brief Static function to add caller id claim to attestation token. + * + * \param[in] token_ctx Token encoding context + * + * \return Returns error code as specified in \ref psa_attest_err_t + */ +static enum psa_attest_err_t +attest_add_caller_id_claim(struct attest_token_ctx *token_ctx) +{ + enum psa_attest_err_t res; + int32_t caller_id; + + res = attest_get_caller_client_id(&caller_id); + if (res != PSA_ATTEST_ERR_SUCCESS) { + return res; + } + + attest_token_add_integer(token_ctx, + EAT_CBOR_ARM_LABEL_CLIENT_ID, + (int64_t)caller_id); + + return PSA_ATTEST_ERR_SUCCESS; +} + +/*! + * \brief Static function to add security lifecycle claim to attestation token. + * + * \param[in] token_ctx Token encoding context + * + * \return Returns error code as specified in \ref psa_attest_err_t + */ + +static enum psa_attest_err_t +attest_add_security_lifecycle_claim(struct attest_token_ctx *token_ctx) +{ + enum tfm_security_lifecycle_t security_lifecycle; + uint32_t slc_value; + int32_t res; + struct useful_buf_c claim_value = {0}; + uint16_t tlv_len; + uint8_t *tlv_ptr = NULL; + int32_t found = 0; + + /* First look up lifecycle state in boot status, it might comes + * from bootloader + */ + found = attest_get_tlv_by_id(SECURITY_LIFECYCLE, &tlv_len, &tlv_ptr); + if (found == 1) { + claim_value.ptr = tlv_ptr + SHARED_DATA_ENTRY_HEADER_SIZE; + claim_value.len = tlv_len - SHARED_DATA_ENTRY_HEADER_SIZE; + res = get_uint(claim_value.ptr, claim_value.len, &slc_value); + if (res) { + return PSA_ATTEST_ERR_GENERAL; + } + security_lifecycle = (enum tfm_security_lifecycle_t)slc_value; + } else { + /* If not found in boot status then use callback function to get it + * from runtime SW + */ + security_lifecycle = tfm_attest_hal_get_security_lifecycle(); + } + + /* Sanity check */ + if (security_lifecycle < TFM_SLC_UNKNOWN || + security_lifecycle > TFM_SLC_DECOMMISSIONED) { + return PSA_ATTEST_ERR_GENERAL; + } + + attest_token_add_integer(token_ctx, + EAT_CBOR_ARM_LABEL_SECURITY_LIFECYCLE, + (int64_t)security_lifecycle); + + return PSA_ATTEST_ERR_SUCCESS; +} + +/*! + * \brief Static function to add challenge claim to attestation token. + * + * \param[in] token_ctx Token encoding context + * \param[in] challenge Pointer to buffer which stores the challenge + * + * \return Returns error code as specified in \ref psa_attest_err_t + */ +static enum psa_attest_err_t +attest_add_challenge_claim(struct attest_token_ctx *token_ctx, + const struct useful_buf_c *challenge) +{ + attest_token_add_bstr(token_ctx, EAT_CBOR_ARM_LABEL_CHALLENGE, challenge); + + return PSA_ATTEST_ERR_SUCCESS; +} + +/*! + * \brief Static function to add the verification service indicator claim + * to the attestation token. + * + * \param[in] token_ctx Token encoding context + * + * \return Returns error code as specified in \ref psa_attest_err_t + */ +static enum psa_attest_err_t +attest_add_verification_service(struct attest_token_ctx *token_ctx) +{ + struct useful_buf_c service; + uint32_t size; + + service.ptr = tfm_attest_hal_get_verification_service(&size); + + if (service.ptr) { + service.len = size; + attest_token_add_tstr(token_ctx, + EAT_CBOR_ARM_LABEL_ORIGINATION, + &service); + } + + return PSA_ATTEST_ERR_SUCCESS; +} + +/*! + * \brief Static function to add the name of the profile definition document + * + * \param[in] token_ctx Token encoding context + * + * \return Returns error code as specified in \ref psa_attest_err_t + */ +static enum psa_attest_err_t +attest_add_profile_definition(struct attest_token_ctx *token_ctx) +{ + struct useful_buf_c profile; + uint32_t size; + + profile.ptr = tfm_attest_hal_get_profile_definition(&size); + + if (profile.ptr) { + profile.len = size; + attest_token_add_tstr(token_ctx, + EAT_CBOR_ARM_LABEL_PROFILE_DEFINITION, + &profile); + } + + return PSA_ATTEST_ERR_SUCCESS; +} + +/*! + * \brief Static function to verify the input challenge size + * + * Only discrete sizes are accepted. + * + * \param[in] challenge_size Size of challenge object in bytes. + * + * \retval PSA_ATTEST_ERR_SUCCESS + * \retval PSA_ATTEST_ERR_INVALID_INPUT + */ +static enum psa_attest_err_t attest_verify_challenge_size(size_t challenge_size) +{ + switch (challenge_size) { + /* Intentional fall through */ + case PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32: + case PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48: + case PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64: + case (PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32 + 4): /* Test purpose */ + return PSA_ATTEST_ERR_SUCCESS; + } + + return PSA_ATTEST_ERR_INVALID_INPUT; +} + +/*! + * \brief Static function to create the initial attestation token + * + * \param[in] challenge Structure to carry the challenge value: + * pointer + challeng's length + * \param[in] token Structure to carry the token info, where to + * create it: pointer + buffer's length + * \param[out] completed_token Structure to carry the info about the created + * token: pointer + final token's length + * + * \return Returns error code as specified in \ref psa_attest_err_t + */ +static enum psa_attest_err_t +attest_create_token(struct useful_buf_c *challenge, + struct useful_buf *token, + struct useful_buf_c *completed_token) +{ + enum psa_attest_err_t attest_err = PSA_ATTEST_ERR_SUCCESS; + enum attest_token_err_t token_err; + struct attest_token_ctx attest_token_ctx; + int32_t key_select; + uint32_t option_flags = 0; + + if (challenge->len == 36) { + /* FixMe: Special challenge with option flags appended. This might can + * be removed when the public API can take option_flags. + */ + option_flags = *(uint32_t *)((uint8_t*)challenge->ptr + 32); + challenge->len = 32; + } + + /* Lower three bits are the key select */ + key_select = option_flags & 0x7; + + /* Get started creating the token. This sets up the CBOR and COSE contexts + * which causes the COSE headers to be constructed. + */ + token_err = attest_token_start(&attest_token_ctx, + option_flags, /* option_flags */ + key_select, /* key_select */ + COSE_ALGORITHM_ES256, /* alg_select */ + token); + + if (token_err != ATTEST_TOKEN_ERR_SUCCESS) { + attest_err = error_mapping(token_err); + goto error; + } + + attest_err = attest_add_challenge_claim(&attest_token_ctx, + challenge); + if (attest_err != PSA_ATTEST_ERR_SUCCESS) { + goto error; + } + + if (!(option_flags & TOKEN_OPT_OMIT_CLAIMS)) { + attest_err = attest_add_boot_seed_claim(&attest_token_ctx); + if (attest_err != PSA_ATTEST_ERR_SUCCESS) { + goto error; + } + + attest_err = attest_add_verification_service(&attest_token_ctx); + if (attest_err != PSA_ATTEST_ERR_SUCCESS) { + goto error; + } + + attest_err = attest_add_profile_definition(&attest_token_ctx); + if (attest_err != PSA_ATTEST_ERR_SUCCESS) { + goto error; + } + + /* FixMe: Remove this #if when MPU will be configured properly. + * Currently in case of TFM_LVL == 3 unaligned access triggers + * a usage fault exception. + */ +#if !defined(TFM_LVL) || (TFM_LVL == 1) + attest_err = attest_add_instance_id_claim(&attest_token_ctx); + if (attest_err != PSA_ATTEST_ERR_SUCCESS) { + goto error; + } + + attest_err = attest_add_hw_version_claim(&attest_token_ctx); + if (attest_err != PSA_ATTEST_ERR_SUCCESS) { + goto error; + } + + attest_err = attest_add_implementation_id_claim(&attest_token_ctx); + if (attest_err != PSA_ATTEST_ERR_SUCCESS) { + goto error; + } +#endif + + attest_err = attest_add_caller_id_claim(&attest_token_ctx); + if (attest_err != PSA_ATTEST_ERR_SUCCESS) { + goto error; + } + + attest_err = attest_add_security_lifecycle_claim(&attest_token_ctx); + if (attest_err != PSA_ATTEST_ERR_SUCCESS) { + goto error; + } + + attest_err = attest_add_all_sw_components(&attest_token_ctx); + if (attest_err != PSA_ATTEST_ERR_SUCCESS) { + goto error; + } + } + + /* Finish up creating the token. This is where the actual signature + * is generated. This finishes up the CBOR encoding too. + */ + token_err = attest_token_finish(&attest_token_ctx, completed_token); + if (token_err) { + attest_err = error_mapping(token_err); + goto error; + } + +error: + return attest_err; +} + +/* Limitations of the current implementation: + * - Token is not signed yet properly, just a fake signature is added to the + * token due to lack of psa_sign_hash() implementation in crypto + * service. + */ +enum psa_attest_err_t +initial_attest_get_token(const psa_invec *in_vec, uint32_t num_invec, + psa_outvec *out_vec, uint32_t num_outvec) +{ + enum psa_attest_err_t attest_err = PSA_ATTEST_ERR_SUCCESS; + struct useful_buf_c challenge; + struct useful_buf token; + struct useful_buf_c completed_token; + + challenge.ptr = in_vec[0].base; + challenge.len = in_vec[0].len; + token.ptr = out_vec[0].base; + token.len = out_vec[0].len; + + attest_err = attest_verify_challenge_size(challenge.len); + if (attest_err != PSA_ATTEST_ERR_SUCCESS) { + goto error; + } + + attest_err = attest_check_memory_access((void *)challenge.ptr, + challenge.len, + TFM_ATTEST_ACCESS_RO); + if (attest_err != PSA_ATTEST_ERR_SUCCESS) { + goto error; + } + + attest_err = attest_check_memory_access(token.ptr, + token.len, + TFM_ATTEST_ACCESS_RW); + if (attest_err != PSA_ATTEST_ERR_SUCCESS) { + goto error; + } + + attest_err = attest_create_token(&challenge, &token, &completed_token); + if (attest_err != PSA_ATTEST_ERR_SUCCESS) { + goto error; + } + + out_vec[0].base = (void *)completed_token.ptr; + out_vec[0].len = completed_token.len; + +error: + return attest_err; +} + +/* Initial implementation, just returns with hard coded value */ +enum psa_attest_err_t +initial_attest_get_token_size(const psa_invec *in_vec, uint32_t num_invec, + psa_outvec *out_vec, uint32_t num_outvec) +{ + enum psa_attest_err_t attest_err = PSA_ATTEST_ERR_SUCCESS; + uint32_t challenge_size = *(uint32_t *)in_vec[0].base; + uint32_t *token_buf_size = (uint32_t *)out_vec[0].base; + struct useful_buf_c challenge; + struct useful_buf token; + struct useful_buf_c completed_token; + + /* Only the size of the challenge is needed */ + challenge.ptr = NULL; + challenge.len = challenge_size; + + /* Special value to get the size of the token, but token is not created */ + token.ptr = NULL; + token.len = INT32_MAX; + + if (out_vec[0].len < sizeof(uint32_t)) { + attest_err = PSA_ATTEST_ERR_INVALID_INPUT; + goto error; + } + + attest_err = attest_verify_challenge_size(challenge_size); + if (attest_err != PSA_ATTEST_ERR_SUCCESS) { + goto error; + } + + attest_err = attest_create_token(&challenge, &token, &completed_token); + if (attest_err != PSA_ATTEST_ERR_SUCCESS) { + goto error; + } + + *token_buf_size = completed_token.len; + +error: + return attest_err; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/CMakeLists.txt b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/CMakeLists.txt new file mode 100644 index 0000000..e1f1985 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/CMakeLists.txt @@ -0,0 +1,40 @@ +#------------------------------------------------------------------------------- +# Copyright (c) 2019, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +#------------------------------------------------------------------------------- + +cmake_minimum_required(VERSION 3.7) + +#Tell cmake where our modules can be found +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/../../../cmake) + +#Include common stuff to control cmake. +include("Common/BuildSys") + +#Start an embedded project. +embedded_project_start(CONFIG "${CMAKE_CURRENT_LIST_DIR}/../../ConfigDefault.cmake") +project(tfm_t_cose LANGUAGES C) +embedded_project_fixup() + +#Some project global settings +set(T_COSE_DIR "${CMAKE_CURRENT_LIST_DIR}") + +#Append all our source files to global lists. +list(APPEND ALL_SRC_C + "${T_COSE_DIR}/src/t_cose_sign1_sign.c" + "${T_COSE_DIR}/src/t_cose_util.c" + "${T_COSE_DIR}/src/t_cose_psa_crypto.c" + ) + +#Setting include directories +embedded_include_directories(PATH ${T_COSE_DIR}/inc ABSOLUTE) + +#Specify what we build (for the t_cose, build as an object library) +add_library(${PROJECT_NAME} OBJECT ${ALL_SRC_C}) + +#Set common compiler flags +config_setting_shared_compiler_flags(${PROJECT_NAME}) + +embedded_project_end(${PROJECT_NAME}) diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/README.md b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/README.md new file mode 100644 index 0000000..9501806 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/README.md @@ -0,0 +1,95 @@ +# t_cose + +## Introduction + +t_cose is a partial implementation of the COSE standard (RFC 8152). +COSE is quite a large standard so a full implementation of all of it +is a large undertaking. This implementation is starting out as just +enough for attestation and maybe CWT (Cbor Web Token) which is very +similar. + +As it may grow to support more of COSE over time, it is structured +with that in mind. + +It is also trying to be portable, the most interesting part of which +is interfacing with the libraries for performing cryptography and +access cryptographic keys. + +## Source files +The following files are more or less the public interface. +* t_cose_common.h +* t_cose_sign1.h +* t_cose_sign1_verify.h + +The rest of the files are internal source files that callers should +not depend on. + +t_cose_defines.h contains contants from RFC 8152 that are +part of the COSE standard. It should never have anything else +in it. + +t_cose_util is some utilities and code common to +signing and verification. Both signing and verifcation +depend on it. + +t_cose_crypto is the crypto porting layer. Generally +the .h file should not need to change for a new +platform. The .c file will be changed lots for +each new platform. + +## Dependency and Portability +t_cose is attempting to be very portable and +have a minmum number of #ifdefs. It is +designed to run 64-bit and 32-bit machines. + +It uses a minimum number of standard C +libraries, mostly just , and . + +It uses QCBOR for CBOR encoding and decoding. +QCBOR is very portable. + +### Cryptography and Keys +There is a cryptographic adaption layer that +provides the following: +* Impedence match of parameters passed to/from the crypto +* Management of algorithm identifiers +* Management of error codes +* Management of key identifiers + +It is framed for the needs of t_cose, and is +not trying to be any kind of general crypto API. + +#### Question +Q: How many crypto APIs does it take to screw in a light bulb? +A: One more than it takes to screw in a light bulb. + +## Copyright and License + +### BSD-3-Clause license + +* Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +### Copyright for this README + +Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/inc/t_cose_common.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/inc/t_cose_common.h new file mode 100644 index 0000000..d509a4b --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/inc/t_cose_common.h @@ -0,0 +1,148 @@ +/* + * t_cose_common.h + * + * Copyright 2019, Laurence Lundblade + * + * SPDX-License-Identifier: BSD-3-Clause + * + * See BSD-3-Clause license in README.mdE. + */ + + +#ifndef __T_COSE_COMMON_H__ +#define __T_COSE_COMMON_H__ + + +/** + * \file t_cose_common.h + * + * \brief Defines common to all public t_cose interfaces. + * + */ + + +/* Private value. Intentionally not documented for Doxygen. + * This is the size allocated for the encoded protected headers. It + * needs to be big enough for make_protected_header() to succeed. It + * currently sized for one header with an algorithm ID up to 32 bits + * long -- one byte for the wrapping map, one byte for the label, 5 + * bytes for the ID. If this is made accidentially too small, QCBOR will + * only return an error, and not overrun any buffers. + * + * 9 extra bytes are added, rounding it up to 16 total, in case some + * other protected header is to be added. + */ +#define T_COSE_SIGN1_MAX_PROT_HEADER (1+1+5+9) + + +/** + * Error codes return by t_cose. + * + * Do not reorder these. It is OK to add + * new ones at the end. + */ +enum t_cose_err_t { + /** + * Operation completed successfully + */ + T_COSE_SUCCESS = 0, + /** + * The requested signing algorithm is not supported. + */ + T_COSE_ERR_UNSUPPORTED_SIGNING_ALG, + /** + * Error constructing the protected headers. + */ + T_COSE_ERR_PROTECTED_HEADERS, + /** + * The hash algorithm needed is not supported. Note that the + * signing algorithm identifier usually identifies the hash + * algorithm. + */ + T_COSE_ERR_UNSUPPORTED_HASH, + /** + * Some system failure when running the hash algorithm. + */ + T_COSE_ERR_HASH_GENERAL_FAIL, + /** + * The buffer to receive a hash result is too small. + */ + T_COSE_ERR_HASH_BUFFER_SIZE, + /** + * The buffer to receive result of a signing operation is too + * small. + */ + T_COSE_ERR_SIG_BUFFER_SIZE, + /** + * The buffer to receive to receive a key is too small. + */ + T_COSE_ERR_KEY_BUFFER_SIZE, + /** + * When verifying a \c COSE_Sign1, something is wrong with the + * format of the CBOR. For example, it is missing something like + * the payload. + */ + T_COSE_ERR_SIGN1_FORMAT, + /** + * When decoding some CBOR like a \c COSE_Sign1, the CBOR was not + * well-formed. Most likely what was supposed to be CBOR was is + * either not or it has been corrupted. + */ + T_COSE_ERR_CBOR_NOT_WELL_FORMED, + /** + * No algorithm ID was found when one is needed. For example, when + * verifying a \c COSE_Sign1. + */ + T_COSE_ERR_NO_ALG_ID, + /** + * No key ID was found when one is needed. For example, when + * verifying a \c COSE_Sign1. + */ + T_COSE_ERR_NO_KID, + /** + * Signature verification failed. For example, the cryptographic + * operations completed successfully but hash wasn't as expected. + */ + T_COSE_ERR_SIG_VERIFY, + /** + * Verification of a short-circuit signature failed. + */ + T_COSE_ERR_BAD_SHORT_CIRCUIT_KID, + /** + * Some (unspecified) argument was not valid. + */ + T_COSE_ERR_INVALID_ARGUMENT, + /** + * Out of heap memory. + */ + T_COSE_ERR_INSUFFICIENT_MEMORY, + /** + * General unspecific failure. + */ + T_COSE_ERR_FAIL, + /** + * Equivalent to \c PSA_ERROR_TAMPERING_DETECTED. + */ + T_COSE_ERR_TAMPERING_DETECTED, + /** + * The key identified by a key slot of a key ID was not found. + */ + T_COSE_ERR_UNKNOWN_KEY, + /** + * The key was found, but it was the wrong type for the operation. + */ + T_COSE_ERR_WRONG_TYPE_OF_KEY, + /** + * Error constructing the \c Sig_structure when signing or verify. + */ + T_COSE_ERR_SIG_STRUCT, + /** + * Signature was short-circuit. THe option to allow verification + * of short-circuit signatures was not set + */ + T_COSE_ERR_SHORT_CIRCUIT_SIG +}; + + + +#endif /* __T_COSE_COMMON_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/inc/t_cose_sign1_sign.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/inc/t_cose_sign1_sign.h new file mode 100644 index 0000000..35b26e5 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/inc/t_cose_sign1_sign.h @@ -0,0 +1,181 @@ +/* + * t_cose_sign1_sign.h + * + * Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * See BSD-3-Clause license in README.md + */ + +#ifndef __T_COSE_SIGN1_H__ +#define __T_COSE_SIGN1_H__ + +#include +#include +#include "qcbor.h" +#include "t_cose_common.h" + + +/** + * \file t_cose_sign1_sign.h + * + * \brief Create a \c COSE_Sign1, usually for EAT or CWT Token. + * + * This creates a \c COSE_Sign1 in compliance with [COSE (RFC 8152)] + * (https://tools.ietf.org/html/rfc8152). A \c COSE_Sign1 is a CBOR + * encoded binary blob that contains headers, a payload and a + * signature. Usually the signature is made with an EC signing + * algorithm like ECDSA. + * + * This implementation is intended to be small and portable to + * different OS's and platforms. Its dependencies are: + * - QCBOR + * - , , + * - Hash functions like SHA-256 + * - Signing functions like ECDSA + * + * There is a cryptographic adaptation layer defined in + * t_cose_crypto.h. An implementation can be made of the functions in + * it for different platforms or OS's. This means that different + * platforms and OS's may support only signing with a particular set + * of algorithms. + * + * This \c COSE_Sign1 implementations is optimized for creating EAT + * tokens. + * + * It should work for CWT and others use cases too. The main point of + * the optimization is that only one output buffer is needed. There is + * no need for one buffer to hold the payload and another to hold the + * end result \c COSE_Sign1. The payload is encoded right into its final + * place in the end result \c COSE_Sign1. + */ + + +/** + * This is the context for creating a \c COSE_Sign1 structure. The caller + * should allocate it and pass it to the functions here. This is + * about 32 bytes so it fits easily on the stack. + */ +struct t_cose_sign1_ctx { + /* Private data structure */ + uint8_t buffer_for_protected_headers[ + T_COSE_SIGN1_MAX_PROT_HEADER]; + struct useful_buf_c protected_headers; + int32_t cose_algorithm_id; + int32_t key_select; + bool short_circuit_sign; + QCBOREncodeContext *cbor_encode_ctx; +}; + + +/** + * \brief Initialize to start creating a \c COSE_Sign1. + * + * \param[in] me The t_cose signing context. + * \param[in] short_circuit_sign \c true to select special test mode. + * \param[in] cose_algorithm_id The algorithm to sign with. The IDs are + * defined in [COSE (RFC 8152)] + * (https://tools.ietf.org/html/rfc8152) or + * in the [IANA COSE Registry] + * (https://www.iana.org/assignments/cose/cose.xhtml). + * \param[in] key_select Which signing key to use. + * \param[in] cbor_encode_ctx The CBOR encoder context to output to. + * + * \return This returns one of the error codes defined by \ref t_cose_err_t. + * + * It is possible to use this to compute the exact size of the + * resulting token so the exact sized buffer can be allocated. To do + * this initialize the \c cbor_encode_ctx with \c UsefulBufC that has + * a \c NULL pointer and large length like \c UINT32_MAX. Then run the + * normal token creation. The result will have a NULL pointer and the + * length of the token that would have been created. When this is run + * like this, the cryptographic functions will not actually run, but + * the size of their output will be taken into account. + * + * The key selection depends on the platform / OS. + * + * Which signing algorithms are supported depends on the platform/OS. + * The header file t_cose_defines.h contains defined constants for + * some of them. A typical example is \ref COSE_ALGORITHM_ES256 which + * indicates ECDSA with the NIST P-256 curve and SHA-256. + * + * To use this, create a \c QCBOREncodeContext and initialize it with + * an output buffer big enough to hold the payload and the COSE Sign 1 + * overhead. This overhead is about 30 bytes plus the size of the + * signature and the size of the key ID. + * + * After the \c QCBOREncodeContext is initialized, call + * t_cose_sign1_init() on it. + * + * Next call \c QCBOREncode_BstrWrap() to indicate the start of the + * payload. + * + * Next call various \c QCBOREncode_Addxxxx() methods to create the + * payload. + * + * Next call \c QCBOREncode_CloseBstrWrap() to indicate the end of the + * payload. This will also return a pointer and length of the payload + * that gets hashed. + * + * Next call t_cose_sign1_finish() with the pointer and length of the + * payload. This will do all the cryptography and complete the COSE + * Sign1. + * + * Finally, call \c QCBOREncode_Finish() to get the pointer and length + * of the complete token. + * + * This implements a special signing test mode called _short_ + * _circuit_ _signing_. This mode is useful when there is no signing + * key available, perhaps because it has not been provisioned or + * configured for the particular device. It may also be because the + * public key cryptographic functions have not been connected up in + * the cryptographic adaptation layer. + * + * It has no value for security at all. Data signed this way should + * not be trusted as anyone can sign like this. + * + * In this mode the signature is the hash of that would normally be + * signed by the public key algorithm. To make the signature the + * correct size for the particular algorithm instances of the hash are + * concatenated to pad it out. + * + * This mode is very useful for testing because all the code except + * the actual signing algorithm is run exactly as it would if a proper + * signing algorithm was run. + * + * The kid (Key ID) put in the unprotected headers is created as + * follows. The EC public key is CBOR encoded as a \c COSE_Key as + * defined in the COSE standard. That encoded CBOR is then + * hashed with SHA-256. This is similar to key IDs defined in IETF + * PKIX, but is based on COSE and CBOR rather than ASN.1. + */ +enum t_cose_err_t t_cose_sign1_init(struct t_cose_sign1_ctx *me, + bool short_circuit_sign, + int32_t cose_algorithm_id, + int32_t key_select, + QCBOREncodeContext *cbor_encode_ctx); + + +/** + * \brief Finish creation of the \c COSE_Sign1. + * + * \param[in] me The t_cose signing context. + * \param[in] payload The pointer and length of the payload. + * + * \return This returns one of the error codes defined by \ref t_cose_err_t. + * + * Call this to complete creation of a signed token started with + * t_cose_sign1_init(). + * + * This is when the signature algorithm is run. + * + * The payload parameter is used only to compute the hash for + * signing. The completed \c COSE_Sign1 is retrieved from the \c + * cbor_encode_ctx by calling \c QCBOREncode_Finish() + */ +enum t_cose_err_t t_cose_sign1_finish(struct t_cose_sign1_ctx *me, + struct useful_buf_c payload); + + +#endif /* __T_COSE_SIGN1_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/src/t_cose_crypto.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/src/t_cose_crypto.h new file mode 100644 index 0000000..ab4faac --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/src/t_cose_crypto.h @@ -0,0 +1,413 @@ +/* + * t_cose_crypto.h + * + * Copyright 2019, Laurence Lundblade + * + * SPDX-License-Identifier: BSD-3-Clause + * + * See BSD-3-Clause license in README.mdE. + */ + + +#ifndef __T_COSE_CRYPTO_H__ +#define __T_COSE_CRYPTO_H__ + +#include "t_cose_common.h" +#include "useful_buf.h" +#include +#include "t_cose_defines.h" + + +/** + * \file t_cose_crypto.h + * + * \brief This is the adaptation layer for cryptographic functions used by + * t_cose. + * + * This is small wrapper around the cryptographic functions to: + * - Map COSE algorithm IDs to TF-M algorithm IDs + * - Map crypto errors to \ref t_cose_err_t errors + * - Have inputs and outputs be \c struct \c useful_buf_c and + * \c struct \c useful_buf + * - Handle key selection + * + * The idea is that implementations can be made of these functions + * that adapt to various cryptographic libraries that are used on + * various platforms and OSs. + * + * This runs entirely off of COSE-style algorithm identifiers. They + * are simple integers and thus work nice as function parameters. An + * initial set is defined by [COSE (RFC 8152)] + * (https://tools.ietf.org/html/rfc8152). New ones can be registered + * in the [IANA COSE Registry] + * (https://www.iana.org/assignments/cose/cose.xhtml). Local use new + * ones can also be defined (\c \#define) if what is needed is not in + * the IANA registry. + * + * Binary data is returned to the caller using a \c struct \c + * useful_buf to pass the buffer to receive the data and its length in + * and a \c useful_buf_c to return the pointer and length of the + * returned data. The point of this is coding hygiene. The buffer + * passed in is not const as it is to be modified. The \c + * useful_buf_c returned is const. + * + * The pointer in the \c useful_buf_c will always point to the buffer + * passed in via the \c useful_buf so the lifetime of the data is + * under control of the caller. + * + * This is not intended as any sort of general cryptographic API. It + * is just the functions needed by t_cose in the form that is most + * useful for t_cose. + */ + + +/** + * Size of the signature output for the NIST P-256 Curve. + */ +#define T_COSE_EC_P256_SIG_SIZE 64 + +/** + * Size of the largest signature of any of the algorithm types + * supported. + * + * This will have to be adjusted if support for other algorithms + * larger is added. + * + * This is a compile time constant so it can be used to define stack + * variable sizes. + */ +#define T_COSE_MAX_EC_SIG_SIZE T_COSE_EC_P256_SIG_SIZE + + +/** + * \brief Get the size in bytes of a particular signature type. + * + * \param[in] cose_sig_alg_id The COSE algorithm ID. + * + * \return The size in bytes of the signature for a public-key signing + * algorithm. + */ +static inline size_t t_cose_signature_size(int32_t cose_sig_alg_id); + + +/** + * \brief Perform public key signing. Part of the t_cose crypto + * adaptation layer. + * + * \param[in] cose_alg_id The algorithm to sign with. The IDs are + * defined in [COSE (RFC 8152)] + * (https://tools.ietf.org/html/rfc8152) or + * in the [IANA COSE Registry] + * (https://www.iana.org/assignments/cose/cose.xhtml). + * A proprietary ID can also be defined + * locally (\c \#define) if the needed + * one hasn't been registered. + * \param[in] key_select Indicates which key to use to sign. + * \param[in] hash_to_sign The bytes to sign. Typically, a hash of + * a payload. + * \param[in] signature_buffer Pointer and length of buffer into which + * the resulting signature is put. + * \param[in] signature Pointer and length of the signature + * returned. + * + * \retval T_COSE_SUCCESS + * Successfully created the signature. + * \retval T_COSE_ERR_SIG_BUFFER_SIZE + * The \c signature_buffer too small. + * \retval T_COSE_ERR_UNSUPPORTED_SIGNING_ALG + * The requested signing algorithm, \c cose_alg_id, is not + * supported. + * \retval T_COSE_ERR_UNKNOWN_KEY + * The key identified by \c key_select was not found. + * \retval T_COSE_ERR_WRONG_TYPE_OF_KEY + * The key was found, but it was the wrong type. + * \retval T_COSE_ERR_INVALID_ARGUMENT + * Some (unspecified) argument was not valid. + * \retval T_COSE_ERR_INSUFFICIENT_MEMORY + * Insufficient heap memory. + * \retval T_COSE_ERR_FAIL + * General unspecific failure. + * \retval T_COSE_ERR_TAMPERING_DETECTED + * Equivalent to \c PSA_ERROR_TAMPERING_DETECTED. + * + * This is called to do public key signing. The implementation will + * vary from one platform / OS to another but should conform to the + * description here. + * + * The key selection depends on the platform / OS. + * + * See the note in the Detailed Description (the \\file comment block) + * for details on how \c useful_buf and \c useful_buf_c are used to + * return the signature. + * + * To find out the size of the signature buffer needed, call this with + * \c signature_buffer->ptr \c NULL and \c signature_buffer->len a + * very large number like \c UINT32_MAX. The size will be returned in + * \c signature->len. + */ +enum t_cose_err_t +t_cose_crypto_pub_key_sign(int32_t cose_alg_id, + int32_t key_select, + struct useful_buf_c hash_to_sign, + struct useful_buf signature_buffer, + struct useful_buf_c *signature); + + +/** + * \brief perform public key signature verification. Part of the + * t_cose crypto adaptation layer. + * + * \param[in] cose_alg_id The algorithm to use for verification. + * The IDs are defined in [COSE (RFC 8152)] + * (https://tools.ietf.org/html/rfc8152) + * or in the [IANA COSE Registry] + * (https://www.iana.org/assignments/cose/cose.xhtml). + * A proprietary ID can also be defined + * locally (\c \#define) if the needed one + * hasn't been registered. + * \param[in] key_select Verification key selection. + * \param[in] key_id A key id or \c NULL_USEFUL_BUF_C. + * \param[in] hash_to_verify The data or hash that is to be verified. + * \param[in] signature The signature. + * + * This verifies that the \c signature passed in was over the \c + * hash_to_verify passed in. + * + * The public key used to verify the signature is selected by the \c + * key_id if it is not \c NULL_USEFUL_BUF_C or the \c key_select if it + * is. + * + * The key selected must be, or include, a public key of the correct + * type for \c cose_alg_id. + * + * \retval T_COSE_SUCCESS + * The signature is valid + * \retval T_COSE_ERR_SIG_VERIFY + * Signature verification failed. For example, the + * cryptographic operations completed successfully but hash + * wasn't as expected. + * \retval T_COSE_ERR_UNKNOWN_KEY + * The key identified by \c key_select or a \c kid was + * not found. + * \retval T_COSE_ERR_WRONG_TYPE_OF_KEY + * The key was found, but it was the wrong type + * for the operation. + * \retval T_COSE_ERR_UNSUPPORTED_SIGNING_ALG + * The requested signing algorithm is not supported. + * \retval T_COSE_ERR_INVALID_ARGUMENT + * Some (unspecified) argument was not valid. + * \retval T_COSE_ERR_INSUFFICIENT_MEMORY + * Out of heap memory. + * \retval T_COSE_ERR_FAIL + * General unspecific failure. + * \retval T_COSE_ERR_TAMPERING_DETECTED + * Equivalent to \c PSA_ERROR_TAMPERING_DETECTED. + */ +enum t_cose_err_t +t_cose_crypto_pub_key_verify(int32_t cose_alg_id, + int32_t key_select, + struct useful_buf_c key_id, + struct useful_buf_c hash_to_verify, + struct useful_buf_c signature); + + +/** + * The size of X and Y coordinate in 2 parameter style EC public + * key. Format is as defined in [COSE (RFC 8152)] + * (https://tools.ietf.org/html/rfc8152) and [SEC 1: Elliptic Curve + * Cryptography](http://www.secg.org/sec1-v2.pdf). + * + * This size is well-known and documented in public standards. + */ +#define T_COSE_CRYPTO_EC_P256_COORD_SIZE 32 + + +/** + * \brief Get an elliptic curve public key. Part of the t_cose crypto + * adaptation layer. + * + * \param[in] key_select Used to look up the public + * key to return when \c kid is + * \c NULL_USEFUL_BUF_C. + * \param[in] kid A key ID to look up against. May be + * \c NULL_USEFUL_BUF_C. This is typically + * the kid from the COSE unprotected header. + * \param[out] cose_curve_id The curve ID of the key returned as + * defined by [COSE (RFC 8152)] + * (https://tools.ietf.org/html/rfc8152) + * or the IANA COSE registry. + * \param[in] buf_to_hold_x_coord Pointer and length into which the + * X coordinate is put. + * \param[in] buf_to_hold_y_coord Pointer and length into which the + * Y coordinate is put. + * \param[out] x_coord Pointer and length of the returned X + * coordinate. + * \param[out] y_coord Pointer and length of the returned Y + * coordinate. + * + * \retval T_COSE_SUCCESS + * The key was found and is returned. + * \retval T_COSE_ERR_UNKNOWN_KEY + * The key identified by \c key_select or a \c kid was not + * found. + * \retval T_COSE_ERR_WRONG_TYPE_OF_KEY + * The key was found, but it was the wrong type for the + * operation. + * \retval T_COSE_ERR_FAIL + * General unspecific failure. + * \retval T_COSE_ERR_KEY_BUFFER_SIZE + * Buffer to hold the output was too small. + * + * This finds and returns a public key. Where it looks for the key is + * dependent on the OS / platform. + * + * \ref T_COSE_CRYPTO_EC_P256_COORD_SIZE is the size of the X or Y + * coordinate for the NIST P-256 curve. + * + * See the note in the Detailed Description (the \\file comment block) + * for details on how \c useful_buf and \c useful_buf_c are used to + * return the X and Y coordinates. + */ +enum t_cose_err_t +t_cose_crypto_get_ec_pub_key(int32_t key_select, + struct useful_buf_c kid, + int32_t *cose_curve_id, + struct useful_buf buf_to_hold_x_coord, + struct useful_buf buf_to_hold_y_coord, + struct useful_buf_c *x_coord, + struct useful_buf_c *y_coord); + + +/* + * No function to get private key because there is no need for it. + * The private signing key only needs to exist behind + * t_cose_crypto_pub_key_sign(). + */ + + + + +/** + * The context for use with the hash adaptation layer here. + */ +struct t_cose_crypto_hash { + /* Can't put the actual size here without creating dependecy on + * actual hash implementation, so this is a fairly large and + * accommodating size. + */ + uint8_t bytes[280]; +}; + + +/** + * The size of the output of SHA-256 in bytes. + * + * (It is safe to define this independently here as its size is + * well-known and fixed. There is no need to reference + * platform-specific headers and incur messy dependence.) + */ +#define T_COSE_CRYPTO_SHA256_SIZE 32 + + +/** + * \brief Start cryptographic hash. Part of the t_cose crypto + * adaptation layer. + * + * \param[in,out] hash_ctx Pointer to the hash context that + * will be initialized. + * \param[in] cose_hash_alg_id Algorithm ID that identifies the + * hash to use. This is from the + * [IANA COSE Registry] + * (https://www.iana.org/assignments/cose/cose.xhtml). + * As of the creation of this interface + * no identifiers of only a hash + * functions have been registered. + * Signature algorithms that include + * specification of the hash have been + * registered, but they are not to be + * used here. Until hash functions only + * have been officially registered, some + * IDs are defined in the proprietary + * space in t_cose_common.h. + * + * \retval T_COSE_ERR_UNSUPPORTED_HASH + * The requested algorithm is unknown or unsupported. + * + * \retval T_COSE_ERR_HASH_GENERAL_FAIL + * Some general failure of the hash function + * + * This initializes the hash context for the particular algorithm. It + * must be called first. A \c hash_ctx can be reused if it is + * reinitialized. + */ +enum t_cose_err_t +t_cose_crypto_hash_start(struct t_cose_crypto_hash *hash_ctx, + int32_t cose_hash_alg_id); + + +/** + * \brief Feed data into a cryptographic hash. Part of the t_cose + * crypto adaptation layer. + * + * \param[in,out] hash_ctx Pointer to the hash context in which + * accumulate the hash. + * \param[in] data_to_hash Pointer and length of data to feed into + * hash. The pointer may by \c NULL in which + * case no hashing is performed. + * + * There is no return value. If an error occurs it is remembered in \c + * hash_ctx and returned when t_cose_crypto_hash_finish() is called. + * Once in the error state, this function may be called, but it will + * not do anything. + */ +void t_cose_crypto_hash_update(struct t_cose_crypto_hash *hash_ctx, + struct useful_buf_c data_to_hash); + + +/** + * \brief Finish a cryptographic hash. Part of the t_cose crypto + * adaptation layer. + * + * \param[in,out] hash_ctx Pointer to the hash context. + * \param[in] buffer_to_hold_result Pointer and length into which + * the resulting hash is put. + * \param[out] hash_result Pointer and length of the + * resulting hash. + * + * \retval T_COSE_ERR_HASH_GENERAL_FAIL + * Some general failure of the hash function. + * \retval T_COSE_ERR_HASH_BUFFER_SIZE + * The size of the buffer to hold the hash result was + * too small. + * + * Call this to complete the hashing operation. If the everything + * completed correctly, the resulting hash is returned. Note that any + * errors that occurred during t_cose_crypto_hash_update() are + * returned here. + * + * See the note in the Detailed Description (the \\file comment block) + * for details on how \c useful_buf and \c useful_buf_c are used to + * return the hash. + */ +enum t_cose_err_t +t_cose_crypto_hash_finish(struct t_cose_crypto_hash *hash_ctx, + struct useful_buf buffer_to_hold_result, + struct useful_buf_c *hash_result); + + + +/* + * Public inline function. See documentation above. + */ +static inline size_t t_cose_signature_size(int32_t cose_sig_alg_id) +{ + switch(cose_sig_alg_id) { + case COSE_ALGORITHM_ES256: + return T_COSE_EC_P256_SIG_SIZE; + default: + return T_COSE_EC_P256_SIG_SIZE; + } +} + + +#endif /* __T_COSE_CRYPTO_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/src/t_cose_defines.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/src/t_cose_defines.h new file mode 100644 index 0000000..e2cc970 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/src/t_cose_defines.h @@ -0,0 +1,291 @@ +/* + * t_cose_defines.h + * + * Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * See BSD-3-Clause license in README.md + */ + +#ifndef __T_COSE_DEFINES_H__ +#define __T_COSE_DEFINES_H__ + +/** + * \file t_cose_defines.h + * + * \brief Constants from COSE standard and IANA registry. + * + * This file contains constants identifiers defined in [COSE (RFC + * 8152)] (https://tools.ietf.org/html/rfc8152) and [IANA COSE + * Registry] (https://www.iana.org/assignments/cose/cose.xhtml). They + * include algorithm IDs and other constants. + * + * Many constants in the IANA registry are not included here yet as + * they are not needed by t_cose. They can be added if they become + * needed. + */ + + + + +/* --------------- COSE Header parameters ----------- + * https://www.iana.org/assignments/cose/cose.xhtml#header-parameters + */ + +/** + * \def COSE_HEADER_PARAM_ALG + * + * \brief Label of COSE header that indicates an algorithm. + */ +#define COSE_HEADER_PARAM_ALG 1 + +/** + * \def COSE_HEADER_PARAM_KID + * + * \brief Label of COSE header that contains a key ID. + */ +#define COSE_HEADER_PARAM_KID 4 + + + + +/* ------------ COSE Header Algorithm Parameters -------------- + * https://www.iana.org/assignments/cose/cose.xhtml#header-algorithm-parameters + * + * None of these are defined here yet, as they are not needed by t_cose yet. + */ + + + + +/* ------------- COSE Algorithms ---------------------------- + * https://www.iana.org/assignments/cose/cose.xhtml#algorithms + */ + +/** + * \def COSE_ALGORITHM_ES256 + * + * \brief Indicates ECDSA with SHA-256. + * + * Value for \ref COSE_HEADER_PARAM_ALG to indicate ECDSA. w/SHA-256 + */ +#define COSE_ALGORITHM_ES256 -7 + +/** + * \def COSE_ALGORITHM_ES384 + * + * \brief Indicates ECDSA with SHA-384. + * + * Value for \ref COSE_HEADER_PARAM_ALG to indicate ECDSA. w/SHA-384 + */ +#define COSE_ALGORITHM_ES384 -35 + +/** + * \def COSE_ALGORITHM_ES512 + * + * \brief Indicates ECDSA with SHA-384. + * + * Value for \ref COSE_HEADER_PARAM_ALG to indicate ECDSA. w/SHA-512 + */ +#define COSE_ALGORITHM_ES512 -36 + + +/** + * \def COSE_ALG_SHA256_PROPRIETARY + * + * \brief COSE-style algorithm ID for SHA256. The official COSE + * algorithm registry doesn't yet define an ID for a pure hash + * function. One is needed for internal use, so this is defined. + * + * This is only used internally in the implementation and doesn't + * appear in any protocol messages so there are no interoperability + * issues. When this gets defined in the IANA registry, that value can + * be substituted here and all will work fine. + */ +#define COSE_ALG_SHA256_PROPRIETARY -72000 + + + + +/* ---------- COSE Key Common Parameters -------------- + * https://www.iana.org/assignments/cose/cose.xhtml#key-common-parameters + */ + +/** + * \def COSE_KEY_COMMON_KTY + * + * \brief Label for data item containing the key type. + * + * In a \c COSE_Key, label that indicates the data item containing the + * key type. + */ +#define COSE_KEY_COMMON_KTY 1 + +/** + * \def COSE_KEY_COMMON_KID + * + * \brief Label for data item containing the key's kid. + * + * In a \c COSE_Key, label that indicates the data item containing the + * kid of this key. + */ +#define COSE_KEY_COMMON_KID 2 + + + + +/* ---------- COSE Key Type Parameters -------------------- + * https://www.iana.org/assignments/cose/cose.xhtml#key-type-parameters + */ + +/** + * \def COSE_KEY_PARAM_CRV + * + * \brief Label for data item indicating EC curve. + * + * In a \c COSE_Key that holds an EC key of either type \ref + * COSE_KEY_TYPE_EC2 or \ref COSE_KEY_TYPE_OKP this labels the data + * item with the EC curve for the key. + */ +#define COSE_KEY_PARAM_CRV -1 + +/** + * \def COSE_KEY_PARAM_X_COORDINATE + * + * \brief Label for data item that is an X coordinate of an EC key. + * + * In a \c COSE_Key that holds an EC key, this is label that indicates + * the data item containing the X coordinate. + * + * This is used for both key types \ref COSE_KEY_TYPE_EC2 and \ref + * COSE_KEY_TYPE_OKP. + */ +#define COSE_KEY_PARAM_X_COORDINATE -2 + +/** + * \def COSE_KEY_PARAM_Y_COORDINATE + * + * \brief Label for data item that is a y coordinate of an EC key. + * + * In a COSE_Key that holds an EC key, this is label that indicates + * the data item containing the Y coordinate. + * + * This is used only for key type \ref COSE_KEY_TYPE_EC2. + */ +#define COSE_KEY_PARAM_Y_COORDINATE -3 + +/** + * \def COSE_KEY_PARAM_PRIVATE_D + * + * \brief Label for data item that is d, the private part of EC key. + * + * In a \c COSE_Key that holds an EC key, this is label that indicates + * the data item containing the Y coordinate. + * + * This is used for both key types \ref COSE_KEY_TYPE_EC2 and \ref + * COSE_KEY_TYPE_OKP. + */ +#define COSE_KEY_PARAM_PRIVATE_D -4 + + + + +/* ---------- COSE Key Types -------------------------------- + * https://www.iana.org/assignments/cose/cose.xhtml#key-type + */ + +/** + * \def COSE_KEY_TYPE_OKP + * + * \brief Key type is Octet Key Pair + * + * In a \c COSE_Key, this is a value of the data item labeled \ref + * COSE_KEY_COMMON_KTY that indicates the \c COSE_Key is some sort of + * key pair represented by some octets. It may or may not be an EC + * key. + */ +#define COSE_KEY_TYPE_OKP 1 + +/** + * \def COSE_KEY_TYPE_EC2 + * + * \brief Key is a 2-parameter EC key. + * + * In a \c COSE_Key, this is a value of the data item labeled \ref + * COSE_KEY_COMMON_KTY that indicates the \c COSE_Key is an EC key + * specified with two coordinates, X and Y. + */ +#define COSE_KEY_TYPE_EC2 2 + +/** + * \def COSE_KEY_TYPE_SYMMETRIC + * + * \brief Key is a symmetric key. + * + * In a \c COSE_Key, this is a value of the data item labeled \ref + * COSE_KEY_COMMON_KTY that indicates the \c COSE_Key is a symmetric + * key. + */ +#define COSE_KEY_TYPE_SYMMETRIC 4 + + + + +/* ----------- COSE Elliptic Curves --------------------- + * https://www.iana.org/assignments/cose/cose.xhtml#elliptic-curves + */ + +/** + * \def COSE_ELLIPTIC_CURVE_P_256 + * + * \brief Key type for NIST P-256 key + * + * In a \c COSE_Key, this is a value of the data item labeled \ref + * COSE_KEY_PARAM_CRV to indicate the NIST P-256 curve, also known as + * secp256r1. + * + * This key type is always \ref COSE_KEY_TYPE_EC2. + */ +#define COSE_ELLIPTIC_CURVE_P_256 1 + +/** + * \def COSE_ELLIPTIC_CURVE_P_384 + * + * \brief Key type for NIST P-384 key + * + * In a \c COSE_Key, this is a value of the data item labeled \ref + * COSE_KEY_PARAM_CRV to indicate the NIST P-384 curve, also known as + * secp384r1. + * + * This key type is always \ref COSE_KEY_TYPE_EC2. + */ +#define COSE_ELLIPTIC_CURVE_P_384 2 + +/** + * \def COSE_ELLIPTIC_CURVE_P_521 + * + * \brief Key type for NIST P-521 key + * + * In a \c COSE_Key, this is a value of the data item labeled \ref + * COSE_KEY_PARAM_CRV to indicate the NIST P-521 curve, also known as + * secp521r1. + */ +#define COSE_ELLIPTIC_CURVE_P_521 3 + + + + +/* ------- Constants from RFC 8152 --------- + */ + +/** + * \def COSE_SIG_CONTEXT_STRING_SIGNATURE1 + * + * \brief This is a string constant used by COSE to label \c COSE_Sign1 + * structures. See RFC 8152, section 4.4. + */ +#define COSE_SIG_CONTEXT_STRING_SIGNATURE1 "Signature1" + + +#endif /* __T_COSE_DEFINES_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/src/t_cose_sign1_sign.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/src/t_cose_sign1_sign.c new file mode 100644 index 0000000..8f55bc0 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/src/t_cose_sign1_sign.c @@ -0,0 +1,499 @@ +/* + * t_cose_sign1_sign.c + * + * Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * See BSD-3-Clause license in README.md + */ + +#include "t_cose_sign1_sign.h" +#include "qcbor.h" +#include "t_cose_defines.h" +#include "t_cose_crypto.h" +#include "t_cose_util.h" + + +/** + * \file t_cose_sign1_sign.c + * + * \brief This implements t_cose signing + */ + + +/** + * \brief Create a short-circuit signature + * + * \param[in] cose_alg_id Algorithm ID. This is used only to make + * the short-circuit signature the same size + * as the real signature would be for the + * particular algorithm. + * \param[in] hash_to_sign The bytes to sign. Typically, a hash of + * a payload. + * \param[in] signature_buffer Pointer and length of buffer into which + * the resulting signature is put. + * \param[in] signature Pointer and length of the signature + * returned. + * + * \return This returns one of the error codes defined by \ref t_cose_err_t. + * + * This creates the short-circuit signature that is a concatenation of + * hashes up to the expected size of the signature. This is a test + * mode only has it has no security value. This is retained in + * commercial production code as a useful test or demo that can run + * even if key material is not set up or accessible. + */ +static inline enum t_cose_err_t +short_circuit_sign(int32_t cose_alg_id, + struct useful_buf_c hash_to_sign, + struct useful_buf signature_buffer, + struct useful_buf_c *signature) +{ + /* approximate stack use on 32-bit machine: local use: 16 + */ + enum t_cose_err_t return_value; + size_t array_indx; + size_t amount_to_copy; + size_t sig_size; + + sig_size = t_cose_signature_size(cose_alg_id); + + if(sig_size > signature_buffer.len) { + /* Buffer too small for this signature type */ + return_value = T_COSE_ERR_SIG_BUFFER_SIZE; + goto Done; + } + + /* Loop concatening copies of the hash to fill out to signature size */ + for(array_indx = 0; array_indx < sig_size; array_indx += hash_to_sign.len) { + amount_to_copy = sig_size - array_indx; + if(amount_to_copy > hash_to_sign.len) { + amount_to_copy = hash_to_sign.len; + } + memcpy((uint8_t *)signature_buffer.ptr + array_indx, + hash_to_sign.ptr, + amount_to_copy); + } + signature->ptr = signature_buffer.ptr; + signature->len = sig_size; + return_value = T_COSE_SUCCESS; + +Done: + return return_value; +} + + + +/** + * The maximum size of a CBOR Encoded \c COSE_Key that this + * implementation can handle. \c COSE_Key is the serialization format + * for public and other types of keys defined by [COSE (RFC 8152)] + * (https://tools.ietf.org/html/rfc8152). + * + * This can be increased to handle larger keys, but stack usage will + * go up with this increase. + */ +#define MAX_ENCODED_COSE_KEY_SIZE \ + 1 + /* 1 byte to encode map */ \ + 2 + /* 2 bytes to encode key type */ \ + 2 + /* 2 bytes to encode curve */ \ + 2 * /* the X and Y coordinates at 32 bytes each */ \ + (T_COSE_CRYPTO_EC_P256_COORD_SIZE + 1 + 2) + + +/** + * \brief CBOR encode a public key as a \c COSE_Key + * + * \param[in] key_select Identifies the public key to encode. + * + * \param[in] buffer_for_cose_key Pointer and length of buffer into which + * the encoded \c COSE_Key is put. + * \param[in] cose_key Pointer and length of the encoded \c COSE_Key. + * + * \return This returns one of the error codes defined by \ref t_cose_err_t. + * + * \c COSE_Key is the COSE-defined format for serializing a key for + * transmission in a protocol. This function encodes an EC public key + * expressed as an X and Y coordinate. + */ +static enum t_cose_err_t +t_cose_encode_cose_key(int32_t key_select, + struct useful_buf buffer_for_cose_key, + struct useful_buf_c *cose_key) +{ + /* approximate stack use on 32-bit machine: + * local use: 328 + * with calls: 370 + */ + enum t_cose_err_t return_value; + QCBORError qcbor_result; + QCBOREncodeContext cbor_encode_ctx; + USEFUL_BUF_MAKE_STACK_UB( buffer_for_x_coord, + T_COSE_CRYPTO_EC_P256_COORD_SIZE); + USEFUL_BUF_MAKE_STACK_UB( buffer_for_y_coord, + T_COSE_CRYPTO_EC_P256_COORD_SIZE); + struct useful_buf_c x_coord; + struct useful_buf_c y_coord; + int32_t cose_curve_id; + struct useful_buf_c encoded_key_id; + + /* Get the public key x and y */ + return_value = t_cose_crypto_get_ec_pub_key(key_select, + NULL_USEFUL_BUF_C, + &cose_curve_id, + buffer_for_x_coord, + buffer_for_y_coord, + &x_coord, + &y_coord); + if(return_value != T_COSE_SUCCESS) { + goto Done; + } + + /* Encode it into a COSE_Key structure */ + QCBOREncode_Init(&cbor_encode_ctx, buffer_for_cose_key); + QCBOREncode_OpenMap(&cbor_encode_ctx); + QCBOREncode_AddInt64ToMapN(&cbor_encode_ctx, + COSE_KEY_COMMON_KTY, + COSE_KEY_TYPE_EC2); + QCBOREncode_AddInt64ToMapN(&cbor_encode_ctx, + COSE_KEY_PARAM_CRV, + cose_curve_id); + QCBOREncode_AddBytesToMapN(&cbor_encode_ctx, + COSE_KEY_PARAM_X_COORDINATE, + x_coord); + QCBOREncode_AddBytesToMapN(&cbor_encode_ctx, + COSE_KEY_PARAM_Y_COORDINATE, + y_coord); + QCBOREncode_CloseMap(&cbor_encode_ctx); + + qcbor_result = QCBOREncode_Finish(&cbor_encode_ctx, &encoded_key_id); + if(qcbor_result != QCBOR_SUCCESS) { + /* Mainly means that the COSE_Key was too big for buffer_for_cose_key */ + return_value = T_COSE_ERR_PROTECTED_HEADERS; + goto Done; + } + + /* Finish up and return */ + *cose_key = encoded_key_id; + return_value = T_COSE_SUCCESS; + +Done: + return return_value; +} + + +/** + * \brief SHA-256 hash a buffer in one quick function + * + * \param[in] bytes_to_hash The bytes to be hashed. + * + * \param[in] buffer_for_hash Pointer and length into which + * the resulting hash is put. + * \param[out] hash Pointer and length of the + * resulting hash. + * \return This returns one of the error codes defined by \ref t_cose_err_t. + * + * Simple wrapper for start, update and finish interface to a hash. + * + * Having this as a separate function helps keep stack usage down and + * is convenient. + */ +static enum t_cose_err_t quick_sha256(struct useful_buf_c bytes_to_hash, + struct useful_buf buffer_for_hash, + struct useful_buf_c *hash) +{ + /* approximate stack use on 32-bit machine: + local use: 132 + */ + enum t_cose_err_t return_value = 0; + struct t_cose_crypto_hash hash_ctx; + + return_value = t_cose_crypto_hash_start(&hash_ctx, + COSE_ALG_SHA256_PROPRIETARY); + if(return_value) { + goto Done; + } + t_cose_crypto_hash_update(&hash_ctx, bytes_to_hash); + return_value = t_cose_crypto_hash_finish(&hash_ctx, + buffer_for_hash, + hash); + +Done: + return return_value; +} + + +/** + * \brief Make a key ID based on the public key to go in the kid + * unprotected header. + * + * \param[in] key_select Identifies the public key. + * \param[in] buffer_for_key_id Pointer and length into which + * the resulting key ID is put. + * \param[out] key_id Pointer and length of the + * resulting key ID. + * + * \return This returns one of the error codes defined by \ref t_cose_err_t. + * + * + * See t_cose_sign1_init() for documentation of the key ID format + * created here. + */ +static inline enum t_cose_err_t get_keyid(int32_t key_select, + struct useful_buf buffer_for_key_id, + struct useful_buf_c *key_id) +{ + /* approximate stack use on 32-bit machine: + * local use: 100 + * with calls inlined: 560 + * with calls not inlined: 428 + */ + enum t_cose_err_t return_value; + USEFUL_BUF_MAKE_STACK_UB( buffer_for_cose_key, + MAX_ENCODED_COSE_KEY_SIZE); + struct useful_buf_c cose_key; + + /* Doing the COSE encoding and the hashing in separate functions + * called from here reduces the stack usage in this function by a + * lot + */ + + /* Get the key and encode it as a COSE_Key */ + return_value = t_cose_encode_cose_key(key_select, + buffer_for_cose_key, + &cose_key); + if(return_value != T_COSE_SUCCESS) { + goto Done; + } + + /* SHA256 hash of it is all we care about in the end */ + return_value = quick_sha256(cose_key, buffer_for_key_id, key_id); + +Done: + return return_value; +} + + +/** + * \brief Makes the protected headers for COSE. + * + * \param[in] cose_alg_id The COSE algorithm ID to put in the headers. + * + * \param[in] buffer_for_header Pointer and length into which + * the resulting encoded protected + * headers is put. + * + * \return The pointer and length of the protected headers is + * returned, or \c NULL_USEFUL_BUF_C if this fails. + * + * The protected headers are returned in fully encoded CBOR format as + * they are added to the \c COSE_Sign1 as a binary string. This is + * different from the unprotected headers which are not handled this + * way. + * + * This returns \c NULL_USEFUL_BUF_C if buffer_for_header was too + * small. See also definition of \ref T_COSE_SIGN1_MAX_PROT_HEADER + */ +static inline struct useful_buf_c +make_protected_header(int32_t cose_alg_id, + struct useful_buf buffer_for_header) +{ + /* approximate stack use on 32-bit machine: + * local use: 170 + * with calls: 210 + */ + struct useful_buf_c protected_headers; + QCBORError qcbor_result; + QCBOREncodeContext cbor_encode_ctx; + struct useful_buf_c return_value; + + QCBOREncode_Init(&cbor_encode_ctx, buffer_for_header); + QCBOREncode_OpenMap(&cbor_encode_ctx); + QCBOREncode_AddInt64ToMapN(&cbor_encode_ctx, + COSE_HEADER_PARAM_ALG, + cose_alg_id); + QCBOREncode_CloseMap(&cbor_encode_ctx); + qcbor_result = QCBOREncode_Finish(&cbor_encode_ctx, &protected_headers); + + if(qcbor_result == QCBOR_SUCCESS) { + return_value = protected_headers; + } else { + return_value = NULL_USEFUL_BUF_C; + } + + return return_value; +} + + +/** + * \brief Add the unprotected headers to a CBOR encoding context + * + * \param[in] cbor_encode_ctx CBOR encoding context to output to + * \param[in] kid The key ID to go into the kid header. + * + * No error is returned. If an error occurred it will be returned when + * \c QCBOR_Finish() is called on \c cbor_encode_ctx. + * + * The unprotected headers added by this are just the key ID + */ +static inline void add_unprotected_headers(QCBOREncodeContext *cbor_encode_ctx, + struct useful_buf_c kid) +{ + QCBOREncode_OpenMap(cbor_encode_ctx); + QCBOREncode_AddBytesToMapN(cbor_encode_ctx, COSE_HEADER_PARAM_KID, kid); + QCBOREncode_CloseMap(cbor_encode_ctx); +} + + +/* + * Public function. See t_cose_sign1_sign.h + */ +enum t_cose_err_t t_cose_sign1_init(struct t_cose_sign1_ctx *me, + bool short_circuit_sign, + int32_t cose_alg_id, + int32_t key_select, + QCBOREncodeContext *cbor_encode_ctx) +{ + /* approximate stack use on 32-bit machine: + * local use: 66 + * with calls inlined: 900 + * with calls not inlined: 500 + */ + + int32_t hash_alg; + enum t_cose_err_t return_value; + USEFUL_BUF_MAKE_STACK_UB( buffer_for_kid, T_COSE_CRYPTO_SHA256_SIZE); + struct useful_buf_c kid; + struct useful_buf buffer_for_protected_header; + + /* Check the cose_alg_id now by getting the hash alg as an early + error check even though it is not used until later. */ + hash_alg = hash_alg_id_from_sig_alg_id(cose_alg_id); + if(hash_alg == INT32_MAX) { + return T_COSE_ERR_UNSUPPORTED_SIGNING_ALG; + } + + /* Remember all the parameters in the context */ + me->cose_algorithm_id = cose_alg_id; + me->key_select = key_select; + me->short_circuit_sign = short_circuit_sign; + me->cbor_encode_ctx = cbor_encode_ctx; + + /* Get the key id because it goes into the headers that are about + to be made. */ + if(short_circuit_sign) { + return_value = get_short_circuit_kid(buffer_for_kid, &kid); + } else { + return_value = get_keyid(key_select, buffer_for_kid, &kid); + } + if(return_value) { + goto Done; + } + + /* Get started with the tagged array that holds the four parts of + a cose single signed message */ + QCBOREncode_AddTag(cbor_encode_ctx, CBOR_TAG_COSE_SIGN1); + QCBOREncode_OpenArray(cbor_encode_ctx); + + /* The protected headers, which are added as a wrapped bstr */ + buffer_for_protected_header = + USEFUL_BUF_FROM_BYTE_ARRAY(me->buffer_for_protected_headers); + me->protected_headers = make_protected_header(cose_alg_id, + buffer_for_protected_header); + if(useful_buf_c_is_null(me->protected_headers)) { + /* The sizing of storage for protected headers is + off (should never happen in tested, released code) */ + return_value = T_COSE_SUCCESS; + goto Done; + } + QCBOREncode_AddBytes(cbor_encode_ctx, me->protected_headers); + + /* The Unprotected headers */ + add_unprotected_headers(cbor_encode_ctx, kid); + + /* Any failures in CBOR encoding will be caught in finish + when the CBOR encoding is closed off. No need to track + here as the CBOR encoder tracks it internally. */ + + return_value = T_COSE_SUCCESS; + +Done: + return return_value; +} + + +/* + * Public function. See t_cose_sign1_sign.h + */ +enum t_cose_err_t t_cose_sign1_finish(struct t_cose_sign1_ctx *me, + struct useful_buf_c signed_payload) +{ + /* approximate stack use on 32-bit machine: + * local use: 116 + * with calls inline: 500 + * with calls not inlined; 450 + */ + enum t_cose_err_t return_value; + /* pointer and length of the completed tbs hash */ + struct useful_buf_c tbs_hash; + /* Pointer and length of the completed signature */ + struct useful_buf_c signature; + /* Buffer for the actual signature */ + USEFUL_BUF_MAKE_STACK_UB( buffer_for_signature, + T_COSE_MAX_EC_SIG_SIZE); + /* Buffer for the tbs hash. Only big enough for SHA256 */ + USEFUL_BUF_MAKE_STACK_UB( buffer_for_tbs_hash, + T_COSE_CRYPTO_SHA256_SIZE); + + /* Create the hash of the to-be-signed bytes. Inputs to the hash + * are the protected headers, the payload that getting signed, the + * cose signature alg from which the hash alg is determined. The + * cose_algorithm_id was checked in t_cose_sign1_init() so it + * doesn't need to be checked here. + */ + return_value = create_tbs_hash(me->cose_algorithm_id, + buffer_for_tbs_hash, + &tbs_hash, + me->protected_headers, + signed_payload); + if(return_value) { + goto Done; + } + + /* Compute the signature using public key crypto. The key selector + * and algorithm ID are passed in to know how and what to sign + * with. The hash of the TBS bytes are what is signed. A buffer in + * which to place the signature is passed in and the signature is + * returned. + * + * Short-circuit signing is invoked if requested. It does no + * public key operation and requires no key. It is just a test + * mode that always works. + */ + if(me->short_circuit_sign) { + return_value = short_circuit_sign(me->cose_algorithm_id, + tbs_hash, + buffer_for_signature, + &signature); + } else { + return_value = t_cose_crypto_pub_key_sign(me->cose_algorithm_id, + me->key_select, + tbs_hash, + buffer_for_signature, + &signature); + } + if(return_value) { + goto Done; + } + + /* Add signature to CBOR and close out the array */ + QCBOREncode_AddBytes(me->cbor_encode_ctx, signature); + QCBOREncode_CloseArray(me->cbor_encode_ctx); + + /* CBOR encoding errors are tracked in the CBOR encoding context + and handled in the layer above this */ + +Done: + return return_value; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/src/t_cose_util.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/src/t_cose_util.c new file mode 100644 index 0000000..ba4910e --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/src/t_cose_util.c @@ -0,0 +1,189 @@ +/* + * t_cose_util.c + * + * Copyright 2019, Laurence Lundblade + * + * SPDX-License-Identifier: BSD-3-Clause + * + * See BSD-3-Clause license in README.mdE. + */ + +#include "t_cose_util.h" +#include "qcbor.h" +#include "t_cose_defines.h" +#include "t_cose_common.h" +#include "t_cose_crypto.h" + + +/** + * \file t_cose_util.c + * + * \brief Implementation of t_cose utility functions. + * + */ + + +/* + * Public function. See t_cose_util.h + */ +int32_t hash_alg_id_from_sig_alg_id(int32_t cose_sig_alg_id) +{ + /* if other hashes, particularly those that output bigger hashes + * are added here, various other parts of this code have to be + * changed to have larger buffers. + */ + switch(cose_sig_alg_id) { + + case COSE_ALGORITHM_ES256: + return COSE_ALG_SHA256_PROPRIETARY; + + default: + return INT32_MAX; + } +} + + +/* + * Format of to-be-signed bytes used by create_tbs_hash(). + * This is defined in COSE (RFC 8152). It is the input + * to the hash. + * + * Sig_structure = [ + * context : "Signature" / "Signature1" / "CounterSignature", + * body_protected : empty_or_serialized_map, + * ? sign_protected : empty_or_serialized_map, + * external_aad : bstr, + * payload : bstr + * ] + */ + + +/** + * This is the size of the first part of the CBOR encoded TBS + * bytes. It is around 20 bytes. See create_tbs_hash(). + */ +#define T_COSE_SIZE_OF_TBS \ + 1 + /* For opening the array */ \ + sizeof(COSE_SIG_CONTEXT_STRING_SIGNATURE1) + /* "Signature1" */ \ + 2 + /* Overhead for encoding string */ \ + T_COSE_SIGN1_MAX_PROT_HEADER + /* entire protected headers */ \ + 3 * ( /* 3 NULL bstrs for fields not used */ \ + 1 /* size of a NULL bstr */ \ + ) + + +/* + * Public function. See t_cose_util.h + */ +enum t_cose_err_t create_tbs_hash(int32_t cose_alg_id, + struct useful_buf buffer_for_hash, + struct useful_buf_c *hash, + struct useful_buf_c protected_headers, + struct useful_buf_c payload) +{ + /* approximate stack use on 32-bit machine: + * local use: 320 + * with calls: 360 + */ + enum t_cose_err_t return_value; + QCBOREncodeContext cbor_encode_ctx; + UsefulBuf_MAKE_STACK_UB( buffer_for_TBS_first_part, T_COSE_SIZE_OF_TBS); + struct useful_buf_c tbs_first_part; + QCBORError qcbor_result; + struct t_cose_crypto_hash hash_ctx; + int32_t hash_alg_id; + + /* This builds the CBOR-format to-be-signed bytes */ + QCBOREncode_Init(&cbor_encode_ctx, buffer_for_TBS_first_part); + QCBOREncode_OpenArray(&cbor_encode_ctx); + /* context */ + QCBOREncode_AddSZString(&cbor_encode_ctx, + COSE_SIG_CONTEXT_STRING_SIGNATURE1); + /* body_protected */ + QCBOREncode_AddBytes(&cbor_encode_ctx, + protected_headers); + /* sign_protected */ + QCBOREncode_AddBytes(&cbor_encode_ctx, NULL_USEFUL_BUF_C); + /* external_aad */ + QCBOREncode_AddBytes(&cbor_encode_ctx, NULL_USEFUL_BUF_C); + /* fake payload */ + QCBOREncode_AddBytes(&cbor_encode_ctx, NULL_USEFUL_BUF_C); + QCBOREncode_CloseArray(&cbor_encode_ctx); + + /* get the result and convert it to struct useful_buf_c representation */ + qcbor_result = QCBOREncode_Finish(&cbor_encode_ctx, &tbs_first_part); + if(qcbor_result) { + /* Mainly means that the protected_headers were too big + (which should never happen) */ + return_value = T_COSE_ERR_SIG_STRUCT; + goto Done; + } + + /* Start the hashing */ + hash_alg_id = hash_alg_id_from_sig_alg_id(cose_alg_id); + /* Don't check hash_alg_id for failure. t_cose_crypto_hash_start() + will handle it properly + */ + return_value = t_cose_crypto_hash_start(&hash_ctx, hash_alg_id); + if(return_value) { + goto Done; + } + + /* Hash the first part of the TBS. Take all but the last two + * bytes. The last two bytes are the fake payload from above. It + * is replaced by the real payload which is hashed next. The fake + * payload is needed so the array count is right. This is one of + * the main things that make it possible to implement with one + * buffer for the whole cose sign1. + */ + t_cose_crypto_hash_update(&hash_ctx, + useful_buf_head(tbs_first_part, + tbs_first_part.len - 2)); + + /* Hash the payload */ + t_cose_crypto_hash_update(&hash_ctx, payload); + + /* Finish the hash and set up to return it */ + return_value = t_cose_crypto_hash_finish(&hash_ctx, + buffer_for_hash, + hash); + +Done: + return return_value; +} + + +/* + * Public function. See t_cose_util.h + */ +enum t_cose_err_t +get_short_circuit_kid(struct useful_buf buffer_for_kid, + struct useful_buf_c *kid) +{ + /* This is a random hard coded key ID that is used to indicate + * short-circuit signing. It is OK to hard code this as the + * probability of collision with this ID is very low and the same + * as for collision between any two key IDs of any sort. + */ + uint8_t defined_short_circuit_kid[] = { + 0xef, 0x95, 0x4b, 0x4b, 0xd9, 0xbd, 0xf6, 0x70, + 0xd0, 0x33, 0x60, 0x82, 0xf5, 0xef, 0x15, 0x2a, + 0xf8, 0xf3, 0x5b, 0x6a, 0x6c, 0x00, 0xef, 0xa6, + 0xa9, 0xa7, 0x1f, 0x49, 0x51, 0x7e, 0x18, 0xc6}; + + /* Prevent a dumb error where the size constant in the header is + * wrong.This check will be evaluated at compile time and optimize + * out when all is correct. + */ + if(sizeof(defined_short_circuit_kid) != T_COSE_SHORT_CIRCUIT_KID_SIZE) { + return T_COSE_ERR_BAD_SHORT_CIRCUIT_KID; + } + + *kid = useful_buf_copy(buffer_for_kid, + USEFUL_BUF_FROM_BYTE_ARRAY_LITERAL( + defined_short_circuit_kid)); + + return useful_buf_c_is_null(*kid) ? + T_COSE_ERR_KEY_BUFFER_SIZE : + T_COSE_SUCCESS; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/src/t_cose_util.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/src/t_cose_util.h new file mode 100644 index 0000000..7b39dc3 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/t_cose/src/t_cose_util.h @@ -0,0 +1,126 @@ +/* + * t_cose_util.h + * + * Copyright 2019, Laurence Lundblade + * + * SPDX-License-Identifier: BSD-3-Clause + * + * See BSD-3-Clause license in README.mdE. + */ + + +#ifndef __T_COSE_UTIL_H__ +#define __T_COSE_UTIL_H__ + +#include +#include "useful_buf.h" +#include "t_cose_common.h" + +/** + * \file t_cose_util.h + * + * \brief Utility functions used internally by the t_cose implementation. + * + */ + + +/** + * \brief Return hash algorithm ID from a signature algorithm ID + * + * \param[in] cose_sig_alg_id A COSE signature algorithm identifier. + * + * \return \c INT32_MAX when the signature algorithm ID is not known. + * + * This works off of algorithm identifiers defined in the [IANA COSE + * Registry] (https://www.iana.org/assignments/cose/cose.xhtml). + * Corresponding local integer constants are defined in + * t_cose_defines.h. + * + * COSE signing algorithms are the combination of public key + * algorithm, curve, key size, hash algorithm and hash size. They are + * simple integers making them convenient for direct use in code. + * + * This function returns an identifier for only the hash algorithm + * from the combined identifier. + * + * If the needed algorithm identifiers are not in the IANA registry, + * they can be added to it. This will take some time and work. It is + * also fine to use algorithms in the proprietary space. + */ +int32_t hash_alg_id_from_sig_alg_id(int32_t cose_sig_alg_id); + + +/** + * \brief Create the hash of the to-be-signed (TBS) bytes for COSE. + * + * \param[in] cose_alg_id The COSE signing algorithm ID. Used to + * determine which hash function to use. + * \param[in] buffer_for_hash Pointer and length of buffer into which + * the resulting hash is put. + * \param[out] hash Pointer and length of the + * resulting hash. + * \param[in] protected_headers The CBOR encoded protected headers. + * \param[in] payload The CBOR encoded payload + * + * \return This returns one of the error codes defined by \ref t_cose_err_t. + * + * \retval T_COSE_ERR_SIG_STRUCT + * Most likely this is because the protected_headers passed in + * is larger than \ref T_COSE_SIGN1_MAX_PROT_HEADER. + * \retval T_COSE_ERR_UNSUPPORTED_HASH + * If the hash algorithm is not known. + * \retval T_COSE_ERR_HASH_GENERAL_FAIL + * In case of some general hash failure. + * + * The input to the public key signature algorithm in COSE is the hash + * of a CBOR encoded structure containing the protected headers + * algorithm ID and a few other things. This formats that structure + * and computes the hash of it. These are known as the to-be-signed or + * "TBS" bytes. + */ +enum t_cose_err_t create_tbs_hash(int32_t cose_alg_id, + struct useful_buf buffer_for_hash, + struct useful_buf_c *hash, + struct useful_buf_c protected_headers, + struct useful_buf_c payload); + + +/** + * Size of the key returned by get_short_circuit_kid(). It is always + * this size. + */ +#define T_COSE_SHORT_CIRCUIT_KID_SIZE 32 + + +/** + * \brief Get the special kid for short-circuit signing. + * + * \param[in] buffer_for_kid Pointer and length of buffer into which + * the resulting hash is put. It should + * always be at least \ref + * T_COSE_SHORT_CIRCUIT_KID_SIZE. + * \param[out] kid Pointer and length of the returned kid. + * + * \retval T_COSE_SUCCESS + * The kid was returned. + * \retval T_COSE_ERR_KEY_BUFFER_SIZE + * \c buffer_for_kid is too small + * + * This always returns the same key ID. It always indicates + * short-circuit signing. It is OK to hard code this as the + * probability of collision with this ID is extremely low and the same + * as for collision between any two key IDs (kids) of any sort. + * + * This is the value of the kid. + * + * 0xef, 0x95, 0x4b, 0x4b, 0xd9, 0xbd, 0xf6, 0x70, + * 0xd0, 0x33, 0x60, 0x82, 0xf5, 0xef, 0x15, 0x2a, + * 0xf8, 0xf3, 0x5b, 0x6a, 0x6c, 0x00, 0xef, 0xa6, + * 0xa9, 0xa7, 0x1f, 0x49, 0x51, 0x7e, 0x18, 0xc6 + * + */ +enum t_cose_err_t +get_short_circuit_kid(struct useful_buf buffer_for_kid, + struct useful_buf_c *kid); + +#endif /* __T_COSE_UTIL_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_attest_hal.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_attest_hal.h new file mode 100755 index 0000000..b43b109 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_attest_hal.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __TFM_ATTEST_HAL_H__ +#define __TFM_ATTEST_HAL_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Security lifecycle of the device + */ +enum tfm_security_lifecycle_t { + TFM_SLC_UNKNOWN = 0x0000u, + TFM_SLC_ASSEMBLY_AND_TEST = 0x1000u, + TFM_SLC_PSA_ROT_PROVISIONING = 0x2000u, + TFM_SLC_SECURED = 0x3000u, + TFM_SLC_NON_PSA_ROT_DEBUG = 0x4000u, + TFM_SLC_RECOVERABLE_PSA_ROT_DEBUG = 0x5000u, + TFM_SLC_DECOMMISSIONED = 0x6000u, +}; + +/** + * \brief Retrieve the security lifecycle of the device + * + * Security lifecycle is a mandatory claim in the initial attestation token. + * + * \return According to \ref tfm_security_lifecycle_t + */ +enum tfm_security_lifecycle_t tfm_attest_hal_get_security_lifecycle(void); + +/** + * \brief Retrieve the verification service indicator for initial attestation. + * + * It is used by relying party to locate a validation service for the token. + * It can be a text string that can be used to locate the service or can be a + * URL specifying the address of the service. + * + * \param[out] size Length of the string, without the termination zero byte. + * + * \return NULL pointer if not available otherwise the address of the + * verification service string in the device memory. + */ +const char * +tfm_attest_hal_get_verification_service(uint32_t *size); + +/** + * \brief Retrieve the name of the profile definition document for initial + * attestation. + * + * This document describes the 'profile' of the initial attestation token, + * being a full description of the claims, their usage, verification and + * token signing. + * + * \param[out] size Length of the document name, without the termination zero + * byte. + * + * \return NULL pointer if not available otherwise the address of the document + * name string in the device memory. + */ +const char * +tfm_attest_hal_get_profile_definition(uint32_t *size); + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_ATTEST_HAL_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_boot_status.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_boot_status.h new file mode 100755 index 0000000..dbcc6ce --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_boot_status.h @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2018-2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __TFM_BOOT_STATUS_H__ +#define __TFM_BOOT_STATUS_H__ + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Major numbers (4 bit) to identify + * the consumer of shared data in runtime SW + */ +#define TLV_MAJOR_CORE 0x0 +#define TLV_MAJOR_IAS 0x1 + +/** + * The shared data between boot loader and runtime SW is TLV encoded. The + * shared data is stored in a well known location in secure memory and this is + * a contract between boot loader and runtime SW. + * + * The structure of shared data must be the following: + * - At the beginning there must be a header: struct shared_data_tlv_header + * This contains a magic number and a size field which covers the entire + * size of the shared data area including this header. + * - After the header there come the entries which are composed from an entry + * header structure: struct shared_data_tlv_entry and the data. In the entry + * header is a type field (tly_type) which identify the consumer of the + * entry in the runtime SW and specify the subtype of that data item. There + * is a size field (tlv_len) which covers the size of the entry header and + * the data. After this structure comes the actual data. + * - Arbitrary number and size of data entry can be in the shared memory area. + * + * This table gives of overview about the tlv_type field in the entry header. + * The tlv_type always composed from a major and minor number. Major number + * identifies the addressee in runtime SW, who should process the data entry. + * Minor number used to encode more info about the data entry. The actual + * definition of minor number could change per major number. In case of boot + * status data, which is going to be processed by initial attestation service + * the minor number is split further to two part: sw_module and claim. The + * sw_module identifies the SW component in the system which the data item + * belongs to and the claim part identifies the exact type of the data. + * + * |---------------------------------------| + * | tlv_type (16) | + * |---------------------------------------| + * | tlv_major(4)| tlv_minor(12) | + * |---------------------------------------| + * | MAJOR_IAS | sw_module(6) | claim(6) | + * |---------------------------------------| + * | MAJOR_CORE | TBD | + * |---------------------------------------| + */ + +/* Initial attestation: SW components / SW modules + * This list is intended to be adjusted per device. It contains more SW + * components than currently available in TF-M project. It serves as an example, + * what kind of SW components might be available. + */ +#define SW_GENERAL 0x00 +#define SW_BL2 0x01 +#define SW_PROT 0x02 +#define SW_AROT 0x03 +#define SW_SPE 0x04 +#define SW_NSPE 0x05 +#define SW_S_NS 0x06 +#define SW_MAX 0x07 + +/* Initial attestation: Claim per SW components / SW modules */ +/* Bits: 0-2 */ +#define SW_VERSION 0x00 +#define SW_SIGNER_ID 0x01 +#define SW_EPOCH 0x02 +#define SW_TYPE 0x03 +/* Bits: 3-5 */ +#define SW_MEASURE_VALUE 0x08 +#define SW_MEASURE_TYPE 0x09 + +/* Initial attestation: General claim does not belong any particular SW + * component. But they might be part of the boot status. + */ +#define BOOT_SEED 0x00 +#define HW_VERSION 0x01 +#define SECURITY_LIFECYCLE 0x02 + +/* Minor numbers (12 bit) to identify attestation service related data */ +#define TLV_MINOR_IAS_BOOT_SEED ((SW_GENERAL << 6) | BOOT_SEED) +#define TLV_MINOR_IAS_HW_VERSION ((SW_GENERAL << 6) | HW_VERSION) +#define TLV_MINOR_IAS_SLC ((SW_GENERAL << 6) | SECURITY_LIFECYCLE) + +/* Bootloader - It can be more stage */ +#define TLV_MINOR_IAS_BL2_MEASURE_VALUE ((SW_BL2 << 6) | SW_MEASURE_VALUE) +#define TLV_MINOR_IAS_BL2_MEASURE_TYPE ((SW_BL2 << 6) | SW_MEASURE_TYPE) +#define TLV_MINOR_IAS_BL2_VERSION ((SW_BL2 << 6) | SW_VERSION) +#define TLV_MINOR_IAS_BL2_SIGNER_ID ((SW_BL2 << 6) | SW_SIGNER_ID) +#define TLV_MINOR_IAS_BL2_EPOCH ((SW_BL2 << 6) | SW_EPOCH) +#define TLV_MINOR_IAS_BL2_TYPE ((SW_BL2 << 6) | SW_TYPE) + +/* PROT: PSA Root of Trust */ +#define TLV_MINOR_IAS_PROT_MEASURE_VALUE ((SW_PROT << 6) | SW_MEASURE_VALUE) +#define TLV_MINOR_IAS_PROT_MEASURE_TYPE ((SW_PROT << 6) | SW_MEASURE_TYPE) +#define TLV_MINOR_IAS_PROT_VERSION ((SW_PROT << 6) | SW_VERSION) +#define TLV_MINOR_IAS_PROT_SIGNER_ID ((SW_PROT << 6) | SW_SIGNER_ID) +#define TLV_MINOR_IAS_PROT_EPOCH ((SW_PROT << 6) | SW_EPOCH) +#define TLV_MINOR_IAS_PROT_TYPE ((SW_PROT << 6) | SW_TYPE) + +/* AROT: Application Root of Trust */ +#define TLV_MINOR_IAS_AROT_MEASURE_VALUE ((SW_AROT << 6) | SW_MEASURE_VALUE) +#define TLV_MINOR_IAS_AROT_MEASURE_TYPE ((SW_AROT << 6) | SW_MEASURE_TYPE) +#define TLV_MINOR_IAS_AROT_VERSION ((SW_AROT << 6) | SW_VERSION) +#define TLV_MINOR_IAS_AROT_SIGNER_ID ((SW_AROT << 6) | SW_SIGNER_ID) +#define TLV_MINOR_IAS_AROT_EPOCH ((SW_AROT << 6) | SW_EPOCH) +#define TLV_MINOR_IAS_AROT_TYPE ((SW_AROT << 6) | SW_TYPE) + +/* Non-secure processing environment - single non-secure image */ +#define TLV_MINOR_IAS_NSPE_MEASURE_VALUE ((SW_NSPE << 6) | SW_MEASURE_VALUE) +#define TLV_MINOR_IAS_NSPE_MEASURE_TYPE ((SW_NSPE << 6) | SW_MEASURE_TYPE) +#define TLV_MINOR_IAS_NSPE_VERSION ((SW_NSPE << 6) | SW_VERSION) +#define TLV_MINOR_IAS_NSPE_SIGNER_ID ((SW_NSPE << 6) | SW_SIGNER_ID) +#define TLV_MINOR_IAS_NSPE_EPOCH ((SW_NSPE << 6) | SW_EPOCH) +#define TLV_MINOR_IAS_NSPE_TYPE ((SW_NSPE << 6) | SW_TYPE) + +/* Secure processing environment (ARoT + PRoT) - single secure image */ +#define TLV_MINOR_IAS_SPE_MEASURE_VALUE ((SW_SPE << 6) | SW_MEASURE_VALUE) +#define TLV_MINOR_IAS_SPE_MEASURE_TYPE ((SW_SPE << 6) | SW_MEASURE_TYPE) +#define TLV_MINOR_IAS_SPE_VERSION ((SW_SPE << 6) | SW_VERSION) +#define TLV_MINOR_IAS_SPE_SIGNER_ID ((SW_SPE << 6) | SW_SIGNER_ID) +#define TLV_MINOR_IAS_SPE_EPOCH ((SW_SPE << 6) | SW_EPOCH) +#define TLV_MINOR_IAS_SPE_TYPE ((SW_SPE << 6) | SW_TYPE) + +/* SPE + NSPE - combined secure and non-secure image */ +#define TLV_MINOR_IAS_S_NS_MEASURE_VALUE ((SW_S_NS << 6) | SW_MEASURE_VALUE) +#define TLV_MINOR_IAS_S_NS_MEASURE_TYPE ((SW_S_NS << 6) | SW_MEASURE_TYPE) +#define TLV_MINOR_IAS_S_NS_VERSION ((SW_S_NS << 6) | SW_VERSION) +#define TLV_MINOR_IAS_S_NS_SIGNER_ID ((SW_S_NS << 6) | SW_SIGNER_ID) +#define TLV_MINOR_IAS_S_NS_EPOCH ((SW_S_NS << 6) | SW_EPOCH) +#define TLV_MINOR_IAS_S_NS_TYPE ((SW_S_NS << 6) | SW_TYPE) + +/* General macros to handle TLV type */ +#define MAJOR_MASK 0xF /* 4 bit */ +#define MAJOR_POS 12 /* 12 bit */ +#define MINOR_MASK 0xFFF /* 12 bit */ + +#define SET_TLV_TYPE(major, minor) \ + ((((major) & MAJOR_MASK) << MAJOR_POS) | ((minor) & MINOR_MASK)) +#define GET_MAJOR(tlv_type) ((tlv_type) >> MAJOR_POS) +#define GET_MINOR(tlv_type) ((tlv_type) & MINOR_MASK) + +/* Initial attestation specific macros */ +#define MODULE_POS 6 /* 6 bit */ +#define CLAIM_MASK 0x3F /* 6 bit */ +#define MEASUREMENT_CLAIM_POS 3 /* 3 bit */ + +#define GET_IAS_MODULE(tlv_type) (GET_MINOR(tlv_type) >> MODULE_POS) +#define GET_IAS_CLAIM(tlv_type) (GET_MINOR(tlv_type) & CLAIM_MASK) +#define SET_IAS_MINOR(sw_module, claim) (((sw_module) << 6) | (claim)) + +#define GET_IAS_MEASUREMENT_CLAIM(ias_claim) ((ias_claim) >> \ + MEASUREMENT_CLAIM_POS) + +/* Magic value which marks the beginning of shared data area in memory */ +#define SHARED_DATA_TLV_INFO_MAGIC 0x2016 + +/** + * Shared data TLV header. All fields in little endian. + * + * ----------------------------------- + * | tlv_magic(16) | tlv_tot_len(16) | + * ----------------------------------- + */ +struct shared_data_tlv_header { + uint16_t tlv_magic; + uint16_t tlv_tot_len; /* size of whole TLV area (including this header) */ +}; + +#define SHARED_DATA_HEADER_SIZE sizeof(struct shared_data_tlv_header) + +/** + * Shared data TLV entry header format. All fields in little endian. + * + * ------------------------------- + * | tlv_type(16) | tlv_len(16) | + * ------------------------------- + * | Raw data | + * ------------------------------- + */ +struct shared_data_tlv_entry { + uint16_t tlv_type; + uint16_t tlv_len; /* size of single TLV entry (including this header). */ +}; + +#define SHARED_DATA_ENTRY_HEADER_SIZE sizeof(struct shared_data_tlv_entry) +#define SHARED_DATA_ENTRY_SIZE(size) (size + SHARED_DATA_ENTRY_HEADER_SIZE) + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_BOOT_STATUS_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_plat_boot_seed.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_plat_boot_seed.h new file mode 100755 index 0000000..11b79f0 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_plat_boot_seed.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __TFM_PLAT_BOOT_SEED_H__ +#define __TFM_PLAT_BOOT_SEED_H__ +/** + * \file tfm_plat_boot_seed.h + * + * Boot seed is used by a validating entity to ensure multiple reports were + * generated in the same boot session. Boot seed is a random number, generated + * only once during a boot cycle and its value is constant in the same cycle. + * Size recommendation is 256-bit to meet the statistically improbable property. + * Boot seed can be generated by secure boot loader an included to the measured + * boot state or can be generated by PRoT SW. + */ + +/** + * \note The interfaces defined in this file must be implemented for each + * SoC. + */ + +#include +#include "tfm_plat_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \def BOOT_SEED_SIZE + * + * \brief Size of boot seed in bytes. + */ +#define BOOT_SEED_SIZE (32u) + +/** + * \brief Gets the boot seed, which is a constant random number during a boot + * cycle. + * + * \param[in] size The required size of boot seed in bytes + * \param[out] buf Pointer to the buffer to store boot seed + * + * \return TFM_PLAT_ERR_SUCCESS if the value is generated correctly. Otherwise, + * it returns TFM_PLAT_ERR_SYSTEM_ERR. + */ +enum tfm_plat_err_t tfm_plat_get_boot_seed(uint32_t size, uint8_t *buf); + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_PLAT_BOOT_SEED_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_plat_crypto_keys.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_plat_crypto_keys.h new file mode 100755 index 0000000..386d61f --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_plat_crypto_keys.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2017-2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __TFM_PLAT_CRYPTO_KEYS_H__ +#define __TFM_PLAT_CRYPTO_KEYS_H__ +/** + * \note The interfaces defined in this file must be implemented for each + * SoC. + */ + +#include +#include "tfm_plat_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Elliptic curve key type identifiers according to RFC8152 (COSE encoding) + * https://www.iana.org/assignments/cose/cose.xhtml#elliptic-curves + */ +enum ecc_curve_t { + P_256 = 1, /* NIST P-256 also known as secp256r1 */ + P_384 = 2, /* NIST P-384 also known as secp384r1 */ + P_521 = 3, /* NIST P-521 also known as secp521r1 */ + X25519 = 4, /* X25519 for use with ECDH only */ + X448 = 5, /* X448 for use with ECDH only */ + ED25519 = 6, /* Ed25519 for use with EdDSA only */ + ED448 = 7, /* Ed448 for use with EdDSA only */ +}; + +/** + * Structure definition to carry pointer and size information about an Elliptic + * curve key which is stored in a buffer(key_buf) in raw format (without + * encoding): + * - priv_key Base address of the private key in key_buf. It must be + * present on the device. + * - priv_key_size Size of the private key in bytes. + * - pubx_key Base address of x-coordinate of the public key in key_buf. + * It can be empty, because it can be recomputed based on + * private key. + * - pubx_key_size Length of x-coordinate of the public key in key_buf. + * It can be empty, because it can be recomputed based on + * private key. + * - puby_key Base address of y-coordinate of the public key in key_buf. + * It can be empty, because either it can be recomputed based + * on private key or some curve type works without it. + * - puby_key_size Length of y-coordinate of the public key in key_buf. + */ +struct ecc_key_t { + uint8_t *priv_key; + uint32_t priv_key_size; + uint8_t *pubx_key; + uint32_t pubx_key_size; + uint8_t *puby_key; + uint32_t puby_key_size; +}; + +#define ECC_P_256_KEY_SIZE (96u) /* 3 x 32 = 96 bytes priv + pub-x + pub-y */ + +/** + * \brief Gets hardware unique key for encryption + * + * \param[out] key Buf to store the key in + * \param[in] size Size of the buffer + * + * \return Returns error code specified in \ref tfm_plat_err_t + */ +enum tfm_plat_err_t tfm_plat_get_crypto_huk(uint8_t *key, uint32_t size); + +/** + * \brief Get the initial attestation key + * + * The device MUST contain an initial attestation key, which is used to sign the + * token. Initial attestation service supports elliptic curve signing + * algorithms. Device maker can decide whether store only the private key on the + * device or store both (public and private) key. Public key can be recomputed + * based on private key. Keys must be provided in raw format, just binary data + * without any encoding (DER, COSE). Caller provides a buffer to copy all the + * available key components to there. Key components must be copied after + * each other to the buffer. The base address and the length of each key + * component must be indicating in the corresponding field of ecc_key + * (\ref struct ecc_key_t). + * Curve_type indicates to which curve belongs the key. + * + * + * Keys must be provided in + * + * \param[in/out] key_buf Buffer to store the initial attestation key. + * \param[in] size Size of the buffer. + * \param[out] ecc_key A structure to carry pointer and size information + * about the initial attestation key, which is + * stored in key_buf. + * \param[out] curve_type The type of the EC curve, which the key belongs + * to according to \ref ecc_curve_t + * + * \return Returns error code specified in \ref tfm_plat_err_t + */ +enum tfm_plat_err_t +tfm_plat_get_initial_attest_key(uint8_t *key_buf, + uint32_t size, + struct ecc_key_t *ecc_key, + enum ecc_curve_t *curve_type); + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_PLAT_CRYPTO_KEYS_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_plat_defs.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_plat_defs.h new file mode 100755 index 0000000..66747ee --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_plat_defs.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017-2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __TFM_PLAT_DEFS_H__ +#define __TFM_PLAT_DEFS_H__ +/** + * \note The interfaces defined in this file must be implemented for each + * target. + */ + +#include +#include + +enum tfm_plat_err_t { + TFM_PLAT_ERR_SUCCESS = 0, + TFM_PLAT_ERR_SYSTEM_ERR, + TFM_PLAT_ERR_MAX_VALUE, + /* Following entry is only to ensure the error code of int size */ + TFM_PLAT_ERR_FORCE_INT_SIZE = INT_MAX +}; + +/*! + * \def TFM_LINK_SET_OBJECT_IN_PARTITION_SECTION(TFM_PARTITION_NAME) + * + * \brief This macro provides a mechanism to place a function code in a specific + * secure partition at linker time in TF-M Level 3. + * + * \param[in] TFM_PARTITION_NAME TF-M partition name assigned in the manifest + * file "tfm_partition_name" field. + */ +#define TFM_LINK_SET_OBJECT_IN_PARTITION_SECTION(TFM_PARTITION_NAME) \ + __attribute__((section(TFM_PARTITION_NAME"_ATTR_FN"))) + +#endif /* __TFM_PLAT_DEFS_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_plat_device_id.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_plat_device_id.h new file mode 100755 index 0000000..dcce837 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_impl/tfm_plat_device_id.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2018-2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __TFM_PLAT_DEVICE_ID_H__ +#define __TFM_PLAT_DEVICE_ID_H__ +/** + * \file tfm_plat_device_id.h + * + * The interfaces defined in this file are meant to provide the following + * attributes of the device: + * - Instance ID: Unique identifier of the device. + * - Implementation ID: Original implementation signer of the attestation key. + * - Hardware version: Identify the GDSII that went to fabrication. + */ + +/** + * \note The interfaces defined in this file must be implemented for each + * SoC. + */ + +#include +#include "tfm_plat_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \def INSTANCE_ID_MAX_SIZE + * + * \brief Maximum size of instance ID in bytes + */ +#define INSTANCE_ID_MAX_SIZE (33u) + +/** + * \def IMPLEMENTATION_ID_MAX_SIZE + * + * \brief Maximum size of implementation ID in bytes + */ +#define IMPLEMENTATION_ID_MAX_SIZE (32u) + +/** + * \def HW_VERSION_MAX_SIZE + * + * \brief Maximum size of hardware version in bytes + * + * Recommended to use the European Article Number format: EAN-13+5 + */ +#define HW_VERSION_MAX_SIZE (18u) + +/** + * \brief Get the UEID of the device. + * + * This mandatory claim represents the unique identifier of the instance. + * In the PSA definition is a hash of the public attestation key of the + * instance. The claim will be represented by the EAT standard claim UEID + * of type GUID. The EAT definition of a GUID type is that it will be between + * 128 & 256 bits but this implementation will use the full 256 bits to + * accommodate a hash result. + * + * \param[in/out] size As an input value it indicates the size of the caller + * allocated buffer (in bytes) to store the UEID. At return + * its value is updated with the exact size of the UEID. + * \param[out] buf Pointer to the buffer to store the UEID + * + * \return Returns error code specified in \ref tfm_plat_err_t + */ +enum tfm_plat_err_t tfm_plat_get_instance_id(uint32_t *size, uint8_t *buf); + +/** + * \brief Get the Implementation ID of the device. + * + * This mandatory claim represents the original implementation signer of the + * attestation key and identifies the contract between the report and + * verification. A verification service will use this claim to locate the + * details of the verification process. The claim will be represented by a + * custom EAT claim with a value consisting of a CBOR byte string. The size of + * this string will normally be 32 bytes to accommodate a 256 bit hash. + * + * \param[in/out] size As an input value it indicates the size of the caller + * allocated buffer (in bytes) to store the implementation + * ID. At return its value is updated with the exact size + * of the implementation ID. + * \param[out] buf Pointer to the buffer to store the implementation ID + * + * \return Returns error code specified in \ref tfm_plat_err_t + */ +enum tfm_plat_err_t tfm_plat_get_implementation_id(uint32_t *size, + uint8_t *buf); + +/** + * \brief Get the hardware version of the device. + * + * This optional claim provides metadata linking the token to the GDSII that + * went to fabrication for this instance. It is represented as CBOR text string. + * It is recommended to use for identification the format of the European + * Article Number: EAN-13+5. + * + * \param[in/out] size As an input value it indicates the size of the caller + * allocated buffer (in bytes) to store the HW version. At + * return its value is updated with the exact size of the + * HW version. + * \param[out] buf Pointer to the buffer to store the HW version + * + * \return Returns error code specified in \ref tfm_plat_err_t + */ +enum tfm_plat_err_t tfm_plat_get_hw_version(uint32_t *size, uint8_t *buf); + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_PLAT_DEVICE_ID_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_memory_utils.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_memory_utils.h new file mode 100644 index 0000000..852399e --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/attestation/tfm_memory_utils.h @@ -0,0 +1,39 @@ +/* +* Copyright (c) 2018-2019 ARM Limited. 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 __TFM_MEMORY_UTILS_H__ +#define __TFM_MEMORY_UTILS_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +void *tfm_memcpy(void *dest, const void *src, size_t num) +{ + return (memcpy(dest, src, num)); +} + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_MEMORY_UTILS_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/platform/platform_emul.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/platform/platform_emul.c new file mode 100644 index 0000000..8523413 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/platform/platform_emul.c @@ -0,0 +1,40 @@ +/* Copyright (c) 2019 ARM Limited + * + * 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 "psa/lifecycle.h" +#include "platform_srv_impl.h" + +uint32_t psa_security_lifecycle_state(void) +{ + uint32_t lc_state = 0; + psa_status_t status = PSA_SUCCESS; + status = psa_platfrom_lifecycle_get_impl(&lc_state); + if (status != PSA_SUCCESS) { + lc_state = PSA_LIFECYCLE_UNKNOWN; + } + return lc_state; +} + +psa_status_t mbed_psa_reboot_and_request_new_security_state(uint32_t new_state) +{ + return psa_platfrom_lifecycle_change_request_impl(new_state); +} + +void mbed_psa_system_reset(void) +{ + mbed_psa_system_reset_impl(); +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/platform/platform_srv_impl.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/platform/platform_srv_impl.c new file mode 100644 index 0000000..9854633 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/platform/platform_srv_impl.c @@ -0,0 +1,56 @@ +/* Copyright (c) 2019-2020 Arm Limited + * + * 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 "psa/lifecycle.h" +#include "psa/internal_trusted_storage.h" +#include "platform_srv_impl.h" +#include "cmsis.h" + +#ifndef MBED_CONF_LIFECYCLE_STATE +#define MBED_CONF_LIFECYCLE_STATE PSA_LIFECYCLE_ASSEMBLY_AND_TEST +#endif + +psa_status_t psa_platfrom_lifecycle_get_impl(uint32_t *lc_state) +{ + *lc_state = MBED_CONF_LIFECYCLE_STATE; + return PSA_SUCCESS; +} + +psa_status_t psa_its_reset(); + +psa_status_t psa_platfrom_lifecycle_change_request_impl(uint32_t state) +{ + if (PSA_LIFECYCLE_ASSEMBLY_AND_TEST == state) { + return psa_its_reset(); + } + return PSA_ERROR_NOT_SUPPORTED; +} + +MBED_WEAK void mbed_psa_system_reset_impl(void) +{ + /* Reset the system */ + NVIC_SystemReset(); +} + +MBED_WEAK enum tfm_platform_err_t tfm_platform_hal_ioctl(tfm_platform_ioctl_req_t request, + psa_invec *in_vec, + psa_outvec *out_vec) +{ + (void)in_vec; + (void)out_vec; + return TFM_PLATFORM_ERR_NOT_SUPPORTED; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/platform/platform_srv_impl.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/platform/platform_srv_impl.h new file mode 100644 index 0000000..29e704f --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/platform/platform_srv_impl.h @@ -0,0 +1,43 @@ +/* Copyright (c) 2019-2020 Arm Limited + * + * 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 __PLATFROM_SRV_IMPL_H__ +#define __PLATFROM_SRV_IMPL_H__ + +#include "psa/client.h" +#include "psa/lifecycle.h" +#include "mbed_toolchain.h" +#include "tfm_platform_api.h" + +psa_status_t psa_platfrom_lifecycle_get_impl(uint32_t *lc_state); +psa_status_t psa_platfrom_lifecycle_change_request_impl(uint32_t lc_state); +MBED_NORETURN void mbed_psa_system_reset_impl(void); + +/*! + * \brief Performs a platform-specific service + * + * \param[in] request Request identifier (valid values vary + * based on the platform) + * \param[in] in_vec Input buffer to the requested service (or NULL) + * \param[out] out_vec Output buffer to the requested service (or NULL) + * + * \return Returns values as specified by the \ref tfm_platform_err_t + */ +enum tfm_platform_err_t tfm_platform_hal_ioctl(tfm_platform_ioctl_req_t request, + psa_invec *in_vec, + psa_outvec *out_vec); +#endif // __PLATFROM_SRV_IMPL_H__ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/common/psa_storage_common_impl.cpp b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/common/psa_storage_common_impl.cpp new file mode 100644 index 0000000..1f68596 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/common/psa_storage_common_impl.cpp @@ -0,0 +1,287 @@ +/* Copyright (c) 2018 ARM Limited + * + * 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 +#include "TDBStore.h" +#include "psa_storage_common_impl.h" +#include "mbed_error.h" +#include "mbed_assert.h" +#include "mbed_toolchain.h" + +using namespace mbed; + +#ifdef __cplusplus +extern "C" +{ +#endif + +// Maximum length of filename we use for kvstore API. +// pid: 6; delimiter: 1; uid: 11; str terminator: 1 +#define PSA_STORAGE_FILE_NAME_MAX 19 + +#define FLAGS_MSK PSA_STORAGE_FLAG_WRITE_ONCE + +#define STR_EXPAND(tok) #tok + +const uint8_t base64_coding_table[] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '+', '-' +}; + +void psa_storage_handle_version(KVStore *kvstore, const char *version_key, const psa_storage_version_t *curr_version, + migrate_func_t migrate_func) +{ + psa_storage_version_t read_version = {0, 0}; + size_t actual_size = 0; + bool write_version = false; + int status = kvstore->get(version_key, &read_version, sizeof(read_version), &actual_size, 0); + if (status == MBED_SUCCESS) { + if (actual_size != sizeof(read_version)) { + error("PSA storage version data is corrupt"); + } + } else if (status == MBED_ERROR_ITEM_NOT_FOUND) { + write_version = true; + } else { + error("Could not read PSA storage version data"); + } + + if ((read_version.major > curr_version->major) || + ((read_version.major == curr_version->major) && (read_version.minor > curr_version->minor))) { + error("Downgrading PSA storage version is not allowed"); + } + + if ((read_version.major < curr_version->major) || + ((read_version.major == curr_version->major) && (read_version.minor < curr_version->minor))) { + psa_status_t migration_status = migrate_func(kvstore, &read_version, curr_version); + if (migration_status != PSA_SUCCESS) { + error("PSA storage migration failed"); + } + + write_version = true; + } + + if (write_version) { + if (kvstore->set(version_key, curr_version, sizeof(psa_storage_version_t), 0) != MBED_SUCCESS) { + error("Could not write PSA storage version"); + } + } +} + +/* + * \brief Convert KVStore stauts codes to PSA internal storage status codes + * + * \param[in] status - KVStore status code + * \return PSA internal storage status code + */ +static psa_status_t convert_status(int status) +{ + switch (status) { + case MBED_SUCCESS: + return PSA_SUCCESS; + case MBED_ERROR_WRITE_PROTECTED: + return PSA_ERROR_NOT_PERMITTED; + case MBED_ERROR_MEDIA_FULL: + return PSA_ERROR_INSUFFICIENT_STORAGE; + case MBED_ERROR_ITEM_NOT_FOUND: + return PSA_ERROR_DOES_NOT_EXIST; + case MBED_ERROR_INVALID_DATA_DETECTED: + return PSA_ERROR_DATA_CORRUPT; + case MBED_ERROR_INVALID_ARGUMENT: + return PSA_ERROR_INVALID_ARGUMENT; + case MBED_ERROR_READ_FAILED: // fallthrough + case MBED_ERROR_WRITE_FAILED: + return PSA_ERROR_STORAGE_FAILURE; + case MBED_ERROR_AUTHENTICATION_FAILED: // fallthrough + case MBED_ERROR_RBP_AUTHENTICATION_FAILED: + return PSA_ERROR_INVALID_SIGNATURE; + default: + return PSA_ERROR_GENERIC_ERROR; + } +} + +/* + * \brief Logic shift right + * + * \note must operate on unsinged integers to prevent negative carry + * \param x[in] input number for shifting + * \param n[in] number of bits to shift right + * \return the result + */ +static MBED_FORCEINLINE uint32_t lsr32(uint32_t x, uint32_t n) +{ + return x >> n; +} + +/* + * \brief Logic shift right + * + * \note must operate on unsinged integers to prevent negative carry + * \param x[in] input number for shifting + * \param n[in] number of bits to shift right + * \return the result + */ +static MBED_FORCEINLINE uint64_t lsr64(uint64_t x, uint32_t n) +{ + return x >> n; +} + +/* + * \breif Generate KVStore file name + * + * Generate KVStore file name by Base64 encoding PID and UID with a delimiter. + * Delimiter is required for determining between PID and UID. + * + * \param[out] tdb_filename - pointer to a buffer for the file name + * \param[in] tdb_filename_size - output buffer size + * \param[in] uid - PSA internal storage unique ID + * \param[in] pid - owner PSA partition ID + */ +static void generate_fn(char *tdb_filename, uint32_t tdb_filename_size, psa_storage_uid_t uid, int32_t pid) +{ + MBED_ASSERT(tdb_filename != NULL); + MBED_ASSERT(tdb_filename_size == PSA_STORAGE_FILE_NAME_MAX); + + uint8_t filename_idx = 0; + uint32_t unsigned_pid = (uint32_t)pid; // binary only representation for bitwise operations + + // Iterate on PID; each time convert 6 bits of PID into a character; first iteration must be done + do { + tdb_filename[filename_idx++] = base64_coding_table[unsigned_pid & 0x3F]; + unsigned_pid = lsr32(unsigned_pid, 6); + } while (unsigned_pid != 0); + + // Write delimiter + tdb_filename[filename_idx++] = '#'; + + // Iterate on UID; each time convert 6 bits of UID into a character; first iteration must be done + do { + tdb_filename[filename_idx++] = base64_coding_table[uid & 0x3F]; + uid = lsr64(uid, 6); + } while (uid != 0); + + tdb_filename[filename_idx++] = '\0'; + MBED_ASSERT(filename_idx <= PSA_STORAGE_FILE_NAME_MAX); +} + +psa_status_t psa_storage_set_impl(KVStore *kvstore, int32_t pid, psa_storage_uid_t uid, + size_t data_length, const void *p_data, + uint32_t kv_create_flags) +{ + if (uid == 0) { + return PSA_ERROR_INVALID_ARGUMENT; + } + // Generate KVStore key + char kv_key[PSA_STORAGE_FILE_NAME_MAX] = {'\0'}; + generate_fn(kv_key, PSA_STORAGE_FILE_NAME_MAX, uid, pid); + + int status = kvstore->set(kv_key, p_data, data_length, kv_create_flags); + + return convert_status(status); +} + +psa_status_t psa_storage_get_impl(KVStore *kvstore, int32_t pid, psa_storage_uid_t uid, + size_t data_offset, size_t data_length, void *p_data, size_t *p_data_length) +{ + if (uid == 0) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + // Generate KVStore key + char kv_key[PSA_STORAGE_FILE_NAME_MAX] = {'\0'}; + generate_fn(kv_key, PSA_STORAGE_FILE_NAME_MAX, uid, pid); + + KVStore::info_t kv_info; + int status = kvstore->get_info(kv_key, &kv_info); + + if (status == MBED_SUCCESS) { + if (data_offset > kv_info.size) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + // Verify (size + offset) does not wrap around + if (data_length + data_offset < data_length) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (data_offset + data_length > kv_info.size) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + status = kvstore->get(kv_key, p_data, data_length, p_data_length, data_offset); + } + + return convert_status(status); +} + +psa_status_t psa_storage_get_info_impl(KVStore *kvstore, int32_t pid, psa_storage_uid_t uid, + struct psa_storage_info_t *p_info, uint32_t *kv_get_flags) +{ + + if (uid == 0) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + // Generate KVStore key + char kv_key[PSA_STORAGE_FILE_NAME_MAX] = {'\0'}; + generate_fn(kv_key, PSA_STORAGE_FILE_NAME_MAX, uid, pid); + + KVStore::info_t kv_info; + int status = kvstore->get_info(kv_key, &kv_info); + + if (status == MBED_SUCCESS) { + p_info->flags = 0; + if (kv_info.flags & KVStore::WRITE_ONCE_FLAG) { + p_info->flags |= PSA_STORAGE_FLAG_WRITE_ONCE; + } + *kv_get_flags = kv_info.flags; + p_info->size = kv_info.size; + p_info->capacity = kv_info.size; + } + + return convert_status(status); +} + +psa_status_t psa_storage_remove_impl(KVStore *kvstore, int32_t pid, psa_storage_uid_t uid) +{ + if (uid == 0) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + // Generate KVStore key + char kv_key[PSA_STORAGE_FILE_NAME_MAX] = {'\0'}; + generate_fn(kv_key, PSA_STORAGE_FILE_NAME_MAX, uid, pid); + + int status = kvstore->remove(kv_key); + + return convert_status(status); +} + +psa_status_t psa_storage_reset_impl(KVStore *kvstore) +{ + int status = kvstore->reset(); + return convert_status(status); +} + +#ifdef __cplusplus +} +#endif diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/common/psa_storage_common_impl.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/common/psa_storage_common_impl.h new file mode 100644 index 0000000..86f3617 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/common/psa_storage_common_impl.h @@ -0,0 +1,50 @@ +/* Copyright (c) 2019 ARM Limited + * + * 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 __PSA_STORAGE_COMMON_IMPL_H__ +#define __PSA_STORAGE_COMMON_IMPL_H__ + +#include "psa/error.h" +#include "psa/storage_common.h" +#include "KVStore.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef struct { + uint32_t major; + uint32_t minor; +} psa_storage_version_t; + +typedef psa_status_t (*migrate_func_t)(mbed::KVStore *kvstore, const psa_storage_version_t *old_version, const psa_storage_version_t *new_version); + +void psa_storage_handle_version(mbed::KVStore *kvstore, const char *version_key, const psa_storage_version_t *version, + migrate_func_t migrate_func); +psa_status_t psa_storage_set_impl(mbed::KVStore *kvstore, int32_t pid, psa_storage_uid_t uid, size_t data_length, const void *p_data, uint32_t kv_create_flags); +psa_status_t psa_storage_get_impl(mbed::KVStore *kvstore, int32_t pid, psa_storage_uid_t uid, size_t data_offset, size_t data_length, void *p_data, size_t *p_data_length); +psa_status_t psa_storage_get_info_impl(mbed::KVStore *kvstore, int32_t pid, psa_storage_uid_t uid, struct psa_storage_info_t *p_info, uint32_t *kv_get_flags); +psa_status_t psa_storage_remove_impl(mbed::KVStore *kvstore, int32_t pid, psa_storage_uid_t uid); +psa_status_t psa_storage_reset_impl(mbed::KVStore *kvstore); + +#ifdef __cplusplus +} +#endif + + +#endif // __PSA_STORAGE_COMMON_IMPL_H__ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/its/pits_impl.cpp b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/its/pits_impl.cpp new file mode 100644 index 0000000..6f0835d --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/its/pits_impl.cpp @@ -0,0 +1,147 @@ +/* Copyright (c) 2019 ARM Limited + * + * 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 +#include "KVStore.h" +#include "TDBStore.h" +#include "psa/internal_trusted_storage.h" +#include "psa_storage_common_impl.h" +#include "pits_impl.h" +#include "mbed_error.h" +#include "mbed_toolchain.h" + +using namespace mbed; + +#if defined(TARGET_TFM) +KVStore *get_its_kvstore_instance(void); +#else +#include "KVMap.h" +#endif + + + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define STR_EXPAND(tok) #tok +#define ITS_VERSION_KEY "PSA_ITS_VERSION" // ITS version entry identifier in TDBStore + +static KVStore *kvstore = NULL; +static bool initialized = false; + + +MBED_WEAK psa_status_t its_version_migrate(KVStore *kvstore, + const psa_storage_version_t *old_version, const psa_storage_version_t *new_version) +{ + (void)kvstore; + (void)old_version; + (void)new_version; + return PSA_SUCCESS; +} + + +static void its_init(void) +{ +#if defined(TARGET_TFM) + kvstore = get_its_kvstore_instance(); +#else + KVMap &kv_map = KVMap::get_instance(); + kvstore = kv_map.get_internal_kv_instance(STR_EXPAND(MBED_CONF_STORAGE_DEFAULT_KV)); +#endif + psa_storage_version_t version = {PSA_ITS_API_VERSION_MAJOR, PSA_ITS_API_VERSION_MINOR}; + if (!kvstore) { + // Can only happen due to system misconfiguration. + // Thus considered as unrecoverable error for runtime. + error("Failed getting kvstore instance\n"); + } + + psa_storage_handle_version(kvstore, ITS_VERSION_KEY, &version, its_version_migrate); + initialized = true; +} + +// used from test only +void its_deinit(void) +{ + kvstore = NULL; + initialized = false; +} + + +psa_status_t psa_its_set_impl(int32_t pid, psa_storage_uid_t uid, size_t data_length, const void *p_data, psa_storage_create_flags_t create_flags) +{ + if (!initialized) { + its_init(); + } + + if (create_flags & ~PSA_STORAGE_FLAG_WRITE_ONCE) { + return PSA_ERROR_NOT_SUPPORTED; + } + + return psa_storage_set_impl(kvstore, pid, uid, data_length, p_data, create_flags); +} + +psa_status_t psa_its_get_impl(int32_t pid, psa_storage_uid_t uid, size_t data_offset, size_t data_length, void *p_data, size_t *p_data_length) +{ + if (!initialized) { + its_init(); + } + + return psa_storage_get_impl(kvstore, pid, uid, data_offset, data_length, p_data, p_data_length); +} + +psa_status_t psa_its_get_info_impl(int32_t pid, psa_storage_uid_t uid, struct psa_storage_info_t *p_info) +{ + uint32_t kv_get_flags; + if (!initialized) { + its_init(); + } + + return psa_storage_get_info_impl(kvstore, pid, uid, p_info, &kv_get_flags); +} + +psa_status_t psa_its_remove_impl(int32_t pid, psa_storage_uid_t uid) +{ + if (!initialized) { + its_init(); + } + + return psa_storage_remove_impl(kvstore, pid, uid); +} + +psa_status_t psa_its_reset_impl() +{ + // Do not call its_init here to avoid version check before reset +#if defined(TARGET_TFM) + kvstore = get_its_kvstore_instance(); +#else + KVMap &kv_map = KVMap::get_instance(); + kvstore = kv_map.get_internal_kv_instance(STR_EXPAND(MBED_CONF_STORAGE_DEFAULT_KV)); +#endif + if (!kvstore) { + // Can only happen due to system misconfiguration. + // Thus considered as unrecoverable error for runtime. + error("Failed getting kvstore instance\n"); + } + + return psa_storage_reset_impl(kvstore); +} + +#ifdef __cplusplus +} +#endif diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/its/pits_impl.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/its/pits_impl.h new file mode 100644 index 0000000..43d076d --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/its/pits_impl.h @@ -0,0 +1,39 @@ +/* Copyright (c) 2018 ARM Limited + * + * 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 __PITS_IMPL_H__ +#define __PITS_IMPL_H__ + +#include "psa/error.h" +#include "psa/storage_common.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +psa_status_t psa_its_set_impl(int32_t pid, psa_storage_uid_t uid, size_t data_length, const void *p_data, psa_storage_create_flags_t create_flags); +psa_status_t psa_its_get_impl(int32_t pid, psa_storage_uid_t uid, size_t data_offset, size_t data_length, void *p_data, size_t *p_data_length); +psa_status_t psa_its_get_info_impl(int32_t pid, psa_storage_uid_t uid, struct psa_storage_info_t *p_info); +psa_status_t psa_its_remove_impl(int32_t pid, psa_storage_uid_t uid); +psa_status_t psa_its_reset_impl(); + +#ifdef __cplusplus +} +#endif + +#endif // __PITS_IMPL_H__ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/its/psa_prot_internal_storage.cpp b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/its/psa_prot_internal_storage.cpp new file mode 100644 index 0000000..bce3709 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/its/psa_prot_internal_storage.cpp @@ -0,0 +1,108 @@ +/* Copyright (c) 2018 ARM Limited + * + * 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 +#include + +#include "psa/internal_trusted_storage.h" +#include "psa/storage_common.h" +#include "pits_impl.h" +#include "kv_config.h" +#include "mbed_error.h" + +// In EMUL world, there is no real partitioning, which makes the source partition irrelevant. +// So here we set a global pid value to be used for when calling IMPL functions +#define PSA_ITS_EMUL_PID 1 + +psa_status_t psa_its_set(psa_storage_uid_t uid, size_t data_length, const void *p_data, psa_storage_create_flags_t create_flags) +{ + if (!p_data && data_length) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + // KVStore initiation: + // - In EMUL (non-secure single core) we do it here since we don't have another context to do it inside. + // - Repeating calls has no effect + int kv_status = kv_init_storage_config(); + if (kv_status != MBED_SUCCESS) { + return PSA_ERROR_STORAGE_FAILURE; + } + + psa_status_t res = psa_its_set_impl(PSA_ITS_EMUL_PID, uid, data_length, p_data, create_flags); + + return res; +} + +psa_status_t psa_its_get(psa_storage_uid_t uid, size_t data_offset, size_t data_length, void *p_data, size_t *p_data_length) +{ + if ((!p_data && data_length) || !p_data_length) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + // KVStore initiation: + // - In EMUL (non-secure single core) we do it here since we don't have another context to do it inside. + // - Repeating calls has no effect + int kv_status = kv_init_storage_config(); + if (kv_status != MBED_SUCCESS) { + return PSA_ERROR_STORAGE_FAILURE; + } + + return psa_its_get_impl(PSA_ITS_EMUL_PID, uid, data_offset, data_length, p_data, p_data_length); +} + +psa_status_t psa_its_get_info(psa_storage_uid_t uid, struct psa_storage_info_t *p_info) +{ + if (!p_info) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + // KVStore initiation: + // - In EMUL (non-secure single core) we do it here since we don't have another context to do it inside. + // - Repeating calls has no effect + int kv_status = kv_init_storage_config(); + if (kv_status != MBED_SUCCESS) { + return PSA_ERROR_STORAGE_FAILURE; + } + + return psa_its_get_info_impl(PSA_ITS_EMUL_PID, uid, p_info); +} + +psa_status_t psa_its_remove(psa_storage_uid_t uid) +{ + // KVStore initiation: + // - In EMUL (non-secure single core) we do it here since we don't have another context to do it inside. + // - Repeating calls has no effect + int kv_status = kv_init_storage_config(); + if (kv_status != MBED_SUCCESS) { + return PSA_ERROR_STORAGE_FAILURE; + } + + return psa_its_remove_impl(PSA_ITS_EMUL_PID, uid); +} + +extern "C" psa_status_t psa_its_reset() +{ + // KVStore initiation: + // - In EMUL (non-secure single core) we do it here since we don't have another context to do it inside. + // - Repeating calls has no effect + int kv_status = kv_init_storage_config(); + if (kv_status != MBED_SUCCESS) { + return PSA_ERROR_STORAGE_FAILURE; + } + + return psa_its_reset_impl(); +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/its/psa_prot_internal_storage.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/its/psa_prot_internal_storage.h new file mode 100644 index 0000000..b4e1a0e --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/its/psa_prot_internal_storage.h @@ -0,0 +1,164 @@ +/* Copyright (C) 2019, ARM Limited, 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. + */ +/** @file +@brief This file describes the PSA Internal Trusted Storage API +*/ + +#ifndef __PSA_INTERNAL_TRUSTED_STORAGE_H__ +#define __PSA_INTERNAL_TRUSTED_STORAGE_H__ + +#include +#include + +#include "psa/error.h" +#include "psa/storage_common.h" +#include "mbed_toolchain.h" + +#ifdef __cplusplus +extern "C" { +#endif +#define PSA_ITS_API_VERSION_MAJOR 1 /**< The major version number of the PSA ITS API. It will be incremented on significant updates that may include breaking changes */ +#define PSA_ITS_API_VERSION_MINOR 1 /**< The minor version number of the PSA ITS API. It will be incremented in small updates that are unlikely to include breaking changes */ + +// These deprecated types are still used by our PSA compliance test tools +MBED_DEPRECATED("ITS specific types should not be used") +typedef psa_status_t psa_its_status_t; + +MBED_DEPRECATED("ITS specific types should not be used") +typedef psa_storage_create_flags_t psa_its_create_flags_t; + +MBED_DEPRECATED("ITS specific types should not be used") +typedef psa_storage_uid_t psa_its_uid_t; + +MBED_DEPRECATED("ITS specific types should not be used") +#define psa_its_info_t psa_storage_info_t + +// These defines should also be deprecated +#define PSA_ITS_SUCCESS PSA_SUCCESS +#define PSA_ITS_ERROR_UID_NOT_FOUND PSA_ERROR_DOES_NOT_EXIST +#define PSA_ITS_ERROR_STORAGE_FAILURE PSA_ERROR_STORAGE_FAILURE +#define PSA_ITS_ERROR_INSUFFICIENT_SPACE PSA_ERROR_INSUFFICIENT_STORAGE +#define PSA_ITS_ERROR_OFFSET_INVALID PSA_ERROR_INVALID_ARGUMENT +#define PSA_ITS_ERROR_INCORRECT_SIZE PSA_ERROR_BUFFER_TOO_SMALL +#define PSA_ITS_ERROR_INVALID_ARGUMENTS PSA_ERROR_INVALID_ARGUMENT +#define PSA_ITS_ERROR_FLAGS_NOT_SUPPORTED PSA_ERROR_NOT_SUPPORTED +#define PSA_ITS_ERROR_WRITE_ONCE PSA_ERROR_NOT_PERMITTED +#define PSA_ITS_FLAG_WRITE_ONCE PSA_STORAGE_FLAG_WRITE_ONCE + +MBED_DEPRECATED("PS specific types should not be used") +typedef psa_status_t psa_ps_status_t; +MBED_DEPRECATED("PS specific types should not be used") +typedef psa_storage_uid_t psa_ps_uid_t; +MBED_DEPRECATED("PS specific types should not be used") +typedef psa_storage_create_flags_t psa_ps_create_flags_t; +MBED_DEPRECATED("PS specific types should not be used") +#define psa_ps_info_t psa_storage_info_t + +#define PSA_PS_SUCCESS PSA_SUCCESS +#define PSA_PS_ERROR_UID_NOT_FOUND PSA_ERROR_DOES_NOT_EXIST +#define PSA_PS_ERROR_STORAGE_FAILURE PSA_ERROR_STORAGE_FAILURE +#define PSA_PS_ERROR_INSUFFICIENT_SPACE PSA_ERROR_INSUFFICIENT_STORAGE +#define PSA_PS_ERROR_OFFSET_INVALID PSA_ERROR_INVALID_ARGUMENT +#define PSA_PS_ERROR_INCORRECT_SIZE PSA_ERROR_BUFFER_TOO_SMALL +#define PSA_PS_ERROR_INVALID_ARGUMENT PSA_ERROR_INVALID_ARGUMENT +#define PSA_PS_ERROR_FLAGS_NOT_SUPPORTED PSA_ERROR_NOT_SUPPORTED +#define PSA_PS_ERROR_WRITE_ONCE PSA_ERROR_NOT_PERMITTED +#define PSA_PS_FLAG_WRITE_ONCE PSA_STORAGE_FLAG_WRITE_ONCE + +/** + * \brief create a new or modify an existing uid/value pair + * + * \param[in] uid the identifier for the data + * \param[in] data_length The size in bytes of the data in `p_data` + * \param[in] p_data A buffer containing the data + * \param[in] create_flags The flags that the data will be stored with + * + * \return A status indicating the success/failure of the operation + + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the provided `uid` value was already created with PSA_STORAGE_WRITE_ONCE_FLAG + * \retval PSA_ERROR_NOT_SUPPORTED The operation failed because one or more of the flags provided in `create_flags` is not supported or is not valid + * \retval PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because there was insufficient space on the storage medium + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + * \retval PSA_ERROR_INVALID_ARGUMENTS The operation failed because one of the provided pointers(`p_data`) + * is invalid, for example is `NULL` or references memory the caller cannot access + */ +psa_status_t psa_its_set(psa_storage_uid_t uid, + size_t data_length, + const void *p_data, + psa_storage_create_flags_t create_flags); + +/** + * \brief Retrieve the value associated with a provided uid + * + * \param[in] uid The uid value + * \param[in] data_offset The starting offset of the data requested + * \param[in] data_length the amount of data requested (and the minimum allocated size of the `p_data` buffer) + * \param[out] p_data The buffer where the data will be placed upon successful completion + * \param[out] p_data_length The actual amount of data returned + + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided `uid` value was not found in the storage + * \retval PSA_ERROR_BUFFER_TOO_SMALL The operation failed because the data associated with provided `uid` is not the same size as `data_size` + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_data`, `p_data_length`) + * is invalid. For example is `NULL` or references memory the caller cannot access + */ +psa_status_t psa_its_get(psa_storage_uid_t uid, + size_t data_offset, + size_t data_length, + void *p_data, + size_t *p_data_length); + +/** + * \brief Retrieve the metadata about the provided uid + * + * \param[in] uid The uid value + * \param[out] p_info A pointer to the `psa_storage_info_t` struct that will be populated with the metadata + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided uid value was not found in the storage + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_info`) + * is invalid, for example is `NULL` or references memory the caller cannot access + */ +psa_status_t psa_its_get_info(psa_storage_uid_t uid, + struct psa_storage_info_t *p_info); + +/** + * \brief Remove the provided key and its associated data from the storage + * + * \param[in] uid The uid value + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided key value was not found in the storage + * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the provided key value was created with PSA_STORAGE_WRITE_ONCE_FLAG + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + */ +psa_status_t psa_its_remove(psa_storage_uid_t uid); + +#ifdef __cplusplus +} +#endif + +#endif // __PSA_INTERNAL_TRUSTED_STORAGE_H__ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/ps/protected_storage.cpp b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/ps/protected_storage.cpp new file mode 100644 index 0000000..65aea41 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/services/storage/ps/protected_storage.cpp @@ -0,0 +1,173 @@ +/* Copyright (c) 2019 ARM Limited + * + * 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 +#include "KVMap.h" +#include "KVStore.h" +#include "kv_config.h" +#include "TDBStore.h" +#include "psa/protected_storage.h" +#include "psa_storage_common_impl.h" +#include "mbed_error.h" +#include "mbed_toolchain.h" + +using namespace mbed; + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define STR_EXPAND(tok) #tok +#define PS_VERSION_KEY "PSA_PS_VERSION" // PS version entry identifier in TDBStore + +// Global PID for protected storage, used when calling IMPL functions +#define PSA_PS_GLOBAL_PID 1 + +static KVStore *kvstore = NULL; +static bool initialized = false; + +MBED_WEAK psa_status_t ps_version_migrate(KVStore *kvstore, + const psa_storage_version_t *old_version, const psa_storage_version_t *new_version) +{ + (void)kvstore; + (void)old_version; + (void)new_version; + return PSA_SUCCESS; +} + + +static void ps_init(void) +{ + int ret = kv_init_storage_config(); + if (ret) { + // Can only happen due to system misconfiguration. + // Thus considered as unrecoverable error for runtime. + error("Failed initializing kvstore configuration\n"); + } + KVMap &kv_map = KVMap::get_instance(); + psa_storage_version_t version = {PSA_PS_API_VERSION_MAJOR, PSA_PS_API_VERSION_MINOR}; + kvstore = kv_map.get_main_kv_instance(STR_EXPAND(MBED_CONF_STORAGE_DEFAULT_KV)); + KVStore *int_kvstore = kv_map.get_internal_kv_instance(STR_EXPAND(MBED_CONF_STORAGE_DEFAULT_KV));; + if (!kvstore || !int_kvstore) { + // Can only happen due to system misconfiguration. + // Thus considered as unrecoverable error for runtime. + error("Failed getting kvstore instance\n"); + } + + psa_storage_handle_version(kvstore, PS_VERSION_KEY, &version, ps_version_migrate); + initialized = true; +} + +// used from test only +void ps_deinit(void) +{ + kvstore = NULL; + initialized = false; +} + + +psa_status_t psa_ps_set(psa_storage_uid_t uid, size_t data_length, const void *p_data, psa_storage_create_flags_t create_flags) +{ + if (!initialized) { + ps_init(); + } + + if (create_flags & ~ + (PSA_STORAGE_FLAG_WRITE_ONCE | PSA_STORAGE_FLAG_NO_CONFIDENTIALITY | PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION)) { + return PSA_ERROR_NOT_SUPPORTED; + } + + // Assume confidentiality and replay protection are set by default + uint32_t kv_create_flags = KVStore::REQUIRE_CONFIDENTIALITY_FLAG | KVStore::REQUIRE_REPLAY_PROTECTION_FLAG; + + if (create_flags & PSA_STORAGE_FLAG_NO_CONFIDENTIALITY) { + kv_create_flags &= ~KVStore::REQUIRE_CONFIDENTIALITY_FLAG; + } + if (create_flags & PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION) { + kv_create_flags &= ~KVStore::REQUIRE_REPLAY_PROTECTION_FLAG; + } + if (create_flags & PSA_STORAGE_FLAG_WRITE_ONCE) { + kv_create_flags |= KVStore::WRITE_ONCE_FLAG; + } + + return psa_storage_set_impl(kvstore, PSA_PS_GLOBAL_PID, uid, data_length, p_data, kv_create_flags); +} + +psa_status_t psa_ps_get(psa_storage_uid_t uid, size_t data_offset, size_t data_length, void *p_data, size_t *p_data_length) +{ + if (!initialized) { + ps_init(); + } + + return psa_storage_get_impl(kvstore, PSA_PS_GLOBAL_PID, uid, data_offset, data_length, p_data, p_data_length); +} + +psa_status_t psa_ps_get_info(psa_storage_uid_t uid, struct psa_storage_info_t *p_info) +{ + psa_status_t ret; + uint32_t kv_get_flags; + + if (!initialized) { + ps_init(); + } + + ret = psa_storage_get_info_impl(kvstore, PSA_PS_GLOBAL_PID, uid, p_info, &kv_get_flags); + + if ((kv_get_flags & ~KVStore::REQUIRE_CONFIDENTIALITY_FLAG) == kv_get_flags) { + p_info->flags |= PSA_STORAGE_FLAG_NO_CONFIDENTIALITY; + } + if ((kv_get_flags & ~KVStore::REQUIRE_REPLAY_PROTECTION_FLAG) == kv_get_flags) { + p_info->flags |= PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION; + } + + return ret; +} + +psa_status_t psa_ps_remove(psa_storage_uid_t uid) +{ + if (!initialized) { + ps_init(); + } + + return psa_storage_remove_impl(kvstore, PSA_PS_GLOBAL_PID, uid); +} + +extern "C" psa_status_t psa_ps_reset() +{ + // Do not call its_init here to avoid version check before reset + int ret = kv_init_storage_config(); + if (ret) { + // Can only happen due to system misconfiguration. + // Thus considered as unrecoverable error for runtime. + error("Failed initializing kvstore configuration\n"); + } + + KVMap &kv_map = KVMap::get_instance(); + kvstore = kv_map.get_main_kv_instance(STR_EXPAND(MBED_CONF_STORAGE_DEFAULT_KV)); + if (!kvstore) { + // Can only happen due to system misconfiguration. + // Thus considered as unrecoverable error for runtime. + error("Failed getting kvstore instance\n"); + } + + return psa_storage_reset_impl(kvstore); +} + +#ifdef __cplusplus +} +#endif diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/src/client.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/src/client.c new file mode 100644 index 0000000..2cc8bb4 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/src/client.c @@ -0,0 +1,51 @@ +/* Copyright (c) 2017-2020 ARM Limited + * + * 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. + */ + +/* This implementation of the PSA Client API is provided for application + * compatibility on single v7-M targets. The client implementation is stubbed + * and non-functional, but present and returns sane errors. */ + +#include "psa/client.h" + +uint32_t psa_framework_version(void) +{ + return PSA_FRAMEWORK_VERSION; +} + +uint32_t psa_version(uint32_t sid) +{ + return PSA_VERSION_NONE; +} + +psa_handle_t psa_connect(uint32_t sid, uint32_t version) +{ + return PSA_ERROR_PROGRAMMER_ERROR; +} + +psa_status_t psa_call(psa_handle_t handle, int32_t type, + const psa_invec *in_vec, + size_t in_len, + psa_outvec *out_vec, + size_t out_len) +{ + return PSA_ERROR_PROGRAMMER_ERROR; +} + +void psa_close(psa_handle_t handle) +{ + return; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/src/default_random_seed.cpp b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/src/default_random_seed.cpp new file mode 100644 index 0000000..92e0c12 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/src/default_random_seed.cpp @@ -0,0 +1,17 @@ +#include "mbed.h" +#include "crypto.h" +#include "default_random_seed.h" +#include "psa/internal_trusted_storage.h" + +int mbed_default_seed_read(unsigned char *buf, size_t buf_len) +{ + size_t actual_size; + psa_status_t rc = psa_its_get(PSA_CRYPTO_ITS_RANDOM_SEED_UID, 0, buf_len, buf, &actual_size); + return (rc); +} + +int mbed_default_seed_write(unsigned char *buf, size_t buf_len) +{ + psa_status_t rc = psa_its_set(PSA_CRYPTO_ITS_RANDOM_SEED_UID, buf_len, buf, 0); + return (rc); +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val.h new file mode 100644 index 0000000..e4d1fa4 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val.h @@ -0,0 +1,277 @@ +/** @file + * Copyright (c) 2018-2019, 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 _VAL_COMMON_H_ +#define _VAL_COMMON_H_ + +#include "pal_common.h" + +#ifndef VAL_NSPE_BUILD +#define STATIC_DECLARE static +#else +#define STATIC_DECLARE +#endif + +#ifndef __WEAK +#define __WEAK __attribute__((weak)) +#endif + +#ifndef __UNUSED +#define __UNUSED __attribute__((unused)) +#endif + +#ifndef TRUE +#define TRUE 0 +#endif +#ifndef FALSE +#define FALSE 1 +#endif + +#ifndef INT_MAX +#define INT_MAX 0xFFFFFFFF +#endif + +#define _CONCAT(A,B) A##B +#define CONCAT(A,B) _CONCAT(A,B) + +/* test status defines */ +#define TEST_START 0x01 +#define TEST_END 0x02 +#define TEST_PASS 0x04 +#define TEST_FAIL 0x08 +#define TEST_SKIP 0x10 +#define TEST_PENDING 0x20 + +#define TEST_NUM_BIT 32 +#define TEST_STATE_BIT 8 +#define TEST_STATUS_BIT 0 + +#define TEST_NUM_MASK 0xFFFFFFFF +#define TEST_STATE_MASK 0xFF +#define TEST_STATUS_MASK 0xFF + +#define RESULT_START(status) (((TEST_START) << TEST_STATE_BIT) | ((status) << TEST_STATUS_BIT)) +#define RESULT_END(status) (((TEST_END) << TEST_STATE_BIT) | ((status) << TEST_STATUS_BIT)) +#define RESULT_PASS(status) (((TEST_PASS) << TEST_STATE_BIT) | ((status) << TEST_STATUS_BIT)) +#define RESULT_FAIL(status) (((TEST_FAIL) << TEST_STATE_BIT) | ((status) << TEST_STATUS_BIT)) +#define RESULT_SKIP(status) (((TEST_SKIP) << TEST_STATE_BIT) | ((status) << TEST_STATUS_BIT)) +#define RESULT_PENDING(status) (((TEST_PENDING) << TEST_STATE_BIT) | ((status) << TEST_STATUS_BIT)) + +#define IS_TEST_FAIL(status) (((status >> TEST_STATE_BIT) & TEST_STATE_MASK) == TEST_FAIL) +#define IS_TEST_PASS(status) (((status >> TEST_STATE_BIT) & TEST_STATE_MASK) == TEST_PASS) +#define IS_TEST_SKIP(status) (((status >> TEST_STATE_BIT) & TEST_STATE_MASK) == TEST_SKIP) +#define IS_TEST_PENDING(status) (((status >> TEST_STATE_BIT) & TEST_STATE_MASK) == TEST_PENDING) +#define IS_TEST_START(status) (((status >> TEST_STATE_BIT) & TEST_STATE_MASK) == TEST_START) +#define IS_TEST_END(status) (((status >> TEST_STATE_BIT) & TEST_STATE_MASK) == TEST_END) +#define VAL_ERROR(status) ((status & TEST_STATUS_MASK) ? 1 : 0) + + + +/* Test Defines */ +#define TEST_PUBLISH(test_id, entry) + +#define VAL_MAX_TEST_PER_COMP 200 +#define VAL_FF_BASE 0 +#define VAL_CRYPTO_BASE 1 +#define VAL_PROTECTED_STORAGE_BASE 2 +#define VAL_INTERNAL_TRUSTED_STORAGE_BASE 3 +#define VAL_INITIAL_ATTESTATION_BASE 4 + +#define VAL_GET_COMP_NUM(test_id) \ + ((test_id - (test_id % VAL_MAX_TEST_PER_COMP)) / VAL_MAX_TEST_PER_COMP) +#define VAL_GET_TEST_NUM(test_id) (test_id % VAL_MAX_TEST_PER_COMP) +#define VAL_CREATE_TEST_ID(comp,num) ((comp*VAL_MAX_TEST_PER_COMP) + num) + +#define TEST_FIELD(num1,num2) (num2 << 8 | num1) +#define GET_TEST_ISOLATION_LEVEL(num) (num & 0x3) +#define GET_WD_TIMOUT_TYPE(num) ((num >> 8) & 0x7) + +#define TEST_CHECKPOINT_NUM(n) n +#define TEST(n) n +#define BLOCK(n) n + +#define BLOCK_NUM_POS 8 +#define ACTION_POS 16 +#define GET_TEST_NUM(n) (0xff & n) +#define GET_BLOCK_NUM(n) ((n >> BLOCK_NUM_POS) & 0xff) + +#define GET_ACTION_NUM(n) ((n >> ACTION_POS) & 0xff) +#define TEST_EXECUTE_FUNC 1 +#define TEST_RETURN_RESULT 2 +#define INVALID_HANDLE 0x1234DEAD + +#define VAL_NVMEM_BLOCK_SIZE 4 +#define VAL_NVMEM_OFFSET(nvmem_idx) (nvmem_idx * VAL_NVMEM_BLOCK_SIZE) + +#define UART_INIT_SIGN 0xff +#define UART_PRINT_SIGN 0xfe + +#define TEST_PANIC() \ + do { \ + } while(1) + +#define TEST_ASSERT_EQUAL(arg1, arg2, checkpoint) \ + do { \ + if ((arg1) != arg2) \ + { \ + val->print(PRINT_ERROR, "\tFailed at Checkpoint: %d\n", checkpoint); \ + val->print(PRINT_ERROR, "\tActual: %d\n", arg1); \ + val->print(PRINT_ERROR, "\tExpected: %d\n", arg2); \ + return 1; \ + } \ + } while (0) + +#define TEST_ASSERT_DUAL(arg1, status1, status2, checkpoint) \ + do { \ + if ((arg1) != status1 && (arg1) != status2) \ + { \ + val->print(PRINT_ERROR, "\tFailed at Checkpoint: %d\n", checkpoint); \ + val->print(PRINT_ERROR, "\tActual: %d\n", arg1); \ + val->print(PRINT_ERROR, "\tExpected: %d", status1); \ + val->print(PRINT_ERROR, "or %d\n", status2); \ + return 1; \ + } \ + } while (0) + +#define TEST_ASSERT_NOT_EQUAL(arg1, arg2, checkpoint) \ + do { \ + if ((arg1) == arg2) \ + { \ + val->print(PRINT_ERROR, "\tFailed at Checkpoint: %d\n", checkpoint); \ + val->print(PRINT_ERROR, "\tValue: %d\n", arg1); \ + return 1; \ + } \ + } while (0) + +#define TEST_ASSERT_MEMCMP(buf1, buf2, size, checkpoint) \ + do { \ + if (memcmp(buf1, buf2, size)) \ + { \ + val->print(PRINT_ERROR, "\tFailed at Checkpoint: %d : ", checkpoint); \ + val->print(PRINT_ERROR, "Unequal data in compared buffers\n", 0); \ + return 1; \ + } \ + } while (0) + +/* enums */ +typedef enum { + CALLER_NONSECURE = 0x0, + CALLER_SECURE = 0x1, +} caller_security_t; + +typedef enum { + TEST_ISOLATION_L1 = 0x1, + TEST_ISOLATION_L2 = 0x2, + TEST_ISOLATION_L3 = 0x3, +} test_isolation_level_t; + +typedef enum { + BOOT_UNKNOWN = 0x1, + BOOT_NOT_EXPECTED = 0x2, + BOOT_EXPECTED_NS = 0x3, + BOOT_EXPECTED_S = 0x4, + BOOT_EXPECTED_BUT_FAILED = 0x5, + BOOT_EXPECTED_CRYPTO = 0x6, +} boot_state_t; + +typedef enum { + NV_BOOT = 0x0, + NV_TEST_ID_PREVIOUS = 0x1, + NV_TEST_ID_CURRENT = 0x2, + NV_TEST_CNT = 0x3, +} nvmem_index_t; + +/* enums to report test sub-state */ +typedef enum { + VAL_STATUS_SUCCESS = 0x0, + VAL_STATUS_INVALID = 0x10, + VAL_STATUS_ERROR = 0x11, + VAL_STATUS_NOT_FOUND = 0x12, + VAL_STATUS_LOAD_ERROR = 0x13, + VAL_STATUS_INSUFFICIENT_SIZE = 0x14, + VAL_STATUS_CONNECTION_FAILED = 0x15, + VAL_STATUS_CALL_FAILED = 0x16, + VAL_STATUS_READ_FAILED = 0x17, + VAL_STATUS_WRITE_FAILED = 0x18, + VAL_STATUS_ISOLATION_LEVEL_NOT_SUPP = 0x19, + VAL_STATUS_INIT_FAILED = 0x1A, + VAL_STATUS_SPM_FAILED = 0x1B, + VAL_STATUS_SPM_UNEXPECTED_BEH = 0x1C, + VAL_STATUS_FRAMEWORK_VERSION_FAILED = 0x1D, + VAL_STATUS_VERSION_API_FAILED = 0x1E, + VAL_STATUS_INVALID_HANDLE = 0x1F, + VAL_STATUS_INVALID_MSG_TYPE = 0x20, + VAL_STATUS_WRONG_IDENTITY = 0x21, + VAL_STATUS_MSG_INSIZE_FAILED = 0x22, + VAL_STATUS_MSG_OUTSIZE_FAILED = 0x23, + VAL_STATUS_SKIP_FAILED = 0x24, + VAL_STATUS_CRYPTO_FAILURE = 0x25, + VAL_STATUS_INVALID_SIZE = 0x26, + VAL_STATUS_DATA_MISMATCH = 0x27, + VAL_STATUS_BOOT_EXPECTED_BUT_FAILED = 0x28, + VAL_STATUS_INIT_ALREADY_DONE = 0x29, + VAL_STATUS_HEAP_NOT_AVAILABLE = 0x2A, + VAL_STATUS_UNSUPPORTED = 0x2B, + VAL_STATUS_ERROR_MAX = INT_MAX, +} val_status_t; + +/* verbosity enums */ +typedef enum { + PRINT_INFO = 1, + PRINT_DEBUG = 2, + PRINT_TEST = 3, + PRINT_WARN = 4, + PRINT_ERROR = 5, + PRINT_ALWAYS = 9 +} print_verbosity_t; + +/* Interrupt test function id enums */ +typedef enum { + TEST_PSA_EOI_WITH_NON_INTR_SIGNAL = 1, + TEST_PSA_EOI_WITH_MULTIPLE_SIGNALS = 2, + TEST_PSA_EOI_WITH_UNASSERTED_SIGNAL = 3, + TEST_INTR_SERVICE = 4, +} test_intr_fn_id_t; + +/* typedef's */ +typedef struct { + boot_state_t state; +} boot_t; + +typedef struct { + uint32_t pass_cnt: 8; + uint32_t skip_cnt: 8; + uint32_t fail_cnt: 8; + uint32_t sim_error_cnt: 8; +} test_count_t; + +typedef struct { + uint16_t test_num; + uint8_t block_num; +} test_info_t; + + +/* struture to capture test state */ +typedef struct { + uint16_t reserved; + uint8_t state; + uint8_t status; +} test_status_buffer_t; + +typedef int32_t (*client_test_t)(caller_security_t caller); +typedef int32_t (*server_test_t)(void); +#endif /* VAL_COMMON_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_attestation.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_attestation.c new file mode 100644 index 0000000..cd8069a --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_attestation.c @@ -0,0 +1,40 @@ +/** @file + * Copyright (c) 2019, 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_target.h" +#include "pal_interfaces_ns.h" +#include "val_framework.h" +#include "val_client_defs.h" +#include "val_attestation.h" + +/** + @brief - This API will call the requested attestation function + @param - type : function code + ... : variable number of arguments + @return - Error status +**/ + +int32_t val_attestation_function(int type, ...) +{ + va_list valist; + val_status_t status; + + va_start(valist, type); + status = pal_attestation_function(type, valist); + va_end(valist); + return status; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_attestation.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_attestation.h new file mode 100644 index 0000000..5322723 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_attestation.h @@ -0,0 +1,33 @@ +/** @file + * Copyright (c) 2019, 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 _VAL_INITIAL_ATTESTATION_H_ +#define _VAL_INITIAL_ATTESTATION_H_ + +#include "val.h" +#include "psa_initial_attestation_api.h" + +#define MAX_CHALLENGE_SIZE PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64 + +enum attestation_function_code { + VAL_INITIAL_ATTEST_GET_TOKEN = 0x1, + VAL_INITIAL_ATTEST_GET_TOKEN_SIZE = 0x2, + VAL_INITIAL_ATTEST_VERIFY_TOKEN = 0x3, +}; + +int32_t val_attestation_function(int type, ...); +#endif /* _VAL_INITIAL_ATTESTATION_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_client_defs.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_client_defs.h new file mode 100644 index 0000000..d1d18d7 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_client_defs.h @@ -0,0 +1,34 @@ +/** @file + * Copyright (c) 2018-2019, 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 _VAL_CLIENT_H_ +#define _VAL_CLIENT_H_ + +#include "val.h" +#include "psa/client.h" +#include "crypto_values.h" + +#define INVALID_SID 0x0000FA20 + +#ifndef CLIENT_TEST_DISPATCHER_SID +#define CLIENT_TEST_DISPATCHER_SID 0x0 +#endif + +#ifndef SERVER_TEST_DISPATCHER_SID +#define SERVER_TEST_DISPATCHER_SID 0x0 +#endif +#endif /* _VAL_CLIENT_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_entry.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_entry.h new file mode 100644 index 0000000..2b885e0 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_entry.h @@ -0,0 +1,32 @@ +/** @file + * Copyright (c) 2018-2019, 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 _VAL_ENTRY_H_ +#define _VAL_ENTRY_H_ + +#include "val_framework.h" + +#define PSA_ACS_MAJOR_VER 0 +#define PSA_ACS_MINOR_VER 8 + +/** + @brief - PSA Test Suite C main function, does VAL init and calls test dispatcher + @param - None + @return - void +**/ +extern void val_entry(void); +#endif diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_framework.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_framework.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_framework.h diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_greentea.cpp b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_greentea.cpp new file mode 100644 index 0000000..ba57016 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_greentea.cpp @@ -0,0 +1,297 @@ +#include "greentea-client/test_env.h" +#include "inttypes.h" +#include "val_greentea.h" + +void pal_mbed_os_compliance_test_initialize(void); +void pal_mbed_os_compliance_test_destroy(void); + +#ifdef __cplusplus +extern "C" { +#endif + + + +/* globals */ +test_status_buffer_t g_status_buffer; + +void mbed_val_test_init(uint32_t test_num, char8_t *desc, uint32_t test_bitfield) +{ + /*global init*/ + g_status_buffer.state = 0; + g_status_buffer.status = VAL_STATUS_INVALID; + + mbed_val_print(PRINT_ALWAYS, "\nTEST: %d | DESCRIPTION: ", test_num); + mbed_val_print(PRINT_ALWAYS, desc, 0); + GREENTEA_SETUP(100, "default_auto"); + mbed_val_set_status(RESULT_START(VAL_STATUS_SUCCESS)); + pal_mbed_os_compliance_test_initialize(); + return; +} + +void mbed_val_test_exit(void) +{ + uint32_t status = mbed_val_get_status(); + pal_mbed_os_compliance_test_destroy(); + /* return if test skipped or failed */ + if (IS_TEST_FAIL(status) || IS_TEST_SKIP(status)) { + GREENTEA_TESTSUITE_RESULT(false); + } else { + GREENTEA_TESTSUITE_RESULT(true); + mbed_val_set_status(RESULT_END(VAL_STATUS_SUCCESS)); + } +} + +/** +@brief - This function executes given list of tests from non-secure sequentially + This covers non-secure to secure IPC API scenario +@param - test_num : Test_num +@param - tests_list : list of tests to be executed +@param - server_hs : Initiate a server handshake +@return - val_status_t +**/ +val_status_t mbed_val_execute_non_secure_tests(uint32_t test_num, client_test_t *tests_list, + bool_t server_hs) +{ + val_status_t status = VAL_STATUS_SUCCESS; + int32_t test_status = VAL_STATUS_SUCCESS; + psa_handle_t handle; + uint32_t i = 1; + test_info_t test_info; + char testcase_name[100] = ""; + bool continue_test = true; + + test_info.test_num = test_num; + + mbed_val_print(PRINT_TEST, "[Info] Executing tests from non-secure\n", 0); + while (tests_list[i] != NULL) { + memset(testcase_name, 0, 100); + sprintf(testcase_name, "Check%" PRIu32, i); + GREENTEA_TESTCASE_START(testcase_name); + if (server_hs == TRUE) { + /* Handshake with server tests */ + test_info.block_num = i; + status = mbed_val_execute_secure_test_func(&handle, test_info, + SERVER_TEST_DISPATCHER_SID); + if (VAL_ERROR(status)) { + mbed_val_set_status(RESULT_FAIL(status)); + mbed_val_print(PRINT_ERROR, "[Check%d] START\n", i); + return status; + } else { + mbed_val_print(PRINT_DEBUG, "[Check%d] START\n", i); + } + } + + /* Execute client tests */ + test_status = tests_list[i](CALLER_NONSECURE); + + if (server_hs == TRUE) { + /* Retrive Server test status */ + status = mbed_val_get_secure_test_result(&handle); + } + + if (test_status != VAL_STATUS_SUCCESS) { + status = VAL_STATUS_ERROR; + } + + if (IS_TEST_SKIP(status)) { + mbed_val_set_status(status); + mbed_val_print(PRINT_DEBUG, "[Check%d] SKIPPED\n", i); + GREENTEA_TESTCASE_FINISH(testcase_name, 1, 0); + continue_test = false; + } else if (VAL_ERROR(status)) { + mbed_val_set_status(RESULT_FAIL(status)); + if (server_hs == TRUE) { + mbed_val_print(PRINT_ERROR, "[Check%d] FAILED\n", i); + } + GREENTEA_TESTCASE_FINISH(testcase_name, 0, 1); + continue_test = false; + } else { + if (server_hs == TRUE) { + mbed_val_print(PRINT_DEBUG, "[Check%d] PASSED\n", i); + } + GREENTEA_TESTCASE_FINISH(testcase_name, 1, 0); + continue_test = true; + } + + if (!continue_test) { + return status; + } + + i++; + } + return status; +} + +/** +@brief - Records the state and status of test +@return - val_status_t +**/ +val_status_t mbed_val_set_status(uint32_t status) +{ + g_status_buffer.state = ((status >> TEST_STATE_BIT) & TEST_STATE_MASK); + g_status_buffer.status = (status & TEST_STATUS_MASK); + + return VAL_STATUS_SUCCESS; +} + +/** +@brief - Updates the state and status for a given test +@return - test status +**/ +uint32_t mbed_val_get_status(void) +{ + return ((g_status_buffer.state) << TEST_STATE_BIT) | (g_status_buffer.status); +} + +/** +@brief - This function is used to handshake between: + - nonsecure client fn to server test fn + - secure client fn and server test fn + - nonsecure client fn to secure client test fn +@param - handle : handle returned while connecting given sid +@param - test_info : Test_num and block_num to be executed +@param - sid : RoT service to be connected. Partition dispatcher sid +@return - val_status_t +**/ +val_status_t mbed_val_execute_secure_test_func(psa_handle_t *handle, test_info_t test_info, uint32_t sid) +{ + uint32_t test_data; + val_status_t status = VAL_STATUS_SUCCESS; + psa_status_t status_of_call = PSA_SUCCESS; + + *handle = pal_ipc_connect(sid, 0); + if (*handle < 0) { + mbed_val_print(PRINT_ERROR, "Could not connect SID. Handle=%x\n", *handle); + return VAL_STATUS_CONNECTION_FAILED; + } + + test_data = ((uint32_t)(test_info.test_num) | ((uint32_t)(test_info.block_num) << BLOCK_NUM_POS) | ((uint32_t)(TEST_EXECUTE_FUNC) << ACTION_POS)); + psa_invec data[1] = {{&test_data, sizeof(test_data)}}; + + status_of_call = pal_ipc_call(*handle, data, 1, NULL, 0); + if (status_of_call != PSA_SUCCESS) { + status = VAL_STATUS_CALL_FAILED; + mbed_val_print(PRINT_ERROR, "Call to dispatch SF failed. Status=%x\n", status_of_call); + pal_ipc_close(*handle); + } + + return status; +} + +/** +@brief - Print module. This is client interface API of secure partition + mbed_val_print_sf API for nspe world +@param - verbosity: Print verbosity level + - string : Input string + - data : Value for format specifier +@return - val_status_t +**/ +val_status_t mbed_val_print(print_verbosity_t verbosity, const char *string, uint32_t data) +{ + if (data != 0) { + printf(string, data); + } else { + printf(string); + } + + return VAL_STATUS_SUCCESS; +} + +/** +@brief - This function is used to retrive the status of previously connected test function + using mbed_val_execute_secure_test_func +@param - handle : handle of server function. Handle of Partition dispatcher sid +@return - The status of test functions +**/ +val_status_t mbed_val_get_secure_test_result(psa_handle_t *handle) +{ + uint32_t test_data; + val_status_t status = VAL_STATUS_SUCCESS; + psa_status_t status_of_call = PSA_SUCCESS; + + test_data = (TEST_RETURN_RESULT << ACTION_POS); + + psa_outvec resp = {&status, sizeof(status)}; + psa_invec data[1] = {{&test_data, sizeof(test_data)}}; + + status_of_call = pal_ipc_call(*handle, data, 1, &resp, 1); + if (status_of_call != PSA_SUCCESS) { + status = VAL_STATUS_CALL_FAILED; + mbed_val_print(PRINT_ERROR, "Call to dispatch SF failed. Status=%x\n", status_of_call); + } + + pal_ipc_close(*handle); + return status; +} + +/** + * @brief Connect to given sid + @param -sid : RoT service id + @param -minor_version : minor_version of RoT service + @param -handle - return connection handle + * @return val_status_t + */ +val_status_t mbed_val_ipc_connect(uint32_t sid, uint32_t minor_version, psa_handle_t *handle) +{ + *handle = pal_ipc_connect(sid, minor_version); + + if (*handle < 0) { + return VAL_STATUS_CONNECTION_FAILED; + } + + return VAL_STATUS_SUCCESS; +} + +/** + * @brief Call a connected Root of Trust Service.@n + * The caller must provide an array of ::psa_invec_t structures as the input payload. + * + * @param handle Handle for the connection. + * @param in_vec Array of psa_invec structures. + * @param in_len Number of psa_invec structures in in_vec. + * @param out_vec Array of psa_outvec structures for optional Root of Trust Service response. + * @param out_len Number of psa_outvec structures in out_vec. + * @return val_status_t + */ +val_status_t mbed_val_ipc_call(psa_handle_t handle, psa_invec *in_vec, size_t in_len, + psa_outvec *out_vec, size_t out_len) +{ + psa_status_t call_status = PSA_SUCCESS; + + call_status = pal_ipc_call(handle, in_vec, in_len, out_vec, out_len); + + if (call_status != PSA_SUCCESS) { + return VAL_STATUS_CALL_FAILED; + } + + return VAL_STATUS_SUCCESS; +} + +/** + * @brief Close a connection to a Root of Trust Service. + * Sends the PSA_IPC_DISCONNECT message to the Root of Trust Service so it can clean up resources. + * + * @param handle Handle for the connection. + * @return void + */ +void mbed_val_ipc_close(psa_handle_t handle) +{ + pal_ipc_close(handle); +} + + +/** + * @brief reprogram the watchdog timer + * always succeeds on mbed-greentead testing. + * + * @param timeout_type type of timeout. + * @return val_status_t + */ +val_status_t mbed_val_wd_reprogram_timer(wd_timeout_type_t timeout_type) +{ + return VAL_STATUS_SUCCESS; +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_greentea.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_greentea.h new file mode 100644 index 0000000..a8d7da8 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_greentea.h @@ -0,0 +1,30 @@ +#ifndef _VAL_GREENTEA_H_ +#define _VAL_GREENTEA_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "val.h" +#include "val_interfaces.h" + +void mbed_val_test_init(uint32_t test_num, char8_t *desc, uint32_t test_bitfield); +void mbed_val_test_exit(void); +val_status_t mbed_val_execute_non_secure_tests(uint32_t test_num, client_test_t *tests_list, bool_t server_hs); +val_status_t mbed_val_set_status(uint32_t status); +uint32_t mbed_val_get_status(void); +val_status_t mbed_val_execute_secure_test_func(psa_handle_t *handle, test_info_t test_info, uint32_t sid); +val_status_t mbed_val_print(print_verbosity_t verbosity, const char *string, uint32_t data); +val_status_t mbed_val_get_secure_test_result(psa_handle_t *handle); +val_status_t mbed_val_ipc_connect(uint32_t sid, uint32_t minor_version, psa_handle_t *handle); +val_status_t mbed_val_ipc_call(psa_handle_t handle, psa_invec *in_vec, size_t in_len, + psa_outvec *out_vec, size_t out_len); +void mbed_val_ipc_close(psa_handle_t handle); +val_status_t mbed_val_wd_reprogram_timer(wd_timeout_type_t timeout_type); + +#ifdef __cplusplus +} +#endif + +#endif // _VAL_GREENTEA_H_ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_interfaces.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_interfaces.c new file mode 100644 index 0000000..b6bf085 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_interfaces.c @@ -0,0 +1,60 @@ +/** @file + * Copyright (c) 2018-2019, 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_greentea.h" +#include "val_interfaces.h" +#include "val_internal_trusted_storage.h" +#include "val_protected_storage.h" +#include "val_attestation.h" + +/*VAL APIs to be used by test */ +const val_api_t val_api = { + .print = mbed_val_print, + .set_status = mbed_val_set_status, + .get_status = mbed_val_get_status, + .test_init = mbed_val_test_init, + .test_exit = mbed_val_test_exit, + .err_check_set = NULL, + .target_get_config = NULL, + .execute_non_secure_tests = mbed_val_execute_non_secure_tests, + .switch_to_secure_client = NULL, + .execute_secure_test_func = mbed_val_execute_secure_test_func, + .get_secure_test_result = mbed_val_get_secure_test_result, + .ipc_connect = mbed_val_ipc_connect, + .ipc_call = mbed_val_ipc_call, + .ipc_close = mbed_val_ipc_close, + .nvmem_read = NULL, + .nvmem_write = NULL, + .wd_timer_init = NULL, + .wd_timer_enable = NULL, + .wd_timer_disable = NULL, + .wd_reprogram_timer = mbed_val_wd_reprogram_timer, + .set_boot_flag = NULL, + .get_boot_flag = NULL, + .its_function = val_its_function, + .ps_function = val_ps_function, + .attestation_function = val_attestation_function, +}; + +const psa_api_t psa_api = { + .framework_version = pal_ipc_framework_version, + .version = pal_ipc_version, + .connect = pal_ipc_connect, + .call = pal_ipc_call, + .close = pal_ipc_close, +}; diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_interfaces.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_interfaces.h new file mode 100644 index 0000000..40bc673 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_interfaces.h @@ -0,0 +1,83 @@ +/** @file + * Copyright (c) 2018-2019, 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 _VAL_INTERFACES_H_ +#define _VAL_INTERFACES_H_ + +#include "val.h" +#include "val_client_defs.h" +#include "pal_interfaces_ns.h" + +/* typedef's */ +typedef struct { + val_status_t (*print)(print_verbosity_t verbosity, + const char *string, uint32_t data); + val_status_t (*set_status)(uint32_t status); + uint32_t (*get_status)(void); + void (*test_init)(uint32_t test_num, char8_t *desc, + uint32_t test_bitfield); + void (*test_exit)(void); + val_status_t (*err_check_set)(uint32_t checkpoint, val_status_t status); + val_status_t (*target_get_config)(cfg_id_t cfg_id, uint8_t **data, uint32_t *size); + val_status_t (*execute_non_secure_tests)(uint32_t test_num, client_test_t *tests_list, + bool_t server_hs); + val_status_t (*switch_to_secure_client)(uint32_t test_num); + val_status_t (*execute_secure_test_func)(psa_handle_t *handle, test_info_t test_info, + uint32_t sid); + val_status_t (*ipc_connect)(uint32_t sid, uint32_t minor_version, + psa_handle_t *handle); + val_status_t (*ipc_call)(psa_handle_t handle, psa_invec *in_vec, + size_t in_len, psa_outvec *out_vec, + size_t out_len); + void (*ipc_close)(psa_handle_t handle); + val_status_t (*get_secure_test_result)(psa_handle_t *handle); + val_status_t (*nvmem_read)(uint32_t offset, void *buffer, int size); + val_status_t (*nvmem_write)(uint32_t offset, void *buffer, int size); + val_status_t (*wd_timer_init)(wd_timeout_type_t timeout_type); + val_status_t (*wd_timer_enable)(void); + val_status_t (*wd_timer_disable)(void); + val_status_t (*wd_reprogram_timer)(wd_timeout_type_t timeout_type); + val_status_t (*set_boot_flag)(boot_state_t state); + val_status_t (*get_boot_flag)(boot_state_t *state); + int32_t (*crypto_function)(int type, ...); + uint32_t (*its_function)(int type, ...); + uint32_t (*ps_function)(int type, ...); + int32_t (*attestation_function)(int type, ...); +} val_api_t; + +typedef struct { + uint32_t (*framework_version)(void); + uint32_t (*version)(uint32_t sid); + psa_handle_t (*connect)(uint32_t sid, uint32_t minor_version); + psa_status_t (*call)(psa_handle_t handle, + const psa_invec *in_vec, + size_t in_len, + psa_outvec *out_vec, + size_t out_len + ); + void (*close)(psa_handle_t handle); +} psa_api_t; + +typedef void (*test_fptr_t)(val_api_t *val, psa_api_t *psa); + +typedef struct { + test_id_t test_id; + test_fptr_t entry_addr; +} val_test_info_t; + +void test_entry(val_api_t *val, psa_api_t *psa); +#endif diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_internal_trusted_storage.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_internal_trusted_storage.c new file mode 100644 index 0000000..e79e9c0 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_internal_trusted_storage.c @@ -0,0 +1,39 @@ +/** @file + * Copyright (c) 2019, 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_target.h" +#include "pal_interfaces_ns.h" +#include "val_framework.h" +#include "val_client_defs.h" +#include "val_internal_trusted_storage.h" + +/** + @brief - This API will call the requested internal trusted storage function + @param - type : function code + ... : variable number of arguments + @return - Error status +**/ +uint32_t val_its_function(int type, ...) +{ + va_list valist; + uint32_t status; + + va_start(valist, type); + status = pal_its_function(type, valist); + va_end(valist); + return status; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_internal_trusted_storage.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_internal_trusted_storage.h new file mode 100644 index 0000000..2f9384d --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_internal_trusted_storage.h @@ -0,0 +1,34 @@ +/** @file + * Copyright (c) 2019, 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 _VAL_INTERNAL_TRUSTED_STORAGE_H_ +#define _VAL_INTERNAL_TRUSTED_STORAGE_H_ + +#include "val.h" + +#define UID_BASE_VALUE 0 +#define BYTES_TO_BITS(byte) (byte * 8) + +enum its_function_code { + VAL_ITS_SET = 0x1, + VAL_ITS_GET = 0x2, + VAL_ITS_GET_INFO = 0x3, + VAL_ITS_REMOVE = 0x4, +}; + +uint32_t val_its_function(int type, ...); +#endif /* _VAL_INTERNAL_TRUSTED_STORAGE_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_protected_storage.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_protected_storage.c new file mode 100644 index 0000000..06c1f50 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_protected_storage.c @@ -0,0 +1,39 @@ +/** @file + * Copyright (c) 2019, 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_target.h" +#include "pal_interfaces_ns.h" +#include "val_framework.h" +#include "val_client_defs.h" +#include "val_protected_storage.h" + +/** + @brief - This API will call the requested protected storage function + @param - type : function code + ... : variable number of arguments + @return - Error status +**/ +uint32_t val_ps_function(int type, ...) +{ + va_list valist; + uint32_t status; + + va_start(valist, type); + status = pal_ps_function(type, valist); + va_end(valist); + return status; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_protected_storage.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_protected_storage.h new file mode 100644 index 0000000..7f05cea --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_protected_storage.h @@ -0,0 +1,37 @@ +/** @file + * Copyright (c) 2019, 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 _VAL_PROTECTED_STORAGE_H_ +#define _VAL_PROTECTED_STORAGE_H_ + +#include "val.h" + +#define UID_BASE_VALUE 0 +#define BYTES_TO_BITS(byte) (byte * 8) + +enum ps_function_code { + VAL_PS_SET = 0x1, + VAL_PS_GET = 0x2, + VAL_PS_GET_INFO = 0x3, + VAL_PS_REMOVE = 0x4, + VAL_PS_CREATE = 0x5, + VAL_PS_SET_EXTENDED = 0x6, + VAL_PS_GET_SUPPORT = 0x7, +}; + +uint32_t val_ps_function(int type, ...); +#endif /* _VAL_PROTECTED_STORAGE_H_ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_target.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_target.h new file mode 100644 index 0000000..1eb7a61 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/val/val_target.h @@ -0,0 +1,205 @@ +/** @file + * Copyright (c) 2018-2019, 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 _TARGET_INFO_DATA_H_ +#define _TARGET_INFO_DATA_H_ + +#include "val.h" + +#define TARGET_CONFIG_CREATE_ID(major, minor, index) \ + (((major & 0xFF) << 24) | ((minor & 0xFF) << 16) | (index & 0xFFFF)) +#define TARGET_CONFIG_GET_MAJOR(config_id) ((config_id >> 24) & 0xFF) +#define TARGET_CONFIG_GET_MINOR(config_id) ((config_id >> 16) & 0xFF) +#define TARGET_CONFIG_INCREMENT_INDEX(config_id) \ + ((config_id & 0xFFFF0000) | ((config_id & 0xFFFF) + 1)) +#define GET_NUM_INSTANCE(struct_type) (struct_type->cfg_type.size >> 24) +#define VAL_TEST_MAJOR_GROUP_MASK 0xFF000000UL +#define VAL_TEST_MINOR_GROUP_MASK 0x00FF0000UL +#define VAL_TEST_CFG_INSTANCE_MASK 0x0000FFFFUL +#define VAL_TEST_INVALID_CFG_ID 0xFFFFFFFFUL +#define TARGET_MIN_CFG_ID TARGET_CONFIG_CREATE_ID(GROUP_SOC_PERIPHERAL, 0, 0) +#define TARGET_MAX_CFG_ID TARGET_CONFIG_CREATE_ID(GROUP_MAX, 0, 0) + +/** + Config IDs for each group/component + 31:24 : MAJOR (group) + 23:16 : MINOR (component) + 16:8 : SUB-component + 7:0 : INSTANCE (instance of same component) +**/ + +/* + MAJOR IDs +*/ +typedef enum _GROUP_CONFIG_ID_ { + GROUP_SOC_PERIPHERAL = 0x1, + GROUP_MEMORY = 0x2, + GROUP_MISCELLANEOUS = 0x3, + GROUP_MAX = 0xFF, +} group_cfg_id_t; + +/* + MINOR IDs + */ +typedef enum _SOC_PERIPHERAL_CONFIG_ID_ { + SOC_PERIPHERAL_UART = 0x1, + SOC_PERIPHERAL_TIMER = 0x2, + SOC_PERIPHERAL_WATCHDOG = 0x3, +} soc_peripheral_cfg_id_t; + +typedef enum _MEMORY_CONFIG_ID_ { + MEMORY_NVMEM = 0x2, + MEMORY_NSPE_MMIO = 0x3, + MEMORY_CLIENT_PARTITION_MMIO = 0x4, + MEMORY_DRIVER_PARTITION_MMIO = 0x5, +} memory_cfg_id_t; + +typedef enum _MISCELLANEOUS_CONFIG_ID_ { + MISCELLANEOUS_BOOT = 0x1, + MISCELLANEOUS_DUT = 0x2 +} miscellaneous_cfg_id_t; + +/** + Assign group type to each system component +**/ +typedef enum _COMPONENT_GROUPING_ { + UART = GROUP_SOC_PERIPHERAL, + TIMER = GROUP_SOC_PERIPHERAL, + WATCHDOG = GROUP_SOC_PERIPHERAL, + NVMEM = GROUP_MEMORY, + NSPE_MMIO = GROUP_MEMORY, + CLIENT_PARTITION_MMIO = GROUP_MEMORY, + DRIVER_PARTITION_MMIO = GROUP_MEMORY, + BOOT = GROUP_MISCELLANEOUS, + DUT = GROUP_MISCELLANEOUS, +} comp_group_assign_t; + +/** + Target Configuration Header +**/ +typedef struct _TARGET_CFG_HDR_ { + /* PSA_CFG */ + uint32_t signature[2]; + /* 8 byte String describing the Target platform */ + uint32_t target_string[2]; + /* version = 1 for now */ + uint32_t version; + /* Header Size */ + uint32_t size; +} target_cfg_hdr_t; + +typedef enum { + LEVEL1 = 0x1, + LEVEL2, + LEVEL3, +} firmware_level_t; + +typedef enum { + NOT_AVAILABLE = 0x0, + AVAILABLE = 0x1, +} is_available_t; + +typedef enum { + SECURE_ACCESS = 0x100, + NONSECURE_ACCESS, + SECURE_PROGRAMMABLE, + NONSECURE_PROGRAMMABLE +} dev_attr_t; + +typedef enum { + MEM_SECURE = 0x100, + MEM_NONSECURE, + MEM_NSC, +} mem_tgt_attr_t; + +typedef enum { + TYPE_READ_ONLY = 0x10, + TYPE_WRITE_ONLY, + TYPE_READ_WRITE, + TYPE_EXECUTE, + TYPE_RESERVED, +} perm_type_t; + +typedef struct _CFG_HDR_TYPE_ { + cfg_id_t cfg_id; + /* size inclusive of this header */ + uint32_t size; +} cfg_type_t; + +/** + Memory Information +**/ +typedef struct _MEM_INFO_DESC_ { + cfg_type_t cfg_type; + uint32_t num; +} memory_hdr_t; + +typedef struct _MEM_REGION_ { + cfg_type_t cfg_type; + addr_t start; + addr_t end; + mem_tgt_attr_t attribute; + perm_type_t permission; +} memory_desc_t; + +/* + SOC Peripheral description structures +*/ +typedef struct _SOC_PER_INFO_NUM_ { + cfg_type_t cfg_type; + uint32_t num; +} soc_peripheral_hdr_t; + +typedef struct _SOC_PER_INFO_DESC_ { + cfg_type_t cfg_type; + uint32_t vendor_id; + uint32_t device_id; + addr_t base; + uint32_t size; + uint32_t intr_id; + perm_type_t permission; + uint32_t timeout_in_micro_sec_low; + uint32_t timeout_in_micro_sec_medium; + uint32_t timeout_in_micro_sec_high; + uint32_t timeout_in_micro_sec_crypto; + uint32_t num_of_tick_per_micro_sec; + dev_attr_t attribute; +} soc_peripheral_desc_t; + +/** + System Miscellaneous Information +**/ + +typedef struct _MISCELLANEOUS_INFO_HDR_ { + cfg_type_t cfg_type; + uint32_t num; +} miscellaneous_hdr_t; + +typedef struct _MISCELLANEOUS_INFO_DESC_ { + cfg_type_t cfg_type; + firmware_level_t implemented_psa_firmware_isolation_level; + addr_t ns_start_addr_of_combine_test_binary; + is_available_t combine_test_binary_in_ram; + addr_t ns_test_addr; +} miscellaneous_desc_t; + +/*val target config read apis */ +STATIC_DECLARE val_status_t val_target_get_config(cfg_id_t cfg_id, uint8_t **data, uint32_t *size); +STATIC_DECLARE val_status_t val_target_cfg_get_next(void **blob); +STATIC_DECLARE val_status_t val_target_get_cfg_blob(cfg_id_t cfg_id, uint8_t **data, uint32_t *size); +STATIC_DECLARE val_status_t val_target_get_config(cfg_id_t cfg_id, uint8_t **data, uint32_t *size); +#endif diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/platform_multicore.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/platform_multicore.c new file mode 100644 index 0000000..e860ae0 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/platform_multicore.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2019 Arm Limited. All rights reserved. + * Copyright (c) 2019 Cypress Semiconductor Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "cmsis_compiler.h" + +#include "platform_multicore.h" +#include "tfm_multi_core_api.h" +#include "tfm_ns_mailbox.h" + +#include "cy_ipc_drv.h" +#include "cy_sysint.h" +#if CY_SYSTEM_CPU_CM0P +#include "spe_ipc_config.h" +#else +#include "ns_ipc_config.h" +#endif + +int platform_mailbox_fetch_msg_ptr(void **msg_ptr) +{ + cy_en_ipcdrv_status_t status; + + if (!msg_ptr) { + return PLATFORM_MAILBOX_INVAL_PARAMS; + } + + status = Cy_IPC_Drv_ReadMsgPtr(Cy_IPC_Drv_GetIpcBaseAddress(IPC_RX_CHAN), + msg_ptr); + if (status != CY_IPC_DRV_SUCCESS) { + return PLATFORM_MAILBOX_RX_ERROR; + } + + Cy_IPC_Drv_ReleaseNotify(Cy_IPC_Drv_GetIpcBaseAddress(IPC_RX_CHAN), + IPC_RX_RELEASE_MASK); + return PLATFORM_MAILBOX_SUCCESS; +} + +int platform_mailbox_fetch_msg_data(uint32_t *data_ptr) +{ + cy_en_ipcdrv_status_t status; + + if (!data_ptr) { + return PLATFORM_MAILBOX_INVAL_PARAMS; + } + + status = Cy_IPC_Drv_ReadMsgWord(Cy_IPC_Drv_GetIpcBaseAddress(IPC_RX_CHAN), + data_ptr); + if (status != CY_IPC_DRV_SUCCESS) { + return PLATFORM_MAILBOX_RX_ERROR; + } + + Cy_IPC_Drv_ReleaseNotify(Cy_IPC_Drv_GetIpcBaseAddress(IPC_RX_CHAN), + IPC_RX_RELEASE_MASK); + return PLATFORM_MAILBOX_SUCCESS; +} + +int platform_mailbox_send_msg_ptr(const void *msg_ptr) +{ + cy_en_ipcdrv_status_t status; + + if (!msg_ptr) + return PLATFORM_MAILBOX_INVAL_PARAMS; + + status = Cy_IPC_Drv_SendMsgPtr(Cy_IPC_Drv_GetIpcBaseAddress(IPC_TX_CHAN), + IPC_TX_NOTIFY_MASK, msg_ptr); + if (status != CY_IPC_DRV_SUCCESS) { + return PLATFORM_MAILBOX_TX_ERROR; + } + + return PLATFORM_MAILBOX_SUCCESS; +} + +int platform_mailbox_send_msg_data(uint32_t data) +{ + cy_en_ipcdrv_status_t status; + + status = Cy_IPC_Drv_SendMsgWord(Cy_IPC_Drv_GetIpcBaseAddress(IPC_TX_CHAN), + IPC_TX_NOTIFY_MASK, data); + if (status != CY_IPC_DRV_SUCCESS) { + return PLATFORM_MAILBOX_TX_ERROR; + } + + return PLATFORM_MAILBOX_SUCCESS; +} + +void platform_mailbox_wait_for_notify(void) +{ + uint32_t status; + + while (1) { + status = Cy_IPC_Drv_GetInterruptStatusMasked( + Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT)); + status >>= CY_IPC_NOTIFY_SHIFT; + if (status & IPC_RX_INT_MASK) { + break; + } + } + + Cy_IPC_Drv_ClearInterrupt(Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT), + 0, IPC_RX_INT_MASK); +} + +int platform_ns_ipc_init(void) +{ + Cy_IPC_Drv_SetInterruptMask(Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT), + 0, IPC_RX_INT_MASK); + return PLATFORM_MAILBOX_SUCCESS; +} + +int32_t tfm_platform_ns_wait_for_s_cpu_ready(void) +{ + uint32_t data = 0; + + if (platform_ns_ipc_init() != PLATFORM_MAILBOX_SUCCESS) { + return PLATFORM_MAILBOX_INVAL_PARAMS; + } + while(data != IPC_SYNC_MAGIC) + { + platform_mailbox_wait_for_notify(); + platform_mailbox_fetch_msg_data(&data); + } + + if (platform_mailbox_send_msg_data(~IPC_SYNC_MAGIC) != + PLATFORM_MAILBOX_SUCCESS) { + return PLATFORM_MAILBOX_RX_ERROR; + } + return PLATFORM_MAILBOX_SUCCESS; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/platform_ns_mailbox.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/platform_ns_mailbox.c new file mode 100644 index 0000000..dc94e63 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/platform_ns_mailbox.c @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * Copyright (c) 2019, Cypress Semiconductor Corporation. All rights reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* -------------------------------------- Includes ----------------------------------- */ +#include +#include + +#include "cmsis_compiler.h" + +#include "cy_ipc_drv.h" +#include "cy_sysint.h" + +#include "ns_ipc_config.h" +#include "tfm_ns_mailbox.h" +#include "platform_multicore.h" +#include "cmsis_os2.h" + +static uint8_t saved_irq_state = 1; + +/* -------------------------------------- HAL API ------------------------------------ */ + +static void mailbox_ipc_init(void) +{ + Cy_IPC_Drv_SetInterruptMask(Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT), + 0, IPC_RX_INT_MASK); +} + +static void mailbox_ipc_config(void) +{ + NVIC_SetPriority(PSA_CLIENT_REPLY_NVIC_IRQn, PSA_CLIENT_REPLY_IRQ_PRIORITY); + + NVIC_EnableIRQ(PSA_CLIENT_REPLY_NVIC_IRQn); +} + +int32_t tfm_ns_mailbox_hal_notify_peer(void) +{ + cy_en_ipcdrv_status_t status; + + status = Cy_IPC_Drv_SendMsgWord(Cy_IPC_Drv_GetIpcBaseAddress(IPC_TX_CHAN), + IPC_TX_NOTIFY_MASK, + PSA_CLIENT_CALL_REQ_MAGIC); + + if (status == CY_IPC_DRV_SUCCESS) { + return MAILBOX_SUCCESS; + } else { + return MAILBOX_CHAN_BUSY; + } +} + +int32_t tfm_ns_mailbox_hal_init(struct ns_mailbox_queue_t *queue) +{ + uint32_t stage; + + if (!queue) { + return MAILBOX_INVAL_PARAMS; + } + + /* + * FIXME + * Further verification of mailbox queue address may be required according + * to diverse NSPE implementations. + */ + + mailbox_ipc_init(); + + /* + * Wait until SPE mailbox library is ready to receive NSPE mailbox queue + * address. + */ + while (1) { + platform_mailbox_wait_for_notify(); + + platform_mailbox_fetch_msg_data(&stage); + if (stage == NS_MAILBOX_INIT_ENABLE) { + break; + } + } + + /* Send out the address */ + platform_mailbox_send_msg_ptr(queue); + + /* Wait until SPE mailbox service is ready */ + while (1) { + platform_mailbox_wait_for_notify(); + + platform_mailbox_fetch_msg_data(&stage); + if (stage == S_MAILBOX_READY) { + break; + } + } + + mailbox_ipc_config(); + + return MAILBOX_SUCCESS; +} + +const void *tfm_ns_mailbox_get_task_handle(void) +{ + return osThreadGetId(); +} + +void tfm_ns_mailbox_hal_wait_reply(mailbox_msg_handle_t handle) +{ + osThreadFlagsWait(handle, osFlagsWaitAll, osWaitForever); +} + +void tfm_ns_mailbox_hal_enter_critical(void) +{ + saved_irq_state = Cy_SysLib_EnterCriticalSection(); + + IPC_STRUCT_Type* ipc_struct = + Cy_IPC_Drv_GetIpcBaseAddress(IPC_PSA_MAILBOX_LOCK_CHAN); + while(CY_IPC_DRV_SUCCESS != Cy_IPC_Drv_LockAcquire (ipc_struct)) + { + } +} + +void tfm_ns_mailbox_hal_exit_critical(void) +{ + IPC_STRUCT_Type* ipc_struct = + Cy_IPC_Drv_GetIpcBaseAddress(IPC_PSA_MAILBOX_LOCK_CHAN); + Cy_IPC_Drv_LockRelease(ipc_struct, CY_IPC_NO_NOTIFICATION); + Cy_SysLib_ExitCriticalSection(saved_irq_state); +} + +void tfm_ns_mailbox_hal_enter_critical_isr(void) +{ + IPC_STRUCT_Type* ipc_struct = + Cy_IPC_Drv_GetIpcBaseAddress(IPC_PSA_MAILBOX_LOCK_CHAN); + while(CY_IPC_DRV_SUCCESS != Cy_IPC_Drv_LockAcquire (ipc_struct)) + { + } +} + +void tfm_ns_mailbox_hal_exit_critical_isr(void) +{ + IPC_STRUCT_Type* ipc_struct = + Cy_IPC_Drv_GetIpcBaseAddress(IPC_PSA_MAILBOX_LOCK_CHAN); + Cy_IPC_Drv_LockRelease(ipc_struct, CY_IPC_NO_NOTIFICATION); +} + +static bool mailbox_clear_intr(void) +{ + uint32_t status; + + status = Cy_IPC_Drv_GetInterruptStatusMasked( + Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT)); + status >>= CY_IPC_NOTIFY_SHIFT; + if ((status & IPC_RX_INT_MASK) == 0) { + return false; + } + + Cy_IPC_Drv_ClearInterrupt(Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT), + 0, IPC_RX_INT_MASK); + return true; +} + +void cpuss_interrupts_ipc_8_IRQHandler(void) +{ + uint32_t magic; + mailbox_msg_handle_t handle; + osThreadId_t task_handle; + + if (!mailbox_clear_intr()) + return; + + platform_mailbox_fetch_msg_data(&magic); + if (magic == PSA_CLIENT_CALL_REPLY_MAGIC) { + /* Handle all the pending replies */ + while (1) { + handle = tfm_ns_mailbox_fetch_reply_msg_isr(); + if (handle == MAILBOX_MSG_NULL_HANDLE) { + break; + } + + task_handle = (osThreadId_t)tfm_ns_mailbox_get_msg_owner(handle); + if (task_handle) { + osThreadFlagsSet(task_handle, handle); + } + } + } +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_mbed_boot.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_mbed_boot.c new file mode 100644 index 0000000..c8d595f --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_mbed_boot.c @@ -0,0 +1,67 @@ +/* mbed Microcontroller Library + * Copyright (c) 2020 ARM Limited + * 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 "mbed_error.h" +#include "tfm_multi_core_api.h" +#include "tfm_ns_mailbox.h" +#include "platform_multicore.h" +#include "tfm_ns_interface.h" + +static struct ns_mailbox_queue_t ns_mailbox_queue; + +void mbed_tfm_init(void) +{ + /* + * In case the of dual CPU, we need to initialize IPC, mailbox + * and NS interface after the RTOS has started to enable + * communication from Secure and Non-Secure cores. + */ + int32_t ret; + + ret = tfm_ns_wait_for_s_cpu_ready(); + /* + * Normally would expect "TFM_SUCCESS" returned here by TF-M, as this + * isn't a mailbox function. There may be some platforms other than PSoC6, + * which doesn't require tfm_ns_wait_for_s_cpu_ready() implementation. + * "PLATFORM_MAILBOX_SUCCESS" is a low-level error code and should be + * replaced by "TFM_SUCCESS". + * As the function definition has been imported from the TF-M, therefore + * a issue has been raised - https://developer.trustedfirmware.org/T660 + */ + if (ret != PLATFORM_MAILBOX_SUCCESS) { + /* Avoid undefined behavior after multi-core sync-up failed */ + MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, + MBED_ERROR_CODE_INITIALIZATION_FAILED), + "Failed to sync-up multi-core"); + } + + ret = tfm_ns_mailbox_init(&ns_mailbox_queue); + if (ret != MAILBOX_SUCCESS) { + /* Avoid undefined behavior after NS mailbox initialization failed */ + MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, + MBED_ERROR_CODE_INITIALIZATION_FAILED), + "Failed to initialize NS mailbox"); + } + + ret = tfm_ns_interface_init(); + if (ret != TFM_SUCCESS) { + /* Avoid undefined behavior after NS interface initialization failed */ + MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, + MBED_ERROR_CODE_INITIALIZATION_FAILED), + "Failed to initialize NS interface"); + } +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_multi_core_api.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_multi_core_api.c new file mode 100644 index 0000000..231e895 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_multi_core_api.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "tfm_api.h" +#include "tfm_mailbox.h" +#include "tfm_multi_core_api.h" +#include "cmsis_os2.h" +#include "mbed_rtos_storage.h" + +#define MAX_SEMAPHORE_COUNT NUM_MAILBOX_QUEUE_SLOT + +static void *ns_lock_handle = NULL; +static mbed_rtos_storage_semaphore_t tfm_ns_sema_obj; + +__attribute__((weak)) +enum tfm_status_e tfm_ns_interface_init(void) +{ + osSemaphoreAttr_t sema_attrib = { + .name = "tfm_ns_lock", + .attr_bits = 0, + .cb_size = sizeof(tfm_ns_sema_obj), + .cb_mem = &tfm_ns_sema_obj + }; + + ns_lock_handle = osSemaphoreNew(MAX_SEMAPHORE_COUNT, + MAX_SEMAPHORE_COUNT, + &sema_attrib); + if (!ns_lock_handle) { + return TFM_ERROR_GENERIC; + } + + return TFM_SUCCESS; +} + +int32_t tfm_ns_wait_for_s_cpu_ready(void) +{ + return tfm_platform_ns_wait_for_s_cpu_ready(); +} + +uint32_t tfm_ns_multi_core_lock_acquire(void) +{ + return osSemaphoreAcquire(ns_lock_handle, osWaitForever); +} + +uint32_t tfm_ns_multi_core_lock_release(void) +{ + return osSemaphoreRelease(ns_lock_handle); +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_multi_core_psa_ns_api.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_multi_core_psa_ns_api.c new file mode 100644 index 0000000..fae580e --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_multi_core_psa_ns_api.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include + +#include "psa/client.h" +#include "psa/error.h" +#include "tfm_api.h" +#include "tfm_multi_core_api.h" +#include "tfm_ns_mailbox.h" + +/* + * TODO + * Currently, force all the non-secure client to share the same ID. + * + * It requires a more clear mechanism to synchronize the non-secure client + * ID with SPE in dual core scenario. + * In current design, the value is transferred to SPE via mailbox message. + * A dedicated routine to receive the non-secure client information in + * TF-M core/SPM in dual core scenario should be added besides current + * implementation for single Armv8-M. + * The non-secure client identification is shared with SPE in + * single Armv8-M scenario via CMSIS TrustZone context management API, + * which may not work in dual core scenario. + */ +#define NON_SECURE_CLIENT_ID (1) + +/* + * TODO + * Require a formal definition of errors related to mailbox in PSA client call. + */ +#define PSA_INTER_CORE_COMM_ERR (INT32_MIN + 0xFF) + +static void mailbox_wait_reply(mailbox_msg_handle_t handle) +{ + /* + * If the system can support multiple outstanding NS PSA Client calls, call + * tfm_ns_mailbox_wait_reply() to sleep and wait for reply. The NS side + * should implement tfm_ns_mailbox_hal_wait_reply() and wake-up mechanism. + * Otherwise, by default, call tfm_ns_mailbox_is_msg_replied() to simply + * poll the reply status of the mailbox message of current thread. + */ +#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL + tfm_ns_mailbox_wait_reply(handle); +#else + while (!tfm_ns_mailbox_is_msg_replied(handle)) { + } +#endif +} + +/**** API functions ****/ + +uint32_t psa_framework_version(void) +{ + struct psa_client_params_t params; + mailbox_msg_handle_t handle; + uint32_t version; + int32_t ret; + + if (tfm_ns_multi_core_lock_acquire() != 0) { + return PSA_VERSION_NONE; + } + + handle = tfm_ns_mailbox_tx_client_req(MAILBOX_PSA_FRAMEWORK_VERSION, + ¶ms, NON_SECURE_CLIENT_ID); + if (handle < 0) { + tfm_ns_multi_core_lock_release(); + return PSA_VERSION_NONE; + } + + mailbox_wait_reply(handle); + + ret = tfm_ns_mailbox_rx_client_reply(handle, (int32_t *)&version); + if (ret != MAILBOX_SUCCESS) { + version = PSA_VERSION_NONE; + } + + if (tfm_ns_multi_core_lock_release() != 0) { + return PSA_VERSION_NONE; + } + + return version; +} + +uint32_t psa_version(uint32_t sid) +{ + struct psa_client_params_t params; + mailbox_msg_handle_t handle; + uint32_t version; + int32_t ret; + + params.psa_version_params.sid = sid; + + if (tfm_ns_multi_core_lock_acquire() != 0) { + return PSA_VERSION_NONE; + } + + handle = tfm_ns_mailbox_tx_client_req(MAILBOX_PSA_VERSION, ¶ms, + NON_SECURE_CLIENT_ID); + if (handle < 0) { + tfm_ns_multi_core_lock_release(); + return PSA_VERSION_NONE; + } + + mailbox_wait_reply(handle); + + ret = tfm_ns_mailbox_rx_client_reply(handle, (int32_t *)&version); + if (ret != MAILBOX_SUCCESS) { + version = PSA_VERSION_NONE; + } + + if (tfm_ns_multi_core_lock_release() != 0) { + return PSA_VERSION_NONE; + } + + return version; +} + +psa_handle_t psa_connect(uint32_t sid, uint32_t version) +{ + struct psa_client_params_t params; + mailbox_msg_handle_t handle; + psa_handle_t psa_handle; + int32_t ret; + + params.psa_connect_params.sid = sid; + params.psa_connect_params.version = version; + + if (tfm_ns_multi_core_lock_acquire() != 0) { + return PSA_NULL_HANDLE; + } + + handle = tfm_ns_mailbox_tx_client_req(MAILBOX_PSA_CONNECT, ¶ms, + NON_SECURE_CLIENT_ID); + if (handle < 0) { + tfm_ns_multi_core_lock_release(); + return PSA_NULL_HANDLE; + } + + mailbox_wait_reply(handle); + + ret = tfm_ns_mailbox_rx_client_reply(handle, (int32_t *)&psa_handle); + if (ret != MAILBOX_SUCCESS) { + psa_handle = PSA_NULL_HANDLE; + } + + if (tfm_ns_multi_core_lock_release() != 0) { + return PSA_NULL_HANDLE; + } + + return psa_handle; +} + +psa_status_t psa_call(psa_handle_t handle, int32_t type, + const psa_invec *in_vec, size_t in_len, + psa_outvec *out_vec, size_t out_len) +{ + struct psa_client_params_t params; + mailbox_msg_handle_t msg_handle; + int32_t ret; + psa_status_t status; + + params.psa_call_params.handle = handle; + params.psa_call_params.type = type; + params.psa_call_params.in_vec = in_vec; + params.psa_call_params.in_len = in_len; + params.psa_call_params.out_vec = out_vec; + params.psa_call_params.out_len = out_len; + + if (tfm_ns_multi_core_lock_acquire() != 0) { + return PSA_ERROR_GENERIC_ERROR; + } + + msg_handle = tfm_ns_mailbox_tx_client_req(MAILBOX_PSA_CALL, ¶ms, + NON_SECURE_CLIENT_ID); + if (msg_handle < 0) { + tfm_ns_multi_core_lock_release(); + return PSA_INTER_CORE_COMM_ERR; + } + + mailbox_wait_reply(msg_handle); + + ret = tfm_ns_mailbox_rx_client_reply(msg_handle, (int32_t *)&status); + if (ret != MAILBOX_SUCCESS) { + status = PSA_INTER_CORE_COMM_ERR; + } + + if (tfm_ns_multi_core_lock_release() != 0) { + return PSA_ERROR_GENERIC_ERROR; + } + + return status; +} + +void psa_close(psa_handle_t handle) +{ + struct psa_client_params_t params; + mailbox_msg_handle_t msg_handle; + int32_t reply; + + params.psa_close_params.handle = handle; + + if (tfm_ns_multi_core_lock_acquire() != 0) { + return; + } + + msg_handle = tfm_ns_mailbox_tx_client_req(MAILBOX_PSA_CLOSE, ¶ms, + NON_SECURE_CLIENT_ID); + if (msg_handle < 0) { + tfm_ns_multi_core_lock_release(); + return; + } + + mailbox_wait_reply(msg_handle); + + (void)tfm_ns_mailbox_rx_client_reply(msg_handle, &reply); + + tfm_ns_multi_core_lock_release(); +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_ns_mailbox.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_ns_mailbox.c new file mode 100644 index 0000000..f7326f0 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_ns_mailbox.c @@ -0,0 +1,425 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include "tfm_ns_mailbox.h" + +/* The pointer to NSPE mailbox queue */ +static struct ns_mailbox_queue_t *mailbox_queue_ptr = NULL; + +static inline void clear_queue_slot_empty(uint8_t idx) +{ + if (idx < NUM_MAILBOX_QUEUE_SLOT) { + mailbox_queue_ptr->empty_slots &= ~(1 << idx); + } +} + +static inline void set_queue_slot_empty(uint8_t idx) +{ + if (idx < NUM_MAILBOX_QUEUE_SLOT) { + mailbox_queue_ptr->empty_slots |= (1 << idx); + } +} + +static inline void set_queue_slot_pend(uint8_t idx) +{ + if (idx < NUM_MAILBOX_QUEUE_SLOT) { + mailbox_queue_ptr->pend_slots |= (1 << idx); + } +} + +static inline int32_t get_mailbox_msg_handle(uint8_t idx, + mailbox_msg_handle_t *handle) +{ + if ((idx >= NUM_MAILBOX_QUEUE_SLOT) || !handle) { + return MAILBOX_INVAL_PARAMS; + } + + *handle = (mailbox_msg_handle_t)(idx + 1); + + return MAILBOX_SUCCESS; +} + +static inline int32_t get_mailbox_msg_idx(mailbox_msg_handle_t handle, + uint8_t *idx) +{ + if ((handle == MAILBOX_MSG_NULL_HANDLE) || !idx) { + return MAILBOX_INVAL_PARAMS; + } + + *idx = (uint8_t)(handle - 1); + + return MAILBOX_SUCCESS; +} + +static inline void clear_queue_slot_replied(uint8_t idx) +{ + if (idx < NUM_MAILBOX_QUEUE_SLOT) { + mailbox_queue_ptr->replied_slots &= ~(1 << idx); + } +} + +static inline void set_queue_slot_woken(uint8_t idx) +{ + if (idx < NUM_MAILBOX_QUEUE_SLOT) { + mailbox_queue_ptr->queue[idx].is_woken = true; + } +} + +static inline bool is_queue_slot_woken(uint8_t idx) +{ + if (idx < NUM_MAILBOX_QUEUE_SLOT) { + return mailbox_queue_ptr->queue[idx].is_woken; + } + + return false; +} + +static inline void clear_queue_slot_woken(uint8_t idx) +{ + if (idx < NUM_MAILBOX_QUEUE_SLOT) { + mailbox_queue_ptr->queue[idx].is_woken = false; + } +} + +static uint8_t acquire_empty_slot(const struct ns_mailbox_queue_t *queue) +{ + uint8_t idx; + mailbox_queue_status_t status; + + tfm_ns_mailbox_hal_enter_critical(); + status = queue->empty_slots; + + if (!status) { + /* No empty slot */ + tfm_ns_mailbox_hal_exit_critical(); + return NUM_MAILBOX_QUEUE_SLOT; + } + + for (idx = 0; idx < NUM_MAILBOX_QUEUE_SLOT; idx++) { + if (status & (1 << idx)) { + break; + } + } + + clear_queue_slot_empty(idx); + + tfm_ns_mailbox_hal_exit_critical(); + + return idx; +} + +static void set_msg_owner(uint8_t idx, const void *owner) +{ + if (idx < NUM_MAILBOX_QUEUE_SLOT) { + mailbox_queue_ptr->queue[idx].owner = owner; + } +} + +#ifdef TFM_MULTI_CORE_TEST +void tfm_ns_mailbox_tx_stats_init(void) +{ + if (!mailbox_queue_ptr) { + return; + } + + tfm_ns_mailbox_hal_enter_critical(); + + mailbox_queue_ptr->nr_tx = 0; + mailbox_queue_ptr->nr_used_slots = 0; + + tfm_ns_mailbox_hal_exit_critical(); +} + +static void mailbox_tx_stats_update(struct ns_mailbox_queue_t *ns_queue) +{ + mailbox_queue_status_t empty_status; + uint8_t idx, nr_empty = 0; + + if (!ns_queue) { + return; + } + + tfm_ns_mailbox_hal_enter_critical(); + + ns_queue->nr_tx++; + + /* Count the number of used slots when this tx arrives */ + empty_status = ns_queue->empty_slots; + tfm_ns_mailbox_hal_exit_critical(); + + if (empty_status) { + for (idx = 0; idx < NUM_MAILBOX_QUEUE_SLOT; idx++) { + if (empty_status & (0x1UL << idx)) { + nr_empty++; + } + } + } + + tfm_ns_mailbox_hal_enter_critical(); + ns_queue->nr_used_slots += (NUM_MAILBOX_QUEUE_SLOT - nr_empty); + tfm_ns_mailbox_hal_exit_critical(); +} + +void tfm_ns_mailbox_stats_avg_slot(struct ns_mailbox_stats_res_t *stats_res) +{ + uint32_t nr_used_slots, nr_tx; + + if (!mailbox_queue_ptr || !stats_res) { + return; + } + + tfm_ns_mailbox_hal_enter_critical(); + nr_used_slots = mailbox_queue_ptr->nr_used_slots; + nr_tx = mailbox_queue_ptr->nr_tx; + tfm_ns_mailbox_hal_exit_critical(); + + stats_res->avg_nr_slots = nr_used_slots / nr_tx; + nr_used_slots %= nr_tx; + stats_res->avg_nr_slots_tenths = nr_used_slots * 10 / nr_tx; +} +#endif + +mailbox_msg_handle_t tfm_ns_mailbox_tx_client_req(uint32_t call_type, + const struct psa_client_params_t *params, + int32_t client_id) +{ + uint8_t idx; + struct mailbox_msg_t *msg_ptr; + mailbox_msg_handle_t handle; + const void *task_handle; + + if (!mailbox_queue_ptr) { + return MAILBOX_MSG_NULL_HANDLE; + } + + if (!params) { + return MAILBOX_MSG_NULL_HANDLE; + } + + idx = acquire_empty_slot(mailbox_queue_ptr); + if (idx >= NUM_MAILBOX_QUEUE_SLOT) { + return MAILBOX_QUEUE_FULL; + } + +#ifdef TFM_MULTI_CORE_TEST + mailbox_tx_stats_update(mailbox_queue_ptr); +#endif + + /* Fill the mailbox message */ + msg_ptr = &mailbox_queue_ptr->queue[idx].msg; + + msg_ptr->call_type = call_type; + memcpy(&msg_ptr->params, params, sizeof(msg_ptr->params)); + msg_ptr->client_id = client_id; + + /* + * Fetch the current task handle. The task will be woken up according the + * handle value set in the owner field. + */ + task_handle = tfm_ns_mailbox_get_task_handle(); + set_msg_owner(idx, task_handle); + + get_mailbox_msg_handle(idx, &handle); + + tfm_ns_mailbox_hal_enter_critical(); + set_queue_slot_pend(idx); + tfm_ns_mailbox_hal_exit_critical(); + + tfm_ns_mailbox_hal_notify_peer(); + + return handle; +} + +int32_t tfm_ns_mailbox_rx_client_reply(mailbox_msg_handle_t handle, + int32_t *reply) +{ + uint8_t idx; + int32_t ret; + + if (!mailbox_queue_ptr) { + return MAILBOX_INVAL_PARAMS; + } + + if ((handle == MAILBOX_MSG_NULL_HANDLE) || (!reply)) { + return MAILBOX_INVAL_PARAMS; + } + + ret = get_mailbox_msg_idx(handle, &idx); + if (ret != MAILBOX_SUCCESS) { + return ret; + } + + *reply = mailbox_queue_ptr->queue[idx].reply.return_val; + + /* Clear up the owner field */ + set_msg_owner(idx, NULL); + + tfm_ns_mailbox_hal_enter_critical(); + clear_queue_slot_replied(idx); + clear_queue_slot_woken(idx); + /* + * Make sure that the empty flag is set after all the other status flags are + * re-initialized. + */ + set_queue_slot_empty(idx); + tfm_ns_mailbox_hal_exit_critical(); + + return MAILBOX_SUCCESS; +} + +bool tfm_ns_mailbox_is_msg_replied(mailbox_msg_handle_t handle) +{ + uint8_t idx; + int32_t ret; + mailbox_queue_status_t status; + + if (!mailbox_queue_ptr) { + return false; + } + + if (handle == MAILBOX_MSG_NULL_HANDLE) { + return false; + } + + ret = get_mailbox_msg_idx(handle, &idx); + if (ret != MAILBOX_SUCCESS) { + return false; + } + + tfm_ns_mailbox_hal_enter_critical(); + status = mailbox_queue_ptr->replied_slots; + tfm_ns_mailbox_hal_exit_critical(); + + if (status & (1 << idx)) { + return true; + } + + return false; +} + +mailbox_msg_handle_t tfm_ns_mailbox_fetch_reply_msg_isr(void) +{ + uint8_t idx; + mailbox_msg_handle_t handle; + mailbox_queue_status_t replied_status; + + if (!mailbox_queue_ptr) { + return MAILBOX_MSG_NULL_HANDLE; + } + + tfm_ns_mailbox_hal_enter_critical_isr(); + replied_status = mailbox_queue_ptr->replied_slots; + tfm_ns_mailbox_hal_exit_critical_isr(); + + if (!replied_status) { + return MAILBOX_MSG_NULL_HANDLE; + } + + for (idx = 0; idx < NUM_MAILBOX_QUEUE_SLOT; idx++) { + /* Find the first replied message in queue */ + if (replied_status & (0x1UL << idx)) { + tfm_ns_mailbox_hal_enter_critical_isr(); + clear_queue_slot_replied(idx); + set_queue_slot_woken(idx); + tfm_ns_mailbox_hal_exit_critical_isr(); + + if (get_mailbox_msg_handle(idx, &handle) == MAILBOX_SUCCESS) { + return handle; + } + } + } + + return MAILBOX_MSG_NULL_HANDLE; +} + +const void *tfm_ns_mailbox_get_msg_owner(mailbox_msg_handle_t handle) +{ + uint8_t idx; + + if (get_mailbox_msg_idx(handle, &idx) != MAILBOX_SUCCESS) { + return NULL; + } + + if (idx < NUM_MAILBOX_QUEUE_SLOT) { + return mailbox_queue_ptr->queue[idx].owner; + } + + return NULL; +} + +int32_t tfm_ns_mailbox_init(struct ns_mailbox_queue_t *queue) +{ + int32_t ret; + + if (!queue) { + return MAILBOX_INVAL_PARAMS; + } + + /* + * Further verification of mailbox queue address may be required according + * to non-secure memory assignment. + */ + + memset(queue, 0, sizeof(*queue)); + + /* Initialize empty bitmask */ + queue->empty_slots = + (mailbox_queue_status_t)((1UL << (NUM_MAILBOX_QUEUE_SLOT - 1)) - 1); + queue->empty_slots += + (mailbox_queue_status_t)(1UL << (NUM_MAILBOX_QUEUE_SLOT - 1)); + + mailbox_queue_ptr = queue; + + /* Platform specific initialization. */ + ret = tfm_ns_mailbox_hal_init(queue); + +#ifdef TFM_MULTI_CORE_TEST + tfm_ns_mailbox_tx_stats_init(); +#endif + + return ret; +} + +#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL +int32_t tfm_ns_mailbox_wait_reply(mailbox_msg_handle_t handle) +{ + uint8_t idx; + int32_t ret; + + if (!mailbox_queue_ptr) { + return MAILBOX_INVAL_PARAMS; + } + + if (handle == MAILBOX_MSG_NULL_HANDLE) { + return MAILBOX_INVAL_PARAMS; + } + + ret = get_mailbox_msg_idx(handle, &idx); + if (ret != MAILBOX_SUCCESS) { + return ret; + } + + while (1) { + tfm_ns_mailbox_hal_wait_reply(handle); + + /* + * Woken up from sleep + * Check the completed flag to make sure that the current thread is + * woken up by reply event, rather than other events. + */ + tfm_ns_mailbox_hal_enter_critical(); + if (is_queue_slot_woken(idx)) { + tfm_ns_mailbox_hal_exit_critical(); + break; + } + tfm_ns_mailbox_hal_exit_critical(); + } + + return MAILBOX_SUCCESS; +} +#endif diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/cmsis_nvic_virtual.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/cmsis_nvic_virtual.c new file mode 100644 index 0000000..bee8597 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/cmsis_nvic_virtual.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2019-2020 Arm Limited + * + * 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 "cmsis_nvic_virtual.h" +#include "tfm_platform_api.h" + +void NVIC_SystemReset(void) +{ + tfm_platform_system_reset(); +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/tfm_mbed_boot.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/tfm_mbed_boot.c new file mode 100644 index 0000000..87bcbbb --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/tfm_mbed_boot.c @@ -0,0 +1,37 @@ +/* mbed Microcontroller Library + * Copyright (c) 2020 ARM Limited + * 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 "mbed_error.h" +#include "tfm_ns_interface.h" + +void mbed_tfm_init(void) +{ + /* + * In case of V8-M, we need to initialize NS interface + * after the RTOS has started to enable + * communication from Secure and Non-Secure cores. + */ + int32_t ret; + + ret = tfm_ns_interface_init(); + if (ret != TFM_SUCCESS) { + /* Avoid undefined behavior after NS interface initialization failed */ + MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, + MBED_ERROR_CODE_INITIALIZATION_FAILED), + "Failed to initialize NS interface"); + } +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/tfm_ns_interface.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/tfm_ns_interface.c new file mode 100644 index 0000000..9759145 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/tfm_ns_interface.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2017-2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +#include +#include + +#include "tfm_api.h" +#include "tfm_ns_interface.h" +#include "cmsis_os2.h" + +/** + * \brief the ns_lock ID + */ +static osMutexId_t ns_lock_handle = NULL; + +__attribute__((weak)) +int32_t tfm_ns_interface_dispatch(veneer_fn fn, + uint32_t arg0, uint32_t arg1, + uint32_t arg2, uint32_t arg3) +{ + int32_t result; + osStatus_t status; + + /* TFM request protected by NS lock */ + status = osMutexAcquire(ns_lock_handle, osWaitForever); + if (status != osOK) { + return (int32_t)TFM_ERROR_GENERIC; + } + + result = fn(arg0, arg1, arg2, arg3); + + status = osMutexRelease(ns_lock_handle); + if (status != osOK) { + return (int32_t)TFM_ERROR_GENERIC; + } + + return result; +} + +__attribute__((weak)) +enum tfm_status_e tfm_ns_interface_init(void) +{ + const osMutexAttr_t attr = { + .name = NULL, + .attr_bits = osMutexPrioInherit, /* Priority inheritance is recommended + * to enable if it is supported. + * For recursive mutex and the ability + * of auto release when owner being + * terminated is not required. + */ + .cb_mem = NULL, + .cb_size = 0U + }; + + ns_lock_handle = osMutexNew(&attr); + if (!ns_lock_handle) { + return TFM_ERROR_GENERIC; + } + + return TFM_SUCCESS; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/tfm_psa_ns_api.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/tfm_psa_ns_api.c new file mode 100644 index 0000000..9a677a2 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/tfm_psa_ns_api.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018-2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "psa/client.h" +#include "tfm_ns_interface.h" +#include "tfm_api.h" + +/**** API functions ****/ + +uint32_t psa_framework_version(void) +{ + return tfm_ns_interface_dispatch( + (veneer_fn)tfm_psa_framework_version_veneer, + 0, + 0, + 0, + 0); +} + +uint32_t psa_version(uint32_t sid) +{ + return tfm_ns_interface_dispatch( + (veneer_fn)tfm_psa_version_veneer, + sid, + 0, + 0, + 0); +} + +psa_handle_t psa_connect(uint32_t sid, uint32_t version) +{ + return tfm_ns_interface_dispatch( + (veneer_fn)tfm_psa_connect_veneer, + sid, + version, + 0, + 0); +} + +psa_status_t psa_call(psa_handle_t handle, int32_t type, + const psa_invec *in_vec, + size_t in_len, + psa_outvec *out_vec, + size_t out_len) +{ + /* FixMe: sanity check can be added to offload some NS thread checks from + * TFM secure API + */ + + /* Due to v8M restrictions, TF-M NS API needs to add another layer of + * serialization in order for NS to pass arguments to S + */ + const struct tfm_control_parameter_t ctrl_param = { + .type = type, + .in_len = in_len, + .out_len = out_len, + }; + + return tfm_ns_interface_dispatch( + (veneer_fn)tfm_psa_call_veneer, + (uint32_t)handle, + (uint32_t)&ctrl_param, + (uint32_t)in_vec, + (uint32_t)out_vec); +} + +void psa_close(psa_handle_t handle) +{ + (void)tfm_ns_interface_dispatch( + (veneer_fn)tfm_psa_close_veneer, + (uint32_t)handle, + 0, + 0, + 0); +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/VERSION.txt b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/VERSION.txt new file mode 100644 index 0000000..cc1d7ed --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/VERSION.txt @@ -0,0 +1 @@ +9fd2fd6250d5 diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/cmsis_nvic_virtual.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/cmsis_nvic_virtual.h new file mode 100644 index 0000000..a1a8b61 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/cmsis_nvic_virtual.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2019 Arm Limited + * + * 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 "cmsis.h" + +#ifndef NVIC_VIRTUAL_H +#define NVIC_VIRTUAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* NVIC functions */ +#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping +#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping +#define NVIC_EnableIRQ __NVIC_EnableIRQ +#define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ +#define NVIC_DisableIRQ __NVIC_DisableIRQ +#define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ +#define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ +#define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ +#define NVIC_GetActive __NVIC_GetActive +#define NVIC_SetPriority __NVIC_SetPriority +#define NVIC_GetPriority __NVIC_GetPriority + +/** + * \brief Overriding the default CMSIS system reset implementation by calling + * secure TFM service. + * + */ +void NVIC_SystemReset(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/ns_ipc_config.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/ns_ipc_config.h new file mode 100644 index 0000000..e1cd7b7 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/ns_ipc_config.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _IPC_CONFIG_H_ +#define _IPC_CONFIG_H_ + +#include "platform_multicore.h" + +#define IPC_RX_CHAN IPC_PSA_CLIENT_REPLY_CHAN +#define IPC_RX_INTR_STRUCT IPC_PSA_CLIENT_REPLY_INTR_STRUCT +#define IPC_RX_INT_MASK IPC_PSA_CLIENT_REPLY_INTR_MASK + +#define IPC_TX_CHAN IPC_PSA_CLIENT_CALL_CHAN +#define IPC_TX_NOTIFY_MASK IPC_PSA_CLIENT_CALL_NOTIFY_MASK + +#define PSA_CLIENT_REPLY_NVIC_IRQn IPC_PSA_CLIENT_REPLY_IPC_INTR +#define PSA_CLIENT_REPLY_IRQ_PRIORITY 3 + +#endif diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/platform_multicore.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/platform_multicore.h new file mode 100644 index 0000000..ae9855e --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/platform_multicore.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * Copyright (c) 2019, Cypress Semiconductor Corporation. All rights reserved + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef _TFM_PLATFORM_MULTICORE_ +#define _TFM_PLATFORM_MULTICORE_ + +#include +#include "cy_device_headers.h" + +#define IPC_PSA_CLIENT_CALL_CHAN (8) +#define IPC_PSA_CLIENT_CALL_INTR_STRUCT (6) +#define IPC_PSA_CLIENT_CALL_INTR_MASK (1 << IPC_PSA_CLIENT_CALL_CHAN) +#define IPC_PSA_CLIENT_CALL_NOTIFY_MASK (1 << IPC_PSA_CLIENT_CALL_INTR_STRUCT) +#define IPC_PSA_CLIENT_CALL_IPC_INTR cpuss_interrupts_ipc_6_IRQn + +#define IPC_PSA_CLIENT_REPLY_CHAN (9) +#define IPC_PSA_CLIENT_REPLY_INTR_STRUCT (8) +#define IPC_PSA_CLIENT_REPLY_INTR_MASK (1 << IPC_PSA_CLIENT_REPLY_CHAN) +#define IPC_PSA_CLIENT_REPLY_NOTIFY_MASK (1 << IPC_PSA_CLIENT_REPLY_INTR_STRUCT) +#define IPC_PSA_CLIENT_REPLY_IPC_INTR cpuss_interrupts_ipc_8_IRQn + +#define IPC_PSA_MAILBOX_LOCK_CHAN (10) + +#define IPC_RX_RELEASE_MASK (0) + +#define CY_IPC_NOTIFY_SHIFT (16) + +#define PSA_CLIENT_CALL_REQ_MAGIC (0xA5CF50C6) +#define PSA_CLIENT_CALL_REPLY_MAGIC (0xC605FC5A) + +#define NS_MAILBOX_INIT_ENABLE (0xAE) +#define S_MAILBOX_READY (0xC3) + +#define PLATFORM_MAILBOX_SUCCESS (0x0) +#define PLATFORM_MAILBOX_INVAL_PARAMS (INT32_MIN + 1) +#define PLATFORM_MAILBOX_TX_ERROR (INT32_MIN + 2) +#define PLATFORM_MAILBOX_RX_ERROR (INT32_MIN + 3) +#define PLATFORM_MAILBOX_INIT_ERROR (INT32_MIN + 4) + +/* Inter-Processor Communication (IPC) data channel for the Semaphores */ +#define PLATFORM_MAILBOX_IPC_CHAN_SEMA CY_IPC_CHAN_SEMA +#define MAILBOX_SEMAPHORE_NUM (16) + +#define IPC_SYNC_MAGIC 0x7DADE011 + +/** + * \brief Fetch a pointer from mailbox message + * + * \param[out] msg_ptr The address to write the pointer value to. + * + * \retval 0 The operation succeeds. + * \retval else The operation fails. + */ +int platform_mailbox_fetch_msg_ptr(void **msg_ptr); + +/** + * \brief Fetch a data value from mailbox message + * + * \param[out] data_ptr The address to write the pointer value to. + * + * \retval 0 The operation succeeds. + * \retval else The operation fails. + */ +int platform_mailbox_fetch_msg_data(uint32_t *data_ptr); + +/** + * \brief Send a pointer via mailbox message + * + * \param[in] msg_ptr The pointer value to be sent. + * + * \retval 0 The operation succeeds. + * \retval else The operation fails. + */ +int platform_mailbox_send_msg_ptr(const void *msg_ptr); + +/** + * \brief Send a data value via mailbox message + * + * \param[in] data The data value to be sent + * + * \retval 0 The operation succeeds. + * \retval else The operation fails. + */ +int platform_mailbox_send_msg_data(uint32_t data); + +/** + * \brief Wait for a mailbox notify event. + */ +void platform_mailbox_wait_for_notify(void); + +/** + * \brief IPC initialization + * + * \retval 0 The operation succeeds. + * \retval else The operation fails. + */ +int platform_ns_ipc_init(void); + +#endif diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/client.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/client.h new file mode 100644 index 0000000..4115f93 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/client.h @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2018-2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __PSA_CLIENT_H__ +#define __PSA_CLIENT_H__ + +#include +#include + +#include "psa/error.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*********************** PSA Client Macros and Types *************************/ + +/** + * The version of the PSA Framework API that is being used to build the calling + * firmware. + */ +#define PSA_FRAMEWORK_VERSION (0x0100u) + +/** + * Return value from psa_version() if the requested RoT Service is not present + * in the system. + */ +#define PSA_VERSION_NONE (0u) + +/** + * The zero-value null handle can be assigned to variables used in clients and + * RoT Services, indicating that there is no current connection or message. + */ +#define PSA_NULL_HANDLE ((psa_handle_t)0) + +/** + * Tests whether a handle value returned by psa_connect() is valid. + */ +#define PSA_HANDLE_IS_VALID(handle) ((psa_handle_t)(handle) > 0) + +/** + * Converts the handle value returned from a failed call psa_connect() into + * an error code. + */ +#define PSA_HANDLE_TO_ERROR(handle) ((psa_status_t)(handle)) + +/** + * Maximum number of input and output vectors for a request to psa_call(). + */ +#define PSA_MAX_IOVEC (4u) + +/** + * An IPC message type that indicates a generic client request. + */ +#define PSA_IPC_CALL (0) + +typedef int32_t psa_handle_t; + +/** + * A read-only input memory region provided to an RoT Service. + */ +typedef struct psa_invec { + const void *base; /*!< the start address of the memory buffer */ + size_t len; /*!< the size in bytes */ +} psa_invec; + +/** + * A writable output memory region provided to an RoT Service. + */ +typedef struct psa_outvec { + void *base; /*!< the start address of the memory buffer */ + size_t len; /*!< the size in bytes */ +} psa_outvec; + +/*************************** PSA Client API **********************************/ + +/** + * \brief Retrieve the version of the PSA Framework API that is implemented. + * + * \return version The version of the PSA Framework implementation + * that is providing the runtime services to the + * caller. The major and minor version are encoded + * as follows: + * \arg version[15:8] -- major version number. + * \arg version[7:0] -- minor version number. + */ +uint32_t psa_framework_version(void); + +/** + * \brief Retrieve the version of an RoT Service or indicate that it is not + * present on this system. + * + * \param[in] sid ID of the RoT Service to query. + * + * \retval PSA_VERSION_NONE The RoT Service is not implemented, or the + * caller is not permitted to access the service. + * \retval > 0 The version of the implemented RoT Service. + */ +uint32_t psa_version(uint32_t sid); + +/** + * \brief Connect to an RoT Service by its SID. + * + * \param[in] sid ID of the RoT Service to connect to. + * \param[in] version Requested version of the RoT Service. + * + * \retval > 0 A handle for the connection. + * \retval PSA_ERROR_CONNECTION_REFUSED The SPM or RoT Service has refused the + * connection. + * \retval PSA_ERROR_CONNECTION_BUSY The SPM or RoT Service cannot make the + * connection at the moment. + * \retval "PROGRAMMER ERROR" The call is a PROGRAMMER ERROR if one or more + * of the following are true: + * \arg The RoT Service ID is not present. + * \arg The RoT Service version is not supported. + * \arg The caller is not allowed to access the RoT + * service. + */ +psa_handle_t psa_connect(uint32_t sid, uint32_t version); + +/** + * \brief Call an RoT Service on an established connection. + * + * \param[in] handle A handle to an established connection. + * \param[in] type The reuqest type. + * Must be zero( \ref PSA_IPC_CALL) or positive. + * \param[in] in_vec Array of input \ref psa_invec structures. + * \param[in] in_len Number of input \ref psa_invec structures. + * \param[in/out] out_vec Array of output \ref psa_outvec structures. + * \param[in] out_len Number of output \ref psa_outvec structures. + * + * \retval >=0 RoT Service-specific status value. + * \retval <0 RoT Service-specific error code. + * \retval PSA_ERROR_PROGRAMMER_ERROR The connection has been terminated by the + * RoT Service. The call is a PROGRAMMER ERROR if + * one or more of the following are true: + * \arg An invalid handle was passed. + * \arg The connection is already handling a request. + * \arg type < 0. + * \arg An invalid memory reference was provided. + * \arg in_len + out_len > PSA_MAX_IOVEC. + * \arg The message is unrecognized by the RoT + * Service or incorrectly formatted. + */ +psa_status_t psa_call(psa_handle_t handle, int32_t type, + const psa_invec *in_vec, + size_t in_len, + psa_outvec *out_vec, + size_t out_len); + +/** + * \brief Close a connection to an RoT Service. + * + * \param[in] handle A handle to an established connection, or the + * null handle. + * + * \retval void Success. + * \retval "PROGRAMMER ERROR" The call is a PROGRAMMER ERROR if one or more + * of the following are true: + * \arg An invalid handle was provided that is not + * the null handle. + * \arg The connection is currently handling a + * request. + */ +void psa_close(psa_handle_t handle); + +#ifdef __cplusplus +} +#endif + +#endif /* __PSA_CLIENT_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto.h new file mode 100644 index 0000000..9158117 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto.h @@ -0,0 +1,3770 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +/** + * \file psa/crypto.h + * \brief Platform Security Architecture cryptography module + */ + +#ifndef PSA_CRYPTO_H +#define PSA_CRYPTO_H + +#include "psa/crypto_platform.h" + +#include + +#ifdef __DOXYGEN_ONLY__ +/* This __DOXYGEN_ONLY__ block contains mock definitions for things that + * must be defined in the crypto_platform.h header. These mock definitions + * are present in this file as a convenience to generate pretty-printed + * documentation that includes those definitions. */ + +/** \defgroup platform Implementation-specific definitions + * @{ + */ + +/** \brief Key handle. + * + * This type represents open handles to keys. It must be an unsigned integral + * type. The choice of type is implementation-dependent. + * + * 0 is not a valid key handle. How other handle values are assigned is + * implementation-dependent. + */ +typedef _unsigned_integral_type_ psa_key_handle_t; + +/**@}*/ +#endif /* __DOXYGEN_ONLY__ */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* The file "crypto_types.h" declares types that encode errors, + * algorithms, key types, policies, etc. */ +#include "psa/crypto_types.h" + +/** \defgroup version API version + * @{ + */ + +/** + * The major version of this implementation of the PSA Crypto API + */ +#define PSA_CRYPTO_API_VERSION_MAJOR 1 + +/** + * The minor version of this implementation of the PSA Crypto API + */ +#define PSA_CRYPTO_API_VERSION_MINOR 0 + +/**@}*/ + +/* The file "crypto_values.h" declares macros to build and analyze values + * of integral types defined in "crypto_types.h". */ +#include "psa/crypto_values.h" + +/** \defgroup initialization Library initialization + * @{ + */ + +/** + * \brief Library initialization. + * + * Applications must call this function before calling any other + * function in this module. + * + * Applications may call this function more than once. Once a call + * succeeds, subsequent calls are guaranteed to succeed. + * + * If the application calls other functions before calling psa_crypto_init(), + * the behavior is undefined. Implementations are encouraged to either perform + * the operation as if the library had been initialized or to return + * #PSA_ERROR_BAD_STATE or some other applicable error. In particular, + * implementations should not return a success status if the lack of + * initialization may have security implications, for example due to improper + * seeding of the random number generator. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + */ +psa_status_t psa_crypto_init(void); + +/**@}*/ + +/** \addtogroup attributes + * @{ + */ + +/** \def PSA_KEY_ATTRIBUTES_INIT + * + * This macro returns a suitable initializer for a key attribute structure + * of type #psa_key_attributes_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_KEY_ATTRIBUTES_INIT {0} +#endif + +/** Return an initial value for a key attributes structure. + */ +static psa_key_attributes_t psa_key_attributes_init(void); + +/** Declare a key as persistent and set its key identifier. + * + * If the attribute structure currently declares the key as volatile (which + * is the default content of an attribute structure), this function sets + * the lifetime attribute to #PSA_KEY_LIFETIME_PERSISTENT. + * + * This function does not access storage, it merely stores the given + * value in the structure. + * The persistent key will be written to storage when the attribute + * structure is passed to a key creation function such as + * psa_import_key(), psa_generate_key(), + * psa_key_derivation_output_key() or psa_copy_key(). + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param id The persistent identifier for the key. + */ +static void psa_set_key_id(psa_key_attributes_t *attributes, + psa_key_id_t id); + +/** Set the location of a persistent key. + * + * To make a key persistent, you must give it a persistent key identifier + * with psa_set_key_id(). By default, a key that has a persistent identifier + * is stored in the default storage area identifier by + * #PSA_KEY_LIFETIME_PERSISTENT. Call this function to choose a storage + * area, or to explicitly declare the key as volatile. + * + * This function does not access storage, it merely stores the given + * value in the structure. + * The persistent key will be written to storage when the attribute + * structure is passed to a key creation function such as + * psa_import_key(), psa_generate_key(), + * psa_key_derivation_output_key() or psa_copy_key(). + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param lifetime The lifetime for the key. + * If this is #PSA_KEY_LIFETIME_VOLATILE, the + * key will be volatile, and the key identifier + * attribute is reset to 0. + */ +static void psa_set_key_lifetime(psa_key_attributes_t *attributes, + psa_key_lifetime_t lifetime); + +/** Retrieve the key identifier from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The persistent identifier stored in the attribute structure. + * This value is unspecified if the attribute structure declares + * the key as volatile. + */ +static psa_key_id_t psa_get_key_id(const psa_key_attributes_t *attributes); + +/** Retrieve the lifetime from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The lifetime value stored in the attribute structure. + */ +static psa_key_lifetime_t psa_get_key_lifetime( + const psa_key_attributes_t *attributes); + +/** Declare usage flags for a key. + * + * Usage flags are part of a key's usage policy. They encode what + * kind of operations are permitted on the key. For more details, + * refer to the documentation of the type #psa_key_usage_t. + * + * This function overwrites any usage flags + * previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param usage_flags The usage flags to write. + */ +static void psa_set_key_usage_flags(psa_key_attributes_t *attributes, + psa_key_usage_t usage_flags); + +/** Retrieve the usage flags from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The usage flags stored in the attribute structure. + */ +static psa_key_usage_t psa_get_key_usage_flags( + const psa_key_attributes_t *attributes); + +/** Declare the permitted algorithm policy for a key. + * + * The permitted algorithm policy of a key encodes which algorithm or + * algorithms are permitted to be used with this key. The following + * algorithm policies are supported: + * - 0 does not allow any cryptographic operation with the key. The key + * may be used for non-cryptographic actions such as exporting (if + * permitted by the usage flags). + * - An algorithm value permits this particular algorithm. + * - An algorithm wildcard built from #PSA_ALG_ANY_HASH allows the specified + * signature scheme with any hash algorithm. + * + * This function overwrites any algorithm policy + * previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param alg The permitted algorithm policy to write. + */ +static void psa_set_key_algorithm(psa_key_attributes_t *attributes, + psa_algorithm_t alg); + + +/** Retrieve the algorithm policy from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The algorithm stored in the attribute structure. + */ +static psa_algorithm_t psa_get_key_algorithm( + const psa_key_attributes_t *attributes); + +/** Declare the type of a key. + * + * This function overwrites any key type + * previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param type The key type to write. + * If this is 0, the key type in \p attributes + * becomes unspecified. + */ +static void psa_set_key_type(psa_key_attributes_t *attributes, + psa_key_type_t type); + + +/** Declare the size of a key. + * + * This function overwrites any key size previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param bits The key size in bits. + * If this is 0, the key size in \p attributes + * becomes unspecified. Keys of size 0 are + * not supported. + */ +static void psa_set_key_bits(psa_key_attributes_t *attributes, + size_t bits); + +/** Retrieve the key type from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The key type stored in the attribute structure. + */ +static psa_key_type_t psa_get_key_type(const psa_key_attributes_t *attributes); + +/** Retrieve the key size from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The key size stored in the attribute structure, in bits. + */ +static size_t psa_get_key_bits(const psa_key_attributes_t *attributes); + +/** Retrieve the attributes of a key. + * + * This function first resets the attribute structure as with + * psa_reset_key_attributes(). It then copies the attributes of + * the given key into the given attribute structure. + * + * \note This function may allocate memory or other resources. + * Once you have called this function on an attribute structure, + * you must call psa_reset_key_attributes() to free these resources. + * + * \param[in] handle Handle to the key to query. + * \param[in,out] attributes On success, the attributes of the key. + * On failure, equivalent to a + * freshly-initialized structure. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_get_key_attributes(psa_key_handle_t handle, + psa_key_attributes_t *attributes); + +/** Reset a key attribute structure to a freshly initialized state. + * + * You must initialize the attribute structure as described in the + * documentation of the type #psa_key_attributes_t before calling this + * function. Once the structure has been initialized, you may call this + * function at any time. + * + * This function frees any auxiliary resources that the structure + * may contain. + * + * \param[in,out] attributes The attribute structure to reset. + */ +void psa_reset_key_attributes(psa_key_attributes_t *attributes); + +/**@}*/ + +/** \defgroup key_management Key management + * @{ + */ + +/** Open a handle to an existing persistent key. + * + * Open a handle to a persistent key. A key is persistent if it was created + * with a lifetime other than #PSA_KEY_LIFETIME_VOLATILE. A persistent key + * always has a nonzero key identifier, set with psa_set_key_id() when + * creating the key. Implementations may provide additional pre-provisioned + * keys that can be opened with psa_open_key(). Such keys have a key identifier + * in the vendor range, as documented in the description of #psa_key_id_t. + * + * The application must eventually close the handle with psa_close_key() or + * psa_destroy_key() to release associated resources. If the application dies + * without calling one of these functions, the implementation should perform + * the equivalent of a call to psa_close_key(). + * + * Some implementations permit an application to open the same key multiple + * times. If this is successful, each call to psa_open_key() will return a + * different key handle. + * + * \note Applications that rely on opening a key multiple times will not be + * portable to implementations that only permit a single key handle to be + * opened. See also :ref:\`key-handles\`. + * + * \param id The persistent identifier of the key. + * \param[out] handle On success, a handle to the key. + * + * \retval #PSA_SUCCESS + * Success. The application can now use the value of `*handle` + * to access the key. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * The implementation does not have sufficient resources to open the + * key. This can be due to reaching an implementation limit on the + * number of open keys, the number of open key handles, or available + * memory. + * \retval #PSA_ERROR_DOES_NOT_EXIST + * There is no persistent key with key identifier \p id. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p id is not a valid persistent key identifier. + * \retval #PSA_ERROR_NOT_PERMITTED + * The specified key exists, but the application does not have the + * permission to access it. Note that this specification does not + * define any way to create such a key, but it may be possible + * through implementation-specific means. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_open_key(psa_key_id_t id, + psa_key_handle_t *handle); + + +/** Close a key handle. + * + * If the handle designates a volatile key, this will destroy the key material + * and free all associated resources, just like psa_destroy_key(). + * + * If this is the last open handle to a persistent key, then closing the handle + * will free all resources associated with the key in volatile memory. The key + * data in persistent storage is not affected and can be opened again later + * with a call to psa_open_key(). + * + * Closing the key handle makes the handle invalid, and the key handle + * must not be used again by the application. + * + * \note If the key handle was used to set up an active + * :ref:\`multipart operation \`, then closing the + * key handle can cause the multipart operation to fail. Applications should + * maintain the key handle until after the multipart operation has finished. + * + * \param handle The key handle to close. + * If this is \c 0, do nothing and return \c PSA_SUCCESS. + * + * \retval #PSA_SUCCESS + * \p handle was a valid handle or \c 0. It is now closed. + * \retval #PSA_ERROR_INVALID_HANDLE + * \p handle is not a valid handle nor \c 0. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_close_key(psa_key_handle_t handle); + +/** Make a copy of a key. + * + * Copy key material from one location to another. + * + * This function is primarily useful to copy a key from one location + * to another, since it populates a key using the material from + * another key which may have a different lifetime. + * + * This function may be used to share a key with a different party, + * subject to implementation-defined restrictions on key sharing. + * + * The policy on the source key must have the usage flag + * #PSA_KEY_USAGE_COPY set. + * This flag is sufficient to permit the copy if the key has the lifetime + * #PSA_KEY_LIFETIME_VOLATILE or #PSA_KEY_LIFETIME_PERSISTENT. + * Some secure elements do not provide a way to copy a key without + * making it extractable from the secure element. If a key is located + * in such a secure element, then the key must have both usage flags + * #PSA_KEY_USAGE_COPY and #PSA_KEY_USAGE_EXPORT in order to make + * a copy of the key outside the secure element. + * + * The resulting key may only be used in a way that conforms to + * both the policy of the original key and the policy specified in + * the \p attributes parameter: + * - The usage flags on the resulting key are the bitwise-and of the + * usage flags on the source policy and the usage flags in \p attributes. + * - If both allow the same algorithm or wildcard-based + * algorithm policy, the resulting key has the same algorithm policy. + * - If either of the policies allows an algorithm and the other policy + * allows a wildcard-based algorithm policy that includes this algorithm, + * the resulting key allows the same algorithm. + * - If the policies do not allow any algorithm in common, this function + * fails with the status #PSA_ERROR_INVALID_ARGUMENT. + * + * The effect of this function on implementation-defined attributes is + * implementation-defined. + * + * \param source_handle The key to copy. It must be a valid key handle. + * \param[in] attributes The attributes for the new key. + * They are used as follows: + * - The key type and size may be 0. If either is + * nonzero, it must match the corresponding + * attribute of the source key. + * - The key location (the lifetime and, for + * persistent keys, the key identifier) is + * used directly. + * - The policy constraints (usage flags and + * algorithm policy) are combined from + * the source key and \p attributes so that + * both sets of restrictions apply, as + * described in the documentation of this function. + * \param[out] target_handle On success, a handle to the newly created key. + * \c 0 on failure. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \p source_handle is invalid. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The lifetime or identifier in \p attributes are invalid. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The policy constraints on the source and specified in + * \p attributes are incompatible. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p attributes specifies a key type or key size + * which does not match the attributes of the source key. + * \retval #PSA_ERROR_NOT_PERMITTED + * The source key does not have the #PSA_KEY_USAGE_COPY usage flag. + * \retval #PSA_ERROR_NOT_PERMITTED + * The source key is not exportable and its lifetime does not + * allow copying it to the target's lifetime. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_copy_key(psa_key_handle_t source_handle, + const psa_key_attributes_t *attributes, + psa_key_handle_t *target_handle); + + +/** + * \brief Destroy a key. + * + * This function destroys a key from both volatile + * memory and, if applicable, non-volatile storage. Implementations shall + * make a best effort to ensure that that the key material cannot be recovered. + * + * This function also erases any metadata such as policies and frees + * resources associated with the key. To free all resources associated with + * the key, all handles to the key must be closed or destroyed. + * + * Destroying the key makes the handle invalid, and the key handle + * must not be used again by the application. Using other open handles to the + * destroyed key in a cryptographic operation will result in an error. + * + * If a key is currently in use in a multipart operation, then destroying the + * key will cause the multipart operation to fail. + * + * \param handle Handle to the key to erase. + * If this is \c 0, do nothing and return \c PSA_SUCCESS. + * + * \retval #PSA_SUCCESS + * \p handle was a valid handle and the key material that it + * referred to has been erased. + * Alternatively, \p handle is \c 0. + * \retval #PSA_ERROR_NOT_PERMITTED + * The key cannot be erased because it is + * read-only, either due to a policy or due to physical restrictions. + * \retval #PSA_ERROR_INVALID_HANDLE + * \p handle is not a valid handle nor \c 0. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * There was an failure in communication with the cryptoprocessor. + * The key material may still be present in the cryptoprocessor. + * \retval #PSA_ERROR_STORAGE_FAILURE + * The storage is corrupted. Implementations shall make a best effort + * to erase key material even in this stage, however applications + * should be aware that it may be impossible to guarantee that the + * key material is not recoverable in such cases. + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * An unexpected condition which is not a storage corruption or + * a communication failure occurred. The cryptoprocessor may have + * been compromised. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_destroy_key(psa_key_handle_t handle); + +/**@}*/ + +/** \defgroup import_export Key import and export + * @{ + */ + +/** + * \brief Import a key in binary format. + * + * This function supports any output from psa_export_key(). Refer to the + * documentation of psa_export_public_key() for the format of public keys + * and to the documentation of psa_export_key() for the format for + * other key types. + * + * The key data determines the key size. The attributes may optionally + * specify a key size; in this case it must match the size determined + * from the key data. A key size of 0 in \p attributes indicates that + * the key size is solely determined by the key data. + * + * Implementations must reject an attempt to import a key of size 0. + * + * This specification supports a single format for each key type. + * Implementations may support other formats as long as the standard + * format is supported. Implementations that support other formats + * should ensure that the formats are clearly unambiguous so as to + * minimize the risk that an invalid input is accidentally interpreted + * according to a different format. + * + * \param[in] attributes The attributes for the new key. + * The key size is always determined from the + * \p data buffer. + * If the key size in \p attributes is nonzero, + * it must be equal to the size from \p data. + * \param[out] handle On success, a handle to the newly created key. + * \c 0 on failure. + * \param[in] data Buffer containing the key data. The content of this + * buffer is interpreted according to the type declared + * in \p attributes. + * All implementations must support at least the format + * described in the documentation + * of psa_export_key() or psa_export_public_key() for + * the chosen type. Implementations may allow other + * formats, but should be conservative: implementations + * should err on the side of rejecting content if it + * may be erroneous (e.g. wrong type or truncated data). + * \param data_length Size of the \p data buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The key type or key size is not supported, either by the + * implementation in general or in this particular persistent location. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key attributes, as a whole, are invalid. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key data is not correctly formatted. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size in \p attributes is nonzero and does not match the size + * of the key data. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_import_key(const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + psa_key_handle_t *handle); + + + +/** + * \brief Export a key in binary format. + * + * The output of this function can be passed to psa_import_key() to + * create an equivalent object. + * + * If the implementation of psa_import_key() supports other formats + * beyond the format specified here, the output from psa_export_key() + * must use the representation specified here, not the original + * representation. + * + * For standard key types, the output format is as follows: + * + * - For symmetric keys (including MAC keys), the format is the + * raw bytes of the key. + * - For DES, the key data consists of 8 bytes. The parity bits must be + * correct. + * - For Triple-DES, the format is the concatenation of the + * two or three DES keys. + * - For RSA key pairs (#PSA_KEY_TYPE_RSA_KEY_PAIR), the format + * is the non-encrypted DER encoding of the representation defined by + * PKCS\#1 (RFC 8017) as `RSAPrivateKey`, version 0. + * ``` + * RSAPrivateKey ::= SEQUENCE { + * version INTEGER, -- must be 0 + * modulus INTEGER, -- n + * publicExponent INTEGER, -- e + * privateExponent INTEGER, -- d + * prime1 INTEGER, -- p + * prime2 INTEGER, -- q + * exponent1 INTEGER, -- d mod (p-1) + * exponent2 INTEGER, -- d mod (q-1) + * coefficient INTEGER, -- (inverse of q) mod p + * } + * ``` + * - For elliptic curve key pairs (key types for which + * #PSA_KEY_TYPE_IS_ECC_KEY_PAIR is true), the format is + * a representation of the private value as a `ceiling(m/8)`-byte string + * where `m` is the bit size associated with the curve, i.e. the bit size + * of the order of the curve's coordinate field. This byte string is + * in little-endian order for Montgomery curves (curve types + * `PSA_ECC_CURVE_CURVEXXX`), and in big-endian order for Weierstrass + * curves (curve types `PSA_ECC_CURVE_SECTXXX`, `PSA_ECC_CURVE_SECPXXX` + * and `PSA_ECC_CURVE_BRAINPOOL_PXXX`). + * This is the content of the `privateKey` field of the `ECPrivateKey` + * format defined by RFC 5915. + * - For Diffie-Hellman key exchange key pairs (key types for which + * #PSA_KEY_TYPE_IS_DH_KEY_PAIR is true), the + * format is the representation of the private key `x` as a big-endian byte + * string. The length of the byte string is the private key size in bytes + * (leading zeroes are not stripped). + * - For public keys (key types for which #PSA_KEY_TYPE_IS_PUBLIC_KEY is + * true), the format is the same as for psa_export_public_key(). + * + * The policy on the key must have the usage flag #PSA_KEY_USAGE_EXPORT set. + * + * \param handle Handle to the key to export. + * \param[out] data Buffer where the key data is to be written. + * \param data_size Size of the \p data buffer in bytes. + * \param[out] data_length On success, the number of bytes + * that make up the key data. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * The key does not have the #PSA_KEY_USAGE_EXPORT flag. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p data buffer is too small. You can determine a + * sufficient buffer size by calling + * #PSA_KEY_EXPORT_MAX_SIZE(\c type, \c bits) + * where \c type is the key type + * and \c bits is the key size in bits. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_export_key(psa_key_handle_t handle, + uint8_t *data, + size_t data_size, + size_t *data_length); + +/** + * \brief Export a public key or the public part of a key pair in binary format. + * + * The output of this function can be passed to psa_import_key() to + * create an object that is equivalent to the public key. + * + * This specification supports a single format for each key type. + * Implementations may support other formats as long as the standard + * format is supported. Implementations that support other formats + * should ensure that the formats are clearly unambiguous so as to + * minimize the risk that an invalid input is accidentally interpreted + * according to a different format. + * + * For standard key types, the output format is as follows: + * - For RSA public keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY), the DER encoding of + * the representation defined by RFC 3279 §2.3.1 as `RSAPublicKey`. + * ``` + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER } -- e + * ``` + * - For elliptic curve public keys (key types for which + * #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true), the format is the uncompressed + * representation defined by SEC1 §2.3.3 as the content of an ECPoint. + * Let `m` be the bit size associated with the curve, i.e. the bit size of + * `q` for a curve over `F_q`. The representation consists of: + * - The byte 0x04; + * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; + * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. + * - For Diffie-Hellman key exchange public keys (key types for which + * #PSA_KEY_TYPE_IS_DH_PUBLIC_KEY is true), + * the format is the representation of the public key `y = g^x mod p` as a + * big-endian byte string. The length of the byte string is the length of the + * base prime `p` in bytes. + * + * Exporting a public key object or the public part of a key pair is + * always permitted, regardless of the key's usage flags. + * + * \param handle Handle to the key to export. + * \param[out] data Buffer where the key data is to be written. + * \param data_size Size of the \p data buffer in bytes. + * \param[out] data_length On success, the number of bytes + * that make up the key data. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key is neither a public key nor a key pair. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p data buffer is too small. You can determine a + * sufficient buffer size by calling + * #PSA_KEY_EXPORT_MAX_SIZE(#PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(\c type), \c bits) + * where \c type is the key type + * and \c bits is the key size in bits. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_export_public_key(psa_key_handle_t handle, + uint8_t *data, + size_t data_size, + size_t *data_length); + + + +/**@}*/ + +/** \defgroup hash Message digests + * @{ + */ + +/** Calculate the hash (digest) of a message. + * + * \note To verify the hash of a message against an + * expected value, use psa_hash_compare() instead. + * + * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_HASH(\p alg) is true). + * \param[in] input Buffer containing the message to hash. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] hash Buffer where the hash is to be written. + * \param hash_size Size of the \p hash buffer in bytes. + * \param[out] hash_length On success, the number of bytes + * that make up the hash value. This is always + * #PSA_HASH_SIZE(\p alg). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a hash algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p hash_size is too small + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_compute(psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *hash, + size_t hash_size, + size_t *hash_length); + +/** Calculate the hash (digest) of a message and compare it with a + * reference value. + * + * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_HASH(\p alg) is true). + * \param[in] input Buffer containing the message to hash. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] hash Buffer containing the expected hash value. + * \param hash_length Size of the \p hash buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected hash is identical to the actual hash of the input. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The hash of the message was calculated successfully, but it + * differs from the expected hash. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a hash algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p input_length or \p hash_length do not match the hash size for \p alg + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_compare(psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *hash, + const size_t hash_length); + +/** The type of the state data structure for multipart hash operations. + * + * Before calling any function on a hash operation object, the application must + * initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_hash_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_hash_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_HASH_OPERATION_INIT, + * for example: + * \code + * psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_hash_operation_init() + * to the structure, for example: + * \code + * psa_hash_operation_t operation; + * operation = psa_hash_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure except + * as directed by the documentation of a specific implementation. */ +typedef struct psa_hash_operation_s psa_hash_operation_t; + +/** \def PSA_HASH_OPERATION_INIT + * + * This macro returns a suitable initializer for a hash operation object + * of type #psa_hash_operation_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_HASH_OPERATION_INIT {0} +#endif + +/** Return an initial value for a hash operation object. + */ +static psa_hash_operation_t psa_hash_operation_init(void); + +/** Set up a multipart hash operation. + * + * The sequence of operations to calculate a hash (message digest) + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_hash_operation_t, e.g. #PSA_HASH_OPERATION_INIT. + * -# Call psa_hash_setup() to specify the algorithm. + * -# Call psa_hash_update() zero, one or more times, passing a fragment + * of the message each time. The hash that is calculated is the hash + * of the concatenation of these messages in order. + * -# To calculate the hash, call psa_hash_finish(). + * To compare the hash with an expected value, call psa_hash_verify(). + * + * If an error occurs at any step after a call to psa_hash_setup(), the + * operation will need to be reset by a call to psa_hash_abort(). The + * application may call psa_hash_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_hash_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_hash_finish() or psa_hash_verify(). + * - A call to psa_hash_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_hash_operation_t and not yet in use. + * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_HASH(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not a supported hash algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p alg is not a hash algorithm. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_setup(psa_hash_operation_t *operation, + psa_algorithm_t alg); + +/** Add a message fragment to a multipart hash operation. + * + * The application must call psa_hash_setup() before calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_hash_abort(). + * + * \param[in,out] operation Active hash operation. + * \param[in] input Buffer containing the message fragment to hash. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it muct be active). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_update(psa_hash_operation_t *operation, + const uint8_t *input, + size_t input_length); + +/** Finish the calculation of the hash of a message. + * + * The application must call psa_hash_setup() before calling this function. + * This function calculates the hash of the message formed by concatenating + * the inputs passed to preceding calls to psa_hash_update(). + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_hash_abort(). + * + * \warning Applications should not call this function if they expect + * a specific value for the hash. Call psa_hash_verify() instead. + * Beware that comparing integrity or authenticity data such as + * hash values with a function such as \c memcmp is risky + * because the time taken by the comparison may leak information + * about the hashed data which could allow an attacker to guess + * a valid hash and thereby bypass security controls. + * + * \param[in,out] operation Active hash operation. + * \param[out] hash Buffer where the hash is to be written. + * \param hash_size Size of the \p hash buffer in bytes. + * \param[out] hash_length On success, the number of bytes + * that make up the hash value. This is always + * #PSA_HASH_SIZE(\c alg) where \c alg is the + * hash algorithm that is calculated. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p hash buffer is too small. You can determine a + * sufficient buffer size by calling #PSA_HASH_SIZE(\c alg) + * where \c alg is the hash algorithm that is calculated. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_finish(psa_hash_operation_t *operation, + uint8_t *hash, + size_t hash_size, + size_t *hash_length); + +/** Finish the calculation of the hash of a message and compare it with + * an expected value. + * + * The application must call psa_hash_setup() before calling this function. + * This function calculates the hash of the message formed by concatenating + * the inputs passed to preceding calls to psa_hash_update(). It then + * compares the calculated hash with the expected hash passed as a + * parameter to this function. + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_hash_abort(). + * + * \note Implementations shall make the best effort to ensure that the + * comparison between the actual hash and the expected hash is performed + * in constant time. + * + * \param[in,out] operation Active hash operation. + * \param[in] hash Buffer containing the expected hash value. + * \param hash_length Size of the \p hash buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected hash is identical to the actual hash of the message. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The hash of the message was calculated successfully, but it + * differs from the expected hash. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_verify(psa_hash_operation_t *operation, + const uint8_t *hash, + size_t hash_length); + +/** Abort a hash operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_hash_setup() again. + * + * You may call this function any time after the operation object has + * been initialized by one of the methods described in #psa_hash_operation_t. + * + * In particular, calling psa_hash_abort() after the operation has been + * terminated by a call to psa_hash_abort(), psa_hash_finish() or + * psa_hash_verify() is safe and has no effect. + * + * \param[in,out] operation Initialized hash operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_abort(psa_hash_operation_t *operation); + +/** Clone a hash operation. + * + * This function copies the state of an ongoing hash operation to + * a new operation object. In other words, this function is equivalent + * to calling psa_hash_setup() on \p target_operation with the same + * algorithm that \p source_operation was set up for, then + * psa_hash_update() on \p target_operation with the same input that + * that was passed to \p source_operation. After this function returns, the + * two objects are independent, i.e. subsequent calls involving one of + * the objects do not affect the other object. + * + * \param[in] source_operation The active hash operation to clone. + * \param[in,out] target_operation The operation object to set up. + * It must be initialized but not active. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_BAD_STATE + * The \p source_operation state is not valid (it must be active). + * \retval #PSA_ERROR_BAD_STATE + * The \p target_operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation, + psa_hash_operation_t *target_operation); + +/**@}*/ + +/** \defgroup MAC Message authentication codes + * @{ + */ + +/** Calculate the MAC (message authentication code) of a message. + * + * \note To verify the MAC of a message against an + * expected value, use psa_mac_verify() instead. + * Beware that comparing integrity or authenticity data such as + * MAC values with a function such as \c memcmp is risky + * because the time taken by the comparison may leak information + * about the MAC value which could allow an attacker to guess + * a valid MAC and thereby bypass security controls. + * + * \param handle Handle to the key to use for the operation. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * \param[in] input Buffer containing the input message. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] mac Buffer where the MAC value is to be written. + * \param mac_size Size of the \p mac buffer in bytes. + * \param[out] mac_length On success, the number of bytes + * that make up the MAC value. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p mac_size is too small + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_compute(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *mac, + size_t mac_size, + size_t *mac_length); + +/** Calculate the MAC of a message and compare it with a reference value. + * + * \param handle Handle to the key to use for the operation. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * \param[in] input Buffer containing the input message. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] mac Buffer containing the expected MAC value. + * \param mac_length Size of the \p mac buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected MAC is identical to the actual MAC of the input. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The MAC of the message was calculated successfully, but it + * differs from the expected value. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_verify(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *mac, + const size_t mac_length); + +/** The type of the state data structure for multipart MAC operations. + * + * Before calling any function on a MAC operation object, the application must + * initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_mac_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_mac_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_MAC_OPERATION_INIT, + * for example: + * \code + * psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_mac_operation_init() + * to the structure, for example: + * \code + * psa_mac_operation_t operation; + * operation = psa_mac_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure except + * as directed by the documentation of a specific implementation. */ +typedef struct psa_mac_operation_s psa_mac_operation_t; + +/** \def PSA_MAC_OPERATION_INIT + * + * This macro returns a suitable initializer for a MAC operation object of type + * #psa_mac_operation_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_MAC_OPERATION_INIT {0} +#endif + +/** Return an initial value for a MAC operation object. + */ +static psa_mac_operation_t psa_mac_operation_init(void); + +/** Set up a multipart MAC calculation operation. + * + * This function sets up the calculation of the MAC + * (message authentication code) of a byte string. + * To verify the MAC of a message against an + * expected value, use psa_mac_verify_setup() instead. + * + * The sequence of operations to calculate a MAC is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT. + * -# Call psa_mac_sign_setup() to specify the algorithm and key. + * -# Call psa_mac_update() zero, one or more times, passing a fragment + * of the message each time. The MAC that is calculated is the MAC + * of the concatenation of these messages in order. + * -# At the end of the message, call psa_mac_sign_finish() to finish + * calculating the MAC value and retrieve it. + * + * If an error occurs at any step after a call to psa_mac_sign_setup(), the + * operation will need to be reset by a call to psa_mac_abort(). The + * application may call psa_mac_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_mac_sign_setup(), the application must + * eventually terminate the operation through one of the following methods: + * - A successful call to psa_mac_sign_finish(). + * - A call to psa_mac_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_mac_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Set up a multipart MAC verification operation. + * + * This function sets up the verification of the MAC + * (message authentication code) of a byte string against an expected value. + * + * The sequence of operations to verify a MAC is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT. + * -# Call psa_mac_verify_setup() to specify the algorithm and key. + * -# Call psa_mac_update() zero, one or more times, passing a fragment + * of the message each time. The MAC that is calculated is the MAC + * of the concatenation of these messages in order. + * -# At the end of the message, call psa_mac_verify_finish() to finish + * calculating the actual MAC of the message and verify it against + * the expected value. + * + * If an error occurs at any step after a call to psa_mac_verify_setup(), the + * operation will need to be reset by a call to psa_mac_abort(). The + * application may call psa_mac_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_mac_verify_setup(), the application must + * eventually terminate the operation through one of the following methods: + * - A successful call to psa_mac_verify_finish(). + * - A call to psa_mac_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_mac_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c key is not compatible with \c alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \c alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Add a message fragment to a multipart MAC operation. + * + * The application must call psa_mac_sign_setup() or psa_mac_verify_setup() + * before calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_mac_abort(). + * + * \param[in,out] operation Active MAC operation. + * \param[in] input Buffer containing the message fragment to add to + * the MAC calculation. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_update(psa_mac_operation_t *operation, + const uint8_t *input, + size_t input_length); + +/** Finish the calculation of the MAC of a message. + * + * The application must call psa_mac_sign_setup() before calling this function. + * This function calculates the MAC of the message formed by concatenating + * the inputs passed to preceding calls to psa_mac_update(). + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_mac_abort(). + * + * \warning Applications should not call this function if they expect + * a specific value for the MAC. Call psa_mac_verify_finish() instead. + * Beware that comparing integrity or authenticity data such as + * MAC values with a function such as \c memcmp is risky + * because the time taken by the comparison may leak information + * about the MAC value which could allow an attacker to guess + * a valid MAC and thereby bypass security controls. + * + * \param[in,out] operation Active MAC operation. + * \param[out] mac Buffer where the MAC value is to be written. + * \param mac_size Size of the \p mac buffer in bytes. + * \param[out] mac_length On success, the number of bytes + * that make up the MAC value. This is always + * #PSA_MAC_FINAL_SIZE(\c key_type, \c key_bits, \c alg) + * where \c key_type and \c key_bits are the type and + * bit-size respectively of the key and \c alg is the + * MAC algorithm that is calculated. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active mac sign + * operation). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p mac buffer is too small. You can determine a + * sufficient buffer size by calling PSA_MAC_FINAL_SIZE(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, + uint8_t *mac, + size_t mac_size, + size_t *mac_length); + +/** Finish the calculation of the MAC of a message and compare it with + * an expected value. + * + * The application must call psa_mac_verify_setup() before calling this function. + * This function calculates the MAC of the message formed by concatenating + * the inputs passed to preceding calls to psa_mac_update(). It then + * compares the calculated MAC with the expected MAC passed as a + * parameter to this function. + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_mac_abort(). + * + * \note Implementations shall make the best effort to ensure that the + * comparison between the actual MAC and the expected MAC is performed + * in constant time. + * + * \param[in,out] operation Active MAC operation. + * \param[in] mac Buffer containing the expected MAC value. + * \param mac_length Size of the \p mac buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected MAC is identical to the actual MAC of the message. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The MAC of the message was calculated successfully, but it + * differs from the expected MAC. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active mac verify + * operation). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation, + const uint8_t *mac, + size_t mac_length); + +/** Abort a MAC operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_mac_sign_setup() or psa_mac_verify_setup() again. + * + * You may call this function any time after the operation object has + * been initialized by one of the methods described in #psa_mac_operation_t. + * + * In particular, calling psa_mac_abort() after the operation has been + * terminated by a call to psa_mac_abort(), psa_mac_sign_finish() or + * psa_mac_verify_finish() is safe and has no effect. + * + * \param[in,out] operation Initialized MAC operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_abort(psa_mac_operation_t *operation); + +/**@}*/ + +/** \defgroup cipher Symmetric ciphers + * @{ + */ + +/** Encrypt a message using a symmetric cipher. + * + * This function encrypts a message with a random IV (initialization + * vector). Use the multipart operation interface with a + * #psa_cipher_operation_t object to provide other forms of IV. + * + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * \param[in] input Buffer containing the message to encrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the output is to be written. + * The output contains the IV followed by + * the ciphertext proper. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_encrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Decrypt a message using a symmetric cipher. + * + * This function decrypts a message encrypted with a symmetric cipher. + * + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * \param[in] input Buffer containing the message to decrypt. + * This consists of the IV followed by the + * ciphertext proper. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the plaintext is to be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_decrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** The type of the state data structure for multipart cipher operations. + * + * Before calling any function on a cipher operation object, the application + * must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_cipher_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_cipher_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_CIPHER_OPERATION_INIT, + * for example: + * \code + * psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_cipher_operation_init() + * to the structure, for example: + * \code + * psa_cipher_operation_t operation; + * operation = psa_cipher_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure except + * as directed by the documentation of a specific implementation. */ +typedef struct psa_cipher_operation_s psa_cipher_operation_t; + +/** \def PSA_CIPHER_OPERATION_INIT + * + * This macro returns a suitable initializer for a cipher operation object of + * type #psa_cipher_operation_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_CIPHER_OPERATION_INIT {0} +#endif + +/** Return an initial value for a cipher operation object. + */ +static psa_cipher_operation_t psa_cipher_operation_init(void); + +/** Set the key for a multipart symmetric encryption operation. + * + * The sequence of operations to encrypt a message with a symmetric cipher + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_cipher_operation_t, e.g. + * #PSA_CIPHER_OPERATION_INIT. + * -# Call psa_cipher_encrypt_setup() to specify the algorithm and key. + * -# Call either psa_cipher_generate_iv() or psa_cipher_set_iv() to + * generate or set the IV (initialization vector). You should use + * psa_cipher_generate_iv() unless the protocol you are implementing + * requires a specific IV value. + * -# Call psa_cipher_update() zero, one or more times, passing a fragment + * of the message each time. + * -# Call psa_cipher_finish(). + * + * If an error occurs at any step after a call to psa_cipher_encrypt_setup(), + * the operation will need to be reset by a call to psa_cipher_abort(). The + * application may call psa_cipher_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_cipher_encrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_cipher_finish(). + * - A call to psa_cipher_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_cipher_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Set the key for a multipart symmetric decryption operation. + * + * The sequence of operations to decrypt a message with a symmetric cipher + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_cipher_operation_t, e.g. + * #PSA_CIPHER_OPERATION_INIT. + * -# Call psa_cipher_decrypt_setup() to specify the algorithm and key. + * -# Call psa_cipher_set_iv() with the IV (initialization vector) for the + * decryption. If the IV is prepended to the ciphertext, you can call + * psa_cipher_update() on a buffer containing the IV followed by the + * beginning of the message. + * -# Call psa_cipher_update() zero, one or more times, passing a fragment + * of the message each time. + * -# Call psa_cipher_finish(). + * + * If an error occurs at any step after a call to psa_cipher_decrypt_setup(), + * the operation will need to be reset by a call to psa_cipher_abort(). The + * application may call psa_cipher_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_cipher_decrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_cipher_finish(). + * - A call to psa_cipher_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_cipher_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Generate an IV for a symmetric encryption operation. + * + * This function generates a random IV (initialization vector), nonce + * or initial counter value for the encryption operation as appropriate + * for the chosen algorithm, key type and key size. + * + * The application must call psa_cipher_encrypt_setup() before + * calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \param[in,out] operation Active cipher operation. + * \param[out] iv Buffer where the generated IV is to be written. + * \param iv_size Size of the \p iv buffer in bytes. + * \param[out] iv_length On success, the number of bytes of the + * generated IV. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with no IV set). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p iv buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation, + uint8_t *iv, + size_t iv_size, + size_t *iv_length); + +/** Set the IV for a symmetric encryption or decryption operation. + * + * This function sets the IV (initialization vector), nonce + * or initial counter value for the encryption or decryption operation. + * + * The application must call psa_cipher_encrypt_setup() before + * calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \note When encrypting, applications should use psa_cipher_generate_iv() + * instead of this function, unless implementing a protocol that requires + * a non-random IV. + * + * \param[in,out] operation Active cipher operation. + * \param[in] iv Buffer containing the IV to use. + * \param iv_length Size of the IV in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active cipher + * encrypt operation, with no IV set). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size of \p iv is not acceptable for the chosen algorithm, + * or the chosen algorithm does not use an IV. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, + const uint8_t *iv, + size_t iv_length); + +/** Encrypt or decrypt a message fragment in an active cipher operation. + * + * Before calling this function, you must: + * 1. Call either psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup(). + * The choice of setup function determines whether this function + * encrypts or decrypts its input. + * 2. If the algorithm requires an IV, call psa_cipher_generate_iv() + * (recommended when encrypting) or psa_cipher_set_iv(). + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \param[in,out] operation Active cipher operation. + * \param[in] input Buffer containing the message fragment to + * encrypt or decrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the output is to be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with an IV set + * if required for the algorithm). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Finish encrypting or decrypting a message in a cipher operation. + * + * The application must call psa_cipher_encrypt_setup() or + * psa_cipher_decrypt_setup() before calling this function. The choice + * of setup function determines whether this function encrypts or + * decrypts its input. + * + * This function finishes the encryption or decryption of the message + * formed by concatenating the inputs passed to preceding calls to + * psa_cipher_update(). + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \param[in,out] operation Active cipher operation. + * \param[out] output Buffer where the output is to be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total input size passed to this operation is not valid for + * this particular algorithm. For example, the algorithm is a based + * on block cipher and requires a whole number of blocks, but the + * total input size is not a multiple of the block size. + * \retval #PSA_ERROR_INVALID_PADDING + * This is a decryption operation for an algorithm that includes + * padding, and the ciphertext does not contain valid padding. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with an IV set + * if required for the algorithm). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Abort a cipher operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup() again. + * + * You may call this function any time after the operation object has + * been initialized as described in #psa_cipher_operation_t. + * + * In particular, calling psa_cipher_abort() after the operation has been + * terminated by a call to psa_cipher_abort() or psa_cipher_finish() + * is safe and has no effect. + * + * \param[in,out] operation Initialized cipher operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation); + +/**@}*/ + +/** \defgroup aead Authenticated encryption with associated data (AEAD) + * @{ + */ + +/** Process an authenticated encryption operation. + * + * \param handle Handle to the key to use for the operation. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param[in] nonce Nonce or IV to use. + * \param nonce_length Size of the \p nonce buffer in bytes. + * \param[in] additional_data Additional data that will be authenticated + * but not encrypted. + * \param additional_data_length Size of \p additional_data in bytes. + * \param[in] plaintext Data that will be authenticated and + * encrypted. + * \param plaintext_length Size of \p plaintext in bytes. + * \param[out] ciphertext Output buffer for the authenticated and + * encrypted data. The additional data is not + * part of this output. For algorithms where the + * encrypted data and the authentication tag + * are defined as separate outputs, the + * authentication tag is appended to the + * encrypted data. + * \param ciphertext_size Size of the \p ciphertext buffer in bytes. + * This must be at least + * #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\p alg, + * \p plaintext_length). + * \param[out] ciphertext_length On success, the size of the output + * in the \p ciphertext buffer. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not an AEAD algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p ciphertext_size is too small + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_encrypt(psa_key_handle_t handle, + 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 *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length); + +/** Process an authenticated decryption operation. + * + * \param handle Handle to the key to use for the operation. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param[in] nonce Nonce or IV to use. + * \param nonce_length Size of the \p nonce buffer in bytes. + * \param[in] additional_data Additional data that has been authenticated + * but not encrypted. + * \param additional_data_length Size of \p additional_data in bytes. + * \param[in] ciphertext Data that has been authenticated and + * encrypted. For algorithms where the + * encrypted data and the authentication tag + * are defined as separate inputs, the buffer + * must contain the encrypted data followed + * by the authentication tag. + * \param ciphertext_length Size of \p ciphertext in bytes. + * \param[out] plaintext Output buffer for the decrypted data. + * \param plaintext_size Size of the \p plaintext buffer in bytes. + * This must be at least + * #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\p alg, + * \p ciphertext_length). + * \param[out] plaintext_length On success, the size of the output + * in the \p plaintext buffer. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The ciphertext is not authentic. + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not an AEAD algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p plaintext_size or \p nonce_length is too small + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_decrypt(psa_key_handle_t handle, + 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 *ciphertext, + size_t ciphertext_length, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length); + +/** The type of the state data structure for multipart AEAD operations. + * + * Before calling any function on an AEAD operation object, the application + * must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_aead_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_aead_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_AEAD_OPERATION_INIT, + * for example: + * \code + * psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_aead_operation_init() + * to the structure, for example: + * \code + * psa_aead_operation_t operation; + * operation = psa_aead_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure except + * as directed by the documentation of a specific implementation. */ +typedef struct psa_aead_operation_s psa_aead_operation_t; + +/** \def PSA_AEAD_OPERATION_INIT + * + * This macro returns a suitable initializer for an AEAD operation object of + * type #psa_aead_operation_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_AEAD_OPERATION_INIT {0} +#endif + +/** Return an initial value for an AEAD operation object. + */ +static psa_aead_operation_t psa_aead_operation_init(void); + +/** Set the key for a multipart authenticated encryption operation. + * + * The sequence of operations to encrypt a message with authentication + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_aead_operation_t, e.g. + * #PSA_AEAD_OPERATION_INIT. + * -# Call psa_aead_encrypt_setup() to specify the algorithm and key. + * -# If needed, call psa_aead_set_lengths() to specify the length of the + * inputs to the subsequent calls to psa_aead_update_ad() and + * psa_aead_update(). See the documentation of psa_aead_set_lengths() + * for details. + * -# Call either psa_aead_generate_nonce() or psa_aead_set_nonce() to + * generate or set the nonce. You should use + * psa_aead_generate_nonce() unless the protocol you are implementing + * requires a specific nonce value. + * -# Call psa_aead_update_ad() zero, one or more times, passing a fragment + * of the non-encrypted additional authenticated data each time. + * -# Call psa_aead_update() zero, one or more times, passing a fragment + * of the message to encrypt each time. + * -# Call psa_aead_finish(). + * + * If an error occurs at any step after a call to psa_aead_encrypt_setup(), + * the operation will need to be reset by a call to psa_aead_abort(). The + * application may call psa_aead_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_aead_encrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_aead_finish(). + * - A call to psa_aead_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_aead_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not an AEAD algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Set the key for a multipart authenticated decryption operation. + * + * The sequence of operations to decrypt a message with authentication + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_aead_operation_t, e.g. + * #PSA_AEAD_OPERATION_INIT. + * -# Call psa_aead_decrypt_setup() to specify the algorithm and key. + * -# If needed, call psa_aead_set_lengths() to specify the length of the + * inputs to the subsequent calls to psa_aead_update_ad() and + * psa_aead_update(). See the documentation of psa_aead_set_lengths() + * for details. + * -# Call psa_aead_set_nonce() with the nonce for the decryption. + * -# Call psa_aead_update_ad() zero, one or more times, passing a fragment + * of the non-encrypted additional authenticated data each time. + * -# Call psa_aead_update() zero, one or more times, passing a fragment + * of the ciphertext to decrypt each time. + * -# Call psa_aead_verify(). + * + * If an error occurs at any step after a call to psa_aead_decrypt_setup(), + * the operation will need to be reset by a call to psa_aead_abort(). The + * application may call psa_aead_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_aead_decrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_aead_verify(). + * - A call to psa_aead_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_aead_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not an AEAD algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Generate a random nonce for an authenticated encryption operation. + * + * This function generates a random nonce for the authenticated encryption + * operation with an appropriate size for the chosen algorithm, key type + * and key size. + * + * The application must call psa_aead_encrypt_setup() before + * calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \param[in,out] operation Active AEAD operation. + * \param[out] nonce Buffer where the generated nonce is to be + * written. + * \param nonce_size Size of the \p nonce buffer in bytes. + * \param[out] nonce_length On success, the number of bytes of the + * generated nonce. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active aead encrypt + operation, with no nonce set). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p nonce buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation, + uint8_t *nonce, + size_t nonce_size, + size_t *nonce_length); + +/** Set the nonce for an authenticated encryption or decryption operation. + * + * This function sets the nonce for the authenticated + * encryption or decryption operation. + * + * The application must call psa_aead_encrypt_setup() or + * psa_aead_decrypt_setup() before calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \note When encrypting, applications should use psa_aead_generate_nonce() + * instead of this function, unless implementing a protocol that requires + * a non-random IV. + * + * \param[in,out] operation Active AEAD operation. + * \param[in] nonce Buffer containing the nonce to use. + * \param nonce_length Size of the nonce in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with no nonce + * set). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size of \p nonce is not acceptable for the chosen algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation, + const uint8_t *nonce, + size_t nonce_length); + +/** Declare the lengths of the message and additional data for AEAD. + * + * The application must call this function before calling + * psa_aead_update_ad() or psa_aead_update() if the algorithm for + * the operation requires it. If the algorithm does not require it, + * calling this function is optional, but if this function is called + * then the implementation must enforce the lengths. + * + * You may call this function before or after setting the nonce with + * psa_aead_set_nonce() or psa_aead_generate_nonce(). + * + * - For #PSA_ALG_CCM, calling this function is required. + * - For the other AEAD algorithms defined in this specification, calling + * this function is not required. + * - For vendor-defined algorithm, refer to the vendor documentation. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \param[in,out] operation Active AEAD operation. + * \param ad_length Size of the non-encrypted additional + * authenticated data in bytes. + * \param plaintext_length Size of the plaintext to encrypt in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, and + * psa_aead_update_ad() and psa_aead_update() must not have been + * called yet). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * At least one of the lengths is not acceptable for the chosen + * algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation, + size_t ad_length, + size_t plaintext_length); + +/** Pass additional data to an active AEAD operation. + * + * Additional data is authenticated, but not encrypted. + * + * You may call this function multiple times to pass successive fragments + * of the additional data. You may not call this function after passing + * data to encrypt or decrypt with psa_aead_update(). + * + * Before calling this function, you must: + * 1. Call either psa_aead_encrypt_setup() or psa_aead_decrypt_setup(). + * 2. Set the nonce with psa_aead_generate_nonce() or psa_aead_set_nonce(). + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \warning When decrypting, until psa_aead_verify() has returned #PSA_SUCCESS, + * there is no guarantee that the input is valid. Therefore, until + * you have called psa_aead_verify() and it has returned #PSA_SUCCESS, + * treat the input as untrusted and prepare to undo any action that + * depends on the input if psa_aead_verify() returns an error status. + * + * \param[in,out] operation Active AEAD operation. + * \param[in] input Buffer containing the fragment of + * additional data. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, have a nonce + * set, have lengths set if required by the algorithm, and + * psa_aead_update() must not have been called yet). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total input length overflows the additional data length that + * was previously specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length); + +/** Encrypt or decrypt a message fragment in an active AEAD operation. + * + * Before calling this function, you must: + * 1. Call either psa_aead_encrypt_setup() or psa_aead_decrypt_setup(). + * The choice of setup function determines whether this function + * encrypts or decrypts its input. + * 2. Set the nonce with psa_aead_generate_nonce() or psa_aead_set_nonce(). + * 3. Call psa_aead_update_ad() to pass all the additional data. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \warning When decrypting, until psa_aead_verify() has returned #PSA_SUCCESS, + * there is no guarantee that the input is valid. Therefore, until + * you have called psa_aead_verify() and it has returned #PSA_SUCCESS: + * - Do not use the output in any way other than storing it in a + * confidential location. If you take any action that depends + * on the tentative decrypted data, this action will need to be + * undone if the input turns out not to be valid. Furthermore, + * if an adversary can observe that this action took place + * (for example through timing), they may be able to use this + * fact as an oracle to decrypt any message encrypted with the + * same key. + * - In particular, do not copy the output anywhere but to a + * memory or storage space that you have exclusive access to. + * + * This function does not require the input to be aligned to any + * particular block boundary. If the implementation can only process + * a whole block at a time, it must consume all the input provided, but + * it may delay the end of the corresponding output until a subsequent + * call to psa_aead_update(), psa_aead_finish() or psa_aead_verify() + * provides sufficient input. The amount of data that can be delayed + * in this way is bounded by #PSA_AEAD_UPDATE_OUTPUT_SIZE. + * + * \param[in,out] operation Active AEAD operation. + * \param[in] input Buffer containing the message fragment to + * encrypt or decrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the output is to be written. + * \param output_size Size of the \p output buffer in bytes. + * This must be at least + * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c alg, + * \p input_length) where \c alg is the + * algorithm that is being calculated. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, have a nonce + * set, and have lengths set if required by the algorithm). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * You can determine a sufficient buffer size by calling + * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c alg, \p input_length) + * where \c alg is the algorithm that is being calculated. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update_ad() so far is + * less than the additional data length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total input length overflows the plaintext length that + * was previously specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_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); + +/** Finish encrypting a message in an AEAD operation. + * + * The operation must have been set up with psa_aead_encrypt_setup(). + * + * This function finishes the authentication of the additional data + * formed by concatenating the inputs passed to preceding calls to + * psa_aead_update_ad() with the plaintext formed by concatenating the + * inputs passed to preceding calls to psa_aead_update(). + * + * This function has two output buffers: + * - \p ciphertext contains trailing ciphertext that was buffered from + * preceding calls to psa_aead_update(). + * - \p tag contains the authentication tag. Its length is always + * #PSA_AEAD_TAG_LENGTH(\c alg) where \c alg is the AEAD algorithm + * that the operation performs. + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \param[in,out] operation Active AEAD operation. + * \param[out] ciphertext Buffer where the last part of the ciphertext + * is to be written. + * \param ciphertext_size Size of the \p ciphertext buffer in bytes. + * This must be at least + * #PSA_AEAD_FINISH_OUTPUT_SIZE(\c alg) where + * \c alg is the algorithm that is being + * calculated. + * \param[out] ciphertext_length On success, the number of bytes of + * returned ciphertext. + * \param[out] tag Buffer where the authentication tag is + * to be written. + * \param tag_size Size of the \p tag buffer in bytes. + * This must be at least + * #PSA_AEAD_TAG_LENGTH(\c alg) where \c alg is + * the algorithm that is being calculated. + * \param[out] tag_length On success, the number of bytes + * that make up the returned tag. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active encryption + * operation with a nonce set). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p ciphertext or \p tag buffer is too small. + * You can determine a sufficient buffer size for \p ciphertext by + * calling #PSA_AEAD_FINISH_OUTPUT_SIZE(\c alg) + * where \c alg is the algorithm that is being calculated. + * You can determine a sufficient buffer size for \p tag by + * calling #PSA_AEAD_TAG_LENGTH(\c alg). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update_ad() so far is + * less than the additional data length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update() so far is + * less than the plaintext length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_finish(psa_aead_operation_t *operation, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length, + uint8_t *tag, + size_t tag_size, + size_t *tag_length); + +/** Finish authenticating and decrypting a message in an AEAD operation. + * + * The operation must have been set up with psa_aead_decrypt_setup(). + * + * This function finishes the authenticated decryption of the message + * components: + * + * - The additional data consisting of the concatenation of the inputs + * passed to preceding calls to psa_aead_update_ad(). + * - The ciphertext consisting of the concatenation of the inputs passed to + * preceding calls to psa_aead_update(). + * - The tag passed to this function call. + * + * If the authentication tag is correct, this function outputs any remaining + * plaintext and reports success. If the authentication tag is not correct, + * this function returns #PSA_ERROR_INVALID_SIGNATURE. + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \note Implementations shall make the best effort to ensure that the + * comparison between the actual tag and the expected tag is performed + * in constant time. + * + * \param[in,out] operation Active AEAD operation. + * \param[out] plaintext Buffer where the last part of the plaintext + * is to be written. This is the remaining data + * from previous calls to psa_aead_update() + * that could not be processed until the end + * of the input. + * \param plaintext_size Size of the \p plaintext buffer in bytes. + * This must be at least + * #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c alg) where + * \c alg is the algorithm that is being + * calculated. + * \param[out] plaintext_length On success, the number of bytes of + * returned plaintext. + * \param[in] tag Buffer containing the authentication tag. + * \param tag_length Size of the \p tag buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The calculations were successful, but the authentication tag is + * not correct. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active decryption + * operation with a nonce set). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p plaintext buffer is too small. + * You can determine a sufficient buffer size for \p plaintext by + * calling #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c alg) + * where \c alg is the algorithm that is being calculated. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update_ad() so far is + * less than the additional data length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update() so far is + * less than the plaintext length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_verify(psa_aead_operation_t *operation, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length, + const uint8_t *tag, + size_t tag_length); + +/** Abort an AEAD operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_aead_encrypt_setup() or psa_aead_decrypt_setup() again. + * + * You may call this function any time after the operation object has + * been initialized as described in #psa_aead_operation_t. + * + * In particular, calling psa_aead_abort() after the operation has been + * terminated by a call to psa_aead_abort(), psa_aead_finish() or + * psa_aead_verify() is safe and has no effect. + * + * \param[in,out] operation Initialized AEAD operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_abort(psa_aead_operation_t *operation); + +/**@}*/ + +/** \defgroup asymmetric Asymmetric cryptography + * @{ + */ + +/** + * \brief Sign a hash or short message with a private key. + * + * Note that to perform a hash-and-sign signature algorithm, you must + * first calculate the hash by calling psa_hash_setup(), psa_hash_update() + * and psa_hash_finish(). Then pass the resulting hash as the \p hash + * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) + * to determine the hash algorithm to use. + * + * \param handle Handle to the key to use for the operation. + * It must be an asymmetric key pair. + * \param alg A signature algorithm that is compatible with + * the type of \p handle. + * \param[in] hash The hash or message to sign. + * \param hash_length Size of the \p hash buffer in bytes. + * \param[out] signature Buffer where the signature is to be written. + * \param signature_size Size of the \p signature buffer in bytes. + * \param[out] signature_length On success, the number of bytes + * that make up the returned signature value. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p signature buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p handle. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_sign_hash(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length); + +/** + * \brief Verify the signature a hash or short message using a public key. + * + * Note that to perform a hash-and-sign signature algorithm, you must + * first calculate the hash by calling psa_hash_setup(), psa_hash_update() + * and psa_hash_finish(). Then pass the resulting hash as the \p hash + * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) + * to determine the hash algorithm to use. + * + * \param handle Handle to the key to use for the operation. + * It must be a public key or an asymmetric key pair. + * \param alg A signature algorithm that is compatible with + * the type of \p handle. + * \param[in] hash The hash or message whose signature is to be + * verified. + * \param hash_length Size of the \p hash buffer in bytes. + * \param[in] signature Buffer containing the signature to verify. + * \param signature_length Size of the \p signature buffer in bytes. + * + * \retval #PSA_SUCCESS + * The signature is valid. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The calculation was perfomed successfully, but the passed + * signature is not a valid signature. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_verify_hash(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length); + +/** + * \brief Encrypt a short message with a public key. + * + * \param handle Handle to the key to use for the operation. + * It must be a public key or an asymmetric + * key pair. + * \param alg An asymmetric encryption algorithm that is + * compatible with the type of \p handle. + * \param[in] input The message to encrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[in] salt A salt or label, if supported by the + * encryption algorithm. + * If the algorithm does not support a + * salt, pass \c NULL. + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass \c NULL. + * + * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported. + * \param salt_length Size of the \p salt buffer in bytes. + * If \p salt is \c NULL, pass 0. + * \param[out] output Buffer where the encrypted message is to + * be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p handle. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_asymmetric_encrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** + * \brief Decrypt a short message with a private key. + * + * \param handle Handle to the key to use for the operation. + * It must be an asymmetric key pair. + * \param alg An asymmetric encryption algorithm that is + * compatible with the type of \p handle. + * \param[in] input The message to decrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[in] salt A salt or label, if supported by the + * encryption algorithm. + * If the algorithm does not support a + * salt, pass \c NULL. + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass \c NULL. + * + * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported. + * \param salt_length Size of the \p salt buffer in bytes. + * If \p salt is \c NULL, pass 0. + * \param[out] output Buffer where the decrypted message is to + * be written. + * \param output_size Size of the \c output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p handle. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_INVALID_PADDING + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_asymmetric_decrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/**@}*/ + +/** \defgroup key_derivation Key derivation and pseudorandom generation + * @{ + */ + +/** The type of the state data structure for key derivation operations. + * + * Before calling any function on a key derivation operation object, the + * application must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_key_derivation_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_key_derivation_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_KEY_DERIVATION_OPERATION_INIT, + * for example: + * \code + * psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_key_derivation_operation_init() + * to the structure, for example: + * \code + * psa_key_derivation_operation_t operation; + * operation = psa_key_derivation_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure except + * as directed by the documentation of a specific implementation. + */ +typedef struct psa_key_derivation_s psa_key_derivation_operation_t; + +/** \def PSA_KEY_DERIVATION_OPERATION_INIT + * + * This macro returns a suitable initializer for a key derivation operation + * object of type #psa_key_derivation_operation_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_KEY_DERIVATION_OPERATION_INIT {0} +#endif + +/** Return an initial value for a key derivation operation object. + */ +static psa_key_derivation_operation_t psa_key_derivation_operation_init(void); + +/** Set up a key derivation operation. + * + * A key derivation algorithm takes some inputs and uses them to generate + * a byte stream in a deterministic way. + * This byte stream can be used to produce keys and other + * cryptographic material. + * + * To derive a key: + * -# Start with an initialized object of type #psa_key_derivation_operation_t. + * -# Call psa_key_derivation_setup() to select the algorithm. + * -# Provide the inputs for the key derivation by calling + * psa_key_derivation_input_bytes() or psa_key_derivation_input_key() + * as appropriate. Which inputs are needed, in what order, and whether + * they may be keys and if so of what type depends on the algorithm. + * -# Optionally set the operation's maximum capacity with + * psa_key_derivation_set_capacity(). You may do this before, in the middle + * of or after providing inputs. For some algorithms, this step is mandatory + * because the output depends on the maximum capacity. + * -# To derive a key, call psa_key_derivation_output_key(). + * To derive a byte string for a different purpose, call + * psa_key_derivation_output_bytes(). + * Successive calls to these functions use successive output bytes + * calculated by the key derivation algorithm. + * -# Clean up the key derivation operation object with + * psa_key_derivation_abort(). + * + * If this function returns an error, the key derivation operation object is + * not changed. + * + * If an error occurs at any step after a call to psa_key_derivation_setup(), + * the operation will need to be reset by a call to psa_key_derivation_abort(). + * + * Implementations must reject an attempt to derive a key of size 0. + * + * \param[in,out] operation The key derivation operation object + * to set up. It must + * have been initialized but not set up yet. + * \param alg The key derivation algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_KEY_DERIVATION(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c alg is not a key derivation algorithm. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \c alg is not supported or is not a key derivation algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_setup( + psa_key_derivation_operation_t *operation, + psa_algorithm_t alg); + +/** Retrieve the current capacity of a key derivation operation. + * + * The capacity of a key derivation is the maximum number of bytes that it can + * return. When you get *N* bytes of output from a key derivation operation, + * this reduces its capacity by *N*. + * + * \param[in] operation The operation to query. + * \param[out] capacity On success, the capacity of the operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_get_capacity( + const psa_key_derivation_operation_t *operation, + size_t *capacity); + +/** Set the maximum capacity of a key derivation operation. + * + * The capacity of a key derivation operation is the maximum number of bytes + * that the key derivation operation can return from this point onwards. + * + * \param[in,out] operation The key derivation operation object to modify. + * \param capacity The new capacity of the operation. + * It must be less or equal to the operation's + * current capacity. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p capacity is larger than the operation's current capacity. + * In this case, the operation object remains valid and its capacity + * remains unchanged. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_set_capacity( + psa_key_derivation_operation_t *operation, + size_t capacity); + +/** Use the maximum possible capacity for a key derivation operation. + * + * Use this value as the capacity argument when setting up a key derivation + * to indicate that the operation should have the maximum possible capacity. + * The value of the maximum possible capacity depends on the key derivation + * algorithm. + */ +#define PSA_KEY_DERIVATION_UNLIMITED_CAPACITY ((size_t)(-1)) + +/** Provide an input for key derivation or key agreement. + * + * Which inputs are required and in what order depends on the algorithm. + * Refer to the documentation of each key derivation or key agreement + * algorithm for information. + * + * This function passes direct inputs, which is usually correct for + * non-secret inputs. To pass a secret input, which should be in a key + * object, call psa_key_derivation_input_key() instead of this function. + * Refer to the documentation of individual step types + * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t) + * for more information. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() and must not + * have produced any output yet. + * \param step Which step the input data is for. + * \param[in] data Input data to use. + * \param data_length Size of the \p data buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step is not compatible with the operation's algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step does not allow direct inputs. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this input \p step. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_input_bytes( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length); + +/** Provide an input for key derivation in the form of a key. + * + * Which inputs are required and in what order depends on the algorithm. + * Refer to the documentation of each key derivation or key agreement + * algorithm for information. + * + * This function obtains input from a key object, which is usually correct for + * secret inputs or for non-secret personalization strings kept in the key + * store. To pass a non-secret parameter which is not in the key store, + * call psa_key_derivation_input_bytes() instead of this function. + * Refer to the documentation of individual step types + * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t) + * for more information. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() and must not + * have produced any output yet. + * \param step Which step the input data is for. + * \param handle Handle to the key. It must have an + * appropriate type for \p step and must + * allow the usage #PSA_KEY_USAGE_DERIVE. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step is not compatible with the operation's algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step does not allow key inputs of the given type + * or does not allow key inputs at all. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this input \p step. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_input_key( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_handle_t handle); + +/** Perform a key agreement and use the shared secret as input to a key + * derivation. + * + * A key agreement algorithm takes two inputs: a private key \p private_key + * a public key \p peer_key. + * The result of this function is passed as input to a key derivation. + * The output of this key derivation can be extracted by reading from the + * resulting operation to produce keys and other cryptographic material. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() with a + * key agreement and derivation algorithm + * \c alg (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_KEY_AGREEMENT(\c alg) is true + * and #PSA_ALG_IS_RAW_KEY_AGREEMENT(\c alg) + * is false). + * The operation must be ready for an + * input of the type given by \p step. + * \param step Which step the input data is for. + * \param private_key Handle to the private key to use. + * \param[in] peer_key Public key of the peer. The peer key must be in the + * same format that psa_import_key() accepts for the + * public key type corresponding to the type of + * private_key. That is, this function performs the + * equivalent of + * #psa_import_key(..., + * `peer_key`, `peer_key_length`) where + * with key attributes indicating the public key + * type corresponding to the type of `private_key`. + * For example, for EC keys, this means that peer_key + * is interpreted as a point on the curve that the + * private key is on. The standard formats for public + * keys are documented in the documentation of + * psa_export_public_key(). + * \param peer_key_length Size of \p peer_key in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this key agreement \p step. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c private_key is not compatible with \c alg, + * or \p peer_key is not valid for \c alg or not compatible with + * \c private_key. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \c alg is not supported or is not a key derivation algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step does not allow an input resulting from a key agreement. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_key_agreement( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_handle_t private_key, + const uint8_t *peer_key, + size_t peer_key_length); + +/** Read some data from a key derivation operation. + * + * This function calculates output bytes from a key derivation algorithm and + * return those bytes. + * If you view the key derivation's output as a stream of bytes, this + * function destructively reads the requested number of bytes from the + * stream. + * The operation's capacity decreases by the number of bytes read. + * + * If this function returns an error status other than + * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to read from. + * \param[out] output Buffer where the output will be written. + * \param output_length Number of bytes to output. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INSUFFICIENT_DATA + * The operation's capacity was less than + * \p output_length bytes. Note that in this case, + * no output is written to the output buffer. + * The operation's capacity is set to 0, thus + * subsequent calls to this function will not + * succeed, even with a smaller output buffer. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active and completed + * all required input steps). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_output_bytes( + psa_key_derivation_operation_t *operation, + uint8_t *output, + size_t output_length); + +/** Derive a key from an ongoing key derivation operation. + * + * This function calculates output bytes from a key derivation algorithm + * and uses those bytes to generate a key deterministically. + * The key's location, usage policy, type and size are taken from + * \p attributes. + * + * If you view the key derivation's output as a stream of bytes, this + * function destructively reads as many bytes as required from the + * stream. + * The operation's capacity decreases by the number of bytes read. + * + * If this function returns an error status other than + * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * How much output is produced and consumed from the operation, and how + * the key is derived, depends on the key type: + * + * - For key types for which the key is an arbitrary sequence of bytes + * of a given size, this function is functionally equivalent to + * calling #psa_key_derivation_output_bytes + * and passing the resulting output to #psa_import_key. + * However, this function has a security benefit: + * if the implementation provides an isolation boundary then + * the key material is not exposed outside the isolation boundary. + * As a consequence, for these key types, this function always consumes + * exactly (\p bits / 8) bytes from the operation. + * The following key types defined in this specification follow this scheme: + * + * - #PSA_KEY_TYPE_AES; + * - #PSA_KEY_TYPE_ARC4; + * - #PSA_KEY_TYPE_CAMELLIA; + * - #PSA_KEY_TYPE_DERIVE; + * - #PSA_KEY_TYPE_HMAC. + * + * - For ECC keys on a Montgomery elliptic curve + * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a + * Montgomery curve), this function always draws a byte string whose + * length is determined by the curve, and sets the mandatory bits + * accordingly. That is: + * + * - #PSA_ECC_CURVE_CURVE25519: draw a 32-byte string + * and process it as specified in RFC 7748 §5. + * - #PSA_ECC_CURVE_CURVE448: draw a 56-byte string + * and process it as specified in RFC 7748 §5. + * + * - For key types for which the key is represented by a single sequence of + * \p bits bits with constraints as to which bit sequences are acceptable, + * this function draws a byte string of length (\p bits / 8) bytes rounded + * up to the nearest whole number of bytes. If the resulting byte string + * is acceptable, it becomes the key, otherwise the drawn bytes are discarded. + * This process is repeated until an acceptable byte string is drawn. + * The byte string drawn from the operation is interpreted as specified + * for the output produced by psa_export_key(). + * The following key types defined in this specification follow this scheme: + * + * - #PSA_KEY_TYPE_DES. + * Force-set the parity bits, but discard forbidden weak keys. + * For 2-key and 3-key triple-DES, the three keys are generated + * successively (for example, for 3-key triple-DES, + * if the first 8 bytes specify a weak key and the next 8 bytes do not, + * discard the first 8 bytes, use the next 8 bytes as the first key, + * and continue reading output from the operation to derive the other + * two keys). + * - Finite-field Diffie-Hellman keys (#PSA_KEY_TYPE_DH_KEY_PAIR(\c group) + * where \c group designates any Diffie-Hellman group) and + * ECC keys on a Weierstrass elliptic curve + * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a + * Weierstrass curve). + * For these key types, interpret the byte string as integer + * in big-endian order. Discard it if it is not in the range + * [0, *N* - 2] where *N* is the boundary of the private key domain + * (the prime *p* for Diffie-Hellman, the subprime *q* for DSA, + * or the order of the curve's base point for ECC). + * Add 1 to the resulting integer and use this as the private key *x*. + * This method allows compliance to NIST standards, specifically + * the methods titled "key-pair generation by testing candidates" + * in NIST SP 800-56A §5.6.1.1.4 for Diffie-Hellman, + * in FIPS 186-4 §B.1.2 for DSA, and + * in NIST SP 800-56A §5.6.1.2.2 or + * FIPS 186-4 §B.4.2 for elliptic curve keys. + * + * - For other key types, including #PSA_KEY_TYPE_RSA_KEY_PAIR, + * the way in which the operation output is consumed is + * implementation-defined. + * + * In all cases, the data that is read is discarded from the operation. + * The operation's capacity is decreased by the number of bytes read. + * + * For algorithms that take an input step #PSA_KEY_DERIVATION_INPUT_SECRET, + * the input to that step must be provided with psa_key_derivation_input_key(). + * Future versions of this specification may include additional restrictions + * on the derived key based on the attributes and strength of the secret key. + * + * \param[in] attributes The attributes for the new key. + * \param[in,out] operation The key derivation operation object to read from. + * \param[out] handle On success, a handle to the newly created key. + * \c 0 on failure. + * + * \retval #PSA_SUCCESS + * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_INSUFFICIENT_DATA + * There was not enough data to create the desired key. + * Note that in this case, no output is written to the output buffer. + * The operation's capacity is set to 0, thus subsequent calls to + * this function will not succeed, even with a smaller output buffer. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The key type or key size is not supported, either by the + * implementation in general or in this particular location. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The provided key attributes are not valid for the operation. + * \retval #PSA_ERROR_NOT_PERMITTED + * The #PSA_KEY_DERIVATION_INPUT_SECRET input was not provided through + * a key. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active and completed + * all required input steps). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_output_key( + const psa_key_attributes_t *attributes, + psa_key_derivation_operation_t *operation, + psa_key_handle_t *handle); + +/** Abort a key derivation operation. + * + * Aborting an operation frees all associated resources except for the \c + * operation structure itself. Once aborted, the operation object can be reused + * for another operation by calling psa_key_derivation_setup() again. + * + * This function may be called at any time after the operation + * object has been initialized as described in #psa_key_derivation_operation_t. + * + * In particular, it is valid to call psa_key_derivation_abort() twice, or to + * call psa_key_derivation_abort() on an operation that has not been set up. + * + * \param[in,out] operation The operation to abort. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_abort( + psa_key_derivation_operation_t *operation); + +/** Perform a key agreement and return the raw shared secret. + * + * \warning The raw result of a key agreement algorithm such as finite-field + * Diffie-Hellman or elliptic curve Diffie-Hellman has biases and should + * not be used directly as key material. It should instead be passed as + * input to a key derivation algorithm. To chain a key agreement with + * a key derivation, use psa_key_derivation_key_agreement() and other + * functions from the key derivation interface. + * + * \param alg The key agreement algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_RAW_KEY_AGREEMENT(\p alg) + * is true). + * \param private_key Handle to the private key to use. + * \param[in] peer_key Public key of the peer. It must be + * in the same format that psa_import_key() + * accepts. The standard formats for public + * keys are documented in the documentation + * of psa_export_public_key(). + * \param peer_key_length Size of \p peer_key in bytes. + * \param[out] output Buffer where the decrypted message is to + * be written. + * \param output_size Size of the \c output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p alg is not a key agreement algorithm + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p private_key is not compatible with \p alg, + * or \p peer_key is not valid for \p alg or not compatible with + * \p private_key. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p output_size is too small + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not a supported key agreement algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, + psa_key_handle_t private_key, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/**@}*/ + +/** \defgroup random Random generation + * @{ + */ + +/** + * \brief Generate random bytes. + * + * \warning This function **can** fail! Callers MUST check the return status + * and MUST NOT use the content of the output buffer if the return + * status is not #PSA_SUCCESS. + * + * \note To generate a key, use psa_generate_key() instead. + * + * \param[out] output Output buffer for the generated data. + * \param output_size Number of bytes to generate and output. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_generate_random(uint8_t *output, + size_t output_size); + +/** + * \brief Generate a key or key pair. + * + * The key is generated randomly. + * Its location, usage policy, type and size are taken from \p attributes. + * + * Implementations must reject an attempt to generate a key of size 0. + * + * The following type-specific considerations apply: + * - For RSA keys (#PSA_KEY_TYPE_RSA_KEY_PAIR), + * the public exponent is 65537. + * The modulus is a product of two probabilistic primes + * between 2^{n-1} and 2^n where n is the bit size specified in the + * attributes. + * + * \param[in] attributes The attributes for the new key. + * \param[out] handle On success, a handle to the newly created key. + * \c 0 on failure. + * + * \retval #PSA_SUCCESS + * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, + psa_key_handle_t *handle); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +/* The file "crypto_sizes.h" contains definitions for size calculation + * macros whose definitions are implementation-specific. */ +#include "psa/crypto_sizes.h" + +/* The file "crypto_struct.h" contains definitions for + * implementation-specific structs that are declared above. */ +#include "psa/crypto_struct.h" + +/* The file "crypto_extra.h" contains vendor-specific definitions. This + * can include vendor-defined algorithms, extra functions, etc. */ +#include "psa/crypto_extra.h" + +#endif /* PSA_CRYPTO_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_compat.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_compat.h new file mode 100644 index 0000000..518008b --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_compat.h @@ -0,0 +1,111 @@ +/** + * \file psa/crypto_compat.h + * + * \brief PSA cryptography module: Backward compatibility aliases + * + * This header declares alternative names for macro and functions. + * New application code should not use these names. + * These names may be removed in a future version of Mbed Crypto. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + */ +/* + * Copyright (C) 2019-2020, ARM Limited, 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef PSA_CRYPTO_COMPAT_H +#define PSA_CRYPTO_COMPAT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +/* + * Mechanism for declaring deprecated values + */ +#if defined(MBEDTLS_DEPRECATED_WARNING) && !defined(MBEDTLS_PSA_DEPRECATED) +#define MBEDTLS_PSA_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_PSA_DEPRECATED +#endif + +typedef MBEDTLS_PSA_DEPRECATED size_t mbedtls_deprecated_size_t; +typedef MBEDTLS_PSA_DEPRECATED psa_status_t mbedtls_deprecated_psa_status_t; +typedef MBEDTLS_PSA_DEPRECATED psa_key_usage_t mbedtls_deprecated_psa_key_usage_t; + +#define MBEDTLS_DEPRECATED_CONSTANT( type, value ) \ + ( (mbedtls_deprecated_##type) ( value ) ) + +/* + * Deprecated PSA Crypto error code definitions (PSA Crypto API <= 1.0 beta2) + */ +#define PSA_ERROR_UNKNOWN_ERROR \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_GENERIC_ERROR ) +#define PSA_ERROR_OCCUPIED_SLOT \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_ALREADY_EXISTS ) +#define PSA_ERROR_EMPTY_SLOT \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_DOES_NOT_EXIST ) +#define PSA_ERROR_INSUFFICIENT_CAPACITY \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_INSUFFICIENT_DATA ) +#define PSA_ERROR_TAMPERING_DETECTED \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_CORRUPTION_DETECTED ) + +/* + * Deprecated PSA Crypto numerical encodings (PSA Crypto API <= 1.0 beta3) + */ +#define PSA_KEY_USAGE_SIGN \ + MBEDTLS_DEPRECATED_CONSTANT( psa_key_usage_t, PSA_KEY_USAGE_SIGN_HASH ) +#define PSA_KEY_USAGE_VERIFY \ + MBEDTLS_DEPRECATED_CONSTANT( psa_key_usage_t, PSA_KEY_USAGE_VERIFY_HASH ) + +/* + * Deprecated PSA Crypto size calculation macros (PSA Crypto API <= 1.0 beta3) + */ +#define PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE \ + MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_SIGNATURE_MAX_SIZE ) +#define PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE( key_type, key_bits, alg ) \ + MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_SIGN_OUTPUT_SIZE( key_type, key_bits, alg ) ) + +/* + * Deprecated PSA Crypto function names (PSA Crypto API <= 1.0 beta3) + */ +MBEDTLS_PSA_DEPRECATED psa_status_t psa_asymmetric_sign( psa_key_handle_t key, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length ); + +MBEDTLS_PSA_DEPRECATED psa_status_t psa_asymmetric_verify( psa_key_handle_t key, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length ); + +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_COMPAT_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_extra.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_extra.h new file mode 100644 index 0000000..33c9c05 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_extra.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +/** + * \file psa/crypto_extra.h + * + * \brief PSA cryptography module: vendor extensions + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * This file is reserved for vendor-specific definitions. + */ + +#ifndef PSA_CRYPTO_EXTRA_H +#define PSA_CRYPTO_EXTRA_H + +#include "psa/crypto_compat.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \brief Declare the enrollment algorithm for a key. + * + * An operation on a key may indifferently use the algorithm set with + * psa_set_key_algorithm() or with this function. + * + * \param[out] attributes The attribute structure to write to. + * \param alg2 A second algorithm that the key may be used + * for, in addition to the algorithm set with + * psa_set_key_algorithm(). + * + * \warning Setting an enrollment algorithm is not recommended, because + * using the same key with different algorithms can allow some + * attacks based on arithmetic relations between different + * computations made with the same key, or can escalate harmless + * side channels into exploitable ones. Use this function only + * if it is necessary to support a protocol for which it has been + * verified that the usage of the key with multiple algorithms + * is safe. + */ +static inline void psa_set_key_enrollment_algorithm( + psa_key_attributes_t *attributes, + psa_algorithm_t alg2) +{ + attributes->core.policy.alg2 = alg2; +} + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_EXTRA_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_platform.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_platform.h new file mode 100644 index 0000000..c3120e4 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_platform.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +/** + * \file psa/crypto_platform.h + * + * \brief PSA cryptography module: Mbed TLS platform definitions + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * This file contains platform-dependent type definitions. + * + * In implementations with isolation between the application and the + * cryptography module, implementers should take care to ensure that + * the definitions that are exposed to applications match what the + * module implements. + */ + +#ifndef PSA_CRYPTO_PLATFORM_H +#define PSA_CRYPTO_PLATFORM_H + +/* PSA requires several types which C99 provides in stdint.h. */ +#include + +/* Integral type representing a key handle. */ +typedef uint16_t psa_key_handle_t; + +/* This implementation distinguishes *application key identifiers*, which + * are the key identifiers specified by the application, from + * *key file identifiers*, which are the key identifiers that the library + * sees internally. The two types can be different if there is a remote + * call layer between the application and the library which supports + * multiple client applications that do not have access to each others' + * keys. The point of having different types is that the key file + * identifier may encode not only the key identifier specified by the + * application, but also the the identity of the application. + * + * Note that this is an internal concept of the library and the remote + * call layer. The application itself never sees anything other than + * #psa_app_key_id_t with its standard definition. + */ + +/* The application key identifier is always what the application sees as + * #psa_key_id_t. */ +typedef uint32_t psa_app_key_id_t; + +#endif /* PSA_CRYPTO_PLATFORM_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_sizes.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_sizes.h new file mode 100644 index 0000000..4f67501 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_sizes.h @@ -0,0 +1,650 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +/** + * \file psa/crypto_sizes.h + * + * \brief PSA cryptography module: Mbed TLS buffer size macros + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * This file contains the definitions of macros that are useful to + * compute buffer sizes. The signatures and semantics of these macros + * are standardized, but the definitions are not, because they depend on + * the available algorithms and, in some cases, on permitted tolerances + * on buffer sizes. + * + * In implementations with isolation between the application and the + * cryptography module, implementers should take care to ensure that + * the definitions that are exposed to applications match what the + * module implements. + * + * Macros that compute sizes whose values do not depend on the + * implementation are in crypto.h. + */ + +#ifndef PSA_CRYPTO_SIZES_H +#define PSA_CRYPTO_SIZES_H + +#define PSA_BITS_TO_BYTES(bits) (((bits) + 7) / 8) +#define PSA_BYTES_TO_BITS(bytes) ((bytes) * 8) + +#define PSA_ROUND_UP_TO_MULTIPLE(block_size, length) \ + (((length) + (block_size) - 1) / (block_size) * (block_size)) + +/** The size of the output of psa_hash_finish(), in bytes. + * + * This is also the hash size that psa_hash_verify() expects. + * + * \param alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p alg) is true), or an HMAC algorithm + * (#PSA_ALG_HMAC(\c hash_alg) where \c hash_alg is a + * hash algorithm). + * + * \return The hash size for the specified hash algorithm. + * If the hash algorithm is not recognized, return 0. + * An implementation may return either 0 or the correct size + * for a hash algorithm that it recognizes, but does not support. + */ +#define PSA_HASH_SIZE(alg) \ + ( \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD2 ? 16 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD4 ? 16 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 16 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 20 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 20 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_224 ? 28 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_256 ? 32 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_384 ? 48 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512 ? 64 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 28 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 32 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 28 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 32 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 48 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 64 : \ + 0) + +/** \def PSA_HASH_MAX_SIZE + * + * Maximum size of a hash. + * + * This macro must expand to a compile-time constant integer. This value + * should be the maximum size of a hash supported by the implementation, + * in bytes, and must be no smaller than this maximum. + */ +/* Note: for HMAC-SHA-3, the block size is 144 bytes for HMAC-SHA3-226, + * 136 bytes for HMAC-SHA3-256, 104 bytes for SHA3-384, 72 bytes for + * HMAC-SHA3-512. */ +#define PSA_HASH_MAX_SIZE 64 +#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 128 + +/** \def PSA_MAC_MAX_SIZE + * + * Maximum size of a MAC. + * + * This macro must expand to a compile-time constant integer. This value + * should be the maximum size of a MAC supported by the implementation, + * in bytes, and must be no smaller than this maximum. + */ +/* All non-HMAC MACs have a maximum size that's smaller than the + * minimum possible value of PSA_HASH_MAX_SIZE in this implementation. */ +/* Note that the encoding of truncated MAC algorithms limits this value + * to 64 bytes. + */ +#define PSA_MAC_MAX_SIZE PSA_HASH_MAX_SIZE + +/** The tag size for an AEAD algorithm, in bytes. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return The tag size for the specified algorithm. + * If the AEAD algorithm does not have an identified + * tag that can be distinguished from the rest of + * the ciphertext, return 0. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +#define PSA_AEAD_TAG_LENGTH(alg) \ + (PSA_ALG_IS_AEAD(alg) ? \ + (((alg) & PSA_ALG_AEAD_TAG_LENGTH_MASK) >> PSA_AEAD_TAG_LENGTH_OFFSET) : \ + 0) + +/* The maximum size of an RSA key on this implementation, in bits. + * This is a vendor-specific macro. + * + * Mbed TLS does not set a hard limit on the size of RSA keys: any key + * whose parameters fit in a bignum is accepted. However large keys can + * induce a large memory usage and long computation times. Unlike other + * auxiliary macros in this file and in crypto.h, which reflect how the + * library is configured, this macro defines how the library is + * configured. This implementation refuses to import or generate an + * RSA key whose size is larger than the value defined here. + * + * Note that an implementation may set different size limits for different + * operations, and does not need to accept all key sizes up to the limit. */ +#define PSA_VENDOR_RSA_MAX_KEY_BITS 4096 + +/* The maximum size of an ECC key on this implementation, in bits. + * This is a vendor-specific macro. */ +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 521 + +/** Bit size associated with an elliptic curve. + * + * \param curve An elliptic curve (value of type #psa_ecc_curve_t). + * + * \return The size associated with \p curve, in bits. + * This may be 0 if the implementation does not support + * the specified curve. + */ +#define PSA_ECC_CURVE_BITS(curve) \ + ((curve) == PSA_ECC_CURVE_SECT163K1 ? 163 : \ + (curve) == PSA_ECC_CURVE_SECT163R1 ? 163 : \ + (curve) == PSA_ECC_CURVE_SECT163R2 ? 163 : \ + (curve) == PSA_ECC_CURVE_SECT193R1 ? 193 : \ + (curve) == PSA_ECC_CURVE_SECT193R2 ? 193 : \ + (curve) == PSA_ECC_CURVE_SECT233K1 ? 233 : \ + (curve) == PSA_ECC_CURVE_SECT233R1 ? 233 : \ + (curve) == PSA_ECC_CURVE_SECT239K1 ? 239 : \ + (curve) == PSA_ECC_CURVE_SECT283K1 ? 283 : \ + (curve) == PSA_ECC_CURVE_SECT283R1 ? 283 : \ + (curve) == PSA_ECC_CURVE_SECT409K1 ? 409 : \ + (curve) == PSA_ECC_CURVE_SECT409R1 ? 409 : \ + (curve) == PSA_ECC_CURVE_SECT571K1 ? 571 : \ + (curve) == PSA_ECC_CURVE_SECT571R1 ? 571 : \ + (curve) == PSA_ECC_CURVE_SECP160K1 ? 160 : \ + (curve) == PSA_ECC_CURVE_SECP160R1 ? 160 : \ + (curve) == PSA_ECC_CURVE_SECP160R2 ? 160 : \ + (curve) == PSA_ECC_CURVE_SECP192K1 ? 192 : \ + (curve) == PSA_ECC_CURVE_SECP192R1 ? 192 : \ + (curve) == PSA_ECC_CURVE_SECP224K1 ? 224 : \ + (curve) == PSA_ECC_CURVE_SECP224R1 ? 224 : \ + (curve) == PSA_ECC_CURVE_SECP256K1 ? 256 : \ + (curve) == PSA_ECC_CURVE_SECP256R1 ? 256 : \ + (curve) == PSA_ECC_CURVE_SECP384R1 ? 384 : \ + (curve) == PSA_ECC_CURVE_SECP521R1 ? 521 : \ + (curve) == PSA_ECC_CURVE_BRAINPOOL_P256R1 ? 256 : \ + (curve) == PSA_ECC_CURVE_BRAINPOOL_P384R1 ? 384 : \ + (curve) == PSA_ECC_CURVE_BRAINPOOL_P512R1 ? 512 : \ + (curve) == PSA_ECC_CURVE_CURVE25519 ? 255 : \ + (curve) == PSA_ECC_CURVE_CURVE448 ? 448 : \ + 0) + +/** \def PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN + * + * This macro returns the maximum length of the PSK supported + * by the TLS-1.2 PSK-to-MS key derivation. + * + * Quoting RFC 4279, Sect 5.3: + * TLS implementations supporting these ciphersuites MUST support + * arbitrary PSK identities up to 128 octets in length, and arbitrary + * PSKs up to 64 octets in length. Supporting longer identities and + * keys is RECOMMENDED. + * + * Therefore, no implementation should define a value smaller than 64 + * for #PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN. + */ +#define PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN 128 + +/** The maximum size of a block cipher supported by the implementation. */ +#define PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE 16 + +/** The size of the output of psa_mac_sign_finish(), in bytes. + * + * This is also the MAC size that psa_mac_verify_finish() expects. + * + * \param key_type The type of the MAC key. + * \param key_bits The size of the MAC key in bits. + * \param alg A MAC algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_MAC(\p alg) is true). + * + * \return The MAC size for the specified algorithm with + * the specified key parameters. + * \return 0 if the MAC algorithm is not recognized. + * \return Either 0 or the correct size for a MAC algorithm that + * the implementation recognizes, but does not support. + * \return Unspecified if the key parameters are not consistent + * with the algorithm. + */ +#define PSA_MAC_FINAL_SIZE(key_type, key_bits, alg) \ + ((alg) & PSA_ALG_MAC_TRUNCATION_MASK ? PSA_MAC_TRUNCATED_LENGTH(alg) : \ + PSA_ALG_IS_HMAC(alg) ? PSA_HASH_SIZE(PSA_ALG_HMAC_GET_HASH(alg)) : \ + PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) ? PSA_BLOCK_CIPHER_BLOCK_SIZE(key_type) : \ + ((void)(key_type), (void)(key_bits), 0)) + +/** The maximum size of the output of psa_aead_encrypt(), in bytes. + * + * If the size of the ciphertext buffer is at least this large, it is + * guaranteed that psa_aead_encrypt() will not fail due to an + * insufficient buffer size. Depending on the algorithm, the actual size of + * the ciphertext may be smaller. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param plaintext_length Size of the plaintext in bytes. + * + * \return The AEAD ciphertext size for the specified + * algorithm. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +#define PSA_AEAD_ENCRYPT_OUTPUT_SIZE(alg, plaintext_length) \ + (PSA_AEAD_TAG_LENGTH(alg) != 0 ? \ + (plaintext_length) + PSA_AEAD_TAG_LENGTH(alg) : \ + 0) + +/** The maximum size of the output of psa_aead_decrypt(), in bytes. + * + * If the size of the plaintext buffer is at least this large, it is + * guaranteed that psa_aead_decrypt() will not fail due to an + * insufficient buffer size. Depending on the algorithm, the actual size of + * the plaintext may be smaller. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param ciphertext_length Size of the plaintext in bytes. + * + * \return The AEAD ciphertext size for the specified + * algorithm. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +#define PSA_AEAD_DECRYPT_OUTPUT_SIZE(alg, ciphertext_length) \ + (PSA_AEAD_TAG_LENGTH(alg) != 0 ? \ + (ciphertext_length) - PSA_AEAD_TAG_LENGTH(alg) : \ + 0) + +/** A sufficient output buffer size for psa_aead_update(). + * + * If the size of the output buffer is at least this large, it is + * guaranteed that psa_aead_update() will not fail due to an + * insufficient buffer size. The actual size of the output may be smaller + * in any given call. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param input_length Size of the input in bytes. + * + * \return A sufficient output buffer size for the specified + * algorithm. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +/* For all the AEAD modes defined in this specification, it is possible + * to emit output without delay. However, hardware may not always be + * capable of this. So for modes based on a block cipher, allow the + * implementation to delay the output until it has a full block. */ +#define PSA_AEAD_UPDATE_OUTPUT_SIZE(alg, input_length) \ + (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ + PSA_ROUND_UP_TO_MULTIPLE(PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE, (input_length)) : \ + (input_length)) + +/** A sufficient ciphertext buffer size for psa_aead_finish(). + * + * If the size of the ciphertext buffer is at least this large, it is + * guaranteed that psa_aead_finish() will not fail due to an + * insufficient ciphertext buffer size. The actual size of the output may + * be smaller in any given call. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return A sufficient ciphertext buffer size for the + * specified algorithm. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +#define PSA_AEAD_FINISH_OUTPUT_SIZE(alg) \ + (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ + PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE : \ + 0) + +/** A sufficient plaintext buffer size for psa_aead_verify(). + * + * If the size of the plaintext buffer is at least this large, it is + * guaranteed that psa_aead_verify() will not fail due to an + * insufficient plaintext buffer size. The actual size of the output may + * be smaller in any given call. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return A sufficient plaintext buffer size for the + * specified algorithm. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +#define PSA_AEAD_VERIFY_OUTPUT_SIZE(alg) \ + (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ + PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE : \ + 0) + +#define PSA_RSA_MINIMUM_PADDING_SIZE(alg) \ + (PSA_ALG_IS_RSA_OAEP(alg) ? \ + 2 * PSA_HASH_SIZE(PSA_ALG_RSA_OAEP_GET_HASH(alg)) + 1 : \ + 11 /*PKCS#1v1.5*/) + +/** + * \brief ECDSA signature size for a given curve bit size + * + * \param curve_bits Curve size in bits. + * \return Signature size in bytes. + * + * \note This macro returns a compile-time constant if its argument is one. + */ +#define PSA_ECDSA_SIGNATURE_SIZE(curve_bits) \ + (PSA_BITS_TO_BYTES(curve_bits) * 2) + +/** Sufficient signature buffer size for psa_sign_hash(). + * + * This macro returns a sufficient buffer size for a signature using a key + * of the specified type and size, with the specified algorithm. + * Note that the actual size of the signature may be smaller + * (some algorithms produce a variable-size signature). + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type An asymmetric key type (this may indifferently be a + * key pair type or a public key type). + * \param key_bits The size of the key in bits. + * \param alg The signature algorithm. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_sign_hash() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported + * by the implementation, this macro shall return either a + * sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_SIGN_OUTPUT_SIZE(key_type, key_bits, alg) \ + (PSA_KEY_TYPE_IS_RSA(key_type) ? ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \ + PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_ECDSA_SIGNATURE_SIZE(key_bits) : \ + ((void)alg, 0)) + +#define PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE \ + PSA_ECDSA_SIGNATURE_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) + +/** \def PSA_SIGNATURE_MAX_SIZE + * + * Maximum size of an asymmetric signature. + * + * This macro must expand to a compile-time constant integer. This value + * should be the maximum size of a signature supported by the implementation, + * in bytes, and must be no smaller than this maximum. + */ +#define PSA_SIGNATURE_MAX_SIZE \ + (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) > PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE ? \ + PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) : \ + PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE) + +/** Sufficient output buffer size for psa_asymmetric_encrypt(). + * + * This macro returns a sufficient buffer size for a ciphertext produced using + * a key of the specified type and size, with the specified algorithm. + * Note that the actual size of the ciphertext may be smaller, depending + * on the algorithm. + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type An asymmetric key type (this may indifferently be a + * key pair type or a public key type). + * \param key_bits The size of the key in bits. + * \param alg The signature algorithm. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_asymmetric_encrypt() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported + * by the implementation, this macro shall return either a + * sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \ + (PSA_KEY_TYPE_IS_RSA(key_type) ? \ + ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \ + 0) + +/** Sufficient output buffer size for psa_asymmetric_decrypt(). + * + * This macro returns a sufficient buffer size for a ciphertext produced using + * a key of the specified type and size, with the specified algorithm. + * Note that the actual size of the ciphertext may be smaller, depending + * on the algorithm. + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type An asymmetric key type (this may indifferently be a + * key pair type or a public key type). + * \param key_bits The size of the key in bits. + * \param alg The signature algorithm. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_asymmetric_decrypt() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported + * by the implementation, this macro shall return either a + * sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \ + (PSA_KEY_TYPE_IS_RSA(key_type) ? \ + PSA_BITS_TO_BYTES(key_bits) - PSA_RSA_MINIMUM_PADDING_SIZE(alg) : \ + 0) + +/* Maximum size of the ASN.1 encoding of an INTEGER with the specified + * number of bits. + * + * This definition assumes that bits <= 2^19 - 9 so that the length field + * is at most 3 bytes. The length of the encoding is the length of the + * bit string padded to a whole number of bytes plus: + * - 1 type byte; + * - 1 to 3 length bytes; + * - 0 to 1 bytes of leading 0 due to the sign bit. + */ +#define PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(bits) \ + ((bits) / 8 + 5) + +/* Maximum size of the export encoding of an RSA public key. + * Assumes that the public exponent is less than 2^32. + * + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER } -- e + * + * - 4 bytes of SEQUENCE overhead; + * - n : INTEGER; + * - 7 bytes for the public exponent. + */ +#define PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) \ + (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) + 11) + +/* Maximum size of the export encoding of an RSA key pair. + * Assumes thatthe public exponent is less than 2^32 and that the size + * difference between the two primes is at most 1 bit. + * + * RSAPrivateKey ::= SEQUENCE { + * version Version, -- 0 + * modulus INTEGER, -- N-bit + * publicExponent INTEGER, -- 32-bit + * privateExponent INTEGER, -- N-bit + * prime1 INTEGER, -- N/2-bit + * prime2 INTEGER, -- N/2-bit + * exponent1 INTEGER, -- N/2-bit + * exponent2 INTEGER, -- N/2-bit + * coefficient INTEGER, -- N/2-bit + * } + * + * - 4 bytes of SEQUENCE overhead; + * - 3 bytes of version; + * - 7 half-size INTEGERs plus 2 full-size INTEGERs, + * overapproximated as 9 half-size INTEGERS; + * - 7 bytes for the public exponent. + */ +#define PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits) \ + (9 * PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE((key_bits) / 2 + 1) + 14) + +/* Maximum size of the export encoding of a DSA public key. + * + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } -- contains DSAPublicKey + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters Dss-Parms } -- SEQUENCE of 3 INTEGERs + * DSAPublicKey ::= INTEGER -- public key, Y + * + * - 3 * 4 bytes of SEQUENCE overhead; + * - 1 + 1 + 7 bytes of algorithm (DSA OID); + * - 4 bytes of BIT STRING overhead; + * - 3 full-size INTEGERs (p, g, y); + * - 1 + 1 + 32 bytes for 1 sub-size INTEGER (q <= 256 bits). + */ +#define PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) \ + (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3 + 59) + +/* Maximum size of the export encoding of a DSA key pair. + * + * DSAPrivateKey ::= SEQUENCE { + * version Version, -- 0 + * prime INTEGER, -- p + * subprime INTEGER, -- q + * generator INTEGER, -- g + * public INTEGER, -- y + * private INTEGER, -- x + * } + * + * - 4 bytes of SEQUENCE overhead; + * - 3 bytes of version; + * - 3 full-size INTEGERs (p, g, y); + * - 2 * (1 + 1 + 32) bytes for 2 sub-size INTEGERs (q, x <= 256 bits). + */ +#define PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits) \ + (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3 + 75) + +/* Maximum size of the export encoding of an ECC public key. + * + * The representation of an ECC public key is: + * - The byte 0x04; + * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; + * - `y_P` as a `ceiling(m/8)`-byte string, big-endian; + * - where m is the bit size associated with the curve. + * + * - 1 byte + 2 * point size. + */ +#define PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) \ + (2 * PSA_BITS_TO_BYTES(key_bits) + 1) + +/* Maximum size of the export encoding of an ECC key pair. + * + * An ECC key pair is represented by the secret value. + */ +#define PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) \ + (PSA_BITS_TO_BYTES(key_bits)) + +/** Sufficient output buffer size for psa_export_key() or psa_export_public_key(). + * + * This macro returns a compile-time constant if its arguments are + * compile-time constants. + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * The following code illustrates how to allocate enough memory to export + * a key by querying the key type and size at runtime. + * \code{c} + * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + * psa_status_t status; + * status = psa_get_key_attributes(key, &attributes); + * if (status != PSA_SUCCESS) handle_error(...); + * psa_key_type_t key_type = psa_get_key_type(&attributes); + * size_t key_bits = psa_get_key_bits(&attributes); + * size_t buffer_size = PSA_KEY_EXPORT_MAX_SIZE(key_type, key_bits); + * psa_reset_key_attributes(&attributes); + * uint8_t *buffer = malloc(buffer_size); + * if (buffer == NULL) handle_error(...); + * size_t buffer_length; + * status = psa_export_key(key, buffer, buffer_size, &buffer_length); + * if (status != PSA_SUCCESS) handle_error(...); + * \endcode + * + * For psa_export_public_key(), calculate the buffer size from the + * public key type. You can use the macro #PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR + * to convert a key pair type to the corresponding public key type. + * \code{c} + * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + * psa_status_t status; + * status = psa_get_key_attributes(key, &attributes); + * if (status != PSA_SUCCESS) handle_error(...); + * psa_key_type_t key_type = psa_get_key_type(&attributes); + * psa_key_type_t public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(key_type); + * size_t key_bits = psa_get_key_bits(&attributes); + * size_t buffer_size = PSA_KEY_EXPORT_MAX_SIZE(public_key_type, key_bits); + * psa_reset_key_attributes(&attributes); + * uint8_t *buffer = malloc(buffer_size); + * if (buffer == NULL) handle_error(...); + * size_t buffer_length; + * status = psa_export_public_key(key, buffer, buffer_size, &buffer_length); + * if (status != PSA_SUCCESS) handle_error(...); + * \endcode + * + * \param key_type A supported key type. + * \param key_bits The size of the key in bits. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_sign_hash() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported + * by the implementation, this macro shall return either a + * sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_KEY_EXPORT_MAX_SIZE(key_type, key_bits) \ + (PSA_KEY_TYPE_IS_UNSTRUCTURED(key_type) ? PSA_BITS_TO_BYTES(key_bits) : \ + (key_type) == PSA_KEY_TYPE_RSA_KEY_PAIR ? PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits) : \ + (key_type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY ? PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ + (key_type) == PSA_KEY_TYPE_DSA_KEY_PAIR ? PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits) : \ + (key_type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY ? PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ + PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) ? PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) : \ + PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type) ? PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) : \ + 0) + +#endif /* PSA_CRYPTO_SIZES_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_struct.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_struct.h new file mode 100644 index 0000000..403a734 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_struct.h @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +/** + * \file psa/crypto_struct.h + * + * \brief PSA cryptography module: structured type implementations + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * This file contains the definitions of some data structures with + * implementation-specific definitions. + * + * In implementations with isolation between the application and the + * cryptography module, it is expected that the front-end and the back-end + * would have different versions of this file. + */ + +#ifndef PSA_CRYPTO_STRUCT_H +#define PSA_CRYPTO_STRUCT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Note that the below structures are different from the decalrations in + * mbed-crypto. This is because TF-M maintains 'front-end' and 'back-end' + * versions of this header. In the front-end version, exported to NS + * clients in interface/include/psa, a crypto operation is defined as an + * opaque handle to a context in the Crypto service. The back-end + * version, directly included from the mbed-crypto repo by the Crypto + * service, contains the full definition of the operation structs. + * + * One of the functions of the Crypto service is to allocate the back-end + * operation contexts in its own partition memory (in crypto_alloc.c), + * and then do the mapping between front-end operation handles passed by + * NS clients and the corresponding back-end operation contexts. The + * advantage of doing it this way is that internal mbed-crypto state is never + * exposed to the NS client. + */ + +struct psa_hash_operation_s +{ + uint32_t handle; +}; + +#define PSA_HASH_OPERATION_INIT {0} +static inline struct psa_hash_operation_s psa_hash_operation_init( void ) +{ + const struct psa_hash_operation_s v = PSA_HASH_OPERATION_INIT; + return( v ); +} + +struct psa_mac_operation_s +{ + uint32_t handle; +}; + +#define PSA_MAC_OPERATION_INIT {0} +static inline struct psa_mac_operation_s psa_mac_operation_init( void ) +{ + const struct psa_mac_operation_s v = PSA_MAC_OPERATION_INIT; + return( v ); +} + +struct psa_cipher_operation_s +{ + uint32_t handle; +}; + +#define PSA_CIPHER_OPERATION_INIT {0} +static inline struct psa_cipher_operation_s psa_cipher_operation_init( void ) +{ + const struct psa_cipher_operation_s v = PSA_CIPHER_OPERATION_INIT; + return( v ); +} + +struct psa_aead_operation_s +{ + uint32_t handle; +}; + +#define PSA_AEAD_OPERATION_INIT {0} +static inline struct psa_aead_operation_s psa_aead_operation_init( void ) +{ + const struct psa_aead_operation_s v = PSA_AEAD_OPERATION_INIT; + return( v ); +} + +struct psa_key_derivation_s +{ + uint32_t handle; +}; + +#define PSA_KEY_DERIVATION_OPERATION_INIT {0} +static inline struct psa_key_derivation_s psa_key_derivation_operation_init( void ) +{ + const struct psa_key_derivation_s v = PSA_KEY_DERIVATION_OPERATION_INIT; + return( v ); +} + +struct psa_key_policy_s +{ + psa_key_usage_t usage; + psa_algorithm_t alg; + psa_algorithm_t alg2; +}; +typedef struct psa_key_policy_s psa_key_policy_t; + +#define PSA_KEY_POLICY_INIT {0, 0, 0} +static inline struct psa_key_policy_s psa_key_policy_init( void ) +{ + const struct psa_key_policy_s v = PSA_KEY_POLICY_INIT; + return( v ); +} + +/* The type used internally for key sizes. + * Public interfaces use size_t, but internally we use a smaller type. */ +typedef uint16_t psa_key_bits_t; +/* The maximum value of the type used to represent bit-sizes. + * This is used to mark an invalid key size. */ +#define PSA_KEY_BITS_TOO_LARGE ( (psa_key_bits_t) ( -1 ) ) +/* The maximum size of a key in bits. + * Currently defined as the maximum that can be represented, rounded down + * to a whole number of bytes. + * This is an uncast value so that it can be used in preprocessor + * conditionals. */ +#define PSA_MAX_KEY_BITS 0xfff8 + +/** A mask of flags that can be stored in key attributes. + * + * This type is also used internally to store flags in slots. Internal + * flags are defined in library/psa_crypto_core.h. Internal flags may have + * the same value as external flags if they are properly handled during + * key creation and in psa_get_key_attributes. + */ +typedef uint16_t psa_key_attributes_flag_t; + +#define MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER \ + ( (psa_key_attributes_flag_t) 0x0001 ) + +/* A mask of key attribute flags used externally only. + * Only meant for internal checks inside the library. */ +#define MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY ( \ + MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER | \ + 0 ) + +/* A mask of key attribute flags used both internally and externally. + * Currently there aren't any. */ +#define MBEDTLS_PSA_KA_MASK_DUAL_USE ( \ + 0 ) + +typedef struct +{ + psa_key_type_t type; + psa_key_lifetime_t lifetime; + psa_key_id_t id; + psa_key_policy_t policy; + psa_key_bits_t bits; + psa_key_attributes_flag_t flags; +} psa_core_key_attributes_t; + +#define PSA_CORE_KEY_ATTRIBUTES_INIT {0, 0, PSA_KEY_ID_INIT, PSA_KEY_POLICY_INIT, 0, 0} + +struct psa_key_attributes_s +{ + psa_core_key_attributes_t core; +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + psa_key_slot_number_t slot_number; +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + void *domain_parameters; + size_t domain_parameters_size; +}; + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +#define PSA_KEY_ATTRIBUTES_INIT {PSA_CORE_KEY_ATTRIBUTES_INIT, 0, NULL, 0} +#else +#define PSA_KEY_ATTRIBUTES_INIT {PSA_CORE_KEY_ATTRIBUTES_INIT, NULL, 0} +#endif + +static inline struct psa_key_attributes_s psa_key_attributes_init( void ) +{ + const struct psa_key_attributes_s v = PSA_KEY_ATTRIBUTES_INIT; + return( v ); +} + +static inline void psa_set_key_id(psa_key_attributes_t *attributes, + psa_key_id_t id) +{ + attributes->core.id = id; + if( attributes->core.lifetime == PSA_KEY_LIFETIME_VOLATILE ) + attributes->core.lifetime = PSA_KEY_LIFETIME_PERSISTENT; +} + +static inline psa_key_id_t psa_get_key_id( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.id ); +} + +static inline void psa_set_key_lifetime(psa_key_attributes_t *attributes, + psa_key_lifetime_t lifetime) +{ + attributes->core.lifetime = lifetime; + if( lifetime == PSA_KEY_LIFETIME_VOLATILE ) + { +#ifdef MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER + attributes->core.id.key_id = 0; + attributes->core.id.owner = 0; +#else + attributes->core.id = 0; +#endif + } +} + +static inline psa_key_lifetime_t psa_get_key_lifetime( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.lifetime ); +} + +static inline void psa_set_key_usage_flags(psa_key_attributes_t *attributes, + psa_key_usage_t usage_flags) +{ + attributes->core.policy.usage = usage_flags; +} + +static inline psa_key_usage_t psa_get_key_usage_flags( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.policy.usage ); +} + +static inline void psa_set_key_algorithm(psa_key_attributes_t *attributes, + psa_algorithm_t alg) +{ + attributes->core.policy.alg = alg; +} + +static inline psa_algorithm_t psa_get_key_algorithm( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.policy.alg ); +} + +/* This function is declared in crypto_extra.h, which comes after this + * header file, but we need the function here, so repeat the declaration. */ +psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes, + psa_key_type_t type, + const uint8_t *data, + size_t data_length); + +static inline void psa_set_key_type(psa_key_attributes_t *attributes, + psa_key_type_t type) +{ + if( attributes->domain_parameters == NULL ) + { + /* Common case: quick path */ + attributes->core.type = type; + } + else + { + /* Call the bigger function to free the old domain paramteres. + * Ignore any errors which may arise due to type requiring + * non-default domain parameters, since this function can't + * report errors. */ + (void) psa_set_key_domain_parameters( attributes, type, NULL, 0 ); + } +} + +static inline psa_key_type_t psa_get_key_type( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.type ); +} + +static inline void psa_set_key_bits(psa_key_attributes_t *attributes, + size_t bits) +{ + if( bits > PSA_MAX_KEY_BITS ) + attributes->core.bits = PSA_KEY_BITS_TOO_LARGE; + else + attributes->core.bits = (psa_key_bits_t) bits; +} + +static inline size_t psa_get_key_bits( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.bits ); +} + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_STRUCT_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_types.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_types.h new file mode 100644 index 0000000..690999f --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_types.h @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +/** + * \file psa/crypto_types.h + * + * \brief PSA cryptography module: type aliases. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. Drivers must include the appropriate driver + * header file. + * + * This file contains portable definitions of integral types for properties + * of cryptographic keys, designations of cryptographic algorithms, and + * error codes returned by the library. + * + * This header file does not declare any function. + */ + +#ifndef PSA_CRYPTO_TYPES_H +#define PSA_CRYPTO_TYPES_H + +#include + +/** \defgroup error Error codes + * @{ + */ + +/** + * \brief Function return status. + * + * This is either #PSA_SUCCESS (which is zero), indicating success, + * or a small negative value indicating that an error occurred. Errors are + * encoded as one of the \c PSA_ERROR_xxx values defined here. */ +/* If #PSA_SUCCESS is already defined, it means that #psa_status_t + * is also defined in an external header, so prevent its multiple + * definition. + */ +#ifndef PSA_SUCCESS +typedef int32_t psa_status_t; +#endif + +/**@}*/ + +/** \defgroup crypto_types Key and algorithm types + * @{ + */ + +/** \brief Encoding of a key type. + */ +typedef uint32_t psa_key_type_t; + +/** The type of PSA elliptic curve identifiers. + * + * The curve identifier is required to create an ECC key using the + * PSA_KEY_TYPE_ECC_KEY_PAIR() or PSA_KEY_TYPE_ECC_PUBLIC_KEY() + * macros. + * + * The encoding of curve identifiers is taken from the + * TLS Supported Groups Registry (formerly known as the + * TLS EC Named Curve Registry) + * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 + * + * This specification defines identifiers for some of the curves in the IANA + * registry. Implementations that support other curves that are in the IANA + * registry should use the IANA value and a implementation-specific identifier. + * Implemenations that support non-IANA curves should use one of the following + * approaches for allocating a key type: + * + * 1. Select a ::psa_ecc_curve_t value in the range #PSA_ECC_CURVE_VENDOR_MIN to + * #PSA_ECC_CURVE_VENDOR_MAX, which is a subset of the IANA private use + * range. + * 2. Use a ::psa_key_type_t value that is vendor-defined. + * + * The first option is recommended. + */ +typedef uint16_t psa_ecc_curve_t; + +/** The type of PSA Diffie-Hellman group identifiers. + * + * The group identifier is required to create an Diffie-Hellman key using the + * PSA_KEY_TYPE_DH_KEY_PAIR() or PSA_KEY_TYPE_DH_PUBLIC_KEY() + * macros. + * + * The encoding of group identifiers is taken from the + * TLS Supported Groups Registry (formerly known as the + * TLS EC Named Curve Registry) + * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 + * + * This specification defines identifiers for some of the groups in the IANA + * registry. Implementations that support other groups that are in the IANA + * registry should use the IANA value and a implementation-specific identifier. + * Implemenations that support non-IANA groups should use one of the following + * approaches for allocating a key type: + * + * 1. Select a ::psa_dh_group_t value in the range #PSA_DH_GROUP_VENDOR_MIN to + * #PSA_DH_GROUP_VENDOR_MAX, which is a subset of the IANA private use + * range. + * 2. Select a ::psa_dh_group_t value from the named groups allocated for + * GREASE in the IETF draft specification. The GREASE specification and + * values are listed below. + * 3. Use a ::psa_key_type_t value that is vendor-defined. + * + * Option 1 or 2 are recommended. + * + * The current draft of the GREASE specification is + * https://datatracker.ietf.org/doc/draft-ietf-tls-grease + * + * The following GREASE values are allocated for named groups: + * \code + * 0x0A0A + * 0x1A1A + * 0x2A2A + * 0x3A3A + * 0x4A4A + * 0x5A5A + * 0x6A6A + * 0x7A7A + * 0x8A8A + * 0x9A9A + * 0xAAAA + * 0xBABA + * 0xCACA + * 0xDADA + * 0xEAEA + * 0xFAFA + * \endcode + */ +typedef uint16_t psa_dh_group_t; + +/** \brief Encoding of a cryptographic algorithm. + * + * For algorithms that can be applied to multiple key types, this type + * does not encode the key type. For example, for symmetric ciphers + * based on a block cipher, #psa_algorithm_t encodes the block cipher + * mode and the padding mode while the block cipher itself is encoded + * via #psa_key_type_t. + */ +typedef uint32_t psa_algorithm_t; + +/**@}*/ + +/** \defgroup key_lifetimes Key lifetimes + * @{ + */ + +/** Encoding of key lifetimes. + * + * The lifetime of a key indicates where it is stored and what system actions + * may create and destroy it. + * + * Keys with the lifetime #PSA_KEY_LIFETIME_VOLATILE are automatically + * destroyed when the application terminates or on a power reset. + * + * Keys with a lifetime other than #PSA_KEY_LIFETIME_VOLATILE are said + * to be _persistent_. + * Persistent keys are preserved if the application or the system restarts. + * Persistent keys have a key identifier of type #psa_key_id_t. + * The application can call psa_open_key() to open a persistent key that + * it created previously. + */ +typedef uint32_t psa_key_lifetime_t; + +/** Encoding of identifiers of persistent keys. + * + * - Applications may freely choose key identifiers in the range + * #PSA_KEY_ID_USER_MIN to #PSA_KEY_ID_USER_MAX. + * - Implementations may define additional key identifiers in the range + * #PSA_KEY_ID_VENDOR_MIN to #PSA_KEY_ID_VENDOR_MAX. + * - 0 is reserved as an invalid key identifier. + * - Key identifiers outside these ranges are reserved for future use. + */ +typedef uint32_t psa_key_id_t; +#define PSA_KEY_ID_INIT 0 + +/**@}*/ + +/** \defgroup policy Key policies + * @{ + */ + +/** \brief Encoding of permitted usage on a key. */ +typedef uint32_t psa_key_usage_t; + +/**@}*/ + +/** \defgroup attributes Key attributes + * @{ + */ + +/** The type of a structure containing key attributes. + * + * This is an opaque structure that can represent the metadata of a key + * object. Metadata that can be stored in attributes includes: + * - The location of the key in storage, indicated by its key identifier + * and its lifetime. + * - The key's policy, comprising usage flags and a specification of + * the permitted algorithm(s). + * - Information about the key itself: the key type and its size. + * - Implementations may define additional attributes. + * + * The actual key material is not considered an attribute of a key. + * Key attributes do not contain information that is generally considered + * highly confidential. + * + * An attribute structure can be a simple data structure where each function + * `psa_set_key_xxx` sets a field and the corresponding function + * `psa_get_key_xxx` retrieves the value of the corresponding field. + * However, implementations may report values that are equivalent to the + * original one, but have a different encoding. For example, an + * implementation may use a more compact representation for types where + * many bit-patterns are invalid or not supported, and store all values + * that it does not support as a special marker value. In such an + * implementation, after setting an invalid value, the corresponding + * get function returns an invalid value which may not be the one that + * was originally stored. + * + * An attribute structure may contain references to auxiliary resources, + * for example pointers to allocated memory or indirect references to + * pre-calculated values. In order to free such resources, the application + * must call psa_reset_key_attributes(). As an exception, calling + * psa_reset_key_attributes() on an attribute structure is optional if + * the structure has only been modified by the following functions + * since it was initialized or last reset with psa_reset_key_attributes(): + * - psa_set_key_id() + * - psa_set_key_lifetime() + * - psa_set_key_type() + * - psa_set_key_bits() + * - psa_set_key_usage_flags() + * - psa_set_key_algorithm() + * + * Before calling any function on a key attribute structure, the application + * must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_key_attributes_t attributes; + * memset(&attributes, 0, sizeof(attributes)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_key_attributes_t attributes = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_KEY_ATTRIBUTES_INIT, + * for example: + * \code + * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + * \endcode + * - Assign the result of the function psa_key_attributes_init() + * to the structure, for example: + * \code + * psa_key_attributes_t attributes; + * attributes = psa_key_attributes_init(); + * \endcode + * + * A freshly initialized attribute structure contains the following + * values: + * + * - lifetime: #PSA_KEY_LIFETIME_VOLATILE. + * - key identifier: 0 (which is not a valid key identifier). + * - type: \c 0 (meaning that the type is unspecified). + * - key size: \c 0 (meaning that the size is unspecified). + * - usage flags: \c 0 (which allows no usage except exporting a public key). + * - algorithm: \c 0 (which allows no cryptographic usage, but allows + * exporting). + * + * A typical sequence to create a key is as follows: + * -# Create and initialize an attribute structure. + * -# If the key is persistent, call psa_set_key_id(). + * Also call psa_set_key_lifetime() to place the key in a non-default + * location. + * -# Set the key policy with psa_set_key_usage_flags() and + * psa_set_key_algorithm(). + * -# Set the key type with psa_set_key_type(). + * Skip this step if copying an existing key with psa_copy_key(). + * -# When generating a random key with psa_generate_key() or deriving a key + * with psa_key_derivation_output_key(), set the desired key size with + * psa_set_key_bits(). + * -# Call a key creation function: psa_import_key(), psa_generate_key(), + * psa_key_derivation_output_key() or psa_copy_key(). This function reads + * the attribute structure, creates a key with these attributes, and + * outputs a handle to the newly created key. + * -# The attribute structure is now no longer necessary. + * You may call psa_reset_key_attributes(), although this is optional + * with the workflow presented here because the attributes currently + * defined in this specification do not require any additional resources + * beyond the structure itself. + * + * A typical sequence to query a key's attributes is as follows: + * -# Call psa_get_key_attributes(). + * -# Call `psa_get_key_xxx` functions to retrieve the attribute(s) that + * you are interested in. + * -# Call psa_reset_key_attributes() to free any resources that may be + * used by the attribute structure. + * + * Once a key has been created, it is impossible to change its attributes. + */ +typedef struct psa_key_attributes_s psa_key_attributes_t; + +/**@}*/ + +/** \defgroup derivation Key derivation + * @{ + */ + +/** \brief Encoding of the step of a key derivation. */ +typedef uint16_t psa_key_derivation_step_t; + +/**@}*/ + +#endif /* PSA_CRYPTO_TYPES_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_values.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_values.h new file mode 100644 index 0000000..7fde073 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_values.h @@ -0,0 +1,1701 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +/** + * \file psa/crypto_values.h + * + * \brief PSA cryptography module: macros to build and analyze integer values. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. Drivers must include the appropriate driver + * header file. + * + * This file contains portable definitions of macros to build and analyze + * values of integral types that encode properties of cryptographic keys, + * designations of cryptographic algorithms, and error codes returned by + * the library. + * + * This header file only defines preprocessor macros. + */ + +#ifndef PSA_CRYPTO_VALUES_H +#define PSA_CRYPTO_VALUES_H + +/** \defgroup error Error codes + * @{ + */ + +/* PSA error codes */ + +/** The action was completed successfully. */ +#ifndef PSA_SUCCESS +#define PSA_SUCCESS ((psa_status_t)0) +#endif + +/** An error occurred that does not correspond to any defined + * failure cause. + * + * Implementations may use this error code if none of the other standard + * error codes are applicable. */ +#define PSA_ERROR_GENERIC_ERROR ((psa_status_t)-132) + +/** The requested operation or a parameter is not supported + * by this implementation. + * + * Implementations should return this error code when an enumeration + * parameter such as a key type, algorithm, etc. is not recognized. + * If a combination of parameters is recognized and identified as + * not valid, return #PSA_ERROR_INVALID_ARGUMENT instead. */ +#define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)-134) + +/** The requested action is denied by a policy. + * + * Implementations should return this error code when the parameters + * are recognized as valid and supported, and a policy explicitly + * denies the requested operation. + * + * If a subset of the parameters of a function call identify a + * forbidden operation, and another subset of the parameters are + * not valid or not supported, it is unspecified whether the function + * returns #PSA_ERROR_NOT_PERMITTED, #PSA_ERROR_NOT_SUPPORTED or + * #PSA_ERROR_INVALID_ARGUMENT. */ +#define PSA_ERROR_NOT_PERMITTED ((psa_status_t)-133) + +/** An output buffer is too small. + * + * Applications can call the \c PSA_xxx_SIZE macro listed in the function + * description to determine a sufficient buffer size. + * + * Implementations should preferably return this error code only + * in cases when performing the operation with a larger output + * buffer would succeed. However implementations may return this + * error if a function has invalid or unsupported parameters in addition + * to the parameters that determine the necessary output buffer size. */ +#define PSA_ERROR_BUFFER_TOO_SMALL ((psa_status_t)-138) + +/** Asking for an item that already exists + * + * Implementations should return this error, when attempting + * to write an item (like a key) that already exists. */ +#define PSA_ERROR_ALREADY_EXISTS ((psa_status_t)-139) + +/** Asking for an item that doesn't exist + * + * Implementations should return this error, if a requested item (like + * a key) does not exist. */ +#define PSA_ERROR_DOES_NOT_EXIST ((psa_status_t)-140) + +/** The requested action cannot be performed in the current state. + * + * Multipart operations return this error when one of the + * functions is called out of sequence. Refer to the function + * descriptions for permitted sequencing of functions. + * + * Implementations shall not return this error code to indicate + * that a key either exists or not, + * but shall instead return #PSA_ERROR_ALREADY_EXISTS or #PSA_ERROR_DOES_NOT_EXIST + * as applicable. + * + * Implementations shall not return this error code to indicate that a + * key handle is invalid, but shall return #PSA_ERROR_INVALID_HANDLE + * instead. */ +#define PSA_ERROR_BAD_STATE ((psa_status_t)-137) + +/** The parameters passed to the function are invalid. + * + * Implementations may return this error any time a parameter or + * combination of parameters are recognized as invalid. + * + * Implementations shall not return this error code to indicate that a + * key handle is invalid, but shall return #PSA_ERROR_INVALID_HANDLE + * instead. + */ +#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)-135) + +/** There is not enough runtime memory. + * + * If the action is carried out across multiple security realms, this + * error can refer to available memory in any of the security realms. */ +#define PSA_ERROR_INSUFFICIENT_MEMORY ((psa_status_t)-141) + +/** There is not enough persistent storage. + * + * Functions that modify the key storage return this error code if + * there is insufficient storage space on the host media. In addition, + * many functions that do not otherwise access storage may return this + * error code if the implementation requires a mandatory log entry for + * the requested action and the log storage space is full. */ +#define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)-142) + +/** There was a communication failure inside the implementation. + * + * This can indicate a communication failure between the application + * and an external cryptoprocessor or between the cryptoprocessor and + * an external volatile or persistent memory. A communication failure + * may be transient or permanent depending on the cause. + * + * \warning If a function returns this error, it is undetermined + * whether the requested action has completed or not. Implementations + * should return #PSA_SUCCESS on successful completion whenever + * possible, however functions may return #PSA_ERROR_COMMUNICATION_FAILURE + * if the requested action was completed successfully in an external + * cryptoprocessor but there was a breakdown of communication before + * the cryptoprocessor could report the status to the application. + */ +#define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t)-145) + +/** There was a storage failure that may have led to data loss. + * + * This error indicates that some persistent storage is corrupted. + * It should not be used for a corruption of volatile memory + * (use #PSA_ERROR_CORRUPTION_DETECTED), for a communication error + * between the cryptoprocessor and its external storage (use + * #PSA_ERROR_COMMUNICATION_FAILURE), or when the storage is + * in a valid state but is full (use #PSA_ERROR_INSUFFICIENT_STORAGE). + * + * Note that a storage failure does not indicate that any data that was + * previously read is invalid. However this previously read data may no + * longer be readable from storage. + * + * When a storage failure occurs, it is no longer possible to ensure + * the global integrity of the keystore. Depending on the global + * integrity guarantees offered by the implementation, access to other + * data may or may not fail even if the data is still readable but + * its integrity cannot be guaranteed. + * + * Implementations should only use this error code to report a + * permanent storage corruption. However application writers should + * keep in mind that transient errors while reading the storage may be + * reported using this error code. */ +#define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)-146) + +/** A hardware failure was detected. + * + * A hardware failure may be transient or permanent depending on the + * cause. */ +#define PSA_ERROR_HARDWARE_FAILURE ((psa_status_t)-147) + +/** A tampering attempt was detected. + * + * If an application receives this error code, there is no guarantee + * that previously accessed or computed data was correct and remains + * confidential. Applications should not perform any security function + * and should enter a safe failure state. + * + * Implementations may return this error code if they detect an invalid + * state that cannot happen during normal operation and that indicates + * that the implementation's security guarantees no longer hold. Depending + * on the implementation architecture and on its security and safety goals, + * the implementation may forcibly terminate the application. + * + * This error code is intended as a last resort when a security breach + * is detected and it is unsure whether the keystore data is still + * protected. Implementations shall only return this error code + * to report an alarm from a tampering detector, to indicate that + * the confidentiality of stored data can no longer be guaranteed, + * or to indicate that the integrity of previously returned data is now + * considered compromised. Implementations shall not use this error code + * to indicate a hardware failure that merely makes it impossible to + * perform the requested operation (use #PSA_ERROR_COMMUNICATION_FAILURE, + * #PSA_ERROR_STORAGE_FAILURE, #PSA_ERROR_HARDWARE_FAILURE, + * #PSA_ERROR_INSUFFICIENT_ENTROPY or other applicable error code + * instead). + * + * This error indicates an attack against the application. Implementations + * shall not return this error code as a consequence of the behavior of + * the application itself. */ +#define PSA_ERROR_CORRUPTION_DETECTED ((psa_status_t)-151) + +/** There is not enough entropy to generate random data needed + * for the requested action. + * + * This error indicates a failure of a hardware random generator. + * Application writers should note that this error can be returned not + * only by functions whose purpose is to generate random data, such + * as key, IV or nonce generation, but also by functions that execute + * an algorithm with a randomized result, as well as functions that + * use randomization of intermediate computations as a countermeasure + * to certain attacks. + * + * Implementations should avoid returning this error after psa_crypto_init() + * has succeeded. Implementations should generate sufficient + * entropy during initialization and subsequently use a cryptographically + * secure pseudorandom generator (PRNG). However implementations may return + * this error at any time if a policy requires the PRNG to be reseeded + * during normal operation. */ +#define PSA_ERROR_INSUFFICIENT_ENTROPY ((psa_status_t)-148) + +/** The signature, MAC or hash is incorrect. + * + * Verification functions return this error if the verification + * calculations completed successfully, and the value to be verified + * was determined to be incorrect. + * + * If the value to verify has an invalid size, implementations may return + * either #PSA_ERROR_INVALID_ARGUMENT or #PSA_ERROR_INVALID_SIGNATURE. */ +#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) + +/** The decrypted padding is incorrect. + * + * \warning In some protocols, when decrypting data, it is essential that + * the behavior of the application does not depend on whether the padding + * is correct, down to precise timing. Applications should prefer + * protocols that use authenticated encryption rather than plain + * encryption. If the application must perform a decryption of + * unauthenticated data, the application writer should take care not + * to reveal whether the padding is invalid. + * + * Implementations should strive to make valid and invalid padding + * as close as possible to indistinguishable to an external observer. + * In particular, the timing of a decryption operation should not + * depend on the validity of the padding. */ +#define PSA_ERROR_INVALID_PADDING ((psa_status_t)-150) + +/** Return this error when there's insufficient data when attempting + * to read from a resource. */ +#define PSA_ERROR_INSUFFICIENT_DATA ((psa_status_t)-143) + +/** The key handle is not valid. See also :ref:\`key-handles\`. + */ +#define PSA_ERROR_INVALID_HANDLE ((psa_status_t)-136) + +/**@}*/ + +/** \defgroup crypto_types Key and algorithm types + * @{ + */ + +/** An invalid key type value. + * + * Zero is not the encoding of any key type. + */ +#define PSA_KEY_TYPE_NONE ((psa_key_type_t)0x00000000) + +/** Vendor-defined key type flag. + * + * Key types defined by this standard will never have the + * #PSA_KEY_TYPE_VENDOR_FLAG bit set. Vendors who define additional key types + * must use an encoding with the #PSA_KEY_TYPE_VENDOR_FLAG bit set and should + * respect the bitwise structure used by standard encodings whenever practical. + */ +#define PSA_KEY_TYPE_VENDOR_FLAG ((psa_key_type_t)0x80000000) + +#define PSA_KEY_TYPE_CATEGORY_MASK ((psa_key_type_t)0x70000000) +#define PSA_KEY_TYPE_CATEGORY_SYMMETRIC ((psa_key_type_t)0x40000000) +#define PSA_KEY_TYPE_CATEGORY_RAW ((psa_key_type_t)0x50000000) +#define PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY ((psa_key_type_t)0x60000000) +#define PSA_KEY_TYPE_CATEGORY_KEY_PAIR ((psa_key_type_t)0x70000000) + +#define PSA_KEY_TYPE_CATEGORY_FLAG_PAIR ((psa_key_type_t)0x10000000) + +/** Whether a key type is vendor-defined. + * + * See also #PSA_KEY_TYPE_VENDOR_FLAG. + */ +#define PSA_KEY_TYPE_IS_VENDOR_DEFINED(type) \ + (((type) & PSA_KEY_TYPE_VENDOR_FLAG) != 0) + +/** Whether a key type is an unstructured array of bytes. + * + * This encompasses both symmetric keys and non-key data. + */ +#define PSA_KEY_TYPE_IS_UNSTRUCTURED(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK & ~(psa_key_type_t)0x10000000) == \ + PSA_KEY_TYPE_CATEGORY_SYMMETRIC) + +/** Whether a key type is asymmetric: either a key pair or a public key. */ +#define PSA_KEY_TYPE_IS_ASYMMETRIC(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK \ + & ~PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) == \ + PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY) +/** Whether a key type is the public part of a key pair. */ +#define PSA_KEY_TYPE_IS_PUBLIC_KEY(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY) +/** Whether a key type is a key pair containing a private part and a public + * part. */ +#define PSA_KEY_TYPE_IS_KEY_PAIR(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_KEY_PAIR) +/** The key pair type corresponding to a public key type. + * + * You may also pass a key pair type as \p type, it will be left unchanged. + * + * \param type A public key type or key pair type. + * + * \return The corresponding key pair type. + * If \p type is not a public key or a key pair, + * the return value is undefined. + */ +#define PSA_KEY_TYPE_KEY_PAIR_OF_PUBLIC_KEY(type) \ + ((type) | PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) +/** The public key type corresponding to a key pair type. + * + * You may also pass a key pair type as \p type, it will be left unchanged. + * + * \param type A public key type or key pair type. + * + * \return The corresponding public key type. + * If \p type is not a public key or a key pair, + * the return value is undefined. + */ +#define PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) \ + ((type) & ~PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) + +/** Raw data. + * + * A "key" of this type cannot be used for any cryptographic operation. + * Applications may use this type to store arbitrary data in the keystore. */ +#define PSA_KEY_TYPE_RAW_DATA ((psa_key_type_t)0x50000001) + +/** HMAC key. + * + * The key policy determines which underlying hash algorithm the key can be + * used for. + * + * HMAC keys should generally have the same size as the underlying hash. + * This size can be calculated with #PSA_HASH_SIZE(\c alg) where + * \c alg is the HMAC algorithm or the underlying hash algorithm. */ +#define PSA_KEY_TYPE_HMAC ((psa_key_type_t)0x51000000) + +/** A secret for key derivation. + * + * The key policy determines which key derivation algorithm the key + * can be used for. + */ +#define PSA_KEY_TYPE_DERIVE ((psa_key_type_t)0x52000000) + +/** Key for a cipher, AEAD or MAC algorithm based on the AES block cipher. + * + * The size of the key can be 16 bytes (AES-128), 24 bytes (AES-192) or + * 32 bytes (AES-256). + */ +#define PSA_KEY_TYPE_AES ((psa_key_type_t)0x40000001) + +/** Key for a cipher or MAC algorithm based on DES or 3DES (Triple-DES). + * + * The size of the key can be 8 bytes (single DES), 16 bytes (2-key 3DES) or + * 24 bytes (3-key 3DES). + * + * Note that single DES and 2-key 3DES are weak and strongly + * deprecated and should only be used to decrypt legacy data. 3-key 3DES + * is weak and deprecated and should only be used in legacy protocols. + */ +#define PSA_KEY_TYPE_DES ((psa_key_type_t)0x40000002) + +/** Key for a cipher, AEAD or MAC algorithm based on the + * Camellia block cipher. */ +#define PSA_KEY_TYPE_CAMELLIA ((psa_key_type_t)0x40000003) + +/** Key for the RC4 stream cipher. + * + * Note that RC4 is weak and deprecated and should only be used in + * legacy protocols. */ +#define PSA_KEY_TYPE_ARC4 ((psa_key_type_t)0x40000004) + +/** Key for the ChaCha20 stream cipher or the Chacha20-Poly1305 AEAD algorithm. + * + * ChaCha20 and the ChaCha20_Poly1305 construction are defined in RFC 7539. + * + * Implementations must support 12-byte nonces, may support 8-byte nonces, + * and should reject other sizes. + */ +#define PSA_KEY_TYPE_CHACHA20 ((psa_key_type_t)0x40000005) + +/** RSA public key. */ +#define PSA_KEY_TYPE_RSA_PUBLIC_KEY ((psa_key_type_t)0x60010000) +/** RSA key pair (private and public key). */ +#define PSA_KEY_TYPE_RSA_KEY_PAIR ((psa_key_type_t)0x70010000) +/** Whether a key type is an RSA key (pair or public-only). */ +#define PSA_KEY_TYPE_IS_RSA(type) \ + (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY) + +#define PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE ((psa_key_type_t)0x60030000) +#define PSA_KEY_TYPE_ECC_KEY_PAIR_BASE ((psa_key_type_t)0x70030000) +#define PSA_KEY_TYPE_ECC_CURVE_MASK ((psa_key_type_t)0x0000ffff) +/** Elliptic curve key pair. + * + * \param curve A value of type ::psa_ecc_curve_t that identifies the + * ECC curve to be used. + */ +#define PSA_KEY_TYPE_ECC_KEY_PAIR(curve) \ + (PSA_KEY_TYPE_ECC_KEY_PAIR_BASE | (curve)) +/** Elliptic curve public key. + * + * \param curve A value of type ::psa_ecc_curve_t that identifies the + * ECC curve to be used. + */ +#define PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve) \ + (PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE | (curve)) + +/** Whether a key type is an elliptic curve key (pair or public-only). */ +#define PSA_KEY_TYPE_IS_ECC(type) \ + ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) & \ + ~PSA_KEY_TYPE_ECC_CURVE_MASK) == PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE) +/** Whether a key type is an elliptic curve key pair. */ +#define PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type) \ + (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \ + PSA_KEY_TYPE_ECC_KEY_PAIR_BASE) +/** Whether a key type is an elliptic curve public key. */ +#define PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(type) \ + (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \ + PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE) + +/** Extract the curve from an elliptic curve key type. */ +#define PSA_KEY_TYPE_GET_CURVE(type) \ + ((psa_ecc_curve_t) (PSA_KEY_TYPE_IS_ECC(type) ? \ + ((type) & PSA_KEY_TYPE_ECC_CURVE_MASK) : \ + 0)) + +/* The encoding of curve identifiers is currently aligned with the + * TLS Supported Groups Registry (formerly known as the + * TLS EC Named Curve Registry) + * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 + * The values are defined by RFC 8422 and RFC 7027. */ +#define PSA_ECC_CURVE_SECT163K1 ((psa_ecc_curve_t) 0x0001) +#define PSA_ECC_CURVE_SECT163R1 ((psa_ecc_curve_t) 0x0002) +#define PSA_ECC_CURVE_SECT163R2 ((psa_ecc_curve_t) 0x0003) +#define PSA_ECC_CURVE_SECT193R1 ((psa_ecc_curve_t) 0x0004) +#define PSA_ECC_CURVE_SECT193R2 ((psa_ecc_curve_t) 0x0005) +#define PSA_ECC_CURVE_SECT233K1 ((psa_ecc_curve_t) 0x0006) +#define PSA_ECC_CURVE_SECT233R1 ((psa_ecc_curve_t) 0x0007) +#define PSA_ECC_CURVE_SECT239K1 ((psa_ecc_curve_t) 0x0008) +#define PSA_ECC_CURVE_SECT283K1 ((psa_ecc_curve_t) 0x0009) +#define PSA_ECC_CURVE_SECT283R1 ((psa_ecc_curve_t) 0x000a) +#define PSA_ECC_CURVE_SECT409K1 ((psa_ecc_curve_t) 0x000b) +#define PSA_ECC_CURVE_SECT409R1 ((psa_ecc_curve_t) 0x000c) +#define PSA_ECC_CURVE_SECT571K1 ((psa_ecc_curve_t) 0x000d) +#define PSA_ECC_CURVE_SECT571R1 ((psa_ecc_curve_t) 0x000e) +#define PSA_ECC_CURVE_SECP160K1 ((psa_ecc_curve_t) 0x000f) +#define PSA_ECC_CURVE_SECP160R1 ((psa_ecc_curve_t) 0x0010) +#define PSA_ECC_CURVE_SECP160R2 ((psa_ecc_curve_t) 0x0011) +#define PSA_ECC_CURVE_SECP192K1 ((psa_ecc_curve_t) 0x0012) +#define PSA_ECC_CURVE_SECP192R1 ((psa_ecc_curve_t) 0x0013) +#define PSA_ECC_CURVE_SECP224K1 ((psa_ecc_curve_t) 0x0014) +#define PSA_ECC_CURVE_SECP224R1 ((psa_ecc_curve_t) 0x0015) +#define PSA_ECC_CURVE_SECP256K1 ((psa_ecc_curve_t) 0x0016) +#define PSA_ECC_CURVE_SECP256R1 ((psa_ecc_curve_t) 0x0017) +#define PSA_ECC_CURVE_SECP384R1 ((psa_ecc_curve_t) 0x0018) +#define PSA_ECC_CURVE_SECP521R1 ((psa_ecc_curve_t) 0x0019) +#define PSA_ECC_CURVE_BRAINPOOL_P256R1 ((psa_ecc_curve_t) 0x001a) +#define PSA_ECC_CURVE_BRAINPOOL_P384R1 ((psa_ecc_curve_t) 0x001b) +#define PSA_ECC_CURVE_BRAINPOOL_P512R1 ((psa_ecc_curve_t) 0x001c) +/** Curve25519. + * + * This is the curve defined in Bernstein et al., + * _Curve25519: new Diffie-Hellman speed records_, LNCS 3958, 2006. + * The algorithm #PSA_ALG_ECDH performs X25519 when used with this curve. + */ +#define PSA_ECC_CURVE_CURVE25519 ((psa_ecc_curve_t) 0x001d) +/** Curve448 + * + * This is the curve defined in Hamburg, + * _Ed448-Goldilocks, a new elliptic curve_, NIST ECC Workshop, 2015. + * The algorithm #PSA_ALG_ECDH performs X448 when used with this curve. + */ +#define PSA_ECC_CURVE_CURVE448 ((psa_ecc_curve_t) 0x001e) + +/** Minimum value for a vendor-defined ECC curve identifier + * + * The range for vendor-defined curve identifiers is a subset of the IANA + * registry private use range, `0xfe00` - `0xfeff`. + */ +#define PSA_ECC_CURVE_VENDOR_MIN ((psa_ecc_curve_t) 0xfe00) +/** Maximum value for a vendor-defined ECC curve identifier + * + * The range for vendor-defined curve identifiers is a subset of the IANA + * registry private use range, `0xfe00` - `0xfeff`. + */ +#define PSA_ECC_CURVE_VENDOR_MAX ((psa_ecc_curve_t) 0xfe7f) + +#define PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE ((psa_key_type_t)0x60040000) +#define PSA_KEY_TYPE_DH_KEY_PAIR_BASE ((psa_key_type_t)0x70040000) +#define PSA_KEY_TYPE_DH_GROUP_MASK ((psa_key_type_t)0x0000ffff) +/** Diffie-Hellman key pair. + * + * \param group A value of type ::psa_dh_group_t that identifies the + * Diffie-Hellman group to be used. + */ +#define PSA_KEY_TYPE_DH_KEY_PAIR(group) \ + (PSA_KEY_TYPE_DH_KEY_PAIR_BASE | (group)) +/** Diffie-Hellman public key. + * + * \param group A value of type ::psa_dh_group_t that identifies the + * Diffie-Hellman group to be used. + */ +#define PSA_KEY_TYPE_DH_PUBLIC_KEY(group) \ + (PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE | (group)) + +/** Whether a key type is a Diffie-Hellman key (pair or public-only). */ +#define PSA_KEY_TYPE_IS_DH(type) \ + ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) & \ + ~PSA_KEY_TYPE_DH_GROUP_MASK) == PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE) +/** Whether a key type is a Diffie-Hellman key pair. */ +#define PSA_KEY_TYPE_IS_DH_KEY_PAIR(type) \ + (((type) & ~PSA_KEY_TYPE_DH_GROUP_MASK) == \ + PSA_KEY_TYPE_DH_KEY_PAIR_BASE) +/** Whether a key type is a Diffie-Hellman public key. */ +#define PSA_KEY_TYPE_IS_DH_PUBLIC_KEY(type) \ + (((type) & ~PSA_KEY_TYPE_DH_GROUP_MASK) == \ + PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE) + +/** Extract the group from a Diffie-Hellman key type. */ +#define PSA_KEY_TYPE_GET_GROUP(type) \ + ((psa_dh_group_t) (PSA_KEY_TYPE_IS_DH(type) ? \ + ((type) & PSA_KEY_TYPE_DH_GROUP_MASK) : \ + 0)) + +/* The encoding of group identifiers is currently aligned with the + * TLS Supported Groups Registry (formerly known as the + * TLS EC Named Curve Registry) + * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 + * The values are defined by RFC 7919. */ +#define PSA_DH_GROUP_FFDHE2048 ((psa_dh_group_t) 0x0100) +#define PSA_DH_GROUP_FFDHE3072 ((psa_dh_group_t) 0x0101) +#define PSA_DH_GROUP_FFDHE4096 ((psa_dh_group_t) 0x0102) +#define PSA_DH_GROUP_FFDHE6144 ((psa_dh_group_t) 0x0103) +#define PSA_DH_GROUP_FFDHE8192 ((psa_dh_group_t) 0x0104) + +/** Minimum value for a vendor-defined Diffie Hellman group identifier + * + * The range for vendor-defined group identifiers is a subset of the IANA + * registry private use range, `0x01fc` - `0x01ff`. + */ +#define PSA_DH_GROUP_VENDOR_MIN ((psa_dh_group_t) 0x01fc) +/** Maximum value for a vendor-defined Diffie Hellman group identifier + * + * The range for vendor-defined group identifiers is a subset of the IANA + * registry private use range, `0x01fc` - `0x01ff`. + */ +#define PSA_DH_GROUP_VENDOR_MAX ((psa_dh_group_t) 0x01fd) + +/** The block size of a block cipher. + * + * \param type A cipher key type (value of type #psa_key_type_t). + * + * \return The block size for a block cipher, or 1 for a stream cipher. + * The return value is undefined if \p type is not a supported + * cipher key type. + * + * \note It is possible to build stream cipher algorithms on top of a block + * cipher, for example CTR mode (#PSA_ALG_CTR). + * This macro only takes the key type into account, so it cannot be + * used to determine the size of the data that #psa_cipher_update() + * might buffer for future processing in general. + * + * \note This macro returns a compile-time constant if its argument is one. + * + * \warning This macro may evaluate its argument multiple times. + */ +#define PSA_BLOCK_CIPHER_BLOCK_SIZE(type) \ + ( \ + (type) == PSA_KEY_TYPE_AES ? 16 : \ + (type) == PSA_KEY_TYPE_DES ? 8 : \ + (type) == PSA_KEY_TYPE_CAMELLIA ? 16 : \ + (type) == PSA_KEY_TYPE_ARC4 ? 1 : \ + (type) == PSA_KEY_TYPE_CHACHA20 ? 1 : \ + 0) + +/** Vendor-defined algorithm flag. + * + * Algorithms defined by this standard will never have the #PSA_ALG_VENDOR_FLAG + * bit set. Vendors who define additional algorithms must use an encoding with + * the #PSA_ALG_VENDOR_FLAG bit set and should respect the bitwise structure + * used by standard encodings whenever practical. + */ +#define PSA_ALG_VENDOR_FLAG ((psa_algorithm_t)0x80000000) + +#define PSA_ALG_CATEGORY_MASK ((psa_algorithm_t)0x7f000000) +#define PSA_ALG_CATEGORY_HASH ((psa_algorithm_t)0x01000000) +#define PSA_ALG_CATEGORY_MAC ((psa_algorithm_t)0x02000000) +#define PSA_ALG_CATEGORY_CIPHER ((psa_algorithm_t)0x04000000) +#define PSA_ALG_CATEGORY_AEAD ((psa_algorithm_t)0x06000000) +#define PSA_ALG_CATEGORY_SIGN ((psa_algorithm_t)0x10000000) +#define PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION ((psa_algorithm_t)0x12000000) +#define PSA_ALG_CATEGORY_KEY_DERIVATION ((psa_algorithm_t)0x20000000) +#define PSA_ALG_CATEGORY_KEY_AGREEMENT ((psa_algorithm_t)0x30000000) + +/** Whether an algorithm is vendor-defined. + * + * See also #PSA_ALG_VENDOR_FLAG. + */ +#define PSA_ALG_IS_VENDOR_DEFINED(alg) \ + (((alg) & PSA_ALG_VENDOR_FLAG) != 0) + +/** Whether the specified algorithm is a hash algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a hash algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_HASH(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_HASH) + +/** Whether the specified algorithm is a MAC algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a MAC algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_MAC(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_MAC) + +/** Whether the specified algorithm is a symmetric cipher algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a symmetric cipher algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_CIPHER(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_CIPHER) + +/** Whether the specified algorithm is an authenticated encryption + * with associated data (AEAD) algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is an AEAD algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_AEAD(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_AEAD) + +/** Whether the specified algorithm is a public-key signature algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a public-key signature algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_SIGN(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_SIGN) + +/** Whether the specified algorithm is a public-key encryption algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a public-key encryption algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION) + +/** Whether the specified algorithm is a key agreement algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a key agreement algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_KEY_AGREEMENT(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_AGREEMENT) + +/** Whether the specified algorithm is a key derivation algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a key derivation algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_KEY_DERIVATION(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_DERIVATION) + +#define PSA_ALG_HASH_MASK ((psa_algorithm_t)0x000000ff) +/** MD2 */ +#define PSA_ALG_MD2 ((psa_algorithm_t)0x01000001) +/** MD4 */ +#define PSA_ALG_MD4 ((psa_algorithm_t)0x01000002) +/** MD5 */ +#define PSA_ALG_MD5 ((psa_algorithm_t)0x01000003) +/** PSA_ALG_RIPEMD160 */ +#define PSA_ALG_RIPEMD160 ((psa_algorithm_t)0x01000004) +/** SHA1 */ +#define PSA_ALG_SHA_1 ((psa_algorithm_t)0x01000005) +/** SHA2-224 */ +#define PSA_ALG_SHA_224 ((psa_algorithm_t)0x01000008) +/** SHA2-256 */ +#define PSA_ALG_SHA_256 ((psa_algorithm_t)0x01000009) +/** SHA2-384 */ +#define PSA_ALG_SHA_384 ((psa_algorithm_t)0x0100000a) +/** SHA2-512 */ +#define PSA_ALG_SHA_512 ((psa_algorithm_t)0x0100000b) +/** SHA2-512/224 */ +#define PSA_ALG_SHA_512_224 ((psa_algorithm_t)0x0100000c) +/** SHA2-512/256 */ +#define PSA_ALG_SHA_512_256 ((psa_algorithm_t)0x0100000d) +/** SHA3-224 */ +#define PSA_ALG_SHA3_224 ((psa_algorithm_t)0x01000010) +/** SHA3-256 */ +#define PSA_ALG_SHA3_256 ((psa_algorithm_t)0x01000011) +/** SHA3-384 */ +#define PSA_ALG_SHA3_384 ((psa_algorithm_t)0x01000012) +/** SHA3-512 */ +#define PSA_ALG_SHA3_512 ((psa_algorithm_t)0x01000013) + +/** In a hash-and-sign algorithm policy, allow any hash algorithm. + * + * This value may be used to form the algorithm usage field of a policy + * for a signature algorithm that is parametrized by a hash. The key + * may then be used to perform operations using the same signature + * algorithm parametrized with any supported hash. + * + * That is, suppose that `PSA_xxx_SIGNATURE` is one of the following macros: + * - #PSA_ALG_RSA_PKCS1V15_SIGN, #PSA_ALG_RSA_PSS, + * - #PSA_ALG_ECDSA, #PSA_ALG_DETERMINISTIC_ECDSA. + * Then you may create and use a key as follows: + * - Set the key usage field using #PSA_ALG_ANY_HASH, for example: + * ``` + * psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); // or VERIFY + * psa_set_key_algorithm(&attributes, PSA_xxx_SIGNATURE(PSA_ALG_ANY_HASH)); + * ``` + * - Import or generate key material. + * - Call psa_sign_hash() or psa_verify_hash(), passing + * an algorithm built from `PSA_xxx_SIGNATURE` and a specific hash. Each + * call to sign or verify a message may use a different hash. + * ``` + * psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA_256), ...); + * psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA_512), ...); + * psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA3_256), ...); + * ``` + * + * This value may not be used to build other algorithms that are + * parametrized over a hash. For any valid use of this macro to build + * an algorithm \c alg, #PSA_ALG_IS_HASH_AND_SIGN(\c alg) is true. + * + * This value may not be used to build an algorithm specification to + * perform an operation. It is only valid to build policies. + */ +#define PSA_ALG_ANY_HASH ((psa_algorithm_t)0x010000ff) + +#define PSA_ALG_MAC_SUBCATEGORY_MASK ((psa_algorithm_t)0x00c00000) +#define PSA_ALG_HMAC_BASE ((psa_algorithm_t)0x02800000) +/** Macro to build an HMAC algorithm. + * + * For example, #PSA_ALG_HMAC(#PSA_ALG_SHA_256) is HMAC-SHA-256. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding HMAC algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_HMAC(hash_alg) \ + (PSA_ALG_HMAC_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) + +#define PSA_ALG_HMAC_GET_HASH(hmac_alg) \ + (PSA_ALG_CATEGORY_HASH | ((hmac_alg) & PSA_ALG_HASH_MASK)) + +/** Whether the specified algorithm is an HMAC algorithm. + * + * HMAC is a family of MAC algorithms that are based on a hash function. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is an HMAC algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_HMAC(alg) \ + (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \ + PSA_ALG_HMAC_BASE) + +/* In the encoding of a MAC algorithm, the bits corresponding to + * PSA_ALG_MAC_TRUNCATION_MASK encode the length to which the MAC is + * truncated. As an exception, the value 0 means the untruncated algorithm, + * whatever its length is. The length is encoded in 6 bits, so it can + * reach up to 63; the largest MAC is 64 bytes so its trivial truncation + * to full length is correctly encoded as 0 and any non-trivial truncation + * is correctly encoded as a value between 1 and 63. */ +#define PSA_ALG_MAC_TRUNCATION_MASK ((psa_algorithm_t)0x00003f00) +#define PSA_MAC_TRUNCATION_OFFSET 8 + +/** Macro to build a truncated MAC algorithm. + * + * A truncated MAC algorithm is identical to the corresponding MAC + * algorithm except that the MAC value for the truncated algorithm + * consists of only the first \p mac_length bytes of the MAC value + * for the untruncated algorithm. + * + * \note This macro may allow constructing algorithm identifiers that + * are not valid, either because the specified length is larger + * than the untruncated MAC or because the specified length is + * smaller than permitted by the implementation. + * + * \note It is implementation-defined whether a truncated MAC that + * is truncated to the same length as the MAC of the untruncated + * algorithm is considered identical to the untruncated algorithm + * for policy comparison purposes. + * + * \param mac_alg A MAC algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg) + * is true). This may be a truncated or untruncated + * MAC algorithm. + * \param mac_length Desired length of the truncated MAC in bytes. + * This must be at most the full length of the MAC + * and must be at least an implementation-specified + * minimum. The implementation-specified minimum + * shall not be zero. + * + * \return The corresponding MAC algorithm with the specified + * length. + * \return Unspecified if \p alg is not a supported + * MAC algorithm or if \p mac_length is too small or + * too large for the specified MAC algorithm. + */ +#define PSA_ALG_TRUNCATED_MAC(mac_alg, mac_length) \ + (((mac_alg) & ~PSA_ALG_MAC_TRUNCATION_MASK) | \ + ((mac_length) << PSA_MAC_TRUNCATION_OFFSET & PSA_ALG_MAC_TRUNCATION_MASK)) + +/** Macro to build the base MAC algorithm corresponding to a truncated + * MAC algorithm. + * + * \param mac_alg A MAC algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg) + * is true). This may be a truncated or untruncated + * MAC algorithm. + * + * \return The corresponding base MAC algorithm. + * \return Unspecified if \p alg is not a supported + * MAC algorithm. + */ +#define PSA_ALG_FULL_LENGTH_MAC(mac_alg) \ + ((mac_alg) & ~PSA_ALG_MAC_TRUNCATION_MASK) + +/** Length to which a MAC algorithm is truncated. + * + * \param mac_alg A MAC algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg) + * is true). + * + * \return Length of the truncated MAC in bytes. + * \return 0 if \p alg is a non-truncated MAC algorithm. + * \return Unspecified if \p alg is not a supported + * MAC algorithm. + */ +#define PSA_MAC_TRUNCATED_LENGTH(mac_alg) \ + (((mac_alg) & PSA_ALG_MAC_TRUNCATION_MASK) >> PSA_MAC_TRUNCATION_OFFSET) + +#define PSA_ALG_CIPHER_MAC_BASE ((psa_algorithm_t)0x02c00000) +/** The CBC-MAC construction over a block cipher + * + * \warning CBC-MAC is insecure in many cases. + * A more secure mode, such as #PSA_ALG_CMAC, is recommended. + */ +#define PSA_ALG_CBC_MAC ((psa_algorithm_t)0x02c00001) +/** The CMAC construction over a block cipher */ +#define PSA_ALG_CMAC ((psa_algorithm_t)0x02c00002) + +/** Whether the specified algorithm is a MAC algorithm based on a block cipher. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a MAC algorithm based on a block cipher, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) \ + (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \ + PSA_ALG_CIPHER_MAC_BASE) + +#define PSA_ALG_CIPHER_STREAM_FLAG ((psa_algorithm_t)0x00800000) +#define PSA_ALG_CIPHER_FROM_BLOCK_FLAG ((psa_algorithm_t)0x00400000) + +/** Whether the specified algorithm is a stream cipher. + * + * A stream cipher is a symmetric cipher that encrypts or decrypts messages + * by applying a bitwise-xor with a stream of bytes that is generated + * from a key. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a stream cipher algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier or if it is not a symmetric cipher algorithm. + */ +#define PSA_ALG_IS_STREAM_CIPHER(alg) \ + (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_CIPHER_STREAM_FLAG)) == \ + (PSA_ALG_CATEGORY_CIPHER | PSA_ALG_CIPHER_STREAM_FLAG)) + +/** The ARC4 stream cipher algorithm. + */ +#define PSA_ALG_ARC4 ((psa_algorithm_t)0x04800001) + +/** The ChaCha20 stream cipher. + * + * ChaCha20 is defined in RFC 7539. + * + * The nonce size for psa_cipher_set_iv() or psa_cipher_generate_iv() + * must be 12. + * + * The initial block counter is always 0. + * + */ +#define PSA_ALG_CHACHA20 ((psa_algorithm_t)0x04800005) + +/** The CTR stream cipher mode. + * + * CTR is a stream cipher which is built from a block cipher. + * The underlying block cipher is determined by the key type. + * For example, to use AES-128-CTR, use this algorithm with + * a key of type #PSA_KEY_TYPE_AES and a length of 128 bits (16 bytes). + */ +#define PSA_ALG_CTR ((psa_algorithm_t)0x04c00001) + +/** The CFB stream cipher mode. + * + * The underlying block cipher is determined by the key type. + */ +#define PSA_ALG_CFB ((psa_algorithm_t)0x04c00002) + +/** The OFB stream cipher mode. + * + * The underlying block cipher is determined by the key type. + */ +#define PSA_ALG_OFB ((psa_algorithm_t)0x04c00003) + +/** The XTS cipher mode. + * + * XTS is a cipher mode which is built from a block cipher. It requires at + * least one full block of input, but beyond this minimum the input + * does not need to be a whole number of blocks. + */ +#define PSA_ALG_XTS ((psa_algorithm_t)0x044000ff) + +/** The CBC block cipher chaining mode, with no padding. + * + * The underlying block cipher is determined by the key type. + * + * This symmetric cipher mode can only be used with messages whose lengths + * are whole number of blocks for the chosen block cipher. + */ +#define PSA_ALG_CBC_NO_PADDING ((psa_algorithm_t)0x04600100) + +/** The CBC block cipher chaining mode with PKCS#7 padding. + * + * The underlying block cipher is determined by the key type. + * + * This is the padding method defined by PKCS#7 (RFC 2315) §10.3. + */ +#define PSA_ALG_CBC_PKCS7 ((psa_algorithm_t)0x04600101) + +#define PSA_ALG_AEAD_FROM_BLOCK_FLAG ((psa_algorithm_t)0x00400000) + +/** Whether the specified algorithm is an AEAD mode on a block cipher. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is an AEAD algorithm which is an AEAD mode based on + * a block cipher, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) \ + (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_AEAD_FROM_BLOCK_FLAG)) == \ + (PSA_ALG_CATEGORY_AEAD | PSA_ALG_AEAD_FROM_BLOCK_FLAG)) + +/** The CCM authenticated encryption algorithm. + * + * The underlying block cipher is determined by the key type. + */ +#define PSA_ALG_CCM ((psa_algorithm_t)0x06401001) + +/** The GCM authenticated encryption algorithm. + * + * The underlying block cipher is determined by the key type. + */ +#define PSA_ALG_GCM ((psa_algorithm_t)0x06401002) + +/** The Chacha20-Poly1305 AEAD algorithm. + * + * The ChaCha20_Poly1305 construction is defined in RFC 7539. + * + * Implementations must support 12-byte nonces, may support 8-byte nonces, + * and should reject other sizes. + * + * Implementations must support 16-byte tags and should reject other sizes. + */ +#define PSA_ALG_CHACHA20_POLY1305 ((psa_algorithm_t)0x06001005) + +/* In the encoding of a AEAD algorithm, the bits corresponding to + * PSA_ALG_AEAD_TAG_LENGTH_MASK encode the length of the AEAD tag. + * The constants for default lengths follow this encoding. + */ +#define PSA_ALG_AEAD_TAG_LENGTH_MASK ((psa_algorithm_t)0x00003f00) +#define PSA_AEAD_TAG_LENGTH_OFFSET 8 + +/** Macro to build a shortened AEAD algorithm. + * + * A shortened AEAD algorithm is similar to the corresponding AEAD + * algorithm, but has an authentication tag that consists of fewer bytes. + * Depending on the algorithm, the tag length may affect the calculation + * of the ciphertext. + * + * \param aead_alg An AEAD algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_AEAD(\p alg) + * is true). + * \param tag_length Desired length of the authentication tag in bytes. + * + * \return The corresponding AEAD algorithm with the specified + * length. + * \return Unspecified if \p alg is not a supported + * AEAD algorithm or if \p tag_length is not valid + * for the specified AEAD algorithm. + */ +#define PSA_ALG_AEAD_WITH_TAG_LENGTH(aead_alg, tag_length) \ + (((aead_alg) & ~PSA_ALG_AEAD_TAG_LENGTH_MASK) | \ + ((tag_length) << PSA_AEAD_TAG_LENGTH_OFFSET & \ + PSA_ALG_AEAD_TAG_LENGTH_MASK)) + +/** Calculate the corresponding AEAD algorithm with the default tag length. + * + * \param aead_alg An AEAD algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return The corresponding AEAD algorithm with the default + * tag length for that algorithm. + */ +#define PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH(aead_alg) \ + ( \ + PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, PSA_ALG_CCM) \ + PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, PSA_ALG_GCM) \ + PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, PSA_ALG_CHACHA20_POLY1305) \ + 0) +#define PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, ref) \ + PSA_ALG_AEAD_WITH_TAG_LENGTH(aead_alg, 0) == \ + PSA_ALG_AEAD_WITH_TAG_LENGTH(ref, 0) ? \ + ref : + +#define PSA_ALG_RSA_PKCS1V15_SIGN_BASE ((psa_algorithm_t)0x10020000) +/** RSA PKCS#1 v1.5 signature with hashing. + * + * This is the signature scheme defined by RFC 8017 + * (PKCS#1: RSA Cryptography Specifications) under the name + * RSASSA-PKCS1-v1_5. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding RSA PKCS#1 v1.5 signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_RSA_PKCS1V15_SIGN(hash_alg) \ + (PSA_ALG_RSA_PKCS1V15_SIGN_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +/** Raw PKCS#1 v1.5 signature. + * + * The input to this algorithm is the DigestInfo structure used by + * RFC 8017 (PKCS#1: RSA Cryptography Specifications), §9.2 + * steps 3–6. + */ +#define PSA_ALG_RSA_PKCS1V15_SIGN_RAW PSA_ALG_RSA_PKCS1V15_SIGN_BASE +#define PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PKCS1V15_SIGN_BASE) + +#define PSA_ALG_RSA_PSS_BASE ((psa_algorithm_t)0x10030000) +/** RSA PSS signature with hashing. + * + * This is the signature scheme defined by RFC 8017 + * (PKCS#1: RSA Cryptography Specifications) under the name + * RSASSA-PSS, with the message generation function MGF1, and with + * a salt length equal to the length of the hash. The specified + * hash algorithm is used to hash the input message, to create the + * salted hash, and for the mask generation. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding RSA PSS signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_RSA_PSS(hash_alg) \ + (PSA_ALG_RSA_PSS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_IS_RSA_PSS(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PSS_BASE) + +#define PSA_ALG_ECDSA_BASE ((psa_algorithm_t)0x10060000) +/** ECDSA signature with hashing. + * + * This is the ECDSA signature scheme defined by ANSI X9.62, + * with a random per-message secret number (*k*). + * + * The representation of the signature as a byte string consists of + * the concatentation of the signature values *r* and *s*. Each of + * *r* and *s* is encoded as an *N*-octet string, where *N* is the length + * of the base point of the curve in octets. Each value is represented + * in big-endian order (most significant octet first). + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding ECDSA signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_ECDSA(hash_alg) \ + (PSA_ALG_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +/** ECDSA signature without hashing. + * + * This is the same signature scheme as #PSA_ALG_ECDSA(), but + * without specifying a hash algorithm. This algorithm may only be + * used to sign or verify a sequence of bytes that should be an + * already-calculated hash. Note that the input is padded with + * zeros on the left or truncated on the left as required to fit + * the curve size. + */ +#define PSA_ALG_ECDSA_ANY PSA_ALG_ECDSA_BASE +#define PSA_ALG_DETERMINISTIC_ECDSA_BASE ((psa_algorithm_t)0x10070000) +/** Deterministic ECDSA signature with hashing. + * + * This is the deterministic ECDSA signature scheme defined by RFC 6979. + * + * The representation of a signature is the same as with #PSA_ALG_ECDSA(). + * + * Note that when this algorithm is used for verification, signatures + * made with randomized ECDSA (#PSA_ALG_ECDSA(\p hash_alg)) with the + * same private key are accepted. In other words, + * #PSA_ALG_DETERMINISTIC_ECDSA(\p hash_alg) differs from + * #PSA_ALG_ECDSA(\p hash_alg) only for signature, not for verification. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding deterministic ECDSA signature + * algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_DETERMINISTIC_ECDSA(hash_alg) \ + (PSA_ALG_DETERMINISTIC_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_ECDSA_DETERMINISTIC_FLAG ((psa_algorithm_t)0x00010000) +#define PSA_ALG_IS_ECDSA(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_ECDSA_DETERMINISTIC_FLAG) == \ + PSA_ALG_ECDSA_BASE) +#define PSA_ALG_ECDSA_IS_DETERMINISTIC(alg) \ + (((alg) & PSA_ALG_ECDSA_DETERMINISTIC_FLAG) != 0) +#define PSA_ALG_IS_DETERMINISTIC_ECDSA(alg) \ + (PSA_ALG_IS_ECDSA(alg) && PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) +#define PSA_ALG_IS_RANDOMIZED_ECDSA(alg) \ + (PSA_ALG_IS_ECDSA(alg) && !PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) + +/** Whether the specified algorithm is a hash-and-sign algorithm. + * + * Hash-and-sign algorithms are public-key signature algorithms structured + * in two parts: first the calculation of a hash in a way that does not + * depend on the key, then the calculation of a signature from the + * hash value and the key. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a hash-and-sign algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_HASH_AND_SIGN(alg) \ + (PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || \ + PSA_ALG_IS_ECDSA(alg)) + +/** Get the hash used by a hash-and-sign signature algorithm. + * + * A hash-and-sign algorithm is a signature algorithm which is + * composed of two phases: first a hashing phase which does not use + * the key and produces a hash of the input message, then a signing + * phase which only uses the hash and the key and not the message + * itself. + * + * \param alg A signature algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_SIGN(\p alg) is true). + * + * \return The underlying hash algorithm if \p alg is a hash-and-sign + * algorithm. + * \return 0 if \p alg is a signature algorithm that does not + * follow the hash-and-sign structure. + * \return Unspecified if \p alg is not a signature algorithm or + * if it is not supported by the implementation. + */ +#define PSA_ALG_SIGN_GET_HASH(alg) \ + (PSA_ALG_IS_HASH_AND_SIGN(alg) ? \ + ((alg) & PSA_ALG_HASH_MASK) == 0 ? /*"raw" algorithm*/ 0 : \ + ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ + 0) + +/** RSA PKCS#1 v1.5 encryption. + */ +#define PSA_ALG_RSA_PKCS1V15_CRYPT ((psa_algorithm_t)0x12020000) + +#define PSA_ALG_RSA_OAEP_BASE ((psa_algorithm_t)0x12030000) +/** RSA OAEP encryption. + * + * This is the encryption scheme defined by RFC 8017 + * (PKCS#1: RSA Cryptography Specifications) under the name + * RSAES-OAEP, with the message generation function MGF1. + * + * \param hash_alg The hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true) to use + * for MGF1. + * + * \return The corresponding RSA OAEP signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_RSA_OAEP(hash_alg) \ + (PSA_ALG_RSA_OAEP_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_IS_RSA_OAEP(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_OAEP_BASE) +#define PSA_ALG_RSA_OAEP_GET_HASH(alg) \ + (PSA_ALG_IS_RSA_OAEP(alg) ? \ + ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ + 0) + +#define PSA_ALG_HKDF_BASE ((psa_algorithm_t)0x20000100) +/** Macro to build an HKDF algorithm. + * + * For example, `PSA_ALG_HKDF(PSA_ALG_SHA256)` is HKDF using HMAC-SHA-256. + * + * This key derivation algorithm uses the following inputs: + * - #PSA_KEY_DERIVATION_INPUT_SALT is the salt used in the "extract" step. + * It is optional; if omitted, the derivation uses an empty salt. + * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key used in the "extract" step. + * - #PSA_KEY_DERIVATION_INPUT_INFO is the info string used in the "expand" step. + * You must pass #PSA_KEY_DERIVATION_INPUT_SALT before #PSA_KEY_DERIVATION_INPUT_SECRET. + * You may pass #PSA_KEY_DERIVATION_INPUT_INFO at any time after steup and before + * starting to generate output. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding HKDF algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_HKDF(hash_alg) \ + (PSA_ALG_HKDF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +/** Whether the specified algorithm is an HKDF algorithm. + * + * HKDF is a family of key derivation algorithms that are based on a hash + * function and the HMAC construction. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is an HKDF algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_HKDF(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_BASE) +#define PSA_ALG_HKDF_GET_HASH(hkdf_alg) \ + (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) + +#define PSA_ALG_TLS12_PRF_BASE ((psa_algorithm_t)0x20000200) +/** Macro to build a TLS-1.2 PRF algorithm. + * + * TLS 1.2 uses a custom pseudorandom function (PRF) for key schedule, + * specified in Section 5 of RFC 5246. It is based on HMAC and can be + * used with either SHA-256 or SHA-384. + * + * This key derivation algorithm uses the following inputs, which must be + * passed in the order given here: + * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed. + * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key. + * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label. + * + * For the application to TLS-1.2 key expansion, the seed is the + * concatenation of ServerHello.Random + ClientHello.Random, + * and the label is "key expansion". + * + * For example, `PSA_ALG_TLS12_PRF(PSA_ALG_SHA256)` represents the + * TLS 1.2 PRF using HMAC-SHA-256. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding TLS-1.2 PRF algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_TLS12_PRF(hash_alg) \ + (PSA_ALG_TLS12_PRF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) + +/** Whether the specified algorithm is a TLS-1.2 PRF algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a TLS-1.2 PRF algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_TLS12_PRF(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_TLS12_PRF_BASE) +#define PSA_ALG_TLS12_PRF_GET_HASH(hkdf_alg) \ + (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) + +#define PSA_ALG_TLS12_PSK_TO_MS_BASE ((psa_algorithm_t)0x20000300) +/** Macro to build a TLS-1.2 PSK-to-MasterSecret algorithm. + * + * In a pure-PSK handshake in TLS 1.2, the master secret is derived + * from the PreSharedKey (PSK) through the application of padding + * (RFC 4279, Section 2) and the TLS-1.2 PRF (RFC 5246, Section 5). + * The latter is based on HMAC and can be used with either SHA-256 + * or SHA-384. + * + * This key derivation algorithm uses the following inputs, which must be + * passed in the order given here: + * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed. + * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key. + * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label. + * + * For the application to TLS-1.2, the seed (which is + * forwarded to the TLS-1.2 PRF) is the concatenation of the + * ClientHello.Random + ServerHello.Random, + * and the label is "master secret" or "extended master secret". + * + * For example, `PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA256)` represents the + * TLS-1.2 PSK to MasterSecret derivation PRF using HMAC-SHA-256. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding TLS-1.2 PSK to MS algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_TLS12_PSK_TO_MS(hash_alg) \ + (PSA_ALG_TLS12_PSK_TO_MS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) + +/** Whether the specified algorithm is a TLS-1.2 PSK to MS algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a TLS-1.2 PSK to MS algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_TLS12_PSK_TO_MS(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_TLS12_PSK_TO_MS_BASE) +#define PSA_ALG_TLS12_PSK_TO_MS_GET_HASH(hkdf_alg) \ + (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) + +#define PSA_ALG_KEY_DERIVATION_MASK ((psa_algorithm_t)0x0803ffff) +#define PSA_ALG_KEY_AGREEMENT_MASK ((psa_algorithm_t)0x10fc0000) + +/** Macro to build a combined algorithm that chains a key agreement with + * a key derivation. + * + * \param ka_alg A key agreement algorithm (\c PSA_ALG_XXX value such + * that #PSA_ALG_IS_KEY_AGREEMENT(\p ka_alg) is true). + * \param kdf_alg A key derivation algorithm (\c PSA_ALG_XXX value such + * that #PSA_ALG_IS_KEY_DERIVATION(\p kdf_alg) is true). + * + * \return The corresponding key agreement and derivation + * algorithm. + * \return Unspecified if \p ka_alg is not a supported + * key agreement algorithm or \p kdf_alg is not a + * supported key derivation algorithm. + */ +#define PSA_ALG_KEY_AGREEMENT(ka_alg, kdf_alg) \ + ((ka_alg) | (kdf_alg)) + +#define PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) \ + (((alg) & PSA_ALG_KEY_DERIVATION_MASK) | PSA_ALG_CATEGORY_KEY_DERIVATION) + +#define PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) \ + (((alg) & PSA_ALG_KEY_AGREEMENT_MASK) | PSA_ALG_CATEGORY_KEY_AGREEMENT) + +/** Whether the specified algorithm is a raw key agreement algorithm. + * + * A raw key agreement algorithm is one that does not specify + * a key derivation function. + * Usually, raw key agreement algorithms are constructed directly with + * a \c PSA_ALG_xxx macro while non-raw key agreement algorithms are + * constructed with PSA_ALG_KEY_AGREEMENT(). + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a raw key agreement algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_RAW_KEY_AGREEMENT(alg) \ + (PSA_ALG_IS_KEY_AGREEMENT(alg) && \ + PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) == PSA_ALG_CATEGORY_KEY_DERIVATION) + +#define PSA_ALG_IS_KEY_DERIVATION_OR_AGREEMENT(alg) \ + ((PSA_ALG_IS_KEY_DERIVATION(alg) || PSA_ALG_IS_KEY_AGREEMENT(alg))) + +/** The finite-field Diffie-Hellman (DH) key agreement algorithm. + * + * The shared secret produced by key agreement is + * `g^{ab}` in big-endian format. + * It is `ceiling(m / 8)` bytes long where `m` is the size of the prime `p` + * in bits. + */ +#define PSA_ALG_FFDH ((psa_algorithm_t)0x30100000) + +/** Whether the specified algorithm is a finite field Diffie-Hellman algorithm. + * + * This includes the raw finite field Diffie-Hellman algorithm as well as + * finite-field Diffie-Hellman followed by any supporter key derivation + * algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a finite field Diffie-Hellman algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key agreement algorithm identifier. + */ +#define PSA_ALG_IS_FFDH(alg) \ + (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_FFDH) + +/** The elliptic curve Diffie-Hellman (ECDH) key agreement algorithm. + * + * The shared secret produced by key agreement is the x-coordinate of + * the shared secret point. It is always `ceiling(m / 8)` bytes long where + * `m` is the bit size associated with the curve, i.e. the bit size of the + * order of the curve's coordinate field. When `m` is not a multiple of 8, + * the byte containing the most significant bit of the shared secret + * is padded with zero bits. The byte order is either little-endian + * or big-endian depending on the curve type. + * + * - For Montgomery curves (curve types `PSA_ECC_CURVE_CURVEXXX`), + * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` + * in little-endian byte order. + * The bit size is 448 for Curve448 and 255 for Curve25519. + * - For Weierstrass curves over prime fields (curve types + * `PSA_ECC_CURVE_SECPXXX` and `PSA_ECC_CURVE_BRAINPOOL_PXXX`), + * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` + * in big-endian byte order. + * The bit size is `m = ceiling(log_2(p))` for the field `F_p`. + * - For Weierstrass curves over binary fields (curve types + * `PSA_ECC_CURVE_SECTXXX`), + * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` + * in big-endian byte order. + * The bit size is `m` for the field `F_{2^m}`. + */ +#define PSA_ALG_ECDH ((psa_algorithm_t)0x30200000) + +/** Whether the specified algorithm is an elliptic curve Diffie-Hellman + * algorithm. + * + * This includes the raw elliptic curve Diffie-Hellman algorithm as well as + * elliptic curve Diffie-Hellman followed by any supporter key derivation + * algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is an elliptic curve Diffie-Hellman algorithm, + * 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key agreement algorithm identifier. + */ +#define PSA_ALG_IS_ECDH(alg) \ + (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_ECDH) + +/** Whether the specified algorithm encoding is a wildcard. + * + * Wildcard values may only be used to set the usage algorithm field in + * a policy, not to perform an operation. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a wildcard algorithm encoding. + * \return 0 if \c alg is a non-wildcard algorithm encoding (suitable for + * an operation). + * \return This macro may return either 0 or 1 if \c alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_WILDCARD(alg) \ + (PSA_ALG_IS_HASH_AND_SIGN(alg) ? \ + PSA_ALG_SIGN_GET_HASH(alg) == PSA_ALG_ANY_HASH : \ + (alg) == PSA_ALG_ANY_HASH) + +/**@}*/ + +/** \defgroup key_lifetimes Key lifetimes + * @{ + */ + +/** A volatile key only exists as long as the handle to it is not closed. + * The key material is guaranteed to be erased on a power reset. + */ +#define PSA_KEY_LIFETIME_VOLATILE ((psa_key_lifetime_t)0x00000000) + +/** The default storage area for persistent keys. + * + * A persistent key remains in storage until it is explicitly destroyed or + * until the corresponding storage area is wiped. This specification does + * not define any mechanism to wipe a storage area, but implementations may + * provide their own mechanism (for example to perform a factory reset, + * to prepare for device refurbishment, or to uninstall an application). + * + * This lifetime value is the default storage area for the calling + * application. Implementations may offer other storage areas designated + * by other lifetime values as implementation-specific extensions. + */ +#define PSA_KEY_LIFETIME_PERSISTENT ((psa_key_lifetime_t)0x00000001) + +/** The minimum value for a key identifier chosen by the application. + */ +#define PSA_KEY_ID_USER_MIN ((psa_app_key_id_t)0x00000001) +/** The maximum value for a key identifier chosen by the application. + */ +#define PSA_KEY_ID_USER_MAX ((psa_app_key_id_t)0x3fffffff) +/** The minimum value for a key identifier chosen by the implementation. + */ +#define PSA_KEY_ID_VENDOR_MIN ((psa_app_key_id_t)0x40000000) +/** The maximum value for a key identifier chosen by the implementation. + */ +#define PSA_KEY_ID_VENDOR_MAX ((psa_app_key_id_t)0x7fffffff) + +/**@}*/ + +/** \defgroup policy Key policies + * @{ + */ + +/** Whether the key may be exported. + * + * A public key or the public part of a key pair may always be exported + * regardless of the value of this permission flag. + * + * If a key does not have export permission, implementations shall not + * allow the key to be exported in plain form from the cryptoprocessor, + * whether through psa_export_key() or through a proprietary interface. + * The key may however be exportable in a wrapped form, i.e. in a form + * where it is encrypted by another key. + */ +#define PSA_KEY_USAGE_EXPORT ((psa_key_usage_t)0x00000001) + +/** Whether the key may be copied. + * + * This flag allows the use of psa_copy_key() to make a copy of the key + * with the same policy or a more restrictive policy. + * + * For lifetimes for which the key is located in a secure element which + * enforce the non-exportability of keys, copying a key outside the secure + * element also requires the usage flag #PSA_KEY_USAGE_EXPORT. + * Copying the key inside the secure element is permitted with just + * #PSA_KEY_USAGE_COPY if the secure element supports it. + * For keys with the lifetime #PSA_KEY_LIFETIME_VOLATILE or + * #PSA_KEY_LIFETIME_PERSISTENT, the usage flag #PSA_KEY_USAGE_COPY + * is sufficient to permit the copy. + */ +#define PSA_KEY_USAGE_COPY ((psa_key_usage_t)0x00000002) + +/** Whether the key may be used to encrypt a message. + * + * This flag allows the key to be used for a symmetric encryption operation, + * for an AEAD encryption-and-authentication operation, + * or for an asymmetric encryption operation, + * if otherwise permitted by the key's type and policy. + * + * For a key pair, this concerns the public key. + */ +#define PSA_KEY_USAGE_ENCRYPT ((psa_key_usage_t)0x00000100) + +/** Whether the key may be used to decrypt a message. + * + * This flag allows the key to be used for a symmetric decryption operation, + * for an AEAD decryption-and-verification operation, + * or for an asymmetric decryption operation, + * if otherwise permitted by the key's type and policy. + * + * For a key pair, this concerns the private key. + */ +#define PSA_KEY_USAGE_DECRYPT ((psa_key_usage_t)0x00000200) + +/** Whether the key may be used to sign a message. + * + * This flag allows the key to be used for a MAC calculation operation + * or for an asymmetric signature operation, + * if otherwise permitted by the key's type and policy. + * + * For a key pair, this concerns the private key. + */ +#define PSA_KEY_USAGE_SIGN_HASH ((psa_key_usage_t)0x00000400) + +/** Whether the key may be used to verify a message signature. + * + * This flag allows the key to be used for a MAC verification operation + * or for an asymmetric signature verification operation, + * if otherwise permitted by by the key's type and policy. + * + * For a key pair, this concerns the public key. + */ +#define PSA_KEY_USAGE_VERIFY_HASH ((psa_key_usage_t)0x00000800) + +/** Whether the key may be used to derive other keys. + */ +#define PSA_KEY_USAGE_DERIVE ((psa_key_usage_t)0x00001000) + +/**@}*/ + +/** \defgroup derivation Key derivation + * @{ + */ + +/** A secret input for key derivation. + * + * This should be a key of type #PSA_KEY_TYPE_DERIVE + * (passed to psa_key_derivation_input_key()) + * or the shared secret resulting from a key agreement + * (obtained via psa_key_derivation_key_agreement()). + * + * The secret can also be a direct input (passed to + * key_derivation_input_bytes()). In this case, the derivation operation + * may not be used to derive keys: the operation will only allow + * psa_key_derivation_output_bytes(), not psa_key_derivation_output_key(). + */ +#define PSA_KEY_DERIVATION_INPUT_SECRET ((psa_key_derivation_step_t)0x0101) + +/** A label for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + */ +#define PSA_KEY_DERIVATION_INPUT_LABEL ((psa_key_derivation_step_t)0x0201) + +/** A salt for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + */ +#define PSA_KEY_DERIVATION_INPUT_SALT ((psa_key_derivation_step_t)0x0202) + +/** An information string for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + */ +#define PSA_KEY_DERIVATION_INPUT_INFO ((psa_key_derivation_step_t)0x0203) + +/** A seed for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + */ +#define PSA_KEY_DERIVATION_INPUT_SEED ((psa_key_derivation_step_t)0x0204) + +/**@}*/ + +#endif /* PSA_CRYPTO_VALUES_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/error.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/error.h new file mode 100644 index 0000000..439dba4 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/error.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/** + * \file psa/error.h + * \brief Standard error codes for the SPM and RoT Services + */ + +#ifndef __PSA_ERROR_H__ +#define __PSA_ERROR_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* If #PSA_SUCCESS is already defined, it means that #psa_status_t + * is also defined in an external header, so prevent its multiple + * definition. + */ +#ifndef PSA_SUCCESS +typedef int32_t psa_status_t; +#endif + +#define PSA_SUCCESS ((psa_status_t)0) + +#define PSA_ERROR_PROGRAMMER_ERROR ((psa_status_t)-129) +#define PSA_ERROR_CONNECTION_REFUSED ((psa_status_t)-130) +#define PSA_ERROR_CONNECTION_BUSY ((psa_status_t)-131) +#define PSA_ERROR_GENERIC_ERROR ((psa_status_t)-132) +#define PSA_ERROR_NOT_PERMITTED ((psa_status_t)-133) +#define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)-134) +#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)-135) +#define PSA_ERROR_INVALID_HANDLE ((psa_status_t)-136) +#define PSA_ERROR_BAD_STATE ((psa_status_t)-137) +#define PSA_ERROR_BUFFER_TOO_SMALL ((psa_status_t)-138) +#define PSA_ERROR_ALREADY_EXISTS ((psa_status_t)-139) +#define PSA_ERROR_DOES_NOT_EXIST ((psa_status_t)-140) +#define PSA_ERROR_INSUFFICIENT_MEMORY ((psa_status_t)-141) +#define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)-142) +#define PSA_ERROR_INSUFFICIENT_DATA ((psa_status_t)-143) +#define PSA_ERROR_SERVICE_FAILURE ((psa_status_t)-144) +#define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t)-145) +#define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)-146) +#define PSA_ERROR_HARDWARE_FAILURE ((psa_status_t)-147) +#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) + +#ifdef __cplusplus +} +#endif + +#endif /* __PSA_ERROR_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/initial_attestation.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/initial_attestation.h new file mode 100644 index 0000000..c125a4d --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/initial_attestation.h @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/***************************************************************************/ +/* DRAFT UNDER REVIEW */ +/* These APIs are still evolving and are meant as a prototype for review.*/ +/* The APIs will change depending on feedback and will be firmed up */ +/* to a stable set of APIs once all the feedback has been considered. */ +/***************************************************************************/ + +#ifndef __PSA_INITIAL_ATTESTATION_H__ +#define __PSA_INITIAL_ATTESTATION_H__ + +#include +#include +#include +#include "psa/crypto.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief PSA INITIAL ATTESTATION API version + * + * Initial attestation API version is: 1.0.0 + */ +#define PSA_INITIAL_ATTEST_API_VERSION_MAJOR (1) +#define PSA_INITIAL_ATTEST_API_VERSION_MINOR (0) + +/** + * The allowed size of input challenge in bytes: 32, 48, 64 + * Challenge can be a nonce from server + * or the hash of some combined data : nonce + attested data by caller. + */ +#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32 (32u) +#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48 (48u) +#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64 (64u) + +/** + * The maximum size of an attestation token that can be generated by the + * attestation service. Used to configure buffers for services that verify the + * produced tokens. + */ +#define PSA_INITIAL_ATTEST_MAX_TOKEN_SIZE (0x400) + +/** + * The list of fixed claims in the initial attestation token is still evolving, + * you can expect slight changes in the future. + * + * The initial attestation token is planned to be aligned with future version of + * Entity Attestation Token format: + * https://tools.ietf.org/html/draft-mandyam-eat-01 + * + * Current list of claims: + * - Challenge: Input object from caller. Can be a single nonce from server + * or hash of nonce and attested data. It is intended to provide + * freshness to reports and the caller has responsibility to + * arrange this. Allowed length: 32, 48, 64 bytes. The claim is + * modeled to be eventually represented by the EAT standard + * claim nonce. Until such a time as that standard exists, + * the claim will be represented by a custom claim. Value + * is encoded as byte string. + * + * - Instance ID: It represents the unique identifier of the instance. In the + * PSA definition it is a hash of the public attestation key + * of the instance. The claim is modeled to be eventually + * represented by the EAT standard claim UEID of type GUID. + * Until such a time as that standard exists, the claim will be + * represented by a custom claim Value is encoded as byte + * string. + * + * - Verification service indicator: Optional, recommended claim. It is used by + * a Relying Party to locate a validation service for the token. + * The value is a text string that can be used to locate the + * service or a URL specifying the address of the service. The + * claim is modeled to be eventually represented by the EAT + * standard claim origination. Until such a time as that + * standard exists, the claim will be represented by a custom + * claim. Value is encoded as text string. + * + * - Profile definition: Optional, recommended claim. It contains the name of + * a document that describes the 'profile' of the token, being + * a full description of the claims, their usage, verification + * and token signing. The document name may include versioning. + * Custom claim with a value encoded as text string. + * + * - Implementation ID: It represents the original implementation signer of the + * attestation key and identifies the contract between the + * report and verification. A verification service will use this + * claim to locate the details of the verification process. + * Custom claim with a value encoded as byte string. + * + * - Security lifecycle: It represents the current lifecycle state of the + * instance. Custom claim with a value encoded as integer that + * is divided to convey a major state and a minor state. The + * PSA state and implementation state are encoded as follows: + * - version[15:8] - PSA lifecycle state - major + * - version[7:0] - IMPLEMENTATION DEFINED state - minor + * Possible PSA lifecycle states: + * - Unknown (0x1000u), + * - PSA_RoT_Provisioning (0x2000u), + * - Secured (0x3000u), + * - Non_PSA_RoT_Debug(0x4000u), + * - Recoverable_PSA_RoT_Debug (0x5000u), + * - Decommissioned (0x6000u) + * + * - Client ID: The partition ID of that secure partition or non-secure + * thread who called the initial attestation API. Custom claim + * with a value encoded as a *signed* integer. Negative number + * represents non-secure caller, positive numbers represents + * secure callers, zero is invalid. + * + * - HW version: Optional claim. Globally unique number in EAN-13 format + * identifying the GDSII that went to fabrication, HW and ROM. + * It can be used to reference the security level of the PSA-ROT + * via a certification website. Custom claim with a value is + * encoded as text string. + + * - Boot seed: It represents a random value created at system boot time that + * will allow differentiation of reports from different system + * sessions. The size is 32 bytes. Custom claim with a value is + * encoded as byte string. + * + * - Software components: Recommended claim. It represents the software state + * of the system. The value of the claim is an array of CBOR map + * entries, with one entry per software component within the + * device. Each map contains multiple claims that describe + * evidence about the details of the software component. + * + * - Measurement type: Optional claim. It represents the role of the + * software component. Value is encoded as short(!) text + * string. + * + * - Measurement value: It represents a hash of the invariant software + * component in memory at start-up time. The value must be a + * cryptographic hash of 256 bits or stronger.Value is + * encoded as byte string. + * + * - Version: Optional claim. It represents the issued software version. + * Value is encoded as text string. + * + * - Signer ID: It represents the hash of a signing authority public key. + * Value is encoded as byte string. + * + * - Measurement description: Optional claim. It represents the way in which + * the measurement value of the software component is + * computed. Value is encoded as text string containing an + * abbreviated description (name) of the measurement method. + * + * - No software measurements: In the event that the implementation does not + * contain any software measurements then the software + * components claim above can be omitted but instead + * it is mandatory to include this claim to indicate this is a + * deliberate state. Custom claim a value is encoded as unsigned + * integer set to 1. + */ + +/** + * \brief Get initial attestation token + * + * \param[in] auth_challenge Pointer to buffer where challenge input is + * stored. Nonce and / or hash of attested data. + * Must be always + * \ref PSA_INITIAL_ATTEST_TOKEN_SIZE bytes + * long. + * \param[in] challenge_size Size of challenge object in bytes. + * \param[out] token_buf Pointer to the buffer where attestation token + * will be stored. + * \param[in] token_buf_size Size of allocated buffer for token, in bytes. + * \param[out] token_size Size of the token that has been returned, in + * bytes. + * + * \return Returns error code as specified in \ref psa_status_t + */ +psa_status_t +psa_initial_attest_get_token(const uint8_t *auth_challenge, + size_t challenge_size, + uint8_t *token_buf, + size_t token_buf_size, + size_t *token_size); + +/** + * \brief Get the exact size of initial attestation token in bytes. + * + * It just returns with the size of the IAT token. It can be used if the caller + * dynamically allocates memory for the token buffer. + * + * \param[in] challenge_size Size of challenge object in bytes. This must be + * a supported challenge size (as above). + * \param[out] token_size Size of the token in bytes, which is created by + * initial attestation service. + * + * \return Returns error code as specified in \ref psa_status_t + */ +psa_status_t +psa_initial_attest_get_token_size(size_t challenge_size, + size_t *token_size); + +/** + * \brief Get the initial attestation public key. + * + * \param[out] public_key Pointer to the buffer where the public key + * will be stored. + * \param[in] key_buf_size Size of allocated buffer for key, in bytes. + * \param[out] public_key_len Size of public key in bytes. + * \param[out] public_key_curve Type of the elliptic curve which the key + * belongs to. + * + * \note Currently only the ECDSA P-256 over SHA-256 algorithm is supported. + * + * \return Returns error code as specified in \ref psa_status_t + */ +psa_status_t +tfm_initial_attest_get_public_key(uint8_t *public_key, + size_t public_key_buf_size, + size_t *public_key_len, + psa_ecc_curve_t *elliptic_curve_type); + +#ifdef __cplusplus +} +#endif + +#endif /* __PSA_INITIAL_ATTESTATION_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/internal_trusted_storage.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/internal_trusted_storage.h new file mode 100644 index 0000000..3920bc9 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/internal_trusted_storage.h @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/** This file describes the PSA Internal Trusted Storage API +*/ + +#ifndef PSA_INTERNAL_TRUSTED_STORAGE_H +#define PSA_INTERNAL_TRUSTED_STORAGE_H + +#include +#include + +#include "psa/error.h" +#include "psa/storage_common.h" + +#ifdef __cplusplus +extern "C" { +#endif +#define PSA_ITS_API_VERSION_MAJOR 1 /**< The major version number of the + * PSA ITS API + */ +#define PSA_ITS_API_VERSION_MINOR 0 /**< The minor version number of the + * PSA ITS API + */ +// This version of the header file is associated with 1.0 final release. + +/** + * \brief Create a new, or modify an existing, uid/value pair + * + * Stores data in the internal storage. + * + * \param[in] uid The identifier for the data + * \param[in] data_length The size in bytes of the data in `p_data` + * \param[in] p_data A buffer containing the data + * \param[in] create_flags The flags that the data will be stored with + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the + * provided `uid` value was already + * created with + * PSA_STORAGE_FLAG_WRITE_ONCE + * \retval PSA_ERROR_NOT_SUPPORTED The operation failed because one or + * more of the flags provided in + * `create_flags` is not supported or is + * not valid + * \retval PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because there + * was insufficient space on the + * storage medium + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the + * physical storage has failed (Fatal + * error) + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one + * of the provided pointers(`p_data`) + * is invalid, for example is `NULL` or + * references memory the caller cannot + * access + */ +psa_status_t psa_its_set(psa_storage_uid_t uid, + size_t data_length, + const void *p_data, + psa_storage_create_flags_t create_flags); + +/** + * \brief Retrieve data associated with a provided UID + * + * Retrieves up to `data_size` bytes of the data associated with `uid`, starting + * at `data_offset` bytes from the beginning of the data. Upon successful + * completion, the data will be placed in the `p_data` buffer, which must be at + * least `data_size` bytes in size. The length of the data returned will be in + * `p_data_length`. If `data_size` is 0, the contents of `p_data_length` will + * be set to zero. + * + * \param[in] uid The uid value + * \param[in] data_offset The starting offset of the data requested + * \param[in] data_size The amount of data requested + * \param[out] p_data On success, the buffer where the data will + * be placed + * \param[out] p_data_length On success, this will contain size of the data + * placed in `p_data` + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the + * provided `uid` value was not found in + * the storage + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the + * physical storage has failed (Fatal + * error) + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the + * provided arguments (`p_data`, + * `p_data_length`) is invalid, for example + * is `NULL` or references memory the + * caller cannot access. In addition, this + * can also happen if `data_offset` is + * larger than the size of the data + * associated with `uid` + */ +psa_status_t psa_its_get(psa_storage_uid_t uid, + size_t data_offset, + size_t data_size, + void *p_data, + size_t *p_data_length); + +/** + * \brief Retrieve the metadata about the provided uid + * + * Retrieves the metadata stored for a given `uid` as a `psa_storage_info_t` + * structure. + * + * \param[in] uid The `uid` value + * \param[out] p_info A pointer to the `psa_storage_info_t` struct that will + * be populated with the metadata + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided + * uid value was not found in the storage + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical + * storage has failed (Fatal error) + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the + * provided pointers(`p_info`) + * is invalid, for example is `NULL` or + * references memory the caller cannot + * access + */ +psa_status_t psa_its_get_info(psa_storage_uid_t uid, + struct psa_storage_info_t *p_info); + +/** + * \brief Remove the provided uid and its associated data from the storage + * + * Deletes the data from internal storage. + * + * \param[in] uid The `uid` value + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more + * of the given arguments were invalid (null + * pointer, wrong flags and so on) + * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided + * uid value was not found in the storage + * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the provided + * uid value was created with + * PSA_STORAGE_FLAG_WRITE_ONCE + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical + * storage has failed (Fatal error) + */ +psa_status_t psa_its_remove(psa_storage_uid_t uid); + +#ifdef __cplusplus +} +#endif + +#endif // PSA_INTERNAL_TRUSTED_STORAGE_H diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/protected_storage.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/protected_storage.h new file mode 100644 index 0000000..e76205c --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/protected_storage.h @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/* This file describes the PSA Protected Storage API */ + +#ifndef PSA_PROTECTED_STORAGE_H +#define PSA_PROTECTED_STORAGE_H + +#include +#include + +#include "psa/error.h" +#include "psa/storage_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief PSA_PS_API_VERSION version + * + * Major and minor PSA_PS_API_VERSION numbers + */ +#define PSA_PS_API_VERSION_MAJOR 1 +#define PSA_PS_API_VERSION_MINOR 0 + +// This version of the header file is associated with 1.0 final release + +/** + * \brief Create a new, or modify an existing, uid/value pair + * + * Stores data in the protected storage. + * + * \param[in] uid The identifier for the data + * \param[in] data_length The size in bytes of the data in `p_data` + * \param[in] p_data A buffer containing the data + * \param[in] create_flags The flags that the data will be stored with + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the + * provided `uid` value was already + * created with + * PSA_STORAGE_FLAG_WRITE_ONCE + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one + * of the provided pointers(`p_data`) + * is invalid, for example is `NULL` or + * references memory the caller cannot + * access + * \retval PSA_ERROR_NOT_SUPPORTED The operation failed because one or + * more of the flags provided in + * `create_flags` is not supported or is + * not valid + * \retval PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because there + * was insufficient space on the + * storage medium + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the + * physical storage has failed (Fatal + * error) + * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an + * unspecified internal failure + */ +psa_status_t psa_ps_set(psa_storage_uid_t uid, + size_t data_length, + const void *p_data, + psa_storage_create_flags_t create_flags); + +/** + * \brief Retrieve data associated with a provided uid + * + * Retrieves up to `data_size` bytes of the data associated with `uid`, starting + * at `data_offset` bytes from the beginning of the data. Upon successful + * completion, the data will be placed in the `p_data` buffer, which must be at + * least `data_size` bytes in size. The length of the data returned will be in + * `p_data_length`. If `data_size` is 0, the contents of `p_data_length` will + * be set to zero. + * + * \param[in] uid The uid value + * \param[in] data_offset The starting offset of the data requested + * \param[in] data_size The amount of data requested + * \param[out] p_data On success, the buffer where the data will + * be placed + * \param[out] p_data_length On success, this will contain size of the data + * placed in `p_data` + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the + * provided arguments (`p_data`, + * `p_data_length`) is invalid, for example + * is `NULL` or references memory the + * caller cannot access. In addition, this + * can also happen if `data_offset` is + * larger than the size of the data + * associated with `uid` + * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the + * provided `uid` value was not found in + * the storage + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the + * physical storage has failed (Fatal + * error) + * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an + * unspecified internal failure + * \retval PSA_ERROR_DATA_CORRUPT The operation failed because the data + * associated with the UID was corrupt + * \retval PSA_ERROR_INVALID_SIGNATURE The operation failed because the data + * associated with the UID failed + * authentication + */ +psa_status_t psa_ps_get(psa_storage_uid_t uid, + size_t data_offset, + size_t data_size, + void *p_data, + size_t *p_data_length); + +/** + * \brief Retrieve the metadata about the provided uid + * + * Retrieves the metadata stored for a given `uid` + * + * \param[in] uid The `uid` value + * \param[out] p_info A pointer to the `psa_storage_info_t` struct that will + * be populated with the metadata + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the + * provided pointers(`p_info`) + * is invalid, for example is `NULL` or + * references memory the caller cannot + * access + * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided + * uid value was not found in the storage + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical + * storage has failed (Fatal error) + * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an + * unspecified internal failure + * \retval PSA_ERROR_DATA_CORRUPT The operation failed because the data + * associated with the UID was corrupt + */ +psa_status_t psa_ps_get_info(psa_storage_uid_t uid, + struct psa_storage_info_t *p_info); + +/** + * \brief Remove the provided uid and its associated data from the storage + * + * Removes previously stored data and any associated metadata, + * including rollback protection data. + * + * \param[in] uid The `uid` value + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more + * of the given arguments were invalid (null + * pointer, wrong flags and so on) + * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided + * uid value was not found in the storage + * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the provided + * uid value was created with + * PSA_STORAGE_FLAG_WRITE_ONCE + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical + * storage has failed (Fatal error) + * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an + * unspecified internal failure + */ +psa_status_t psa_ps_remove(psa_storage_uid_t uid); + +/** + * \brief Reserves storage for the specified uid + * + * Upon success, the capacity of the storage will be capacity, and the size + * will be 0. It is only necessary to call this function for assets that will + * be written with the psa_ps_set_extended function. If only the psa_ps_set + * function is needed, calls to this function are redundant. + * + * \param[in] uid The `uid` value + * \param[in] capacity The capacity to be allocated in bytes + * \param[in] create_flags Flags indicating properties of storage + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the + * physical storage has failed + * (Fatal error) + * \retval PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because the + * capacity is bigger than the current + * available space + * \retval PSA_ERROR_NOT_SUPPORTED The operation failed because the + * function is not implemented or one + * or more create_flags are not + * supported. + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because uid was + * 0 or create_flags specified flags + * that are not defined in the API. + * \retval PSA_ERROR_GENERIC_ERROR The operation failed due to an + * unspecified error + * \retval PSA_ERROR_ALREADY_EXISTS Storage for the specified uid + * already exists + */ +psa_status_t psa_ps_create(psa_storage_uid_t uid, + size_t capacity, + psa_storage_create_flags_t create_flags); + +/** + * \brief Sets partial data into an asset + * + * Before calling this function, the storage must have been reserved with a call + * to psa_ps_create. It can also be used to overwrite data in an asset that was + * created with a call to psa_ps_set. Calling this function with data_length = 0 + * is permitted, which will make no change to the stored data.This function can + * overwrite existing data and/or extend it up to the capacity for the uid + * specified in psa_ps_create, but cannot create gaps. + * + * That is, it has preconditions: + * - data_offset <= size + * - data_offset + data_length <= capacity + * and postconditions: + * - size = max(size, data_offset + data_length) + * - capacity unchanged. + * + * \param[in] uid The `uid` value + * \param[in] data_offset Offset within the asset to start the write + * \param[in] data_length The size in bytes of the data in p_data to write + * \param[in] p_data Pointer to a buffer which contains the data to write + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The asset exists, the input parameters + * are correct and the data is correctly + * written in the physical storage. + * \retval PSA_ERROR_STORAGE_FAILURE The data was not written correctly in + * the physical storage + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more + * of the preconditions listed above + * regarding data_offset, size, or + * data_length was violated. + * \retval PSA_ERROR_DOES_NOT_EXIST The specified uid was not found + * \retval PSA_ERROR_NOT_SUPPORTED The implementation of the API does not + * support this function + * \retval PSA_ERROR_GENERIC_ERROR The operation failed due to an + * unspecified error + * \retval PSA_ERROR_DATA_CORRUPT The operation failed because the + * existing data has been corrupted. + * \retval PSA_ERROR_INVALID_SIGNATURE The operation failed because the + * existing data failed authentication + * (MAC check failed). + * \retval PSA_ERROR_NOT_PERMITTED The operation failed because it was + * attempted on an asset which was written + * with the flag + * PSA_STORAGE_FLAG_WRITE_ONCE + */ +psa_status_t psa_ps_set_extended(psa_storage_uid_t uid, + size_t data_offset, + size_t data_length, + const void *p_data); + +/** + * \brief Lists optional features. + * + * \return A bitmask with flags set for all of + * the optional features supported by the + * implementation.Currently defined flags + * are limited to + * PSA_STORAGE_SUPPORT_SET_EXTENDED + */ +uint32_t psa_ps_get_support(void); + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_PROTECTED_STORAGE_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/storage_common.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/storage_common.h new file mode 100644 index 0000000..3f901c5 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/storage_common.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/* This file includes common definitions for PSA storage +*/ + +#ifndef PSA_STORAGE_COMMON_H +#define PSA_STORAGE_COMMON_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint32_t psa_storage_create_flags_t; + +typedef uint64_t psa_storage_uid_t; + +/* Flags */ + +#define PSA_STORAGE_FLAG_NONE 0u +#define PSA_STORAGE_FLAG_WRITE_ONCE (1u << 0) +#define PSA_STORAGE_FLAG_NO_CONFIDENTIALITY (1u << 1) +#define PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION (1u << 2) + +/* A container for metadata associated with a specific uid */ + +struct psa_storage_info_t { + size_t capacity; + size_t size; + psa_storage_create_flags_t flags; +}; + +#define PSA_STORAGE_SUPPORT_SET_EXTENDED (1u << 0) + +#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) +#define PSA_ERROR_DATA_CORRUPT ((psa_status_t)-152) + +#ifdef __cplusplus +} +#endif + +#endif // PSA_STORAGE_COMMON_H diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa_manifest/sid.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa_manifest/sid.h new file mode 100644 index 0000000..2fc3394 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa_manifest/sid.h @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ + +#ifndef __PSA_MANIFEST_SID_H__ +#define __PSA_MANIFEST_SID_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/******** TFM_SP_STORAGE ********/ +#define TFM_SST_SET_SID (0x00000060U) +#define TFM_SST_SET_VERSION (1U) +#define TFM_SST_GET_SID (0x00000061U) +#define TFM_SST_GET_VERSION (1U) +#define TFM_SST_GET_INFO_SID (0x00000062U) +#define TFM_SST_GET_INFO_VERSION (1U) +#define TFM_SST_REMOVE_SID (0x00000063U) +#define TFM_SST_REMOVE_VERSION (1U) +#define TFM_SST_GET_SUPPORT_SID (0x00000064U) +#define TFM_SST_GET_SUPPORT_VERSION (1U) + +/******** TFM_SP_ITS ********/ +#define TFM_ITS_SET_SID (0x00000070U) +#define TFM_ITS_SET_VERSION (1U) +#define TFM_ITS_GET_SID (0x00000071U) +#define TFM_ITS_GET_VERSION (1U) +#define TFM_ITS_GET_INFO_SID (0x00000072U) +#define TFM_ITS_GET_INFO_VERSION (1U) +#define TFM_ITS_REMOVE_SID (0x00000073U) +#define TFM_ITS_REMOVE_VERSION (1U) + +/******** TFM_SP_CRYPTO ********/ +#define TFM_CRYPTO_SID (0x00000080U) +#define TFM_CRYPTO_VERSION (1U) + +/******** TFM_SP_PLATFORM ********/ +#define TFM_SP_PLATFORM_SYSTEM_RESET_SID (0x00000040U) +#define TFM_SP_PLATFORM_SYSTEM_RESET_VERSION (1U) +#define TFM_SP_PLATFORM_IOCTL_SID (0x00000041U) +#define TFM_SP_PLATFORM_IOCTL_VERSION (1U) +#define TFM_SP_PLATFORM_NV_COUNTER_SID (0x00000042U) +#define TFM_SP_PLATFORM_NV_COUNTER_VERSION (1U) + +/******** TFM_SP_INITIAL_ATTESTATION ********/ +#define TFM_ATTEST_GET_TOKEN_SID (0x00000020U) +#define TFM_ATTEST_GET_TOKEN_VERSION (1U) +#define TFM_ATTEST_GET_TOKEN_SIZE_SID (0x00000021U) +#define TFM_ATTEST_GET_TOKEN_SIZE_VERSION (1U) +#define TFM_ATTEST_GET_PUBLIC_KEY_SID (0x00000022U) +#define TFM_ATTEST_GET_PUBLIC_KEY_VERSION (1U) + +/******** TFM_SP_CORE_TEST ********/ +#define SPM_CORE_TEST_INIT_SUCCESS_SID (0x0000F020U) +#define SPM_CORE_TEST_INIT_SUCCESS_VERSION (1U) +#define SPM_CORE_TEST_DIRECT_RECURSION_SID (0x0000F021U) +#define SPM_CORE_TEST_DIRECT_RECURSION_VERSION (1U) +#define SPM_CORE_TEST_MPU_ACCESS_SID (0x0000F022U) +#define SPM_CORE_TEST_MPU_ACCESS_VERSION (1U) +#define SPM_CORE_TEST_MEMORY_PERMISSIONS_SID (0x0000F023U) +#define SPM_CORE_TEST_MEMORY_PERMISSIONS_VERSION (1U) +#define SPM_CORE_TEST_SS_TO_SS_SID (0x0000F024U) +#define SPM_CORE_TEST_SS_TO_SS_VERSION (1U) +#define SPM_CORE_TEST_SS_TO_SS_BUFFER_SID (0x0000F025U) +#define SPM_CORE_TEST_SS_TO_SS_BUFFER_VERSION (1U) +#define SPM_CORE_TEST_OUTVEC_WRITE_SID (0x0000F026U) +#define SPM_CORE_TEST_OUTVEC_WRITE_VERSION (1U) +#define SPM_CORE_TEST_PERIPHERAL_ACCESS_SID (0x0000F027U) +#define SPM_CORE_TEST_PERIPHERAL_ACCESS_VERSION (1U) +#define SPM_CORE_TEST_GET_CALLER_CLIENT_ID_SID (0x0000F028U) +#define SPM_CORE_TEST_GET_CALLER_CLIENT_ID_VERSION (1U) +#define SPM_CORE_TEST_SPM_REQUEST_SID (0x0000F029U) +#define SPM_CORE_TEST_SPM_REQUEST_VERSION (1U) +#define SPM_CORE_TEST_BLOCK_SID (0x0000F02AU) +#define SPM_CORE_TEST_BLOCK_VERSION (1U) +#define SPM_CORE_TEST_NS_THREAD_SID (0x0000F02BU) +#define SPM_CORE_TEST_NS_THREAD_VERSION (1U) + +/******** TFM_SP_CORE_TEST_2 ********/ +#define SPM_CORE_TEST_2_SLAVE_SERVICE_SID (0x0000F040U) +#define SPM_CORE_TEST_2_SLAVE_SERVICE_VERSION (1U) +#define SPM_CORE_TEST_2_CHECK_CALLER_CLIENT_ID_SID (0x0000F041U) +#define SPM_CORE_TEST_2_CHECK_CALLER_CLIENT_ID_VERSION (1U) +#define SPM_CORE_TEST_2_GET_EVERY_SECOND_BYTE_SID (0x0000F042U) +#define SPM_CORE_TEST_2_GET_EVERY_SECOND_BYTE_VERSION (1U) +#define SPM_CORE_TEST_2_INVERT_SID (0x0000F043U) +#define SPM_CORE_TEST_2_INVERT_VERSION (1U) +#define SPM_CORE_TEST_2_PREPARE_TEST_SCENARIO_SID (0x0000F044U) +#define SPM_CORE_TEST_2_PREPARE_TEST_SCENARIO_VERSION (1U) +#define SPM_CORE_TEST_2_EXECUTE_TEST_SCENARIO_SID (0x0000F045U) +#define SPM_CORE_TEST_2_EXECUTE_TEST_SCENARIO_VERSION (1U) + +/******** TFM_SP_SECURE_TEST_PARTITION ********/ +#define TFM_SECURE_CLIENT_SFN_RUN_TESTS_SID (0x0000F000U) +#define TFM_SECURE_CLIENT_SFN_RUN_TESTS_VERSION (1U) + +/******** TFM_SP_IPC_SERVICE_TEST ********/ +#define IPC_SERVICE_TEST_BASIC_SID (0x0000F080U) +#define IPC_SERVICE_TEST_BASIC_VERSION (1U) +#define IPC_SERVICE_TEST_PSA_ACCESS_APP_MEM_SID (0x0000F081U) +#define IPC_SERVICE_TEST_PSA_ACCESS_APP_MEM_VERSION (1U) +#define IPC_SERVICE_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_SID (0x0000F082U) +#define IPC_SERVICE_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_VERSION (1U) +#define IPC_SERVICE_TEST_APP_ACCESS_PSA_MEM_SID (0x0000F083U) +#define IPC_SERVICE_TEST_APP_ACCESS_PSA_MEM_VERSION (1U) +#define IPC_SERVICE_TEST_CLIENT_PROGRAMMER_ERROR_SID (0x0000F084U) +#define IPC_SERVICE_TEST_CLIENT_PROGRAMMER_ERROR_VERSION (1U) + +/******** TFM_SP_IPC_CLIENT_TEST ********/ +#define IPC_CLIENT_TEST_BASIC_SID (0x0000F060U) +#define IPC_CLIENT_TEST_BASIC_VERSION (1U) +#define IPC_CLIENT_TEST_PSA_ACCESS_APP_MEM_SID (0x0000F061U) +#define IPC_CLIENT_TEST_PSA_ACCESS_APP_MEM_VERSION (1U) +#define IPC_CLIENT_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_SID (0x0000F062U) +#define IPC_CLIENT_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_VERSION (1U) +#define IPC_CLIENT_TEST_APP_ACCESS_PSA_MEM_SID (0x0000F063U) +#define IPC_CLIENT_TEST_APP_ACCESS_PSA_MEM_VERSION (1U) +#define IPC_CLIENT_TEST_MEM_CHECK_SID (0x0000F064U) +#define IPC_CLIENT_TEST_MEM_CHECK_VERSION (1U) + +/******** TFM_IRQ_TEST_1 ********/ +#define SPM_CORE_IRQ_TEST_1_PREPARE_TEST_SCENARIO_SID (0x0000F0A0U) +#define SPM_CORE_IRQ_TEST_1_PREPARE_TEST_SCENARIO_VERSION (1U) +#define SPM_CORE_IRQ_TEST_1_EXECUTE_TEST_SCENARIO_SID (0x0000F0A1U) +#define SPM_CORE_IRQ_TEST_1_EXECUTE_TEST_SCENARIO_VERSION (1U) + +/******** TFM_SP_SST_TEST ********/ +#define TFM_SST_TEST_PREPARE_SID (0x0000F0C0U) +#define TFM_SST_TEST_PREPARE_VERSION (1U) + +/******** TFM_SP_SECURE_CLIENT_2 ********/ +#define TFM_SECURE_CLIENT_2_SID (0x0000F0E0U) +#define TFM_SECURE_CLIENT_2_VERSION (1U) + +/******** TFM_SP_MULTI_CORE_TEST ********/ +#define MULTI_CORE_MULTI_CLIENT_CALL_TEST_0_SID (0x0000F100U) +#define MULTI_CORE_MULTI_CLIENT_CALL_TEST_0_VERSION (1U) +#define MULTI_CORE_MULTI_CLIENT_CALL_TEST_1_SID (0x0000F101U) +#define MULTI_CORE_MULTI_CLIENT_CALL_TEST_1_VERSION (1U) + +#ifdef __cplusplus +} +#endif + +#endif /* __PSA_MANIFEST_SID_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_api.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_api.h new file mode 100644 index 0000000..09abc39 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_api.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2017-2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __TFM_API_H__ +#define __TFM_API_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "psa/client.h" + +#define TFM_INVALID_CLIENT_ID 0 + +/** + * \brief Checks if the provided client ID is a secure client ID. + * + * \param[in] client_id Client ID to check. + * + * \retval 1 Client ID is secure. + * \retval 0 Client ID is non-secure. + */ +#define TFM_CLIENT_ID_IS_S(client_id) ((client_id)>0) + +/** + * \brief Checks if the provided client ID is a non-secure client ID. + * + * \param[in] client_id Client ID to check. + * + * \retval 1 Client ID is non-secure. + * \retval 0 Client ID is secure. + */ +#define TFM_CLIENT_ID_IS_NS(client_id) ((client_id)<0) + +/* The mask used for timeout values */ +#define PSA_TIMEOUT_MASK PSA_BLOCK + +/* FixMe: sort out DEBUG compile option and limit return value options + * on external interfaces */ +enum tfm_status_e +{ + TFM_SUCCESS = 0, + TFM_PARTITION_BUSY, + TFM_ERROR_SECURE_DOMAIN_LOCKED, + TFM_ERROR_INVALID_PARAMETER, + TFM_ERROR_PARTITION_NON_REENTRANT, + TFM_ERROR_NS_THREAD_MODE_CALL, + TFM_ERROR_NOT_INITIALIZED, + TFM_ERROR_NO_ACTIVE_PARTITION, + TFM_ERROR_INVALID_EXC_MODE, + TFM_SECURE_LOCK_FAILED, + TFM_SECURE_UNLOCK_FAILED, + TFM_ERROR_GENERIC = 0x1F, +}; + +/* + * Structure to package type, in_len and out_len, it is mainly used for + * psa_call. + */ +struct tfm_control_parameter_t { + int32_t type; + size_t in_len; + size_t out_len; +}; + +/********************* Secure function declarations ***************************/ + +/** + * \brief Assign client ID to the current TZ context. + * + * \param[in] ns_client_id The client ID to be assigned to the current + * context. + * \retval TFM_SUCCESS The client ID assigned successfully. + * \retval error code The client ID assignment failed, an error code + * returned according to \ref tfm_status_e. + * \note This function have to be called from handler mode. + */ +enum tfm_status_e tfm_register_client_id (int32_t ns_client_id); + +/** + * \brief Retrieve the version of the PSA Framework API that is implemented. + * + * \return The version of the PSA Framework. + */ +uint32_t tfm_psa_framework_version_veneer(void); + +/** + * \brief Return version of secure function provided by secure binary. + * + * \param[in] sid ID of secure service. + * + * \return Version number of secure function. + */ +uint32_t tfm_psa_version_veneer(uint32_t sid); + +/** + * \brief Connect to secure function. + * + * \param[in] sid ID of secure service. + * \param[in] version Version of SF requested by client. + * + * \return Returns handle to connection. + */ +psa_handle_t tfm_psa_connect_veneer(uint32_t sid, uint32_t version); + +/** + * \brief Call a secure function referenced by a connection handle. + * + * \param[in] handle Handle to connection. + * \param[in] ctrl_param Parameter structure, includes reuqest type, + * in_num and out_num. + * \param[in] in_vec Array of input \ref psa_invec structures. + * \param[in/out] out_vec Array of output \ref psa_outvec structures. + * + * \return Returns \ref psa_status_t status code. + */ +psa_status_t tfm_psa_call_veneer(psa_handle_t handle, + const struct tfm_control_parameter_t *ctrl_param, + const psa_invec *in_vec, + psa_outvec *out_vec); + +/** + * \brief Close connection to secure function referenced by a connection handle. + * + * \param[in] handle Handle to connection + * + * \return void + */ +void tfm_psa_close_veneer(psa_handle_t handle); + +/***************** End Secure function declarations ***************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_API_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_crypto_defs.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_crypto_defs.h new file mode 100644 index 0000000..53c03ce --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_crypto_defs.h @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __TFM_CRYPTO_DEFS_H__ +#define __TFM_CRYPTO_DEFS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include "tfm_api.h" +#include "psa/crypto.h" + +/** + * \brief This type is used to overcome a limitation in the number of maximum + * IOVECs that can be used especially in psa_aead_encrypt and + * psa_aead_decrypt. To be removed in case the AEAD APIs number of + * parameters passed gets restructured + */ +#define TFM_CRYPTO_MAX_NONCE_LENGTH (16u) +struct tfm_crypto_aead_pack_input { + uint8_t nonce[TFM_CRYPTO_MAX_NONCE_LENGTH]; + uint32_t nonce_length; +}; + +/** + * \brief Structure used to pack non-pointer types in a call + * + */ +struct tfm_crypto_pack_iovec { + uint32_t sfn_id; /*!< Secure function ID used to dispatch the + * request + */ + uint16_t step; /*!< Key derivation step */ + psa_key_handle_t key_handle; /*!< Key handle */ + psa_algorithm_t alg; /*!< Algorithm */ + uint32_t op_handle; /*!< Frontend context handle associated to a + * multipart operation + */ + size_t capacity; /*!< Key derivation capacity */ + + struct tfm_crypto_aead_pack_input aead_in; /*!< FixMe: Temporarily used for + * AEAD until the API is + * restructured + */ +}; + +/** + * \brief Define a progressive numerical value for each SID which can be used + * when dispatching the requests to the service + */ +enum { + TFM_CRYPTO_GET_KEY_ATTRIBUTES_SID = (0u), + TFM_CRYPTO_RESET_KEY_ATTRIBUTES_SID, + TFM_CRYPTO_OPEN_KEY_SID, + TFM_CRYPTO_CLOSE_KEY_SID, + TFM_CRYPTO_IMPORT_KEY_SID, + TFM_CRYPTO_DESTROY_KEY_SID, + TFM_CRYPTO_EXPORT_KEY_SID, + TFM_CRYPTO_EXPORT_PUBLIC_KEY_SID, + TFM_CRYPTO_COPY_KEY_SID, + TFM_CRYPTO_HASH_COMPUTE_SID, + TFM_CRYPTO_HASH_COMPARE_SID, + TFM_CRYPTO_HASH_SETUP_SID, + TFM_CRYPTO_HASH_UPDATE_SID, + TFM_CRYPTO_HASH_FINISH_SID, + TFM_CRYPTO_HASH_VERIFY_SID, + TFM_CRYPTO_HASH_ABORT_SID, + TFM_CRYPTO_HASH_CLONE_SID, + TFM_CRYPTO_MAC_COMPUTE_SID, + TFM_CRYPTO_MAC_VERIFY_SID, + TFM_CRYPTO_MAC_SIGN_SETUP_SID, + TFM_CRYPTO_MAC_VERIFY_SETUP_SID, + TFM_CRYPTO_MAC_UPDATE_SID, + TFM_CRYPTO_MAC_SIGN_FINISH_SID, + TFM_CRYPTO_MAC_VERIFY_FINISH_SID, + TFM_CRYPTO_MAC_ABORT_SID, + TFM_CRYPTO_CIPHER_ENCRYPT_SID, + TFM_CRYPTO_CIPHER_DECRYPT_SID, + TFM_CRYPTO_CIPHER_ENCRYPT_SETUP_SID, + TFM_CRYPTO_CIPHER_DECRYPT_SETUP_SID, + TFM_CRYPTO_CIPHER_GENERATE_IV_SID, + TFM_CRYPTO_CIPHER_SET_IV_SID, + TFM_CRYPTO_CIPHER_UPDATE_SID, + TFM_CRYPTO_CIPHER_FINISH_SID, + TFM_CRYPTO_CIPHER_ABORT_SID, + TFM_CRYPTO_AEAD_ENCRYPT_SID, + TFM_CRYPTO_AEAD_DECRYPT_SID, + TFM_CRYPTO_AEAD_ENCRYPT_SETUP_SID, + TFM_CRYPTO_AEAD_DECRYPT_SETUP_SID, + TFM_CRYPTO_AEAD_GENERATE_NONCE_SID, + TFM_CRYPTO_AEAD_SET_NONCE_SID, + TFM_CRYPTO_AEAD_SET_LENGTHS_SID, + TFM_CRYPTO_AEAD_UPDATE_AD_SID, + TFM_CRYPTO_AEAD_UPDATE_SID, + TFM_CRYPTO_AEAD_FINISH_SID, + TFM_CRYPTO_AEAD_VERIFY_SID, + TFM_CRYPTO_AEAD_ABORT_SID, + TFM_CRYPTO_SIGN_HASH_SID, + TFM_CRYPTO_VERIFY_HASH_SID, + TFM_CRYPTO_ASYMMETRIC_ENCRYPT_SID, + TFM_CRYPTO_ASYMMETRIC_DECRYPT_SID, + TFM_CRYPTO_KEY_DERIVATION_SETUP_SID, + TFM_CRYPTO_KEY_DERIVATION_GET_CAPACITY_SID, + TFM_CRYPTO_KEY_DERIVATION_SET_CAPACITY_SID, + TFM_CRYPTO_KEY_DERIVATION_INPUT_BYTES_SID, + TFM_CRYPTO_KEY_DERIVATION_INPUT_KEY_SID, + TFM_CRYPTO_KEY_DERIVATION_KEY_AGREEMENT_SID, + TFM_CRYPTO_KEY_DERIVATION_OUTPUT_BYTES_SID, + TFM_CRYPTO_KEY_DERIVATION_OUTPUT_KEY_SID, + TFM_CRYPTO_KEY_DERIVATION_ABORT_SID, + TFM_CRYPTO_RAW_KEY_AGREEMENT_SID, + TFM_CRYPTO_GENERATE_RANDOM_SID, + TFM_CRYPTO_GENERATE_KEY_SID, + TFM_CRYPTO_SET_KEY_DOMAIN_PARAMETERS_SID, + TFM_CRYPTO_GET_KEY_DOMAIN_PARAMETERS_SID, + TFM_CRYPTO_SID_MAX, +}; + +/** + * \brief Define an invalid value for an SID + * + */ +#define TFM_CRYPTO_SID_INVALID (~0x0u) + +/** + * \brief This value is used to mark an handle as invalid. + * + */ +#define TFM_CRYPTO_INVALID_HANDLE (0x0u) + +/** + * \brief The persistent key identifier that refers to the hardware unique key. + * + */ +#define TFM_CRYPTO_KEY_ID_HUK (0xFFFF815Bu) + +/** + * \brief The algorithm identifier that refers to key derivation from the + * hardware unique key. + * + */ +#define TFM_CRYPTO_ALG_HUK_DERIVATION ((psa_algorithm_t)0xB0000F00) + +/** + * \brief Define miscellaneous literal constants that are used in the service + * + */ +enum { + TFM_CRYPTO_NOT_IN_USE = 0, + TFM_CRYPTO_IN_USE = 1 +}; + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_CRYPTO_DEFS_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_mailbox.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_mailbox.h new file mode 100644 index 0000000..3d128f4 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_mailbox.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/* + * This is header file of common mailbox objects shared by NSPE and SPE. + * Please refer to tfm_ns_mailbox.h for the definitions only used in NSPE + * mailbox library. + * Please refer to tfm_spe_mailbox.h for the SPE specific definitions and APIs. + */ + +#ifndef __TFM_MAILBOX_H__ +#define __TFM_MAILBOX_H__ + +#include +#include +#include +#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL +#include "device_cfg.h" +#endif +#include "psa/client.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * If multiple outstanding NS PSA Client calls is enabled, multi-core platform + * should define the number of mailbox queue slots NUM_MAILBOX_QUEUE_SLOT in + * platform device_cfg.h. + * Otherwise, NUM_MAILBOX_QUEUE_SLOT is defined as 1. + */ +#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL +#ifndef NUM_MAILBOX_QUEUE_SLOT +#error "Error: Platform doesn't define NUM_MAILBOX_QUEUE_SLOT for mailbox queue" +#endif + +#if (NUM_MAILBOX_QUEUE_SLOT < 2) +#error "Error: Invalid NUM_MAILBOX_QUEUE_SLOT. The value should be more than 1" +#endif + +/* + * The number of slots should be no more than the number of bits in + * mailbox_queue_status_t. + * Here the value is hardcoded. A better way is to define a sizeof() to + * calculate the bits in mailbox_queue_status_t and dump it with pragma message. + */ +#if (NUM_MAILBOX_QUEUE_SLOT > 32) +#error "Error: Invalid NUM_MAILBOX_QUEUE_SLOT. The value should be no more than 32" +#endif +#else /* TFM_MULTI_CORE_MULTI_CLIENT_CALL */ +/* Force the number of mailbox queue slots as 1. */ +#undef NUM_MAILBOX_QUEUE_SLOT +#define NUM_MAILBOX_QUEUE_SLOT (1) +#endif /* TFM_MULTI_CORE_MULTI_CLIENT_CALL */ + +/* PSA client call type value */ +#define MAILBOX_PSA_FRAMEWORK_VERSION (0x1) +#define MAILBOX_PSA_VERSION (0x2) +#define MAILBOX_PSA_CONNECT (0x3) +#define MAILBOX_PSA_CALL (0x4) +#define MAILBOX_PSA_CLOSE (0x5) + +/* Return code of mailbox APIs */ +#define MAILBOX_SUCCESS (0) +#define MAILBOX_QUEUE_FULL (INT32_MIN + 1) +#define MAILBOX_INVAL_PARAMS (INT32_MIN + 2) +#define MAILBOX_NO_PERMS (INT32_MIN + 3) +#define MAILBOX_NO_PEND_EVENT (INT32_MIN + 4) +#define MAILBOX_CHAN_BUSY (INT32_MIN + 5) +#define MAILBOX_CALLBACK_REG_ERROR (INT32_MIN + 6) +#define MAILBOX_INIT_ERROR (INT32_MIN + 7) + +/* + * This structure holds the parameters used in a PSA client call. + */ +struct psa_client_params_t { + union { + struct { + uint32_t sid; + } psa_version_params; + + struct { + uint32_t sid; + uint32_t version; + } psa_connect_params; + + struct { + psa_handle_t handle; + int32_t type; + const psa_invec *in_vec; + size_t in_len; + psa_outvec *out_vec; + size_t out_len; + } psa_call_params; + + struct { + psa_handle_t handle; + } psa_close_params; + }; +}; + +/* Mailbox message passed from NSPE to SPE to deliver a PSA client call */ +struct mailbox_msg_t { + uint32_t call_type; /* PSA client call type */ + struct psa_client_params_t params; /* Contain parameters used in PSA + * client call + */ + + int32_t client_id; /* Optional client ID of the + * non-secure caller. + * It is required to identify the + * non-secure task when NSPE OS + * enforces non-secure task isolation + */ +}; + +/* A handle to a mailbox message in use */ +typedef int32_t mailbox_msg_handle_t; + +#define MAILBOX_MSG_NULL_HANDLE ((mailbox_msg_handle_t)0) + +/* + * Mailbox reply structure in non-secure memory + * to hold the PSA client call return result from SPE + */ +struct mailbox_reply_t { + int32_t return_val; +}; + +/* A single slot structure in NSPE mailbox queue */ +struct ns_mailbox_slot_t { + struct mailbox_msg_t msg; + struct mailbox_reply_t reply; + const void *owner; /* Handle of the owner task of this + * slot + */ + bool is_woken; /* Indicate that owner task has been + * or should be woken up, after the + * replied is received. + */ +}; + +typedef uint32_t mailbox_queue_status_t; + +/* NSPE mailbox queue */ +struct ns_mailbox_queue_t { + mailbox_queue_status_t empty_slots; /* Bitmask of empty slots */ + mailbox_queue_status_t pend_slots; /* Bitmask of slots pending + * for SPE handling + */ + mailbox_queue_status_t replied_slots; /* Bitmask of active slots + * containing PSA client call + * return result + */ + + struct ns_mailbox_slot_t queue[NUM_MAILBOX_QUEUE_SLOT]; + +#ifdef TFM_MULTI_CORE_TEST + uint32_t nr_tx; /* The total number of + * submission of NS PSA Client + * calls from NS task via + * mailbox. + */ + uint32_t nr_used_slots; /* The total number of used + * mailbox queue slots each time + * NS thread requests a mailbox + * queue slot. + */ +#endif +}; + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_MAILBOX_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_multi_core_api.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_multi_core_api.h new file mode 100644 index 0000000..7999fa4 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_multi_core_api.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __TFM_MULTI_CORE_API__ +#define __TFM_MULTI_CORE_API__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/** + * \brief Called on the non-secure CPU. + * Flags that the non-secure side has completed its initialization. + * Waits, if necessary, for the secure CPU to flag that it has completed + * its initialization. + * + * \return Return 0 if succeeds. + * \return Otherwise, return specific error code. + */ +int32_t tfm_ns_wait_for_s_cpu_ready(void); + +/** + * \brief Synchronisation with secure CPU, platform-specific implementation. + * Flags that the non-secure side has completed its initialization. + * Waits, if necessary, for the secure CPU to flag that it has completed + * its initialization. + * + * \retval Return 0 if succeeds. + * \retval Otherwise, return specific error code. + */ +int32_t tfm_platform_ns_wait_for_s_cpu_ready(void); + +/** + * \brief Acquire the multi-core lock for synchronizing PSA client call(s) + * The actual implementation depends on the use scenario. + * + * \return \ref TFM_SUCCESS on success + * \return \ref TFM_ERROR_GENERIC on error + */ +uint32_t tfm_ns_multi_core_lock_acquire(void); + +/** + * \brief Release the multi-core lock for synchronizing PSA client call(s) + * The actual implementation depends on the use scenario. + * + * \return \ref TFM_SUCCESS on success + * \return \ref TFM_ERROR_GENERIC on error + */ +uint32_t tfm_ns_multi_core_lock_release(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_MULTI_CORE_API__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_ns_interface.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_ns_interface.h new file mode 100644 index 0000000..21857be --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_ns_interface.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017-2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +#ifndef __TFM_NS_INTERFACE_H__ +#define __TFM_NS_INTERFACE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "tfm_api.h" + +typedef int32_t (*veneer_fn) (uint32_t arg0, uint32_t arg1, + uint32_t arg2, uint32_t arg3); + +/** + * \brief NS interface, veneer function dispatcher + * + * \details This function implements the dispatching mechanism for the + * desired veneer function, to be called with the parameters + * described from arg0 to arg3. + * + * \param[in] fn Function pointer to the veneer function desired + * \param[in] arg0 Argument 0 + * \param[in] arg1 Argument 1 + * \param[in] arg2 Argument 2 + * \param[in] arg3 Argument 3 + * + * \return Returns the same return value of the requested veneer function + */ +int32_t tfm_ns_interface_dispatch(veneer_fn fn, + uint32_t arg0, uint32_t arg1, + uint32_t arg2, uint32_t arg3); + +/** + * \brief NS interface, Initialise the NS interface + * + * \details This function needs to be called from the NS world to + * properly initialise the NS interface towards TF-M. This + * function will initialise all the objects required for + * runtime dispatching of TF-M requests to services + * + * \return A value according to \ref enum tfm_status_e + */ +enum tfm_status_e tfm_ns_interface_init(void); +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_NS_INTERFACE_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_ns_mailbox.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_ns_mailbox.h new file mode 100644 index 0000000..ba902aa --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_ns_mailbox.h @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/* Data types and API definitions in NSPE mailbox library */ + +#ifndef __TFM_NS_MAILBOX_H__ +#define __TFM_NS_MAILBOX_H__ + +#include +#include +#include "tfm_mailbox.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef TFM_MULTI_CORE_TEST +/** + * \brief The structure to hold the statistics result of NSPE mailbox + */ +struct ns_mailbox_stats_res_t { + uint8_t avg_nr_slots; /* The value before the decimal point + * in the average number of NSPE + * mailbox slots in use. + */ + uint8_t avg_nr_slots_tenths; /* The first digit value after the + * decimal point in the average + * number of NSPE mailbox slots in use. + */ +}; +#endif + +/** + * \brief Prepare and send PSA client request to SPE via mailbox. + * + * \param[in] call_type PSA client call type + * \param[in] params Parmaters used for PSA client call + * \param[in] client_id Optional client ID of non-secure caller. + * It is required to identify the non-secure caller + * when NSPE OS enforces non-secure task isolation. + * + * \retval >= 0 The handle to the mailbox message assigned. + * \retval < 0 Operation failed with an error code. + */ +mailbox_msg_handle_t tfm_ns_mailbox_tx_client_req(uint32_t call_type, + const struct psa_client_params_t *params, + int32_t client_id); + +/** + * \brief Fetch PSA client return result. + * + * \param[in] handle The handle to the mailbox message + * \param[out] reply The address to be written with return result. + * + * \retval MAILBOX_SUCCESS Successfully get PSA client call return result. + * \retval Other return code Operation failed with an error code. + */ +int32_t tfm_ns_mailbox_rx_client_reply(mailbox_msg_handle_t handle, + int32_t *reply); + +/** + * \brief Check whether a specific mailbox message has been replied. + * + * \param[in] handle The handle to the mailbox message + * + * \retval true The PSA client call return value is replied. + * \retval false The PSA client call return value is not + * replied yet. + */ +bool tfm_ns_mailbox_is_msg_replied(mailbox_msg_handle_t handle); + +/** + * \brief NSPE mailbox initialization + * + * \param[in] queue The base address of NSPE mailbox queue to be + * initialized. + * + * \retval MAILBOX_SUCCESS Operation succeeded. + * \retval Other return code Operation failed with an error code. + */ +int32_t tfm_ns_mailbox_init(struct ns_mailbox_queue_t *queue); + +#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL +/** + * \brief Get the handle of the current non-secure task executing mailbox + * functionalities + * + * \note This function should be implemented according to platform, NS OS + * and actual use scenario. + * This function can be ignored or return NULL if sleep/wake-up mechanism + * is not required in PSA Client API implementation. + * + * \return Return the handle of task. + */ +const void *tfm_ns_mailbox_get_task_handle(void); +#else +static inline const void *tfm_ns_mailbox_get_task_handle(void) +{ + return NULL; +} +#endif + +/** + * \brief Fetch the handle to the first replied mailbox message in the NSPE + * mailbox queue. + * This function is intended to be called inside platform specific + * notification IRQ handler. + * + * \note The replied status of the fetched mailbox message will be cleaned after + * the message is fetched. When this function is called again, it fetches + * the next replied mailbox message from the NSPE mailbox queue. + * + * \return Return the handle to the first replied mailbox message in the + * queue. + * Return \ref MAILBOX_MSG_NULL_HANDLE if no mailbox message is replied. + */ +mailbox_msg_handle_t tfm_ns_mailbox_fetch_reply_msg_isr(void); + +/** + * \brief Return the handle of owner task of a mailbox message according to the + * \ref mailbox_msg_handle_t + * + * \param[in] handle The handle of mailbox message. + * + * \return Return the handle value of the owner task. + */ +const void *tfm_ns_mailbox_get_msg_owner(mailbox_msg_handle_t handle); + +#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL +/** + * \brief Wait for the reply returned from SPE to the mailbox message specified + * by handle + * + * \param[in] handle The handle of mailbox message. + * + * \retval MAILBOX_SUCCESS Return from waiting successfully. + * \retval Other return code Failed to wait with an error code. + */ +int32_t tfm_ns_mailbox_wait_reply(mailbox_msg_handle_t handle); +#endif + +/** + * \brief Platform specific NSPE mailbox initialization. + * Invoked by \ref tfm_ns_mailbox_init(). + * + * \param[in] queue The base address of NSPE mailbox queue to be + * initialized. + * + * \retval MAILBOX_SUCCESS Operation succeeded. + * \retval Other return code Operation failed with an error code. + */ +int32_t tfm_ns_mailbox_hal_init(struct ns_mailbox_queue_t *queue); + +/** + * \brief Notify SPE to deal with the PSA client call sent via mailbox + * + * \note The implementation depends on platform specific hardware and use case. + * + * \retval MAILBOX_SUCCESS Operation succeeded. + * \retval Other return code Operation failed with an error code. + */ +int32_t tfm_ns_mailbox_hal_notify_peer(void); + +/** + * \brief Enter critical section of NSPE mailbox. + * + * \note The implementation depends on platform specific hardware and use case. + */ +void tfm_ns_mailbox_hal_enter_critical(void); + +/** + * \brief Exit critical section of NSPE mailbox. + * + * \note The implementation depends on platform specific hardware and use case. + */ +void tfm_ns_mailbox_hal_exit_critical(void); + +/** + * \brief Enter critical section of NSPE mailbox in IRQ handler. + * + * \note The implementation depends on platform specific hardware and use case. + */ +void tfm_ns_mailbox_hal_enter_critical_isr(void); + +/** + * \brief Enter critical section of NSPE mailbox in IRQ handler + * + * \note The implementation depends on platform specific hardware and use case. + */ +void tfm_ns_mailbox_hal_exit_critical_isr(void); + +#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL +/** + * \brief Performs platform and NS OS specific waiting mechanism to wait for + * the reply of the specified mailbox message to be returned from SPE. + * + * \note This function is implemented by platform and NS OS specific waiting + * mechanism accroding to use scenario. + * + * \param[in] handle The handle of mailbox message. + */ +void tfm_ns_mailbox_hal_wait_reply(mailbox_msg_handle_t handle); +#endif + +#ifdef TFM_MULTI_CORE_TEST +/** + * \brief Initialize the statistics module in TF-M NSPE mailbox. + * + * \note This function is only available when multi-core tests are enabled. + */ +void tfm_ns_mailbox_tx_stats_init(void); + +/** + * \brief Calculate the average number of used NS mailbox queue slots each time + * NS task requires a queue slot to submit mailbox message, which is + * recorded in NS mailbox statisitics module. + * + * \note This function is only available when multi-core tests are enabled. + * + * \param[in] stats_res The buffer to be written with + * \ref ns_mailbox_stats_res_t. + * + * \return Return the calculation result. + */ +void tfm_ns_mailbox_stats_avg_slot(struct ns_mailbox_stats_res_t *stats_res); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_NS_MAILBOX_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_ns_svc.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_ns_svc.h new file mode 100644 index 0000000..def0c2f --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_ns_svc.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2017-2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include "cmsis_compiler.h" + +#ifndef __TFM_NS_SVC_H__ +#define __TFM_NS_SVC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Include all the SVC handler headers + */ +#include "tfm_nspm_svc_handler.h" + +/** + * \brief Macro to encode an svc instruction + * + */ +#define SVC(code) __ASM volatile("svc %0" : : "I" (code)) + +/** + * \def LIST_SVC_NSPM + * + * \brief This is an X macro which lists + * the SVC interface exposed by TF-M + * for the NS OS. + * + */ +#define LIST_SVC_NSPM \ + X(SVC_TFM_NSPM_REGISTER_CLIENT_ID, tfm_nspm_svc_register_client_id) \ + +/** + * \brief Numbers associated to each SVC available + * + * \details Start from 1 as 0 is reserved by RTX + */ +enum tfm_svc_num { + SVC_INVALID = 0, + +#define X(SVC_ENUM, SVC_HANDLER) SVC_ENUM, + + /* SVC API for Services */ +#ifdef TFM_NS_CLIENT_IDENTIFICATION + LIST_SVC_NSPM +#endif + +#undef X + + /* add all the new entries above this line */ + SVC_TFM_MAX, +}; + +/* number of user SVC functions */ +#define USER_SVC_COUNT ((uint32_t)SVC_TFM_MAX - 1) + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_NS_SVC_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_platform_api.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_platform_api.h new file mode 100644 index 0000000..8c9b0db --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_platform_api.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __TFM_PLATFORM_API__ +#define __TFM_PLATFORM_API__ + +#include +#include +#include +#include "tfm_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief TFM secure partition platform API version + */ +#define TFM_PLATFORM_API_VERSION_MAJOR (0) +#define TFM_PLATFORM_API_VERSION_MINOR (3) + +#define TFM_PLATFORM_API_ID_NV_READ (1010) +#define TFM_PLATFORM_API_ID_NV_INCREMENT (1011) + +/*! + * \enum tfm_platform_err_t + * + * \brief Platform service error types + * + */ +enum tfm_platform_err_t { + TFM_PLATFORM_ERR_SUCCESS = 0, + TFM_PLATFORM_ERR_SYSTEM_ERROR, + TFM_PLATFORM_ERR_INVALID_PARAM, + TFM_PLATFORM_ERR_NOT_SUPPORTED, + + /* Following entry is only to ensure the error code of int size */ + TFM_PLATFORM_ERR_FORCE_INT_SIZE = INT_MAX +}; + +typedef int32_t tfm_platform_ioctl_req_t; + +/*! + * \brief Resets the system. + * + * \return Returns values as specified by the \ref tfm_platform_err_t + */ +enum tfm_platform_err_t tfm_platform_system_reset(void); + +/*! + * \brief Performs a platform-specific service + * + * \param[in] request Request identifier (valid values vary + * based on the platform) + * \param[in] input Input buffer to the requested service (or NULL) + * \param[in,out] output Output buffer to the requested service (or NULL) + * + * \return Returns values as specified by the \ref tfm_platform_err_t + */ +enum tfm_platform_err_t tfm_platform_ioctl(tfm_platform_ioctl_req_t request, + psa_invec *input, + psa_outvec *output); + +/*! + * \brief Increments the given non-volatile (NV) counter by one + * + * \param[in] counter_id NV counter ID. + * + * \return TFM_PLATFORM_ERR_SUCCESS if the value is read correctly. Otherwise, + * it returns TFM_PLATFORM_ERR_SYSTEM_ERROR. + */ +enum tfm_platform_err_t +tfm_platform_nv_counter_increment(uint32_t counter_id); + +/*! + * \brief Reads the given non-volatile (NV) counter + * + * \param[in] counter_id NV counter ID. + * \param[in] size Size of the buffer to store NV counter value + * in bytes. + * \param[out] val Pointer to store the current NV counter value. + * + * \return TFM_PLATFORM_ERR_SUCCESS if the value is read correctly. Otherwise, + * it returns TFM_PLATFORM_ERR_SYSTEM_ERROR. + */ +enum tfm_platform_err_t +tfm_platform_nv_counter_read(uint32_t counter_id, + uint32_t size, uint8_t *val); + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_PLATFORM_API__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_veneers.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_veneers.h new file mode 100644 index 0000000..d2d9207 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_veneers.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ + +#ifndef __TFM_VENEERS_H__ +#define __TFM_VENEERS_H__ + +#include "tfm_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef TFM_PARTITION_SECURE_STORAGE +/******** TFM_SP_STORAGE ********/ +psa_status_t tfm_tfm_sst_set_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_sst_get_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_sst_get_info_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_sst_remove_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_sst_get_support_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_SECURE_STORAGE */ + +#ifdef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE +/******** TFM_SP_ITS ********/ +psa_status_t tfm_tfm_its_set_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_its_get_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_its_get_info_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_its_remove_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */ + +#ifdef TFM_PARTITION_AUDIT_LOG +/******** TFM_SP_AUDIT_LOG ********/ +psa_status_t tfm_audit_core_retrieve_record_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_audit_core_add_record_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_audit_core_get_info_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_audit_core_get_record_info_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_audit_core_delete_record_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_AUDIT_LOG */ + +#ifdef TFM_PARTITION_CRYPTO +/******** TFM_SP_CRYPTO ********/ +psa_status_t tfm_tfm_crypto_get_key_attributes_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_open_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_close_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_reset_key_attributes_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_import_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_destroy_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_export_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_export_public_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_copy_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_hash_compute_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_hash_compare_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_hash_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_hash_update_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_hash_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_hash_verify_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_hash_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_hash_clone_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_mac_compute_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_mac_verify_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_mac_sign_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_mac_verify_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_mac_update_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_mac_sign_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_mac_verify_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_mac_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_encrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_decrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_encrypt_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_decrypt_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_generate_iv_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_set_iv_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_update_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_encrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_decrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_encrypt_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_decrypt_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_generate_nonce_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_set_nonce_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_set_lengths_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_update_ad_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_update_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_verify_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_sign_hash_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_verify_hash_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_asymmetric_encrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_asymmetric_decrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_get_capacity_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_set_capacity_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_input_bytes_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_input_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_key_agreement_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_output_bytes_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_output_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_raw_key_agreement_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_generate_random_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_generate_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_CRYPTO */ + +#ifdef TFM_PARTITION_PLATFORM +/******** TFM_SP_PLATFORM ********/ +psa_status_t tfm_platform_sp_system_reset_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_platform_sp_ioctl_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_platform_sp_nv_counter_read_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_platform_sp_nv_counter_increment_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_PLATFORM */ + +#ifdef TFM_PARTITION_INITIAL_ATTESTATION +/******** TFM_SP_INITIAL_ATTESTATION ********/ +psa_status_t tfm_initial_attest_get_token_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_initial_attest_get_token_size_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_initial_attest_get_public_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_INITIAL_ATTESTATION */ + +#ifdef TFM_PARTITION_TEST_CORE +/******** TFM_SP_CORE_TEST ********/ +psa_status_t tfm_spm_core_test_sfn_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_spm_core_test_sfn_init_success_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_spm_core_test_sfn_direct_recursion_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_TEST_CORE */ + +#ifdef TFM_PARTITION_TEST_CORE +/******** TFM_SP_CORE_TEST_2 ********/ +psa_status_t tfm_spm_core_test_2_slave_service_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_spm_core_test_2_sfn_invert_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_spm_core_test_2_check_caller_client_id_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_spm_core_test_2_get_every_second_byte_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_spm_core_test_2_prepare_test_scenario_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_spm_core_test_2_execute_test_scenario_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_TEST_CORE */ + +#ifdef TFM_PARTITION_TEST_SECURE_SERVICES +/******** TFM_SP_SECURE_TEST_PARTITION ********/ +psa_status_t tfm_tfm_secure_client_service_sfn_run_tests_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ + +#ifdef TFM_PARTITION_TEST_CORE_IPC +/******** TFM_SP_IPC_SERVICE_TEST ********/ +#endif /* TFM_PARTITION_TEST_CORE_IPC */ + +#ifdef TFM_PARTITION_TEST_CORE_IPC +/******** TFM_SP_IPC_CLIENT_TEST ********/ +#endif /* TFM_PARTITION_TEST_CORE_IPC */ + +#ifdef TFM_ENABLE_IRQ_TEST +/******** TFM_IRQ_TEST_1 ********/ +psa_status_t tfm_spm_irq_test_1_prepare_test_scenario_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_spm_irq_test_1_execute_test_scenario_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_ENABLE_IRQ_TEST */ + +#ifdef TFM_PARTITION_TEST_SST +/******** TFM_SP_SST_TEST ********/ +psa_status_t tfm_tfm_sst_test_prepare_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_TEST_SST */ + +#ifdef TFM_PARTITION_TEST_SECURE_SERVICES +/******** TFM_SP_SECURE_CLIENT_2 ********/ +psa_status_t tfm_tfm_secure_client_2_call_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ + +#ifdef TFM_MULTI_CORE_TEST +/******** TFM_SP_MULTI_CORE_TEST ********/ +#endif /* TFM_MULTI_CORE_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_VENEERS_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_crypto_ipc_api.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_crypto_ipc_api.c new file mode 100644 index 0000000..70b3a0d --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_crypto_ipc_api.c @@ -0,0 +1,1875 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "tfm_crypto_defs.h" +#include "psa/crypto.h" +#include "tfm_ns_interface.h" +#include "psa_manifest/sid.h" +#include "psa/client.h" + +#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0])) + +#define PSA_CONNECT(service) \ + psa_handle_t ipc_handle; \ + ipc_handle = psa_connect(service##_SID, service##_VERSION); \ + if (!PSA_HANDLE_IS_VALID(ipc_handle)) { \ + return PSA_ERROR_GENERIC_ERROR; \ + } \ + +#define PSA_CLOSE() psa_close(ipc_handle) + +#define API_DISPATCH(sfn_name, sfn_id) \ + psa_call(ipc_handle, PSA_IPC_CALL, \ + in_vec, ARRAY_SIZE(in_vec), \ + out_vec, ARRAY_SIZE(out_vec)) + +#define API_DISPATCH_NO_OUTVEC(sfn_name, sfn_id) \ + psa_call(ipc_handle, PSA_IPC_CALL, \ + in_vec, ARRAY_SIZE(in_vec), \ + (psa_outvec *)NULL, 0) + +psa_status_t psa_crypto_init(void) +{ + /* Service init is performed during TFM boot up, + * so application level initialisation is empty + */ + return PSA_SUCCESS; +} + +psa_status_t psa_open_key(psa_key_id_t id, + psa_key_handle_t *handle) +{ +#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + const struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_OPEN_KEY_SID, + }; + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = &id, .len = sizeof(psa_key_id_t)}, + }; + psa_outvec out_vec[] = { + {.base = handle, .len = sizeof(psa_key_handle_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_open_key, + TFM_CRYPTO_OPEN_KEY); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ +} + +psa_status_t psa_close_key(psa_key_handle_t handle) +{ +#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + const struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_CLOSE_KEY_SID, + .key_handle = handle, + }; + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_close_key, + TFM_CRYPTO_CLOSE_KEY);; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ +} + +psa_status_t psa_import_key(const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + psa_key_handle_t *handle) +{ +#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_IMPORT_KEY_SID, + }; + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = attributes, .len = sizeof(psa_key_attributes_t)}, + {.base = data, .len = data_length} + }; + psa_outvec out_vec[] = { + {.base = handle, .len = sizeof(psa_key_handle_t)} + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_import_key, + TFM_CRYPTO_IMPORT_KEY); + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ +} + +psa_status_t psa_destroy_key(psa_key_handle_t handle) +{ +#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_DESTROY_KEY_SID, + .key_handle = handle, + }; + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_destroy_key, + TFM_CRYPTO_DESTROY_KEY); + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ +} + +psa_status_t psa_get_key_attributes(psa_key_handle_t handle, + psa_key_attributes_t *attributes) +{ +#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_GET_KEY_ATTRIBUTES_SID, + .key_handle = handle, + }; + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = attributes, .len = sizeof(psa_key_attributes_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_get_key_attributes, + TFM_CRYPTO_GET_KEY_ATTRIBUTES); + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ +} + +void psa_reset_key_attributes(psa_key_attributes_t *attributes) +{ +#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED + return; +#else + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_RESET_KEY_ATTRIBUTES_SID, + }; + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = attributes, .len = sizeof(psa_key_attributes_t)}, + }; + + psa_handle_t ipc_handle; + ipc_handle = psa_connect(TFM_CRYPTO_SID, TFM_CRYPTO_VERSION); + if (!PSA_HANDLE_IS_VALID(ipc_handle)) { + return; + } + + (void)API_DISPATCH(tfm_crypto_reset_key_attributes, + TFM_CRYPTO_RESET_KEY_ATTRIBUTES); + PSA_CLOSE(); + + return; +#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ +} + +psa_status_t psa_export_key(psa_key_handle_t handle, + uint8_t *data, + size_t data_size, + size_t *data_length) +{ +#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_EXPORT_KEY_SID, + .key_handle = handle, + }; + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = data, .len = data_size} + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_export_key, + TFM_CRYPTO_EXPORT_KEY); + + *data_length = out_vec[0].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ +} + +psa_status_t psa_export_public_key(psa_key_handle_t handle, + uint8_t *data, + size_t data_size, + size_t *data_length) +{ +#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_EXPORT_PUBLIC_KEY_SID, + .key_handle = handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = data, .len = data_size} + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_export_public_key, + TFM_CRYPTO_EXPORT_PUBLIC_KEY); + + *data_length = out_vec[0].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ +} + +psa_status_t psa_copy_key(psa_key_handle_t source_handle, + const psa_key_attributes_t *attributes, + psa_key_handle_t *target_handle) +{ +#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_COPY_KEY_SID, + .key_handle = source_handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = attributes, .len = sizeof(psa_key_attributes_t)}, + + }; + + psa_outvec out_vec[] = { + {.base = target_handle, .len = sizeof(psa_key_handle_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_copy_key, + TFM_CRYPTO_COPY_KEY); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ +} + +psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation, + unsigned char *iv, + size_t iv_size, + size_t *iv_length) +{ +#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_CIPHER_GENERATE_IV_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + {.base = iv, .len = iv_size}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_cipher_generate_iv, + TFM_CRYPTO_CIPHER_GENERATE_IV); + + *iv_length = out_vec[1].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ +} + +psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, + const unsigned char *iv, + size_t iv_length) +{ +#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_CIPHER_SET_IV_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = iv, .len = iv_length}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_cipher_set_iv, + TFM_CRYPTO_CIPHER_SET_IV); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ +} + +psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg) +{ +#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_CIPHER_ENCRYPT_SETUP_SID, + .key_handle = handle, + .alg = alg, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_cipher_encrypt_setup, + TFM_CRYPTO_CIPHER_ENCRYPT_SETUP); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ +} + +psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg) +{ +#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_CIPHER_DECRYPT_SETUP_SID, + .key_handle = handle, + .alg = alg, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_cipher_decrypt_setup, + TFM_CRYPTO_CIPHER_DECRYPT_SETUP); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ +} + +psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, + const uint8_t *input, + size_t input_length, + unsigned char *output, + size_t output_size, + size_t *output_length) +{ +#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_CIPHER_UPDATE_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = input, .len = input_length}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + {.base = output, .len = output_size} + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_cipher_update, + TFM_CRYPTO_CIPHER_UPDATE); + + *output_length = out_vec[1].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ +} + +psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation) +{ +#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_CIPHER_ABORT_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_cipher_abort, + TFM_CRYPTO_CIPHER_ABORT); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ +} + +psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ +#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_CIPHER_FINISH_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + {.base = output, .len = output_size}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_cipher_finish, + TFM_CRYPTO_CIPHER_FINISH); + + *output_length = out_vec[1].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ +} + +psa_status_t psa_hash_setup(psa_hash_operation_t *operation, + psa_algorithm_t alg) +{ +#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_HASH_SETUP_SID, + .alg = alg, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_hash_setup, + TFM_CRYPTO_HASH_SETUP); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_HASH_MODULE_DISABLED */ +} + +psa_status_t psa_hash_update(psa_hash_operation_t *operation, + const uint8_t *input, + size_t input_length) +{ +#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_HASH_UPDATE_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = input, .len = input_length}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_hash_update, + TFM_CRYPTO_HASH_UPDATE); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_HASH_MODULE_DISABLED */ +} + +psa_status_t psa_hash_finish(psa_hash_operation_t *operation, + uint8_t *hash, + size_t hash_size, + size_t *hash_length) +{ +#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_HASH_FINISH_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + {.base = hash, .len = hash_size}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_hash_finish, + TFM_CRYPTO_HASH_FINISH); + + *hash_length = out_vec[1].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_HASH_MODULE_DISABLED */ +} + +psa_status_t psa_hash_verify(psa_hash_operation_t *operation, + const uint8_t *hash, + size_t hash_length) +{ +#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_HASH_VERIFY_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = hash, .len = hash_length}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_hash_verify, + TFM_CRYPTO_HASH_VERIFY); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_HASH_MODULE_DISABLED */ +} + +psa_status_t psa_hash_abort(psa_hash_operation_t *operation) +{ +#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_HASH_ABORT_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_hash_abort, + TFM_CRYPTO_HASH_ABORT); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_HASH_MODULE_DISABLED */ +} + +psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation, + psa_hash_operation_t *target_operation) +{ +#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_HASH_CLONE_SID, + .op_handle = source_operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = target_operation, .len = sizeof(psa_hash_operation_t)}, + }; + + if (target_operation && (target_operation->handle != 0)) { + return PSA_ERROR_BAD_STATE; + } + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_hash_clone, + TFM_CRYPTO_HASH_CLONE); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_HASH_MODULE_DISABLED */ +} + +psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg) +{ +#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_MAC_SIGN_SETUP_SID, + .key_handle = handle, + .alg = alg, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_mac_sign_setup, + TFM_CRYPTO_MAC_SIGN_SETUP); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */ +} + +psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg) +{ +#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_MAC_VERIFY_SETUP_SID, + .key_handle = handle, + .alg = alg, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_mac_verify_setup, + TFM_CRYPTO_MAC_VERIFY_SETUP); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */ +} + +psa_status_t psa_mac_update(psa_mac_operation_t *operation, + const uint8_t *input, + size_t input_length) +{ +#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_MAC_UPDATE_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = input, .len = input_length}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_mac_update, + TFM_CRYPTO_MAC_UPDATE); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */ +} + +psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, + uint8_t *mac, + size_t mac_size, + size_t *mac_length) +{ +#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_MAC_SIGN_FINISH_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + {.base = mac, .len = mac_size}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_mac_sign_finish, + TFM_CRYPTO_MAC_SIGN_FINISH); + + *mac_length = out_vec[1].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */ +} + +psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation, + const uint8_t *mac, + size_t mac_length) +{ +#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_MAC_VERIFY_FINISH_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = mac, .len = mac_length}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_mac_verify_finish, + TFM_CRYPTO_MAC_VERIFY_FINISH); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */ +} + +psa_status_t psa_mac_abort(psa_mac_operation_t *operation) +{ +#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_MAC_ABORT_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_mac_abort, + TFM_CRYPTO_MAC_ABORT); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */ +} + +psa_status_t psa_aead_encrypt(psa_key_handle_t handle, + 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 *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length) +{ +#ifdef TFM_CRYPTO_AEAD_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_AEAD_ENCRYPT_SID, + .key_handle = handle, + .alg = alg, + .aead_in = {.nonce = {0}, .nonce_length = nonce_length} + }; + + /* Sanitize the optional input */ + if ((additional_data == NULL) && (additional_data_length != 0)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + size_t idx = 0; + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = plaintext, .len = plaintext_length}, + {.base = additional_data, .len = additional_data_length}, + }; + psa_outvec out_vec[] = { + {.base = ciphertext, .len = ciphertext_size}, + }; + + if (nonce_length > TFM_CRYPTO_MAX_NONCE_LENGTH) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (nonce != NULL) { + for (idx = 0; idx < nonce_length; idx++) { + iov.aead_in.nonce[idx] = nonce[idx]; + } + } + + PSA_CONNECT(TFM_CRYPTO); + + size_t in_len = ARRAY_SIZE(in_vec); + if (additional_data == NULL) { + in_len--; + } + status = psa_call(ipc_handle, PSA_IPC_CALL, in_vec, in_len, + out_vec, ARRAY_SIZE(out_vec)); + + *ciphertext_length = out_vec[0].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_AEAD_MODULE_DISABLED */ +} + +psa_status_t psa_aead_decrypt(psa_key_handle_t handle, + 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 *ciphertext, + size_t ciphertext_length, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length) +{ +#ifdef TFM_CRYPTO_AEAD_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_AEAD_DECRYPT_SID, + .key_handle = handle, + .alg = alg, + .aead_in = {.nonce = {0}, .nonce_length = nonce_length} + }; + + /* Sanitize the optional input */ + if ((additional_data == NULL) && (additional_data_length != 0)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + size_t idx = 0; + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = ciphertext, .len = ciphertext_length}, + {.base = additional_data, .len = additional_data_length}, + }; + psa_outvec out_vec[] = { + {.base = plaintext, .len = plaintext_size}, + }; + + if (nonce_length > TFM_CRYPTO_MAX_NONCE_LENGTH) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (nonce != NULL) { + for (idx = 0; idx < nonce_length; idx++) { + iov.aead_in.nonce[idx] = nonce[idx]; + } + } + + PSA_CONNECT(TFM_CRYPTO); + + size_t in_len = ARRAY_SIZE(in_vec); + if (additional_data == NULL) { + in_len--; + } + status = psa_call(ipc_handle, PSA_IPC_CALL, in_vec, in_len, + out_vec, ARRAY_SIZE(out_vec)); + + *plaintext_length = out_vec[0].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_AEAD_MODULE_DISABLED */ +} + +psa_status_t psa_asymmetric_sign(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length) +{ + return psa_sign_hash(handle, alg, hash, hash_length, signature, signature_size, signature_length); +} + +psa_status_t psa_sign_hash(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length) +{ +#ifdef TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_SIGN_HASH_SID, + .key_handle = handle, + .alg = alg, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = hash, .len = hash_length}, + }; + psa_outvec out_vec[] = { + {.base = signature, .len = signature_size}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_sign_hash, + TFM_CRYPTO_SIGN_HASH); + + *signature_length = out_vec[0].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED */ +} + +psa_status_t psa_asymmetric_verify(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length) +{ + return psa_verify_hash(handle, alg, hash, hash_length, signature, signature_length); +} + +psa_status_t psa_verify_hash(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length) +{ +#ifdef TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_VERIFY_HASH_SID, + .key_handle = handle, + .alg = alg + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = hash, .len = hash_length}, + {.base = signature, .len = signature_length} + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_verify_hash, + TFM_CRYPTO_VERIFY_HASH); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED */ +} + +psa_status_t psa_asymmetric_encrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ +#ifdef TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_ASYMMETRIC_ENCRYPT_SID, + .key_handle = handle, + .alg = alg + }; + + /* Sanitize the optional input */ + if ((salt == NULL) && (salt_length != 0)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = input, .len = input_length}, + {.base = salt, .len = salt_length} + }; + + psa_outvec out_vec[] = { + {.base = output, .len = output_size}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + size_t in_len = ARRAY_SIZE(in_vec); + if (salt == NULL) { + in_len--; + } + status = psa_call(ipc_handle, PSA_IPC_CALL, in_vec, in_len, + out_vec, ARRAY_SIZE(out_vec)); + + *output_length = out_vec[0].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED */ +} + +psa_status_t psa_asymmetric_decrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ +#ifdef TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_ASYMMETRIC_DECRYPT_SID, + .key_handle = handle, + .alg = alg + }; + + /* Sanitize the optional input */ + if ((salt == NULL) && (salt_length != 0)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = input, .len = input_length}, + {.base = salt, .len = salt_length} + }; + + psa_outvec out_vec[] = { + {.base = output, .len = output_size}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + size_t in_len = ARRAY_SIZE(in_vec); + if (salt == NULL) { + in_len--; + } + status = psa_call(ipc_handle, PSA_IPC_CALL, in_vec, in_len, + out_vec, ARRAY_SIZE(out_vec)); + + *output_length = out_vec[0].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED */ +} + +psa_status_t psa_key_derivation_get_capacity( + const psa_key_derivation_operation_t *operation, + size_t *capacity) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_GET_CAPACITY_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + + psa_outvec out_vec[] = { + {.base = capacity, .len = sizeof(size_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_key_derivation_get_capacity, + TFM_CRYPTO_KEY_DERIVATION_GET_CAPACITY); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_key_derivation_output_bytes( + psa_key_derivation_operation_t *operation, + uint8_t *output, + size_t output_length) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_OUTPUT_BYTES_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + + psa_outvec out_vec[] = { + {.base = output, .len = output_length}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_key_derivation_output_bytes, + TFM_CRYPTO_KEY_DERIVATION_OUTPUT_BYTES); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_key_derivation_input_key( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_handle_t handle) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_INPUT_KEY_SID, + .key_handle = handle, + .step = step, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_key_derivation_input_key, + TFM_CRYPTO_KEY_DERIVATION_INPUT_KEY); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_key_derivation_abort( + psa_key_derivation_operation_t *operation) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_ABORT_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_key_derivation_abort, + TFM_CRYPTO_KEY_DERIVATION_ABORT); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_key_derivation_key_agreement( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_handle_t private_key, + const uint8_t *peer_key, + size_t peer_key_length) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_KEY_AGREEMENT_SID, + .key_handle = private_key, + .step = step, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = peer_key, .len = peer_key_length}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_key_derivation_key_agreement, + TFM_CRYPTO_KEY_DERIVATION_KEY_AGREEMENT); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_generate_random(uint8_t *output, + size_t output_size) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_GENERATE_RANDOM_SID, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + + psa_outvec out_vec[] = { + {.base = output, .len = output_size}, + }; + + if (output_size == 0) { + return PSA_SUCCESS; + } + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_generate_random, + TFM_CRYPTO_GENERATE_RANDOM); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, + psa_key_handle_t *handle) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_GENERATE_KEY_SID, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = attributes, .len = sizeof(psa_key_attributes_t)}, + }; + + psa_outvec out_vec[] = { + {.base = handle, .len = sizeof(psa_key_handle_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_generate_key, + TFM_CRYPTO_GENERATE_KEY); + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes, + psa_key_type_t type, + const uint8_t *data, + size_t data_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_get_key_domain_parameters( + const psa_key_attributes_t *attributes, + uint8_t *data, + size_t data_size, + size_t *data_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_hash_compare(psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *hash, + const size_t hash_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_finish(psa_aead_operation_t *operation, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length, + uint8_t *tag, + size_t tag_size, + size_t *tag_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_verify(psa_aead_operation_t *operation, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length, + const uint8_t *tag, + size_t tag_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_abort(psa_aead_operation_t *operation) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_mac_compute(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *mac, + size_t mac_size, + size_t *mac_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_mac_verify(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *mac, + const size_t mac_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_cipher_encrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_cipher_decrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, + psa_key_handle_t private_key, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_RAW_KEY_AGREEMENT_SID, + .alg = alg, + .key_handle = private_key + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = peer_key, .len = peer_key_length}, + }; + + psa_outvec out_vec[] = { + {.base = output, .len = output_size}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_raw_key_agreement, + TFM_CRYPTO_RAW_KEY_AGREEMENT); + + *output_length = out_vec[0].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_key_derivation_setup(psa_key_derivation_operation_t *operation, + psa_algorithm_t alg) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_SETUP_SID, + .alg = alg, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_key_derivation_setup, + TFM_CRYPTO_KEY_DERIVATION_SETUP); + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_key_derivation_set_capacity( + psa_key_derivation_operation_t *operation, + size_t capacity) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_SET_CAPACITY_SID, + .capacity = capacity, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_key_derivation_set_capacity, + TFM_CRYPTO_KEY_DERIVATION_SET_CAPACITY); + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_key_derivation_input_bytes( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_INPUT_BYTES_SID, + .step = step, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = data, .len = data_length}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_key_derivation_input_bytes, + TFM_CRYPTO_KEY_DERIVATION_INPUT_BYTES); + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_key_derivation_output_key( + const psa_key_attributes_t *attributes, + psa_key_derivation_operation_t *operation, + psa_key_handle_t *handle) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_OUTPUT_KEY_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = attributes, .len = sizeof(psa_key_attributes_t)}, + }; + + psa_outvec out_vec[] = { + {.base = handle, .len = sizeof(psa_key_handle_t)} + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_key_derivation_output_key, + TFM_CRYPTO_KEY_DERIVATION_OUTPUT_KEY); + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_hash_compute(psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *hash, + size_t hash_size, + size_t *hash_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation, + uint8_t *nonce, + size_t nonce_size, + size_t *nonce_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation, + const uint8_t *nonce, + size_t nonce_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation, + size_t ad_length, + size_t plaintext_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_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 status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_initial_attestation_ipc_api.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_initial_attestation_ipc_api.c new file mode 100644 index 0000000..78f9dec --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_initial_attestation_ipc_api.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "psa/initial_attestation.h" +#include "tfm_ns_interface.h" +#include "psa/client.h" +#include "psa/crypto_types.h" +#include "psa_manifest/sid.h" + +#define IOVEC_LEN(x) (sizeof(x)/sizeof(x[0])) + +psa_status_t +psa_initial_attest_get_token(const uint8_t *auth_challenge, + size_t challenge_size, + uint8_t *token_buf, + size_t token_buf_size, + size_t *token_size) +{ + psa_handle_t handle = PSA_NULL_HANDLE; + psa_status_t status; + + psa_invec in_vec[] = { + {auth_challenge, challenge_size} + }; + psa_outvec out_vec[] = { + {token_buf, token_buf_size} + }; + + handle = psa_connect(TFM_ATTEST_GET_TOKEN_SID, + TFM_ATTEST_GET_TOKEN_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_HANDLE_TO_ERROR(handle); + } + + status = psa_call(handle, PSA_IPC_CALL, + in_vec, IOVEC_LEN(in_vec), + out_vec, IOVEC_LEN(out_vec)); + psa_close(handle); + + if (status == PSA_SUCCESS) { + *token_size = out_vec[0].len; + } + + return status; +} + +psa_status_t +psa_initial_attest_get_token_size(size_t challenge_size, + size_t *token_size) +{ + psa_handle_t handle = PSA_NULL_HANDLE; + psa_status_t status; + psa_invec in_vec[] = { + {&challenge_size, sizeof(challenge_size)} + }; + psa_outvec out_vec[] = { + {token_size, sizeof(size_t)} + }; + + handle = psa_connect(TFM_ATTEST_GET_TOKEN_SIZE_SID, + TFM_ATTEST_GET_TOKEN_SIZE_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_HANDLE_TO_ERROR(handle); + } + + status = psa_call(handle, PSA_IPC_CALL, + in_vec, IOVEC_LEN(in_vec), + out_vec, IOVEC_LEN(out_vec)); + psa_close(handle); + + return status; +} + +psa_status_t +tfm_initial_attest_get_public_key(uint8_t *public_key, + size_t public_key_buf_size, + size_t *public_key_len, + psa_ecc_curve_t *elliptic_curve_type) +{ + psa_handle_t handle = PSA_NULL_HANDLE; + psa_status_t status; + + psa_outvec out_vec[] = { + {.base = public_key, .len = public_key_buf_size}, + {.base = elliptic_curve_type, .len = sizeof(*elliptic_curve_type)}, + {.base = public_key_len, .len = sizeof(*public_key_len)} + }; + + handle = psa_connect(TFM_ATTEST_GET_PUBLIC_KEY_SID, + TFM_ATTEST_GET_PUBLIC_KEY_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_HANDLE_TO_ERROR(handle); + } + + status = psa_call(handle, PSA_IPC_CALL, + NULL, 0, + out_vec, IOVEC_LEN(out_vec)); + psa_close(handle); + + return status; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_its_ipc_api.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_its_ipc_api.c new file mode 100644 index 0000000..9326f7b --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_its_ipc_api.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "psa/internal_trusted_storage.h" +#include "tfm_api.h" + +#include "psa/client.h" +#include "psa_manifest/sid.h" + +#define IOVEC_LEN(x) (sizeof(x)/sizeof(x[0])) + +psa_status_t psa_its_set(psa_storage_uid_t uid, + size_t data_length, + const void *p_data, + psa_storage_create_flags_t create_flags) +{ + psa_status_t status; + psa_handle_t handle; + + psa_invec in_vec[] = { + { .base = &uid, .len = sizeof(uid) }, + { .base = p_data, .len = data_length }, + { .base = &create_flags, .len = sizeof(create_flags) } + }; + + handle = psa_connect(TFM_ITS_SET_SID, TFM_ITS_SET_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_ERROR_GENERIC_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), NULL, 0); + + psa_close(handle); + + if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + return status; +} + +psa_status_t psa_its_get(psa_storage_uid_t uid, + size_t data_offset, + size_t data_size, + void *p_data, + size_t *p_data_length) +{ + psa_status_t status; + psa_handle_t handle; + + psa_invec in_vec[] = { + { .base = &uid, .len = sizeof(uid) }, + { .base = &data_offset, .len = sizeof(data_offset) } + }; + + psa_outvec out_vec[] = { + { .base = p_data, .len = data_size } + }; + + if (p_data_length == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + handle = psa_connect(TFM_ITS_GET_SID, TFM_ITS_GET_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_ERROR_GENERIC_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), out_vec, + IOVEC_LEN(out_vec)); + + psa_close(handle); + + if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + *p_data_length = out_vec[0].len; + + return status; +} + +psa_status_t psa_its_get_info(psa_storage_uid_t uid, + struct psa_storage_info_t *p_info) +{ + psa_status_t status; + psa_handle_t handle; + + psa_invec in_vec[] = { + { .base = &uid, .len = sizeof(uid) } + }; + + psa_outvec out_vec[] = { + { .base = p_info, .len = sizeof(*p_info) } + }; + + handle = psa_connect(TFM_ITS_GET_INFO_SID, TFM_ITS_GET_INFO_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_ERROR_GENERIC_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), out_vec, + IOVEC_LEN(out_vec)); + + psa_close(handle); + + if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + return status; +} + +psa_status_t psa_its_remove(psa_storage_uid_t uid) +{ + psa_status_t status; + psa_handle_t handle; + + psa_invec in_vec[] = { + { .base = &uid, .len = sizeof(uid) } + }; + + handle = psa_connect(TFM_ITS_REMOVE_SID, TFM_ITS_REMOVE_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_ERROR_GENERIC_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), NULL, 0); + + psa_close(handle); + + return status; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_platform_ipc_api.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_platform_ipc_api.c new file mode 100644 index 0000000..c43fe8b --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_platform_ipc_api.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include "tfm_platform_api.h" +#include "psa_manifest/sid.h" + +enum tfm_platform_err_t tfm_platform_system_reset(void) +{ + psa_status_t status = PSA_ERROR_CONNECTION_REFUSED; + psa_handle_t handle = PSA_NULL_HANDLE; + + handle = psa_connect(TFM_SP_PLATFORM_SYSTEM_RESET_SID, + TFM_SP_PLATFORM_SYSTEM_RESET_VERSION); + if (handle <= 0) { + return TFM_PLATFORM_ERR_SYSTEM_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, + NULL, 0, NULL, 0); + psa_close(handle); + + if (status < PSA_SUCCESS) { + return TFM_PLATFORM_ERR_SYSTEM_ERROR; + } else { + return (enum tfm_platform_err_t) status; + } + +} + +enum tfm_platform_err_t +tfm_platform_ioctl(tfm_platform_ioctl_req_t request, + psa_invec *input, psa_outvec *output) +{ + tfm_platform_ioctl_req_t req = request; + struct psa_invec in_vec[2] = { {0} }; + size_t inlen, outlen; + psa_status_t status = PSA_ERROR_CONNECTION_REFUSED; + psa_handle_t handle = PSA_NULL_HANDLE; + + in_vec[0].base = &req; + in_vec[0].len = sizeof(req); + if (input != NULL) { + in_vec[1].base = input->base; + in_vec[1].len = input->len; + inlen = 2; + } else { + inlen = 1; + } + + if (output != NULL) { + outlen = 1; + } else { + outlen = 0; + } + + handle = psa_connect(TFM_SP_PLATFORM_IOCTL_SID, + TFM_SP_PLATFORM_IOCTL_VERSION); + if (handle <= 0) { + return TFM_PLATFORM_ERR_SYSTEM_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, + in_vec, inlen, + output, outlen); + psa_close(handle); + + if (status < PSA_SUCCESS) { + return TFM_PLATFORM_ERR_SYSTEM_ERROR; + } else { + return (enum tfm_platform_err_t) status; + } +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_sst_ipc_api.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_sst_ipc_api.c new file mode 100644 index 0000000..4130428 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_sst_ipc_api.c @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2017-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "psa/protected_storage.h" + +#include "tfm_ns_interface.h" +#include "psa_manifest/sid.h" + +#define IOVEC_LEN(x) (uint32_t)(sizeof(x)/sizeof(x[0])) + +psa_status_t psa_ps_set(psa_storage_uid_t uid, + size_t data_length, + const void *p_data, + psa_storage_create_flags_t create_flags) +{ + psa_status_t status; + psa_handle_t handle; + + psa_invec in_vec[] = { + { .base = &uid, .len = sizeof(uid) }, + { .base = p_data, .len = data_length }, + { .base = &create_flags, .len = sizeof(create_flags) } + }; + + handle = psa_connect(TFM_SST_SET_SID, TFM_SST_SET_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_ERROR_GENERIC_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), + NULL, 0); + + psa_close(handle); + + /* A parameter with a buffer pointer pointer that has data length longer + * than maximum permitted is treated as a secure violation. + * TF-M framework rejects the request with TFM_ERROR_INVALID_PARAMETER. + */ + if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + return status; +} + +psa_status_t psa_ps_get(psa_storage_uid_t uid, + size_t data_offset, + size_t data_size, + void *p_data, + size_t *p_data_length) +{ + psa_status_t status; + psa_handle_t handle; + + psa_invec in_vec[] = { + { .base = &uid, .len = sizeof(uid) }, + { .base = &data_offset, .len = sizeof(data_offset) } + }; + + psa_outvec out_vec[] = { + { .base = p_data, .len = data_size } + }; + + if (p_data_length == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + handle = psa_connect(TFM_SST_GET_SID, TFM_SST_GET_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_ERROR_GENERIC_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), out_vec, + IOVEC_LEN(out_vec)); + + psa_close(handle); + + *p_data_length = out_vec[0].len; + + return status; +} + +psa_status_t psa_ps_get_info(psa_storage_uid_t uid, + struct psa_storage_info_t *p_info) +{ + psa_status_t status; + psa_handle_t handle; + + psa_invec in_vec[] = { + { .base = &uid, .len = sizeof(uid) } + }; + + psa_outvec out_vec[] = { + { .base = p_info, .len = sizeof(*p_info) } + }; + + handle = psa_connect(TFM_SST_GET_INFO_SID, TFM_SST_GET_INFO_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_ERROR_GENERIC_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), out_vec, + IOVEC_LEN(out_vec)); + + psa_close(handle); + + return status; +} + +psa_status_t psa_ps_remove(psa_storage_uid_t uid) +{ + psa_status_t status; + psa_handle_t handle; + + psa_invec in_vec[] = { + { .base = &uid, .len = sizeof(uid) } + }; + + + handle = psa_connect(TFM_SST_REMOVE_SID, TFM_SST_REMOVE_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_ERROR_GENERIC_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), + NULL, 0); + + psa_close(handle); + + return status; +} + +psa_status_t psa_ps_create(psa_storage_uid_t uid, size_t size, + psa_storage_create_flags_t create_flags) +{ + (void)uid; + (void)size; + (void)create_flags; + + return PSA_ERROR_NOT_SUPPORTED; +} + +psa_status_t psa_ps_set_extended(psa_storage_uid_t uid, size_t data_offset, + size_t data_length, const void *p_data) +{ + (void)uid; + (void)data_offset; + (void)data_length; + (void)p_data; + + return PSA_ERROR_NOT_SUPPORTED; +} + +uint32_t psa_ps_get_support(void) +{ + /* Initialise support_flags to a sensible default, to avoid returning an + * uninitialised value in case the secure function fails. + */ + uint32_t support_flags = 0; + psa_handle_t handle; + + psa_outvec out_vec[] = { + { .base = &support_flags, .len = sizeof(support_flags) } + }; + + /* The PSA API does not return an error, so any error from TF-M is + * ignored. + */ + handle = psa_connect(TFM_SST_GET_SUPPORT_SID, TFM_SST_GET_SUPPORT_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return support_flags; + } + + (void)psa_call(handle, PSA_IPC_CALL, NULL, 0, out_vec, IOVEC_LEN(out_vec)); + + psa_close(handle); + + return support_flags; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/platform_multicore.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/platform_multicore.c new file mode 100644 index 0000000..e860ae0 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/platform_multicore.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2019 Arm Limited. All rights reserved. + * Copyright (c) 2019 Cypress Semiconductor Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "cmsis_compiler.h" + +#include "platform_multicore.h" +#include "tfm_multi_core_api.h" +#include "tfm_ns_mailbox.h" + +#include "cy_ipc_drv.h" +#include "cy_sysint.h" +#if CY_SYSTEM_CPU_CM0P +#include "spe_ipc_config.h" +#else +#include "ns_ipc_config.h" +#endif + +int platform_mailbox_fetch_msg_ptr(void **msg_ptr) +{ + cy_en_ipcdrv_status_t status; + + if (!msg_ptr) { + return PLATFORM_MAILBOX_INVAL_PARAMS; + } + + status = Cy_IPC_Drv_ReadMsgPtr(Cy_IPC_Drv_GetIpcBaseAddress(IPC_RX_CHAN), + msg_ptr); + if (status != CY_IPC_DRV_SUCCESS) { + return PLATFORM_MAILBOX_RX_ERROR; + } + + Cy_IPC_Drv_ReleaseNotify(Cy_IPC_Drv_GetIpcBaseAddress(IPC_RX_CHAN), + IPC_RX_RELEASE_MASK); + return PLATFORM_MAILBOX_SUCCESS; +} + +int platform_mailbox_fetch_msg_data(uint32_t *data_ptr) +{ + cy_en_ipcdrv_status_t status; + + if (!data_ptr) { + return PLATFORM_MAILBOX_INVAL_PARAMS; + } + + status = Cy_IPC_Drv_ReadMsgWord(Cy_IPC_Drv_GetIpcBaseAddress(IPC_RX_CHAN), + data_ptr); + if (status != CY_IPC_DRV_SUCCESS) { + return PLATFORM_MAILBOX_RX_ERROR; + } + + Cy_IPC_Drv_ReleaseNotify(Cy_IPC_Drv_GetIpcBaseAddress(IPC_RX_CHAN), + IPC_RX_RELEASE_MASK); + return PLATFORM_MAILBOX_SUCCESS; +} + +int platform_mailbox_send_msg_ptr(const void *msg_ptr) +{ + cy_en_ipcdrv_status_t status; + + if (!msg_ptr) + return PLATFORM_MAILBOX_INVAL_PARAMS; + + status = Cy_IPC_Drv_SendMsgPtr(Cy_IPC_Drv_GetIpcBaseAddress(IPC_TX_CHAN), + IPC_TX_NOTIFY_MASK, msg_ptr); + if (status != CY_IPC_DRV_SUCCESS) { + return PLATFORM_MAILBOX_TX_ERROR; + } + + return PLATFORM_MAILBOX_SUCCESS; +} + +int platform_mailbox_send_msg_data(uint32_t data) +{ + cy_en_ipcdrv_status_t status; + + status = Cy_IPC_Drv_SendMsgWord(Cy_IPC_Drv_GetIpcBaseAddress(IPC_TX_CHAN), + IPC_TX_NOTIFY_MASK, data); + if (status != CY_IPC_DRV_SUCCESS) { + return PLATFORM_MAILBOX_TX_ERROR; + } + + return PLATFORM_MAILBOX_SUCCESS; +} + +void platform_mailbox_wait_for_notify(void) +{ + uint32_t status; + + while (1) { + status = Cy_IPC_Drv_GetInterruptStatusMasked( + Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT)); + status >>= CY_IPC_NOTIFY_SHIFT; + if (status & IPC_RX_INT_MASK) { + break; + } + } + + Cy_IPC_Drv_ClearInterrupt(Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT), + 0, IPC_RX_INT_MASK); +} + +int platform_ns_ipc_init(void) +{ + Cy_IPC_Drv_SetInterruptMask(Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT), + 0, IPC_RX_INT_MASK); + return PLATFORM_MAILBOX_SUCCESS; +} + +int32_t tfm_platform_ns_wait_for_s_cpu_ready(void) +{ + uint32_t data = 0; + + if (platform_ns_ipc_init() != PLATFORM_MAILBOX_SUCCESS) { + return PLATFORM_MAILBOX_INVAL_PARAMS; + } + while(data != IPC_SYNC_MAGIC) + { + platform_mailbox_wait_for_notify(); + platform_mailbox_fetch_msg_data(&data); + } + + if (platform_mailbox_send_msg_data(~IPC_SYNC_MAGIC) != + PLATFORM_MAILBOX_SUCCESS) { + return PLATFORM_MAILBOX_RX_ERROR; + } + return PLATFORM_MAILBOX_SUCCESS; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/platform_ns_mailbox.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/platform_ns_mailbox.c new file mode 100644 index 0000000..af08ac1 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/platform_ns_mailbox.c @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * Copyright (c) 2019, Cypress Semiconductor Corporation. All rights reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* -------------------------------------- Includes ----------------------------------- */ +#include +#include + +#include "cmsis_compiler.h" + +#include "cy_ipc_drv.h" +#include "cy_sysint.h" +#include "cy_ipc_sema.h" + +#include "ns_ipc_config.h" +#include "tfm_ns_mailbox.h" +#include "platform_multicore.h" +#include "cmsis_os2.h" + +static uint8_t saved_irq_state = 1; + +/* -------------------------------------- HAL API ------------------------------------ */ + +static void mailbox_ipc_init(void) +{ + Cy_IPC_Drv_SetInterruptMask(Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT), + 0, IPC_RX_INT_MASK); +} + +static void mailbox_ipc_config(void) +{ + NVIC_SetPriority(PSA_CLIENT_REPLY_NVIC_IRQn, PSA_CLIENT_REPLY_IRQ_PRIORITY); + + NVIC_EnableIRQ(PSA_CLIENT_REPLY_NVIC_IRQn); +} + +int32_t tfm_ns_mailbox_hal_notify_peer(void) +{ + cy_en_ipcdrv_status_t status; + + status = Cy_IPC_Drv_SendMsgWord(Cy_IPC_Drv_GetIpcBaseAddress(IPC_TX_CHAN), + IPC_TX_NOTIFY_MASK, + PSA_CLIENT_CALL_REQ_MAGIC); + + if (status == CY_IPC_DRV_SUCCESS) { + return MAILBOX_SUCCESS; + } else { + return MAILBOX_CHAN_BUSY; + } +} + +static int32_t mailbox_sema_init(void) +{ + /* semaphore data */ + static uint32_t tfm_sema __attribute__((section("TFM_SHARED_DATA"))); + + if (Cy_IPC_Sema_Init(PLATFORM_MAILBOX_IPC_CHAN_SEMA, + sizeof(tfm_sema) * CHAR_BIT, + &tfm_sema) != CY_IPC_SEMA_SUCCESS) { + return PLATFORM_MAILBOX_INIT_ERROR; + } + return PLATFORM_MAILBOX_SUCCESS; +} + +int32_t tfm_ns_mailbox_hal_init(struct ns_mailbox_queue_t *queue) +{ + uint32_t stage; + + if (!queue) { + return MAILBOX_INVAL_PARAMS; + } + + /* Init semaphores used for critical sections */ + if (mailbox_sema_init() != PLATFORM_MAILBOX_SUCCESS) + return MAILBOX_INIT_ERROR; + + /* + * FIXME + * Further verification of mailbox queue address may be required according + * to diverse NSPE implementations. + */ + + mailbox_ipc_init(); + + /* + * Wait until SPE mailbox library is ready to receive NSPE mailbox queue + * address. + */ + while (1) { + platform_mailbox_wait_for_notify(); + + platform_mailbox_fetch_msg_data(&stage); + if (stage == NS_MAILBOX_INIT_ENABLE) { + break; + } + } + + /* Send out the address */ + platform_mailbox_send_msg_ptr(queue); + + /* Wait until SPE mailbox service is ready */ + while (1) { + platform_mailbox_wait_for_notify(); + + platform_mailbox_fetch_msg_data(&stage); + if (stage == S_MAILBOX_READY) { + break; + } + } + + mailbox_ipc_config(); + + return MAILBOX_SUCCESS; +} + +const void *tfm_ns_mailbox_get_task_handle(void) +{ +#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL + return osThreadGetId(); +#else + return NULL; +#endif +} + +void tfm_ns_mailbox_hal_wait_reply(mailbox_msg_handle_t handle) +{ + osThreadFlagsWait(handle, osFlagsWaitAll, osWaitForever); +} + +static cy_en_ipcsema_status_t mailbox_raw_spin_lock(uint32_t ipc_channel, + uint32_t sema_num) +{ + uint32_t semaIndex; + uint32_t semaMask; + cy_stc_ipc_sema_t *semaStruct; + cy_en_ipcdrv_status_t acqStatus; + cy_en_ipcsema_status_t ret = CY_IPC_SEMA_BAD_PARAM; + bool is_lock = false; + IPC_STRUCT_Type *semaIpcStruct; + + /* Get IPC register structure */ + semaIpcStruct = Cy_IPC_Drv_GetIpcBaseAddress(ipc_channel); + /* Get pointer to structure */ + semaStruct = (cy_stc_ipc_sema_t *)Cy_IPC_Drv_ReadDataValue(semaIpcStruct); + + if (sema_num < semaStruct->maxSema) { + semaIndex = sema_num / CY_IPC_SEMA_PER_WORD; + semaMask = (uint32_t)(1ul << (sema_num - \ + (semaIndex * CY_IPC_SEMA_PER_WORD))); + + while (!is_lock) { + /* Check to make sure the IPC channel is released + If so, check if specific channel can be locked. */ + do { + acqStatus = Cy_IPC_Drv_LockAcquire(semaIpcStruct); + } while (acqStatus != CY_IPC_DRV_SUCCESS); + + if ((semaStruct->arrayPtr[semaIndex] & semaMask) == 0ul) { + semaStruct->arrayPtr[semaIndex] |= semaMask; + is_lock = true; + } + + /* Release, but do not trigger a release event */ + (void)Cy_IPC_Drv_LockRelease(semaIpcStruct, + CY_IPC_NO_NOTIFICATION); + + if (!is_lock) { + /* + * The secure core is occupying this lock. Insert a small delay + * to give the secure core a chance to acquire the IPC channel + * and release the lock. + * Otherwise, the secure core may not be able to release the + * lock if non-secure core has higher CPU frequency. It will + * generate a deadlock. + * This delay won't harm performance too much since non-secure + * core has to busy wait here anyway. + * Alternatively, non-secure core can wait for release + * notification event from secure core. However, it is more + * complex and requires more code and more modifications. + */ + volatile uint32_t count = 1000; + while(count > 0) { + count--; + } + Cy_IPC_Sema_Status(sema_num); + } + } + + ret = CY_IPC_SEMA_SUCCESS; + } + + return ret; +} + +static cy_en_ipcsema_status_t mailbox_raw_spin_unlock(uint32_t ipc_channel, + uint32_t sema_num) +{ + uint32_t semaIndex; + uint32_t semaMask; + cy_stc_ipc_sema_t *semaStruct; + cy_en_ipcdrv_status_t acqStatus; + cy_en_ipcsema_status_t ret = CY_IPC_SEMA_BAD_PARAM; + bool is_unlock = false; + IPC_STRUCT_Type *semaIpcStruct; + + /* Get IPC register structure */ + semaIpcStruct = Cy_IPC_Drv_GetIpcBaseAddress(ipc_channel); + /* Get pointer to structure */ + semaStruct = (cy_stc_ipc_sema_t *)Cy_IPC_Drv_ReadDataValue(semaIpcStruct); + + if (sema_num < semaStruct->maxSema) { + semaIndex = sema_num / CY_IPC_SEMA_PER_WORD; + semaMask = (uint32_t)(1ul << (sema_num - \ + (semaIndex * CY_IPC_SEMA_PER_WORD))); + + while (!is_unlock) { + /* Check to make sure the IPC channel is released + If so, check if specific channel can be locked. */ + do { + acqStatus = Cy_IPC_Drv_LockAcquire(semaIpcStruct); + } while (acqStatus != CY_IPC_DRV_SUCCESS); + + if ((semaStruct->arrayPtr[semaIndex] & semaMask) != 0ul) { + semaStruct->arrayPtr[semaIndex] &= ~semaMask; + is_unlock = true; + } + + /* Release, but do not trigger a release event */ + (void)Cy_IPC_Drv_LockRelease(semaIpcStruct, + CY_IPC_NO_NOTIFICATION); + } + + ret = CY_IPC_SEMA_SUCCESS; + } + + return ret; +} + +void tfm_ns_mailbox_hal_enter_critical(void) +{ + saved_irq_state = Cy_SysLib_EnterCriticalSection(); + + mailbox_raw_spin_lock(CY_IPC_CHAN_SEMA, MAILBOX_SEMAPHORE_NUM); +} + +void tfm_ns_mailbox_hal_exit_critical(void) +{ + mailbox_raw_spin_unlock(CY_IPC_CHAN_SEMA, MAILBOX_SEMAPHORE_NUM); + + Cy_SysLib_ExitCriticalSection(saved_irq_state); +} + +void tfm_ns_mailbox_hal_enter_critical_isr(void) +{ + mailbox_raw_spin_lock(CY_IPC_CHAN_SEMA, MAILBOX_SEMAPHORE_NUM); +} + +void tfm_ns_mailbox_hal_exit_critical_isr(void) +{ + mailbox_raw_spin_unlock(CY_IPC_CHAN_SEMA, MAILBOX_SEMAPHORE_NUM); +} + +static bool mailbox_clear_intr(void) +{ + uint32_t status; + + status = Cy_IPC_Drv_GetInterruptStatusMasked( + Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT)); + status >>= CY_IPC_NOTIFY_SHIFT; + if ((status & IPC_RX_INT_MASK) == 0) { + return false; + } + + Cy_IPC_Drv_ClearInterrupt(Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT), + 0, IPC_RX_INT_MASK); + return true; +} + +void cpuss_interrupts_ipc_5_IRQHandler(void) +{ + uint32_t magic; + mailbox_msg_handle_t handle; + osThreadId_t task_handle; + + if (!mailbox_clear_intr()) + return; + + platform_mailbox_fetch_msg_data(&magic); + if (magic == PSA_CLIENT_CALL_REPLY_MAGIC) { + /* Handle all the pending replies */ + while (1) { + handle = tfm_ns_mailbox_fetch_reply_msg_isr(); + if (handle == MAILBOX_MSG_NULL_HANDLE) { + break; + } + + task_handle = (osThreadId_t)tfm_ns_mailbox_get_msg_owner(handle); + if (task_handle) { + /* According to the description of CMSIS-RTOS v2 Thread Flags, + * osThreadFlagsSet() can be called inside Interrupt Service + * Routine. */ + osThreadFlagsSet(task_handle, handle); + } + } + } +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/tfm_mbed_boot.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/tfm_mbed_boot.c new file mode 100644 index 0000000..c8d595f --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/tfm_mbed_boot.c @@ -0,0 +1,67 @@ +/* mbed Microcontroller Library + * Copyright (c) 2020 ARM Limited + * 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 "mbed_error.h" +#include "tfm_multi_core_api.h" +#include "tfm_ns_mailbox.h" +#include "platform_multicore.h" +#include "tfm_ns_interface.h" + +static struct ns_mailbox_queue_t ns_mailbox_queue; + +void mbed_tfm_init(void) +{ + /* + * In case the of dual CPU, we need to initialize IPC, mailbox + * and NS interface after the RTOS has started to enable + * communication from Secure and Non-Secure cores. + */ + int32_t ret; + + ret = tfm_ns_wait_for_s_cpu_ready(); + /* + * Normally would expect "TFM_SUCCESS" returned here by TF-M, as this + * isn't a mailbox function. There may be some platforms other than PSoC6, + * which doesn't require tfm_ns_wait_for_s_cpu_ready() implementation. + * "PLATFORM_MAILBOX_SUCCESS" is a low-level error code and should be + * replaced by "TFM_SUCCESS". + * As the function definition has been imported from the TF-M, therefore + * a issue has been raised - https://developer.trustedfirmware.org/T660 + */ + if (ret != PLATFORM_MAILBOX_SUCCESS) { + /* Avoid undefined behavior after multi-core sync-up failed */ + MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, + MBED_ERROR_CODE_INITIALIZATION_FAILED), + "Failed to sync-up multi-core"); + } + + ret = tfm_ns_mailbox_init(&ns_mailbox_queue); + if (ret != MAILBOX_SUCCESS) { + /* Avoid undefined behavior after NS mailbox initialization failed */ + MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, + MBED_ERROR_CODE_INITIALIZATION_FAILED), + "Failed to initialize NS mailbox"); + } + + ret = tfm_ns_interface_init(); + if (ret != TFM_SUCCESS) { + /* Avoid undefined behavior after NS interface initialization failed */ + MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, + MBED_ERROR_CODE_INITIALIZATION_FAILED), + "Failed to initialize NS interface"); + } +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/tfm_multi_core_api.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/tfm_multi_core_api.c new file mode 100644 index 0000000..b58738f --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/tfm_multi_core_api.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "tfm_api.h" +#include "tfm_mailbox.h" +#include "tfm_multi_core_api.h" +#include "cmsis_os2.h" + +#define MAX_SEMAPHORE_COUNT NUM_MAILBOX_QUEUE_SLOT + +static osSemaphoreId_t ns_lock_handle = NULL; + +__attribute__((weak)) +enum tfm_status_e tfm_ns_interface_init(void) +{ + osSemaphoreAttr_t sema_attrib = {0}; + + ns_lock_handle = osSemaphoreNew(MAX_SEMAPHORE_COUNT, + MAX_SEMAPHORE_COUNT, + &sema_attrib); + if (!ns_lock_handle) { + return TFM_ERROR_GENERIC; + } + + return TFM_SUCCESS; +} + +int32_t tfm_ns_wait_for_s_cpu_ready(void) +{ + return tfm_platform_ns_wait_for_s_cpu_ready(); +} + +uint32_t tfm_ns_multi_core_lock_acquire(void) +{ + return osSemaphoreAcquire(ns_lock_handle, osWaitForever); +} + +uint32_t tfm_ns_multi_core_lock_release(void) +{ + return osSemaphoreRelease(ns_lock_handle); +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/tfm_multi_core_psa_ns_api.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/tfm_multi_core_psa_ns_api.c new file mode 100644 index 0000000..3af3af8 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/tfm_multi_core_psa_ns_api.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include + +#include "psa/client.h" +#include "psa/error.h" +#include "tfm_api.h" +#include "tfm_multi_core_api.h" +#include "tfm_ns_mailbox.h" + +/* + * TODO + * Currently, force all the non-secure client to share the same ID. + * + * It requires a more clear mechanism to synchronize the non-secure client + * ID with SPE in dual core scenario. + * In current design, the value is transferred to SPE via mailbox message. + * A dedicated routine to receive the non-secure client information in + * TF-M core/SPM in dual core scenario should be added besides current + * implementation for single Armv8-M. + * The non-secure client identification is shared with SPE in + * single Armv8-M scenario via CMSIS TrustZone context management API, + * which may not work in dual core scenario. + */ +#define NON_SECURE_CLIENT_ID (1) + +/* + * TODO + * Require a formal definition of errors related to mailbox in PSA client call. + */ +#define PSA_INTER_CORE_COMM_ERR (INT32_MIN + 0xFF) + +static void mailbox_wait_reply(mailbox_msg_handle_t handle) +{ + /* + * If the system can support multiple outstanding NS PSA Client calls, call + * tfm_ns_mailbox_wait_reply() to sleep and wait for reply. The NS side + * should implement tfm_ns_mailbox_hal_wait_reply() and wake-up mechanism. + * Otherwise, by default, call tfm_ns_mailbox_is_msg_replied() to simply + * poll the reply status of the mailbox message of current thread. + */ +#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL + tfm_ns_mailbox_wait_reply(handle); +#else + while (!tfm_ns_mailbox_is_msg_replied(handle)) { + } +#endif +} + +/**** API functions ****/ + +uint32_t psa_framework_version(void) +{ + struct psa_client_params_t params; + mailbox_msg_handle_t handle; + uint32_t version; + int32_t ret; + + if (tfm_ns_multi_core_lock_acquire() != TFM_SUCCESS) { + return PSA_VERSION_NONE; + } + + handle = tfm_ns_mailbox_tx_client_req(MAILBOX_PSA_FRAMEWORK_VERSION, + ¶ms, NON_SECURE_CLIENT_ID); + if (handle < 0) { + tfm_ns_multi_core_lock_release(); + return PSA_VERSION_NONE; + } + + mailbox_wait_reply(handle); + + ret = tfm_ns_mailbox_rx_client_reply(handle, (int32_t *)&version); + if (ret != MAILBOX_SUCCESS) { + version = PSA_VERSION_NONE; + } + + if (tfm_ns_multi_core_lock_release() != TFM_SUCCESS) { + return PSA_VERSION_NONE; + } + + return version; +} + +uint32_t psa_version(uint32_t sid) +{ + struct psa_client_params_t params; + mailbox_msg_handle_t handle; + uint32_t version; + int32_t ret; + + params.psa_version_params.sid = sid; + + if (tfm_ns_multi_core_lock_acquire() != TFM_SUCCESS) { + return PSA_VERSION_NONE; + } + + handle = tfm_ns_mailbox_tx_client_req(MAILBOX_PSA_VERSION, ¶ms, + NON_SECURE_CLIENT_ID); + if (handle < 0) { + tfm_ns_multi_core_lock_release(); + return PSA_VERSION_NONE; + } + + mailbox_wait_reply(handle); + + ret = tfm_ns_mailbox_rx_client_reply(handle, (int32_t *)&version); + if (ret != MAILBOX_SUCCESS) { + version = PSA_VERSION_NONE; + } + + if (tfm_ns_multi_core_lock_release() != TFM_SUCCESS) { + return PSA_VERSION_NONE; + } + + return version; +} + +psa_handle_t psa_connect(uint32_t sid, uint32_t version) +{ + struct psa_client_params_t params; + mailbox_msg_handle_t handle; + psa_handle_t psa_handle; + int32_t ret; + + params.psa_connect_params.sid = sid; + params.psa_connect_params.version = version; + + if (tfm_ns_multi_core_lock_acquire() != TFM_SUCCESS) { + return PSA_NULL_HANDLE; + } + + handle = tfm_ns_mailbox_tx_client_req(MAILBOX_PSA_CONNECT, ¶ms, + NON_SECURE_CLIENT_ID); + if (handle < 0) { + tfm_ns_multi_core_lock_release(); + return PSA_NULL_HANDLE; + } + + mailbox_wait_reply(handle); + + ret = tfm_ns_mailbox_rx_client_reply(handle, (int32_t *)&psa_handle); + if (ret != MAILBOX_SUCCESS) { + psa_handle = PSA_NULL_HANDLE; + } + + if (tfm_ns_multi_core_lock_release() != TFM_SUCCESS) { + return PSA_NULL_HANDLE; + } + + return psa_handle; +} + +psa_status_t psa_call(psa_handle_t handle, int32_t type, + const psa_invec *in_vec, size_t in_len, + psa_outvec *out_vec, size_t out_len) +{ + struct psa_client_params_t params; + mailbox_msg_handle_t msg_handle; + int32_t ret; + psa_status_t status; + + params.psa_call_params.handle = handle; + params.psa_call_params.type = type; + params.psa_call_params.in_vec = in_vec; + params.psa_call_params.in_len = in_len; + params.psa_call_params.out_vec = out_vec; + params.psa_call_params.out_len = out_len; + + if (tfm_ns_multi_core_lock_acquire() != TFM_SUCCESS) { + return PSA_ERROR_GENERIC_ERROR; + } + + msg_handle = tfm_ns_mailbox_tx_client_req(MAILBOX_PSA_CALL, ¶ms, + NON_SECURE_CLIENT_ID); + if (msg_handle < 0) { + tfm_ns_multi_core_lock_release(); + return PSA_INTER_CORE_COMM_ERR; + } + + mailbox_wait_reply(msg_handle); + + ret = tfm_ns_mailbox_rx_client_reply(msg_handle, (int32_t *)&status); + if (ret != MAILBOX_SUCCESS) { + status = PSA_INTER_CORE_COMM_ERR; + } + + if (tfm_ns_multi_core_lock_release() != TFM_SUCCESS) { + return PSA_ERROR_GENERIC_ERROR; + } + + return status; +} + +void psa_close(psa_handle_t handle) +{ + struct psa_client_params_t params; + mailbox_msg_handle_t msg_handle; + int32_t reply; + + params.psa_close_params.handle = handle; + + if (tfm_ns_multi_core_lock_acquire() != TFM_SUCCESS) { + return; + } + + msg_handle = tfm_ns_mailbox_tx_client_req(MAILBOX_PSA_CLOSE, ¶ms, + NON_SECURE_CLIENT_ID); + if (msg_handle < 0) { + tfm_ns_multi_core_lock_release(); + return; + } + + mailbox_wait_reply(msg_handle); + + (void)tfm_ns_mailbox_rx_client_reply(msg_handle, &reply); + + tfm_ns_multi_core_lock_release(); +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/tfm_ns_mailbox.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/tfm_ns_mailbox.c new file mode 100644 index 0000000..f7326f0 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_DUALCPU/src/tfm_ns_mailbox.c @@ -0,0 +1,425 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include "tfm_ns_mailbox.h" + +/* The pointer to NSPE mailbox queue */ +static struct ns_mailbox_queue_t *mailbox_queue_ptr = NULL; + +static inline void clear_queue_slot_empty(uint8_t idx) +{ + if (idx < NUM_MAILBOX_QUEUE_SLOT) { + mailbox_queue_ptr->empty_slots &= ~(1 << idx); + } +} + +static inline void set_queue_slot_empty(uint8_t idx) +{ + if (idx < NUM_MAILBOX_QUEUE_SLOT) { + mailbox_queue_ptr->empty_slots |= (1 << idx); + } +} + +static inline void set_queue_slot_pend(uint8_t idx) +{ + if (idx < NUM_MAILBOX_QUEUE_SLOT) { + mailbox_queue_ptr->pend_slots |= (1 << idx); + } +} + +static inline int32_t get_mailbox_msg_handle(uint8_t idx, + mailbox_msg_handle_t *handle) +{ + if ((idx >= NUM_MAILBOX_QUEUE_SLOT) || !handle) { + return MAILBOX_INVAL_PARAMS; + } + + *handle = (mailbox_msg_handle_t)(idx + 1); + + return MAILBOX_SUCCESS; +} + +static inline int32_t get_mailbox_msg_idx(mailbox_msg_handle_t handle, + uint8_t *idx) +{ + if ((handle == MAILBOX_MSG_NULL_HANDLE) || !idx) { + return MAILBOX_INVAL_PARAMS; + } + + *idx = (uint8_t)(handle - 1); + + return MAILBOX_SUCCESS; +} + +static inline void clear_queue_slot_replied(uint8_t idx) +{ + if (idx < NUM_MAILBOX_QUEUE_SLOT) { + mailbox_queue_ptr->replied_slots &= ~(1 << idx); + } +} + +static inline void set_queue_slot_woken(uint8_t idx) +{ + if (idx < NUM_MAILBOX_QUEUE_SLOT) { + mailbox_queue_ptr->queue[idx].is_woken = true; + } +} + +static inline bool is_queue_slot_woken(uint8_t idx) +{ + if (idx < NUM_MAILBOX_QUEUE_SLOT) { + return mailbox_queue_ptr->queue[idx].is_woken; + } + + return false; +} + +static inline void clear_queue_slot_woken(uint8_t idx) +{ + if (idx < NUM_MAILBOX_QUEUE_SLOT) { + mailbox_queue_ptr->queue[idx].is_woken = false; + } +} + +static uint8_t acquire_empty_slot(const struct ns_mailbox_queue_t *queue) +{ + uint8_t idx; + mailbox_queue_status_t status; + + tfm_ns_mailbox_hal_enter_critical(); + status = queue->empty_slots; + + if (!status) { + /* No empty slot */ + tfm_ns_mailbox_hal_exit_critical(); + return NUM_MAILBOX_QUEUE_SLOT; + } + + for (idx = 0; idx < NUM_MAILBOX_QUEUE_SLOT; idx++) { + if (status & (1 << idx)) { + break; + } + } + + clear_queue_slot_empty(idx); + + tfm_ns_mailbox_hal_exit_critical(); + + return idx; +} + +static void set_msg_owner(uint8_t idx, const void *owner) +{ + if (idx < NUM_MAILBOX_QUEUE_SLOT) { + mailbox_queue_ptr->queue[idx].owner = owner; + } +} + +#ifdef TFM_MULTI_CORE_TEST +void tfm_ns_mailbox_tx_stats_init(void) +{ + if (!mailbox_queue_ptr) { + return; + } + + tfm_ns_mailbox_hal_enter_critical(); + + mailbox_queue_ptr->nr_tx = 0; + mailbox_queue_ptr->nr_used_slots = 0; + + tfm_ns_mailbox_hal_exit_critical(); +} + +static void mailbox_tx_stats_update(struct ns_mailbox_queue_t *ns_queue) +{ + mailbox_queue_status_t empty_status; + uint8_t idx, nr_empty = 0; + + if (!ns_queue) { + return; + } + + tfm_ns_mailbox_hal_enter_critical(); + + ns_queue->nr_tx++; + + /* Count the number of used slots when this tx arrives */ + empty_status = ns_queue->empty_slots; + tfm_ns_mailbox_hal_exit_critical(); + + if (empty_status) { + for (idx = 0; idx < NUM_MAILBOX_QUEUE_SLOT; idx++) { + if (empty_status & (0x1UL << idx)) { + nr_empty++; + } + } + } + + tfm_ns_mailbox_hal_enter_critical(); + ns_queue->nr_used_slots += (NUM_MAILBOX_QUEUE_SLOT - nr_empty); + tfm_ns_mailbox_hal_exit_critical(); +} + +void tfm_ns_mailbox_stats_avg_slot(struct ns_mailbox_stats_res_t *stats_res) +{ + uint32_t nr_used_slots, nr_tx; + + if (!mailbox_queue_ptr || !stats_res) { + return; + } + + tfm_ns_mailbox_hal_enter_critical(); + nr_used_slots = mailbox_queue_ptr->nr_used_slots; + nr_tx = mailbox_queue_ptr->nr_tx; + tfm_ns_mailbox_hal_exit_critical(); + + stats_res->avg_nr_slots = nr_used_slots / nr_tx; + nr_used_slots %= nr_tx; + stats_res->avg_nr_slots_tenths = nr_used_slots * 10 / nr_tx; +} +#endif + +mailbox_msg_handle_t tfm_ns_mailbox_tx_client_req(uint32_t call_type, + const struct psa_client_params_t *params, + int32_t client_id) +{ + uint8_t idx; + struct mailbox_msg_t *msg_ptr; + mailbox_msg_handle_t handle; + const void *task_handle; + + if (!mailbox_queue_ptr) { + return MAILBOX_MSG_NULL_HANDLE; + } + + if (!params) { + return MAILBOX_MSG_NULL_HANDLE; + } + + idx = acquire_empty_slot(mailbox_queue_ptr); + if (idx >= NUM_MAILBOX_QUEUE_SLOT) { + return MAILBOX_QUEUE_FULL; + } + +#ifdef TFM_MULTI_CORE_TEST + mailbox_tx_stats_update(mailbox_queue_ptr); +#endif + + /* Fill the mailbox message */ + msg_ptr = &mailbox_queue_ptr->queue[idx].msg; + + msg_ptr->call_type = call_type; + memcpy(&msg_ptr->params, params, sizeof(msg_ptr->params)); + msg_ptr->client_id = client_id; + + /* + * Fetch the current task handle. The task will be woken up according the + * handle value set in the owner field. + */ + task_handle = tfm_ns_mailbox_get_task_handle(); + set_msg_owner(idx, task_handle); + + get_mailbox_msg_handle(idx, &handle); + + tfm_ns_mailbox_hal_enter_critical(); + set_queue_slot_pend(idx); + tfm_ns_mailbox_hal_exit_critical(); + + tfm_ns_mailbox_hal_notify_peer(); + + return handle; +} + +int32_t tfm_ns_mailbox_rx_client_reply(mailbox_msg_handle_t handle, + int32_t *reply) +{ + uint8_t idx; + int32_t ret; + + if (!mailbox_queue_ptr) { + return MAILBOX_INVAL_PARAMS; + } + + if ((handle == MAILBOX_MSG_NULL_HANDLE) || (!reply)) { + return MAILBOX_INVAL_PARAMS; + } + + ret = get_mailbox_msg_idx(handle, &idx); + if (ret != MAILBOX_SUCCESS) { + return ret; + } + + *reply = mailbox_queue_ptr->queue[idx].reply.return_val; + + /* Clear up the owner field */ + set_msg_owner(idx, NULL); + + tfm_ns_mailbox_hal_enter_critical(); + clear_queue_slot_replied(idx); + clear_queue_slot_woken(idx); + /* + * Make sure that the empty flag is set after all the other status flags are + * re-initialized. + */ + set_queue_slot_empty(idx); + tfm_ns_mailbox_hal_exit_critical(); + + return MAILBOX_SUCCESS; +} + +bool tfm_ns_mailbox_is_msg_replied(mailbox_msg_handle_t handle) +{ + uint8_t idx; + int32_t ret; + mailbox_queue_status_t status; + + if (!mailbox_queue_ptr) { + return false; + } + + if (handle == MAILBOX_MSG_NULL_HANDLE) { + return false; + } + + ret = get_mailbox_msg_idx(handle, &idx); + if (ret != MAILBOX_SUCCESS) { + return false; + } + + tfm_ns_mailbox_hal_enter_critical(); + status = mailbox_queue_ptr->replied_slots; + tfm_ns_mailbox_hal_exit_critical(); + + if (status & (1 << idx)) { + return true; + } + + return false; +} + +mailbox_msg_handle_t tfm_ns_mailbox_fetch_reply_msg_isr(void) +{ + uint8_t idx; + mailbox_msg_handle_t handle; + mailbox_queue_status_t replied_status; + + if (!mailbox_queue_ptr) { + return MAILBOX_MSG_NULL_HANDLE; + } + + tfm_ns_mailbox_hal_enter_critical_isr(); + replied_status = mailbox_queue_ptr->replied_slots; + tfm_ns_mailbox_hal_exit_critical_isr(); + + if (!replied_status) { + return MAILBOX_MSG_NULL_HANDLE; + } + + for (idx = 0; idx < NUM_MAILBOX_QUEUE_SLOT; idx++) { + /* Find the first replied message in queue */ + if (replied_status & (0x1UL << idx)) { + tfm_ns_mailbox_hal_enter_critical_isr(); + clear_queue_slot_replied(idx); + set_queue_slot_woken(idx); + tfm_ns_mailbox_hal_exit_critical_isr(); + + if (get_mailbox_msg_handle(idx, &handle) == MAILBOX_SUCCESS) { + return handle; + } + } + } + + return MAILBOX_MSG_NULL_HANDLE; +} + +const void *tfm_ns_mailbox_get_msg_owner(mailbox_msg_handle_t handle) +{ + uint8_t idx; + + if (get_mailbox_msg_idx(handle, &idx) != MAILBOX_SUCCESS) { + return NULL; + } + + if (idx < NUM_MAILBOX_QUEUE_SLOT) { + return mailbox_queue_ptr->queue[idx].owner; + } + + return NULL; +} + +int32_t tfm_ns_mailbox_init(struct ns_mailbox_queue_t *queue) +{ + int32_t ret; + + if (!queue) { + return MAILBOX_INVAL_PARAMS; + } + + /* + * Further verification of mailbox queue address may be required according + * to non-secure memory assignment. + */ + + memset(queue, 0, sizeof(*queue)); + + /* Initialize empty bitmask */ + queue->empty_slots = + (mailbox_queue_status_t)((1UL << (NUM_MAILBOX_QUEUE_SLOT - 1)) - 1); + queue->empty_slots += + (mailbox_queue_status_t)(1UL << (NUM_MAILBOX_QUEUE_SLOT - 1)); + + mailbox_queue_ptr = queue; + + /* Platform specific initialization. */ + ret = tfm_ns_mailbox_hal_init(queue); + +#ifdef TFM_MULTI_CORE_TEST + tfm_ns_mailbox_tx_stats_init(); +#endif + + return ret; +} + +#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL +int32_t tfm_ns_mailbox_wait_reply(mailbox_msg_handle_t handle) +{ + uint8_t idx; + int32_t ret; + + if (!mailbox_queue_ptr) { + return MAILBOX_INVAL_PARAMS; + } + + if (handle == MAILBOX_MSG_NULL_HANDLE) { + return MAILBOX_INVAL_PARAMS; + } + + ret = get_mailbox_msg_idx(handle, &idx); + if (ret != MAILBOX_SUCCESS) { + return ret; + } + + while (1) { + tfm_ns_mailbox_hal_wait_reply(handle); + + /* + * Woken up from sleep + * Check the completed flag to make sure that the current thread is + * woken up by reply event, rather than other events. + */ + tfm_ns_mailbox_hal_enter_critical(); + if (is_queue_slot_woken(idx)) { + tfm_ns_mailbox_hal_exit_critical(); + break; + } + tfm_ns_mailbox_hal_exit_critical(); + } + + return MAILBOX_SUCCESS; +} +#endif diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_V8M/src/cmsis_nvic_virtual.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_V8M/src/cmsis_nvic_virtual.c new file mode 100644 index 0000000..bee8597 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_V8M/src/cmsis_nvic_virtual.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2019-2020 Arm Limited + * + * 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 "cmsis_nvic_virtual.h" +#include "tfm_platform_api.h" + +void NVIC_SystemReset(void) +{ + tfm_platform_system_reset(); +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_V8M/src/tfm_mbed_boot.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_V8M/src/tfm_mbed_boot.c new file mode 100644 index 0000000..87bcbbb --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_V8M/src/tfm_mbed_boot.c @@ -0,0 +1,37 @@ +/* mbed Microcontroller Library + * Copyright (c) 2020 ARM Limited + * 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 "mbed_error.h" +#include "tfm_ns_interface.h" + +void mbed_tfm_init(void) +{ + /* + * In case of V8-M, we need to initialize NS interface + * after the RTOS has started to enable + * communication from Secure and Non-Secure cores. + */ + int32_t ret; + + ret = tfm_ns_interface_init(); + if (ret != TFM_SUCCESS) { + /* Avoid undefined behavior after NS interface initialization failed */ + MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, + MBED_ERROR_CODE_INITIALIZATION_FAILED), + "Failed to initialize NS interface"); + } +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_V8M/src/tfm_ns_interface.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_V8M/src/tfm_ns_interface.c new file mode 100644 index 0000000..9759145 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_V8M/src/tfm_ns_interface.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2017-2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +#include +#include + +#include "tfm_api.h" +#include "tfm_ns_interface.h" +#include "cmsis_os2.h" + +/** + * \brief the ns_lock ID + */ +static osMutexId_t ns_lock_handle = NULL; + +__attribute__((weak)) +int32_t tfm_ns_interface_dispatch(veneer_fn fn, + uint32_t arg0, uint32_t arg1, + uint32_t arg2, uint32_t arg3) +{ + int32_t result; + osStatus_t status; + + /* TFM request protected by NS lock */ + status = osMutexAcquire(ns_lock_handle, osWaitForever); + if (status != osOK) { + return (int32_t)TFM_ERROR_GENERIC; + } + + result = fn(arg0, arg1, arg2, arg3); + + status = osMutexRelease(ns_lock_handle); + if (status != osOK) { + return (int32_t)TFM_ERROR_GENERIC; + } + + return result; +} + +__attribute__((weak)) +enum tfm_status_e tfm_ns_interface_init(void) +{ + const osMutexAttr_t attr = { + .name = NULL, + .attr_bits = osMutexPrioInherit, /* Priority inheritance is recommended + * to enable if it is supported. + * For recursive mutex and the ability + * of auto release when owner being + * terminated is not required. + */ + .cb_mem = NULL, + .cb_size = 0U + }; + + ns_lock_handle = osMutexNew(&attr); + if (!ns_lock_handle) { + return TFM_ERROR_GENERIC; + } + + return TFM_SUCCESS; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_V8M/src/tfm_psa_ns_api.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_V8M/src/tfm_psa_ns_api.c new file mode 100644 index 0000000..9a677a2 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/TARGET_TFM_V8M/src/tfm_psa_ns_api.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018-2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "psa/client.h" +#include "tfm_ns_interface.h" +#include "tfm_api.h" + +/**** API functions ****/ + +uint32_t psa_framework_version(void) +{ + return tfm_ns_interface_dispatch( + (veneer_fn)tfm_psa_framework_version_veneer, + 0, + 0, + 0, + 0); +} + +uint32_t psa_version(uint32_t sid) +{ + return tfm_ns_interface_dispatch( + (veneer_fn)tfm_psa_version_veneer, + sid, + 0, + 0, + 0); +} + +psa_handle_t psa_connect(uint32_t sid, uint32_t version) +{ + return tfm_ns_interface_dispatch( + (veneer_fn)tfm_psa_connect_veneer, + sid, + version, + 0, + 0); +} + +psa_status_t psa_call(psa_handle_t handle, int32_t type, + const psa_invec *in_vec, + size_t in_len, + psa_outvec *out_vec, + size_t out_len) +{ + /* FixMe: sanity check can be added to offload some NS thread checks from + * TFM secure API + */ + + /* Due to v8M restrictions, TF-M NS API needs to add another layer of + * serialization in order for NS to pass arguments to S + */ + const struct tfm_control_parameter_t ctrl_param = { + .type = type, + .in_len = in_len, + .out_len = out_len, + }; + + return tfm_ns_interface_dispatch( + (veneer_fn)tfm_psa_call_veneer, + (uint32_t)handle, + (uint32_t)&ctrl_param, + (uint32_t)in_vec, + (uint32_t)out_vec); +} + +void psa_close(psa_handle_t handle) +{ + (void)tfm_ns_interface_dispatch( + (veneer_fn)tfm_psa_close_veneer, + (uint32_t)handle, + 0, + 0, + 0); +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/VERSION.txt b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/VERSION.txt new file mode 100644 index 0000000..54d3b42 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/VERSION.txt @@ -0,0 +1 @@ +a630d86e91a8 diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/cmsis_nvic_virtual.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/cmsis_nvic_virtual.h new file mode 100644 index 0000000..a1a8b61 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/cmsis_nvic_virtual.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2019 Arm Limited + * + * 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 "cmsis.h" + +#ifndef NVIC_VIRTUAL_H +#define NVIC_VIRTUAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* NVIC functions */ +#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping +#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping +#define NVIC_EnableIRQ __NVIC_EnableIRQ +#define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ +#define NVIC_DisableIRQ __NVIC_DisableIRQ +#define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ +#define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ +#define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ +#define NVIC_GetActive __NVIC_GetActive +#define NVIC_SetPriority __NVIC_SetPriority +#define NVIC_GetPriority __NVIC_GetPriority + +/** + * \brief Overriding the default CMSIS system reset implementation by calling + * secure TFM service. + * + */ +void NVIC_SystemReset(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/ns_ipc_config.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/ns_ipc_config.h new file mode 100644 index 0000000..e1cd7b7 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/ns_ipc_config.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _IPC_CONFIG_H_ +#define _IPC_CONFIG_H_ + +#include "platform_multicore.h" + +#define IPC_RX_CHAN IPC_PSA_CLIENT_REPLY_CHAN +#define IPC_RX_INTR_STRUCT IPC_PSA_CLIENT_REPLY_INTR_STRUCT +#define IPC_RX_INT_MASK IPC_PSA_CLIENT_REPLY_INTR_MASK + +#define IPC_TX_CHAN IPC_PSA_CLIENT_CALL_CHAN +#define IPC_TX_NOTIFY_MASK IPC_PSA_CLIENT_CALL_NOTIFY_MASK + +#define PSA_CLIENT_REPLY_NVIC_IRQn IPC_PSA_CLIENT_REPLY_IPC_INTR +#define PSA_CLIENT_REPLY_IRQ_PRIORITY 3 + +#endif diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/platform_multicore.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/platform_multicore.h new file mode 100644 index 0000000..f90fb1e --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/platform_multicore.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * Copyright (c) 2019, Cypress Semiconductor Corporation. All rights reserved + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef _TFM_PLATFORM_MULTICORE_ +#define _TFM_PLATFORM_MULTICORE_ + +#include +#include "cy_device_headers.h" + +#define IPC_PSA_CLIENT_CALL_CHAN (8) +#define IPC_PSA_CLIENT_CALL_INTR_STRUCT (6) +#define IPC_PSA_CLIENT_CALL_INTR_MASK (1 << IPC_PSA_CLIENT_CALL_CHAN) +#define IPC_PSA_CLIENT_CALL_NOTIFY_MASK (1 << IPC_PSA_CLIENT_CALL_INTR_STRUCT) +#define IPC_PSA_CLIENT_CALL_IPC_INTR cpuss_interrupts_ipc_6_IRQn + +#define IPC_PSA_CLIENT_REPLY_CHAN (9) +#define IPC_PSA_CLIENT_REPLY_INTR_STRUCT (5) +#define IPC_PSA_CLIENT_REPLY_INTR_MASK (1 << IPC_PSA_CLIENT_REPLY_CHAN) +#define IPC_PSA_CLIENT_REPLY_NOTIFY_MASK (1 << IPC_PSA_CLIENT_REPLY_INTR_STRUCT) +#define IPC_PSA_CLIENT_REPLY_IPC_INTR cpuss_interrupts_ipc_5_IRQn + +#define IPC_RX_RELEASE_MASK (0) + +#define CY_IPC_NOTIFY_SHIFT (16) + +#define PSA_CLIENT_CALL_REQ_MAGIC (0xA5CF50C6) +#define PSA_CLIENT_CALL_REPLY_MAGIC (0xC605FC5A) + +#define NS_MAILBOX_INIT_ENABLE (0xAE) +#define S_MAILBOX_READY (0xC3) + +#define PLATFORM_MAILBOX_SUCCESS (0x0) +#define PLATFORM_MAILBOX_INVAL_PARAMS (INT32_MIN + 1) +#define PLATFORM_MAILBOX_TX_ERROR (INT32_MIN + 2) +#define PLATFORM_MAILBOX_RX_ERROR (INT32_MIN + 3) +#define PLATFORM_MAILBOX_INIT_ERROR (INT32_MIN + 4) + +/* Inter-Processor Communication (IPC) data channel for the Semaphores */ +#define PLATFORM_MAILBOX_IPC_CHAN_SEMA CY_IPC_CHAN_SEMA +#define MAILBOX_SEMAPHORE_NUM (16) + +#define IPC_SYNC_MAGIC 0x7DADE011 + +/** + * \brief Fetch a pointer from mailbox message + * + * \param[out] msg_ptr The address to write the pointer value to. + * + * \retval 0 The operation succeeds. + * \retval else The operation fails. + */ +int platform_mailbox_fetch_msg_ptr(void **msg_ptr); + +/** + * \brief Fetch a data value from mailbox message + * + * \param[out] data_ptr The address to write the pointer value to. + * + * \retval 0 The operation succeeds. + * \retval else The operation fails. + */ +int platform_mailbox_fetch_msg_data(uint32_t *data_ptr); + +/** + * \brief Send a pointer via mailbox message + * + * \param[in] msg_ptr The pointer value to be sent. + * + * \retval 0 The operation succeeds. + * \retval else The operation fails. + */ +int platform_mailbox_send_msg_ptr(const void *msg_ptr); + +/** + * \brief Send a data value via mailbox message + * + * \param[in] data The data value to be sent + * + * \retval 0 The operation succeeds. + * \retval else The operation fails. + */ +int platform_mailbox_send_msg_data(uint32_t data); + +/** + * \brief Wait for a mailbox notify event. + */ +void platform_mailbox_wait_for_notify(void); + +/** + * \brief IPC initialization + * + * \retval 0 The operation succeeds. + * \retval else The operation fails. + */ +int platform_ns_ipc_init(void); + +#endif diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/client.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/client.h new file mode 100644 index 0000000..4115f93 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/client.h @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2018-2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __PSA_CLIENT_H__ +#define __PSA_CLIENT_H__ + +#include +#include + +#include "psa/error.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*********************** PSA Client Macros and Types *************************/ + +/** + * The version of the PSA Framework API that is being used to build the calling + * firmware. + */ +#define PSA_FRAMEWORK_VERSION (0x0100u) + +/** + * Return value from psa_version() if the requested RoT Service is not present + * in the system. + */ +#define PSA_VERSION_NONE (0u) + +/** + * The zero-value null handle can be assigned to variables used in clients and + * RoT Services, indicating that there is no current connection or message. + */ +#define PSA_NULL_HANDLE ((psa_handle_t)0) + +/** + * Tests whether a handle value returned by psa_connect() is valid. + */ +#define PSA_HANDLE_IS_VALID(handle) ((psa_handle_t)(handle) > 0) + +/** + * Converts the handle value returned from a failed call psa_connect() into + * an error code. + */ +#define PSA_HANDLE_TO_ERROR(handle) ((psa_status_t)(handle)) + +/** + * Maximum number of input and output vectors for a request to psa_call(). + */ +#define PSA_MAX_IOVEC (4u) + +/** + * An IPC message type that indicates a generic client request. + */ +#define PSA_IPC_CALL (0) + +typedef int32_t psa_handle_t; + +/** + * A read-only input memory region provided to an RoT Service. + */ +typedef struct psa_invec { + const void *base; /*!< the start address of the memory buffer */ + size_t len; /*!< the size in bytes */ +} psa_invec; + +/** + * A writable output memory region provided to an RoT Service. + */ +typedef struct psa_outvec { + void *base; /*!< the start address of the memory buffer */ + size_t len; /*!< the size in bytes */ +} psa_outvec; + +/*************************** PSA Client API **********************************/ + +/** + * \brief Retrieve the version of the PSA Framework API that is implemented. + * + * \return version The version of the PSA Framework implementation + * that is providing the runtime services to the + * caller. The major and minor version are encoded + * as follows: + * \arg version[15:8] -- major version number. + * \arg version[7:0] -- minor version number. + */ +uint32_t psa_framework_version(void); + +/** + * \brief Retrieve the version of an RoT Service or indicate that it is not + * present on this system. + * + * \param[in] sid ID of the RoT Service to query. + * + * \retval PSA_VERSION_NONE The RoT Service is not implemented, or the + * caller is not permitted to access the service. + * \retval > 0 The version of the implemented RoT Service. + */ +uint32_t psa_version(uint32_t sid); + +/** + * \brief Connect to an RoT Service by its SID. + * + * \param[in] sid ID of the RoT Service to connect to. + * \param[in] version Requested version of the RoT Service. + * + * \retval > 0 A handle for the connection. + * \retval PSA_ERROR_CONNECTION_REFUSED The SPM or RoT Service has refused the + * connection. + * \retval PSA_ERROR_CONNECTION_BUSY The SPM or RoT Service cannot make the + * connection at the moment. + * \retval "PROGRAMMER ERROR" The call is a PROGRAMMER ERROR if one or more + * of the following are true: + * \arg The RoT Service ID is not present. + * \arg The RoT Service version is not supported. + * \arg The caller is not allowed to access the RoT + * service. + */ +psa_handle_t psa_connect(uint32_t sid, uint32_t version); + +/** + * \brief Call an RoT Service on an established connection. + * + * \param[in] handle A handle to an established connection. + * \param[in] type The reuqest type. + * Must be zero( \ref PSA_IPC_CALL) or positive. + * \param[in] in_vec Array of input \ref psa_invec structures. + * \param[in] in_len Number of input \ref psa_invec structures. + * \param[in/out] out_vec Array of output \ref psa_outvec structures. + * \param[in] out_len Number of output \ref psa_outvec structures. + * + * \retval >=0 RoT Service-specific status value. + * \retval <0 RoT Service-specific error code. + * \retval PSA_ERROR_PROGRAMMER_ERROR The connection has been terminated by the + * RoT Service. The call is a PROGRAMMER ERROR if + * one or more of the following are true: + * \arg An invalid handle was passed. + * \arg The connection is already handling a request. + * \arg type < 0. + * \arg An invalid memory reference was provided. + * \arg in_len + out_len > PSA_MAX_IOVEC. + * \arg The message is unrecognized by the RoT + * Service or incorrectly formatted. + */ +psa_status_t psa_call(psa_handle_t handle, int32_t type, + const psa_invec *in_vec, + size_t in_len, + psa_outvec *out_vec, + size_t out_len); + +/** + * \brief Close a connection to an RoT Service. + * + * \param[in] handle A handle to an established connection, or the + * null handle. + * + * \retval void Success. + * \retval "PROGRAMMER ERROR" The call is a PROGRAMMER ERROR if one or more + * of the following are true: + * \arg An invalid handle was provided that is not + * the null handle. + * \arg The connection is currently handling a + * request. + */ +void psa_close(psa_handle_t handle); + +#ifdef __cplusplus +} +#endif + +#endif /* __PSA_CLIENT_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto.h new file mode 100644 index 0000000..1459195 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto.h @@ -0,0 +1,3774 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +/** + * \file psa/crypto.h + * \brief Platform Security Architecture cryptography module + */ + +#ifndef PSA_CRYPTO_H +#define PSA_CRYPTO_H + +#include + +#ifdef __DOXYGEN_ONLY__ +/* This __DOXYGEN_ONLY__ block contains mock definitions for things that + * must be defined in the crypto_platform.h header. These mock definitions + * are present in this file as a convenience to generate pretty-printed + * documentation that includes those definitions. */ + +/** \defgroup platform Implementation-specific definitions + * @{ + */ + +/** \brief Key handle. + * + * This type represents open handles to keys. It must be an unsigned integral + * type. The choice of type is implementation-dependent. + * + * 0 is not a valid key handle. How other handle values are assigned is + * implementation-dependent. + */ +typedef _unsigned_integral_type_ psa_key_handle_t; + +/**@}*/ +#endif /* __DOXYGEN_ONLY__ */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* The file "crypto_types.h" declares types that encode errors, + * algorithms, key types, policies, etc. */ +#include "psa/crypto_types.h" + +/** \defgroup version API version + * @{ + */ + +/** + * The major version of this implementation of the PSA Crypto API + */ +#define PSA_CRYPTO_API_VERSION_MAJOR 1 + +/** + * The minor version of this implementation of the PSA Crypto API + */ +#define PSA_CRYPTO_API_VERSION_MINOR 0 + +/**@}*/ + +/* The file "crypto_values.h" declares macros to build and analyze values + * of integral types defined in "crypto_types.h". */ +#include "psa/crypto_values.h" + +/** \defgroup initialization Library initialization + * @{ + */ + +/** + * \brief Library initialization. + * + * Applications must call this function before calling any other + * function in this module. + * + * Applications may call this function more than once. Once a call + * succeeds, subsequent calls are guaranteed to succeed. + * + * If the application calls other functions before calling psa_crypto_init(), + * the behavior is undefined. Implementations are encouraged to either perform + * the operation as if the library had been initialized or to return + * #PSA_ERROR_BAD_STATE or some other applicable error. In particular, + * implementations should not return a success status if the lack of + * initialization may have security implications, for example due to improper + * seeding of the random number generator. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + */ +psa_status_t psa_crypto_init(void); + +/**@}*/ + +/** \addtogroup attributes + * @{ + */ + +/** \def PSA_KEY_ATTRIBUTES_INIT + * + * This macro returns a suitable initializer for a key attribute structure + * of type #psa_key_attributes_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_KEY_ATTRIBUTES_INIT {0} +#endif + +/** Return an initial value for a key attributes structure. + */ +static psa_key_attributes_t psa_key_attributes_init(void); + +/** Declare a key as persistent and set its key identifier. + * + * If the attribute structure currently declares the key as volatile (which + * is the default content of an attribute structure), this function sets + * the lifetime attribute to #PSA_KEY_LIFETIME_PERSISTENT. + * + * This function does not access storage, it merely stores the given + * value in the structure. + * The persistent key will be written to storage when the attribute + * structure is passed to a key creation function such as + * psa_import_key(), psa_generate_key(), + * psa_key_derivation_output_key() or psa_copy_key(). + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param id The persistent identifier for the key. + */ +static void psa_set_key_id(psa_key_attributes_t *attributes, + psa_key_id_t id); + +/** Set the location of a persistent key. + * + * To make a key persistent, you must give it a persistent key identifier + * with psa_set_key_id(). By default, a key that has a persistent identifier + * is stored in the default storage area identifier by + * #PSA_KEY_LIFETIME_PERSISTENT. Call this function to choose a storage + * area, or to explicitly declare the key as volatile. + * + * This function does not access storage, it merely stores the given + * value in the structure. + * The persistent key will be written to storage when the attribute + * structure is passed to a key creation function such as + * psa_import_key(), psa_generate_key(), + * psa_key_derivation_output_key() or psa_copy_key(). + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param lifetime The lifetime for the key. + * If this is #PSA_KEY_LIFETIME_VOLATILE, the + * key will be volatile, and the key identifier + * attribute is reset to 0. + */ +static void psa_set_key_lifetime(psa_key_attributes_t *attributes, + psa_key_lifetime_t lifetime); + +/** Retrieve the key identifier from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The persistent identifier stored in the attribute structure. + * This value is unspecified if the attribute structure declares + * the key as volatile. + */ +static psa_key_id_t psa_get_key_id(const psa_key_attributes_t *attributes); + +/** Retrieve the lifetime from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The lifetime value stored in the attribute structure. + */ +static psa_key_lifetime_t psa_get_key_lifetime( + const psa_key_attributes_t *attributes); + +/** Declare usage flags for a key. + * + * Usage flags are part of a key's usage policy. They encode what + * kind of operations are permitted on the key. For more details, + * refer to the documentation of the type #psa_key_usage_t. + * + * This function overwrites any usage flags + * previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param usage_flags The usage flags to write. + */ +static void psa_set_key_usage_flags(psa_key_attributes_t *attributes, + psa_key_usage_t usage_flags); + +/** Retrieve the usage flags from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The usage flags stored in the attribute structure. + */ +static psa_key_usage_t psa_get_key_usage_flags( + const psa_key_attributes_t *attributes); + +/** Declare the permitted algorithm policy for a key. + * + * The permitted algorithm policy of a key encodes which algorithm or + * algorithms are permitted to be used with this key. The following + * algorithm policies are supported: + * - 0 does not allow any cryptographic operation with the key. The key + * may be used for non-cryptographic actions such as exporting (if + * permitted by the usage flags). + * - An algorithm value permits this particular algorithm. + * - An algorithm wildcard built from #PSA_ALG_ANY_HASH allows the specified + * signature scheme with any hash algorithm. + * + * This function overwrites any algorithm policy + * previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param alg The permitted algorithm policy to write. + */ +static void psa_set_key_algorithm(psa_key_attributes_t *attributes, + psa_algorithm_t alg); + + +/** Retrieve the algorithm policy from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The algorithm stored in the attribute structure. + */ +static psa_algorithm_t psa_get_key_algorithm( + const psa_key_attributes_t *attributes); + +/** Declare the type of a key. + * + * This function overwrites any key type + * previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param type The key type to write. + * If this is 0, the key type in \p attributes + * becomes unspecified. + */ +static void psa_set_key_type(psa_key_attributes_t *attributes, + psa_key_type_t type); + + +/** Declare the size of a key. + * + * This function overwrites any key size previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param bits The key size in bits. + * If this is 0, the key size in \p attributes + * becomes unspecified. Keys of size 0 are + * not supported. + */ +static void psa_set_key_bits(psa_key_attributes_t *attributes, + size_t bits); + +/** Retrieve the key type from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The key type stored in the attribute structure. + */ +static psa_key_type_t psa_get_key_type(const psa_key_attributes_t *attributes); + +/** Retrieve the key size from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The key size stored in the attribute structure, in bits. + */ +static size_t psa_get_key_bits(const psa_key_attributes_t *attributes); + +/** Retrieve the attributes of a key. + * + * This function first resets the attribute structure as with + * psa_reset_key_attributes(). It then copies the attributes of + * the given key into the given attribute structure. + * + * \note This function may allocate memory or other resources. + * Once you have called this function on an attribute structure, + * you must call psa_reset_key_attributes() to free these resources. + * + * \param[in] handle Handle to the key to query. + * \param[in,out] attributes On success, the attributes of the key. + * On failure, equivalent to a + * freshly-initialized structure. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_get_key_attributes(psa_key_handle_t handle, + psa_key_attributes_t *attributes); + +/** Reset a key attribute structure to a freshly initialized state. + * + * You must initialize the attribute structure as described in the + * documentation of the type #psa_key_attributes_t before calling this + * function. Once the structure has been initialized, you may call this + * function at any time. + * + * This function frees any auxiliary resources that the structure + * may contain. + * + * \param[in,out] attributes The attribute structure to reset. + */ +void psa_reset_key_attributes(psa_key_attributes_t *attributes); + +/**@}*/ + +/** \defgroup key_management Key management + * @{ + */ + +/** Open a handle to an existing persistent key. + * + * Open a handle to a persistent key. A key is persistent if it was created + * with a lifetime other than #PSA_KEY_LIFETIME_VOLATILE. A persistent key + * always has a nonzero key identifier, set with psa_set_key_id() when + * creating the key. Implementations may provide additional pre-provisioned + * keys that can be opened with psa_open_key(). Such keys have a key identifier + * in the vendor range, as documented in the description of #psa_key_id_t. + * + * The application must eventually close the handle with psa_close_key() or + * psa_destroy_key() to release associated resources. If the application dies + * without calling one of these functions, the implementation should perform + * the equivalent of a call to psa_close_key(). + * + * Some implementations permit an application to open the same key multiple + * times. If this is successful, each call to psa_open_key() will return a + * different key handle. + * + * \note Applications that rely on opening a key multiple times will not be + * portable to implementations that only permit a single key handle to be + * opened. See also :ref:\`key-handles\`. + * + * \param id The persistent identifier of the key. + * \param[out] handle On success, a handle to the key. + * + * \retval #PSA_SUCCESS + * Success. The application can now use the value of `*handle` + * to access the key. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * The implementation does not have sufficient resources to open the + * key. This can be due to reaching an implementation limit on the + * number of open keys, the number of open key handles, or available + * memory. + * \retval #PSA_ERROR_DOES_NOT_EXIST + * There is no persistent key with key identifier \p id. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p id is not a valid persistent key identifier. + * \retval #PSA_ERROR_NOT_PERMITTED + * The specified key exists, but the application does not have the + * permission to access it. Note that this specification does not + * define any way to create such a key, but it may be possible + * through implementation-specific means. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_open_key(psa_key_id_t id, + psa_key_handle_t *handle); + + +/** Close a key handle. + * + * If the handle designates a volatile key, this will destroy the key material + * and free all associated resources, just like psa_destroy_key(). + * + * If this is the last open handle to a persistent key, then closing the handle + * will free all resources associated with the key in volatile memory. The key + * data in persistent storage is not affected and can be opened again later + * with a call to psa_open_key(). + * + * Closing the key handle makes the handle invalid, and the key handle + * must not be used again by the application. + * + * \note If the key handle was used to set up an active + * :ref:\`multipart operation \`, then closing the + * key handle can cause the multipart operation to fail. Applications should + * maintain the key handle until after the multipart operation has finished. + * + * \param handle The key handle to close. + * If this is \c 0, do nothing and return \c PSA_SUCCESS. + * + * \retval #PSA_SUCCESS + * \p handle was a valid handle or \c 0. It is now closed. + * \retval #PSA_ERROR_INVALID_HANDLE + * \p handle is not a valid handle nor \c 0. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_close_key(psa_key_handle_t handle); + +/** Make a copy of a key. + * + * Copy key material from one location to another. + * + * This function is primarily useful to copy a key from one location + * to another, since it populates a key using the material from + * another key which may have a different lifetime. + * + * This function may be used to share a key with a different party, + * subject to implementation-defined restrictions on key sharing. + * + * The policy on the source key must have the usage flag + * #PSA_KEY_USAGE_COPY set. + * This flag is sufficient to permit the copy if the key has the lifetime + * #PSA_KEY_LIFETIME_VOLATILE or #PSA_KEY_LIFETIME_PERSISTENT. + * Some secure elements do not provide a way to copy a key without + * making it extractable from the secure element. If a key is located + * in such a secure element, then the key must have both usage flags + * #PSA_KEY_USAGE_COPY and #PSA_KEY_USAGE_EXPORT in order to make + * a copy of the key outside the secure element. + * + * The resulting key may only be used in a way that conforms to + * both the policy of the original key and the policy specified in + * the \p attributes parameter: + * - The usage flags on the resulting key are the bitwise-and of the + * usage flags on the source policy and the usage flags in \p attributes. + * - If both allow the same algorithm or wildcard-based + * algorithm policy, the resulting key has the same algorithm policy. + * - If either of the policies allows an algorithm and the other policy + * allows a wildcard-based algorithm policy that includes this algorithm, + * the resulting key allows the same algorithm. + * - If the policies do not allow any algorithm in common, this function + * fails with the status #PSA_ERROR_INVALID_ARGUMENT. + * + * The effect of this function on implementation-defined attributes is + * implementation-defined. + * + * \param source_handle The key to copy. It must be a valid key handle. + * \param[in] attributes The attributes for the new key. + * They are used as follows: + * - The key type and size may be 0. If either is + * nonzero, it must match the corresponding + * attribute of the source key. + * - The key location (the lifetime and, for + * persistent keys, the key identifier) is + * used directly. + * - The policy constraints (usage flags and + * algorithm policy) are combined from + * the source key and \p attributes so that + * both sets of restrictions apply, as + * described in the documentation of this function. + * \param[out] target_handle On success, a handle to the newly created key. + * \c 0 on failure. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \p source_handle is invalid. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The lifetime or identifier in \p attributes are invalid. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The policy constraints on the source and specified in + * \p attributes are incompatible. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p attributes specifies a key type or key size + * which does not match the attributes of the source key. + * \retval #PSA_ERROR_NOT_PERMITTED + * The source key does not have the #PSA_KEY_USAGE_COPY usage flag. + * \retval #PSA_ERROR_NOT_PERMITTED + * The source key is not exportable and its lifetime does not + * allow copying it to the target's lifetime. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_copy_key(psa_key_handle_t source_handle, + const psa_key_attributes_t *attributes, + psa_key_handle_t *target_handle); + + +/** + * \brief Destroy a key. + * + * This function destroys a key from both volatile + * memory and, if applicable, non-volatile storage. Implementations shall + * make a best effort to ensure that that the key material cannot be recovered. + * + * This function also erases any metadata such as policies and frees + * resources associated with the key. To free all resources associated with + * the key, all handles to the key must be closed or destroyed. + * + * Destroying the key makes the handle invalid, and the key handle + * must not be used again by the application. Using other open handles to the + * destroyed key in a cryptographic operation will result in an error. + * + * If a key is currently in use in a multipart operation, then destroying the + * key will cause the multipart operation to fail. + * + * \param handle Handle to the key to erase. + * If this is \c 0, do nothing and return \c PSA_SUCCESS. + * + * \retval #PSA_SUCCESS + * \p handle was a valid handle and the key material that it + * referred to has been erased. + * Alternatively, \p handle is \c 0. + * \retval #PSA_ERROR_NOT_PERMITTED + * The key cannot be erased because it is + * read-only, either due to a policy or due to physical restrictions. + * \retval #PSA_ERROR_INVALID_HANDLE + * \p handle is not a valid handle nor \c 0. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * There was an failure in communication with the cryptoprocessor. + * The key material may still be present in the cryptoprocessor. + * \retval #PSA_ERROR_STORAGE_FAILURE + * The storage is corrupted. Implementations shall make a best effort + * to erase key material even in this stage, however applications + * should be aware that it may be impossible to guarantee that the + * key material is not recoverable in such cases. + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * An unexpected condition which is not a storage corruption or + * a communication failure occurred. The cryptoprocessor may have + * been compromised. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_destroy_key(psa_key_handle_t handle); + +/**@}*/ + +/** \defgroup import_export Key import and export + * @{ + */ + +/** + * \brief Import a key in binary format. + * + * This function supports any output from psa_export_key(). Refer to the + * documentation of psa_export_public_key() for the format of public keys + * and to the documentation of psa_export_key() for the format for + * other key types. + * + * The key data determines the key size. The attributes may optionally + * specify a key size; in this case it must match the size determined + * from the key data. A key size of 0 in \p attributes indicates that + * the key size is solely determined by the key data. + * + * Implementations must reject an attempt to import a key of size 0. + * + * This specification supports a single format for each key type. + * Implementations may support other formats as long as the standard + * format is supported. Implementations that support other formats + * should ensure that the formats are clearly unambiguous so as to + * minimize the risk that an invalid input is accidentally interpreted + * according to a different format. + * + * \param[in] attributes The attributes for the new key. + * The key size is always determined from the + * \p data buffer. + * If the key size in \p attributes is nonzero, + * it must be equal to the size from \p data. + * \param[out] handle On success, a handle to the newly created key. + * \c 0 on failure. + * \param[in] data Buffer containing the key data. The content of this + * buffer is interpreted according to the type declared + * in \p attributes. + * All implementations must support at least the format + * described in the documentation + * of psa_export_key() or psa_export_public_key() for + * the chosen type. Implementations may allow other + * formats, but should be conservative: implementations + * should err on the side of rejecting content if it + * may be erroneous (e.g. wrong type or truncated data). + * \param data_length Size of the \p data buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The key type or key size is not supported, either by the + * implementation in general or in this particular persistent location. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key attributes, as a whole, are invalid. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key data is not correctly formatted. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size in \p attributes is nonzero and does not match the size + * of the key data. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_import_key(const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + psa_key_handle_t *handle); + + + +/** + * \brief Export a key in binary format. + * + * The output of this function can be passed to psa_import_key() to + * create an equivalent object. + * + * If the implementation of psa_import_key() supports other formats + * beyond the format specified here, the output from psa_export_key() + * must use the representation specified here, not the original + * representation. + * + * For standard key types, the output format is as follows: + * + * - For symmetric keys (including MAC keys), the format is the + * raw bytes of the key. + * - For DES, the key data consists of 8 bytes. The parity bits must be + * correct. + * - For Triple-DES, the format is the concatenation of the + * two or three DES keys. + * - For RSA key pairs (#PSA_KEY_TYPE_RSA_KEY_PAIR), the format + * is the non-encrypted DER encoding of the representation defined by + * PKCS\#1 (RFC 8017) as `RSAPrivateKey`, version 0. + * ``` + * RSAPrivateKey ::= SEQUENCE { + * version INTEGER, -- must be 0 + * modulus INTEGER, -- n + * publicExponent INTEGER, -- e + * privateExponent INTEGER, -- d + * prime1 INTEGER, -- p + * prime2 INTEGER, -- q + * exponent1 INTEGER, -- d mod (p-1) + * exponent2 INTEGER, -- d mod (q-1) + * coefficient INTEGER, -- (inverse of q) mod p + * } + * ``` + * - For elliptic curve key pairs (key types for which + * #PSA_KEY_TYPE_IS_ECC_KEY_PAIR is true), the format is + * a representation of the private value as a `ceiling(m/8)`-byte string + * where `m` is the bit size associated with the curve, i.e. the bit size + * of the order of the curve's coordinate field. This byte string is + * in little-endian order for Montgomery curves (curve types + * `PSA_ECC_CURVE_CURVEXXX`), and in big-endian order for Weierstrass + * curves (curve types `PSA_ECC_CURVE_SECTXXX`, `PSA_ECC_CURVE_SECPXXX` + * and `PSA_ECC_CURVE_BRAINPOOL_PXXX`). + * This is the content of the `privateKey` field of the `ECPrivateKey` + * format defined by RFC 5915. + * - For Diffie-Hellman key exchange key pairs (key types for which + * #PSA_KEY_TYPE_IS_DH_KEY_PAIR is true), the + * format is the representation of the private key `x` as a big-endian byte + * string. The length of the byte string is the private key size in bytes + * (leading zeroes are not stripped). + * - For public keys (key types for which #PSA_KEY_TYPE_IS_PUBLIC_KEY is + * true), the format is the same as for psa_export_public_key(). + * + * The policy on the key must have the usage flag #PSA_KEY_USAGE_EXPORT set. + * + * \param handle Handle to the key to export. + * \param[out] data Buffer where the key data is to be written. + * \param data_size Size of the \p data buffer in bytes. + * \param[out] data_length On success, the number of bytes + * that make up the key data. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * The key does not have the #PSA_KEY_USAGE_EXPORT flag. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p data buffer is too small. You can determine a + * sufficient buffer size by calling + * #PSA_KEY_EXPORT_MAX_SIZE(\c type, \c bits) + * where \c type is the key type + * and \c bits is the key size in bits. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_export_key(psa_key_handle_t handle, + uint8_t *data, + size_t data_size, + size_t *data_length); + +/** + * \brief Export a public key or the public part of a key pair in binary format. + * + * The output of this function can be passed to psa_import_key() to + * create an object that is equivalent to the public key. + * + * This specification supports a single format for each key type. + * Implementations may support other formats as long as the standard + * format is supported. Implementations that support other formats + * should ensure that the formats are clearly unambiguous so as to + * minimize the risk that an invalid input is accidentally interpreted + * according to a different format. + * + * For standard key types, the output format is as follows: + * - For RSA public keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY), the DER encoding of + * the representation defined by RFC 3279 §2.3.1 as `RSAPublicKey`. + * ``` + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER } -- e + * ``` + * - For elliptic curve public keys (key types for which + * #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true), the format is the uncompressed + * representation defined by SEC1 §2.3.3 as the content of an ECPoint. + * Let `m` be the bit size associated with the curve, i.e. the bit size of + * `q` for a curve over `F_q`. The representation consists of: + * - The byte 0x04; + * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; + * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. + * - For Diffie-Hellman key exchange public keys (key types for which + * #PSA_KEY_TYPE_IS_DH_PUBLIC_KEY is true), + * the format is the representation of the public key `y = g^x mod p` as a + * big-endian byte string. The length of the byte string is the length of the + * base prime `p` in bytes. + * + * Exporting a public key object or the public part of a key pair is + * always permitted, regardless of the key's usage flags. + * + * \param handle Handle to the key to export. + * \param[out] data Buffer where the key data is to be written. + * \param data_size Size of the \p data buffer in bytes. + * \param[out] data_length On success, the number of bytes + * that make up the key data. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key is neither a public key nor a key pair. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p data buffer is too small. You can determine a + * sufficient buffer size by calling + * #PSA_KEY_EXPORT_MAX_SIZE(#PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(\c type), \c bits) + * where \c type is the key type + * and \c bits is the key size in bits. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_export_public_key(psa_key_handle_t handle, + uint8_t *data, + size_t data_size, + size_t *data_length); + + + +/**@}*/ + +/** \defgroup hash Message digests + * @{ + */ + +/** Calculate the hash (digest) of a message. + * + * \note To verify the hash of a message against an + * expected value, use psa_hash_compare() instead. + * + * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_HASH(\p alg) is true). + * \param[in] input Buffer containing the message to hash. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] hash Buffer where the hash is to be written. + * \param hash_size Size of the \p hash buffer in bytes. + * \param[out] hash_length On success, the number of bytes + * that make up the hash value. This is always + * #PSA_HASH_SIZE(\p alg). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a hash algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p hash_size is too small + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_compute(psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *hash, + size_t hash_size, + size_t *hash_length); + +/** Calculate the hash (digest) of a message and compare it with a + * reference value. + * + * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_HASH(\p alg) is true). + * \param[in] input Buffer containing the message to hash. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] hash Buffer containing the expected hash value. + * \param hash_length Size of the \p hash buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected hash is identical to the actual hash of the input. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The hash of the message was calculated successfully, but it + * differs from the expected hash. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a hash algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p input_length or \p hash_length do not match the hash size for \p alg + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_compare(psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *hash, + const size_t hash_length); + +/** The type of the state data structure for multipart hash operations. + * + * Before calling any function on a hash operation object, the application must + * initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_hash_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_hash_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_HASH_OPERATION_INIT, + * for example: + * \code + * psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_hash_operation_init() + * to the structure, for example: + * \code + * psa_hash_operation_t operation; + * operation = psa_hash_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure except + * as directed by the documentation of a specific implementation. */ +typedef struct psa_hash_operation_s psa_hash_operation_t; + +/** \def PSA_HASH_OPERATION_INIT + * + * This macro returns a suitable initializer for a hash operation object + * of type #psa_hash_operation_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_HASH_OPERATION_INIT {0} +#endif + +/** Return an initial value for a hash operation object. + */ +static psa_hash_operation_t psa_hash_operation_init(void); + +/** Set up a multipart hash operation. + * + * The sequence of operations to calculate a hash (message digest) + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_hash_operation_t, e.g. #PSA_HASH_OPERATION_INIT. + * -# Call psa_hash_setup() to specify the algorithm. + * -# Call psa_hash_update() zero, one or more times, passing a fragment + * of the message each time. The hash that is calculated is the hash + * of the concatenation of these messages in order. + * -# To calculate the hash, call psa_hash_finish(). + * To compare the hash with an expected value, call psa_hash_verify(). + * + * If an error occurs at any step after a call to psa_hash_setup(), the + * operation will need to be reset by a call to psa_hash_abort(). The + * application may call psa_hash_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_hash_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_hash_finish() or psa_hash_verify(). + * - A call to psa_hash_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_hash_operation_t and not yet in use. + * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_HASH(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not a supported hash algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p alg is not a hash algorithm. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_setup(psa_hash_operation_t *operation, + psa_algorithm_t alg); + +/** Add a message fragment to a multipart hash operation. + * + * The application must call psa_hash_setup() before calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_hash_abort(). + * + * \param[in,out] operation Active hash operation. + * \param[in] input Buffer containing the message fragment to hash. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it muct be active). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_update(psa_hash_operation_t *operation, + const uint8_t *input, + size_t input_length); + +/** Finish the calculation of the hash of a message. + * + * The application must call psa_hash_setup() before calling this function. + * This function calculates the hash of the message formed by concatenating + * the inputs passed to preceding calls to psa_hash_update(). + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_hash_abort(). + * + * \warning Applications should not call this function if they expect + * a specific value for the hash. Call psa_hash_verify() instead. + * Beware that comparing integrity or authenticity data such as + * hash values with a function such as \c memcmp is risky + * because the time taken by the comparison may leak information + * about the hashed data which could allow an attacker to guess + * a valid hash and thereby bypass security controls. + * + * \param[in,out] operation Active hash operation. + * \param[out] hash Buffer where the hash is to be written. + * \param hash_size Size of the \p hash buffer in bytes. + * \param[out] hash_length On success, the number of bytes + * that make up the hash value. This is always + * #PSA_HASH_SIZE(\c alg) where \c alg is the + * hash algorithm that is calculated. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p hash buffer is too small. You can determine a + * sufficient buffer size by calling #PSA_HASH_SIZE(\c alg) + * where \c alg is the hash algorithm that is calculated. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_finish(psa_hash_operation_t *operation, + uint8_t *hash, + size_t hash_size, + size_t *hash_length); + +/** Finish the calculation of the hash of a message and compare it with + * an expected value. + * + * The application must call psa_hash_setup() before calling this function. + * This function calculates the hash of the message formed by concatenating + * the inputs passed to preceding calls to psa_hash_update(). It then + * compares the calculated hash with the expected hash passed as a + * parameter to this function. + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_hash_abort(). + * + * \note Implementations shall make the best effort to ensure that the + * comparison between the actual hash and the expected hash is performed + * in constant time. + * + * \param[in,out] operation Active hash operation. + * \param[in] hash Buffer containing the expected hash value. + * \param hash_length Size of the \p hash buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected hash is identical to the actual hash of the message. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The hash of the message was calculated successfully, but it + * differs from the expected hash. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_verify(psa_hash_operation_t *operation, + const uint8_t *hash, + size_t hash_length); + +/** Abort a hash operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_hash_setup() again. + * + * You may call this function any time after the operation object has + * been initialized by one of the methods described in #psa_hash_operation_t. + * + * In particular, calling psa_hash_abort() after the operation has been + * terminated by a call to psa_hash_abort(), psa_hash_finish() or + * psa_hash_verify() is safe and has no effect. + * + * \param[in,out] operation Initialized hash operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_abort(psa_hash_operation_t *operation); + +/** Clone a hash operation. + * + * This function copies the state of an ongoing hash operation to + * a new operation object. In other words, this function is equivalent + * to calling psa_hash_setup() on \p target_operation with the same + * algorithm that \p source_operation was set up for, then + * psa_hash_update() on \p target_operation with the same input that + * that was passed to \p source_operation. After this function returns, the + * two objects are independent, i.e. subsequent calls involving one of + * the objects do not affect the other object. + * + * \param[in] source_operation The active hash operation to clone. + * \param[in,out] target_operation The operation object to set up. + * It must be initialized but not active. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_BAD_STATE + * The \p source_operation state is not valid (it must be active). + * \retval #PSA_ERROR_BAD_STATE + * The \p target_operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation, + psa_hash_operation_t *target_operation); + +/**@}*/ + +/** \defgroup MAC Message authentication codes + * @{ + */ + +/** Calculate the MAC (message authentication code) of a message. + * + * \note To verify the MAC of a message against an + * expected value, use psa_mac_verify() instead. + * Beware that comparing integrity or authenticity data such as + * MAC values with a function such as \c memcmp is risky + * because the time taken by the comparison may leak information + * about the MAC value which could allow an attacker to guess + * a valid MAC and thereby bypass security controls. + * + * \param handle Handle to the key to use for the operation. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * \param[in] input Buffer containing the input message. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] mac Buffer where the MAC value is to be written. + * \param mac_size Size of the \p mac buffer in bytes. + * \param[out] mac_length On success, the number of bytes + * that make up the MAC value. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p mac_size is too small + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_compute(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *mac, + size_t mac_size, + size_t *mac_length); + +/** Calculate the MAC of a message and compare it with a reference value. + * + * \param handle Handle to the key to use for the operation. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * \param[in] input Buffer containing the input message. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] mac Buffer containing the expected MAC value. + * \param mac_length Size of the \p mac buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected MAC is identical to the actual MAC of the input. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The MAC of the message was calculated successfully, but it + * differs from the expected value. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_verify(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *mac, + const size_t mac_length); + +/** The type of the state data structure for multipart MAC operations. + * + * Before calling any function on a MAC operation object, the application must + * initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_mac_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_mac_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_MAC_OPERATION_INIT, + * for example: + * \code + * psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_mac_operation_init() + * to the structure, for example: + * \code + * psa_mac_operation_t operation; + * operation = psa_mac_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure except + * as directed by the documentation of a specific implementation. */ +typedef struct psa_mac_operation_s psa_mac_operation_t; + +/** \def PSA_MAC_OPERATION_INIT + * + * This macro returns a suitable initializer for a MAC operation object of type + * #psa_mac_operation_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_MAC_OPERATION_INIT {0} +#endif + +/** Return an initial value for a MAC operation object. + */ +static psa_mac_operation_t psa_mac_operation_init(void); + +/** Set up a multipart MAC calculation operation. + * + * This function sets up the calculation of the MAC + * (message authentication code) of a byte string. + * To verify the MAC of a message against an + * expected value, use psa_mac_verify_setup() instead. + * + * The sequence of operations to calculate a MAC is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT. + * -# Call psa_mac_sign_setup() to specify the algorithm and key. + * -# Call psa_mac_update() zero, one or more times, passing a fragment + * of the message each time. The MAC that is calculated is the MAC + * of the concatenation of these messages in order. + * -# At the end of the message, call psa_mac_sign_finish() to finish + * calculating the MAC value and retrieve it. + * + * If an error occurs at any step after a call to psa_mac_sign_setup(), the + * operation will need to be reset by a call to psa_mac_abort(). The + * application may call psa_mac_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_mac_sign_setup(), the application must + * eventually terminate the operation through one of the following methods: + * - A successful call to psa_mac_sign_finish(). + * - A call to psa_mac_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_mac_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Set up a multipart MAC verification operation. + * + * This function sets up the verification of the MAC + * (message authentication code) of a byte string against an expected value. + * + * The sequence of operations to verify a MAC is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT. + * -# Call psa_mac_verify_setup() to specify the algorithm and key. + * -# Call psa_mac_update() zero, one or more times, passing a fragment + * of the message each time. The MAC that is calculated is the MAC + * of the concatenation of these messages in order. + * -# At the end of the message, call psa_mac_verify_finish() to finish + * calculating the actual MAC of the message and verify it against + * the expected value. + * + * If an error occurs at any step after a call to psa_mac_verify_setup(), the + * operation will need to be reset by a call to psa_mac_abort(). The + * application may call psa_mac_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_mac_verify_setup(), the application must + * eventually terminate the operation through one of the following methods: + * - A successful call to psa_mac_verify_finish(). + * - A call to psa_mac_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_mac_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c key is not compatible with \c alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \c alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Add a message fragment to a multipart MAC operation. + * + * The application must call psa_mac_sign_setup() or psa_mac_verify_setup() + * before calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_mac_abort(). + * + * \param[in,out] operation Active MAC operation. + * \param[in] input Buffer containing the message fragment to add to + * the MAC calculation. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_update(psa_mac_operation_t *operation, + const uint8_t *input, + size_t input_length); + +/** Finish the calculation of the MAC of a message. + * + * The application must call psa_mac_sign_setup() before calling this function. + * This function calculates the MAC of the message formed by concatenating + * the inputs passed to preceding calls to psa_mac_update(). + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_mac_abort(). + * + * \warning Applications should not call this function if they expect + * a specific value for the MAC. Call psa_mac_verify_finish() instead. + * Beware that comparing integrity or authenticity data such as + * MAC values with a function such as \c memcmp is risky + * because the time taken by the comparison may leak information + * about the MAC value which could allow an attacker to guess + * a valid MAC and thereby bypass security controls. + * + * \param[in,out] operation Active MAC operation. + * \param[out] mac Buffer where the MAC value is to be written. + * \param mac_size Size of the \p mac buffer in bytes. + * \param[out] mac_length On success, the number of bytes + * that make up the MAC value. This is always + * #PSA_MAC_FINAL_SIZE(\c key_type, \c key_bits, \c alg) + * where \c key_type and \c key_bits are the type and + * bit-size respectively of the key and \c alg is the + * MAC algorithm that is calculated. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active mac sign + * operation). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p mac buffer is too small. You can determine a + * sufficient buffer size by calling PSA_MAC_FINAL_SIZE(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, + uint8_t *mac, + size_t mac_size, + size_t *mac_length); + +/** Finish the calculation of the MAC of a message and compare it with + * an expected value. + * + * The application must call psa_mac_verify_setup() before calling this function. + * This function calculates the MAC of the message formed by concatenating + * the inputs passed to preceding calls to psa_mac_update(). It then + * compares the calculated MAC with the expected MAC passed as a + * parameter to this function. + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_mac_abort(). + * + * \note Implementations shall make the best effort to ensure that the + * comparison between the actual MAC and the expected MAC is performed + * in constant time. + * + * \param[in,out] operation Active MAC operation. + * \param[in] mac Buffer containing the expected MAC value. + * \param mac_length Size of the \p mac buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected MAC is identical to the actual MAC of the message. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The MAC of the message was calculated successfully, but it + * differs from the expected MAC. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active mac verify + * operation). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation, + const uint8_t *mac, + size_t mac_length); + +/** Abort a MAC operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_mac_sign_setup() or psa_mac_verify_setup() again. + * + * You may call this function any time after the operation object has + * been initialized by one of the methods described in #psa_mac_operation_t. + * + * In particular, calling psa_mac_abort() after the operation has been + * terminated by a call to psa_mac_abort(), psa_mac_sign_finish() or + * psa_mac_verify_finish() is safe and has no effect. + * + * \param[in,out] operation Initialized MAC operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_abort(psa_mac_operation_t *operation); + +/**@}*/ + +/** \defgroup cipher Symmetric ciphers + * @{ + */ + +/** Encrypt a message using a symmetric cipher. + * + * This function encrypts a message with a random IV (initialization + * vector). Use the multipart operation interface with a + * #psa_cipher_operation_t object to provide other forms of IV. + * + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * \param[in] input Buffer containing the message to encrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the output is to be written. + * The output contains the IV followed by + * the ciphertext proper. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_encrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Decrypt a message using a symmetric cipher. + * + * This function decrypts a message encrypted with a symmetric cipher. + * + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * \param[in] input Buffer containing the message to decrypt. + * This consists of the IV followed by the + * ciphertext proper. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the plaintext is to be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_decrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** The type of the state data structure for multipart cipher operations. + * + * Before calling any function on a cipher operation object, the application + * must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_cipher_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_cipher_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_CIPHER_OPERATION_INIT, + * for example: + * \code + * psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_cipher_operation_init() + * to the structure, for example: + * \code + * psa_cipher_operation_t operation; + * operation = psa_cipher_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure except + * as directed by the documentation of a specific implementation. */ +typedef struct psa_cipher_operation_s psa_cipher_operation_t; + +/** \def PSA_CIPHER_OPERATION_INIT + * + * This macro returns a suitable initializer for a cipher operation object of + * type #psa_cipher_operation_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_CIPHER_OPERATION_INIT {0} +#endif + +/** Return an initial value for a cipher operation object. + */ +static psa_cipher_operation_t psa_cipher_operation_init(void); + +/** Set the key for a multipart symmetric encryption operation. + * + * The sequence of operations to encrypt a message with a symmetric cipher + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_cipher_operation_t, e.g. + * #PSA_CIPHER_OPERATION_INIT. + * -# Call psa_cipher_encrypt_setup() to specify the algorithm and key. + * -# Call either psa_cipher_generate_iv() or psa_cipher_set_iv() to + * generate or set the IV (initialization vector). You should use + * psa_cipher_generate_iv() unless the protocol you are implementing + * requires a specific IV value. + * -# Call psa_cipher_update() zero, one or more times, passing a fragment + * of the message each time. + * -# Call psa_cipher_finish(). + * + * If an error occurs at any step after a call to psa_cipher_encrypt_setup(), + * the operation will need to be reset by a call to psa_cipher_abort(). The + * application may call psa_cipher_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_cipher_encrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_cipher_finish(). + * - A call to psa_cipher_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_cipher_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Set the key for a multipart symmetric decryption operation. + * + * The sequence of operations to decrypt a message with a symmetric cipher + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_cipher_operation_t, e.g. + * #PSA_CIPHER_OPERATION_INIT. + * -# Call psa_cipher_decrypt_setup() to specify the algorithm and key. + * -# Call psa_cipher_set_iv() with the IV (initialization vector) for the + * decryption. If the IV is prepended to the ciphertext, you can call + * psa_cipher_update() on a buffer containing the IV followed by the + * beginning of the message. + * -# Call psa_cipher_update() zero, one or more times, passing a fragment + * of the message each time. + * -# Call psa_cipher_finish(). + * + * If an error occurs at any step after a call to psa_cipher_decrypt_setup(), + * the operation will need to be reset by a call to psa_cipher_abort(). The + * application may call psa_cipher_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_cipher_decrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_cipher_finish(). + * - A call to psa_cipher_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_cipher_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Generate an IV for a symmetric encryption operation. + * + * This function generates a random IV (initialization vector), nonce + * or initial counter value for the encryption operation as appropriate + * for the chosen algorithm, key type and key size. + * + * The application must call psa_cipher_encrypt_setup() before + * calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \param[in,out] operation Active cipher operation. + * \param[out] iv Buffer where the generated IV is to be written. + * \param iv_size Size of the \p iv buffer in bytes. + * \param[out] iv_length On success, the number of bytes of the + * generated IV. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with no IV set). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p iv buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation, + uint8_t *iv, + size_t iv_size, + size_t *iv_length); + +/** Set the IV for a symmetric encryption or decryption operation. + * + * This function sets the IV (initialization vector), nonce + * or initial counter value for the encryption or decryption operation. + * + * The application must call psa_cipher_encrypt_setup() before + * calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \note When encrypting, applications should use psa_cipher_generate_iv() + * instead of this function, unless implementing a protocol that requires + * a non-random IV. + * + * \param[in,out] operation Active cipher operation. + * \param[in] iv Buffer containing the IV to use. + * \param iv_length Size of the IV in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active cipher + * encrypt operation, with no IV set). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size of \p iv is not acceptable for the chosen algorithm, + * or the chosen algorithm does not use an IV. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, + const uint8_t *iv, + size_t iv_length); + +/** Encrypt or decrypt a message fragment in an active cipher operation. + * + * Before calling this function, you must: + * 1. Call either psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup(). + * The choice of setup function determines whether this function + * encrypts or decrypts its input. + * 2. If the algorithm requires an IV, call psa_cipher_generate_iv() + * (recommended when encrypting) or psa_cipher_set_iv(). + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \param[in,out] operation Active cipher operation. + * \param[in] input Buffer containing the message fragment to + * encrypt or decrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the output is to be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with an IV set + * if required for the algorithm). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Finish encrypting or decrypting a message in a cipher operation. + * + * The application must call psa_cipher_encrypt_setup() or + * psa_cipher_decrypt_setup() before calling this function. The choice + * of setup function determines whether this function encrypts or + * decrypts its input. + * + * This function finishes the encryption or decryption of the message + * formed by concatenating the inputs passed to preceding calls to + * psa_cipher_update(). + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \param[in,out] operation Active cipher operation. + * \param[out] output Buffer where the output is to be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total input size passed to this operation is not valid for + * this particular algorithm. For example, the algorithm is a based + * on block cipher and requires a whole number of blocks, but the + * total input size is not a multiple of the block size. + * \retval #PSA_ERROR_INVALID_PADDING + * This is a decryption operation for an algorithm that includes + * padding, and the ciphertext does not contain valid padding. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with an IV set + * if required for the algorithm). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Abort a cipher operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup() again. + * + * You may call this function any time after the operation object has + * been initialized as described in #psa_cipher_operation_t. + * + * In particular, calling psa_cipher_abort() after the operation has been + * terminated by a call to psa_cipher_abort() or psa_cipher_finish() + * is safe and has no effect. + * + * \param[in,out] operation Initialized cipher operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation); + +/**@}*/ + +/** \defgroup aead Authenticated encryption with associated data (AEAD) + * @{ + */ + +/** Process an authenticated encryption operation. + * + * \param handle Handle to the key to use for the operation. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param[in] nonce Nonce or IV to use. + * \param nonce_length Size of the \p nonce buffer in bytes. + * \param[in] additional_data Additional data that will be authenticated + * but not encrypted. + * \param additional_data_length Size of \p additional_data in bytes. + * \param[in] plaintext Data that will be authenticated and + * encrypted. + * \param plaintext_length Size of \p plaintext in bytes. + * \param[out] ciphertext Output buffer for the authenticated and + * encrypted data. The additional data is not + * part of this output. For algorithms where the + * encrypted data and the authentication tag + * are defined as separate outputs, the + * authentication tag is appended to the + * encrypted data. + * \param ciphertext_size Size of the \p ciphertext buffer in bytes. + * This must be at least + * #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\p alg, + * \p plaintext_length). + * \param[out] ciphertext_length On success, the size of the output + * in the \p ciphertext buffer. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not an AEAD algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p ciphertext_size is too small + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_encrypt(psa_key_handle_t handle, + 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 *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length); + +/** Process an authenticated decryption operation. + * + * \param handle Handle to the key to use for the operation. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param[in] nonce Nonce or IV to use. + * \param nonce_length Size of the \p nonce buffer in bytes. + * \param[in] additional_data Additional data that has been authenticated + * but not encrypted. + * \param additional_data_length Size of \p additional_data in bytes. + * \param[in] ciphertext Data that has been authenticated and + * encrypted. For algorithms where the + * encrypted data and the authentication tag + * are defined as separate inputs, the buffer + * must contain the encrypted data followed + * by the authentication tag. + * \param ciphertext_length Size of \p ciphertext in bytes. + * \param[out] plaintext Output buffer for the decrypted data. + * \param plaintext_size Size of the \p plaintext buffer in bytes. + * This must be at least + * #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\p alg, + * \p ciphertext_length). + * \param[out] plaintext_length On success, the size of the output + * in the \p plaintext buffer. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The ciphertext is not authentic. + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not an AEAD algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p plaintext_size or \p nonce_length is too small + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_decrypt(psa_key_handle_t handle, + 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 *ciphertext, + size_t ciphertext_length, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length); + +/** The type of the state data structure for multipart AEAD operations. + * + * Before calling any function on an AEAD operation object, the application + * must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_aead_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_aead_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_AEAD_OPERATION_INIT, + * for example: + * \code + * psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_aead_operation_init() + * to the structure, for example: + * \code + * psa_aead_operation_t operation; + * operation = psa_aead_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure except + * as directed by the documentation of a specific implementation. */ +typedef struct psa_aead_operation_s psa_aead_operation_t; + +/** \def PSA_AEAD_OPERATION_INIT + * + * This macro returns a suitable initializer for an AEAD operation object of + * type #psa_aead_operation_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_AEAD_OPERATION_INIT {0} +#endif + +/** Return an initial value for an AEAD operation object. + */ +static psa_aead_operation_t psa_aead_operation_init(void); + +/** Set the key for a multipart authenticated encryption operation. + * + * The sequence of operations to encrypt a message with authentication + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_aead_operation_t, e.g. + * #PSA_AEAD_OPERATION_INIT. + * -# Call psa_aead_encrypt_setup() to specify the algorithm and key. + * -# If needed, call psa_aead_set_lengths() to specify the length of the + * inputs to the subsequent calls to psa_aead_update_ad() and + * psa_aead_update(). See the documentation of psa_aead_set_lengths() + * for details. + * -# Call either psa_aead_generate_nonce() or psa_aead_set_nonce() to + * generate or set the nonce. You should use + * psa_aead_generate_nonce() unless the protocol you are implementing + * requires a specific nonce value. + * -# Call psa_aead_update_ad() zero, one or more times, passing a fragment + * of the non-encrypted additional authenticated data each time. + * -# Call psa_aead_update() zero, one or more times, passing a fragment + * of the message to encrypt each time. + * -# Call psa_aead_finish(). + * + * If an error occurs at any step after a call to psa_aead_encrypt_setup(), + * the operation will need to be reset by a call to psa_aead_abort(). The + * application may call psa_aead_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_aead_encrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_aead_finish(). + * - A call to psa_aead_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_aead_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not an AEAD algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Set the key for a multipart authenticated decryption operation. + * + * The sequence of operations to decrypt a message with authentication + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_aead_operation_t, e.g. + * #PSA_AEAD_OPERATION_INIT. + * -# Call psa_aead_decrypt_setup() to specify the algorithm and key. + * -# If needed, call psa_aead_set_lengths() to specify the length of the + * inputs to the subsequent calls to psa_aead_update_ad() and + * psa_aead_update(). See the documentation of psa_aead_set_lengths() + * for details. + * -# Call psa_aead_set_nonce() with the nonce for the decryption. + * -# Call psa_aead_update_ad() zero, one or more times, passing a fragment + * of the non-encrypted additional authenticated data each time. + * -# Call psa_aead_update() zero, one or more times, passing a fragment + * of the ciphertext to decrypt each time. + * -# Call psa_aead_verify(). + * + * If an error occurs at any step after a call to psa_aead_decrypt_setup(), + * the operation will need to be reset by a call to psa_aead_abort(). The + * application may call psa_aead_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_aead_decrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_aead_verify(). + * - A call to psa_aead_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_aead_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not an AEAD algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Generate a random nonce for an authenticated encryption operation. + * + * This function generates a random nonce for the authenticated encryption + * operation with an appropriate size for the chosen algorithm, key type + * and key size. + * + * The application must call psa_aead_encrypt_setup() before + * calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \param[in,out] operation Active AEAD operation. + * \param[out] nonce Buffer where the generated nonce is to be + * written. + * \param nonce_size Size of the \p nonce buffer in bytes. + * \param[out] nonce_length On success, the number of bytes of the + * generated nonce. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active aead encrypt + operation, with no nonce set). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p nonce buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation, + uint8_t *nonce, + size_t nonce_size, + size_t *nonce_length); + +/** Set the nonce for an authenticated encryption or decryption operation. + * + * This function sets the nonce for the authenticated + * encryption or decryption operation. + * + * The application must call psa_aead_encrypt_setup() or + * psa_aead_decrypt_setup() before calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \note When encrypting, applications should use psa_aead_generate_nonce() + * instead of this function, unless implementing a protocol that requires + * a non-random IV. + * + * \param[in,out] operation Active AEAD operation. + * \param[in] nonce Buffer containing the nonce to use. + * \param nonce_length Size of the nonce in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with no nonce + * set). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size of \p nonce is not acceptable for the chosen algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation, + const uint8_t *nonce, + size_t nonce_length); + +/** Declare the lengths of the message and additional data for AEAD. + * + * The application must call this function before calling + * psa_aead_update_ad() or psa_aead_update() if the algorithm for + * the operation requires it. If the algorithm does not require it, + * calling this function is optional, but if this function is called + * then the implementation must enforce the lengths. + * + * You may call this function before or after setting the nonce with + * psa_aead_set_nonce() or psa_aead_generate_nonce(). + * + * - For #PSA_ALG_CCM, calling this function is required. + * - For the other AEAD algorithms defined in this specification, calling + * this function is not required. + * - For vendor-defined algorithm, refer to the vendor documentation. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \param[in,out] operation Active AEAD operation. + * \param ad_length Size of the non-encrypted additional + * authenticated data in bytes. + * \param plaintext_length Size of the plaintext to encrypt in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, and + * psa_aead_update_ad() and psa_aead_update() must not have been + * called yet). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * At least one of the lengths is not acceptable for the chosen + * algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation, + size_t ad_length, + size_t plaintext_length); + +/** Pass additional data to an active AEAD operation. + * + * Additional data is authenticated, but not encrypted. + * + * You may call this function multiple times to pass successive fragments + * of the additional data. You may not call this function after passing + * data to encrypt or decrypt with psa_aead_update(). + * + * Before calling this function, you must: + * 1. Call either psa_aead_encrypt_setup() or psa_aead_decrypt_setup(). + * 2. Set the nonce with psa_aead_generate_nonce() or psa_aead_set_nonce(). + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \warning When decrypting, until psa_aead_verify() has returned #PSA_SUCCESS, + * there is no guarantee that the input is valid. Therefore, until + * you have called psa_aead_verify() and it has returned #PSA_SUCCESS, + * treat the input as untrusted and prepare to undo any action that + * depends on the input if psa_aead_verify() returns an error status. + * + * \param[in,out] operation Active AEAD operation. + * \param[in] input Buffer containing the fragment of + * additional data. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, have a nonce + * set, have lengths set if required by the algorithm, and + * psa_aead_update() must not have been called yet). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total input length overflows the additional data length that + * was previously specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length); + +/** Encrypt or decrypt a message fragment in an active AEAD operation. + * + * Before calling this function, you must: + * 1. Call either psa_aead_encrypt_setup() or psa_aead_decrypt_setup(). + * The choice of setup function determines whether this function + * encrypts or decrypts its input. + * 2. Set the nonce with psa_aead_generate_nonce() or psa_aead_set_nonce(). + * 3. Call psa_aead_update_ad() to pass all the additional data. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \warning When decrypting, until psa_aead_verify() has returned #PSA_SUCCESS, + * there is no guarantee that the input is valid. Therefore, until + * you have called psa_aead_verify() and it has returned #PSA_SUCCESS: + * - Do not use the output in any way other than storing it in a + * confidential location. If you take any action that depends + * on the tentative decrypted data, this action will need to be + * undone if the input turns out not to be valid. Furthermore, + * if an adversary can observe that this action took place + * (for example through timing), they may be able to use this + * fact as an oracle to decrypt any message encrypted with the + * same key. + * - In particular, do not copy the output anywhere but to a + * memory or storage space that you have exclusive access to. + * + * This function does not require the input to be aligned to any + * particular block boundary. If the implementation can only process + * a whole block at a time, it must consume all the input provided, but + * it may delay the end of the corresponding output until a subsequent + * call to psa_aead_update(), psa_aead_finish() or psa_aead_verify() + * provides sufficient input. The amount of data that can be delayed + * in this way is bounded by #PSA_AEAD_UPDATE_OUTPUT_SIZE. + * + * \param[in,out] operation Active AEAD operation. + * \param[in] input Buffer containing the message fragment to + * encrypt or decrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the output is to be written. + * \param output_size Size of the \p output buffer in bytes. + * This must be at least + * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c alg, + * \p input_length) where \c alg is the + * algorithm that is being calculated. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, have a nonce + * set, and have lengths set if required by the algorithm). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * You can determine a sufficient buffer size by calling + * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c alg, \p input_length) + * where \c alg is the algorithm that is being calculated. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update_ad() so far is + * less than the additional data length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total input length overflows the plaintext length that + * was previously specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_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); + +/** Finish encrypting a message in an AEAD operation. + * + * The operation must have been set up with psa_aead_encrypt_setup(). + * + * This function finishes the authentication of the additional data + * formed by concatenating the inputs passed to preceding calls to + * psa_aead_update_ad() with the plaintext formed by concatenating the + * inputs passed to preceding calls to psa_aead_update(). + * + * This function has two output buffers: + * - \p ciphertext contains trailing ciphertext that was buffered from + * preceding calls to psa_aead_update(). + * - \p tag contains the authentication tag. Its length is always + * #PSA_AEAD_TAG_LENGTH(\c alg) where \c alg is the AEAD algorithm + * that the operation performs. + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \param[in,out] operation Active AEAD operation. + * \param[out] ciphertext Buffer where the last part of the ciphertext + * is to be written. + * \param ciphertext_size Size of the \p ciphertext buffer in bytes. + * This must be at least + * #PSA_AEAD_FINISH_OUTPUT_SIZE(\c alg) where + * \c alg is the algorithm that is being + * calculated. + * \param[out] ciphertext_length On success, the number of bytes of + * returned ciphertext. + * \param[out] tag Buffer where the authentication tag is + * to be written. + * \param tag_size Size of the \p tag buffer in bytes. + * This must be at least + * #PSA_AEAD_TAG_LENGTH(\c alg) where \c alg is + * the algorithm that is being calculated. + * \param[out] tag_length On success, the number of bytes + * that make up the returned tag. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active encryption + * operation with a nonce set). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p ciphertext or \p tag buffer is too small. + * You can determine a sufficient buffer size for \p ciphertext by + * calling #PSA_AEAD_FINISH_OUTPUT_SIZE(\c alg) + * where \c alg is the algorithm that is being calculated. + * You can determine a sufficient buffer size for \p tag by + * calling #PSA_AEAD_TAG_LENGTH(\c alg). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update_ad() so far is + * less than the additional data length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update() so far is + * less than the plaintext length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_finish(psa_aead_operation_t *operation, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length, + uint8_t *tag, + size_t tag_size, + size_t *tag_length); + +/** Finish authenticating and decrypting a message in an AEAD operation. + * + * The operation must have been set up with psa_aead_decrypt_setup(). + * + * This function finishes the authenticated decryption of the message + * components: + * + * - The additional data consisting of the concatenation of the inputs + * passed to preceding calls to psa_aead_update_ad(). + * - The ciphertext consisting of the concatenation of the inputs passed to + * preceding calls to psa_aead_update(). + * - The tag passed to this function call. + * + * If the authentication tag is correct, this function outputs any remaining + * plaintext and reports success. If the authentication tag is not correct, + * this function returns #PSA_ERROR_INVALID_SIGNATURE. + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \note Implementations shall make the best effort to ensure that the + * comparison between the actual tag and the expected tag is performed + * in constant time. + * + * \param[in,out] operation Active AEAD operation. + * \param[out] plaintext Buffer where the last part of the plaintext + * is to be written. This is the remaining data + * from previous calls to psa_aead_update() + * that could not be processed until the end + * of the input. + * \param plaintext_size Size of the \p plaintext buffer in bytes. + * This must be at least + * #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c alg) where + * \c alg is the algorithm that is being + * calculated. + * \param[out] plaintext_length On success, the number of bytes of + * returned plaintext. + * \param[in] tag Buffer containing the authentication tag. + * \param tag_length Size of the \p tag buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The calculations were successful, but the authentication tag is + * not correct. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active decryption + * operation with a nonce set). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p plaintext buffer is too small. + * You can determine a sufficient buffer size for \p plaintext by + * calling #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c alg) + * where \c alg is the algorithm that is being calculated. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update_ad() so far is + * less than the additional data length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update() so far is + * less than the plaintext length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_verify(psa_aead_operation_t *operation, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length, + const uint8_t *tag, + size_t tag_length); + +/** Abort an AEAD operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_aead_encrypt_setup() or psa_aead_decrypt_setup() again. + * + * You may call this function any time after the operation object has + * been initialized as described in #psa_aead_operation_t. + * + * In particular, calling psa_aead_abort() after the operation has been + * terminated by a call to psa_aead_abort(), psa_aead_finish() or + * psa_aead_verify() is safe and has no effect. + * + * \param[in,out] operation Initialized AEAD operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_abort(psa_aead_operation_t *operation); + +/**@}*/ + +/** \defgroup asymmetric Asymmetric cryptography + * @{ + */ + +/** + * \brief Sign a hash or short message with a private key. + * + * Note that to perform a hash-and-sign signature algorithm, you must + * first calculate the hash by calling psa_hash_setup(), psa_hash_update() + * and psa_hash_finish(). Then pass the resulting hash as the \p hash + * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) + * to determine the hash algorithm to use. + * + * \param handle Handle to the key to use for the operation. + * It must be an asymmetric key pair. + * \param alg A signature algorithm that is compatible with + * the type of \p handle. + * \param[in] hash The hash or message to sign. + * \param hash_length Size of the \p hash buffer in bytes. + * \param[out] signature Buffer where the signature is to be written. + * \param signature_size Size of the \p signature buffer in bytes. + * \param[out] signature_length On success, the number of bytes + * that make up the returned signature value. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p signature buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p handle. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_sign_hash(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length); + +/** + * \brief Verify the signature a hash or short message using a public key. + * + * Note that to perform a hash-and-sign signature algorithm, you must + * first calculate the hash by calling psa_hash_setup(), psa_hash_update() + * and psa_hash_finish(). Then pass the resulting hash as the \p hash + * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) + * to determine the hash algorithm to use. + * + * \param handle Handle to the key to use for the operation. + * It must be a public key or an asymmetric key pair. + * \param alg A signature algorithm that is compatible with + * the type of \p handle. + * \param[in] hash The hash or message whose signature is to be + * verified. + * \param hash_length Size of the \p hash buffer in bytes. + * \param[in] signature Buffer containing the signature to verify. + * \param signature_length Size of the \p signature buffer in bytes. + * + * \retval #PSA_SUCCESS + * The signature is valid. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The calculation was perfomed successfully, but the passed + * signature is not a valid signature. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_verify_hash(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length); + +/** + * \brief Encrypt a short message with a public key. + * + * \param handle Handle to the key to use for the operation. + * It must be a public key or an asymmetric + * key pair. + * \param alg An asymmetric encryption algorithm that is + * compatible with the type of \p handle. + * \param[in] input The message to encrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[in] salt A salt or label, if supported by the + * encryption algorithm. + * If the algorithm does not support a + * salt, pass \c NULL. + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass \c NULL. + * + * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported. + * \param salt_length Size of the \p salt buffer in bytes. + * If \p salt is \c NULL, pass 0. + * \param[out] output Buffer where the encrypted message is to + * be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p handle. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_asymmetric_encrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** + * \brief Decrypt a short message with a private key. + * + * \param handle Handle to the key to use for the operation. + * It must be an asymmetric key pair. + * \param alg An asymmetric encryption algorithm that is + * compatible with the type of \p handle. + * \param[in] input The message to decrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[in] salt A salt or label, if supported by the + * encryption algorithm. + * If the algorithm does not support a + * salt, pass \c NULL. + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass \c NULL. + * + * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported. + * \param salt_length Size of the \p salt buffer in bytes. + * If \p salt is \c NULL, pass 0. + * \param[out] output Buffer where the decrypted message is to + * be written. + * \param output_size Size of the \c output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p handle. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_INVALID_PADDING + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_asymmetric_decrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/**@}*/ + +/** \defgroup key_derivation Key derivation and pseudorandom generation + * @{ + */ + +/** The type of the state data structure for key derivation operations. + * + * Before calling any function on a key derivation operation object, the + * application must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_key_derivation_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_key_derivation_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_KEY_DERIVATION_OPERATION_INIT, + * for example: + * \code + * psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_key_derivation_operation_init() + * to the structure, for example: + * \code + * psa_key_derivation_operation_t operation; + * operation = psa_key_derivation_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure except + * as directed by the documentation of a specific implementation. + */ +typedef struct psa_key_derivation_s psa_key_derivation_operation_t; + +/** \def PSA_KEY_DERIVATION_OPERATION_INIT + * + * This macro returns a suitable initializer for a key derivation operation + * object of type #psa_key_derivation_operation_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_KEY_DERIVATION_OPERATION_INIT {0} +#endif + +/** Return an initial value for a key derivation operation object. + */ +static psa_key_derivation_operation_t psa_key_derivation_operation_init(void); + +/** Set up a key derivation operation. + * + * A key derivation algorithm takes some inputs and uses them to generate + * a byte stream in a deterministic way. + * This byte stream can be used to produce keys and other + * cryptographic material. + * + * To derive a key: + * -# Start with an initialized object of type #psa_key_derivation_operation_t. + * -# Call psa_key_derivation_setup() to select the algorithm. + * -# Provide the inputs for the key derivation by calling + * psa_key_derivation_input_bytes() or psa_key_derivation_input_key() + * as appropriate. Which inputs are needed, in what order, and whether + * they may be keys and if so of what type depends on the algorithm. + * -# Optionally set the operation's maximum capacity with + * psa_key_derivation_set_capacity(). You may do this before, in the middle + * of or after providing inputs. For some algorithms, this step is mandatory + * because the output depends on the maximum capacity. + * -# To derive a key, call psa_key_derivation_output_key(). + * To derive a byte string for a different purpose, call + * psa_key_derivation_output_bytes(). + * Successive calls to these functions use successive output bytes + * calculated by the key derivation algorithm. + * -# Clean up the key derivation operation object with + * psa_key_derivation_abort(). + * + * If this function returns an error, the key derivation operation object is + * not changed. + * + * If an error occurs at any step after a call to psa_key_derivation_setup(), + * the operation will need to be reset by a call to psa_key_derivation_abort(). + * + * Implementations must reject an attempt to derive a key of size 0. + * + * \param[in,out] operation The key derivation operation object + * to set up. It must + * have been initialized but not set up yet. + * \param alg The key derivation algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_KEY_DERIVATION(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c alg is not a key derivation algorithm. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \c alg is not supported or is not a key derivation algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_setup( + psa_key_derivation_operation_t *operation, + psa_algorithm_t alg); + +/** Retrieve the current capacity of a key derivation operation. + * + * The capacity of a key derivation is the maximum number of bytes that it can + * return. When you get *N* bytes of output from a key derivation operation, + * this reduces its capacity by *N*. + * + * \param[in] operation The operation to query. + * \param[out] capacity On success, the capacity of the operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_get_capacity( + const psa_key_derivation_operation_t *operation, + size_t *capacity); + +/** Set the maximum capacity of a key derivation operation. + * + * The capacity of a key derivation operation is the maximum number of bytes + * that the key derivation operation can return from this point onwards. + * + * \param[in,out] operation The key derivation operation object to modify. + * \param capacity The new capacity of the operation. + * It must be less or equal to the operation's + * current capacity. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p capacity is larger than the operation's current capacity. + * In this case, the operation object remains valid and its capacity + * remains unchanged. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_set_capacity( + psa_key_derivation_operation_t *operation, + size_t capacity); + +/** Use the maximum possible capacity for a key derivation operation. + * + * Use this value as the capacity argument when setting up a key derivation + * to indicate that the operation should have the maximum possible capacity. + * The value of the maximum possible capacity depends on the key derivation + * algorithm. + */ +#define PSA_KEY_DERIVATION_UNLIMITED_CAPACITY ((size_t)(-1)) + +/** Provide an input for key derivation or key agreement. + * + * Which inputs are required and in what order depends on the algorithm. + * Refer to the documentation of each key derivation or key agreement + * algorithm for information. + * + * This function passes direct inputs, which is usually correct for + * non-secret inputs. To pass a secret input, which should be in a key + * object, call psa_key_derivation_input_key() instead of this function. + * Refer to the documentation of individual step types + * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t) + * for more information. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() and must not + * have produced any output yet. + * \param step Which step the input data is for. + * \param[in] data Input data to use. + * \param data_length Size of the \p data buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step is not compatible with the operation's algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step does not allow direct inputs. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this input \p step. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_input_bytes( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length); + +/** Provide an input for key derivation in the form of a key. + * + * Which inputs are required and in what order depends on the algorithm. + * Refer to the documentation of each key derivation or key agreement + * algorithm for information. + * + * This function obtains input from a key object, which is usually correct for + * secret inputs or for non-secret personalization strings kept in the key + * store. To pass a non-secret parameter which is not in the key store, + * call psa_key_derivation_input_bytes() instead of this function. + * Refer to the documentation of individual step types + * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t) + * for more information. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() and must not + * have produced any output yet. + * \param step Which step the input data is for. + * \param handle Handle to the key. It must have an + * appropriate type for \p step and must + * allow the usage #PSA_KEY_USAGE_DERIVE. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step is not compatible with the operation's algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step does not allow key inputs of the given type + * or does not allow key inputs at all. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this input \p step. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_input_key( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_handle_t handle); + +/** Perform a key agreement and use the shared secret as input to a key + * derivation. + * + * A key agreement algorithm takes two inputs: a private key \p private_key + * a public key \p peer_key. + * The result of this function is passed as input to a key derivation. + * The output of this key derivation can be extracted by reading from the + * resulting operation to produce keys and other cryptographic material. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() with a + * key agreement and derivation algorithm + * \c alg (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_KEY_AGREEMENT(\c alg) is true + * and #PSA_ALG_IS_RAW_KEY_AGREEMENT(\c alg) + * is false). + * The operation must be ready for an + * input of the type given by \p step. + * \param step Which step the input data is for. + * \param private_key Handle to the private key to use. + * \param[in] peer_key Public key of the peer. The peer key must be in the + * same format that psa_import_key() accepts for the + * public key type corresponding to the type of + * private_key. That is, this function performs the + * equivalent of + * #psa_import_key(..., + * `peer_key`, `peer_key_length`) where + * with key attributes indicating the public key + * type corresponding to the type of `private_key`. + * For example, for EC keys, this means that peer_key + * is interpreted as a point on the curve that the + * private key is on. The standard formats for public + * keys are documented in the documentation of + * psa_export_public_key(). + * \param peer_key_length Size of \p peer_key in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this key agreement \p step. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c private_key is not compatible with \c alg, + * or \p peer_key is not valid for \c alg or not compatible with + * \c private_key. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \c alg is not supported or is not a key derivation algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step does not allow an input resulting from a key agreement. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_key_agreement( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_handle_t private_key, + const uint8_t *peer_key, + size_t peer_key_length); + +/** Read some data from a key derivation operation. + * + * This function calculates output bytes from a key derivation algorithm and + * return those bytes. + * If you view the key derivation's output as a stream of bytes, this + * function destructively reads the requested number of bytes from the + * stream. + * The operation's capacity decreases by the number of bytes read. + * + * If this function returns an error status other than + * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to read from. + * \param[out] output Buffer where the output will be written. + * \param output_length Number of bytes to output. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INSUFFICIENT_DATA + * The operation's capacity was less than + * \p output_length bytes. Note that in this case, + * no output is written to the output buffer. + * The operation's capacity is set to 0, thus + * subsequent calls to this function will not + * succeed, even with a smaller output buffer. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active and completed + * all required input steps). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_output_bytes( + psa_key_derivation_operation_t *operation, + uint8_t *output, + size_t output_length); + +/** Derive a key from an ongoing key derivation operation. + * + * This function calculates output bytes from a key derivation algorithm + * and uses those bytes to generate a key deterministically. + * The key's location, usage policy, type and size are taken from + * \p attributes. + * + * If you view the key derivation's output as a stream of bytes, this + * function destructively reads as many bytes as required from the + * stream. + * The operation's capacity decreases by the number of bytes read. + * + * If this function returns an error status other than + * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * How much output is produced and consumed from the operation, and how + * the key is derived, depends on the key type: + * + * - For key types for which the key is an arbitrary sequence of bytes + * of a given size, this function is functionally equivalent to + * calling #psa_key_derivation_output_bytes + * and passing the resulting output to #psa_import_key. + * However, this function has a security benefit: + * if the implementation provides an isolation boundary then + * the key material is not exposed outside the isolation boundary. + * As a consequence, for these key types, this function always consumes + * exactly (\p bits / 8) bytes from the operation. + * The following key types defined in this specification follow this scheme: + * + * - #PSA_KEY_TYPE_AES; + * - #PSA_KEY_TYPE_ARC4; + * - #PSA_KEY_TYPE_CAMELLIA; + * - #PSA_KEY_TYPE_DERIVE; + * - #PSA_KEY_TYPE_HMAC. + * + * - For ECC keys on a Montgomery elliptic curve + * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a + * Montgomery curve), this function always draws a byte string whose + * length is determined by the curve, and sets the mandatory bits + * accordingly. That is: + * + * - #PSA_ECC_CURVE_CURVE25519: draw a 32-byte string + * and process it as specified in RFC 7748 §5. + * - #PSA_ECC_CURVE_CURVE448: draw a 56-byte string + * and process it as specified in RFC 7748 §5. + * + * - For key types for which the key is represented by a single sequence of + * \p bits bits with constraints as to which bit sequences are acceptable, + * this function draws a byte string of length (\p bits / 8) bytes rounded + * up to the nearest whole number of bytes. If the resulting byte string + * is acceptable, it becomes the key, otherwise the drawn bytes are discarded. + * This process is repeated until an acceptable byte string is drawn. + * The byte string drawn from the operation is interpreted as specified + * for the output produced by psa_export_key(). + * The following key types defined in this specification follow this scheme: + * + * - #PSA_KEY_TYPE_DES. + * Force-set the parity bits, but discard forbidden weak keys. + * For 2-key and 3-key triple-DES, the three keys are generated + * successively (for example, for 3-key triple-DES, + * if the first 8 bytes specify a weak key and the next 8 bytes do not, + * discard the first 8 bytes, use the next 8 bytes as the first key, + * and continue reading output from the operation to derive the other + * two keys). + * - Finite-field Diffie-Hellman keys (#PSA_KEY_TYPE_DH_KEY_PAIR(\c group) + * where \c group designates any Diffie-Hellman group) and + * ECC keys on a Weierstrass elliptic curve + * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a + * Weierstrass curve). + * For these key types, interpret the byte string as integer + * in big-endian order. Discard it if it is not in the range + * [0, *N* - 2] where *N* is the boundary of the private key domain + * (the prime *p* for Diffie-Hellman, the subprime *q* for DSA, + * or the order of the curve's base point for ECC). + * Add 1 to the resulting integer and use this as the private key *x*. + * This method allows compliance to NIST standards, specifically + * the methods titled "key-pair generation by testing candidates" + * in NIST SP 800-56A §5.6.1.1.4 for Diffie-Hellman, + * in FIPS 186-4 §B.1.2 for DSA, and + * in NIST SP 800-56A §5.6.1.2.2 or + * FIPS 186-4 §B.4.2 for elliptic curve keys. + * + * - For other key types, including #PSA_KEY_TYPE_RSA_KEY_PAIR, + * the way in which the operation output is consumed is + * implementation-defined. + * + * In all cases, the data that is read is discarded from the operation. + * The operation's capacity is decreased by the number of bytes read. + * + * For algorithms that take an input step #PSA_KEY_DERIVATION_INPUT_SECRET, + * the input to that step must be provided with psa_key_derivation_input_key(). + * Future versions of this specification may include additional restrictions + * on the derived key based on the attributes and strength of the secret key. + * + * \param[in] attributes The attributes for the new key. + * \param[in,out] operation The key derivation operation object to read from. + * \param[out] handle On success, a handle to the newly created key. + * \c 0 on failure. + * + * \retval #PSA_SUCCESS + * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_INSUFFICIENT_DATA + * There was not enough data to create the desired key. + * Note that in this case, no output is written to the output buffer. + * The operation's capacity is set to 0, thus subsequent calls to + * this function will not succeed, even with a smaller output buffer. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The key type or key size is not supported, either by the + * implementation in general or in this particular location. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The provided key attributes are not valid for the operation. + * \retval #PSA_ERROR_NOT_PERMITTED + * The #PSA_KEY_DERIVATION_INPUT_SECRET input was not provided through + * a key. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active and completed + * all required input steps). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_output_key( + const psa_key_attributes_t *attributes, + psa_key_derivation_operation_t *operation, + psa_key_handle_t *handle); + +/** Abort a key derivation operation. + * + * Aborting an operation frees all associated resources except for the \c + * operation structure itself. Once aborted, the operation object can be reused + * for another operation by calling psa_key_derivation_setup() again. + * + * This function may be called at any time after the operation + * object has been initialized as described in #psa_key_derivation_operation_t. + * + * In particular, it is valid to call psa_key_derivation_abort() twice, or to + * call psa_key_derivation_abort() on an operation that has not been set up. + * + * \param[in,out] operation The operation to abort. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_abort( + psa_key_derivation_operation_t *operation); + +/** Perform a key agreement and return the raw shared secret. + * + * \warning The raw result of a key agreement algorithm such as finite-field + * Diffie-Hellman or elliptic curve Diffie-Hellman has biases and should + * not be used directly as key material. It should instead be passed as + * input to a key derivation algorithm. To chain a key agreement with + * a key derivation, use psa_key_derivation_key_agreement() and other + * functions from the key derivation interface. + * + * \param alg The key agreement algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_RAW_KEY_AGREEMENT(\p alg) + * is true). + * \param private_key Handle to the private key to use. + * \param[in] peer_key Public key of the peer. It must be + * in the same format that psa_import_key() + * accepts. The standard formats for public + * keys are documented in the documentation + * of psa_export_public_key(). + * \param peer_key_length Size of \p peer_key in bytes. + * \param[out] output Buffer where the decrypted message is to + * be written. + * \param output_size Size of the \c output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p alg is not a key agreement algorithm + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p private_key is not compatible with \p alg, + * or \p peer_key is not valid for \p alg or not compatible with + * \p private_key. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p output_size is too small + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not a supported key agreement algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, + psa_key_handle_t private_key, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/**@}*/ + +/** \defgroup random Random generation + * @{ + */ + +/** + * \brief Generate random bytes. + * + * \warning This function **can** fail! Callers MUST check the return status + * and MUST NOT use the content of the output buffer if the return + * status is not #PSA_SUCCESS. + * + * \note To generate a key, use psa_generate_key() instead. + * + * \param[out] output Output buffer for the generated data. + * \param output_size Number of bytes to generate and output. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_generate_random(uint8_t *output, + size_t output_size); + +/** + * \brief Generate a key or key pair. + * + * The key is generated randomly. + * Its location, usage policy, type and size are taken from \p attributes. + * + * Implementations must reject an attempt to generate a key of size 0. + * + * The following type-specific considerations apply: + * - For RSA keys (#PSA_KEY_TYPE_RSA_KEY_PAIR), + * the public exponent is 65537. + * The modulus is a product of two probabilistic primes + * between 2^{n-1} and 2^n where n is the bit size specified in the + * attributes. + * + * \param[in] attributes The attributes for the new key. + * \param[out] handle On success, a handle to the newly created key. + * \c 0 on failure. + * + * \retval #PSA_SUCCESS + * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, + psa_key_handle_t *handle); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +/* The file "crypto_sizes.h" contains definitions for size calculation + * macros whose definitions are implementation-specific. */ +#include "psa/crypto_sizes.h" + +/* The file "crypto_client_struct.h" contains definitions for structures + * whose definitions differ in the client view and the PSA server + * implementation in TF-M. */ +#include "psa/crypto_client_struct.h" + + +/* The file "crypto_struct.h" contains definitions for + * implementation-specific structs that are declared above. */ +#include "psa/crypto_struct.h" + +/* The file "crypto_extra.h" contains vendor-specific definitions. This + * can include vendor-defined algorithms, extra functions, etc. */ +#include "psa/crypto_extra.h" + +#endif /* PSA_CRYPTO_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_client_struct.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_client_struct.h new file mode 100644 index 0000000..1d919b0 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_client_struct.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +/** + * \file psa/crypto_client_struct.h + * + * \brief PSA cryptography client key attribute definitions + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * This file contains the definitions of some data structures with + * PSA crypto client specific definitions. This is for implementations + * with isolation between the Client applications and the Crypto + * Server module, it is expected that the front-end and the back-end + * would have different versions of the data structure. + */ +#ifndef PSA_CRYPTO_CLIENT_STRUCT_H +#define PSA_CRYPTO_CLIENT_STRUCT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* This is the client view of the `key_attributes` structure. Only + * fields which need to be set by the PSA crypto client are present. + * The PSA crypto service will maintain a different version of the + * data structure internally. */ +struct psa_client_key_attributes_s +{ + uint32_t type; + uint32_t lifetime; + uint32_t id; + uint32_t alg; + uint32_t alg2; + uint32_t usage; + uint16_t bits; +}; + +#define PSA_CLIENT_KEY_ATTRIBUTES_INIT {0, 0, 0, 0, 0, 0, 0} + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_CLIENT_STRUCT_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_compat.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_compat.h new file mode 100644 index 0000000..518008b --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_compat.h @@ -0,0 +1,111 @@ +/** + * \file psa/crypto_compat.h + * + * \brief PSA cryptography module: Backward compatibility aliases + * + * This header declares alternative names for macro and functions. + * New application code should not use these names. + * These names may be removed in a future version of Mbed Crypto. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + */ +/* + * Copyright (C) 2019-2020, ARM Limited, 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef PSA_CRYPTO_COMPAT_H +#define PSA_CRYPTO_COMPAT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +/* + * Mechanism for declaring deprecated values + */ +#if defined(MBEDTLS_DEPRECATED_WARNING) && !defined(MBEDTLS_PSA_DEPRECATED) +#define MBEDTLS_PSA_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_PSA_DEPRECATED +#endif + +typedef MBEDTLS_PSA_DEPRECATED size_t mbedtls_deprecated_size_t; +typedef MBEDTLS_PSA_DEPRECATED psa_status_t mbedtls_deprecated_psa_status_t; +typedef MBEDTLS_PSA_DEPRECATED psa_key_usage_t mbedtls_deprecated_psa_key_usage_t; + +#define MBEDTLS_DEPRECATED_CONSTANT( type, value ) \ + ( (mbedtls_deprecated_##type) ( value ) ) + +/* + * Deprecated PSA Crypto error code definitions (PSA Crypto API <= 1.0 beta2) + */ +#define PSA_ERROR_UNKNOWN_ERROR \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_GENERIC_ERROR ) +#define PSA_ERROR_OCCUPIED_SLOT \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_ALREADY_EXISTS ) +#define PSA_ERROR_EMPTY_SLOT \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_DOES_NOT_EXIST ) +#define PSA_ERROR_INSUFFICIENT_CAPACITY \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_INSUFFICIENT_DATA ) +#define PSA_ERROR_TAMPERING_DETECTED \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_CORRUPTION_DETECTED ) + +/* + * Deprecated PSA Crypto numerical encodings (PSA Crypto API <= 1.0 beta3) + */ +#define PSA_KEY_USAGE_SIGN \ + MBEDTLS_DEPRECATED_CONSTANT( psa_key_usage_t, PSA_KEY_USAGE_SIGN_HASH ) +#define PSA_KEY_USAGE_VERIFY \ + MBEDTLS_DEPRECATED_CONSTANT( psa_key_usage_t, PSA_KEY_USAGE_VERIFY_HASH ) + +/* + * Deprecated PSA Crypto size calculation macros (PSA Crypto API <= 1.0 beta3) + */ +#define PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE \ + MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_SIGNATURE_MAX_SIZE ) +#define PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE( key_type, key_bits, alg ) \ + MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_SIGN_OUTPUT_SIZE( key_type, key_bits, alg ) ) + +/* + * Deprecated PSA Crypto function names (PSA Crypto API <= 1.0 beta3) + */ +MBEDTLS_PSA_DEPRECATED psa_status_t psa_asymmetric_sign( psa_key_handle_t key, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length ); + +MBEDTLS_PSA_DEPRECATED psa_status_t psa_asymmetric_verify( psa_key_handle_t key, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length ); + +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_COMPAT_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_extra.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_extra.h new file mode 100644 index 0000000..d658b76 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_extra.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +/** + * \file psa/crypto_extra.h + * + * \brief PSA cryptography module: vendor extensions + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * This file is reserved for vendor-specific definitions. + */ + +#ifndef PSA_CRYPTO_EXTRA_H +#define PSA_CRYPTO_EXTRA_H + +#include "psa/crypto_compat.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \addtogroup crypto_types + * @{ + */ + +/** DSA public key. + * + * The import and export format is the + * representation of the public key `y = g^x mod p` as a big-endian byte + * string. The length of the byte string is the length of the base prime `p` + * in bytes. + */ +#define PSA_KEY_TYPE_DSA_PUBLIC_KEY ((psa_key_type_t)0x60020000) + +/** DSA key pair (private and public key). + * + * The import and export format is the + * representation of the private key `x` as a big-endian byte string. The + * length of the byte string is the private key size in bytes (leading zeroes + * are not stripped). + * + * Determinstic DSA key derivation with psa_generate_derived_key follows + * FIPS 186-4 §B.1.2: interpret the byte string as integer + * in big-endian order. Discard it if it is not in the range + * [0, *N* - 2] where *N* is the boundary of the private key domain + * (the prime *p* for Diffie-Hellman, the subprime *q* for DSA, + * or the order of the curve's base point for ECC). + * Add 1 to the resulting integer and use this as the private key *x*. + * + */ +#define PSA_KEY_TYPE_DSA_KEY_PAIR ((psa_key_type_t)0x70020000) + +/**@}*/ + +/** \brief Declare the enrollment algorithm for a key. + * + * An operation on a key may indifferently use the algorithm set with + * psa_set_key_algorithm() or with this function. + * + * \param[out] attributes The attribute structure to write to. + * \param alg2 A second algorithm that the key may be used + * for, in addition to the algorithm set with + * psa_set_key_algorithm(). + * + * \warning Setting an enrollment algorithm is not recommended, because + * using the same key with different algorithms can allow some + * attacks based on arithmetic relations between different + * computations made with the same key, or can escalate harmless + * side channels into exploitable ones. Use this function only + * if it is necessary to support a protocol for which it has been + * verified that the usage of the key with multiple algorithms + * is safe. + */ +static inline void psa_set_key_enrollment_algorithm( + psa_key_attributes_t *attributes, + psa_algorithm_t alg2) +{ + attributes->alg2 = alg2; +} + +/** Retrieve the enrollment algorithm policy from key attributes. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The enrollment algorithm stored in the attribute structure. + */ +static inline psa_algorithm_t psa_get_key_enrollment_algorithm( + const psa_key_attributes_t *attributes) +{ + return attributes->alg2; +} + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_EXTRA_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_platform.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_platform.h new file mode 100644 index 0000000..c3120e4 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_platform.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +/** + * \file psa/crypto_platform.h + * + * \brief PSA cryptography module: Mbed TLS platform definitions + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * This file contains platform-dependent type definitions. + * + * In implementations with isolation between the application and the + * cryptography module, implementers should take care to ensure that + * the definitions that are exposed to applications match what the + * module implements. + */ + +#ifndef PSA_CRYPTO_PLATFORM_H +#define PSA_CRYPTO_PLATFORM_H + +/* PSA requires several types which C99 provides in stdint.h. */ +#include + +/* Integral type representing a key handle. */ +typedef uint16_t psa_key_handle_t; + +/* This implementation distinguishes *application key identifiers*, which + * are the key identifiers specified by the application, from + * *key file identifiers*, which are the key identifiers that the library + * sees internally. The two types can be different if there is a remote + * call layer between the application and the library which supports + * multiple client applications that do not have access to each others' + * keys. The point of having different types is that the key file + * identifier may encode not only the key identifier specified by the + * application, but also the the identity of the application. + * + * Note that this is an internal concept of the library and the remote + * call layer. The application itself never sees anything other than + * #psa_app_key_id_t with its standard definition. + */ + +/* The application key identifier is always what the application sees as + * #psa_key_id_t. */ +typedef uint32_t psa_app_key_id_t; + +#endif /* PSA_CRYPTO_PLATFORM_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_sizes.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_sizes.h new file mode 100644 index 0000000..4f67501 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_sizes.h @@ -0,0 +1,650 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +/** + * \file psa/crypto_sizes.h + * + * \brief PSA cryptography module: Mbed TLS buffer size macros + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * This file contains the definitions of macros that are useful to + * compute buffer sizes. The signatures and semantics of these macros + * are standardized, but the definitions are not, because they depend on + * the available algorithms and, in some cases, on permitted tolerances + * on buffer sizes. + * + * In implementations with isolation between the application and the + * cryptography module, implementers should take care to ensure that + * the definitions that are exposed to applications match what the + * module implements. + * + * Macros that compute sizes whose values do not depend on the + * implementation are in crypto.h. + */ + +#ifndef PSA_CRYPTO_SIZES_H +#define PSA_CRYPTO_SIZES_H + +#define PSA_BITS_TO_BYTES(bits) (((bits) + 7) / 8) +#define PSA_BYTES_TO_BITS(bytes) ((bytes) * 8) + +#define PSA_ROUND_UP_TO_MULTIPLE(block_size, length) \ + (((length) + (block_size) - 1) / (block_size) * (block_size)) + +/** The size of the output of psa_hash_finish(), in bytes. + * + * This is also the hash size that psa_hash_verify() expects. + * + * \param alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p alg) is true), or an HMAC algorithm + * (#PSA_ALG_HMAC(\c hash_alg) where \c hash_alg is a + * hash algorithm). + * + * \return The hash size for the specified hash algorithm. + * If the hash algorithm is not recognized, return 0. + * An implementation may return either 0 or the correct size + * for a hash algorithm that it recognizes, but does not support. + */ +#define PSA_HASH_SIZE(alg) \ + ( \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD2 ? 16 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD4 ? 16 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 16 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 20 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 20 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_224 ? 28 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_256 ? 32 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_384 ? 48 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512 ? 64 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 28 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 32 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 28 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 32 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 48 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 64 : \ + 0) + +/** \def PSA_HASH_MAX_SIZE + * + * Maximum size of a hash. + * + * This macro must expand to a compile-time constant integer. This value + * should be the maximum size of a hash supported by the implementation, + * in bytes, and must be no smaller than this maximum. + */ +/* Note: for HMAC-SHA-3, the block size is 144 bytes for HMAC-SHA3-226, + * 136 bytes for HMAC-SHA3-256, 104 bytes for SHA3-384, 72 bytes for + * HMAC-SHA3-512. */ +#define PSA_HASH_MAX_SIZE 64 +#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 128 + +/** \def PSA_MAC_MAX_SIZE + * + * Maximum size of a MAC. + * + * This macro must expand to a compile-time constant integer. This value + * should be the maximum size of a MAC supported by the implementation, + * in bytes, and must be no smaller than this maximum. + */ +/* All non-HMAC MACs have a maximum size that's smaller than the + * minimum possible value of PSA_HASH_MAX_SIZE in this implementation. */ +/* Note that the encoding of truncated MAC algorithms limits this value + * to 64 bytes. + */ +#define PSA_MAC_MAX_SIZE PSA_HASH_MAX_SIZE + +/** The tag size for an AEAD algorithm, in bytes. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return The tag size for the specified algorithm. + * If the AEAD algorithm does not have an identified + * tag that can be distinguished from the rest of + * the ciphertext, return 0. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +#define PSA_AEAD_TAG_LENGTH(alg) \ + (PSA_ALG_IS_AEAD(alg) ? \ + (((alg) & PSA_ALG_AEAD_TAG_LENGTH_MASK) >> PSA_AEAD_TAG_LENGTH_OFFSET) : \ + 0) + +/* The maximum size of an RSA key on this implementation, in bits. + * This is a vendor-specific macro. + * + * Mbed TLS does not set a hard limit on the size of RSA keys: any key + * whose parameters fit in a bignum is accepted. However large keys can + * induce a large memory usage and long computation times. Unlike other + * auxiliary macros in this file and in crypto.h, which reflect how the + * library is configured, this macro defines how the library is + * configured. This implementation refuses to import or generate an + * RSA key whose size is larger than the value defined here. + * + * Note that an implementation may set different size limits for different + * operations, and does not need to accept all key sizes up to the limit. */ +#define PSA_VENDOR_RSA_MAX_KEY_BITS 4096 + +/* The maximum size of an ECC key on this implementation, in bits. + * This is a vendor-specific macro. */ +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 521 + +/** Bit size associated with an elliptic curve. + * + * \param curve An elliptic curve (value of type #psa_ecc_curve_t). + * + * \return The size associated with \p curve, in bits. + * This may be 0 if the implementation does not support + * the specified curve. + */ +#define PSA_ECC_CURVE_BITS(curve) \ + ((curve) == PSA_ECC_CURVE_SECT163K1 ? 163 : \ + (curve) == PSA_ECC_CURVE_SECT163R1 ? 163 : \ + (curve) == PSA_ECC_CURVE_SECT163R2 ? 163 : \ + (curve) == PSA_ECC_CURVE_SECT193R1 ? 193 : \ + (curve) == PSA_ECC_CURVE_SECT193R2 ? 193 : \ + (curve) == PSA_ECC_CURVE_SECT233K1 ? 233 : \ + (curve) == PSA_ECC_CURVE_SECT233R1 ? 233 : \ + (curve) == PSA_ECC_CURVE_SECT239K1 ? 239 : \ + (curve) == PSA_ECC_CURVE_SECT283K1 ? 283 : \ + (curve) == PSA_ECC_CURVE_SECT283R1 ? 283 : \ + (curve) == PSA_ECC_CURVE_SECT409K1 ? 409 : \ + (curve) == PSA_ECC_CURVE_SECT409R1 ? 409 : \ + (curve) == PSA_ECC_CURVE_SECT571K1 ? 571 : \ + (curve) == PSA_ECC_CURVE_SECT571R1 ? 571 : \ + (curve) == PSA_ECC_CURVE_SECP160K1 ? 160 : \ + (curve) == PSA_ECC_CURVE_SECP160R1 ? 160 : \ + (curve) == PSA_ECC_CURVE_SECP160R2 ? 160 : \ + (curve) == PSA_ECC_CURVE_SECP192K1 ? 192 : \ + (curve) == PSA_ECC_CURVE_SECP192R1 ? 192 : \ + (curve) == PSA_ECC_CURVE_SECP224K1 ? 224 : \ + (curve) == PSA_ECC_CURVE_SECP224R1 ? 224 : \ + (curve) == PSA_ECC_CURVE_SECP256K1 ? 256 : \ + (curve) == PSA_ECC_CURVE_SECP256R1 ? 256 : \ + (curve) == PSA_ECC_CURVE_SECP384R1 ? 384 : \ + (curve) == PSA_ECC_CURVE_SECP521R1 ? 521 : \ + (curve) == PSA_ECC_CURVE_BRAINPOOL_P256R1 ? 256 : \ + (curve) == PSA_ECC_CURVE_BRAINPOOL_P384R1 ? 384 : \ + (curve) == PSA_ECC_CURVE_BRAINPOOL_P512R1 ? 512 : \ + (curve) == PSA_ECC_CURVE_CURVE25519 ? 255 : \ + (curve) == PSA_ECC_CURVE_CURVE448 ? 448 : \ + 0) + +/** \def PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN + * + * This macro returns the maximum length of the PSK supported + * by the TLS-1.2 PSK-to-MS key derivation. + * + * Quoting RFC 4279, Sect 5.3: + * TLS implementations supporting these ciphersuites MUST support + * arbitrary PSK identities up to 128 octets in length, and arbitrary + * PSKs up to 64 octets in length. Supporting longer identities and + * keys is RECOMMENDED. + * + * Therefore, no implementation should define a value smaller than 64 + * for #PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN. + */ +#define PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN 128 + +/** The maximum size of a block cipher supported by the implementation. */ +#define PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE 16 + +/** The size of the output of psa_mac_sign_finish(), in bytes. + * + * This is also the MAC size that psa_mac_verify_finish() expects. + * + * \param key_type The type of the MAC key. + * \param key_bits The size of the MAC key in bits. + * \param alg A MAC algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_MAC(\p alg) is true). + * + * \return The MAC size for the specified algorithm with + * the specified key parameters. + * \return 0 if the MAC algorithm is not recognized. + * \return Either 0 or the correct size for a MAC algorithm that + * the implementation recognizes, but does not support. + * \return Unspecified if the key parameters are not consistent + * with the algorithm. + */ +#define PSA_MAC_FINAL_SIZE(key_type, key_bits, alg) \ + ((alg) & PSA_ALG_MAC_TRUNCATION_MASK ? PSA_MAC_TRUNCATED_LENGTH(alg) : \ + PSA_ALG_IS_HMAC(alg) ? PSA_HASH_SIZE(PSA_ALG_HMAC_GET_HASH(alg)) : \ + PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) ? PSA_BLOCK_CIPHER_BLOCK_SIZE(key_type) : \ + ((void)(key_type), (void)(key_bits), 0)) + +/** The maximum size of the output of psa_aead_encrypt(), in bytes. + * + * If the size of the ciphertext buffer is at least this large, it is + * guaranteed that psa_aead_encrypt() will not fail due to an + * insufficient buffer size. Depending on the algorithm, the actual size of + * the ciphertext may be smaller. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param plaintext_length Size of the plaintext in bytes. + * + * \return The AEAD ciphertext size for the specified + * algorithm. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +#define PSA_AEAD_ENCRYPT_OUTPUT_SIZE(alg, plaintext_length) \ + (PSA_AEAD_TAG_LENGTH(alg) != 0 ? \ + (plaintext_length) + PSA_AEAD_TAG_LENGTH(alg) : \ + 0) + +/** The maximum size of the output of psa_aead_decrypt(), in bytes. + * + * If the size of the plaintext buffer is at least this large, it is + * guaranteed that psa_aead_decrypt() will not fail due to an + * insufficient buffer size. Depending on the algorithm, the actual size of + * the plaintext may be smaller. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param ciphertext_length Size of the plaintext in bytes. + * + * \return The AEAD ciphertext size for the specified + * algorithm. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +#define PSA_AEAD_DECRYPT_OUTPUT_SIZE(alg, ciphertext_length) \ + (PSA_AEAD_TAG_LENGTH(alg) != 0 ? \ + (ciphertext_length) - PSA_AEAD_TAG_LENGTH(alg) : \ + 0) + +/** A sufficient output buffer size for psa_aead_update(). + * + * If the size of the output buffer is at least this large, it is + * guaranteed that psa_aead_update() will not fail due to an + * insufficient buffer size. The actual size of the output may be smaller + * in any given call. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param input_length Size of the input in bytes. + * + * \return A sufficient output buffer size for the specified + * algorithm. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +/* For all the AEAD modes defined in this specification, it is possible + * to emit output without delay. However, hardware may not always be + * capable of this. So for modes based on a block cipher, allow the + * implementation to delay the output until it has a full block. */ +#define PSA_AEAD_UPDATE_OUTPUT_SIZE(alg, input_length) \ + (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ + PSA_ROUND_UP_TO_MULTIPLE(PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE, (input_length)) : \ + (input_length)) + +/** A sufficient ciphertext buffer size for psa_aead_finish(). + * + * If the size of the ciphertext buffer is at least this large, it is + * guaranteed that psa_aead_finish() will not fail due to an + * insufficient ciphertext buffer size. The actual size of the output may + * be smaller in any given call. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return A sufficient ciphertext buffer size for the + * specified algorithm. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +#define PSA_AEAD_FINISH_OUTPUT_SIZE(alg) \ + (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ + PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE : \ + 0) + +/** A sufficient plaintext buffer size for psa_aead_verify(). + * + * If the size of the plaintext buffer is at least this large, it is + * guaranteed that psa_aead_verify() will not fail due to an + * insufficient plaintext buffer size. The actual size of the output may + * be smaller in any given call. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return A sufficient plaintext buffer size for the + * specified algorithm. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +#define PSA_AEAD_VERIFY_OUTPUT_SIZE(alg) \ + (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ + PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE : \ + 0) + +#define PSA_RSA_MINIMUM_PADDING_SIZE(alg) \ + (PSA_ALG_IS_RSA_OAEP(alg) ? \ + 2 * PSA_HASH_SIZE(PSA_ALG_RSA_OAEP_GET_HASH(alg)) + 1 : \ + 11 /*PKCS#1v1.5*/) + +/** + * \brief ECDSA signature size for a given curve bit size + * + * \param curve_bits Curve size in bits. + * \return Signature size in bytes. + * + * \note This macro returns a compile-time constant if its argument is one. + */ +#define PSA_ECDSA_SIGNATURE_SIZE(curve_bits) \ + (PSA_BITS_TO_BYTES(curve_bits) * 2) + +/** Sufficient signature buffer size for psa_sign_hash(). + * + * This macro returns a sufficient buffer size for a signature using a key + * of the specified type and size, with the specified algorithm. + * Note that the actual size of the signature may be smaller + * (some algorithms produce a variable-size signature). + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type An asymmetric key type (this may indifferently be a + * key pair type or a public key type). + * \param key_bits The size of the key in bits. + * \param alg The signature algorithm. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_sign_hash() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported + * by the implementation, this macro shall return either a + * sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_SIGN_OUTPUT_SIZE(key_type, key_bits, alg) \ + (PSA_KEY_TYPE_IS_RSA(key_type) ? ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \ + PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_ECDSA_SIGNATURE_SIZE(key_bits) : \ + ((void)alg, 0)) + +#define PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE \ + PSA_ECDSA_SIGNATURE_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) + +/** \def PSA_SIGNATURE_MAX_SIZE + * + * Maximum size of an asymmetric signature. + * + * This macro must expand to a compile-time constant integer. This value + * should be the maximum size of a signature supported by the implementation, + * in bytes, and must be no smaller than this maximum. + */ +#define PSA_SIGNATURE_MAX_SIZE \ + (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) > PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE ? \ + PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) : \ + PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE) + +/** Sufficient output buffer size for psa_asymmetric_encrypt(). + * + * This macro returns a sufficient buffer size for a ciphertext produced using + * a key of the specified type and size, with the specified algorithm. + * Note that the actual size of the ciphertext may be smaller, depending + * on the algorithm. + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type An asymmetric key type (this may indifferently be a + * key pair type or a public key type). + * \param key_bits The size of the key in bits. + * \param alg The signature algorithm. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_asymmetric_encrypt() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported + * by the implementation, this macro shall return either a + * sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \ + (PSA_KEY_TYPE_IS_RSA(key_type) ? \ + ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \ + 0) + +/** Sufficient output buffer size for psa_asymmetric_decrypt(). + * + * This macro returns a sufficient buffer size for a ciphertext produced using + * a key of the specified type and size, with the specified algorithm. + * Note that the actual size of the ciphertext may be smaller, depending + * on the algorithm. + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type An asymmetric key type (this may indifferently be a + * key pair type or a public key type). + * \param key_bits The size of the key in bits. + * \param alg The signature algorithm. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_asymmetric_decrypt() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported + * by the implementation, this macro shall return either a + * sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \ + (PSA_KEY_TYPE_IS_RSA(key_type) ? \ + PSA_BITS_TO_BYTES(key_bits) - PSA_RSA_MINIMUM_PADDING_SIZE(alg) : \ + 0) + +/* Maximum size of the ASN.1 encoding of an INTEGER with the specified + * number of bits. + * + * This definition assumes that bits <= 2^19 - 9 so that the length field + * is at most 3 bytes. The length of the encoding is the length of the + * bit string padded to a whole number of bytes plus: + * - 1 type byte; + * - 1 to 3 length bytes; + * - 0 to 1 bytes of leading 0 due to the sign bit. + */ +#define PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(bits) \ + ((bits) / 8 + 5) + +/* Maximum size of the export encoding of an RSA public key. + * Assumes that the public exponent is less than 2^32. + * + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER } -- e + * + * - 4 bytes of SEQUENCE overhead; + * - n : INTEGER; + * - 7 bytes for the public exponent. + */ +#define PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) \ + (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) + 11) + +/* Maximum size of the export encoding of an RSA key pair. + * Assumes thatthe public exponent is less than 2^32 and that the size + * difference between the two primes is at most 1 bit. + * + * RSAPrivateKey ::= SEQUENCE { + * version Version, -- 0 + * modulus INTEGER, -- N-bit + * publicExponent INTEGER, -- 32-bit + * privateExponent INTEGER, -- N-bit + * prime1 INTEGER, -- N/2-bit + * prime2 INTEGER, -- N/2-bit + * exponent1 INTEGER, -- N/2-bit + * exponent2 INTEGER, -- N/2-bit + * coefficient INTEGER, -- N/2-bit + * } + * + * - 4 bytes of SEQUENCE overhead; + * - 3 bytes of version; + * - 7 half-size INTEGERs plus 2 full-size INTEGERs, + * overapproximated as 9 half-size INTEGERS; + * - 7 bytes for the public exponent. + */ +#define PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits) \ + (9 * PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE((key_bits) / 2 + 1) + 14) + +/* Maximum size of the export encoding of a DSA public key. + * + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } -- contains DSAPublicKey + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters Dss-Parms } -- SEQUENCE of 3 INTEGERs + * DSAPublicKey ::= INTEGER -- public key, Y + * + * - 3 * 4 bytes of SEQUENCE overhead; + * - 1 + 1 + 7 bytes of algorithm (DSA OID); + * - 4 bytes of BIT STRING overhead; + * - 3 full-size INTEGERs (p, g, y); + * - 1 + 1 + 32 bytes for 1 sub-size INTEGER (q <= 256 bits). + */ +#define PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) \ + (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3 + 59) + +/* Maximum size of the export encoding of a DSA key pair. + * + * DSAPrivateKey ::= SEQUENCE { + * version Version, -- 0 + * prime INTEGER, -- p + * subprime INTEGER, -- q + * generator INTEGER, -- g + * public INTEGER, -- y + * private INTEGER, -- x + * } + * + * - 4 bytes of SEQUENCE overhead; + * - 3 bytes of version; + * - 3 full-size INTEGERs (p, g, y); + * - 2 * (1 + 1 + 32) bytes for 2 sub-size INTEGERs (q, x <= 256 bits). + */ +#define PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits) \ + (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3 + 75) + +/* Maximum size of the export encoding of an ECC public key. + * + * The representation of an ECC public key is: + * - The byte 0x04; + * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; + * - `y_P` as a `ceiling(m/8)`-byte string, big-endian; + * - where m is the bit size associated with the curve. + * + * - 1 byte + 2 * point size. + */ +#define PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) \ + (2 * PSA_BITS_TO_BYTES(key_bits) + 1) + +/* Maximum size of the export encoding of an ECC key pair. + * + * An ECC key pair is represented by the secret value. + */ +#define PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) \ + (PSA_BITS_TO_BYTES(key_bits)) + +/** Sufficient output buffer size for psa_export_key() or psa_export_public_key(). + * + * This macro returns a compile-time constant if its arguments are + * compile-time constants. + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * The following code illustrates how to allocate enough memory to export + * a key by querying the key type and size at runtime. + * \code{c} + * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + * psa_status_t status; + * status = psa_get_key_attributes(key, &attributes); + * if (status != PSA_SUCCESS) handle_error(...); + * psa_key_type_t key_type = psa_get_key_type(&attributes); + * size_t key_bits = psa_get_key_bits(&attributes); + * size_t buffer_size = PSA_KEY_EXPORT_MAX_SIZE(key_type, key_bits); + * psa_reset_key_attributes(&attributes); + * uint8_t *buffer = malloc(buffer_size); + * if (buffer == NULL) handle_error(...); + * size_t buffer_length; + * status = psa_export_key(key, buffer, buffer_size, &buffer_length); + * if (status != PSA_SUCCESS) handle_error(...); + * \endcode + * + * For psa_export_public_key(), calculate the buffer size from the + * public key type. You can use the macro #PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR + * to convert a key pair type to the corresponding public key type. + * \code{c} + * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + * psa_status_t status; + * status = psa_get_key_attributes(key, &attributes); + * if (status != PSA_SUCCESS) handle_error(...); + * psa_key_type_t key_type = psa_get_key_type(&attributes); + * psa_key_type_t public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(key_type); + * size_t key_bits = psa_get_key_bits(&attributes); + * size_t buffer_size = PSA_KEY_EXPORT_MAX_SIZE(public_key_type, key_bits); + * psa_reset_key_attributes(&attributes); + * uint8_t *buffer = malloc(buffer_size); + * if (buffer == NULL) handle_error(...); + * size_t buffer_length; + * status = psa_export_public_key(key, buffer, buffer_size, &buffer_length); + * if (status != PSA_SUCCESS) handle_error(...); + * \endcode + * + * \param key_type A supported key type. + * \param key_bits The size of the key in bits. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_sign_hash() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported + * by the implementation, this macro shall return either a + * sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_KEY_EXPORT_MAX_SIZE(key_type, key_bits) \ + (PSA_KEY_TYPE_IS_UNSTRUCTURED(key_type) ? PSA_BITS_TO_BYTES(key_bits) : \ + (key_type) == PSA_KEY_TYPE_RSA_KEY_PAIR ? PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits) : \ + (key_type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY ? PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ + (key_type) == PSA_KEY_TYPE_DSA_KEY_PAIR ? PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits) : \ + (key_type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY ? PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ + PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) ? PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) : \ + PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type) ? PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) : \ + 0) + +#endif /* PSA_CRYPTO_SIZES_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_struct.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_struct.h new file mode 100644 index 0000000..ac08987 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_struct.h @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +/** + * \file psa/crypto_struct.h + * + * \brief PSA cryptography module: structured type implementations + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * This file contains the definitions of some data structures with + * implementation-specific definitions. + * + * In implementations with isolation between the application and the + * cryptography module, it is expected that the front-end and the back-end + * would have different versions of this file. + */ + +#ifndef PSA_CRYPTO_STRUCT_H +#define PSA_CRYPTO_STRUCT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Note that the below structures are different from the decalrations in + * mbed-crypto. This is because TF-M maintains 'front-end' and 'back-end' + * versions of this header. In the front-end version, exported to NS + * clients in interface/include/psa, a crypto operation is defined as an + * opaque handle to a context in the Crypto service. The back-end + * version, directly included from the mbed-crypto repo by the Crypto + * service, contains the full definition of the operation structs. + * + * One of the functions of the Crypto service is to allocate the back-end + * operation contexts in its own partition memory (in crypto_alloc.c), + * and then do the mapping between front-end operation handles passed by + * NS clients and the corresponding back-end operation contexts. The + * advantage of doing it this way is that internal mbed-crypto state is never + * exposed to the NS client. + */ + +struct psa_hash_operation_s +{ + uint32_t handle; +}; + +#define PSA_HASH_OPERATION_INIT {0} +static inline struct psa_hash_operation_s psa_hash_operation_init( void ) +{ + const struct psa_hash_operation_s v = PSA_HASH_OPERATION_INIT; + return( v ); +} + +struct psa_mac_operation_s +{ + uint32_t handle; +}; + +#define PSA_MAC_OPERATION_INIT {0} +static inline struct psa_mac_operation_s psa_mac_operation_init( void ) +{ + const struct psa_mac_operation_s v = PSA_MAC_OPERATION_INIT; + return( v ); +} + +struct psa_cipher_operation_s +{ + uint32_t handle; +}; + +#define PSA_CIPHER_OPERATION_INIT {0} +static inline struct psa_cipher_operation_s psa_cipher_operation_init( void ) +{ + const struct psa_cipher_operation_s v = PSA_CIPHER_OPERATION_INIT; + return( v ); +} + +struct psa_aead_operation_s +{ + uint32_t handle; +}; + +#define PSA_AEAD_OPERATION_INIT {0} +static inline struct psa_aead_operation_s psa_aead_operation_init( void ) +{ + const struct psa_aead_operation_s v = PSA_AEAD_OPERATION_INIT; + return( v ); +} + +struct psa_key_derivation_s +{ + uint32_t handle; +}; + +#define PSA_KEY_DERIVATION_OPERATION_INIT {0} +static inline struct psa_key_derivation_s psa_key_derivation_operation_init( void ) +{ + const struct psa_key_derivation_s v = PSA_KEY_DERIVATION_OPERATION_INIT; + return( v ); +} + +/* The type used internally for key sizes. + * Public interfaces use size_t, but internally we use a smaller type. */ +typedef uint16_t psa_key_bits_t; +/* The maximum value of the type used to represent bit-sizes. + * This is used to mark an invalid key size. */ +#define PSA_KEY_BITS_TOO_LARGE ( (psa_key_bits_t) ( -1 ) ) +/* The maximum size of a key in bits. + * Currently defined as the maximum that can be represented, rounded down + * to a whole number of bytes. + * This is an uncast value so that it can be used in preprocessor + * conditionals. */ +#define PSA_MAX_KEY_BITS 0xfff8 + +#define PSA_KEY_ATTRIBUTES_INIT PSA_CLIENT_KEY_ATTRIBUTES_INIT + +static inline struct psa_client_key_attributes_s psa_key_attributes_init( void ) +{ + const struct psa_client_key_attributes_s v = PSA_KEY_ATTRIBUTES_INIT; + return( v ); +} + +static inline void psa_set_key_id(psa_key_attributes_t *attributes, + psa_key_id_t id) +{ + attributes->id = id; + if( attributes->lifetime == PSA_KEY_LIFETIME_VOLATILE ) + attributes->lifetime = PSA_KEY_LIFETIME_PERSISTENT; +} + +static inline psa_key_id_t psa_get_key_id( + const psa_key_attributes_t *attributes) +{ + return( attributes->id ); +} + +static inline void psa_set_key_lifetime(psa_key_attributes_t *attributes, + psa_key_lifetime_t lifetime) +{ + attributes->lifetime = lifetime; + if( lifetime == PSA_KEY_LIFETIME_VOLATILE ) + { + attributes->id = 0; + } +} + +static inline psa_key_lifetime_t psa_get_key_lifetime( + const psa_key_attributes_t *attributes) +{ + return( attributes->lifetime ); +} + +static inline void psa_set_key_usage_flags(psa_key_attributes_t *attributes, + psa_key_usage_t usage_flags) +{ + attributes->usage = usage_flags; +} + +static inline psa_key_usage_t psa_get_key_usage_flags( + const psa_key_attributes_t *attributes) +{ + return( attributes->usage ); +} + +static inline void psa_set_key_algorithm(psa_key_attributes_t *attributes, + psa_algorithm_t alg) +{ + attributes->alg = alg; +} + +static inline psa_algorithm_t psa_get_key_algorithm( + const psa_key_attributes_t *attributes) +{ + return( attributes->alg ); +} + +static inline void psa_set_key_type(psa_key_attributes_t *attributes, + psa_key_type_t type) +{ + attributes->type = type; +} + +static inline psa_key_type_t psa_get_key_type( + const psa_key_attributes_t *attributes) +{ + return( attributes->type ); +} + +static inline void psa_set_key_bits(psa_key_attributes_t *attributes, + size_t bits) +{ + if( bits > PSA_MAX_KEY_BITS ) + attributes->bits = PSA_KEY_BITS_TOO_LARGE; + else + attributes->bits = bits; +} + +static inline size_t psa_get_key_bits( + const psa_key_attributes_t *attributes) +{ + return( attributes->bits ); +} + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_STRUCT_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_types.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_types.h new file mode 100644 index 0000000..6ac95a8 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_types.h @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +/** + * \file psa/crypto_types.h + * + * \brief PSA cryptography module: type aliases. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. Drivers must include the appropriate driver + * header file. + * + * This file contains portable definitions of integral types for properties + * of cryptographic keys, designations of cryptographic algorithms, and + * error codes returned by the library. + * + * This header file does not declare any function. + */ + +#ifndef PSA_CRYPTO_TYPES_H +#define PSA_CRYPTO_TYPES_H + +#include + +/** \defgroup error Error codes + * @{ + */ + +/** + * \brief Function return status. + * + * This is either #PSA_SUCCESS (which is zero), indicating success, + * or a small negative value indicating that an error occurred. Errors are + * encoded as one of the \c PSA_ERROR_xxx values defined here. */ +/* If #PSA_SUCCESS is already defined, it means that #psa_status_t + * is also defined in an external header, so prevent its multiple + * definition. + */ +#ifndef PSA_SUCCESS +typedef int32_t psa_status_t; +#endif + +/**@}*/ + +/** \defgroup crypto_types Key and algorithm types + * @{ + */ + +/* Integral type representing a key handle. */ +typedef uint16_t psa_key_handle_t; + + +/** \brief Encoding of a key type. + */ +typedef uint32_t psa_key_type_t; + +/** The type of PSA elliptic curve identifiers. + * + * The curve identifier is required to create an ECC key using the + * PSA_KEY_TYPE_ECC_KEY_PAIR() or PSA_KEY_TYPE_ECC_PUBLIC_KEY() + * macros. + * + * The encoding of curve identifiers is taken from the + * TLS Supported Groups Registry (formerly known as the + * TLS EC Named Curve Registry) + * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 + * + * This specification defines identifiers for some of the curves in the IANA + * registry. Implementations that support other curves that are in the IANA + * registry should use the IANA value and a implementation-specific identifier. + * Implemenations that support non-IANA curves should use one of the following + * approaches for allocating a key type: + * + * 1. Select a ::psa_ecc_curve_t value in the range #PSA_ECC_CURVE_VENDOR_MIN to + * #PSA_ECC_CURVE_VENDOR_MAX, which is a subset of the IANA private use + * range. + * 2. Use a ::psa_key_type_t value that is vendor-defined. + * + * The first option is recommended. + */ +typedef uint16_t psa_ecc_curve_t; + +/** The type of PSA Diffie-Hellman group identifiers. + * + * The group identifier is required to create an Diffie-Hellman key using the + * PSA_KEY_TYPE_DH_KEY_PAIR() or PSA_KEY_TYPE_DH_PUBLIC_KEY() + * macros. + * + * The encoding of group identifiers is taken from the + * TLS Supported Groups Registry (formerly known as the + * TLS EC Named Curve Registry) + * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 + * + * This specification defines identifiers for some of the groups in the IANA + * registry. Implementations that support other groups that are in the IANA + * registry should use the IANA value and a implementation-specific identifier. + * Implemenations that support non-IANA groups should use one of the following + * approaches for allocating a key type: + * + * 1. Select a ::psa_dh_group_t value in the range #PSA_DH_GROUP_VENDOR_MIN to + * #PSA_DH_GROUP_VENDOR_MAX, which is a subset of the IANA private use + * range. + * 2. Select a ::psa_dh_group_t value from the named groups allocated for + * GREASE in the IETF draft specification. The GREASE specification and + * values are listed below. + * 3. Use a ::psa_key_type_t value that is vendor-defined. + * + * Option 1 or 2 are recommended. + * + * The current draft of the GREASE specification is + * https://datatracker.ietf.org/doc/draft-ietf-tls-grease + * + * The following GREASE values are allocated for named groups: + * \code + * 0x0A0A + * 0x1A1A + * 0x2A2A + * 0x3A3A + * 0x4A4A + * 0x5A5A + * 0x6A6A + * 0x7A7A + * 0x8A8A + * 0x9A9A + * 0xAAAA + * 0xBABA + * 0xCACA + * 0xDADA + * 0xEAEA + * 0xFAFA + * \endcode + */ +typedef uint16_t psa_dh_group_t; + +/** \brief Encoding of a cryptographic algorithm. + * + * For algorithms that can be applied to multiple key types, this type + * does not encode the key type. For example, for symmetric ciphers + * based on a block cipher, #psa_algorithm_t encodes the block cipher + * mode and the padding mode while the block cipher itself is encoded + * via #psa_key_type_t. + */ +typedef uint32_t psa_algorithm_t; + +/**@}*/ + +/** \defgroup key_lifetimes Key lifetimes + * @{ + */ + +/** Encoding of key lifetimes. + * + * The lifetime of a key indicates where it is stored and what system actions + * may create and destroy it. + * + * Keys with the lifetime #PSA_KEY_LIFETIME_VOLATILE are automatically + * destroyed when the application terminates or on a power reset. + * + * Keys with a lifetime other than #PSA_KEY_LIFETIME_VOLATILE are said + * to be _persistent_. + * Persistent keys are preserved if the application or the system restarts. + * Persistent keys have a key identifier of type #psa_key_id_t. + * The application can call psa_open_key() to open a persistent key that + * it created previously. + */ +typedef uint32_t psa_key_lifetime_t; + +/** Encoding of identifiers of persistent keys. + * + * - Applications may freely choose key identifiers in the range + * #PSA_KEY_ID_USER_MIN to #PSA_KEY_ID_USER_MAX. + * - Implementations may define additional key identifiers in the range + * #PSA_KEY_ID_VENDOR_MIN to #PSA_KEY_ID_VENDOR_MAX. + * - 0 is reserved as an invalid key identifier. + * - Key identifiers outside these ranges are reserved for future use. + */ +typedef uint32_t psa_key_id_t; +#define PSA_KEY_ID_INIT 0 + +/**@}*/ + +/** \defgroup policy Key policies + * @{ + */ + +/** \brief Encoding of permitted usage on a key. */ +typedef uint32_t psa_key_usage_t; + +/**@}*/ + +/** \defgroup attributes Key attributes + * @{ + */ + +/** The type of a structure containing key attributes. + * + * This is an opaque structure that can represent the metadata of a key + * object. Metadata that can be stored in attributes includes: + * - The location of the key in storage, indicated by its key identifier + * and its lifetime. + * - The key's policy, comprising usage flags and a specification of + * the permitted algorithm(s). + * - Information about the key itself: the key type and its size. + * - Implementations may define additional attributes. + * + * The actual key material is not considered an attribute of a key. + * Key attributes do not contain information that is generally considered + * highly confidential. + * + * An attribute structure can be a simple data structure where each function + * `psa_set_key_xxx` sets a field and the corresponding function + * `psa_get_key_xxx` retrieves the value of the corresponding field. + * However, implementations may report values that are equivalent to the + * original one, but have a different encoding. For example, an + * implementation may use a more compact representation for types where + * many bit-patterns are invalid or not supported, and store all values + * that it does not support as a special marker value. In such an + * implementation, after setting an invalid value, the corresponding + * get function returns an invalid value which may not be the one that + * was originally stored. + * + * An attribute structure may contain references to auxiliary resources, + * for example pointers to allocated memory or indirect references to + * pre-calculated values. In order to free such resources, the application + * must call psa_reset_key_attributes(). As an exception, calling + * psa_reset_key_attributes() on an attribute structure is optional if + * the structure has only been modified by the following functions + * since it was initialized or last reset with psa_reset_key_attributes(): + * - psa_set_key_id() + * - psa_set_key_lifetime() + * - psa_set_key_type() + * - psa_set_key_bits() + * - psa_set_key_usage_flags() + * - psa_set_key_algorithm() + * + * Before calling any function on a key attribute structure, the application + * must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_key_attributes_t attributes; + * memset(&attributes, 0, sizeof(attributes)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_key_attributes_t attributes = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_KEY_ATTRIBUTES_INIT, + * for example: + * \code + * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + * \endcode + * - Assign the result of the function psa_key_attributes_init() + * to the structure, for example: + * \code + * psa_key_attributes_t attributes; + * attributes = psa_key_attributes_init(); + * \endcode + * + * A freshly initialized attribute structure contains the following + * values: + * + * - lifetime: #PSA_KEY_LIFETIME_VOLATILE. + * - key identifier: 0 (which is not a valid key identifier). + * - type: \c 0 (meaning that the type is unspecified). + * - key size: \c 0 (meaning that the size is unspecified). + * - usage flags: \c 0 (which allows no usage except exporting a public key). + * - algorithm: \c 0 (which allows no cryptographic usage, but allows + * exporting). + * + * A typical sequence to create a key is as follows: + * -# Create and initialize an attribute structure. + * -# If the key is persistent, call psa_set_key_id(). + * Also call psa_set_key_lifetime() to place the key in a non-default + * location. + * -# Set the key policy with psa_set_key_usage_flags() and + * psa_set_key_algorithm(). + * -# Set the key type with psa_set_key_type(). + * Skip this step if copying an existing key with psa_copy_key(). + * -# When generating a random key with psa_generate_key() or deriving a key + * with psa_key_derivation_output_key(), set the desired key size with + * psa_set_key_bits(). + * -# Call a key creation function: psa_import_key(), psa_generate_key(), + * psa_key_derivation_output_key() or psa_copy_key(). This function reads + * the attribute structure, creates a key with these attributes, and + * outputs a handle to the newly created key. + * -# The attribute structure is now no longer necessary. + * You may call psa_reset_key_attributes(), although this is optional + * with the workflow presented here because the attributes currently + * defined in this specification do not require any additional resources + * beyond the structure itself. + * + * A typical sequence to query a key's attributes is as follows: + * -# Call psa_get_key_attributes(). + * -# Call `psa_get_key_xxx` functions to retrieve the attribute(s) that + * you are interested in. + * -# Call psa_reset_key_attributes() to free any resources that may be + * used by the attribute structure. + * + * Once a key has been created, it is impossible to change its attributes. + */ +typedef struct psa_client_key_attributes_s psa_key_attributes_t; + +/**@}*/ + +/** \defgroup derivation Key derivation + * @{ + */ + +/** \brief Encoding of the step of a key derivation. */ +typedef uint16_t psa_key_derivation_step_t; + +/**@}*/ + +#endif /* PSA_CRYPTO_TYPES_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_values.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_values.h new file mode 100644 index 0000000..e21ef27 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/crypto_values.h @@ -0,0 +1,1701 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +/** + * \file psa/crypto_values.h + * + * \brief PSA cryptography module: macros to build and analyze integer values. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. Drivers must include the appropriate driver + * header file. + * + * This file contains portable definitions of macros to build and analyze + * values of integral types that encode properties of cryptographic keys, + * designations of cryptographic algorithms, and error codes returned by + * the library. + * + * This header file only defines preprocessor macros. + */ + +#ifndef PSA_CRYPTO_VALUES_H +#define PSA_CRYPTO_VALUES_H + +/** \defgroup error Error codes + * @{ + */ + +/* PSA error codes */ + +/** The action was completed successfully. */ +#ifndef PSA_SUCCESS +#define PSA_SUCCESS ((psa_status_t)0) +#endif + +/** An error occurred that does not correspond to any defined + * failure cause. + * + * Implementations may use this error code if none of the other standard + * error codes are applicable. */ +#define PSA_ERROR_GENERIC_ERROR ((psa_status_t)-132) + +/** The requested operation or a parameter is not supported + * by this implementation. + * + * Implementations should return this error code when an enumeration + * parameter such as a key type, algorithm, etc. is not recognized. + * If a combination of parameters is recognized and identified as + * not valid, return #PSA_ERROR_INVALID_ARGUMENT instead. */ +#define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)-134) + +/** The requested action is denied by a policy. + * + * Implementations should return this error code when the parameters + * are recognized as valid and supported, and a policy explicitly + * denies the requested operation. + * + * If a subset of the parameters of a function call identify a + * forbidden operation, and another subset of the parameters are + * not valid or not supported, it is unspecified whether the function + * returns #PSA_ERROR_NOT_PERMITTED, #PSA_ERROR_NOT_SUPPORTED or + * #PSA_ERROR_INVALID_ARGUMENT. */ +#define PSA_ERROR_NOT_PERMITTED ((psa_status_t)-133) + +/** An output buffer is too small. + * + * Applications can call the \c PSA_xxx_SIZE macro listed in the function + * description to determine a sufficient buffer size. + * + * Implementations should preferably return this error code only + * in cases when performing the operation with a larger output + * buffer would succeed. However implementations may return this + * error if a function has invalid or unsupported parameters in addition + * to the parameters that determine the necessary output buffer size. */ +#define PSA_ERROR_BUFFER_TOO_SMALL ((psa_status_t)-138) + +/** Asking for an item that already exists + * + * Implementations should return this error, when attempting + * to write an item (like a key) that already exists. */ +#define PSA_ERROR_ALREADY_EXISTS ((psa_status_t)-139) + +/** Asking for an item that doesn't exist + * + * Implementations should return this error, if a requested item (like + * a key) does not exist. */ +#define PSA_ERROR_DOES_NOT_EXIST ((psa_status_t)-140) + +/** The requested action cannot be performed in the current state. + * + * Multipart operations return this error when one of the + * functions is called out of sequence. Refer to the function + * descriptions for permitted sequencing of functions. + * + * Implementations shall not return this error code to indicate + * that a key either exists or not, + * but shall instead return #PSA_ERROR_ALREADY_EXISTS or #PSA_ERROR_DOES_NOT_EXIST + * as applicable. + * + * Implementations shall not return this error code to indicate that a + * key handle is invalid, but shall return #PSA_ERROR_INVALID_HANDLE + * instead. */ +#define PSA_ERROR_BAD_STATE ((psa_status_t)-137) + +/** The parameters passed to the function are invalid. + * + * Implementations may return this error any time a parameter or + * combination of parameters are recognized as invalid. + * + * Implementations shall not return this error code to indicate that a + * key handle is invalid, but shall return #PSA_ERROR_INVALID_HANDLE + * instead. + */ +#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)-135) + +/** There is not enough runtime memory. + * + * If the action is carried out across multiple security realms, this + * error can refer to available memory in any of the security realms. */ +#define PSA_ERROR_INSUFFICIENT_MEMORY ((psa_status_t)-141) + +/** There is not enough persistent storage. + * + * Functions that modify the key storage return this error code if + * there is insufficient storage space on the host media. In addition, + * many functions that do not otherwise access storage may return this + * error code if the implementation requires a mandatory log entry for + * the requested action and the log storage space is full. */ +#define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)-142) + +/** There was a communication failure inside the implementation. + * + * This can indicate a communication failure between the application + * and an external cryptoprocessor or between the cryptoprocessor and + * an external volatile or persistent memory. A communication failure + * may be transient or permanent depending on the cause. + * + * \warning If a function returns this error, it is undetermined + * whether the requested action has completed or not. Implementations + * should return #PSA_SUCCESS on successful completion whenever + * possible, however functions may return #PSA_ERROR_COMMUNICATION_FAILURE + * if the requested action was completed successfully in an external + * cryptoprocessor but there was a breakdown of communication before + * the cryptoprocessor could report the status to the application. + */ +#define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t)-145) + +/** There was a storage failure that may have led to data loss. + * + * This error indicates that some persistent storage is corrupted. + * It should not be used for a corruption of volatile memory + * (use #PSA_ERROR_CORRUPTION_DETECTED), for a communication error + * between the cryptoprocessor and its external storage (use + * #PSA_ERROR_COMMUNICATION_FAILURE), or when the storage is + * in a valid state but is full (use #PSA_ERROR_INSUFFICIENT_STORAGE). + * + * Note that a storage failure does not indicate that any data that was + * previously read is invalid. However this previously read data may no + * longer be readable from storage. + * + * When a storage failure occurs, it is no longer possible to ensure + * the global integrity of the keystore. Depending on the global + * integrity guarantees offered by the implementation, access to other + * data may or may not fail even if the data is still readable but + * its integrity cannot be guaranteed. + * + * Implementations should only use this error code to report a + * permanent storage corruption. However application writers should + * keep in mind that transient errors while reading the storage may be + * reported using this error code. */ +#define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)-146) + +/** A hardware failure was detected. + * + * A hardware failure may be transient or permanent depending on the + * cause. */ +#define PSA_ERROR_HARDWARE_FAILURE ((psa_status_t)-147) + +/** A tampering attempt was detected. + * + * If an application receives this error code, there is no guarantee + * that previously accessed or computed data was correct and remains + * confidential. Applications should not perform any security function + * and should enter a safe failure state. + * + * Implementations may return this error code if they detect an invalid + * state that cannot happen during normal operation and that indicates + * that the implementation's security guarantees no longer hold. Depending + * on the implementation architecture and on its security and safety goals, + * the implementation may forcibly terminate the application. + * + * This error code is intended as a last resort when a security breach + * is detected and it is unsure whether the keystore data is still + * protected. Implementations shall only return this error code + * to report an alarm from a tampering detector, to indicate that + * the confidentiality of stored data can no longer be guaranteed, + * or to indicate that the integrity of previously returned data is now + * considered compromised. Implementations shall not use this error code + * to indicate a hardware failure that merely makes it impossible to + * perform the requested operation (use #PSA_ERROR_COMMUNICATION_FAILURE, + * #PSA_ERROR_STORAGE_FAILURE, #PSA_ERROR_HARDWARE_FAILURE, + * #PSA_ERROR_INSUFFICIENT_ENTROPY or other applicable error code + * instead). + * + * This error indicates an attack against the application. Implementations + * shall not return this error code as a consequence of the behavior of + * the application itself. */ +#define PSA_ERROR_CORRUPTION_DETECTED ((psa_status_t)-151) + +/** There is not enough entropy to generate random data needed + * for the requested action. + * + * This error indicates a failure of a hardware random generator. + * Application writers should note that this error can be returned not + * only by functions whose purpose is to generate random data, such + * as key, IV or nonce generation, but also by functions that execute + * an algorithm with a randomized result, as well as functions that + * use randomization of intermediate computations as a countermeasure + * to certain attacks. + * + * Implementations should avoid returning this error after psa_crypto_init() + * has succeeded. Implementations should generate sufficient + * entropy during initialization and subsequently use a cryptographically + * secure pseudorandom generator (PRNG). However implementations may return + * this error at any time if a policy requires the PRNG to be reseeded + * during normal operation. */ +#define PSA_ERROR_INSUFFICIENT_ENTROPY ((psa_status_t)-148) + +/** The signature, MAC or hash is incorrect. + * + * Verification functions return this error if the verification + * calculations completed successfully, and the value to be verified + * was determined to be incorrect. + * + * If the value to verify has an invalid size, implementations may return + * either #PSA_ERROR_INVALID_ARGUMENT or #PSA_ERROR_INVALID_SIGNATURE. */ +#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) + +/** The decrypted padding is incorrect. + * + * \warning In some protocols, when decrypting data, it is essential that + * the behavior of the application does not depend on whether the padding + * is correct, down to precise timing. Applications should prefer + * protocols that use authenticated encryption rather than plain + * encryption. If the application must perform a decryption of + * unauthenticated data, the application writer should take care not + * to reveal whether the padding is invalid. + * + * Implementations should strive to make valid and invalid padding + * as close as possible to indistinguishable to an external observer. + * In particular, the timing of a decryption operation should not + * depend on the validity of the padding. */ +#define PSA_ERROR_INVALID_PADDING ((psa_status_t)-150) + +/** Return this error when there's insufficient data when attempting + * to read from a resource. */ +#define PSA_ERROR_INSUFFICIENT_DATA ((psa_status_t)-143) + +/** The key handle is not valid. See also :ref:\`key-handles\`. + */ +#define PSA_ERROR_INVALID_HANDLE ((psa_status_t)-136) + +/**@}*/ + +/** \defgroup crypto_types Key and algorithm types + * @{ + */ + +/** An invalid key type value. + * + * Zero is not the encoding of any key type. + */ +#define PSA_KEY_TYPE_NONE ((psa_key_type_t)0x00000000) + +/** Vendor-defined key type flag. + * + * Key types defined by this standard will never have the + * #PSA_KEY_TYPE_VENDOR_FLAG bit set. Vendors who define additional key types + * must use an encoding with the #PSA_KEY_TYPE_VENDOR_FLAG bit set and should + * respect the bitwise structure used by standard encodings whenever practical. + */ +#define PSA_KEY_TYPE_VENDOR_FLAG ((psa_key_type_t)0x80000000) + +#define PSA_KEY_TYPE_CATEGORY_MASK ((psa_key_type_t)0x70000000) +#define PSA_KEY_TYPE_CATEGORY_SYMMETRIC ((psa_key_type_t)0x40000000) +#define PSA_KEY_TYPE_CATEGORY_RAW ((psa_key_type_t)0x50000000) +#define PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY ((psa_key_type_t)0x60000000) +#define PSA_KEY_TYPE_CATEGORY_KEY_PAIR ((psa_key_type_t)0x70000000) + +#define PSA_KEY_TYPE_CATEGORY_FLAG_PAIR ((psa_key_type_t)0x10000000) + +/** Whether a key type is vendor-defined. + * + * See also #PSA_KEY_TYPE_VENDOR_FLAG. + */ +#define PSA_KEY_TYPE_IS_VENDOR_DEFINED(type) \ + (((type) & PSA_KEY_TYPE_VENDOR_FLAG) != 0) + +/** Whether a key type is an unstructured array of bytes. + * + * This encompasses both symmetric keys and non-key data. + */ +#define PSA_KEY_TYPE_IS_UNSTRUCTURED(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK & ~(psa_key_type_t)0x10000000) == \ + PSA_KEY_TYPE_CATEGORY_SYMMETRIC) + +/** Whether a key type is asymmetric: either a key pair or a public key. */ +#define PSA_KEY_TYPE_IS_ASYMMETRIC(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK \ + & ~PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) == \ + PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY) +/** Whether a key type is the public part of a key pair. */ +#define PSA_KEY_TYPE_IS_PUBLIC_KEY(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY) +/** Whether a key type is a key pair containing a private part and a public + * part. */ +#define PSA_KEY_TYPE_IS_KEY_PAIR(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_KEY_PAIR) +/** The key pair type corresponding to a public key type. + * + * You may also pass a key pair type as \p type, it will be left unchanged. + * + * \param type A public key type or key pair type. + * + * \return The corresponding key pair type. + * If \p type is not a public key or a key pair, + * the return value is undefined. + */ +#define PSA_KEY_TYPE_KEY_PAIR_OF_PUBLIC_KEY(type) \ + ((type) | PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) +/** The public key type corresponding to a key pair type. + * + * You may also pass a key pair type as \p type, it will be left unchanged. + * + * \param type A public key type or key pair type. + * + * \return The corresponding public key type. + * If \p type is not a public key or a key pair, + * the return value is undefined. + */ +#define PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) \ + ((type) & ~PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) + +/** Raw data. + * + * A "key" of this type cannot be used for any cryptographic operation. + * Applications may use this type to store arbitrary data in the keystore. */ +#define PSA_KEY_TYPE_RAW_DATA ((psa_key_type_t)0x50000001) + +/** HMAC key. + * + * The key policy determines which underlying hash algorithm the key can be + * used for. + * + * HMAC keys should generally have the same size as the underlying hash. + * This size can be calculated with #PSA_HASH_SIZE(\c alg) where + * \c alg is the HMAC algorithm or the underlying hash algorithm. */ +#define PSA_KEY_TYPE_HMAC ((psa_key_type_t)0x51000000) + +/** A secret for key derivation. + * + * The key policy determines which key derivation algorithm the key + * can be used for. + */ +#define PSA_KEY_TYPE_DERIVE ((psa_key_type_t)0x52000000) + +/** Key for a cipher, AEAD or MAC algorithm based on the AES block cipher. + * + * The size of the key can be 16 bytes (AES-128), 24 bytes (AES-192) or + * 32 bytes (AES-256). + */ +#define PSA_KEY_TYPE_AES ((psa_key_type_t)0x40000001) + +/** Key for a cipher or MAC algorithm based on DES or 3DES (Triple-DES). + * + * The size of the key can be 8 bytes (single DES), 16 bytes (2-key 3DES) or + * 24 bytes (3-key 3DES). + * + * Note that single DES and 2-key 3DES are weak and strongly + * deprecated and should only be used to decrypt legacy data. 3-key 3DES + * is weak and deprecated and should only be used in legacy protocols. + */ +#define PSA_KEY_TYPE_DES ((psa_key_type_t)0x40000002) + +/** Key for a cipher, AEAD or MAC algorithm based on the + * Camellia block cipher. */ +#define PSA_KEY_TYPE_CAMELLIA ((psa_key_type_t)0x40000003) + +/** Key for the RC4 stream cipher. + * + * Note that RC4 is weak and deprecated and should only be used in + * legacy protocols. */ +#define PSA_KEY_TYPE_ARC4 ((psa_key_type_t)0x40000004) + +/** Key for the ChaCha20 stream cipher or the Chacha20-Poly1305 AEAD algorithm. + * + * ChaCha20 and the ChaCha20_Poly1305 construction are defined in RFC 7539. + * + * Implementations must support 12-byte nonces, may support 8-byte nonces, + * and should reject other sizes. + */ +#define PSA_KEY_TYPE_CHACHA20 ((psa_key_type_t)0x40000005) + +/** RSA public key. */ +#define PSA_KEY_TYPE_RSA_PUBLIC_KEY ((psa_key_type_t)0x60010000) +/** RSA key pair (private and public key). */ +#define PSA_KEY_TYPE_RSA_KEY_PAIR ((psa_key_type_t)0x70010000) +/** Whether a key type is an RSA key (pair or public-only). */ +#define PSA_KEY_TYPE_IS_RSA(type) \ + (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY) + +#define PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE ((psa_key_type_t)0x60030000) +#define PSA_KEY_TYPE_ECC_KEY_PAIR_BASE ((psa_key_type_t)0x70030000) +#define PSA_KEY_TYPE_ECC_CURVE_MASK ((psa_key_type_t)0x0000ffff) +/** Elliptic curve key pair. + * + * \param curve A value of type ::psa_ecc_curve_t that identifies the + * ECC curve to be used. + */ +#define PSA_KEY_TYPE_ECC_KEY_PAIR(curve) \ + (PSA_KEY_TYPE_ECC_KEY_PAIR_BASE | (curve)) +/** Elliptic curve public key. + * + * \param curve A value of type ::psa_ecc_curve_t that identifies the + * ECC curve to be used. + */ +#define PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve) \ + (PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE | (curve)) + +/** Whether a key type is an elliptic curve key (pair or public-only). */ +#define PSA_KEY_TYPE_IS_ECC(type) \ + ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) & \ + ~PSA_KEY_TYPE_ECC_CURVE_MASK) == PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE) +/** Whether a key type is an elliptic curve key pair. */ +#define PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type) \ + (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \ + PSA_KEY_TYPE_ECC_KEY_PAIR_BASE) +/** Whether a key type is an elliptic curve public key. */ +#define PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(type) \ + (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \ + PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE) + +/** Extract the curve from an elliptic curve key type. */ +#define PSA_KEY_TYPE_GET_CURVE(type) \ + ((psa_ecc_curve_t) (PSA_KEY_TYPE_IS_ECC(type) ? \ + ((type) & PSA_KEY_TYPE_ECC_CURVE_MASK) : \ + 0)) + +/* The encoding of curve identifiers is currently aligned with the + * TLS Supported Groups Registry (formerly known as the + * TLS EC Named Curve Registry) + * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 + * The values are defined by RFC 8422 and RFC 7027. */ +#define PSA_ECC_CURVE_SECT163K1 ((psa_ecc_curve_t) 0x0001) +#define PSA_ECC_CURVE_SECT163R1 ((psa_ecc_curve_t) 0x0002) +#define PSA_ECC_CURVE_SECT163R2 ((psa_ecc_curve_t) 0x0003) +#define PSA_ECC_CURVE_SECT193R1 ((psa_ecc_curve_t) 0x0004) +#define PSA_ECC_CURVE_SECT193R2 ((psa_ecc_curve_t) 0x0005) +#define PSA_ECC_CURVE_SECT233K1 ((psa_ecc_curve_t) 0x0006) +#define PSA_ECC_CURVE_SECT233R1 ((psa_ecc_curve_t) 0x0007) +#define PSA_ECC_CURVE_SECT239K1 ((psa_ecc_curve_t) 0x0008) +#define PSA_ECC_CURVE_SECT283K1 ((psa_ecc_curve_t) 0x0009) +#define PSA_ECC_CURVE_SECT283R1 ((psa_ecc_curve_t) 0x000a) +#define PSA_ECC_CURVE_SECT409K1 ((psa_ecc_curve_t) 0x000b) +#define PSA_ECC_CURVE_SECT409R1 ((psa_ecc_curve_t) 0x000c) +#define PSA_ECC_CURVE_SECT571K1 ((psa_ecc_curve_t) 0x000d) +#define PSA_ECC_CURVE_SECT571R1 ((psa_ecc_curve_t) 0x000e) +#define PSA_ECC_CURVE_SECP160K1 ((psa_ecc_curve_t) 0x000f) +#define PSA_ECC_CURVE_SECP160R1 ((psa_ecc_curve_t) 0x0010) +#define PSA_ECC_CURVE_SECP160R2 ((psa_ecc_curve_t) 0x0011) +#define PSA_ECC_CURVE_SECP192K1 ((psa_ecc_curve_t) 0x0012) +#define PSA_ECC_CURVE_SECP192R1 ((psa_ecc_curve_t) 0x0013) +#define PSA_ECC_CURVE_SECP224K1 ((psa_ecc_curve_t) 0x0014) +#define PSA_ECC_CURVE_SECP224R1 ((psa_ecc_curve_t) 0x0015) +#define PSA_ECC_CURVE_SECP256K1 ((psa_ecc_curve_t) 0x0016) +#define PSA_ECC_CURVE_SECP256R1 ((psa_ecc_curve_t) 0x0017) +#define PSA_ECC_CURVE_SECP384R1 ((psa_ecc_curve_t) 0x0018) +#define PSA_ECC_CURVE_SECP521R1 ((psa_ecc_curve_t) 0x0019) +#define PSA_ECC_CURVE_BRAINPOOL_P256R1 ((psa_ecc_curve_t) 0x001a) +#define PSA_ECC_CURVE_BRAINPOOL_P384R1 ((psa_ecc_curve_t) 0x001b) +#define PSA_ECC_CURVE_BRAINPOOL_P512R1 ((psa_ecc_curve_t) 0x001c) +/** Curve25519. + * + * This is the curve defined in Bernstein et al., + * _Curve25519: new Diffie-Hellman speed records_, LNCS 3958, 2006. + * The algorithm #PSA_ALG_ECDH performs X25519 when used with this curve. + */ +#define PSA_ECC_CURVE_CURVE25519 ((psa_ecc_curve_t) 0x001d) +/** Curve448 + * + * This is the curve defined in Hamburg, + * _Ed448-Goldilocks, a new elliptic curve_, NIST ECC Workshop, 2015. + * The algorithm #PSA_ALG_ECDH performs X448 when used with this curve. + */ +#define PSA_ECC_CURVE_CURVE448 ((psa_ecc_curve_t) 0x001e) + +/** Minimum value for a vendor-defined ECC curve identifier + * + * The range for vendor-defined curve identifiers is a subset of the IANA + * registry private use range, `0xfe00` - `0xfeff`. + */ +#define PSA_ECC_CURVE_VENDOR_MIN ((psa_ecc_curve_t) 0xfe00) +/** Maximum value for a vendor-defined ECC curve identifier + * + * The range for vendor-defined curve identifiers is a subset of the IANA + * registry private use range, `0xfe00` - `0xfeff`. + */ +#define PSA_ECC_CURVE_VENDOR_MAX ((psa_ecc_curve_t) 0xfe7f) + +#define PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE ((psa_key_type_t)0x60040000) +#define PSA_KEY_TYPE_DH_KEY_PAIR_BASE ((psa_key_type_t)0x70040000) +#define PSA_KEY_TYPE_DH_GROUP_MASK ((psa_key_type_t)0x0000ffff) +/** Diffie-Hellman key pair. + * + * \param group A value of type ::psa_dh_group_t that identifies the + * Diffie-Hellman group to be used. + */ +#define PSA_KEY_TYPE_DH_KEY_PAIR(group) \ + (PSA_KEY_TYPE_DH_KEY_PAIR_BASE | (group)) +/** Diffie-Hellman public key. + * + * \param group A value of type ::psa_dh_group_t that identifies the + * Diffie-Hellman group to be used. + */ +#define PSA_KEY_TYPE_DH_PUBLIC_KEY(group) \ + (PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE | (group)) + +/** Whether a key type is a Diffie-Hellman key (pair or public-only). */ +#define PSA_KEY_TYPE_IS_DH(type) \ + ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) & \ + ~PSA_KEY_TYPE_DH_GROUP_MASK) == PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE) +/** Whether a key type is a Diffie-Hellman key pair. */ +#define PSA_KEY_TYPE_IS_DH_KEY_PAIR(type) \ + (((type) & ~PSA_KEY_TYPE_DH_GROUP_MASK) == \ + PSA_KEY_TYPE_DH_KEY_PAIR_BASE) +/** Whether a key type is a Diffie-Hellman public key. */ +#define PSA_KEY_TYPE_IS_DH_PUBLIC_KEY(type) \ + (((type) & ~PSA_KEY_TYPE_DH_GROUP_MASK) == \ + PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE) + +/** Extract the group from a Diffie-Hellman key type. */ +#define PSA_KEY_TYPE_GET_GROUP(type) \ + ((psa_dh_group_t) (PSA_KEY_TYPE_IS_DH(type) ? \ + ((type) & PSA_KEY_TYPE_DH_GROUP_MASK) : \ + 0)) + +/* The encoding of group identifiers is currently aligned with the + * TLS Supported Groups Registry (formerly known as the + * TLS EC Named Curve Registry) + * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 + * The values are defined by RFC 7919. */ +#define PSA_DH_GROUP_FFDHE2048 ((psa_dh_group_t) 0x0100) +#define PSA_DH_GROUP_FFDHE3072 ((psa_dh_group_t) 0x0101) +#define PSA_DH_GROUP_FFDHE4096 ((psa_dh_group_t) 0x0102) +#define PSA_DH_GROUP_FFDHE6144 ((psa_dh_group_t) 0x0103) +#define PSA_DH_GROUP_FFDHE8192 ((psa_dh_group_t) 0x0104) + +/** Minimum value for a vendor-defined Diffie Hellman group identifier + * + * The range for vendor-defined group identifiers is a subset of the IANA + * registry private use range, `0x01fc` - `0x01ff`. + */ +#define PSA_DH_GROUP_VENDOR_MIN ((psa_dh_group_t) 0x01fc) +/** Maximum value for a vendor-defined Diffie Hellman group identifier + * + * The range for vendor-defined group identifiers is a subset of the IANA + * registry private use range, `0x01fc` - `0x01ff`. + */ +#define PSA_DH_GROUP_VENDOR_MAX ((psa_dh_group_t) 0x01fd) + +/** The block size of a block cipher. + * + * \param type A cipher key type (value of type #psa_key_type_t). + * + * \return The block size for a block cipher, or 1 for a stream cipher. + * The return value is undefined if \p type is not a supported + * cipher key type. + * + * \note It is possible to build stream cipher algorithms on top of a block + * cipher, for example CTR mode (#PSA_ALG_CTR). + * This macro only takes the key type into account, so it cannot be + * used to determine the size of the data that #psa_cipher_update() + * might buffer for future processing in general. + * + * \note This macro returns a compile-time constant if its argument is one. + * + * \warning This macro may evaluate its argument multiple times. + */ +#define PSA_BLOCK_CIPHER_BLOCK_SIZE(type) \ + ( \ + (type) == PSA_KEY_TYPE_AES ? 16 : \ + (type) == PSA_KEY_TYPE_DES ? 8 : \ + (type) == PSA_KEY_TYPE_CAMELLIA ? 16 : \ + (type) == PSA_KEY_TYPE_ARC4 ? 1 : \ + (type) == PSA_KEY_TYPE_CHACHA20 ? 1 : \ + 0) + +/** Vendor-defined algorithm flag. + * + * Algorithms defined by this standard will never have the #PSA_ALG_VENDOR_FLAG + * bit set. Vendors who define additional algorithms must use an encoding with + * the #PSA_ALG_VENDOR_FLAG bit set and should respect the bitwise structure + * used by standard encodings whenever practical. + */ +#define PSA_ALG_VENDOR_FLAG ((psa_algorithm_t)0x80000000) + +#define PSA_ALG_CATEGORY_MASK ((psa_algorithm_t)0x7f000000) +#define PSA_ALG_CATEGORY_HASH ((psa_algorithm_t)0x01000000) +#define PSA_ALG_CATEGORY_MAC ((psa_algorithm_t)0x02000000) +#define PSA_ALG_CATEGORY_CIPHER ((psa_algorithm_t)0x04000000) +#define PSA_ALG_CATEGORY_AEAD ((psa_algorithm_t)0x06000000) +#define PSA_ALG_CATEGORY_SIGN ((psa_algorithm_t)0x10000000) +#define PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION ((psa_algorithm_t)0x12000000) +#define PSA_ALG_CATEGORY_KEY_DERIVATION ((psa_algorithm_t)0x20000000) +#define PSA_ALG_CATEGORY_KEY_AGREEMENT ((psa_algorithm_t)0x30000000) + +/** Whether an algorithm is vendor-defined. + * + * See also #PSA_ALG_VENDOR_FLAG. + */ +#define PSA_ALG_IS_VENDOR_DEFINED(alg) \ + (((alg) & PSA_ALG_VENDOR_FLAG) != 0) + +/** Whether the specified algorithm is a hash algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a hash algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_HASH(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_HASH) + +/** Whether the specified algorithm is a MAC algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a MAC algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_MAC(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_MAC) + +/** Whether the specified algorithm is a symmetric cipher algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a symmetric cipher algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_CIPHER(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_CIPHER) + +/** Whether the specified algorithm is an authenticated encryption + * with associated data (AEAD) algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is an AEAD algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_AEAD(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_AEAD) + +/** Whether the specified algorithm is a public-key signature algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a public-key signature algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_SIGN(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_SIGN) + +/** Whether the specified algorithm is a public-key encryption algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a public-key encryption algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION) + +/** Whether the specified algorithm is a key agreement algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a key agreement algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_KEY_AGREEMENT(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_AGREEMENT) + +/** Whether the specified algorithm is a key derivation algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a key derivation algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_KEY_DERIVATION(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_DERIVATION) + +#define PSA_ALG_HASH_MASK ((psa_algorithm_t)0x000000ff) +/** MD2 */ +#define PSA_ALG_MD2 ((psa_algorithm_t)0x01000001) +/** MD4 */ +#define PSA_ALG_MD4 ((psa_algorithm_t)0x01000002) +/** MD5 */ +#define PSA_ALG_MD5 ((psa_algorithm_t)0x01000003) +/** PSA_ALG_RIPEMD160 */ +#define PSA_ALG_RIPEMD160 ((psa_algorithm_t)0x01000004) +/** SHA1 */ +#define PSA_ALG_SHA_1 ((psa_algorithm_t)0x01000005) +/** SHA2-224 */ +#define PSA_ALG_SHA_224 ((psa_algorithm_t)0x01000008) +/** SHA2-256 */ +#define PSA_ALG_SHA_256 ((psa_algorithm_t)0x01000009) +/** SHA2-384 */ +#define PSA_ALG_SHA_384 ((psa_algorithm_t)0x0100000a) +/** SHA2-512 */ +#define PSA_ALG_SHA_512 ((psa_algorithm_t)0x0100000b) +/** SHA2-512/224 */ +#define PSA_ALG_SHA_512_224 ((psa_algorithm_t)0x0100000c) +/** SHA2-512/256 */ +#define PSA_ALG_SHA_512_256 ((psa_algorithm_t)0x0100000d) +/** SHA3-224 */ +#define PSA_ALG_SHA3_224 ((psa_algorithm_t)0x01000010) +/** SHA3-256 */ +#define PSA_ALG_SHA3_256 ((psa_algorithm_t)0x01000011) +/** SHA3-384 */ +#define PSA_ALG_SHA3_384 ((psa_algorithm_t)0x01000012) +/** SHA3-512 */ +#define PSA_ALG_SHA3_512 ((psa_algorithm_t)0x01000013) + +/** In a hash-and-sign algorithm policy, allow any hash algorithm. + * + * This value may be used to form the algorithm usage field of a policy + * for a signature algorithm that is parametrized by a hash. The key + * may then be used to perform operations using the same signature + * algorithm parametrized with any supported hash. + * + * That is, suppose that `PSA_xxx_SIGNATURE` is one of the following macros: + * - #PSA_ALG_RSA_PKCS1V15_SIGN, #PSA_ALG_RSA_PSS, + * - #PSA_ALG_ECDSA, #PSA_ALG_DETERMINISTIC_ECDSA. + * Then you may create and use a key as follows: + * - Set the key usage field using #PSA_ALG_ANY_HASH, for example: + * ``` + * psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); // or VERIFY + * psa_set_key_algorithm(&attributes, PSA_xxx_SIGNATURE(PSA_ALG_ANY_HASH)); + * ``` + * - Import or generate key material. + * - Call psa_sign_hash() or psa_verify_hash(), passing + * an algorithm built from `PSA_xxx_SIGNATURE` and a specific hash. Each + * call to sign or verify a message may use a different hash. + * ``` + * psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA_256), ...); + * psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA_512), ...); + * psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA3_256), ...); + * ``` + * + * This value may not be used to build other algorithms that are + * parametrized over a hash. For any valid use of this macro to build + * an algorithm \c alg, #PSA_ALG_IS_HASH_AND_SIGN(\c alg) is true. + * + * This value may not be used to build an algorithm specification to + * perform an operation. It is only valid to build policies. + */ +#define PSA_ALG_ANY_HASH ((psa_algorithm_t)0x010000ff) + +#define PSA_ALG_MAC_SUBCATEGORY_MASK ((psa_algorithm_t)0x00c00000) +#define PSA_ALG_HMAC_BASE ((psa_algorithm_t)0x02800000) +/** Macro to build an HMAC algorithm. + * + * For example, #PSA_ALG_HMAC(#PSA_ALG_SHA_256) is HMAC-SHA-256. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding HMAC algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_HMAC(hash_alg) \ + (PSA_ALG_HMAC_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) + +#define PSA_ALG_HMAC_GET_HASH(hmac_alg) \ + (PSA_ALG_CATEGORY_HASH | ((hmac_alg) & PSA_ALG_HASH_MASK)) + +/** Whether the specified algorithm is an HMAC algorithm. + * + * HMAC is a family of MAC algorithms that are based on a hash function. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is an HMAC algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_HMAC(alg) \ + (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \ + PSA_ALG_HMAC_BASE) + +/* In the encoding of a MAC algorithm, the bits corresponding to + * PSA_ALG_MAC_TRUNCATION_MASK encode the length to which the MAC is + * truncated. As an exception, the value 0 means the untruncated algorithm, + * whatever its length is. The length is encoded in 6 bits, so it can + * reach up to 63; the largest MAC is 64 bytes so its trivial truncation + * to full length is correctly encoded as 0 and any non-trivial truncation + * is correctly encoded as a value between 1 and 63. */ +#define PSA_ALG_MAC_TRUNCATION_MASK ((psa_algorithm_t)0x00003f00) +#define PSA_MAC_TRUNCATION_OFFSET 8 + +/** Macro to build a truncated MAC algorithm. + * + * A truncated MAC algorithm is identical to the corresponding MAC + * algorithm except that the MAC value for the truncated algorithm + * consists of only the first \p mac_length bytes of the MAC value + * for the untruncated algorithm. + * + * \note This macro may allow constructing algorithm identifiers that + * are not valid, either because the specified length is larger + * than the untruncated MAC or because the specified length is + * smaller than permitted by the implementation. + * + * \note It is implementation-defined whether a truncated MAC that + * is truncated to the same length as the MAC of the untruncated + * algorithm is considered identical to the untruncated algorithm + * for policy comparison purposes. + * + * \param mac_alg A MAC algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg) + * is true). This may be a truncated or untruncated + * MAC algorithm. + * \param mac_length Desired length of the truncated MAC in bytes. + * This must be at most the full length of the MAC + * and must be at least an implementation-specified + * minimum. The implementation-specified minimum + * shall not be zero. + * + * \return The corresponding MAC algorithm with the specified + * length. + * \return Unspecified if \p alg is not a supported + * MAC algorithm or if \p mac_length is too small or + * too large for the specified MAC algorithm. + */ +#define PSA_ALG_TRUNCATED_MAC(mac_alg, mac_length) \ + (((mac_alg) & ~PSA_ALG_MAC_TRUNCATION_MASK) | \ + ((mac_length) << PSA_MAC_TRUNCATION_OFFSET & PSA_ALG_MAC_TRUNCATION_MASK)) + +/** Macro to build the base MAC algorithm corresponding to a truncated + * MAC algorithm. + * + * \param mac_alg A MAC algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg) + * is true). This may be a truncated or untruncated + * MAC algorithm. + * + * \return The corresponding base MAC algorithm. + * \return Unspecified if \p alg is not a supported + * MAC algorithm. + */ +#define PSA_ALG_FULL_LENGTH_MAC(mac_alg) \ + ((mac_alg) & ~PSA_ALG_MAC_TRUNCATION_MASK) + +/** Length to which a MAC algorithm is truncated. + * + * \param mac_alg A MAC algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg) + * is true). + * + * \return Length of the truncated MAC in bytes. + * \return 0 if \p alg is a non-truncated MAC algorithm. + * \return Unspecified if \p alg is not a supported + * MAC algorithm. + */ +#define PSA_MAC_TRUNCATED_LENGTH(mac_alg) \ + (((mac_alg) & PSA_ALG_MAC_TRUNCATION_MASK) >> PSA_MAC_TRUNCATION_OFFSET) + +#define PSA_ALG_CIPHER_MAC_BASE ((psa_algorithm_t)0x02c00000) +/** The CBC-MAC construction over a block cipher + * + * \warning CBC-MAC is insecure in many cases. + * A more secure mode, such as #PSA_ALG_CMAC, is recommended. + */ +#define PSA_ALG_CBC_MAC ((psa_algorithm_t)0x02c00001) +/** The CMAC construction over a block cipher */ +#define PSA_ALG_CMAC ((psa_algorithm_t)0x02c00002) + +/** Whether the specified algorithm is a MAC algorithm based on a block cipher. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a MAC algorithm based on a block cipher, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) \ + (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \ + PSA_ALG_CIPHER_MAC_BASE) + +#define PSA_ALG_CIPHER_STREAM_FLAG ((psa_algorithm_t)0x00800000) +#define PSA_ALG_CIPHER_FROM_BLOCK_FLAG ((psa_algorithm_t)0x00400000) + +/** Whether the specified algorithm is a stream cipher. + * + * A stream cipher is a symmetric cipher that encrypts or decrypts messages + * by applying a bitwise-xor with a stream of bytes that is generated + * from a key. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a stream cipher algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier or if it is not a symmetric cipher algorithm. + */ +#define PSA_ALG_IS_STREAM_CIPHER(alg) \ + (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_CIPHER_STREAM_FLAG)) == \ + (PSA_ALG_CATEGORY_CIPHER | PSA_ALG_CIPHER_STREAM_FLAG)) + +/** The ARC4 stream cipher algorithm. + */ +#define PSA_ALG_ARC4 ((psa_algorithm_t)0x04800001) + +/** The ChaCha20 stream cipher. + * + * ChaCha20 is defined in RFC 7539. + * + * The nonce size for psa_cipher_set_iv() or psa_cipher_generate_iv() + * must be 12. + * + * The initial block counter is always 0. + * + */ +#define PSA_ALG_CHACHA20 ((psa_algorithm_t)0x04800005) + +/** The CTR stream cipher mode. + * + * CTR is a stream cipher which is built from a block cipher. + * The underlying block cipher is determined by the key type. + * For example, to use AES-128-CTR, use this algorithm with + * a key of type #PSA_KEY_TYPE_AES and a length of 128 bits (16 bytes). + */ +#define PSA_ALG_CTR ((psa_algorithm_t)0x04c00001) + +/** The CFB stream cipher mode. + * + * The underlying block cipher is determined by the key type. + */ +#define PSA_ALG_CFB ((psa_algorithm_t)0x04c00002) + +/** The OFB stream cipher mode. + * + * The underlying block cipher is determined by the key type. + */ +#define PSA_ALG_OFB ((psa_algorithm_t)0x04c00003) + +/** The XTS cipher mode. + * + * XTS is a cipher mode which is built from a block cipher. It requires at + * least one full block of input, but beyond this minimum the input + * does not need to be a whole number of blocks. + */ +#define PSA_ALG_XTS ((psa_algorithm_t)0x044000ff) + +/** The CBC block cipher chaining mode, with no padding. + * + * The underlying block cipher is determined by the key type. + * + * This symmetric cipher mode can only be used with messages whose lengths + * are whole number of blocks for the chosen block cipher. + */ +#define PSA_ALG_CBC_NO_PADDING ((psa_algorithm_t)0x04600100) + +/** The CBC block cipher chaining mode with PKCS#7 padding. + * + * The underlying block cipher is determined by the key type. + * + * This is the padding method defined by PKCS#7 (RFC 2315) §10.3. + */ +#define PSA_ALG_CBC_PKCS7 ((psa_algorithm_t)0x04600101) + +#define PSA_ALG_AEAD_FROM_BLOCK_FLAG ((psa_algorithm_t)0x00400000) + +/** Whether the specified algorithm is an AEAD mode on a block cipher. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is an AEAD algorithm which is an AEAD mode based on + * a block cipher, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) \ + (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_AEAD_FROM_BLOCK_FLAG)) == \ + (PSA_ALG_CATEGORY_AEAD | PSA_ALG_AEAD_FROM_BLOCK_FLAG)) + +/** The CCM authenticated encryption algorithm. + * + * The underlying block cipher is determined by the key type. + */ +#define PSA_ALG_CCM ((psa_algorithm_t)0x06401001) + +/** The GCM authenticated encryption algorithm. + * + * The underlying block cipher is determined by the key type. + */ +#define PSA_ALG_GCM ((psa_algorithm_t)0x06401002) + +/** The Chacha20-Poly1305 AEAD algorithm. + * + * The ChaCha20_Poly1305 construction is defined in RFC 7539. + * + * Implementations must support 12-byte nonces, may support 8-byte nonces, + * and should reject other sizes. + * + * Implementations must support 16-byte tags and should reject other sizes. + */ +#define PSA_ALG_CHACHA20_POLY1305 ((psa_algorithm_t)0x06001005) + +/* In the encoding of a AEAD algorithm, the bits corresponding to + * PSA_ALG_AEAD_TAG_LENGTH_MASK encode the length of the AEAD tag. + * The constants for default lengths follow this encoding. + */ +#define PSA_ALG_AEAD_TAG_LENGTH_MASK ((psa_algorithm_t)0x00003f00) +#define PSA_AEAD_TAG_LENGTH_OFFSET 8 + +/** Macro to build a shortened AEAD algorithm. + * + * A shortened AEAD algorithm is similar to the corresponding AEAD + * algorithm, but has an authentication tag that consists of fewer bytes. + * Depending on the algorithm, the tag length may affect the calculation + * of the ciphertext. + * + * \param aead_alg An AEAD algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_AEAD(\p alg) + * is true). + * \param tag_length Desired length of the authentication tag in bytes. + * + * \return The corresponding AEAD algorithm with the specified + * length. + * \return Unspecified if \p alg is not a supported + * AEAD algorithm or if \p tag_length is not valid + * for the specified AEAD algorithm. + */ +#define PSA_ALG_AEAD_WITH_TAG_LENGTH(aead_alg, tag_length) \ + (((aead_alg) & ~PSA_ALG_AEAD_TAG_LENGTH_MASK) | \ + ((tag_length) << PSA_AEAD_TAG_LENGTH_OFFSET & \ + PSA_ALG_AEAD_TAG_LENGTH_MASK)) + +/** Calculate the corresponding AEAD algorithm with the default tag length. + * + * \param aead_alg An AEAD algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return The corresponding AEAD algorithm with the default + * tag length for that algorithm. + */ +#define PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH(aead_alg) \ + ( \ + PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, PSA_ALG_CCM) \ + PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, PSA_ALG_GCM) \ + PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, PSA_ALG_CHACHA20_POLY1305) \ + 0) +#define PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, ref) \ + PSA_ALG_AEAD_WITH_TAG_LENGTH(aead_alg, 0) == \ + PSA_ALG_AEAD_WITH_TAG_LENGTH(ref, 0) ? \ + ref : + +#define PSA_ALG_RSA_PKCS1V15_SIGN_BASE ((psa_algorithm_t)0x10020000) +/** RSA PKCS#1 v1.5 signature with hashing. + * + * This is the signature scheme defined by RFC 8017 + * (PKCS#1: RSA Cryptography Specifications) under the name + * RSASSA-PKCS1-v1_5. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding RSA PKCS#1 v1.5 signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_RSA_PKCS1V15_SIGN(hash_alg) \ + (PSA_ALG_RSA_PKCS1V15_SIGN_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +/** Raw PKCS#1 v1.5 signature. + * + * The input to this algorithm is the DigestInfo structure used by + * RFC 8017 (PKCS#1: RSA Cryptography Specifications), §9.2 + * steps 3–6. + */ +#define PSA_ALG_RSA_PKCS1V15_SIGN_RAW PSA_ALG_RSA_PKCS1V15_SIGN_BASE +#define PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PKCS1V15_SIGN_BASE) + +#define PSA_ALG_RSA_PSS_BASE ((psa_algorithm_t)0x10030000) +/** RSA PSS signature with hashing. + * + * This is the signature scheme defined by RFC 8017 + * (PKCS#1: RSA Cryptography Specifications) under the name + * RSASSA-PSS, with the message generation function MGF1, and with + * a salt length equal to the length of the hash. The specified + * hash algorithm is used to hash the input message, to create the + * salted hash, and for the mask generation. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding RSA PSS signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_RSA_PSS(hash_alg) \ + (PSA_ALG_RSA_PSS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_IS_RSA_PSS(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PSS_BASE) + +#define PSA_ALG_ECDSA_BASE ((psa_algorithm_t)0x10060000) +/** ECDSA signature with hashing. + * + * This is the ECDSA signature scheme defined by ANSI X9.62, + * with a random per-message secret number (*k*). + * + * The representation of the signature as a byte string consists of + * the concatentation of the signature values *r* and *s*. Each of + * *r* and *s* is encoded as an *N*-octet string, where *N* is the length + * of the base point of the curve in octets. Each value is represented + * in big-endian order (most significant octet first). + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding ECDSA signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_ECDSA(hash_alg) \ + (PSA_ALG_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +/** ECDSA signature without hashing. + * + * This is the same signature scheme as #PSA_ALG_ECDSA(), but + * without specifying a hash algorithm. This algorithm may only be + * used to sign or verify a sequence of bytes that should be an + * already-calculated hash. Note that the input is padded with + * zeros on the left or truncated on the left as required to fit + * the curve size. + */ +#define PSA_ALG_ECDSA_ANY PSA_ALG_ECDSA_BASE +#define PSA_ALG_DETERMINISTIC_ECDSA_BASE ((psa_algorithm_t)0x10070000) +/** Deterministic ECDSA signature with hashing. + * + * This is the deterministic ECDSA signature scheme defined by RFC 6979. + * + * The representation of a signature is the same as with #PSA_ALG_ECDSA(). + * + * Note that when this algorithm is used for verification, signatures + * made with randomized ECDSA (#PSA_ALG_ECDSA(\p hash_alg)) with the + * same private key are accepted. In other words, + * #PSA_ALG_DETERMINISTIC_ECDSA(\p hash_alg) differs from + * #PSA_ALG_ECDSA(\p hash_alg) only for signature, not for verification. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding deterministic ECDSA signature + * algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_DETERMINISTIC_ECDSA(hash_alg) \ + (PSA_ALG_DETERMINISTIC_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_ECDSA_DETERMINISTIC_FLAG ((psa_algorithm_t)0x00010000) +#define PSA_ALG_IS_ECDSA(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_ECDSA_DETERMINISTIC_FLAG) == \ + PSA_ALG_ECDSA_BASE) +#define PSA_ALG_ECDSA_IS_DETERMINISTIC(alg) \ + (((alg) & PSA_ALG_ECDSA_DETERMINISTIC_FLAG) != 0) +#define PSA_ALG_IS_DETERMINISTIC_ECDSA(alg) \ + (PSA_ALG_IS_ECDSA(alg) && PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) +#define PSA_ALG_IS_RANDOMIZED_ECDSA(alg) \ + (PSA_ALG_IS_ECDSA(alg) && !PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) + +/** Whether the specified algorithm is a hash-and-sign algorithm. + * + * Hash-and-sign algorithms are public-key signature algorithms structured + * in two parts: first the calculation of a hash in a way that does not + * depend on the key, then the calculation of a signature from the + * hash value and the key. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a hash-and-sign algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_HASH_AND_SIGN(alg) \ + (PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || \ + PSA_ALG_IS_ECDSA(alg)) + +/** Get the hash used by a hash-and-sign signature algorithm. + * + * A hash-and-sign algorithm is a signature algorithm which is + * composed of two phases: first a hashing phase which does not use + * the key and produces a hash of the input message, then a signing + * phase which only uses the hash and the key and not the message + * itself. + * + * \param alg A signature algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_SIGN(\p alg) is true). + * + * \return The underlying hash algorithm if \p alg is a hash-and-sign + * algorithm. + * \return 0 if \p alg is a signature algorithm that does not + * follow the hash-and-sign structure. + * \return Unspecified if \p alg is not a signature algorithm or + * if it is not supported by the implementation. + */ +#define PSA_ALG_SIGN_GET_HASH(alg) \ + (PSA_ALG_IS_HASH_AND_SIGN(alg) ? \ + ((alg) & PSA_ALG_HASH_MASK) == 0 ? /*"raw" algorithm*/ 0 : \ + ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ + 0) + +/** RSA PKCS#1 v1.5 encryption. + */ +#define PSA_ALG_RSA_PKCS1V15_CRYPT ((psa_algorithm_t)0x12020000) + +#define PSA_ALG_RSA_OAEP_BASE ((psa_algorithm_t)0x12030000) +/** RSA OAEP encryption. + * + * This is the encryption scheme defined by RFC 8017 + * (PKCS#1: RSA Cryptography Specifications) under the name + * RSAES-OAEP, with the message generation function MGF1. + * + * \param hash_alg The hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true) to use + * for MGF1. + * + * \return The corresponding RSA OAEP signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_RSA_OAEP(hash_alg) \ + (PSA_ALG_RSA_OAEP_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_IS_RSA_OAEP(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_OAEP_BASE) +#define PSA_ALG_RSA_OAEP_GET_HASH(alg) \ + (PSA_ALG_IS_RSA_OAEP(alg) ? \ + ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ + 0) + +#define PSA_ALG_HKDF_BASE ((psa_algorithm_t)0x20000100) +/** Macro to build an HKDF algorithm. + * + * For example, `PSA_ALG_HKDF(PSA_ALG_SHA256)` is HKDF using HMAC-SHA-256. + * + * This key derivation algorithm uses the following inputs: + * - #PSA_KEY_DERIVATION_INPUT_SALT is the salt used in the "extract" step. + * It is optional; if omitted, the derivation uses an empty salt. + * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key used in the "extract" step. + * - #PSA_KEY_DERIVATION_INPUT_INFO is the info string used in the "expand" step. + * You must pass #PSA_KEY_DERIVATION_INPUT_SALT before #PSA_KEY_DERIVATION_INPUT_SECRET. + * You may pass #PSA_KEY_DERIVATION_INPUT_INFO at any time after steup and before + * starting to generate output. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding HKDF algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_HKDF(hash_alg) \ + (PSA_ALG_HKDF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +/** Whether the specified algorithm is an HKDF algorithm. + * + * HKDF is a family of key derivation algorithms that are based on a hash + * function and the HMAC construction. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is an HKDF algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_HKDF(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_BASE) +#define PSA_ALG_HKDF_GET_HASH(hkdf_alg) \ + (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) + +#define PSA_ALG_TLS12_PRF_BASE ((psa_algorithm_t)0x20000200) +/** Macro to build a TLS-1.2 PRF algorithm. + * + * TLS 1.2 uses a custom pseudorandom function (PRF) for key schedule, + * specified in Section 5 of RFC 5246. It is based on HMAC and can be + * used with either SHA-256 or SHA-384. + * + * This key derivation algorithm uses the following inputs, which must be + * passed in the order given here: + * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed. + * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key. + * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label. + * + * For the application to TLS-1.2 key expansion, the seed is the + * concatenation of ServerHello.Random + ClientHello.Random, + * and the label is "key expansion". + * + * For example, `PSA_ALG_TLS12_PRF(PSA_ALG_SHA256)` represents the + * TLS 1.2 PRF using HMAC-SHA-256. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding TLS-1.2 PRF algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_TLS12_PRF(hash_alg) \ + (PSA_ALG_TLS12_PRF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) + +/** Whether the specified algorithm is a TLS-1.2 PRF algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a TLS-1.2 PRF algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_TLS12_PRF(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_TLS12_PRF_BASE) +#define PSA_ALG_TLS12_PRF_GET_HASH(hkdf_alg) \ + (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) + +#define PSA_ALG_TLS12_PSK_TO_MS_BASE ((psa_algorithm_t)0x20000300) +/** Macro to build a TLS-1.2 PSK-to-MasterSecret algorithm. + * + * In a pure-PSK handshake in TLS 1.2, the master secret is derived + * from the PreSharedKey (PSK) through the application of padding + * (RFC 4279, Section 2) and the TLS-1.2 PRF (RFC 5246, Section 5). + * The latter is based on HMAC and can be used with either SHA-256 + * or SHA-384. + * + * This key derivation algorithm uses the following inputs, which must be + * passed in the order given here: + * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed. + * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key. + * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label. + * + * For the application to TLS-1.2, the seed (which is + * forwarded to the TLS-1.2 PRF) is the concatenation of the + * ClientHello.Random + ServerHello.Random, + * and the label is "master secret" or "extended master secret". + * + * For example, `PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA256)` represents the + * TLS-1.2 PSK to MasterSecret derivation PRF using HMAC-SHA-256. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding TLS-1.2 PSK to MS algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_TLS12_PSK_TO_MS(hash_alg) \ + (PSA_ALG_TLS12_PSK_TO_MS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) + +/** Whether the specified algorithm is a TLS-1.2 PSK to MS algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a TLS-1.2 PSK to MS algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_TLS12_PSK_TO_MS(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_TLS12_PSK_TO_MS_BASE) +#define PSA_ALG_TLS12_PSK_TO_MS_GET_HASH(hkdf_alg) \ + (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) + +#define PSA_ALG_KEY_DERIVATION_MASK ((psa_algorithm_t)0x0803ffff) +#define PSA_ALG_KEY_AGREEMENT_MASK ((psa_algorithm_t)0x10fc0000) + +/** Macro to build a combined algorithm that chains a key agreement with + * a key derivation. + * + * \param ka_alg A key agreement algorithm (\c PSA_ALG_XXX value such + * that #PSA_ALG_IS_KEY_AGREEMENT(\p ka_alg) is true). + * \param kdf_alg A key derivation algorithm (\c PSA_ALG_XXX value such + * that #PSA_ALG_IS_KEY_DERIVATION(\p kdf_alg) is true). + * + * \return The corresponding key agreement and derivation + * algorithm. + * \return Unspecified if \p ka_alg is not a supported + * key agreement algorithm or \p kdf_alg is not a + * supported key derivation algorithm. + */ +#define PSA_ALG_KEY_AGREEMENT(ka_alg, kdf_alg) \ + ((ka_alg) | (kdf_alg)) + +#define PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) \ + (((alg) & PSA_ALG_KEY_DERIVATION_MASK) | PSA_ALG_CATEGORY_KEY_DERIVATION) + +#define PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) \ + (((alg) & PSA_ALG_KEY_AGREEMENT_MASK) | PSA_ALG_CATEGORY_KEY_AGREEMENT) + +/** Whether the specified algorithm is a raw key agreement algorithm. + * + * A raw key agreement algorithm is one that does not specify + * a key derivation function. + * Usually, raw key agreement algorithms are constructed directly with + * a \c PSA_ALG_xxx macro while non-raw key agreement algorithms are + * constructed with PSA_ALG_KEY_AGREEMENT(). + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a raw key agreement algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_RAW_KEY_AGREEMENT(alg) \ + (PSA_ALG_IS_KEY_AGREEMENT(alg) && \ + PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) == PSA_ALG_CATEGORY_KEY_DERIVATION) + +#define PSA_ALG_IS_KEY_DERIVATION_OR_AGREEMENT(alg) \ + ((PSA_ALG_IS_KEY_DERIVATION(alg) || PSA_ALG_IS_KEY_AGREEMENT(alg))) + +/** The finite-field Diffie-Hellman (DH) key agreement algorithm. + * + * The shared secret produced by key agreement is + * `g^{ab}` in big-endian format. + * It is `ceiling(m / 8)` bytes long where `m` is the size of the prime `p` + * in bits. + */ +#define PSA_ALG_FFDH ((psa_algorithm_t)0x30100000) + +/** Whether the specified algorithm is a finite field Diffie-Hellman algorithm. + * + * This includes the raw finite field Diffie-Hellman algorithm as well as + * finite-field Diffie-Hellman followed by any supporter key derivation + * algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a finite field Diffie-Hellman algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key agreement algorithm identifier. + */ +#define PSA_ALG_IS_FFDH(alg) \ + (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_FFDH) + +/** The elliptic curve Diffie-Hellman (ECDH) key agreement algorithm. + * + * The shared secret produced by key agreement is the x-coordinate of + * the shared secret point. It is always `ceiling(m / 8)` bytes long where + * `m` is the bit size associated with the curve, i.e. the bit size of the + * order of the curve's coordinate field. When `m` is not a multiple of 8, + * the byte containing the most significant bit of the shared secret + * is padded with zero bits. The byte order is either little-endian + * or big-endian depending on the curve type. + * + * - For Montgomery curves (curve types `PSA_ECC_CURVE_CURVEXXX`), + * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` + * in little-endian byte order. + * The bit size is 448 for Curve448 and 255 for Curve25519. + * - For Weierstrass curves over prime fields (curve types + * `PSA_ECC_CURVE_SECPXXX` and `PSA_ECC_CURVE_BRAINPOOL_PXXX`), + * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` + * in big-endian byte order. + * The bit size is `m = ceiling(log_2(p))` for the field `F_p`. + * - For Weierstrass curves over binary fields (curve types + * `PSA_ECC_CURVE_SECTXXX`), + * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` + * in big-endian byte order. + * The bit size is `m` for the field `F_{2^m}`. + */ +#define PSA_ALG_ECDH ((psa_algorithm_t)0x30200000) + +/** Whether the specified algorithm is an elliptic curve Diffie-Hellman + * algorithm. + * + * This includes the raw elliptic curve Diffie-Hellman algorithm as well as + * elliptic curve Diffie-Hellman followed by any supporter key derivation + * algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is an elliptic curve Diffie-Hellman algorithm, + * 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key agreement algorithm identifier. + */ +#define PSA_ALG_IS_ECDH(alg) \ + (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_ECDH) + +/** Whether the specified algorithm encoding is a wildcard. + * + * Wildcard values may only be used to set the usage algorithm field in + * a policy, not to perform an operation. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a wildcard algorithm encoding. + * \return 0 if \c alg is a non-wildcard algorithm encoding (suitable for + * an operation). + * \return This macro may return either 0 or 1 if \c alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_WILDCARD(alg) \ + (PSA_ALG_IS_HASH_AND_SIGN(alg) ? \ + PSA_ALG_SIGN_GET_HASH(alg) == PSA_ALG_ANY_HASH : \ + (alg) == PSA_ALG_ANY_HASH) + +/**@}*/ + +/** \defgroup key_lifetimes Key lifetimes + * @{ + */ + +/** A volatile key only exists as long as the handle to it is not closed. + * The key material is guaranteed to be erased on a power reset. + */ +#define PSA_KEY_LIFETIME_VOLATILE ((psa_key_lifetime_t)0x00000000) + +/** The default storage area for persistent keys. + * + * A persistent key remains in storage until it is explicitly destroyed or + * until the corresponding storage area is wiped. This specification does + * not define any mechanism to wipe a storage area, but implementations may + * provide their own mechanism (for example to perform a factory reset, + * to prepare for device refurbishment, or to uninstall an application). + * + * This lifetime value is the default storage area for the calling + * application. Implementations may offer other storage areas designated + * by other lifetime values as implementation-specific extensions. + */ +#define PSA_KEY_LIFETIME_PERSISTENT ((psa_key_lifetime_t)0x00000001) + +/** The minimum value for a key identifier chosen by the application. + */ +#define PSA_KEY_ID_USER_MIN ((psa_key_id_t)0x00000001) +/** The maximum value for a key identifier chosen by the application. + */ +#define PSA_KEY_ID_USER_MAX ((psa_key_id_t)0x3fffffff) +/** The minimum value for a key identifier chosen by the implementation. + */ +#define PSA_KEY_ID_VENDOR_MIN ((psa_key_id_t)0x40000000) +/** The maximum value for a key identifier chosen by the implementation. + */ +#define PSA_KEY_ID_VENDOR_MAX ((psa_key_id_t)0x7fffffff) + +/**@}*/ + +/** \defgroup policy Key policies + * @{ + */ + +/** Whether the key may be exported. + * + * A public key or the public part of a key pair may always be exported + * regardless of the value of this permission flag. + * + * If a key does not have export permission, implementations shall not + * allow the key to be exported in plain form from the cryptoprocessor, + * whether through psa_export_key() or through a proprietary interface. + * The key may however be exportable in a wrapped form, i.e. in a form + * where it is encrypted by another key. + */ +#define PSA_KEY_USAGE_EXPORT ((psa_key_usage_t)0x00000001) + +/** Whether the key may be copied. + * + * This flag allows the use of psa_copy_key() to make a copy of the key + * with the same policy or a more restrictive policy. + * + * For lifetimes for which the key is located in a secure element which + * enforce the non-exportability of keys, copying a key outside the secure + * element also requires the usage flag #PSA_KEY_USAGE_EXPORT. + * Copying the key inside the secure element is permitted with just + * #PSA_KEY_USAGE_COPY if the secure element supports it. + * For keys with the lifetime #PSA_KEY_LIFETIME_VOLATILE or + * #PSA_KEY_LIFETIME_PERSISTENT, the usage flag #PSA_KEY_USAGE_COPY + * is sufficient to permit the copy. + */ +#define PSA_KEY_USAGE_COPY ((psa_key_usage_t)0x00000002) + +/** Whether the key may be used to encrypt a message. + * + * This flag allows the key to be used for a symmetric encryption operation, + * for an AEAD encryption-and-authentication operation, + * or for an asymmetric encryption operation, + * if otherwise permitted by the key's type and policy. + * + * For a key pair, this concerns the public key. + */ +#define PSA_KEY_USAGE_ENCRYPT ((psa_key_usage_t)0x00000100) + +/** Whether the key may be used to decrypt a message. + * + * This flag allows the key to be used for a symmetric decryption operation, + * for an AEAD decryption-and-verification operation, + * or for an asymmetric decryption operation, + * if otherwise permitted by the key's type and policy. + * + * For a key pair, this concerns the private key. + */ +#define PSA_KEY_USAGE_DECRYPT ((psa_key_usage_t)0x00000200) + +/** Whether the key may be used to sign a message. + * + * This flag allows the key to be used for a MAC calculation operation + * or for an asymmetric signature operation, + * if otherwise permitted by the key's type and policy. + * + * For a key pair, this concerns the private key. + */ +#define PSA_KEY_USAGE_SIGN_HASH ((psa_key_usage_t)0x00000400) + +/** Whether the key may be used to verify a message signature. + * + * This flag allows the key to be used for a MAC verification operation + * or for an asymmetric signature verification operation, + * if otherwise permitted by by the key's type and policy. + * + * For a key pair, this concerns the public key. + */ +#define PSA_KEY_USAGE_VERIFY_HASH ((psa_key_usage_t)0x00000800) + +/** Whether the key may be used to derive other keys. + */ +#define PSA_KEY_USAGE_DERIVE ((psa_key_usage_t)0x00001000) + +/**@}*/ + +/** \defgroup derivation Key derivation + * @{ + */ + +/** A secret input for key derivation. + * + * This should be a key of type #PSA_KEY_TYPE_DERIVE + * (passed to psa_key_derivation_input_key()) + * or the shared secret resulting from a key agreement + * (obtained via psa_key_derivation_key_agreement()). + * + * The secret can also be a direct input (passed to + * key_derivation_input_bytes()). In this case, the derivation operation + * may not be used to derive keys: the operation will only allow + * psa_key_derivation_output_bytes(), not psa_key_derivation_output_key(). + */ +#define PSA_KEY_DERIVATION_INPUT_SECRET ((psa_key_derivation_step_t)0x0101) + +/** A label for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + */ +#define PSA_KEY_DERIVATION_INPUT_LABEL ((psa_key_derivation_step_t)0x0201) + +/** A salt for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + */ +#define PSA_KEY_DERIVATION_INPUT_SALT ((psa_key_derivation_step_t)0x0202) + +/** An information string for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + */ +#define PSA_KEY_DERIVATION_INPUT_INFO ((psa_key_derivation_step_t)0x0203) + +/** A seed for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + */ +#define PSA_KEY_DERIVATION_INPUT_SEED ((psa_key_derivation_step_t)0x0204) + +/**@}*/ + +#endif /* PSA_CRYPTO_VALUES_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/error.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/error.h new file mode 100644 index 0000000..439dba4 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/error.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/** + * \file psa/error.h + * \brief Standard error codes for the SPM and RoT Services + */ + +#ifndef __PSA_ERROR_H__ +#define __PSA_ERROR_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* If #PSA_SUCCESS is already defined, it means that #psa_status_t + * is also defined in an external header, so prevent its multiple + * definition. + */ +#ifndef PSA_SUCCESS +typedef int32_t psa_status_t; +#endif + +#define PSA_SUCCESS ((psa_status_t)0) + +#define PSA_ERROR_PROGRAMMER_ERROR ((psa_status_t)-129) +#define PSA_ERROR_CONNECTION_REFUSED ((psa_status_t)-130) +#define PSA_ERROR_CONNECTION_BUSY ((psa_status_t)-131) +#define PSA_ERROR_GENERIC_ERROR ((psa_status_t)-132) +#define PSA_ERROR_NOT_PERMITTED ((psa_status_t)-133) +#define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)-134) +#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)-135) +#define PSA_ERROR_INVALID_HANDLE ((psa_status_t)-136) +#define PSA_ERROR_BAD_STATE ((psa_status_t)-137) +#define PSA_ERROR_BUFFER_TOO_SMALL ((psa_status_t)-138) +#define PSA_ERROR_ALREADY_EXISTS ((psa_status_t)-139) +#define PSA_ERROR_DOES_NOT_EXIST ((psa_status_t)-140) +#define PSA_ERROR_INSUFFICIENT_MEMORY ((psa_status_t)-141) +#define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)-142) +#define PSA_ERROR_INSUFFICIENT_DATA ((psa_status_t)-143) +#define PSA_ERROR_SERVICE_FAILURE ((psa_status_t)-144) +#define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t)-145) +#define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)-146) +#define PSA_ERROR_HARDWARE_FAILURE ((psa_status_t)-147) +#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) + +#ifdef __cplusplus +} +#endif + +#endif /* __PSA_ERROR_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/initial_attestation.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/initial_attestation.h new file mode 100644 index 0000000..c125a4d --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/initial_attestation.h @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/***************************************************************************/ +/* DRAFT UNDER REVIEW */ +/* These APIs are still evolving and are meant as a prototype for review.*/ +/* The APIs will change depending on feedback and will be firmed up */ +/* to a stable set of APIs once all the feedback has been considered. */ +/***************************************************************************/ + +#ifndef __PSA_INITIAL_ATTESTATION_H__ +#define __PSA_INITIAL_ATTESTATION_H__ + +#include +#include +#include +#include "psa/crypto.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief PSA INITIAL ATTESTATION API version + * + * Initial attestation API version is: 1.0.0 + */ +#define PSA_INITIAL_ATTEST_API_VERSION_MAJOR (1) +#define PSA_INITIAL_ATTEST_API_VERSION_MINOR (0) + +/** + * The allowed size of input challenge in bytes: 32, 48, 64 + * Challenge can be a nonce from server + * or the hash of some combined data : nonce + attested data by caller. + */ +#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32 (32u) +#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48 (48u) +#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64 (64u) + +/** + * The maximum size of an attestation token that can be generated by the + * attestation service. Used to configure buffers for services that verify the + * produced tokens. + */ +#define PSA_INITIAL_ATTEST_MAX_TOKEN_SIZE (0x400) + +/** + * The list of fixed claims in the initial attestation token is still evolving, + * you can expect slight changes in the future. + * + * The initial attestation token is planned to be aligned with future version of + * Entity Attestation Token format: + * https://tools.ietf.org/html/draft-mandyam-eat-01 + * + * Current list of claims: + * - Challenge: Input object from caller. Can be a single nonce from server + * or hash of nonce and attested data. It is intended to provide + * freshness to reports and the caller has responsibility to + * arrange this. Allowed length: 32, 48, 64 bytes. The claim is + * modeled to be eventually represented by the EAT standard + * claim nonce. Until such a time as that standard exists, + * the claim will be represented by a custom claim. Value + * is encoded as byte string. + * + * - Instance ID: It represents the unique identifier of the instance. In the + * PSA definition it is a hash of the public attestation key + * of the instance. The claim is modeled to be eventually + * represented by the EAT standard claim UEID of type GUID. + * Until such a time as that standard exists, the claim will be + * represented by a custom claim Value is encoded as byte + * string. + * + * - Verification service indicator: Optional, recommended claim. It is used by + * a Relying Party to locate a validation service for the token. + * The value is a text string that can be used to locate the + * service or a URL specifying the address of the service. The + * claim is modeled to be eventually represented by the EAT + * standard claim origination. Until such a time as that + * standard exists, the claim will be represented by a custom + * claim. Value is encoded as text string. + * + * - Profile definition: Optional, recommended claim. It contains the name of + * a document that describes the 'profile' of the token, being + * a full description of the claims, their usage, verification + * and token signing. The document name may include versioning. + * Custom claim with a value encoded as text string. + * + * - Implementation ID: It represents the original implementation signer of the + * attestation key and identifies the contract between the + * report and verification. A verification service will use this + * claim to locate the details of the verification process. + * Custom claim with a value encoded as byte string. + * + * - Security lifecycle: It represents the current lifecycle state of the + * instance. Custom claim with a value encoded as integer that + * is divided to convey a major state and a minor state. The + * PSA state and implementation state are encoded as follows: + * - version[15:8] - PSA lifecycle state - major + * - version[7:0] - IMPLEMENTATION DEFINED state - minor + * Possible PSA lifecycle states: + * - Unknown (0x1000u), + * - PSA_RoT_Provisioning (0x2000u), + * - Secured (0x3000u), + * - Non_PSA_RoT_Debug(0x4000u), + * - Recoverable_PSA_RoT_Debug (0x5000u), + * - Decommissioned (0x6000u) + * + * - Client ID: The partition ID of that secure partition or non-secure + * thread who called the initial attestation API. Custom claim + * with a value encoded as a *signed* integer. Negative number + * represents non-secure caller, positive numbers represents + * secure callers, zero is invalid. + * + * - HW version: Optional claim. Globally unique number in EAN-13 format + * identifying the GDSII that went to fabrication, HW and ROM. + * It can be used to reference the security level of the PSA-ROT + * via a certification website. Custom claim with a value is + * encoded as text string. + + * - Boot seed: It represents a random value created at system boot time that + * will allow differentiation of reports from different system + * sessions. The size is 32 bytes. Custom claim with a value is + * encoded as byte string. + * + * - Software components: Recommended claim. It represents the software state + * of the system. The value of the claim is an array of CBOR map + * entries, with one entry per software component within the + * device. Each map contains multiple claims that describe + * evidence about the details of the software component. + * + * - Measurement type: Optional claim. It represents the role of the + * software component. Value is encoded as short(!) text + * string. + * + * - Measurement value: It represents a hash of the invariant software + * component in memory at start-up time. The value must be a + * cryptographic hash of 256 bits or stronger.Value is + * encoded as byte string. + * + * - Version: Optional claim. It represents the issued software version. + * Value is encoded as text string. + * + * - Signer ID: It represents the hash of a signing authority public key. + * Value is encoded as byte string. + * + * - Measurement description: Optional claim. It represents the way in which + * the measurement value of the software component is + * computed. Value is encoded as text string containing an + * abbreviated description (name) of the measurement method. + * + * - No software measurements: In the event that the implementation does not + * contain any software measurements then the software + * components claim above can be omitted but instead + * it is mandatory to include this claim to indicate this is a + * deliberate state. Custom claim a value is encoded as unsigned + * integer set to 1. + */ + +/** + * \brief Get initial attestation token + * + * \param[in] auth_challenge Pointer to buffer where challenge input is + * stored. Nonce and / or hash of attested data. + * Must be always + * \ref PSA_INITIAL_ATTEST_TOKEN_SIZE bytes + * long. + * \param[in] challenge_size Size of challenge object in bytes. + * \param[out] token_buf Pointer to the buffer where attestation token + * will be stored. + * \param[in] token_buf_size Size of allocated buffer for token, in bytes. + * \param[out] token_size Size of the token that has been returned, in + * bytes. + * + * \return Returns error code as specified in \ref psa_status_t + */ +psa_status_t +psa_initial_attest_get_token(const uint8_t *auth_challenge, + size_t challenge_size, + uint8_t *token_buf, + size_t token_buf_size, + size_t *token_size); + +/** + * \brief Get the exact size of initial attestation token in bytes. + * + * It just returns with the size of the IAT token. It can be used if the caller + * dynamically allocates memory for the token buffer. + * + * \param[in] challenge_size Size of challenge object in bytes. This must be + * a supported challenge size (as above). + * \param[out] token_size Size of the token in bytes, which is created by + * initial attestation service. + * + * \return Returns error code as specified in \ref psa_status_t + */ +psa_status_t +psa_initial_attest_get_token_size(size_t challenge_size, + size_t *token_size); + +/** + * \brief Get the initial attestation public key. + * + * \param[out] public_key Pointer to the buffer where the public key + * will be stored. + * \param[in] key_buf_size Size of allocated buffer for key, in bytes. + * \param[out] public_key_len Size of public key in bytes. + * \param[out] public_key_curve Type of the elliptic curve which the key + * belongs to. + * + * \note Currently only the ECDSA P-256 over SHA-256 algorithm is supported. + * + * \return Returns error code as specified in \ref psa_status_t + */ +psa_status_t +tfm_initial_attest_get_public_key(uint8_t *public_key, + size_t public_key_buf_size, + size_t *public_key_len, + psa_ecc_curve_t *elliptic_curve_type); + +#ifdef __cplusplus +} +#endif + +#endif /* __PSA_INITIAL_ATTESTATION_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/internal_trusted_storage.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/internal_trusted_storage.h new file mode 100644 index 0000000..3920bc9 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/internal_trusted_storage.h @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/** This file describes the PSA Internal Trusted Storage API +*/ + +#ifndef PSA_INTERNAL_TRUSTED_STORAGE_H +#define PSA_INTERNAL_TRUSTED_STORAGE_H + +#include +#include + +#include "psa/error.h" +#include "psa/storage_common.h" + +#ifdef __cplusplus +extern "C" { +#endif +#define PSA_ITS_API_VERSION_MAJOR 1 /**< The major version number of the + * PSA ITS API + */ +#define PSA_ITS_API_VERSION_MINOR 0 /**< The minor version number of the + * PSA ITS API + */ +// This version of the header file is associated with 1.0 final release. + +/** + * \brief Create a new, or modify an existing, uid/value pair + * + * Stores data in the internal storage. + * + * \param[in] uid The identifier for the data + * \param[in] data_length The size in bytes of the data in `p_data` + * \param[in] p_data A buffer containing the data + * \param[in] create_flags The flags that the data will be stored with + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the + * provided `uid` value was already + * created with + * PSA_STORAGE_FLAG_WRITE_ONCE + * \retval PSA_ERROR_NOT_SUPPORTED The operation failed because one or + * more of the flags provided in + * `create_flags` is not supported or is + * not valid + * \retval PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because there + * was insufficient space on the + * storage medium + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the + * physical storage has failed (Fatal + * error) + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one + * of the provided pointers(`p_data`) + * is invalid, for example is `NULL` or + * references memory the caller cannot + * access + */ +psa_status_t psa_its_set(psa_storage_uid_t uid, + size_t data_length, + const void *p_data, + psa_storage_create_flags_t create_flags); + +/** + * \brief Retrieve data associated with a provided UID + * + * Retrieves up to `data_size` bytes of the data associated with `uid`, starting + * at `data_offset` bytes from the beginning of the data. Upon successful + * completion, the data will be placed in the `p_data` buffer, which must be at + * least `data_size` bytes in size. The length of the data returned will be in + * `p_data_length`. If `data_size` is 0, the contents of `p_data_length` will + * be set to zero. + * + * \param[in] uid The uid value + * \param[in] data_offset The starting offset of the data requested + * \param[in] data_size The amount of data requested + * \param[out] p_data On success, the buffer where the data will + * be placed + * \param[out] p_data_length On success, this will contain size of the data + * placed in `p_data` + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the + * provided `uid` value was not found in + * the storage + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the + * physical storage has failed (Fatal + * error) + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the + * provided arguments (`p_data`, + * `p_data_length`) is invalid, for example + * is `NULL` or references memory the + * caller cannot access. In addition, this + * can also happen if `data_offset` is + * larger than the size of the data + * associated with `uid` + */ +psa_status_t psa_its_get(psa_storage_uid_t uid, + size_t data_offset, + size_t data_size, + void *p_data, + size_t *p_data_length); + +/** + * \brief Retrieve the metadata about the provided uid + * + * Retrieves the metadata stored for a given `uid` as a `psa_storage_info_t` + * structure. + * + * \param[in] uid The `uid` value + * \param[out] p_info A pointer to the `psa_storage_info_t` struct that will + * be populated with the metadata + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided + * uid value was not found in the storage + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical + * storage has failed (Fatal error) + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the + * provided pointers(`p_info`) + * is invalid, for example is `NULL` or + * references memory the caller cannot + * access + */ +psa_status_t psa_its_get_info(psa_storage_uid_t uid, + struct psa_storage_info_t *p_info); + +/** + * \brief Remove the provided uid and its associated data from the storage + * + * Deletes the data from internal storage. + * + * \param[in] uid The `uid` value + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more + * of the given arguments were invalid (null + * pointer, wrong flags and so on) + * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided + * uid value was not found in the storage + * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the provided + * uid value was created with + * PSA_STORAGE_FLAG_WRITE_ONCE + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical + * storage has failed (Fatal error) + */ +psa_status_t psa_its_remove(psa_storage_uid_t uid); + +#ifdef __cplusplus +} +#endif + +#endif // PSA_INTERNAL_TRUSTED_STORAGE_H diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/protected_storage.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/protected_storage.h new file mode 100644 index 0000000..e76205c --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/protected_storage.h @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/* This file describes the PSA Protected Storage API */ + +#ifndef PSA_PROTECTED_STORAGE_H +#define PSA_PROTECTED_STORAGE_H + +#include +#include + +#include "psa/error.h" +#include "psa/storage_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief PSA_PS_API_VERSION version + * + * Major and minor PSA_PS_API_VERSION numbers + */ +#define PSA_PS_API_VERSION_MAJOR 1 +#define PSA_PS_API_VERSION_MINOR 0 + +// This version of the header file is associated with 1.0 final release + +/** + * \brief Create a new, or modify an existing, uid/value pair + * + * Stores data in the protected storage. + * + * \param[in] uid The identifier for the data + * \param[in] data_length The size in bytes of the data in `p_data` + * \param[in] p_data A buffer containing the data + * \param[in] create_flags The flags that the data will be stored with + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the + * provided `uid` value was already + * created with + * PSA_STORAGE_FLAG_WRITE_ONCE + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one + * of the provided pointers(`p_data`) + * is invalid, for example is `NULL` or + * references memory the caller cannot + * access + * \retval PSA_ERROR_NOT_SUPPORTED The operation failed because one or + * more of the flags provided in + * `create_flags` is not supported or is + * not valid + * \retval PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because there + * was insufficient space on the + * storage medium + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the + * physical storage has failed (Fatal + * error) + * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an + * unspecified internal failure + */ +psa_status_t psa_ps_set(psa_storage_uid_t uid, + size_t data_length, + const void *p_data, + psa_storage_create_flags_t create_flags); + +/** + * \brief Retrieve data associated with a provided uid + * + * Retrieves up to `data_size` bytes of the data associated with `uid`, starting + * at `data_offset` bytes from the beginning of the data. Upon successful + * completion, the data will be placed in the `p_data` buffer, which must be at + * least `data_size` bytes in size. The length of the data returned will be in + * `p_data_length`. If `data_size` is 0, the contents of `p_data_length` will + * be set to zero. + * + * \param[in] uid The uid value + * \param[in] data_offset The starting offset of the data requested + * \param[in] data_size The amount of data requested + * \param[out] p_data On success, the buffer where the data will + * be placed + * \param[out] p_data_length On success, this will contain size of the data + * placed in `p_data` + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the + * provided arguments (`p_data`, + * `p_data_length`) is invalid, for example + * is `NULL` or references memory the + * caller cannot access. In addition, this + * can also happen if `data_offset` is + * larger than the size of the data + * associated with `uid` + * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the + * provided `uid` value was not found in + * the storage + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the + * physical storage has failed (Fatal + * error) + * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an + * unspecified internal failure + * \retval PSA_ERROR_DATA_CORRUPT The operation failed because the data + * associated with the UID was corrupt + * \retval PSA_ERROR_INVALID_SIGNATURE The operation failed because the data + * associated with the UID failed + * authentication + */ +psa_status_t psa_ps_get(psa_storage_uid_t uid, + size_t data_offset, + size_t data_size, + void *p_data, + size_t *p_data_length); + +/** + * \brief Retrieve the metadata about the provided uid + * + * Retrieves the metadata stored for a given `uid` + * + * \param[in] uid The `uid` value + * \param[out] p_info A pointer to the `psa_storage_info_t` struct that will + * be populated with the metadata + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the + * provided pointers(`p_info`) + * is invalid, for example is `NULL` or + * references memory the caller cannot + * access + * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided + * uid value was not found in the storage + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical + * storage has failed (Fatal error) + * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an + * unspecified internal failure + * \retval PSA_ERROR_DATA_CORRUPT The operation failed because the data + * associated with the UID was corrupt + */ +psa_status_t psa_ps_get_info(psa_storage_uid_t uid, + struct psa_storage_info_t *p_info); + +/** + * \brief Remove the provided uid and its associated data from the storage + * + * Removes previously stored data and any associated metadata, + * including rollback protection data. + * + * \param[in] uid The `uid` value + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more + * of the given arguments were invalid (null + * pointer, wrong flags and so on) + * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided + * uid value was not found in the storage + * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the provided + * uid value was created with + * PSA_STORAGE_FLAG_WRITE_ONCE + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical + * storage has failed (Fatal error) + * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an + * unspecified internal failure + */ +psa_status_t psa_ps_remove(psa_storage_uid_t uid); + +/** + * \brief Reserves storage for the specified uid + * + * Upon success, the capacity of the storage will be capacity, and the size + * will be 0. It is only necessary to call this function for assets that will + * be written with the psa_ps_set_extended function. If only the psa_ps_set + * function is needed, calls to this function are redundant. + * + * \param[in] uid The `uid` value + * \param[in] capacity The capacity to be allocated in bytes + * \param[in] create_flags Flags indicating properties of storage + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the + * physical storage has failed + * (Fatal error) + * \retval PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because the + * capacity is bigger than the current + * available space + * \retval PSA_ERROR_NOT_SUPPORTED The operation failed because the + * function is not implemented or one + * or more create_flags are not + * supported. + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because uid was + * 0 or create_flags specified flags + * that are not defined in the API. + * \retval PSA_ERROR_GENERIC_ERROR The operation failed due to an + * unspecified error + * \retval PSA_ERROR_ALREADY_EXISTS Storage for the specified uid + * already exists + */ +psa_status_t psa_ps_create(psa_storage_uid_t uid, + size_t capacity, + psa_storage_create_flags_t create_flags); + +/** + * \brief Sets partial data into an asset + * + * Before calling this function, the storage must have been reserved with a call + * to psa_ps_create. It can also be used to overwrite data in an asset that was + * created with a call to psa_ps_set. Calling this function with data_length = 0 + * is permitted, which will make no change to the stored data.This function can + * overwrite existing data and/or extend it up to the capacity for the uid + * specified in psa_ps_create, but cannot create gaps. + * + * That is, it has preconditions: + * - data_offset <= size + * - data_offset + data_length <= capacity + * and postconditions: + * - size = max(size, data_offset + data_length) + * - capacity unchanged. + * + * \param[in] uid The `uid` value + * \param[in] data_offset Offset within the asset to start the write + * \param[in] data_length The size in bytes of the data in p_data to write + * \param[in] p_data Pointer to a buffer which contains the data to write + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The asset exists, the input parameters + * are correct and the data is correctly + * written in the physical storage. + * \retval PSA_ERROR_STORAGE_FAILURE The data was not written correctly in + * the physical storage + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more + * of the preconditions listed above + * regarding data_offset, size, or + * data_length was violated. + * \retval PSA_ERROR_DOES_NOT_EXIST The specified uid was not found + * \retval PSA_ERROR_NOT_SUPPORTED The implementation of the API does not + * support this function + * \retval PSA_ERROR_GENERIC_ERROR The operation failed due to an + * unspecified error + * \retval PSA_ERROR_DATA_CORRUPT The operation failed because the + * existing data has been corrupted. + * \retval PSA_ERROR_INVALID_SIGNATURE The operation failed because the + * existing data failed authentication + * (MAC check failed). + * \retval PSA_ERROR_NOT_PERMITTED The operation failed because it was + * attempted on an asset which was written + * with the flag + * PSA_STORAGE_FLAG_WRITE_ONCE + */ +psa_status_t psa_ps_set_extended(psa_storage_uid_t uid, + size_t data_offset, + size_t data_length, + const void *p_data); + +/** + * \brief Lists optional features. + * + * \return A bitmask with flags set for all of + * the optional features supported by the + * implementation.Currently defined flags + * are limited to + * PSA_STORAGE_SUPPORT_SET_EXTENDED + */ +uint32_t psa_ps_get_support(void); + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_PROTECTED_STORAGE_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/storage_common.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/storage_common.h new file mode 100644 index 0000000..3f901c5 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa/storage_common.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/* This file includes common definitions for PSA storage +*/ + +#ifndef PSA_STORAGE_COMMON_H +#define PSA_STORAGE_COMMON_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint32_t psa_storage_create_flags_t; + +typedef uint64_t psa_storage_uid_t; + +/* Flags */ + +#define PSA_STORAGE_FLAG_NONE 0u +#define PSA_STORAGE_FLAG_WRITE_ONCE (1u << 0) +#define PSA_STORAGE_FLAG_NO_CONFIDENTIALITY (1u << 1) +#define PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION (1u << 2) + +/* A container for metadata associated with a specific uid */ + +struct psa_storage_info_t { + size_t capacity; + size_t size; + psa_storage_create_flags_t flags; +}; + +#define PSA_STORAGE_SUPPORT_SET_EXTENDED (1u << 0) + +#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) +#define PSA_ERROR_DATA_CORRUPT ((psa_status_t)-152) + +#ifdef __cplusplus +} +#endif + +#endif // PSA_STORAGE_COMMON_H diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa_manifest/sid.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa_manifest/sid.h new file mode 100644 index 0000000..f9bdf7c --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/psa_manifest/sid.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ + +#ifndef __PSA_MANIFEST_SID_H__ +#define __PSA_MANIFEST_SID_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/******** TFM_SP_PS ********/ +#define TFM_PS_SET_SID (0x00000060U) +#define TFM_PS_SET_VERSION (1U) +#define TFM_PS_GET_SID (0x00000061U) +#define TFM_PS_GET_VERSION (1U) +#define TFM_PS_GET_INFO_SID (0x00000062U) +#define TFM_PS_GET_INFO_VERSION (1U) +#define TFM_PS_REMOVE_SID (0x00000063U) +#define TFM_PS_REMOVE_VERSION (1U) +#define TFM_PS_GET_SUPPORT_SID (0x00000064U) +#define TFM_PS_GET_SUPPORT_VERSION (1U) + +/******** TFM_SP_ITS ********/ +#define TFM_ITS_SET_SID (0x00000070U) +#define TFM_ITS_SET_VERSION (1U) +#define TFM_ITS_GET_SID (0x00000071U) +#define TFM_ITS_GET_VERSION (1U) +#define TFM_ITS_GET_INFO_SID (0x00000072U) +#define TFM_ITS_GET_INFO_VERSION (1U) +#define TFM_ITS_REMOVE_SID (0x00000073U) +#define TFM_ITS_REMOVE_VERSION (1U) + +/******** TFM_SP_CRYPTO ********/ +#define TFM_CRYPTO_SID (0x00000080U) +#define TFM_CRYPTO_VERSION (1U) + +/******** TFM_SP_PLATFORM ********/ +#define TFM_SP_PLATFORM_SYSTEM_RESET_SID (0x00000040U) +#define TFM_SP_PLATFORM_SYSTEM_RESET_VERSION (1U) +#define TFM_SP_PLATFORM_IOCTL_SID (0x00000041U) +#define TFM_SP_PLATFORM_IOCTL_VERSION (1U) +#define TFM_SP_PLATFORM_NV_COUNTER_SID (0x00000042U) +#define TFM_SP_PLATFORM_NV_COUNTER_VERSION (1U) + +/******** TFM_SP_INITIAL_ATTESTATION ********/ +#define TFM_ATTEST_GET_TOKEN_SID (0x00000020U) +#define TFM_ATTEST_GET_TOKEN_VERSION (1U) +#define TFM_ATTEST_GET_TOKEN_SIZE_SID (0x00000021U) +#define TFM_ATTEST_GET_TOKEN_SIZE_VERSION (1U) +#define TFM_ATTEST_GET_PUBLIC_KEY_SID (0x00000022U) +#define TFM_ATTEST_GET_PUBLIC_KEY_VERSION (1U) + +/******** TFM_SP_CORE_TEST ********/ +#define SPM_CORE_TEST_INIT_SUCCESS_SID (0x0000F020U) +#define SPM_CORE_TEST_INIT_SUCCESS_VERSION (1U) +#define SPM_CORE_TEST_DIRECT_RECURSION_SID (0x0000F021U) +#define SPM_CORE_TEST_DIRECT_RECURSION_VERSION (1U) +#define SPM_CORE_TEST_SS_TO_SS_SID (0x0000F024U) +#define SPM_CORE_TEST_SS_TO_SS_VERSION (1U) +#define SPM_CORE_TEST_SS_TO_SS_BUFFER_SID (0x0000F025U) +#define SPM_CORE_TEST_SS_TO_SS_BUFFER_VERSION (1U) +#define SPM_CORE_TEST_OUTVEC_WRITE_SID (0x0000F026U) +#define SPM_CORE_TEST_OUTVEC_WRITE_VERSION (1U) +#define SPM_CORE_TEST_PERIPHERAL_ACCESS_SID (0x0000F027U) +#define SPM_CORE_TEST_PERIPHERAL_ACCESS_VERSION (1U) +#define SPM_CORE_TEST_GET_CALLER_CLIENT_ID_SID (0x0000F028U) +#define SPM_CORE_TEST_GET_CALLER_CLIENT_ID_VERSION (1U) +#define SPM_CORE_TEST_SPM_REQUEST_SID (0x0000F029U) +#define SPM_CORE_TEST_SPM_REQUEST_VERSION (1U) +#define SPM_CORE_TEST_BLOCK_SID (0x0000F02AU) +#define SPM_CORE_TEST_BLOCK_VERSION (1U) +#define SPM_CORE_TEST_NS_THREAD_SID (0x0000F02BU) +#define SPM_CORE_TEST_NS_THREAD_VERSION (1U) + +/******** TFM_SP_CORE_TEST_2 ********/ +#define SPM_CORE_TEST_2_SLAVE_SERVICE_SID (0x0000F040U) +#define SPM_CORE_TEST_2_SLAVE_SERVICE_VERSION (1U) +#define SPM_CORE_TEST_2_CHECK_CALLER_CLIENT_ID_SID (0x0000F041U) +#define SPM_CORE_TEST_2_CHECK_CALLER_CLIENT_ID_VERSION (1U) +#define SPM_CORE_TEST_2_GET_EVERY_SECOND_BYTE_SID (0x0000F042U) +#define SPM_CORE_TEST_2_GET_EVERY_SECOND_BYTE_VERSION (1U) +#define SPM_CORE_TEST_2_INVERT_SID (0x0000F043U) +#define SPM_CORE_TEST_2_INVERT_VERSION (1U) +#define SPM_CORE_TEST_2_PREPARE_TEST_SCENARIO_SID (0x0000F044U) +#define SPM_CORE_TEST_2_PREPARE_TEST_SCENARIO_VERSION (1U) +#define SPM_CORE_TEST_2_EXECUTE_TEST_SCENARIO_SID (0x0000F045U) +#define SPM_CORE_TEST_2_EXECUTE_TEST_SCENARIO_VERSION (1U) + +/******** TFM_SP_SECURE_TEST_PARTITION ********/ +#define TFM_SECURE_CLIENT_SFN_RUN_TESTS_SID (0x0000F000U) +#define TFM_SECURE_CLIENT_SFN_RUN_TESTS_VERSION (1U) + +/******** TFM_SP_IPC_SERVICE_TEST ********/ +#define IPC_SERVICE_TEST_BASIC_SID (0x0000F080U) +#define IPC_SERVICE_TEST_BASIC_VERSION (1U) +#define IPC_SERVICE_TEST_PSA_ACCESS_APP_MEM_SID (0x0000F081U) +#define IPC_SERVICE_TEST_PSA_ACCESS_APP_MEM_VERSION (1U) +#define IPC_SERVICE_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_SID (0x0000F082U) +#define IPC_SERVICE_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_VERSION (1U) +#define IPC_SERVICE_TEST_APP_ACCESS_PSA_MEM_SID (0x0000F083U) +#define IPC_SERVICE_TEST_APP_ACCESS_PSA_MEM_VERSION (1U) +#define IPC_SERVICE_TEST_CLIENT_PROGRAMMER_ERROR_SID (0x0000F084U) +#define IPC_SERVICE_TEST_CLIENT_PROGRAMMER_ERROR_VERSION (1U) + +/******** TFM_SP_IPC_CLIENT_TEST ********/ +#define IPC_CLIENT_TEST_BASIC_SID (0x0000F060U) +#define IPC_CLIENT_TEST_BASIC_VERSION (1U) +#define IPC_CLIENT_TEST_PSA_ACCESS_APP_MEM_SID (0x0000F061U) +#define IPC_CLIENT_TEST_PSA_ACCESS_APP_MEM_VERSION (1U) +#define IPC_CLIENT_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_SID (0x0000F062U) +#define IPC_CLIENT_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_VERSION (1U) +#define IPC_CLIENT_TEST_APP_ACCESS_PSA_MEM_SID (0x0000F063U) +#define IPC_CLIENT_TEST_APP_ACCESS_PSA_MEM_VERSION (1U) +#define IPC_CLIENT_TEST_MEM_CHECK_SID (0x0000F064U) +#define IPC_CLIENT_TEST_MEM_CHECK_VERSION (1U) + +/******** TFM_IRQ_TEST_1 ********/ +#define SPM_CORE_IRQ_TEST_1_PREPARE_TEST_SCENARIO_SID (0x0000F0A0U) +#define SPM_CORE_IRQ_TEST_1_PREPARE_TEST_SCENARIO_VERSION (1U) +#define SPM_CORE_IRQ_TEST_1_EXECUTE_TEST_SCENARIO_SID (0x0000F0A1U) +#define SPM_CORE_IRQ_TEST_1_EXECUTE_TEST_SCENARIO_VERSION (1U) + +/******** TFM_SP_PS_TEST ********/ +#define TFM_PS_TEST_PREPARE_SID (0x0000F0C0U) +#define TFM_PS_TEST_PREPARE_VERSION (1U) + +/******** TFM_SP_SECURE_CLIENT_2 ********/ +#define TFM_SECURE_CLIENT_2_SID (0x0000F0E0U) +#define TFM_SECURE_CLIENT_2_VERSION (1U) + +/******** TFM_SP_MULTI_CORE_TEST ********/ +#define MULTI_CORE_MULTI_CLIENT_CALL_TEST_0_SID (0x0000F100U) +#define MULTI_CORE_MULTI_CLIENT_CALL_TEST_0_VERSION (1U) +#define MULTI_CORE_MULTI_CLIENT_CALL_TEST_1_SID (0x0000F101U) +#define MULTI_CORE_MULTI_CLIENT_CALL_TEST_1_VERSION (1U) + +#ifdef __cplusplus +} +#endif + +#endif /* __PSA_MANIFEST_SID_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_api.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_api.h new file mode 100644 index 0000000..09abc39 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_api.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2017-2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __TFM_API_H__ +#define __TFM_API_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "psa/client.h" + +#define TFM_INVALID_CLIENT_ID 0 + +/** + * \brief Checks if the provided client ID is a secure client ID. + * + * \param[in] client_id Client ID to check. + * + * \retval 1 Client ID is secure. + * \retval 0 Client ID is non-secure. + */ +#define TFM_CLIENT_ID_IS_S(client_id) ((client_id)>0) + +/** + * \brief Checks if the provided client ID is a non-secure client ID. + * + * \param[in] client_id Client ID to check. + * + * \retval 1 Client ID is non-secure. + * \retval 0 Client ID is secure. + */ +#define TFM_CLIENT_ID_IS_NS(client_id) ((client_id)<0) + +/* The mask used for timeout values */ +#define PSA_TIMEOUT_MASK PSA_BLOCK + +/* FixMe: sort out DEBUG compile option and limit return value options + * on external interfaces */ +enum tfm_status_e +{ + TFM_SUCCESS = 0, + TFM_PARTITION_BUSY, + TFM_ERROR_SECURE_DOMAIN_LOCKED, + TFM_ERROR_INVALID_PARAMETER, + TFM_ERROR_PARTITION_NON_REENTRANT, + TFM_ERROR_NS_THREAD_MODE_CALL, + TFM_ERROR_NOT_INITIALIZED, + TFM_ERROR_NO_ACTIVE_PARTITION, + TFM_ERROR_INVALID_EXC_MODE, + TFM_SECURE_LOCK_FAILED, + TFM_SECURE_UNLOCK_FAILED, + TFM_ERROR_GENERIC = 0x1F, +}; + +/* + * Structure to package type, in_len and out_len, it is mainly used for + * psa_call. + */ +struct tfm_control_parameter_t { + int32_t type; + size_t in_len; + size_t out_len; +}; + +/********************* Secure function declarations ***************************/ + +/** + * \brief Assign client ID to the current TZ context. + * + * \param[in] ns_client_id The client ID to be assigned to the current + * context. + * \retval TFM_SUCCESS The client ID assigned successfully. + * \retval error code The client ID assignment failed, an error code + * returned according to \ref tfm_status_e. + * \note This function have to be called from handler mode. + */ +enum tfm_status_e tfm_register_client_id (int32_t ns_client_id); + +/** + * \brief Retrieve the version of the PSA Framework API that is implemented. + * + * \return The version of the PSA Framework. + */ +uint32_t tfm_psa_framework_version_veneer(void); + +/** + * \brief Return version of secure function provided by secure binary. + * + * \param[in] sid ID of secure service. + * + * \return Version number of secure function. + */ +uint32_t tfm_psa_version_veneer(uint32_t sid); + +/** + * \brief Connect to secure function. + * + * \param[in] sid ID of secure service. + * \param[in] version Version of SF requested by client. + * + * \return Returns handle to connection. + */ +psa_handle_t tfm_psa_connect_veneer(uint32_t sid, uint32_t version); + +/** + * \brief Call a secure function referenced by a connection handle. + * + * \param[in] handle Handle to connection. + * \param[in] ctrl_param Parameter structure, includes reuqest type, + * in_num and out_num. + * \param[in] in_vec Array of input \ref psa_invec structures. + * \param[in/out] out_vec Array of output \ref psa_outvec structures. + * + * \return Returns \ref psa_status_t status code. + */ +psa_status_t tfm_psa_call_veneer(psa_handle_t handle, + const struct tfm_control_parameter_t *ctrl_param, + const psa_invec *in_vec, + psa_outvec *out_vec); + +/** + * \brief Close connection to secure function referenced by a connection handle. + * + * \param[in] handle Handle to connection + * + * \return void + */ +void tfm_psa_close_veneer(psa_handle_t handle); + +/***************** End Secure function declarations ***************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_API_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_crypto_defs.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_crypto_defs.h new file mode 100644 index 0000000..dd45e3b --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_crypto_defs.h @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __TFM_CRYPTO_DEFS_H__ +#define __TFM_CRYPTO_DEFS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include "tfm_api.h" +#include "psa/crypto.h" + +/** + * \brief This type is used to overcome a limitation in the number of maximum + * IOVECs that can be used especially in psa_aead_encrypt and + * psa_aead_decrypt. To be removed in case the AEAD APIs number of + * parameters passed gets restructured + */ +#define TFM_CRYPTO_MAX_NONCE_LENGTH (16u) +struct tfm_crypto_aead_pack_input { + uint8_t nonce[TFM_CRYPTO_MAX_NONCE_LENGTH]; + uint32_t nonce_length; +}; + +/** + * \brief Structure used to pack non-pointer types in a call + * + */ +struct tfm_crypto_pack_iovec { + uint32_t sfn_id; /*!< Secure function ID used to dispatch the + * request + */ + uint16_t step; /*!< Key derivation step */ + psa_key_handle_t key_handle; /*!< Key handle */ + psa_algorithm_t alg; /*!< Algorithm */ + psa_algorithm_t alg2; /*!< Enrollment Algorithm */ + uint32_t op_handle; /*!< Frontend context handle associated to a + * multipart operation + */ + size_t capacity; /*!< Key derivation capacity */ + + struct tfm_crypto_aead_pack_input aead_in; /*!< FixMe: Temporarily used for + * AEAD until the API is + * restructured + */ +}; + +/** + * \brief Define a progressive numerical value for each SID which can be used + * when dispatching the requests to the service + */ +enum { + TFM_CRYPTO_GET_KEY_ATTRIBUTES_SID = (0u), + TFM_CRYPTO_RESET_KEY_ATTRIBUTES_SID, + TFM_CRYPTO_OPEN_KEY_SID, + TFM_CRYPTO_CLOSE_KEY_SID, + TFM_CRYPTO_IMPORT_KEY_SID, + TFM_CRYPTO_DESTROY_KEY_SID, + TFM_CRYPTO_EXPORT_KEY_SID, + TFM_CRYPTO_EXPORT_PUBLIC_KEY_SID, + TFM_CRYPTO_COPY_KEY_SID, + TFM_CRYPTO_HASH_COMPUTE_SID, + TFM_CRYPTO_HASH_COMPARE_SID, + TFM_CRYPTO_HASH_SETUP_SID, + TFM_CRYPTO_HASH_UPDATE_SID, + TFM_CRYPTO_HASH_FINISH_SID, + TFM_CRYPTO_HASH_VERIFY_SID, + TFM_CRYPTO_HASH_ABORT_SID, + TFM_CRYPTO_HASH_CLONE_SID, + TFM_CRYPTO_MAC_COMPUTE_SID, + TFM_CRYPTO_MAC_VERIFY_SID, + TFM_CRYPTO_MAC_SIGN_SETUP_SID, + TFM_CRYPTO_MAC_VERIFY_SETUP_SID, + TFM_CRYPTO_MAC_UPDATE_SID, + TFM_CRYPTO_MAC_SIGN_FINISH_SID, + TFM_CRYPTO_MAC_VERIFY_FINISH_SID, + TFM_CRYPTO_MAC_ABORT_SID, + TFM_CRYPTO_CIPHER_ENCRYPT_SID, + TFM_CRYPTO_CIPHER_DECRYPT_SID, + TFM_CRYPTO_CIPHER_ENCRYPT_SETUP_SID, + TFM_CRYPTO_CIPHER_DECRYPT_SETUP_SID, + TFM_CRYPTO_CIPHER_GENERATE_IV_SID, + TFM_CRYPTO_CIPHER_SET_IV_SID, + TFM_CRYPTO_CIPHER_UPDATE_SID, + TFM_CRYPTO_CIPHER_FINISH_SID, + TFM_CRYPTO_CIPHER_ABORT_SID, + TFM_CRYPTO_AEAD_ENCRYPT_SID, + TFM_CRYPTO_AEAD_DECRYPT_SID, + TFM_CRYPTO_AEAD_ENCRYPT_SETUP_SID, + TFM_CRYPTO_AEAD_DECRYPT_SETUP_SID, + TFM_CRYPTO_AEAD_GENERATE_NONCE_SID, + TFM_CRYPTO_AEAD_SET_NONCE_SID, + TFM_CRYPTO_AEAD_SET_LENGTHS_SID, + TFM_CRYPTO_AEAD_UPDATE_AD_SID, + TFM_CRYPTO_AEAD_UPDATE_SID, + TFM_CRYPTO_AEAD_FINISH_SID, + TFM_CRYPTO_AEAD_VERIFY_SID, + TFM_CRYPTO_AEAD_ABORT_SID, + TFM_CRYPTO_SIGN_HASH_SID, + TFM_CRYPTO_VERIFY_HASH_SID, + TFM_CRYPTO_ASYMMETRIC_ENCRYPT_SID, + TFM_CRYPTO_ASYMMETRIC_DECRYPT_SID, + TFM_CRYPTO_KEY_DERIVATION_SETUP_SID, + TFM_CRYPTO_KEY_DERIVATION_GET_CAPACITY_SID, + TFM_CRYPTO_KEY_DERIVATION_SET_CAPACITY_SID, + TFM_CRYPTO_KEY_DERIVATION_INPUT_BYTES_SID, + TFM_CRYPTO_KEY_DERIVATION_INPUT_KEY_SID, + TFM_CRYPTO_KEY_DERIVATION_KEY_AGREEMENT_SID, + TFM_CRYPTO_KEY_DERIVATION_OUTPUT_BYTES_SID, + TFM_CRYPTO_KEY_DERIVATION_OUTPUT_KEY_SID, + TFM_CRYPTO_KEY_DERIVATION_ABORT_SID, + TFM_CRYPTO_RAW_KEY_AGREEMENT_SID, + TFM_CRYPTO_GENERATE_RANDOM_SID, + TFM_CRYPTO_GENERATE_KEY_SID, + TFM_CRYPTO_SET_KEY_DOMAIN_PARAMETERS_SID, + TFM_CRYPTO_GET_KEY_DOMAIN_PARAMETERS_SID, + TFM_CRYPTO_SID_MAX, +}; + +/** + * \brief Define an invalid value for an SID + * + */ +#define TFM_CRYPTO_SID_INVALID (~0x0u) + +/** + * \brief This value is used to mark an handle as invalid. + * + */ +#define TFM_CRYPTO_INVALID_HANDLE (0x0u) + +/** + * \brief The persistent key identifier that refers to the hardware unique key. + * + */ +#define TFM_CRYPTO_KEY_ID_HUK (0xFFFF815Bu) + +/** + * \brief The algorithm identifier that refers to key derivation from the + * hardware unique key. + * + */ +#define TFM_CRYPTO_ALG_HUK_DERIVATION ((psa_algorithm_t)0xB0000F00) + +/** + * \brief Define miscellaneous literal constants that are used in the service + * + */ +enum { + TFM_CRYPTO_NOT_IN_USE = 0, + TFM_CRYPTO_IN_USE = 1 +}; + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_CRYPTO_DEFS_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_mailbox.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_mailbox.h new file mode 100644 index 0000000..3d128f4 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_mailbox.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/* + * This is header file of common mailbox objects shared by NSPE and SPE. + * Please refer to tfm_ns_mailbox.h for the definitions only used in NSPE + * mailbox library. + * Please refer to tfm_spe_mailbox.h for the SPE specific definitions and APIs. + */ + +#ifndef __TFM_MAILBOX_H__ +#define __TFM_MAILBOX_H__ + +#include +#include +#include +#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL +#include "device_cfg.h" +#endif +#include "psa/client.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * If multiple outstanding NS PSA Client calls is enabled, multi-core platform + * should define the number of mailbox queue slots NUM_MAILBOX_QUEUE_SLOT in + * platform device_cfg.h. + * Otherwise, NUM_MAILBOX_QUEUE_SLOT is defined as 1. + */ +#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL +#ifndef NUM_MAILBOX_QUEUE_SLOT +#error "Error: Platform doesn't define NUM_MAILBOX_QUEUE_SLOT for mailbox queue" +#endif + +#if (NUM_MAILBOX_QUEUE_SLOT < 2) +#error "Error: Invalid NUM_MAILBOX_QUEUE_SLOT. The value should be more than 1" +#endif + +/* + * The number of slots should be no more than the number of bits in + * mailbox_queue_status_t. + * Here the value is hardcoded. A better way is to define a sizeof() to + * calculate the bits in mailbox_queue_status_t and dump it with pragma message. + */ +#if (NUM_MAILBOX_QUEUE_SLOT > 32) +#error "Error: Invalid NUM_MAILBOX_QUEUE_SLOT. The value should be no more than 32" +#endif +#else /* TFM_MULTI_CORE_MULTI_CLIENT_CALL */ +/* Force the number of mailbox queue slots as 1. */ +#undef NUM_MAILBOX_QUEUE_SLOT +#define NUM_MAILBOX_QUEUE_SLOT (1) +#endif /* TFM_MULTI_CORE_MULTI_CLIENT_CALL */ + +/* PSA client call type value */ +#define MAILBOX_PSA_FRAMEWORK_VERSION (0x1) +#define MAILBOX_PSA_VERSION (0x2) +#define MAILBOX_PSA_CONNECT (0x3) +#define MAILBOX_PSA_CALL (0x4) +#define MAILBOX_PSA_CLOSE (0x5) + +/* Return code of mailbox APIs */ +#define MAILBOX_SUCCESS (0) +#define MAILBOX_QUEUE_FULL (INT32_MIN + 1) +#define MAILBOX_INVAL_PARAMS (INT32_MIN + 2) +#define MAILBOX_NO_PERMS (INT32_MIN + 3) +#define MAILBOX_NO_PEND_EVENT (INT32_MIN + 4) +#define MAILBOX_CHAN_BUSY (INT32_MIN + 5) +#define MAILBOX_CALLBACK_REG_ERROR (INT32_MIN + 6) +#define MAILBOX_INIT_ERROR (INT32_MIN + 7) + +/* + * This structure holds the parameters used in a PSA client call. + */ +struct psa_client_params_t { + union { + struct { + uint32_t sid; + } psa_version_params; + + struct { + uint32_t sid; + uint32_t version; + } psa_connect_params; + + struct { + psa_handle_t handle; + int32_t type; + const psa_invec *in_vec; + size_t in_len; + psa_outvec *out_vec; + size_t out_len; + } psa_call_params; + + struct { + psa_handle_t handle; + } psa_close_params; + }; +}; + +/* Mailbox message passed from NSPE to SPE to deliver a PSA client call */ +struct mailbox_msg_t { + uint32_t call_type; /* PSA client call type */ + struct psa_client_params_t params; /* Contain parameters used in PSA + * client call + */ + + int32_t client_id; /* Optional client ID of the + * non-secure caller. + * It is required to identify the + * non-secure task when NSPE OS + * enforces non-secure task isolation + */ +}; + +/* A handle to a mailbox message in use */ +typedef int32_t mailbox_msg_handle_t; + +#define MAILBOX_MSG_NULL_HANDLE ((mailbox_msg_handle_t)0) + +/* + * Mailbox reply structure in non-secure memory + * to hold the PSA client call return result from SPE + */ +struct mailbox_reply_t { + int32_t return_val; +}; + +/* A single slot structure in NSPE mailbox queue */ +struct ns_mailbox_slot_t { + struct mailbox_msg_t msg; + struct mailbox_reply_t reply; + const void *owner; /* Handle of the owner task of this + * slot + */ + bool is_woken; /* Indicate that owner task has been + * or should be woken up, after the + * replied is received. + */ +}; + +typedef uint32_t mailbox_queue_status_t; + +/* NSPE mailbox queue */ +struct ns_mailbox_queue_t { + mailbox_queue_status_t empty_slots; /* Bitmask of empty slots */ + mailbox_queue_status_t pend_slots; /* Bitmask of slots pending + * for SPE handling + */ + mailbox_queue_status_t replied_slots; /* Bitmask of active slots + * containing PSA client call + * return result + */ + + struct ns_mailbox_slot_t queue[NUM_MAILBOX_QUEUE_SLOT]; + +#ifdef TFM_MULTI_CORE_TEST + uint32_t nr_tx; /* The total number of + * submission of NS PSA Client + * calls from NS task via + * mailbox. + */ + uint32_t nr_used_slots; /* The total number of used + * mailbox queue slots each time + * NS thread requests a mailbox + * queue slot. + */ +#endif +}; + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_MAILBOX_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_multi_core_api.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_multi_core_api.h new file mode 100644 index 0000000..7999fa4 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_multi_core_api.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __TFM_MULTI_CORE_API__ +#define __TFM_MULTI_CORE_API__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/** + * \brief Called on the non-secure CPU. + * Flags that the non-secure side has completed its initialization. + * Waits, if necessary, for the secure CPU to flag that it has completed + * its initialization. + * + * \return Return 0 if succeeds. + * \return Otherwise, return specific error code. + */ +int32_t tfm_ns_wait_for_s_cpu_ready(void); + +/** + * \brief Synchronisation with secure CPU, platform-specific implementation. + * Flags that the non-secure side has completed its initialization. + * Waits, if necessary, for the secure CPU to flag that it has completed + * its initialization. + * + * \retval Return 0 if succeeds. + * \retval Otherwise, return specific error code. + */ +int32_t tfm_platform_ns_wait_for_s_cpu_ready(void); + +/** + * \brief Acquire the multi-core lock for synchronizing PSA client call(s) + * The actual implementation depends on the use scenario. + * + * \return \ref TFM_SUCCESS on success + * \return \ref TFM_ERROR_GENERIC on error + */ +uint32_t tfm_ns_multi_core_lock_acquire(void); + +/** + * \brief Release the multi-core lock for synchronizing PSA client call(s) + * The actual implementation depends on the use scenario. + * + * \return \ref TFM_SUCCESS on success + * \return \ref TFM_ERROR_GENERIC on error + */ +uint32_t tfm_ns_multi_core_lock_release(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_MULTI_CORE_API__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_ns_interface.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_ns_interface.h new file mode 100644 index 0000000..21857be --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_ns_interface.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017-2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +#ifndef __TFM_NS_INTERFACE_H__ +#define __TFM_NS_INTERFACE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "tfm_api.h" + +typedef int32_t (*veneer_fn) (uint32_t arg0, uint32_t arg1, + uint32_t arg2, uint32_t arg3); + +/** + * \brief NS interface, veneer function dispatcher + * + * \details This function implements the dispatching mechanism for the + * desired veneer function, to be called with the parameters + * described from arg0 to arg3. + * + * \param[in] fn Function pointer to the veneer function desired + * \param[in] arg0 Argument 0 + * \param[in] arg1 Argument 1 + * \param[in] arg2 Argument 2 + * \param[in] arg3 Argument 3 + * + * \return Returns the same return value of the requested veneer function + */ +int32_t tfm_ns_interface_dispatch(veneer_fn fn, + uint32_t arg0, uint32_t arg1, + uint32_t arg2, uint32_t arg3); + +/** + * \brief NS interface, Initialise the NS interface + * + * \details This function needs to be called from the NS world to + * properly initialise the NS interface towards TF-M. This + * function will initialise all the objects required for + * runtime dispatching of TF-M requests to services + * + * \return A value according to \ref enum tfm_status_e + */ +enum tfm_status_e tfm_ns_interface_init(void); +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_NS_INTERFACE_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_ns_mailbox.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_ns_mailbox.h new file mode 100644 index 0000000..2fcb1b6 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_ns_mailbox.h @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/* Data types and API definitions in NSPE mailbox library */ + +#ifndef __TFM_NS_MAILBOX_H__ +#define __TFM_NS_MAILBOX_H__ + +#include +#include +#include "tfm_mailbox.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef TFM_MULTI_CORE_TEST +/** + * \brief The structure to hold the statistics result of NSPE mailbox + */ +struct ns_mailbox_stats_res_t { + uint8_t avg_nr_slots; /* The value before the decimal point + * in the average number of NSPE + * mailbox slots in use. + */ + uint8_t avg_nr_slots_tenths; /* The first digit value after the + * decimal point in the average + * number of NSPE mailbox slots in use. + */ +}; +#endif + +/** + * \brief Prepare and send PSA client request to SPE via mailbox. + * + * \param[in] call_type PSA client call type + * \param[in] params Parmaters used for PSA client call + * \param[in] client_id Optional client ID of non-secure caller. + * It is required to identify the non-secure caller + * when NSPE OS enforces non-secure task isolation. + * + * \retval >= 0 The handle to the mailbox message assigned. + * \retval < 0 Operation failed with an error code. + */ +mailbox_msg_handle_t tfm_ns_mailbox_tx_client_req(uint32_t call_type, + const struct psa_client_params_t *params, + int32_t client_id); + +/** + * \brief Fetch PSA client return result. + * + * \param[in] handle The handle to the mailbox message + * \param[out] reply The address to be written with return result. + * + * \retval MAILBOX_SUCCESS Successfully get PSA client call return result. + * \retval Other return code Operation failed with an error code. + */ +int32_t tfm_ns_mailbox_rx_client_reply(mailbox_msg_handle_t handle, + int32_t *reply); + +/** + * \brief Check whether a specific mailbox message has been replied. + * + * \param[in] handle The handle to the mailbox message + * + * \retval true The PSA client call return value is replied. + * \retval false The PSA client call return value is not + * replied yet. + */ +bool tfm_ns_mailbox_is_msg_replied(mailbox_msg_handle_t handle); + +/** + * \brief NSPE mailbox initialization + * + * \param[in] queue The base address of NSPE mailbox queue to be + * initialized. + * + * \retval MAILBOX_SUCCESS Operation succeeded. + * \retval Other return code Operation failed with an error code. + */ +int32_t tfm_ns_mailbox_init(struct ns_mailbox_queue_t *queue); + +/** + * \brief Get the handle of the current non-secure task executing mailbox + * functionalities + * + * \note This function should be implemented according to platform, NS OS + * and actual use scenario. + * This function can be ignored or return NULL if sleep/wake-up mechanism + * is not required in PSA Client API implementation. + * + * \return Return the handle of task. + */ +const void *tfm_ns_mailbox_get_task_handle(void); + +/** + * \brief Fetch the handle to the first replied mailbox message in the NSPE + * mailbox queue. + * This function is intended to be called inside platform specific + * notification IRQ handler. + * + * \note The replied status of the fetched mailbox message will be cleaned after + * the message is fetched. When this function is called again, it fetches + * the next replied mailbox message from the NSPE mailbox queue. + * + * \return Return the handle to the first replied mailbox message in the + * queue. + * Return \ref MAILBOX_MSG_NULL_HANDLE if no mailbox message is replied. + */ +mailbox_msg_handle_t tfm_ns_mailbox_fetch_reply_msg_isr(void); + +/** + * \brief Return the handle of owner task of a mailbox message according to the + * \ref mailbox_msg_handle_t + * + * \param[in] handle The handle of mailbox message. + * + * \return Return the handle value of the owner task. + */ +const void *tfm_ns_mailbox_get_msg_owner(mailbox_msg_handle_t handle); + +#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL +/** + * \brief Wait for the reply returned from SPE to the mailbox message specified + * by handle + * + * \param[in] handle The handle of mailbox message. + * + * \retval MAILBOX_SUCCESS Return from waiting successfully. + * \retval Other return code Failed to wait with an error code. + */ +int32_t tfm_ns_mailbox_wait_reply(mailbox_msg_handle_t handle); +#endif + +/** + * \brief Platform specific NSPE mailbox initialization. + * Invoked by \ref tfm_ns_mailbox_init(). + * + * \param[in] queue The base address of NSPE mailbox queue to be + * initialized. + * + * \retval MAILBOX_SUCCESS Operation succeeded. + * \retval Other return code Operation failed with an error code. + */ +int32_t tfm_ns_mailbox_hal_init(struct ns_mailbox_queue_t *queue); + +/** + * \brief Notify SPE to deal with the PSA client call sent via mailbox + * + * \note The implementation depends on platform specific hardware and use case. + * + * \retval MAILBOX_SUCCESS Operation succeeded. + * \retval Other return code Operation failed with an error code. + */ +int32_t tfm_ns_mailbox_hal_notify_peer(void); + +/** + * \brief Enter critical section of NSPE mailbox. + * + * \note The implementation depends on platform specific hardware and use case. + */ +void tfm_ns_mailbox_hal_enter_critical(void); + +/** + * \brief Exit critical section of NSPE mailbox. + * + * \note The implementation depends on platform specific hardware and use case. + */ +void tfm_ns_mailbox_hal_exit_critical(void); + +/** + * \brief Enter critical section of NSPE mailbox in IRQ handler. + * + * \note The implementation depends on platform specific hardware and use case. + */ +void tfm_ns_mailbox_hal_enter_critical_isr(void); + +/** + * \brief Enter critical section of NSPE mailbox in IRQ handler + * + * \note The implementation depends on platform specific hardware and use case. + */ +void tfm_ns_mailbox_hal_exit_critical_isr(void); + +#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL +/** + * \brief Performs platform and NS OS specific waiting mechanism to wait for + * the reply of the specified mailbox message to be returned from SPE. + * + * \note This function is implemented by platform and NS OS specific waiting + * mechanism accroding to use scenario. + * + * \param[in] handle The handle of mailbox message. + */ +void tfm_ns_mailbox_hal_wait_reply(mailbox_msg_handle_t handle); +#endif + +#ifdef TFM_MULTI_CORE_TEST +/** + * \brief Initialize the statistics module in TF-M NSPE mailbox. + * + * \note This function is only available when multi-core tests are enabled. + */ +void tfm_ns_mailbox_tx_stats_init(void); + +/** + * \brief Calculate the average number of used NS mailbox queue slots each time + * NS task requires a queue slot to submit mailbox message, which is + * recorded in NS mailbox statisitics module. + * + * \note This function is only available when multi-core tests are enabled. + * + * \param[in] stats_res The buffer to be written with + * \ref ns_mailbox_stats_res_t. + * + * \return Return the calculation result. + */ +void tfm_ns_mailbox_stats_avg_slot(struct ns_mailbox_stats_res_t *stats_res); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_NS_MAILBOX_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_ns_svc.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_ns_svc.h new file mode 100644 index 0000000..def0c2f --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_ns_svc.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2017-2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include "cmsis_compiler.h" + +#ifndef __TFM_NS_SVC_H__ +#define __TFM_NS_SVC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Include all the SVC handler headers + */ +#include "tfm_nspm_svc_handler.h" + +/** + * \brief Macro to encode an svc instruction + * + */ +#define SVC(code) __ASM volatile("svc %0" : : "I" (code)) + +/** + * \def LIST_SVC_NSPM + * + * \brief This is an X macro which lists + * the SVC interface exposed by TF-M + * for the NS OS. + * + */ +#define LIST_SVC_NSPM \ + X(SVC_TFM_NSPM_REGISTER_CLIENT_ID, tfm_nspm_svc_register_client_id) \ + +/** + * \brief Numbers associated to each SVC available + * + * \details Start from 1 as 0 is reserved by RTX + */ +enum tfm_svc_num { + SVC_INVALID = 0, + +#define X(SVC_ENUM, SVC_HANDLER) SVC_ENUM, + + /* SVC API for Services */ +#ifdef TFM_NS_CLIENT_IDENTIFICATION + LIST_SVC_NSPM +#endif + +#undef X + + /* add all the new entries above this line */ + SVC_TFM_MAX, +}; + +/* number of user SVC functions */ +#define USER_SVC_COUNT ((uint32_t)SVC_TFM_MAX - 1) + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_NS_SVC_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_platform_api.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_platform_api.h new file mode 100644 index 0000000..8c9b0db --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_platform_api.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __TFM_PLATFORM_API__ +#define __TFM_PLATFORM_API__ + +#include +#include +#include +#include "tfm_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief TFM secure partition platform API version + */ +#define TFM_PLATFORM_API_VERSION_MAJOR (0) +#define TFM_PLATFORM_API_VERSION_MINOR (3) + +#define TFM_PLATFORM_API_ID_NV_READ (1010) +#define TFM_PLATFORM_API_ID_NV_INCREMENT (1011) + +/*! + * \enum tfm_platform_err_t + * + * \brief Platform service error types + * + */ +enum tfm_platform_err_t { + TFM_PLATFORM_ERR_SUCCESS = 0, + TFM_PLATFORM_ERR_SYSTEM_ERROR, + TFM_PLATFORM_ERR_INVALID_PARAM, + TFM_PLATFORM_ERR_NOT_SUPPORTED, + + /* Following entry is only to ensure the error code of int size */ + TFM_PLATFORM_ERR_FORCE_INT_SIZE = INT_MAX +}; + +typedef int32_t tfm_platform_ioctl_req_t; + +/*! + * \brief Resets the system. + * + * \return Returns values as specified by the \ref tfm_platform_err_t + */ +enum tfm_platform_err_t tfm_platform_system_reset(void); + +/*! + * \brief Performs a platform-specific service + * + * \param[in] request Request identifier (valid values vary + * based on the platform) + * \param[in] input Input buffer to the requested service (or NULL) + * \param[in,out] output Output buffer to the requested service (or NULL) + * + * \return Returns values as specified by the \ref tfm_platform_err_t + */ +enum tfm_platform_err_t tfm_platform_ioctl(tfm_platform_ioctl_req_t request, + psa_invec *input, + psa_outvec *output); + +/*! + * \brief Increments the given non-volatile (NV) counter by one + * + * \param[in] counter_id NV counter ID. + * + * \return TFM_PLATFORM_ERR_SUCCESS if the value is read correctly. Otherwise, + * it returns TFM_PLATFORM_ERR_SYSTEM_ERROR. + */ +enum tfm_platform_err_t +tfm_platform_nv_counter_increment(uint32_t counter_id); + +/*! + * \brief Reads the given non-volatile (NV) counter + * + * \param[in] counter_id NV counter ID. + * \param[in] size Size of the buffer to store NV counter value + * in bytes. + * \param[out] val Pointer to store the current NV counter value. + * + * \return TFM_PLATFORM_ERR_SUCCESS if the value is read correctly. Otherwise, + * it returns TFM_PLATFORM_ERR_SYSTEM_ERROR. + */ +enum tfm_platform_err_t +tfm_platform_nv_counter_read(uint32_t counter_id, + uint32_t size, uint8_t *val); + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_PLATFORM_API__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_veneers.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_veneers.h new file mode 100644 index 0000000..c66006a --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/include/tfm_veneers.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ + +#ifndef __TFM_VENEERS_H__ +#define __TFM_VENEERS_H__ + +#include "tfm_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef TFM_PARTITION_PROTECTED_STORAGE +/******** TFM_SP_PS ********/ +psa_status_t tfm_tfm_ps_set_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_ps_get_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_ps_get_info_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_ps_remove_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_ps_get_support_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_PROTECTED_STORAGE */ + +#ifdef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE +/******** TFM_SP_ITS ********/ +psa_status_t tfm_tfm_its_set_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_its_get_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_its_get_info_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_its_remove_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */ + +#ifdef TFM_PARTITION_AUDIT_LOG +/******** TFM_SP_AUDIT_LOG ********/ +psa_status_t tfm_audit_core_retrieve_record_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_audit_core_add_record_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_audit_core_get_info_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_audit_core_get_record_info_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_audit_core_delete_record_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_AUDIT_LOG */ + +#ifdef TFM_PARTITION_CRYPTO +/******** TFM_SP_CRYPTO ********/ +psa_status_t tfm_tfm_crypto_get_key_attributes_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_open_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_close_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_reset_key_attributes_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_import_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_destroy_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_export_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_export_public_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_copy_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_hash_compute_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_hash_compare_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_hash_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_hash_update_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_hash_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_hash_verify_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_hash_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_hash_clone_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_mac_compute_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_mac_verify_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_mac_sign_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_mac_verify_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_mac_update_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_mac_sign_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_mac_verify_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_mac_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_encrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_decrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_encrypt_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_decrypt_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_generate_iv_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_set_iv_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_update_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_encrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_decrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_encrypt_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_decrypt_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_generate_nonce_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_set_nonce_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_set_lengths_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_update_ad_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_update_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_verify_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_sign_hash_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_verify_hash_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_asymmetric_encrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_asymmetric_decrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_get_capacity_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_set_capacity_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_input_bytes_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_input_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_key_agreement_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_output_bytes_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_output_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_raw_key_agreement_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_generate_random_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_generate_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_CRYPTO */ + +#ifdef TFM_PARTITION_PLATFORM +/******** TFM_SP_PLATFORM ********/ +psa_status_t tfm_platform_sp_system_reset_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_platform_sp_ioctl_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_platform_sp_nv_counter_read_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_platform_sp_nv_counter_increment_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_PLATFORM */ + +#ifdef TFM_PARTITION_INITIAL_ATTESTATION +/******** TFM_SP_INITIAL_ATTESTATION ********/ +psa_status_t tfm_initial_attest_get_token_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_initial_attest_get_token_size_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_initial_attest_get_public_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_INITIAL_ATTESTATION */ + +#ifdef TFM_PARTITION_TEST_CORE +/******** TFM_SP_CORE_TEST ********/ +psa_status_t tfm_spm_core_test_sfn_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_spm_core_test_sfn_init_success_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_spm_core_test_sfn_direct_recursion_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_TEST_CORE */ + +#ifdef TFM_PARTITION_TEST_CORE +/******** TFM_SP_CORE_TEST_2 ********/ +psa_status_t tfm_spm_core_test_2_slave_service_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_spm_core_test_2_sfn_invert_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_spm_core_test_2_check_caller_client_id_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_spm_core_test_2_get_every_second_byte_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_spm_core_test_2_prepare_test_scenario_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_spm_core_test_2_execute_test_scenario_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_TEST_CORE */ + +#ifdef TFM_PARTITION_TEST_SECURE_SERVICES +/******** TFM_SP_SECURE_TEST_PARTITION ********/ +psa_status_t tfm_tfm_secure_client_service_sfn_run_tests_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ + +#ifdef TFM_PARTITION_TEST_CORE_IPC +/******** TFM_SP_IPC_SERVICE_TEST ********/ +#endif /* TFM_PARTITION_TEST_CORE_IPC */ + +#ifdef TFM_PARTITION_TEST_CORE_IPC +/******** TFM_SP_IPC_CLIENT_TEST ********/ +#endif /* TFM_PARTITION_TEST_CORE_IPC */ + +#ifdef TFM_ENABLE_IRQ_TEST +/******** TFM_IRQ_TEST_1 ********/ +psa_status_t tfm_spm_irq_test_1_prepare_test_scenario_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_spm_irq_test_1_execute_test_scenario_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_ENABLE_IRQ_TEST */ + +#ifdef TFM_PARTITION_TEST_PS +/******** TFM_SP_PS_TEST ********/ +psa_status_t tfm_tfm_ps_test_prepare_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_TEST_PS */ + +#ifdef TFM_PARTITION_TEST_SECURE_SERVICES +/******** TFM_SP_SECURE_CLIENT_2 ********/ +psa_status_t tfm_tfm_secure_client_2_call_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ + +#ifdef TFM_MULTI_CORE_TEST +/******** TFM_SP_MULTI_CORE_TEST ********/ +#endif /* TFM_MULTI_CORE_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_VENEERS_H__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/src/tfm_crypto_ipc_api.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/src/tfm_crypto_ipc_api.c new file mode 100644 index 0000000..70b3a0d --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/src/tfm_crypto_ipc_api.c @@ -0,0 +1,1875 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "tfm_crypto_defs.h" +#include "psa/crypto.h" +#include "tfm_ns_interface.h" +#include "psa_manifest/sid.h" +#include "psa/client.h" + +#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0])) + +#define PSA_CONNECT(service) \ + psa_handle_t ipc_handle; \ + ipc_handle = psa_connect(service##_SID, service##_VERSION); \ + if (!PSA_HANDLE_IS_VALID(ipc_handle)) { \ + return PSA_ERROR_GENERIC_ERROR; \ + } \ + +#define PSA_CLOSE() psa_close(ipc_handle) + +#define API_DISPATCH(sfn_name, sfn_id) \ + psa_call(ipc_handle, PSA_IPC_CALL, \ + in_vec, ARRAY_SIZE(in_vec), \ + out_vec, ARRAY_SIZE(out_vec)) + +#define API_DISPATCH_NO_OUTVEC(sfn_name, sfn_id) \ + psa_call(ipc_handle, PSA_IPC_CALL, \ + in_vec, ARRAY_SIZE(in_vec), \ + (psa_outvec *)NULL, 0) + +psa_status_t psa_crypto_init(void) +{ + /* Service init is performed during TFM boot up, + * so application level initialisation is empty + */ + return PSA_SUCCESS; +} + +psa_status_t psa_open_key(psa_key_id_t id, + psa_key_handle_t *handle) +{ +#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + const struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_OPEN_KEY_SID, + }; + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = &id, .len = sizeof(psa_key_id_t)}, + }; + psa_outvec out_vec[] = { + {.base = handle, .len = sizeof(psa_key_handle_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_open_key, + TFM_CRYPTO_OPEN_KEY); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ +} + +psa_status_t psa_close_key(psa_key_handle_t handle) +{ +#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + const struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_CLOSE_KEY_SID, + .key_handle = handle, + }; + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_close_key, + TFM_CRYPTO_CLOSE_KEY);; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ +} + +psa_status_t psa_import_key(const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + psa_key_handle_t *handle) +{ +#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_IMPORT_KEY_SID, + }; + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = attributes, .len = sizeof(psa_key_attributes_t)}, + {.base = data, .len = data_length} + }; + psa_outvec out_vec[] = { + {.base = handle, .len = sizeof(psa_key_handle_t)} + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_import_key, + TFM_CRYPTO_IMPORT_KEY); + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ +} + +psa_status_t psa_destroy_key(psa_key_handle_t handle) +{ +#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_DESTROY_KEY_SID, + .key_handle = handle, + }; + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_destroy_key, + TFM_CRYPTO_DESTROY_KEY); + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ +} + +psa_status_t psa_get_key_attributes(psa_key_handle_t handle, + psa_key_attributes_t *attributes) +{ +#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_GET_KEY_ATTRIBUTES_SID, + .key_handle = handle, + }; + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = attributes, .len = sizeof(psa_key_attributes_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_get_key_attributes, + TFM_CRYPTO_GET_KEY_ATTRIBUTES); + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ +} + +void psa_reset_key_attributes(psa_key_attributes_t *attributes) +{ +#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED + return; +#else + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_RESET_KEY_ATTRIBUTES_SID, + }; + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = attributes, .len = sizeof(psa_key_attributes_t)}, + }; + + psa_handle_t ipc_handle; + ipc_handle = psa_connect(TFM_CRYPTO_SID, TFM_CRYPTO_VERSION); + if (!PSA_HANDLE_IS_VALID(ipc_handle)) { + return; + } + + (void)API_DISPATCH(tfm_crypto_reset_key_attributes, + TFM_CRYPTO_RESET_KEY_ATTRIBUTES); + PSA_CLOSE(); + + return; +#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ +} + +psa_status_t psa_export_key(psa_key_handle_t handle, + uint8_t *data, + size_t data_size, + size_t *data_length) +{ +#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_EXPORT_KEY_SID, + .key_handle = handle, + }; + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = data, .len = data_size} + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_export_key, + TFM_CRYPTO_EXPORT_KEY); + + *data_length = out_vec[0].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ +} + +psa_status_t psa_export_public_key(psa_key_handle_t handle, + uint8_t *data, + size_t data_size, + size_t *data_length) +{ +#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_EXPORT_PUBLIC_KEY_SID, + .key_handle = handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = data, .len = data_size} + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_export_public_key, + TFM_CRYPTO_EXPORT_PUBLIC_KEY); + + *data_length = out_vec[0].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ +} + +psa_status_t psa_copy_key(psa_key_handle_t source_handle, + const psa_key_attributes_t *attributes, + psa_key_handle_t *target_handle) +{ +#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_COPY_KEY_SID, + .key_handle = source_handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = attributes, .len = sizeof(psa_key_attributes_t)}, + + }; + + psa_outvec out_vec[] = { + {.base = target_handle, .len = sizeof(psa_key_handle_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_copy_key, + TFM_CRYPTO_COPY_KEY); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ +} + +psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation, + unsigned char *iv, + size_t iv_size, + size_t *iv_length) +{ +#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_CIPHER_GENERATE_IV_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + {.base = iv, .len = iv_size}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_cipher_generate_iv, + TFM_CRYPTO_CIPHER_GENERATE_IV); + + *iv_length = out_vec[1].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ +} + +psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, + const unsigned char *iv, + size_t iv_length) +{ +#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_CIPHER_SET_IV_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = iv, .len = iv_length}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_cipher_set_iv, + TFM_CRYPTO_CIPHER_SET_IV); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ +} + +psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg) +{ +#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_CIPHER_ENCRYPT_SETUP_SID, + .key_handle = handle, + .alg = alg, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_cipher_encrypt_setup, + TFM_CRYPTO_CIPHER_ENCRYPT_SETUP); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ +} + +psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg) +{ +#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_CIPHER_DECRYPT_SETUP_SID, + .key_handle = handle, + .alg = alg, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_cipher_decrypt_setup, + TFM_CRYPTO_CIPHER_DECRYPT_SETUP); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ +} + +psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, + const uint8_t *input, + size_t input_length, + unsigned char *output, + size_t output_size, + size_t *output_length) +{ +#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_CIPHER_UPDATE_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = input, .len = input_length}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + {.base = output, .len = output_size} + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_cipher_update, + TFM_CRYPTO_CIPHER_UPDATE); + + *output_length = out_vec[1].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ +} + +psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation) +{ +#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_CIPHER_ABORT_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_cipher_abort, + TFM_CRYPTO_CIPHER_ABORT); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ +} + +psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ +#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_CIPHER_FINISH_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + {.base = output, .len = output_size}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_cipher_finish, + TFM_CRYPTO_CIPHER_FINISH); + + *output_length = out_vec[1].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ +} + +psa_status_t psa_hash_setup(psa_hash_operation_t *operation, + psa_algorithm_t alg) +{ +#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_HASH_SETUP_SID, + .alg = alg, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_hash_setup, + TFM_CRYPTO_HASH_SETUP); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_HASH_MODULE_DISABLED */ +} + +psa_status_t psa_hash_update(psa_hash_operation_t *operation, + const uint8_t *input, + size_t input_length) +{ +#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_HASH_UPDATE_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = input, .len = input_length}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_hash_update, + TFM_CRYPTO_HASH_UPDATE); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_HASH_MODULE_DISABLED */ +} + +psa_status_t psa_hash_finish(psa_hash_operation_t *operation, + uint8_t *hash, + size_t hash_size, + size_t *hash_length) +{ +#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_HASH_FINISH_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + {.base = hash, .len = hash_size}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_hash_finish, + TFM_CRYPTO_HASH_FINISH); + + *hash_length = out_vec[1].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_HASH_MODULE_DISABLED */ +} + +psa_status_t psa_hash_verify(psa_hash_operation_t *operation, + const uint8_t *hash, + size_t hash_length) +{ +#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_HASH_VERIFY_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = hash, .len = hash_length}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_hash_verify, + TFM_CRYPTO_HASH_VERIFY); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_HASH_MODULE_DISABLED */ +} + +psa_status_t psa_hash_abort(psa_hash_operation_t *operation) +{ +#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_HASH_ABORT_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_hash_abort, + TFM_CRYPTO_HASH_ABORT); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_HASH_MODULE_DISABLED */ +} + +psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation, + psa_hash_operation_t *target_operation) +{ +#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_HASH_CLONE_SID, + .op_handle = source_operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = target_operation, .len = sizeof(psa_hash_operation_t)}, + }; + + if (target_operation && (target_operation->handle != 0)) { + return PSA_ERROR_BAD_STATE; + } + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_hash_clone, + TFM_CRYPTO_HASH_CLONE); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_HASH_MODULE_DISABLED */ +} + +psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg) +{ +#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_MAC_SIGN_SETUP_SID, + .key_handle = handle, + .alg = alg, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_mac_sign_setup, + TFM_CRYPTO_MAC_SIGN_SETUP); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */ +} + +psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg) +{ +#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_MAC_VERIFY_SETUP_SID, + .key_handle = handle, + .alg = alg, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_mac_verify_setup, + TFM_CRYPTO_MAC_VERIFY_SETUP); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */ +} + +psa_status_t psa_mac_update(psa_mac_operation_t *operation, + const uint8_t *input, + size_t input_length) +{ +#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_MAC_UPDATE_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = input, .len = input_length}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_mac_update, + TFM_CRYPTO_MAC_UPDATE); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */ +} + +psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, + uint8_t *mac, + size_t mac_size, + size_t *mac_length) +{ +#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_MAC_SIGN_FINISH_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + {.base = mac, .len = mac_size}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_mac_sign_finish, + TFM_CRYPTO_MAC_SIGN_FINISH); + + *mac_length = out_vec[1].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */ +} + +psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation, + const uint8_t *mac, + size_t mac_length) +{ +#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_MAC_VERIFY_FINISH_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = mac, .len = mac_length}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_mac_verify_finish, + TFM_CRYPTO_MAC_VERIFY_FINISH); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */ +} + +psa_status_t psa_mac_abort(psa_mac_operation_t *operation) +{ +#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_MAC_ABORT_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_mac_abort, + TFM_CRYPTO_MAC_ABORT); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */ +} + +psa_status_t psa_aead_encrypt(psa_key_handle_t handle, + 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 *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length) +{ +#ifdef TFM_CRYPTO_AEAD_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_AEAD_ENCRYPT_SID, + .key_handle = handle, + .alg = alg, + .aead_in = {.nonce = {0}, .nonce_length = nonce_length} + }; + + /* Sanitize the optional input */ + if ((additional_data == NULL) && (additional_data_length != 0)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + size_t idx = 0; + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = plaintext, .len = plaintext_length}, + {.base = additional_data, .len = additional_data_length}, + }; + psa_outvec out_vec[] = { + {.base = ciphertext, .len = ciphertext_size}, + }; + + if (nonce_length > TFM_CRYPTO_MAX_NONCE_LENGTH) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (nonce != NULL) { + for (idx = 0; idx < nonce_length; idx++) { + iov.aead_in.nonce[idx] = nonce[idx]; + } + } + + PSA_CONNECT(TFM_CRYPTO); + + size_t in_len = ARRAY_SIZE(in_vec); + if (additional_data == NULL) { + in_len--; + } + status = psa_call(ipc_handle, PSA_IPC_CALL, in_vec, in_len, + out_vec, ARRAY_SIZE(out_vec)); + + *ciphertext_length = out_vec[0].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_AEAD_MODULE_DISABLED */ +} + +psa_status_t psa_aead_decrypt(psa_key_handle_t handle, + 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 *ciphertext, + size_t ciphertext_length, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length) +{ +#ifdef TFM_CRYPTO_AEAD_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_AEAD_DECRYPT_SID, + .key_handle = handle, + .alg = alg, + .aead_in = {.nonce = {0}, .nonce_length = nonce_length} + }; + + /* Sanitize the optional input */ + if ((additional_data == NULL) && (additional_data_length != 0)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + size_t idx = 0; + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = ciphertext, .len = ciphertext_length}, + {.base = additional_data, .len = additional_data_length}, + }; + psa_outvec out_vec[] = { + {.base = plaintext, .len = plaintext_size}, + }; + + if (nonce_length > TFM_CRYPTO_MAX_NONCE_LENGTH) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (nonce != NULL) { + for (idx = 0; idx < nonce_length; idx++) { + iov.aead_in.nonce[idx] = nonce[idx]; + } + } + + PSA_CONNECT(TFM_CRYPTO); + + size_t in_len = ARRAY_SIZE(in_vec); + if (additional_data == NULL) { + in_len--; + } + status = psa_call(ipc_handle, PSA_IPC_CALL, in_vec, in_len, + out_vec, ARRAY_SIZE(out_vec)); + + *plaintext_length = out_vec[0].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_AEAD_MODULE_DISABLED */ +} + +psa_status_t psa_asymmetric_sign(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length) +{ + return psa_sign_hash(handle, alg, hash, hash_length, signature, signature_size, signature_length); +} + +psa_status_t psa_sign_hash(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length) +{ +#ifdef TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_SIGN_HASH_SID, + .key_handle = handle, + .alg = alg, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = hash, .len = hash_length}, + }; + psa_outvec out_vec[] = { + {.base = signature, .len = signature_size}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_sign_hash, + TFM_CRYPTO_SIGN_HASH); + + *signature_length = out_vec[0].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED */ +} + +psa_status_t psa_asymmetric_verify(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length) +{ + return psa_verify_hash(handle, alg, hash, hash_length, signature, signature_length); +} + +psa_status_t psa_verify_hash(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length) +{ +#ifdef TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_VERIFY_HASH_SID, + .key_handle = handle, + .alg = alg + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = hash, .len = hash_length}, + {.base = signature, .len = signature_length} + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_verify_hash, + TFM_CRYPTO_VERIFY_HASH); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED */ +} + +psa_status_t psa_asymmetric_encrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ +#ifdef TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_ASYMMETRIC_ENCRYPT_SID, + .key_handle = handle, + .alg = alg + }; + + /* Sanitize the optional input */ + if ((salt == NULL) && (salt_length != 0)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = input, .len = input_length}, + {.base = salt, .len = salt_length} + }; + + psa_outvec out_vec[] = { + {.base = output, .len = output_size}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + size_t in_len = ARRAY_SIZE(in_vec); + if (salt == NULL) { + in_len--; + } + status = psa_call(ipc_handle, PSA_IPC_CALL, in_vec, in_len, + out_vec, ARRAY_SIZE(out_vec)); + + *output_length = out_vec[0].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED */ +} + +psa_status_t psa_asymmetric_decrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ +#ifdef TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_ASYMMETRIC_DECRYPT_SID, + .key_handle = handle, + .alg = alg + }; + + /* Sanitize the optional input */ + if ((salt == NULL) && (salt_length != 0)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = input, .len = input_length}, + {.base = salt, .len = salt_length} + }; + + psa_outvec out_vec[] = { + {.base = output, .len = output_size}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + size_t in_len = ARRAY_SIZE(in_vec); + if (salt == NULL) { + in_len--; + } + status = psa_call(ipc_handle, PSA_IPC_CALL, in_vec, in_len, + out_vec, ARRAY_SIZE(out_vec)); + + *output_length = out_vec[0].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED */ +} + +psa_status_t psa_key_derivation_get_capacity( + const psa_key_derivation_operation_t *operation, + size_t *capacity) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_GET_CAPACITY_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + + psa_outvec out_vec[] = { + {.base = capacity, .len = sizeof(size_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_key_derivation_get_capacity, + TFM_CRYPTO_KEY_DERIVATION_GET_CAPACITY); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_key_derivation_output_bytes( + psa_key_derivation_operation_t *operation, + uint8_t *output, + size_t output_length) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_OUTPUT_BYTES_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + + psa_outvec out_vec[] = { + {.base = output, .len = output_length}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_key_derivation_output_bytes, + TFM_CRYPTO_KEY_DERIVATION_OUTPUT_BYTES); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_key_derivation_input_key( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_handle_t handle) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_INPUT_KEY_SID, + .key_handle = handle, + .step = step, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_key_derivation_input_key, + TFM_CRYPTO_KEY_DERIVATION_INPUT_KEY); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_key_derivation_abort( + psa_key_derivation_operation_t *operation) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_ABORT_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_key_derivation_abort, + TFM_CRYPTO_KEY_DERIVATION_ABORT); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_key_derivation_key_agreement( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_handle_t private_key, + const uint8_t *peer_key, + size_t peer_key_length) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_KEY_AGREEMENT_SID, + .key_handle = private_key, + .step = step, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = peer_key, .len = peer_key_length}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_key_derivation_key_agreement, + TFM_CRYPTO_KEY_DERIVATION_KEY_AGREEMENT); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_generate_random(uint8_t *output, + size_t output_size) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_GENERATE_RANDOM_SID, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + + psa_outvec out_vec[] = { + {.base = output, .len = output_size}, + }; + + if (output_size == 0) { + return PSA_SUCCESS; + } + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_generate_random, + TFM_CRYPTO_GENERATE_RANDOM); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, + psa_key_handle_t *handle) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_GENERATE_KEY_SID, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = attributes, .len = sizeof(psa_key_attributes_t)}, + }; + + psa_outvec out_vec[] = { + {.base = handle, .len = sizeof(psa_key_handle_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_generate_key, + TFM_CRYPTO_GENERATE_KEY); + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes, + psa_key_type_t type, + const uint8_t *data, + size_t data_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_get_key_domain_parameters( + const psa_key_attributes_t *attributes, + uint8_t *data, + size_t data_size, + size_t *data_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_hash_compare(psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *hash, + const size_t hash_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_finish(psa_aead_operation_t *operation, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length, + uint8_t *tag, + size_t tag_size, + size_t *tag_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_verify(psa_aead_operation_t *operation, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length, + const uint8_t *tag, + size_t tag_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_abort(psa_aead_operation_t *operation) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_mac_compute(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *mac, + size_t mac_size, + size_t *mac_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_mac_verify(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *mac, + const size_t mac_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_cipher_encrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_cipher_decrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, + psa_key_handle_t private_key, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_RAW_KEY_AGREEMENT_SID, + .alg = alg, + .key_handle = private_key + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = peer_key, .len = peer_key_length}, + }; + + psa_outvec out_vec[] = { + {.base = output, .len = output_size}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_raw_key_agreement, + TFM_CRYPTO_RAW_KEY_AGREEMENT); + + *output_length = out_vec[0].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_key_derivation_setup(psa_key_derivation_operation_t *operation, + psa_algorithm_t alg) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_SETUP_SID, + .alg = alg, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_key_derivation_setup, + TFM_CRYPTO_KEY_DERIVATION_SETUP); + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_key_derivation_set_capacity( + psa_key_derivation_operation_t *operation, + size_t capacity) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_SET_CAPACITY_SID, + .capacity = capacity, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_key_derivation_set_capacity, + TFM_CRYPTO_KEY_DERIVATION_SET_CAPACITY); + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_key_derivation_input_bytes( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_INPUT_BYTES_SID, + .step = step, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = data, .len = data_length}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_key_derivation_input_bytes, + TFM_CRYPTO_KEY_DERIVATION_INPUT_BYTES); + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_key_derivation_output_key( + const psa_key_attributes_t *attributes, + psa_key_derivation_operation_t *operation, + psa_key_handle_t *handle) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_OUTPUT_KEY_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = attributes, .len = sizeof(psa_key_attributes_t)}, + }; + + psa_outvec out_vec[] = { + {.base = handle, .len = sizeof(psa_key_handle_t)} + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_key_derivation_output_key, + TFM_CRYPTO_KEY_DERIVATION_OUTPUT_KEY); + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_hash_compute(psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *hash, + size_t hash_size, + size_t *hash_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation, + uint8_t *nonce, + size_t nonce_size, + size_t *nonce_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation, + const uint8_t *nonce, + size_t nonce_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation, + size_t ad_length, + size_t plaintext_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_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 status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/src/tfm_initial_attestation_ipc_api.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/src/tfm_initial_attestation_ipc_api.c new file mode 100644 index 0000000..78f9dec --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/src/tfm_initial_attestation_ipc_api.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "psa/initial_attestation.h" +#include "tfm_ns_interface.h" +#include "psa/client.h" +#include "psa/crypto_types.h" +#include "psa_manifest/sid.h" + +#define IOVEC_LEN(x) (sizeof(x)/sizeof(x[0])) + +psa_status_t +psa_initial_attest_get_token(const uint8_t *auth_challenge, + size_t challenge_size, + uint8_t *token_buf, + size_t token_buf_size, + size_t *token_size) +{ + psa_handle_t handle = PSA_NULL_HANDLE; + psa_status_t status; + + psa_invec in_vec[] = { + {auth_challenge, challenge_size} + }; + psa_outvec out_vec[] = { + {token_buf, token_buf_size} + }; + + handle = psa_connect(TFM_ATTEST_GET_TOKEN_SID, + TFM_ATTEST_GET_TOKEN_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_HANDLE_TO_ERROR(handle); + } + + status = psa_call(handle, PSA_IPC_CALL, + in_vec, IOVEC_LEN(in_vec), + out_vec, IOVEC_LEN(out_vec)); + psa_close(handle); + + if (status == PSA_SUCCESS) { + *token_size = out_vec[0].len; + } + + return status; +} + +psa_status_t +psa_initial_attest_get_token_size(size_t challenge_size, + size_t *token_size) +{ + psa_handle_t handle = PSA_NULL_HANDLE; + psa_status_t status; + psa_invec in_vec[] = { + {&challenge_size, sizeof(challenge_size)} + }; + psa_outvec out_vec[] = { + {token_size, sizeof(size_t)} + }; + + handle = psa_connect(TFM_ATTEST_GET_TOKEN_SIZE_SID, + TFM_ATTEST_GET_TOKEN_SIZE_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_HANDLE_TO_ERROR(handle); + } + + status = psa_call(handle, PSA_IPC_CALL, + in_vec, IOVEC_LEN(in_vec), + out_vec, IOVEC_LEN(out_vec)); + psa_close(handle); + + return status; +} + +psa_status_t +tfm_initial_attest_get_public_key(uint8_t *public_key, + size_t public_key_buf_size, + size_t *public_key_len, + psa_ecc_curve_t *elliptic_curve_type) +{ + psa_handle_t handle = PSA_NULL_HANDLE; + psa_status_t status; + + psa_outvec out_vec[] = { + {.base = public_key, .len = public_key_buf_size}, + {.base = elliptic_curve_type, .len = sizeof(*elliptic_curve_type)}, + {.base = public_key_len, .len = sizeof(*public_key_len)} + }; + + handle = psa_connect(TFM_ATTEST_GET_PUBLIC_KEY_SID, + TFM_ATTEST_GET_PUBLIC_KEY_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_HANDLE_TO_ERROR(handle); + } + + status = psa_call(handle, PSA_IPC_CALL, + NULL, 0, + out_vec, IOVEC_LEN(out_vec)); + psa_close(handle); + + return status; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/src/tfm_its_ipc_api.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/src/tfm_its_ipc_api.c new file mode 100644 index 0000000..9326f7b --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/src/tfm_its_ipc_api.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "psa/internal_trusted_storage.h" +#include "tfm_api.h" + +#include "psa/client.h" +#include "psa_manifest/sid.h" + +#define IOVEC_LEN(x) (sizeof(x)/sizeof(x[0])) + +psa_status_t psa_its_set(psa_storage_uid_t uid, + size_t data_length, + const void *p_data, + psa_storage_create_flags_t create_flags) +{ + psa_status_t status; + psa_handle_t handle; + + psa_invec in_vec[] = { + { .base = &uid, .len = sizeof(uid) }, + { .base = p_data, .len = data_length }, + { .base = &create_flags, .len = sizeof(create_flags) } + }; + + handle = psa_connect(TFM_ITS_SET_SID, TFM_ITS_SET_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_ERROR_GENERIC_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), NULL, 0); + + psa_close(handle); + + if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + return status; +} + +psa_status_t psa_its_get(psa_storage_uid_t uid, + size_t data_offset, + size_t data_size, + void *p_data, + size_t *p_data_length) +{ + psa_status_t status; + psa_handle_t handle; + + psa_invec in_vec[] = { + { .base = &uid, .len = sizeof(uid) }, + { .base = &data_offset, .len = sizeof(data_offset) } + }; + + psa_outvec out_vec[] = { + { .base = p_data, .len = data_size } + }; + + if (p_data_length == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + handle = psa_connect(TFM_ITS_GET_SID, TFM_ITS_GET_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_ERROR_GENERIC_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), out_vec, + IOVEC_LEN(out_vec)); + + psa_close(handle); + + if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + *p_data_length = out_vec[0].len; + + return status; +} + +psa_status_t psa_its_get_info(psa_storage_uid_t uid, + struct psa_storage_info_t *p_info) +{ + psa_status_t status; + psa_handle_t handle; + + psa_invec in_vec[] = { + { .base = &uid, .len = sizeof(uid) } + }; + + psa_outvec out_vec[] = { + { .base = p_info, .len = sizeof(*p_info) } + }; + + handle = psa_connect(TFM_ITS_GET_INFO_SID, TFM_ITS_GET_INFO_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_ERROR_GENERIC_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), out_vec, + IOVEC_LEN(out_vec)); + + psa_close(handle); + + if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + return status; +} + +psa_status_t psa_its_remove(psa_storage_uid_t uid) +{ + psa_status_t status; + psa_handle_t handle; + + psa_invec in_vec[] = { + { .base = &uid, .len = sizeof(uid) } + }; + + handle = psa_connect(TFM_ITS_REMOVE_SID, TFM_ITS_REMOVE_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_ERROR_GENERIC_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), NULL, 0); + + psa_close(handle); + + return status; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/src/tfm_platform_ipc_api.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/src/tfm_platform_ipc_api.c new file mode 100644 index 0000000..c43fe8b --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/src/tfm_platform_ipc_api.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include "tfm_platform_api.h" +#include "psa_manifest/sid.h" + +enum tfm_platform_err_t tfm_platform_system_reset(void) +{ + psa_status_t status = PSA_ERROR_CONNECTION_REFUSED; + psa_handle_t handle = PSA_NULL_HANDLE; + + handle = psa_connect(TFM_SP_PLATFORM_SYSTEM_RESET_SID, + TFM_SP_PLATFORM_SYSTEM_RESET_VERSION); + if (handle <= 0) { + return TFM_PLATFORM_ERR_SYSTEM_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, + NULL, 0, NULL, 0); + psa_close(handle); + + if (status < PSA_SUCCESS) { + return TFM_PLATFORM_ERR_SYSTEM_ERROR; + } else { + return (enum tfm_platform_err_t) status; + } + +} + +enum tfm_platform_err_t +tfm_platform_ioctl(tfm_platform_ioctl_req_t request, + psa_invec *input, psa_outvec *output) +{ + tfm_platform_ioctl_req_t req = request; + struct psa_invec in_vec[2] = { {0} }; + size_t inlen, outlen; + psa_status_t status = PSA_ERROR_CONNECTION_REFUSED; + psa_handle_t handle = PSA_NULL_HANDLE; + + in_vec[0].base = &req; + in_vec[0].len = sizeof(req); + if (input != NULL) { + in_vec[1].base = input->base; + in_vec[1].len = input->len; + inlen = 2; + } else { + inlen = 1; + } + + if (output != NULL) { + outlen = 1; + } else { + outlen = 0; + } + + handle = psa_connect(TFM_SP_PLATFORM_IOCTL_SID, + TFM_SP_PLATFORM_IOCTL_VERSION); + if (handle <= 0) { + return TFM_PLATFORM_ERR_SYSTEM_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, + in_vec, inlen, + output, outlen); + psa_close(handle); + + if (status < PSA_SUCCESS) { + return TFM_PLATFORM_ERR_SYSTEM_ERROR; + } else { + return (enum tfm_platform_err_t) status; + } +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/src/tfm_ps_ipc_api.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/src/tfm_ps_ipc_api.c new file mode 100644 index 0000000..7cc3a63 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_1/src/tfm_ps_ipc_api.c @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2017-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "psa/protected_storage.h" + +#include "tfm_ns_interface.h" +#include "psa_manifest/sid.h" + +#define IOVEC_LEN(x) (uint32_t)(sizeof(x)/sizeof(x[0])) + +psa_status_t psa_ps_set(psa_storage_uid_t uid, + size_t data_length, + const void *p_data, + psa_storage_create_flags_t create_flags) +{ + psa_status_t status; + psa_handle_t handle; + + psa_invec in_vec[] = { + { .base = &uid, .len = sizeof(uid) }, + { .base = p_data, .len = data_length }, + { .base = &create_flags, .len = sizeof(create_flags) } + }; + + handle = psa_connect(TFM_PS_SET_SID, TFM_PS_SET_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_ERROR_GENERIC_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), + NULL, 0); + + psa_close(handle); + + /* A parameter with a buffer pointer pointer that has data length longer + * than maximum permitted is treated as a secure violation. + * TF-M framework rejects the request with TFM_ERROR_INVALID_PARAMETER. + */ + if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + return status; +} + +psa_status_t psa_ps_get(psa_storage_uid_t uid, + size_t data_offset, + size_t data_size, + void *p_data, + size_t *p_data_length) +{ + psa_status_t status; + psa_handle_t handle; + + psa_invec in_vec[] = { + { .base = &uid, .len = sizeof(uid) }, + { .base = &data_offset, .len = sizeof(data_offset) } + }; + + psa_outvec out_vec[] = { + { .base = p_data, .len = data_size } + }; + + if (p_data_length == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + handle = psa_connect(TFM_PS_GET_SID, TFM_PS_GET_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_ERROR_GENERIC_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), out_vec, + IOVEC_LEN(out_vec)); + + psa_close(handle); + + *p_data_length = out_vec[0].len; + + return status; +} + +psa_status_t psa_ps_get_info(psa_storage_uid_t uid, + struct psa_storage_info_t *p_info) +{ + psa_status_t status; + psa_handle_t handle; + + psa_invec in_vec[] = { + { .base = &uid, .len = sizeof(uid) } + }; + + psa_outvec out_vec[] = { + { .base = p_info, .len = sizeof(*p_info) } + }; + + handle = psa_connect(TFM_PS_GET_INFO_SID, TFM_PS_GET_INFO_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_ERROR_GENERIC_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), out_vec, + IOVEC_LEN(out_vec)); + + psa_close(handle); + + return status; +} + +psa_status_t psa_ps_remove(psa_storage_uid_t uid) +{ + psa_status_t status; + psa_handle_t handle; + + psa_invec in_vec[] = { + { .base = &uid, .len = sizeof(uid) } + }; + + + handle = psa_connect(TFM_PS_REMOVE_SID, TFM_PS_REMOVE_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_ERROR_GENERIC_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), + NULL, 0); + + psa_close(handle); + + return status; +} + +psa_status_t psa_ps_create(psa_storage_uid_t uid, size_t size, + psa_storage_create_flags_t create_flags) +{ + (void)uid; + (void)size; + (void)create_flags; + + return PSA_ERROR_NOT_SUPPORTED; +} + +psa_status_t psa_ps_set_extended(psa_storage_uid_t uid, size_t data_offset, + size_t data_length, const void *p_data) +{ + (void)uid; + (void)data_offset; + (void)data_length; + (void)p_data; + + return PSA_ERROR_NOT_SUPPORTED; +} + +uint32_t psa_ps_get_support(void) +{ + /* Initialise support_flags to a sensible default, to avoid returning an + * uninitialised value in case the secure function fails. + */ + uint32_t support_flags = 0; + psa_handle_t handle; + + psa_outvec out_vec[] = { + { .base = &support_flags, .len = sizeof(support_flags) } + }; + + /* The PSA API does not return an error, so any error from TF-M is + * ignored. + */ + handle = psa_connect(TFM_PS_GET_SUPPORT_SID, TFM_PS_GET_SUPPORT_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return support_flags; + } + + (void)psa_call(handle, PSA_IPC_CALL, NULL, 0, out_vec, IOVEC_LEN(out_vec)); + + psa_close(handle); + + return support_flags; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/inc/default_random_seed.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/inc/default_random_seed.h new file mode 100644 index 0000000..5d15fb4 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/inc/default_random_seed.h @@ -0,0 +1,44 @@ + + +#ifndef DEFAULT_RANDOM_SEED_H +#define DEFAULT_RANDOM_SEED_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + + +/** Read seed from the secure storage. + * + * This function will be the default function for reading the Random seed. + * + * @param buf[out] buffer to hold the seed value from the secure storage + * @param buf_len[in] input buffer length + * + * @returns + * secure storage API return value. + * + */ +int mbed_default_seed_read(unsigned char *buf, size_t buf_len); + +/** Writes seed to the secure storage. + * + * This function will be the default function for writing the Random seed. + * + * @param buf[in] buffer to the seed value + * @param buf_len[in] input buffer length + * + * @returns + * secure storage API return value. + */ +int mbed_default_seed_write(unsigned char *buf, size_t buf_len); + + +#ifdef __cplusplus +} +#endif + +#endif /* DEFAULT_RANDOM_SEED_H */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/inc/psa/tfm_platform_api.h b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/inc/psa/tfm_platform_api.h new file mode 100644 index 0000000..86be961 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/inc/psa/tfm_platform_api.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __TFM_PLATFORM_API__ +#define __TFM_PLATFORM_API__ + +#include +#include +#include "psa/client.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief TFM secure partition platform API version + */ +#define TFM_PLATFORM_API_VERSION_MAJOR (0) +#define TFM_PLATFORM_API_VERSION_MINOR (3) + +/*! + * \enum tfm_platform_err_t + * + * \brief Platform service error types + * + */ +enum tfm_platform_err_t { + TFM_PLATFORM_ERR_SUCCESS = 0, + TFM_PLATFORM_ERR_SYSTEM_ERROR, + TFM_PLATFORM_ERR_INVALID_PARAM, + TFM_PLATFORM_ERR_NOT_SUPPORTED, + + /* Following entry is only to ensure the error code of int size */ + TFM_PLATFORM_ERR_FORCE_INT_SIZE = INT_MAX +}; + +typedef int32_t tfm_platform_ioctl_req_t; + +/*! + * \brief Performs a platform-specific service + * + * \param[in] request Request identifier (valid values vary + * based on the platform) + * \param[in] input Input buffer to the requested service (or NULL) + * \param[in,out] output Output buffer to the requested service (or NULL) + * + * \return Returns values as specified by the \ref tfm_platform_err_t + */ +enum tfm_platform_err_t tfm_platform_ioctl(tfm_platform_ioctl_req_t request, + psa_invec *input, + psa_outvec *output); + + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_PLATFORM_API__ */ diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/mbed_lib.json b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/mbed_lib.json new file mode 100644 index 0000000..b1087b1 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/mbed_lib.json @@ -0,0 +1,6 @@ +{ + "name": "psa", + "config": { + "present": 1 + } +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/src/psa_hrng.c b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/src/psa_hrng.c new file mode 100644 index 0000000..f5c0a30 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/src/psa_hrng.c @@ -0,0 +1,53 @@ +/* Copyright (c) 2018-2020 ARM Limited + * + * 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 "trng_api.h" +#include "crypto.h" +#include "mbed_toolchain.h" + +MBED_WEAK void trng_init(trng_t *obj) +{ + (void)(obj); +} + + +MBED_WEAK void trng_free(trng_t *obj) +{ + (void)(obj); +} + +MBED_WEAK int trng_get_bytes(trng_t *obj, uint8_t *output, size_t length, size_t *output_length) +{ + ((void)(obj)); + if (output == NULL || output_length == NULL) { + return -1; + } + + psa_status_t status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + return -1; + } + + status = psa_generate_random(output, length); + if (status != PSA_SUCCESS) { + return -1; + } + + *output_length = length; + + return 0; +} diff --git a/platform/FEATURE_EXPERIMENTAL_API/mbed_lib.json b/platform/FEATURE_EXPERIMENTAL_API/mbed_lib.json new file mode 100644 index 0000000..d04ec872 --- /dev/null +++ b/platform/FEATURE_EXPERIMENTAL_API/mbed_lib.json @@ -0,0 +1,6 @@ +{ + "name": "experimental_api", + "config": { + "present": 1 + } +}