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