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