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_aead_encrypt_setup(psa_aead_operation_t * operation,psa_key_id_t key,psa_algorithm_t alg)11 psa_status_t psa_aead_encrypt_setup(psa_aead_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 return crypto_caller_aead_encrypt_setup(&psa_crypto_client_instance.base,
19 &operation->handle, key, alg);
20 }
21
psa_aead_decrypt_setup(psa_aead_operation_t * operation,psa_key_id_t key,psa_algorithm_t alg)22 psa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation,
23 psa_key_id_t key,
24 psa_algorithm_t alg)
25 {
26 if (psa_crypto_client_instance.init_status != PSA_SUCCESS)
27 return psa_crypto_client_instance.init_status;
28
29 return crypto_caller_aead_decrypt_setup(&psa_crypto_client_instance.base,
30 &operation->handle, key, alg);
31 }
32
psa_aead_generate_nonce(psa_aead_operation_t * operation,uint8_t * nonce,size_t nonce_size,size_t * nonce_length)33 psa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation,
34 uint8_t *nonce,
35 size_t nonce_size,
36 size_t *nonce_length)
37 {
38 return crypto_caller_aead_generate_nonce(&psa_crypto_client_instance.base,
39 operation->handle,
40 nonce, nonce_size, nonce_length);
41 }
42
psa_aead_set_nonce(psa_aead_operation_t * operation,const uint8_t * nonce,size_t nonce_length)43 psa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation,
44 const uint8_t *nonce,
45 size_t nonce_length)
46 {
47 return crypto_caller_aead_set_nonce(&psa_crypto_client_instance.base,
48 operation->handle,
49 nonce, nonce_length);
50 }
51
psa_aead_set_lengths(psa_aead_operation_t * operation,size_t ad_length,size_t plaintext_length)52 psa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation,
53 size_t ad_length,
54 size_t plaintext_length)
55 {
56 return crypto_caller_aead_set_lengths(&psa_crypto_client_instance.base,
57 operation->handle,
58 ad_length, plaintext_length);
59 }
60
psa_aead_update_ad(psa_aead_operation_t * operation,const uint8_t * input,size_t input_length)61 psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation,
62 const uint8_t *input,
63 size_t input_length)
64 {
65 return crypto_caller_aead_update_ad(&psa_crypto_client_instance.base,
66 operation->handle,
67 input, input_length);
68 }
69
psa_aead_update(psa_aead_operation_t * operation,const uint8_t * input,size_t input_length,uint8_t * output,size_t output_size,size_t * output_length)70 psa_status_t psa_aead_update(psa_aead_operation_t *operation,
71 const uint8_t *input,
72 size_t input_length,
73 uint8_t *output,
74 size_t output_size,
75 size_t *output_length)
76 {
77 psa_status_t status = crypto_caller_aead_update(&psa_crypto_client_instance.base,
78 operation->handle,
79 input, input_length,
80 output, output_size, output_length);
81
82 /*
83 * If too small a buffer has been provided for the output, the operation
84 * state will have been updated but the result can't be put anywhere. This
85 * is an unrecoveral condition so abort the operation.
86 */
87 if (status == PSA_ERROR_BUFFER_TOO_SMALL) {
88
89 psa_aead_abort(operation);
90 }
91
92 return status;
93 }
94
psa_aead_finish(psa_aead_operation_t * operation,uint8_t * aeadtext,size_t aeadtext_size,size_t * aeadtext_length,uint8_t * tag,size_t tag_size,size_t * tag_length)95 psa_status_t psa_aead_finish(psa_aead_operation_t *operation,
96 uint8_t *aeadtext,
97 size_t aeadtext_size,
98 size_t *aeadtext_length,
99 uint8_t *tag,
100 size_t tag_size,
101 size_t *tag_length)
102 {
103 return crypto_caller_aead_finish(&psa_crypto_client_instance.base,
104 operation->handle,
105 aeadtext, aeadtext_size, aeadtext_length,
106 tag, tag_size, tag_length);
107 }
108
psa_aead_verify(psa_aead_operation_t * operation,uint8_t * plaintext,size_t plaintext_size,size_t * plaintext_length,const uint8_t * tag,size_t tag_length)109 psa_status_t psa_aead_verify(psa_aead_operation_t *operation,
110 uint8_t *plaintext,
111 size_t plaintext_size,
112 size_t *plaintext_length,
113 const uint8_t *tag,
114 size_t tag_length)
115 {
116 return crypto_caller_aead_verify(&psa_crypto_client_instance.base,
117 operation->handle,
118 plaintext, plaintext_size, plaintext_length,
119 tag, tag_length);
120 }
121
psa_aead_abort(psa_aead_operation_t * operation)122 psa_status_t psa_aead_abort(psa_aead_operation_t *operation)
123 {
124 return crypto_caller_aead_abort(&psa_crypto_client_instance.base,
125 operation->handle);
126 }
127
multi_aead_update_ad(psa_aead_operation_t * operation,const uint8_t * input,size_t input_length)128 static psa_status_t multi_aead_update_ad(psa_aead_operation_t *operation,
129 const uint8_t *input,
130 size_t input_length)
131 {
132 psa_status_t psa_status = PSA_SUCCESS;
133 size_t max_update_size =
134 crypto_caller_aead_max_update_ad_size(&psa_crypto_client_instance.base);
135 size_t bytes_input = 0;
136
137 if (!max_update_size) {
138
139 /* Don't know the max update size so assume that the entire
140 * input and output can be handled in a single update. If
141 * this isn't true, the first aead update operation will fail
142 * safely.
143 */
144 max_update_size = input_length;
145 }
146
147 while (bytes_input < input_length) {
148
149 size_t bytes_remaining = input_length - bytes_input;
150 size_t update_len = (bytes_remaining < max_update_size) ?
151 bytes_remaining :
152 max_update_size;
153
154 psa_status = psa_aead_update_ad(operation,
155 &input[bytes_input], update_len);
156
157 if (psa_status != PSA_SUCCESS) break;
158
159 bytes_input += update_len;
160 }
161
162 return psa_status;
163 }
164
multi_aead_update(psa_aead_operation_t * operation,const uint8_t * input,size_t input_length,uint8_t * output,size_t output_size,size_t * output_length)165 static psa_status_t multi_aead_update(psa_aead_operation_t *operation,
166 const uint8_t *input,
167 size_t input_length,
168 uint8_t *output,
169 size_t output_size,
170 size_t *output_length)
171 {
172 psa_status_t psa_status = PSA_SUCCESS;
173 size_t max_update_size =
174 crypto_caller_aead_max_update_size(&psa_crypto_client_instance.base);
175 size_t bytes_input = 0;
176 size_t bytes_output = 0;
177
178 *output_length = 0;
179
180 if (!max_update_size) {
181
182 /* Don't know the max update size so assume that the entire
183 * input and output can be handled in a single update. If
184 * this isn't true, the first aead update operation will fail
185 * safely.
186 */
187 max_update_size = input_length;
188 }
189
190 while ((bytes_input < input_length) && (bytes_output < output_size)) {
191
192 size_t update_output_len = 0;
193 size_t bytes_remaining = input_length - bytes_input;
194 size_t update_len = (bytes_remaining < max_update_size) ?
195 bytes_remaining :
196 max_update_size;
197
198 psa_status = psa_aead_update(operation,
199 &input[bytes_input], update_len,
200 &output[bytes_output], output_size - bytes_output, &update_output_len);
201
202 if (psa_status != PSA_SUCCESS) break;
203
204 bytes_input += update_len;
205 bytes_output += update_output_len;
206 }
207
208 if (psa_status == PSA_SUCCESS) {
209
210 *output_length = bytes_output;
211 }
212
213 return psa_status;
214 }
215
psa_aead_encrypt(psa_key_id_t key,psa_algorithm_t alg,const uint8_t * nonce,size_t nonce_length,const uint8_t * additional_data,size_t additional_data_length,const uint8_t * plaintext,size_t plaintext_length,uint8_t * aeadtext,size_t aeadtext_size,size_t * aeadtext_length)216 psa_status_t psa_aead_encrypt(psa_key_id_t key,
217 psa_algorithm_t alg,
218 const uint8_t *nonce,
219 size_t nonce_length,
220 const uint8_t *additional_data,
221 size_t additional_data_length,
222 const uint8_t *plaintext,
223 size_t plaintext_length,
224 uint8_t *aeadtext,
225 size_t aeadtext_size,
226 size_t *aeadtext_length)
227 {
228 psa_aead_operation_t operation = psa_aead_operation_init();
229 size_t bytes_output = 0;
230 *aeadtext_length = 0;
231
232 psa_status_t psa_status = psa_aead_encrypt_setup(&operation, key, alg);
233 if (psa_status != PSA_SUCCESS) return psa_status;
234
235 if ((psa_status = psa_aead_set_lengths(&operation, additional_data_length, plaintext_length),
236 psa_status == PSA_SUCCESS) &&
237 (psa_status = psa_aead_set_nonce(&operation, nonce, nonce_length),
238 psa_status == PSA_SUCCESS) &&
239 (psa_status = multi_aead_update_ad(&operation, additional_data, additional_data_length),
240 psa_status == PSA_SUCCESS) &&
241 (psa_status = multi_aead_update(&operation, plaintext, plaintext_length,
242 aeadtext, aeadtext_size, &bytes_output),
243 psa_status == PSA_SUCCESS))
244 {
245 size_t remaining_aead_len = 0;
246 size_t tag_len = 0;
247
248 psa_status = psa_aead_finish(&operation,
249 NULL, 0, &remaining_aead_len,
250 &aeadtext[bytes_output], aeadtext_size - bytes_output, &tag_len);
251
252 if (psa_status == PSA_SUCCESS) {
253
254 *aeadtext_length = bytes_output + remaining_aead_len + tag_len;
255 }
256 else {
257
258 psa_aead_abort(&operation);
259 }
260 }
261 else {
262
263 psa_aead_abort(&operation);
264 }
265
266 return psa_status;
267 }
268
psa_aead_decrypt(psa_key_id_t key,psa_algorithm_t alg,const uint8_t * nonce,size_t nonce_length,const uint8_t * additional_data,size_t additional_data_length,const uint8_t * aeadtext,size_t aeadtext_length,uint8_t * plaintext,size_t plaintext_size,size_t * plaintext_length)269 psa_status_t psa_aead_decrypt(psa_key_id_t key,
270 psa_algorithm_t alg,
271 const uint8_t *nonce,
272 size_t nonce_length,
273 const uint8_t *additional_data,
274 size_t additional_data_length,
275 const uint8_t *aeadtext,
276 size_t aeadtext_length,
277 uint8_t *plaintext,
278 size_t plaintext_size,
279 size_t *plaintext_length)
280 {
281 psa_aead_operation_t operation = psa_aead_operation_init();
282 size_t bytes_output = 0;
283 *plaintext_length = 0;
284
285 psa_status_t psa_status = psa_aead_decrypt_setup(&operation, key, alg);
286 if (psa_status != PSA_SUCCESS) return psa_status;
287
288 size_t tag_len = PSA_ALG_AEAD_GET_TAG_LENGTH(alg);
289 size_t ciphertext_len = (aeadtext_length > tag_len) ? aeadtext_length - tag_len : 0;
290
291 if ((psa_status = psa_aead_set_lengths(&operation, additional_data_length, ciphertext_len),
292 psa_status == PSA_SUCCESS) &&
293 (psa_status = psa_aead_set_nonce(&operation, nonce, nonce_length),
294 psa_status == PSA_SUCCESS) &&
295 (psa_status = multi_aead_update_ad(&operation, additional_data, additional_data_length),
296 psa_status == PSA_SUCCESS) &&
297 (psa_status = multi_aead_update(&operation, aeadtext, ciphertext_len,
298 plaintext, plaintext_size, &bytes_output),
299 psa_status == PSA_SUCCESS))
300 {
301 size_t remaining_plaintext_len = 0;
302
303 psa_status = psa_aead_verify(&operation,
304 NULL, 0, &remaining_plaintext_len,
305 &aeadtext[bytes_output], aeadtext_length - bytes_output);
306
307 if (psa_status == PSA_SUCCESS) {
308
309 *plaintext_length = bytes_output + remaining_plaintext_len;
310 }
311 else {
312
313 psa_aead_abort(&operation);
314 }
315 }
316 else {
317
318 psa_aead_abort(&operation);
319 }
320
321 return psa_status;
322 }
323