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