From d9e3aab39d2af7d7a822993ededaa41cd0311c53 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 17 Nov 2012 13:24:19 +0900 Subject: [PATCH] monitor: Decode Security Manager Protocol --- monitor/bt.h | 75 ++++++++++++ monitor/l2cap.c | 297 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 361 insertions(+), 11 deletions(-) diff --git a/monitor/bt.h b/monitor/bt.h index 0f97f979c..f91545db3 100644 --- a/monitor/bt.h +++ b/monitor/bt.h @@ -1579,6 +1579,81 @@ struct bt_l2cap_amp_disconn_phy_link_rsp { uint8_t status; } __attribute__ ((packed)); +struct bt_l2cap_hdr_att { + uint8_t code; +} __attribute__ ((packed)); + +struct bt_l2cap_hdr_smp { + uint8_t code; +} __attribute__ ((packed)); + +#define BT_L2CAP_SMP_PAIRING_REQUEST 0x01 +struct bt_l2cap_smp_pairing_request { + uint8_t io_capa; + uint8_t oob_data; + uint8_t auth_req; + uint8_t max_key_size; + uint8_t init_key_dist; + uint8_t resp_key_dist; +} __attribute__ ((packed)); + +#define BT_L2CAP_SMP_PAIRING_RESPONSE 0x02 +struct bt_l2cap_smp_pairing_response { + uint8_t io_capa; + uint8_t oob_data; + uint8_t auth_req; + uint8_t max_key_size; + uint8_t init_key_dist; + uint8_t resp_key_dist; +} __attribute__ ((packed)); + +#define BT_L2CAP_SMP_PAIRING_CONFIRM 0x03 +struct bt_l2cap_smp_pairing_confirm { + uint8_t value[16]; +} __attribute__ ((packed)); + +#define BT_L2CAP_SMP_PAIRING_RANDOM 0x04 +struct bt_l2cap_smp_pairing_random { + uint8_t value[16]; +} __attribute__ ((packed)); + +#define BT_L2CAP_SMP_PAIRING_FAILED 0x05 +struct bt_l2cap_smp_pairing_failed { + uint8_t reason; +} __attribute__ ((packed)); + +#define BT_L2CAP_SMP_ENCRYPT_INFO 0x06 +struct bt_l2cap_smp_encrypt_info { + uint8_t ltk[16]; +} __attribute__ ((packed)); + +#define BT_L2CAP_SMP_MASTER_IDENT 0x07 +struct bt_l2cap_smp_master_ident { + uint16_t ediv; + uint64_t rand; +} __attribute__ ((packed)); + +#define BT_L2CAP_SMP_IDENT_INFO 0x08 +struct bt_l2cap_smp_ident_info { + uint8_t irk[16]; +} __attribute__ ((packed)); + +#define BT_L2CAP_SMP_IDENT_ADDR_INFO 0x09 +struct bt_l2cap_smp_ident_addr_info { + uint8_t addr_type; + uint8_t addr[6]; +} __attribute__ ((packed)); + +#define BT_L2CAP_SMP_SIGNING_INFO 0x0a +struct bt_l2cap_smp_signing_info { + uint8_t csrk[16]; +} __attribute__ ((packed)); + +#define BT_L2CAP_SMP_SECURITY_REQUEST 0x0b +struct bt_l2cap_smp_security_request { + uint8_t auth_req; +} __attribute__ ((packed)); + struct bt_sdp_hdr { uint8_t pdu; uint16_t tid; diff --git a/monitor/l2cap.c b/monitor/l2cap.c index 48c3d1c1b..6904d05ea 100644 --- a/monitor/l2cap.c +++ b/monitor/l2cap.c @@ -1557,6 +1557,270 @@ static void att_packet(uint16_t index, bool in, uint16_t handle, opcode_data->func(&frame); } +static void print_hex_field(const char *label, const uint8_t *data, + uint8_t len) +{ + char str[len * 2 + 1]; + uint8_t i; + + for (i = 0; i < len; i++) + sprintf(str + (i * 2), "%2.2x", data[i]); + + print_field("%s: %s", label, str); +} + +static void print_addr(const uint8_t *addr, uint8_t addr_type) +{ + const char *str; + + switch (addr_type) { + case 0x00: + print_field("Address: %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", + addr[5], addr[4], addr[3], + addr[2], addr[1], addr[0]); + break; + case 0x01: + switch ((addr[5] & 0xc0) >> 6) { + case 0x00: + str = "Non-Resolvable"; + break; + case 0x01: + str = "Resolvable"; + break; + case 0x03: + str = "Static"; + break; + default: + str = "Reserved"; + break; + } + + print_field("Address: %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X" + " (%s)", addr[5], addr[4], addr[3], + addr[2], addr[1], addr[0], str); + break; + default: + print_field("Address: %2.2X-%2.2X-%2.2X-%2.2X-%2.2X-%2.2X", + addr[5], addr[4], addr[3], + addr[2], addr[1], addr[0]); + break; + } +} + +static void print_addr_type(uint8_t addr_type) +{ + const char *str; + + switch (addr_type) { + case 0x00: + str = "Public"; + break; + case 0x01: + str = "Random"; + break; + default: + str = "Reserved"; + break; + } + + print_field("Address type: %s (0x%2.2x)", str, addr_type); +} + +static void print_smp_io_capa(uint8_t io_capa) +{ + const char *str; + + switch (io_capa) { + case 0x00: + str = "DisplayOnly"; + break; + case 0x01: + str = "DisplayYesNo"; + break; + case 0x02: + str = "KeyboardOnly"; + break; + case 0x03: + str = "NoInputNoOutput"; + break; + case 0x04: + str = "KeyboardDisplay"; + break; + default: + str = "Reserved"; + break; + } + + print_field("IO capability: %s (0x%2.2x)", str, io_capa); +} + +static void print_smp_oob_data(uint8_t oob_data) +{ + const char *str; + + switch (oob_data) { + case 0x00: + str = "Authentication data not present"; + break; + case 0x01: + str = "Authentication data from remote device present"; + break; + default: + str = "Reserved"; + break; + } + + print_field("OOB data: %s (0x%2.2x)", str, oob_data); +} + +static void print_smp_auth_req(uint8_t auth_req) +{ + const char *str; + + switch (auth_req & 0x03) { + case 0x00: + str = "No bonding"; + break; + case 0x01: + str = "Bonding"; + break; + default: + str = "Reserved"; + break; + } + + print_field("Authentication requirement: %s - %s (0x%2.2x)", + str, (auth_req & 0x04) ? "MITM" : "No MITM", auth_req); +} + +static void smp_pairing_request(const struct l2cap_frame *frame) +{ + const struct bt_l2cap_smp_pairing_request *pdu = frame->data; + + print_smp_io_capa(pdu->io_capa); + print_smp_oob_data(pdu->oob_data); + print_smp_auth_req(pdu->auth_req); + + print_field("Max encryption key size: %d", pdu->max_key_size); + print_field("Initiator key distribution: 0x%2.2x", pdu->init_key_dist); + print_field("Responder key distribution: 0x%2.2x", pdu->resp_key_dist); +} + +static void smp_pairing_response(const struct l2cap_frame *frame) +{ + const struct bt_l2cap_smp_pairing_response *pdu = frame->data; + + print_smp_io_capa(pdu->io_capa); + print_smp_oob_data(pdu->oob_data); + print_smp_auth_req(pdu->auth_req); + + print_field("Max encryption key size: %d", pdu->max_key_size); + print_field("Initiator key distribution: 0x%2.2x", pdu->init_key_dist); + print_field("Responder key distribution: 0x%2.2x", pdu->resp_key_dist); +} + +static void smp_pairing_confirm(const struct l2cap_frame *frame) +{ + const struct bt_l2cap_smp_pairing_confirm *pdu = frame->data; + + print_hex_field("Confim value", pdu->value, 16); +} + +static void smp_pairing_random(const struct l2cap_frame *frame) +{ + const struct bt_l2cap_smp_pairing_random *pdu = frame->data; + + print_hex_field("Random value", pdu->value, 16); +} + +static void smp_pairing_failed(const struct l2cap_frame *frame) +{ + const struct bt_l2cap_smp_pairing_failed *pdu = frame->data; + const char *str; + + switch (pdu->reason) { + case 0x01: + str = "Passkey entry failed"; + break; + case 0x02: + str = "OOB not available"; + break; + case 0x03: + str = "Authentication requirements"; + break; + case 0x04: + str = "Confirm value failed"; + break; + case 0x05: + str = "Pairing not supported"; + break; + case 0x06: + str = "Encryption key size"; + break; + case 0x07: + str = "Command not supported"; + break; + case 0x08: + str = "Unspecified reason"; + break; + case 0x09: + str = "Repeated attempts"; + break; + case 0x0a: + str = "Invalid parameters"; + break; + default: + str = "Reserved"; + break; + } + + print_field("Reason: %s (0x%2.2x)", str, pdu->reason); +} + +static void smp_encrypt_info(const struct l2cap_frame *frame) +{ + const struct bt_l2cap_smp_encrypt_info *pdu = frame->data; + + print_hex_field("Long term key", pdu->ltk, 16); +} + +static void smp_master_ident(const struct l2cap_frame *frame) +{ + const struct bt_l2cap_smp_master_ident *pdu = frame->data; + + print_field("EDIV: 0x%4.4x", btohs(pdu->ediv)); + print_field("Rand: 0x%16.16" PRIx64, btohll(pdu->rand)); +} + +static void smp_ident_info(const struct l2cap_frame *frame) +{ + const struct bt_l2cap_smp_ident_info *pdu = frame->data; + + print_hex_field("Identity resolving key", pdu->irk, 16); +} + +static void smp_ident_addr_info(const struct l2cap_frame *frame) +{ + const struct bt_l2cap_smp_ident_addr_info *pdu = frame->data; + + print_addr_type(pdu->addr_type); + print_addr(pdu->addr, pdu->addr_type); +} + +static void smp_signing_info(const struct l2cap_frame *frame) +{ + const struct bt_l2cap_smp_signing_info *pdu = frame->data; + + print_hex_field("Signature key", pdu->csrk, 16); +} + +static void smp_security_request(const struct l2cap_frame *frame) +{ + const struct bt_l2cap_smp_security_request *pdu = frame->data; + + print_smp_auth_req(pdu->auth_req); +} + struct smp_opcode_data { uint8_t opcode; const char *str; @@ -1566,17 +1830,28 @@ struct smp_opcode_data { }; static const struct smp_opcode_data smp_opcode_table[] = { - { 0x01, "Pairing Request" }, - { 0x02, "Pairing Response" }, - { 0x03, "Pairing Confirm" }, - { 0x04, "Pairing Random" }, - { 0x05, "Pairing Failed" }, - { 0x06, "Encryption Information" }, - { 0x07, "Master Identification" }, - { 0x08, "Identity Information" }, - { 0x09, "Identity Address Information" }, - { 0x0a, "Signing Information" }, - { 0x0b, "Security Request" }, + { 0x01, "Pairing Request", + smp_pairing_request, 6, true }, + { 0x02, "Pairing Response", + smp_pairing_response, 6, true }, + { 0x03, "Pairing Confirm", + smp_pairing_confirm, 16, true }, + { 0x04, "Pairing Random", + smp_pairing_random, 16, true }, + { 0x05, "Pairing Failed", + smp_pairing_failed, 1, true }, + { 0x06, "Encryption Information", + smp_encrypt_info, 16, true }, + { 0x07, "Master Identification", + smp_master_ident, 10, true }, + { 0x08, "Identity Information", + smp_ident_info, 16, true }, + { 0x09, "Identity Address Information", + smp_ident_addr_info, 7, true }, + { 0x0a, "Signing Information", + smp_signing_info, 16, true }, + { 0x0b, "Security Request", + smp_security_request, 1, true }, { } }; -- 2.47.3