/src/mbedtls/library/psa_crypto_aead.c
Line | Count | Source |
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 | return status; |
314 | 0 | } |
315 | | |
316 | | /* Set the key and algorithm for a multipart authenticated encryption |
317 | | * operation. */ |
318 | | psa_status_t mbedtls_psa_aead_encrypt_setup( |
319 | | mbedtls_psa_aead_operation_t *operation, |
320 | | const psa_key_attributes_t *attributes, |
321 | | const uint8_t *key_buffer, |
322 | | size_t key_buffer_size, |
323 | | psa_algorithm_t alg) |
324 | 0 | { |
325 | 0 | psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; |
326 | |
|
327 | 0 | status = psa_aead_setup(operation, attributes, key_buffer, |
328 | 0 | key_buffer_size, alg); |
329 | |
|
330 | 0 | if (status == PSA_SUCCESS) { |
331 | 0 | operation->is_encrypt = 1; |
332 | 0 | } |
333 | |
|
334 | 0 | return status; |
335 | 0 | } |
336 | | |
337 | | /* Set the key and algorithm for a multipart authenticated decryption |
338 | | * operation. */ |
339 | | psa_status_t mbedtls_psa_aead_decrypt_setup( |
340 | | mbedtls_psa_aead_operation_t *operation, |
341 | | const psa_key_attributes_t *attributes, |
342 | | const uint8_t *key_buffer, |
343 | | size_t key_buffer_size, |
344 | | psa_algorithm_t alg) |
345 | 0 | { |
346 | 0 | psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; |
347 | |
|
348 | 0 | status = psa_aead_setup(operation, attributes, key_buffer, |
349 | 0 | key_buffer_size, alg); |
350 | |
|
351 | 0 | if (status == PSA_SUCCESS) { |
352 | 0 | operation->is_encrypt = 0; |
353 | 0 | } |
354 | |
|
355 | 0 | return status; |
356 | 0 | } |
357 | | |
358 | | /* Set a nonce for the multipart AEAD operation*/ |
359 | | psa_status_t mbedtls_psa_aead_set_nonce( |
360 | | mbedtls_psa_aead_operation_t *operation, |
361 | | const uint8_t *nonce, |
362 | | size_t nonce_length) |
363 | 0 | { |
364 | 0 | psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; |
365 | |
|
366 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) |
367 | 0 | if (operation->alg == PSA_ALG_GCM) { |
368 | 0 | status = mbedtls_to_psa_error( |
369 | 0 | mbedtls_gcm_starts(&operation->ctx.gcm, |
370 | 0 | operation->is_encrypt ? |
371 | 0 | MBEDTLS_GCM_ENCRYPT : MBEDTLS_GCM_DECRYPT, |
372 | 0 | nonce, |
373 | 0 | nonce_length)); |
374 | 0 | } else |
375 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ |
376 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) |
377 | 0 | if (operation->alg == PSA_ALG_CCM) { |
378 | 0 | status = mbedtls_to_psa_error( |
379 | 0 | mbedtls_ccm_starts(&operation->ctx.ccm, |
380 | 0 | operation->is_encrypt ? |
381 | 0 | MBEDTLS_CCM_ENCRYPT : MBEDTLS_CCM_DECRYPT, |
382 | 0 | nonce, |
383 | 0 | nonce_length)); |
384 | 0 | } else |
385 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ |
386 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) |
387 | 0 | if (operation->alg == PSA_ALG_CHACHA20_POLY1305) { |
388 | | /* Note - ChaChaPoly allows an 8 byte nonce, but we would have to |
389 | | * allocate a buffer in the operation, copy the nonce to it and pad |
390 | | * it, so for now check the nonce is 12 bytes, as |
391 | | * mbedtls_chachapoly_starts() assumes it can read 12 bytes from the |
392 | | * passed in buffer. */ |
393 | 0 | if (nonce_length != 12) { |
394 | 0 | return PSA_ERROR_INVALID_ARGUMENT; |
395 | 0 | } |
396 | | |
397 | 0 | status = mbedtls_to_psa_error( |
398 | 0 | mbedtls_chachapoly_starts(&operation->ctx.chachapoly, |
399 | 0 | nonce, |
400 | 0 | operation->is_encrypt ? |
401 | 0 | MBEDTLS_CHACHAPOLY_ENCRYPT : |
402 | 0 | MBEDTLS_CHACHAPOLY_DECRYPT)); |
403 | 0 | } else |
404 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ |
405 | 0 | { |
406 | 0 | (void) operation; |
407 | 0 | (void) nonce; |
408 | 0 | (void) nonce_length; |
409 | |
|
410 | 0 | return PSA_ERROR_NOT_SUPPORTED; |
411 | 0 | } |
412 | | |
413 | 0 | return status; |
414 | 0 | } |
415 | | |
416 | | /* Declare the lengths of the message and additional data for AEAD. */ |
417 | | psa_status_t mbedtls_psa_aead_set_lengths( |
418 | | mbedtls_psa_aead_operation_t *operation, |
419 | | size_t ad_length, |
420 | | size_t plaintext_length) |
421 | 0 | { |
422 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) |
423 | 0 | if (operation->alg == PSA_ALG_CCM) { |
424 | 0 | return mbedtls_to_psa_error( |
425 | 0 | mbedtls_ccm_set_lengths(&operation->ctx.ccm, |
426 | 0 | ad_length, |
427 | 0 | plaintext_length, |
428 | 0 | operation->tag_length)); |
429 | |
|
430 | 0 | } |
431 | | #else /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ |
432 | | (void) operation; |
433 | | (void) ad_length; |
434 | | (void) plaintext_length; |
435 | | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ |
436 | | |
437 | 0 | return PSA_SUCCESS; |
438 | 0 | } |
439 | | |
440 | | /* Pass additional data to an active multipart AEAD operation. */ |
441 | | psa_status_t mbedtls_psa_aead_update_ad( |
442 | | mbedtls_psa_aead_operation_t *operation, |
443 | | const uint8_t *input, |
444 | | size_t input_length) |
445 | 0 | { |
446 | 0 | psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; |
447 | |
|
448 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) |
449 | 0 | if (operation->alg == PSA_ALG_GCM) { |
450 | 0 | status = mbedtls_to_psa_error( |
451 | 0 | mbedtls_gcm_update_ad(&operation->ctx.gcm, input, input_length)); |
452 | 0 | } else |
453 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ |
454 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) |
455 | 0 | if (operation->alg == PSA_ALG_CCM) { |
456 | 0 | status = mbedtls_to_psa_error( |
457 | 0 | mbedtls_ccm_update_ad(&operation->ctx.ccm, input, input_length)); |
458 | 0 | } else |
459 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ |
460 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) |
461 | 0 | if (operation->alg == PSA_ALG_CHACHA20_POLY1305) { |
462 | 0 | status = mbedtls_to_psa_error( |
463 | 0 | mbedtls_chachapoly_update_aad(&operation->ctx.chachapoly, |
464 | 0 | input, |
465 | 0 | input_length)); |
466 | 0 | } else |
467 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ |
468 | 0 | { |
469 | 0 | (void) operation; |
470 | 0 | (void) input; |
471 | 0 | (void) input_length; |
472 | |
|
473 | 0 | return PSA_ERROR_NOT_SUPPORTED; |
474 | 0 | } |
475 | | |
476 | 0 | return status; |
477 | 0 | } |
478 | | |
479 | | /* Encrypt or decrypt a message fragment in an active multipart AEAD |
480 | | * operation.*/ |
481 | | psa_status_t mbedtls_psa_aead_update( |
482 | | mbedtls_psa_aead_operation_t *operation, |
483 | | const uint8_t *input, |
484 | | size_t input_length, |
485 | | uint8_t *output, |
486 | | size_t output_size, |
487 | | size_t *output_length) |
488 | 0 | { |
489 | 0 | size_t update_output_length; |
490 | 0 | psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; |
491 | |
|
492 | 0 | update_output_length = input_length; |
493 | |
|
494 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) |
495 | 0 | if (operation->alg == PSA_ALG_GCM) { |
496 | 0 | status = mbedtls_to_psa_error( |
497 | 0 | mbedtls_gcm_update(&operation->ctx.gcm, |
498 | 0 | input, input_length, |
499 | 0 | output, output_size, |
500 | 0 | &update_output_length)); |
501 | 0 | } else |
502 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ |
503 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) |
504 | 0 | if (operation->alg == PSA_ALG_CCM) { |
505 | 0 | if (output_size < input_length) { |
506 | 0 | return PSA_ERROR_BUFFER_TOO_SMALL; |
507 | 0 | } |
508 | | |
509 | 0 | status = mbedtls_to_psa_error( |
510 | 0 | mbedtls_ccm_update(&operation->ctx.ccm, |
511 | 0 | input, input_length, |
512 | 0 | output, output_size, |
513 | 0 | &update_output_length)); |
514 | 0 | } else |
515 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ |
516 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) |
517 | 0 | if (operation->alg == PSA_ALG_CHACHA20_POLY1305) { |
518 | 0 | if (output_size < input_length) { |
519 | 0 | return PSA_ERROR_BUFFER_TOO_SMALL; |
520 | 0 | } |
521 | | |
522 | 0 | status = mbedtls_to_psa_error( |
523 | 0 | mbedtls_chachapoly_update(&operation->ctx.chachapoly, |
524 | 0 | input_length, |
525 | 0 | input, |
526 | 0 | output)); |
527 | 0 | } else |
528 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ |
529 | 0 | { |
530 | 0 | (void) operation; |
531 | 0 | (void) input; |
532 | 0 | (void) output; |
533 | 0 | (void) output_size; |
534 | |
|
535 | 0 | return PSA_ERROR_NOT_SUPPORTED; |
536 | 0 | } |
537 | | |
538 | 0 | if (status == PSA_SUCCESS) { |
539 | 0 | *output_length = update_output_length; |
540 | 0 | } |
541 | |
|
542 | 0 | return status; |
543 | 0 | } |
544 | | |
545 | | /* Finish encrypting a message in a multipart AEAD operation. */ |
546 | | psa_status_t mbedtls_psa_aead_finish( |
547 | | mbedtls_psa_aead_operation_t *operation, |
548 | | uint8_t *ciphertext, |
549 | | size_t ciphertext_size, |
550 | | size_t *ciphertext_length, |
551 | | uint8_t *tag, |
552 | | size_t tag_size, |
553 | | size_t *tag_length) |
554 | 0 | { |
555 | 0 | psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; |
556 | 0 | size_t finish_output_size = 0; |
557 | |
|
558 | 0 | if (tag_size < operation->tag_length) { |
559 | 0 | return PSA_ERROR_BUFFER_TOO_SMALL; |
560 | 0 | } |
561 | | |
562 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) |
563 | 0 | if (operation->alg == PSA_ALG_GCM) { |
564 | 0 | status = mbedtls_to_psa_error( |
565 | 0 | mbedtls_gcm_finish(&operation->ctx.gcm, |
566 | 0 | ciphertext, ciphertext_size, ciphertext_length, |
567 | 0 | tag, operation->tag_length)); |
568 | 0 | } else |
569 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ |
570 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) |
571 | 0 | if (operation->alg == PSA_ALG_CCM) { |
572 | | /* tag must be big enough to store a tag of size passed into set |
573 | | * lengths. */ |
574 | 0 | if (tag_size < operation->tag_length) { |
575 | 0 | return PSA_ERROR_BUFFER_TOO_SMALL; |
576 | 0 | } |
577 | | |
578 | 0 | status = mbedtls_to_psa_error( |
579 | 0 | mbedtls_ccm_finish(&operation->ctx.ccm, |
580 | 0 | tag, operation->tag_length)); |
581 | 0 | } else |
582 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ |
583 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) |
584 | 0 | if (operation->alg == PSA_ALG_CHACHA20_POLY1305) { |
585 | | /* Belt and braces. Although the above tag_size check should have |
586 | | * already done this, if we later start supporting smaller tag sizes |
587 | | * for chachapoly, then passing a tag buffer smaller than 16 into here |
588 | | * could cause a buffer overflow, so better safe than sorry. */ |
589 | 0 | if (tag_size < 16) { |
590 | 0 | return PSA_ERROR_BUFFER_TOO_SMALL; |
591 | 0 | } |
592 | | |
593 | 0 | status = mbedtls_to_psa_error( |
594 | 0 | mbedtls_chachapoly_finish(&operation->ctx.chachapoly, |
595 | 0 | tag)); |
596 | 0 | } else |
597 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ |
598 | 0 | { |
599 | 0 | (void) ciphertext; |
600 | 0 | (void) ciphertext_size; |
601 | 0 | (void) ciphertext_length; |
602 | 0 | (void) tag; |
603 | 0 | (void) tag_size; |
604 | 0 | (void) tag_length; |
605 | |
|
606 | 0 | return PSA_ERROR_NOT_SUPPORTED; |
607 | 0 | } |
608 | | |
609 | 0 | if (status == PSA_SUCCESS) { |
610 | | /* This will be zero for all supported algorithms currently, but left |
611 | | * here for future support. */ |
612 | 0 | *ciphertext_length = finish_output_size; |
613 | 0 | *tag_length = operation->tag_length; |
614 | 0 | } |
615 | |
|
616 | 0 | return status; |
617 | 0 | } |
618 | | |
619 | | /* Abort an AEAD operation */ |
620 | | psa_status_t mbedtls_psa_aead_abort( |
621 | | mbedtls_psa_aead_operation_t *operation) |
622 | 0 | { |
623 | 0 | switch (operation->alg) { |
624 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) |
625 | 0 | case PSA_ALG_CCM: |
626 | 0 | mbedtls_ccm_free(&operation->ctx.ccm); |
627 | 0 | break; |
628 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ |
629 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) |
630 | 0 | case PSA_ALG_GCM: |
631 | 0 | mbedtls_gcm_free(&operation->ctx.gcm); |
632 | 0 | break; |
633 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ |
634 | 0 | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) |
635 | 0 | case PSA_ALG_CHACHA20_POLY1305: |
636 | 0 | mbedtls_chachapoly_free(&operation->ctx.chachapoly); |
637 | 0 | break; |
638 | 0 | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ |
639 | 0 | } |
640 | | |
641 | 0 | operation->is_encrypt = 0; |
642 | |
|
643 | 0 | return PSA_SUCCESS; |
644 | 0 | } |
645 | | |
646 | | #endif /* MBEDTLS_PSA_CRYPTO_C */ |