1 /*
2 * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <psa/crypto.h>
8 #include "psa_crypto_client.h"
9 #include "crypto_caller_selector.h"
10
psa_cipher_encrypt_setup(psa_cipher_operation_t * operation,psa_key_id_t key,psa_algorithm_t alg)11 psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation,
12 psa_key_id_t key,
13 psa_algorithm_t alg)
14 {
15 if (psa_crypto_client_instance.init_status != PSA_SUCCESS)
16 return psa_crypto_client_instance.init_status;
17
18 if (operation->handle)
19 return PSA_ERROR_BAD_STATE;
20
21 return crypto_caller_cipher_encrypt_setup(&psa_crypto_client_instance.base,
22 &operation->handle,
23 key, alg);
24 }
25
psa_cipher_decrypt_setup(psa_cipher_operation_t * operation,psa_key_id_t key,psa_algorithm_t alg)26 psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation,
27 psa_key_id_t key,
28 psa_algorithm_t alg)
29 {
30 if (psa_crypto_client_instance.init_status != PSA_SUCCESS)
31 return psa_crypto_client_instance.init_status;
32
33 if (operation->handle)
34 return PSA_ERROR_BAD_STATE;
35
36 return crypto_caller_cipher_decrypt_setup(&psa_crypto_client_instance.base,
37 &operation->handle,
38 key, alg);
39 }
40
psa_cipher_generate_iv(psa_cipher_operation_t * operation,uint8_t * iv,size_t iv_size,size_t * iv_length)41 psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation,
42 uint8_t *iv,
43 size_t iv_size,
44 size_t *iv_length)
45 {
46 return crypto_caller_cipher_generate_iv(&psa_crypto_client_instance.base,
47 operation->handle,
48 iv, iv_size, iv_length);
49 }
50
psa_cipher_set_iv(psa_cipher_operation_t * operation,const uint8_t * iv,size_t iv_length)51 psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation,
52 const uint8_t *iv,
53 size_t iv_length)
54 {
55 return crypto_caller_cipher_set_iv(&psa_crypto_client_instance.base,
56 operation->handle,
57 iv, iv_length);
58 }
59
psa_cipher_update(psa_cipher_operation_t * operation,const uint8_t * input,size_t input_length,uint8_t * output,size_t output_size,size_t * output_length)60 psa_status_t psa_cipher_update(psa_cipher_operation_t *operation,
61 const uint8_t *input,
62 size_t input_length,
63 uint8_t *output,
64 size_t output_size,
65 size_t *output_length)
66 {
67 return crypto_caller_cipher_update(&psa_crypto_client_instance.base,
68 operation->handle,
69 input, input_length,
70 output, output_size, output_length);
71 }
72
psa_cipher_finish(psa_cipher_operation_t * operation,uint8_t * output,size_t output_size,size_t * output_length)73 psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation,
74 uint8_t *output,
75 size_t output_size,
76 size_t *output_length)
77 {
78 return crypto_caller_cipher_finish(&psa_crypto_client_instance.base,
79 operation->handle,
80 output, output_size, output_length);
81 }
82
psa_cipher_abort(psa_cipher_operation_t * operation)83 psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation)
84 {
85 return crypto_caller_cipher_abort(&psa_crypto_client_instance.base,
86 operation->handle);
87 }
88
multi_cipher_update(psa_cipher_operation_t * operation,const uint8_t * input,size_t input_length,uint8_t * output,size_t output_size,size_t * output_length)89 static psa_status_t multi_cipher_update(psa_cipher_operation_t *operation,
90 const uint8_t *input,
91 size_t input_length,
92 uint8_t *output,
93 size_t output_size,
94 size_t *output_length)
95 {
96 psa_status_t psa_status = PSA_SUCCESS;
97 size_t max_update_size =
98 crypto_caller_cipher_max_update_size(&psa_crypto_client_instance.base);
99 size_t bytes_input = 0;
100 size_t bytes_output = 0;
101
102 *output_length = 0;
103
104 if (!max_update_size) {
105
106 /* Don't know the max update size so assume that the entire
107 * input and output can be handled in a single update. If
108 * this isn't true, the first cipher update operation will fail
109 * safely.
110 */
111 max_update_size = input_length;
112 }
113
114 while (bytes_input < input_length) {
115
116 if (bytes_output >= output_size) {
117
118 psa_status = PSA_ERROR_BUFFER_TOO_SMALL;
119 break;
120 }
121
122 size_t update_output_len = 0;
123 size_t bytes_remaining = input_length - bytes_input;
124 size_t update_len = (bytes_remaining < max_update_size) ?
125 bytes_remaining :
126 max_update_size;
127
128 psa_status = psa_cipher_update(operation,
129 &input[bytes_input], update_len,
130 &output[bytes_output], output_size - bytes_output, &update_output_len);
131
132 if (psa_status != PSA_SUCCESS)
133 break;
134
135 bytes_input += update_len;
136 bytes_output += update_output_len;
137 }
138
139 if (psa_status == PSA_SUCCESS) {
140
141 if (bytes_output < output_size) {
142
143 size_t finish_output_len = 0;
144
145 psa_status = psa_cipher_finish(operation,
146 &output[bytes_output], output_size - bytes_output, &finish_output_len);
147
148 if (psa_status == PSA_SUCCESS) {
149
150 *output_length = bytes_output + finish_output_len;
151 }
152 else {
153
154 psa_cipher_abort(operation);
155 }
156 }
157 else {
158
159 psa_status = PSA_ERROR_BUFFER_TOO_SMALL;
160 }
161 }
162
163 return psa_status;
164 }
165
psa_cipher_encrypt(psa_key_id_t key,psa_algorithm_t alg,const uint8_t * input,size_t input_length,uint8_t * output,size_t output_size,size_t * output_length)166 psa_status_t psa_cipher_encrypt(psa_key_id_t key,
167 psa_algorithm_t alg,
168 const uint8_t *input,
169 size_t input_length,
170 uint8_t *output,
171 size_t output_size,
172 size_t *output_length)
173 {
174 psa_cipher_operation_t operation = psa_cipher_operation_init();
175 psa_status_t psa_status = psa_cipher_encrypt_setup(&operation, key, alg);
176
177 if (psa_status == PSA_SUCCESS) {
178
179 size_t ciphertext_len = 0;
180 size_t iv_len = 0;
181
182 psa_status = psa_cipher_generate_iv(&operation, output, output_size, &iv_len);
183
184 if (psa_status == PSA_SUCCESS) {
185
186 if (iv_len <= output_size) {
187
188 psa_status = multi_cipher_update(&operation,
189 input, input_length,
190 &output[iv_len], output_size - iv_len, &ciphertext_len);
191
192 *output_length = iv_len + ciphertext_len;
193 }
194 else {
195
196 psa_status = PSA_ERROR_BUFFER_TOO_SMALL;
197 }
198 }
199
200 if (psa_status != PSA_SUCCESS) {
201
202 psa_cipher_abort(&operation);
203 }
204 }
205
206 return psa_status;
207 }
208
psa_cipher_decrypt(psa_key_id_t key,psa_algorithm_t alg,const uint8_t * input,size_t input_length,uint8_t * output,size_t output_size,size_t * output_length)209 psa_status_t psa_cipher_decrypt(psa_key_id_t key,
210 psa_algorithm_t alg,
211 const uint8_t *input,
212 size_t input_length,
213 uint8_t *output,
214 size_t output_size,
215 size_t *output_length)
216 {
217 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
218 psa_status_t psa_status = psa_get_key_attributes(key, &attributes);
219
220 if (psa_status == PSA_SUCCESS) {
221
222 psa_cipher_operation_t operation = psa_cipher_operation_init();
223 psa_status = psa_cipher_decrypt_setup(&operation, key, alg);
224
225 if (psa_status == PSA_SUCCESS) {
226
227 size_t iv_len = PSA_CIPHER_IV_LENGTH(psa_get_key_type(&attributes), alg);
228
229 if (input_length >= iv_len) {
230
231 psa_status = psa_cipher_set_iv(&operation, input, iv_len);
232
233 if (psa_status == PSA_SUCCESS) {
234
235 psa_status = multi_cipher_update(&operation,
236 &input[iv_len], input_length - iv_len,
237 output, output_size, output_length);
238 }
239 }
240 else {
241
242 psa_status = PSA_ERROR_INVALID_ARGUMENT;
243 }
244
245 if (psa_status != PSA_SUCCESS) {
246
247 psa_cipher_abort(&operation);
248 }
249 }
250
251 psa_reset_key_attributes(&attributes);
252 }
253
254 return psa_status;
255 }
256