1 /******************************************************************************
2  *
3  *  Copyright (C) 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 "common/bt_target.h"
26 #include "osi/allocator.h"
27 
28 #if SMP_INCLUDED == TRUE
29 //    #include <stdio.h>
30 #include <string.h>
31 
32 #include "stack/btm_ble_api.h"
33 #include "smp_int.h"
34 #include "stack/hcimsgs.h"
35 
36 typedef struct {
37     UINT8               *text;
38     UINT16              len;
39     UINT16              round;
40 } tCMAC_CB;
41 
42 tCMAC_CB    cmac_cb;
43 
44 /* Rb for AES-128 as block cipher, LSB as [0] */
45 const BT_OCTET16 const_Rb = {
46     0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
47     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
48 };
49 
print128(BT_OCTET16 x,const UINT8 * key_name)50 void print128(BT_OCTET16 x, const UINT8 *key_name)
51 {
52 #if SMP_DEBUG == TRUE && SMP_DEBUG_VERBOSE == TRUE
53     UINT8  *p = (UINT8 *)x;
54     UINT8  i;
55 
56     SMP_TRACE_WARNING("%s(MSB ~ LSB) = ", key_name);
57 
58     for (i = 0; i < 4; i ++) {
59         SMP_TRACE_WARNING("%02x %02x %02x %02x",
60                           p[BT_OCTET16_LEN - i * 4 - 1], p[BT_OCTET16_LEN - i * 4 - 2],
61                           p[BT_OCTET16_LEN - i * 4 - 3], p[BT_OCTET16_LEN - i * 4 - 4]);
62     }
63 #endif
64 }
65 
66 /*******************************************************************************
67 **
68 ** Function         padding
69 **
70 ** Description      utility function to padding the given text to be a 128 bits
71 **                  data. The parameter dest is input and output parameter, it
72 **                  must point to a BT_OCTET16_LEN memory space; where include
73 **                  length bytes valid data.
74 **
75 ** Returns          void
76 **
77 *******************************************************************************/
padding(BT_OCTET16 dest,UINT8 length)78 static void padding ( BT_OCTET16 dest, UINT8 length )
79 {
80     UINT8   i, *p = dest;
81     /* original last block */
82     for ( i = length ; i < BT_OCTET16_LEN; i++ ) {
83         p[BT_OCTET16_LEN - i - 1] = ( i == length ) ? 0x80 : 0;
84     }
85 }
86 /*******************************************************************************
87 **
88 ** Function         leftshift_onebit
89 **
90 ** Description      utility function to left shift one bit for a 128 bits value.
91 **
92 ** Returns          void
93 **
94 *******************************************************************************/
leftshift_onebit(UINT8 * input,UINT8 * output)95 static void leftshift_onebit(UINT8 *input, UINT8 *output)
96 {
97     UINT8   i, overflow = 0 , next_overflow = 0;
98     SMP_TRACE_EVENT ("leftshift_onebit ");
99     /* input[0] is LSB */
100     for ( i = 0; i < BT_OCTET16_LEN ; i ++ ) {
101         next_overflow = (input[i] & 0x80) ? 1 : 0;
102         output[i] = (input[i] << 1) | overflow;
103         overflow = next_overflow;
104     }
105     return;
106 }
107 /*******************************************************************************
108 **
109 ** Function         cmac_aes_cleanup
110 **
111 ** Description      clean up function for AES_CMAC algorithm.
112 **
113 ** Returns          void
114 **
115 *******************************************************************************/
cmac_aes_cleanup(void)116 static void cmac_aes_cleanup(void)
117 {
118     if (cmac_cb.text != NULL) {
119         osi_free(cmac_cb.text);
120     }
121     memset(&cmac_cb, 0, sizeof(tCMAC_CB));
122 }
123 
124 /*******************************************************************************
125 **
126 ** Function         cmac_aes_k_calculate
127 **
128 ** Description      This function is the calculation of block cipher using AES-128.
129 **
130 ** Returns          void
131 **
132 *******************************************************************************/
cmac_aes_k_calculate(BT_OCTET16 key,UINT8 * p_signature,UINT16 tlen)133 static BOOLEAN cmac_aes_k_calculate(BT_OCTET16 key, UINT8 *p_signature, UINT16 tlen)
134 {
135     tSMP_ENC output;
136     UINT16    i = 1, err = 0;
137     UINT8    x[16] = {0};
138     UINT8   *p_mac;
139 
140     SMP_TRACE_EVENT ("cmac_aes_k_calculate ");
141 
142     while (i <= cmac_cb.round) {
143         smp_xor_128(&cmac_cb.text[(cmac_cb.round - i)*BT_OCTET16_LEN], x); /* Mi' := Mi (+) X  */
144 
145         if (!SMP_Encrypt(key, BT_OCTET16_LEN, &cmac_cb.text[(cmac_cb.round - i)*BT_OCTET16_LEN], BT_OCTET16_LEN, &output)) {
146             err = 1;
147             break;
148         }
149 
150         memcpy(x, output.param_buf, BT_OCTET16_LEN);
151         i ++;
152     }
153 
154     if (!err) {
155         p_mac = output.param_buf + (BT_OCTET16_LEN - tlen);
156         memcpy(p_signature, p_mac, tlen);
157 
158         SMP_TRACE_DEBUG("tlen = %d p_mac = %p", tlen, p_mac);
159         SMP_TRACE_DEBUG("p_mac[0] = 0x%02x p_mac[1] = 0x%02x p_mac[2] = 0x%02x p_mac[3] = 0x%02x",
160                         *p_mac, *(p_mac + 1), *(p_mac + 2), *(p_mac + 3));
161         SMP_TRACE_DEBUG("p_mac[4] = 0x%02x p_mac[5] = 0x%02x p_mac[6] = 0x%02x p_mac[7] = 0x%02x",
162                         *(p_mac + 4), *(p_mac + 5), *(p_mac + 6), *(p_mac + 7));
163 
164         return TRUE;
165 
166     } else {
167         return FALSE;
168     }
169 }
170 /*******************************************************************************
171 **
172 ** Function         cmac_prepare_last_block
173 **
174 ** Description      This function proceeed to prepare the last block of message
175 **                  Mn depending on the size of the message.
176 **
177 ** Returns          void
178 **
179 *******************************************************************************/
cmac_prepare_last_block(BT_OCTET16 k1,BT_OCTET16 k2)180 static void cmac_prepare_last_block (BT_OCTET16 k1, BT_OCTET16 k2)
181 {
182 //    UINT8       x[16] = {0};
183     BOOLEAN      flag;
184 
185     SMP_TRACE_EVENT ("cmac_prepare_last_block ");
186     /* last block is a complete block set flag to 1 */
187     flag = ((cmac_cb.len % BT_OCTET16_LEN) == 0 && cmac_cb.len != 0)  ? TRUE : FALSE;
188 
189     SMP_TRACE_DEBUG("flag = %d round = %d", flag, cmac_cb.round);
190 
191     if ( flag ) {
192         /* last block is complete block */
193         smp_xor_128(&cmac_cb.text[0], k1);
194     } else { /* padding then xor with k2 */
195         padding(&cmac_cb.text[0], (UINT8)(cmac_cb.len % 16));
196 
197         smp_xor_128(&cmac_cb.text[0], k2);
198     }
199 }
200 /*******************************************************************************
201 **
202 ** Function         cmac_subkey_cont
203 **
204 ** Description      This is the callback function when CIPHk(0[128]) is completed.
205 **
206 ** Returns          void
207 **
208 *******************************************************************************/
cmac_subkey_cont(tSMP_ENC * p)209 static void cmac_subkey_cont(tSMP_ENC *p)
210 {
211     UINT8 k1[BT_OCTET16_LEN], k2[BT_OCTET16_LEN];
212     UINT8 *pp = p->param_buf;
213     SMP_TRACE_EVENT ("cmac_subkey_cont ");
214     print128(pp, (const UINT8 *)"K1 before shift");
215 
216     /* If MSB(L) = 0, then K1 = L << 1 */
217     if ( (pp[BT_OCTET16_LEN - 1] & 0x80) != 0 ) {
218         /* Else K1 = ( L << 1 ) (+) Rb */
219         leftshift_onebit(pp, k1);
220         smp_xor_128(k1, const_Rb);
221     } else {
222         leftshift_onebit(pp, k1);
223     }
224 
225     if ( (k1[BT_OCTET16_LEN - 1] & 0x80) != 0 ) {
226         /* K2 =  (K1 << 1) (+) Rb */
227         leftshift_onebit(k1, k2);
228         smp_xor_128(k2, const_Rb);
229     } else {
230         /* If MSB(K1) = 0, then K2 = K1 << 1 */
231         leftshift_onebit(k1, k2);
232     }
233 
234     print128(k1, (const UINT8 *)"K1");
235     print128(k2, (const UINT8 *)"K2");
236 
237     cmac_prepare_last_block (k1, k2);
238 }
239 /*******************************************************************************
240 **
241 ** Function         cmac_generate_subkey
242 **
243 ** Description      This is the function to generate the two subkeys.
244 **
245 ** Parameters       key - CMAC key, expect SRK when used by SMP.
246 **
247 ** Returns          void
248 **
249 *******************************************************************************/
cmac_generate_subkey(BT_OCTET16 key)250 static BOOLEAN cmac_generate_subkey(BT_OCTET16 key)
251 {
252     BT_OCTET16 z = {0};
253     BOOLEAN     ret = TRUE;
254     tSMP_ENC output;
255     SMP_TRACE_EVENT (" cmac_generate_subkey");
256 
257     if (SMP_Encrypt(key, BT_OCTET16_LEN, z, BT_OCTET16_LEN, &output)) {
258         cmac_subkey_cont(&output);;
259     } else {
260         ret = FALSE;
261     }
262 
263     return ret;
264 }
265 /*******************************************************************************
266 **
267 ** Function         aes_cipher_msg_auth_code
268 **
269 ** Description      This is the AES-CMAC Generation Function with tlen implemented.
270 **
271 ** Parameters       key - CMAC key in little endian order, expect SRK when used by SMP.
272 **                  input - text to be signed in little endian byte order.
273 **                  length - length of the input in byte.
274 **                  tlen - lenth of mac desired
275 **                  p_signature - data pointer to where signed data to be stored, tlen long.
276 **
277 ** Returns          FALSE if out of resources, TRUE in other cases.
278 **
279 *******************************************************************************/
aes_cipher_msg_auth_code(BT_OCTET16 key,UINT8 * input,UINT16 length,UINT16 tlen,UINT8 * p_signature)280 BOOLEAN aes_cipher_msg_auth_code(BT_OCTET16 key, UINT8 *input, UINT16 length,
281                                  UINT16 tlen, UINT8 *p_signature)
282 {
283     UINT16  len, diff;
284     UINT16  n = (length + BT_OCTET16_LEN - 1) / BT_OCTET16_LEN;       /* n is number of rounds */
285     BOOLEAN ret = FALSE;
286 
287     SMP_TRACE_EVENT ("%s", __func__);
288 
289     if (n == 0) {
290         n = 1;
291     }
292     len = n * BT_OCTET16_LEN;
293 
294     SMP_TRACE_DEBUG("AES128_CMAC started, allocate buffer size = %d", len);
295     /* allocate a memory space of multiple of 16 bytes to hold text  */
296     if ((cmac_cb.text = (UINT8 *)osi_malloc(len)) != NULL) {
297         cmac_cb.round = n;
298 
299         memset(cmac_cb.text, 0, len);
300         diff = len - length;
301 
302         if (input != NULL && length > 0) {
303             memcpy(&cmac_cb.text[diff] , input, (int)length);
304             cmac_cb.len = length;
305         } else {
306             cmac_cb.len = 0;
307         }
308 
309         /* prepare calculation for subkey s and last block of data */
310         if (cmac_generate_subkey(key)) {
311             /* start calculation */
312             ret = cmac_aes_k_calculate(key, p_signature, tlen);
313         }
314         /* clean up */
315         cmac_aes_cleanup();
316     } else {
317         ret = FALSE;
318         SMP_TRACE_ERROR("No resources");
319     }
320 
321     return ret;
322 }
323 
324 #if 0 /* testing code, sample data from spec */
325 void test_cmac_cback(UINT8 *p_mac, UINT16 tlen)
326 {
327     SMP_TRACE_EVENT ("test_cmac_cback ");
328     SMP_TRACE_ERROR("test_cmac_cback");
329 }
330 
331 void test_cmac(void)
332 {
333     SMP_TRACE_EVENT ("test_cmac ");
334     UINT8 M[64] = {
335         0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
336         0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
337         0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
338         0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
339         0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
340         0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
341         0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
342         0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
343     };
344 
345     UINT8 key[16] = {
346         0x3c, 0x4f, 0xcf, 0x09, 0x88, 0x15, 0xf7, 0xab,
347         0xa6, 0xd2, 0xae, 0x28, 0x16, 0x15, 0x7e, 0x2b
348     };
349     UINT8 i = 0, tmp;
350     UINT16 len;
351 
352     len = 64;
353 
354     for (i = 0; i < len / 2; i ++) {
355         tmp = M[i];
356         M[i] = M[len - 1 - i];
357         M[len - 1 - i] = tmp;
358     }
359 
360 
361     memset(&cmac_cb, 0, sizeof(tCMAC_CB));
362 
363     SMP_TRACE_WARNING("\n Example 1: len = %d\n", len);
364 
365     aes_cipher_msg_auth_code(key, M, len, 128, test_cmac_cback, 0);
366 
367 }
368 #endif
369 #endif
370