diff options
Diffstat (limited to 'net/bluetooth/smp.c')
-rw-r--r-- | net/bluetooth/smp.c | 74 |
1 files changed, 69 insertions, 5 deletions
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 45e527d3c741..9e1193174064 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
@@ -661,6 +661,7 @@ static void smp_failure(struct l2cap_conn *conn, u8 reason) | |||
661 | #define REQ_PASSKEY 0x02 | 661 | #define REQ_PASSKEY 0x02 |
662 | #define CFM_PASSKEY 0x03 | 662 | #define CFM_PASSKEY 0x03 |
663 | #define REQ_OOB 0x04 | 663 | #define REQ_OOB 0x04 |
664 | #define DSP_PASSKEY 0x05 | ||
664 | #define OVERLAP 0xFF | 665 | #define OVERLAP 0xFF |
665 | 666 | ||
666 | static const u8 gen_method[5][5] = { | 667 | static const u8 gen_method[5][5] = { |
@@ -671,6 +672,14 @@ static const u8 gen_method[5][5] = { | |||
671 | { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP }, | 672 | { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP }, |
672 | }; | 673 | }; |
673 | 674 | ||
675 | static const u8 sc_method[5][5] = { | ||
676 | { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY }, | ||
677 | { JUST_WORKS, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY }, | ||
678 | { DSP_PASSKEY, DSP_PASSKEY, REQ_PASSKEY, JUST_WORKS, DSP_PASSKEY }, | ||
679 | { JUST_WORKS, JUST_CFM, JUST_WORKS, JUST_WORKS, JUST_CFM }, | ||
680 | { DSP_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY }, | ||
681 | }; | ||
682 | |||
674 | static u8 get_auth_method(struct smp_chan *smp, u8 local_io, u8 remote_io) | 683 | static u8 get_auth_method(struct smp_chan *smp, u8 local_io, u8 remote_io) |
675 | { | 684 | { |
676 | /* If either side has unknown io_caps, use JUST_CFM (which gets | 685 | /* If either side has unknown io_caps, use JUST_CFM (which gets |
@@ -680,6 +689,9 @@ static u8 get_auth_method(struct smp_chan *smp, u8 local_io, u8 remote_io) | |||
680 | remote_io > SMP_IO_KEYBOARD_DISPLAY) | 689 | remote_io > SMP_IO_KEYBOARD_DISPLAY) |
681 | return JUST_CFM; | 690 | return JUST_CFM; |
682 | 691 | ||
692 | if (test_bit(SMP_FLAG_SC, &smp->flags)) | ||
693 | return sc_method[remote_io][local_io]; | ||
694 | |||
683 | return gen_method[remote_io][local_io]; | 695 | return gen_method[remote_io][local_io]; |
684 | } | 696 | } |
685 | 697 | ||
@@ -1305,6 +1317,11 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
1305 | memcpy(&smp->preq[1], req, sizeof(*req)); | 1317 | memcpy(&smp->preq[1], req, sizeof(*req)); |
1306 | skb_pull(skb, sizeof(*req)); | 1318 | skb_pull(skb, sizeof(*req)); |
1307 | 1319 | ||
1320 | build_pairing_cmd(conn, req, &rsp, auth); | ||
1321 | |||
1322 | if (rsp.auth_req & SMP_AUTH_SC) | ||
1323 | set_bit(SMP_FLAG_SC, &smp->flags); | ||
1324 | |||
1308 | if (conn->hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT) | 1325 | if (conn->hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT) |
1309 | sec_level = BT_SECURITY_MEDIUM; | 1326 | sec_level = BT_SECURITY_MEDIUM; |
1310 | else | 1327 | else |
@@ -1323,11 +1340,6 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
1323 | return SMP_AUTH_REQUIREMENTS; | 1340 | return SMP_AUTH_REQUIREMENTS; |
1324 | } | 1341 | } |
1325 | 1342 | ||
1326 | build_pairing_cmd(conn, req, &rsp, auth); | ||
1327 | |||
1328 | if (rsp.auth_req & SMP_AUTH_SC) | ||
1329 | set_bit(SMP_FLAG_SC, &smp->flags); | ||
1330 | |||
1331 | key_size = min(req->max_key_size, rsp.max_key_size); | 1343 | key_size = min(req->max_key_size, rsp.max_key_size); |
1332 | if (check_enc_key_size(conn, key_size)) | 1344 | if (check_enc_key_size(conn, key_size)) |
1333 | return SMP_ENC_KEY_SIZE; | 1345 | return SMP_ENC_KEY_SIZE; |
@@ -1901,12 +1913,54 @@ static int smp_cmd_sign_info(struct l2cap_conn *conn, struct sk_buff *skb) | |||
1901 | return 0; | 1913 | return 0; |
1902 | } | 1914 | } |
1903 | 1915 | ||
1916 | static u8 sc_select_method(struct smp_chan *smp) | ||
1917 | { | ||
1918 | struct l2cap_conn *conn = smp->conn; | ||
1919 | struct hci_conn *hcon = conn->hcon; | ||
1920 | struct smp_cmd_pairing *local, *remote; | ||
1921 | u8 local_mitm, remote_mitm, local_io, remote_io, method; | ||
1922 | |||
1923 | /* The preq/prsp contain the raw Pairing Request/Response PDUs | ||
1924 | * which are needed as inputs to some crypto functions. To get | ||
1925 | * the "struct smp_cmd_pairing" from them we need to skip the | ||
1926 | * first byte which contains the opcode. | ||
1927 | */ | ||
1928 | if (hcon->out) { | ||
1929 | local = (void *) &smp->preq[1]; | ||
1930 | remote = (void *) &smp->prsp[1]; | ||
1931 | } else { | ||
1932 | local = (void *) &smp->prsp[1]; | ||
1933 | remote = (void *) &smp->preq[1]; | ||
1934 | } | ||
1935 | |||
1936 | local_io = local->io_capability; | ||
1937 | remote_io = remote->io_capability; | ||
1938 | |||
1939 | local_mitm = (local->auth_req & SMP_AUTH_MITM); | ||
1940 | remote_mitm = (remote->auth_req & SMP_AUTH_MITM); | ||
1941 | |||
1942 | /* If either side wants MITM, look up the method from the table, | ||
1943 | * otherwise use JUST WORKS. | ||
1944 | */ | ||
1945 | if (local_mitm || remote_mitm) | ||
1946 | method = get_auth_method(smp, local_io, remote_io); | ||
1947 | else | ||
1948 | method = JUST_WORKS; | ||
1949 | |||
1950 | /* Don't confirm locally initiated pairing attempts */ | ||
1951 | if (method == JUST_CFM && test_bit(SMP_FLAG_INITIATOR, &smp->flags)) | ||
1952 | method = JUST_WORKS; | ||
1953 | |||
1954 | return method; | ||
1955 | } | ||
1956 | |||
1904 | static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) | 1957 | static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) |
1905 | { | 1958 | { |
1906 | struct smp_cmd_public_key *key = (void *) skb->data; | 1959 | struct smp_cmd_public_key *key = (void *) skb->data; |
1907 | struct hci_conn *hcon = conn->hcon; | 1960 | struct hci_conn *hcon = conn->hcon; |
1908 | struct l2cap_chan *chan = conn->smp; | 1961 | struct l2cap_chan *chan = conn->smp; |
1909 | struct smp_chan *smp = chan->data; | 1962 | struct smp_chan *smp = chan->data; |
1963 | struct hci_dev *hdev = hcon->hdev; | ||
1910 | struct smp_cmd_pairing_confirm cfm; | 1964 | struct smp_cmd_pairing_confirm cfm; |
1911 | int err; | 1965 | int err; |
1912 | 1966 | ||
@@ -1936,6 +1990,16 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) | |||
1936 | 1990 | ||
1937 | set_bit(SMP_FLAG_REMOTE_PK, &smp->flags); | 1991 | set_bit(SMP_FLAG_REMOTE_PK, &smp->flags); |
1938 | 1992 | ||
1993 | smp->method = sc_select_method(smp); | ||
1994 | |||
1995 | BT_DBG("%s selected method 0x%02x", hdev->name, smp->method); | ||
1996 | |||
1997 | /* JUST_WORKS and JUST_CFM result in an unauthenticated key */ | ||
1998 | if (smp->method == JUST_WORKS || smp->method == JUST_CFM) | ||
1999 | hcon->pending_sec_level = BT_SECURITY_MEDIUM; | ||
2000 | else | ||
2001 | hcon->pending_sec_level = BT_SECURITY_FIPS; | ||
2002 | |||
1939 | /* The Initiating device waits for the non-initiating device to | 2003 | /* The Initiating device waits for the non-initiating device to |
1940 | * send the confirm value. | 2004 | * send the confirm value. |
1941 | */ | 2005 | */ |