blob: 340f674cfd656bc49dcd9838f7ae785bea9ca55c [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;
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. */
50 mbedtls_cipher_init( &operation->ctx.cipher );
51
Ronald Crond6d28882020-12-14 14:56:02 +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
59 ret = mbedtls_cipher_setup( &operation->ctx.cipher, cipher_info );
60 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 );
70 ret = mbedtls_cipher_setkey( &operation->ctx.cipher,
71 keys,
72 192, cipher_operation );
73 }
74 else
75#endif
76 {
77 ret = mbedtls_cipher_setkey( &operation->ctx.cipher, key_buffer,
78 (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:
88 ret = mbedtls_cipher_set_padding_mode( &operation->ctx.cipher,
89 MBEDTLS_PADDING_NONE );
90 break;
91 case PSA_ALG_CBC_PKCS7:
92 ret = mbedtls_cipher_set_padding_mode( &operation->ctx.cipher,
93 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
104 operation->block_size = ( PSA_ALG_IS_STREAM_CIPHER( alg ) ? 1 :
105 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 {
109 operation->iv_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH( key_type );
110 }
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 ) )
115 operation->iv_size = 12;
116#endif
117
118exit:
119 return( mbedtls_to_psa_error( ret ) );
120}
121
122psa_status_t mbedtls_psa_cipher_encrypt_setup(
123 psa_cipher_operation_t *operation,
124 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
133psa_status_t mbedtls_psa_cipher_decrypt_setup(
134 psa_cipher_operation_t *operation,
135 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
144psa_status_t mbedtls_psa_cipher_generate_iv(
145 psa_cipher_operation_t *operation,
146 uint8_t *iv, size_t iv_size, size_t *iv_length )
147{
148 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
149
150 if( iv_size < operation->iv_size )
151 return( PSA_ERROR_BUFFER_TOO_SMALL );
152
153 ret = mbedtls_psa_get_random( MBEDTLS_PSA_RANDOM_STATE,
154 iv, operation->iv_size );
155 if( ret != 0 )
156 return( mbedtls_to_psa_error( ret ) );
157
158 *iv_length = operation->iv_size;
159
160 return( mbedtls_psa_cipher_set_iv( operation, iv, *iv_length ) );
161}
162
163psa_status_t mbedtls_psa_cipher_set_iv( psa_cipher_operation_t *operation,
164 const uint8_t *iv,
165 size_t iv_length )
166{
167 if( iv_length != operation->iv_size )
168 return( PSA_ERROR_INVALID_ARGUMENT );
169
170 return( mbedtls_to_psa_error(
171 mbedtls_cipher_set_iv( &operation->ctx.cipher,
172 iv, iv_length ) ) );
173}
174
175/* Process input for which the algorithm is set to ECB mode. This requires
176 * manual processing, since the PSA API is defined as being able to process
177 * arbitrary-length calls to psa_cipher_update() with ECB mode, but the
178 * underlying mbedtls_cipher_update only takes full blocks. */
179static psa_status_t psa_cipher_update_ecb(
180 mbedtls_cipher_context_t *ctx,
181 const uint8_t *input,
182 size_t input_length,
183 uint8_t *output,
184 size_t output_size,
185 size_t *output_length )
186{
187 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
188 size_t block_size = ctx->cipher_info->block_size;
189 size_t internal_output_length = 0;
190 *output_length = 0;
191
192 if( input_length == 0 )
193 {
194 status = PSA_SUCCESS;
195 goto exit;
196 }
197
198 if( ctx->unprocessed_len > 0 )
199 {
200 /* Fill up to block size, and run the block if there's a full one. */
201 size_t bytes_to_copy = block_size - ctx->unprocessed_len;
202
203 if( input_length < bytes_to_copy )
204 bytes_to_copy = input_length;
205
206 memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ),
207 input, bytes_to_copy );
208 input_length -= bytes_to_copy;
209 input += bytes_to_copy;
210 ctx->unprocessed_len += bytes_to_copy;
211
212 if( ctx->unprocessed_len == block_size )
213 {
214 status = mbedtls_to_psa_error(
215 mbedtls_cipher_update( ctx,
216 ctx->unprocessed_data,
217 block_size,
218 output, &internal_output_length ) );
219
220 if( status != PSA_SUCCESS )
221 goto exit;
222
223 output += internal_output_length;
224 output_size -= internal_output_length;
225 *output_length += internal_output_length;
226 ctx->unprocessed_len = 0;
227 }
228 }
229
230 while( input_length >= block_size )
231 {
232 /* Run all full blocks we have, one by one */
233 status = mbedtls_to_psa_error(
234 mbedtls_cipher_update( ctx, input,
235 block_size,
236 output, &internal_output_length ) );
237
238 if( status != PSA_SUCCESS )
239 goto exit;
240
241 input_length -= block_size;
242 input += block_size;
243
244 output += internal_output_length;
245 output_size -= internal_output_length;
246 *output_length += internal_output_length;
247 }
248
249 if( input_length > 0 )
250 {
251 /* Save unprocessed bytes for later processing */
252 memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ),
253 input, input_length );
254 ctx->unprocessed_len += input_length;
255 }
256
257 status = PSA_SUCCESS;
258
259exit:
260 return( status );
261}
262
263psa_status_t mbedtls_psa_cipher_update( psa_cipher_operation_t *operation,
264 const uint8_t *input,
265 size_t input_length,
266 uint8_t *output,
267 size_t output_size,
268 size_t *output_length )
269{
270 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
271 size_t expected_output_size;
272
273 if( ! PSA_ALG_IS_STREAM_CIPHER( operation->alg ) )
274 {
275 /* Take the unprocessed partial block left over from previous
276 * update calls, if any, plus the input to this call. Remove
277 * the last partial block, if any. You get the data that will be
278 * output in this call. */
279 expected_output_size =
280 ( operation->ctx.cipher.unprocessed_len + input_length )
281 / operation->block_size * operation->block_size;
282 }
283 else
284 {
285 expected_output_size = input_length;
286 }
287
288 if( output_size < expected_output_size )
289 return( PSA_ERROR_BUFFER_TOO_SMALL );
290
291 if( operation->alg == PSA_ALG_ECB_NO_PADDING )
292 {
293 /* mbedtls_cipher_update has an API inconsistency: it will only
294 * process a single block at a time in ECB mode. Abstract away that
295 * inconsistency here to match the PSA API behaviour. */
296 status = psa_cipher_update_ecb( &operation->ctx.cipher,
297 input,
298 input_length,
299 output,
300 output_size,
301 output_length );
302 }
303 else
304 {
305 status = mbedtls_to_psa_error(
306 mbedtls_cipher_update( &operation->ctx.cipher, input,
307 input_length, output, output_length ) );
308 }
309
310 return( status );
311}
312
313psa_status_t mbedtls_psa_cipher_finish( psa_cipher_operation_t *operation,
314 uint8_t *output,
315 size_t output_size,
316 size_t *output_length )
317{
318 psa_status_t status = PSA_ERROR_GENERIC_ERROR;
319 uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH];
320
321 if( operation->ctx.cipher.unprocessed_len != 0 )
322 {
323 if( operation->alg == PSA_ALG_ECB_NO_PADDING ||
324 operation->alg == PSA_ALG_CBC_NO_PADDING )
325 {
326 status = PSA_ERROR_INVALID_ARGUMENT;
327 goto exit;
328 }
329 }
330
331 status = mbedtls_to_psa_error(
332 mbedtls_cipher_finish( &operation->ctx.cipher,
333 temp_output_buffer,
334 output_length ) );
335 if( status != PSA_SUCCESS )
336 goto exit;
337
338 if( *output_length == 0 )
339 ; /* Nothing to copy. Note that output may be NULL in this case. */
340 else if( output_size >= *output_length )
341 memcpy( output, temp_output_buffer, *output_length );
342 else
343 status = PSA_ERROR_BUFFER_TOO_SMALL;
344
345exit:
346 mbedtls_platform_zeroize( temp_output_buffer,
347 sizeof( temp_output_buffer ) );
348
349 return( status );
350}
351
352psa_status_t mbedtls_psa_cipher_abort( psa_cipher_operation_t *operation )
353{
354 mbedtls_cipher_free( &operation->ctx.cipher );
355
356 return( PSA_SUCCESS );
357}
358
Ronald Cron0ff57952021-03-08 16:46:35 +0100359#endif /* MBEDTLS_PSA_CRYPTO_C */