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