blob: 07c52d433ac8d053b9fdd232c99d6eede12ac595 [file] [log] [blame]
Ronald Cron7ceee8d2021-03-17 16:55:43 +01001/*
2 * PSA AEAD entry points
3 */
4/*
5 * Copyright The Mbed TLS Contributors
6 * SPDX-License-Identifier: Apache-2.0
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License"); you may
9 * not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21#include "common.h"
22
23#if defined(MBEDTLS_PSA_CRYPTO_C)
24
25#include "psa_crypto_aead.h"
Ronald Cron46f91782021-03-17 08:16:34 +010026#include "psa_crypto_core.h"
27
28#include "mbedtls/ccm.h"
29#include "mbedtls/chachapoly.h"
30#include "mbedtls/cipher.h"
31#include "mbedtls/gcm.h"
32
Ronald Cron46f91782021-03-17 08:16:34 +010033
Paul Elliott07a30c42021-04-20 14:13:23 +010034static void psa_aead_abort_internal( psa_aead_operation_t *operation )
Ronald Cron46f91782021-03-17 08:16:34 +010035{
Paul Elliott07a30c42021-04-20 14:13:23 +010036 switch( operation->alg )
Ronald Cron46f91782021-03-17 08:16:34 +010037 {
38#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
39 case PSA_ALG_CCM:
40 mbedtls_ccm_free( &operation->ctx.ccm );
41 break;
42#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
43#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
44 case PSA_ALG_GCM:
45 mbedtls_gcm_free( &operation->ctx.gcm );
46 break;
47#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
Ronald Cronb9349a62021-03-26 13:32:29 +010048#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
49 case PSA_ALG_CHACHA20_POLY1305:
50 mbedtls_chachapoly_free( &operation->ctx.chachapoly );
51 break;
52#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
Ronald Cron46f91782021-03-17 08:16:34 +010053 }
54}
55
56static psa_status_t psa_aead_setup(
Paul Elliott07a30c42021-04-20 14:13:23 +010057 psa_aead_operation_t *operation,
Ronald Cron46f91782021-03-17 08:16:34 +010058 const psa_key_attributes_t *attributes,
59 const uint8_t *key_buffer,
60 psa_algorithm_t alg )
61{
62 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
63 size_t key_bits;
Ronald Cronecbc0682021-03-26 13:25:17 +010064 const mbedtls_cipher_info_t *cipher_info;
Ronald Cron46f91782021-03-17 08:16:34 +010065 mbedtls_cipher_id_t cipher_id;
Ronald Cronecbc0682021-03-26 13:25:17 +010066 size_t full_tag_length = 0;
Ronald Cron46f91782021-03-17 08:16:34 +010067
68 key_bits = attributes->core.bits;
69
Ronald Cronecbc0682021-03-26 13:25:17 +010070 cipher_info = mbedtls_cipher_info_from_psa( alg,
71 attributes->core.type, key_bits,
72 &cipher_id );
73 if( cipher_info == NULL )
Ronald Cron46f91782021-03-17 08:16:34 +010074 return( PSA_ERROR_NOT_SUPPORTED );
75
76 switch( PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, 0 ) )
77 {
78#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
79 case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 0 ):
Paul Elliott07a30c42021-04-20 14:13:23 +010080 operation->alg = PSA_ALG_CCM;
Ronald Cronecbc0682021-03-26 13:25:17 +010081 full_tag_length = 16;
Ronald Cron46f91782021-03-17 08:16:34 +010082 /* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16.
83 * The call to mbedtls_ccm_encrypt_and_tag or
84 * mbedtls_ccm_auth_decrypt will validate the tag length. */
85 if( PSA_BLOCK_CIPHER_BLOCK_LENGTH( attributes->core.type ) != 16 )
86 return( PSA_ERROR_INVALID_ARGUMENT );
87
88 mbedtls_ccm_init( &operation->ctx.ccm );
89 status = mbedtls_to_psa_error(
90 mbedtls_ccm_setkey( &operation->ctx.ccm, cipher_id,
91 key_buffer, (unsigned int) key_bits ) );
92 if( status != PSA_SUCCESS )
93 return( status );
94 break;
95#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
96
97#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
98 case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 0 ):
Paul Elliott07a30c42021-04-20 14:13:23 +010099 operation->alg = PSA_ALG_GCM;
Ronald Cronecbc0682021-03-26 13:25:17 +0100100 full_tag_length = 16;
Ronald Cron46f91782021-03-17 08:16:34 +0100101 /* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16.
102 * The call to mbedtls_gcm_crypt_and_tag or
103 * mbedtls_gcm_auth_decrypt will validate the tag length. */
104 if( PSA_BLOCK_CIPHER_BLOCK_LENGTH( attributes->core.type ) != 16 )
105 return( PSA_ERROR_INVALID_ARGUMENT );
106
107 mbedtls_gcm_init( &operation->ctx.gcm );
108 status = mbedtls_to_psa_error(
109 mbedtls_gcm_setkey( &operation->ctx.gcm, cipher_id,
110 key_buffer, (unsigned int) key_bits ) );
111 if( status != PSA_SUCCESS )
112 return( status );
113 break;
114#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
115
116#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
117 case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CHACHA20_POLY1305, 0 ):
Paul Elliott07a30c42021-04-20 14:13:23 +0100118 operation->alg = PSA_ALG_CHACHA20_POLY1305;
Ronald Cronecbc0682021-03-26 13:25:17 +0100119 full_tag_length = 16;
Ronald Cron46f91782021-03-17 08:16:34 +0100120 /* We only support the default tag length. */
121 if( alg != PSA_ALG_CHACHA20_POLY1305 )
122 return( PSA_ERROR_NOT_SUPPORTED );
123
124 mbedtls_chachapoly_init( &operation->ctx.chachapoly );
125 status = mbedtls_to_psa_error(
126 mbedtls_chachapoly_setkey( &operation->ctx.chachapoly,
127 key_buffer ) );
128 if( status != PSA_SUCCESS )
129 return( status );
130 break;
131#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
132
133 default:
134 return( PSA_ERROR_NOT_SUPPORTED );
135 }
136
Bence Szépkútiec174e22021-03-19 18:46:15 +0100137 if( PSA_AEAD_TAG_LENGTH( attributes->core.type,
138 key_bits, alg )
139 > full_tag_length )
Ronald Cron46f91782021-03-17 08:16:34 +0100140 return( PSA_ERROR_INVALID_ARGUMENT );
141
Bence Szépkútiec174e22021-03-19 18:46:15 +0100142 operation->tag_length = PSA_AEAD_TAG_LENGTH( attributes->core.type,
143 key_bits,
144 alg );
Ronald Cron46f91782021-03-17 08:16:34 +0100145
146 return( PSA_SUCCESS );
147}
148
149psa_status_t mbedtls_psa_aead_encrypt(
150 const psa_key_attributes_t *attributes,
151 const uint8_t *key_buffer, size_t key_buffer_size,
152 psa_algorithm_t alg,
153 const uint8_t *nonce, size_t nonce_length,
154 const uint8_t *additional_data, size_t additional_data_length,
155 const uint8_t *plaintext, size_t plaintext_length,
156 uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length )
157{
158 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Paul Elliott07a30c42021-04-20 14:13:23 +0100159 psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
Ronald Cron46f91782021-03-17 08:16:34 +0100160 uint8_t *tag;
161 (void) key_buffer_size;
162
163 status = psa_aead_setup( &operation, attributes, key_buffer, alg );
164 if( status != PSA_SUCCESS )
165 goto exit;
166
167 /* For all currently supported modes, the tag is at the end of the
168 * ciphertext. */
169 if( ciphertext_size < ( plaintext_length + operation.tag_length ) )
170 {
171 status = PSA_ERROR_BUFFER_TOO_SMALL;
172 goto exit;
173 }
174 tag = ciphertext + plaintext_length;
175
Ronald Cron46f91782021-03-17 08:16:34 +0100176#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
Paul Elliott07a30c42021-04-20 14:13:23 +0100177 if( operation.alg == PSA_ALG_CCM )
Ronald Cron46f91782021-03-17 08:16:34 +0100178 {
179 status = mbedtls_to_psa_error(
180 mbedtls_ccm_encrypt_and_tag( &operation.ctx.ccm,
181 plaintext_length,
182 nonce, nonce_length,
183 additional_data,
184 additional_data_length,
185 plaintext, ciphertext,
186 tag, operation.tag_length ) );
187 }
188 else
189#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
Ronald Cron810eb162021-04-06 09:01:39 +0200190#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
Paul Elliott07a30c42021-04-20 14:13:23 +0100191 if( operation.alg == PSA_ALG_GCM )
Ronald Cron810eb162021-04-06 09:01:39 +0200192 {
193 status = mbedtls_to_psa_error(
194 mbedtls_gcm_crypt_and_tag( &operation.ctx.gcm,
195 MBEDTLS_GCM_ENCRYPT,
196 plaintext_length,
197 nonce, nonce_length,
198 additional_data, additional_data_length,
199 plaintext, ciphertext,
200 operation.tag_length, tag ) );
201 }
202 else
203#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
Ronald Cron46f91782021-03-17 08:16:34 +0100204#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
Paul Elliott07a30c42021-04-20 14:13:23 +0100205 if( operation.alg == PSA_ALG_CHACHA20_POLY1305 )
Ronald Cron46f91782021-03-17 08:16:34 +0100206 {
207 if( nonce_length != 12 || operation.tag_length != 16 )
208 {
209 status = PSA_ERROR_NOT_SUPPORTED;
210 goto exit;
211 }
212 status = mbedtls_to_psa_error(
213 mbedtls_chachapoly_encrypt_and_tag( &operation.ctx.chachapoly,
214 plaintext_length,
215 nonce,
216 additional_data,
217 additional_data_length,
218 plaintext,
219 ciphertext,
220 tag ) );
221 }
222 else
223#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
224 {
225 (void) tag;
226 return( PSA_ERROR_NOT_SUPPORTED );
227 }
228
229 if( status == PSA_SUCCESS )
230 *ciphertext_length = plaintext_length + operation.tag_length;
231
232exit:
233 psa_aead_abort_internal( &operation );
234
235 return( status );
236}
237
238/* Locate the tag in a ciphertext buffer containing the encrypted data
239 * followed by the tag. Return the length of the part preceding the tag in
240 * *plaintext_length. This is the size of the plaintext in modes where
241 * the encrypted data has the same size as the plaintext, such as
242 * CCM and GCM. */
243static psa_status_t psa_aead_unpadded_locate_tag( size_t tag_length,
244 const uint8_t *ciphertext,
245 size_t ciphertext_length,
246 size_t plaintext_size,
247 const uint8_t **p_tag )
248{
249 size_t payload_length;
250 if( tag_length > ciphertext_length )
251 return( PSA_ERROR_INVALID_ARGUMENT );
252 payload_length = ciphertext_length - tag_length;
253 if( payload_length > plaintext_size )
254 return( PSA_ERROR_BUFFER_TOO_SMALL );
255 *p_tag = ciphertext + payload_length;
256 return( PSA_SUCCESS );
257}
258
259psa_status_t mbedtls_psa_aead_decrypt(
260 const psa_key_attributes_t *attributes,
261 const uint8_t *key_buffer, size_t key_buffer_size,
262 psa_algorithm_t alg,
263 const uint8_t *nonce, size_t nonce_length,
264 const uint8_t *additional_data, size_t additional_data_length,
265 const uint8_t *ciphertext, size_t ciphertext_length,
266 uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length )
267{
268 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Paul Elliott07a30c42021-04-20 14:13:23 +0100269 psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
Ronald Cron46f91782021-03-17 08:16:34 +0100270 const uint8_t *tag = NULL;
271 (void) key_buffer_size;
272
273 status = psa_aead_setup( &operation, attributes, key_buffer, alg );
274 if( status != PSA_SUCCESS )
275 goto exit;
276
277 status = psa_aead_unpadded_locate_tag( operation.tag_length,
278 ciphertext, ciphertext_length,
279 plaintext_size, &tag );
280 if( status != PSA_SUCCESS )
281 goto exit;
282
Ronald Cron46f91782021-03-17 08:16:34 +0100283#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
Paul Elliott07a30c42021-04-20 14:13:23 +0100284 if( operation.alg == PSA_ALG_CCM )
Ronald Cron46f91782021-03-17 08:16:34 +0100285 {
286 status = mbedtls_to_psa_error(
287 mbedtls_ccm_auth_decrypt( &operation.ctx.ccm,
288 ciphertext_length - operation.tag_length,
289 nonce, nonce_length,
290 additional_data,
291 additional_data_length,
292 ciphertext, plaintext,
293 tag, operation.tag_length ) );
294 }
295 else
296#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
Ronald Cron810eb162021-04-06 09:01:39 +0200297#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
Paul Elliott07a30c42021-04-20 14:13:23 +0100298 if( operation.alg == PSA_ALG_GCM )
Ronald Cron810eb162021-04-06 09:01:39 +0200299 {
300 status = mbedtls_to_psa_error(
301 mbedtls_gcm_auth_decrypt( &operation.ctx.gcm,
302 ciphertext_length - operation.tag_length,
303 nonce, nonce_length,
304 additional_data,
305 additional_data_length,
306 tag, operation.tag_length,
307 ciphertext, plaintext ) );
308 }
309 else
310#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
Ronald Cron46f91782021-03-17 08:16:34 +0100311#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
Paul Elliott07a30c42021-04-20 14:13:23 +0100312 if( operation.alg == PSA_ALG_CHACHA20_POLY1305 )
Ronald Cron46f91782021-03-17 08:16:34 +0100313 {
314 if( nonce_length != 12 || operation.tag_length != 16 )
315 {
316 status = PSA_ERROR_NOT_SUPPORTED;
317 goto exit;
318 }
319 status = mbedtls_to_psa_error(
320 mbedtls_chachapoly_auth_decrypt( &operation.ctx.chachapoly,
321 ciphertext_length - operation.tag_length,
322 nonce,
323 additional_data,
324 additional_data_length,
325 tag,
326 ciphertext,
327 plaintext ) );
328 }
329 else
330#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
331 {
332 return( PSA_ERROR_NOT_SUPPORTED );
333 }
334
335 if( status == PSA_SUCCESS )
336 *plaintext_length = ciphertext_length - operation.tag_length;
337
338exit:
339 psa_aead_abort_internal( &operation );
340
341 if( status == PSA_SUCCESS )
342 *plaintext_length = ciphertext_length - operation.tag_length;
343 return( status );
344}
Ronald Cron7ceee8d2021-03-17 16:55:43 +0100345
346#endif /* MBEDTLS_PSA_CRYPTO_C */
347