Home | History | Annotate | Download | only in gatt
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 1999-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 GATT authentication handling functions
     22  *
     23  ******************************************************************************/
     24 #include "bt_target.h"
     25 #include "bt_utils.h"
     26 
     27 #include <string.h>
     28 #include "bt_common.h"
     29 
     30 #include "btm_int.h"
     31 #include "gatt_api.h"
     32 #include "gatt_int.h"
     33 #include "osi/include/osi.h"
     34 
     35 /*******************************************************************************
     36  *
     37  * Function         gatt_sign_data
     38  *
     39  * Description      This function sign the data for write command.
     40  *
     41  * Returns          true if encrypted, otherwise false.
     42  *
     43  ******************************************************************************/
     44 static bool gatt_sign_data(tGATT_CLCB* p_clcb) {
     45   tGATT_VALUE* p_attr = (tGATT_VALUE*)p_clcb->p_attr_buf;
     46   uint8_t *p_data = NULL, *p;
     47   uint16_t payload_size = p_clcb->p_tcb->payload_size;
     48   bool status = false;
     49   uint8_t* p_signature;
     50 
     51   /* do not need to mark channel securoty activity for data signing */
     52   gatt_set_sec_act(p_clcb->p_tcb, GATT_SEC_OK);
     53 
     54   p_data =
     55       (uint8_t*)osi_malloc(p_attr->len + 3); /* 3 = 2 byte handle + opcode */
     56 
     57   p = p_data;
     58   UINT8_TO_STREAM(p, GATT_SIGN_CMD_WRITE);
     59   UINT16_TO_STREAM(p, p_attr->handle);
     60   ARRAY_TO_STREAM(p, p_attr->value, p_attr->len);
     61 
     62   /* sign data length should be attribulte value length plus 2B handle + 1B op
     63    * code */
     64   if ((payload_size - GATT_AUTH_SIGN_LEN - 3) < p_attr->len)
     65     p_attr->len = payload_size - GATT_AUTH_SIGN_LEN - 3;
     66 
     67   p_signature = p_attr->value + p_attr->len;
     68   if (BTM_BleDataSignature(
     69           p_clcb->p_tcb->peer_bda, p_data,
     70           (uint16_t)(p_attr->len + 3), /* 3 = 2 byte handle + opcode */
     71           p_signature)) {
     72     p_attr->len += BTM_BLE_AUTH_SIGN_LEN;
     73     gatt_set_ch_state(p_clcb->p_tcb, GATT_CH_OPEN);
     74     gatt_act_write(p_clcb, GATT_SEC_SIGN_DATA);
     75   } else {
     76     gatt_end_operation(p_clcb, GATT_INTERNAL_ERROR, NULL);
     77   }
     78 
     79   osi_free(p_data);
     80 
     81   return status;
     82 }
     83 
     84 /*******************************************************************************
     85  *
     86  * Function         gatt_verify_signature
     87  *
     88  * Description      This function start to verify the sign data when receiving
     89  *                  the data from peer device.
     90  *
     91  * Returns
     92  *
     93  ******************************************************************************/
     94 void gatt_verify_signature(tGATT_TCB* p_tcb, BT_HDR* p_buf) {
     95   uint16_t cmd_len;
     96   uint8_t op_code;
     97   uint8_t *p, *p_orig = (uint8_t *)(p_buf + 1) + p_buf->offset;
     98   uint32_t counter;
     99 
    100   if (p_buf->len < GATT_AUTH_SIGN_LEN + 4) {
    101     GATT_TRACE_ERROR("%s: Data length %u less than expected %u", __func__,
    102                      p_buf->len, GATT_AUTH_SIGN_LEN + 4);
    103     return;
    104   }
    105   cmd_len = p_buf->len - GATT_AUTH_SIGN_LEN + 4;
    106   p = p_orig + cmd_len - 4;
    107   STREAM_TO_UINT32(counter, p);
    108 
    109   if (BTM_BleVerifySignature(p_tcb->peer_bda, p_orig, cmd_len, counter, p)) {
    110     STREAM_TO_UINT8(op_code, p_orig);
    111     gatt_server_handle_client_req(p_tcb, op_code, (uint16_t)(p_buf->len - 1),
    112                                   p_orig);
    113   } else {
    114     /* if this is a bad signature, assume from attacker, ignore it  */
    115     GATT_TRACE_ERROR("Signature Verification Failed, data ignored");
    116   }
    117 
    118   return;
    119 }
    120 /*******************************************************************************
    121  *
    122  * Function         gatt_sec_check_complete
    123  *
    124  * Description      security check complete and proceed to data sending action.
    125  *
    126  * Returns          void.
    127  *
    128  ******************************************************************************/
    129 void gatt_sec_check_complete(bool sec_check_ok, tGATT_CLCB* p_clcb,
    130                              uint8_t sec_act) {
    131   if (p_clcb && p_clcb->p_tcb &&
    132       fixed_queue_is_empty(p_clcb->p_tcb->pending_enc_clcb)) {
    133     gatt_set_sec_act(p_clcb->p_tcb, GATT_SEC_NONE);
    134   }
    135 
    136   if (!sec_check_ok) {
    137     gatt_end_operation(p_clcb, GATT_AUTH_FAIL, NULL);
    138   } else if (p_clcb->operation == GATTC_OPTYPE_WRITE) {
    139     gatt_act_write(p_clcb, sec_act);
    140   } else if (p_clcb->operation == GATTC_OPTYPE_READ) {
    141     gatt_act_read(p_clcb, p_clcb->counter);
    142   }
    143 }
    144 /*******************************************************************************
    145  *
    146  * Function         gatt_enc_cmpl_cback
    147  *
    148  * Description      link encryption complete callback.
    149  *
    150  * Returns
    151  *
    152  ******************************************************************************/
    153 void gatt_enc_cmpl_cback(BD_ADDR bd_addr, tBT_TRANSPORT transport,
    154                          UNUSED_ATTR void* p_ref_data, tBTM_STATUS result) {
    155   tGATT_TCB* p_tcb;
    156   uint8_t sec_flag;
    157   bool status = false;
    158 
    159   GATT_TRACE_DEBUG("gatt_enc_cmpl_cback");
    160   p_tcb = gatt_find_tcb_by_addr(bd_addr, transport);
    161   if (p_tcb != NULL) {
    162     if (gatt_get_sec_act(p_tcb) == GATT_SEC_ENC_PENDING) return;
    163 
    164     tGATT_PENDING_ENC_CLCB* p_buf =
    165         (tGATT_PENDING_ENC_CLCB*)fixed_queue_try_dequeue(
    166             p_tcb->pending_enc_clcb);
    167     if (p_buf != NULL) {
    168       if (result == BTM_SUCCESS) {
    169         if (gatt_get_sec_act(p_tcb) == GATT_SEC_ENCRYPT_MITM) {
    170           BTM_GetSecurityFlagsByTransport(bd_addr, &sec_flag, transport);
    171 
    172           if (sec_flag & BTM_SEC_FLAG_LKEY_AUTHED) {
    173             status = true;
    174           }
    175         } else {
    176           status = true;
    177         }
    178       }
    179       gatt_sec_check_complete(status, p_buf->p_clcb, p_tcb->sec_act);
    180       osi_free(p_buf);
    181       /* start all other pending operation in queue */
    182       for (size_t count = fixed_queue_length(p_tcb->pending_enc_clcb);
    183            count > 0; count--) {
    184         p_buf = (tGATT_PENDING_ENC_CLCB*)fixed_queue_try_dequeue(
    185             p_tcb->pending_enc_clcb);
    186         if (p_buf != NULL) {
    187           gatt_security_check_start(p_buf->p_clcb);
    188           osi_free(p_buf);
    189         } else
    190           break;
    191       }
    192     } else {
    193       GATT_TRACE_ERROR("Unknown operation encryption completed");
    194     }
    195   } else {
    196     GATT_TRACE_ERROR("enc callback for unknown bd_addr");
    197   }
    198 }
    199 
    200 /*******************************************************************************
    201  *
    202  * Function         gatt_notify_enc_cmpl
    203  *
    204  * Description      link encryption complete notification for all encryption
    205  *                  process initiated outside GATT.
    206  *
    207  * Returns
    208  *
    209  ******************************************************************************/
    210 void gatt_notify_enc_cmpl(BD_ADDR bd_addr) {
    211   tGATT_TCB* p_tcb;
    212   uint8_t i = 0;
    213 
    214   p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_LE);
    215   if (p_tcb != NULL) {
    216     for (i = 0; i < GATT_MAX_APPS; i++) {
    217       if (gatt_cb.cl_rcb[i].in_use && gatt_cb.cl_rcb[i].app_cb.p_enc_cmpl_cb) {
    218         (*gatt_cb.cl_rcb[i].app_cb.p_enc_cmpl_cb)(gatt_cb.cl_rcb[i].gatt_if,
    219                                                   bd_addr);
    220       }
    221     }
    222 
    223     if (gatt_get_sec_act(p_tcb) == GATT_SEC_ENC_PENDING) {
    224       gatt_set_sec_act(p_tcb, GATT_SEC_NONE);
    225 
    226       size_t count = fixed_queue_length(p_tcb->pending_enc_clcb);
    227       for (; count > 0; count--) {
    228         tGATT_PENDING_ENC_CLCB* p_buf =
    229             (tGATT_PENDING_ENC_CLCB*)fixed_queue_try_dequeue(
    230                 p_tcb->pending_enc_clcb);
    231         if (p_buf != NULL) {
    232           gatt_security_check_start(p_buf->p_clcb);
    233           osi_free(p_buf);
    234         } else
    235           break;
    236       }
    237     }
    238   } else {
    239     GATT_TRACE_DEBUG("notify GATT for encryption completion of unknown device");
    240   }
    241   return;
    242 }
    243 /*******************************************************************************
    244  *
    245  * Function         gatt_set_sec_act
    246  *
    247  * Description      This function set the sec_act in clcb
    248  *
    249  * Returns          none
    250  *
    251  ******************************************************************************/
    252 void gatt_set_sec_act(tGATT_TCB* p_tcb, tGATT_SEC_ACTION sec_act) {
    253   if (p_tcb) {
    254     p_tcb->sec_act = sec_act;
    255   }
    256 }
    257 /*******************************************************************************
    258  *
    259  * Function         gatt_get_sec_act
    260  *
    261  * Description      This function get the sec_act in clcb
    262  *
    263  * Returns          none
    264  *
    265  ******************************************************************************/
    266 tGATT_SEC_ACTION gatt_get_sec_act(tGATT_TCB* p_tcb) {
    267   tGATT_SEC_ACTION sec_act = GATT_SEC_NONE;
    268   if (p_tcb) {
    269     sec_act = p_tcb->sec_act;
    270   }
    271   return sec_act;
    272 }
    273 /*******************************************************************************
    274  *
    275  * Function         gatt_determine_sec_act
    276  *
    277  * Description      This routine determine the security action based on
    278  *                  auth_request and current link status
    279  *
    280  * Returns          tGATT_SEC_ACTION security action
    281  *
    282  ******************************************************************************/
    283 tGATT_SEC_ACTION gatt_determine_sec_act(tGATT_CLCB* p_clcb) {
    284   tGATT_SEC_ACTION act = GATT_SEC_OK;
    285   uint8_t sec_flag;
    286   tGATT_TCB* p_tcb = p_clcb->p_tcb;
    287   tGATT_AUTH_REQ auth_req = p_clcb->auth_req;
    288   bool is_link_encrypted = false;
    289   bool is_link_key_known = false;
    290   bool is_key_mitm = false;
    291   uint8_t key_type;
    292   tBTM_BLE_SEC_REQ_ACT sec_act = BTM_LE_SEC_NONE;
    293 
    294   if (auth_req == GATT_AUTH_REQ_NONE) return act;
    295 
    296   BTM_GetSecurityFlagsByTransport(p_tcb->peer_bda, &sec_flag,
    297                                   p_clcb->p_tcb->transport);
    298 
    299   btm_ble_link_sec_check(p_tcb->peer_bda, auth_req, &sec_act);
    300 
    301   /* if a encryption is pending, need to wait */
    302   if (sec_act == BTM_BLE_SEC_REQ_ACT_DISCARD && auth_req != GATT_AUTH_REQ_NONE)
    303     return GATT_SEC_ENC_PENDING;
    304 
    305   if (sec_flag & (BTM_SEC_FLAG_ENCRYPTED | BTM_SEC_FLAG_LKEY_KNOWN)) {
    306     if (sec_flag & BTM_SEC_FLAG_ENCRYPTED) is_link_encrypted = true;
    307 
    308     is_link_key_known = true;
    309 
    310     if (sec_flag & BTM_SEC_FLAG_LKEY_AUTHED) is_key_mitm = true;
    311   }
    312 
    313   /* first check link key upgrade required or not */
    314   switch (auth_req) {
    315     case GATT_AUTH_REQ_MITM:
    316     case GATT_AUTH_REQ_SIGNED_MITM:
    317       if (!is_key_mitm) act = GATT_SEC_ENCRYPT_MITM;
    318       break;
    319 
    320     case GATT_AUTH_REQ_NO_MITM:
    321     case GATT_AUTH_REQ_SIGNED_NO_MITM:
    322       if (!is_link_key_known) act = GATT_SEC_ENCRYPT_NO_MITM;
    323       break;
    324     default:
    325       break;
    326   }
    327 
    328   /* now check link needs to be encrypted or not if the link key upgrade is not
    329    * required */
    330   if (act == GATT_SEC_OK) {
    331     if (p_tcb->transport == BT_TRANSPORT_LE &&
    332         (p_clcb->operation == GATTC_OPTYPE_WRITE) &&
    333         (p_clcb->op_subtype == GATT_WRITE_NO_RSP)) {
    334       /* this is a write command request
    335          check data signing required or not */
    336       if (!is_link_encrypted) {
    337         btm_ble_get_enc_key_type(p_tcb->peer_bda, &key_type);
    338 
    339         if ((key_type & BTM_LE_KEY_LCSRK) &&
    340             ((auth_req == GATT_AUTH_REQ_SIGNED_NO_MITM) ||
    341              (auth_req == GATT_AUTH_REQ_SIGNED_MITM))) {
    342           act = GATT_SEC_SIGN_DATA;
    343         } else {
    344           act = GATT_SEC_ENCRYPT;
    345         }
    346       }
    347     } else {
    348       if (!is_link_encrypted) {
    349         act = GATT_SEC_ENCRYPT;
    350       }
    351     }
    352   }
    353 
    354   return act;
    355 }
    356 
    357 /*******************************************************************************
    358  *
    359  * Function         gatt_get_link_encrypt_status
    360  *
    361  * Description      This routine get the encryption status of the specified link
    362  *
    363  *
    364  * Returns          tGATT_STATUS link encryption status
    365  *
    366  ******************************************************************************/
    367 tGATT_STATUS gatt_get_link_encrypt_status(tGATT_TCB* p_tcb) {
    368   tGATT_STATUS encrypt_status = GATT_NOT_ENCRYPTED;
    369   uint8_t sec_flag = 0;
    370 
    371   BTM_GetSecurityFlagsByTransport(p_tcb->peer_bda, &sec_flag, p_tcb->transport);
    372 
    373   if ((sec_flag & BTM_SEC_FLAG_ENCRYPTED) &&
    374       (sec_flag & BTM_SEC_FLAG_LKEY_KNOWN)) {
    375     encrypt_status = GATT_ENCRYPED_NO_MITM;
    376     if (sec_flag & BTM_SEC_FLAG_LKEY_AUTHED)
    377       encrypt_status = GATT_ENCRYPED_MITM;
    378   }
    379 
    380   GATT_TRACE_DEBUG("gatt_get_link_encrypt_status status=0x%x", encrypt_status);
    381   return encrypt_status;
    382 }
    383 
    384 /*******************************************************************************
    385  *
    386  * Function         gatt_convert_sec_action
    387  *
    388  * Description      Convert GATT security action enum into equivalent
    389  *                  BTM BLE security action enum
    390  *
    391  * Returns          bool    true - conversation is successful
    392  *
    393  ******************************************************************************/
    394 static bool gatt_convert_sec_action(tGATT_SEC_ACTION gatt_sec_act,
    395                                     tBTM_BLE_SEC_ACT* p_btm_sec_act) {
    396   bool status = true;
    397   switch (gatt_sec_act) {
    398     case GATT_SEC_ENCRYPT:
    399       *p_btm_sec_act = BTM_BLE_SEC_ENCRYPT;
    400       break;
    401     case GATT_SEC_ENCRYPT_NO_MITM:
    402       *p_btm_sec_act = BTM_BLE_SEC_ENCRYPT_NO_MITM;
    403       break;
    404     case GATT_SEC_ENCRYPT_MITM:
    405       *p_btm_sec_act = BTM_BLE_SEC_ENCRYPT_MITM;
    406       break;
    407     default:
    408       status = false;
    409       break;
    410   }
    411 
    412   return status;
    413 }
    414 /*******************************************************************************
    415  *
    416  * Function         gatt_check_enc_req
    417  *
    418  * Description      check link security.
    419  *
    420  * Returns          true if encrypted, otherwise false.
    421  *
    422  ******************************************************************************/
    423 bool gatt_security_check_start(tGATT_CLCB* p_clcb) {
    424   tGATT_TCB* p_tcb = p_clcb->p_tcb;
    425   tGATT_SEC_ACTION gatt_sec_act;
    426   tBTM_BLE_SEC_ACT btm_ble_sec_act;
    427   bool status = true;
    428   tBTM_STATUS btm_status;
    429   tGATT_SEC_ACTION sec_act_old = gatt_get_sec_act(p_tcb);
    430 
    431   gatt_sec_act = gatt_determine_sec_act(p_clcb);
    432 
    433   if (sec_act_old == GATT_SEC_NONE) gatt_set_sec_act(p_tcb, gatt_sec_act);
    434 
    435   switch (gatt_sec_act) {
    436     case GATT_SEC_SIGN_DATA:
    437       GATT_TRACE_DEBUG("gatt_security_check_start: Do data signing");
    438       gatt_sign_data(p_clcb);
    439       break;
    440     case GATT_SEC_ENCRYPT:
    441     case GATT_SEC_ENCRYPT_NO_MITM:
    442     case GATT_SEC_ENCRYPT_MITM:
    443       if (sec_act_old < GATT_SEC_ENCRYPT) {
    444         GATT_TRACE_DEBUG(
    445             "gatt_security_check_start: Encrypt now or key upgreade first");
    446         gatt_convert_sec_action(gatt_sec_act, &btm_ble_sec_act);
    447         btm_status =
    448             BTM_SetEncryption(p_tcb->peer_bda, p_tcb->transport,
    449                               gatt_enc_cmpl_cback, NULL, btm_ble_sec_act);
    450         if ((btm_status != BTM_SUCCESS) && (btm_status != BTM_CMD_STARTED)) {
    451           GATT_TRACE_ERROR(
    452               "gatt_security_check_start BTM_SetEncryption failed "
    453               "btm_status=%d",
    454               btm_status);
    455           status = false;
    456         }
    457       }
    458       if (status) gatt_add_pending_enc_channel_clcb(p_tcb, p_clcb);
    459       break;
    460     case GATT_SEC_ENC_PENDING:
    461       gatt_add_pending_enc_channel_clcb(p_tcb, p_clcb);
    462       /* wait for link encrypotion to finish */
    463       break;
    464     default:
    465       gatt_sec_check_complete(true, p_clcb, gatt_sec_act);
    466       break;
    467   }
    468 
    469   if (status == false) {
    470     gatt_set_sec_act(p_tcb, GATT_SEC_NONE);
    471     gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
    472   }
    473 
    474   return status;
    475 }
    476