1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
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;
}
|