Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
bb8f2cb2
K
Kernel
项目概览
openeuler
/
Kernel
1 年多 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
bb8f2cb2
编写于
13年前
作者:
J
John W. Linville
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' of
git://github.com/padovan/bluetooth-next
上级
ed46fdfc
ab0ff76d
变更
14
隐藏空白更改
内联
并排
Showing
14 changed file
with
538 addition
and
287 deletion
+538
-287
include/net/bluetooth/hci.h
include/net/bluetooth/hci.h
+10
-0
include/net/bluetooth/hci_core.h
include/net/bluetooth/hci_core.h
+21
-4
include/net/bluetooth/l2cap.h
include/net/bluetooth/l2cap.h
+1
-7
include/net/bluetooth/mgmt.h
include/net/bluetooth/mgmt.h
+16
-0
include/net/bluetooth/smp.h
include/net/bluetooth/smp.h
+17
-0
net/bluetooth/hci_conn.c
net/bluetooth/hci_conn.c
+1
-1
net/bluetooth/hci_core.c
net/bluetooth/hci_core.c
+23
-34
net/bluetooth/hci_event.c
net/bluetooth/hci_event.c
+8
-8
net/bluetooth/hci_sock.c
net/bluetooth/hci_sock.c
+16
-2
net/bluetooth/hci_sysfs.c
net/bluetooth/hci_sysfs.c
+2
-0
net/bluetooth/hidp/core.c
net/bluetooth/hidp/core.c
+3
-0
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_core.c
+14
-4
net/bluetooth/mgmt.c
net/bluetooth/mgmt.c
+152
-60
net/bluetooth/smp.c
net/bluetooth/smp.c
+254
-167
未找到文件。
include/net/bluetooth/hci.h
浏览文件 @
bb8f2cb2
...
...
@@ -716,6 +716,16 @@ struct hci_rp_read_bd_addr {
bdaddr_t
bdaddr
;
}
__packed
;
#define HCI_OP_WRITE_PAGE_SCAN_ACTIVITY 0x0c1c
struct
hci_cp_write_page_scan_activity
{
__le16
interval
;
__le16
window
;
}
__packed
;
#define HCI_OP_WRITE_PAGE_SCAN_TYPE 0x0c47
#define PAGE_SCAN_TYPE_STANDARD 0x00
#define PAGE_SCAN_TYPE_INTERLACED 0x01
#define HCI_OP_LE_SET_EVENT_MASK 0x2001
struct
hci_cp_le_set_event_mask
{
__u8
mask
[
8
];
...
...
This diff is collapsed.
Click to expand it.
include/net/bluetooth/hci_core.h
浏览文件 @
bb8f2cb2
...
...
@@ -195,8 +195,6 @@ struct hci_dev {
__u16
init_last_cmd
;
struct
crypto_blkcipher
*
tfm
;
struct
inquiry_cache
inq_cache
;
struct
hci_conn_hash
conn_hash
;
struct
list_head
blacklist
;
...
...
@@ -348,6 +346,7 @@ enum {
HCI_CONN_RSWITCH_PEND
,
HCI_CONN_MODE_CHANGE_PEND
,
HCI_CONN_SCO_SETUP_PEND
,
HCI_CONN_LE_SMP_PEND
,
};
static
inline
void
hci_conn_hash_init
(
struct
hci_dev
*
hdev
)
...
...
@@ -395,6 +394,22 @@ static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c)
}
}
static
inline
unsigned
int
hci_conn_num
(
struct
hci_dev
*
hdev
,
__u8
type
)
{
struct
hci_conn_hash
*
h
=
&
hdev
->
conn_hash
;
switch
(
type
)
{
case
ACL_LINK
:
return
h
->
acl_num
;
case
LE_LINK
:
return
h
->
le_num
;
case
SCO_LINK
:
case
ESCO_LINK
:
return
h
->
sco_num
;
default:
return
0
;
}
}
static
inline
struct
hci_conn
*
hci_conn_hash_lookup_handle
(
struct
hci_dev
*
hdev
,
__u16
handle
)
{
...
...
@@ -475,7 +490,7 @@ static inline void hci_conn_put(struct hci_conn *conn)
{
if
(
atomic_dec_and_test
(
&
conn
->
refcnt
))
{
unsigned
long
timeo
;
if
(
conn
->
type
==
ACL_LINK
)
{
if
(
conn
->
type
==
ACL_LINK
||
conn
->
type
==
LE_LINK
)
{
del_timer
(
&
conn
->
idle_timer
);
if
(
conn
->
state
==
BT_CONNECTED
)
{
timeo
=
msecs_to_jiffies
(
conn
->
disc_timeout
);
...
...
@@ -838,7 +853,7 @@ int mgmt_powered(u16 index, u8 powered);
int
mgmt_discoverable
(
u16
index
,
u8
discoverable
);
int
mgmt_connectable
(
u16
index
,
u8
connectable
);
int
mgmt_new_key
(
u16
index
,
struct
link_key
*
key
,
u8
persistent
);
int
mgmt_connected
(
u16
index
,
bdaddr_t
*
bdaddr
);
int
mgmt_connected
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
link_type
);
int
mgmt_disconnected
(
u16
index
,
bdaddr_t
*
bdaddr
);
int
mgmt_disconnect_failed
(
u16
index
);
int
mgmt_connect_failed
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
status
);
...
...
@@ -858,6 +873,8 @@ int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi,
u8
*
eir
);
int
mgmt_remote_name
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
*
name
);
int
mgmt_discovering
(
u16
index
,
u8
discovering
);
int
mgmt_device_blocked
(
u16
index
,
bdaddr_t
*
bdaddr
);
int
mgmt_device_unblocked
(
u16
index
,
bdaddr_t
*
bdaddr
);
/* HCI info for socket */
#define hci_pi(sk) ((struct hci_pinfo *) sk)
...
...
This diff is collapsed.
Click to expand it.
include/net/bluetooth/l2cap.h
浏览文件 @
bb8f2cb2
...
...
@@ -409,14 +409,8 @@ struct l2cap_conn {
__u8
disc_reason
;
__u8
preq
[
7
];
/* SMP Pairing Request */
__u8
prsp
[
7
];
/* SMP Pairing Response */
__u8
prnd
[
16
];
/* SMP Pairing Random */
__u8
pcnf
[
16
];
/* SMP Pairing Confirm */
__u8
tk
[
16
];
/* SMP Temporary Key */
__u8
smp_key_size
;
struct
timer_list
security_timer
;
struct
smp_chan
*
smp_chan
;
struct
list_head
chan_l
;
rwlock_t
chan_lock
;
...
...
This diff is collapsed.
Click to expand it.
include/net/bluetooth/mgmt.h
浏览文件 @
bb8f2cb2
...
...
@@ -211,6 +211,11 @@ struct mgmt_cp_unblock_device {
bdaddr_t
bdaddr
;
}
__packed
;
#define MGMT_OP_SET_FAST_CONNECTABLE 0x001F
struct
mgmt_cp_set_fast_connectable
{
__u8
enable
;
}
__packed
;
#define MGMT_EV_CMD_COMPLETE 0x0001
struct
mgmt_ev_cmd_complete
{
__le16
opcode
;
...
...
@@ -249,6 +254,7 @@ struct mgmt_ev_new_key {
#define MGMT_EV_CONNECTED 0x000B
struct
mgmt_ev_connected
{
bdaddr_t
bdaddr
;
__u8
link_type
;
}
__packed
;
#define MGMT_EV_DISCONNECTED 0x000C
...
...
@@ -301,3 +307,13 @@ struct mgmt_ev_remote_name {
}
__packed
;
#define MGMT_EV_DISCOVERING 0x0014
#define MGMT_EV_DEVICE_BLOCKED 0x0015
struct
mgmt_ev_device_blocked
{
bdaddr_t
bdaddr
;
}
__packed
;
#define MGMT_EV_DEVICE_UNBLOCKED 0x0016
struct
mgmt_ev_device_unblocked
{
bdaddr_t
bdaddr
;
}
__packed
;
This diff is collapsed.
Click to expand it.
include/net/bluetooth/smp.h
浏览文件 @
bb8f2cb2
...
...
@@ -115,9 +115,26 @@ struct smp_cmd_security_req {
#define SMP_MIN_ENC_KEY_SIZE 7
#define SMP_MAX_ENC_KEY_SIZE 16
struct
smp_chan
{
struct
l2cap_conn
*
conn
;
u8
preq
[
7
];
/* SMP Pairing Request */
u8
prsp
[
7
];
/* SMP Pairing Response */
u8
prnd
[
16
];
/* SMP Pairing Random (local) */
u8
rrnd
[
16
];
/* SMP Pairing Random (remote) */
u8
pcnf
[
16
];
/* SMP Pairing Confirm */
u8
tk
[
16
];
/* SMP Temporary Key */
u8
smp_key_size
;
struct
crypto_blkcipher
*
tfm
;
struct
work_struct
confirm
;
struct
work_struct
random
;
};
/* SMP Commands */
int
smp_conn_security
(
struct
l2cap_conn
*
conn
,
__u8
sec_level
);
int
smp_sig_channel
(
struct
l2cap_conn
*
conn
,
struct
sk_buff
*
skb
);
int
smp_distribute_keys
(
struct
l2cap_conn
*
conn
,
__u8
force
);
void
smp_chan_destroy
(
struct
l2cap_conn
*
conn
);
#endif
/* __SMP_H */
This diff is collapsed.
Click to expand it.
net/bluetooth/hci_conn.c
浏览文件 @
bb8f2cb2
...
...
@@ -218,7 +218,7 @@ void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
cp
.
handle
=
cpu_to_le16
(
conn
->
handle
);
memcpy
(
cp
.
ltk
,
ltk
,
sizeof
(
cp
.
ltk
));
cp
.
ediv
=
ediv
;
memcpy
(
cp
.
rand
,
rand
,
sizeof
(
rand
));
memcpy
(
cp
.
rand
,
rand
,
sizeof
(
cp
.
rand
));
hci_send_cmd
(
hdev
,
HCI_OP_LE_START_ENC
,
sizeof
(
cp
),
&
cp
);
}
...
...
This diff is collapsed.
Click to expand it.
net/bluetooth/hci_core.c
浏览文件 @
bb8f2cb2
...
...
@@ -1312,59 +1312,41 @@ int hci_blacklist_clear(struct hci_dev *hdev)
int
hci_blacklist_add
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
)
{
struct
bdaddr_list
*
entry
;
int
err
;
if
(
bacmp
(
bdaddr
,
BDADDR_ANY
)
==
0
)
return
-
EBADF
;
hci_dev_lock_bh
(
hdev
);
if
(
hci_blacklist_lookup
(
hdev
,
bdaddr
))
{
err
=
-
EEXIST
;
goto
err
;
}
if
(
hci_blacklist_lookup
(
hdev
,
bdaddr
))
return
-
EEXIST
;
entry
=
kzalloc
(
sizeof
(
struct
bdaddr_list
),
GFP_KERNEL
);
if
(
!
entry
)
{
err
=
-
ENOMEM
;
goto
err
;
}
if
(
!
entry
)
return
-
ENOMEM
;
bacpy
(
&
entry
->
bdaddr
,
bdaddr
);
list_add
(
&
entry
->
list
,
&
hdev
->
blacklist
);
err
=
0
;
err:
hci_dev_unlock_bh
(
hdev
);
return
err
;
return
mgmt_device_blocked
(
hdev
->
id
,
bdaddr
);
}
int
hci_blacklist_del
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
)
{
struct
bdaddr_list
*
entry
;
int
err
=
0
;
hci_dev_lock_bh
(
hdev
);
if
(
bacmp
(
bdaddr
,
BDADDR_ANY
)
==
0
)
{
hci_blacklist_clear
(
hdev
);
goto
done
;
return
hci_blacklist_clear
(
hdev
);
}
entry
=
hci_blacklist_lookup
(
hdev
,
bdaddr
);
if
(
!
entry
)
{
err
=
-
ENOENT
;
goto
done
;
return
-
ENOENT
;
}
list_del
(
&
entry
->
list
);
kfree
(
entry
);
done:
hci_dev_unlock_bh
(
hdev
);
return
err
;
return
mgmt_device_unblocked
(
hdev
->
id
,
bdaddr
);
}
static
void
hci_clear_adv_cache
(
unsigned
long
arg
)
...
...
@@ -1523,11 +1505,6 @@ int hci_register_dev(struct hci_dev *hdev)
if
(
!
hdev
->
workqueue
)
goto
nomem
;
hdev
->
tfm
=
crypto_alloc_blkcipher
(
"ecb(aes)"
,
0
,
CRYPTO_ALG_ASYNC
);
if
(
IS_ERR
(
hdev
->
tfm
))
BT_INFO
(
"Failed to load transform for ecb(aes): %ld"
,
PTR_ERR
(
hdev
->
tfm
));
hci_register_sysfs
(
hdev
);
hdev
->
rfkill
=
rfkill_alloc
(
hdev
->
name
,
&
hdev
->
dev
,
...
...
@@ -1576,9 +1553,6 @@ int hci_unregister_dev(struct hci_dev *hdev)
!
test_bit
(
HCI_SETUP
,
&
hdev
->
flags
))
mgmt_index_removed
(
hdev
->
id
);
if
(
!
IS_ERR
(
hdev
->
tfm
))
crypto_free_blkcipher
(
hdev
->
tfm
);
hci_notify
(
hdev
,
HCI_DEV_UNREG
);
if
(
hdev
->
rfkill
)
{
...
...
@@ -2074,6 +2048,9 @@ static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int
min
=
c
->
sent
;
conn
=
c
;
}
if
(
hci_conn_num
(
hdev
,
type
)
==
num
)
break
;
}
if
(
conn
)
{
...
...
@@ -2131,6 +2108,9 @@ static inline void hci_sched_acl(struct hci_dev *hdev)
BT_DBG
(
"%s"
,
hdev
->
name
);
if
(
!
hci_conn_num
(
hdev
,
ACL_LINK
))
return
;
if
(
!
test_bit
(
HCI_RAW
,
&
hdev
->
flags
))
{
/* ACL tx timeout must be longer than maximum
* link supervision timeout (40.9 seconds) */
...
...
@@ -2162,6 +2142,9 @@ static inline void hci_sched_sco(struct hci_dev *hdev)
BT_DBG
(
"%s"
,
hdev
->
name
);
if
(
!
hci_conn_num
(
hdev
,
SCO_LINK
))
return
;
while
(
hdev
->
sco_cnt
&&
(
conn
=
hci_low_sent
(
hdev
,
SCO_LINK
,
&
quote
)))
{
while
(
quote
--
&&
(
skb
=
skb_dequeue
(
&
conn
->
data_q
)))
{
BT_DBG
(
"skb %p len %d"
,
skb
,
skb
->
len
);
...
...
@@ -2182,6 +2165,9 @@ static inline void hci_sched_esco(struct hci_dev *hdev)
BT_DBG
(
"%s"
,
hdev
->
name
);
if
(
!
hci_conn_num
(
hdev
,
ESCO_LINK
))
return
;
while
(
hdev
->
sco_cnt
&&
(
conn
=
hci_low_sent
(
hdev
,
ESCO_LINK
,
&
quote
)))
{
while
(
quote
--
&&
(
skb
=
skb_dequeue
(
&
conn
->
data_q
)))
{
BT_DBG
(
"skb %p len %d"
,
skb
,
skb
->
len
);
...
...
@@ -2202,6 +2188,9 @@ static inline void hci_sched_le(struct hci_dev *hdev)
BT_DBG
(
"%s"
,
hdev
->
name
);
if
(
!
hci_conn_num
(
hdev
,
LE_LINK
))
return
;
if
(
!
test_bit
(
HCI_RAW
,
&
hdev
->
flags
))
{
/* LE tx timeout must be longer than maximum
* link supervision timeout (40.9 seconds) */
...
...
This diff is collapsed.
Click to expand it.
net/bluetooth/hci_event.c
浏览文件 @
bb8f2cb2
...
...
@@ -898,16 +898,15 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
if
(
!
cp
)
return
;
hci_dev_lock
(
hdev
);
if
(
cp
->
enable
==
0x01
)
{
del_timer
(
&
hdev
->
adv_timer
);
hci_dev_lock
(
hdev
);
hci_adv_entries_clear
(
hdev
);
hci_dev_unlock
(
hdev
);
}
else
if
(
cp
->
enable
==
0x00
)
{
mod_timer
(
&
hdev
->
adv_timer
,
jiffies
+
ADV_CLEAR_TIMEOUT
);
}
hci_dev_unlock
(
hdev
);
}
static
void
hci_cc_le_ltk_reply
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
...
...
@@ -1103,9 +1102,10 @@ static int hci_outgoing_auth_needed(struct hci_dev *hdev,
return
0
;
/* Only request authentication for SSP connections or non-SSP
* devices with sec_level HIGH */
* devices with sec_level HIGH
or if MITM protection is requested
*/
if
(
!
(
hdev
->
ssp_mode
>
0
&&
conn
->
ssp_mode
>
0
)
&&
conn
->
pending_sec_level
!=
BT_SECURITY_HIGH
)
conn
->
pending_sec_level
!=
BT_SECURITY_HIGH
&&
!
(
conn
->
auth_type
&
0x01
))
return
0
;
return
1
;
...
...
@@ -1412,7 +1412,7 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
conn
->
state
=
BT_CONFIG
;
hci_conn_hold
(
conn
);
conn
->
disc_timeout
=
HCI_DISCONN_TIMEOUT
;
mgmt_connected
(
hdev
->
id
,
&
ev
->
bdaddr
);
mgmt_connected
(
hdev
->
id
,
&
ev
->
bdaddr
,
conn
->
type
);
}
else
conn
->
state
=
BT_CONNECTED
;
...
...
@@ -2816,7 +2816,7 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff
goto
unlock
;
}
mgmt_connected
(
hdev
->
id
,
&
ev
->
bdaddr
);
mgmt_connected
(
hdev
->
id
,
&
ev
->
bdaddr
,
conn
->
type
);
conn
->
sec_level
=
BT_SECURITY_LOW
;
conn
->
handle
=
__le16_to_cpu
(
ev
->
handle
);
...
...
This diff is collapsed.
Click to expand it.
net/bluetooth/hci_sock.c
浏览文件 @
bb8f2cb2
...
...
@@ -183,21 +183,35 @@ static int hci_sock_release(struct socket *sock)
static
int
hci_sock_blacklist_add
(
struct
hci_dev
*
hdev
,
void
__user
*
arg
)
{
bdaddr_t
bdaddr
;
int
err
;
if
(
copy_from_user
(
&
bdaddr
,
arg
,
sizeof
(
bdaddr
)))
return
-
EFAULT
;
return
hci_blacklist_add
(
hdev
,
&
bdaddr
);
hci_dev_lock_bh
(
hdev
);
err
=
hci_blacklist_add
(
hdev
,
&
bdaddr
);
hci_dev_unlock_bh
(
hdev
);
return
err
;
}
static
int
hci_sock_blacklist_del
(
struct
hci_dev
*
hdev
,
void
__user
*
arg
)
{
bdaddr_t
bdaddr
;
int
err
;
if
(
copy_from_user
(
&
bdaddr
,
arg
,
sizeof
(
bdaddr
)))
return
-
EFAULT
;
return
hci_blacklist_del
(
hdev
,
&
bdaddr
);
hci_dev_lock_bh
(
hdev
);
err
=
hci_blacklist_del
(
hdev
,
&
bdaddr
);
hci_dev_unlock_bh
(
hdev
);
return
err
;
}
/* Ioctls that require bound socket */
...
...
This diff is collapsed.
Click to expand it.
net/bluetooth/hci_sysfs.c
浏览文件 @
bb8f2cb2
...
...
@@ -23,6 +23,8 @@ static inline char *link_typetostr(int type)
return
"SCO"
;
case
ESCO_LINK
:
return
"eSCO"
;
case
LE_LINK
:
return
"LE"
;
default:
return
"UNKNOWN"
;
}
...
...
This diff is collapsed.
Click to expand it.
net/bluetooth/hidp/core.c
浏览文件 @
bb8f2cb2
...
...
@@ -872,6 +872,9 @@ static int hidp_start(struct hid_device *hid)
struct
hidp_session
*
session
=
hid
->
driver_data
;
struct
hid_report
*
report
;
if
(
hid
->
quirks
&
HID_QUIRK_NO_INIT_REPORTS
)
return
0
;
list_for_each_entry
(
report
,
&
hid
->
report_enum
[
HID_INPUT_REPORT
].
report_list
,
list
)
hidp_send_report
(
session
,
report
);
...
...
This diff is collapsed.
Click to expand it.
net/bluetooth/l2cap_core.c
浏览文件 @
bb8f2cb2
...
...
@@ -907,6 +907,9 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
if
(
!
conn
->
hcon
->
out
&&
conn
->
hcon
->
type
==
LE_LINK
)
l2cap_le_conn_ready
(
conn
);
if
(
conn
->
hcon
->
out
&&
conn
->
hcon
->
type
==
LE_LINK
)
smp_conn_security
(
conn
,
conn
->
hcon
->
pending_sec_level
);
read_lock
(
&
conn
->
chan_lock
);
list_for_each_entry
(
chan
,
&
conn
->
chan_l
,
list
)
{
...
...
@@ -986,8 +989,10 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
if
(
conn
->
info_state
&
L2CAP_INFO_FEAT_MASK_REQ_SENT
)
del_timer_sync
(
&
conn
->
info_timer
);
if
(
test_
bit
(
HCI_CONN_ENCRYPT_PEND
,
&
hcon
->
pend
))
if
(
test_
and_clear_bit
(
HCI_CONN_LE_SMP_PEND
,
&
hcon
->
pend
))
{
del_timer
(
&
conn
->
security_timer
);
smp_chan_destroy
(
conn
);
}
hcon
->
l2cap_data
=
NULL
;
kfree
(
conn
);
...
...
@@ -1519,7 +1524,9 @@ struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *m
return
skb
;
}
struct
sk_buff
*
l2cap_create_iframe_pdu
(
struct
l2cap_chan
*
chan
,
struct
msghdr
*
msg
,
size_t
len
,
u16
control
,
u16
sdulen
)
static
struct
sk_buff
*
l2cap_create_iframe_pdu
(
struct
l2cap_chan
*
chan
,
struct
msghdr
*
msg
,
size_t
len
,
u16
control
,
u16
sdulen
)
{
struct
sock
*
sk
=
chan
->
sk
;
struct
l2cap_conn
*
conn
=
chan
->
conn
;
...
...
@@ -4093,6 +4100,11 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
BT_DBG
(
"conn %p"
,
conn
);
if
(
hcon
->
type
==
LE_LINK
)
{
smp_distribute_keys
(
conn
,
0
);
del_timer
(
&
conn
->
security_timer
);
}
read_lock
(
&
conn
->
chan_lock
);
list_for_each_entry
(
chan
,
&
conn
->
chan_l
,
list
)
{
...
...
@@ -4105,9 +4117,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
if
(
chan
->
scid
==
L2CAP_CID_LE_DATA
)
{
if
(
!
status
&&
encrypt
)
{
chan
->
sec_level
=
hcon
->
sec_level
;
del_timer
(
&
conn
->
security_timer
);
l2cap_chan_ready
(
sk
);
smp_distribute_keys
(
conn
,
0
);
}
bh_unlock_sock
(
sk
);
...
...
This diff is collapsed.
Click to expand it.
net/bluetooth/mgmt.c
浏览文件 @
bb8f2cb2
...
...
@@ -908,7 +908,7 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len)
struct
hci_dev
*
hdev
;
struct
mgmt_cp_load_keys
*
cp
;
u16
key_count
,
expected_len
;
int
i
,
err
;
int
i
;
cp
=
(
void
*
)
data
;
...
...
@@ -918,9 +918,9 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len)
key_count
=
get_unaligned_le16
(
&
cp
->
key_count
);
expected_len
=
sizeof
(
*
cp
)
+
key_count
*
sizeof
(
struct
mgmt_key_info
);
if
(
expected_len
>
len
)
{
BT_ERR
(
"load_keys: expected
at least
%u bytes, got %u bytes"
,
expected_len
,
len
);
if
(
expected_len
!=
len
)
{
BT_ERR
(
"load_keys: expected %u bytes, got %u bytes"
,
len
,
expected_
len
);
return
-
EINVAL
;
}
...
...
@@ -942,36 +942,17 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len)
else
clear_bit
(
HCI_DEBUG_KEYS
,
&
hdev
->
flags
);
len
-=
sizeof
(
*
cp
);
i
=
0
;
while
(
i
<
len
)
{
struct
mgmt_key_info
*
key
=
(
void
*
)
cp
->
keys
+
i
;
i
+=
sizeof
(
*
key
)
+
key
->
dlen
;
if
(
key
->
type
==
HCI_LK_SMP_LTK
)
{
struct
key_master_id
*
id
=
(
void
*
)
key
->
data
;
if
(
key
->
dlen
!=
sizeof
(
struct
key_master_id
))
continue
;
hci_add_ltk
(
hdev
,
0
,
&
key
->
bdaddr
,
key
->
pin_len
,
id
->
ediv
,
id
->
rand
,
key
->
val
);
continue
;
}
for
(
i
=
0
;
i
<
key_count
;
i
++
)
{
struct
mgmt_key_info
*
key
=
&
cp
->
keys
[
i
];
hci_add_link_key
(
hdev
,
NULL
,
0
,
&
key
->
bdaddr
,
key
->
val
,
key
->
type
,
key
->
pin_len
);
}
err
=
cmd_complete
(
sk
,
index
,
MGMT_OP_LOAD_KEYS
,
NULL
,
0
);
hci_dev_unlock_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
return
0
;
}
static
int
remove_key
(
struct
sock
*
sk
,
u16
index
,
unsigned
char
*
data
,
u16
len
)
...
...
@@ -1347,6 +1328,7 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len)
struct
hci_dev
*
hdev
;
struct
mgmt_cp_pair_device
*
cp
;
struct
pending_cmd
*
cmd
;
struct
adv_entry
*
entry
;
u8
sec_level
,
auth_type
;
struct
hci_conn
*
conn
;
int
err
;
...
...
@@ -1364,15 +1346,20 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len)
hci_dev_lock_bh
(
hdev
);
if
(
cp
->
io_cap
==
0x03
)
{
sec_level
=
BT_SECURITY_MEDIUM
;
sec_level
=
BT_SECURITY_MEDIUM
;
if
(
cp
->
io_cap
==
0x03
)
auth_type
=
HCI_AT_DEDICATED_BONDING
;
}
else
{
sec_level
=
BT_SECURITY_HIGH
;
else
auth_type
=
HCI_AT_DEDICATED_BONDING_MITM
;
}
conn
=
hci_connect
(
hdev
,
ACL_LINK
,
&
cp
->
bdaddr
,
sec_level
,
auth_type
);
entry
=
hci_find_adv_entry
(
hdev
,
&
cp
->
bdaddr
);
if
(
entry
)
conn
=
hci_connect
(
hdev
,
LE_LINK
,
&
cp
->
bdaddr
,
sec_level
,
auth_type
);
else
conn
=
hci_connect
(
hdev
,
ACL_LINK
,
&
cp
->
bdaddr
,
sec_level
,
auth_type
);
if
(
IS_ERR
(
conn
))
{
err
=
PTR_ERR
(
conn
);
goto
unlock
;
...
...
@@ -1391,7 +1378,10 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len)
goto
unlock
;
}
conn
->
connect_cfm_cb
=
pairing_complete_cb
;
/* For LE, just connecting isn't a proof that the pairing finished */
if
(
!
entry
)
conn
->
connect_cfm_cb
=
pairing_complete_cb
;
conn
->
security_cfm_cb
=
pairing_complete_cb
;
conn
->
disconn_cfm_cb
=
pairing_complete_cb
;
conn
->
io_capability
=
cp
->
io_cap
;
...
...
@@ -1689,13 +1679,12 @@ static int block_device(struct sock *sk, u16 index, unsigned char *data,
u16
len
)
{
struct
hci_dev
*
hdev
;
struct
mgmt_cp_block_device
*
cp
;
struct
pending_cmd
*
cmd
;
struct
mgmt_cp_block_device
*
cp
=
(
void
*
)
data
;
int
err
;
BT_DBG
(
"hci%u"
,
index
);
cp
=
(
void
*
)
data
;
if
(
len
!=
sizeof
(
*
cp
))
return
cmd_status
(
sk
,
index
,
MGMT_OP_BLOCK_DEVICE
,
EINVAL
);
...
...
@@ -1705,6 +1694,14 @@ static int block_device(struct sock *sk, u16 index, unsigned char *data,
return
cmd_status
(
sk
,
index
,
MGMT_OP_BLOCK_DEVICE
,
ENODEV
);
hci_dev_lock_bh
(
hdev
);
cmd
=
mgmt_pending_add
(
sk
,
MGMT_OP_BLOCK_DEVICE
,
index
,
NULL
,
0
);
if
(
!
cmd
)
{
err
=
-
ENOMEM
;
goto
failed
;
}
err
=
hci_blacklist_add
(
hdev
,
&
cp
->
bdaddr
);
if
(
err
<
0
)
...
...
@@ -1712,6 +1709,11 @@ static int block_device(struct sock *sk, u16 index, unsigned char *data,
else
err
=
cmd_complete
(
sk
,
index
,
MGMT_OP_BLOCK_DEVICE
,
NULL
,
0
);
mgmt_pending_remove
(
cmd
);
failed:
hci_dev_unlock_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
...
...
@@ -1721,13 +1723,12 @@ static int unblock_device(struct sock *sk, u16 index, unsigned char *data,
u16
len
)
{
struct
hci_dev
*
hdev
;
struct
mgmt_cp_unblock_device
*
cp
;
struct
pending_cmd
*
cmd
;
struct
mgmt_cp_unblock_device
*
cp
=
(
void
*
)
data
;
int
err
;
BT_DBG
(
"hci%u"
,
index
);
cp
=
(
void
*
)
data
;
if
(
len
!=
sizeof
(
*
cp
))
return
cmd_status
(
sk
,
index
,
MGMT_OP_UNBLOCK_DEVICE
,
EINVAL
);
...
...
@@ -1737,6 +1738,14 @@ static int unblock_device(struct sock *sk, u16 index, unsigned char *data,
return
cmd_status
(
sk
,
index
,
MGMT_OP_UNBLOCK_DEVICE
,
ENODEV
);
hci_dev_lock_bh
(
hdev
);
cmd
=
mgmt_pending_add
(
sk
,
MGMT_OP_UNBLOCK_DEVICE
,
index
,
NULL
,
0
);
if
(
!
cmd
)
{
err
=
-
ENOMEM
;
goto
failed
;
}
err
=
hci_blacklist_del
(
hdev
,
&
cp
->
bdaddr
);
if
(
err
<
0
)
...
...
@@ -1744,6 +1753,67 @@ static int unblock_device(struct sock *sk, u16 index, unsigned char *data,
else
err
=
cmd_complete
(
sk
,
index
,
MGMT_OP_UNBLOCK_DEVICE
,
NULL
,
0
);
mgmt_pending_remove
(
cmd
);
failed:
hci_dev_unlock_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
}
static
int
set_fast_connectable
(
struct
sock
*
sk
,
u16
index
,
unsigned
char
*
data
,
u16
len
)
{
struct
hci_dev
*
hdev
;
struct
mgmt_cp_set_fast_connectable
*
cp
=
(
void
*
)
data
;
struct
hci_cp_write_page_scan_activity
acp
;
u8
type
;
int
err
;
BT_DBG
(
"hci%u"
,
index
);
if
(
len
!=
sizeof
(
*
cp
))
return
cmd_status
(
sk
,
index
,
MGMT_OP_SET_FAST_CONNECTABLE
,
EINVAL
);
hdev
=
hci_dev_get
(
index
);
if
(
!
hdev
)
return
cmd_status
(
sk
,
index
,
MGMT_OP_SET_FAST_CONNECTABLE
,
ENODEV
);
hci_dev_lock
(
hdev
);
if
(
cp
->
enable
)
{
type
=
PAGE_SCAN_TYPE_INTERLACED
;
acp
.
interval
=
0x0024
;
/* 22.5 msec page scan interval */
}
else
{
type
=
PAGE_SCAN_TYPE_STANDARD
;
/* default */
acp
.
interval
=
0x0800
;
/* default 1.28 sec page scan */
}
acp
.
window
=
0x0012
;
/* default 11.25 msec page scan window */
err
=
hci_send_cmd
(
hdev
,
HCI_OP_WRITE_PAGE_SCAN_ACTIVITY
,
sizeof
(
acp
),
&
acp
);
if
(
err
<
0
)
{
err
=
cmd_status
(
sk
,
index
,
MGMT_OP_SET_FAST_CONNECTABLE
,
-
err
);
goto
done
;
}
err
=
hci_send_cmd
(
hdev
,
HCI_OP_WRITE_PAGE_SCAN_TYPE
,
1
,
&
type
);
if
(
err
<
0
)
{
err
=
cmd_status
(
sk
,
index
,
MGMT_OP_SET_FAST_CONNECTABLE
,
-
err
);
goto
done
;
}
err
=
cmd_complete
(
sk
,
index
,
MGMT_OP_SET_FAST_CONNECTABLE
,
NULL
,
0
);
done:
hci_dev_unlock
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
...
...
@@ -1869,6 +1939,10 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
case
MGMT_OP_UNBLOCK_DEVICE
:
err
=
unblock_device
(
sk
,
index
,
buf
+
sizeof
(
*
hdr
),
len
);
break
;
case
MGMT_OP_SET_FAST_CONNECTABLE
:
err
=
set_fast_connectable
(
sk
,
index
,
buf
+
sizeof
(
*
hdr
),
len
);
break
;
default:
BT_DBG
(
"Unknown op %u"
,
opcode
);
err
=
cmd_status
(
sk
,
index
,
opcode
,
0x01
);
...
...
@@ -1977,35 +2051,25 @@ int mgmt_connectable(u16 index, u8 connectable)
int
mgmt_new_key
(
u16
index
,
struct
link_key
*
key
,
u8
persistent
)
{
struct
mgmt_ev_new_key
*
ev
;
int
err
,
total
;
total
=
sizeof
(
struct
mgmt_ev_new_key
)
+
key
->
dlen
;
ev
=
kzalloc
(
total
,
GFP_ATOMIC
);
if
(
!
ev
)
return
-
ENOMEM
;
bacpy
(
&
ev
->
key
.
bdaddr
,
&
key
->
bdaddr
);
ev
->
key
.
type
=
key
->
type
;
memcpy
(
ev
->
key
.
val
,
key
->
val
,
16
);
ev
->
key
.
pin_len
=
key
->
pin_len
;
ev
->
key
.
dlen
=
key
->
dlen
;
ev
->
store_hint
=
persistent
;
struct
mgmt_ev_new_key
ev
;
memcpy
(
ev
->
key
.
data
,
key
->
data
,
key
->
dlen
);
err
=
mgmt_event
(
MGMT_EV_NEW_KEY
,
index
,
ev
,
total
,
NULL
);
memset
(
&
ev
,
0
,
sizeof
(
ev
));
kfree
(
ev
);
ev
.
store_hint
=
persistent
;
bacpy
(
&
ev
.
key
.
bdaddr
,
&
key
->
bdaddr
);
ev
.
key
.
type
=
key
->
type
;
memcpy
(
ev
.
key
.
val
,
key
->
val
,
16
);
ev
.
key
.
pin_len
=
key
->
pin_len
;
return
err
;
return
mgmt_event
(
MGMT_EV_NEW_KEY
,
index
,
&
ev
,
sizeof
(
ev
),
NULL
)
;
}
int
mgmt_connected
(
u16
index
,
bdaddr_t
*
bdaddr
)
int
mgmt_connected
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
link_type
)
{
struct
mgmt_ev_connected
ev
;
bacpy
(
&
ev
.
bdaddr
,
bdaddr
);
ev
.
link_type
=
link_type
;
return
mgmt_event
(
MGMT_EV_CONNECTED
,
index
,
&
ev
,
sizeof
(
ev
),
NULL
);
}
...
...
@@ -2260,12 +2324,14 @@ int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi,
memset
(
&
ev
,
0
,
sizeof
(
ev
));
bacpy
(
&
ev
.
bdaddr
,
bdaddr
);
memcpy
(
ev
.
dev_class
,
dev_class
,
sizeof
(
ev
.
dev_class
));
ev
.
rssi
=
rssi
;
if
(
eir
)
memcpy
(
ev
.
eir
,
eir
,
sizeof
(
ev
.
eir
));
if
(
dev_class
)
memcpy
(
ev
.
dev_class
,
dev_class
,
sizeof
(
ev
.
dev_class
));
return
mgmt_event
(
MGMT_EV_DEVICE_FOUND
,
index
,
&
ev
,
sizeof
(
ev
),
NULL
);
}
...
...
@@ -2286,3 +2352,29 @@ int mgmt_discovering(u16 index, u8 discovering)
return
mgmt_event
(
MGMT_EV_DISCOVERING
,
index
,
&
discovering
,
sizeof
(
discovering
),
NULL
);
}
int
mgmt_device_blocked
(
u16
index
,
bdaddr_t
*
bdaddr
)
{
struct
pending_cmd
*
cmd
;
struct
mgmt_ev_device_blocked
ev
;
cmd
=
mgmt_pending_find
(
MGMT_OP_BLOCK_DEVICE
,
index
);
bacpy
(
&
ev
.
bdaddr
,
bdaddr
);
return
mgmt_event
(
MGMT_EV_DEVICE_BLOCKED
,
index
,
&
ev
,
sizeof
(
ev
),
cmd
?
cmd
->
sk
:
NULL
);
}
int
mgmt_device_unblocked
(
u16
index
,
bdaddr_t
*
bdaddr
)
{
struct
pending_cmd
*
cmd
;
struct
mgmt_ev_device_unblocked
ev
;
cmd
=
mgmt_pending_find
(
MGMT_OP_UNBLOCK_DEVICE
,
index
);
bacpy
(
&
ev
.
bdaddr
,
bdaddr
);
return
mgmt_event
(
MGMT_EV_DEVICE_UNBLOCKED
,
index
,
&
ev
,
sizeof
(
ev
),
cmd
?
cmd
->
sk
:
NULL
);
}
This diff is collapsed.
Click to expand it.
net/bluetooth/smp.c
浏览文件 @
bb8f2cb2
...
...
@@ -182,18 +182,9 @@ static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
return
;
hci_send_acl
(
conn
->
hcon
,
skb
,
0
);
}
static
__u8
seclevel_to_authreq
(
__u8
level
)
{
switch
(
level
)
{
case
BT_SECURITY_HIGH
:
/* Right now we don't support bonding */
return
SMP_AUTH_MITM
;
default:
return
SMP_AUTH_NONE
;
}
mod_timer
(
&
conn
->
security_timer
,
jiffies
+
msecs_to_jiffies
(
SMP_TIMEOUT
));
}
static
void
build_pairing_cmd
(
struct
l2cap_conn
*
conn
,
...
...
@@ -205,7 +196,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
dist_keys
=
0
;
if
(
test_bit
(
HCI_PAIRABLE
,
&
conn
->
hcon
->
hdev
->
flags
))
{
dist_keys
=
SMP_DIST_ENC_KEY
|
SMP_DIST_ID_KEY
|
SMP_DIST_SIGN
;
dist_keys
=
SMP_DIST_ENC_KEY
;
authreq
|=
SMP_AUTH_BONDING
;
}
...
...
@@ -229,24 +220,184 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
static
u8
check_enc_key_size
(
struct
l2cap_conn
*
conn
,
__u8
max_key_size
)
{
struct
smp_chan
*
smp
=
conn
->
smp_chan
;
if
((
max_key_size
>
SMP_MAX_ENC_KEY_SIZE
)
||
(
max_key_size
<
SMP_MIN_ENC_KEY_SIZE
))
return
SMP_ENC_KEY_SIZE
;
conn
->
smp_key_size
=
max_key_size
;
smp
->
smp_key_size
=
max_key_size
;
return
0
;
}
static
void
confirm_work
(
struct
work_struct
*
work
)
{
struct
smp_chan
*
smp
=
container_of
(
work
,
struct
smp_chan
,
confirm
);
struct
l2cap_conn
*
conn
=
smp
->
conn
;
struct
crypto_blkcipher
*
tfm
;
struct
smp_cmd_pairing_confirm
cp
;
int
ret
;
u8
res
[
16
],
reason
;
BT_DBG
(
"conn %p"
,
conn
);
tfm
=
crypto_alloc_blkcipher
(
"ecb(aes)"
,
0
,
CRYPTO_ALG_ASYNC
);
if
(
IS_ERR
(
tfm
))
{
reason
=
SMP_UNSPECIFIED
;
goto
error
;
}
smp
->
tfm
=
tfm
;
if
(
conn
->
hcon
->
out
)
ret
=
smp_c1
(
tfm
,
smp
->
tk
,
smp
->
prnd
,
smp
->
preq
,
smp
->
prsp
,
0
,
conn
->
src
,
conn
->
hcon
->
dst_type
,
conn
->
dst
,
res
);
else
ret
=
smp_c1
(
tfm
,
smp
->
tk
,
smp
->
prnd
,
smp
->
preq
,
smp
->
prsp
,
conn
->
hcon
->
dst_type
,
conn
->
dst
,
0
,
conn
->
src
,
res
);
if
(
ret
)
{
reason
=
SMP_UNSPECIFIED
;
goto
error
;
}
swap128
(
res
,
cp
.
confirm_val
);
smp_send_cmd
(
smp
->
conn
,
SMP_CMD_PAIRING_CONFIRM
,
sizeof
(
cp
),
&
cp
);
return
;
error:
smp_send_cmd
(
conn
,
SMP_CMD_PAIRING_FAIL
,
sizeof
(
reason
),
&
reason
);
smp_chan_destroy
(
conn
);
}
static
void
random_work
(
struct
work_struct
*
work
)
{
struct
smp_chan
*
smp
=
container_of
(
work
,
struct
smp_chan
,
random
);
struct
l2cap_conn
*
conn
=
smp
->
conn
;
struct
hci_conn
*
hcon
=
conn
->
hcon
;
struct
crypto_blkcipher
*
tfm
=
smp
->
tfm
;
u8
reason
,
confirm
[
16
],
res
[
16
],
key
[
16
];
int
ret
;
if
(
IS_ERR_OR_NULL
(
tfm
))
{
reason
=
SMP_UNSPECIFIED
;
goto
error
;
}
BT_DBG
(
"conn %p %s"
,
conn
,
conn
->
hcon
->
out
?
"master"
:
"slave"
);
if
(
hcon
->
out
)
ret
=
smp_c1
(
tfm
,
smp
->
tk
,
smp
->
rrnd
,
smp
->
preq
,
smp
->
prsp
,
0
,
conn
->
src
,
hcon
->
dst_type
,
conn
->
dst
,
res
);
else
ret
=
smp_c1
(
tfm
,
smp
->
tk
,
smp
->
rrnd
,
smp
->
preq
,
smp
->
prsp
,
hcon
->
dst_type
,
conn
->
dst
,
0
,
conn
->
src
,
res
);
if
(
ret
)
{
reason
=
SMP_UNSPECIFIED
;
goto
error
;
}
swap128
(
res
,
confirm
);
if
(
memcmp
(
smp
->
pcnf
,
confirm
,
sizeof
(
smp
->
pcnf
))
!=
0
)
{
BT_ERR
(
"Pairing failed (confirmation values mismatch)"
);
reason
=
SMP_CONFIRM_FAILED
;
goto
error
;
}
if
(
hcon
->
out
)
{
u8
stk
[
16
],
rand
[
8
];
__le16
ediv
;
memset
(
rand
,
0
,
sizeof
(
rand
));
ediv
=
0
;
smp_s1
(
tfm
,
smp
->
tk
,
smp
->
rrnd
,
smp
->
prnd
,
key
);
swap128
(
key
,
stk
);
memset
(
stk
+
smp
->
smp_key_size
,
0
,
SMP_MAX_ENC_KEY_SIZE
-
smp
->
smp_key_size
);
if
(
test_and_set_bit
(
HCI_CONN_ENCRYPT_PEND
,
&
hcon
->
pend
))
{
reason
=
SMP_UNSPECIFIED
;
goto
error
;
}
hci_le_start_enc
(
hcon
,
ediv
,
rand
,
stk
);
hcon
->
enc_key_size
=
smp
->
smp_key_size
;
}
else
{
u8
stk
[
16
],
r
[
16
],
rand
[
8
];
__le16
ediv
;
memset
(
rand
,
0
,
sizeof
(
rand
));
ediv
=
0
;
swap128
(
smp
->
prnd
,
r
);
smp_send_cmd
(
conn
,
SMP_CMD_PAIRING_RANDOM
,
sizeof
(
r
),
r
);
smp_s1
(
tfm
,
smp
->
tk
,
smp
->
prnd
,
smp
->
rrnd
,
key
);
swap128
(
key
,
stk
);
memset
(
stk
+
smp
->
smp_key_size
,
0
,
SMP_MAX_ENC_KEY_SIZE
-
smp
->
smp_key_size
);
hci_add_ltk
(
hcon
->
hdev
,
0
,
conn
->
dst
,
smp
->
smp_key_size
,
ediv
,
rand
,
stk
);
}
return
;
error:
smp_send_cmd
(
conn
,
SMP_CMD_PAIRING_FAIL
,
sizeof
(
reason
),
&
reason
);
smp_chan_destroy
(
conn
);
}
static
struct
smp_chan
*
smp_chan_create
(
struct
l2cap_conn
*
conn
)
{
struct
smp_chan
*
smp
;
smp
=
kzalloc
(
sizeof
(
struct
smp_chan
),
GFP_ATOMIC
);
if
(
!
smp
)
return
NULL
;
INIT_WORK
(
&
smp
->
confirm
,
confirm_work
);
INIT_WORK
(
&
smp
->
random
,
random_work
);
smp
->
conn
=
conn
;
conn
->
smp_chan
=
smp
;
hci_conn_hold
(
conn
->
hcon
);
return
smp
;
}
void
smp_chan_destroy
(
struct
l2cap_conn
*
conn
)
{
kfree
(
conn
->
smp_chan
);
hci_conn_put
(
conn
->
hcon
);
}
static
u8
smp_cmd_pairing_req
(
struct
l2cap_conn
*
conn
,
struct
sk_buff
*
skb
)
{
struct
smp_cmd_pairing
rsp
,
*
req
=
(
void
*
)
skb
->
data
;
struct
smp_chan
*
smp
;
u8
key_size
;
int
ret
;
BT_DBG
(
"conn %p"
,
conn
);
conn
->
preq
[
0
]
=
SMP_CMD_PAIRING_REQ
;
memcpy
(
&
conn
->
preq
[
1
],
req
,
sizeof
(
*
req
));
if
(
!
test_and_set_bit
(
HCI_CONN_LE_SMP_PEND
,
&
conn
->
hcon
->
pend
))
smp
=
smp_chan_create
(
conn
);
smp
=
conn
->
smp_chan
;
smp
->
preq
[
0
]
=
SMP_CMD_PAIRING_REQ
;
memcpy
(
&
smp
->
preq
[
1
],
req
,
sizeof
(
*
req
));
skb_pull
(
skb
,
sizeof
(
*
req
));
if
(
req
->
oob_flag
)
...
...
@@ -260,32 +411,33 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
return
SMP_ENC_KEY_SIZE
;
/* Just works */
memset
(
conn
->
tk
,
0
,
sizeof
(
conn
->
tk
));
memset
(
smp
->
tk
,
0
,
sizeof
(
smp
->
tk
));
ret
=
smp_rand
(
smp
->
prnd
);
if
(
ret
)
return
SMP_UNSPECIFIED
;
conn
->
prsp
[
0
]
=
SMP_CMD_PAIRING_RSP
;
memcpy
(
&
conn
->
prsp
[
1
],
&
rsp
,
sizeof
(
rsp
));
smp
->
prsp
[
0
]
=
SMP_CMD_PAIRING_RSP
;
memcpy
(
&
smp
->
prsp
[
1
],
&
rsp
,
sizeof
(
rsp
));
smp_send_cmd
(
conn
,
SMP_CMD_PAIRING_RSP
,
sizeof
(
rsp
),
&
rsp
);
mod_timer
(
&
conn
->
security_timer
,
jiffies
+
msecs_to_jiffies
(
SMP_TIMEOUT
));
return
0
;
}
static
u8
smp_cmd_pairing_rsp
(
struct
l2cap_conn
*
conn
,
struct
sk_buff
*
skb
)
{
struct
smp_cmd_pairing
*
req
,
*
rsp
=
(
void
*
)
skb
->
data
;
struct
smp_cmd_pairing_confirm
cp
;
struct
crypto_blkcipher
*
tfm
=
conn
->
hcon
->
hdev
->
tfm
;
struct
smp_chan
*
smp
=
conn
->
smp_chan
;
struct
hci_dev
*
hdev
=
conn
->
hcon
->
hdev
;
u8
key_size
;
int
ret
;
u8
res
[
16
],
key_size
;
BT_DBG
(
"conn %p"
,
conn
);
skb_pull
(
skb
,
sizeof
(
*
rsp
));
req
=
(
void
*
)
&
conn
->
preq
[
1
];
req
=
(
void
*
)
&
smp
->
preq
[
1
];
key_size
=
min
(
req
->
max_key_size
,
rsp
->
max_key_size
);
if
(
check_enc_key_size
(
conn
,
key_size
))
...
...
@@ -295,222 +447,154 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
return
SMP_OOB_NOT_AVAIL
;
/* Just works */
memset
(
conn
->
tk
,
0
,
sizeof
(
conn
->
tk
));
conn
->
prsp
[
0
]
=
SMP_CMD_PAIRING_RSP
;
memcpy
(
&
conn
->
prsp
[
1
],
rsp
,
sizeof
(
*
rsp
));
ret
=
smp_rand
(
conn
->
prnd
);
if
(
ret
)
return
SMP_UNSPECIFIED
;
memset
(
smp
->
tk
,
0
,
sizeof
(
smp
->
tk
));
ret
=
smp_c1
(
tfm
,
conn
->
tk
,
conn
->
prnd
,
conn
->
preq
,
conn
->
prsp
,
0
,
conn
->
src
,
conn
->
hcon
->
dst_type
,
conn
->
dst
,
res
);
ret
=
smp_rand
(
smp
->
prnd
);
if
(
ret
)
return
SMP_UNSPECIFIED
;
swap128
(
res
,
cp
.
confirm_val
);
smp
->
prsp
[
0
]
=
SMP_CMD_PAIRING_RSP
;
memcpy
(
&
smp
->
prsp
[
1
],
rsp
,
sizeof
(
*
rsp
));
smp_send_cmd
(
conn
,
SMP_CMD_PAIRING_CONFIRM
,
sizeof
(
cp
),
&
cp
);
queue_work
(
hdev
->
workqueue
,
&
smp
->
confirm
);
return
0
;
}
static
u8
smp_cmd_pairing_confirm
(
struct
l2cap_conn
*
conn
,
struct
sk_buff
*
skb
)
{
struct
crypto_blkcipher
*
tfm
=
conn
->
hcon
->
hdev
->
tfm
;
struct
smp_chan
*
smp
=
conn
->
smp_chan
;
struct
hci_dev
*
hdev
=
conn
->
hcon
->
hdev
;
BT_DBG
(
"conn %p %s"
,
conn
,
conn
->
hcon
->
out
?
"master"
:
"slave"
);
memcpy
(
conn
->
pcnf
,
skb
->
data
,
sizeof
(
conn
->
pcnf
));
skb_pull
(
skb
,
sizeof
(
conn
->
pcnf
));
memcpy
(
smp
->
pcnf
,
skb
->
data
,
sizeof
(
smp
->
pcnf
));
skb_pull
(
skb
,
sizeof
(
smp
->
pcnf
));
if
(
conn
->
hcon
->
out
)
{
u8
random
[
16
];
swap128
(
conn
->
prnd
,
random
);
swap128
(
smp
->
prnd
,
random
);
smp_send_cmd
(
conn
,
SMP_CMD_PAIRING_RANDOM
,
sizeof
(
random
),
random
);
}
else
{
struct
smp_cmd_pairing_confirm
cp
;
int
ret
;
u8
res
[
16
];
ret
=
smp_rand
(
conn
->
prnd
);
if
(
ret
)
return
SMP_UNSPECIFIED
;
ret
=
smp_c1
(
tfm
,
conn
->
tk
,
conn
->
prnd
,
conn
->
preq
,
conn
->
prsp
,
conn
->
hcon
->
dst_type
,
conn
->
dst
,
0
,
conn
->
src
,
res
);
if
(
ret
)
return
SMP_CONFIRM_FAILED
;
swap128
(
res
,
cp
.
confirm_val
);
smp_send_cmd
(
conn
,
SMP_CMD_PAIRING_CONFIRM
,
sizeof
(
cp
),
&
cp
);
queue_work
(
hdev
->
workqueue
,
&
smp
->
confirm
);
}
mod_timer
(
&
conn
->
security_timer
,
jiffies
+
msecs_to_jiffies
(
SMP_TIMEOUT
));
return
0
;
}
static
u8
smp_cmd_pairing_random
(
struct
l2cap_conn
*
conn
,
struct
sk_buff
*
skb
)
{
struct
hci_conn
*
hcon
=
conn
->
hcon
;
struct
crypto_blkcipher
*
tfm
=
hcon
->
hdev
->
tfm
;
int
ret
;
u8
key
[
16
],
res
[
16
],
random
[
16
],
confirm
[
16
];
struct
smp_chan
*
smp
=
conn
->
smp_chan
;
struct
hci_dev
*
hdev
=
conn
->
hcon
->
hdev
;
swap128
(
skb
->
data
,
random
);
skb_pull
(
skb
,
sizeof
(
random
));
if
(
conn
->
hcon
->
out
)
ret
=
smp_c1
(
tfm
,
conn
->
tk
,
random
,
conn
->
preq
,
conn
->
prsp
,
0
,
conn
->
src
,
conn
->
hcon
->
dst_type
,
conn
->
dst
,
res
);
else
ret
=
smp_c1
(
tfm
,
conn
->
tk
,
random
,
conn
->
preq
,
conn
->
prsp
,
conn
->
hcon
->
dst_type
,
conn
->
dst
,
0
,
conn
->
src
,
res
);
if
(
ret
)
return
SMP_UNSPECIFIED
;
BT_DBG
(
"conn %p %s"
,
conn
,
conn
->
hcon
->
out
?
"master"
:
"slave"
);
swap128
(
res
,
confirm
);
if
(
memcmp
(
conn
->
pcnf
,
confirm
,
sizeof
(
conn
->
pcnf
))
!=
0
)
{
BT_ERR
(
"Pairing failed (confirmation values mismatch)"
);
return
SMP_CONFIRM_FAILED
;
}
if
(
conn
->
hcon
->
out
)
{
u8
stk
[
16
],
rand
[
8
];
__le16
ediv
;
memset
(
rand
,
0
,
sizeof
(
rand
));
ediv
=
0
;
BT_DBG
(
"conn %p"
,
conn
);
smp_s1
(
tfm
,
conn
->
tk
,
random
,
conn
->
prnd
,
key
);
swap128
(
key
,
stk
);
swap128
(
skb
->
data
,
smp
->
rrnd
);
skb_pull
(
skb
,
sizeof
(
smp
->
rrnd
)
);
memset
(
stk
+
conn
->
smp_key_size
,
0
,
SMP_MAX_ENC_KEY_SIZE
-
conn
->
smp_key_size
);
queue_work
(
hdev
->
workqueue
,
&
smp
->
random
);
hci_le_start_enc
(
hcon
,
ediv
,
rand
,
stk
);
hcon
->
enc_key_size
=
conn
->
smp_key_size
;
}
else
{
u8
stk
[
16
],
r
[
16
],
rand
[
8
];
__le16
ediv
;
return
0
;
}
memset
(
rand
,
0
,
sizeof
(
rand
));
ediv
=
0
;
static
u8
smp_ltk_encrypt
(
struct
l2cap_conn
*
conn
)
{
struct
link_key
*
key
;
struct
key_master_id
*
master
;
struct
hci_conn
*
hcon
=
conn
->
hcon
;
swap128
(
conn
->
prnd
,
r
);
smp_send_cmd
(
conn
,
SMP_CMD_PAIRING_RANDOM
,
sizeof
(
r
),
r
);
key
=
hci_find_link_key_type
(
hcon
->
hdev
,
conn
->
dst
,
HCI_LK_SMP_LTK
);
if
(
!
key
)
return
0
;
smp_s1
(
tfm
,
conn
->
tk
,
conn
->
prnd
,
random
,
key
);
swap128
(
key
,
stk
);
if
(
test_and_set_bit
(
HCI_CONN_ENCRYPT_PEND
,
&
hcon
->
pend
))
return
1
;
memset
(
stk
+
conn
->
smp_key_size
,
0
,
SMP_MAX_ENC_KEY_SIZE
-
conn
->
smp_key_size
);
master
=
(
void
*
)
key
->
data
;
hci_le_start_enc
(
hcon
,
master
->
ediv
,
master
->
rand
,
key
->
val
);
hcon
->
enc_key_size
=
key
->
pin_len
;
hci_add_ltk
(
conn
->
hcon
->
hdev
,
0
,
conn
->
dst
,
conn
->
smp_key_size
,
ediv
,
rand
,
stk
);
}
return
1
;
return
0
;
}
static
u8
smp_cmd_security_req
(
struct
l2cap_conn
*
conn
,
struct
sk_buff
*
skb
)
{
struct
smp_cmd_security_req
*
rp
=
(
void
*
)
skb
->
data
;
struct
smp_cmd_pairing
cp
;
struct
hci_conn
*
hcon
=
conn
->
hcon
;
struct
smp_chan
*
smp
;
BT_DBG
(
"conn %p"
,
conn
);
if
(
test_bit
(
HCI_CONN_ENCRYPT_PEND
,
&
hcon
->
pend
))
hcon
->
pending_sec_level
=
BT_SECURITY_MEDIUM
;
if
(
smp_ltk_encrypt
(
conn
))
return
0
;
if
(
test_and_set_bit
(
HCI_CONN_LE_SMP_PEND
,
&
hcon
->
pend
))
return
0
;
smp
=
smp_chan_create
(
conn
);
skb_pull
(
skb
,
sizeof
(
*
rp
));
memset
(
&
cp
,
0
,
sizeof
(
cp
));
build_pairing_cmd
(
conn
,
&
cp
,
NULL
,
rp
->
auth_req
);
conn
->
preq
[
0
]
=
SMP_CMD_PAIRING_REQ
;
memcpy
(
&
conn
->
preq
[
1
],
&
cp
,
sizeof
(
cp
));
smp
->
preq
[
0
]
=
SMP_CMD_PAIRING_REQ
;
memcpy
(
&
smp
->
preq
[
1
],
&
cp
,
sizeof
(
cp
));
smp_send_cmd
(
conn
,
SMP_CMD_PAIRING_REQ
,
sizeof
(
cp
),
&
cp
);
mod_timer
(
&
conn
->
security_timer
,
jiffies
+
msecs_to_jiffies
(
SMP_TIMEOUT
));
set_bit
(
HCI_CONN_ENCRYPT_PEND
,
&
hcon
->
pend
);
return
0
;
}
int
smp_conn_security
(
struct
l2cap_conn
*
conn
,
__u8
sec_level
)
{
struct
hci_conn
*
hcon
=
conn
->
hcon
;
__u8
authreq
;
struct
smp_chan
*
smp
=
conn
->
smp_chan
;
BT_DBG
(
"conn %p hcon %p level 0x%2.2x"
,
conn
,
hcon
,
sec_level
);
if
(
!
lmp_host_le_capable
(
hcon
->
hdev
))
return
1
;
if
(
IS_ERR
(
hcon
->
hdev
->
tfm
))
return
1
;
if
(
test_bit
(
HCI_CONN_ENCRYPT_PEND
,
&
hcon
->
pend
))
return
0
;
if
(
sec_level
==
BT_SECURITY_LOW
)
return
1
;
if
(
hcon
->
sec_level
>=
sec_level
)
return
1
;
authreq
=
seclevel_to_authreq
(
sec_level
);
if
(
hcon
->
link_mode
&
HCI_LM_MASTER
)
{
struct
smp_cmd_pairing
cp
;
struct
link_key
*
key
;
if
(
hcon
->
link_mode
&
HCI_LM_MASTER
)
if
(
smp_ltk_encrypt
(
conn
))
goto
done
;
key
=
hci_find_link_key_type
(
hcon
->
hdev
,
conn
->
dst
,
HCI_LK_SMP_LTK
);
if
(
key
)
{
struct
key_master_id
*
master
=
(
void
*
)
key
->
data
;
if
(
test_and_set_bit
(
HCI_CONN_LE_SMP_PEND
,
&
hcon
->
pend
))
return
0
;
hci_le_start_enc
(
hcon
,
master
->
ediv
,
master
->
rand
,
key
->
val
);
hcon
->
enc_key_size
=
key
->
pin_len
;
smp
=
smp_chan_create
(
conn
);
goto
done
;
}
build_pairing_cmd
(
conn
,
&
cp
,
NULL
,
authreq
);
conn
->
preq
[
0
]
=
SMP_CMD_PAIRING_REQ
;
memcpy
(
&
conn
->
preq
[
1
],
&
cp
,
sizeof
(
cp
));
if
(
hcon
->
link_mode
&
HCI_LM_MASTER
)
{
struct
smp_cmd_pairing
cp
;
mod_timer
(
&
conn
->
security_timer
,
jiffies
+
msecs_to_jiffies
(
SMP_TIMEOUT
));
build_pairing_cmd
(
conn
,
&
cp
,
NULL
,
SMP_AUTH_NONE
);
smp
->
preq
[
0
]
=
SMP_CMD_PAIRING_REQ
;
memcpy
(
&
smp
->
preq
[
1
],
&
cp
,
sizeof
(
cp
));
smp_send_cmd
(
conn
,
SMP_CMD_PAIRING_REQ
,
sizeof
(
cp
),
&
cp
);
}
else
{
struct
smp_cmd_security_req
cp
;
cp
.
auth_req
=
authreq
;
cp
.
auth_req
=
SMP_AUTH_NONE
;
smp_send_cmd
(
conn
,
SMP_CMD_SECURITY_REQ
,
sizeof
(
cp
),
&
cp
);
}
done:
hcon
->
pending_sec_level
=
sec_level
;
set_bit
(
HCI_CONN_ENCRYPT_PEND
,
&
hcon
->
pend
);
return
0
;
}
...
...
@@ -518,10 +602,11 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
static
int
smp_cmd_encrypt_info
(
struct
l2cap_conn
*
conn
,
struct
sk_buff
*
skb
)
{
struct
smp_cmd_encrypt_info
*
rp
=
(
void
*
)
skb
->
data
;
struct
smp_chan
*
smp
=
conn
->
smp_chan
;
skb_pull
(
skb
,
sizeof
(
*
rp
));
memcpy
(
conn
->
tk
,
rp
->
ltk
,
sizeof
(
conn
->
tk
));
memcpy
(
smp
->
tk
,
rp
->
ltk
,
sizeof
(
smp
->
tk
));
return
0
;
}
...
...
@@ -529,11 +614,12 @@ static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
static
int
smp_cmd_master_ident
(
struct
l2cap_conn
*
conn
,
struct
sk_buff
*
skb
)
{
struct
smp_cmd_master_ident
*
rp
=
(
void
*
)
skb
->
data
;
struct
smp_chan
*
smp
=
conn
->
smp_chan
;
skb_pull
(
skb
,
sizeof
(
*
rp
));
hci_add_ltk
(
conn
->
hcon
->
hdev
,
1
,
conn
->
src
,
conn
->
smp_key_size
,
rp
->
ediv
,
rp
->
rand
,
conn
->
tk
);
hci_add_ltk
(
conn
->
hcon
->
hdev
,
1
,
conn
->
src
,
smp
->
smp_key_size
,
rp
->
ediv
,
rp
->
rand
,
smp
->
tk
);
smp_distribute_keys
(
conn
,
1
);
...
...
@@ -552,12 +638,6 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
goto
done
;
}
if
(
IS_ERR
(
conn
->
hcon
->
hdev
->
tfm
))
{
err
=
PTR_ERR
(
conn
->
hcon
->
hdev
->
tfm
);
reason
=
SMP_PAIRING_NOTSUPP
;
goto
done
;
}
skb_pull
(
skb
,
sizeof
(
code
));
switch
(
code
)
{
...
...
@@ -621,20 +701,21 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
int
smp_distribute_keys
(
struct
l2cap_conn
*
conn
,
__u8
force
)
{
struct
smp_cmd_pairing
*
req
,
*
rsp
;
struct
smp_chan
*
smp
=
conn
->
smp_chan
;
__u8
*
keydist
;
BT_DBG
(
"conn %p force %d"
,
conn
,
force
);
if
(
IS_ERR
(
conn
->
hcon
->
hdev
->
tfm
))
return
PTR_ERR
(
conn
->
hcon
->
hdev
->
tfm
)
;
if
(
!
test_bit
(
HCI_CONN_LE_SMP_PEND
,
&
conn
->
hcon
->
pend
))
return
0
;
rsp
=
(
void
*
)
&
conn
->
prsp
[
1
];
rsp
=
(
void
*
)
&
smp
->
prsp
[
1
];
/* The responder sends its keys first */
if
(
!
force
&&
conn
->
hcon
->
out
&&
(
rsp
->
resp_key_dist
&
0x07
))
return
0
;
req
=
(
void
*
)
&
conn
->
preq
[
1
];
req
=
(
void
*
)
&
smp
->
preq
[
1
];
if
(
conn
->
hcon
->
out
)
{
keydist
=
&
rsp
->
init_key_dist
;
...
...
@@ -658,7 +739,7 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
smp_send_cmd
(
conn
,
SMP_CMD_ENCRYPT_INFO
,
sizeof
(
enc
),
&
enc
);
hci_add_ltk
(
conn
->
hcon
->
hdev
,
1
,
conn
->
dst
,
conn
->
smp_key_size
,
hci_add_ltk
(
conn
->
hcon
->
hdev
,
1
,
conn
->
dst
,
smp
->
smp_key_size
,
ediv
,
ident
.
rand
,
enc
.
ltk
);
ident
.
ediv
=
cpu_to_le16
(
ediv
);
...
...
@@ -698,5 +779,11 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
*
keydist
&=
~
SMP_DIST_SIGN
;
}
if
(
conn
->
hcon
->
out
||
force
)
{
clear_bit
(
HCI_CONN_LE_SMP_PEND
,
&
conn
->
hcon
->
pend
);
del_timer
(
&
conn
->
security_timer
);
smp_chan_destroy
(
conn
);
}
return
0
;
}
This diff is collapsed.
Click to expand it.
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录
新手
引导
客服
返回
顶部