1 /*
2 * Copyright The Mbed TLS Contributors
3 * 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.
16 */
17
18 #include "psa/crypto.h"
19 #include <string.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22
23 #define ASSERT( predicate ) \
24 do \
25 { \
26 if( ! ( predicate ) ) \
27 { \
28 printf( "\tassertion failed at %s:%d - '%s'\r\n", \
29 __FILE__, __LINE__, #predicate); \
30 goto exit; \
31 } \
32 } while ( 0 )
33
34 #define ASSERT_STATUS( actual, expected ) \
35 do \
36 { \
37 if( ( actual ) != ( expected ) ) \
38 { \
39 printf( "\tassertion failed at %s:%d - " \
40 "actual:%d expected:%d\r\n", __FILE__, __LINE__, \
41 (psa_status_t) actual, (psa_status_t) expected ); \
42 goto exit; \
43 } \
44 } while ( 0 )
45
46 #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) || \
49 defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
main(void)50 int main( void )
51 {
52 printf( "MBEDTLS_PSA_CRYPTO_C and/or MBEDTLS_AES_C and/or "
53 "MBEDTLS_CIPHER_MODE_CBC and/or MBEDTLS_CIPHER_MODE_CTR "
54 "and/or MBEDTLS_CIPHER_MODE_WITH_PADDING "
55 "not defined and/or MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER"
56 " defined.\r\n" );
57 return( 0 );
58 }
59 #else
60
cipher_operation(psa_cipher_operation_t * operation,const uint8_t * input,size_t input_size,size_t part_size,uint8_t * output,size_t output_size,size_t * output_len)61 static psa_status_t cipher_operation( psa_cipher_operation_t *operation,
62 const uint8_t * input,
63 size_t input_size,
64 size_t part_size,
65 uint8_t * output,
66 size_t output_size,
67 size_t *output_len )
68 {
69 psa_status_t status;
70 size_t bytes_to_write = 0, bytes_written = 0, len = 0;
71
72 *output_len = 0;
73 while( bytes_written != input_size )
74 {
75 bytes_to_write = ( input_size - bytes_written > part_size ?
76 part_size :
77 input_size - bytes_written );
78
79 status = psa_cipher_update( operation, input + bytes_written,
80 bytes_to_write, output + *output_len,
81 output_size - *output_len, &len );
82 ASSERT_STATUS( status, PSA_SUCCESS );
83
84 bytes_written += bytes_to_write;
85 *output_len += len;
86 }
87
88 status = psa_cipher_finish( operation, output + *output_len,
89 output_size - *output_len, &len );
90 ASSERT_STATUS( status, PSA_SUCCESS );
91 *output_len += len;
92
93 exit:
94 return( status );
95 }
96
cipher_encrypt(psa_key_id_t key,psa_algorithm_t alg,uint8_t * iv,size_t iv_size,const uint8_t * input,size_t input_size,size_t part_size,uint8_t * output,size_t output_size,size_t * output_len)97 static psa_status_t cipher_encrypt( psa_key_id_t key,
98 psa_algorithm_t alg,
99 uint8_t * iv,
100 size_t iv_size,
101 const uint8_t * input,
102 size_t input_size,
103 size_t part_size,
104 uint8_t * output,
105 size_t output_size,
106 size_t *output_len )
107 {
108 psa_status_t status;
109 psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
110 size_t iv_len = 0;
111
112 memset( &operation, 0, sizeof( operation ) );
113 status = psa_cipher_encrypt_setup( &operation, key, alg );
114 ASSERT_STATUS( status, PSA_SUCCESS );
115
116 status = psa_cipher_generate_iv( &operation, iv, iv_size, &iv_len );
117 ASSERT_STATUS( status, PSA_SUCCESS );
118
119 status = cipher_operation( &operation, input, input_size, part_size,
120 output, output_size, output_len );
121 ASSERT_STATUS( status, PSA_SUCCESS );
122
123 exit:
124 psa_cipher_abort( &operation );
125 return( status );
126 }
127
cipher_decrypt(psa_key_id_t key,psa_algorithm_t alg,const uint8_t * iv,size_t iv_size,const uint8_t * input,size_t input_size,size_t part_size,uint8_t * output,size_t output_size,size_t * output_len)128 static psa_status_t cipher_decrypt( psa_key_id_t key,
129 psa_algorithm_t alg,
130 const uint8_t * iv,
131 size_t iv_size,
132 const uint8_t * input,
133 size_t input_size,
134 size_t part_size,
135 uint8_t * output,
136 size_t output_size,
137 size_t *output_len )
138 {
139 psa_status_t status;
140 psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
141
142 memset( &operation, 0, sizeof( operation ) );
143 status = psa_cipher_decrypt_setup( &operation, key, alg );
144 ASSERT_STATUS( status, PSA_SUCCESS );
145
146 status = psa_cipher_set_iv( &operation, iv, iv_size );
147 ASSERT_STATUS( status, PSA_SUCCESS );
148
149 status = cipher_operation( &operation, input, input_size, part_size,
150 output, output_size, output_len );
151 ASSERT_STATUS( status, PSA_SUCCESS );
152
153 exit:
154 psa_cipher_abort( &operation );
155 return( status );
156 }
157
158 static psa_status_t
cipher_example_encrypt_decrypt_aes_cbc_nopad_1_block(void)159 cipher_example_encrypt_decrypt_aes_cbc_nopad_1_block( void )
160 {
161 enum {
162 block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH( PSA_KEY_TYPE_AES ),
163 key_bits = 256,
164 part_size = block_size,
165 };
166 const psa_algorithm_t alg = PSA_ALG_CBC_NO_PADDING;
167
168 psa_status_t status;
169 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
170 psa_key_id_t key = 0;
171 size_t output_len = 0;
172 uint8_t iv[block_size];
173 uint8_t input[block_size];
174 uint8_t encrypt[block_size];
175 uint8_t decrypt[block_size];
176
177 status = psa_generate_random( input, sizeof( input ) );
178 ASSERT_STATUS( status, PSA_SUCCESS );
179
180 psa_set_key_usage_flags( &attributes,
181 PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT );
182 psa_set_key_algorithm( &attributes, alg );
183 psa_set_key_type( &attributes, PSA_KEY_TYPE_AES );
184 psa_set_key_bits( &attributes, key_bits );
185
186 status = psa_generate_key( &attributes, &key );
187 ASSERT_STATUS( status, PSA_SUCCESS );
188
189 status = cipher_encrypt( key, alg, iv, sizeof( iv ),
190 input, sizeof( input ), part_size,
191 encrypt, sizeof( encrypt ), &output_len );
192 ASSERT_STATUS( status, PSA_SUCCESS );
193
194 status = cipher_decrypt( key, alg, iv, sizeof( iv ),
195 encrypt, output_len, part_size,
196 decrypt, sizeof( decrypt ), &output_len );
197 ASSERT_STATUS( status, PSA_SUCCESS );
198
199 status = memcmp( input, decrypt, sizeof( input ) );
200 ASSERT_STATUS( status, PSA_SUCCESS );
201
202 exit:
203 psa_destroy_key( key );
204 return( status );
205 }
206
cipher_example_encrypt_decrypt_aes_cbc_pkcs7_multi(void)207 static psa_status_t cipher_example_encrypt_decrypt_aes_cbc_pkcs7_multi( void )
208 {
209 enum {
210 block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH( PSA_KEY_TYPE_AES ),
211 key_bits = 256,
212 input_size = 100,
213 part_size = 10,
214 };
215
216 const psa_algorithm_t alg = PSA_ALG_CBC_PKCS7;
217
218 psa_status_t status;
219 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
220 psa_key_id_t key = 0;
221 size_t output_len = 0;
222 uint8_t iv[block_size], input[input_size],
223 encrypt[input_size + block_size], decrypt[input_size + block_size];
224
225 status = psa_generate_random( input, sizeof( input ) );
226 ASSERT_STATUS( status, PSA_SUCCESS );
227
228 psa_set_key_usage_flags( &attributes,
229 PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT );
230 psa_set_key_algorithm( &attributes, alg );
231 psa_set_key_type( &attributes, PSA_KEY_TYPE_AES );
232 psa_set_key_bits( &attributes, key_bits );
233
234 status = psa_generate_key( &attributes, &key );
235 ASSERT_STATUS( status, PSA_SUCCESS );
236
237 status = cipher_encrypt( key, alg, iv, sizeof( iv ),
238 input, sizeof( input ), part_size,
239 encrypt, sizeof( encrypt ), &output_len );
240 ASSERT_STATUS( status, PSA_SUCCESS );
241
242 status = cipher_decrypt( key, alg, iv, sizeof( iv ),
243 encrypt, output_len, part_size,
244 decrypt, sizeof( decrypt ), &output_len );
245 ASSERT_STATUS( status, PSA_SUCCESS );
246
247 status = memcmp( input, decrypt, sizeof( input ) );
248 ASSERT_STATUS( status, PSA_SUCCESS );
249
250 exit:
251 psa_destroy_key( key );
252 return( status );
253 }
254
cipher_example_encrypt_decrypt_aes_ctr_multi(void)255 static psa_status_t cipher_example_encrypt_decrypt_aes_ctr_multi( void )
256 {
257 enum {
258 block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH( PSA_KEY_TYPE_AES ),
259 key_bits = 256,
260 input_size = 100,
261 part_size = 10,
262 };
263 const psa_algorithm_t alg = PSA_ALG_CTR;
264
265 psa_status_t status;
266 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
267 psa_key_id_t key = 0;
268 size_t output_len = 0;
269 uint8_t iv[block_size], input[input_size], encrypt[input_size],
270 decrypt[input_size];
271
272 status = psa_generate_random( input, sizeof( input ) );
273 ASSERT_STATUS( status, PSA_SUCCESS );
274
275 psa_set_key_usage_flags( &attributes,
276 PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT );
277 psa_set_key_algorithm( &attributes, alg );
278 psa_set_key_type( &attributes, PSA_KEY_TYPE_AES );
279 psa_set_key_bits( &attributes, key_bits );
280
281 status = psa_generate_key( &attributes, &key );
282 ASSERT_STATUS( status, PSA_SUCCESS );
283
284 status = cipher_encrypt( key, alg, iv, sizeof( iv ),
285 input, sizeof( input ), part_size,
286 encrypt, sizeof( encrypt ), &output_len );
287 ASSERT_STATUS( status, PSA_SUCCESS );
288
289 status = cipher_decrypt( key, alg, iv, sizeof( iv ),
290 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
297 exit:
298 psa_destroy_key( key );
299 return( status );
300 }
301
cipher_examples(void)302 static void cipher_examples( void )
303 {
304 psa_status_t status;
305
306 printf( "cipher encrypt/decrypt AES CBC no padding:\r\n" );
307 status = cipher_example_encrypt_decrypt_aes_cbc_nopad_1_block( );
308 if( status == PSA_SUCCESS )
309 printf( "\tsuccess!\r\n" );
310
311 printf( "cipher encrypt/decrypt AES CBC PKCS7 multipart:\r\n" );
312 status = cipher_example_encrypt_decrypt_aes_cbc_pkcs7_multi( );
313 if( status == PSA_SUCCESS )
314 printf( "\tsuccess!\r\n" );
315
316 printf( "cipher encrypt/decrypt AES CTR multipart:\r\n" );
317 status = cipher_example_encrypt_decrypt_aes_ctr_multi( );
318 if( status == PSA_SUCCESS )
319 printf( "\tsuccess!\r\n" );
320 }
321
main(void)322 int main( void )
323 {
324 ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
325 cipher_examples( );
326 exit:
327 mbedtls_psa_crypto_free( );
328 return( 0 );
329 }
330 #endif /* MBEDTLS_PSA_CRYPTO_C && MBEDTLS_AES_C && MBEDTLS_CIPHER_MODE_CBC &&
331 MBEDTLS_CIPHER_MODE_CTR && MBEDTLS_CIPHER_MODE_WITH_PADDING */
332