summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCasper Bonde <c.bonde@samsung.com>2015-05-21 11:08:45 +0200
committerPavlin Radoslavov <pavlin@google.com>2015-06-09 13:56:06 -0700
commit818d0f2afb10c75125b0df9ea2bce6108268a269 (patch)
tree3439f55ca3f82c9b7b6c62b60be272bcc09ac906
parent15d6b3144d92167d1f4f88cc87a50c2571a2c166 (diff)
downloadandroid_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.c11
-rw-r--r--bta/dm/bta_dm_api.c3
-rw-r--r--bta/dm/bta_dm_int.h1
-rw-r--r--bta/include/bta_api.h7
-rw-r--r--btif/src/btif_dm.c6
-rw-r--r--btif/src/btif_sock_l2cap.c4
-rw-r--r--btif/src/btif_sock_rfc.c2
-rw-r--r--btif/src/btif_storage.c5
-rw-r--r--stack/btm/btm_dev.c12
-rw-r--r--stack/btm/btm_int.h4
-rw-r--r--stack/btm/btm_sec.c150
-rw-r--r--stack/include/btm_api.h6
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);
/*******************************************************************************