From 734dbad7305293aad19f517c29f01db5d41495ab Mon Sep 17 00:00:00 2001 From: julhal01 Date: Mon, 21 Dec 2020 10:27:41 +0000 Subject: Add packed-c protocol support for crypto service To provide a lightweight parameter encoding that is aligned to conventions used by SCMI, the packed-c parameter serialization has been added to the crypto service. This builds on generic components that allow other packed-c service access protocols to be added easily. Service level tests have been extended to use both protobuf and packed-c clients. Signed-off-by: julhal01 Change-Id: I9279b0814bcc9cf6c4aa4e30629e2f46f2df4c23 --- components/app/ts-demo/test/ts-demo_tests.cpp | 5 +- components/common/tlv/component.cmake | 13 + components/common/tlv/test/component.cmake | 13 + components/common/tlv/test/tlv_tests.cpp | 207 ++++++ components/common/tlv/tlv.c | 99 +++ components/common/tlv/tlv.h | 108 +++ .../test/protocol/check_rpc_status_alignment.cpp | 34 + .../rpc/common/test/protocol/component.cmake | 14 + .../service/crypto/client/cpp/crypto_client.cpp | 774 -------------------- .../service/crypto/client/cpp/crypto_client.h | 53 +- .../crypto/client/cpp/packed-c/component.cmake | 14 + .../client/cpp/packed-c/packedc_crypto_client.cpp | 749 +++++++++++++++++++ .../client/cpp/packed-c/packedc_crypto_client.h | 65 ++ .../crypto/client/cpp/protobuf/component.cmake | 14 + .../client/cpp/protobuf/protobuf_crypto_client.cpp | 799 +++++++++++++++++++++ .../client/cpp/protobuf/protobuf_crypto_client.h | 65 ++ .../crypto/client/test/mock/mock_crypto_client.cpp | 4 + .../test/standalone/standalone_crypto_client.cpp | 4 + .../crypto/client/test/test_crypto_client.cpp | 4 +- .../crypto/client/test/test_crypto_client.h | 6 +- .../provider/serializer/packed-c/component.cmake | 14 + .../packed-c/packedc_crypto_provider_serializer.c | 661 +++++++++++++++++ .../packed-c/packedc_crypto_provider_serializer.h | 25 + .../packed-c/packedc_key_attributes_translator.c | 22 + .../packed-c/packedc_key_attributes_translator.h | 17 + .../provider/serializer/protobuf/component.cmake | 6 - .../protobuf/pb_crypto_provider_serializer.c | 2 +- .../protobuf/pb_crypto_provider_serializer.h | 5 +- .../protobuf/pb_key_attributes_translator.h | 2 +- .../protocol/check_crypto_opcode_alignment.cpp | 34 + .../check_crypto_packed-c_protocol_alignment.cpp | 136 ++++ .../check_crypto_protobuf_protocol_alignment.cpp | 136 ++++ .../service/crypto/test/protocol/component.cmake | 16 + .../service/crypto/test/service/component.cmake | 4 +- .../test/service/crypto_service_limit_tests.cpp | 4 +- .../test/service/crypto_service_op_tests.cpp | 383 ---------- .../test/service/crypto_service_scenarios.cpp | 348 +++++++++ .../crypto/test/service/crypto_service_scenarios.h | 30 + .../crypto/test/service/packed-c/component.cmake | 14 + .../packed-c/crypto_service_packedc_tests.cpp | 88 +++ .../crypto/test/service/protobuf/component.cmake | 14 + .../protobuf/crypto_service_protobuf_tests.cpp | 88 +++ .../services/crypto/crypto_service_context.cpp | 4 + deployments/component-test/component-test.cmake | 10 +- deployments/crypto/opteesp/CMakeLists.txt | 2 + deployments/crypto/opteesp/crypto_sp.c | 7 +- deployments/libts/linux-pc/CMakeLists.txt | 10 +- deployments/ts-demo/ts-demo.cmake | 10 +- deployments/ts-demo/ts-demo.cpp | 6 +- deployments/ts-service-test/ts-service-test.cmake | 6 + .../packed-c/test/check_rpc_status_packed-c.cpp | 33 - protocols/rpc/common/packed-c/test/component.cmake | 14 - .../service/crypto/packed-c/asymmetric_decrypt.h | 31 + .../service/crypto/packed-c/asymmetric_encrypt.h | 31 + protocols/service/crypto/packed-c/close_key.h | 17 + protocols/service/crypto/packed-c/component.cmake | 2 +- protocols/service/crypto/packed-c/destroy_key.h | 17 + protocols/service/crypto/packed-c/export_key.h | 23 + .../service/crypto/packed-c/export_public_key.h | 23 + protocols/service/crypto/packed-c/generate_key.h | 24 + .../service/crypto/packed-c/generate_random.h | 23 + protocols/service/crypto/packed-c/import_key.h | 30 + protocols/service/crypto/packed-c/key_attributes.h | 122 ++++ protocols/service/crypto/packed-c/opcodes.h | 2 +- protocols/service/crypto/packed-c/open_key.h | 23 + protocols/service/crypto/packed-c/sign_hash.h | 30 + protocols/service/crypto/packed-c/verify_hash.h | 25 + .../service/crypto/protobuf/key_attributes.proto | 4 +- 68 files changed, 4351 insertions(+), 1271 deletions(-) create mode 100644 components/common/tlv/component.cmake create mode 100644 components/common/tlv/test/component.cmake create mode 100644 components/common/tlv/test/tlv_tests.cpp create mode 100644 components/common/tlv/tlv.c create mode 100644 components/common/tlv/tlv.h create mode 100644 components/rpc/common/test/protocol/check_rpc_status_alignment.cpp create mode 100644 components/rpc/common/test/protocol/component.cmake create mode 100644 components/service/crypto/client/cpp/packed-c/component.cmake create mode 100644 components/service/crypto/client/cpp/packed-c/packedc_crypto_client.cpp create mode 100644 components/service/crypto/client/cpp/packed-c/packedc_crypto_client.h create mode 100644 components/service/crypto/client/cpp/protobuf/component.cmake create mode 100644 components/service/crypto/client/cpp/protobuf/protobuf_crypto_client.cpp create mode 100644 components/service/crypto/client/cpp/protobuf/protobuf_crypto_client.h create mode 100644 components/service/crypto/provider/serializer/packed-c/component.cmake create mode 100644 components/service/crypto/provider/serializer/packed-c/packedc_crypto_provider_serializer.c create mode 100644 components/service/crypto/provider/serializer/packed-c/packedc_crypto_provider_serializer.h create mode 100644 components/service/crypto/provider/serializer/packed-c/packedc_key_attributes_translator.c create mode 100644 components/service/crypto/provider/serializer/packed-c/packedc_key_attributes_translator.h create mode 100644 components/service/crypto/test/protocol/check_crypto_opcode_alignment.cpp create mode 100644 components/service/crypto/test/protocol/check_crypto_packed-c_protocol_alignment.cpp create mode 100644 components/service/crypto/test/protocol/check_crypto_protobuf_protocol_alignment.cpp create mode 100644 components/service/crypto/test/protocol/component.cmake delete mode 100644 components/service/crypto/test/service/crypto_service_op_tests.cpp create mode 100644 components/service/crypto/test/service/crypto_service_scenarios.cpp create mode 100644 components/service/crypto/test/service/crypto_service_scenarios.h create mode 100644 components/service/crypto/test/service/packed-c/component.cmake create mode 100644 components/service/crypto/test/service/packed-c/crypto_service_packedc_tests.cpp create mode 100644 components/service/crypto/test/service/protobuf/component.cmake create mode 100644 components/service/crypto/test/service/protobuf/crypto_service_protobuf_tests.cpp delete mode 100644 protocols/rpc/common/packed-c/test/check_rpc_status_packed-c.cpp delete mode 100644 protocols/rpc/common/packed-c/test/component.cmake create mode 100644 protocols/service/crypto/packed-c/asymmetric_decrypt.h create mode 100644 protocols/service/crypto/packed-c/asymmetric_encrypt.h create mode 100644 protocols/service/crypto/packed-c/close_key.h create mode 100644 protocols/service/crypto/packed-c/destroy_key.h create mode 100644 protocols/service/crypto/packed-c/export_key.h create mode 100644 protocols/service/crypto/packed-c/export_public_key.h create mode 100644 protocols/service/crypto/packed-c/generate_key.h create mode 100644 protocols/service/crypto/packed-c/generate_random.h create mode 100644 protocols/service/crypto/packed-c/import_key.h create mode 100644 protocols/service/crypto/packed-c/key_attributes.h create mode 100644 protocols/service/crypto/packed-c/open_key.h create mode 100644 protocols/service/crypto/packed-c/sign_hash.h create mode 100644 protocols/service/crypto/packed-c/verify_hash.h diff --git a/components/app/ts-demo/test/ts-demo_tests.cpp b/components/app/ts-demo/test/ts-demo_tests.cpp index 66295572a..5f23c2778 100644 --- a/components/app/ts-demo/test/ts-demo_tests.cpp +++ b/components/app/ts-demo/test/ts-demo_tests.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -27,10 +28,10 @@ TEST_GROUP(TsDemoTests) { m_crypto_service_context = service_locator_query("sn:trustedfirmware.org:crypto:0", &status); CHECK(m_crypto_service_context); - m_rpc_session_handle = service_context_open(m_crypto_service_context, TS_RPC_ENCODING_PROTOBUF, &caller); + m_rpc_session_handle = service_context_open(m_crypto_service_context, TS_RPC_ENCODING_PACKED_C, &caller); CHECK(m_rpc_session_handle); - m_crypto_client = new crypto_client(caller); + m_crypto_client = new packedc_crypto_client(caller); } void teardown() diff --git a/components/common/tlv/component.cmake b/components/common/tlv/component.cmake new file mode 100644 index 000000000..6fafa16c7 --- /dev/null +++ b/components/common/tlv/component.cmake @@ -0,0 +1,13 @@ +#------------------------------------------------------------------------------- +# Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +#------------------------------------------------------------------------------- +if (NOT DEFINED TGT) + message(FATAL_ERROR "mandatory parameter TGT is not defined.") +endif() + +target_sources(${TGT} PRIVATE + "${CMAKE_CURRENT_LIST_DIR}/tlv.c" + ) diff --git a/components/common/tlv/test/component.cmake b/components/common/tlv/test/component.cmake new file mode 100644 index 000000000..4394d30ff --- /dev/null +++ b/components/common/tlv/test/component.cmake @@ -0,0 +1,13 @@ +#------------------------------------------------------------------------------- +# Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +#------------------------------------------------------------------------------- +if (NOT DEFINED TGT) + message(FATAL_ERROR "mandatory parameter TGT is not defined.") +endif() + +target_sources(${TGT} PRIVATE + "${CMAKE_CURRENT_LIST_DIR}/tlv_tests.cpp" + ) diff --git a/components/common/tlv/test/tlv_tests.cpp b/components/common/tlv/test/tlv_tests.cpp new file mode 100644 index 000000000..661a81024 --- /dev/null +++ b/components/common/tlv/test/tlv_tests.cpp @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +TEST_GROUP(TlvTests) +{ + +}; + +TEST(TlvTests, decodeGoodRecords) +{ + struct tlv_const_iterator iter; + struct tlv_record decoded_record; + + /* Case 1: Valid single zero length record */ + const uint8_t case_1[] = { + 0x77, 0x31, 0x00, 0x00 + }; + + tlv_const_iterator_begin(&iter, case_1, sizeof(case_1)); + CHECK_TRUE(tlv_decode(&iter, &decoded_record)); + UNSIGNED_LONGS_EQUAL(0x7731, decoded_record.tag); + UNSIGNED_LONGS_EQUAL(0, decoded_record.length); + CHECK_FALSE(tlv_decode(&iter, &decoded_record)); + + /* Case 2: Two valid records */ + const uint8_t case_2[] = { + 0x01, 0x10, 0x00, 0x01, 0x50, + 0x02, 0x11, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04 + }; + + tlv_const_iterator_begin(&iter, case_2, sizeof(case_2)); + CHECK_TRUE(tlv_decode(&iter, &decoded_record)); + UNSIGNED_LONGS_EQUAL(0x0110, decoded_record.tag); + UNSIGNED_LONGS_EQUAL(1, decoded_record.length); + UNSIGNED_LONGS_EQUAL(0x50, decoded_record.value[0]); + CHECK_TRUE(tlv_decode(&iter, &decoded_record)); + UNSIGNED_LONGS_EQUAL(0x0211, decoded_record.tag); + UNSIGNED_LONGS_EQUAL(4, decoded_record.length); + UNSIGNED_LONGS_EQUAL(0x01, decoded_record.value[0]); + UNSIGNED_LONGS_EQUAL(0x02, decoded_record.value[1]); + UNSIGNED_LONGS_EQUAL(0x03, decoded_record.value[2]); + UNSIGNED_LONGS_EQUAL(0x04, decoded_record.value[3]); + CHECK_FALSE(tlv_decode(&iter, &decoded_record)); +} + +TEST(TlvTests, findAndDecode) +{ + struct tlv_const_iterator iter; + struct tlv_record decoded_record; + + /* + * Checks use of the tlv_find_decode method to extract known records + * from a sequence of records, encoded in ascending tag order, that includes + * ones that the receiver isn't interested in. + */ + const uint8_t encoded_records[] = { + 0x00, 0x01, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x03, 0x88, 0x88, 0x88, + 0x00, 0x07, 0x00, 0x02, 0x77, 0x77, + 0x00, 0x09, 0x00, 0x01, 0x77 + }; + + tlv_const_iterator_begin(&iter, encoded_records, sizeof(encoded_records)); + CHECK_TRUE(tlv_find_decode(&iter, 0x0001, &decoded_record)); + UNSIGNED_LONGS_EQUAL(0, decoded_record.length); + CHECK_TRUE(tlv_find_decode(&iter, 0x0007, &decoded_record)); + UNSIGNED_LONGS_EQUAL(2, decoded_record.length); + CHECK_TRUE(tlv_find_decode(&iter, 0x0009, &decoded_record)); + UNSIGNED_LONGS_EQUAL(1, decoded_record.length); +} + +TEST(TlvTests, decodeBadRecords) +{ + struct tlv_const_iterator iter; + struct tlv_record decoded_record; + + /* Case 1: Too short to accommodate a valid header */ + const uint8_t case_1[] = { + 0x77, 0x31, 0x00 + }; + + tlv_const_iterator_begin(&iter, case_1, sizeof(case_1)); + CHECK_FALSE(tlv_decode(&iter, &decoded_record)); + + /* Case 1: A complete record followed by a truncated one */ + const uint8_t case_2[] = { + 0x77, 0x31, 0x00, 0x00, + 0x03, 0x21, 0x00, 0x03, 0xaa + }; + + tlv_const_iterator_begin(&iter, case_2, sizeof(case_2)); + CHECK_TRUE(tlv_decode(&iter, &decoded_record)); + CHECK_FALSE(tlv_decode(&iter, &decoded_record)); +} + +TEST(TlvTests, encodeRecords) +{ + struct tlv_iterator iter; + struct tlv_record record_to_encode; + size_t required_space; + + /* Case 1: Encode zero length record */ + const uint8_t case_1_expected[] = { + 0x66, 0x77, 0x00, 0x00 + }; + record_to_encode.tag = 0x6677; + record_to_encode.length = 0; + record_to_encode.value = NULL; + required_space = tlv_required_space(record_to_encode.length); + uint8_t case_1_actual[required_space]; + tlv_iterator_begin(&iter, case_1_actual, required_space); + CHECK_TRUE(tlv_encode(&iter, &record_to_encode)); + MEMCMP_EQUAL(case_1_expected, case_1_actual, required_space); + + /* Case 2: Encode two records */ + const uint8_t case_2_expected[] = { + 0xa8, 0xa9, 0x00, 0x01, 0x88, + 0xa8, 0xaa, 0x00, 0x02, 0x01, 0x02 + }; + + required_space = tlv_required_space(1) + tlv_required_space(2); + uint8_t case_2_actual[required_space]; + tlv_iterator_begin(&iter, case_2_actual, required_space); + + record_to_encode.tag = 0xa8a9; + record_to_encode.length = 1; + record_to_encode.value = &case_2_expected[4]; + CHECK_TRUE(tlv_encode(&iter, &record_to_encode)); + + record_to_encode.tag = 0xa8aa; + record_to_encode.length = 2; + record_to_encode.value = &case_2_expected[9]; + CHECK_TRUE(tlv_encode(&iter, &record_to_encode)); + + MEMCMP_EQUAL(case_2_expected, case_2_actual, required_space); + + /* Check that you can't encode beyond the limit of the buffer */ + CHECK_FALSE(tlv_encode(&iter, &record_to_encode)); +} + +TEST(TlvTests, encodeInsufficientSpace) +{ + struct tlv_iterator iter; + struct tlv_record record_to_encode; + size_t required_space; + + /* Case 1: Encode record into buffer that isn't big enough */ + const uint8_t case_1_expected[] = { + 0x66, 0x77, 0x00, 0x03, 0x01, 0x02, 0x03 + }; + record_to_encode.tag = 0x6677; + record_to_encode.length = 3; + record_to_encode.value = &case_1_expected[4]; + required_space = tlv_required_space(record_to_encode.length) - 1; + uint8_t case_1_actual[required_space]; + tlv_iterator_begin(&iter, case_1_actual, required_space); + CHECK_FALSE(tlv_encode(&iter, &record_to_encode)); +} + +TEST(TlvTests, encodeWrongOrder) +{ + struct tlv_iterator iter; + struct tlv_record record_to_encode; + size_t required_space; + + /* Check defence against encoding successive records + * out of tag value order. Encoding rules require + * records to be in ascending tag value order. + */ + const uint8_t record_value[] = { + 0x11, 0x22, 0x33, 0x44 + }; + + /* Attemps to encode 4 records, the first 3 obey order + * rule, the last one doesn't + */ + required_space = tlv_required_space(sizeof(record_value)) * 4; + uint8_t encode_buffer[required_space]; + tlv_iterator_begin(&iter, encode_buffer, required_space); + + record_to_encode.tag = 1; + record_to_encode.length = sizeof(record_value); + record_to_encode.value = record_value; + CHECK_TRUE(tlv_encode(&iter, &record_to_encode)); + + record_to_encode.tag = 2; + record_to_encode.length = sizeof(record_value); + record_to_encode.value = record_value; + CHECK_TRUE(tlv_encode(&iter, &record_to_encode)); + + record_to_encode.tag = 2; + record_to_encode.length = sizeof(record_value); + record_to_encode.value = record_value; + CHECK_TRUE(tlv_encode(&iter, &record_to_encode)); + + record_to_encode.tag = 1; + record_to_encode.length = sizeof(record_value); + record_to_encode.value = record_value; + CHECK_FALSE(tlv_encode(&iter, &record_to_encode)); +} diff --git a/components/common/tlv/tlv.c b/components/common/tlv/tlv.c new file mode 100644 index 000000000..13088321c --- /dev/null +++ b/components/common/tlv/tlv.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "tlv.h" +#include + +size_t tlv_required_space(size_t length) +{ + return TLV_HDR_LEN + length; +} + +void tlv_iterator_begin(struct tlv_iterator *iter, uint8_t *buf, size_t bufsize) +{ + iter->pos = buf; + iter->limit = &buf[bufsize]; + + /* Defend against overflow */ + if (iter->limit < buf) iter->limit = buf; + + /* Used to enforce ascending tag order when encoding */ + iter->prev_tag = 0; +} + +void tlv_const_iterator_begin(struct tlv_const_iterator *iter, const uint8_t *buf, size_t bufsize) +{ + iter->pos = buf; + iter->limit = &buf[bufsize]; + + /* Defend against overflow */ + if (iter->limit < buf) iter->limit = buf; +} + +bool tlv_encode(struct tlv_iterator *iter, const struct tlv_record *input) +{ + bool success = false; + size_t required_space = tlv_required_space(input->length); + size_t available_space = iter->limit - iter->pos; + + if (required_space <= available_space && input->tag >= iter->prev_tag) { + + iter->pos[TLV_TAG_OFFSET + 0] = (uint8_t)(input->tag >> 8); + iter->pos[TLV_TAG_OFFSET + 1] = (uint8_t)(input->tag); + iter->pos[TLV_LENGTH_OFFSET + 0] = (uint8_t)(input->length >> 8); + iter->pos[TLV_LENGTH_OFFSET + 1] = (uint8_t)(input->length); + + memcpy(&iter->pos[TLV_VALUE_OFFSET], input->value, input->length); + + iter->pos += required_space; + iter->prev_tag = input->tag; + success = true; + } + + return success; +} + +bool tlv_decode(struct tlv_const_iterator *iter, struct tlv_record *output) +{ + bool success = false; + size_t max_space = iter->limit - iter->pos; + + if (max_space >= TLV_HDR_LEN) { + + size_t record_len; + output->tag = (iter->pos[TLV_TAG_OFFSET + 0] << 8) | iter->pos[TLV_TAG_OFFSET + 1]; + output->length = (iter->pos[TLV_LENGTH_OFFSET + 0] << 8) | iter->pos[TLV_LENGTH_OFFSET + 1]; + output->value = &iter->pos[TLV_VALUE_OFFSET]; + + record_len = output->length + TLV_HDR_LEN; + + if (record_len <= max_space) { + + iter->pos += record_len; + success = true; + } + } + + return success; +} + +bool tlv_find_decode(struct tlv_const_iterator *iter, uint16_t tag, struct tlv_record *output) +{ + while (tlv_decode(iter, output)) { + + if (output->tag == tag) { + /* Found a record */ + return true; + } + else if (output->tag > tag) { + /* Iterated beyond the expected parameter */ + return false; + } + } + + /* Reached the end of the buffer without finding a record with the requested tag */ + return false; +} diff --git a/components/common/tlv/tlv.h b/components/common/tlv/tlv.h new file mode 100644 index 000000000..64233a380 --- /dev/null +++ b/components/common/tlv/tlv.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TLV_H +#define TLV_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * TLV provides a general purpose serialization for variable length + * objects, identified by a tag. A serialized TLV record has the following + * structure: + * | Tag | Length | Value | + * | (16-bits) | (16-bits) | (Length bytes) | + * + * No assumptions are made about the alignment of the start of a serialized record. + * Tag and Length fields are encoded in Big Endian byte order. + */ +#define TLV_TAG_WIDTH (2) +#define TLV_LENGTH_WIDTH (2) +#define TLV_HDR_LEN (TLV_TAG_WIDTH + TLV_LENGTH_WIDTH) +#define TLV_TAG_OFFSET (0) +#define TLV_LENGTH_OFFSET TLV_TAG_WIDTH +#define TLV_VALUE_OFFSET TLV_HDR_LEN + +/* + * TLV record structure provides access to a serialized record. + */ +struct tlv_record +{ + uint16_t tag; + uint16_t length; + const uint8_t *value; +}; + +/* + * Iterator state for interating over serialized tlv records when encoding. + */ +struct tlv_iterator +{ + uint8_t *pos; + uint8_t *limit; + uint16_t prev_tag; +}; + +/* + * Iterator state for interating over serialized tlv records when decoding. + */ +struct tlv_const_iterator +{ + const uint8_t *pos; + const uint8_t *limit; +}; + +/* + * Return the space required in bytes for a serialized record with the + * specified value length. + */ +size_t tlv_required_space(size_t length); + +/* + * Initializes a TLV iterator to the start of a buffer. Used when writing + * records to a buffer when encoding. + */ +void tlv_iterator_begin(struct tlv_iterator *iter, uint8_t *buf, size_t bufsize); + +/* + * Initializes a TLV const iterator to the start of a buffer. Used when reading + * records from a buffer when decoding. + */ +void tlv_const_iterator_begin(struct tlv_const_iterator *iter, const uint8_t *buf, size_t bufsize); + +/* + * Encode a serialized record and advance the iterator, ready to encode the next + * record. Returns true if successful, false if insufficient room. + */ +bool tlv_encode(struct tlv_iterator *iter, const struct tlv_record *input); + +/* + * Decode a serialized record and advance the iterator, ready to decode the next + * record (if there is one). Returns true if successful, false there is no serialized record + * or an incomplete one. + */ +bool tlv_decode(struct tlv_const_iterator *iter, struct tlv_record *output); + +/* + * Advances the iterator until a record with the specified tag is found. If + * it's found, it's decoded and the iterator is advanced to the next position. + * This can be used when decoding an expected set of records, encoded in ascending + * tag order. Any unrecognised records are skipped over. This is the typical + * decoding pattern. + */ +bool tlv_find_decode(struct tlv_const_iterator *iter, uint16_t tag, struct tlv_record *output); + +#ifdef __cplusplus +} +#endif + +#endif /* TLV_H */ diff --git a/components/rpc/common/test/protocol/check_rpc_status_alignment.cpp b/components/rpc/common/test/protocol/check_rpc_status_alignment.cpp new file mode 100644 index 000000000..81cf64e3f --- /dev/null +++ b/components/rpc/common/test/protocol/check_rpc_status_alignment.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include + +/* + * Check alignment of RPC status protocol values for different protocol + * definition schemes. + */ +TEST_GROUP(RpcStatusProtocolChecks) { + +}; + +TEST(RpcStatusProtocolChecks, checkProtobufRpcStatusCodes) { + + /* + * Check alignment between packed-c and protobuf rpc status codes + */ + LONGS_EQUAL(TS_RPC_CALL_ACCEPTED, ts_rpc_Status_CALL_ACCEPTED); + LONGS_EQUAL(TS_RPC_ERROR_EP_DOES_NOT_EXIT, ts_rpc_Status_ERROR_EP_DOES_NOT_EXIT); + LONGS_EQUAL(TS_RPC_ERROR_INVALID_OPCODE, ts_rpc_Status_ERROR_INVALID_OPCODE); + LONGS_EQUAL(TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED, ts_rpc_Status_ERROR_SERIALIZATION_NOT_SUPPORTED); + LONGS_EQUAL(TS_RPC_ERROR_INVALID_REQ_BODY, ts_rpc_Status_ERROR_INVALID_REQ_BODY); + LONGS_EQUAL(TS_RPC_ERROR_INVALID_RESP_BODY, ts_rpc_Status_ERROR_INVALID_RESP_BODY); + LONGS_EQUAL(TS_RPC_ERROR_RESOURCE_FAILURE, ts_rpc_Status_ERROR_RESOURCE_FAILURE); + LONGS_EQUAL(TS_RPC_ERROR_NOT_READY, ts_rpc_Status_ERROR_NOT_READY); + LONGS_EQUAL(TS_RPC_ERROR_INVALID_TRANSACTION, ts_rpc_Status_ERROR_INVALID_TRANSACTION); + LONGS_EQUAL(TS_RPC_ERROR_INTERNAL, ts_rpc_Status_ERROR_INTERNAL); + LONGS_EQUAL(TS_RPC_ERROR_INVALID_PARAMETER, ts_rpc_Status_ERROR_INVALID_PARAMETER); +} \ No newline at end of file diff --git a/components/rpc/common/test/protocol/component.cmake b/components/rpc/common/test/protocol/component.cmake new file mode 100644 index 000000000..8c7dabe4c --- /dev/null +++ b/components/rpc/common/test/protocol/component.cmake @@ -0,0 +1,14 @@ +#------------------------------------------------------------------------------- +# Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +#------------------------------------------------------------------------------- +if (NOT DEFINED TGT) + message(FATAL_ERROR "mandatory parameter TGT is not defined.") +endif() + +target_sources(${TGT} PRIVATE + "${CMAKE_CURRENT_LIST_DIR}/check_rpc_status_alignment.cpp" + ) + diff --git a/components/service/crypto/client/cpp/crypto_client.cpp b/components/service/crypto/client/cpp/crypto_client.cpp index b27a58544..602a6b5bb 100644 --- a/components/service/crypto/client/cpp/crypto_client.cpp +++ b/components/service/crypto/client/cpp/crypto_client.cpp @@ -4,27 +4,8 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#include -#include #include "crypto_client.h" #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include crypto_client::crypto_client() : m_caller(NULL), @@ -54,758 +35,3 @@ int crypto_client::err_rpc_status() const { return m_err_rpc_status; } - -psa_status_t crypto_client::generate_key(const psa_key_attributes_t *attributes, psa_key_handle_t *handle) -{ - size_t req_len; - psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; - ts_crypto_GenerateKeyIn req_msg = ts_crypto_GenerateKeyIn_init_default; - - translate_key_attributes(req_msg.attributes, *attributes); - req_msg.has_attributes = true; - - if (pb_get_encoded_size(&req_len, ts_crypto_GenerateKeyIn_fields, &req_msg)) { - - rpc_call_handle call_handle; - uint8_t *req_buf; - - call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); - - if (call_handle) { - - uint8_t *resp_buf; - size_t resp_len; - int opstatus; - - pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len); - pb_encode(&ostream, ts_crypto_GenerateKeyIn_fields, &req_msg); - - m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, - ts_crypto_Opcode_GENERATE_KEY, &opstatus, &resp_buf, &resp_len); - - if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) { - - psa_status = opstatus; - - if (psa_status == PSA_SUCCESS) { - - ts_crypto_GenerateKeyOut resp_msg = ts_crypto_GenerateKeyOut_init_default; - pb_istream_t istream = pb_istream_from_buffer(resp_buf, resp_len); - - if (pb_decode(&istream, ts_crypto_GenerateKeyOut_fields, &resp_msg)) { - - *handle = resp_msg.handle; - } - else { - /* Failed to decode response message */ - psa_status = PSA_ERROR_GENERIC_ERROR; - } - } - } - - rpc_caller_end(m_caller, call_handle); - } - } - - return psa_status; -} - -psa_status_t crypto_client::destroy_key(psa_key_handle_t handle) -{ - size_t req_len; - psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; - ts_crypto_DestroyKeyIn req_msg = ts_crypto_DestroyKeyIn_init_default; - - req_msg.handle = handle; - - if (pb_get_encoded_size(&req_len, ts_crypto_DestroyKeyIn_fields, &req_msg)) { - - rpc_call_handle call_handle; - uint8_t *req_buf; - - call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); - - if (call_handle) { - - uint8_t *resp_buf; - size_t resp_len; - int opstatus; - - pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len); - pb_encode(&ostream, ts_crypto_DestroyKeyIn_fields, &req_msg); - - m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, - ts_crypto_Opcode_DESTROY_KEY, &opstatus, &resp_buf, &resp_len); - - if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) psa_status = opstatus; - - rpc_caller_end(m_caller, call_handle); - } - } - - return psa_status; -} - -psa_status_t crypto_client::open_key(psa_key_id_t id, psa_key_handle_t *handle) -{ - size_t req_len; - psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; - ts_crypto_OpenKeyIn req_msg = ts_crypto_OpenKeyIn_init_default; - req_msg.id = id; - - if (pb_get_encoded_size(&req_len, ts_crypto_OpenKeyIn_fields, &req_msg)) { - - rpc_call_handle call_handle; - uint8_t *req_buf; - - call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); - - if (call_handle) { - - uint8_t *resp_buf; - size_t resp_len; - int opstatus; - - pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len); - pb_encode(&ostream, ts_crypto_OpenKeyIn_fields, &req_msg); - - m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, - ts_crypto_Opcode_OPEN_KEY, &opstatus, &resp_buf, &resp_len); - - if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) { - - psa_status = opstatus; - - if (psa_status == PSA_SUCCESS) { - - ts_crypto_OpenKeyOut resp_msg = ts_crypto_OpenKeyOut_init_default; - pb_istream_t istream = pb_istream_from_buffer(resp_buf, resp_len); - - if (pb_decode(&istream, ts_crypto_OpenKeyOut_fields, &resp_msg)) { - - *handle = resp_msg.handle; - } - else { - /* Failed to decode response message */ - psa_status = PSA_ERROR_GENERIC_ERROR; - } - } - } - - rpc_caller_end(m_caller, call_handle); - } - } - - return psa_status; -} - -psa_status_t crypto_client::close_key(psa_key_handle_t handle) -{ - size_t req_len; - psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; - ts_crypto_CloseKeyIn req_msg = ts_crypto_CloseKeyIn_init_default; - - req_msg.handle = handle; - - if (pb_get_encoded_size(&req_len, ts_crypto_CloseKeyIn_fields, &req_msg)) { - - rpc_call_handle call_handle; - uint8_t *req_buf; - - call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); - - if (call_handle) { - - uint8_t *resp_buf; - size_t resp_len; - int opstatus; - - pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len); - pb_encode(&ostream, ts_crypto_CloseKeyIn_fields, &req_msg); - - m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, - ts_crypto_Opcode_CLOSE_KEY, &opstatus, &resp_buf, &resp_len); - - if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) psa_status = opstatus; - - rpc_caller_end(m_caller, call_handle); - } - } - - return psa_status; -} - -psa_status_t crypto_client::import_key(const psa_key_attributes_t *attributes, - const uint8_t *data, size_t data_length, psa_key_handle_t *handle) -{ - size_t req_len; - psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; - ts_crypto_ImportKeyIn req_msg = ts_crypto_ImportKeyIn_init_default; - pb_bytes_array_t *key_byte_array = pb_malloc_byte_array_containing_bytes(data, data_length); - - translate_key_attributes(req_msg.attributes, *attributes); - req_msg.has_attributes = true; - req_msg.data = pb_out_byte_array(key_byte_array); - - if (pb_get_encoded_size(&req_len, ts_crypto_ImportKeyIn_fields, &req_msg)) { - - rpc_call_handle call_handle; - uint8_t *req_buf; - - call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); - - if (call_handle) { - - uint8_t *resp_buf; - size_t resp_len; - int opstatus; - - pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len); - pb_encode(&ostream, ts_crypto_ImportKeyIn_fields, &req_msg); - - m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, - ts_crypto_Opcode_IMPORT_KEY, &opstatus, &resp_buf, &resp_len); - - if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) { - - psa_status = opstatus; - - if (psa_status == PSA_SUCCESS) { - - ts_crypto_ImportKeyOut resp_msg = ts_crypto_ImportKeyOut_init_default; - pb_istream_t istream = pb_istream_from_buffer(resp_buf, resp_len); - - if (pb_decode(&istream, ts_crypto_ImportKeyOut_fields, &resp_msg)) { - - *handle = resp_msg.handle; - } - else { - /* Failed to decode response message */ - psa_status = PSA_ERROR_GENERIC_ERROR; - } - } - } - - rpc_caller_end(m_caller, call_handle); - } - } - - ::free(key_byte_array); - - return psa_status; -} - -psa_status_t crypto_client::export_key(psa_key_handle_t handle, - uint8_t *data, size_t data_size, - size_t *data_length) -{ - size_t req_len; - psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; - ts_crypto_ExportKeyIn req_msg = ts_crypto_ExportKeyIn_init_default; - req_msg.handle = handle; - - *data_length = 0; /* For failure case */ - - if (pb_get_encoded_size(&req_len, ts_crypto_ExportKeyIn_fields, &req_msg)) { - - rpc_call_handle call_handle; - uint8_t *req_buf; - - call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); - - if (call_handle) { - - uint8_t *resp_buf; - size_t resp_len; - int opstatus; - - pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len); - pb_encode(&ostream, ts_crypto_ExportKeyIn_fields, &req_msg); - - m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, - ts_crypto_Opcode_EXPORT_KEY, &opstatus, &resp_buf, &resp_len); - - if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) { - - psa_status = opstatus; - - if (psa_status == PSA_SUCCESS) { - - ts_crypto_ExportKeyOut resp_msg = ts_crypto_ExportKeyOut_init_default; - pb_bytes_array_t *exported_key = pb_malloc_byte_array(resp_len); - - if (exported_key) { - - resp_msg.data = pb_in_byte_array(exported_key); - pb_istream_t istream = pb_istream_from_buffer(resp_buf, resp_len); - - if (pb_decode(&istream, ts_crypto_ExportKeyOut_fields, &resp_msg)) { - - if (exported_key->size <= data_size) { - - memcpy(data, exported_key->bytes, exported_key->size); - *data_length = exported_key->size; - } - else { - /* Provided buffer is too small */ - psa_status = PSA_ERROR_BUFFER_TOO_SMALL; - } - } - else { - /* Failed to decode response message */ - psa_status = PSA_ERROR_GENERIC_ERROR; - } - - ::free(exported_key); - } - else { - /* Failed to allocate buffer for exported key */ - psa_status = PSA_ERROR_INSUFFICIENT_MEMORY; - } - } - } - - rpc_caller_end(m_caller, call_handle); - } - } - - return psa_status; -} - -psa_status_t crypto_client::export_public_key(psa_key_handle_t handle, - uint8_t *data, size_t data_size, size_t *data_length) -{ - size_t req_len; - psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; - ts_crypto_ExportPublicKeyIn req_msg = ts_crypto_ExportPublicKeyIn_init_default; - req_msg.handle = handle; - - *data_length = 0; /* For failure case */ - - if (pb_get_encoded_size(&req_len, ts_crypto_ExportPublicKeyIn_fields, &req_msg)) { - - rpc_call_handle call_handle; - uint8_t *req_buf; - - call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); - - if (call_handle) { - - uint8_t *resp_buf; - size_t resp_len; - int opstatus; - - pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len); - pb_encode(&ostream, ts_crypto_ExportPublicKeyIn_fields, &req_msg); - - m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, - ts_crypto_Opcode_EXPORT_PUBLIC_KEY, &opstatus, &resp_buf, &resp_len); - - if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) { - - psa_status = opstatus; - - if (psa_status == PSA_SUCCESS) { - - ts_crypto_ExportPublicKeyOut resp_msg = ts_crypto_ExportPublicKeyOut_init_default; - pb_bytes_array_t *exported_key = pb_malloc_byte_array(resp_len); - - if (exported_key) { - - resp_msg.data = pb_in_byte_array(exported_key); - pb_istream_t istream = pb_istream_from_buffer(resp_buf, resp_len); - - if (pb_decode(&istream, ts_crypto_ExportPublicKeyOut_fields, &resp_msg)) { - - if (exported_key->size <= data_size) { - - memcpy(data, exported_key->bytes, exported_key->size); - *data_length = exported_key->size; - } - else { - /* Provided buffer is too small */ - psa_status = PSA_ERROR_BUFFER_TOO_SMALL; - } - } - else { - /* Failed to decode response message */ - psa_status = PSA_ERROR_GENERIC_ERROR; - } - - ::free(exported_key); - } - else { - /* Failed to alloocate buffer for exported key */ - psa_status = PSA_ERROR_INSUFFICIENT_MEMORY; - } - } - } - - rpc_caller_end(m_caller, call_handle); - } - } - - return psa_status; -} - -psa_status_t crypto_client::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) -{ - size_t req_len; - pb_bytes_array_t *hash_byte_array = pb_malloc_byte_array_containing_bytes(hash, hash_length); - psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; - ts_crypto_SignHashIn req_msg = ts_crypto_SignHashIn_init_default; - - *signature_length = 0; /* For failure case */ - - req_msg.handle = handle; - req_msg.alg = alg; - req_msg.hash = pb_out_byte_array(hash_byte_array); - - if (pb_get_encoded_size(&req_len, ts_crypto_SignHashIn_fields, &req_msg)) { - - rpc_call_handle call_handle; - uint8_t *req_buf; - - call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); - - if (call_handle) { - - uint8_t *resp_buf; - size_t resp_len; - int opstatus; - - pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len); - pb_encode(&ostream, ts_crypto_SignHashIn_fields, &req_msg); - - m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, - ts_crypto_Opcode_SIGN_HASH, &opstatus, &resp_buf, &resp_len); - - if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) { - - psa_status = opstatus; - - if (psa_status == PSA_SUCCESS) { - - pb_bytes_array_t *sig_byte_array = pb_malloc_byte_array(PSA_SIGNATURE_MAX_SIZE); - ts_crypto_SignHashOut resp_msg = ts_crypto_SignHashOut_init_default; - resp_msg.signature = pb_in_byte_array(sig_byte_array); - - pb_istream_t istream = pb_istream_from_buffer(resp_buf, resp_len); - - if (pb_decode(&istream, ts_crypto_SignHashOut_fields, &resp_msg)) { - - if (sig_byte_array->size <= signature_size) { - - memcpy(signature, sig_byte_array->bytes, sig_byte_array->size); - *signature_length = sig_byte_array->size; - } - else { - /* Provided buffer is too small */ - psa_status = PSA_ERROR_BUFFER_TOO_SMALL; - } - } - else { - /* Failed to decode response message */ - psa_status = PSA_ERROR_GENERIC_ERROR; - } - - ::free(sig_byte_array); - } - } - - rpc_caller_end(m_caller, call_handle); - } - } - - ::free(hash_byte_array); - - return psa_status; -} - - -psa_status_t crypto_client::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) -{ - size_t req_len; - pb_bytes_array_t *hash_byte_array = pb_malloc_byte_array_containing_bytes(hash, hash_length); - pb_bytes_array_t *sig_byte_array = pb_malloc_byte_array_containing_bytes(signature, signature_length); - psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; - ts_crypto_VerifyHashIn req_msg = ts_crypto_VerifyHashIn_init_default; - - req_msg.handle = handle; - req_msg.alg = alg; - req_msg.hash = pb_out_byte_array(hash_byte_array); - req_msg.signature = pb_out_byte_array(sig_byte_array); - - if (pb_get_encoded_size(&req_len, ts_crypto_VerifyHashIn_fields, &req_msg)) { - - rpc_call_handle call_handle; - uint8_t *req_buf; - - call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); - - if (call_handle) { - - uint8_t *resp_buf; - size_t resp_len; - int opstatus; - - pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len); - pb_encode(&ostream, ts_crypto_VerifyHashIn_fields, &req_msg); - - m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, - ts_crypto_Opcode_VERIFY_HASH, &opstatus, &resp_buf, &resp_len); - - if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) psa_status = opstatus; - - rpc_caller_end(m_caller, call_handle); - } - } - - ::free(hash_byte_array); - ::free(sig_byte_array); - - return psa_status; -} - -psa_status_t crypto_client::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) -{ - size_t req_len; - pb_bytes_array_t *plaintext_byte_array = pb_malloc_byte_array_containing_bytes(input, input_length); - pb_bytes_array_t *salt_byte_array = pb_malloc_byte_array_containing_bytes(salt, salt_length); - psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; - ts_crypto_AsymmetricEncryptIn req_msg = ts_crypto_AsymmetricEncryptIn_init_default; - - *output_length = 0; /* For failure case */ - - req_msg.handle = handle; - req_msg.alg = alg; - req_msg.plaintext = pb_out_byte_array(plaintext_byte_array); - req_msg.salt = pb_out_byte_array(salt_byte_array); - - if (pb_get_encoded_size(&req_len, ts_crypto_AsymmetricEncryptIn_fields, &req_msg)) { - - rpc_call_handle call_handle; - uint8_t *req_buf; - - call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); - - if (call_handle) { - - uint8_t *resp_buf; - size_t resp_len; - int opstatus = PSA_ERROR_GENERIC_ERROR; - - pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len); - pb_encode(&ostream, ts_crypto_AsymmetricEncryptIn_fields, &req_msg); - - m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, - ts_crypto_Opcode_ASYMMETRIC_ENCRYPT, &opstatus, &resp_buf, &resp_len); - - if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) { - - psa_status = opstatus; - - if (psa_status == PSA_SUCCESS) { - - pb_bytes_array_t *ciphertext_byte_array = pb_malloc_byte_array(output_size); - ts_crypto_AsymmetricEncryptOut resp_msg = ts_crypto_AsymmetricEncryptOut_init_default; - resp_msg.ciphertext = pb_in_byte_array(ciphertext_byte_array); - - pb_istream_t istream = pb_istream_from_buffer(resp_buf, resp_len); - - if (pb_decode(&istream, ts_crypto_AsymmetricEncryptOut_fields, &resp_msg)) { - - if (ciphertext_byte_array->size <= output_size) { - - memcpy(output, ciphertext_byte_array->bytes, ciphertext_byte_array->size); - *output_length = ciphertext_byte_array->size; - } - else { - /* Provided buffer is too small */ - psa_status = PSA_ERROR_BUFFER_TOO_SMALL; - } - } - else { - /* Failed to decode response message */ - psa_status = PSA_ERROR_GENERIC_ERROR; - } - - ::free(ciphertext_byte_array); - } - } - - rpc_caller_end(m_caller, call_handle); - } - } - - ::free(plaintext_byte_array); - ::free(salt_byte_array); - - return psa_status; -} - -psa_status_t crypto_client::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) -{ - size_t req_len; - pb_bytes_array_t *ciphertext_byte_array = pb_malloc_byte_array_containing_bytes(input, input_length); - pb_bytes_array_t *salt_byte_array = pb_malloc_byte_array_containing_bytes(salt, salt_length); - psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; - ts_crypto_AsymmetricDecryptIn req_msg = ts_crypto_AsymmetricDecryptIn_init_default; - - *output_length = 0; /* For failure case */ - - req_msg.handle = handle; - req_msg.alg = alg; - req_msg.ciphertext = pb_out_byte_array(ciphertext_byte_array); - req_msg.salt = pb_out_byte_array(salt_byte_array); - - if (pb_get_encoded_size(&req_len, ts_crypto_AsymmetricDecryptIn_fields, &req_msg)) { - - rpc_call_handle call_handle; - uint8_t *req_buf; - - call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); - - if (call_handle) { - - uint8_t *resp_buf; - size_t resp_len; - int opstatus; - - pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len); - pb_encode(&ostream, ts_crypto_AsymmetricDecryptIn_fields, &req_msg); - - m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, - ts_crypto_Opcode_ASYMMETRIC_DECRYPT, &opstatus, &resp_buf, &resp_len); - - if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) { - - psa_status = opstatus; - - if (psa_status == PSA_SUCCESS) { - - pb_bytes_array_t *plaintext_byte_array = pb_malloc_byte_array(output_size); - ts_crypto_AsymmetricDecryptOut resp_msg = ts_crypto_AsymmetricDecryptOut_init_default; - resp_msg.plaintext = pb_in_byte_array(plaintext_byte_array); - - pb_istream_t istream = pb_istream_from_buffer(resp_buf, resp_len); - - if (pb_decode(&istream, ts_crypto_AsymmetricDecryptOut_fields, &resp_msg)) { - - if (plaintext_byte_array->size <= output_size) { - - memcpy(output, plaintext_byte_array->bytes, plaintext_byte_array->size); - *output_length = plaintext_byte_array->size; - } - else { - /* Provided buffer is too small */ - m_err_rpc_status = PSA_ERROR_BUFFER_TOO_SMALL; - } - } - else { - /* Failed to decode response message */ - m_err_rpc_status = PSA_ERROR_GENERIC_ERROR; - } - - ::free(plaintext_byte_array); - } - } - - rpc_caller_end(m_caller, call_handle); - } - } - - ::free(ciphertext_byte_array); - ::free(salt_byte_array); - - return psa_status; -} - -psa_status_t crypto_client::generate_random(uint8_t *output, size_t output_size) -{ - size_t req_len; - psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; - ts_crypto_GenerateRandomIn req_msg = ts_crypto_GenerateRandomIn_init_default; - - req_msg.size = output_size; - - if (pb_get_encoded_size(&req_len, ts_crypto_GenerateRandomIn_fields, &req_msg)) { - - rpc_call_handle call_handle; - uint8_t *req_buf; - - call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); - - if (call_handle) { - - uint8_t *resp_buf; - size_t resp_len; - int opstatus; - - pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len); - pb_encode(&ostream, ts_crypto_GenerateRandomIn_fields, &req_msg); - - m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, - ts_crypto_Opcode_GENERATE_RANDOM, &opstatus, &resp_buf, &resp_len); - - if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) { - - psa_status = opstatus; - - if (psa_status == PSA_SUCCESS) { - - pb_bytes_array_t *output_byte_array = pb_malloc_byte_array(output_size); - ts_crypto_GenerateRandomOut resp_msg = ts_crypto_GenerateRandomOut_init_default; - resp_msg.random_bytes = pb_in_byte_array(output_byte_array); - - pb_istream_t istream = pb_istream_from_buffer(resp_buf, resp_len); - - if (pb_decode(&istream, ts_crypto_GenerateRandomOut_fields, &resp_msg)) { - - if (output_byte_array->size == output_size) { - - memcpy(output, output_byte_array->bytes, output_byte_array->size); - } - else { - /* Mismatch between requested and generated length */ - psa_status = PSA_ERROR_GENERIC_ERROR; - } - } - else { - /* Failed to decode response message */ - psa_status = PSA_ERROR_GENERIC_ERROR; - } - - ::free(output_byte_array); - } - } - - rpc_caller_end(m_caller, call_handle); - } - } - - return psa_status; -} - -void crypto_client::translate_key_attributes(ts_crypto_KeyAttributes &proto_attributes, - const psa_key_attributes_t &psa_attributes) -{ - proto_attributes.type = psa_get_key_type(&psa_attributes); - proto_attributes.key_bits = psa_get_key_bits(&psa_attributes); - proto_attributes.lifetime = psa_get_key_lifetime(&psa_attributes); - proto_attributes.id = psa_get_key_id(&psa_attributes); - - proto_attributes.has_policy = true; - proto_attributes.policy.usage = psa_get_key_usage_flags(&psa_attributes); - proto_attributes.policy.alg = psa_get_key_algorithm(&psa_attributes); - } diff --git a/components/service/crypto/client/cpp/crypto_client.h b/components/service/crypto/client/cpp/crypto_client.h index 3d0366f3a..5f6f0e133 100644 --- a/components/service/crypto/client/cpp/crypto_client.h +++ b/components/service/crypto/client/cpp/crypto_client.h @@ -9,66 +9,61 @@ #include #include -#include - struct rpc_caller; -/** Provides a client interface for accessing an instance of the PSA Crypto service. - **/ +/* + * Provides a client interface for accessing an instance of the Crypto service + * using a C++ version of the PSA Crypto API. + */ class crypto_client { public: - crypto_client(struct rpc_caller *caller); virtual ~crypto_client(); int err_rpc_status() const; /* Key lifecycle methods */ - psa_status_t generate_key(const psa_key_attributes_t *attributes, psa_key_handle_t *handle); - psa_status_t destroy_key(psa_key_handle_t handle); - psa_status_t open_key(psa_key_id_t id, psa_key_handle_t *handle); - psa_status_t close_key(psa_key_handle_t handle); - psa_status_t import_key(const psa_key_attributes_t *attributes, - const uint8_t *data, size_t data_length, psa_key_handle_t *handle); + virtual psa_status_t generate_key(const psa_key_attributes_t *attributes, psa_key_handle_t *handle) = 0; + virtual psa_status_t destroy_key(psa_key_handle_t handle) = 0; + virtual psa_status_t open_key(psa_key_id_t id, psa_key_handle_t *handle) = 0; + virtual psa_status_t close_key(psa_key_handle_t handle) = 0; + virtual psa_status_t import_key(const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, psa_key_handle_t *handle) = 0; /* Key export methods */ - psa_status_t export_key(psa_key_handle_t handle, + virtual psa_status_t export_key(psa_key_handle_t handle, uint8_t *data, size_t data_size, - size_t *data_length); - psa_status_t export_public_key(psa_key_handle_t handle, - uint8_t *data, size_t data_size, size_t *data_length); + size_t *data_length) = 0; + virtual psa_status_t export_public_key(psa_key_handle_t handle, + uint8_t *data, size_t data_size, size_t *data_length) = 0; /* Sign/verify methods */ - psa_status_t sign_hash(psa_key_handle_t handle, psa_algorithm_t alg, + virtual psa_status_t 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_status_t verify_hash(psa_key_handle_t handle, psa_algorithm_t alg, + uint8_t *signature, size_t signature_size, size_t *signature_length) = 0; + virtual psa_status_t 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); + const uint8_t *signature, size_t signature_length) = 0; /* Asymmetric encrypt/decrypt */ - psa_status_t asymmetric_encrypt(psa_key_handle_t handle, psa_algorithm_t alg, + virtual psa_status_t 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_status_t asymmetric_decrypt(psa_key_handle_t handle, psa_algorithm_t alg, + uint8_t *output, size_t output_size, size_t *output_length) = 0; + virtual psa_status_t 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); + uint8_t *output, size_t output_size, size_t *output_length) = 0; /* Random number generation */ - psa_status_t generate_random(uint8_t *output, size_t output_size); + virtual psa_status_t generate_random(uint8_t *output, size_t output_size) = 0; protected: crypto_client(); + crypto_client(struct rpc_caller *caller); void set_caller(struct rpc_caller *caller); -private: - - void translate_key_attributes(ts_crypto_KeyAttributes &proto_attributes, - const psa_key_attributes_t &psa_attributes); - struct rpc_caller *m_caller; int m_err_rpc_status; }; diff --git a/components/service/crypto/client/cpp/packed-c/component.cmake b/components/service/crypto/client/cpp/packed-c/component.cmake new file mode 100644 index 000000000..7ad58abaf --- /dev/null +++ b/components/service/crypto/client/cpp/packed-c/component.cmake @@ -0,0 +1,14 @@ +#------------------------------------------------------------------------------- +# Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +#------------------------------------------------------------------------------- +if (NOT DEFINED TGT) + message(FATAL_ERROR "mandatory parameter TGT is not defined.") +endif() + +target_sources(${TGT} PRIVATE + "${CMAKE_CURRENT_LIST_DIR}/packedc_crypto_client.cpp" + ) + diff --git a/components/service/crypto/client/cpp/packed-c/packedc_crypto_client.cpp b/components/service/crypto/client/cpp/packed-c/packedc_crypto_client.cpp new file mode 100644 index 000000000..e0e85e01b --- /dev/null +++ b/components/service/crypto/client/cpp/packed-c/packedc_crypto_client.cpp @@ -0,0 +1,749 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include "packedc_crypto_client.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +packedc_crypto_client::packedc_crypto_client() : + crypto_client() +{ + +} + +packedc_crypto_client::packedc_crypto_client(struct rpc_caller *caller) : + crypto_client(caller) +{ + +} + +packedc_crypto_client::~packedc_crypto_client() +{ + +} + +psa_status_t packedc_crypto_client::generate_key(const psa_key_attributes_t *attributes, psa_key_handle_t *handle) +{ + psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; + struct ts_crypto_generate_key_in req_msg; + size_t req_len = sizeof(ts_crypto_generate_key_in); + + translate_key_attributes(req_msg.attributes, *attributes); + + rpc_call_handle call_handle; + uint8_t *req_buf; + + call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); + + if (call_handle) { + + uint8_t *resp_buf; + size_t resp_len; + int opstatus; + + memcpy(req_buf, &req_msg, req_len); + + m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, + TS_CRYPTO_OPCODE_GENERATE_KEY, &opstatus, &resp_buf, &resp_len); + + if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) { + + psa_status = opstatus; + + if (psa_status == PSA_SUCCESS) { + + if (resp_len >= sizeof(ts_crypto_generate_key_out)) { + + struct ts_crypto_generate_key_out resp_msg; + memcpy(&resp_msg, resp_buf, sizeof(ts_crypto_generate_key_out)); + *handle = resp_msg.handle; + } + else { + /* Failed to decode response message */ + psa_status = PSA_ERROR_GENERIC_ERROR; + } + } + } + + rpc_caller_end(m_caller, call_handle); + } + + return psa_status; +} + +psa_status_t packedc_crypto_client::destroy_key(psa_key_handle_t handle) +{ + psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; + struct ts_crypto_destroy_key_in req_msg; + size_t req_len = sizeof(ts_crypto_destroy_key_in); + + req_msg.handle = handle; + + rpc_call_handle call_handle; + uint8_t *req_buf; + + call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); + + if (call_handle) { + + uint8_t *resp_buf; + size_t resp_len; + int opstatus; + + memcpy(req_buf, &req_msg, req_len); + + m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, + TS_CRYPTO_OPCODE_DESTROY_KEY, &opstatus, &resp_buf, &resp_len); + + if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) psa_status = opstatus; + + rpc_caller_end(m_caller, call_handle); + } + + return psa_status; +} + +psa_status_t packedc_crypto_client::open_key(psa_key_id_t id, psa_key_handle_t *handle) +{ + psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; + struct ts_crypto_open_key_in req_msg; + size_t req_len = sizeof(ts_crypto_open_key_in); + + req_msg.id = id; + + rpc_call_handle call_handle; + uint8_t *req_buf; + + call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); + + if (call_handle) { + + uint8_t *resp_buf; + size_t resp_len; + int opstatus; + + memcpy(req_buf, &req_msg, req_len); + + m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, + TS_CRYPTO_OPCODE_OPEN_KEY, &opstatus, &resp_buf, &resp_len); + + if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) { + + psa_status = opstatus; + + if (psa_status == PSA_SUCCESS) { + + if (resp_len >= sizeof(ts_crypto_open_key_out)) { + + struct ts_crypto_open_key_out resp_msg; + memcpy(&resp_msg, resp_buf, sizeof(ts_crypto_open_key_out)); + *handle = resp_msg.handle; + } + else { + /* Failed to decode response message */ + psa_status = PSA_ERROR_GENERIC_ERROR; + } + } + } + + rpc_caller_end(m_caller, call_handle); + } + + return psa_status; +} + +psa_status_t packedc_crypto_client::close_key(psa_key_handle_t handle) +{ + psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; + struct ts_crypto_close_key_in req_msg; + size_t req_len = sizeof(ts_crypto_close_key_in); + + req_msg.handle = handle; + + rpc_call_handle call_handle; + uint8_t *req_buf; + + call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); + + if (call_handle) { + + uint8_t *resp_buf; + size_t resp_len; + int opstatus; + + memcpy(req_buf, &req_msg, req_len); + + m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, + TS_CRYPTO_OPCODE_CLOSE_KEY, &opstatus, &resp_buf, &resp_len); + + if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) psa_status = opstatus; + + rpc_caller_end(m_caller, call_handle); + } + + return psa_status; +} + +psa_status_t packedc_crypto_client::import_key(const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, psa_key_handle_t *handle) +{ + psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; + struct ts_crypto_import_key_in req_msg; + size_t req_fixed_len = sizeof(ts_crypto_import_key_in); + size_t req_len = req_fixed_len + tlv_required_space(data_length); + + translate_key_attributes(req_msg.attributes, *attributes); + + struct tlv_record key_record; + key_record.tag = TS_CRYPTO_IMPORT_KEY_IN_TAG_DATA; + key_record.length = data_length; + key_record.value = data; + + rpc_call_handle call_handle; + uint8_t *req_buf; + + call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); + + if (call_handle) { + + uint8_t *resp_buf; + size_t resp_len; + int opstatus; + struct tlv_iterator req_iter; + + memcpy(req_buf, &req_msg, req_fixed_len); + + tlv_iterator_begin(&req_iter, &req_buf[req_fixed_len], req_len - req_fixed_len); + tlv_encode(&req_iter, &key_record); + + m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, + TS_CRYPTO_OPCODE_IMPORT_KEY, &opstatus, &resp_buf, &resp_len); + + if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) { + + psa_status = opstatus; + + if (psa_status == PSA_SUCCESS) { + + if (resp_len >= sizeof(ts_crypto_open_key_out)) { + + struct ts_crypto_import_key_out resp_msg; + memcpy(&resp_msg, resp_buf, sizeof(ts_crypto_import_key_out)); + *handle = resp_msg.handle; + } + else { + /* Failed to decode response message */ + psa_status = PSA_ERROR_GENERIC_ERROR; + } + } + } + + rpc_caller_end(m_caller, call_handle); + } + + return psa_status; +} + +psa_status_t packedc_crypto_client::export_key(psa_key_handle_t handle, + uint8_t *data, size_t data_size, + size_t *data_length) +{ + psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; + struct ts_crypto_export_key_in req_msg; + size_t req_len = sizeof(ts_crypto_export_key_in); + + req_msg.handle = handle; + + *data_length = 0; /* For failure case */ + + rpc_call_handle call_handle; + uint8_t *req_buf; + + call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); + + if (call_handle) { + + uint8_t *resp_buf; + size_t resp_len; + int opstatus; + + memcpy(req_buf, &req_msg, req_len); + + m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, + TS_CRYPTO_OPCODE_EXPORT_KEY, &opstatus, &resp_buf, &resp_len); + + if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) { + + psa_status = opstatus; + + if (psa_status == PSA_SUCCESS) { + + struct tlv_const_iterator resp_iter; + struct tlv_record decoded_record; + tlv_const_iterator_begin(&resp_iter, resp_buf, resp_len); + + if (tlv_find_decode(&resp_iter, TS_CRYPTO_EXPORT_KEY_OUT_TAG_DATA, &decoded_record)) { + + if (decoded_record.length <= data_size) { + + memcpy(data, decoded_record.value, decoded_record.length); + *data_length = decoded_record.length; + } + else { + /* Provided buffer is too small */ + psa_status = PSA_ERROR_BUFFER_TOO_SMALL; + } + } + else { + /* Mandatory response parameter missing */ + psa_status = PSA_ERROR_GENERIC_ERROR; + } + } + } + + rpc_caller_end(m_caller, call_handle); + } + + return psa_status; +} + +psa_status_t packedc_crypto_client::export_public_key(psa_key_handle_t handle, + uint8_t *data, size_t data_size, size_t *data_length) +{ + psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; + struct ts_crypto_export_public_key_in req_msg; + size_t req_len = sizeof(ts_crypto_export_public_key_in); + + req_msg.handle = handle; + + *data_length = 0; /* For failure case */ + + rpc_call_handle call_handle; + uint8_t *req_buf; + + call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); + + if (call_handle) { + + uint8_t *resp_buf; + size_t resp_len; + int opstatus; + + memcpy(req_buf, &req_msg, req_len); + + m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, + TS_CRYPTO_OPCODE_EXPORT_PUBLIC_KEY, &opstatus, &resp_buf, &resp_len); + + if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) { + + psa_status = opstatus; + + if (psa_status == PSA_SUCCESS) { + + struct tlv_const_iterator resp_iter; + struct tlv_record decoded_record; + tlv_const_iterator_begin(&resp_iter, resp_buf, resp_len); + + if (tlv_find_decode(&resp_iter, TS_CRYPTO_EXPORT_PUBLIC_KEY_OUT_TAG_DATA, &decoded_record)) { + + if (decoded_record.length <= data_size) { + + memcpy(data, decoded_record.value, decoded_record.length); + *data_length = decoded_record.length; + } + else { + /* Provided buffer is too small */ + psa_status = PSA_ERROR_BUFFER_TOO_SMALL; + } + } + else { + /* Mandatory response parameter missing */ + psa_status = PSA_ERROR_GENERIC_ERROR; + } + } + } + + rpc_caller_end(m_caller, call_handle); + } + + return psa_status; +} + +psa_status_t packedc_crypto_client::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_status_t psa_status = PSA_ERROR_GENERIC_ERROR; + struct ts_crypto_sign_hash_in req_msg; + size_t req_fixed_len = sizeof(ts_crypto_sign_hash_in); + size_t req_len = req_fixed_len + tlv_required_space(hash_length); + + *signature_length = 0; /* For failure case */ + + req_msg.handle = handle; + req_msg.alg = alg; + + struct tlv_record hash_record; + hash_record.tag = TS_CRYPTO_SIGN_HASH_IN_TAG_HASH; + hash_record.length = hash_length; + hash_record.value = hash; + + rpc_call_handle call_handle; + uint8_t *req_buf; + + call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); + + if (call_handle) { + + uint8_t *resp_buf; + size_t resp_len; + int opstatus; + struct tlv_iterator req_iter; + + memcpy(req_buf, &req_msg, req_fixed_len); + + tlv_iterator_begin(&req_iter, &req_buf[req_fixed_len], req_len - req_fixed_len); + tlv_encode(&req_iter, &hash_record); + + m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, + TS_CRYPTO_OPCODE_SIGN_HASH, &opstatus, &resp_buf, &resp_len); + + if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) { + + psa_status = opstatus; + + if (psa_status == PSA_SUCCESS) { + + struct tlv_const_iterator resp_iter; + struct tlv_record decoded_record; + tlv_const_iterator_begin(&resp_iter, resp_buf, resp_len); + + if (tlv_find_decode(&resp_iter, TS_CRYPTO_SIGN_HASH_OUT_TAG_SIGNATURE, &decoded_record)) { + + if (decoded_record.length <= signature_size) { + + memcpy(signature, decoded_record.value, decoded_record.length); + *signature_length = decoded_record.length; + } + else { + /* Provided buffer is too small */ + psa_status = PSA_ERROR_BUFFER_TOO_SMALL; + } + } + else { + /* Mandatory response parameter missing */ + psa_status = PSA_ERROR_GENERIC_ERROR; + } + } + } + + rpc_caller_end(m_caller, call_handle); + } + + return psa_status; +} + + +psa_status_t packedc_crypto_client::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_status_t psa_status = PSA_ERROR_GENERIC_ERROR; + struct ts_crypto_verify_hash_in req_msg; + size_t req_fixed_len = sizeof(ts_crypto_verify_hash_in); + size_t req_len = req_fixed_len + tlv_required_space(hash_length) + tlv_required_space(signature_length); + + req_msg.handle = handle; + req_msg.alg = alg; + + struct tlv_record hash_record; + hash_record.tag = TS_CRYPTO_VERIFY_HASH_IN_TAG_HASH; + hash_record.length = hash_length; + hash_record.value = hash; + + struct tlv_record sig_record; + sig_record.tag = TS_CRYPTO_VERIFY_HASH_IN_TAG_SIGNATURE; + sig_record.length = signature_length; + sig_record.value = signature; + + rpc_call_handle call_handle; + uint8_t *req_buf; + + call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); + + if (call_handle) { + + uint8_t *resp_buf; + size_t resp_len; + int opstatus; + struct tlv_iterator req_iter; + + memcpy(req_buf, &req_msg, req_fixed_len); + + tlv_iterator_begin(&req_iter, &req_buf[req_fixed_len], req_len - req_fixed_len); + tlv_encode(&req_iter, &hash_record); + tlv_encode(&req_iter, &sig_record); + + m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, + TS_CRYPTO_OPCODE_VERIFY_HASH, &opstatus, &resp_buf, &resp_len); + + if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) psa_status = opstatus; + + rpc_caller_end(m_caller, call_handle); + } + + return psa_status; +} + +psa_status_t packedc_crypto_client::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_status_t psa_status = PSA_ERROR_GENERIC_ERROR; + struct ts_crypto_asymmetric_encrypt_in req_msg; + size_t req_fixed_len = sizeof(ts_crypto_asymmetric_encrypt_in); + size_t req_len = req_fixed_len + tlv_required_space(input_length) + tlv_required_space(salt_length); + + *output_length = 0; /* For failure case */ + + req_msg.handle = handle; + req_msg.alg = alg; + + struct tlv_record plaintext_record; + plaintext_record.tag = TS_CRYPTO_ASYMMETRIC_ENCRYPT_IN_TAG_PLAINTEXT; + plaintext_record.length = input_length; + plaintext_record.value = input; + + struct tlv_record salt_record; + salt_record.tag = TS_CRYPTO_ASYMMETRIC_ENCRYPT_IN_TAG_SALT; + salt_record.length = salt_length; + salt_record.value = salt; + + rpc_call_handle call_handle; + uint8_t *req_buf; + + call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); + + if (call_handle) { + + uint8_t *resp_buf; + size_t resp_len; + int opstatus = PSA_ERROR_GENERIC_ERROR; + struct tlv_iterator req_iter; + + memcpy(req_buf, &req_msg, req_fixed_len); + + tlv_iterator_begin(&req_iter, &req_buf[req_fixed_len], req_len - req_fixed_len); + tlv_encode(&req_iter, &plaintext_record); + tlv_encode(&req_iter, &salt_record); + + m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, + TS_CRYPTO_OPCODE_ASYMMETRIC_ENCRYPT, &opstatus, &resp_buf, &resp_len); + + if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) { + + psa_status = opstatus; + + if (psa_status == PSA_SUCCESS) { + + struct tlv_const_iterator resp_iter; + struct tlv_record decoded_record; + tlv_const_iterator_begin(&resp_iter, resp_buf, resp_len); + + if (tlv_find_decode(&resp_iter, TS_CRYPTO_ASYMMETRIC_ENCRYPT_OUT_TAG_CIPHERTEXT, &decoded_record)) { + + if (decoded_record.length <= output_size) { + + memcpy(output, decoded_record.value, decoded_record.length); + *output_length = decoded_record.length; + } + else { + /* Provided buffer is too small */ + psa_status = PSA_ERROR_BUFFER_TOO_SMALL; + } + } + else { + /* Mandatory response parameter missing */ + psa_status = PSA_ERROR_GENERIC_ERROR; + } + } + } + + rpc_caller_end(m_caller, call_handle); + } + + return psa_status; +} + +psa_status_t packedc_crypto_client::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_status_t psa_status = PSA_ERROR_GENERIC_ERROR; + struct ts_crypto_asymmetric_decrypt_in req_msg; + size_t req_fixed_len = sizeof(ts_crypto_asymmetric_decrypt_in); + size_t req_len = req_fixed_len + tlv_required_space(input_length) + tlv_required_space(salt_length); + + *output_length = 0; /* For failure case */ + + req_msg.handle = handle; + req_msg.alg = alg; + + struct tlv_record ciphertext_record; + ciphertext_record.tag = TS_CRYPTO_ASYMMETRIC_DECRYPT_IN_TAG_CIPHERTEXT; + ciphertext_record.length = input_length; + ciphertext_record.value = input; + + struct tlv_record salt_record; + salt_record.tag = TS_CRYPTO_ASYMMETRIC_DECRYPT_IN_TAG_SALT; + salt_record.length = salt_length; + salt_record.value = salt; + + rpc_call_handle call_handle; + uint8_t *req_buf; + + call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); + + if (call_handle) { + + uint8_t *resp_buf; + size_t resp_len; + int opstatus; + struct tlv_iterator req_iter; + + memcpy(req_buf, &req_msg, req_fixed_len); + + tlv_iterator_begin(&req_iter, &req_buf[req_fixed_len], req_len - req_fixed_len); + tlv_encode(&req_iter, &ciphertext_record); + tlv_encode(&req_iter, &salt_record); + + m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, + TS_CRYPTO_OPCODE_ASYMMETRIC_DECRYPT, &opstatus, &resp_buf, &resp_len); + + if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) { + + psa_status = opstatus; + + if (psa_status == PSA_SUCCESS) { + + struct tlv_const_iterator resp_iter; + struct tlv_record decoded_record; + tlv_const_iterator_begin(&resp_iter, resp_buf, resp_len); + + if (tlv_find_decode(&resp_iter, TS_CRYPTO_ASYMMETRIC_DECRYPT_OUT_TAG_PLAINTEXT, &decoded_record)) { + + if (decoded_record.length <= output_size) { + + memcpy(output, decoded_record.value, decoded_record.length); + *output_length = decoded_record.length; + } + else { + /* Provided buffer is too small */ + psa_status = PSA_ERROR_BUFFER_TOO_SMALL; + } + } + else { + /* Mandatory response parameter missing */ + psa_status = PSA_ERROR_GENERIC_ERROR; + } + } + } + + rpc_caller_end(m_caller, call_handle); + } + + return psa_status; +} + +psa_status_t packedc_crypto_client::generate_random(uint8_t *output, size_t output_size) +{ + psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; + struct ts_crypto_generate_random_in req_msg; + size_t req_len = sizeof(ts_crypto_generate_random_in); + + req_msg.size = output_size; + + rpc_call_handle call_handle; + uint8_t *req_buf; + + call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); + + if (call_handle) { + + uint8_t *resp_buf; + size_t resp_len; + int opstatus; + + memcpy(req_buf, &req_msg, req_len); + + m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, + TS_CRYPTO_OPCODE_GENERATE_RANDOM, &opstatus, &resp_buf, &resp_len); + + if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) { + + psa_status = opstatus; + + if (psa_status == PSA_SUCCESS) { + + struct tlv_const_iterator resp_iter; + struct tlv_record decoded_record; + tlv_const_iterator_begin(&resp_iter, resp_buf, resp_len); + + if (tlv_find_decode(&resp_iter, TS_CRYPTO_GENERATE_RANDOM_OUT_TAG_RANDOM_BYTES, &decoded_record)) { + + if (decoded_record.length <= output_size) { + + memcpy(output, decoded_record.value, decoded_record.length); + } + else { + /* Provided buffer is too small */ + psa_status = PSA_ERROR_BUFFER_TOO_SMALL; + } + } + else { + /* Mandatory response parameter missing */ + psa_status = PSA_ERROR_GENERIC_ERROR; + } + } + } + + rpc_caller_end(m_caller, call_handle); + } + + return psa_status; +} + +void packedc_crypto_client::translate_key_attributes(struct ts_crypto_key_attributes &proto_attributes, + const psa_key_attributes_t &psa_attributes) +{ + proto_attributes.type = psa_get_key_type(&psa_attributes); + proto_attributes.key_bits = psa_get_key_bits(&psa_attributes); + proto_attributes.lifetime = psa_get_key_lifetime(&psa_attributes); + proto_attributes.id = psa_get_key_id(&psa_attributes); + + proto_attributes.policy.usage = psa_get_key_usage_flags(&psa_attributes); + proto_attributes.policy.alg = psa_get_key_algorithm(&psa_attributes); + } diff --git a/components/service/crypto/client/cpp/packed-c/packedc_crypto_client.h b/components/service/crypto/client/cpp/packed-c/packedc_crypto_client.h new file mode 100644 index 000000000..fb5d7729b --- /dev/null +++ b/components/service/crypto/client/cpp/packed-c/packedc_crypto_client.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PACKEDC_CRYPTO_CLIENT_H +#define PACKEDC_CRYPTO_CLIENT_H + +#include +#include + +/* + * A concrete crypto_client that uses the packed-c based crypto access protocol + */ +class packedc_crypto_client : public crypto_client +{ +public: + packedc_crypto_client(); + packedc_crypto_client(struct rpc_caller *caller); + virtual ~packedc_crypto_client(); + + /* Key lifecycle methods */ + psa_status_t generate_key(const psa_key_attributes_t *attributes, psa_key_handle_t *handle); + psa_status_t destroy_key(psa_key_handle_t handle); + psa_status_t open_key(psa_key_id_t id, psa_key_handle_t *handle); + psa_status_t close_key(psa_key_handle_t handle); + psa_status_t import_key(const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, psa_key_handle_t *handle); + + /* Key export methods */ + psa_status_t export_key(psa_key_handle_t handle, + uint8_t *data, size_t data_size, + size_t *data_length); + psa_status_t export_public_key(psa_key_handle_t handle, + uint8_t *data, size_t data_size, size_t *data_length); + + /* Sign/verify methods */ + psa_status_t 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_status_t 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); + + /* Asymmetric encrypt/decrypt */ + psa_status_t 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_status_t 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); + + /* Random number generation */ + psa_status_t generate_random(uint8_t *output, size_t output_size); + +private: + + void translate_key_attributes(struct ts_crypto_key_attributes &proto_attributes, + const psa_key_attributes_t &psa_attributes); +}; + +#endif /* PACKEDC_CRYPTO_CLIENT_H */ diff --git a/components/service/crypto/client/cpp/protobuf/component.cmake b/components/service/crypto/client/cpp/protobuf/component.cmake new file mode 100644 index 000000000..ddb3f6bf7 --- /dev/null +++ b/components/service/crypto/client/cpp/protobuf/component.cmake @@ -0,0 +1,14 @@ +#------------------------------------------------------------------------------- +# Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +#------------------------------------------------------------------------------- +if (NOT DEFINED TGT) + message(FATAL_ERROR "mandatory parameter TGT is not defined.") +endif() + +target_sources(${TGT} PRIVATE + "${CMAKE_CURRENT_LIST_DIR}/protobuf_crypto_client.cpp" + ) + diff --git a/components/service/crypto/client/cpp/protobuf/protobuf_crypto_client.cpp b/components/service/crypto/client/cpp/protobuf/protobuf_crypto_client.cpp new file mode 100644 index 000000000..681859086 --- /dev/null +++ b/components/service/crypto/client/cpp/protobuf/protobuf_crypto_client.cpp @@ -0,0 +1,799 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include "protobuf_crypto_client.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +protobuf_crypto_client::protobuf_crypto_client() : + crypto_client() +{ + +} + +protobuf_crypto_client::protobuf_crypto_client(struct rpc_caller *caller) : + crypto_client(caller) +{ + +} + +protobuf_crypto_client::~protobuf_crypto_client() +{ + +} + +psa_status_t protobuf_crypto_client::generate_key(const psa_key_attributes_t *attributes, psa_key_handle_t *handle) +{ + size_t req_len; + psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; + ts_crypto_GenerateKeyIn req_msg = ts_crypto_GenerateKeyIn_init_default; + + translate_key_attributes(req_msg.attributes, *attributes); + req_msg.has_attributes = true; + + if (pb_get_encoded_size(&req_len, ts_crypto_GenerateKeyIn_fields, &req_msg)) { + + rpc_call_handle call_handle; + uint8_t *req_buf; + + call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); + + if (call_handle) { + + uint8_t *resp_buf; + size_t resp_len; + int opstatus; + + pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len); + pb_encode(&ostream, ts_crypto_GenerateKeyIn_fields, &req_msg); + + m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, + ts_crypto_Opcode_GENERATE_KEY, &opstatus, &resp_buf, &resp_len); + + if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) { + + psa_status = opstatus; + + if (psa_status == PSA_SUCCESS) { + + ts_crypto_GenerateKeyOut resp_msg = ts_crypto_GenerateKeyOut_init_default; + pb_istream_t istream = pb_istream_from_buffer(resp_buf, resp_len); + + if (pb_decode(&istream, ts_crypto_GenerateKeyOut_fields, &resp_msg)) { + + *handle = resp_msg.handle; + } + else { + /* Failed to decode response message */ + psa_status = PSA_ERROR_GENERIC_ERROR; + } + } + } + + rpc_caller_end(m_caller, call_handle); + } + } + + return psa_status; +} + +psa_status_t protobuf_crypto_client::destroy_key(psa_key_handle_t handle) +{ + size_t req_len; + psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; + ts_crypto_DestroyKeyIn req_msg = ts_crypto_DestroyKeyIn_init_default; + + req_msg.handle = handle; + + if (pb_get_encoded_size(&req_len, ts_crypto_DestroyKeyIn_fields, &req_msg)) { + + rpc_call_handle call_handle; + uint8_t *req_buf; + + call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); + + if (call_handle) { + + uint8_t *resp_buf; + size_t resp_len; + int opstatus; + + pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len); + pb_encode(&ostream, ts_crypto_DestroyKeyIn_fields, &req_msg); + + m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, + ts_crypto_Opcode_DESTROY_KEY, &opstatus, &resp_buf, &resp_len); + + if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) psa_status = opstatus; + + rpc_caller_end(m_caller, call_handle); + } + } + + return psa_status; +} + +psa_status_t protobuf_crypto_client::open_key(psa_key_id_t id, psa_key_handle_t *handle) +{ + size_t req_len; + psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; + ts_crypto_OpenKeyIn req_msg = ts_crypto_OpenKeyIn_init_default; + req_msg.id = id; + + if (pb_get_encoded_size(&req_len, ts_crypto_OpenKeyIn_fields, &req_msg)) { + + rpc_call_handle call_handle; + uint8_t *req_buf; + + call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); + + if (call_handle) { + + uint8_t *resp_buf; + size_t resp_len; + int opstatus; + + pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len); + pb_encode(&ostream, ts_crypto_OpenKeyIn_fields, &req_msg); + + m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, + ts_crypto_Opcode_OPEN_KEY, &opstatus, &resp_buf, &resp_len); + + if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) { + + psa_status = opstatus; + + if (psa_status == PSA_SUCCESS) { + + ts_crypto_OpenKeyOut resp_msg = ts_crypto_OpenKeyOut_init_default; + pb_istream_t istream = pb_istream_from_buffer(resp_buf, resp_len); + + if (pb_decode(&istream, ts_crypto_OpenKeyOut_fields, &resp_msg)) { + + *handle = resp_msg.handle; + } + else { + /* Failed to decode response message */ + psa_status = PSA_ERROR_GENERIC_ERROR; + } + } + } + + rpc_caller_end(m_caller, call_handle); + } + } + + return psa_status; +} + +psa_status_t protobuf_crypto_client::close_key(psa_key_handle_t handle) +{ + size_t req_len; + psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; + ts_crypto_CloseKeyIn req_msg = ts_crypto_CloseKeyIn_init_default; + + req_msg.handle = handle; + + if (pb_get_encoded_size(&req_len, ts_crypto_CloseKeyIn_fields, &req_msg)) { + + rpc_call_handle call_handle; + uint8_t *req_buf; + + call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); + + if (call_handle) { + + uint8_t *resp_buf; + size_t resp_len; + int opstatus; + + pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len); + pb_encode(&ostream, ts_crypto_CloseKeyIn_fields, &req_msg); + + m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, + ts_crypto_Opcode_CLOSE_KEY, &opstatus, &resp_buf, &resp_len); + + if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) psa_status = opstatus; + + rpc_caller_end(m_caller, call_handle); + } + } + + return psa_status; +} + +psa_status_t protobuf_crypto_client::import_key(const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, psa_key_handle_t *handle) +{ + size_t req_len; + psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; + ts_crypto_ImportKeyIn req_msg = ts_crypto_ImportKeyIn_init_default; + pb_bytes_array_t *key_byte_array = pb_malloc_byte_array_containing_bytes(data, data_length); + + translate_key_attributes(req_msg.attributes, *attributes); + req_msg.has_attributes = true; + req_msg.data = pb_out_byte_array(key_byte_array); + + if (pb_get_encoded_size(&req_len, ts_crypto_ImportKeyIn_fields, &req_msg)) { + + rpc_call_handle call_handle; + uint8_t *req_buf; + + call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); + + if (call_handle) { + + uint8_t *resp_buf; + size_t resp_len; + int opstatus; + + pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len); + pb_encode(&ostream, ts_crypto_ImportKeyIn_fields, &req_msg); + + m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, + ts_crypto_Opcode_IMPORT_KEY, &opstatus, &resp_buf, &resp_len); + + if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) { + + psa_status = opstatus; + + if (psa_status == PSA_SUCCESS) { + + ts_crypto_ImportKeyOut resp_msg = ts_crypto_ImportKeyOut_init_default; + pb_istream_t istream = pb_istream_from_buffer(resp_buf, resp_len); + + if (pb_decode(&istream, ts_crypto_ImportKeyOut_fields, &resp_msg)) { + + *handle = resp_msg.handle; + } + else { + /* Failed to decode response message */ + psa_status = PSA_ERROR_GENERIC_ERROR; + } + } + } + + rpc_caller_end(m_caller, call_handle); + } + } + + ::free(key_byte_array); + + return psa_status; +} + +psa_status_t protobuf_crypto_client::export_key(psa_key_handle_t handle, + uint8_t *data, size_t data_size, + size_t *data_length) +{ + size_t req_len; + psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; + ts_crypto_ExportKeyIn req_msg = ts_crypto_ExportKeyIn_init_default; + req_msg.handle = handle; + + *data_length = 0; /* For failure case */ + + if (pb_get_encoded_size(&req_len, ts_crypto_ExportKeyIn_fields, &req_msg)) { + + rpc_call_handle call_handle; + uint8_t *req_buf; + + call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); + + if (call_handle) { + + uint8_t *resp_buf; + size_t resp_len; + int opstatus; + + pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len); + pb_encode(&ostream, ts_crypto_ExportKeyIn_fields, &req_msg); + + m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, + ts_crypto_Opcode_EXPORT_KEY, &opstatus, &resp_buf, &resp_len); + + if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) { + + psa_status = opstatus; + + if (psa_status == PSA_SUCCESS) { + + ts_crypto_ExportKeyOut resp_msg = ts_crypto_ExportKeyOut_init_default; + pb_bytes_array_t *exported_key = pb_malloc_byte_array(resp_len); + + if (exported_key) { + + resp_msg.data = pb_in_byte_array(exported_key); + pb_istream_t istream = pb_istream_from_buffer(resp_buf, resp_len); + + if (pb_decode(&istream, ts_crypto_ExportKeyOut_fields, &resp_msg)) { + + if (exported_key->size <= data_size) { + + memcpy(data, exported_key->bytes, exported_key->size); + *data_length = exported_key->size; + } + else { + /* Provided buffer is too small */ + psa_status = PSA_ERROR_BUFFER_TOO_SMALL; + } + } + else { + /* Failed to decode response message */ + psa_status = PSA_ERROR_GENERIC_ERROR; + } + + ::free(exported_key); + } + else { + /* Failed to allocate buffer for exported key */ + psa_status = PSA_ERROR_INSUFFICIENT_MEMORY; + } + } + } + + rpc_caller_end(m_caller, call_handle); + } + } + + return psa_status; +} + +psa_status_t protobuf_crypto_client::export_public_key(psa_key_handle_t handle, + uint8_t *data, size_t data_size, size_t *data_length) +{ + size_t req_len; + psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; + ts_crypto_ExportPublicKeyIn req_msg = ts_crypto_ExportPublicKeyIn_init_default; + req_msg.handle = handle; + + *data_length = 0; /* For failure case */ + + if (pb_get_encoded_size(&req_len, ts_crypto_ExportPublicKeyIn_fields, &req_msg)) { + + rpc_call_handle call_handle; + uint8_t *req_buf; + + call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); + + if (call_handle) { + + uint8_t *resp_buf; + size_t resp_len; + int opstatus; + + pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len); + pb_encode(&ostream, ts_crypto_ExportPublicKeyIn_fields, &req_msg); + + m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, + ts_crypto_Opcode_EXPORT_PUBLIC_KEY, &opstatus, &resp_buf, &resp_len); + + if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) { + + psa_status = opstatus; + + if (psa_status == PSA_SUCCESS) { + + ts_crypto_ExportPublicKeyOut resp_msg = ts_crypto_ExportPublicKeyOut_init_default; + pb_bytes_array_t *exported_key = pb_malloc_byte_array(resp_len); + + if (exported_key) { + + resp_msg.data = pb_in_byte_array(exported_key); + pb_istream_t istream = pb_istream_from_buffer(resp_buf, resp_len); + + if (pb_decode(&istream, ts_crypto_ExportPublicKeyOut_fields, &resp_msg)) { + + if (exported_key->size <= data_size) { + + memcpy(data, exported_key->bytes, exported_key->size); + *data_length = exported_key->size; + } + else { + /* Provided buffer is too small */ + psa_status = PSA_ERROR_BUFFER_TOO_SMALL; + } + } + else { + /* Failed to decode response message */ + psa_status = PSA_ERROR_GENERIC_ERROR; + } + + ::free(exported_key); + } + else { + /* Failed to alloocate buffer for exported key */ + psa_status = PSA_ERROR_INSUFFICIENT_MEMORY; + } + } + } + + rpc_caller_end(m_caller, call_handle); + } + } + + return psa_status; +} + +psa_status_t protobuf_crypto_client::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) +{ + size_t req_len; + pb_bytes_array_t *hash_byte_array = pb_malloc_byte_array_containing_bytes(hash, hash_length); + psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; + ts_crypto_SignHashIn req_msg = ts_crypto_SignHashIn_init_default; + + *signature_length = 0; /* For failure case */ + + req_msg.handle = handle; + req_msg.alg = alg; + req_msg.hash = pb_out_byte_array(hash_byte_array); + + if (pb_get_encoded_size(&req_len, ts_crypto_SignHashIn_fields, &req_msg)) { + + rpc_call_handle call_handle; + uint8_t *req_buf; + + call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); + + if (call_handle) { + + uint8_t *resp_buf; + size_t resp_len; + int opstatus; + + pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len); + pb_encode(&ostream, ts_crypto_SignHashIn_fields, &req_msg); + + m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, + ts_crypto_Opcode_SIGN_HASH, &opstatus, &resp_buf, &resp_len); + + if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) { + + psa_status = opstatus; + + if (psa_status == PSA_SUCCESS) { + + pb_bytes_array_t *sig_byte_array = pb_malloc_byte_array(PSA_SIGNATURE_MAX_SIZE); + ts_crypto_SignHashOut resp_msg = ts_crypto_SignHashOut_init_default; + resp_msg.signature = pb_in_byte_array(sig_byte_array); + + pb_istream_t istream = pb_istream_from_buffer(resp_buf, resp_len); + + if (pb_decode(&istream, ts_crypto_SignHashOut_fields, &resp_msg)) { + + if (sig_byte_array->size <= signature_size) { + + memcpy(signature, sig_byte_array->bytes, sig_byte_array->size); + *signature_length = sig_byte_array->size; + } + else { + /* Provided buffer is too small */ + psa_status = PSA_ERROR_BUFFER_TOO_SMALL; + } + } + else { + /* Failed to decode response message */ + psa_status = PSA_ERROR_GENERIC_ERROR; + } + + ::free(sig_byte_array); + } + } + + rpc_caller_end(m_caller, call_handle); + } + } + + ::free(hash_byte_array); + + return psa_status; +} + + +psa_status_t protobuf_crypto_client::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) +{ + size_t req_len; + pb_bytes_array_t *hash_byte_array = pb_malloc_byte_array_containing_bytes(hash, hash_length); + pb_bytes_array_t *sig_byte_array = pb_malloc_byte_array_containing_bytes(signature, signature_length); + psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; + ts_crypto_VerifyHashIn req_msg = ts_crypto_VerifyHashIn_init_default; + + req_msg.handle = handle; + req_msg.alg = alg; + req_msg.hash = pb_out_byte_array(hash_byte_array); + req_msg.signature = pb_out_byte_array(sig_byte_array); + + if (pb_get_encoded_size(&req_len, ts_crypto_VerifyHashIn_fields, &req_msg)) { + + rpc_call_handle call_handle; + uint8_t *req_buf; + + call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); + + if (call_handle) { + + uint8_t *resp_buf; + size_t resp_len; + int opstatus; + + pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len); + pb_encode(&ostream, ts_crypto_VerifyHashIn_fields, &req_msg); + + m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, + ts_crypto_Opcode_VERIFY_HASH, &opstatus, &resp_buf, &resp_len); + + if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) psa_status = opstatus; + + rpc_caller_end(m_caller, call_handle); + } + } + + ::free(hash_byte_array); + ::free(sig_byte_array); + + return psa_status; +} + +psa_status_t protobuf_crypto_client::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) +{ + size_t req_len; + pb_bytes_array_t *plaintext_byte_array = pb_malloc_byte_array_containing_bytes(input, input_length); + pb_bytes_array_t *salt_byte_array = pb_malloc_byte_array_containing_bytes(salt, salt_length); + psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; + ts_crypto_AsymmetricEncryptIn req_msg = ts_crypto_AsymmetricEncryptIn_init_default; + + *output_length = 0; /* For failure case */ + + req_msg.handle = handle; + req_msg.alg = alg; + req_msg.plaintext = pb_out_byte_array(plaintext_byte_array); + req_msg.salt = pb_out_byte_array(salt_byte_array); + + if (pb_get_encoded_size(&req_len, ts_crypto_AsymmetricEncryptIn_fields, &req_msg)) { + + rpc_call_handle call_handle; + uint8_t *req_buf; + + call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); + + if (call_handle) { + + uint8_t *resp_buf; + size_t resp_len; + int opstatus = PSA_ERROR_GENERIC_ERROR; + + pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len); + pb_encode(&ostream, ts_crypto_AsymmetricEncryptIn_fields, &req_msg); + + m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, + ts_crypto_Opcode_ASYMMETRIC_ENCRYPT, &opstatus, &resp_buf, &resp_len); + + if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) { + + psa_status = opstatus; + + if (psa_status == PSA_SUCCESS) { + + pb_bytes_array_t *ciphertext_byte_array = pb_malloc_byte_array(output_size); + ts_crypto_AsymmetricEncryptOut resp_msg = ts_crypto_AsymmetricEncryptOut_init_default; + resp_msg.ciphertext = pb_in_byte_array(ciphertext_byte_array); + + pb_istream_t istream = pb_istream_from_buffer(resp_buf, resp_len); + + if (pb_decode(&istream, ts_crypto_AsymmetricEncryptOut_fields, &resp_msg)) { + + if (ciphertext_byte_array->size <= output_size) { + + memcpy(output, ciphertext_byte_array->bytes, ciphertext_byte_array->size); + *output_length = ciphertext_byte_array->size; + } + else { + /* Provided buffer is too small */ + psa_status = PSA_ERROR_BUFFER_TOO_SMALL; + } + } + else { + /* Failed to decode response message */ + psa_status = PSA_ERROR_GENERIC_ERROR; + } + + ::free(ciphertext_byte_array); + } + } + + rpc_caller_end(m_caller, call_handle); + } + } + + ::free(plaintext_byte_array); + ::free(salt_byte_array); + + return psa_status; +} + +psa_status_t protobuf_crypto_client::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) +{ + size_t req_len; + pb_bytes_array_t *ciphertext_byte_array = pb_malloc_byte_array_containing_bytes(input, input_length); + pb_bytes_array_t *salt_byte_array = pb_malloc_byte_array_containing_bytes(salt, salt_length); + psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; + ts_crypto_AsymmetricDecryptIn req_msg = ts_crypto_AsymmetricDecryptIn_init_default; + + *output_length = 0; /* For failure case */ + + req_msg.handle = handle; + req_msg.alg = alg; + req_msg.ciphertext = pb_out_byte_array(ciphertext_byte_array); + req_msg.salt = pb_out_byte_array(salt_byte_array); + + if (pb_get_encoded_size(&req_len, ts_crypto_AsymmetricDecryptIn_fields, &req_msg)) { + + rpc_call_handle call_handle; + uint8_t *req_buf; + + call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); + + if (call_handle) { + + uint8_t *resp_buf; + size_t resp_len; + int opstatus; + + pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len); + pb_encode(&ostream, ts_crypto_AsymmetricDecryptIn_fields, &req_msg); + + m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, + ts_crypto_Opcode_ASYMMETRIC_DECRYPT, &opstatus, &resp_buf, &resp_len); + + if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) { + + psa_status = opstatus; + + if (psa_status == PSA_SUCCESS) { + + pb_bytes_array_t *plaintext_byte_array = pb_malloc_byte_array(output_size); + ts_crypto_AsymmetricDecryptOut resp_msg = ts_crypto_AsymmetricDecryptOut_init_default; + resp_msg.plaintext = pb_in_byte_array(plaintext_byte_array); + + pb_istream_t istream = pb_istream_from_buffer(resp_buf, resp_len); + + if (pb_decode(&istream, ts_crypto_AsymmetricDecryptOut_fields, &resp_msg)) { + + if (plaintext_byte_array->size <= output_size) { + + memcpy(output, plaintext_byte_array->bytes, plaintext_byte_array->size); + *output_length = plaintext_byte_array->size; + } + else { + /* Provided buffer is too small */ + m_err_rpc_status = PSA_ERROR_BUFFER_TOO_SMALL; + } + } + else { + /* Failed to decode response message */ + m_err_rpc_status = PSA_ERROR_GENERIC_ERROR; + } + + ::free(plaintext_byte_array); + } + } + + rpc_caller_end(m_caller, call_handle); + } + } + + ::free(ciphertext_byte_array); + ::free(salt_byte_array); + + return psa_status; +} + +psa_status_t protobuf_crypto_client::generate_random(uint8_t *output, size_t output_size) +{ + size_t req_len; + psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; + ts_crypto_GenerateRandomIn req_msg = ts_crypto_GenerateRandomIn_init_default; + + req_msg.size = output_size; + + if (pb_get_encoded_size(&req_len, ts_crypto_GenerateRandomIn_fields, &req_msg)) { + + rpc_call_handle call_handle; + uint8_t *req_buf; + + call_handle = rpc_caller_begin(m_caller, &req_buf, req_len); + + if (call_handle) { + + uint8_t *resp_buf; + size_t resp_len; + int opstatus; + + pb_ostream_t ostream = pb_ostream_from_buffer(req_buf, req_len); + pb_encode(&ostream, ts_crypto_GenerateRandomIn_fields, &req_msg); + + m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle, + ts_crypto_Opcode_GENERATE_RANDOM, &opstatus, &resp_buf, &resp_len); + + if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) { + + psa_status = opstatus; + + if (psa_status == PSA_SUCCESS) { + + pb_bytes_array_t *output_byte_array = pb_malloc_byte_array(output_size); + ts_crypto_GenerateRandomOut resp_msg = ts_crypto_GenerateRandomOut_init_default; + resp_msg.random_bytes = pb_in_byte_array(output_byte_array); + + pb_istream_t istream = pb_istream_from_buffer(resp_buf, resp_len); + + if (pb_decode(&istream, ts_crypto_GenerateRandomOut_fields, &resp_msg)) { + + if (output_byte_array->size == output_size) { + + memcpy(output, output_byte_array->bytes, output_byte_array->size); + } + else { + /* Mismatch between requested and generated length */ + psa_status = PSA_ERROR_GENERIC_ERROR; + } + } + else { + /* Failed to decode response message */ + psa_status = PSA_ERROR_GENERIC_ERROR; + } + + ::free(output_byte_array); + } + } + + rpc_caller_end(m_caller, call_handle); + } + } + + return psa_status; +} + +void protobuf_crypto_client::translate_key_attributes(ts_crypto_KeyAttributes &proto_attributes, + const psa_key_attributes_t &psa_attributes) +{ + proto_attributes.type = psa_get_key_type(&psa_attributes); + proto_attributes.key_bits = psa_get_key_bits(&psa_attributes); + proto_attributes.lifetime = psa_get_key_lifetime(&psa_attributes); + proto_attributes.id = psa_get_key_id(&psa_attributes); + + proto_attributes.has_policy = true; + proto_attributes.policy.usage = psa_get_key_usage_flags(&psa_attributes); + proto_attributes.policy.alg = psa_get_key_algorithm(&psa_attributes); + } diff --git a/components/service/crypto/client/cpp/protobuf/protobuf_crypto_client.h b/components/service/crypto/client/cpp/protobuf/protobuf_crypto_client.h new file mode 100644 index 000000000..e2a355a1d --- /dev/null +++ b/components/service/crypto/client/cpp/protobuf/protobuf_crypto_client.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PROTOBUF_CRYPTO_CLIENT_H +#define PROTOBUF_CRYPTO_CLIENT_H + +#include +#include + +/* + * A concrete crypto_client that uses the protobuf based crypto access protocol + */ +class protobuf_crypto_client : public crypto_client +{ +public: + protobuf_crypto_client(); + protobuf_crypto_client(struct rpc_caller *caller); + virtual ~protobuf_crypto_client(); + + /* Key lifecycle methods */ + psa_status_t generate_key(const psa_key_attributes_t *attributes, psa_key_handle_t *handle); + psa_status_t destroy_key(psa_key_handle_t handle); + psa_status_t open_key(psa_key_id_t id, psa_key_handle_t *handle); + psa_status_t close_key(psa_key_handle_t handle); + psa_status_t import_key(const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, psa_key_handle_t *handle); + + /* Key export methods */ + psa_status_t export_key(psa_key_handle_t handle, + uint8_t *data, size_t data_size, + size_t *data_length); + psa_status_t export_public_key(psa_key_handle_t handle, + uint8_t *data, size_t data_size, size_t *data_length); + + /* Sign/verify methods */ + psa_status_t 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_status_t 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); + + /* Asymmetric encrypt/decrypt */ + psa_status_t 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_status_t 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); + + /* Random number generation */ + psa_status_t generate_random(uint8_t *output, size_t output_size); + +private: + + void translate_key_attributes(ts_crypto_KeyAttributes &proto_attributes, + const psa_key_attributes_t &psa_attributes); +}; + +#endif /* PROTOBUF_CRYPTO_CLIENT_H */ diff --git a/components/service/crypto/client/test/mock/mock_crypto_client.cpp b/components/service/crypto/client/test/mock/mock_crypto_client.cpp index a654ed14a..4ca482a5e 100644 --- a/components/service/crypto/client/test/mock/mock_crypto_client.cpp +++ b/components/service/crypto/client/test/mock/mock_crypto_client.cpp @@ -6,6 +6,7 @@ #include "mock_crypto_client.h" #include +#include mock_crypto_client::mock_crypto_client() : test_crypto_client(), @@ -40,6 +41,9 @@ bool mock_crypto_client::init() mbed_crypto_provider_register_serializer(&m_crypto_provider, TS_RPC_ENCODING_PROTOBUF, pb_crypto_provider_serializer_instance()); + mbed_crypto_provider_register_serializer(&m_crypto_provider, + TS_RPC_ENCODING_PACKED_C, packedc_crypto_provider_serializer_instance()); + rpc_caller_set_encoding_scheme(crypto_caller, TS_RPC_ENCODING_PROTOBUF); crypto_client::set_caller(crypto_caller); diff --git a/components/service/crypto/client/test/standalone/standalone_crypto_client.cpp b/components/service/crypto/client/test/standalone/standalone_crypto_client.cpp index 459e42d6c..343bec1ad 100644 --- a/components/service/crypto/client/test/standalone/standalone_crypto_client.cpp +++ b/components/service/crypto/client/test/standalone/standalone_crypto_client.cpp @@ -8,6 +8,7 @@ #include #include #include +#include standalone_crypto_client::standalone_crypto_client() : test_crypto_client(), @@ -58,6 +59,9 @@ bool standalone_crypto_client::init() mbed_crypto_provider_register_serializer(&m_crypto_provider, TS_RPC_ENCODING_PROTOBUF, pb_crypto_provider_serializer_instance()); + mbed_crypto_provider_register_serializer(&m_crypto_provider, + TS_RPC_ENCODING_PACKED_C, packedc_crypto_provider_serializer_instance()); + rpc_caller_set_encoding_scheme(crypto_caller, TS_RPC_ENCODING_PROTOBUF); crypto_client::set_caller(crypto_caller); diff --git a/components/service/crypto/client/test/test_crypto_client.cpp b/components/service/crypto/client/test/test_crypto_client.cpp index 72327904c..3217c61ac 100644 --- a/components/service/crypto/client/test/test_crypto_client.cpp +++ b/components/service/crypto/client/test/test_crypto_client.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -10,7 +10,7 @@ test_crypto_client::factory *test_crypto_client::m_default_factory = NULL; test_crypto_client::test_crypto_client() : - crypto_client(), + protobuf_crypto_client(), m_is_initialized(false), m_injected_faults() { diff --git a/components/service/crypto/client/test/test_crypto_client.h b/components/service/crypto/client/test/test_crypto_client.h index 5b927dbe0..f1d70a1d1 100644 --- a/components/service/crypto/client/test/test_crypto_client.h +++ b/components/service/crypto/client/test/test_crypto_client.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -7,7 +7,7 @@ #ifndef TEST_CRYPTO_CLIENT_H #define TEST_CRYPTO_CLIENT_H -#include +#include #include /* @@ -20,7 +20,7 @@ * Each virtual test method is paired with a is_supported() method to * allow test cases to adapt to circumstances. */ -class test_crypto_client : public crypto_client +class test_crypto_client : public protobuf_crypto_client { public: virtual ~test_crypto_client(); diff --git a/components/service/crypto/provider/serializer/packed-c/component.cmake b/components/service/crypto/provider/serializer/packed-c/component.cmake new file mode 100644 index 000000000..f4b010621 --- /dev/null +++ b/components/service/crypto/provider/serializer/packed-c/component.cmake @@ -0,0 +1,14 @@ +#------------------------------------------------------------------------------- +# Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +#------------------------------------------------------------------------------- +if (NOT DEFINED TGT) + message(FATAL_ERROR "mandatory parameter TGT is not defined.") +endif() + +target_sources(${TGT} PRIVATE + "${CMAKE_CURRENT_LIST_DIR}/packedc_crypto_provider_serializer.c" + "${CMAKE_CURRENT_LIST_DIR}/packedc_key_attributes_translator.c" + ) diff --git a/components/service/crypto/provider/serializer/packed-c/packedc_crypto_provider_serializer.c b/components/service/crypto/provider/serializer/packed-c/packedc_crypto_provider_serializer.c new file mode 100644 index 000000000..f39aa1cff --- /dev/null +++ b/components/service/crypto/provider/serializer/packed-c/packedc_crypto_provider_serializer.c @@ -0,0 +1,661 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "packedc_crypto_provider_serializer.h" +#include "packedc_key_attributes_translator.h" + +/* Returns the maximum possible deserialized parameter size for a packed-c encoded message. */ +static size_t max_deserialised_parameter_size(const struct call_param_buf *req_buf) +{ + /* + * Assume that a deserialized parameter must be the same size or smaller than the + * entire serialized message. + */ + return req_buf->data_len; +} + +/* Operation: generate_key */ +static rpc_status_t deserialize_generate_key_req(const struct call_param_buf *req_buf, + psa_key_attributes_t *attributes) +{ + rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY; + struct ts_crypto_generate_key_in recv_msg; + size_t expected_fixed_len = sizeof(struct ts_crypto_generate_key_in); + + if (expected_fixed_len <= req_buf->data_len) { + + memcpy(&recv_msg, req_buf->data, expected_fixed_len); + packedc_crypto_provider_translate_key_attributes(attributes, &recv_msg.attributes); + rpc_status = TS_RPC_CALL_ACCEPTED; + } + + return rpc_status; +} + +static rpc_status_t serialize_generate_key_resp(struct call_param_buf *resp_buf, + psa_key_handle_t handle) +{ + rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL; + struct ts_crypto_generate_key_out resp_msg; + size_t fixed_len = sizeof(struct ts_crypto_generate_key_out); + + resp_msg.handle = handle; + + if (fixed_len <= resp_buf->size) { + + memcpy(resp_buf->data, &resp_msg, fixed_len); + resp_buf->data_len = fixed_len; + rpc_status = TS_RPC_CALL_ACCEPTED; + } + + return rpc_status; +} + +/* Operation: destroy_key */ +static rpc_status_t deserialize_destroy_key_req(const struct call_param_buf *req_buf, + psa_key_handle_t *handle) +{ + rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY; + struct ts_crypto_destroy_key_in recv_msg; + size_t expected_fixed_len = sizeof(struct ts_crypto_destroy_key_in); + + if (expected_fixed_len <= req_buf->data_len) { + + memcpy(&recv_msg, req_buf->data, expected_fixed_len); + *handle = recv_msg.handle; + rpc_status = TS_RPC_CALL_ACCEPTED; + } + + return rpc_status; +} + +/* Operation: open_key */ +static rpc_status_t deserialize_open_key_req(const struct call_param_buf *req_buf, psa_key_id_t *id) +{ + rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY; + struct ts_crypto_open_key_in recv_msg; + size_t expected_fixed_len = sizeof(struct ts_crypto_open_key_in); + + if (expected_fixed_len <= req_buf->data_len) { + + memcpy(&recv_msg, req_buf->data, expected_fixed_len); + *id = recv_msg.id; + rpc_status = TS_RPC_CALL_ACCEPTED; + } + + return rpc_status; +} + +static rpc_status_t serialize_open_key_resp(struct call_param_buf *resp_buf, + psa_key_handle_t handle) +{ + rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL; + struct ts_crypto_open_key_out resp_msg; + size_t fixed_len = sizeof(struct ts_crypto_open_key_out); + + resp_msg.handle = handle; + + if (fixed_len <= resp_buf->size) { + + memcpy(resp_buf->data, &resp_msg, fixed_len); + resp_buf->data_len = fixed_len; + rpc_status = TS_RPC_CALL_ACCEPTED; + } + + return rpc_status; +} + +/* Operation: close_key */ +static rpc_status_t deserialize_close_key_req(const struct call_param_buf *req_buf, + psa_key_handle_t *handle) +{ + rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY; + struct ts_crypto_close_key_in recv_msg; + size_t expected_fixed_len = sizeof(struct ts_crypto_close_key_in); + + if (expected_fixed_len <= req_buf->data_len) { + + memcpy(&recv_msg, req_buf->data, expected_fixed_len); + *handle = recv_msg.handle; + rpc_status = TS_RPC_CALL_ACCEPTED; + } + + return rpc_status; +} + +/* Operation: export_key */ +static rpc_status_t deserialize_export_key_req(const struct call_param_buf *req_buf, + psa_key_handle_t *handle) +{ + rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY; + struct ts_crypto_export_key_in recv_msg; + size_t expected_fixed_len = sizeof(struct ts_crypto_export_key_in); + + if (expected_fixed_len <= req_buf->data_len) { + + memcpy(&recv_msg, req_buf->data, expected_fixed_len); + *handle = recv_msg.handle; + rpc_status = TS_RPC_CALL_ACCEPTED; + } + + return rpc_status; +} + +static rpc_status_t serialize_export_key_resp(struct call_param_buf *resp_buf, + const uint8_t *data, size_t data_len) +{ + rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL; + struct tlv_iterator resp_iter; + + struct tlv_record key_record; + key_record.tag = TS_CRYPTO_EXPORT_KEY_OUT_TAG_DATA; + key_record.length = data_len; + key_record.value = data; + + tlv_iterator_begin(&resp_iter, resp_buf->data, resp_buf->size); + + if (tlv_encode(&resp_iter, &key_record)) { + + resp_buf->data_len = tlv_required_space(data_len); + rpc_status = TS_RPC_CALL_ACCEPTED; + } + + return rpc_status; +} + +/* Operation: export_public_key */ +static rpc_status_t deserialize_export_public_key_req(const struct call_param_buf *req_buf, + psa_key_handle_t *handle) +{ + rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY; + struct ts_crypto_export_public_key_in recv_msg; + size_t expected_fixed_len = sizeof(struct ts_crypto_export_public_key_in); + + if (expected_fixed_len <= req_buf->data_len) { + + memcpy(&recv_msg, req_buf->data, expected_fixed_len); + *handle = recv_msg.handle; + rpc_status = TS_RPC_CALL_ACCEPTED; + } + + return rpc_status; +} + +static rpc_status_t serialize_export_public_key_resp(struct call_param_buf *resp_buf, + const uint8_t *data, size_t data_len) +{ + rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL; + struct tlv_iterator resp_iter; + + struct tlv_record key_record; + key_record.tag = TS_CRYPTO_EXPORT_PUBLIC_KEY_OUT_TAG_DATA; + key_record.length = data_len; + key_record.value = data; + + tlv_iterator_begin(&resp_iter, resp_buf->data, resp_buf->size); + + if (tlv_encode(&resp_iter, &key_record)) { + + resp_buf->data_len = tlv_required_space(data_len); + rpc_status = TS_RPC_CALL_ACCEPTED; + } + + return rpc_status; +} + +/* Operation: import_key */ +static rpc_status_t deserialize_import_key_req(const struct call_param_buf *req_buf, + psa_key_attributes_t *attributes, uint8_t *data, size_t *data_len) +{ + rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY; + struct ts_crypto_import_key_in recv_msg; + size_t expected_fixed_len = sizeof(struct ts_crypto_import_key_in); + + if (expected_fixed_len <= req_buf->data_len) { + + struct tlv_const_iterator resp_iter; + struct tlv_record decoded_record; + + rpc_status = TS_RPC_CALL_ACCEPTED; + + memcpy(&recv_msg, req_buf->data, expected_fixed_len); + packedc_crypto_provider_translate_key_attributes(attributes, &recv_msg.attributes); + + tlv_const_iterator_begin(&resp_iter, + (uint8_t*)req_buf->data + expected_fixed_len, + req_buf->data_len - expected_fixed_len); + + if (tlv_find_decode(&resp_iter, TS_CRYPTO_IMPORT_KEY_IN_TAG_DATA, &decoded_record)) { + + if (decoded_record.length <= *data_len) { + + memcpy(data, decoded_record.value, decoded_record.length); + *data_len = decoded_record.length; + } + else { + /* Buffer provided too small */ + return TS_RPC_ERROR_INVALID_REQ_BODY; + } + } + else { + /* Default for missing parameter */ + *data_len = 0; + } + } + + return rpc_status; +} + +static rpc_status_t serialize_import_key_resp(struct call_param_buf *resp_buf, + psa_key_handle_t handle) +{ + rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL; + struct ts_crypto_import_key_out resp_msg; + size_t fixed_len = sizeof(struct ts_crypto_import_key_out); + + resp_msg.handle = handle; + + if (fixed_len <= resp_buf->size) { + + memcpy(resp_buf->data, &resp_msg, fixed_len); + resp_buf->data_len = fixed_len; + rpc_status = TS_RPC_CALL_ACCEPTED; + } + + return rpc_status; +} + +/* Operation: sign_hash */ +static rpc_status_t deserialize_sign_hash_req(const struct call_param_buf *req_buf, + psa_key_handle_t *handle, psa_algorithm_t *alg, + uint8_t *hash, size_t *hash_len) +{ + rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY; + struct ts_crypto_sign_hash_in recv_msg; + size_t expected_fixed_len = sizeof(struct ts_crypto_sign_hash_in); + + if (expected_fixed_len <= req_buf->data_len) { + + struct tlv_const_iterator resp_iter; + struct tlv_record decoded_record; + + rpc_status = TS_RPC_CALL_ACCEPTED; + + memcpy(&recv_msg, req_buf->data, expected_fixed_len); + + *handle = recv_msg.handle; + *alg = recv_msg.alg; + + tlv_const_iterator_begin(&resp_iter, + (uint8_t*)req_buf->data + expected_fixed_len, + req_buf->data_len - expected_fixed_len); + + if (tlv_find_decode(&resp_iter, TS_CRYPTO_SIGN_HASH_IN_TAG_HASH, &decoded_record)) { + + if (decoded_record.length <= *hash_len) { + + memcpy(hash, decoded_record.value, decoded_record.length); + *hash_len = decoded_record.length; + } + else { + /* Buffer provided too small */ + return TS_RPC_ERROR_INVALID_REQ_BODY; + } + } + else { + /* Default to a zero length hash */ + *hash_len = 0; + } + } + + return rpc_status; +} + +static rpc_status_t serialize_sign_hash_resp(struct call_param_buf *resp_buf, + const uint8_t *sig, size_t sig_len) +{ + rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL; + struct tlv_iterator resp_iter; + + struct tlv_record sig_record; + sig_record.tag = TS_CRYPTO_SIGN_HASH_OUT_TAG_SIGNATURE; + sig_record.length = sig_len; + sig_record.value = sig; + + tlv_iterator_begin(&resp_iter, resp_buf->data, resp_buf->size); + + if (tlv_encode(&resp_iter, &sig_record)) { + + resp_buf->data_len = tlv_required_space(sig_len); + rpc_status = TS_RPC_CALL_ACCEPTED; + } + + return rpc_status; +} + +/* Operation: verify_hash */ +static rpc_status_t deserialize_verify_hash_req(const struct call_param_buf *req_buf, + psa_key_handle_t *handle, psa_algorithm_t *alg, + uint8_t *hash, size_t *hash_len, + uint8_t *sig, size_t *sig_len) +{ + rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY; + struct ts_crypto_verify_hash_in recv_msg; + size_t expected_fixed_len = sizeof(struct ts_crypto_verify_hash_in); + + if (expected_fixed_len <= req_buf->data_len) { + + struct tlv_const_iterator resp_iter; + struct tlv_record decoded_record; + + rpc_status = TS_RPC_CALL_ACCEPTED; + + memcpy(&recv_msg, req_buf->data, expected_fixed_len); + + *handle = recv_msg.handle; + *alg = recv_msg.alg; + + tlv_const_iterator_begin(&resp_iter, + (uint8_t*)req_buf->data + expected_fixed_len, + req_buf->data_len - expected_fixed_len); + + if (tlv_find_decode(&resp_iter, TS_CRYPTO_VERIFY_HASH_IN_TAG_HASH, &decoded_record)) { + + if (decoded_record.length <= *hash_len) { + + memcpy(hash, decoded_record.value, decoded_record.length); + *hash_len = decoded_record.length; + } + else { + /* Buffer provided too small */ + return TS_RPC_ERROR_INVALID_REQ_BODY; + } + } + else { + /* Default to a zero length hash */ + *hash_len = 0; + } + + if (tlv_find_decode(&resp_iter, TS_CRYPTO_VERIFY_HASH_IN_TAG_SIGNATURE, &decoded_record)) { + + if (decoded_record.length <= *sig_len) { + + memcpy(sig, decoded_record.value, decoded_record.length); + *sig_len = decoded_record.length; + } + else { + /* Buffer provided too small */ + return TS_RPC_ERROR_INVALID_REQ_BODY; + } + } + else { + /* Default to a zero length hash */ + *sig_len = 0; + } + } + + return rpc_status; +} + +/* Operation: asymmetric_decrypt */ +static rpc_status_t deserialize_asymmetric_decrypt_req(const struct call_param_buf *req_buf, + psa_key_handle_t *handle, psa_algorithm_t *alg, + uint8_t *ciphertext, size_t *ciphertext_len, + uint8_t *salt, size_t *salt_len) +{ + rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY; + struct ts_crypto_asymmetric_decrypt_in recv_msg; + size_t expected_fixed_len = sizeof(struct ts_crypto_asymmetric_decrypt_in); + + if (expected_fixed_len <= req_buf->data_len) { + + struct tlv_const_iterator resp_iter; + struct tlv_record decoded_record; + + rpc_status = TS_RPC_CALL_ACCEPTED; + + memcpy(&recv_msg, req_buf->data, expected_fixed_len); + + *handle = recv_msg.handle; + *alg = recv_msg.alg; + + tlv_const_iterator_begin(&resp_iter, + (uint8_t*)req_buf->data + expected_fixed_len, + req_buf->data_len - expected_fixed_len); + + if (tlv_find_decode(&resp_iter, TS_CRYPTO_ASYMMETRIC_DECRYPT_IN_TAG_CIPHERTEXT, &decoded_record)) { + + if (decoded_record.length <= *ciphertext_len) { + + memcpy(ciphertext, decoded_record.value, decoded_record.length); + *ciphertext_len = decoded_record.length; + } + else { + /* Buffer provided too small */ + return TS_RPC_ERROR_INVALID_REQ_BODY; + } + } + else { + /* Default to a zero length hash */ + *ciphertext_len = 0; + } + + if (tlv_find_decode(&resp_iter, TS_CRYPTO_ASYMMETRIC_DECRYPT_IN_TAG_SALT, &decoded_record)) { + + if (decoded_record.length <= *salt_len) { + + memcpy(salt, decoded_record.value, decoded_record.length); + *salt_len = decoded_record.length; + } + else { + /* Buffer provided too small */ + return TS_RPC_ERROR_INVALID_REQ_BODY; + } + } + else { + /* Default to a zero length hash */ + *salt_len = 0; + } + } + + return rpc_status; +} + +static rpc_status_t serialize_asymmetric_decrypt_resp(struct call_param_buf *resp_buf, + const uint8_t *plaintext, size_t plaintext_len) +{ + rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL; + struct tlv_iterator resp_iter; + + struct tlv_record sig_record; + sig_record.tag = TS_CRYPTO_ASYMMETRIC_DECRYPT_OUT_TAG_PLAINTEXT; + sig_record.length = plaintext_len; + sig_record.value = plaintext; + + tlv_iterator_begin(&resp_iter, resp_buf->data, resp_buf->size); + + if (tlv_encode(&resp_iter, &sig_record)) { + + resp_buf->data_len = tlv_required_space(plaintext_len); + rpc_status = TS_RPC_CALL_ACCEPTED; + } + + return rpc_status; +} + +/* Operation: asymmetric_encrypt */ +static rpc_status_t deserialize_asymmetric_encrypt_req(const struct call_param_buf *req_buf, + psa_key_handle_t *handle, psa_algorithm_t *alg, + uint8_t *plaintext, size_t *plaintext_len, + uint8_t *salt, size_t *salt_len) +{ + rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY; + struct ts_crypto_asymmetric_encrypt_in recv_msg; + size_t expected_fixed_len = sizeof(struct ts_crypto_asymmetric_encrypt_in); + + if (expected_fixed_len <= req_buf->data_len) { + + struct tlv_const_iterator resp_iter; + struct tlv_record decoded_record; + + rpc_status = TS_RPC_CALL_ACCEPTED; + + memcpy(&recv_msg, req_buf->data, expected_fixed_len); + + *handle = recv_msg.handle; + *alg = recv_msg.alg; + + tlv_const_iterator_begin(&resp_iter, + (uint8_t*)req_buf->data + expected_fixed_len, + req_buf->data_len - expected_fixed_len); + + if (tlv_find_decode(&resp_iter, TS_CRYPTO_ASYMMETRIC_ENCRYPT_IN_TAG_PLAINTEXT, &decoded_record)) { + + if (decoded_record.length <= *plaintext_len) { + + memcpy(plaintext, decoded_record.value, decoded_record.length); + *plaintext_len = decoded_record.length; + } + else { + /* Buffer provided too small */ + return TS_RPC_ERROR_INVALID_REQ_BODY; + } + } + else { + /* Default to a zero length hash */ + *plaintext_len = 0; + } + + if (tlv_find_decode(&resp_iter, TS_CRYPTO_ASYMMETRIC_ENCRYPT_IN_TAG_SALT, &decoded_record)) { + + if (decoded_record.length <= *salt_len) { + + memcpy(salt, decoded_record.value, decoded_record.length); + *salt_len = decoded_record.length; + } + else { + /* Buffer provided too small */ + return TS_RPC_ERROR_INVALID_REQ_BODY; + } + } + else { + /* Default to a zero length hash */ + *salt_len = 0; + } + } + + return rpc_status; +} + +static rpc_status_t serialize_asymmetric_encrypt_resp(struct call_param_buf *resp_buf, + const uint8_t *ciphertext, size_t ciphertext_len) +{ + rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL; + struct tlv_iterator resp_iter; + + struct tlv_record sig_record; + sig_record.tag = TS_CRYPTO_ASYMMETRIC_ENCRYPT_OUT_TAG_CIPHERTEXT; + sig_record.length = ciphertext_len; + sig_record.value = ciphertext; + + tlv_iterator_begin(&resp_iter, resp_buf->data, resp_buf->size); + + if (tlv_encode(&resp_iter, &sig_record)) { + + resp_buf->data_len = tlv_required_space(ciphertext_len); + rpc_status = TS_RPC_CALL_ACCEPTED; + } + + return rpc_status; +} + +/* Operation: generate_random */ +static rpc_status_t deserialize_generate_random_req(const struct call_param_buf *req_buf, + size_t *size) +{ + rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY; + struct ts_crypto_generate_random_in recv_msg; + size_t expected_fixed_len = sizeof(struct ts_crypto_generate_random_in); + + if (expected_fixed_len <= req_buf->data_len) { + + memcpy(&recv_msg, req_buf->data, expected_fixed_len); + *size = recv_msg.size; + rpc_status = TS_RPC_CALL_ACCEPTED; + } + + return rpc_status; +} + +static rpc_status_t serialize_generate_random_resp(struct call_param_buf *resp_buf, + const uint8_t *output, size_t output_len) +{ + rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL; + struct tlv_iterator resp_iter; + + struct tlv_record out_record; + out_record.tag = TS_CRYPTO_GENERATE_RANDOM_OUT_TAG_RANDOM_BYTES; + out_record.length = output_len; + out_record.value = output; + + tlv_iterator_begin(&resp_iter, resp_buf->data, resp_buf->size); + + if (tlv_encode(&resp_iter, &out_record)) { + + resp_buf->data_len = tlv_required_space(output_len); + rpc_status = TS_RPC_CALL_ACCEPTED; + } + + return rpc_status; +} + +/* Singleton method to provide access to the serializer instance */ +const struct crypto_provider_serializer *packedc_crypto_provider_serializer_instance(void) +{ + static const struct crypto_provider_serializer instance = { + max_deserialised_parameter_size, + deserialize_generate_key_req, + serialize_generate_key_resp, + deserialize_destroy_key_req, + deserialize_open_key_req, + serialize_open_key_resp, + deserialize_close_key_req, + deserialize_export_key_req, + serialize_export_key_resp, + deserialize_export_public_key_req, + serialize_export_public_key_resp, + deserialize_import_key_req, + serialize_import_key_resp, + deserialize_sign_hash_req, + serialize_sign_hash_resp, + deserialize_verify_hash_req, + deserialize_asymmetric_decrypt_req, + serialize_asymmetric_decrypt_resp, + deserialize_asymmetric_encrypt_req, + serialize_asymmetric_encrypt_resp, + deserialize_generate_random_req, + serialize_generate_random_resp + }; + + return &instance; +} diff --git a/components/service/crypto/provider/serializer/packed-c/packedc_crypto_provider_serializer.h b/components/service/crypto/provider/serializer/packed-c/packedc_crypto_provider_serializer.h new file mode 100644 index 000000000..2fdac43f7 --- /dev/null +++ b/components/service/crypto/provider/serializer/packed-c/packedc_crypto_provider_serializer.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PACKEDC_CRYPTO_PROVIDER_SERIALIZER_H +#define PACKEDC_CRYPTO_PROVIDER_SERIALIZER_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Singleton method to provide access to the packed-c serializer + * for the crypto service provider. + */ +const struct crypto_provider_serializer *packedc_crypto_provider_serializer_instance(void); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* PACKEDC_CRYPTO_PROVIDER_SERIALIZER_H */ diff --git a/components/service/crypto/provider/serializer/packed-c/packedc_key_attributes_translator.c b/components/service/crypto/provider/serializer/packed-c/packedc_key_attributes_translator.c new file mode 100644 index 000000000..cb88ceca4 --- /dev/null +++ b/components/service/crypto/provider/serializer/packed-c/packedc_key_attributes_translator.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include "packedc_key_attributes_translator.h" + +void packedc_crypto_provider_translate_key_attributes(psa_key_attributes_t *psa_attributes, + const struct ts_crypto_key_attributes *proto_attributes) { + + psa_set_key_type(psa_attributes, proto_attributes->type); + psa_set_key_bits(psa_attributes, proto_attributes->key_bits); + psa_set_key_lifetime(psa_attributes, proto_attributes->lifetime); + + if (proto_attributes->lifetime == PSA_KEY_LIFETIME_PERSISTENT) { + + psa_set_key_id(psa_attributes, proto_attributes->id); + } + + psa_set_key_usage_flags(psa_attributes, proto_attributes->policy.usage); + psa_set_key_algorithm(psa_attributes, proto_attributes->policy.alg); +} diff --git a/components/service/crypto/provider/serializer/packed-c/packedc_key_attributes_translator.h b/components/service/crypto/provider/serializer/packed-c/packedc_key_attributes_translator.h new file mode 100644 index 000000000..ae8871d82 --- /dev/null +++ b/components/service/crypto/provider/serializer/packed-c/packedc_key_attributes_translator.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PACKEDC_CRYPTO_PROVIDER_KEY_ATTRIBUTES_TRANSLATOR_H +#define PACKEDC_CRYPTO_PROVIDER_KEY_ATTRIBUTES_TRANSLATOR_H + +#include +#include + +void packedc_crypto_provider_translate_key_attributes( + psa_key_attributes_t *psa_attributes, + const struct ts_crypto_key_attributes *proto_attributes); + +#endif /* PACKEDC_CRYPTO_PROVIDER_KEY_ATTRIBUTES_TRANSLATOR_H */ \ No newline at end of file diff --git a/components/service/crypto/provider/serializer/protobuf/component.cmake b/components/service/crypto/provider/serializer/protobuf/component.cmake index 2a075b74d..f2772bd52 100644 --- a/components/service/crypto/provider/serializer/protobuf/component.cmake +++ b/components/service/crypto/provider/serializer/protobuf/component.cmake @@ -12,9 +12,3 @@ target_sources(${TGT} PRIVATE "${CMAKE_CURRENT_LIST_DIR}/pb_crypto_provider_serializer.c" "${CMAKE_CURRENT_LIST_DIR}/pb_key_attributes_translator.c" ) - - -target_include_directories(${TGT} - PRIVATE - "${CMAKE_CURRENT_LIST_DIR}" - ) diff --git a/components/service/crypto/provider/serializer/protobuf/pb_crypto_provider_serializer.c b/components/service/crypto/provider/serializer/protobuf/pb_crypto_provider_serializer.c index 2cf38fee8..a2631eafe 100644 --- a/components/service/crypto/provider/serializer/protobuf/pb_crypto_provider_serializer.c +++ b/components/service/crypto/provider/serializer/protobuf/pb_crypto_provider_serializer.c @@ -29,7 +29,7 @@ static size_t max_deserialised_parameter_size(const struct call_param_buf *req_buf) { /* - * Assume that a deserialized parameter must be the same size or smalled than the + * Assume that a deserialized parameter must be the same size or smaller than the * entire serialized message. */ return req_buf->data_len; diff --git a/components/service/crypto/provider/serializer/protobuf/pb_crypto_provider_serializer.h b/components/service/crypto/provider/serializer/protobuf/pb_crypto_provider_serializer.h index 64191c02d..08ca2f0bb 100644 --- a/components/service/crypto/provider/serializer/protobuf/pb_crypto_provider_serializer.h +++ b/components/service/crypto/provider/serializer/protobuf/pb_crypto_provider_serializer.h @@ -13,10 +13,11 @@ extern "C" { #endif -/* Singleton method to provide access to the Protobuf serializer +/* + * Singleton method to provide access to the Protobuf serializer * for the crypto service provider. */ -extern const struct crypto_provider_serializer *pb_crypto_provider_serializer_instance(void); +const struct crypto_provider_serializer *pb_crypto_provider_serializer_instance(void); #ifdef __cplusplus } /* extern "C" */ diff --git a/components/service/crypto/provider/serializer/protobuf/pb_key_attributes_translator.h b/components/service/crypto/provider/serializer/protobuf/pb_key_attributes_translator.h index 5de359bb3..ef77c7390 100644 --- a/components/service/crypto/provider/serializer/protobuf/pb_key_attributes_translator.h +++ b/components/service/crypto/provider/serializer/protobuf/pb_key_attributes_translator.h @@ -10,7 +10,7 @@ #include #include -extern void pb_crypto_provider_translate_key_attributes( +void pb_crypto_provider_translate_key_attributes( psa_key_attributes_t *psa_attributes, const ts_crypto_KeyAttributes *proto_attributes); diff --git a/components/service/crypto/test/protocol/check_crypto_opcode_alignment.cpp b/components/service/crypto/test/protocol/check_crypto_opcode_alignment.cpp new file mode 100644 index 000000000..40910fad7 --- /dev/null +++ b/components/service/crypto/test/protocol/check_crypto_opcode_alignment.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include + +/* + * Check alignment of Crypto service opcode definitions + */ +TEST_GROUP(CryptoProtocolOpcodeChecks) +{ + +}; + +TEST(CryptoProtocolOpcodeChecks, checkPackedcToProtobuf) +{ + CHECK_EQUAL(TS_CRYPTO_OPCODE_GENERATE_KEY, ts_crypto_Opcode_GENERATE_KEY); + CHECK_EQUAL(TS_CRYPTO_OPCODE_DESTROY_KEY, ts_crypto_Opcode_DESTROY_KEY); + CHECK_EQUAL(TS_CRYPTO_OPCODE_OPEN_KEY, ts_crypto_Opcode_OPEN_KEY); + CHECK_EQUAL(TS_CRYPTO_OPCODE_CLOSE_KEY, ts_crypto_Opcode_CLOSE_KEY); + CHECK_EQUAL(TS_CRYPTO_OPCODE_EXPORT_KEY, ts_crypto_Opcode_EXPORT_KEY); + CHECK_EQUAL(TS_CRYPTO_OPCODE_EXPORT_PUBLIC_KEY, ts_crypto_Opcode_EXPORT_PUBLIC_KEY); + CHECK_EQUAL(TS_CRYPTO_OPCODE_IMPORT_KEY, ts_crypto_Opcode_IMPORT_KEY); + CHECK_EQUAL(TS_CRYPTO_OPCODE_SIGN_HASH, ts_crypto_Opcode_SIGN_HASH); + CHECK_EQUAL(TS_CRYPTO_OPCODE_VERIFY_HASH, ts_crypto_Opcode_VERIFY_HASH); + CHECK_EQUAL(TS_CRYPTO_OPCODE_ASYMMETRIC_DECRYPT, ts_crypto_Opcode_ASYMMETRIC_DECRYPT); + CHECK_EQUAL(TS_CRYPTO_OPCODE_ASYMMETRIC_ENCRYPT, ts_crypto_Opcode_ASYMMETRIC_ENCRYPT); + CHECK_EQUAL(TS_CRYPTO_OPCODE_GENERATE_RANDOM, ts_crypto_Opcode_GENERATE_RANDOM); +} + diff --git a/components/service/crypto/test/protocol/check_crypto_packed-c_protocol_alignment.cpp b/components/service/crypto/test/protocol/check_crypto_packed-c_protocol_alignment.cpp new file mode 100644 index 000000000..ff7ee0f86 --- /dev/null +++ b/components/service/crypto/test/protocol/check_crypto_packed-c_protocol_alignment.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include + +/* + * Check alignment of Crypto service packed-c protocol definitions for + * alignment with PSA C API definitions. + */ +TEST_GROUP(CryptoProtocolPackedcChecks) +{ + +}; + +TEST(CryptoProtocolPackedcChecks, checkKeyType) +{ + /* + * Check alignment between PSA and protobuf key type definitions + */ + CHECK_EQUAL(PSA_KEY_TYPE_RAW_DATA, TS_CRYPTO_KEY_TYPE_RAW_DATA); + CHECK_EQUAL(PSA_KEY_TYPE_HMAC, TS_CRYPTO_KEY_TYPE_HMAC); + CHECK_EQUAL(PSA_KEY_TYPE_DERIVE, TS_CRYPTO_KEY_TYPE_DERIVE); + CHECK_EQUAL(PSA_KEY_TYPE_AES, TS_CRYPTO_KEY_TYPE_AES); + CHECK_EQUAL(PSA_KEY_TYPE_DES, TS_CRYPTO_KEY_TYPE_DES); + CHECK_EQUAL(PSA_KEY_TYPE_CAMELLIA, TS_CRYPTO_KEY_TYPE_CAMELLIA); + CHECK_EQUAL(PSA_KEY_TYPE_ARC4, TS_CRYPTO_KEY_TYPE_ARC4); + CHECK_EQUAL(PSA_KEY_TYPE_CHACHA20, TS_CRYPTO_KEY_TYPE_CHACHA20); + CHECK_EQUAL(PSA_KEY_TYPE_RSA_PUBLIC_KEY, TS_CRYPTO_KEY_TYPE_RSA_PUBLIC_KEY); + CHECK_EQUAL(PSA_KEY_TYPE_RSA_KEY_PAIR, TS_CRYPTO_KEY_TYPE_RSA_KEY_PAIR); + CHECK_EQUAL(PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE, TS_CRYPTO_KEY_TYPE_ECC_PUBLIC_KEY_BASE); + CHECK_EQUAL(PSA_KEY_TYPE_ECC_KEY_PAIR_BASE, TS_CRYPTO_KEY_TYPE_ECC_KEY_PAIR_BASE); + CHECK_EQUAL(PSA_KEY_TYPE_ECC_CURVE_MASK, TS_CRYPTO_KEY_TYPE_ECC_CURVE_MASK); + CHECK_EQUAL(PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE, TS_CRYPTO_KEY_TYPE_DH_PUBLIC_KEY_BASE); + CHECK_EQUAL(PSA_KEY_TYPE_DH_KEY_PAIR_BASE, TS_CRYPTO_KEY_TYPE_DH_KEY_PAIR_BASE); + CHECK_EQUAL(PSA_KEY_TYPE_DH_GROUP_MASK, TS_CRYPTO_KEY_TYPE_DH_GROUP_MASK); +} + +TEST(CryptoProtocolPackedcChecks, checkEccCurve) +{ + /* + * ECC curves for use with ECC Key types + */ + CHECK_EQUAL(PSA_ECC_CURVE_SECP_K1, TS_CRYPTO_ECC_CURVE_SECP_K1); + CHECK_EQUAL(PSA_ECC_CURVE_SECP_R1, TS_CRYPTO_ECC_CURVE_SECP_R1); + CHECK_EQUAL(PSA_ECC_CURVE_SECP_R2, TS_CRYPTO_ECC_CURVE_SECP_R2); + CHECK_EQUAL(PSA_ECC_CURVE_SECT_K1, TS_CRYPTO_ECC_CURVE_SECT_K1); + CHECK_EQUAL(PSA_ECC_CURVE_SECT_R1, TS_CRYPTO_ECC_CURVE_SECT_R1); + CHECK_EQUAL(PSA_ECC_CURVE_SECT_R2, TS_CRYPTO_ECC_CURVE_SECT_R2); + CHECK_EQUAL(PSA_ECC_CURVE_BRAINPOOL_P_R1, TS_CRYPTO_ECC_CURVE_BRAINPOOL_P_R1); + CHECK_EQUAL(PSA_ECC_CURVE_MONTGOMERY, TS_CRYPTO_ECC_CURVE_MONTGOMERY); +} + +TEST(CryptoProtocolPackedcChecks, checkDhGroup) +{ + /* + * Diffie-Hellman groups for use with DH key types + */ + CHECK_EQUAL(PSA_DH_GROUP_RFC7919, TS_CRYPTO_DH_GROUP_RFC7919); +} + +TEST(CryptoProtocolPackedcChecks, checkAlg) +{ + /* + * Crypto algorithms + */ + CHECK_EQUAL(PSA_ALG_HASH_MASK, TS_CRYPTO_ALG_HASH_MASK); + CHECK_EQUAL(PSA_ALG_MD2, TS_CRYPTO_ALG_MD2); + CHECK_EQUAL(PSA_ALG_MD4, TS_CRYPTO_ALG_MD4); + CHECK_EQUAL(PSA_ALG_MD5, TS_CRYPTO_ALG_MD5); + CHECK_EQUAL(PSA_ALG_RIPEMD160, TS_CRYPTO_ALG_RIPEMD160); + CHECK_EQUAL(PSA_ALG_SHA_1, TS_CRYPTO_ALG_SHA_1); + CHECK_EQUAL(PSA_ALG_SHA_224, TS_CRYPTO_ALG_SHA_224); + CHECK_EQUAL(PSA_ALG_SHA_256, TS_CRYPTO_ALG_SHA_256); + CHECK_EQUAL(PSA_ALG_SHA_384, TS_CRYPTO_ALG_SHA_384); + CHECK_EQUAL(PSA_ALG_SHA_512, TS_CRYPTO_ALG_SHA_512); + CHECK_EQUAL(PSA_ALG_SHA_512_224, TS_CRYPTO_ALG_SHA_512_224); + CHECK_EQUAL(PSA_ALG_SHA_512_256, TS_CRYPTO_ALG_SHA_512_256); + CHECK_EQUAL(PSA_ALG_SHA3_224, TS_CRYPTO_ALG_SHA3_224); + CHECK_EQUAL(PSA_ALG_SHA3_256, TS_CRYPTO_ALG_SHA3_256); + CHECK_EQUAL(PSA_ALG_SHA3_384, TS_CRYPTO_ALG_SHA3_384); + CHECK_EQUAL(PSA_ALG_SHA3_512, TS_CRYPTO_ALG_SHA3_512); + CHECK_EQUAL(PSA_ALG_CBC_MAC, TS_CRYPTO_ALG_CBC_MAC); + CHECK_EQUAL(PSA_ALG_CMAC, TS_CRYPTO_ALG_CMAC); + CHECK_EQUAL(PSA_ALG_ARC4, TS_CRYPTO_ALG_ARC4); + CHECK_EQUAL(PSA_ALG_CHACHA20, TS_CRYPTO_ALG_CHACHA20); + CHECK_EQUAL(PSA_ALG_CTR, TS_CRYPTO_ALG_CTR); + CHECK_EQUAL(PSA_ALG_CFB, TS_CRYPTO_ALG_CFB); + CHECK_EQUAL(PSA_ALG_OFB, TS_CRYPTO_ALG_OFB); + CHECK_EQUAL(PSA_ALG_XTS, TS_CRYPTO_ALG_XTS); + CHECK_EQUAL(PSA_ALG_CBC_NO_PADDING, TS_CRYPTO_ALG_CBC_NO_PADDING); + CHECK_EQUAL(PSA_ALG_CBC_PKCS7, TS_CRYPTO_ALG_CBC_PKCS7); + CHECK_EQUAL(PSA_ALG_AEAD_FROM_BLOCK_FLAG, TS_CRYPTO_ALG_AEAD_FROM_BLOCK_FLAG); + CHECK_EQUAL(PSA_ALG_CCM, TS_CRYPTO_ALG_CCM); + CHECK_EQUAL(PSA_ALG_GCM, TS_CRYPTO_ALG_GCM); + CHECK_EQUAL(PSA_ALG_CHACHA20_POLY1305, TS_CRYPTO_ALG_CHACHA20_POLY1305); + CHECK_EQUAL(PSA_ALG_RSA_PKCS1V15_SIGN_BASE, TS_CRYPTO_ALG_RSA_PKCS1V15_SIGN_BASE); + CHECK_EQUAL(PSA_ALG_RSA_PSS_BASE, TS_CRYPTO_ALG_RSA_PSS_BASE); + CHECK_EQUAL(PSA_ALG_ECDSA_BASE, TS_CRYPTO_ALG_ECDSA_BASE); + CHECK_EQUAL(PSA_ALG_DETERMINISTIC_ECDSA_BASE, TS_CRYPTO_ALG_DETERMINISTIC_ECDSA_BASE); + CHECK_EQUAL(PSA_ALG_RSA_PKCS1V15_CRYPT, TS_CRYPTO_ALG_RSA_PKCS1V15_CRYPT); + CHECK_EQUAL(PSA_ALG_RSA_OAEP_BASE, TS_CRYPTO_ALG_RSA_OAEP_BASE); + CHECK_EQUAL(PSA_ALG_HKDF_BASE, TS_CRYPTO_ALG_HKDF_BASE); + CHECK_EQUAL(PSA_ALG_TLS12_PRF_BASE, TS_CRYPTO_ALG_TLS12_PRF_BASE); + CHECK_EQUAL(PSA_ALG_TLS12_PSK_TO_MS_BASE, TS_CRYPTO_ALG_TLS12_PSK_TO_MS_BASE); + CHECK_EQUAL(PSA_ALG_KEY_DERIVATION_MASK, TS_CRYPTO_ALG_KEY_DERIVATION_MASK); + CHECK_EQUAL(PSA_ALG_KEY_AGREEMENT_MASK, TS_CRYPTO_ALG_KEY_AGREEMENT_MASK); + CHECK_EQUAL(PSA_ALG_FFDH, TS_CRYPTO_ALG_FFDH); + CHECK_EQUAL(PSA_ALG_ECDH, TS_CRYPTO_ALG_ECDH); +} + +TEST(CryptoProtocolPackedcChecks, checkKeyLifetime) +{ + /* + * Key lifetime + */ + CHECK_EQUAL(PSA_KEY_LIFETIME_VOLATILE, TS_CRYPTO_KEY_LIFETIME_VOLATILE); + CHECK_EQUAL(PSA_KEY_LIFETIME_PERSISTENT, TS_CRYPTO_KEY_LIFETIME_PERSISTENT); +} + +TEST(CryptoProtocolPackedcChecks, checkKeyUsage) +{ + /* + * Key usage constraints + */ + CHECK_EQUAL(PSA_KEY_USAGE_EXPORT, TS_CRYPTO_KEY_USAGE_EXPORT); + CHECK_EQUAL(PSA_KEY_USAGE_COPY, TS_CRYPTO_KEY_USAGE_COPY); + CHECK_EQUAL(PSA_KEY_USAGE_ENCRYPT, TS_CRYPTO_KEY_USAGE_ENCRYPT); + CHECK_EQUAL(PSA_KEY_USAGE_DECRYPT, TS_CRYPTO_KEY_USAGE_DECRYPT); + CHECK_EQUAL(PSA_KEY_USAGE_SIGN_HASH, TS_CRYPTO_KEY_USAGE_SIGN_HASH); + CHECK_EQUAL(PSA_KEY_USAGE_VERIFY_HASH, TS_CRYPTO_KEY_USAGE_VERIFY_HASH); + CHECK_EQUAL(PSA_KEY_USAGE_DERIVE, TS_CRYPTO_KEY_USAGE_DERIVE); +} \ No newline at end of file diff --git a/components/service/crypto/test/protocol/check_crypto_protobuf_protocol_alignment.cpp b/components/service/crypto/test/protocol/check_crypto_protobuf_protocol_alignment.cpp new file mode 100644 index 000000000..16f8cba5f --- /dev/null +++ b/components/service/crypto/test/protocol/check_crypto_protobuf_protocol_alignment.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include + +/* + * Check alignment of Crypto service protobuf protocol definitions for + * alignment with PSA C API definitions. + */ +TEST_GROUP(CryptoProtocolProtobufChecks) +{ + +}; + +TEST(CryptoProtocolProtobufChecks, checkKeyType) +{ + /* + * Check alignment between PSA and protobuf key type definitions + */ + CHECK_EQUAL(PSA_KEY_TYPE_RAW_DATA, ts_crypto_KeyType_KEY_TYPE_RAW_DATA); + CHECK_EQUAL(PSA_KEY_TYPE_HMAC, ts_crypto_KeyType_KEY_TYPE_HMAC); + CHECK_EQUAL(PSA_KEY_TYPE_DERIVE, ts_crypto_KeyType_KEY_TYPE_DERIVE); + CHECK_EQUAL(PSA_KEY_TYPE_AES, ts_crypto_KeyType_KEY_TYPE_AES); + CHECK_EQUAL(PSA_KEY_TYPE_DES, ts_crypto_KeyType_KEY_TYPE_DES); + CHECK_EQUAL(PSA_KEY_TYPE_CAMELLIA, ts_crypto_KeyType_KEY_TYPE_CAMELLIA); + CHECK_EQUAL(PSA_KEY_TYPE_ARC4, ts_crypto_KeyType_KEY_TYPE_ARC4); + CHECK_EQUAL(PSA_KEY_TYPE_CHACHA20, ts_crypto_KeyType_KEY_TYPE_CHACHA20); + CHECK_EQUAL(PSA_KEY_TYPE_RSA_PUBLIC_KEY, ts_crypto_KeyType_KEY_TYPE_RSA_PUBLIC_KEY); + CHECK_EQUAL(PSA_KEY_TYPE_RSA_KEY_PAIR, ts_crypto_KeyType_KEY_TYPE_RSA_KEY_PAIR); + CHECK_EQUAL(PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE, ts_crypto_KeyType_KEY_TYPE_ECC_PUBLIC_KEY_BASE); + CHECK_EQUAL(PSA_KEY_TYPE_ECC_KEY_PAIR_BASE, ts_crypto_KeyType_KEY_TYPE_ECC_KEY_PAIR_BASE); + CHECK_EQUAL(PSA_KEY_TYPE_ECC_CURVE_MASK, ts_crypto_KeyType_KEY_TYPE_ECC_CURVE_MASK); + CHECK_EQUAL(PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE, ts_crypto_KeyType_KEY_TYPE_DH_PUBLIC_KEY_BASE); + CHECK_EQUAL(PSA_KEY_TYPE_DH_KEY_PAIR_BASE, ts_crypto_KeyType_KEY_TYPE_DH_KEY_PAIR_BASE); + CHECK_EQUAL(PSA_KEY_TYPE_DH_GROUP_MASK, ts_crypto_KeyType_KEY_TYPE_DH_GROUP_MASK); +} + +TEST(CryptoProtocolProtobufChecks, checkEccCurve) +{ + /* + * ECC curves for use with ECC Key types + */ + CHECK_EQUAL(PSA_ECC_CURVE_SECP_K1, ts_crypto_EccCurve_ECC_CURVE_SECP_K1); + CHECK_EQUAL(PSA_ECC_CURVE_SECP_R1, ts_crypto_EccCurve_ECC_CURVE_SECP_R1); + CHECK_EQUAL(PSA_ECC_CURVE_SECP_R2, ts_crypto_EccCurve_ECC_CURVE_SECP_R2); + CHECK_EQUAL(PSA_ECC_CURVE_SECT_K1, ts_crypto_EccCurve_ECC_CURVE_SECT_K1); + CHECK_EQUAL(PSA_ECC_CURVE_SECT_R1, ts_crypto_EccCurve_ECC_CURVE_SECT_R1); + CHECK_EQUAL(PSA_ECC_CURVE_SECT_R2, ts_crypto_EccCurve_ECC_CURVE_SECT_R2); + CHECK_EQUAL(PSA_ECC_CURVE_BRAINPOOL_P_R1, ts_crypto_EccCurve_ECC_CURVE_BRAINPOOL_P_R1); + CHECK_EQUAL(PSA_ECC_CURVE_MONTGOMERY, ts_crypto_EccCurve_ECC_CURVE_MONTGOMERY); +} + +TEST(CryptoProtocolProtobufChecks, checkDhGroup) +{ + /* + * Diffie-Hellman groups for use with DH key types + */ + CHECK_EQUAL(PSA_DH_GROUP_RFC7919, ts_crypto_DhGroup_DH_GROUP_RFC7919); +} + +TEST(CryptoProtocolProtobufChecks, checkAlg) +{ + /* + * Crypto algorithms + */ + CHECK_EQUAL(PSA_ALG_HASH_MASK, ts_crypto_Alg_ALG_HASH_MASK); + CHECK_EQUAL(PSA_ALG_MD2, ts_crypto_Alg_ALG_MD2); + CHECK_EQUAL(PSA_ALG_MD4, ts_crypto_Alg_ALG_MD4); + CHECK_EQUAL(PSA_ALG_MD5, ts_crypto_Alg_ALG_MD5); + CHECK_EQUAL(PSA_ALG_RIPEMD160, ts_crypto_Alg_ALG_RIPEMD160); + CHECK_EQUAL(PSA_ALG_SHA_1, ts_crypto_Alg_ALG_SHA_1); + CHECK_EQUAL(PSA_ALG_SHA_224, ts_crypto_Alg_ALG_SHA_224); + CHECK_EQUAL(PSA_ALG_SHA_256, ts_crypto_Alg_ALG_SHA_256); + CHECK_EQUAL(PSA_ALG_SHA_384, ts_crypto_Alg_ALG_SHA_384); + CHECK_EQUAL(PSA_ALG_SHA_512, ts_crypto_Alg_ALG_SHA_512); + CHECK_EQUAL(PSA_ALG_SHA_512_224, ts_crypto_Alg_ALG_SHA_512_224); + CHECK_EQUAL(PSA_ALG_SHA_512_256, ts_crypto_Alg_ALG_SHA_512_256); + CHECK_EQUAL(PSA_ALG_SHA3_224, ts_crypto_Alg_ALG_SHA3_224); + CHECK_EQUAL(PSA_ALG_SHA3_256, ts_crypto_Alg_ALG_SHA3_256); + CHECK_EQUAL(PSA_ALG_SHA3_384, ts_crypto_Alg_ALG_SHA3_384); + CHECK_EQUAL(PSA_ALG_SHA3_512, ts_crypto_Alg_ALG_SHA3_512); + CHECK_EQUAL(PSA_ALG_CBC_MAC, ts_crypto_Alg_ALG_CBC_MAC); + CHECK_EQUAL(PSA_ALG_CMAC, ts_crypto_Alg_ALG_CMAC); + CHECK_EQUAL(PSA_ALG_ARC4, ts_crypto_Alg_ALG_ARC4); + CHECK_EQUAL(PSA_ALG_CHACHA20, ts_crypto_Alg_ALG_CHACHA20); + CHECK_EQUAL(PSA_ALG_CTR, ts_crypto_Alg_ALG_CTR); + CHECK_EQUAL(PSA_ALG_CFB, ts_crypto_Alg_ALG_CFB); + CHECK_EQUAL(PSA_ALG_OFB, ts_crypto_Alg_ALG_OFB); + CHECK_EQUAL(PSA_ALG_XTS, ts_crypto_Alg_ALG_XTS); + CHECK_EQUAL(PSA_ALG_CBC_NO_PADDING, ts_crypto_Alg_ALG_CBC_NO_PADDING); + CHECK_EQUAL(PSA_ALG_CBC_PKCS7, ts_crypto_Alg_ALG_CBC_PKCS7); + CHECK_EQUAL(PSA_ALG_AEAD_FROM_BLOCK_FLAG, ts_crypto_Alg_ALG_AEAD_FROM_BLOCK_FLAG); + CHECK_EQUAL(PSA_ALG_CCM, ts_crypto_Alg_ALG_CCM); + CHECK_EQUAL(PSA_ALG_GCM, ts_crypto_Alg_ALG_GCM); + CHECK_EQUAL(PSA_ALG_CHACHA20_POLY1305, ts_crypto_Alg_ALG_CHACHA20_POLY1305); + CHECK_EQUAL(PSA_ALG_RSA_PKCS1V15_SIGN_BASE, ts_crypto_Alg_ALG_RSA_PKCS1V15_SIGN_BASE); + CHECK_EQUAL(PSA_ALG_RSA_PSS_BASE, ts_crypto_Alg_ALG_RSA_PSS_BASE); + CHECK_EQUAL(PSA_ALG_ECDSA_BASE, ts_crypto_Alg_ALG_ECDSA_BASE); + CHECK_EQUAL(PSA_ALG_DETERMINISTIC_ECDSA_BASE, ts_crypto_Alg_ALG_DETERMINISTIC_ECDSA_BASE); + CHECK_EQUAL(PSA_ALG_RSA_PKCS1V15_CRYPT, ts_crypto_Alg_ALG_RSA_PKCS1V15_CRYPT); + CHECK_EQUAL(PSA_ALG_RSA_OAEP_BASE, ts_crypto_Alg_ALG_RSA_OAEP_BASE); + CHECK_EQUAL(PSA_ALG_HKDF_BASE, ts_crypto_Alg_ALG_HKDF_BASE); + CHECK_EQUAL(PSA_ALG_TLS12_PRF_BASE, ts_crypto_Alg_ALG_TLS12_PRF_BASE); + CHECK_EQUAL(PSA_ALG_TLS12_PSK_TO_MS_BASE, ts_crypto_Alg_ALG_TLS12_PSK_TO_MS_BASE); + CHECK_EQUAL(PSA_ALG_KEY_DERIVATION_MASK, ts_crypto_Alg_ALG_KEY_DERIVATION_MASK); + CHECK_EQUAL(PSA_ALG_KEY_AGREEMENT_MASK, ts_crypto_Alg_ALG_KEY_AGREEMENT_MASK); + CHECK_EQUAL(PSA_ALG_FFDH, ts_crypto_Alg_ALG_FFDH); + CHECK_EQUAL(PSA_ALG_ECDH, ts_crypto_Alg_ALG_ECDH); +} + +TEST(CryptoProtocolProtobufChecks, checkKeyLifetime) +{ + /* + * Key lifetime + */ + CHECK_EQUAL(PSA_KEY_LIFETIME_VOLATILE, ts_crypto_KeyLifetime_KEY_LIFETIME_VOLATILE); + CHECK_EQUAL(PSA_KEY_LIFETIME_PERSISTENT, ts_crypto_KeyLifetime_KEY_LIFETIME_PERSISTENT); +} + +TEST(CryptoProtocolProtobufChecks, checkKeyUsage) +{ + /* + * Key usage constraints + */ + CHECK_EQUAL(PSA_KEY_USAGE_EXPORT, ts_crypto_KeyUsage_KEY_USAGE_EXPORT); + CHECK_EQUAL(PSA_KEY_USAGE_COPY, ts_crypto_KeyUsage_KEY_USAGE_COPY); + CHECK_EQUAL(PSA_KEY_USAGE_ENCRYPT, ts_crypto_KeyUsage_KEY_USAGE_ENCRYPT); + CHECK_EQUAL(PSA_KEY_USAGE_DECRYPT, ts_crypto_KeyUsage_KEY_USAGE_DECRYPT); + CHECK_EQUAL(PSA_KEY_USAGE_SIGN_HASH, ts_crypto_KeyUsage_KEY_USAGE_SIGN_HASH); + CHECK_EQUAL(PSA_KEY_USAGE_VERIFY_HASH, ts_crypto_KeyUsage_KEY_USAGE_VERIFY_HASH); + CHECK_EQUAL(PSA_KEY_USAGE_DERIVE, ts_crypto_KeyUsage_KEY_USAGE_DERIVE); +} diff --git a/components/service/crypto/test/protocol/component.cmake b/components/service/crypto/test/protocol/component.cmake new file mode 100644 index 000000000..ed590bc94 --- /dev/null +++ b/components/service/crypto/test/protocol/component.cmake @@ -0,0 +1,16 @@ +#------------------------------------------------------------------------------- +# Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +#------------------------------------------------------------------------------- +if (NOT DEFINED TGT) + message(FATAL_ERROR "mandatory parameter TGT is not defined.") +endif() + +target_sources(${TGT} PRIVATE + "${CMAKE_CURRENT_LIST_DIR}/check_crypto_opcode_alignment.cpp" + "${CMAKE_CURRENT_LIST_DIR}/check_crypto_protobuf_protocol_alignment.cpp" + "${CMAKE_CURRENT_LIST_DIR}/check_crypto_packed-c_protocol_alignment.cpp" + ) + diff --git a/components/service/crypto/test/service/component.cmake b/components/service/crypto/test/service/component.cmake index 26366fd36..8aad32042 100644 --- a/components/service/crypto/test/service/component.cmake +++ b/components/service/crypto/test/service/component.cmake @@ -1,5 +1,5 @@ #------------------------------------------------------------------------------- -# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. +# Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -9,7 +9,7 @@ if (NOT DEFINED TGT) endif() target_sources(${TGT} PRIVATE - "${CMAKE_CURRENT_LIST_DIR}/crypto_service_op_tests.cpp" + "${CMAKE_CURRENT_LIST_DIR}/crypto_service_scenarios.cpp" "${CMAKE_CURRENT_LIST_DIR}/crypto_service_limit_tests.cpp" ) diff --git a/components/service/crypto/test/service/crypto_service_limit_tests.cpp b/components/service/crypto/test/service/crypto_service_limit_tests.cpp index 392391a10..2bb19f99a 100644 --- a/components/service/crypto/test/service/crypto_service_limit_tests.cpp +++ b/components/service/crypto/test/service/crypto_service_limit_tests.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include #include @@ -36,7 +36,7 @@ TEST_GROUP(CryptoServiceLimitTests) m_rpc_session_handle = service_context_open(m_crypto_service_context, TS_RPC_ENCODING_PROTOBUF, &caller); CHECK(m_rpc_session_handle); - m_crypto_client = new crypto_client(caller); + m_crypto_client = new protobuf_crypto_client(caller); } void teardown() diff --git a/components/service/crypto/test/service/crypto_service_op_tests.cpp b/components/service/crypto/test/service/crypto_service_op_tests.cpp deleted file mode 100644 index 569a196c8..000000000 --- a/components/service/crypto/test/service/crypto_service_op_tests.cpp +++ /dev/null @@ -1,383 +0,0 @@ -/* - * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include -#include -#include -#include -#include -#include -#include - -/* - * Service-level tests that focus on exercising each supported operation. - * These are mainly valid behaviour tests with the goal of checking - * that the number of operations supported is as expected. - */ -TEST_GROUP(CryptoServiceOpTests) -{ - void setup() - { - struct rpc_caller *caller; - int status; - - m_rpc_session_handle = NULL; - m_crypto_service_context = NULL; - m_crypto_client = NULL; - - service_locator_init(); - - m_crypto_service_context = service_locator_query("sn:trustedfirmware.org:crypto:0", &status); - CHECK_TRUE(m_crypto_service_context); - - m_rpc_session_handle = service_context_open(m_crypto_service_context, TS_RPC_ENCODING_PROTOBUF, &caller); - CHECK_TRUE(m_rpc_session_handle); - - m_crypto_client = new crypto_client(caller); - } - - void teardown() - { - delete m_crypto_client; - m_crypto_client = NULL; - - service_context_close(m_crypto_service_context, m_rpc_session_handle); - m_rpc_session_handle = NULL; - - service_context_relinquish(m_crypto_service_context); - m_crypto_service_context = NULL; - } - - rpc_session_handle m_rpc_session_handle; - struct service_context *m_crypto_service_context; - crypto_client *m_crypto_client; -}; - -TEST(CryptoServiceOpTests, generateVolatileKeys) -{ - psa_status_t status; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - - psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE); - psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); - psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)); - psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1)); - psa_set_key_bits(&attributes, 256); - - /* Generate first key */ - psa_key_handle_t key_handle_1; - status = m_crypto_client->generate_key(&attributes, &key_handle_1); - CHECK_EQUAL(PSA_SUCCESS, status); - - /* And another */ - psa_key_handle_t key_handle_2; - status = m_crypto_client->generate_key(&attributes, &key_handle_2); - CHECK_EQUAL(PSA_SUCCESS, status); - - /* Expect the key handles to be different */ - CHECK(key_handle_1 != key_handle_2); - - /* Remove the keys */ - status = m_crypto_client->destroy_key(key_handle_1); - CHECK_EQUAL(PSA_SUCCESS, status); - status = m_crypto_client->destroy_key(key_handle_2); - CHECK_EQUAL(PSA_SUCCESS, status); - - psa_reset_key_attributes(&attributes); -} - -TEST(CryptoServiceOpTests, generatePersistentKeys) -{ - psa_status_t status; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - - psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); - psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)); - psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1)); - psa_set_key_bits(&attributes, 256); - - /* First try and generate a key with an invalid keu id */ - psa_key_id_t key_id_invalid = 0; - psa_set_key_id(&attributes, key_id_invalid); - psa_key_handle_t key_handle_invalid; - status = m_crypto_client->generate_key(&attributes, &key_handle_invalid); - CHECK_EQUAL(PSA_ERROR_INVALID_ARGUMENT, status); - - /* Generate first key */ - psa_key_id_t key_id_1 = 100000; - psa_set_key_id(&attributes, key_id_1); - psa_key_handle_t key_handle_1; - status = m_crypto_client->generate_key(&attributes, &key_handle_1); - CHECK_EQUAL(PSA_SUCCESS, status); - - /* And another */ - psa_key_id_t key_id_2 = 2; - psa_set_key_id(&attributes, key_id_2); - psa_key_handle_t key_handle_2; - status = m_crypto_client->generate_key(&attributes, &key_handle_2); - CHECK_EQUAL(PSA_SUCCESS, status); - - /* Expect the key handles to be different */ - CHECK(key_handle_1 != key_handle_2); - - /* Obtain more handles using key_open */ - psa_key_handle_t key_handle_3; - status = m_crypto_client->open_key(key_id_1, &key_handle_3); - CHECK_EQUAL(PSA_SUCCESS, status); - - psa_key_handle_t key_handle_4; - status = m_crypto_client->open_key(key_id_1, &key_handle_4); - CHECK_EQUAL(PSA_SUCCESS, status); - - /* Relinquish handles */ - status = m_crypto_client->close_key(key_handle_3); - CHECK_EQUAL(PSA_SUCCESS, status); - status = m_crypto_client->close_key(key_handle_4); - CHECK_EQUAL(PSA_SUCCESS, status); - - /* Expect close handle to now be invalid */ - status = m_crypto_client->close_key(key_handle_4); - CHECK_EQUAL(PSA_ERROR_INVALID_HANDLE, status); - - /* Remove the keys */ - status = m_crypto_client->destroy_key(key_handle_1); - CHECK_EQUAL(PSA_SUCCESS, status); - status = m_crypto_client->destroy_key(key_handle_2); - CHECK_EQUAL(PSA_SUCCESS, status); - - psa_reset_key_attributes(&attributes); -} - -TEST(CryptoServiceOpTests, exportPublicKey) -{ - psa_status_t status; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_key_handle_t key_handle; - - psa_set_key_id(&attributes, 10); - psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); - psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)); - psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1)); - psa_set_key_bits(&attributes, 256); - - /* Generate a key */ - status = m_crypto_client->generate_key(&attributes, &key_handle); - CHECK_EQUAL(PSA_SUCCESS, status); - - psa_reset_key_attributes(&attributes); - - /* Export the public key */ - uint8_t key_buf[PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(256)]; - size_t key_len = 0; - - status = m_crypto_client->export_public_key(key_handle, key_buf, sizeof(key_buf), &key_len); - CHECK_EQUAL(PSA_SUCCESS, status); - CHECK(key_len > 0); - - /* Remove the key */ - status = m_crypto_client->destroy_key(key_handle); - CHECK_EQUAL(PSA_SUCCESS, status); -} - -TEST(CryptoServiceOpTests, exportAndImportKeyPair) -{ - psa_status_t status; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_key_handle_t key_handle_1; - psa_key_handle_t key_handle_2; - - psa_set_key_id(&attributes, 11); - psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT); - psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)); - psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1)); - psa_set_key_bits(&attributes, 256); - - /* Generate a key */ - status = m_crypto_client->generate_key(&attributes, &key_handle_1); - CHECK_EQUAL(PSA_SUCCESS, status); - - /* Export the key pair */ - uint8_t key_buf[PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(256)]; - size_t key_len = 0; - - status = m_crypto_client->export_key(key_handle_1, key_buf, sizeof(key_buf), &key_len); - CHECK_EQUAL(PSA_SUCCESS, status); - CHECK(key_len > 0); - - /* Import the key pair value with a different key id */ - psa_set_key_id(&attributes, 12); - status = m_crypto_client->import_key(&attributes, key_buf, key_len, &key_handle_2); - CHECK_EQUAL(PSA_SUCCESS, status); - - psa_reset_key_attributes(&attributes); - - /* Remove the keys */ - status = m_crypto_client->destroy_key(key_handle_1); - CHECK_EQUAL(PSA_SUCCESS, status); - status = m_crypto_client->destroy_key(key_handle_2); - CHECK_EQUAL(PSA_SUCCESS, status); -} - -TEST(CryptoServiceOpTests, signAndVerifyHash) -{ - psa_status_t status; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_key_handle_t key_handle; - - psa_set_key_id(&attributes, 13); - psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH); - psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)); - psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1)); - psa_set_key_bits(&attributes, 256); - - /* Generate a key */ - status = m_crypto_client->generate_key(&attributes, &key_handle); - CHECK_EQUAL(PSA_SUCCESS, status); - - psa_reset_key_attributes(&attributes); - - /* Sign a hash */ - uint8_t hash[20]; - uint8_t signature[PSA_SIGNATURE_MAX_SIZE]; - size_t signature_length; - - memset(hash, 0x71, sizeof(hash)); - - status = m_crypto_client->sign_hash(key_handle, - PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256), hash, sizeof(hash), - signature, sizeof(signature), &signature_length); - - CHECK_EQUAL(PSA_SUCCESS, status); - CHECK(signature_length > 0); - - /* Verify the signature */ - status = m_crypto_client->verify_hash(key_handle, - PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256), hash, sizeof(hash), - signature, signature_length); - CHECK_EQUAL(PSA_SUCCESS, status); - - /* Change the hash and expect verify to fail */ - hash[0] = 0x72; - status = m_crypto_client->verify_hash(key_handle, - PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256), hash, sizeof(hash), - signature, signature_length); - CHECK_EQUAL(PSA_ERROR_INVALID_SIGNATURE, status); - - /* Remove the key */ - status = m_crypto_client->destroy_key(key_handle); - CHECK_EQUAL(PSA_SUCCESS, status); -} - -TEST(CryptoServiceOpTests, asymEncryptDecrypt) -{ - psa_status_t status; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_key_handle_t key_handle; - - psa_set_key_id(&attributes, 14); - psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT); - psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT); - psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR); - psa_set_key_bits(&attributes, 256); - - /* Generate a key */ - status = m_crypto_client->generate_key(&attributes, &key_handle); - CHECK_EQUAL(PSA_SUCCESS, status); - - psa_reset_key_attributes(&attributes); - - /* Encrypt a message */ - uint8_t message[] = {'q','u','i','c','k','b','r','o','w','n','f','o','x'}; - uint8_t ciphertext[256]; - size_t ciphertext_len = 0; - - status = m_crypto_client->asymmetric_encrypt(key_handle, PSA_ALG_RSA_PKCS1V15_CRYPT, - message, sizeof(message), NULL, 0, - ciphertext, sizeof(ciphertext), &ciphertext_len); - CHECK_EQUAL(PSA_SUCCESS, status); - - /* Decrypt it */ - uint8_t plaintext[256]; - size_t plaintext_len = 0; - - status = m_crypto_client->asymmetric_decrypt(key_handle, PSA_ALG_RSA_PKCS1V15_CRYPT, - ciphertext, ciphertext_len, NULL, 0, - plaintext, sizeof(plaintext), &plaintext_len); - CHECK_EQUAL(PSA_SUCCESS, status); - - /* Expect the encrypted/decrypted message to match theh original */ - CHECK_EQUAL(sizeof(message), plaintext_len); - CHECK(memcmp(message, plaintext, plaintext_len) == 0); - - /* Remove the key */ - status = m_crypto_client->destroy_key(key_handle); - CHECK_EQUAL(PSA_SUCCESS, status); -} - -TEST(CryptoServiceOpTests, generateRandomNumbers) -{ - psa_status_t status; - uint8_t num1_8bit[1]; - uint8_t num2_8bit[1]; - uint8_t num3_16bit[2]; - uint8_t num4_16bit[2]; - uint8_t num5_24bit[3]; - uint8_t num6_24bit[3]; - uint8_t num7_32bit[4]; - uint8_t num8_32bit[4]; - uint8_t num9_64bit[8]; - uint8_t num10_64bit[8]; - uint8_t num11_128bit[16]; - uint8_t num12_128bit[16]; - - /* Clear all buffers */ - memset(num1_8bit, 0, sizeof(num1_8bit)); - memset(num2_8bit, 0, sizeof(num2_8bit)); - memset(num3_16bit, 0, sizeof(num3_16bit)); - memset(num4_16bit, 0, sizeof(num4_16bit)); - memset(num5_24bit, 0, sizeof(num5_24bit)); - memset(num6_24bit, 0, sizeof(num6_24bit)); - memset(num7_32bit, 0, sizeof(num7_32bit)); - memset(num8_32bit, 0, sizeof(num8_32bit)); - memset(num9_64bit, 0, sizeof(num9_64bit)); - memset(num10_64bit, 0, sizeof(num10_64bit)); - memset(num11_128bit, 0, sizeof(num11_128bit)); - memset(num12_128bit, 0, sizeof(num12_128bit)); - - /* Generate some different size random numbers */ - status = m_crypto_client->generate_random(num1_8bit, sizeof(num1_8bit)); - CHECK_EQUAL(PSA_SUCCESS, status); - status = m_crypto_client->generate_random(num2_8bit, sizeof(num2_8bit)); - CHECK_EQUAL(PSA_SUCCESS, status); - status = m_crypto_client->generate_random(num3_16bit, sizeof(num3_16bit)); - CHECK_EQUAL(PSA_SUCCESS, status); - status = m_crypto_client->generate_random(num4_16bit, sizeof(num4_16bit)); - CHECK_EQUAL(PSA_SUCCESS, status); - status = m_crypto_client->generate_random(num5_24bit, sizeof(num5_24bit)); - CHECK_EQUAL(PSA_SUCCESS, status); - status = m_crypto_client->generate_random(num6_24bit, sizeof(num6_24bit)); - CHECK_EQUAL(PSA_SUCCESS, status); - status = m_crypto_client->generate_random(num7_32bit, sizeof(num7_32bit)); - CHECK_EQUAL(PSA_SUCCESS, status); - status = m_crypto_client->generate_random(num8_32bit, sizeof(num8_32bit)); - CHECK_EQUAL(PSA_SUCCESS, status); - status = m_crypto_client->generate_random(num9_64bit, sizeof(num9_64bit)); - CHECK_EQUAL(PSA_SUCCESS, status); - status = m_crypto_client->generate_random(num10_64bit, sizeof(num10_64bit)); - CHECK_EQUAL(PSA_SUCCESS, status); - status = m_crypto_client->generate_random(num11_128bit, sizeof(num11_128bit)); - CHECK_EQUAL(PSA_SUCCESS, status); - status = m_crypto_client->generate_random(num12_128bit, sizeof(num12_128bit)); - CHECK_EQUAL(PSA_SUCCESS, status); - - /* Expect different numbers to be generated */ - CHECK(memcmp(num1_8bit, num2_8bit, sizeof(num1_8bit)) != 0); - CHECK(memcmp(num3_16bit, num4_16bit, sizeof(num3_16bit)) != 0); - CHECK(memcmp(num5_24bit, num6_24bit, sizeof(num5_24bit)) != 0); - CHECK(memcmp(num7_32bit, num8_32bit, sizeof(num7_32bit)) != 0); - CHECK(memcmp(num9_64bit, num10_64bit, sizeof(num9_64bit)) != 0); - CHECK(memcmp(num11_128bit, num12_128bit, sizeof(num11_128bit)) != 0); -} diff --git a/components/service/crypto/test/service/crypto_service_scenarios.cpp b/components/service/crypto/test/service/crypto_service_scenarios.cpp new file mode 100644 index 000000000..80d727923 --- /dev/null +++ b/components/service/crypto/test/service/crypto_service_scenarios.cpp @@ -0,0 +1,348 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include "crypto_service_scenarios.h" + + +crypto_service_scenarios::crypto_service_scenarios(crypto_client *crypto_client) : + m_crypto_client(crypto_client) +{ + +} + +crypto_service_scenarios::~crypto_service_scenarios() +{ + delete m_crypto_client; + m_crypto_client = NULL; +} + +void crypto_service_scenarios::generateVolatileKeys() +{ + psa_status_t status; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + + psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); + psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)); + psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1)); + psa_set_key_bits(&attributes, 256); + + /* Generate first key */ + psa_key_handle_t key_handle_1; + status = m_crypto_client->generate_key(&attributes, &key_handle_1); + CHECK_EQUAL(PSA_SUCCESS, status); + + /* And another */ + psa_key_handle_t key_handle_2; + status = m_crypto_client->generate_key(&attributes, &key_handle_2); + CHECK_EQUAL(PSA_SUCCESS, status); + + /* Expect the key handles to be different */ + CHECK(key_handle_1 != key_handle_2); + + /* Remove the keys */ + status = m_crypto_client->destroy_key(key_handle_1); + CHECK_EQUAL(PSA_SUCCESS, status); + status = m_crypto_client->destroy_key(key_handle_2); + CHECK_EQUAL(PSA_SUCCESS, status); + + psa_reset_key_attributes(&attributes); +} + +void crypto_service_scenarios::generatePersistentKeys() +{ + psa_status_t status; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); + psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)); + psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1)); + psa_set_key_bits(&attributes, 256); + + /* First try and generate a key with an invalid keu id */ + psa_key_id_t key_id_invalid = 0; + psa_set_key_id(&attributes, key_id_invalid); + psa_key_handle_t key_handle_invalid; + status = m_crypto_client->generate_key(&attributes, &key_handle_invalid); + CHECK_EQUAL(PSA_ERROR_INVALID_ARGUMENT, status); + + /* Generate first key */ + psa_key_id_t key_id_1 = 100000; + psa_set_key_id(&attributes, key_id_1); + psa_key_handle_t key_handle_1; + status = m_crypto_client->generate_key(&attributes, &key_handle_1); + CHECK_EQUAL(PSA_SUCCESS, status); + + /* And another */ + psa_key_id_t key_id_2 = 2; + psa_set_key_id(&attributes, key_id_2); + psa_key_handle_t key_handle_2; + status = m_crypto_client->generate_key(&attributes, &key_handle_2); + CHECK_EQUAL(PSA_SUCCESS, status); + + /* Expect the key handles to be different */ + CHECK(key_handle_1 != key_handle_2); + + /* Obtain more handles using key_open */ + psa_key_handle_t key_handle_3; + status = m_crypto_client->open_key(key_id_1, &key_handle_3); + CHECK_EQUAL(PSA_SUCCESS, status); + + psa_key_handle_t key_handle_4; + status = m_crypto_client->open_key(key_id_1, &key_handle_4); + CHECK_EQUAL(PSA_SUCCESS, status); + + /* Relinquish handles */ + status = m_crypto_client->close_key(key_handle_3); + CHECK_EQUAL(PSA_SUCCESS, status); + status = m_crypto_client->close_key(key_handle_4); + CHECK_EQUAL(PSA_SUCCESS, status); + + /* Expect close handle to now be invalid */ + status = m_crypto_client->close_key(key_handle_4); + CHECK_EQUAL(PSA_ERROR_INVALID_HANDLE, status); + + /* Remove the keys */ + status = m_crypto_client->destroy_key(key_handle_1); + CHECK_EQUAL(PSA_SUCCESS, status); + status = m_crypto_client->destroy_key(key_handle_2); + CHECK_EQUAL(PSA_SUCCESS, status); + + psa_reset_key_attributes(&attributes); +} + +void crypto_service_scenarios::exportPublicKey() +{ + psa_status_t status; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_handle_t key_handle; + + psa_set_key_id(&attributes, 10); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); + psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)); + psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1)); + psa_set_key_bits(&attributes, 256); + + /* Generate a key */ + status = m_crypto_client->generate_key(&attributes, &key_handle); + CHECK_EQUAL(PSA_SUCCESS, status); + + psa_reset_key_attributes(&attributes); + + /* Export the public key */ + uint8_t key_buf[PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(256)]; + size_t key_len = 0; + + status = m_crypto_client->export_public_key(key_handle, key_buf, sizeof(key_buf), &key_len); + CHECK_EQUAL(PSA_SUCCESS, status); + CHECK_TRUE(key_len > 0); + + /* Remove the key */ + status = m_crypto_client->destroy_key(key_handle); + CHECK_EQUAL(PSA_SUCCESS, status); +} + +void crypto_service_scenarios::exportAndImportKeyPair() +{ + psa_status_t status; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_handle_t key_handle_1; + psa_key_handle_t key_handle_2; + + psa_set_key_id(&attributes, 11); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT); + psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)); + psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1)); + psa_set_key_bits(&attributes, 256); + + /* Generate a key */ + status = m_crypto_client->generate_key(&attributes, &key_handle_1); + CHECK_EQUAL(PSA_SUCCESS, status); + + /* Export the key pair */ + uint8_t key_buf[PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(256)]; + size_t key_len = 0; + + status = m_crypto_client->export_key(key_handle_1, key_buf, sizeof(key_buf), &key_len); + CHECK_EQUAL(PSA_SUCCESS, status); + CHECK(key_len > 0); + + /* Import the key pair value with a different key id */ + psa_set_key_id(&attributes, 12); + status = m_crypto_client->import_key(&attributes, key_buf, key_len, &key_handle_2); + CHECK_EQUAL(PSA_SUCCESS, status); + + psa_reset_key_attributes(&attributes); + + /* Remove the keys */ + status = m_crypto_client->destroy_key(key_handle_1); + CHECK_EQUAL(PSA_SUCCESS, status); + status = m_crypto_client->destroy_key(key_handle_2); + CHECK_EQUAL(PSA_SUCCESS, status); +} + +void crypto_service_scenarios::signAndVerifyHash() +{ + psa_status_t status; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_handle_t key_handle; + + psa_set_key_id(&attributes, 13); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH); + psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)); + psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1)); + psa_set_key_bits(&attributes, 256); + + /* Generate a key */ + status = m_crypto_client->generate_key(&attributes, &key_handle); + CHECK_EQUAL(PSA_SUCCESS, status); + + psa_reset_key_attributes(&attributes); + + /* Sign a hash */ + uint8_t hash[20]; + uint8_t signature[PSA_SIGNATURE_MAX_SIZE]; + size_t signature_length; + + memset(hash, 0x71, sizeof(hash)); + + status = m_crypto_client->sign_hash(key_handle, + PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256), hash, sizeof(hash), + signature, sizeof(signature), &signature_length); + + CHECK_EQUAL(PSA_SUCCESS, status); + CHECK(signature_length > 0); + + /* Verify the signature */ + status = m_crypto_client->verify_hash(key_handle, + PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256), hash, sizeof(hash), + signature, signature_length); + CHECK_EQUAL(PSA_SUCCESS, status); + + /* Change the hash and expect verify to fail */ + hash[0] = 0x72; + status = m_crypto_client->verify_hash(key_handle, + PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256), hash, sizeof(hash), + signature, signature_length); + CHECK_EQUAL(PSA_ERROR_INVALID_SIGNATURE, status); + + /* Remove the key */ + status = m_crypto_client->destroy_key(key_handle); + CHECK_EQUAL(PSA_SUCCESS, status); +} + +void crypto_service_scenarios::asymEncryptDecrypt() +{ + psa_status_t status; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_handle_t key_handle; + + psa_set_key_id(&attributes, 14); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT); + psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR); + psa_set_key_bits(&attributes, 256); + + /* Generate a key */ + status = m_crypto_client->generate_key(&attributes, &key_handle); + CHECK_EQUAL(PSA_SUCCESS, status); + + psa_reset_key_attributes(&attributes); + + /* Encrypt a message */ + uint8_t message[] = {'q','u','i','c','k','b','r','o','w','n','f','o','x'}; + uint8_t ciphertext[256]; + size_t ciphertext_len = 0; + + status = m_crypto_client->asymmetric_encrypt(key_handle, PSA_ALG_RSA_PKCS1V15_CRYPT, + message, sizeof(message), NULL, 0, + ciphertext, sizeof(ciphertext), &ciphertext_len); + CHECK_EQUAL(PSA_SUCCESS, status); + + /* Decrypt it */ + uint8_t plaintext[256]; + size_t plaintext_len = 0; + + status = m_crypto_client->asymmetric_decrypt(key_handle, PSA_ALG_RSA_PKCS1V15_CRYPT, + ciphertext, ciphertext_len, NULL, 0, + plaintext, sizeof(plaintext), &plaintext_len); + CHECK_EQUAL(PSA_SUCCESS, status); + + /* Expect the encrypted/decrypted message to match theh original */ + CHECK_EQUAL(sizeof(message), plaintext_len); + MEMCMP_EQUAL(message, plaintext, plaintext_len); + + /* Remove the key */ + status = m_crypto_client->destroy_key(key_handle); + CHECK_EQUAL(PSA_SUCCESS, status); +} + +void crypto_service_scenarios::generateRandomNumbers() +{ + psa_status_t status; + uint8_t num1_8bit[1]; + uint8_t num2_8bit[1]; + uint8_t num3_16bit[2]; + uint8_t num4_16bit[2]; + uint8_t num5_24bit[3]; + uint8_t num6_24bit[3]; + uint8_t num7_32bit[4]; + uint8_t num8_32bit[4]; + uint8_t num9_64bit[8]; + uint8_t num10_64bit[8]; + uint8_t num11_128bit[16]; + uint8_t num12_128bit[16]; + + /* Clear all buffers */ + memset(num1_8bit, 0, sizeof(num1_8bit)); + memset(num2_8bit, 0, sizeof(num2_8bit)); + memset(num3_16bit, 0, sizeof(num3_16bit)); + memset(num4_16bit, 0, sizeof(num4_16bit)); + memset(num5_24bit, 0, sizeof(num5_24bit)); + memset(num6_24bit, 0, sizeof(num6_24bit)); + memset(num7_32bit, 0, sizeof(num7_32bit)); + memset(num8_32bit, 0, sizeof(num8_32bit)); + memset(num9_64bit, 0, sizeof(num9_64bit)); + memset(num10_64bit, 0, sizeof(num10_64bit)); + memset(num11_128bit, 0, sizeof(num11_128bit)); + memset(num12_128bit, 0, sizeof(num12_128bit)); + + /* Generate some different size random numbers */ + status = m_crypto_client->generate_random(num1_8bit, sizeof(num1_8bit)); + CHECK_EQUAL(PSA_SUCCESS, status); + status = m_crypto_client->generate_random(num2_8bit, sizeof(num2_8bit)); + CHECK_EQUAL(PSA_SUCCESS, status); + status = m_crypto_client->generate_random(num3_16bit, sizeof(num3_16bit)); + CHECK_EQUAL(PSA_SUCCESS, status); + status = m_crypto_client->generate_random(num4_16bit, sizeof(num4_16bit)); + CHECK_EQUAL(PSA_SUCCESS, status); + status = m_crypto_client->generate_random(num5_24bit, sizeof(num5_24bit)); + CHECK_EQUAL(PSA_SUCCESS, status); + status = m_crypto_client->generate_random(num6_24bit, sizeof(num6_24bit)); + CHECK_EQUAL(PSA_SUCCESS, status); + status = m_crypto_client->generate_random(num7_32bit, sizeof(num7_32bit)); + CHECK_EQUAL(PSA_SUCCESS, status); + status = m_crypto_client->generate_random(num8_32bit, sizeof(num8_32bit)); + CHECK_EQUAL(PSA_SUCCESS, status); + status = m_crypto_client->generate_random(num9_64bit, sizeof(num9_64bit)); + CHECK_EQUAL(PSA_SUCCESS, status); + status = m_crypto_client->generate_random(num10_64bit, sizeof(num10_64bit)); + CHECK_EQUAL(PSA_SUCCESS, status); + status = m_crypto_client->generate_random(num11_128bit, sizeof(num11_128bit)); + CHECK_EQUAL(PSA_SUCCESS, status); + status = m_crypto_client->generate_random(num12_128bit, sizeof(num12_128bit)); + CHECK_EQUAL(PSA_SUCCESS, status); + + /* For larger numbers, it should be improbable that numbers are the same */ + CHECK(memcmp(num5_24bit, num6_24bit, sizeof(num5_24bit)) != 0); + CHECK(memcmp(num7_32bit, num8_32bit, sizeof(num7_32bit)) != 0); + CHECK(memcmp(num9_64bit, num10_64bit, sizeof(num9_64bit)) != 0); + CHECK(memcmp(num11_128bit, num12_128bit, sizeof(num11_128bit)) != 0); +} diff --git a/components/service/crypto/test/service/crypto_service_scenarios.h b/components/service/crypto/test/service/crypto_service_scenarios.h new file mode 100644 index 000000000..2c7d18838 --- /dev/null +++ b/components/service/crypto/test/service/crypto_service_scenarios.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * Service-level test scenarios for the crypto service that may be reused using + * different concrete crypto_clients to check end-to-end operation using different + * protocol serialization schemes. + */ +class crypto_service_scenarios +{ +public: + crypto_service_scenarios(crypto_client *crypto_client); + ~crypto_service_scenarios(); + + void generateRandomNumbers(); + void asymEncryptDecrypt(); + void signAndVerifyHash(); + void exportAndImportKeyPair(); + void exportPublicKey(); + void generatePersistentKeys(); + void generateVolatileKeys(); + +private: + crypto_client *m_crypto_client; +}; diff --git a/components/service/crypto/test/service/packed-c/component.cmake b/components/service/crypto/test/service/packed-c/component.cmake new file mode 100644 index 000000000..fcd6b2028 --- /dev/null +++ b/components/service/crypto/test/service/packed-c/component.cmake @@ -0,0 +1,14 @@ +#------------------------------------------------------------------------------- +# Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +#------------------------------------------------------------------------------- +if (NOT DEFINED TGT) + message(FATAL_ERROR "mandatory parameter TGT is not defined.") +endif() + +target_sources(${TGT} PRIVATE + "${CMAKE_CURRENT_LIST_DIR}/crypto_service_packedc_tests.cpp" + ) + diff --git a/components/service/crypto/test/service/packed-c/crypto_service_packedc_tests.cpp b/components/service/crypto/test/service/packed-c/crypto_service_packedc_tests.cpp new file mode 100644 index 000000000..132bbc8ce --- /dev/null +++ b/components/service/crypto/test/service/packed-c/crypto_service_packedc_tests.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/* + * Service-level tests that use the Protobuf access protocol serialization + */ +TEST_GROUP(CryptoServicePackedcTests) +{ + void setup() + { + struct rpc_caller *caller; + int status; + + m_rpc_session_handle = NULL; + m_crypto_service_context = NULL; + m_scenarios = NULL; + + service_locator_init(); + + m_crypto_service_context = service_locator_query("sn:trustedfirmware.org:crypto:0", &status); + CHECK_TRUE(m_crypto_service_context); + + m_rpc_session_handle = service_context_open(m_crypto_service_context, TS_RPC_ENCODING_PACKED_C, &caller); + CHECK_TRUE(m_rpc_session_handle); + + m_scenarios = new crypto_service_scenarios(new packedc_crypto_client(caller)); + } + + void teardown() + { + delete m_scenarios; + m_scenarios = NULL; + + service_context_close(m_crypto_service_context, m_rpc_session_handle); + m_rpc_session_handle = NULL; + + service_context_relinquish(m_crypto_service_context); + m_crypto_service_context = NULL; + } + + rpc_session_handle m_rpc_session_handle; + struct service_context *m_crypto_service_context; + crypto_service_scenarios *m_scenarios; +}; + +TEST(CryptoServicePackedcTests, generateVolatileKeys) +{ + m_scenarios->generateVolatileKeys(); +} + +TEST(CryptoServicePackedcTests, generatePersistentKeys) +{ + m_scenarios->generatePersistentKeys(); +} + +TEST(CryptoServicePackedcTests, exportPublicKey) +{ + m_scenarios->exportPublicKey(); +} + +TEST(CryptoServicePackedcTests, exportAndImportKeyPair) +{ + m_scenarios->exportAndImportKeyPair(); +} + +TEST(CryptoServicePackedcTests, signAndVerifyHash) +{ + m_scenarios->signAndVerifyHash(); +} + +TEST(CryptoServicePackedcTests, asymEncryptDecrypt) +{ + m_scenarios->asymEncryptDecrypt(); +} + +TEST(CryptoServicePackedcTests, generateRandomNumbers) +{ + m_scenarios->generateRandomNumbers(); +} diff --git a/components/service/crypto/test/service/protobuf/component.cmake b/components/service/crypto/test/service/protobuf/component.cmake new file mode 100644 index 000000000..8d12774ae --- /dev/null +++ b/components/service/crypto/test/service/protobuf/component.cmake @@ -0,0 +1,14 @@ +#------------------------------------------------------------------------------- +# Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +#------------------------------------------------------------------------------- +if (NOT DEFINED TGT) + message(FATAL_ERROR "mandatory parameter TGT is not defined.") +endif() + +target_sources(${TGT} PRIVATE + "${CMAKE_CURRENT_LIST_DIR}/crypto_service_protobuf_tests.cpp" + ) + diff --git a/components/service/crypto/test/service/protobuf/crypto_service_protobuf_tests.cpp b/components/service/crypto/test/service/protobuf/crypto_service_protobuf_tests.cpp new file mode 100644 index 000000000..3d728e22a --- /dev/null +++ b/components/service/crypto/test/service/protobuf/crypto_service_protobuf_tests.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/* + * Service-level tests that use the Protobuf access protocol serialization + */ +TEST_GROUP(CryptoServiceProtobufTests) +{ + void setup() + { + struct rpc_caller *caller; + int status; + + m_rpc_session_handle = NULL; + m_crypto_service_context = NULL; + m_scenarios = NULL; + + service_locator_init(); + + m_crypto_service_context = service_locator_query("sn:trustedfirmware.org:crypto:0", &status); + CHECK_TRUE(m_crypto_service_context); + + m_rpc_session_handle = service_context_open(m_crypto_service_context, TS_RPC_ENCODING_PROTOBUF, &caller); + CHECK_TRUE(m_rpc_session_handle); + + m_scenarios = new crypto_service_scenarios(new protobuf_crypto_client(caller)); + } + + void teardown() + { + delete m_scenarios; + m_scenarios = NULL; + + service_context_close(m_crypto_service_context, m_rpc_session_handle); + m_rpc_session_handle = NULL; + + service_context_relinquish(m_crypto_service_context); + m_crypto_service_context = NULL; + } + + rpc_session_handle m_rpc_session_handle; + struct service_context *m_crypto_service_context; + crypto_service_scenarios *m_scenarios; +}; + +TEST(CryptoServiceProtobufTests, generateVolatileKeys) +{ + m_scenarios->generateVolatileKeys(); +} + +TEST(CryptoServiceProtobufTests, generatePersistentKeys) +{ + m_scenarios->generatePersistentKeys(); +} + +TEST(CryptoServiceProtobufTests, exportPublicKey) +{ + m_scenarios->exportPublicKey(); +} + +TEST(CryptoServiceProtobufTests, exportAndImportKeyPair) +{ + m_scenarios->exportAndImportKeyPair(); +} + +TEST(CryptoServiceProtobufTests, signAndVerifyHash) +{ + m_scenarios->signAndVerifyHash(); +} + +TEST(CryptoServiceProtobufTests, asymEncryptDecrypt) +{ + m_scenarios->asymEncryptDecrypt(); +} + +TEST(CryptoServiceProtobufTests, generateRandomNumbers) +{ + m_scenarios->generateRandomNumbers(); +} diff --git a/components/service/locator/standalone/services/crypto/crypto_service_context.cpp b/components/service/locator/standalone/services/crypto/crypto_service_context.cpp index 054581797..bff9ac101 100644 --- a/components/service/locator/standalone/services/crypto/crypto_service_context.cpp +++ b/components/service/locator/standalone/services/crypto/crypto_service_context.cpp @@ -6,6 +6,7 @@ #include "crypto_service_context.h" #include +#include crypto_service_context::crypto_service_context(const char *sn) : standalone_service_context(sn), @@ -30,6 +31,9 @@ void crypto_service_context::do_init() mbed_crypto_provider_register_serializer(&m_crypto_provider, TS_RPC_ENCODING_PROTOBUF, pb_crypto_provider_serializer_instance()); + mbed_crypto_provider_register_serializer(&m_crypto_provider, + TS_RPC_ENCODING_PACKED_C, packedc_crypto_provider_serializer_instance()); + standalone_service_context::set_rpc_interface(crypto_ep); } diff --git a/deployments/component-test/component-test.cmake b/deployments/component-test/component-test.cmake index 3af6d021f..deadf114d 100644 --- a/deployments/component-test/component-test.cmake +++ b/deployments/component-test/component-test.cmake @@ -18,8 +18,11 @@ add_components( "components/app/ts-demo/test" "components/common/uuid" "components/common/uuid/test" + "components/common/tlv" + "components/common/tlv/test" "components/rpc/common/caller" "components/rpc/common/interface" + "components/rpc/common/test/protocol" "components/rpc/direct" "components/rpc/dummy" "components/service/common" @@ -32,13 +35,19 @@ add_components( "components/service/locator/standalone" "components/service/locator/standalone/services/crypto" "components/service/crypto/client/cpp" + "components/service/crypto/client/cpp/protobuf" + "components/service/crypto/client/cpp/packed-c" "components/service/crypto/client/test" "components/service/crypto/client/test/standalone" "components/service/crypto/provider/mbedcrypto" "components/service/crypto/provider/mbedcrypto/entropy_source/mock" "components/service/crypto/provider/serializer/protobuf" + "components/service/crypto/provider/serializer/packed-c" "components/service/crypto/test/unit" "components/service/crypto/test/service" + "components/service/crypto/test/service/protobuf" + "components/service/crypto/test/service/packed-c" + "components/service/crypto/test/protocol" "components/service/secure_storage/client/psa" "components/service/secure_storage/provider/mock_store" "components/service/secure_storage/provider/secure_flash_store" @@ -47,7 +56,6 @@ add_components( "components/service/secure_storage/test" "protocols/rpc/common/protobuf" "protocols/rpc/common/packed-c" - "protocols/rpc/common/packed-c/test" "protocols/service/crypto/packed-c" "protocols/service/crypto/protobuf" "protocols/service/secure_storage/packed-c" diff --git a/deployments/crypto/opteesp/CMakeLists.txt b/deployments/crypto/opteesp/CMakeLists.txt index fec7b6946..38bc42d2a 100644 --- a/deployments/crypto/opteesp/CMakeLists.txt +++ b/deployments/crypto/opteesp/CMakeLists.txt @@ -31,6 +31,7 @@ target_link_libraries(crypto-sp PRIVATE ${SP_DEV_KIT_LIBRARIES}) add_components(TARGET "crypto-sp" BASE_DIR ${TS_ROOT} COMPONENTS + "components/common/tlv" "components/messaging/ffa/libsp" "components/rpc/ffarpc/endpoint" "components/rpc/ffarpc/caller/sp" @@ -43,6 +44,7 @@ add_components(TARGET "crypto-sp" "components/service/crypto/provider/mbedcrypto" "components/service/crypto/provider/mbedcrypto/entropy_source/mock" "components/service/crypto/provider/serializer/protobuf" + "components/service/crypto/provider/serializer/packed-c" "components/service/secure_storage/client/psa" "protocols/rpc/common/packed-c" "protocols/service/secure_storage/packed-c" diff --git a/deployments/crypto/opteesp/crypto_sp.c b/deployments/crypto/opteesp/crypto_sp.c index 5756d1bdf..ea60d1c70 100644 --- a/deployments/crypto/opteesp/crypto_sp.c +++ b/deployments/crypto/opteesp/crypto_sp.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -59,9 +60,13 @@ void __noreturn sp_main(struct ffa_init_info *init_info) /* Initialize the crypto service */ crypto_iface = mbed_crypto_provider_init(&crypto_provider, storage_caller); - mbed_crypto_provider_register_serializer(&crypto_provider, + + mbed_crypto_provider_register_serializer(&crypto_provider, TS_RPC_ENCODING_PROTOBUF, pb_crypto_provider_serializer_instance()); + mbed_crypto_provider_register_serializer(&crypto_provider, + TS_RPC_ENCODING_PACKED_C, packedc_crypto_provider_serializer_instance()); + ffa_call_ep_init(&ffarpc_call_ep, crypto_iface); /* End of boot phase */ diff --git a/deployments/libts/linux-pc/CMakeLists.txt b/deployments/libts/linux-pc/CMakeLists.txt index 8de05fde9..9c798ad3e 100644 --- a/deployments/libts/linux-pc/CMakeLists.txt +++ b/deployments/libts/linux-pc/CMakeLists.txt @@ -1,5 +1,5 @@ #------------------------------------------------------------------------------- -# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. +# Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -30,6 +30,7 @@ add_components( BASE_DIR ${TS_ROOT} COMPONENTS "components/rpc/direct" + "components/common/tlv" "components/service/common" "components/service/common/serializer/protobuf" "components/service/common/provider" @@ -38,6 +39,7 @@ add_components( "components/service/crypto/provider/mbedcrypto" "components/service/crypto/provider/mbedcrypto/entropy_source/mock" "components/service/crypto/provider/serializer/protobuf" + "components/service/crypto/provider/serializer/packed-c" "components/service/secure_storage/client/psa" "components/service/secure_storage/provider/secure_flash_store" "components/service/secure_storage/provider/secure_flash_store/flash_fs" @@ -82,10 +84,16 @@ add_components( BASE_DIR ${TS_ROOT} COMPONENTS "components/app/test-runner" + "components/common/tlv" "components/service/crypto/test/service" + "components/service/crypto/test/service/protobuf" + "components/service/crypto/test/service/packed-c" "components/service/crypto/client/cpp" + "components/service/crypto/client/cpp/protobuf" + "components/service/crypto/client/cpp/packed-c" "components/service/common/serializer/protobuf" "protocols/service/crypto/protobuf" + "protocols/service/crypto/packed-c" ) #------------------------------------------------------------------------------- diff --git a/deployments/ts-demo/ts-demo.cmake b/deployments/ts-demo/ts-demo.cmake index d6f10674a..828a31e8f 100644 --- a/deployments/ts-demo/ts-demo.cmake +++ b/deployments/ts-demo/ts-demo.cmake @@ -36,9 +36,10 @@ add_components( BASE_DIR ${TS_ROOT} COMPONENTS "components/app/ts-demo" + "components/common/tlv" "components/service/crypto/client/cpp" - "components/service/common/serializer/protobuf" - "protocols/service/crypto/protobuf" + "components/service/crypto/client/cpp/packed-c" + "protocols/service/crypto/packed-c" ) #------------------------------------------------------------------------------- @@ -46,11 +47,6 @@ add_components( # #------------------------------------------------------------------------------- -# Nanopb -include(${TS_ROOT}/external/nanopb/nanopb.cmake) -target_link_libraries(ts-demo PRIVATE nanopb::protobuf-nanopb-static) -protobuf_generate_all(TGT "ts-demo" NAMESPACE "protobuf" BASE_DIR "${TS_ROOT}/protocols") - # Mbedcrypto include(${TS_ROOT}/external/mbed-crypto/mbedcrypto.cmake) target_link_libraries(ts-demo PRIVATE mbedcrypto) diff --git a/deployments/ts-demo/ts-demo.cpp b/deployments/ts-demo/ts-demo.cpp index eaa8b5254..2f607e68f 100644 --- a/deployments/ts-demo/ts-demo.cpp +++ b/deployments/ts-demo/ts-demo.cpp @@ -3,7 +3,7 @@ * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. */ -#include +#include #include #include #include @@ -25,11 +25,11 @@ int main(int argc, char *argv[]) { struct rpc_caller *caller; rpc_session_handle rpc_session_handle; - rpc_session_handle = service_context_open(crypto_service_context, TS_RPC_ENCODING_PROTOBUF, &caller); + rpc_session_handle = service_context_open(crypto_service_context, TS_RPC_ENCODING_PACKED_C, &caller); if (rpc_session_handle) { - crypto_client crypto_client(caller); + packedc_crypto_client crypto_client(caller); status = run_ts_demo(&crypto_client, true); diff --git a/deployments/ts-service-test/ts-service-test.cmake b/deployments/ts-service-test/ts-service-test.cmake index 5630a9940..4bd8c717e 100644 --- a/deployments/ts-service-test/ts-service-test.cmake +++ b/deployments/ts-service-test/ts-service-test.cmake @@ -27,10 +27,16 @@ add_components( TARGET "ts-service-test" BASE_DIR ${TS_ROOT} COMPONENTS + "components/common/tlv" "components/service/crypto/test/service" + "components/service/crypto/test/service/protobuf" + "components/service/crypto/test/service/packed-c" "components/service/crypto/client/cpp" + "components/service/crypto/client/cpp/protobuf" + "components/service/crypto/client/cpp/packed-c" "components/service/common/serializer/protobuf" "protocols/service/crypto/protobuf" + "protocols/service/crypto/packed-c" ) #------------------------------------------------------------------------------- diff --git a/protocols/rpc/common/packed-c/test/check_rpc_status_packed-c.cpp b/protocols/rpc/common/packed-c/test/check_rpc_status_packed-c.cpp deleted file mode 100644 index c377957c0..000000000 --- a/protocols/rpc/common/packed-c/test/check_rpc_status_packed-c.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -#include -#include -#include - -/* - * Check alignment of packed-c protocol values. - */ -TEST_GROUP(PackedCrpcCommonProtocolChecks) { - -}; - -TEST(PackedCrpcCommonProtocolChecks, checkRpcStatusCodes) { - - /* - * Check alignment between packed-c and protobuf rpc status codes - */ - CHECK_EQUAL(TS_RPC_CALL_ACCEPTED, ts_rpc_Status_CALL_ACCEPTED); - CHECK_EQUAL(TS_RPC_ERROR_EP_DOES_NOT_EXIT, ts_rpc_Status_ERROR_EP_DOES_NOT_EXIT); - CHECK_EQUAL(TS_RPC_ERROR_INVALID_OPCODE, ts_rpc_Status_ERROR_INVALID_OPCODE); - CHECK_EQUAL(TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED, ts_rpc_Status_ERROR_SERIALIZATION_NOT_SUPPORTED); - CHECK_EQUAL(TS_RPC_ERROR_INVALID_REQ_BODY, ts_rpc_Status_ERROR_INVALID_REQ_BODY); - CHECK_EQUAL(TS_RPC_ERROR_INVALID_RESP_BODY, ts_rpc_Status_ERROR_INVALID_RESP_BODY); - CHECK_EQUAL(TS_RPC_ERROR_RESOURCE_FAILURE, ts_rpc_Status_ERROR_RESOURCE_FAILURE); - CHECK_EQUAL(TS_RPC_ERROR_NOT_READY, ts_rpc_Status_ERROR_NOT_READY); - CHECK_EQUAL(TS_RPC_ERROR_INVALID_TRANSACTION, ts_rpc_Status_ERROR_INVALID_TRANSACTION); - CHECK_EQUAL(TS_RPC_ERROR_INTERNAL, ts_rpc_Status_ERROR_INTERNAL); - CHECK_EQUAL(TS_RPC_ERROR_INVALID_PARAMETER, ts_rpc_Status_ERROR_INVALID_PARAMETER); -} \ No newline at end of file diff --git a/protocols/rpc/common/packed-c/test/component.cmake b/protocols/rpc/common/packed-c/test/component.cmake deleted file mode 100644 index 28a896bd4..000000000 --- a/protocols/rpc/common/packed-c/test/component.cmake +++ /dev/null @@ -1,14 +0,0 @@ -#------------------------------------------------------------------------------- -# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. -# -# SPDX-License-Identifier: BSD-3-Clause -# -#------------------------------------------------------------------------------- -if (NOT DEFINED TGT) - message(FATAL_ERROR "mandatory parameter TGT is not defined.") -endif() - -target_sources(${TGT} PRIVATE - "${CMAKE_CURRENT_LIST_DIR}/check_rpc_status_packed-c.cpp" - ) - diff --git a/protocols/service/crypto/packed-c/asymmetric_decrypt.h b/protocols/service/crypto/packed-c/asymmetric_decrypt.h new file mode 100644 index 000000000..04c2c6ada --- /dev/null +++ b/protocols/service/crypto/packed-c/asymmetric_decrypt.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TS_CRYPTO_ASYMMETRIC_DECRYPT_H +#define TS_CRYPTO_ASYMMETRIC_DECRYPT_H + +#include + +/* Mandatory fixed sized input parameters */ +struct __attribute__ ((__packed__)) ts_crypto_asymmetric_decrypt_in +{ + uint32_t handle; + uint32_t alg; +}; + +/* Variable length input parameter tags */ +enum +{ + TS_CRYPTO_ASYMMETRIC_DECRYPT_IN_TAG_CIPHERTEXT = 1, + TS_CRYPTO_ASYMMETRIC_DECRYPT_IN_TAG_SALT = 2 +}; + +/* Variable length output parameter tags */ +enum +{ + TS_CRYPTO_ASYMMETRIC_DECRYPT_OUT_TAG_PLAINTEXT = 1 +}; + +#endif /* TS_CRYPTO_ASYMMETRIC_DECRYPT_H */ \ No newline at end of file diff --git a/protocols/service/crypto/packed-c/asymmetric_encrypt.h b/protocols/service/crypto/packed-c/asymmetric_encrypt.h new file mode 100644 index 000000000..9854a9549 --- /dev/null +++ b/protocols/service/crypto/packed-c/asymmetric_encrypt.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TS_CRYPTO_ASYMMETRIC_ENCRYPT_H +#define TS_CRYPTO_ASYMMETRIC_ENCRYPT_H + +#include + +/* Mandatory fixed sized input parameters */ +struct __attribute__ ((__packed__)) ts_crypto_asymmetric_encrypt_in +{ + uint32_t handle; + uint32_t alg; +}; + +/* Variable length input parameter tags */ +enum +{ + TS_CRYPTO_ASYMMETRIC_ENCRYPT_IN_TAG_PLAINTEXT = 1, + TS_CRYPTO_ASYMMETRIC_ENCRYPT_IN_TAG_SALT = 2 +}; + +/* Variable length output parameter tags */ +enum +{ + TS_CRYPTO_ASYMMETRIC_ENCRYPT_OUT_TAG_CIPHERTEXT = 1 +}; + +#endif /* TS_CRYPTO_ASYMMETRIC_ENCRYPT_H */ diff --git a/protocols/service/crypto/packed-c/close_key.h b/protocols/service/crypto/packed-c/close_key.h new file mode 100644 index 000000000..db66c18a2 --- /dev/null +++ b/protocols/service/crypto/packed-c/close_key.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TS_CRYPTO_CLOSE_KEY_H +#define TS_CRYPTO_CLOSE_KEY_H + +#include + +/* Mandatory fixed sized input parameters */ +struct __attribute__ ((__packed__)) ts_crypto_close_key_in +{ + uint32_t handle; +}; + +#endif /* TS_CRYPTO_CLOSE_KEY_H */ \ No newline at end of file diff --git a/protocols/service/crypto/packed-c/component.cmake b/protocols/service/crypto/packed-c/component.cmake index 041f7d549..a1b384236 100644 --- a/protocols/service/crypto/packed-c/component.cmake +++ b/protocols/service/crypto/packed-c/component.cmake @@ -1,5 +1,5 @@ #------------------------------------------------------------------------------- -# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. +# Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # diff --git a/protocols/service/crypto/packed-c/destroy_key.h b/protocols/service/crypto/packed-c/destroy_key.h new file mode 100644 index 000000000..c14d9ea17 --- /dev/null +++ b/protocols/service/crypto/packed-c/destroy_key.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TS_CRYPTO_DESTROY_KEY_H +#define TS_CRYPTO_DESTROY_KEY_H + +#include + +/* Mandatory fixed sized input parameters */ +struct __attribute__ ((__packed__)) ts_crypto_destroy_key_in +{ + uint32_t handle; +}; + +#endif /* TS_CRYPTO_DESTROY_KEY_H */ diff --git a/protocols/service/crypto/packed-c/export_key.h b/protocols/service/crypto/packed-c/export_key.h new file mode 100644 index 000000000..3cc0a3ca1 --- /dev/null +++ b/protocols/service/crypto/packed-c/export_key.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TS_CRYPTO_EXPORT_KEY_H +#define TS_CRYPTO_EXPORT_KEY_H + +#include + +/* Mandatory fixed sized input parameters */ +struct __attribute__ ((__packed__)) ts_crypto_export_key_in +{ + uint32_t handle; +}; + +/* Variable length output parameter tags */ +enum +{ + TS_CRYPTO_EXPORT_KEY_OUT_TAG_DATA = 1 +}; + +#endif /* TS_CRYPTO_EXPORT_KEY_H */ \ No newline at end of file diff --git a/protocols/service/crypto/packed-c/export_public_key.h b/protocols/service/crypto/packed-c/export_public_key.h new file mode 100644 index 000000000..0644e2236 --- /dev/null +++ b/protocols/service/crypto/packed-c/export_public_key.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TS_CRYPTO_EXPORT_PUBLIC_KEY_H +#define TS_CRYPTO_EXPORT_PUBLIC_KEY_H + +#include + +/* Mandatory fixed sized input parameters */ +struct __attribute__ ((__packed__)) ts_crypto_export_public_key_in +{ + uint32_t handle; +}; + +/* Variable length output parameter tags */ +enum +{ + TS_CRYPTO_EXPORT_PUBLIC_KEY_OUT_TAG_DATA = 1 +}; + +#endif /* TS_CRYPTO_EXPORT_PUBLIC_KEY_H */ \ No newline at end of file diff --git a/protocols/service/crypto/packed-c/generate_key.h b/protocols/service/crypto/packed-c/generate_key.h new file mode 100644 index 000000000..828cf69a5 --- /dev/null +++ b/protocols/service/crypto/packed-c/generate_key.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TS_CRYPTO_GENERATE_KEY_H +#define TS_CRYPTO_GENERATE_KEY_H + +#include +#include "key_attributes.h" + +/* Mandatory fixed sized input parameters */ +struct __attribute__ ((__packed__)) ts_crypto_generate_key_in +{ + struct ts_crypto_key_attributes attributes; +}; + +/* Mandatory fixed sized output parameters */ +struct __attribute__ ((__packed__)) ts_crypto_generate_key_out +{ + uint32_t handle; +}; + +#endif /* TS_CRYPTO_GENERATE_KEY_H */ diff --git a/protocols/service/crypto/packed-c/generate_random.h b/protocols/service/crypto/packed-c/generate_random.h new file mode 100644 index 000000000..6e8ccadef --- /dev/null +++ b/protocols/service/crypto/packed-c/generate_random.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TS_CRYPTO_GENERATE_RANDOM_H +#define TS_CRYPTO_GENERATE_RANDOM_H + +#include + +/* Mandatory fixed sized input parameters */ +struct __attribute__ ((__packed__)) ts_crypto_generate_random_in +{ + uint32_t size; +}; + +/* Variable length output parameter tags */ +enum +{ + TS_CRYPTO_GENERATE_RANDOM_OUT_TAG_RANDOM_BYTES = 1 +}; + +#endif /* TS_CRYPTO_GENERATE_RANDOM_H */ \ No newline at end of file diff --git a/protocols/service/crypto/packed-c/import_key.h b/protocols/service/crypto/packed-c/import_key.h new file mode 100644 index 000000000..810151efe --- /dev/null +++ b/protocols/service/crypto/packed-c/import_key.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TS_CRYPTO_IMPORT_KEY_H +#define TS_CRYPTO_IMPORT_KEY_H + +#include +#include "key_attributes.h" + +/* Mandatory fixed sized input parameters */ +struct __attribute__ ((__packed__)) ts_crypto_import_key_in +{ + struct ts_crypto_key_attributes attributes; +}; + +/* Variable length input parameter tags */ +enum +{ + TS_CRYPTO_IMPORT_KEY_IN_TAG_DATA = 1, +}; + +/* Mandatory fixed sized output parameters */ +struct __attribute__ ((__packed__)) ts_crypto_import_key_out +{ + uint32_t handle; +}; + +#endif /* TS_CRYPTO_IMPORT_KEY_H */ diff --git a/protocols/service/crypto/packed-c/key_attributes.h b/protocols/service/crypto/packed-c/key_attributes.h new file mode 100644 index 000000000..881a8f54a --- /dev/null +++ b/protocols/service/crypto/packed-c/key_attributes.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TS_CRYPTO_KEY_ATTRIBUTES_H +#define TS_CRYPTO_KEY_ATTRIBUTES_H + +#include + +/* Key types */ +#define TS_CRYPTO_KEY_TYPE_NONE (0x0000) +#define TS_CRYPTO_KEY_TYPE_RAW_DATA (0x1001) +#define TS_CRYPTO_KEY_TYPE_HMAC (0x1100) +#define TS_CRYPTO_KEY_TYPE_DERIVE (0x1200) +#define TS_CRYPTO_KEY_TYPE_AES (0x2400) +#define TS_CRYPTO_KEY_TYPE_DES (0x2301) +#define TS_CRYPTO_KEY_TYPE_CAMELLIA (0x2403) +#define TS_CRYPTO_KEY_TYPE_ARC4 (0x2002) +#define TS_CRYPTO_KEY_TYPE_CHACHA20 (0x2004) +#define TS_CRYPTO_KEY_TYPE_RSA_PUBLIC_KEY (0x4001) +#define TS_CRYPTO_KEY_TYPE_RSA_KEY_PAIR (0x7001) +#define TS_CRYPTO_KEY_TYPE_ECC_PUBLIC_KEY_BASE (0x4100) +#define TS_CRYPTO_KEY_TYPE_ECC_KEY_PAIR_BASE (0x7100) +#define TS_CRYPTO_KEY_TYPE_ECC_CURVE_MASK (0x00ff) +#define TS_CRYPTO_KEY_TYPE_DH_PUBLIC_KEY_BASE (0x4200) +#define TS_CRYPTO_KEY_TYPE_DH_KEY_PAIR_BASE (0x7200) +#define TS_CRYPTO_KEY_TYPE_DH_GROUP_MASK (0x00ff) + +/* ECC curves for use with ECC Key types */ +#define TS_CRYPTO_ECC_CURVE_NONE (0x00) +#define TS_CRYPTO_ECC_CURVE_SECP_K1 (0x17) +#define TS_CRYPTO_ECC_CURVE_SECP_R1 (0x12) +#define TS_CRYPTO_ECC_CURVE_SECP_R2 (0x1b) +#define TS_CRYPTO_ECC_CURVE_SECT_K1 (0x27) +#define TS_CRYPTO_ECC_CURVE_SECT_R1 (0x22) +#define TS_CRYPTO_ECC_CURVE_SECT_R2 (0x2b) +#define TS_CRYPTO_ECC_CURVE_BRAINPOOL_P_R1 (0x30) +#define TS_CRYPTO_ECC_CURVE_MONTGOMERY (0x41) + +/* Diffie-Hellman groups for use with DH key types */ +#define TS_CRYPTO_DH_GROUP_NONE (0x00) +#define TS_CRYPTO_DH_GROUP_RFC7919 (0x03) + +/* Crypto algorithms */ +#define TS_CRYPTO_ALG_NONE (0x00000000) +#define TS_CRYPTO_ALG_HASH_MASK (0x000000ff) +#define TS_CRYPTO_ALG_MD2 (0x01000001) +#define TS_CRYPTO_ALG_MD4 (0x01000002) +#define TS_CRYPTO_ALG_MD5 (0x01000003) +#define TS_CRYPTO_ALG_RIPEMD160 (0x01000004) +#define TS_CRYPTO_ALG_SHA_1 (0x01000005) +#define TS_CRYPTO_ALG_SHA_224 (0x01000008) +#define TS_CRYPTO_ALG_SHA_256 (0x01000009) +#define TS_CRYPTO_ALG_SHA_384 (0x0100000a) +#define TS_CRYPTO_ALG_SHA_512 (0x0100000b) +#define TS_CRYPTO_ALG_SHA_512_224 (0x0100000c) +#define TS_CRYPTO_ALG_SHA_512_256 (0x0100000d) +#define TS_CRYPTO_ALG_SHA3_224 (0x01000010) +#define TS_CRYPTO_ALG_SHA3_256 (0x01000011) +#define TS_CRYPTO_ALG_SHA3_384 (0x01000012) +#define TS_CRYPTO_ALG_SHA3_512 (0x01000013) +#define TS_CRYPTO_ALG_CBC_MAC (0x02c00001) +#define TS_CRYPTO_ALG_CMAC (0x02c00002) +#define TS_CRYPTO_ALG_ARC4 (0x04800001) +#define TS_CRYPTO_ALG_CHACHA20 (0x04800005) +#define TS_CRYPTO_ALG_CTR (0x04c00001) +#define TS_CRYPTO_ALG_CFB (0x04c00002) +#define TS_CRYPTO_ALG_OFB (0x04c00003) +#define TS_CRYPTO_ALG_XTS (0x044000ff) +#define TS_CRYPTO_ALG_CBC_NO_PADDING (0x04600100) +#define TS_CRYPTO_ALG_CBC_PKCS7 (0x04600101) +#define TS_CRYPTO_ALG_AEAD_FROM_BLOCK_FLAG (0x00400000) +#define TS_CRYPTO_ALG_CCM (0x06401001) +#define TS_CRYPTO_ALG_GCM (0x06401002) +#define TS_CRYPTO_ALG_CHACHA20_POLY1305 (0x06001005) +#define TS_CRYPTO_ALG_RSA_PKCS1V15_SIGN_BASE (0x10020000) +#define TS_CRYPTO_ALG_RSA_PSS_BASE (0x10030000) +#define TS_CRYPTO_ALG_ECDSA_BASE (0x10060000) +#define TS_CRYPTO_ALG_DETERMINISTIC_ECDSA_BASE (0x10070000) +#define TS_CRYPTO_ALG_RSA_PKCS1V15_CRYPT (0x12020000) +#define TS_CRYPTO_ALG_RSA_OAEP_BASE (0x12030000) +#define TS_CRYPTO_ALG_HKDF_BASE (0x20000100) +#define TS_CRYPTO_ALG_TLS12_PRF_BASE (0x20000200) +#define TS_CRYPTO_ALG_TLS12_PSK_TO_MS_BASE (0x20000300) +#define TS_CRYPTO_ALG_KEY_DERIVATION_MASK (0x0803ffff) +#define TS_CRYPTO_ALG_KEY_AGREEMENT_MASK (0x10fc0000) +#define TS_CRYPTO_ALG_FFDH (0x30100000) +#define TS_CRYPTO_ALG_ECDH (0x30200000) + +/* Key lifetime */ +#define TS_CRYPTO_KEY_LIFETIME_VOLATILE (0x00000000) +#define TS_CRYPTO_KEY_LIFETIME_PERSISTENT (0x00000001) + +/* Key usage constraints */ +#define TS_CRYPTO_KEY_USAGE_NONE (0x00000000) +#define TS_CRYPTO_KEY_USAGE_EXPORT (0x00000001) +#define TS_CRYPTO_KEY_USAGE_COPY (0x00000002) +#define TS_CRYPTO_KEY_USAGE_ENCRYPT (0x00000100) +#define TS_CRYPTO_KEY_USAGE_DECRYPT (0x00000200) +#define TS_CRYPTO_KEY_USAGE_SIGN_HASH (0x00000400) +#define TS_CRYPTO_KEY_USAGE_VERIFY_HASH (0x00000800) +#define TS_CRYPTO_KEY_USAGE_DERIVE (0x00001000) + +/* Key policy to define what key can be used for */ +struct __attribute__ ((__packed__)) ts_crypto_key_policy +{ + uint32_t usage; + uint32_t alg; +}; + +/* Key attributes object */ +struct __attribute__ ((__packed__)) ts_crypto_key_attributes +{ + uint32_t type; + uint32_t key_bits; + uint32_t lifetime; + uint32_t id; + struct ts_crypto_key_policy policy; +}; + +#endif /* TS_CRYPTO_KEY_ATTRIBUTES_H */ \ No newline at end of file diff --git a/protocols/service/crypto/packed-c/opcodes.h b/protocols/service/crypto/packed-c/opcodes.h index 40f8ab3ee..eee6ed735 100644 --- a/protocols/service/crypto/packed-c/opcodes.h +++ b/protocols/service/crypto/packed-c/opcodes.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ diff --git a/protocols/service/crypto/packed-c/open_key.h b/protocols/service/crypto/packed-c/open_key.h new file mode 100644 index 000000000..68252adcc --- /dev/null +++ b/protocols/service/crypto/packed-c/open_key.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TS_CRYPTO_OPEN_KEY_H +#define TS_CRYPTO_OPEN_KEY_H + +#include + +/* Mandatory fixed sized input parameters */ +struct __attribute__ ((__packed__)) ts_crypto_open_key_in +{ + uint32_t id; +}; + +/* Mandatory fixed sized output parameters */ +struct __attribute__ ((__packed__)) ts_crypto_open_key_out +{ + uint32_t handle; +}; + +#endif /* TS_CRYPTO_OPEN_KEY_H */ \ No newline at end of file diff --git a/protocols/service/crypto/packed-c/sign_hash.h b/protocols/service/crypto/packed-c/sign_hash.h new file mode 100644 index 000000000..762125c1e --- /dev/null +++ b/protocols/service/crypto/packed-c/sign_hash.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TS_CRYPTO_SIGN_HASH_H +#define TS_CRYPTO_SIGN_HASH_H + +#include + +/* Mandatory fixed sized input parameters */ +struct __attribute__ ((__packed__)) ts_crypto_sign_hash_in +{ + uint32_t handle; + uint32_t alg; +}; + +/* Variable length input parameter tags */ +enum +{ + TS_CRYPTO_SIGN_HASH_IN_TAG_HASH = 1, +}; + +/* Variable length output parameter tags */ +enum +{ + TS_CRYPTO_SIGN_HASH_OUT_TAG_SIGNATURE = 1 +}; + +#endif /* TS_CRYPTO_SIGN_HASH_H */ \ No newline at end of file diff --git a/protocols/service/crypto/packed-c/verify_hash.h b/protocols/service/crypto/packed-c/verify_hash.h new file mode 100644 index 000000000..fc3bbcab4 --- /dev/null +++ b/protocols/service/crypto/packed-c/verify_hash.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TS_CRYPTO_VERIFY_HASH_H +#define TS_CRYPTO_VERIFY_HASH_H + +#include + +/* Mandatory fixed sized input parameters */ +struct __attribute__ ((__packed__)) ts_crypto_verify_hash_in +{ + uint32_t handle; + uint32_t alg; +}; + +/* Variable length input parameter tags */ +enum +{ + TS_CRYPTO_VERIFY_HASH_IN_TAG_HASH = 1, + TS_CRYPTO_VERIFY_HASH_IN_TAG_SIGNATURE = 2 +}; + +#endif /* TS_CRYPTO_VERIFY_HASH_H */ \ No newline at end of file diff --git a/protocols/service/crypto/protobuf/key_attributes.proto b/protocols/service/crypto/protobuf/key_attributes.proto index 7e504f643..bae948b5c 100644 --- a/protocols/service/crypto/protobuf/key_attributes.proto +++ b/protocols/service/crypto/protobuf/key_attributes.proto @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. * SPDX-License-Identifier: BSD-3-Clause */ syntax = "proto3"; @@ -19,7 +19,7 @@ enum KeyType { KEY_TYPE_CAMELLIA = 0x2403; KEY_TYPE_ARC4 = 0x2002; KEY_TYPE_CHACHA20 = 0x2004; - KEY_TYPE_PUBLIC_KEY = 0x4001; + KEY_TYPE_RSA_PUBLIC_KEY = 0x4001; KEY_TYPE_RSA_KEY_PAIR = 0x7001; KEY_TYPE_ECC_PUBLIC_KEY_BASE = 0x4100; KEY_TYPE_ECC_KEY_PAIR_BASE = 0x7100; -- cgit v1.2.3