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