1 /******************************************************************************
2 *
3 * Copyright 2008-2012 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 /******************************************************************************
20 *
21 * This file contains the implementation of the AES128 CMAC algorithm.
22 *
23 ******************************************************************************/
24
25 #include "bt_target.h"
26
27 #include <stdio.h>
28 #include <string.h>
29
30 #include "btm_ble_api.h"
31 #include "hcimsgs.h"
32 #include "smp_int.h"
33
34 typedef struct {
35 uint8_t* text;
36 uint16_t len;
37 uint16_t round;
38 } tCMAC_CB;
39
40 tCMAC_CB cmac_cb;
41
42 /* Rb for AES-128 as block cipher, LSB as [0] */
43 BT_OCTET16 const_Rb = {0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
44 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
45
print128(BT_OCTET16 x,const uint8_t * key_name)46 void print128(BT_OCTET16 x, const uint8_t* key_name) {
47 #if (SMP_DEBUG == TRUE && SMP_DEBUG_VERBOSE == TRUE)
48 uint8_t* p = (uint8_t*)x;
49 uint8_t i;
50
51 SMP_TRACE_WARNING("%s(MSB ~ LSB) = ", key_name);
52
53 for (i = 0; i < 4; i++) {
54 SMP_TRACE_WARNING("%02x %02x %02x %02x", p[BT_OCTET16_LEN - i * 4 - 1],
55 p[BT_OCTET16_LEN - i * 4 - 2],
56 p[BT_OCTET16_LEN - i * 4 - 3],
57 p[BT_OCTET16_LEN - i * 4 - 4]);
58 }
59 #endif
60 }
61
62 /*******************************************************************************
63 *
64 * Function padding
65 *
66 * Description utility function to padding the given text to be a 128 bits
67 * data. The parameter dest is input and output parameter, it
68 * must point to a BT_OCTET16_LEN memory space; where include
69 * length bytes valid data.
70 *
71 * Returns void
72 *
73 ******************************************************************************/
padding(BT_OCTET16 dest,uint8_t length)74 static void padding(BT_OCTET16 dest, uint8_t length) {
75 uint8_t i, *p = dest;
76 /* original last block */
77 for (i = length; i < BT_OCTET16_LEN; i++)
78 p[BT_OCTET16_LEN - i - 1] = (i == length) ? 0x80 : 0;
79 }
80 /*******************************************************************************
81 *
82 * Function leftshift_onebit
83 *
84 * Description utility function to left shift one bit for a 128 bits value.
85 *
86 * Returns void
87 *
88 ******************************************************************************/
leftshift_onebit(uint8_t * input,uint8_t * output)89 static void leftshift_onebit(uint8_t* input, uint8_t* output) {
90 uint8_t i, overflow = 0, next_overflow = 0;
91 SMP_TRACE_EVENT("leftshift_onebit ");
92 /* input[0] is LSB */
93 for (i = 0; i < BT_OCTET16_LEN; i++) {
94 next_overflow = (input[i] & 0x80) ? 1 : 0;
95 output[i] = (input[i] << 1) | overflow;
96 overflow = next_overflow;
97 }
98 return;
99 }
100 /*******************************************************************************
101 *
102 * Function cmac_aes_cleanup
103 *
104 * Description clean up function for AES_CMAC algorithm.
105 *
106 * Returns void
107 *
108 ******************************************************************************/
cmac_aes_cleanup(void)109 static void cmac_aes_cleanup(void) {
110 osi_free(cmac_cb.text);
111 memset(&cmac_cb, 0, sizeof(tCMAC_CB));
112 }
113
114 /*******************************************************************************
115 *
116 * Function cmac_aes_k_calculate
117 *
118 * Description This function is the calculation of block cipher using
119 * AES-128.
120 *
121 * Returns void
122 *
123 ******************************************************************************/
cmac_aes_k_calculate(BT_OCTET16 key,uint8_t * p_signature,uint16_t tlen)124 static bool cmac_aes_k_calculate(BT_OCTET16 key, uint8_t* p_signature,
125 uint16_t tlen) {
126 tSMP_ENC output;
127 uint8_t i = 1, err = 0;
128 uint8_t x[16] = {0};
129 uint8_t* p_mac;
130
131 SMP_TRACE_EVENT("cmac_aes_k_calculate ");
132
133 while (i <= cmac_cb.round) {
134 smp_xor_128(&cmac_cb.text[(cmac_cb.round - i) * BT_OCTET16_LEN],
135 x); /* Mi' := Mi (+) X */
136
137 if (!SMP_Encrypt(key, BT_OCTET16_LEN,
138 &cmac_cb.text[(cmac_cb.round - i) * BT_OCTET16_LEN],
139 BT_OCTET16_LEN, &output)) {
140 err = 1;
141 break;
142 }
143
144 memcpy(x, output.param_buf, BT_OCTET16_LEN);
145 i++;
146 }
147
148 if (!err) {
149 p_mac = output.param_buf + (BT_OCTET16_LEN - tlen);
150 memcpy(p_signature, p_mac, tlen);
151
152 SMP_TRACE_DEBUG("tlen = %d p_mac = %d", tlen, p_mac);
153 SMP_TRACE_DEBUG(
154 "p_mac[0] = 0x%02x p_mac[1] = 0x%02x p_mac[2] = 0x%02x p_mac[3] = "
155 "0x%02x",
156 *p_mac, *(p_mac + 1), *(p_mac + 2), *(p_mac + 3));
157 SMP_TRACE_DEBUG(
158 "p_mac[4] = 0x%02x p_mac[5] = 0x%02x p_mac[6] = 0x%02x p_mac[7] = "
159 "0x%02x",
160 *(p_mac + 4), *(p_mac + 5), *(p_mac + 6), *(p_mac + 7));
161
162 return true;
163
164 } else
165 return false;
166 }
167 /*******************************************************************************
168 *
169 * Function cmac_prepare_last_block
170 *
171 * Description This function proceeed to prepare the last block of message
172 * Mn depending on the size of the message.
173 *
174 * Returns void
175 *
176 ******************************************************************************/
cmac_prepare_last_block(BT_OCTET16 k1,BT_OCTET16 k2)177 static void cmac_prepare_last_block(BT_OCTET16 k1, BT_OCTET16 k2) {
178 // uint8_t x[16] = {0};
179 bool flag;
180
181 SMP_TRACE_EVENT("cmac_prepare_last_block ");
182 /* last block is a complete block set flag to 1 */
183 flag =
184 ((cmac_cb.len % BT_OCTET16_LEN) == 0 && cmac_cb.len != 0) ? true : false;
185
186 SMP_TRACE_WARNING("flag = %d round = %d", flag, cmac_cb.round);
187
188 if (flag) { /* last block is complete block */
189 smp_xor_128(&cmac_cb.text[0], k1);
190 } else /* padding then xor with k2 */
191 {
192 padding(&cmac_cb.text[0], (uint8_t)(cmac_cb.len % 16));
193
194 smp_xor_128(&cmac_cb.text[0], k2);
195 }
196 }
197 /*******************************************************************************
198 *
199 * Function cmac_subkey_cont
200 *
201 * Description This is the callback function when CIPHk(0[128]) is
202 * completed.
203 *
204 * Returns void
205 *
206 ******************************************************************************/
cmac_subkey_cont(tSMP_ENC * p)207 static void cmac_subkey_cont(tSMP_ENC* p) {
208 uint8_t k1[BT_OCTET16_LEN], k2[BT_OCTET16_LEN];
209 uint8_t* pp = p->param_buf;
210 SMP_TRACE_EVENT("cmac_subkey_cont ");
211 print128(pp, (const uint8_t*)"K1 before shift");
212
213 /* If MSB(L) = 0, then K1 = L << 1 */
214 if ((pp[BT_OCTET16_LEN - 1] & 0x80) != 0) {
215 /* Else K1 = ( L << 1 ) (+) Rb */
216 leftshift_onebit(pp, k1);
217 smp_xor_128(k1, const_Rb);
218 } else {
219 leftshift_onebit(pp, k1);
220 }
221
222 if ((k1[BT_OCTET16_LEN - 1] & 0x80) != 0) {
223 /* K2 = (K1 << 1) (+) Rb */
224 leftshift_onebit(k1, k2);
225 smp_xor_128(k2, const_Rb);
226 } else {
227 /* If MSB(K1) = 0, then K2 = K1 << 1 */
228 leftshift_onebit(k1, k2);
229 }
230
231 print128(k1, (const uint8_t*)"K1");
232 print128(k2, (const uint8_t*)"K2");
233
234 cmac_prepare_last_block(k1, k2);
235 }
236 /*******************************************************************************
237 *
238 * Function cmac_generate_subkey
239 *
240 * Description This is the function to generate the two subkeys.
241 *
242 * Parameters key - CMAC key, expect SRK when used by SMP.
243 *
244 * Returns void
245 *
246 ******************************************************************************/
cmac_generate_subkey(BT_OCTET16 key)247 static bool cmac_generate_subkey(BT_OCTET16 key) {
248 BT_OCTET16 z = {0};
249 bool ret = true;
250 tSMP_ENC output;
251 SMP_TRACE_EVENT(" cmac_generate_subkey");
252
253 if (SMP_Encrypt(key, BT_OCTET16_LEN, z, BT_OCTET16_LEN, &output)) {
254 cmac_subkey_cont(&output);
255 ;
256 } else
257 ret = false;
258
259 return ret;
260 }
261 /*******************************************************************************
262 *
263 * Function aes_cipher_msg_auth_code
264 *
265 * Description This is the AES-CMAC Generation Function with tlen
266 * implemented.
267 *
268 * Parameters key - CMAC key in little endian order, expect SRK when used
269 * by SMP.
270 * input - text to be signed in little endian byte order.
271 * length - length of the input in byte.
272 * tlen - lenth of mac desired
273 * p_signature - data pointer to where signed data to be
274 * stored, tlen long.
275 *
276 * Returns false if out of resources, true in other cases.
277 *
278 ******************************************************************************/
aes_cipher_msg_auth_code(BT_OCTET16 key,uint8_t * input,uint16_t length,uint16_t tlen,uint8_t * p_signature)279 bool aes_cipher_msg_auth_code(BT_OCTET16 key, uint8_t* input, uint16_t length,
280 uint16_t tlen, uint8_t* p_signature) {
281 uint16_t len, diff;
282 uint16_t n = (length + BT_OCTET16_LEN - 1) /
283 BT_OCTET16_LEN; /* n is number of rounds */
284 bool ret = false;
285
286 SMP_TRACE_EVENT("%s", __func__);
287
288 if (n == 0) n = 1;
289 len = n * BT_OCTET16_LEN;
290
291 SMP_TRACE_WARNING("AES128_CMAC started, allocate buffer size = %d", len);
292 /* allocate a memory space of multiple of 16 bytes to hold text */
293 cmac_cb.text = (uint8_t*)osi_calloc(len);
294 cmac_cb.round = n;
295 diff = len - length;
296
297 if (input != NULL && length > 0) {
298 memcpy(&cmac_cb.text[diff], input, (int)length);
299 cmac_cb.len = length;
300 } else {
301 cmac_cb.len = 0;
302 }
303
304 /* prepare calculation for subkey s and last block of data */
305 if (cmac_generate_subkey(key)) {
306 /* start calculation */
307 ret = cmac_aes_k_calculate(key, p_signature, tlen);
308 }
309 /* clean up */
310 cmac_aes_cleanup();
311
312 return ret;
313 }
314