blob: a2b29423c2fbdb66cb9be105e2dfcefac2252fca [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(
35 psa_cipher_operation_t *operation,
36 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;
Ronald Cron937dfee2021-03-10 09:17:32 +010045 mbedtls_psa_cipher_operation_t *mbedtls_ctx = &operation->ctx.mbedtls_ctx;
Ronald Crond6d28882020-12-14 14:56:02 +010046
47 (void)key_buffer_size;
48
49 /* Proceed with initializing an mbed TLS cipher context if no driver is
50 * available for the given algorithm & key. */
Ronald Cron937dfee2021-03-10 09:17:32 +010051 mbedtls_cipher_init( &mbedtls_ctx->cipher );
Ronald Crond6d28882020-12-14 14:56:02 +010052
Ronald Cron937dfee2021-03-10 09:17:32 +010053 mbedtls_ctx->alg = alg;
Ronald Crond6d28882020-12-14 14:56:02 +010054 key_bits = attributes->core.bits;
55 cipher_info = mbedtls_cipher_info_from_psa( alg, key_type,
56 key_bits, NULL );
57 if( cipher_info == NULL )
58 return( PSA_ERROR_NOT_SUPPORTED );
59
Ronald Cron937dfee2021-03-10 09:17:32 +010060 ret = mbedtls_cipher_setup( &mbedtls_ctx->cipher, cipher_info );
Ronald Crond6d28882020-12-14 14:56:02 +010061 if( ret != 0 )
62 goto exit;
63
64#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
65 if( key_type == PSA_KEY_TYPE_DES && key_bits == 128 )
66 {
67 /* Two-key Triple-DES is 3-key Triple-DES with K1=K3 */
68 uint8_t keys[24];
69 memcpy( keys, key_buffer, 16 );
70 memcpy( keys + 16, key_buffer, 8 );
Ronald Cron937dfee2021-03-10 09:17:32 +010071 ret = mbedtls_cipher_setkey( &mbedtls_ctx->cipher,
Ronald Crond6d28882020-12-14 14:56:02 +010072 keys,
73 192, cipher_operation );
74 }
75 else
76#endif
77 {
Ronald Cron937dfee2021-03-10 09:17:32 +010078 ret = mbedtls_cipher_setkey( &mbedtls_ctx->cipher, key_buffer,
Ronald Crond6d28882020-12-14 14:56:02 +010079 (int) key_bits, cipher_operation );
80 }
81 if( ret != 0 )
82 goto exit;
83
84#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \
85 defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
86 switch( alg )
87 {
88 case PSA_ALG_CBC_NO_PADDING:
Ronald Cron937dfee2021-03-10 09:17:32 +010089 ret = mbedtls_cipher_set_padding_mode( &mbedtls_ctx->cipher,
Ronald Crond6d28882020-12-14 14:56:02 +010090 MBEDTLS_PADDING_NONE );
91 break;
92 case PSA_ALG_CBC_PKCS7:
Ronald Cron937dfee2021-03-10 09:17:32 +010093 ret = mbedtls_cipher_set_padding_mode( &mbedtls_ctx->cipher,
Ronald Crond6d28882020-12-14 14:56:02 +010094 MBEDTLS_PADDING_PKCS7 );
95 break;
96 default:
97 /* The algorithm doesn't involve padding. */
98 ret = 0;
99 break;
100 }
101 if( ret != 0 )
102 goto exit;
103#endif /* MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING || MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 */
104
Ronald Cron937dfee2021-03-10 09:17:32 +0100105 mbedtls_ctx->block_size = ( PSA_ALG_IS_STREAM_CIPHER( alg ) ? 1 :
Ronald Crond6d28882020-12-14 14:56:02 +0100106 PSA_BLOCK_CIPHER_BLOCK_LENGTH( key_type ) );
107 if( ( alg & PSA_ALG_CIPHER_FROM_BLOCK_FLAG ) != 0 &&
108 alg != PSA_ALG_ECB_NO_PADDING )
109 {
Ronald Cron937dfee2021-03-10 09:17:32 +0100110 mbedtls_ctx->iv_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH( key_type );
Ronald Crond6d28882020-12-14 14:56:02 +0100111 }
112#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20)
113 else
114 if( ( alg == PSA_ALG_STREAM_CIPHER ) &&
115 ( key_type == PSA_KEY_TYPE_CHACHA20 ) )
Ronald Cron937dfee2021-03-10 09:17:32 +0100116 mbedtls_ctx->iv_size = 12;
Ronald Crond6d28882020-12-14 14:56:02 +0100117#endif
118
119exit:
120 return( mbedtls_to_psa_error( ret ) );
121}
122
123psa_status_t mbedtls_psa_cipher_encrypt_setup(
124 psa_cipher_operation_t *operation,
125 const psa_key_attributes_t *attributes,
126 const uint8_t *key_buffer, size_t key_buffer_size,
127 psa_algorithm_t alg )
128{
129 return( cipher_setup( operation, attributes,
130 key_buffer, key_buffer_size,
131 alg, MBEDTLS_ENCRYPT ) );
132}
133
134psa_status_t mbedtls_psa_cipher_decrypt_setup(
135 psa_cipher_operation_t *operation,
136 const psa_key_attributes_t *attributes,
137 const uint8_t *key_buffer, size_t key_buffer_size,
138 psa_algorithm_t alg )
139{
140 return( cipher_setup( operation, attributes,
141 key_buffer, key_buffer_size,
142 alg, MBEDTLS_DECRYPT ) );
143}
Ronald Cron6d051732020-10-01 14:10:20 +0200144
145psa_status_t mbedtls_psa_cipher_generate_iv(
146 psa_cipher_operation_t *operation,
147 uint8_t *iv, size_t iv_size, size_t *iv_length )
148{
149 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Ronald Cron937dfee2021-03-10 09:17:32 +0100150 mbedtls_psa_cipher_operation_t *mbedtls_ctx = &operation->ctx.mbedtls_ctx;
Ronald Cron6d051732020-10-01 14:10:20 +0200151
Ronald Cron937dfee2021-03-10 09:17:32 +0100152 if( iv_size < mbedtls_ctx->iv_size )
Ronald Cron6d051732020-10-01 14:10:20 +0200153 return( PSA_ERROR_BUFFER_TOO_SMALL );
154
155 ret = mbedtls_psa_get_random( MBEDTLS_PSA_RANDOM_STATE,
Ronald Cron937dfee2021-03-10 09:17:32 +0100156 iv, mbedtls_ctx->iv_size );
Ronald Cron6d051732020-10-01 14:10:20 +0200157 if( ret != 0 )
158 return( mbedtls_to_psa_error( ret ) );
159
Ronald Cron937dfee2021-03-10 09:17:32 +0100160 *iv_length = mbedtls_ctx->iv_size;
Ronald Cron6d051732020-10-01 14:10:20 +0200161
162 return( mbedtls_psa_cipher_set_iv( operation, iv, *iv_length ) );
163}
164
165psa_status_t mbedtls_psa_cipher_set_iv( psa_cipher_operation_t *operation,
166 const uint8_t *iv,
167 size_t iv_length )
168{
Ronald Cron937dfee2021-03-10 09:17:32 +0100169 mbedtls_psa_cipher_operation_t *mbedtls_ctx = &operation->ctx.mbedtls_ctx;
170
171 if( iv_length != mbedtls_ctx->iv_size )
Ronald Cron6d051732020-10-01 14:10:20 +0200172 return( PSA_ERROR_INVALID_ARGUMENT );
173
174 return( mbedtls_to_psa_error(
Ronald Cron937dfee2021-03-10 09:17:32 +0100175 mbedtls_cipher_set_iv( &mbedtls_ctx->cipher,
Ronald Cron6d051732020-10-01 14:10:20 +0200176 iv, iv_length ) ) );
177}
178
179/* Process input for which the algorithm is set to ECB mode. This requires
180 * manual processing, since the PSA API is defined as being able to process
181 * arbitrary-length calls to psa_cipher_update() with ECB mode, but the
182 * underlying mbedtls_cipher_update only takes full blocks. */
183static psa_status_t psa_cipher_update_ecb(
184 mbedtls_cipher_context_t *ctx,
185 const uint8_t *input,
186 size_t input_length,
187 uint8_t *output,
188 size_t output_size,
189 size_t *output_length )
190{
191 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
192 size_t block_size = ctx->cipher_info->block_size;
193 size_t internal_output_length = 0;
194 *output_length = 0;
195
196 if( input_length == 0 )
197 {
198 status = PSA_SUCCESS;
199 goto exit;
200 }
201
202 if( ctx->unprocessed_len > 0 )
203 {
204 /* Fill up to block size, and run the block if there's a full one. */
205 size_t bytes_to_copy = block_size - ctx->unprocessed_len;
206
207 if( input_length < bytes_to_copy )
208 bytes_to_copy = input_length;
209
210 memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ),
211 input, bytes_to_copy );
212 input_length -= bytes_to_copy;
213 input += bytes_to_copy;
214 ctx->unprocessed_len += bytes_to_copy;
215
216 if( ctx->unprocessed_len == block_size )
217 {
218 status = mbedtls_to_psa_error(
219 mbedtls_cipher_update( ctx,
220 ctx->unprocessed_data,
221 block_size,
222 output, &internal_output_length ) );
223
224 if( status != PSA_SUCCESS )
225 goto exit;
226
227 output += internal_output_length;
228 output_size -= internal_output_length;
229 *output_length += internal_output_length;
230 ctx->unprocessed_len = 0;
231 }
232 }
233
234 while( input_length >= block_size )
235 {
236 /* Run all full blocks we have, one by one */
237 status = mbedtls_to_psa_error(
238 mbedtls_cipher_update( ctx, input,
239 block_size,
240 output, &internal_output_length ) );
241
242 if( status != PSA_SUCCESS )
243 goto exit;
244
245 input_length -= block_size;
246 input += block_size;
247
248 output += internal_output_length;
249 output_size -= internal_output_length;
250 *output_length += internal_output_length;
251 }
252
253 if( input_length > 0 )
254 {
255 /* Save unprocessed bytes for later processing */
256 memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ),
257 input, input_length );
258 ctx->unprocessed_len += input_length;
259 }
260
261 status = PSA_SUCCESS;
262
263exit:
264 return( status );
265}
266
267psa_status_t mbedtls_psa_cipher_update( psa_cipher_operation_t *operation,
268 const uint8_t *input,
269 size_t input_length,
270 uint8_t *output,
271 size_t output_size,
272 size_t *output_length )
273{
274 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Ronald Cron937dfee2021-03-10 09:17:32 +0100275 mbedtls_psa_cipher_operation_t *mbedtls_ctx = &operation->ctx.mbedtls_ctx;
Ronald Cron6d051732020-10-01 14:10:20 +0200276 size_t expected_output_size;
277
Ronald Cron937dfee2021-03-10 09:17:32 +0100278 if( ! PSA_ALG_IS_STREAM_CIPHER( mbedtls_ctx->alg ) )
Ronald Cron6d051732020-10-01 14:10:20 +0200279 {
280 /* Take the unprocessed partial block left over from previous
281 * update calls, if any, plus the input to this call. Remove
282 * the last partial block, if any. You get the data that will be
283 * output in this call. */
284 expected_output_size =
Ronald Cron937dfee2021-03-10 09:17:32 +0100285 ( mbedtls_ctx->cipher.unprocessed_len + input_length )
286 / mbedtls_ctx->block_size * mbedtls_ctx->block_size;
Ronald Cron6d051732020-10-01 14:10:20 +0200287 }
288 else
289 {
290 expected_output_size = input_length;
291 }
292
293 if( output_size < expected_output_size )
294 return( PSA_ERROR_BUFFER_TOO_SMALL );
295
Ronald Cron937dfee2021-03-10 09:17:32 +0100296 if( mbedtls_ctx->alg == PSA_ALG_ECB_NO_PADDING )
Ronald Cron6d051732020-10-01 14:10:20 +0200297 {
298 /* mbedtls_cipher_update has an API inconsistency: it will only
299 * process a single block at a time in ECB mode. Abstract away that
300 * inconsistency here to match the PSA API behaviour. */
Ronald Cron937dfee2021-03-10 09:17:32 +0100301 status = psa_cipher_update_ecb( &mbedtls_ctx->cipher,
Ronald Cron6d051732020-10-01 14:10:20 +0200302 input,
303 input_length,
304 output,
305 output_size,
306 output_length );
307 }
308 else
309 {
310 status = mbedtls_to_psa_error(
Ronald Cron937dfee2021-03-10 09:17:32 +0100311 mbedtls_cipher_update( &mbedtls_ctx->cipher, input,
Ronald Cron6d051732020-10-01 14:10:20 +0200312 input_length, output, output_length ) );
313 }
314
315 return( status );
316}
317
318psa_status_t mbedtls_psa_cipher_finish( psa_cipher_operation_t *operation,
319 uint8_t *output,
320 size_t output_size,
321 size_t *output_length )
322{
323 psa_status_t status = PSA_ERROR_GENERIC_ERROR;
Ronald Cron937dfee2021-03-10 09:17:32 +0100324 mbedtls_psa_cipher_operation_t *mbedtls_ctx = &operation->ctx.mbedtls_ctx;
Ronald Cron6d051732020-10-01 14:10:20 +0200325 uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH];
326
Ronald Cron937dfee2021-03-10 09:17:32 +0100327 if( mbedtls_ctx->cipher.unprocessed_len != 0 )
Ronald Cron6d051732020-10-01 14:10:20 +0200328 {
Ronald Cron937dfee2021-03-10 09:17:32 +0100329 if( mbedtls_ctx->alg == PSA_ALG_ECB_NO_PADDING ||
330 mbedtls_ctx->alg == PSA_ALG_CBC_NO_PADDING )
Ronald Cron6d051732020-10-01 14:10:20 +0200331 {
332 status = PSA_ERROR_INVALID_ARGUMENT;
333 goto exit;
334 }
335 }
336
337 status = mbedtls_to_psa_error(
Ronald Cron937dfee2021-03-10 09:17:32 +0100338 mbedtls_cipher_finish( &mbedtls_ctx->cipher,
Ronald Cron6d051732020-10-01 14:10:20 +0200339 temp_output_buffer,
340 output_length ) );
341 if( status != PSA_SUCCESS )
342 goto exit;
343
344 if( *output_length == 0 )
345 ; /* Nothing to copy. Note that output may be NULL in this case. */
346 else if( output_size >= *output_length )
347 memcpy( output, temp_output_buffer, *output_length );
348 else
349 status = PSA_ERROR_BUFFER_TOO_SMALL;
350
351exit:
352 mbedtls_platform_zeroize( temp_output_buffer,
353 sizeof( temp_output_buffer ) );
354
355 return( status );
356}
357
358psa_status_t mbedtls_psa_cipher_abort( psa_cipher_operation_t *operation )
359{
Ronald Cron937dfee2021-03-10 09:17:32 +0100360 mbedtls_psa_cipher_operation_t *mbedtls_ctx = &operation->ctx.mbedtls_ctx;
361
362 /* Sanity check (shouldn't happen: operation->alg should
363 * always have been initialized to a valid value). */
364 if( ! PSA_ALG_IS_CIPHER( mbedtls_ctx->alg ) )
365 return( PSA_ERROR_BAD_STATE );
366
367 mbedtls_cipher_free( &mbedtls_ctx->cipher );
Ronald Cron6d051732020-10-01 14:10:20 +0200368
369 return( PSA_SUCCESS );
370}
371
Ronald Cron0ff57952021-03-08 16:46:35 +0100372#endif /* MBEDTLS_PSA_CRYPTO_C */