diff options
Diffstat (limited to 'components/service/crypto/client/psa/psa_asymmetric_encrypt.c')
-rw-r--r-- | components/service/crypto/client/psa/psa_asymmetric_encrypt.c | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/components/service/crypto/client/psa/psa_asymmetric_encrypt.c b/components/service/crypto/client/psa/psa_asymmetric_encrypt.c new file mode 100644 index 000000000..881ef7b20 --- /dev/null +++ b/components/service/crypto/client/psa/psa_asymmetric_encrypt.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <string.h> +#include <stdlib.h> +#include <psa/crypto.h> +#include "psa_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/asymmetric_encrypt.h> +#include <common/tlv/tlv.h> + + +psa_status_t psa_asymmetric_encrypt(psa_key_id_t id, 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(struct ts_crypto_asymmetric_encrypt_in); + size_t req_len = req_fixed_len; + + *output_length = 0; /* For failure case */ + + req_msg.id = id; + req_msg.alg = alg; + + /* Mandatory parameter */ + struct tlv_record plaintext_record; + plaintext_record.tag = TS_CRYPTO_ASYMMETRIC_ENCRYPT_IN_TAG_PLAINTEXT; + plaintext_record.length = input_length; + plaintext_record.value = input; + req_len += tlv_required_space(plaintext_record.length); + + /* Optional parameter */ + struct tlv_record salt_record; + salt_record.tag = TS_CRYPTO_ASYMMETRIC_ENCRYPT_IN_TAG_SALT; + salt_record.length = (salt) ? salt_length : 0; + salt_record.value = salt; + if (salt) req_len += tlv_required_space(salt_record.length); + + rpc_call_handle call_handle; + uint8_t *req_buf; + + call_handle = rpc_caller_begin(psa_crypto_client_instance.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); + if (salt) tlv_encode(&req_iter, &salt_record); + + psa_crypto_client_instance.rpc_status = + rpc_caller_invoke(psa_crypto_client_instance.caller, call_handle, + TS_CRYPTO_OPCODE_ASYMMETRIC_ENCRYPT, &opstatus, &resp_buf, &resp_len); + + if (psa_crypto_client_instance.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(psa_crypto_client_instance.caller, call_handle); + } + + return psa_status; +} |