diff options
-rw-r--r-- | net/bluetooth/smp.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index b12f076d78b1..f59f0510e0b0 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
@@ -1894,6 +1894,58 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) | |||
1894 | return 0; | 1894 | return 0; |
1895 | } | 1895 | } |
1896 | 1896 | ||
1897 | static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb) | ||
1898 | { | ||
1899 | struct smp_cmd_dhkey_check *check = (void *) skb->data; | ||
1900 | struct l2cap_chan *chan = conn->smp; | ||
1901 | struct hci_conn *hcon = conn->hcon; | ||
1902 | struct smp_chan *smp = chan->data; | ||
1903 | u8 a[7], b[7], *local_addr, *remote_addr; | ||
1904 | u8 io_cap[3], r[16], e[16]; | ||
1905 | int err; | ||
1906 | |||
1907 | BT_DBG("conn %p", conn); | ||
1908 | |||
1909 | if (skb->len < sizeof(*check)) | ||
1910 | return SMP_INVALID_PARAMS; | ||
1911 | |||
1912 | memcpy(a, &hcon->init_addr, 6); | ||
1913 | memcpy(b, &hcon->resp_addr, 6); | ||
1914 | a[6] = hcon->init_addr_type; | ||
1915 | b[6] = hcon->resp_addr_type; | ||
1916 | |||
1917 | if (hcon->out) { | ||
1918 | local_addr = a; | ||
1919 | remote_addr = b; | ||
1920 | memcpy(io_cap, &smp->prsp[1], 3); | ||
1921 | } else { | ||
1922 | local_addr = b; | ||
1923 | remote_addr = a; | ||
1924 | memcpy(io_cap, &smp->preq[1], 3); | ||
1925 | } | ||
1926 | |||
1927 | memset(r, 0, sizeof(r)); | ||
1928 | |||
1929 | err = smp_f6(smp->tfm_cmac, smp->mackey, smp->rrnd, smp->prnd, r, | ||
1930 | io_cap, remote_addr, local_addr, e); | ||
1931 | if (err) | ||
1932 | return SMP_UNSPECIFIED; | ||
1933 | |||
1934 | if (memcmp(check->e, e, 16)) | ||
1935 | return SMP_DHKEY_CHECK_FAILED; | ||
1936 | |||
1937 | smp->ltk = hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, | ||
1938 | SMP_LTK_P256, 0, smp->tk, smp->enc_key_size, | ||
1939 | 0, 0); | ||
1940 | |||
1941 | if (hcon->out) { | ||
1942 | hci_le_start_enc(hcon, 0, 0, smp->tk); | ||
1943 | hcon->enc_key_size = smp->enc_key_size; | ||
1944 | } | ||
1945 | |||
1946 | return 0; | ||
1947 | } | ||
1948 | |||
1897 | static int smp_sig_channel(struct l2cap_chan *chan, struct sk_buff *skb) | 1949 | static int smp_sig_channel(struct l2cap_chan *chan, struct sk_buff *skb) |
1898 | { | 1950 | { |
1899 | struct l2cap_conn *conn = chan->conn; | 1951 | struct l2cap_conn *conn = chan->conn; |
@@ -1982,6 +2034,10 @@ static int smp_sig_channel(struct l2cap_chan *chan, struct sk_buff *skb) | |||
1982 | reason = smp_cmd_public_key(conn, skb); | 2034 | reason = smp_cmd_public_key(conn, skb); |
1983 | break; | 2035 | break; |
1984 | 2036 | ||
2037 | case SMP_CMD_DHKEY_CHECK: | ||
2038 | reason = smp_cmd_dhkey_check(conn, skb); | ||
2039 | break; | ||
2040 | |||
1985 | default: | 2041 | default: |
1986 | BT_DBG("Unknown command code 0x%2.2x", code); | 2042 | BT_DBG("Unknown command code 0x%2.2x", code); |
1987 | reason = SMP_CMD_NOTSUPP; | 2043 | reason = SMP_CMD_NOTSUPP; |