Bluetooth: SMP: Handle security request from slave
If sufficently strong key exists enable encryption. If no key is
present or key doesn't meet auth requirements start pairing.
Change-Id: I50be66f895d02dbbce49290c21bbc445ab734b4b
Signed-off-by: Szymon Janc <szymon.janc@tieto.com>
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 755a699..5d90843 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -680,6 +680,39 @@
return 0;
}
+static uint8_t smp_security_request(struct bt_conn *conn, struct bt_buf *buf)
+{
+ struct bt_smp_security_request *req = (void *)buf->data;
+ struct bt_keys *keys;
+ uint8_t auth;
+
+ BT_DBG("\n");
+
+ keys = bt_keys_find(BT_KEYS_IRK, &conn->dst);
+ if (!keys) {
+ goto pair;
+ }
+
+ auth = req->auth_req & BT_SMP_AUTH_MASK;
+ if (auth & (BT_SMP_AUTH_MITM | BT_SMP_AUTH_SC)) {
+ BT_WARN("Unsupported auth requirements: 0x%x, repairing", auth);
+ goto pair;
+ }
+
+ if (bt_hci_le_start_encryption(conn->handle, keys->ltk.rand,
+ keys->ltk.ediv, keys->ltk.val) < 0) {
+ return BT_SMP_ERR_UNSPECIFIED;
+ }
+
+ return 0;
+pair:
+ if (smp_send_pairing_req(conn) < 0) {
+ return BT_SMP_ERR_UNSPECIFIED;
+ }
+
+ return 0;
+}
+
static const struct {
uint8_t (*func)(struct bt_conn *conn, struct bt_buf *buf);
uint8_t expect_len;
@@ -694,6 +727,8 @@
{ smp_pairing_master, sizeof(struct bt_smp_master_ident) },
{ smp_ident_info, sizeof(struct bt_smp_ident_info) },
{ smp_ident_addr_info, sizeof(struct bt_smp_ident_addr_info) },
+ { }, /* Signing Information - Not yet implemented */
+ { smp_security_request, sizeof(struct bt_smp_security_request) },
};
static void bt_smp_recv(struct bt_conn *conn, struct bt_buf *buf)
diff --git a/net/bluetooth/smp.h b/net/bluetooth/smp.h
index 70a1a1c..c7fd255 100644
--- a/net/bluetooth/smp.h
+++ b/net/bluetooth/smp.h
@@ -126,6 +126,11 @@
bt_addr_le_t addr;
} __packed;
+#define BT_SMP_CMD_SECURITY_REQUEST 0x0b
+struct bt_smp_security_request {
+ uint8_t auth_req;
+} __packed;
+
bool bt_smp_irk_matches(const uint8_t irk[16], const bt_addr_t *addr);
int smp_send_pairing_req(struct bt_conn *conn);