Home | History | Annotate | Download | only in smp
      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