blob: a7c36fa0445d44b54ecdaba00ecbe34f2f09ce90 [file] [log] [blame]
itayzafrir10366702018-07-11 13:44:41 +03001#include "psa/crypto.h"
2#include <string.h>
3
4#if defined(MBEDTLS_PLATFORM_C)
5#include "mbedtls/platform.h"
6#else
7#include <stdio.h>
8#define mbedtls_printf printf
9#endif
10
11#define ASSERT( predicate ) \
12 do \
13 { \
14 if( ! ( predicate ) ) \
15 { \
16 mbedtls_printf( "\tassertion failed at %s:%d - '%s'\r\n", \
17 __FILE__, __LINE__, #predicate); \
18 goto exit; \
19 } \
20 } while ( 0 )
21
22#define ASSERT_STATUS( actual, expected ) \
23 do \
24 { \
25 if( ( actual ) != ( expected ) ) \
26 { \
27 mbedtls_printf( "\tassertion failed at %s:%d - " \
28 "actual:%d expected:%d\r\n", __FILE__, __LINE__, \
29 (psa_status_t) actual, (psa_status_t) expected ); \
30 goto exit; \
31 } \
32 } while ( 0 )
33
34/* Use key slot 1 for our cipher key. Key slot 0 is reserved as unused. */
35static const psa_key_slot_t key_slot_cipher = 1;
36
37static psa_status_t set_key_policy( psa_key_slot_t key_slot,
38 psa_key_usage_t key_usage,
39 psa_algorithm_t alg )
40{
41 psa_status_t status;
42 psa_key_policy_t policy;
43
44 psa_key_policy_init( &policy );
45 psa_key_policy_set_usage( &policy, key_usage, alg );
46 status = psa_set_key_policy( key_slot, &policy );
47 ASSERT_STATUS( status, PSA_SUCCESS );
48exit:
49 return( status );
50}
51
52static psa_status_t cipher_operation( psa_cipher_operation_t *operation,
53 const uint8_t * input,
54 size_t input_size,
55 size_t part_size,
56 uint8_t * output,
57 size_t output_size,
58 size_t *output_len )
59{
60 psa_status_t status;
61 size_t bytes_to_write = 0, bytes_written = 0, len = 0;
62
63 *output_len = 0;
64 while( bytes_written != input_size )
65 {
66 bytes_to_write = ( input_size - bytes_written > part_size ?
67 part_size :
68 input_size - bytes_written );
69
70 status = psa_cipher_update( operation, input + bytes_written,
71 bytes_to_write, output + *output_len,
72 output_size - *output_len, &len );
73 ASSERT_STATUS( status, PSA_SUCCESS );
74
75 bytes_written += bytes_to_write;
76 *output_len += len;
77 }
78
79 status = psa_cipher_finish( operation, output + *output_len,
80 output_size - *output_len, &len );
81 ASSERT_STATUS( status, PSA_SUCCESS );
82 *output_len += len;
83
84exit:
85 return( status );
86}
87
88static psa_status_t cipher_encrypt( psa_key_slot_t key_slot,
89 psa_algorithm_t alg,
90 uint8_t * iv,
91 size_t iv_size,
92 const uint8_t * input,
93 size_t input_size,
94 size_t part_size,
95 uint8_t * output,
96 size_t output_size,
97 size_t *output_len )
98{
99 psa_status_t status;
100 psa_cipher_operation_t operation;
101 size_t iv_len = 0;
102
103 memset( &operation, 0, sizeof( operation ) );
104 status = psa_cipher_encrypt_setup( &operation, key_slot, alg );
105 ASSERT_STATUS( status, PSA_SUCCESS );
106
107 status = psa_cipher_generate_iv( &operation, iv, iv_size, &iv_len );
108 ASSERT_STATUS( status, PSA_SUCCESS );
109
110 status = cipher_operation( &operation, input, input_size, part_size,
111 output, output_size, output_len );
112 ASSERT_STATUS( status, PSA_SUCCESS );
113
114exit:
115 psa_cipher_abort( &operation );
116 return( status );
117}
118
119static psa_status_t cipher_decrypt( psa_key_slot_t key_slot,
120 psa_algorithm_t alg,
121 const uint8_t * iv,
122 size_t iv_size,
123 const uint8_t * input,
124 size_t input_size,
125 size_t part_size,
126 uint8_t * output,
127 size_t output_size,
128 size_t *output_len )
129{
130 psa_status_t status;
131 psa_cipher_operation_t operation;
132
133 memset( &operation, 0, sizeof( operation ) );
134 status = psa_cipher_decrypt_setup( &operation, key_slot, alg );
135 ASSERT_STATUS( status, PSA_SUCCESS );
136
137 status = psa_cipher_set_iv( &operation, iv, iv_size );
138 ASSERT_STATUS( status, PSA_SUCCESS );
139
140 status = cipher_operation( &operation, input, input_size, part_size,
141 output, output_size, output_len );
142 ASSERT_STATUS( status, PSA_SUCCESS );
143
144exit:
145 psa_cipher_abort( &operation );
146 return( status );
147}
148
149static psa_status_t
150cipher_example_encrypt_decrypt_aes_cbc_nopad_1_block( void )
151{
152 enum {
153 block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( PSA_KEY_TYPE_AES ),
154 key_bits = 256,
155 part_size = block_size,
156 };
157 const psa_algorithm_t alg = PSA_ALG_CBC_BASE |
158 PSA_ALG_BLOCK_CIPHER_PAD_NONE;
159
160 psa_status_t status;
161 size_t output_len = 0;
162 uint8_t iv[block_size];
163 uint8_t input[block_size];
164 uint8_t encrypt[block_size];
165 uint8_t decrypt[block_size];
166
167 status = psa_generate_random( input, sizeof( input ) );
168 ASSERT_STATUS( status, PSA_SUCCESS );
169
170 status = set_key_policy( key_slot_cipher,
171 PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT,
172 alg );
173 ASSERT_STATUS( status, PSA_SUCCESS );
174
175 status = psa_generate_key( key_slot_cipher, PSA_KEY_TYPE_AES, key_bits,
176 NULL, 0 );
177 ASSERT_STATUS( status, PSA_SUCCESS );
178
179 status = cipher_encrypt( key_slot_cipher, alg, iv, sizeof( iv ),
180 input, sizeof( input ), part_size,
181 encrypt, sizeof( encrypt ), &output_len );
182 ASSERT_STATUS( status, PSA_SUCCESS );
183
184 status = cipher_decrypt( key_slot_cipher, alg, iv, sizeof( iv ),
185 encrypt, output_len, part_size,
186 decrypt, sizeof( decrypt ), &output_len );
187 ASSERT_STATUS( status, PSA_SUCCESS );
188
189 status = memcmp( input, decrypt, sizeof( input ) );
190 ASSERT_STATUS( status, PSA_SUCCESS );
191
192exit:
193 psa_destroy_key( key_slot_cipher );
194 return( status );
195}
196
itayzafrira2d08042018-07-12 10:27:58 +0300197static psa_status_t cipher_example_encrypt_decrypt_aes_cbc_pkcs7_multi( void )
198{
199 enum {
200 block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( PSA_KEY_TYPE_AES ),
201 key_bits = 256,
202 input_size = 100,
203 part_size = 10,
204 };
205
206 const psa_algorithm_t alg = PSA_ALG_CBC_BASE |
207 PSA_ALG_BLOCK_CIPHER_PAD_PKCS7;
208
209 psa_status_t status;
210 size_t output_len = 0;
211 uint8_t iv[block_size], input[input_size],
212 encrypt[input_size + block_size], decrypt[input_size + block_size];
213
214 status = psa_generate_random( input, sizeof( input ) );
215 ASSERT_STATUS( status, PSA_SUCCESS );
216
217 status = set_key_policy( key_slot_cipher,
218 PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT,
219 alg );
220 ASSERT_STATUS( status, PSA_SUCCESS );
221
222 status = psa_generate_key( key_slot_cipher, PSA_KEY_TYPE_AES, key_bits,
223 NULL, 0 );
224 ASSERT_STATUS( status, PSA_SUCCESS );
225
226 status = cipher_encrypt( key_slot_cipher, alg, iv, sizeof( iv ),
227 input, sizeof( input ), part_size,
228 encrypt, sizeof( encrypt ), &output_len );
229 ASSERT_STATUS( status, PSA_SUCCESS );
230
231 status = cipher_decrypt( key_slot_cipher, alg, iv, sizeof( iv ),
232 encrypt, output_len, part_size,
233 decrypt, sizeof( decrypt ), &output_len );
234 ASSERT_STATUS( status, PSA_SUCCESS );
235
236 status = memcmp( input, decrypt, sizeof( input ) );
237 ASSERT_STATUS( status, PSA_SUCCESS );
238
239exit:
240 psa_destroy_key( key_slot_cipher );
241 return( status );
242}
243
itayzafrir44b09d22018-07-12 13:06:41 +0300244static psa_status_t cipher_example_encrypt_decrypt_aes_ctr_multi( void )
245{
246 enum {
247 block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( PSA_KEY_TYPE_AES ),
248 key_bits = 256,
249 input_size = 100,
250 part_size = 10,
251 };
252 const psa_algorithm_t alg = PSA_ALG_CTR;
253
254 psa_status_t status;
255 size_t output_len = 0;
256 uint8_t iv[block_size], input[input_size], encrypt[input_size],
257 decrypt[input_size];
258
259 status = psa_generate_random( input, sizeof( input ) );
260 ASSERT_STATUS( status, PSA_SUCCESS );
261
262 status = set_key_policy( key_slot_cipher,
263 PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT,
264 alg );
265 ASSERT_STATUS( status, PSA_SUCCESS );
266
267 status = psa_generate_key( key_slot_cipher, PSA_KEY_TYPE_AES, key_bits,
268 NULL, 0 );
269 ASSERT_STATUS( status, PSA_SUCCESS );
270
271 status = cipher_encrypt( key_slot_cipher, alg, iv, sizeof( iv ),
272 input, sizeof( input ), part_size,
273 encrypt, sizeof( encrypt ), &output_len );
274 ASSERT_STATUS( status, PSA_SUCCESS );
275
276 status = cipher_decrypt( key_slot_cipher, alg, iv, sizeof( iv ),
277 encrypt, output_len, part_size,
278 decrypt, sizeof( decrypt ), &output_len );
279 ASSERT_STATUS( status, PSA_SUCCESS );
280
281 status = memcmp( input, decrypt, sizeof( input ) );
282 ASSERT_STATUS( status, PSA_SUCCESS );
283
284exit:
285 psa_destroy_key( key_slot_cipher );
286 return( status );
287}
288
itayzafrir10366702018-07-11 13:44:41 +0300289static void cipher_examples( void )
290{
291 psa_status_t status;
292
293 mbedtls_printf( "cipher encrypt/decrypt AES CBC no padding:\r\n" );
294 status = cipher_example_encrypt_decrypt_aes_cbc_nopad_1_block( );
295 if( status == PSA_SUCCESS )
296 mbedtls_printf( "\tsuccess!\r\n" );
itayzafrira2d08042018-07-12 10:27:58 +0300297
298 mbedtls_printf( "cipher encrypt/decrypt AES CBC PKCS7 multipart:\r\n" );
299 status = cipher_example_encrypt_decrypt_aes_cbc_pkcs7_multi( );
300 if( status == PSA_SUCCESS )
301 mbedtls_printf( "\tsuccess!\r\n" );
itayzafrir44b09d22018-07-12 13:06:41 +0300302
303 mbedtls_printf( "cipher encrypt/decrypt AES CTR multipart:\r\n" );
304 status = cipher_example_encrypt_decrypt_aes_ctr_multi( );
305 if( status == PSA_SUCCESS )
306 mbedtls_printf( "\tsuccess!\r\n" );
itayzafrir10366702018-07-11 13:44:41 +0300307}
308
itayzafrira3ff8a62018-07-10 10:10:21 +0300309int main( void )
310{
itayzafrir10366702018-07-11 13:44:41 +0300311 ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
312 cipher_examples( );
313exit:
314 mbedtls_psa_crypto_free( );
itayzafrira3ff8a62018-07-10 10:10:21 +0300315 return( 0 );
316}