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 <julian.hall@arm.com>
Change-Id: I9279b0814bcc9cf6c4aa4e30629e2f46f2df4c23
diff --git a/components/service/crypto/client/cpp/crypto_client.cpp b/components/service/crypto/client/cpp/crypto_client.cpp
index b27a585..602a6b5 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 <cstring>
-#include <cstdlib>
#include "crypto_client.h"
#include <protocols/rpc/common/packed-c/status.h>
-#include <service/common/serializer/protobuf/pb_helper.h>
-#include <rpc_caller.h>
-#include <service/crypto/protobuf/opcodes.pb.h>
-#include <service/crypto/protobuf/generate_key.pb.h>
-#include <service/crypto/protobuf/destroy_key.pb.h>
-#include <service/crypto/protobuf/import_key.pb.h>
-#include <service/crypto/protobuf/open_key.pb.h>
-#include <service/crypto/protobuf/close_key.pb.h>
-#include <service/crypto/protobuf/export_key.pb.h>
-#include <service/crypto/protobuf/export_public_key.pb.h>
-#include <service/crypto/protobuf/sign_hash.pb.h>
-#include <service/crypto/protobuf/verify_hash.pb.h>
-#include <service/crypto/protobuf/asymmetric_encrypt.pb.h>
-#include <service/crypto/protobuf/asymmetric_decrypt.pb.h>
-#include <service/crypto/protobuf/generate_random.pb.h>
-#include <pb_encode.h>
-#include <pb_decode.h>
crypto_client::crypto_client() :
m_caller(NULL),
@@ -54,758 +35,3 @@
{
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 3d0366f..5f6f0e1 100644
--- a/components/service/crypto/client/cpp/crypto_client.h
+++ b/components/service/crypto/client/cpp/crypto_client.h
@@ -9,66 +9,61 @@
#include <cstdint>
#include <psa/crypto.h>
-#include <service/crypto/protobuf/key_attributes.pb.h>
-
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 0000000..7ad58ab
--- /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 0000000..e0e85e0
--- /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 <cstring>
+#include <cstdlib>
+#include "packedc_crypto_client.h"
+#include <protocols/rpc/common/packed-c/status.h>
+#include <protocols/service/crypto/packed-c/opcodes.h>
+#include <protocols/service/crypto/packed-c/key_attributes.h>
+#include <protocols/service/crypto/packed-c/asymmetric_decrypt.h>
+#include <protocols/service/crypto/packed-c/asymmetric_encrypt.h>
+#include <protocols/service/crypto/packed-c/close_key.h>
+#include <protocols/service/crypto/packed-c/destroy_key.h>
+#include <protocols/service/crypto/packed-c/export_key.h>
+#include <protocols/service/crypto/packed-c/export_public_key.h>
+#include <protocols/service/crypto/packed-c/generate_key.h>
+#include <protocols/service/crypto/packed-c/generate_random.h>
+#include <protocols/service/crypto/packed-c/import_key.h>
+#include <protocols/service/crypto/packed-c/open_key.h>
+#include <protocols/service/crypto/packed-c/sign_hash.h>
+#include <protocols/service/crypto/packed-c/verify_hash.h>
+#include <common/tlv/tlv.h>
+#include <rpc_caller.h>
+
+
+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 0000000..fb5d772
--- /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 <service/crypto/client/cpp/crypto_client.h>
+#include <protocols/service/crypto/packed-c/key_attributes.h>
+
+/*
+ * 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 0000000..ddb3f6b
--- /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 0000000..6818590
--- /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 <cstring>
+#include <cstdlib>
+#include "protobuf_crypto_client.h"
+#include <protocols/rpc/common/packed-c/status.h>
+#include <service/common/serializer/protobuf/pb_helper.h>
+#include <rpc_caller.h>
+#include <service/crypto/protobuf/opcodes.pb.h>
+#include <service/crypto/protobuf/generate_key.pb.h>
+#include <service/crypto/protobuf/destroy_key.pb.h>
+#include <service/crypto/protobuf/import_key.pb.h>
+#include <service/crypto/protobuf/open_key.pb.h>
+#include <service/crypto/protobuf/close_key.pb.h>
+#include <service/crypto/protobuf/export_key.pb.h>
+#include <service/crypto/protobuf/export_public_key.pb.h>
+#include <service/crypto/protobuf/sign_hash.pb.h>
+#include <service/crypto/protobuf/verify_hash.pb.h>
+#include <service/crypto/protobuf/asymmetric_encrypt.pb.h>
+#include <service/crypto/protobuf/asymmetric_decrypt.pb.h>
+#include <service/crypto/protobuf/generate_random.pb.h>
+#include <pb_encode.h>
+#include <pb_decode.h>
+
+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 0000000..e2a355a
--- /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 <service/crypto/client/cpp/crypto_client.h>
+#include <service/crypto/protobuf/key_attributes.pb.h>
+
+/*
+ * 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 */