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 *******************************************************************************/
gatt_sign_data(tGATT_CLCB * p_clcb)44 static 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 *******************************************************************************/
gatt_verify_signature(tGATT_TCB * p_tcb,BT_HDR * p_buf)99 void 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 *******************************************************************************/
gatt_sec_check_complete(BOOLEAN sec_check_ok,tGATT_CLCB * p_clcb,UINT8 sec_act)132 void 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 *******************************************************************************/
gatt_enc_cmpl_cback(BD_ADDR bd_addr,tBT_TRANSPORT transport,void * p_ref_data,tBTM_STATUS result)159 void 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 = p_tcb->pending_enc_clcb.count;
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 *******************************************************************************/
gatt_notify_enc_cmpl(BD_ADDR bd_addr)228 void 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 = p_tcb->pending_enc_clcb.count;
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 *******************************************************************************/
gatt_set_sec_act(tGATT_TCB * p_tcb,tGATT_SEC_ACTION sec_act)278 void 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 *******************************************************************************/
gatt_get_sec_act(tGATT_TCB * p_tcb)294 tGATT_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 *******************************************************************************/
gatt_determine_sec_act(tGATT_CLCB * p_clcb)313 tGATT_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 *******************************************************************************/
gatt_get_link_encrypt_status(tGATT_TCB * p_tcb)417 tGATT_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 *******************************************************************************/
gatt_convert_sec_action(tGATT_SEC_ACTION gatt_sec_act,tBTM_BLE_SEC_ACT * p_btm_sec_act)445 static 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 *******************************************************************************/
gatt_security_check_start(tGATT_CLCB * p_clcb)475 BOOLEAN 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