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