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_SIZE( 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_SIZE( 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_SIZE( 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