1 /*
2 * Copyright (c) 2016 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /* Sample to illustrate the usage of crypto APIs. The sample plaintext
8 * and ciphertexts used for crosschecking are from TinyCrypt.
9 */
10
11 #include <zephyr/device.h>
12 #include <zephyr/kernel.h>
13 #include <string.h>
14 #include <zephyr/crypto/crypto.h>
15
16 #define LOG_LEVEL CONFIG_CRYPTO_LOG_LEVEL
17 #include <zephyr/logging/log.h>
18 LOG_MODULE_REGISTER(main);
19
20 #ifdef CONFIG_CRYPTO_TINYCRYPT_SHIM
21 #define CRYPTO_DRV_NAME CONFIG_CRYPTO_TINYCRYPT_SHIM_DRV_NAME
22 #elif CONFIG_CRYPTO_MBEDTLS_SHIM
23 #define CRYPTO_DRV_NAME CONFIG_CRYPTO_MBEDTLS_SHIM_DRV_NAME
24 #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_cryp)
25 #define CRYPTO_DEV_COMPAT st_stm32_cryp
26 #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_aes)
27 #define CRYPTO_DEV_COMPAT st_stm32_aes
28 #elif DT_HAS_COMPAT_STATUS_OKAY(nxp_mcux_dcp)
29 #define CRYPTO_DEV_COMPAT nxp_mcux_dcp
30 #elif CONFIG_CRYPTO_NRF_ECB
31 #define CRYPTO_DEV_COMPAT nordic_nrf_ecb
32 #elif DT_HAS_COMPAT_STATUS_OKAY(renesas_smartbond_crypto)
33 #define CRYPTO_DEV_COMPAT renesas_smartbond_crypto
34 #elif DT_HAS_COMPAT_STATUS_OKAY(ti_cc23x0_aes)
35 #define CRYPTO_DEV_COMPAT ti_cc23x0_aes
36 #elif CONFIG_CRYPTO_SI32
37 #define CRYPTO_DEV_COMPAT silabs_si32_aes
38 #else
39 #error "You need to enable one crypto device"
40 #endif
41
42 /* Some crypto drivers require IO buffers to be aligned, i.e. due to underlying DMA requirements. */
43 #define IO_ALIGNMENT_BYTES 4
44
45 const static uint8_t key[16]
46 __aligned(IO_ALIGNMENT_BYTES) = {0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
47 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c};
48
49 static uint8_t plaintext[64] __aligned(IO_ALIGNMENT_BYTES) = {
50 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73,
51 0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7,
52 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4,
53 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, 0xf6, 0x9f, 0x24, 0x45,
54 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10};
55
56 uint32_t cap_flags;
57
print_buffer_comparison(const uint8_t * wanted_result,uint8_t * result,size_t length)58 static void print_buffer_comparison(const uint8_t *wanted_result,
59 uint8_t *result, size_t length)
60 {
61 int i, j;
62
63 printk("Was waiting for: \n");
64
65 for (i = 0, j = 1; i < length; i++, j++) {
66 printk("0x%02x ", wanted_result[i]);
67
68 if (j == 10) {
69 printk("\n");
70 j = 0;
71 }
72 }
73
74 printk("\nBut got:\n");
75
76 for (i = 0, j = 1; i < length; i++, j++) {
77 printk("0x%02x ", result[i]);
78
79 if (j == 10) {
80 printk("\n");
81 j = 0;
82 }
83 }
84
85 printk("\n");
86 }
87
validate_hw_compatibility(const struct device * dev)88 int validate_hw_compatibility(const struct device *dev)
89 {
90 uint32_t flags = 0U;
91
92 flags = crypto_query_hwcaps(dev);
93 if ((flags & CAP_RAW_KEY) == 0U) {
94 LOG_INF("Please provision the key separately "
95 "as the module doesnt support a raw key");
96 return -1;
97 }
98
99 if ((flags & CAP_SYNC_OPS) == 0U) {
100 LOG_ERR("The app assumes sync semantics. "
101 "Please rewrite the app accordingly before proceeding");
102 return -1;
103 }
104
105 if ((flags & CAP_SEPARATE_IO_BUFS) == 0U) {
106 LOG_ERR("The app assumes distinct IO buffers. "
107 "Please rewrite the app accordingly before proceeding");
108 return -1;
109 }
110
111 cap_flags = CAP_RAW_KEY | CAP_SYNC_OPS | CAP_SEPARATE_IO_BUFS;
112
113 return 0;
114
115 }
116
ecb_mode(const struct device * dev)117 void ecb_mode(const struct device *dev)
118 {
119 /* from FIPS-197 test vectors */
120 const uint8_t ecb_key[16] = {
121 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
122 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
123 };
124 uint8_t ecb_plaintext[16]
125 __aligned(IO_ALIGNMENT_BYTES) = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
126 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
127 uint8_t ecb_ciphertext[16]
128 __aligned(IO_ALIGNMENT_BYTES) = {0x69, 0xC4, 0xE0, 0xD8, 0x6A, 0x7B, 0x04, 0x30,
129 0xD8, 0xCD, 0xB7, 0x80, 0x70, 0xB4, 0xC5, 0x5A};
130
131 uint8_t encrypted[16] __aligned(IO_ALIGNMENT_BYTES) = {0};
132 uint8_t decrypted[16] __aligned(IO_ALIGNMENT_BYTES) = {0};
133 struct cipher_ctx ini = {
134 .keylen = sizeof(ecb_key),
135 .key.bit_stream = ecb_key,
136 .flags = cap_flags,
137 };
138 struct cipher_pkt encrypt = {
139 .in_buf = ecb_plaintext,
140 .in_len = sizeof(ecb_plaintext),
141 .out_buf_max = sizeof(encrypted),
142 .out_buf = encrypted,
143 };
144 struct cipher_pkt decrypt = {
145 .in_buf = encrypt.out_buf,
146 .in_len = sizeof(encrypted),
147 .out_buf = decrypted,
148 .out_buf_max = sizeof(decrypted),
149 };
150
151 if (cipher_begin_session(dev, &ini, CRYPTO_CIPHER_ALGO_AES,
152 CRYPTO_CIPHER_MODE_ECB,
153 CRYPTO_CIPHER_OP_ENCRYPT)) {
154 return;
155 }
156
157 if (cipher_block_op(&ini, &encrypt)) {
158 LOG_ERR("ECB mode ENCRYPT - Failed");
159 goto out;
160 }
161
162 LOG_INF("Output length (encryption): %d", encrypt.out_len);
163
164 if (memcmp(encrypt.out_buf, ecb_ciphertext, sizeof(ecb_ciphertext))) {
165 LOG_ERR("ECB mode ENCRYPT - Mismatch between expected and "
166 "returned cipher text");
167 print_buffer_comparison(ecb_ciphertext, encrypt.out_buf,
168 sizeof(ecb_ciphertext));
169 goto out;
170 }
171
172 LOG_INF("ECB mode ENCRYPT - Match");
173 cipher_free_session(dev, &ini);
174
175 if (cipher_begin_session(dev, &ini, CRYPTO_CIPHER_ALGO_AES,
176 CRYPTO_CIPHER_MODE_ECB,
177 CRYPTO_CIPHER_OP_DECRYPT)) {
178 return;
179 }
180
181 if (cipher_block_op(&ini, &decrypt)) {
182 LOG_ERR("ECB mode DECRYPT - Failed");
183 goto out;
184 }
185
186 LOG_INF("Output length (decryption): %d", decrypt.out_len);
187
188 if (memcmp(decrypt.out_buf, ecb_plaintext, sizeof(ecb_plaintext))) {
189 LOG_ERR("ECB mode DECRYPT - Mismatch between plaintext and "
190 "decrypted cipher text");
191 print_buffer_comparison(ecb_plaintext, decrypt.out_buf,
192 sizeof(ecb_plaintext));
193 goto out;
194 }
195
196 LOG_INF("ECB mode DECRYPT - Match");
197 out:
198 cipher_free_session(dev, &ini);
199 }
200
201 static const uint8_t cbc_ciphertext[80] = {
202 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
203 0x0c, 0x0d, 0x0e, 0x0f, 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46,
204 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d, 0x50, 0x86, 0xcb, 0x9b,
205 0x50, 0x72, 0x19, 0xee, 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2,
206 0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, 0x71, 0x16, 0xe6, 0x9e,
207 0x22, 0x22, 0x95, 0x16, 0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09,
208 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7
209 };
210
cbc_mode(const struct device * dev)211 void cbc_mode(const struct device *dev)
212 {
213 uint8_t encrypted[80] __aligned(IO_ALIGNMENT_BYTES) = {0};
214 uint8_t decrypted[64] __aligned(IO_ALIGNMENT_BYTES) = {0};
215 struct cipher_ctx ini = {
216 .keylen = sizeof(key),
217 .key.bit_stream = key,
218 .flags = cap_flags,
219 };
220 struct cipher_pkt encrypt = {
221 .in_buf = plaintext,
222 .in_len = sizeof(plaintext),
223 .out_buf_max = sizeof(encrypted),
224 .out_buf = encrypted,
225 };
226 struct cipher_pkt decrypt = {
227 .in_buf = encrypt.out_buf,
228 .in_len = sizeof(encrypted),
229 .out_buf = decrypted,
230 .out_buf_max = sizeof(decrypted),
231 };
232
233 static uint8_t iv[16] = {
234 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
235 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
236 };
237
238 if (cipher_begin_session(dev, &ini, CRYPTO_CIPHER_ALGO_AES,
239 CRYPTO_CIPHER_MODE_CBC,
240 CRYPTO_CIPHER_OP_ENCRYPT)) {
241 return;
242 }
243
244 if (cipher_cbc_op(&ini, &encrypt, iv)) {
245 LOG_ERR("CBC mode ENCRYPT - Failed");
246 goto out;
247 }
248
249 LOG_INF("Output length (encryption): %d", encrypt.out_len);
250
251 if (memcmp(encrypt.out_buf, cbc_ciphertext, sizeof(cbc_ciphertext))) {
252 LOG_ERR("CBC mode ENCRYPT - Mismatch between expected and "
253 "returned cipher text");
254 print_buffer_comparison(cbc_ciphertext, encrypt.out_buf,
255 sizeof(cbc_ciphertext));
256 goto out;
257 }
258
259 LOG_INF("CBC mode ENCRYPT - Match");
260 cipher_free_session(dev, &ini);
261
262 if (cipher_begin_session(dev, &ini, CRYPTO_CIPHER_ALGO_AES,
263 CRYPTO_CIPHER_MODE_CBC,
264 CRYPTO_CIPHER_OP_DECRYPT)) {
265 return;
266 }
267
268 /* TinyCrypt keeps IV at the start of encrypted buffer */
269 if (cipher_cbc_op(&ini, &decrypt, encrypted)) {
270 LOG_ERR("CBC mode DECRYPT - Failed");
271 goto out;
272 }
273
274 LOG_INF("Output length (decryption): %d", decrypt.out_len);
275
276 if (memcmp(decrypt.out_buf, plaintext, sizeof(plaintext))) {
277 LOG_ERR("CBC mode DECRYPT - Mismatch between plaintext and "
278 "decrypted cipher text");
279 print_buffer_comparison(plaintext, decrypt.out_buf,
280 sizeof(plaintext));
281 goto out;
282 }
283
284 LOG_INF("CBC mode DECRYPT - Match");
285 out:
286 cipher_free_session(dev, &ini);
287 }
288
289 static const uint8_t ctr_ciphertext[64] = {
290 0x22, 0xe5, 0x2f, 0xb1, 0x77, 0xd8, 0x65, 0xb2,
291 0xf7, 0xc6, 0xb5, 0x12, 0x69, 0x2d, 0x11, 0x4d,
292 0xed, 0x6c, 0x1c, 0x72, 0x25, 0xda, 0xf6, 0xa2,
293 0xaa, 0xd9, 0xd3, 0xda, 0x2d, 0xba, 0x21, 0x68,
294 0x35, 0xc0, 0xaf, 0x6b, 0x6f, 0x40, 0xc3, 0xc6,
295 0xef, 0xc5, 0x85, 0xd0, 0x90, 0x2c, 0xc2, 0x63,
296 0x12, 0x2b, 0xc5, 0x8e, 0x72, 0xde, 0x5c, 0xa2,
297 0xa3, 0x5c, 0x85, 0x3a, 0xb9, 0x2c, 0x6, 0xbb
298 };
299
ctr_mode(const struct device * dev)300 void ctr_mode(const struct device *dev)
301 {
302 uint8_t encrypted[64] __aligned(IO_ALIGNMENT_BYTES) = {0};
303 uint8_t decrypted[64] __aligned(IO_ALIGNMENT_BYTES) = {0};
304 struct cipher_ctx ini = {
305 .keylen = sizeof(key),
306 .key.bit_stream = key,
307 .flags = cap_flags,
308 /* ivlen + ctrlen = keylen , so ctrlen is 128 - 96 = 32 bits */
309 .mode_params.ctr_info.ctr_len = 32,
310 };
311 struct cipher_pkt encrypt = {
312 .in_buf = plaintext,
313 .in_len = sizeof(plaintext),
314 .out_buf_max = sizeof(encrypted),
315 .out_buf = encrypted,
316 };
317 struct cipher_pkt decrypt = {
318 .in_buf = encrypted,
319 .in_len = sizeof(encrypted),
320 .out_buf = decrypted,
321 .out_buf_max = sizeof(decrypted),
322 };
323 uint8_t iv[12] = {
324 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
325 0xf8, 0xf9, 0xfa, 0xfb
326 };
327
328 if (cipher_begin_session(dev, &ini, CRYPTO_CIPHER_ALGO_AES,
329 CRYPTO_CIPHER_MODE_CTR,
330 CRYPTO_CIPHER_OP_ENCRYPT)) {
331 return;
332 }
333
334 if (cipher_ctr_op(&ini, &encrypt, iv)) {
335 LOG_ERR("CTR mode ENCRYPT - Failed");
336 goto out;
337 }
338
339 LOG_INF("Output length (encryption): %d", encrypt.out_len);
340
341 if (memcmp(encrypt.out_buf, ctr_ciphertext, sizeof(ctr_ciphertext))) {
342 LOG_ERR("CTR mode ENCRYPT - Mismatch between expected "
343 "and returned cipher text");
344 print_buffer_comparison(ctr_ciphertext, encrypt.out_buf,
345 sizeof(ctr_ciphertext));
346 goto out;
347 }
348
349 LOG_INF("CTR mode ENCRYPT - Match");
350 cipher_free_session(dev, &ini);
351
352 if (cipher_begin_session(dev, &ini, CRYPTO_CIPHER_ALGO_AES,
353 CRYPTO_CIPHER_MODE_CTR,
354 CRYPTO_CIPHER_OP_DECRYPT)) {
355 return;
356 }
357
358 if (cipher_ctr_op(&ini, &decrypt, iv)) {
359 LOG_ERR("CTR mode DECRYPT - Failed");
360 goto out;
361 }
362
363 LOG_INF("Output length (decryption): %d", decrypt.out_len);
364
365 if (memcmp(decrypt.out_buf, plaintext, sizeof(plaintext))) {
366 LOG_ERR("CTR mode DECRYPT - Mismatch between plaintext "
367 "and decrypted cipher text");
368 print_buffer_comparison(plaintext,
369 decrypt.out_buf, sizeof(plaintext));
370 goto out;
371 }
372
373 LOG_INF("CTR mode DECRYPT - Match");
374 out:
375 cipher_free_session(dev, &ini);
376 }
377
378 /* RFC 3610 test vector #1 */
379 const static uint8_t ccm_key[16] = {
380 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb,
381 0xcc, 0xcd, 0xce, 0xcf
382 };
383 static uint8_t ccm_nonce[13] = {
384 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4,
385 0xa5
386 };
387 static uint8_t ccm_hdr[8] = {
388 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
389 };
390 static uint8_t ccm_data[23] __aligned(IO_ALIGNMENT_BYTES) = {
391 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
392 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e};
393 static const uint8_t ccm_expected[31] = {0x58, 0x8c, 0x97, 0x9a, 0x61, 0xc6, 0x63, 0xd2,
394 0xf0, 0x66, 0xd0, 0xc2, 0xc0, 0xf9, 0x89, 0x80,
395 0x6d, 0x5f, 0x6b, 0x61, 0xda, 0xc3, 0x84, 0x17,
396 0xe8, 0xd1, 0x2c, 0xfd, 0xf9, 0x26, 0xe0};
397
ccm_mode(const struct device * dev)398 void ccm_mode(const struct device *dev)
399 {
400 uint8_t encrypted[50] __aligned(IO_ALIGNMENT_BYTES);
401 uint8_t decrypted[32] __aligned(IO_ALIGNMENT_BYTES);
402 struct cipher_ctx ini = {
403 .keylen = sizeof(ccm_key),
404 .key.bit_stream = ccm_key,
405 .mode_params.ccm_info = {
406 .nonce_len = sizeof(ccm_nonce),
407 .tag_len = 8,
408 },
409 .flags = cap_flags,
410 };
411 struct cipher_pkt encrypt = {
412 .in_buf = ccm_data,
413 .in_len = sizeof(ccm_data),
414 .out_buf_max = sizeof(encrypted),
415 .out_buf = encrypted,
416 };
417 struct cipher_aead_pkt ccm_op = {
418 .ad = ccm_hdr,
419 .ad_len = sizeof(ccm_hdr),
420 .pkt = &encrypt,
421 /* TinyCrypt always puts the tag at the end of the ciphered
422 * text, but other library such as mbedtls might be more
423 * flexible and can take a different buffer for it. So to
424 * make sure test passes on all backends: enforcing the tag
425 * buffer to be after the ciphered text.
426 */
427 .tag = encrypted + sizeof(ccm_data),
428 };
429 struct cipher_pkt decrypt = {
430 .in_buf = encrypted,
431 .in_len = sizeof(ccm_data),
432 .out_buf = decrypted,
433 .out_buf_max = sizeof(decrypted),
434 };
435
436 if (cipher_begin_session(dev, &ini, CRYPTO_CIPHER_ALGO_AES,
437 CRYPTO_CIPHER_MODE_CCM,
438 CRYPTO_CIPHER_OP_ENCRYPT)) {
439 return;
440 }
441
442 ccm_op.pkt = &encrypt;
443 if (cipher_ccm_op(&ini, &ccm_op, ccm_nonce)) {
444 LOG_ERR("CCM mode ENCRYPT - Failed");
445 goto out;
446 }
447
448 LOG_INF("Output length (encryption): %d", encrypt.out_len);
449
450 if (memcmp(encrypt.out_buf, ccm_expected, sizeof(ccm_expected))) {
451 LOG_ERR("CCM mode ENCRYPT - Mismatch between expected "
452 "and returned cipher text");
453 print_buffer_comparison(ccm_expected,
454 encrypt.out_buf, sizeof(ccm_expected));
455 goto out;
456 }
457
458 LOG_INF("CCM mode ENCRYPT - Match");
459 cipher_free_session(dev, &ini);
460
461 if (cipher_begin_session(dev, &ini, CRYPTO_CIPHER_ALGO_AES,
462 CRYPTO_CIPHER_MODE_CCM,
463 CRYPTO_CIPHER_OP_DECRYPT)) {
464 return;
465 }
466
467 ccm_op.pkt = &decrypt;
468 if (cipher_ccm_op(&ini, &ccm_op, ccm_nonce)) {
469 LOG_ERR("CCM mode DECRYPT - Failed");
470 goto out;
471 }
472
473 LOG_INF("Output length (decryption): %d", decrypt.out_len);
474
475 if (memcmp(decrypt.out_buf, ccm_data, sizeof(ccm_data))) {
476 LOG_ERR("CCM mode DECRYPT - Mismatch between plaintext "
477 "and decrypted cipher text");
478 print_buffer_comparison(ccm_data,
479 decrypt.out_buf, sizeof(ccm_data));
480 goto out;
481 }
482
483 LOG_INF("CCM mode DECRYPT - Match");
484 out:
485 cipher_free_session(dev, &ini);
486 }
487
488 /* MACsec GCM-AES test vector 2.4.1 */
489 const static uint8_t gcm_key[16] = {
490 0x07, 0x1b, 0x11, 0x3b, 0x0c, 0xa7, 0x43, 0xfe, 0xcc, 0xcf, 0x3d, 0x05,
491 0x1f, 0x73, 0x73, 0x82
492 };
493 static uint8_t gcm_nonce[12] = {
494 0xf0, 0x76, 0x1e, 0x8d, 0xcd, 0x3d, 0x00, 0x01, 0x76, 0xd4, 0x57, 0xed
495 };
496 static uint8_t gcm_hdr[20] = {
497 0xe2, 0x01, 0x06, 0xd7, 0xcd, 0x0d, 0xf0, 0x76, 0x1e, 0x8d, 0xcd, 0x3d,
498 0x88, 0xe5, 0x4c, 0x2a, 0x76, 0xd4, 0x57, 0xed
499 };
500 static uint8_t gcm_data[42] __aligned(IO_ALIGNMENT_BYTES) = {
501 0x08, 0x00, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
502 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
503 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x00, 0x04};
504 static const uint8_t gcm_expected[58] = {
505 0x13, 0xb4, 0xc7, 0x2b, 0x38, 0x9d, 0xc5, 0x01, 0x8e, 0x72, 0xa1, 0x71, 0xdd, 0x85, 0xa5,
506 0xd3, 0x75, 0x22, 0x74, 0xd3, 0xa0, 0x19, 0xfb, 0xca, 0xed, 0x09, 0xa4, 0x25, 0xcd, 0x9b,
507 0x2e, 0x1c, 0x9b, 0x72, 0xee, 0xe7, 0xc9, 0xde, 0x7d, 0x52, 0xb3, 0xf3, 0xd6, 0xa5, 0x28,
508 0x4f, 0x4a, 0x6d, 0x3f, 0xe2, 0x2a, 0x5d, 0x6c, 0x2b, 0x96, 0x04, 0x94, 0xc3};
509
gcm_mode(const struct device * dev)510 void gcm_mode(const struct device *dev)
511 {
512 uint8_t encrypted[60] __aligned(IO_ALIGNMENT_BYTES) = {0};
513 uint8_t decrypted[44] __aligned(IO_ALIGNMENT_BYTES) = {0};
514 struct cipher_ctx ini = {
515 .keylen = sizeof(gcm_key),
516 .key.bit_stream = gcm_key,
517 .mode_params.gcm_info = {
518 .nonce_len = sizeof(gcm_nonce),
519 .tag_len = 16,
520 },
521 .flags = cap_flags,
522 };
523 struct cipher_pkt encrypt = {
524 .in_buf = gcm_data,
525 .in_len = sizeof(gcm_data),
526 .out_buf_max = sizeof(encrypted),
527 .out_buf = encrypted,
528 };
529 struct cipher_aead_pkt gcm_op = {
530 .ad = gcm_hdr,
531 .ad_len = sizeof(gcm_hdr),
532 .pkt = &encrypt,
533 /* TinyCrypt always puts the tag at the end of the ciphered
534 * text, but other library such as mbedtls might be more
535 * flexible and can take a different buffer for it. So to
536 * make sure test passes on all backends: enforcing the tag
537 * buffer to be after the ciphered text.
538 */
539 .tag = encrypted + sizeof(gcm_data),
540 };
541 struct cipher_pkt decrypt = {
542 .in_buf = encrypted,
543 .in_len = sizeof(gcm_data),
544 .out_buf = decrypted,
545 .out_buf_max = sizeof(decrypted),
546 };
547
548 if (cipher_begin_session(dev, &ini, CRYPTO_CIPHER_ALGO_AES,
549 CRYPTO_CIPHER_MODE_GCM,
550 CRYPTO_CIPHER_OP_ENCRYPT)) {
551 return;
552 }
553
554 gcm_op.pkt = &encrypt;
555 if (cipher_gcm_op(&ini, &gcm_op, gcm_nonce)) {
556 LOG_ERR("GCM mode ENCRYPT - Failed");
557 goto out;
558 }
559
560 LOG_INF("Output length (encryption): %d", encrypt.out_len);
561
562 if (memcmp(encrypt.out_buf, gcm_expected, sizeof(gcm_expected))) {
563 LOG_ERR("GCM mode ENCRYPT - Mismatch between expected "
564 "and returned cipher text");
565 print_buffer_comparison(gcm_expected,
566 encrypt.out_buf, sizeof(gcm_expected));
567 goto out;
568 }
569
570 LOG_INF("GCM mode ENCRYPT - Match");
571 cipher_free_session(dev, &ini);
572
573 if (cipher_begin_session(dev, &ini, CRYPTO_CIPHER_ALGO_AES,
574 CRYPTO_CIPHER_MODE_GCM,
575 CRYPTO_CIPHER_OP_DECRYPT)) {
576 return;
577 }
578
579 gcm_op.pkt = &decrypt;
580 if (cipher_gcm_op(&ini, &gcm_op, gcm_nonce)) {
581 LOG_ERR("GCM mode DECRYPT - Failed");
582 goto out;
583 }
584
585 LOG_INF("Output length (decryption): %d", decrypt.out_len);
586
587 if (memcmp(decrypt.out_buf, gcm_data, sizeof(gcm_data))) {
588 LOG_ERR("GCM mode DECRYPT - Mismatch between plaintext "
589 "and decrypted cipher text");
590 print_buffer_comparison(gcm_data,
591 decrypt.out_buf, sizeof(gcm_data));
592 goto out;
593 }
594
595 LOG_INF("GCM mode DECRYPT - Match");
596 out:
597 cipher_free_session(dev, &ini);
598 }
599
600 struct mode_test {
601 const char *mode;
602 void (*mode_func)(const struct device *dev);
603 };
604
main(void)605 int main(void)
606 {
607 #ifdef CRYPTO_DRV_NAME
608 const struct device *dev = device_get_binding(CRYPTO_DRV_NAME);
609
610 if (!dev) {
611 LOG_ERR("%s pseudo device not found", CRYPTO_DRV_NAME);
612 return 0;
613 }
614 #else
615 const struct device *const dev = DEVICE_DT_GET_ONE(CRYPTO_DEV_COMPAT);
616
617 if (!device_is_ready(dev)) {
618 LOG_ERR("Crypto device is not ready\n");
619 return 0;
620 }
621 #endif
622 const struct mode_test modes[] = {
623 { .mode = "ECB Mode", .mode_func = ecb_mode },
624 { .mode = "CBC Mode", .mode_func = cbc_mode },
625 { .mode = "CTR Mode", .mode_func = ctr_mode },
626 { .mode = "CCM Mode", .mode_func = ccm_mode },
627 { .mode = "GCM Mode", .mode_func = gcm_mode },
628 { },
629 };
630 int i;
631
632 if (validate_hw_compatibility(dev)) {
633 LOG_ERR("Incompatible h/w");
634 return 0;
635 }
636
637 LOG_INF("Cipher Sample");
638
639 for (i = 0; modes[i].mode; i++) {
640 LOG_INF("%s", modes[i].mode);
641 modes[i].mode_func(dev);
642 }
643 return 0;
644 }
645