blob: 86ceecce1eecb9b5af8a930fe8d469f098d3bda0 [file] [log] [blame]
Bence Szépkúti700ee442020-05-26 00:33:31 +02001/*
Bence Szépkúti1e148272020-08-07 13:07:28 +02002 * Copyright The Mbed TLS Contributors
Bence Szépkúti86974652020-06-15 11:59:37 +02003 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 * not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
Bence Szépkúti700ee442020-05-26 00:33:31 +020016 */
17
itayzafrir10366702018-07-11 13:44:41 +030018#include "psa/crypto.h"
19#include <string.h>
itayzafrir10366702018-07-11 13:44:41 +030020#include <stdio.h>
Jaeden Amerodb29ab52019-02-12 16:40:27 +000021#include <stdlib.h>
itayzafrir10366702018-07-11 13:44:41 +030022
23#define ASSERT( predicate ) \
24 do \
25 { \
26 if( ! ( predicate ) ) \
27 { \
Jaeden Amerofa30c332018-12-21 18:42:18 +000028 printf( "\tassertion failed at %s:%d - '%s'\r\n", \
29 __FILE__, __LINE__, #predicate); \
itayzafrir10366702018-07-11 13:44:41 +030030 goto exit; \
31 } \
32 } while ( 0 )
33
34#define ASSERT_STATUS( actual, expected ) \
35 do \
36 { \
37 if( ( actual ) != ( expected ) ) \
38 { \
Jaeden Amerofa30c332018-12-21 18:42:18 +000039 printf( "\tassertion failed at %s:%d - " \
40 "actual:%d expected:%d\r\n", __FILE__, __LINE__, \
itayzafrir10366702018-07-11 13:44:41 +030041 (psa_status_t) actual, (psa_status_t) expected ); \
42 goto exit; \
43 } \
44 } while ( 0 )
45
itayzafrir18ac3312018-07-17 09:28:11 +030046#if !defined(MBEDTLS_PSA_CRYPTO_C) || !defined(MBEDTLS_AES_C) || \
47 !defined(MBEDTLS_CIPHER_MODE_CBC) || !defined(MBEDTLS_CIPHER_MODE_CTR) || \
48 !defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
49int main( void )
50{
Jaeden Amerofa30c332018-12-21 18:42:18 +000051 printf( "MBEDTLS_PSA_CRYPTO_C and/or MBEDTLS_AES_C and/or "
52 "MBEDTLS_CIPHER_MODE_CBC and/or MBEDTLS_CIPHER_MODE_CTR "
53 "and/or MBEDTLS_CIPHER_MODE_WITH_PADDING "
54 "not defined.\r\n" );
itayzafrir18ac3312018-07-17 09:28:11 +030055 return( 0 );
56}
57#else
58
itayzafrir10366702018-07-11 13:44:41 +030059static psa_status_t cipher_operation( psa_cipher_operation_t *operation,
60 const uint8_t * input,
61 size_t input_size,
62 size_t part_size,
63 uint8_t * output,
64 size_t output_size,
65 size_t *output_len )
66{
67 psa_status_t status;
68 size_t bytes_to_write = 0, bytes_written = 0, len = 0;
69
70 *output_len = 0;
71 while( bytes_written != input_size )
72 {
73 bytes_to_write = ( input_size - bytes_written > part_size ?
74 part_size :
75 input_size - bytes_written );
76
77 status = psa_cipher_update( operation, input + bytes_written,
78 bytes_to_write, output + *output_len,
79 output_size - *output_len, &len );
80 ASSERT_STATUS( status, PSA_SUCCESS );
81
82 bytes_written += bytes_to_write;
83 *output_len += len;
84 }
85
86 status = psa_cipher_finish( operation, output + *output_len,
87 output_size - *output_len, &len );
88 ASSERT_STATUS( status, PSA_SUCCESS );
89 *output_len += len;
90
91exit:
92 return( status );
93}
94
Gilles Peskineb0edfb52018-12-03 16:24:51 +010095static psa_status_t cipher_encrypt( psa_key_handle_t key_handle,
itayzafrir10366702018-07-11 13:44:41 +030096 psa_algorithm_t alg,
97 uint8_t * iv,
98 size_t iv_size,
99 const uint8_t * input,
100 size_t input_size,
101 size_t part_size,
102 uint8_t * output,
103 size_t output_size,
104 size_t *output_len )
105{
106 psa_status_t status;
Jaeden Amerob281f742019-02-20 10:40:20 +0000107 psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
itayzafrir10366702018-07-11 13:44:41 +0300108 size_t iv_len = 0;
109
110 memset( &operation, 0, sizeof( operation ) );
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100111 status = psa_cipher_encrypt_setup( &operation, key_handle, alg );
itayzafrir10366702018-07-11 13:44:41 +0300112 ASSERT_STATUS( status, PSA_SUCCESS );
113
114 status = psa_cipher_generate_iv( &operation, iv, iv_size, &iv_len );
115 ASSERT_STATUS( status, PSA_SUCCESS );
116
117 status = cipher_operation( &operation, input, input_size, part_size,
118 output, output_size, output_len );
119 ASSERT_STATUS( status, PSA_SUCCESS );
120
121exit:
122 psa_cipher_abort( &operation );
123 return( status );
124}
125
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100126static psa_status_t cipher_decrypt( psa_key_handle_t key_handle,
itayzafrir10366702018-07-11 13:44:41 +0300127 psa_algorithm_t alg,
128 const uint8_t * iv,
129 size_t iv_size,
130 const uint8_t * input,
131 size_t input_size,
132 size_t part_size,
133 uint8_t * output,
134 size_t output_size,
135 size_t *output_len )
136{
137 psa_status_t status;
Jaeden Amerob281f742019-02-20 10:40:20 +0000138 psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
itayzafrir10366702018-07-11 13:44:41 +0300139
140 memset( &operation, 0, sizeof( operation ) );
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100141 status = psa_cipher_decrypt_setup( &operation, key_handle, alg );
itayzafrir10366702018-07-11 13:44:41 +0300142 ASSERT_STATUS( status, PSA_SUCCESS );
143
144 status = psa_cipher_set_iv( &operation, iv, iv_size );
145 ASSERT_STATUS( status, PSA_SUCCESS );
146
147 status = cipher_operation( &operation, input, input_size, part_size,
148 output, output_size, output_len );
149 ASSERT_STATUS( status, PSA_SUCCESS );
150
151exit:
152 psa_cipher_abort( &operation );
153 return( status );
154}
155
156static psa_status_t
157cipher_example_encrypt_decrypt_aes_cbc_nopad_1_block( void )
158{
159 enum {
160 block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( PSA_KEY_TYPE_AES ),
161 key_bits = 256,
162 part_size = block_size,
163 };
Gilles Peskinedaea26f2018-08-21 14:02:45 +0200164 const psa_algorithm_t alg = PSA_ALG_CBC_NO_PADDING;
itayzafrir10366702018-07-11 13:44:41 +0300165
166 psa_status_t status;
Gilles Peskinedfea0a252019-04-18 13:39:40 +0200167 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
Ronald Cron91e95152020-07-30 17:48:03 +0200168 psa_key_handle_t key_handle = PSA_KEY_HANDLE_INIT;
itayzafrir10366702018-07-11 13:44:41 +0300169 size_t output_len = 0;
170 uint8_t iv[block_size];
171 uint8_t input[block_size];
172 uint8_t encrypt[block_size];
173 uint8_t decrypt[block_size];
174
175 status = psa_generate_random( input, sizeof( input ) );
176 ASSERT_STATUS( status, PSA_SUCCESS );
177
Gilles Peskinedfea0a252019-04-18 13:39:40 +0200178 psa_set_key_usage_flags( &attributes,
179 PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT );
180 psa_set_key_algorithm( &attributes, alg );
181 psa_set_key_type( &attributes, PSA_KEY_TYPE_AES );
Gilles Peskine3a4f1f82019-04-26 13:49:28 +0200182 psa_set_key_bits( &attributes, key_bits );
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100183
Gilles Peskine35ef36b2019-05-16 19:42:05 +0200184 status = psa_generate_key( &attributes, &key_handle );
itayzafrir10366702018-07-11 13:44:41 +0300185 ASSERT_STATUS( status, PSA_SUCCESS );
186
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100187 status = cipher_encrypt( key_handle, alg, iv, sizeof( iv ),
itayzafrir10366702018-07-11 13:44:41 +0300188 input, sizeof( input ), part_size,
189 encrypt, sizeof( encrypt ), &output_len );
190 ASSERT_STATUS( status, PSA_SUCCESS );
191
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100192 status = cipher_decrypt( key_handle, alg, iv, sizeof( iv ),
itayzafrir10366702018-07-11 13:44:41 +0300193 encrypt, output_len, part_size,
194 decrypt, sizeof( decrypt ), &output_len );
195 ASSERT_STATUS( status, PSA_SUCCESS );
196
197 status = memcmp( input, decrypt, sizeof( input ) );
198 ASSERT_STATUS( status, PSA_SUCCESS );
199
200exit:
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100201 psa_destroy_key( key_handle );
itayzafrir10366702018-07-11 13:44:41 +0300202 return( status );
203}
204
itayzafrira2d08042018-07-12 10:27:58 +0300205static psa_status_t cipher_example_encrypt_decrypt_aes_cbc_pkcs7_multi( void )
206{
207 enum {
208 block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( PSA_KEY_TYPE_AES ),
209 key_bits = 256,
210 input_size = 100,
211 part_size = 10,
212 };
213
Gilles Peskinedaea26f2018-08-21 14:02:45 +0200214 const psa_algorithm_t alg = PSA_ALG_CBC_PKCS7;
itayzafrira2d08042018-07-12 10:27:58 +0300215
216 psa_status_t status;
Gilles Peskinedfea0a252019-04-18 13:39:40 +0200217 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
Ronald Cron91e95152020-07-30 17:48:03 +0200218 psa_key_handle_t key_handle = PSA_KEY_HANDLE_INIT;
itayzafrira2d08042018-07-12 10:27:58 +0300219 size_t output_len = 0;
220 uint8_t iv[block_size], input[input_size],
221 encrypt[input_size + block_size], decrypt[input_size + block_size];
222
223 status = psa_generate_random( input, sizeof( input ) );
224 ASSERT_STATUS( status, PSA_SUCCESS );
225
Gilles Peskinedfea0a252019-04-18 13:39:40 +0200226 psa_set_key_usage_flags( &attributes,
227 PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT );
228 psa_set_key_algorithm( &attributes, alg );
229 psa_set_key_type( &attributes, PSA_KEY_TYPE_AES );
Gilles Peskine3a4f1f82019-04-26 13:49:28 +0200230 psa_set_key_bits( &attributes, key_bits );
itayzafrira2d08042018-07-12 10:27:58 +0300231
Gilles Peskine35ef36b2019-05-16 19:42:05 +0200232 status = psa_generate_key( &attributes, &key_handle );
itayzafrira2d08042018-07-12 10:27:58 +0300233 ASSERT_STATUS( status, PSA_SUCCESS );
234
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100235 status = cipher_encrypt( key_handle, alg, iv, sizeof( iv ),
itayzafrira2d08042018-07-12 10:27:58 +0300236 input, sizeof( input ), part_size,
237 encrypt, sizeof( encrypt ), &output_len );
238 ASSERT_STATUS( status, PSA_SUCCESS );
239
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100240 status = cipher_decrypt( key_handle, alg, iv, sizeof( iv ),
itayzafrira2d08042018-07-12 10:27:58 +0300241 encrypt, output_len, part_size,
242 decrypt, sizeof( decrypt ), &output_len );
243 ASSERT_STATUS( status, PSA_SUCCESS );
244
245 status = memcmp( input, decrypt, sizeof( input ) );
246 ASSERT_STATUS( status, PSA_SUCCESS );
247
248exit:
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100249 psa_destroy_key( key_handle );
itayzafrira2d08042018-07-12 10:27:58 +0300250 return( status );
251}
252
itayzafrir44b09d22018-07-12 13:06:41 +0300253static psa_status_t cipher_example_encrypt_decrypt_aes_ctr_multi( void )
254{
255 enum {
256 block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( PSA_KEY_TYPE_AES ),
257 key_bits = 256,
258 input_size = 100,
259 part_size = 10,
260 };
261 const psa_algorithm_t alg = PSA_ALG_CTR;
262
263 psa_status_t status;
Gilles Peskinedfea0a252019-04-18 13:39:40 +0200264 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
Ronald Cron91e95152020-07-30 17:48:03 +0200265 psa_key_handle_t key_handle = PSA_KEY_HANDLE_INIT;
itayzafrir44b09d22018-07-12 13:06:41 +0300266 size_t output_len = 0;
267 uint8_t iv[block_size], input[input_size], encrypt[input_size],
268 decrypt[input_size];
269
270 status = psa_generate_random( input, sizeof( input ) );
271 ASSERT_STATUS( status, PSA_SUCCESS );
272
Gilles Peskinedfea0a252019-04-18 13:39:40 +0200273 psa_set_key_usage_flags( &attributes,
274 PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT );
275 psa_set_key_algorithm( &attributes, alg );
276 psa_set_key_type( &attributes, PSA_KEY_TYPE_AES );
Gilles Peskine3a4f1f82019-04-26 13:49:28 +0200277 psa_set_key_bits( &attributes, key_bits );
itayzafrir44b09d22018-07-12 13:06:41 +0300278
Gilles Peskine35ef36b2019-05-16 19:42:05 +0200279 status = psa_generate_key( &attributes, &key_handle );
itayzafrir44b09d22018-07-12 13:06:41 +0300280 ASSERT_STATUS( status, PSA_SUCCESS );
281
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100282 status = cipher_encrypt( key_handle, alg, iv, sizeof( iv ),
itayzafrir44b09d22018-07-12 13:06:41 +0300283 input, sizeof( input ), part_size,
284 encrypt, sizeof( encrypt ), &output_len );
285 ASSERT_STATUS( status, PSA_SUCCESS );
286
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100287 status = cipher_decrypt( key_handle, alg, iv, sizeof( iv ),
itayzafrir44b09d22018-07-12 13:06:41 +0300288 encrypt, output_len, part_size,
289 decrypt, sizeof( decrypt ), &output_len );
290 ASSERT_STATUS( status, PSA_SUCCESS );
291
292 status = memcmp( input, decrypt, sizeof( input ) );
293 ASSERT_STATUS( status, PSA_SUCCESS );
294
295exit:
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100296 psa_destroy_key( key_handle );
itayzafrir44b09d22018-07-12 13:06:41 +0300297 return( status );
298}
299
itayzafrir10366702018-07-11 13:44:41 +0300300static void cipher_examples( void )
301{
302 psa_status_t status;
303
Jaeden Amerofa30c332018-12-21 18:42:18 +0000304 printf( "cipher encrypt/decrypt AES CBC no padding:\r\n" );
itayzafrir10366702018-07-11 13:44:41 +0300305 status = cipher_example_encrypt_decrypt_aes_cbc_nopad_1_block( );
306 if( status == PSA_SUCCESS )
Jaeden Amerofa30c332018-12-21 18:42:18 +0000307 printf( "\tsuccess!\r\n" );
itayzafrira2d08042018-07-12 10:27:58 +0300308
Jaeden Amerofa30c332018-12-21 18:42:18 +0000309 printf( "cipher encrypt/decrypt AES CBC PKCS7 multipart:\r\n" );
itayzafrira2d08042018-07-12 10:27:58 +0300310 status = cipher_example_encrypt_decrypt_aes_cbc_pkcs7_multi( );
311 if( status == PSA_SUCCESS )
Jaeden Amerofa30c332018-12-21 18:42:18 +0000312 printf( "\tsuccess!\r\n" );
itayzafrir44b09d22018-07-12 13:06:41 +0300313
Jaeden Amerofa30c332018-12-21 18:42:18 +0000314 printf( "cipher encrypt/decrypt AES CTR multipart:\r\n" );
itayzafrir44b09d22018-07-12 13:06:41 +0300315 status = cipher_example_encrypt_decrypt_aes_ctr_multi( );
316 if( status == PSA_SUCCESS )
Jaeden Amerofa30c332018-12-21 18:42:18 +0000317 printf( "\tsuccess!\r\n" );
itayzafrir10366702018-07-11 13:44:41 +0300318}
319
itayzafrira3ff8a62018-07-10 10:10:21 +0300320int main( void )
321{
itayzafrir10366702018-07-11 13:44:41 +0300322 ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
323 cipher_examples( );
324exit:
325 mbedtls_psa_crypto_free( );
itayzafrira3ff8a62018-07-10 10:10:21 +0300326 return( 0 );
327}
itayzafrir18ac3312018-07-17 09:28:11 +0300328#endif /* MBEDTLS_PSA_CRYPTO_C && MBEDTLS_AES_C && MBEDTLS_CIPHER_MODE_CBC &&
329 MBEDTLS_CIPHER_MODE_CTR && MBEDTLS_CIPHER_MODE_WITH_PADDING */