blob: c820d22202ebdff0b1aab0551b14f8683f47278d [file] [log] [blame]
Julian Halld4071382021-07-07 16:45:53 +01001/*
Julian Hallee8e8242022-02-11 14:24:53 +00002 * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
Julian Halld4071382021-07-07 16:45:53 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Julian Halld4071382021-07-07 16:45:53 +01007#include <psa/crypto.h>
8#include "psa_crypto_client.h"
Julian Halla9490042021-08-04 10:43:34 +01009#include "crypto_caller_selector.h"
Julian Hall7a703402021-08-04 09:20:43 +010010
Julian Halld670b412021-07-19 15:16:27 +010011psa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation,
12 psa_key_id_t key,
13 psa_algorithm_t alg)
14{
Julian Hall7a703402021-08-04 09:20:43 +010015 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);
Julian Halld670b412021-07-19 15:16:27 +010020}
21
22psa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation,
23 psa_key_id_t key,
24 psa_algorithm_t alg)
25{
Julian Hall7a703402021-08-04 09:20:43 +010026 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);
Julian Halld670b412021-07-19 15:16:27 +010031}
32
33psa_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{
Julian Hall7a703402021-08-04 09:20:43 +010038 return crypto_caller_aead_generate_nonce(&psa_crypto_client_instance.base,
39 operation->handle,
40 nonce, nonce_size, nonce_length);
Julian Halld670b412021-07-19 15:16:27 +010041}
42
43psa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation,
44 const uint8_t *nonce,
45 size_t nonce_length)
46{
Julian Hall7a703402021-08-04 09:20:43 +010047 return crypto_caller_aead_set_nonce(&psa_crypto_client_instance.base,
48 operation->handle,
49 nonce, nonce_length);
Julian Halld670b412021-07-19 15:16:27 +010050}
51
52psa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation,
53 size_t ad_length,
54 size_t plaintext_length)
55{
Julian Hall7a703402021-08-04 09:20:43 +010056 return crypto_caller_aead_set_lengths(&psa_crypto_client_instance.base,
57 operation->handle,
58 ad_length, plaintext_length);
Julian Halld670b412021-07-19 15:16:27 +010059}
60
61psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation,
62 const uint8_t *input,
63 size_t input_length)
64{
Julian Hall7a703402021-08-04 09:20:43 +010065 return crypto_caller_aead_update_ad(&psa_crypto_client_instance.base,
66 operation->handle,
67 input, input_length);
Julian Halld670b412021-07-19 15:16:27 +010068}
69
70psa_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{
Julian Hall16961d92022-02-16 11:36:09 +000077 psa_status_t status = crypto_caller_aead_update(&psa_crypto_client_instance.base,
Julian Hall7a703402021-08-04 09:20:43 +010078 operation->handle,
79 input, input_length,
80 output, output_size, output_length);
Julian Hall16961d92022-02-16 11:36:09 +000081
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;
Julian Halld670b412021-07-19 15:16:27 +010093}
94
95psa_status_t psa_aead_finish(psa_aead_operation_t *operation,
Julian Hall83456062021-07-22 11:37:09 +010096 uint8_t *aeadtext,
97 size_t aeadtext_size,
98 size_t *aeadtext_length,
Julian Halld670b412021-07-19 15:16:27 +010099 uint8_t *tag,
100 size_t tag_size,
101 size_t *tag_length)
102{
Julian Hall7a703402021-08-04 09:20:43 +0100103 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);
Julian Halld670b412021-07-19 15:16:27 +0100107}
108
109psa_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{
Julian Hall7a703402021-08-04 09:20:43 +0100116 return crypto_caller_aead_verify(&psa_crypto_client_instance.base,
117 operation->handle,
118 plaintext, plaintext_size, plaintext_length,
119 tag, tag_length);
Julian Halld670b412021-07-19 15:16:27 +0100120}
121
122psa_status_t psa_aead_abort(psa_aead_operation_t *operation)
123{
Julian Hall7a703402021-08-04 09:20:43 +0100124 return crypto_caller_aead_abort(&psa_crypto_client_instance.base,
125 operation->handle);
Julian Halld670b412021-07-19 15:16:27 +0100126}
Julian Hallee8e8242022-02-11 14:24:53 +0000127
128static 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
165static 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
216psa_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 }
Julian Hallc6d7e4d2022-02-16 10:37:04 +0000256 else {
257
258 psa_aead_abort(&operation);
259 }
Julian Hallee8e8242022-02-11 14:24:53 +0000260 }
261 else {
262
263 psa_aead_abort(&operation);
264 }
265
266 return psa_status;
267}
268
269psa_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 }
Julian Hallc6d7e4d2022-02-16 10:37:04 +0000311 else {
312
313 psa_aead_abort(&operation);
314 }
Julian Hallee8e8242022-02-11 14:24:53 +0000315 }
316 else {
317
318 psa_aead_abort(&operation);
319 }
320
321 return psa_status;
322}