blob: 147ce815d536703161f66e6473cc9bc20879a6c9 [file] [log] [blame]
Ronald Cron0ff57952021-03-08 16:46:35 +01001/*
2 * PSA cipher driver 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_cipher.h>
Ronald Crond6d28882020-12-14 14:56:02 +010026#include "psa_crypto_core.h"
Ronald Cron6d051732020-10-01 14:10:20 +020027#include "psa_crypto_random_impl.h"
28
Ronald Crond6d28882020-12-14 14:56:02 +010029#include "mbedtls/cipher.h"
Ronald Cron6d051732020-10-01 14:10:20 +020030#include "mbedtls/error.h"
Ronald Cron0ff57952021-03-08 16:46:35 +010031
Ronald Crond6d28882020-12-14 14:56:02 +010032#include <string.h>
33
34static psa_status_t cipher_setup(
Ronald Cron6e412a72021-03-10 09:58:47 +010035 mbedtls_psa_cipher_operation_t *operation,
Ronald Crond6d28882020-12-14 14:56:02 +010036 const psa_key_attributes_t *attributes,
37 const uint8_t *key_buffer, size_t key_buffer_size,
38 psa_algorithm_t alg,
39 mbedtls_operation_t cipher_operation )
40{
41 int ret = 0;
42 size_t key_bits;
43 const mbedtls_cipher_info_t *cipher_info = NULL;
44 psa_key_type_t key_type = attributes->core.type;
45
46 (void)key_buffer_size;
47
48 /* Proceed with initializing an mbed TLS cipher context if no driver is
49 * available for the given algorithm & key. */
Ronald Cron6e412a72021-03-10 09:58:47 +010050 mbedtls_cipher_init( &operation->cipher );
Ronald Crond6d28882020-12-14 14:56:02 +010051
Ronald Cron6e412a72021-03-10 09:58:47 +010052 operation->alg = alg;
Ronald Crond6d28882020-12-14 14:56:02 +010053 key_bits = attributes->core.bits;
54 cipher_info = mbedtls_cipher_info_from_psa( alg, key_type,
55 key_bits, NULL );
56 if( cipher_info == NULL )
57 return( PSA_ERROR_NOT_SUPPORTED );
58
Ronald Cron6e412a72021-03-10 09:58:47 +010059 ret = mbedtls_cipher_setup( &operation->cipher, cipher_info );
Ronald Crond6d28882020-12-14 14:56:02 +010060 if( ret != 0 )
61 goto exit;
62
63#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
64 if( key_type == PSA_KEY_TYPE_DES && key_bits == 128 )
65 {
66 /* Two-key Triple-DES is 3-key Triple-DES with K1=K3 */
67 uint8_t keys[24];
68 memcpy( keys, key_buffer, 16 );
69 memcpy( keys + 16, key_buffer, 8 );
Ronald Cron6e412a72021-03-10 09:58:47 +010070 ret = mbedtls_cipher_setkey( &operation->cipher,
Ronald Crond6d28882020-12-14 14:56:02 +010071 keys,
72 192, cipher_operation );
73 }
74 else
75#endif
76 {
Ronald Cron6e412a72021-03-10 09:58:47 +010077 ret = mbedtls_cipher_setkey( &operation->cipher, key_buffer,
Ronald Crond6d28882020-12-14 14:56:02 +010078 (int) key_bits, cipher_operation );
79 }
80 if( ret != 0 )
81 goto exit;
82
83#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \
84 defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
85 switch( alg )
86 {
87 case PSA_ALG_CBC_NO_PADDING:
Ronald Cron6e412a72021-03-10 09:58:47 +010088 ret = mbedtls_cipher_set_padding_mode( &operation->cipher,
Ronald Crond6d28882020-12-14 14:56:02 +010089 MBEDTLS_PADDING_NONE );
90 break;
91 case PSA_ALG_CBC_PKCS7:
Ronald Cron6e412a72021-03-10 09:58:47 +010092 ret = mbedtls_cipher_set_padding_mode( &operation->cipher,
Ronald Crond6d28882020-12-14 14:56:02 +010093 MBEDTLS_PADDING_PKCS7 );
94 break;
95 default:
96 /* The algorithm doesn't involve padding. */
97 ret = 0;
98 break;
99 }
100 if( ret != 0 )
101 goto exit;
102#endif /* MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING || MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 */
103
Ronald Cron6e412a72021-03-10 09:58:47 +0100104 operation->block_size = ( PSA_ALG_IS_STREAM_CIPHER( alg ) ? 1 :
Ronald Crond6d28882020-12-14 14:56:02 +0100105 PSA_BLOCK_CIPHER_BLOCK_LENGTH( key_type ) );
106 if( ( alg & PSA_ALG_CIPHER_FROM_BLOCK_FLAG ) != 0 &&
107 alg != PSA_ALG_ECB_NO_PADDING )
108 {
Ronald Cron6e412a72021-03-10 09:58:47 +0100109 operation->iv_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH( key_type );
Ronald Crond6d28882020-12-14 14:56:02 +0100110 }
111#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20)
112 else
113 if( ( alg == PSA_ALG_STREAM_CIPHER ) &&
114 ( key_type == PSA_KEY_TYPE_CHACHA20 ) )
Ronald Cron6e412a72021-03-10 09:58:47 +0100115 operation->iv_size = 12;
Ronald Crond6d28882020-12-14 14:56:02 +0100116#endif
117
118exit:
119 return( mbedtls_to_psa_error( ret ) );
120}
121
Ronald Cron8287e6b2021-03-12 10:35:18 +0100122static psa_status_t cipher_encrypt_setup(
Ronald Cron6e412a72021-03-10 09:58:47 +0100123 mbedtls_psa_cipher_operation_t *operation,
Ronald Crond6d28882020-12-14 14:56:02 +0100124 const psa_key_attributes_t *attributes,
125 const uint8_t *key_buffer, size_t key_buffer_size,
126 psa_algorithm_t alg )
127{
128 return( cipher_setup( operation, attributes,
129 key_buffer, key_buffer_size,
130 alg, MBEDTLS_ENCRYPT ) );
131}
132
Ronald Cron8287e6b2021-03-12 10:35:18 +0100133static psa_status_t cipher_decrypt_setup(
Ronald Cron6e412a72021-03-10 09:58:47 +0100134 mbedtls_psa_cipher_operation_t *operation,
Ronald Crond6d28882020-12-14 14:56:02 +0100135 const psa_key_attributes_t *attributes,
136 const uint8_t *key_buffer, size_t key_buffer_size,
137 psa_algorithm_t alg )
138{
139 return( cipher_setup( operation, attributes,
140 key_buffer, key_buffer_size,
141 alg, MBEDTLS_DECRYPT ) );
142}
Ronald Cron6d051732020-10-01 14:10:20 +0200143
Ronald Cron8287e6b2021-03-12 10:35:18 +0100144static psa_status_t cipher_set_iv( mbedtls_psa_cipher_operation_t *operation,
145 const uint8_t *iv, size_t iv_length )
146{
147 if( iv_length != operation->iv_size )
148 return( PSA_ERROR_INVALID_ARGUMENT );
149
150 return( mbedtls_to_psa_error(
151 mbedtls_cipher_set_iv( &operation->cipher,
152 iv, iv_length ) ) );
153}
154
155static psa_status_t cipher_generate_iv(
Ronald Cron6e412a72021-03-10 09:58:47 +0100156 mbedtls_psa_cipher_operation_t *operation,
Ronald Cron6d051732020-10-01 14:10:20 +0200157 uint8_t *iv, size_t iv_size, size_t *iv_length )
158{
159 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
160
Ronald Cron6e412a72021-03-10 09:58:47 +0100161 if( iv_size < operation->iv_size )
Ronald Cron6d051732020-10-01 14:10:20 +0200162 return( PSA_ERROR_BUFFER_TOO_SMALL );
163
164 ret = mbedtls_psa_get_random( MBEDTLS_PSA_RANDOM_STATE,
Ronald Cron6e412a72021-03-10 09:58:47 +0100165 iv, operation->iv_size );
Ronald Cron6d051732020-10-01 14:10:20 +0200166 if( ret != 0 )
167 return( mbedtls_to_psa_error( ret ) );
168
Ronald Cron6e412a72021-03-10 09:58:47 +0100169 *iv_length = operation->iv_size;
Ronald Cron6d051732020-10-01 14:10:20 +0200170
Ronald Cron8287e6b2021-03-12 10:35:18 +0100171 return( cipher_set_iv( operation, iv, *iv_length ) );
Ronald Cron6d051732020-10-01 14:10:20 +0200172}
173
174/* Process input for which the algorithm is set to ECB mode. This requires
175 * manual processing, since the PSA API is defined as being able to process
176 * arbitrary-length calls to psa_cipher_update() with ECB mode, but the
177 * underlying mbedtls_cipher_update only takes full blocks. */
178static psa_status_t psa_cipher_update_ecb(
179 mbedtls_cipher_context_t *ctx,
180 const uint8_t *input,
181 size_t input_length,
182 uint8_t *output,
183 size_t output_size,
184 size_t *output_length )
185{
186 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
187 size_t block_size = ctx->cipher_info->block_size;
188 size_t internal_output_length = 0;
189 *output_length = 0;
190
191 if( input_length == 0 )
192 {
193 status = PSA_SUCCESS;
194 goto exit;
195 }
196
197 if( ctx->unprocessed_len > 0 )
198 {
199 /* Fill up to block size, and run the block if there's a full one. */
200 size_t bytes_to_copy = block_size - ctx->unprocessed_len;
201
202 if( input_length < bytes_to_copy )
203 bytes_to_copy = input_length;
204
205 memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ),
206 input, bytes_to_copy );
207 input_length -= bytes_to_copy;
208 input += bytes_to_copy;
209 ctx->unprocessed_len += bytes_to_copy;
210
211 if( ctx->unprocessed_len == block_size )
212 {
213 status = mbedtls_to_psa_error(
214 mbedtls_cipher_update( ctx,
215 ctx->unprocessed_data,
216 block_size,
217 output, &internal_output_length ) );
218
219 if( status != PSA_SUCCESS )
220 goto exit;
221
222 output += internal_output_length;
223 output_size -= internal_output_length;
224 *output_length += internal_output_length;
225 ctx->unprocessed_len = 0;
226 }
227 }
228
229 while( input_length >= block_size )
230 {
231 /* Run all full blocks we have, one by one */
232 status = mbedtls_to_psa_error(
233 mbedtls_cipher_update( ctx, input,
234 block_size,
235 output, &internal_output_length ) );
236
237 if( status != PSA_SUCCESS )
238 goto exit;
239
240 input_length -= block_size;
241 input += block_size;
242
243 output += internal_output_length;
244 output_size -= internal_output_length;
245 *output_length += internal_output_length;
246 }
247
248 if( input_length > 0 )
249 {
250 /* Save unprocessed bytes for later processing */
251 memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ),
252 input, input_length );
253 ctx->unprocessed_len += input_length;
254 }
255
256 status = PSA_SUCCESS;
257
258exit:
259 return( status );
260}
261
Ronald Cron8287e6b2021-03-12 10:35:18 +0100262static psa_status_t cipher_update( mbedtls_psa_cipher_operation_t *operation,
263 const uint8_t *input,
264 size_t input_length,
265 uint8_t *output,
266 size_t output_size,
267 size_t *output_length )
Ronald Cron6d051732020-10-01 14:10:20 +0200268{
269 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
270 size_t expected_output_size;
271
Ronald Cron6e412a72021-03-10 09:58:47 +0100272 if( ! PSA_ALG_IS_STREAM_CIPHER( operation->alg ) )
Ronald Cron6d051732020-10-01 14:10:20 +0200273 {
274 /* Take the unprocessed partial block left over from previous
275 * update calls, if any, plus the input to this call. Remove
276 * the last partial block, if any. You get the data that will be
277 * output in this call. */
278 expected_output_size =
Ronald Cron6e412a72021-03-10 09:58:47 +0100279 ( operation->cipher.unprocessed_len + input_length )
280 / operation->block_size * operation->block_size;
Ronald Cron6d051732020-10-01 14:10:20 +0200281 }
282 else
283 {
284 expected_output_size = input_length;
285 }
286
287 if( output_size < expected_output_size )
288 return( PSA_ERROR_BUFFER_TOO_SMALL );
289
Ronald Cron6e412a72021-03-10 09:58:47 +0100290 if( operation->alg == PSA_ALG_ECB_NO_PADDING )
Ronald Cron6d051732020-10-01 14:10:20 +0200291 {
292 /* mbedtls_cipher_update has an API inconsistency: it will only
293 * process a single block at a time in ECB mode. Abstract away that
294 * inconsistency here to match the PSA API behaviour. */
Ronald Cron6e412a72021-03-10 09:58:47 +0100295 status = psa_cipher_update_ecb( &operation->cipher,
Ronald Cron6d051732020-10-01 14:10:20 +0200296 input,
297 input_length,
298 output,
299 output_size,
300 output_length );
301 }
302 else
303 {
304 status = mbedtls_to_psa_error(
Ronald Cron6e412a72021-03-10 09:58:47 +0100305 mbedtls_cipher_update( &operation->cipher, input,
Ronald Cron6d051732020-10-01 14:10:20 +0200306 input_length, output, output_length ) );
307 }
308
309 return( status );
310}
311
Ronald Cron8287e6b2021-03-12 10:35:18 +0100312static psa_status_t cipher_finish( mbedtls_psa_cipher_operation_t *operation,
313 uint8_t *output,
314 size_t output_size,
315 size_t *output_length )
Ronald Cron6d051732020-10-01 14:10:20 +0200316{
317 psa_status_t status = PSA_ERROR_GENERIC_ERROR;
318 uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH];
319
Ronald Cron6e412a72021-03-10 09:58:47 +0100320 if( operation->cipher.unprocessed_len != 0 )
Ronald Cron6d051732020-10-01 14:10:20 +0200321 {
Ronald Cron6e412a72021-03-10 09:58:47 +0100322 if( operation->alg == PSA_ALG_ECB_NO_PADDING ||
323 operation->alg == PSA_ALG_CBC_NO_PADDING )
Ronald Cron6d051732020-10-01 14:10:20 +0200324 {
325 status = PSA_ERROR_INVALID_ARGUMENT;
326 goto exit;
327 }
328 }
329
330 status = mbedtls_to_psa_error(
Ronald Cron6e412a72021-03-10 09:58:47 +0100331 mbedtls_cipher_finish( &operation->cipher,
Ronald Cron6d051732020-10-01 14:10:20 +0200332 temp_output_buffer,
333 output_length ) );
334 if( status != PSA_SUCCESS )
335 goto exit;
336
337 if( *output_length == 0 )
338 ; /* Nothing to copy. Note that output may be NULL in this case. */
339 else if( output_size >= *output_length )
340 memcpy( output, temp_output_buffer, *output_length );
341 else
342 status = PSA_ERROR_BUFFER_TOO_SMALL;
343
344exit:
345 mbedtls_platform_zeroize( temp_output_buffer,
346 sizeof( temp_output_buffer ) );
347
348 return( status );
349}
350
Ronald Cron8287e6b2021-03-12 10:35:18 +0100351static psa_status_t cipher_abort( mbedtls_psa_cipher_operation_t *operation )
Ronald Cron6d051732020-10-01 14:10:20 +0200352{
Ronald Cron937dfee2021-03-10 09:17:32 +0100353 /* Sanity check (shouldn't happen: operation->alg should
354 * always have been initialized to a valid value). */
Ronald Cron6e412a72021-03-10 09:58:47 +0100355 if( ! PSA_ALG_IS_CIPHER( operation->alg ) )
Ronald Cron937dfee2021-03-10 09:17:32 +0100356 return( PSA_ERROR_BAD_STATE );
357
Ronald Cron6e412a72021-03-10 09:58:47 +0100358 mbedtls_cipher_free( &operation->cipher );
Ronald Cron6d051732020-10-01 14:10:20 +0200359
360 return( PSA_SUCCESS );
361}
362
Ronald Cron8287e6b2021-03-12 10:35:18 +0100363psa_status_t mbedtls_psa_cipher_encrypt_setup(
364 mbedtls_psa_cipher_operation_t *operation,
365 const psa_key_attributes_t *attributes,
366 const uint8_t *key_buffer, size_t key_buffer_size,
367 psa_algorithm_t alg )
368{
369 return( cipher_encrypt_setup(
370 operation, attributes, key_buffer, key_buffer_size, alg ) );
371}
372
373psa_status_t mbedtls_psa_cipher_decrypt_setup(
374 mbedtls_psa_cipher_operation_t *operation,
375 const psa_key_attributes_t *attributes,
376 const uint8_t *key_buffer, size_t key_buffer_size,
377 psa_algorithm_t alg )
378{
379 return( cipher_decrypt_setup(
380 operation, attributes, key_buffer, key_buffer_size, alg ) );
381}
382
383psa_status_t mbedtls_psa_cipher_generate_iv(
384 mbedtls_psa_cipher_operation_t *operation,
385 uint8_t *iv, size_t iv_size, size_t *iv_length )
386{
387 return( cipher_generate_iv( operation, iv, iv_size, iv_length ) );
388}
389
390psa_status_t mbedtls_psa_cipher_set_iv( mbedtls_psa_cipher_operation_t *operation,
391 const uint8_t *iv,
392 size_t iv_length )
393{
394 return( cipher_set_iv( operation, iv, iv_length ) );
395}
396
397psa_status_t mbedtls_psa_cipher_update( mbedtls_psa_cipher_operation_t *operation,
398 const uint8_t *input,
399 size_t input_length,
400 uint8_t *output,
401 size_t output_size,
402 size_t *output_length )
403{
404 return( cipher_update( operation, input, input_length,
405 output, output_size, output_length ) );
406}
407
408psa_status_t mbedtls_psa_cipher_finish( mbedtls_psa_cipher_operation_t *operation,
409 uint8_t *output,
410 size_t output_size,
411 size_t *output_length )
412{
413 return( cipher_finish( operation, output, output_size, output_length ) );
414}
415
416psa_status_t mbedtls_psa_cipher_abort( mbedtls_psa_cipher_operation_t *operation )
417{
418 return( cipher_abort( operation ) );
419}
420
Ronald Cron0ff57952021-03-08 16:46:35 +0100421#endif /* MBEDTLS_PSA_CRYPTO_C */