diff options
author | Christopher Collins <ccollins@apache.org> | 2016-05-08 21:33:32 -0700 |
---|---|---|
committer | Christopher Collins <ccollins@apache.org> | 2016-05-08 21:53:50 -0700 |
commit | e76defb0437e1811dffe3f630405627eb6b3bf2a (patch) | |
tree | 46772e76896075b2f8f98cd842b25f18bce64352 /net | |
parent | 2a6cf9936308255fa76bcba744cd461781628fda (diff) |
BLE host - remove ble_l2cap_sm_process_status().
This function was ill-conceived.
Diffstat (limited to 'net')
-rw-r--r-- | net/nimble/host/src/ble_l2cap_sm.c | 120 | ||||
-rw-r--r-- | net/nimble/host/src/test/ble_l2cap_sm_test.c | 578 |
2 files changed, 463 insertions, 235 deletions
diff --git a/net/nimble/host/src/ble_l2cap_sm.c b/net/nimble/host/src/ble_l2cap_sm.c index 60cbae8a..376b2f81 100644 --- a/net/nimble/host/src/ble_l2cap_sm.c +++ b/net/nimble/host/src/ble_l2cap_sm.c @@ -403,30 +403,6 @@ ble_l2cap_sm_gap_event(struct ble_l2cap_sm_proc *proc, int status, ble_gap_security_event(proc->conn_handle, status, &sec_state); } -/* We must call this function when the host is unlocked because in - * failure conditions it will transmit which requires that we lock it - */ -static int -ble_l2cap_sm_process_status(struct ble_l2cap_sm_proc *proc, int status, - uint8_t sm_status, int call_cb, int tx_fail) -{ - if (proc == NULL) { - status = BLE_HS_ENOENT; - } else if (status != 0) { - if (tx_fail) { - ble_hs_lock(); - ble_l2cap_sm_pair_fail_tx(proc->conn_handle, sm_status); - ble_hs_unlock(); - } - if (call_cb) { - ble_l2cap_sm_gap_event(proc, status, 0); - } - ble_l2cap_sm_proc_free(proc); - } - - return status; -} - static int ble_l2cap_sm_proc_matches(struct ble_l2cap_sm_proc *proc, uint16_t conn_handle, uint8_t state, int is_initiator) @@ -1037,7 +1013,7 @@ ble_l2cap_sm_pair_req_handle(struct ble_l2cap_sm_proc *proc, } if (conn->bhc_flags & BLE_HS_CONN_F_MASTER) { *out_sm_status = BLE_L2CAP_SM_ERR_CMD_NOT_SUPP; - return BLE_HS_EROLE; + return BLE_HS_SM_US_ERR(BLE_L2CAP_SM_ERR_CMD_NOT_SUPP); } if (!ble_l2cap_sm_pair_cmd_is_valid(req)) { @@ -1310,20 +1286,22 @@ ble_l2cap_sm_rx_key_exchange(uint16_t conn_handle, uint8_t op, ble_l2cap_sm_signing_info_handle(proc, &u.signing_info); break; } - } - /* did we finish RX keys */ - rc = 0; - if (!proc->rx_key_flags) { - if (proc->flags & BLE_L2CAP_SM_PROC_F_INITIATOR) { - /* time for us to send our keys */ - rc = ble_l2cap_sm_key_exchange_go(proc, &sm_status); + /* did we finish RX keys */ + rc = 0; + if (!proc->rx_key_flags) { + if (proc->flags & BLE_L2CAP_SM_PROC_F_INITIATOR) { + /* time for us to send our keys */ + rc = ble_l2cap_sm_key_exchange_go(proc, &sm_status); + } + sm_end = 1; } - sm_end = 1; - } - if (rc != 0 || sm_end) { - ble_l2cap_sm_proc_remove(proc, prev); + if (rc != 0 || sm_end) { + ble_l2cap_sm_proc_remove(proc, prev); + } + } else { + rc = BLE_HS_ENOENT; } ble_hs_unlock(); @@ -1331,14 +1309,15 @@ ble_l2cap_sm_rx_key_exchange(uint16_t conn_handle, uint8_t op, /* a successful ending of the link */ if (rc == 0) { if (sm_end) { - /* TODO put error code here */ ble_l2cap_sm_gap_event(proc, 0, 1); ble_l2cap_sm_key_exchange_events(proc); ble_l2cap_sm_proc_free(proc); } } else { - rc = ble_l2cap_sm_process_status(proc, rc, sm_status, 1, 1); + ble_l2cap_sm_gap_event(proc, sm_status, 0); + ble_l2cap_sm_proc_free(proc); } + return rc; } @@ -1400,14 +1379,20 @@ ble_l2cap_sm_rx_pair_req(uint16_t conn_handle, uint8_t op, } } + if (rc != 0) { + ble_l2cap_sm_pair_fail_tx(proc->conn_handle, sm_status); + } + ble_hs_unlock(); - /* This has to be done after the unlock */ - if (passkey_action != BLE_GAP_PKACT_NONE) { - ble_gap_passkey_event(proc->conn_handle,sm_status, passkey_action); + if (rc == 0) { + if (passkey_action != BLE_GAP_PKACT_NONE) { + ble_gap_passkey_event(conn_handle, sm_status, passkey_action); + } + } else { + ble_l2cap_sm_proc_free(proc); } - rc = ble_l2cap_sm_process_status(proc, rc, sm_status, 0, 1); return rc; } @@ -1443,16 +1428,19 @@ ble_l2cap_sm_rx_pair_rsp(uint16_t conn_handle, uint8_t op, &passkey_action); if (rc != 0) { ble_l2cap_sm_proc_remove(proc, prev); + ble_l2cap_sm_pair_fail_tx(conn_handle, sm_status); } } + ble_hs_unlock(); - /* The GAP callback can only be executed after the unlock. */ - if (passkey_action != BLE_GAP_PKACT_NONE) { - ble_gap_passkey_event(proc->conn_handle,sm_status, passkey_action); + if (rc != 0) { + ble_l2cap_sm_gap_event(proc, rc, 0); + ble_l2cap_sm_proc_free(proc); + } else if (passkey_action != BLE_GAP_PKACT_NONE) { + ble_gap_passkey_event(conn_handle, sm_status, passkey_action); } - rc = ble_l2cap_sm_process_status(proc, rc, sm_status, 1, 1); return rc; } @@ -1482,11 +1470,16 @@ ble_l2cap_sm_rx_pair_confirm(uint16_t conn_handle, uint8_t op, rc = ble_l2cap_sm_confirm_handle(proc, &cmd, &sm_status); if (rc != 0) { ble_l2cap_sm_proc_remove(proc, prev); + ble_l2cap_sm_pair_fail_tx(conn_handle, sm_status); } } ble_hs_unlock(); - rc = ble_l2cap_sm_process_status(proc, rc, sm_status, 1, 1); + if (rc != 0) { + ble_l2cap_sm_gap_event(proc, rc, 0); + ble_l2cap_sm_proc_free(proc); + } + return rc; } @@ -1518,11 +1511,16 @@ ble_l2cap_sm_rx_pair_random(uint16_t conn_handle, uint8_t op, rc = ble_l2cap_sm_random_handle(proc, &cmd, &sm_status); if (rc != 0) { ble_l2cap_sm_proc_remove(proc, prev); + ble_l2cap_sm_pair_fail_tx(conn_handle, sm_status); } } ble_hs_unlock(); - rc = ble_l2cap_sm_process_status(proc, rc, sm_status, 1, 1); + if (rc != 0) { + ble_l2cap_sm_gap_event(proc, rc, 0); + ble_l2cap_sm_proc_free(proc); + } + return rc; } @@ -1552,9 +1550,14 @@ ble_l2cap_sm_rx_pair_fail(uint16_t conn_handle, uint8_t op, } ble_hs_unlock(); - rc = ble_l2cap_sm_process_status(proc, BLE_HS_SM_THEM_ERR(cmd.reason), - 0, 1, 0); - return rc; + if (proc == NULL) { + return BLE_HS_ENOENT; + } + + ble_l2cap_sm_gap_event(proc, BLE_HS_SM_THEM_ERR(cmd.reason), 0); + ble_l2cap_sm_proc_free(proc); + + return 0; } static int @@ -1666,7 +1669,10 @@ ble_l2cap_sm_rx_lt_key_req(struct hci_le_lt_key_req *evt) rc = ble_l2cap_sm_lt_key_req_ltk_handle(evt); } } else if (proc != NULL) { - rc = ble_l2cap_sm_process_status(proc, rc, 0, 1, 0); + ble_l2cap_sm_gap_event(proc, rc, 0); + ble_l2cap_sm_proc_free(proc); + } else { + rc = BLE_HS_ENOENT; } return rc; @@ -1707,12 +1713,10 @@ ble_l2cap_sm_rx_encryption_change(struct hci_encrypt_change *evt) ble_hs_unlock(); - if (proc != NULL && do_key_exchange == 0 && rc == 0) { + if (rc != 0 || (proc != NULL && do_key_exchange == 0)) { /* The pairing procedure is now complete. */ ble_l2cap_sm_gap_event(proc, BLE_HS_HCI_ERR(evt->status), enc_enabled); ble_l2cap_sm_proc_free(proc); - } else if (rc) { - ble_l2cap_sm_process_status(proc, rc, sm_status, 1, 1); } } @@ -1960,12 +1964,14 @@ ble_l2cap_sm_set_tk(uint16_t conn_handle, struct passkey_action *pkey) set_tk_return: if (proc != NULL && rc != 0) { ble_l2cap_sm_proc_remove(proc, prev); + ble_l2cap_sm_pair_fail_tx(conn_handle, sm_error); } ble_hs_unlock(); - if (rc != 0) { - rc = ble_l2cap_sm_process_status(proc, rc, sm_error, 1, 1); + if (proc != NULL && rc != 0) { + ble_l2cap_sm_gap_event(proc, rc, 0); + ble_l2cap_sm_proc_free(proc); } return rc; diff --git a/net/nimble/host/src/test/ble_l2cap_sm_test.c b/net/nimble/host/src/test/ble_l2cap_sm_test.c index dd22a73c..22077c10 100644 --- a/net/nimble/host/src/test/ble_l2cap_sm_test.c +++ b/net/nimble/host/src/test/ble_l2cap_sm_test.c @@ -66,14 +66,13 @@ ble_l2cap_sm_test_util_conn_cb(int event, int status, struct ble_gap_conn_ctxt *ctxt, void *arg) { struct ble_l2cap_sm_test_ltk_info *ltk_info; - - ble_l2cap_sm_test_gap_event = event; - ble_l2cap_sm_test_gap_status = status; + int rc; switch (event) { case BLE_GAP_EVENT_SECURITY: ble_l2cap_sm_test_sec_state = ctxt->desc->sec_state; - return 0; + rc = 0; + break; case BLE_GAP_EVENT_LTK_REQUEST: ltk_info = arg; @@ -88,19 +87,26 @@ ble_l2cap_sm_test_util_conn_cb(int event, int status, ble_l2cap_sm_test_ltk_params = *ctxt->ltk_params; if (ltk_info == NULL) { - return -1; + rc = -1; } else { - return 0; + rc = 0; } + break; default: return 0; } + + ble_l2cap_sm_test_gap_event = event; + ble_l2cap_sm_test_gap_status = status; + + return rc; } static void ble_l2cap_sm_test_util_rx_pair_cmd(struct ble_hs_conn *conn, uint8_t op, - struct ble_l2cap_sm_pair_cmd *cmd) + struct ble_l2cap_sm_pair_cmd *cmd, + int rx_status) { struct hci_data_hdr hci_hdr; struct os_mbuf *om; @@ -125,21 +131,25 @@ ble_l2cap_sm_test_util_rx_pair_cmd(struct ble_hs_conn *conn, uint8_t op, rc = ble_hs_test_util_l2cap_rx_first_frag(conn, BLE_L2CAP_CID_SM, &hci_hdr, om); - TEST_ASSERT_FATAL(rc == 0); + TEST_ASSERT(rc == rx_status); } static void ble_l2cap_sm_test_util_rx_pair_req(struct ble_hs_conn *conn, - struct ble_l2cap_sm_pair_cmd *req) + struct ble_l2cap_sm_pair_cmd *req, + int rx_status) { - ble_l2cap_sm_test_util_rx_pair_cmd(conn, BLE_L2CAP_SM_OP_PAIR_REQ, req); + ble_l2cap_sm_test_util_rx_pair_cmd(conn, BLE_L2CAP_SM_OP_PAIR_REQ, req, + rx_status); } static void ble_l2cap_sm_test_util_rx_pair_rsp(struct ble_hs_conn *conn, - struct ble_l2cap_sm_pair_cmd *rsp) + struct ble_l2cap_sm_pair_cmd *rsp, + int rx_status) { - ble_l2cap_sm_test_util_rx_pair_cmd(conn, BLE_L2CAP_SM_OP_PAIR_RSP, rsp); + ble_l2cap_sm_test_util_rx_pair_cmd(conn, BLE_L2CAP_SM_OP_PAIR_RSP, rsp, + rx_status); } static void @@ -392,105 +402,217 @@ ble_l2cap_sm_test_util_verify_tx_start_enc(uint16_t conn_handle, *****************************************************************************/ static void -ble_l2cap_sm_test_util_peer_lgcy_good( +ble_l2cap_sm_test_util_peer_fail_inval( + int we_are_master, uint8_t *init_addr, uint8_t *rsp_addr, struct ble_l2cap_sm_pair_cmd *pair_req, - struct ble_l2cap_sm_pair_cmd *pair_rsp, - struct ble_l2cap_sm_pair_confirm *confirm_req, - struct ble_l2cap_sm_pair_confirm *confirm_rsp, - struct ble_l2cap_sm_pair_random *random_req, - struct ble_l2cap_sm_pair_random *random_rsp, - int pair_alg, - uint8_t *tk, - uint8_t *stk, - uint64_t r, - uint16_t ediv) + struct ble_l2cap_sm_pair_fail *pair_fail) { struct ble_hs_conn *conn; ble_l2cap_sm_test_util_init(); ble_hs_test_util_set_public_addr(rsp_addr); - ble_l2cap_sm_dbg_set_next_pair_rand(random_rsp->value); conn = ble_hs_test_util_create_conn(2, init_addr, ble_l2cap_sm_test_util_conn_cb, NULL); - /* Peer is the initiator so we must be the slave. */ - conn->bhc_flags &= ~BLE_HS_CONN_F_MASTER; + if (!we_are_master) { + conn->bhc_flags &= ~BLE_HS_CONN_F_MASTER; + } TEST_ASSERT(!conn->bhc_sec_state.enc_enabled); TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 0); /* Receive a pair request from the peer. */ - ble_l2cap_sm_test_util_rx_pair_req(conn, pair_req); + ble_l2cap_sm_test_util_rx_pair_req(conn, pair_req, + BLE_HS_SM_US_ERR(pair_fail->reason)); TEST_ASSERT(!conn->bhc_sec_state.enc_enabled); - TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 1); + TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 0); - /* Ensure we sent the expected pair response. */ + /* Ensure we sent the expected pair fail. */ ble_hs_test_util_tx_all(); - ble_l2cap_sm_test_util_verify_tx_pair_rsp(pair_rsp); + ble_l2cap_sm_test_util_verify_tx_pair_fail(pair_fail); TEST_ASSERT(!conn->bhc_sec_state.enc_enabled); - TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 1); + TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 0); - /* Receive a pair confirm from the peer. */ - ble_l2cap_sm_test_util_rx_confirm(conn, confirm_req); - TEST_ASSERT(!conn->bhc_sec_state.enc_enabled); - TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 1); + /* Verify that security callback was not executed. */ + TEST_ASSERT(ble_l2cap_sm_test_gap_event == -1); + TEST_ASSERT(ble_l2cap_sm_test_gap_status == -1); - /* Ensure we sent the expected pair confirm. */ - ble_hs_test_util_tx_all(); - ble_l2cap_sm_test_util_verify_tx_pair_confirm(confirm_rsp); + /* Verify that connection has correct security state. */ TEST_ASSERT(!conn->bhc_sec_state.enc_enabled); - TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 1); + TEST_ASSERT(!conn->bhc_sec_state.authenticated); +} - /* Receive a pair random from the peer. */ - ble_l2cap_sm_test_util_rx_random(conn, random_req, 0); - TEST_ASSERT(!conn->bhc_sec_state.enc_enabled); - TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 1); +TEST_CASE(ble_l2cap_sm_test_case_peer_fail_inval) +{ + /* Invalid role detected before other arguments. */ + ble_l2cap_sm_test_util_peer_fail_inval( + 1, + ((uint8_t[]){0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c}), + ((uint8_t[]){0x03, 0x02, 0x01, 0x50, 0x13, 0x00}), + ((struct ble_l2cap_sm_pair_cmd[1]) { { + .io_cap = 0x14, + .oob_data_flag = 0, + .authreq = 0x12, + .max_enc_key_size = 20, + .init_key_dist = 0x0b, + .resp_key_dist = 0x11, + } }), + ((struct ble_l2cap_sm_pair_fail[1]) { { + .reason = BLE_L2CAP_SM_ERR_CMD_NOT_SUPP, + } }) + ); - /* Ensure we sent the expected pair random. */ - ble_hs_test_util_tx_all(); - ble_l2cap_sm_test_util_verify_tx_pair_random(random_rsp); - TEST_ASSERT(!conn->bhc_sec_state.enc_enabled); - TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 1); + /* Invalid IO capabiltiies. */ + ble_l2cap_sm_test_util_peer_fail_inval( + 0, + ((uint8_t[]){0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c}), + ((uint8_t[]){0x03, 0x02, 0x01, 0x50, 0x13, 0x00}), + ((struct ble_l2cap_sm_pair_cmd[1]) { { + .io_cap = 0x14, + .oob_data_flag = 0, + .authreq = 0x05, + .max_enc_key_size = 16, + .init_key_dist = 0x07, + .resp_key_dist = 0x07, + } }), + ((struct ble_l2cap_sm_pair_fail[1]) { { + .reason = BLE_L2CAP_SM_ERR_INVAL, + } }) + ); - /* Receive a long term key request from the controller. */ - ble_l2cap_sm_test_util_set_lt_key_req_reply_ack(0, 2); - ble_l2cap_sm_test_util_rx_lt_key_req(2, r, ediv); - TEST_ASSERT(!conn->bhc_sec_state.enc_enabled); - TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 1); + /* Invalid OOB flag. */ + ble_l2cap_sm_test_util_peer_fail_inval( + 0, + ((uint8_t[]){0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c}), + ((uint8_t[]){0x03, 0x02, 0x01, 0x50, 0x13, 0x00}), + ((struct ble_l2cap_sm_pair_cmd[1]) { { + .io_cap = 0x04, + .oob_data_flag = 2, + .authreq = 0x05, + .max_enc_key_size = 16, + .init_key_dist = 0x07, + .resp_key_dist = 0x07, + } }), + ((struct ble_l2cap_sm_pair_fail[1]) { { + .reason = BLE_L2CAP_SM_ERR_INVAL, + } }) + ); - /* Ensure we sent the expected long term key request reply command. */ - ble_l2cap_sm_test_util_verify_tx_lt_key_req_reply(2, stk); - TEST_ASSERT(!conn->bhc_sec_state.enc_enabled); - TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 1); + /* Invalid authreq - reserved bonding flag. */ + ble_l2cap_sm_test_util_peer_fail_inval( + 0, + ((uint8_t[]){0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c}), + ((uint8_t[]){0x03, 0x02, 0x01, 0x50, 0x13, 0x00}), + ((struct ble_l2cap_sm_pair_cmd[1]) { { + .io_cap = 0x04, + .oob_data_flag = 0, + .authreq = 0x2, + .max_enc_key_size = 16, + .init_key_dist = 0x07, + .resp_key_dist = 0x07, + } }), + ((struct ble_l2cap_sm_pair_fail[1]) { { + .reason = BLE_L2CAP_SM_ERR_INVAL, + } }) + ); - /* Receive an encryption changed event. */ - ble_l2cap_sm_test_util_rx_enc_change(2, 0, 1); + /* Invalid authreq - reserved other flag. */ + ble_l2cap_sm_test_util_peer_fail_inval( + 0, + ((uint8_t[]){0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c}), + ((uint8_t[]){0x03, 0x02, 0x01, 0x50, 0x13, 0x00}), + ((struct ble_l2cap_sm_pair_cmd[1]) { { + .io_cap = 0x04, + .oob_data_flag = 0, + .authreq = 0x20, + .max_enc_key_size = 16, + .init_key_dist = 0x07, + .resp_key_dist = 0x07, + } }), + ((struct ble_l2cap_sm_pair_fail[1]) { { + .reason = BLE_L2CAP_SM_ERR_INVAL, + } }) + ); - /* Pairing should now be complete. */ - TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 0); + /* Invalid key size - too small. */ + ble_l2cap_sm_test_util_peer_fail_inval( + 0, + ((uint8_t[]){0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c}), + ((uint8_t[]){0x03, 0x02, 0x01, 0x50, 0x13, 0x00}), + ((struct ble_l2cap_sm_pair_cmd[1]) { { + .io_cap = 0x04, + .oob_data_flag = 0, + .authreq = 0x5, + .max_enc_key_size = 6, + .init_key_dist = 0x07, + .resp_key_dist = 0x07, + } }), + ((struct ble_l2cap_sm_pair_fail[1]) { { + .reason = BLE_L2CAP_SM_ERR_INVAL, + } }) + ); - /* Verify that security callback was executed. */ - TEST_ASSERT(ble_l2cap_sm_test_gap_event == BLE_GAP_EVENT_SECURITY); - TEST_ASSERT(ble_l2cap_sm_test_gap_status == 0); - TEST_ASSERT(ble_l2cap_sm_test_sec_state.pair_alg == pair_alg); - TEST_ASSERT(ble_l2cap_sm_test_sec_state.enc_enabled); - TEST_ASSERT(!ble_l2cap_sm_test_sec_state.authenticated); + /* Invalid key size - too large. */ + ble_l2cap_sm_test_util_peer_fail_inval( + 0, + ((uint8_t[]){0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c}), + ((uint8_t[]){0x03, 0x02, 0x01, 0x50, 0x13, 0x00}), + ((struct ble_l2cap_sm_pair_cmd[1]) { { + .io_cap = 0x04, + .oob_data_flag = 0, + .authreq = 0x5, + .max_enc_key_size = 17, + .init_key_dist = 0x07, + .resp_key_dist = 0x07, + } }), + ((struct ble_l2cap_sm_pair_fail[1]) { { + .reason = BLE_L2CAP_SM_ERR_INVAL, + } }) + ); - /* Verify that connection has correct security state. */ - TEST_ASSERT(ble_l2cap_sm_test_sec_state.pair_alg == - conn->bhc_sec_state.pair_alg); - TEST_ASSERT(ble_l2cap_sm_test_sec_state.enc_enabled == - conn->bhc_sec_state.enc_enabled); - TEST_ASSERT(ble_l2cap_sm_test_sec_state.authenticated == - conn->bhc_sec_state.authenticated); + /* Invalid init key dist. */ + ble_l2cap_sm_test_util_peer_fail_inval( + 0, + ((uint8_t[]){0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c}), + ((uint8_t[]){0x03, 0x02, 0x01, 0x50, 0x13, 0x00}), + ((struct ble_l2cap_sm_pair_cmd[1]) { { + .io_cap = 0x04, + .oob_data_flag = 0, + .authreq = 0x5, + .max_enc_key_size = 16, + .init_key_dist = 0x10, + .resp_key_dist = 0x07, + } }), + ((struct ble_l2cap_sm_pair_fail[1]) { { + .reason = BLE_L2CAP_SM_ERR_INVAL, + } }) + ); + + /* Invalid resp key dist. */ + ble_l2cap_sm_test_util_peer_fail_inval( + 0, + ((uint8_t[]){0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c}), + ((uint8_t[]){0x03, 0x02, 0x01, 0x50, 0x13, 0x00}), + ((struct ble_l2cap_sm_pair_cmd[1]) { { + .io_cap = 0x04, + .oob_data_flag = 0, + .authreq = 0x5, + .max_enc_key_size = 16, + .init_key_dist = 0x07, + .resp_key_dist = 0x10, + } }), + ((struct ble_l2cap_sm_pair_fail[1]) { { + .reason = BLE_L2CAP_SM_ERR_INVAL, + } }) + ); } static void -ble_l2cap_sm_test_util_peer_lgcy_fail( +ble_l2cap_sm_test_util_peer_lgcy_fail_confirm( uint8_t *init_addr, uint8_t *rsp_addr, struct ble_l2cap_sm_pair_cmd *pair_req, @@ -517,7 +639,7 @@ ble_l2cap_sm_test_util_peer_lgcy_fail( TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 0); /* Receive a pair request from the peer. */ - ble_l2cap_sm_test_util_rx_pair_req(conn, pair_req); + ble_l2cap_sm_test_util_rx_pair_req(conn, pair_req, 0); TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 1); /* Ensure we sent the expected pair response. */ @@ -563,65 +685,9 @@ ble_l2cap_sm_test_util_peer_lgcy_fail( conn->bhc_sec_state.authenticated); } -TEST_CASE(ble_l2cap_sm_test_case_peer_lgcy_jw_good) -{ - ble_l2cap_sm_test_util_peer_lgcy_good( - ((uint8_t[]){0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c}), - ((uint8_t[]){0x03, 0x02, 0x01, 0x50, 0x13, 0x00}), - ((struct ble_l2cap_sm_pair_cmd[1]) { { - .io_cap = 0x04, - .oob_data_flag = 0, - .authreq = 0x05, - .max_enc_key_size = 16, - .init_key_dist = 0x07, - .resp_key_dist = 0x07, - } }), - ((struct ble_l2cap_sm_pair_cmd[1]) { { - .io_cap = 3, - .oob_data_flag = 0, - .authreq = 0, - .max_enc_key_size = 16, - .init_key_dist = 0, - .resp_key_dist = 0, - } }), - ((struct ble_l2cap_sm_pair_confirm[1]) { { - .value = { - 0x0a, 0xac, 0xa2, 0xae, 0xa6, 0x98, 0xdc, 0x6d, - 0x65, 0x84, 0x11, 0x69, 0x47, 0x36, 0x8d, 0xa0, - }, - } }), - ((struct ble_l2cap_sm_pair_confirm[1]) { { - .value = { - 0x45, 0xd2, 0x2c, 0x38, 0xd8, 0x91, 0x4f, 0x19, - 0xa2, 0xd4, 0xfc, 0x7d, 0xad, 0x37, 0x79, 0xe0 - }, - } }), - ((struct ble_l2cap_sm_pair_random[1]) { { - .value = { - 0x2b, 0x3b, 0x69, 0xe4, 0xef, 0xab, 0xcc, 0x48, - 0x78, 0x20, 0x1a, 0x54, 0x7a, 0x91, 0x5d, 0xfb, - }, - } }), - ((struct ble_l2cap_sm_pair_random[1]) { { - .value = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - } }), - BLE_L2CAP_SM_PAIR_ALG_JW, - NULL, - ((uint8_t[16]) { - 0xa4, 0x8e, 0x51, 0x0d, 0x33, 0xe7, 0x8f, 0x38, - 0x45, 0xf0, 0x67, 0xc3, 0xd4, 0x05, 0xb3, 0xe6, - }), - 0, - 0 - ); -} - -TEST_CASE(ble_l2cap_sm_test_case_peer_lgcy_fail) +TEST_CASE(ble_l2cap_sm_test_case_peer_lgcy_fail_confirm) { - ble_l2cap_sm_test_util_peer_lgcy_fail( + ble_l2cap_sm_test_util_peer_lgcy_fail_confirm( ((uint8_t[]){0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c}), ((uint8_t[]){0x03, 0x02, 0x01, 0x50, 0x13, 0x00}), ((struct ble_l2cap_sm_pair_cmd[1]) { { @@ -670,12 +736,8 @@ TEST_CASE(ble_l2cap_sm_test_case_peer_lgcy_fail) ); } -/***************************************************************************** - * $us * - *****************************************************************************/ - static void -ble_l2cap_sm_test_util_us_lgcy_good( +ble_l2cap_sm_test_util_peer_lgcy_good( uint8_t *init_addr, uint8_t *rsp_addr, struct ble_l2cap_sm_pair_cmd *pair_req, @@ -691,61 +753,62 @@ ble_l2cap_sm_test_util_us_lgcy_good( uint16_t ediv) { struct ble_hs_conn *conn; - int rc; ble_l2cap_sm_test_util_init(); - ble_hs_test_util_set_public_addr(init_addr); - ble_l2cap_sm_dbg_set_next_pair_rand(random_req->value); - ble_l2cap_sm_dbg_set_next_ediv(ediv); - ble_l2cap_sm_dbg_set_next_start_rand(r); + ble_hs_test_util_set_public_addr(rsp_addr); + ble_l2cap_sm_dbg_set_next_pair_rand(random_rsp->value); - conn = ble_hs_test_util_create_conn(2, rsp_addr, + conn = ble_hs_test_util_create_conn(2, init_addr, ble_l2cap_sm_test_util_conn_cb, NULL); + /* Peer is the initiator so we must be the slave. */ + conn->bhc_flags &= ~BLE_HS_CONN_F_MASTER; + TEST_ASSERT(!conn->bhc_sec_state.enc_enabled); TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 0); - /* Initiate the pairing procedure. */ - rc = ble_hs_test_util_security_initiate(2, 0); - TEST_ASSERT_FATAL(rc == 0); + /* Receive a pair request from the peer. */ + ble_l2cap_sm_test_util_rx_pair_req(conn, pair_req, 0); + TEST_ASSERT(!conn->bhc_sec_state.enc_enabled); + TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 1); - /* Ensure we sent the expected pair request. */ + /* Ensure we sent the expected pair response. */ ble_hs_test_util_tx_all(); - ble_l2cap_sm_test_util_verify_tx_pair_req(pair_req); + ble_l2cap_sm_test_util_verify_tx_pair_rsp(pair_rsp); TEST_ASSERT(!conn->bhc_sec_state.enc_enabled); TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 1); - /* Receive a pair response from the peer. */ - ble_l2cap_sm_test_util_rx_pair_rsp(conn, pair_rsp); + /* Receive a pair confirm from the peer. */ + ble_l2cap_sm_test_util_rx_confirm(conn, confirm_req); TEST_ASSERT(!conn->bhc_sec_state.enc_enabled); TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 1); /* Ensure we sent the expected pair confirm. */ ble_hs_test_util_tx_all(); - ble_l2cap_sm_test_util_verify_tx_pair_confirm(confirm_req); + ble_l2cap_sm_test_util_verify_tx_pair_confirm(confirm_rsp); TEST_ASSERT(!conn->bhc_sec_state.enc_enabled); TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 1); - /* Receive a pair confirm from the peer. */ - ble_l2cap_sm_test_util_rx_confirm(conn, confirm_rsp); + /* Receive a pair random from the peer. */ + ble_l2cap_sm_test_util_rx_random(conn, random_req, 0); TEST_ASSERT(!conn->bhc_sec_state.enc_enabled); TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 1); /* Ensure we sent the expected pair random. */ ble_hs_test_util_tx_all(); - ble_l2cap_sm_test_util_verify_tx_pair_random(random_req); + ble_l2cap_sm_test_util_verify_tx_pair_random(random_rsp); TEST_ASSERT(!conn->bhc_sec_state.enc_enabled); TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 1); - /* Receive a pair random from the peer. */ - ble_l2cap_sm_test_util_rx_random(conn, random_rsp, 0); + /* Receive a long term key request from the controller. */ + ble_l2cap_sm_test_util_set_lt_key_req_reply_ack(0, 2); + ble_l2cap_sm_test_util_rx_lt_key_req(2, r, ediv); TEST_ASSERT(!conn->bhc_sec_state.enc_enabled); TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 1); - /* Ensure we sent the expected start encryption command. */ - ble_hs_test_util_tx_all(); - ble_l2cap_sm_test_util_verify_tx_start_enc(2, r, ediv, stk); + /* Ensure we sent the expected long term key request reply command. */ + ble_l2cap_sm_test_util_verify_tx_lt_key_req_reply(2, stk); TEST_ASSERT(!conn->bhc_sec_state.enc_enabled); TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 1); @@ -771,18 +834,18 @@ ble_l2cap_sm_test_util_us_lgcy_good( conn->bhc_sec_state.authenticated); } -TEST_CASE(ble_l2cap_sm_test_case_us_lgcy_jw_good) +TEST_CASE(ble_l2cap_sm_test_case_peer_lgcy_jw_good) { - ble_l2cap_sm_test_util_us_lgcy_good( - ((uint8_t[]){0x06, 0x05, 0x04, 0x03, 0x02, 0x01}), - ((uint8_t[]){0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a}), + ble_l2cap_sm_test_util_peer_lgcy_good( + ((uint8_t[]){0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c}), + ((uint8_t[]){0x03, 0x02, 0x01, 0x50, 0x13, 0x00}), ((struct ble_l2cap_sm_pair_cmd[1]) { { - .io_cap = 3, + .io_cap = 0x04, .oob_data_flag = 0, - .authreq = 0, + .authreq = 0x05, .max_enc_key_size = 16, - .init_key_dist = 0, - .resp_key_dist = 0, + .init_key_dist = 0x07, + .resp_key_dist = 0x07, } }), ((struct ble_l2cap_sm_pair_cmd[1]) { { .io_cap = 3, @@ -794,20 +857,20 @@ TEST_CASE(ble_l2cap_sm_test_case_us_lgcy_jw_good) } }), ((struct ble_l2cap_sm_pair_confirm[1]) { { .value = { - 0x04, 0x4e, 0xaf, 0xce, 0x30, 0x79, 0x2c, 0x9e, - 0xa2, 0xeb, 0x53, 0x6a, 0xdf, 0xf7, 0x99, 0xb2, + 0x0a, 0xac, 0xa2, 0xae, 0xa6, 0x98, 0xdc, 0x6d, + 0x65, 0x84, 0x11, 0x69, 0x47, 0x36, 0x8d, 0xa0, }, } }), ((struct ble_l2cap_sm_pair_confirm[1]) { { .value = { - 0x04, 0x4e, 0xaf, 0xce, 0x30, 0x79, 0x2c, 0x9e, - 0xa2, 0xeb, 0x53, 0x6a, 0xdf, 0xf7, 0x99, 0xb2, + 0x45, 0xd2, 0x2c, 0x38, 0xd8, 0x91, 0x4f, 0x19, + 0xa2, 0xd4, 0xfc, 0x7d, 0xad, 0x37, 0x79, 0xe0 }, } }), ((struct ble_l2cap_sm_pair_random[1]) { { .value = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2b, 0x3b, 0x69, 0xe4, 0xef, 0xab, 0xcc, 0x48, + 0x78, 0x20, 0x1a, 0x54, 0x7a, 0x91, 0x5d, 0xfb, }, } }), ((struct ble_l2cap_sm_pair_random[1]) { { @@ -819,8 +882,8 @@ TEST_CASE(ble_l2cap_sm_test_case_us_lgcy_jw_good) BLE_L2CAP_SM_PAIR_ALG_JW, NULL, ((uint8_t[16]) { - 0x2e, 0x2b, 0x34, 0xca, 0x59, 0xfa, 0x4c, 0x88, - 0x3b, 0x2c, 0x8a, 0xef, 0xd4, 0x4b, 0xe9, 0x66, + 0xa4, 0x8e, 0x51, 0x0d, 0x33, 0xe7, 0x8f, 0x38, + 0x45, 0xf0, 0x67, 0xc3, 0xd4, 0x05, 0xb3, 0xe6, }), 0, 0 @@ -946,10 +1009,168 @@ TEST_CASE(ble_l2cap_sm_test_case_peer_bonding_bad) ble_l2cap_sm_test_util_peer_bonding_bad(54325, 65437); } +/***************************************************************************** + * $us * + *****************************************************************************/ + +static void +ble_l2cap_sm_test_util_us_lgcy_good( + uint8_t *init_addr, + uint8_t *rsp_addr, + struct ble_l2cap_sm_pair_cmd *pair_req, + struct ble_l2cap_sm_pair_cmd *pair_rsp, + struct ble_l2cap_sm_pair_confirm *confirm_req, + struct ble_l2cap_sm_pair_confirm *confirm_rsp, + struct ble_l2cap_sm_pair_random *random_req, + struct ble_l2cap_sm_pair_random *random_rsp, + int pair_alg, + uint8_t *tk, + uint8_t *stk, + uint64_t r, + uint16_t ediv) +{ + struct ble_hs_conn *conn; + int rc; + + ble_l2cap_sm_test_util_init(); + ble_hs_test_util_set_public_addr(init_addr); + ble_l2cap_sm_dbg_set_next_pair_rand(random_req->value); + ble_l2cap_sm_dbg_set_next_ediv(ediv); + ble_l2cap_sm_dbg_set_next_start_rand(r); + + conn = ble_hs_test_util_create_conn(2, rsp_addr, + ble_l2cap_sm_test_util_conn_cb, + NULL); + + TEST_ASSERT(!conn->bhc_sec_state.enc_enabled); + TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 0); + + /* Initiate the pairing procedure. */ + rc = ble_hs_test_util_security_initiate(2, 0); + TEST_ASSERT_FATAL(rc == 0); + + /* Ensure we sent the expected pair request. */ + ble_hs_test_util_tx_all(); + ble_l2cap_sm_test_util_verify_tx_pair_req(pair_req); + TEST_ASSERT(!conn->bhc_sec_state.enc_enabled); + TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 1); + + /* Receive a pair response from the peer. */ + ble_l2cap_sm_test_util_rx_pair_rsp(conn, pair_rsp, 0); + TEST_ASSERT(!conn->bhc_sec_state.enc_enabled); + TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 1); + + /* Ensure we sent the expected pair confirm. */ + ble_hs_test_util_tx_all(); + ble_l2cap_sm_test_util_verify_tx_pair_confirm(confirm_req); + TEST_ASSERT(!conn->bhc_sec_state.enc_enabled); + TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 1); + + /* Receive a pair confirm from the peer. */ + ble_l2cap_sm_test_util_rx_confirm(conn, confirm_rsp); + TEST_ASSERT(!conn->bhc_sec_state.enc_enabled); + TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 1); + + /* Ensure we sent the expected pair random. */ + ble_hs_test_util_tx_all(); + ble_l2cap_sm_test_util_verify_tx_pair_random(random_req); + TEST_ASSERT(!conn->bhc_sec_state.enc_enabled); + TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 1); + + /* Receive a pair random from the peer. */ + ble_l2cap_sm_test_util_rx_random(conn, random_rsp, 0); + TEST_ASSERT(!conn->bhc_sec_state.enc_enabled); + TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 1); + + /* Ensure we sent the expected start encryption command. */ + ble_hs_test_util_tx_all(); + ble_l2cap_sm_test_util_verify_tx_start_enc(2, r, ediv, stk); + TEST_ASSERT(!conn->bhc_sec_state.enc_enabled); + TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 1); + + /* Receive an encryption changed event. */ + ble_l2cap_sm_test_util_rx_enc_change(2, 0, 1); + + /* Pairing should now be complete. */ + TEST_ASSERT(ble_l2cap_sm_dbg_num_procs() == 0); + + /* Verify that security callback was executed. */ + TEST_ASSERT(ble_l2cap_sm_test_gap_event == BLE_GAP_EVENT_SECURITY); + TEST_ASSERT(ble_l2cap_sm_test_gap_status == 0); + TEST_ASSERT(ble_l2cap_sm_test_sec_state.pair_alg == pair_alg); + TEST_ASSERT(ble_l2cap_sm_test_sec_state.enc_enabled); + TEST_ASSERT(!ble_l2cap_sm_test_sec_state.authenticated); + + /* Verify that connection has correct security state. */ + TEST_ASSERT(ble_l2cap_sm_test_sec_state.pair_alg == + conn->bhc_sec_state.pair_alg); + TEST_ASSERT(ble_l2cap_sm_test_sec_state.enc_enabled == + conn->bhc_sec_state.enc_enabled); + TEST_ASSERT(ble_l2cap_sm_test_sec_state.authenticated == + conn->bhc_sec_state.authenticated); +} + +TEST_CASE(ble_l2cap_sm_test_case_us_lgcy_jw_good) +{ + ble_l2cap_sm_test_util_us_lgcy_good( + ((uint8_t[]){0x06, 0x05, 0x04, 0x03, 0x02, 0x01}), + ((uint8_t[]){0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a}), + ((struct ble_l2cap_sm_pair_cmd[1]) { { + .io_cap = 3, + .oob_data_flag = 0, + .authreq = 0, + .max_enc_key_size = 16, + .init_key_dist = 0, + .resp_key_dist = 0, + } }), + ((struct ble_l2cap_sm_pair_cmd[1]) { { + .io_cap = 3, + .oob_data_flag = 0, + .authreq = 0, + .max_enc_key_size = 16, + .init_key_dist = 0, + .resp_key_dist = 0, + } }), + ((struct ble_l2cap_sm_pair_confirm[1]) { { + .value = { + 0x04, 0x4e, 0xaf, 0xce, 0x30, 0x79, 0x2c, 0x9e, + 0xa2, 0xeb, 0x53, 0x6a, 0xdf, 0xf7, 0x99, 0xb2, + }, + } }), + ((struct ble_l2cap_sm_pair_confirm[1]) { { + .value = { + 0x04, 0x4e, 0xaf, 0xce, 0x30, 0x79, 0x2c, 0x9e, + 0xa2, 0xeb, 0x53, 0x6a, 0xdf, 0xf7, 0x99, 0xb2, + }, + } }), + ((struct ble_l2cap_sm_pair_random[1]) { { + .value = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + } }), + ((struct ble_l2cap_sm_pair_random[1]) { { + .value = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + } }), + BLE_L2CAP_SM_PAIR_ALG_JW, + NULL, + ((uint8_t[16]) { + 0x2e, 0x2b, 0x34, 0xca, 0x59, 0xfa, 0x4c, 0x88, + 0x3b, 0x2c, 0x8a, 0xef, 0xd4, 0x4b, 0xe9, 0x66, + }), + 0, + 0 + ); +} + TEST_SUITE(ble_l2cap_sm_test_suite) { + ble_l2cap_sm_test_case_peer_fail_inval(); + ble_l2cap_sm_test_case_peer_lgcy_fail_confirm(); ble_l2cap_sm_test_case_peer_lgcy_jw_good(); - ble_l2cap_sm_test_case_peer_lgcy_fail(); ble_l2cap_sm_test_case_us_lgcy_jw_good(); ble_l2cap_sm_test_case_peer_bonding_good(); ble_l2cap_sm_test_case_peer_bonding_bad(); @@ -962,6 +1183,7 @@ ble_l2cap_sm_test_all(void) #if !NIMBLE_OPT_SM return 0; #else + tu_config.tc_system_assert=1; ble_l2cap_sm_test_suite(); return tu_any_failed; |