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 "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 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 ******************************************************************************/ 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 ******************************************************************************/ 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 ******************************************************************************/ 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 ******************************************************************************/ 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 ******************************************************************************/ 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 ******************************************************************************/ 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 ******************************************************************************/ 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 ******************************************************************************/ 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