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