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