blob: 2f7c4453d605e3f041e2fa171c70d54d342d1117 [file] [log] [blame]
itayzafrir10366702018-07-11 13:44:41 +03001#include "psa/crypto.h"
2#include <string.h>
itayzafrir10366702018-07-11 13:44:41 +03003#include <stdio.h>
Jaeden Amerodb29ab52019-02-12 16:40:27 +00004#include <stdlib.h>
itayzafrir10366702018-07-11 13:44:41 +03005
6#define ASSERT( predicate ) \
7 do \
8 { \
9 if( ! ( predicate ) ) \
10 { \
Jaeden Amerofa30c332018-12-21 18:42:18 +000011 printf( "\tassertion failed at %s:%d - '%s'\r\n", \
12 __FILE__, __LINE__, #predicate); \
itayzafrir10366702018-07-11 13:44:41 +030013 goto exit; \
14 } \
15 } while ( 0 )
16
17#define ASSERT_STATUS( actual, expected ) \
18 do \
19 { \
20 if( ( actual ) != ( expected ) ) \
21 { \
Jaeden Amerofa30c332018-12-21 18:42:18 +000022 printf( "\tassertion failed at %s:%d - " \
23 "actual:%d expected:%d\r\n", __FILE__, __LINE__, \
itayzafrir10366702018-07-11 13:44:41 +030024 (psa_status_t) actual, (psa_status_t) expected ); \
25 goto exit; \
26 } \
27 } while ( 0 )
28
itayzafrir18ac3312018-07-17 09:28:11 +030029#if !defined(MBEDTLS_PSA_CRYPTO_C) || !defined(MBEDTLS_AES_C) || \
30 !defined(MBEDTLS_CIPHER_MODE_CBC) || !defined(MBEDTLS_CIPHER_MODE_CTR) || \
31 !defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
32int main( void )
33{
Jaeden Amerofa30c332018-12-21 18:42:18 +000034 printf( "MBEDTLS_PSA_CRYPTO_C and/or MBEDTLS_AES_C and/or "
35 "MBEDTLS_CIPHER_MODE_CBC and/or MBEDTLS_CIPHER_MODE_CTR "
36 "and/or MBEDTLS_CIPHER_MODE_WITH_PADDING "
37 "not defined.\r\n" );
itayzafrir18ac3312018-07-17 09:28:11 +030038 return( 0 );
39}
40#else
41
Gilles Peskineb0edfb52018-12-03 16:24:51 +010042static psa_status_t set_key_policy( psa_key_handle_t key_handle,
itayzafrir10366702018-07-11 13:44:41 +030043 psa_key_usage_t key_usage,
44 psa_algorithm_t alg )
45{
46 psa_status_t status;
Jaeden Amero70261c52019-01-04 11:47:20 +000047 psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
itayzafrir10366702018-07-11 13:44:41 +030048
itayzafrir10366702018-07-11 13:44:41 +030049 psa_key_policy_set_usage( &policy, key_usage, alg );
Gilles Peskineb0edfb52018-12-03 16:24:51 +010050 status = psa_set_key_policy( key_handle, &policy );
itayzafrir10366702018-07-11 13:44:41 +030051 ASSERT_STATUS( status, PSA_SUCCESS );
52exit:
53 return( status );
54}
55
56static psa_status_t cipher_operation( psa_cipher_operation_t *operation,
57 const uint8_t * input,
58 size_t input_size,
59 size_t part_size,
60 uint8_t * output,
61 size_t output_size,
62 size_t *output_len )
63{
64 psa_status_t status;
65 size_t bytes_to_write = 0, bytes_written = 0, len = 0;
66
67 *output_len = 0;
68 while( bytes_written != input_size )
69 {
70 bytes_to_write = ( input_size - bytes_written > part_size ?
71 part_size :
72 input_size - bytes_written );
73
74 status = psa_cipher_update( operation, input + bytes_written,
75 bytes_to_write, output + *output_len,
76 output_size - *output_len, &len );
77 ASSERT_STATUS( status, PSA_SUCCESS );
78
79 bytes_written += bytes_to_write;
80 *output_len += len;
81 }
82
83 status = psa_cipher_finish( operation, output + *output_len,
84 output_size - *output_len, &len );
85 ASSERT_STATUS( status, PSA_SUCCESS );
86 *output_len += len;
87
88exit:
89 return( status );
90}
91
Gilles Peskineb0edfb52018-12-03 16:24:51 +010092static psa_status_t cipher_encrypt( psa_key_handle_t key_handle,
itayzafrir10366702018-07-11 13:44:41 +030093 psa_algorithm_t alg,
94 uint8_t * iv,
95 size_t iv_size,
96 const uint8_t * input,
97 size_t input_size,
98 size_t part_size,
99 uint8_t * output,
100 size_t output_size,
101 size_t *output_len )
102{
103 psa_status_t status;
Jaeden Amerob281f742019-02-20 10:40:20 +0000104 psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
itayzafrir10366702018-07-11 13:44:41 +0300105 size_t iv_len = 0;
106
107 memset( &operation, 0, sizeof( operation ) );
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100108 status = psa_cipher_encrypt_setup( &operation, key_handle, alg );
itayzafrir10366702018-07-11 13:44:41 +0300109 ASSERT_STATUS( status, PSA_SUCCESS );
110
111 status = psa_cipher_generate_iv( &operation, iv, iv_size, &iv_len );
112 ASSERT_STATUS( status, PSA_SUCCESS );
113
114 status = cipher_operation( &operation, input, input_size, part_size,
115 output, output_size, output_len );
116 ASSERT_STATUS( status, PSA_SUCCESS );
117
118exit:
119 psa_cipher_abort( &operation );
120 return( status );
121}
122
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100123static psa_status_t cipher_decrypt( psa_key_handle_t key_handle,
itayzafrir10366702018-07-11 13:44:41 +0300124 psa_algorithm_t alg,
125 const uint8_t * iv,
126 size_t iv_size,
127 const uint8_t * input,
128 size_t input_size,
129 size_t part_size,
130 uint8_t * output,
131 size_t output_size,
132 size_t *output_len )
133{
134 psa_status_t status;
Jaeden Amerob281f742019-02-20 10:40:20 +0000135 psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
itayzafrir10366702018-07-11 13:44:41 +0300136
137 memset( &operation, 0, sizeof( operation ) );
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100138 status = psa_cipher_decrypt_setup( &operation, key_handle, alg );
itayzafrir10366702018-07-11 13:44:41 +0300139 ASSERT_STATUS( status, PSA_SUCCESS );
140
141 status = psa_cipher_set_iv( &operation, iv, iv_size );
142 ASSERT_STATUS( status, PSA_SUCCESS );
143
144 status = cipher_operation( &operation, input, input_size, part_size,
145 output, output_size, output_len );
146 ASSERT_STATUS( status, PSA_SUCCESS );
147
148exit:
149 psa_cipher_abort( &operation );
150 return( status );
151}
152
153static psa_status_t
154cipher_example_encrypt_decrypt_aes_cbc_nopad_1_block( void )
155{
156 enum {
157 block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( PSA_KEY_TYPE_AES ),
158 key_bits = 256,
159 part_size = block_size,
160 };
Gilles Peskinedaea26f2018-08-21 14:02:45 +0200161 const psa_algorithm_t alg = PSA_ALG_CBC_NO_PADDING;
itayzafrir10366702018-07-11 13:44:41 +0300162
163 psa_status_t status;
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100164 psa_key_handle_t key_handle = 0;
itayzafrir10366702018-07-11 13:44:41 +0300165 size_t output_len = 0;
166 uint8_t iv[block_size];
167 uint8_t input[block_size];
168 uint8_t encrypt[block_size];
169 uint8_t decrypt[block_size];
170
171 status = psa_generate_random( input, sizeof( input ) );
172 ASSERT_STATUS( status, PSA_SUCCESS );
173
Gilles Peskined40c1fb2019-01-19 12:20:52 +0100174 status = psa_allocate_key( &key_handle );
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100175 ASSERT_STATUS( status, PSA_SUCCESS );
176
177 status = set_key_policy( key_handle,
itayzafrir10366702018-07-11 13:44:41 +0300178 PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT,
179 alg );
180 ASSERT_STATUS( status, PSA_SUCCESS );
181
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100182 status = psa_generate_key( key_handle, PSA_KEY_TYPE_AES, key_bits,
itayzafrir10366702018-07-11 13:44:41 +0300183 NULL, 0 );
184 ASSERT_STATUS( status, PSA_SUCCESS );
185
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100186 status = cipher_encrypt( key_handle, alg, iv, sizeof( iv ),
itayzafrir10366702018-07-11 13:44:41 +0300187 input, sizeof( input ), part_size,
188 encrypt, sizeof( encrypt ), &output_len );
189 ASSERT_STATUS( status, PSA_SUCCESS );
190
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100191 status = cipher_decrypt( key_handle, alg, iv, sizeof( iv ),
itayzafrir10366702018-07-11 13:44:41 +0300192 encrypt, output_len, part_size,
193 decrypt, sizeof( decrypt ), &output_len );
194 ASSERT_STATUS( status, PSA_SUCCESS );
195
196 status = memcmp( input, decrypt, sizeof( input ) );
197 ASSERT_STATUS( status, PSA_SUCCESS );
198
199exit:
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100200 psa_destroy_key( key_handle );
itayzafrir10366702018-07-11 13:44:41 +0300201 return( status );
202}
203
itayzafrira2d08042018-07-12 10:27:58 +0300204static psa_status_t cipher_example_encrypt_decrypt_aes_cbc_pkcs7_multi( void )
205{
206 enum {
207 block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( PSA_KEY_TYPE_AES ),
208 key_bits = 256,
209 input_size = 100,
210 part_size = 10,
211 };
212
Gilles Peskinedaea26f2018-08-21 14:02:45 +0200213 const psa_algorithm_t alg = PSA_ALG_CBC_PKCS7;
itayzafrira2d08042018-07-12 10:27:58 +0300214
215 psa_status_t status;
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100216 psa_key_handle_t key_handle = 0;
itayzafrira2d08042018-07-12 10:27:58 +0300217 size_t output_len = 0;
218 uint8_t iv[block_size], input[input_size],
219 encrypt[input_size + block_size], decrypt[input_size + block_size];
220
221 status = psa_generate_random( input, sizeof( input ) );
222 ASSERT_STATUS( status, PSA_SUCCESS );
223
Gilles Peskined40c1fb2019-01-19 12:20:52 +0100224 status = psa_allocate_key( &key_handle );
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100225 ASSERT_STATUS( status, PSA_SUCCESS );
226
227 status = set_key_policy( key_handle,
itayzafrira2d08042018-07-12 10:27:58 +0300228 PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT,
229 alg );
230 ASSERT_STATUS( status, PSA_SUCCESS );
231
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100232 status = psa_generate_key( key_handle, PSA_KEY_TYPE_AES, key_bits,
itayzafrira2d08042018-07-12 10:27:58 +0300233 NULL, 0 );
234 ASSERT_STATUS( status, PSA_SUCCESS );
235
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100236 status = cipher_encrypt( key_handle, alg, iv, sizeof( iv ),
itayzafrira2d08042018-07-12 10:27:58 +0300237 input, sizeof( input ), part_size,
238 encrypt, sizeof( encrypt ), &output_len );
239 ASSERT_STATUS( status, PSA_SUCCESS );
240
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100241 status = cipher_decrypt( key_handle, alg, iv, sizeof( iv ),
itayzafrira2d08042018-07-12 10:27:58 +0300242 encrypt, output_len, part_size,
243 decrypt, sizeof( decrypt ), &output_len );
244 ASSERT_STATUS( status, PSA_SUCCESS );
245
246 status = memcmp( input, decrypt, sizeof( input ) );
247 ASSERT_STATUS( status, PSA_SUCCESS );
248
249exit:
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100250 psa_destroy_key( key_handle );
itayzafrira2d08042018-07-12 10:27:58 +0300251 return( status );
252}
253
itayzafrir44b09d22018-07-12 13:06:41 +0300254static psa_status_t cipher_example_encrypt_decrypt_aes_ctr_multi( void )
255{
256 enum {
257 block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( PSA_KEY_TYPE_AES ),
258 key_bits = 256,
259 input_size = 100,
260 part_size = 10,
261 };
262 const psa_algorithm_t alg = PSA_ALG_CTR;
263
264 psa_status_t status;
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100265 psa_key_handle_t key_handle = 0;
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 Peskined40c1fb2019-01-19 12:20:52 +0100273 status = psa_allocate_key( &key_handle );
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100274 ASSERT_STATUS( status, PSA_SUCCESS );
275 status = set_key_policy( key_handle,
itayzafrir44b09d22018-07-12 13:06:41 +0300276 PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT,
277 alg );
278 ASSERT_STATUS( status, PSA_SUCCESS );
279
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100280 status = psa_generate_key( key_handle, PSA_KEY_TYPE_AES, key_bits,
itayzafrir44b09d22018-07-12 13:06:41 +0300281 NULL, 0 );
282 ASSERT_STATUS( status, PSA_SUCCESS );
283
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100284 status = cipher_encrypt( key_handle, alg, iv, sizeof( iv ),
itayzafrir44b09d22018-07-12 13:06:41 +0300285 input, sizeof( input ), part_size,
286 encrypt, sizeof( encrypt ), &output_len );
287 ASSERT_STATUS( status, PSA_SUCCESS );
288
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100289 status = cipher_decrypt( key_handle, alg, iv, sizeof( iv ),
itayzafrir44b09d22018-07-12 13:06:41 +0300290 encrypt, output_len, part_size,
291 decrypt, sizeof( decrypt ), &output_len );
292 ASSERT_STATUS( status, PSA_SUCCESS );
293
294 status = memcmp( input, decrypt, sizeof( input ) );
295 ASSERT_STATUS( status, PSA_SUCCESS );
296
297exit:
Gilles Peskineb0edfb52018-12-03 16:24:51 +0100298 psa_destroy_key( key_handle );
itayzafrir44b09d22018-07-12 13:06:41 +0300299 return( status );
300}
301
itayzafrir10366702018-07-11 13:44:41 +0300302static void cipher_examples( void )
303{
304 psa_status_t status;
305
Jaeden Amerofa30c332018-12-21 18:42:18 +0000306 printf( "cipher encrypt/decrypt AES CBC no padding:\r\n" );
itayzafrir10366702018-07-11 13:44:41 +0300307 status = cipher_example_encrypt_decrypt_aes_cbc_nopad_1_block( );
308 if( status == PSA_SUCCESS )
Jaeden Amerofa30c332018-12-21 18:42:18 +0000309 printf( "\tsuccess!\r\n" );
itayzafrira2d08042018-07-12 10:27:58 +0300310
Jaeden Amerofa30c332018-12-21 18:42:18 +0000311 printf( "cipher encrypt/decrypt AES CBC PKCS7 multipart:\r\n" );
itayzafrira2d08042018-07-12 10:27:58 +0300312 status = cipher_example_encrypt_decrypt_aes_cbc_pkcs7_multi( );
313 if( status == PSA_SUCCESS )
Jaeden Amerofa30c332018-12-21 18:42:18 +0000314 printf( "\tsuccess!\r\n" );
itayzafrir44b09d22018-07-12 13:06:41 +0300315
Jaeden Amerofa30c332018-12-21 18:42:18 +0000316 printf( "cipher encrypt/decrypt AES CTR multipart:\r\n" );
itayzafrir44b09d22018-07-12 13:06:41 +0300317 status = cipher_example_encrypt_decrypt_aes_ctr_multi( );
318 if( status == PSA_SUCCESS )
Jaeden Amerofa30c332018-12-21 18:42:18 +0000319 printf( "\tsuccess!\r\n" );
itayzafrir10366702018-07-11 13:44:41 +0300320}
321
Jaeden Amero44a59ab2019-02-11 13:24:47 +0000322#if defined(MBEDTLS_CHECK_PARAMS)
323#include "mbedtls/platform_util.h"
324void mbedtls_param_failed( const char *failure_condition,
325 const char *file,
326 int line )
327{
Jaeden Amerofa30c332018-12-21 18:42:18 +0000328 printf( "%s:%i: Input param failed - %s\n",
Jaeden Amero44a59ab2019-02-11 13:24:47 +0000329 file, line, failure_condition );
Jaeden Amerofa30c332018-12-21 18:42:18 +0000330 exit( EXIT_FAILURE );
Jaeden Amero44a59ab2019-02-11 13:24:47 +0000331}
332#endif
333
itayzafrira3ff8a62018-07-10 10:10:21 +0300334int main( void )
335{
itayzafrir10366702018-07-11 13:44:41 +0300336 ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
337 cipher_examples( );
338exit:
339 mbedtls_psa_crypto_free( );
itayzafrira3ff8a62018-07-10 10:10:21 +0300340 return( 0 );
341}
itayzafrir18ac3312018-07-17 09:28:11 +0300342#endif /* MBEDTLS_PSA_CRYPTO_C && MBEDTLS_AES_C && MBEDTLS_CIPHER_MODE_CBC &&
343 MBEDTLS_CIPHER_MODE_CTR && MBEDTLS_CIPHER_MODE_WITH_PADDING */