Branch data Line data Source code
1 : : /*
2 : : * PSA cipher driver 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_cipher.h"
14 : : #include "psa_crypto_core.h"
15 : : #include "psa_crypto_random_impl.h"
16 : : #include "constant_time_internal.h"
17 : :
18 : : #include "mbedtls/cipher.h"
19 : : #include "mbedtls/error.h"
20 : :
21 : : #include <string.h>
22 : :
23 : : /* mbedtls_cipher_values_from_psa() below only checks if the proper build symbols
24 : : * are enabled, but it does not provide any compatibility check between them
25 : : * (i.e. if the specified key works with the specified algorithm). This helper
26 : : * function is meant to provide this support.
27 : : * mbedtls_cipher_info_from_psa() might be used for the same purpose, but it
28 : : * requires CIPHER_C to be enabled.
29 : : */
30 : 34 : static psa_status_t mbedtls_cipher_validate_values(
31 : : psa_algorithm_t alg,
32 : : psa_key_type_t key_type)
33 : : {
34 : : /* Reduce code size - hinting to the compiler about what it can assume allows the compiler to
35 : : eliminate bits of the logic below. */
36 : : #if !defined(PSA_WANT_KEY_TYPE_AES)
37 : : MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_AES);
38 : : #endif
39 : : #if !defined(PSA_WANT_KEY_TYPE_ARIA)
40 [ - + ]: 34 : MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_ARIA);
41 : : #endif
42 : : #if !defined(PSA_WANT_KEY_TYPE_CAMELLIA)
43 [ - + ]: 34 : MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_CAMELLIA);
44 : : #endif
45 : : #if !defined(PSA_WANT_KEY_TYPE_CHACHA20)
46 [ - + ]: 34 : MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_CHACHA20);
47 : : #endif
48 : : #if !defined(PSA_WANT_KEY_TYPE_DES)
49 [ - + ]: 34 : MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_DES);
50 : : #endif
51 : : #if !defined(PSA_WANT_ALG_CCM)
52 : : MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0));
53 : : #endif
54 : : #if !defined(PSA_WANT_ALG_GCM)
55 [ - + ]: 34 : MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0));
56 : : #endif
57 : : #if !defined(PSA_WANT_ALG_STREAM_CIPHER)
58 [ - + ]: 34 : MBEDTLS_ASSUME(alg != PSA_ALG_STREAM_CIPHER);
59 : : #endif
60 : : #if !defined(PSA_WANT_ALG_CHACHA20_POLY1305)
61 [ - + ]: 34 : MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0));
62 : : #endif
63 : : #if !defined(PSA_WANT_ALG_CCM_STAR_NO_TAG)
64 : : MBEDTLS_ASSUME(alg != PSA_ALG_CCM_STAR_NO_TAG);
65 : : #endif
66 : : #if !defined(PSA_WANT_ALG_CTR)
67 [ - + ]: 34 : MBEDTLS_ASSUME(alg != PSA_ALG_CTR);
68 : : #endif
69 : : #if !defined(PSA_WANT_ALG_CFB)
70 [ - + ]: 34 : MBEDTLS_ASSUME(alg != PSA_ALG_CFB);
71 : : #endif
72 : : #if !defined(PSA_WANT_ALG_OFB)
73 [ - + ]: 34 : MBEDTLS_ASSUME(alg != PSA_ALG_OFB);
74 : : #endif
75 : : #if !defined(PSA_WANT_ALG_ECB_NO_PADDING)
76 : : MBEDTLS_ASSUME(alg != PSA_ALG_ECB_NO_PADDING);
77 : : #endif
78 : : #if !defined(PSA_WANT_ALG_CBC_NO_PADDING)
79 [ - + ]: 34 : MBEDTLS_ASSUME(alg != PSA_ALG_CBC_NO_PADDING);
80 : : #endif
81 : : #if !defined(PSA_WANT_ALG_CBC_PKCS7)
82 [ - + ]: 34 : MBEDTLS_ASSUME(alg != PSA_ALG_CBC_PKCS7);
83 : : #endif
84 : : #if !defined(PSA_WANT_ALG_CMAC)
85 [ - + ]: 34 : MBEDTLS_ASSUME(alg != PSA_ALG_CMAC);
86 : : #endif
87 : :
88 : 34 : if (alg == PSA_ALG_STREAM_CIPHER ||
89 : : alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0)) {
90 : : if (key_type == PSA_KEY_TYPE_CHACHA20) {
91 : : return PSA_SUCCESS;
92 : : }
93 : : }
94 : :
95 [ - + ]: 34 : if (alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0) ||
96 [ # # ]: 0 : alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0) ||
97 : : alg == PSA_ALG_CCM_STAR_NO_TAG) {
98 [ - + ]: 34 : if (key_type == PSA_KEY_TYPE_AES ||
99 : : key_type == PSA_KEY_TYPE_ARIA ||
100 : : key_type == PSA_KEY_TYPE_CAMELLIA) {
101 : : return PSA_SUCCESS;
102 : : }
103 : : }
104 : :
105 : 0 : if (alg == PSA_ALG_CTR ||
106 : : alg == PSA_ALG_CFB ||
107 [ # # ]: 0 : alg == PSA_ALG_OFB ||
108 : : alg == PSA_ALG_XTS ||
109 [ # # ]: 0 : alg == PSA_ALG_ECB_NO_PADDING ||
110 : : alg == PSA_ALG_CBC_NO_PADDING ||
111 : : alg == PSA_ALG_CBC_PKCS7 ||
112 : : alg == PSA_ALG_CMAC) {
113 [ # # ]: 0 : if (key_type == PSA_KEY_TYPE_AES ||
114 : : key_type == PSA_KEY_TYPE_ARIA ||
115 : : key_type == PSA_KEY_TYPE_DES ||
116 : : key_type == PSA_KEY_TYPE_CAMELLIA) {
117 : 0 : return PSA_SUCCESS;
118 : : }
119 : : }
120 : :
121 : : return PSA_ERROR_NOT_SUPPORTED;
122 : : }
123 : :
124 : 34 : psa_status_t mbedtls_cipher_values_from_psa(
125 : : psa_algorithm_t alg,
126 : : psa_key_type_t key_type,
127 : : size_t *key_bits,
128 : : mbedtls_cipher_mode_t *mode,
129 : : mbedtls_cipher_id_t *cipher_id)
130 : : {
131 : 34 : mbedtls_cipher_id_t cipher_id_tmp;
132 : : /* Only DES modifies key_bits */
133 : : #if !defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
134 : 34 : (void) key_bits;
135 : : #endif
136 : :
137 [ + - ]: 34 : if (PSA_ALG_IS_AEAD(alg)) {
138 : 34 : alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0);
139 : : }
140 : :
141 [ + - ]: 34 : if (PSA_ALG_IS_CIPHER(alg) || PSA_ALG_IS_AEAD(alg)) {
142 [ - - + - ]: 34 : switch (alg) {
143 : : #if defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER)
144 : : case PSA_ALG_STREAM_CIPHER:
145 : : *mode = MBEDTLS_MODE_STREAM;
146 : : break;
147 : : #endif
148 : : #if defined(MBEDTLS_PSA_BUILTIN_ALG_CTR)
149 : : case PSA_ALG_CTR:
150 : : *mode = MBEDTLS_MODE_CTR;
151 : : break;
152 : : #endif
153 : : #if defined(MBEDTLS_PSA_BUILTIN_ALG_CFB)
154 : : case PSA_ALG_CFB:
155 : : *mode = MBEDTLS_MODE_CFB;
156 : : break;
157 : : #endif
158 : : #if defined(MBEDTLS_PSA_BUILTIN_ALG_OFB)
159 : : case PSA_ALG_OFB:
160 : : *mode = MBEDTLS_MODE_OFB;
161 : : break;
162 : : #endif
163 : : #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
164 : 0 : case PSA_ALG_ECB_NO_PADDING:
165 : 0 : *mode = MBEDTLS_MODE_ECB;
166 : 0 : break;
167 : : #endif
168 : : #if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING)
169 : : case PSA_ALG_CBC_NO_PADDING:
170 : : *mode = MBEDTLS_MODE_CBC;
171 : : break;
172 : : #endif
173 : : #if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
174 : : case PSA_ALG_CBC_PKCS7:
175 : : *mode = MBEDTLS_MODE_CBC;
176 : : break;
177 : : #endif
178 : : #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG)
179 : 0 : case PSA_ALG_CCM_STAR_NO_TAG:
180 : 0 : *mode = MBEDTLS_MODE_CCM_STAR_NO_TAG;
181 : 0 : break;
182 : : #endif
183 : : #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
184 : 34 : case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0):
185 : 34 : *mode = MBEDTLS_MODE_CCM;
186 : 34 : break;
187 : : #endif
188 : : #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
189 : : case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0):
190 : : *mode = MBEDTLS_MODE_GCM;
191 : : break;
192 : : #endif
193 : : #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
194 : : case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0):
195 : : *mode = MBEDTLS_MODE_CHACHAPOLY;
196 : : break;
197 : : #endif
198 : : default:
199 : : return PSA_ERROR_NOT_SUPPORTED;
200 : : }
201 [ # # ]: 0 : } else if (alg == PSA_ALG_CMAC) {
202 : 0 : *mode = MBEDTLS_MODE_ECB;
203 : : } else {
204 : : return PSA_ERROR_NOT_SUPPORTED;
205 : : }
206 : :
207 [ - + ]: 34 : switch (key_type) {
208 : : #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES)
209 : 34 : case PSA_KEY_TYPE_AES:
210 : 34 : cipher_id_tmp = MBEDTLS_CIPHER_ID_AES;
211 : 34 : break;
212 : : #endif
213 : : #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA)
214 : : case PSA_KEY_TYPE_ARIA:
215 : : cipher_id_tmp = MBEDTLS_CIPHER_ID_ARIA;
216 : : break;
217 : : #endif
218 : : #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
219 : : case PSA_KEY_TYPE_DES:
220 : : /* key_bits is 64 for Single-DES, 128 for two-key Triple-DES,
221 : : * and 192 for three-key Triple-DES. */
222 : : if (*key_bits == 64) {
223 : : cipher_id_tmp = MBEDTLS_CIPHER_ID_DES;
224 : : } else {
225 : : cipher_id_tmp = MBEDTLS_CIPHER_ID_3DES;
226 : : }
227 : : /* mbedtls doesn't recognize two-key Triple-DES as an algorithm,
228 : : * but two-key Triple-DES is functionally three-key Triple-DES
229 : : * with K1=K3, so that's how we present it to mbedtls. */
230 : : if (*key_bits == 128) {
231 : : *key_bits = 192;
232 : : }
233 : : break;
234 : : #endif
235 : : #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA)
236 : : case PSA_KEY_TYPE_CAMELLIA:
237 : : cipher_id_tmp = MBEDTLS_CIPHER_ID_CAMELLIA;
238 : : break;
239 : : #endif
240 : : #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20)
241 : : case PSA_KEY_TYPE_CHACHA20:
242 : : cipher_id_tmp = MBEDTLS_CIPHER_ID_CHACHA20;
243 : : break;
244 : : #endif
245 : : default:
246 : : return PSA_ERROR_NOT_SUPPORTED;
247 : : }
248 [ + - ]: 34 : if (cipher_id != NULL) {
249 : 34 : *cipher_id = cipher_id_tmp;
250 : : }
251 : :
252 : 34 : return mbedtls_cipher_validate_values(alg, key_type);
253 : : }
254 : :
255 : : #if defined(MBEDTLS_CIPHER_C)
256 : 0 : const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa(
257 : : psa_algorithm_t alg,
258 : : psa_key_type_t key_type,
259 : : size_t key_bits,
260 : : mbedtls_cipher_id_t *cipher_id)
261 : : {
262 : 0 : mbedtls_cipher_mode_t mode;
263 : 0 : psa_status_t status;
264 : 0 : mbedtls_cipher_id_t cipher_id_tmp = MBEDTLS_CIPHER_ID_NONE;
265 : :
266 : 0 : status = mbedtls_cipher_values_from_psa(alg, key_type, &key_bits, &mode, &cipher_id_tmp);
267 [ # # ]: 0 : if (status != PSA_SUCCESS) {
268 : : return NULL;
269 : : }
270 [ # # ]: 0 : if (cipher_id != NULL) {
271 : 0 : *cipher_id = cipher_id_tmp;
272 : : }
273 : :
274 : 0 : return mbedtls_cipher_info_from_values(cipher_id_tmp, (int) key_bits, mode);
275 : : }
276 : : #endif /* MBEDTLS_CIPHER_C */
277 : :
278 : : #if defined(MBEDTLS_PSA_BUILTIN_CIPHER)
279 : :
280 : 0 : static psa_status_t psa_cipher_setup(
281 : : mbedtls_psa_cipher_operation_t *operation,
282 : : const psa_key_attributes_t *attributes,
283 : : const uint8_t *key_buffer, size_t key_buffer_size,
284 : : psa_algorithm_t alg,
285 : : mbedtls_operation_t cipher_operation)
286 : : {
287 : 0 : int ret = 0;
288 : 0 : size_t key_bits;
289 : 0 : const mbedtls_cipher_info_t *cipher_info = NULL;
290 : 0 : psa_key_type_t key_type = attributes->type;
291 : :
292 : 0 : (void) key_buffer_size;
293 : :
294 : 0 : mbedtls_cipher_init(&operation->ctx.cipher);
295 : :
296 : 0 : operation->alg = alg;
297 : 0 : key_bits = attributes->bits;
298 : 0 : cipher_info = mbedtls_cipher_info_from_psa(alg, key_type,
299 : : key_bits, NULL);
300 [ # # ]: 0 : if (cipher_info == NULL) {
301 : : return PSA_ERROR_NOT_SUPPORTED;
302 : : }
303 : :
304 : 0 : ret = mbedtls_cipher_setup(&operation->ctx.cipher, cipher_info);
305 [ # # ]: 0 : if (ret != 0) {
306 : 0 : goto exit;
307 : : }
308 : :
309 : : #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
310 : : if (key_type == PSA_KEY_TYPE_DES && key_bits == 128) {
311 : : /* Two-key Triple-DES is 3-key Triple-DES with K1=K3 */
312 : : uint8_t keys[24];
313 : : memcpy(keys, key_buffer, 16);
314 : : memcpy(keys + 16, key_buffer, 8);
315 : : ret = mbedtls_cipher_setkey(&operation->ctx.cipher,
316 : : keys,
317 : : 192, cipher_operation);
318 : : } else
319 : : #endif
320 : : {
321 : 0 : ret = mbedtls_cipher_setkey(&operation->ctx.cipher, key_buffer,
322 : : (int) key_bits, cipher_operation);
323 : : }
324 [ # # ]: 0 : if (ret != 0) {
325 : 0 : goto exit;
326 : : }
327 : :
328 : : #if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \
329 : : defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
330 : : switch (alg) {
331 : : case PSA_ALG_CBC_NO_PADDING:
332 : : ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher,
333 : : MBEDTLS_PADDING_NONE);
334 : : break;
335 : : case PSA_ALG_CBC_PKCS7:
336 : : ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher,
337 : : MBEDTLS_PADDING_PKCS7);
338 : : break;
339 : : default:
340 : : /* The algorithm doesn't involve padding. */
341 : : ret = 0;
342 : : break;
343 : : }
344 : : if (ret != 0) {
345 : : goto exit;
346 : : }
347 : : #endif /* MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING ||
348 : : MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 */
349 : :
350 [ # # # # ]: 0 : operation->block_length = (PSA_ALG_IS_STREAM_CIPHER(alg) ? 1 :
351 : 0 : PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type));
352 [ # # # # : 0 : operation->iv_length = PSA_CIPHER_IV_LENGTH(key_type, alg);
# # # # #
# # # #
# ]
353 : :
354 : 0 : exit:
355 : 0 : return mbedtls_to_psa_error(ret);
356 : : }
357 : :
358 : 0 : psa_status_t mbedtls_psa_cipher_encrypt_setup(
359 : : mbedtls_psa_cipher_operation_t *operation,
360 : : const psa_key_attributes_t *attributes,
361 : : const uint8_t *key_buffer, size_t key_buffer_size,
362 : : psa_algorithm_t alg)
363 : : {
364 : 0 : return psa_cipher_setup(operation, attributes,
365 : : key_buffer, key_buffer_size,
366 : : alg, MBEDTLS_ENCRYPT);
367 : : }
368 : :
369 : 0 : psa_status_t mbedtls_psa_cipher_decrypt_setup(
370 : : mbedtls_psa_cipher_operation_t *operation,
371 : : const psa_key_attributes_t *attributes,
372 : : const uint8_t *key_buffer, size_t key_buffer_size,
373 : : psa_algorithm_t alg)
374 : : {
375 : 0 : return psa_cipher_setup(operation, attributes,
376 : : key_buffer, key_buffer_size,
377 : : alg, MBEDTLS_DECRYPT);
378 : : }
379 : :
380 : 0 : psa_status_t mbedtls_psa_cipher_set_iv(
381 : : mbedtls_psa_cipher_operation_t *operation,
382 : : const uint8_t *iv, size_t iv_length)
383 : : {
384 [ # # ]: 0 : if (iv_length != operation->iv_length) {
385 : : return PSA_ERROR_INVALID_ARGUMENT;
386 : : }
387 : :
388 : 0 : return mbedtls_to_psa_error(
389 : : mbedtls_cipher_set_iv(&operation->ctx.cipher,
390 : : iv, iv_length));
391 : : }
392 : :
393 : : #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
394 : : /** Process input for which the algorithm is set to ECB mode.
395 : : *
396 : : * This requires manual processing, since the PSA API is defined as being
397 : : * able to process arbitrary-length calls to psa_cipher_update() with ECB mode,
398 : : * but the underlying mbedtls_cipher_update only takes full blocks.
399 : : *
400 : : * \param ctx The mbedtls cipher context to use. It must have been
401 : : * set up for ECB.
402 : : * \param[in] input The input plaintext or ciphertext to process.
403 : : * \param input_length The number of bytes to process from \p input.
404 : : * This does not need to be aligned to a block boundary.
405 : : * If there is a partial block at the end of the input,
406 : : * it is stored in \p ctx for future processing.
407 : : * \param output The buffer where the output is written. It must be
408 : : * at least `BS * floor((p + input_length) / BS)` bytes
409 : : * long, where `p` is the number of bytes in the
410 : : * unprocessed partial block in \p ctx (with
411 : : * `0 <= p <= BS - 1`) and `BS` is the block size.
412 : : * \param output_length On success, the number of bytes written to \p output.
413 : : * \c 0 on error.
414 : : *
415 : : * \return #PSA_SUCCESS or an error from a hardware accelerator
416 : : */
417 : 0 : static psa_status_t psa_cipher_update_ecb(
418 : : mbedtls_cipher_context_t *ctx,
419 : : const uint8_t *input,
420 : : size_t input_length,
421 : : uint8_t *output,
422 : : size_t *output_length)
423 : : {
424 : 0 : psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
425 : 0 : size_t block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info);
426 : 0 : size_t internal_output_length = 0;
427 : 0 : *output_length = 0;
428 : :
429 [ # # ]: 0 : if (input_length == 0) {
430 : 0 : status = PSA_SUCCESS;
431 : 0 : goto exit;
432 : : }
433 : :
434 [ # # ]: 0 : if (ctx->unprocessed_len > 0) {
435 : : /* Fill up to block size, and run the block if there's a full one. */
436 : 0 : size_t bytes_to_copy = block_size - ctx->unprocessed_len;
437 : :
438 : 0 : if (input_length < bytes_to_copy) {
439 : : bytes_to_copy = input_length;
440 : : }
441 : :
442 [ # # ]: 0 : memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]),
443 : : input, bytes_to_copy);
444 : 0 : input_length -= bytes_to_copy;
445 : 0 : input += bytes_to_copy;
446 : 0 : ctx->unprocessed_len += bytes_to_copy;
447 : :
448 [ # # ]: 0 : if (ctx->unprocessed_len == block_size) {
449 : 0 : status = mbedtls_to_psa_error(
450 : : mbedtls_cipher_update(ctx,
451 : 0 : ctx->unprocessed_data,
452 : : block_size,
453 : : output, &internal_output_length));
454 : :
455 [ # # ]: 0 : if (status != PSA_SUCCESS) {
456 : 0 : goto exit;
457 : : }
458 : :
459 : 0 : output += internal_output_length;
460 : 0 : *output_length += internal_output_length;
461 : 0 : ctx->unprocessed_len = 0;
462 : : }
463 : : }
464 : :
465 [ # # ]: 0 : while (input_length >= block_size) {
466 : : /* Run all full blocks we have, one by one */
467 : 0 : status = mbedtls_to_psa_error(
468 : : mbedtls_cipher_update(ctx, input,
469 : : block_size,
470 : : output, &internal_output_length));
471 : :
472 [ # # ]: 0 : if (status != PSA_SUCCESS) {
473 : 0 : goto exit;
474 : : }
475 : :
476 : 0 : input_length -= block_size;
477 : 0 : input += block_size;
478 : :
479 : 0 : output += internal_output_length;
480 : 0 : *output_length += internal_output_length;
481 : : }
482 : :
483 [ # # ]: 0 : if (input_length > 0) {
484 : : /* Save unprocessed bytes for later processing */
485 : 0 : memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]),
486 : : input, input_length);
487 : 0 : ctx->unprocessed_len += input_length;
488 : : }
489 : :
490 : : status = PSA_SUCCESS;
491 : :
492 : 0 : exit:
493 : 0 : return status;
494 : : }
495 : : #endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */
496 : :
497 : 0 : psa_status_t mbedtls_psa_cipher_update(
498 : : mbedtls_psa_cipher_operation_t *operation,
499 : : const uint8_t *input, size_t input_length,
500 : : uint8_t *output, size_t output_size, size_t *output_length)
501 : : {
502 : 0 : psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
503 : 0 : size_t expected_output_size;
504 : :
505 [ # # ]: 0 : if (!PSA_ALG_IS_STREAM_CIPHER(operation->alg)) {
506 : : /* Take the unprocessed partial block left over from previous
507 : : * update calls, if any, plus the input to this call. Remove
508 : : * the last partial block, if any. You get the data that will be
509 : : * output in this call. */
510 : 0 : expected_output_size =
511 : 0 : (operation->ctx.cipher.unprocessed_len + input_length)
512 : 0 : / operation->block_length * operation->block_length;
513 : : } else {
514 : : expected_output_size = input_length;
515 : : }
516 : :
517 [ # # ]: 0 : if (output_size < expected_output_size) {
518 : : return PSA_ERROR_BUFFER_TOO_SMALL;
519 : : }
520 : :
521 : : #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
522 [ # # ]: 0 : if (operation->alg == PSA_ALG_ECB_NO_PADDING) {
523 : : /* mbedtls_cipher_update has an API inconsistency: it will only
524 : : * process a single block at a time in ECB mode. Abstract away that
525 : : * inconsistency here to match the PSA API behaviour. */
526 : 0 : status = psa_cipher_update_ecb(&operation->ctx.cipher,
527 : : input,
528 : : input_length,
529 : : output,
530 : : output_length);
531 : : } else
532 : : #endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */
533 [ # # ]: 0 : if (input_length == 0) {
534 : : /* There is no input, nothing to be done */
535 : 0 : *output_length = 0;
536 : 0 : status = PSA_SUCCESS;
537 : : } else {
538 : 0 : status = mbedtls_to_psa_error(
539 : : mbedtls_cipher_update(&operation->ctx.cipher, input,
540 : : input_length, output, output_length));
541 : :
542 [ # # ]: 0 : if (*output_length > output_size) {
543 : 0 : return PSA_ERROR_CORRUPTION_DETECTED;
544 : : }
545 : : }
546 : :
547 : : return status;
548 : : }
549 : :
550 : 0 : psa_status_t mbedtls_psa_cipher_finish(
551 : : mbedtls_psa_cipher_operation_t *operation,
552 : : uint8_t *output, size_t output_size, size_t *output_length)
553 : : {
554 : 0 : psa_status_t status = PSA_ERROR_GENERIC_ERROR;
555 : 0 : size_t invalid_padding = 0;
556 : :
557 : : /* We will copy output_size bytes from temp_output_buffer to the
558 : : * output buffer. We can't use *output_length to determine how
559 : : * much to copy because we must not leak that value through timing
560 : : * when doing decryption with unpadding. But the underlying function
561 : : * is not guaranteed to write beyond *output_length. To ensure we don't
562 : : * leak the former content of the stack to the caller, wipe that
563 : : * former content. */
564 : 0 : uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH] = { 0 };
565 : 0 : if (output_size > sizeof(temp_output_buffer)) {
566 : : output_size = sizeof(temp_output_buffer);
567 : : }
568 : :
569 [ # # ]: 0 : if (operation->ctx.cipher.unprocessed_len != 0) {
570 [ # # ]: 0 : if (operation->alg == PSA_ALG_ECB_NO_PADDING ||
571 : : operation->alg == PSA_ALG_CBC_NO_PADDING) {
572 : 0 : status = PSA_ERROR_INVALID_ARGUMENT;
573 : 0 : goto exit;
574 : : }
575 : : }
576 : :
577 : 0 : status = mbedtls_to_psa_error(
578 : : mbedtls_cipher_finish_padded(&operation->ctx.cipher,
579 : : temp_output_buffer,
580 : : output_length,
581 : : &invalid_padding));
582 [ # # ]: 0 : if (status != PSA_SUCCESS) {
583 : 0 : goto exit;
584 : : }
585 : :
586 [ # # ]: 0 : if (output_size == 0) {
587 : : ; /* Nothing to copy. Note that output may be NULL in this case. */
588 : : } else {
589 : : /* Do not use the value of *output_length to determine how much
590 : : * to copy. When decrypting a padded cipher, the output length is
591 : : * sensitive, and leaking it could allow a padding oracle attack. */
592 : 0 : memcpy(output, temp_output_buffer, output_size);
593 : : }
594 : :
595 : 0 : status = mbedtls_ct_error_if_else_0(invalid_padding,
596 : : PSA_ERROR_INVALID_PADDING);
597 : 0 : mbedtls_ct_condition_t buffer_too_small =
598 : 0 : mbedtls_ct_uint_lt(output_size, *output_length);
599 : 0 : status = mbedtls_ct_error_if(buffer_too_small,
600 : : PSA_ERROR_BUFFER_TOO_SMALL,
601 : : status);
602 : :
603 : 0 : exit:
604 : 0 : mbedtls_platform_zeroize(temp_output_buffer,
605 : : sizeof(temp_output_buffer));
606 : 0 : return status;
607 : : }
608 : :
609 : 0 : psa_status_t mbedtls_psa_cipher_abort(
610 : : mbedtls_psa_cipher_operation_t *operation)
611 : : {
612 : : /* Sanity check (shouldn't happen: operation->alg should
613 : : * always have been initialized to a valid value). */
614 [ # # ]: 0 : if (!PSA_ALG_IS_CIPHER(operation->alg)) {
615 : : return PSA_ERROR_BAD_STATE;
616 : : }
617 : :
618 : 0 : mbedtls_cipher_free(&operation->ctx.cipher);
619 : :
620 : 0 : return PSA_SUCCESS;
621 : : }
622 : :
623 : 0 : psa_status_t mbedtls_psa_cipher_encrypt(
624 : : const psa_key_attributes_t *attributes,
625 : : const uint8_t *key_buffer,
626 : : size_t key_buffer_size,
627 : : psa_algorithm_t alg,
628 : : const uint8_t *iv,
629 : : size_t iv_length,
630 : : const uint8_t *input,
631 : : size_t input_length,
632 : : uint8_t *output,
633 : : size_t output_size,
634 : : size_t *output_length)
635 : : {
636 : 0 : psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
637 : 0 : mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT;
638 : 0 : size_t update_output_length, finish_output_length;
639 : :
640 : 0 : status = mbedtls_psa_cipher_encrypt_setup(&operation, attributes,
641 : : key_buffer, key_buffer_size,
642 : : alg);
643 [ # # ]: 0 : if (status != PSA_SUCCESS) {
644 : 0 : goto exit;
645 : : }
646 : :
647 [ # # ]: 0 : if (iv_length > 0) {
648 : 0 : status = mbedtls_psa_cipher_set_iv(&operation, iv, iv_length);
649 [ # # ]: 0 : if (status != PSA_SUCCESS) {
650 : 0 : goto exit;
651 : : }
652 : : }
653 : :
654 : 0 : status = mbedtls_psa_cipher_update(&operation, input, input_length,
655 : : output, output_size,
656 : : &update_output_length);
657 [ # # ]: 0 : if (status != PSA_SUCCESS) {
658 : 0 : goto exit;
659 : : }
660 : :
661 : 0 : status = mbedtls_psa_cipher_finish(
662 : : &operation,
663 : 0 : mbedtls_buffer_offset(output, update_output_length),
664 : : output_size - update_output_length, &finish_output_length);
665 [ # # ]: 0 : if (status != PSA_SUCCESS) {
666 : 0 : goto exit;
667 : : }
668 : :
669 : 0 : *output_length = update_output_length + finish_output_length;
670 : :
671 : 0 : exit:
672 : 0 : if (status == PSA_SUCCESS) {
673 : 0 : status = mbedtls_psa_cipher_abort(&operation);
674 : : } else {
675 : 0 : mbedtls_psa_cipher_abort(&operation);
676 : : }
677 : :
678 : 0 : return status;
679 : : }
680 : :
681 : 0 : psa_status_t mbedtls_psa_cipher_decrypt(
682 : : const psa_key_attributes_t *attributes,
683 : : const uint8_t *key_buffer,
684 : : size_t key_buffer_size,
685 : : psa_algorithm_t alg,
686 : : const uint8_t *input,
687 : : size_t input_length,
688 : : uint8_t *output,
689 : : size_t output_size,
690 : : size_t *output_length)
691 : : {
692 : 0 : psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
693 : 0 : mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT;
694 : 0 : size_t olength, accumulated_length;
695 : :
696 : 0 : status = mbedtls_psa_cipher_decrypt_setup(&operation, attributes,
697 : : key_buffer, key_buffer_size,
698 : : alg);
699 [ # # ]: 0 : if (status != PSA_SUCCESS) {
700 : 0 : goto exit;
701 : : }
702 : :
703 [ # # ]: 0 : if (operation.iv_length > 0) {
704 : 0 : status = mbedtls_psa_cipher_set_iv(&operation,
705 : : input, operation.iv_length);
706 [ # # ]: 0 : if (status != PSA_SUCCESS) {
707 : 0 : goto exit;
708 : : }
709 : : }
710 : :
711 : 0 : status = mbedtls_psa_cipher_update(
712 : : &operation,
713 : 0 : mbedtls_buffer_offset_const(input, operation.iv_length),
714 : 0 : input_length - operation.iv_length,
715 : : output, output_size, &olength);
716 [ # # ]: 0 : if (status != PSA_SUCCESS) {
717 : 0 : goto exit;
718 : : }
719 : :
720 : 0 : accumulated_length = olength;
721 : :
722 : 0 : status = mbedtls_psa_cipher_finish(
723 : : &operation,
724 : 0 : mbedtls_buffer_offset(output, accumulated_length),
725 : : output_size - accumulated_length, &olength);
726 : :
727 : 0 : *output_length = accumulated_length + olength;
728 : :
729 : 0 : exit:
730 : 0 : /* C99 doesn't allow a declaration to follow a label */;
731 : 0 : psa_status_t abort_status = mbedtls_psa_cipher_abort(&operation);
732 : : /* Normally abort shouldn't fail unless the operation is in a bad
733 : : * state, in which case we'd expect finish to fail with the same error.
734 : : * So it doesn't matter much which call's error code we pick when both
735 : : * fail. However, in unauthenticated decryption specifically, the
736 : : * distinction between PSA_SUCCESS and PSA_ERROR_INVALID_PADDING is
737 : : * security-sensitive (risk of a padding oracle attack), so here we
738 : : * must not have a code path that depends on the value of status. */
739 [ # # ]: 0 : if (abort_status != PSA_SUCCESS) {
740 : 0 : status = abort_status;
741 : : }
742 : :
743 : 0 : return status;
744 : : }
745 : : #endif /* MBEDTLS_PSA_BUILTIN_CIPHER */
746 : :
747 : : #endif /* MBEDTLS_PSA_CRYPTO_C */
|