1 /*
2  * Copyright (c) 2016-2017 Nordic Semiconductor ASA
3  * Copyright (c) 2016 Vinayak Kariappa Chettimada
4  * Copyright 2019-2020 NXP
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include <string.h>
10 
11 #include <zephyr/sys/byteorder.h>
12 
13 #include <zephyr/bluetooth/hci_types.h>
14 
15 #include "hal/ecb.h"
16 
17 #include <zephyr/logging/log.h>
18 
19 #include "hal/debug.h"
20 #include "fsl_cau3_ble.h"
21 
22 LOG_MODULE_REGISTER(bt_ctlr_rv32m1_ecb, LOG_LEVEL_DBG);
23 
ecb_encrypt_be(uint8_t const * const key_be,uint8_t const * const clear_text_be,uint8_t * const cipher_text_be)24 void ecb_encrypt_be(uint8_t const *const key_be, uint8_t const *const clear_text_be,
25 		    uint8_t *const cipher_text_be)
26 {
27 	uint8_t keyAes[16] __aligned(4);
28 	status_t status;
29 
30 	cau3_handle_t handle;
31 
32 	memcpy(&keyAes, key_be, sizeof(keyAes));
33 
34 	/* CAU3 driver supports 4 key slots. */
35 	handle.keySlot = kCAU3_KeySlot1;
36 
37 	/* After encrypt/decrypt req is sent to CAU3, the Host CPU will
38 	 * execute WFE() until CAU3 signals task done by setting the event.
39 	 */
40 	handle.taskDone = kCAU3_TaskDonePoll;
41 
42 	/* Loads the key into CAU3's DMEM and expands the AES key schedule */
43 	status = CAU3_AES_SetKey(CAU3, &handle, keyAes, sizeof(keyAes));
44 	if (status != kStatus_Success) {
45 		LOG_ERR("CAUv3 AES key set failed %d", status);
46 		return;
47 	}
48 
49 	status = CAU3_AES_Encrypt(CAU3, &handle, clear_text_be, cipher_text_be);
50 	if (status != kStatus_Success) {
51 		LOG_ERR("CAUv3 AES encrypt failed %d", status);
52 		return;
53 	}
54 }
55 
ecb_encrypt(uint8_t const * const key_le,uint8_t const * const clear_text_le,uint8_t * const cipher_text_le,uint8_t * const cipher_text_be)56 void ecb_encrypt(uint8_t const *const key_le, uint8_t const *const clear_text_le,
57 		 uint8_t *const cipher_text_le, uint8_t *const cipher_text_be)
58 {
59 	uint8_t keyAes[16] __aligned(4);
60 	uint8_t clear[16];
61 	uint8_t cipher[16];
62 	status_t status;
63 
64 	cau3_handle_t handle;
65 
66 	/* The security function e of the cryptographic toolbox in CAU as in STD
67 	 * The most significant octet of key corresponds to key[0], the most
68 	 * significant octet of plaintextData corresponds to in[0] and the most
69 	 * significant octet of encryptedData corresponds to out[0] using the
70 	 * notation specified in FIPS-197
71 	 * Thus, reverse the input parameters that are LSB to MSB format (le)
72 	 */
73 	sys_memcpy_swap(&keyAes, key_le, sizeof(keyAes));
74 	sys_memcpy_swap(&clear, clear_text_le, sizeof(clear));
75 
76 	/* CAU3 driver supports 4 key slots. */
77 	handle.keySlot = kCAU3_KeySlot1;
78 
79 	/* After encrypt/decrypt req is sent to CAU3, the Host CPU will
80 	 * execute WFE() until CAU3 signals task done by setting the event.
81 	 */
82 	handle.taskDone = kCAU3_TaskDonePoll;
83 
84 	/* Loads the key into CAU3's DMEM and expands the AES key schedule */
85 	status = CAU3_AES_SetKey(CAU3, &handle, keyAes, sizeof(keyAes));
86 	if (status != kStatus_Success) {
87 		LOG_ERR("CAUv3 AES key set failed %d", status);
88 		return;
89 	}
90 
91 	status = CAU3_AES_Encrypt(CAU3, &handle, clear, cipher);
92 	if (status != kStatus_Success) {
93 		LOG_ERR("CAUv3 AES encrypt failed %d", status);
94 		return;
95 	}
96 
97 	if (cipher_text_le) {
98 		/* STD e function outputs in MSB thus reverse for the (le) */
99 		sys_memcpy_swap(cipher_text_le, &cipher[0], sizeof(cipher));
100 	}
101 
102 	if (cipher_text_be) {
103 		memcpy(cipher_text_be, &cipher, sizeof(cipher));
104 	}
105 }
106 
ecb_encrypt_nonblocking(struct ecb * e)107 void ecb_encrypt_nonblocking(struct ecb *e)
108 {
109 	return;
110 }
111 
isr_ecb(void * param)112 void isr_ecb(void *param)
113 {
114 }
115 
116 /*
117  * Used by ULL as in this example:
118  * ltk[16] is copied from the HCI packet, preserving the LSO to MSO format
119  * skd[16] is copied from the PDU, preserving the LSO to MSO format
120  * calc the Session Key and retrieve the MSO to LSO format because that is how
121  * the PDU payload uses the encrypted data; MIC is also MSO to LSO.
122 	ecb_encrypt(&conn->llcp_enc.ltk[0],
123 		    &conn->llcp.encryption.skd[0], NULL,
124 		    &lll->ccm_rx.key[0]);
125  */
ecb_ut(void)126 int ecb_ut(void)
127 {
128 	/*
129 	 * LTK = 0x4C68384139F574D836BCF34E9DFB01BF (MSO to LSO)
130 	 * SKD = SKDm || SKDs
131 	 * SKD (LSO to MSO)
132 	 * :0x13:0x02:0xF1:0xE0:0xDF:0xCE:0xBD:0xAC
133 	 * :0x79:0x68:0x57:0x46:0x35:0x24:0x13:0x02
134 	 * SK = Encrypt(LTK, SKD)
135 	 * SK (LSO to MSO)
136 	 * :0x66:0xC6:0xC2:0x27:0x8E:0x3B:0x8E:0x05
137 	 * :0x3E:0x7E:0xA3:0x26:0x52:0x1B:0xAD:0x99
138 	 */
139 	static const uint8_t ltk_le[16] = {
140 		0xbf, 0x01, 0xfb, 0x9d, 0x4e, 0xf3, 0xbc, 0x36,
141 		0xd8, 0x74, 0xf5, 0x39, 0x41, 0x38, 0x68, 0x4c
142 	};
143 	static const uint8_t skd_le[16] = {
144 		0x13, 0x02, 0xF1, 0xE0, 0xDF, 0xCE, 0xBD, 0xAC,
145 		0x79, 0x68, 0x57, 0x46, 0x35, 0x24, 0x13, 0x02
146 	};
147 	uint8_t key_le[16] = {};
148 	uint8_t key_ref_le[16] = {
149 		0x66, 0xC6, 0xC2, 0x27, 0x8E, 0x3B, 0x8E, 0x05,
150 		0x3E, 0x7E, 0xA3, 0x26, 0x52, 0x1B, 0xAD, 0x99
151 	};
152 	uint32_t status = kStatus_Success;
153 	uint8_t *key;
154 
155 	/* calc the Session Key and compare vs the ref_le in LSO format */
156 	ecb_encrypt(ltk_le, skd_le, key = key_le, NULL);
157 
158 	if (memcmp(key_ref_le, key, 16)) {
159 		printk("Failed session key unit test\n");
160 		status = kStatus_Fail;
161 	}
162 
163 	printk("Session key: %02x %02x %02x %02x %02x %02x %02x %02x "
164 			"%02x %02x %02x %02x %02x %02x %02x %02x\n",
165 			key[0], key[1], key[2], key[3],
166 			key[4], key[5], key[6], key[7],
167 			key[8], key[9], key[10], key[11],
168 			key[12], key[13], key[14], key[15]);
169 
170 	return status;
171 }
172