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