diff options
author | Casper Bonde <c.bonde@samsung.com> | 2015-05-21 11:08:45 +0200 |
---|---|---|
committer | Pavlin Radoslavov <pavlin@google.com> | 2015-06-09 13:56:06 -0700 |
commit | 818d0f2afb10c75125b0df9ea2bce6108268a269 (patch) | |
tree | 3439f55ca3f82c9b7b6c62b60be272bcc09ac906 | |
parent | 15d6b3144d92167d1f4f88cc87a50c2571a2c166 (diff) | |
download | android_system_bt-818d0f2afb10c75125b0df9ea2bce6108268a269.tar.gz android_system_bt-818d0f2afb10c75125b0df9ea2bce6108268a269.tar.bz2 android_system_bt-818d0f2afb10c75125b0df9ea2bce6108268a269.zip |
SAP: Make it possible to enforce a 16-digit pin code (1/5)
This change enable the posibility to enforce using a
16-digit pin or MITM for a RFCOMM or L2CAP connection.
This is needed for the SIM access profile.
Change-Id: I02886ce284f27295205def3c66fb76372f5dab4f
Signed-off-by: Casper Bonde <c.bonde@samsung.com>
-rw-r--r-- | bta/dm/bta_dm_act.c | 11 | ||||
-rw-r--r-- | bta/dm/bta_dm_api.c | 3 | ||||
-rw-r--r-- | bta/dm/bta_dm_int.h | 1 | ||||
-rw-r--r-- | bta/include/bta_api.h | 7 | ||||
-rw-r--r-- | btif/src/btif_dm.c | 6 | ||||
-rw-r--r-- | btif/src/btif_sock_l2cap.c | 4 | ||||
-rw-r--r-- | btif/src/btif_sock_rfc.c | 2 | ||||
-rw-r--r-- | btif/src/btif_storage.c | 5 | ||||
-rw-r--r-- | stack/btm/btm_dev.c | 12 | ||||
-rw-r--r-- | stack/btm/btm_int.h | 4 | ||||
-rw-r--r-- | stack/btm/btm_sec.c | 150 | ||||
-rw-r--r-- | stack/include/btm_api.h | 6 |
12 files changed, 180 insertions, 31 deletions
diff --git a/bta/dm/bta_dm_act.c b/bta/dm/bta_dm_act.c index 9593a42ed..5775296d8 100644 --- a/bta/dm/bta_dm_act.c +++ b/bta/dm/bta_dm_act.c @@ -54,7 +54,7 @@ static void bta_dm_find_services ( BD_ADDR bd_addr); static void bta_dm_discover_next_device(void); static void bta_dm_sdp_callback (UINT16 sdp_status); static UINT8 bta_dm_authorize_cback (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name, UINT8 *service_name, UINT8 service_id, BOOLEAN is_originator); -static UINT8 bta_dm_pin_cback (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name); +static UINT8 bta_dm_pin_cback (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name, BOOLEAN min_16_digit); static UINT8 bta_dm_new_link_key_cback(BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name, LINK_KEY key, UINT8 key_type); static UINT8 bta_dm_authentication_complete_cback(BD_ADDR bd_addr, DEV_CLASS dev_class,BD_NAME bd_name, int result); static void bta_dm_local_name_cback(BD_ADDR bd_addr); @@ -743,7 +743,8 @@ void bta_dm_add_device (tBTA_DM_MSG *p_data) } if (!BTM_SecAddDevice (p_dev->bd_addr, p_dc, p_dev->bd_name, p_dev->features, - trusted_services_mask, p_lc, p_dev->key_type, p_dev->io_cap)) + trusted_services_mask, p_lc, p_dev->key_type, p_dev->io_cap, + p_dev->pin_length)) { APPL_TRACE_ERROR ("BTA_DM: Error adding device %08x%04x", (p_dev->bd_addr[0]<<24)+(p_dev->bd_addr[1]<<16)+(p_dev->bd_addr[2]<<8)+p_dev->bd_addr[3], @@ -2724,7 +2725,8 @@ static void bta_dm_pinname_cback (void *p_data) ** Returns void ** *******************************************************************************/ -static UINT8 bta_dm_pin_cback (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name) +static UINT8 bta_dm_pin_cback (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name, + BOOLEAN min_16_digit) { tBTA_DM_SEC sec_event; @@ -2747,6 +2749,7 @@ static UINT8 bta_dm_pin_cback (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_ BTA_COPY_DEVICE_CLASS(sec_event.pin_req.dev_class, dev_class); BCM_STRNCPY_S((char*)sec_event.pin_req.bd_name, sizeof(BD_NAME), (char*)bd_name, (BD_NAME_LEN-1)); sec_event.pin_req.bd_name[BD_NAME_LEN-1] = 0; + sec_event.pin_req.min_16_digit = min_16_digit; bta_dm_cb.p_sec_cback(BTA_DM_PIN_REQ_EVT, &sec_event); return BTM_CMD_STARTED; @@ -3747,7 +3750,7 @@ static void bta_dm_set_eir (char *local_name) UINT8 free_eir_length = HCI_EXT_INQ_RESPONSE_LEN; #else // BTM_EIR_DEFAULT_FEC_REQUIRED UINT8 free_eir_length = HCI_DM5_PACKET_SIZE; -#endif // BTM_EIR_DEFAULT_FEC_REQUIRED +#endif // BTM_EIR_DEFAULT_FEC_REQUIRED UINT8 num_uuid; UINT8 data_type; UINT8 local_name_len; diff --git a/bta/dm/bta_dm_api.c b/bta/dm/bta_dm_api.c index 21d955809..c9566e96f 100644 --- a/bta/dm/bta_dm_api.c +++ b/bta/dm/bta_dm_api.c @@ -496,7 +496,7 @@ void BTA_DmConfirm(BD_ADDR bd_addr, BOOLEAN accept) *******************************************************************************/ void BTA_DmAddDevice(BD_ADDR bd_addr, DEV_CLASS dev_class, LINK_KEY link_key, tBTA_SERVICE_MASK trusted_mask, BOOLEAN is_trusted, - UINT8 key_type, tBTA_IO_CAP io_cap) + UINT8 key_type, tBTA_IO_CAP io_cap, UINT8 pin_length) { tBTA_DM_API_ADD_DEVICE *p_msg; @@ -527,6 +527,7 @@ void BTA_DmAddDevice(BD_ADDR bd_addr, DEV_CLASS dev_class, LINK_KEY link_key, memset (p_msg->bd_name, 0, BD_NAME_LEN); memset (p_msg->features, 0, sizeof (p_msg->features)); + p_msg->pin_length = pin_length; bta_sys_sendmsg(p_msg); } diff --git a/bta/dm/bta_dm_int.h b/bta/dm/bta_dm_int.h index 9f3890ed7..b7c85ddea 100644 --- a/bta/dm/bta_dm_int.h +++ b/bta/dm/bta_dm_int.h @@ -356,6 +356,7 @@ typedef struct BOOLEAN dc_known; BD_NAME bd_name; UINT8 features[BTA_FEATURE_BYTES_PER_PAGE * (BTA_EXT_FEATURES_PAGE_MAX + 1)]; + UINT8 pin_length; } tBTA_DM_API_ADD_DEVICE; /* data type for BTA_DM_API_REMOVE_ACL_EVT */ diff --git a/bta/include/bta_api.h b/bta/include/bta_api.h index 71906d4a3..4bc4d7567 100644 --- a/bta/include/bta_api.h +++ b/bta/include/bta_api.h @@ -170,8 +170,10 @@ typedef struct #define BTA_SEC_AUTHENTICATE (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_OUT_AUTHENTICATE) /* Authentication required. */ #define BTA_SEC_ENCRYPT (BTM_SEC_IN_ENCRYPT | BTM_SEC_OUT_ENCRYPT) /* Encryption required. */ #define BTA_SEC_MODE4_LEVEL4 (BTM_SEC_MODE4_LEVEL4) /* Mode 4 level 4 service, i.e. incoming/outgoing MITM and P-256 encryption */ +#define BTA_SEC_MITM (BTM_SEC_IN_MITM | BTM_SEC_OUT_MITM) /* Man-In-The_Middle protection */ +#define BTA_SEC_IN_16_DIGITS (BTM_SEC_IN_MIN_16_DIGIT_PIN) /* Min 16 digit for pin code */ -typedef UINT8 tBTA_SEC; +typedef UINT16 tBTA_SEC; /* Ignore for Discoverable, Connectable, Pairable and Connectable Paired only device modes */ @@ -651,6 +653,7 @@ typedef struct BD_ADDR bd_addr; /* BD address peer device. */ DEV_CLASS dev_class; /* Class of Device */ BD_NAME bd_name; /* Name of peer device. */ + BOOLEAN min_16_digit; /* TRUE if the pin returned must be at least 16 digits */ } tBTA_DM_PIN_REQ; /* BLE related definition */ @@ -1606,7 +1609,7 @@ extern void BTA_DmConfirm(BD_ADDR bd_addr, BOOLEAN accept); extern void BTA_DmAddDevice(BD_ADDR bd_addr, DEV_CLASS dev_class, LINK_KEY link_key, tBTA_SERVICE_MASK trusted_mask, BOOLEAN is_trusted, UINT8 key_type, - tBTA_IO_CAP io_cap); + tBTA_IO_CAP io_cap, UINT8 pin_length); /******************************************************************************* ** diff --git a/btif/src/btif_dm.c b/btif/src/btif_dm.c index 976c1ccf2..8b8f121fc 100644 --- a/btif/src/btif_dm.c +++ b/btif/src/btif_dm.c @@ -907,7 +907,7 @@ static void btif_dm_pin_req_evt(tBTA_DM_PIN_REQ *p_pin_req) } /* check for auto pair possiblity only if bond was initiated by local device */ - if (pairing_cb.is_local_initiated) + if (pairing_cb.is_local_initiated && (p_pin_req->min_16_digit == FALSE)) { if (check_cod(&bd_addr, COD_AV_HEADSETS) || check_cod(&bd_addr, COD_AV_HANDSFREE) || @@ -951,7 +951,7 @@ static void btif_dm_pin_req_evt(tBTA_DM_PIN_REQ *p_pin_req) } } HAL_CBACK(bt_hal_cbacks, pin_request_cb, - &bd_addr, &bd_name, cod); + &bd_addr, &bd_name, cod, p_pin_req->min_16_digit); } /******************************************************************************* @@ -3116,7 +3116,7 @@ static void btif_dm_ble_passkey_req_evt(tBTA_DM_PIN_REQ *p_pin_req) cod = COD_UNCLASSIFIED; HAL_CBACK(bt_hal_cbacks, pin_request_cb, - &bd_addr, &bd_name, cod); + &bd_addr, &bd_name, cod, FALSE); } static void btif_dm_ble_key_nc_req_evt(tBTA_DM_SP_KEY_NOTIF *p_notif_req) { diff --git a/btif/src/btif_sock_l2cap.c b/btif/src/btif_sock_l2cap.c index d66fea690..04c5b676b 100644 --- a/btif/src/btif_sock_l2cap.c +++ b/btif/src/btif_sock_l2cap.c @@ -308,6 +308,10 @@ static l2cap_socket *btsock_l2cap_alloc_l(const char *name, const bt_bdaddr_t *a security |= is_server ? BTM_SEC_IN_ENCRYPT : BTM_SEC_OUT_ENCRYPT; if (flags & BTSOCK_FLAG_AUTH) security |= is_server ? BTM_SEC_IN_AUTHENTICATE : BTM_SEC_OUT_AUTHENTICATE; + if (flags & BTSOCK_FLAG_AUTH_MITM) + security |= is_server ? BTM_SEC_IN_MITM : BTM_SEC_OUT_MITM; + if (flags & BTSOCK_FLAG_AUTH_16_DIGIT) + security |= BTM_SEC_IN_MIN_16_DIGIT_PIN; sock = osi_calloc(sizeof(*sock)); if (!sock) { diff --git a/btif/src/btif_sock_rfc.c b/btif/src/btif_sock_rfc.c index 4ecb5acda..f80ed562f 100644 --- a/btif/src/btif_sock_rfc.c +++ b/btif/src/btif_sock_rfc.c @@ -178,6 +178,8 @@ static rfc_slot_t *alloc_rfc_slot(const bt_bdaddr_t *addr, const char *name, con security |= server ? BTM_SEC_IN_AUTHENTICATE : BTM_SEC_OUT_AUTHENTICATE; if(flags & BTSOCK_FLAG_AUTH_MITM) security |= server ? BTM_SEC_IN_MITM : BTM_SEC_OUT_MITM; + if(flags & BTSOCK_FLAG_AUTH_16_DIGIT) + security |= BTM_SEC_IN_MIN_16_DIGIT_PIN; rfc_slot_t *slot = find_free_slot(); if (!slot) { diff --git a/btif/src/btif_storage.c b/btif/src/btif_storage.c index d33d53648..ff7e7aa0e 100644 --- a/btif/src/btif_storage.c +++ b/btif/src/btif_storage.c @@ -509,9 +509,12 @@ static bt_status_t btif_in_fetch_bonded_devices(btif_bonded_devices_t *p_bonded_ { DEV_CLASS dev_class = {0, 0, 0}; int cod; + int pin_length = 0; if(btif_config_get_int(name, "DevClass", &cod)) uint2devclass((UINT32)cod, dev_class); - BTA_DmAddDevice(bd_addr.address, dev_class, link_key, 0, 0, (UINT8)linkkey_type, 0); + btif_config_get_int(name, "PinLength", &pin_length); + BTA_DmAddDevice(bd_addr.address, dev_class, link_key, 0, 0, + (UINT8)linkkey_type, 0, pin_length); #if BLE_INCLUDED == TRUE if (btif_config_get_int(name, "DevType", &device_type) && diff --git a/stack/btm/btm_dev.c b/stack/btm/btm_dev.c index 671d4a6f9..c8265e4bc 100644 --- a/stack/btm/btm_dev.c +++ b/stack/btm/btm_dev.c @@ -60,7 +60,8 @@ static tBTM_SEC_DEV_REC *btm_find_oldest_dev (void); *******************************************************************************/ BOOLEAN BTM_SecAddDevice (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name, UINT8 *features, UINT32 trusted_mask[], - LINK_KEY link_key, UINT8 key_type, tBTM_IO_CAP io_cap) + LINK_KEY link_key, UINT8 key_type, tBTM_IO_CAP io_cap, + UINT8 pin_length) { tBTM_SEC_DEV_REC *p_dev_rec; int i, j; @@ -145,6 +146,15 @@ BOOLEAN BTM_SecAddDevice (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name, p_dev_rec->sec_flags |= BTM_SEC_LINK_KEY_KNOWN; memcpy (p_dev_rec->link_key, link_key, LINK_KEY_LEN); p_dev_rec->link_key_type = key_type; + p_dev_rec->pin_code_length = pin_length; + + if (pin_length >= 16 || + key_type == BTM_LKEY_TYPE_AUTH_COMB || + key_type == BTM_LKEY_TYPE_AUTH_COMB_P_256) { + // Set the fiag if the link key was made by using either a 16 digit + // pin or MITM. + p_dev_rec->sec_flags |= BTM_SEC_16_DIGIT_PIN_AUTHED; + } } #if defined(BTIF_MIXED_MODE_INCLUDED) && (BTIF_MIXED_MODE_INCLUDED == TRUE) diff --git a/stack/btm/btm_int.h b/stack/btm/btm_int.h index 2f3cea95a..0cc177334 100644 --- a/stack/btm/btm_int.h +++ b/stack/btm/btm_int.h @@ -400,7 +400,7 @@ typedef struct tBTM_SCO_PCM_PARAM sco_pcm_param; tBTM_SCO_CODEC_TYPE codec_in_use; /* None, CVSD, MSBC, etc. */ #if BTM_SCO_HCI_INCLUDED == TRUE - tBTM_SCO_ROUTE_TYPE sco_path; + tBTM_SCO_ROUTE_TYPE sco_path; #endif } tSCO_CB; @@ -508,6 +508,7 @@ typedef struct BD_ADDR bd_addr; /* BD_ADDR of the device */ DEV_CLASS dev_class; /* DEV_CLASS of the device */ LINK_KEY link_key; /* Device link key */ + UINT8 pin_code_length; /* Length of the pin_code used for paring */ #define BTM_SEC_AUTHORIZED BTM_SEC_FLAG_AUTHORIZED /* 0x01 */ #define BTM_SEC_AUTHENTICATED BTM_SEC_FLAG_AUTHENTICATED /* 0x02 */ @@ -523,6 +524,7 @@ typedef struct #define BTM_SEC_LE_NAME_KNOWN 0x0800 /* not used */ #define BTM_SEC_LE_LINK_KEY_KNOWN 0x1000 /* bonded with peer (peer LTK and/or SRK is saved) */ #define BTM_SEC_LE_LINK_KEY_AUTHED 0x2000 /* pairing is done with MITM */ +#define BTM_SEC_16_DIGIT_PIN_AUTHED 0x4000 /* pairing is done with 16 digit pin */ UINT16 sec_flags; /* Current device security state */ diff --git a/stack/btm/btm_sec.c b/stack/btm/btm_sec.c index 83b65240f..ca7ff4393 100644 --- a/stack/btm/btm_sec.c +++ b/stack/btm/btm_sec.c @@ -181,6 +181,25 @@ static BOOLEAN btm_dev_authorized (tBTM_SEC_DEV_REC *p_dev_rec) /******************************************************************************* ** +** Function btm_dev_16_digit_authenticated +** +** Description check device is authenticated by using 16 digit pin or MITM +** +** Returns BOOLEAN TRUE or FALSE +** +*******************************************************************************/ +static BOOLEAN btm_dev_16_digit_authenticated(tBTM_SEC_DEV_REC *p_dev_rec) +{ + // BTM_SEC_16_DIGIT_PIN_AUTHED is set if MITM or 16 digit pin is used + if(p_dev_rec->sec_flags & BTM_SEC_16_DIGIT_PIN_AUTHED) + { + return(TRUE); + } + return(FALSE); +} + +/******************************************************************************* +** ** Function btm_serv_trusted ** ** Description check service is trusted @@ -522,6 +541,8 @@ static BOOLEAN btm_sec_set_security_level (CONNECTION_TYPE conn_type, char *p_na is_originator = conn_type; #endif + BTM_TRACE_API("%s : sec: 0x%x", __func__, sec_level); + /* See if the record can be reused (same service name, psm, mx_proto_id, service_id, and mx_chan_id), or obtain the next unused record */ @@ -601,7 +622,8 @@ static BOOLEAN btm_sec_set_security_level (CONNECTION_TYPE conn_type, char *p_na } /* Parameter validation. Originator should not set requirements for incoming connections */ - sec_level &= ~(BTM_SEC_IN_AUTHORIZE | BTM_SEC_IN_ENCRYPT | BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_MITM); + sec_level &= ~(BTM_SEC_IN_AUTHORIZE | BTM_SEC_IN_ENCRYPT | BTM_SEC_IN_AUTHENTICATE + | BTM_SEC_IN_MITM | BTM_SEC_IN_MIN_16_DIGIT_PIN ); if (btm_cb.security_mode == BTM_SEC_MODE_SP || btm_cb.security_mode == BTM_SEC_MODE_SP_DEBUG || @@ -637,14 +659,16 @@ static BOOLEAN btm_sec_set_security_level (CONNECTION_TYPE conn_type, char *p_na { p_srec->ucd_security_flags &= ~(BTM_SEC_IN_AUTHORIZE | BTM_SEC_IN_ENCRYPT | BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_MITM | - BTM_SEC_FORCE_MASTER | BTM_SEC_ATTEMPT_MASTER | BTM_SEC_FORCE_SLAVE | BTM_SEC_ATTEMPT_SLAVE); + BTM_SEC_FORCE_MASTER | BTM_SEC_ATTEMPT_MASTER | BTM_SEC_FORCE_SLAVE | BTM_SEC_ATTEMPT_SLAVE + | BTM_SEC_IN_MIN_16_DIGIT_PIN); } else #endif { p_srec->security_flags &= ~(BTM_SEC_IN_AUTHORIZE | BTM_SEC_IN_ENCRYPT | BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_MITM | - BTM_SEC_FORCE_MASTER | BTM_SEC_ATTEMPT_MASTER | BTM_SEC_FORCE_SLAVE | BTM_SEC_ATTEMPT_SLAVE); + BTM_SEC_FORCE_MASTER | BTM_SEC_ATTEMPT_MASTER | BTM_SEC_FORCE_SLAVE | BTM_SEC_ATTEMPT_SLAVE + | BTM_SEC_IN_MIN_16_DIGIT_PIN); } /* Parameter validation. Acceptor should not set requirements for outgoing connections */ @@ -877,6 +901,9 @@ void BTM_PINCodeReply (BD_ADDR bd_addr, UINT8 res, UINT8 pin_len, UINT8 *p_pin, if (trusted_mask) BTM_SEC_COPY_TRUSTED_DEVICE(trusted_mask, p_dev_rec->trusted_mask); p_dev_rec->sec_flags |= BTM_SEC_LINK_KEY_AUTHED; + if (pin_len >= 16) { + p_dev_rec->sec_flags |= BTM_SEC_16_DIGIT_PIN_AUTHED; + } if ( (btm_cb.pairing_flags & BTM_PAIR_FLAGS_WE_STARTED_DD) && (p_dev_rec->hci_handle == BTM_SEC_INVALID_HANDLE) @@ -884,6 +911,7 @@ void BTM_PINCodeReply (BD_ADDR bd_addr, UINT8 res, UINT8 pin_len, UINT8 *p_pin, { /* This is start of the dedicated bonding if local device is 2.0 */ btm_cb.pin_code_len = pin_len; + p_dev_rec->pin_code_length = pin_len; memcpy (btm_cb.pin_code, p_pin, pin_len); btm_cb.security_mode_changed = TRUE; @@ -997,6 +1025,7 @@ tBTM_STATUS btm_sec_bond_by_transport (BD_ADDR bd_addr, tBT_TRANSPORT transport, if (p_pin && (pin_len <= PIN_CODE_LEN) && (pin_len != 0)) { btm_cb.pin_code_len = pin_len; + p_dev_rec->pin_code_length = pin_len; memcpy (btm_cb.pin_code, p_pin, PIN_CODE_LEN); } @@ -1527,6 +1556,7 @@ void BTM_ConfirmReqReply(tBTM_STATUS res, BD_ADDR bd_addr) { if ((p_dev_rec = btm_find_dev (bd_addr)) != NULL) p_dev_rec->sec_flags |= BTM_SEC_LINK_KEY_AUTHED; + p_dev_rec->sec_flags |= BTM_SEC_16_DIGIT_PIN_AUTHED; } btsnd_hcic_user_conf_reply (bd_addr, TRUE); @@ -2174,7 +2204,12 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle ((((security_required & BTM_SEC_IN_FLAGS) == (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_ENCRYPT)) && (p_dev_rec->sec_flags & BTM_SEC_ENCRYPTED))) || ((((security_required & BTM_SEC_IN_FLAGS) == BTM_SEC_IN_FLAGS) && (p_dev_rec->sec_flags & BTM_SEC_AUTHORIZED))) ) { - rc = BTM_SUCCESS; + // Check for 16 digits (or MITM) + if (((security_required & BTM_SEC_IN_MIN_16_DIGIT_PIN) == 0) || + (((security_required & BTM_SEC_IN_MIN_16_DIGIT_PIN) == BTM_SEC_IN_MIN_16_DIGIT_PIN) && + btm_dev_16_digit_authenticated(p_dev_rec))) { + rc = BTM_SUCCESS; + } } } @@ -2264,7 +2299,11 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle (((security_required & BTM_SEC_IN_FLAGS) == (BTM_SEC_IN_ENCRYPT | BTM_SEC_IN_AUTHORIZE)) && ((btm_dev_authorized(p_dev_rec)||btm_serv_trusted(p_dev_rec, p_serv_rec)) && btm_dev_encrypted(p_dev_rec))) || (((security_required & BTM_SEC_IN_FLAGS) == BTM_SEC_IN_FLAGS) && btm_dev_encrypted(p_dev_rec) && (btm_dev_authorized(p_dev_rec)||btm_serv_trusted(p_dev_rec, p_serv_rec)))) { - rc = BTM_SUCCESS; + // Check for 16 digits (or MITM) + if (((security_required & BTM_SEC_IN_MIN_16_DIGIT_PIN) == 0) || + (((security_required & BTM_SEC_IN_MIN_16_DIGIT_PIN) == BTM_SEC_IN_MIN_16_DIGIT_PIN) && btm_dev_16_digit_authenticated(p_dev_rec))) { + rc = BTM_SUCCESS; + } } } @@ -2548,7 +2587,11 @@ tBTM_STATUS btm_sec_mx_access_request (BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_o ((((security_required & BTM_SEC_IN_FLAGS) == (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_ENCRYPT)) && btm_dev_encrypted(p_dev_rec))) ) { - rc = BTM_SUCCESS; + // Check for 16 digits (or MITM) + if (((security_required & BTM_SEC_IN_MIN_16_DIGIT_PIN) == 0) || + (((security_required & BTM_SEC_IN_MIN_16_DIGIT_PIN) == BTM_SEC_IN_MIN_16_DIGIT_PIN) && btm_dev_16_digit_authenticated(p_dev_rec))) { + rc = BTM_SUCCESS; + } } } if ((rc == BTM_SUCCESS) && (security_required & BTM_SEC_MODE4_LEVEL4) && @@ -3137,7 +3180,9 @@ void btm_sec_rmt_name_request_complete (UINT8 *p_bd_addr, UINT8 *p_bd_name, UINT { BTM_TRACE_EVENT ("btm_sec_rmt_name_request_complete() calling pin_callback"); btm_cb.pairing_flags |= BTM_PAIR_FLAGS_PIN_REQD; - (*btm_cb.api.p_pin_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class, p_bd_name); + (*btm_cb.api.p_pin_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class, p_bd_name, + (p_dev_rec->p_cur_service==NULL) ? FALSE + : (p_dev_rec->p_cur_service->security_flags & BTM_SEC_IN_MIN_16_DIGIT_PIN)); } /* Set the same state again to force the timer to be restarted */ @@ -4144,6 +4189,14 @@ void btm_sec_auth_complete (UINT16 handle, UINT8 status) p_dev_rec->sec_flags |= BTM_SEC_AUTHENTICATED; + if (p_dev_rec->pin_code_length >= 16 || + p_dev_rec->link_key_type == BTM_LKEY_TYPE_AUTH_COMB || + p_dev_rec->link_key_type == BTM_LKEY_TYPE_AUTH_COMB_P_256) { + // If we have MITM protection we have a higher level of security than + // provided by 16 digits PIN + p_dev_rec->sec_flags |= BTM_SEC_16_DIGIT_PIN_AUTHED; + } + /* Authentication succeeded, execute the next security procedure, if any */ status = btm_sec_execute_procedure (p_dev_rec); @@ -4188,10 +4241,18 @@ void btm_sec_encrypt_change (UINT16 handle, UINT8 status, UINT8 encr_enable) if ((status == HCI_SUCCESS) && encr_enable) { - if (p_dev_rec->hci_handle == handle) + if (p_dev_rec->hci_handle == handle) { p_dev_rec->sec_flags |= (BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED); + if (p_dev_rec->pin_code_length >= 16 || + p_dev_rec->link_key_type == BTM_LKEY_TYPE_AUTH_COMB || + p_dev_rec->link_key_type == BTM_LKEY_TYPE_AUTH_COMB_P_256) { + p_dev_rec->sec_flags |= BTM_SEC_16_DIGIT_PIN_AUTHED; + } + } else + { p_dev_rec->sec_flags |= (BTM_SEC_LE_AUTHENTICATED | BTM_SEC_LE_ENCRYPTED); + } } /* It is possible that we decrypted the link to perform role switch */ @@ -4628,6 +4689,12 @@ void btm_sec_connected (UINT8 *bda, UINT16 handle, UINT8 status, UINT8 enc_mode) if (btm_cb.security_mode == BTM_SEC_MODE_LINK) p_dev_rec->sec_flags |= (BTM_SEC_AUTHENTICATED << bit_shift); + if (p_dev_rec->pin_code_length >= 16 || + p_dev_rec->link_key_type == BTM_LKEY_TYPE_AUTH_COMB || + p_dev_rec->link_key_type == BTM_LKEY_TYPE_AUTH_COMB_P_256) { + p_dev_rec->sec_flags |= (BTM_SEC_16_DIGIT_PIN_AUTHED << bit_shift); + } + p_dev_rec->link_key_changed = FALSE; /* After connection is established we perform security if we do not know */ @@ -4759,7 +4826,8 @@ void btm_sec_disconnected (UINT16 handle, UINT8 reason) #endif { p_dev_rec->hci_handle = BTM_SEC_INVALID_HANDLE; - p_dev_rec->sec_flags &= ~(BTM_SEC_AUTHORIZED | BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED | BTM_SEC_ROLE_SWITCHED); + p_dev_rec->sec_flags &= ~(BTM_SEC_AUTHORIZED | BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED + | BTM_SEC_ROLE_SWITCHED | BTM_SEC_16_DIGIT_PIN_AUTHED); } #if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE @@ -4819,6 +4887,17 @@ void btm_sec_link_key_notification (UINT8 *p_bda, UINT8 *p_link_key, UINT8 key_t p_dev_rec->link_key_type = key_type; p_dev_rec->sec_flags |= BTM_SEC_LINK_KEY_KNOWN; + + /* + * Until this point in time, we do not know if MITM was enabled, hence we + * add the extended security flag here. + */ + if (p_dev_rec->pin_code_length >= 16 || + p_dev_rec->link_key_type == BTM_LKEY_TYPE_AUTH_COMB || + p_dev_rec->link_key_type == BTM_LKEY_TYPE_AUTH_COMB_P_256) { + p_dev_rec->sec_flags |= BTM_SEC_16_DIGIT_PIN_AUTHED; + } + #if (BLE_INCLUDED == TRUE) /* BR/EDR connection, update the encryption key size to be 16 as always */ p_dev_rec->enc_key_size = 16; @@ -5119,7 +5198,7 @@ void btm_sec_pin_code_request (UINT8 *p_bda) else { btsnd_hcic_pin_code_req_reply (p_bda, btm_cb.pin_code_len_saved, p_cb->pin_code); - return; + return; } } else if ((btm_cb.pairing_state != BTM_PAIR_STATE_WAIT_PIN_REQ) @@ -5230,8 +5309,12 @@ void btm_sec_pin_code_request (UINT8 *p_bda) BTM_TRACE_EVENT ("btm_sec_pin_code_request going for callback"); btm_cb.pairing_flags |= BTM_PAIR_FLAGS_PIN_REQD; - if (p_cb->api.p_pin_callback) - (*p_cb->api.p_pin_callback) (p_bda, p_dev_rec->dev_class, p_dev_rec->sec_bd_name); + if (p_cb->api.p_pin_callback) { + (*p_cb->api.p_pin_callback) (p_bda, p_dev_rec->dev_class, p_dev_rec->sec_bd_name, + (p_dev_rec->p_cur_service == NULL) ? FALSE + : (p_dev_rec->p_cur_service->security_flags + & BTM_SEC_IN_MIN_16_DIGIT_PIN)); + } } else { @@ -5251,7 +5334,10 @@ void btm_sec_pin_code_request (UINT8 *p_bda) btm_cb.pairing_flags |= BTM_PAIR_FLAGS_PIN_REQD; if (p_cb->api.p_pin_callback) - (*p_cb->api.p_pin_callback) (p_bda, p_dev_rec->dev_class, p_dev_rec->sec_bd_name); + (*p_cb->api.p_pin_callback) (p_bda, p_dev_rec->dev_class, + p_dev_rec->sec_bd_name, (p_dev_rec->p_cur_service == NULL) ? FALSE + : (p_dev_rec->p_cur_service->security_flags + & BTM_SEC_IN_MIN_16_DIGIT_PIN)); } } } @@ -5327,11 +5413,21 @@ static tBTM_STATUS btm_sec_execute_procedure (tBTM_SEC_DEV_REC *p_dev_rec) /* If connection is not authenticated and authentication is required */ /* start authentication and return PENDING to the caller */ - if ((!(p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED)) + if ((((!(p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED)) && (( p_dev_rec->is_originator && (p_dev_rec->security_required & BTM_SEC_OUT_AUTHENTICATE)) - || (!p_dev_rec->is_originator && (p_dev_rec->security_required & BTM_SEC_IN_AUTHENTICATE))) + || (!p_dev_rec->is_originator && (p_dev_rec->security_required & BTM_SEC_IN_AUTHENTICATE)))) + || (!(p_dev_rec->sec_flags & BTM_SEC_16_DIGIT_PIN_AUTHED) + && (!p_dev_rec->is_originator + && (p_dev_rec->security_required & BTM_SEC_IN_MIN_16_DIGIT_PIN)))) && (p_dev_rec->hci_handle != BTM_SEC_INVALID_HANDLE)) { + /* + * We rely on BTM_SEC_16_DIGIT_PIN_AUTHED being set if MITM is in use, + * as 16 DIGIT is only needed if MITM is not used. Unfortunately, the + * BTM_SEC_AUTHENTICATED is used for both MITM and non-MITM + * authenticated connections, hence we cannot distinguish here. + */ + #if (L2CAP_UCD_INCLUDED == TRUE) /* if incoming UCD packet, discard it */ if ( !p_dev_rec->is_originator && (p_dev_rec->is_ucd == TRUE )) @@ -5340,6 +5436,25 @@ static tBTM_STATUS btm_sec_execute_procedure (tBTM_SEC_DEV_REC *p_dev_rec) BTM_TRACE_EVENT ("Security Manager: Start authentication"); + /* + * If we do have a link-key, but we end up here because we need an + * upgrade, then clear the link-key known and authenticated flag before + * restarting authentication. + * WARNING: If the controller has link-key, it is optional and + * recommended for the controller to send a Link_Key_Request. + * In case we need an upgrade, the only alternative would be to delete + * the existing link-key. That could lead to very bad user experience + * or even IOP issues, if a reconnect causes a new connection that + * requires an upgrade. + */ + if ((p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN) + && (!(p_dev_rec->sec_flags & BTM_SEC_16_DIGIT_PIN_AUTHED) + && (!p_dev_rec->is_originator && (p_dev_rec->security_required + & BTM_SEC_IN_MIN_16_DIGIT_PIN)))) { + p_dev_rec->sec_flags &= ~(BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_LINK_KEY_AUTHED + | BTM_SEC_AUTHENTICATED); + } + if (!btm_sec_start_authentication (p_dev_rec)) { return(BTM_NO_RESOURCES); @@ -5978,7 +6093,10 @@ static BOOLEAN btm_sec_check_prefetch_pin (tBTM_SEC_DEV_REC *p_dev_rec) BTM_TRACE_DEBUG("%s() PIN code callback called", __func__); if (btm_bda_to_acl(p_dev_rec->bd_addr, BT_TRANSPORT_BR_EDR) == NULL) btm_cb.pairing_flags |= BTM_PAIR_FLAGS_PIN_REQD; - (btm_cb.api.p_pin_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class, p_dev_rec->sec_bd_name); + (btm_cb.api.p_pin_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class, + p_dev_rec->sec_bd_name, (p_dev_rec->p_cur_service == NULL) ? FALSE + : (p_dev_rec->p_cur_service->security_flags + & BTM_SEC_IN_MIN_16_DIGIT_PIN)); } } diff --git a/stack/include/btm_api.h b/stack/include/btm_api.h index d83692d43..a7c3f9d01 100644 --- a/stack/include/btm_api.h +++ b/stack/include/btm_api.h @@ -1107,6 +1107,7 @@ typedef void (tBTM_ESCO_CBACK) (tBTM_ESCO_EVT event, tBTM_ESCO_EVT_DATA *p_data) #define BTM_SEC_ATTEMPT_SLAVE 0x0800 /* Try to switch connection to be slave */ #define BTM_SEC_IN_MITM 0x1000 /* inbound Do man in the middle protection */ #define BTM_SEC_OUT_MITM 0x2000 /* outbound Do man in the middle protection */ +#define BTM_SEC_IN_MIN_16_DIGIT_PIN 0x4000 /* enforce a minimum of 16 digit for sec mode 2 */ /* Security Flags [bit mask] (BTM_GetSecurityFlags) */ @@ -1321,9 +1322,10 @@ typedef UINT8 (tBTM_AUTHORIZE_CALLBACK) (BD_ADDR bd_addr, DEV_CLASS dev_class, ** BD Address of remote ** Device Class of remote ** BD Name of remote +** Flag indicating the minimum pin code length to be 16 digits */ typedef UINT8 (tBTM_PIN_CALLBACK) (BD_ADDR bd_addr, DEV_CLASS dev_class, - tBTM_BD_NAME bd_name); + tBTM_BD_NAME bd_name, BOOLEAN min_16_digit); /* New Link Key for the connection. Parameters are ** BD Address of remote @@ -3307,7 +3309,7 @@ extern UINT8 BTM_SecClrService (UINT8 service_id); extern BOOLEAN BTM_SecAddDevice (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name, UINT8 *features, UINT32 trusted_mask[], LINK_KEY link_key, - UINT8 key_type, tBTM_IO_CAP io_cap); + UINT8 key_type, tBTM_IO_CAP io_cap, UINT8 pin_length); /******************************************************************************* |