/src/mbedtls/library/psa_crypto_aead.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * PSA AEAD entry points |
3 | | */ |
4 | | /* |
5 | | * Copyright The Mbed TLS Contributors |
6 | | * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later |
7 | | */ |
8 | | |
9 | | #include "common.h" |
10 | | |
11 | | #if defined(MBEDTLS_PSA_CRYPTO_C) |
12 | | |
13 | | #include "psa_crypto_aead.h" |
14 | | #include "psa_crypto_core.h" |
15 | | #include "psa_crypto_cipher.h" |
16 | | |
17 | | #include <string.h> |
18 | | #include "mbedtls/platform.h" |
19 | | |
20 | | #include "mbedtls/ccm.h" |
21 | | #include "mbedtls/chachapoly.h" |
22 | | #include "mbedtls/cipher.h" |
23 | | #include "mbedtls/gcm.h" |
24 | | #include "mbedtls/error.h" |
25 | | |
26 | | static psa_status_t psa_aead_setup( |
27 | | mbedtls_psa_aead_operation_t *operation, |
28 | | const psa_key_attributes_t *attributes, |
29 | | const uint8_t *key_buffer, |
30 | | size_t key_buffer_size, |
31 | | psa_algorithm_t alg) |
32 | 0 | { |
33 | 0 | psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; |
34 | 0 | mbedtls_cipher_id_t cipher_id; |
35 | 0 | mbedtls_cipher_mode_t mode; |
36 | 0 | size_t key_bits = attributes->bits; |
37 | 0 | (void) key_buffer_size; |
38 | |
|
39 | 0 | status = mbedtls_cipher_values_from_psa(alg, attributes->type, |
40 | 0 | &key_bits, &mode, &cipher_id); |
41 | 0 | if (status != PSA_SUCCESS) { |
42 | 0 | return status; |
43 | 0 | } |
44 | | |
45 | 0 | switch (PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0)) { |
46 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) |
47 | 0 | case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0): |
48 | 0 | operation->alg = PSA_ALG_CCM; |
49 | | /* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16. |
50 | | * The call to mbedtls_ccm_encrypt_and_tag or |
51 | | * mbedtls_ccm_auth_decrypt will validate the tag length. */ |
52 | 0 | if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(attributes->type) != 16) { |
53 | 0 | return PSA_ERROR_INVALID_ARGUMENT; |
54 | 0 | } |
55 | | |
56 | 0 | mbedtls_ccm_init(&operation->ctx.ccm); |
57 | 0 | status = mbedtls_to_psa_error( |
58 | 0 | mbedtls_ccm_setkey(&operation->ctx.ccm, cipher_id, |
59 | 0 | key_buffer, (unsigned int) key_bits)); |
60 | 0 | if (status != PSA_SUCCESS) { |
61 | 0 | return status; |
62 | 0 | } |
63 | 0 | break; |
64 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ |
65 | | |
66 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) |
67 | 0 | case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0): |
68 | 0 | operation->alg = PSA_ALG_GCM; |
69 | | /* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16. |
70 | | * The call to mbedtls_gcm_crypt_and_tag or |
71 | | * mbedtls_gcm_auth_decrypt will validate the tag length. */ |
72 | 0 | if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(attributes->type) != 16) { |
73 | 0 | return PSA_ERROR_INVALID_ARGUMENT; |
74 | 0 | } |
75 | | |
76 | 0 | mbedtls_gcm_init(&operation->ctx.gcm); |
77 | 0 | status = mbedtls_to_psa_error( |
78 | 0 | mbedtls_gcm_setkey(&operation->ctx.gcm, cipher_id, |
79 | 0 | key_buffer, (unsigned int) key_bits)); |
80 | 0 | if (status != PSA_SUCCESS) { |
81 | 0 | return status; |
82 | 0 | } |
83 | 0 | break; |
84 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ |
85 | | |
86 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) |
87 | 0 | case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0): |
88 | 0 | operation->alg = PSA_ALG_CHACHA20_POLY1305; |
89 | | /* We only support the default tag length. */ |
90 | 0 | if (alg != PSA_ALG_CHACHA20_POLY1305) { |
91 | 0 | return PSA_ERROR_NOT_SUPPORTED; |
92 | 0 | } |
93 | | |
94 | 0 | mbedtls_chachapoly_init(&operation->ctx.chachapoly); |
95 | 0 | status = mbedtls_to_psa_error( |
96 | 0 | mbedtls_chachapoly_setkey(&operation->ctx.chachapoly, |
97 | 0 | key_buffer)); |
98 | 0 | if (status != PSA_SUCCESS) { |
99 | 0 | return status; |
100 | 0 | } |
101 | 0 | break; |
102 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ |
103 | | |
104 | 0 | default: |
105 | 0 | (void) status; |
106 | 0 | (void) key_buffer; |
107 | 0 | return PSA_ERROR_NOT_SUPPORTED; |
108 | 0 | } |
109 | | |
110 | 0 | operation->key_type = psa_get_key_type(attributes); |
111 | |
|
112 | 0 | operation->tag_length = PSA_ALG_AEAD_GET_TAG_LENGTH(alg); |
113 | |
|
114 | 0 | return PSA_SUCCESS; |
115 | 0 | } |
116 | | |
117 | | psa_status_t mbedtls_psa_aead_encrypt( |
118 | | const psa_key_attributes_t *attributes, |
119 | | const uint8_t *key_buffer, size_t key_buffer_size, |
120 | | psa_algorithm_t alg, |
121 | | const uint8_t *nonce, size_t nonce_length, |
122 | | const uint8_t *additional_data, size_t additional_data_length, |
123 | | const uint8_t *plaintext, size_t plaintext_length, |
124 | | uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length) |
125 | 0 | { |
126 | 0 | psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; |
127 | 0 | mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT; |
128 | 0 | uint8_t *tag; |
129 | |
|
130 | 0 | status = psa_aead_setup(&operation, attributes, key_buffer, |
131 | 0 | key_buffer_size, alg); |
132 | |
|
133 | 0 | if (status != PSA_SUCCESS) { |
134 | 0 | goto exit; |
135 | 0 | } |
136 | | |
137 | | /* For all currently supported modes, the tag is at the end of the |
138 | | * ciphertext. */ |
139 | 0 | if (ciphertext_size < (plaintext_length + operation.tag_length)) { |
140 | 0 | status = PSA_ERROR_BUFFER_TOO_SMALL; |
141 | 0 | goto exit; |
142 | 0 | } |
143 | 0 | tag = ciphertext + plaintext_length; |
144 | |
|
145 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) |
146 | 0 | if (operation.alg == PSA_ALG_CCM) { |
147 | 0 | status = mbedtls_to_psa_error( |
148 | 0 | mbedtls_ccm_encrypt_and_tag(&operation.ctx.ccm, |
149 | 0 | plaintext_length, |
150 | 0 | nonce, nonce_length, |
151 | 0 | additional_data, |
152 | 0 | additional_data_length, |
153 | 0 | plaintext, ciphertext, |
154 | 0 | tag, operation.tag_length)); |
155 | 0 | } else |
156 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ |
157 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) |
158 | 0 | if (operation.alg == PSA_ALG_GCM) { |
159 | 0 | status = mbedtls_to_psa_error( |
160 | 0 | mbedtls_gcm_crypt_and_tag(&operation.ctx.gcm, |
161 | 0 | MBEDTLS_GCM_ENCRYPT, |
162 | 0 | plaintext_length, |
163 | 0 | nonce, nonce_length, |
164 | 0 | additional_data, additional_data_length, |
165 | 0 | plaintext, ciphertext, |
166 | 0 | operation.tag_length, tag)); |
167 | 0 | } else |
168 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ |
169 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) |
170 | 0 | if (operation.alg == PSA_ALG_CHACHA20_POLY1305) { |
171 | 0 | if (operation.tag_length != 16) { |
172 | 0 | status = PSA_ERROR_NOT_SUPPORTED; |
173 | 0 | goto exit; |
174 | 0 | } |
175 | 0 | status = mbedtls_to_psa_error( |
176 | 0 | mbedtls_chachapoly_encrypt_and_tag(&operation.ctx.chachapoly, |
177 | 0 | plaintext_length, |
178 | 0 | nonce, |
179 | 0 | additional_data, |
180 | 0 | additional_data_length, |
181 | 0 | plaintext, |
182 | 0 | ciphertext, |
183 | 0 | tag)); |
184 | 0 | } else |
185 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ |
186 | 0 | { |
187 | 0 | (void) tag; |
188 | 0 | (void) nonce; |
189 | 0 | (void) nonce_length; |
190 | 0 | (void) additional_data; |
191 | 0 | (void) additional_data_length; |
192 | 0 | (void) plaintext; |
193 | 0 | return PSA_ERROR_NOT_SUPPORTED; |
194 | 0 | } |
195 | | |
196 | 0 | if (status == PSA_SUCCESS) { |
197 | 0 | *ciphertext_length = plaintext_length + operation.tag_length; |
198 | 0 | } |
199 | |
|
200 | 0 | exit: |
201 | 0 | mbedtls_psa_aead_abort(&operation); |
202 | |
|
203 | 0 | return status; |
204 | 0 | } |
205 | | |
206 | | /* Locate the tag in a ciphertext buffer containing the encrypted data |
207 | | * followed by the tag. Return the length of the part preceding the tag in |
208 | | * *plaintext_length. This is the size of the plaintext in modes where |
209 | | * the encrypted data has the same size as the plaintext, such as |
210 | | * CCM and GCM. */ |
211 | | static psa_status_t psa_aead_unpadded_locate_tag(size_t tag_length, |
212 | | const uint8_t *ciphertext, |
213 | | size_t ciphertext_length, |
214 | | size_t plaintext_size, |
215 | | const uint8_t **p_tag) |
216 | 0 | { |
217 | 0 | size_t payload_length; |
218 | 0 | if (tag_length > ciphertext_length) { |
219 | 0 | return PSA_ERROR_INVALID_ARGUMENT; |
220 | 0 | } |
221 | 0 | payload_length = ciphertext_length - tag_length; |
222 | 0 | if (payload_length > plaintext_size) { |
223 | 0 | return PSA_ERROR_BUFFER_TOO_SMALL; |
224 | 0 | } |
225 | 0 | *p_tag = ciphertext + payload_length; |
226 | 0 | return PSA_SUCCESS; |
227 | 0 | } |
228 | | |
229 | | psa_status_t mbedtls_psa_aead_decrypt( |
230 | | const psa_key_attributes_t *attributes, |
231 | | const uint8_t *key_buffer, size_t key_buffer_size, |
232 | | psa_algorithm_t alg, |
233 | | const uint8_t *nonce, size_t nonce_length, |
234 | | const uint8_t *additional_data, size_t additional_data_length, |
235 | | const uint8_t *ciphertext, size_t ciphertext_length, |
236 | | uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length) |
237 | 0 | { |
238 | 0 | psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; |
239 | 0 | mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT; |
240 | 0 | const uint8_t *tag = NULL; |
241 | |
|
242 | 0 | status = psa_aead_setup(&operation, attributes, key_buffer, |
243 | 0 | key_buffer_size, alg); |
244 | |
|
245 | 0 | if (status != PSA_SUCCESS) { |
246 | 0 | goto exit; |
247 | 0 | } |
248 | | |
249 | 0 | status = psa_aead_unpadded_locate_tag(operation.tag_length, |
250 | 0 | ciphertext, ciphertext_length, |
251 | 0 | plaintext_size, &tag); |
252 | 0 | if (status != PSA_SUCCESS) { |
253 | 0 | goto exit; |
254 | 0 | } |
255 | | |
256 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) |
257 | 0 | if (operation.alg == PSA_ALG_CCM) { |
258 | 0 | status = mbedtls_to_psa_error( |
259 | 0 | mbedtls_ccm_auth_decrypt(&operation.ctx.ccm, |
260 | 0 | ciphertext_length - operation.tag_length, |
261 | 0 | nonce, nonce_length, |
262 | 0 | additional_data, |
263 | 0 | additional_data_length, |
264 | 0 | ciphertext, plaintext, |
265 | 0 | tag, operation.tag_length)); |
266 | 0 | } else |
267 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ |
268 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) |
269 | 0 | if (operation.alg == PSA_ALG_GCM) { |
270 | 0 | status = mbedtls_to_psa_error( |
271 | 0 | mbedtls_gcm_auth_decrypt(&operation.ctx.gcm, |
272 | 0 | ciphertext_length - operation.tag_length, |
273 | 0 | nonce, nonce_length, |
274 | 0 | additional_data, |
275 | 0 | additional_data_length, |
276 | 0 | tag, operation.tag_length, |
277 | 0 | ciphertext, plaintext)); |
278 | 0 | } else |
279 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ |
280 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) |
281 | 0 | if (operation.alg == PSA_ALG_CHACHA20_POLY1305) { |
282 | 0 | if (operation.tag_length != 16) { |
283 | 0 | status = PSA_ERROR_NOT_SUPPORTED; |
284 | 0 | goto exit; |
285 | 0 | } |
286 | 0 | status = mbedtls_to_psa_error( |
287 | 0 | mbedtls_chachapoly_auth_decrypt(&operation.ctx.chachapoly, |
288 | 0 | ciphertext_length - operation.tag_length, |
289 | 0 | nonce, |
290 | 0 | additional_data, |
291 | 0 | additional_data_length, |
292 | 0 | tag, |
293 | 0 | ciphertext, |
294 | 0 | plaintext)); |
295 | 0 | } else |
296 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ |
297 | 0 | { |
298 | 0 | (void) nonce; |
299 | 0 | (void) nonce_length; |
300 | 0 | (void) additional_data; |
301 | 0 | (void) additional_data_length; |
302 | 0 | (void) plaintext; |
303 | 0 | return PSA_ERROR_NOT_SUPPORTED; |
304 | 0 | } |
305 | | |
306 | 0 | if (status == PSA_SUCCESS) { |
307 | 0 | *plaintext_length = ciphertext_length - operation.tag_length; |
308 | 0 | } |
309 | |
|
310 | 0 | exit: |
311 | 0 | mbedtls_psa_aead_abort(&operation); |
312 | |
|
313 | 0 | if (status == PSA_SUCCESS) { |
314 | 0 | *plaintext_length = ciphertext_length - operation.tag_length; |
315 | 0 | } |
316 | 0 | return status; |
317 | 0 | } |
318 | | |
319 | | /* Set the key and algorithm for a multipart authenticated encryption |
320 | | * operation. */ |
321 | | psa_status_t mbedtls_psa_aead_encrypt_setup( |
322 | | mbedtls_psa_aead_operation_t *operation, |
323 | | const psa_key_attributes_t *attributes, |
324 | | const uint8_t *key_buffer, |
325 | | size_t key_buffer_size, |
326 | | psa_algorithm_t alg) |
327 | 0 | { |
328 | 0 | psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; |
329 | |
|
330 | 0 | status = psa_aead_setup(operation, attributes, key_buffer, |
331 | 0 | key_buffer_size, alg); |
332 | |
|
333 | 0 | if (status == PSA_SUCCESS) { |
334 | 0 | operation->is_encrypt = 1; |
335 | 0 | } |
336 | |
|
337 | 0 | return status; |
338 | 0 | } |
339 | | |
340 | | /* Set the key and algorithm for a multipart authenticated decryption |
341 | | * operation. */ |
342 | | psa_status_t mbedtls_psa_aead_decrypt_setup( |
343 | | mbedtls_psa_aead_operation_t *operation, |
344 | | const psa_key_attributes_t *attributes, |
345 | | const uint8_t *key_buffer, |
346 | | size_t key_buffer_size, |
347 | | psa_algorithm_t alg) |
348 | 0 | { |
349 | 0 | psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; |
350 | |
|
351 | 0 | status = psa_aead_setup(operation, attributes, key_buffer, |
352 | 0 | key_buffer_size, alg); |
353 | |
|
354 | 0 | if (status == PSA_SUCCESS) { |
355 | 0 | operation->is_encrypt = 0; |
356 | 0 | } |
357 | |
|
358 | 0 | return status; |
359 | 0 | } |
360 | | |
361 | | /* Set a nonce for the multipart AEAD operation*/ |
362 | | psa_status_t mbedtls_psa_aead_set_nonce( |
363 | | mbedtls_psa_aead_operation_t *operation, |
364 | | const uint8_t *nonce, |
365 | | size_t nonce_length) |
366 | 0 | { |
367 | 0 | psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; |
368 | |
|
369 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) |
370 | 0 | if (operation->alg == PSA_ALG_GCM) { |
371 | 0 | status = mbedtls_to_psa_error( |
372 | 0 | mbedtls_gcm_starts(&operation->ctx.gcm, |
373 | 0 | operation->is_encrypt ? |
374 | 0 | MBEDTLS_GCM_ENCRYPT : MBEDTLS_GCM_DECRYPT, |
375 | 0 | nonce, |
376 | 0 | nonce_length)); |
377 | 0 | } else |
378 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ |
379 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) |
380 | 0 | if (operation->alg == PSA_ALG_CCM) { |
381 | 0 | status = mbedtls_to_psa_error( |
382 | 0 | mbedtls_ccm_starts(&operation->ctx.ccm, |
383 | 0 | operation->is_encrypt ? |
384 | 0 | MBEDTLS_CCM_ENCRYPT : MBEDTLS_CCM_DECRYPT, |
385 | 0 | nonce, |
386 | 0 | nonce_length)); |
387 | 0 | } else |
388 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ |
389 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) |
390 | 0 | if (operation->alg == PSA_ALG_CHACHA20_POLY1305) { |
391 | | /* Note - ChaChaPoly allows an 8 byte nonce, but we would have to |
392 | | * allocate a buffer in the operation, copy the nonce to it and pad |
393 | | * it, so for now check the nonce is 12 bytes, as |
394 | | * mbedtls_chachapoly_starts() assumes it can read 12 bytes from the |
395 | | * passed in buffer. */ |
396 | 0 | if (nonce_length != 12) { |
397 | 0 | return PSA_ERROR_INVALID_ARGUMENT; |
398 | 0 | } |
399 | | |
400 | 0 | status = mbedtls_to_psa_error( |
401 | 0 | mbedtls_chachapoly_starts(&operation->ctx.chachapoly, |
402 | 0 | nonce, |
403 | 0 | operation->is_encrypt ? |
404 | 0 | MBEDTLS_CHACHAPOLY_ENCRYPT : |
405 | 0 | MBEDTLS_CHACHAPOLY_DECRYPT)); |
406 | 0 | } else |
407 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ |
408 | 0 | { |
409 | 0 | (void) operation; |
410 | 0 | (void) nonce; |
411 | 0 | (void) nonce_length; |
412 | |
|
413 | 0 | return PSA_ERROR_NOT_SUPPORTED; |
414 | 0 | } |
415 | | |
416 | 0 | return status; |
417 | 0 | } |
418 | | |
419 | | /* Declare the lengths of the message and additional data for AEAD. */ |
420 | | psa_status_t mbedtls_psa_aead_set_lengths( |
421 | | mbedtls_psa_aead_operation_t *operation, |
422 | | size_t ad_length, |
423 | | size_t plaintext_length) |
424 | 0 | { |
425 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) |
426 | 0 | if (operation->alg == PSA_ALG_CCM) { |
427 | 0 | return mbedtls_to_psa_error( |
428 | 0 | mbedtls_ccm_set_lengths(&operation->ctx.ccm, |
429 | 0 | ad_length, |
430 | 0 | plaintext_length, |
431 | 0 | operation->tag_length)); |
432 | |
|
433 | 0 | } |
434 | | #else /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ |
435 | | (void) operation; |
436 | | (void) ad_length; |
437 | | (void) plaintext_length; |
438 | | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ |
439 | | |
440 | 0 | return PSA_SUCCESS; |
441 | 0 | } |
442 | | |
443 | | /* Pass additional data to an active multipart AEAD operation. */ |
444 | | psa_status_t mbedtls_psa_aead_update_ad( |
445 | | mbedtls_psa_aead_operation_t *operation, |
446 | | const uint8_t *input, |
447 | | size_t input_length) |
448 | 0 | { |
449 | 0 | psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; |
450 | |
|
451 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) |
452 | 0 | if (operation->alg == PSA_ALG_GCM) { |
453 | 0 | status = mbedtls_to_psa_error( |
454 | 0 | mbedtls_gcm_update_ad(&operation->ctx.gcm, input, input_length)); |
455 | 0 | } else |
456 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ |
457 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) |
458 | 0 | if (operation->alg == PSA_ALG_CCM) { |
459 | 0 | status = mbedtls_to_psa_error( |
460 | 0 | mbedtls_ccm_update_ad(&operation->ctx.ccm, input, input_length)); |
461 | 0 | } else |
462 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ |
463 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) |
464 | 0 | if (operation->alg == PSA_ALG_CHACHA20_POLY1305) { |
465 | 0 | status = mbedtls_to_psa_error( |
466 | 0 | mbedtls_chachapoly_update_aad(&operation->ctx.chachapoly, |
467 | 0 | input, |
468 | 0 | input_length)); |
469 | 0 | } else |
470 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ |
471 | 0 | { |
472 | 0 | (void) operation; |
473 | 0 | (void) input; |
474 | 0 | (void) input_length; |
475 | |
|
476 | 0 | return PSA_ERROR_NOT_SUPPORTED; |
477 | 0 | } |
478 | | |
479 | 0 | return status; |
480 | 0 | } |
481 | | |
482 | | /* Encrypt or decrypt a message fragment in an active multipart AEAD |
483 | | * operation.*/ |
484 | | psa_status_t mbedtls_psa_aead_update( |
485 | | mbedtls_psa_aead_operation_t *operation, |
486 | | const uint8_t *input, |
487 | | size_t input_length, |
488 | | uint8_t *output, |
489 | | size_t output_size, |
490 | | size_t *output_length) |
491 | 0 | { |
492 | 0 | size_t update_output_length; |
493 | 0 | psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; |
494 | |
|
495 | 0 | update_output_length = input_length; |
496 | |
|
497 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) |
498 | 0 | if (operation->alg == PSA_ALG_GCM) { |
499 | 0 | status = mbedtls_to_psa_error( |
500 | 0 | mbedtls_gcm_update(&operation->ctx.gcm, |
501 | 0 | input, input_length, |
502 | 0 | output, output_size, |
503 | 0 | &update_output_length)); |
504 | 0 | } else |
505 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ |
506 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) |
507 | 0 | if (operation->alg == PSA_ALG_CCM) { |
508 | 0 | if (output_size < input_length) { |
509 | 0 | return PSA_ERROR_BUFFER_TOO_SMALL; |
510 | 0 | } |
511 | | |
512 | 0 | status = mbedtls_to_psa_error( |
513 | 0 | mbedtls_ccm_update(&operation->ctx.ccm, |
514 | 0 | input, input_length, |
515 | 0 | output, output_size, |
516 | 0 | &update_output_length)); |
517 | 0 | } else |
518 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ |
519 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) |
520 | 0 | if (operation->alg == PSA_ALG_CHACHA20_POLY1305) { |
521 | 0 | if (output_size < input_length) { |
522 | 0 | return PSA_ERROR_BUFFER_TOO_SMALL; |
523 | 0 | } |
524 | | |
525 | 0 | status = mbedtls_to_psa_error( |
526 | 0 | mbedtls_chachapoly_update(&operation->ctx.chachapoly, |
527 | 0 | input_length, |
528 | 0 | input, |
529 | 0 | output)); |
530 | 0 | } else |
531 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ |
532 | 0 | { |
533 | 0 | (void) operation; |
534 | 0 | (void) input; |
535 | 0 | (void) output; |
536 | 0 | (void) output_size; |
537 | |
|
538 | 0 | return PSA_ERROR_NOT_SUPPORTED; |
539 | 0 | } |
540 | | |
541 | 0 | if (status == PSA_SUCCESS) { |
542 | 0 | *output_length = update_output_length; |
543 | 0 | } |
544 | |
|
545 | 0 | return status; |
546 | 0 | } |
547 | | |
548 | | /* Finish encrypting a message in a multipart AEAD operation. */ |
549 | | psa_status_t mbedtls_psa_aead_finish( |
550 | | mbedtls_psa_aead_operation_t *operation, |
551 | | uint8_t *ciphertext, |
552 | | size_t ciphertext_size, |
553 | | size_t *ciphertext_length, |
554 | | uint8_t *tag, |
555 | | size_t tag_size, |
556 | | size_t *tag_length) |
557 | 0 | { |
558 | 0 | psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; |
559 | 0 | size_t finish_output_size = 0; |
560 | |
|
561 | 0 | if (tag_size < operation->tag_length) { |
562 | 0 | return PSA_ERROR_BUFFER_TOO_SMALL; |
563 | 0 | } |
564 | | |
565 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) |
566 | 0 | if (operation->alg == PSA_ALG_GCM) { |
567 | 0 | status = mbedtls_to_psa_error( |
568 | 0 | mbedtls_gcm_finish(&operation->ctx.gcm, |
569 | 0 | ciphertext, ciphertext_size, ciphertext_length, |
570 | 0 | tag, operation->tag_length)); |
571 | 0 | } else |
572 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ |
573 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) |
574 | 0 | if (operation->alg == PSA_ALG_CCM) { |
575 | | /* tag must be big enough to store a tag of size passed into set |
576 | | * lengths. */ |
577 | 0 | if (tag_size < operation->tag_length) { |
578 | 0 | return PSA_ERROR_BUFFER_TOO_SMALL; |
579 | 0 | } |
580 | | |
581 | 0 | status = mbedtls_to_psa_error( |
582 | 0 | mbedtls_ccm_finish(&operation->ctx.ccm, |
583 | 0 | tag, operation->tag_length)); |
584 | 0 | } else |
585 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ |
586 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) |
587 | 0 | if (operation->alg == PSA_ALG_CHACHA20_POLY1305) { |
588 | | /* Belt and braces. Although the above tag_size check should have |
589 | | * already done this, if we later start supporting smaller tag sizes |
590 | | * for chachapoly, then passing a tag buffer smaller than 16 into here |
591 | | * could cause a buffer overflow, so better safe than sorry. */ |
592 | 0 | if (tag_size < 16) { |
593 | 0 | return PSA_ERROR_BUFFER_TOO_SMALL; |
594 | 0 | } |
595 | | |
596 | 0 | status = mbedtls_to_psa_error( |
597 | 0 | mbedtls_chachapoly_finish(&operation->ctx.chachapoly, |
598 | 0 | tag)); |
599 | 0 | } else |
600 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ |
601 | 0 | { |
602 | 0 | (void) ciphertext; |
603 | 0 | (void) ciphertext_size; |
604 | 0 | (void) ciphertext_length; |
605 | 0 | (void) tag; |
606 | 0 | (void) tag_size; |
607 | 0 | (void) tag_length; |
608 | |
|
609 | 0 | return PSA_ERROR_NOT_SUPPORTED; |
610 | 0 | } |
611 | | |
612 | 0 | if (status == PSA_SUCCESS) { |
613 | | /* This will be zero for all supported algorithms currently, but left |
614 | | * here for future support. */ |
615 | 0 | *ciphertext_length = finish_output_size; |
616 | 0 | *tag_length = operation->tag_length; |
617 | 0 | } |
618 | |
|
619 | 0 | return status; |
620 | 0 | } |
621 | | |
622 | | /* Abort an AEAD operation */ |
623 | | psa_status_t mbedtls_psa_aead_abort( |
624 | | mbedtls_psa_aead_operation_t *operation) |
625 | 0 | { |
626 | 0 | switch (operation->alg) { |
627 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) |
628 | 0 | case PSA_ALG_CCM: |
629 | 0 | mbedtls_ccm_free(&operation->ctx.ccm); |
630 | 0 | break; |
631 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ |
632 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) |
633 | 0 | case PSA_ALG_GCM: |
634 | 0 | mbedtls_gcm_free(&operation->ctx.gcm); |
635 | 0 | break; |
636 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ |
637 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) |
638 | 0 | case PSA_ALG_CHACHA20_POLY1305: |
639 | 0 | mbedtls_chachapoly_free(&operation->ctx.chachapoly); |
640 | 0 | break; |
641 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ |
642 | 0 | } |
643 | | |
644 | 0 | operation->is_encrypt = 0; |
645 | |
|
646 | 0 | return PSA_SUCCESS; |
647 | 0 | } |
648 | | |
649 | | #endif /* MBEDTLS_PSA_CRYPTO_C */ |