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 ******************************************************************************/
gatt_sign_data(tGATT_CLCB * p_clcb)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 ******************************************************************************/
gatt_verify_signature(tGATT_TCB * p_tcb,BT_HDR * p_buf)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 ******************************************************************************/
gatt_sec_check_complete(bool sec_check_ok,tGATT_CLCB * p_clcb,uint8_t sec_act)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 ******************************************************************************/
gatt_enc_cmpl_cback(BD_ADDR bd_addr,tBT_TRANSPORT transport,UNUSED_ATTR void * p_ref_data,tBTM_STATUS result)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 ******************************************************************************/
gatt_notify_enc_cmpl(BD_ADDR bd_addr)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 ******************************************************************************/
gatt_set_sec_act(tGATT_TCB * p_tcb,tGATT_SEC_ACTION sec_act)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 ******************************************************************************/
gatt_get_sec_act(tGATT_TCB * p_tcb)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 ******************************************************************************/
gatt_determine_sec_act(tGATT_CLCB * p_clcb)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 ******************************************************************************/
gatt_get_link_encrypt_status(tGATT_TCB * p_tcb)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 ******************************************************************************/
gatt_convert_sec_action(tGATT_SEC_ACTION gatt_sec_act,tBTM_BLE_SEC_ACT * p_btm_sec_act)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 ******************************************************************************/
gatt_security_check_start(tGATT_CLCB * p_clcb)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