You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2016/06/05 11:52:24 UTC

[37/43] incubator-mynewt-core git commit: BLE Host - Rearrange SM test code.

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/fcafe0a2/net/nimble/host/src/test/ble_sm_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_sm_test.c b/net/nimble/host/src/test/ble_sm_test.c
index aa9182a..6c17eee 100644
--- a/net/nimble/host/src/test/ble_sm_test.c
+++ b/net/nimble/host/src/test/ble_sm_test.c
@@ -765,9 +765,118 @@ ble_sm_test_util_verify_sc_persist(struct ble_sm_test_sc_params *params)
     TEST_ASSERT_FATAL(rc == BLE_HS_ENOENT);
 }
 
-/*****************************************************************************
- * $peer                                                                     *
- *****************************************************************************/
+static void
+ble_sm_test_util_us_lgcy_good(
+    struct ble_sm_test_lgcy_params *params)
+{
+    struct ble_hs_conn *conn;
+    int rc;
+
+    ble_sm_test_util_init();
+    ble_hs_test_util_set_public_addr(params->init_addr);
+    ble_sm_dbg_set_next_pair_rand(params->random_req.value);
+    ble_sm_dbg_set_next_ediv(params->ediv);
+    ble_sm_dbg_set_next_start_rand(params->r);
+
+    if (params->has_enc_info_req) {
+        ble_sm_dbg_set_next_ltk(params->enc_info_req.ltk);
+    }
+
+    ble_hs_test_util_create_conn(2, params->rsp_addr,
+                                 ble_sm_test_util_conn_cb,
+                                 NULL);
+
+    /* This test inspects and modifies the connection object after unlocking
+     * the host mutex.  It is not OK for real code to do this, but this test
+     * can assume the connection list is unchanging.
+     */
+    ble_hs_lock();
+    conn = ble_hs_conn_find(2);
+    TEST_ASSERT_FATAL(conn != NULL);
+    ble_hs_unlock();
+
+    TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
+    TEST_ASSERT(ble_sm_dbg_num_procs() == 0);
+
+    ble_hs_test_util_set_ack(
+        host_hci_opcode_join(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_START_ENCRYPT), 0);
+    if (params->has_sec_req) {
+        ble_sm_test_util_rx_sec_req(2, &params->sec_req, 0);
+    } else {
+        /* Initiate the pairing procedure. */
+        rc = ble_gap_security_initiate(2);
+        TEST_ASSERT_FATAL(rc == 0);
+    }
+
+    /* Ensure we sent the expected pair request. */
+    ble_hs_test_util_tx_all();
+    ble_sm_test_util_verify_tx_pair_req(&params->pair_req);
+    TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
+    TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
+
+    /* Receive a pair response from the peer. */
+    ble_sm_test_util_rx_pair_rsp(2, &params->pair_rsp, 0);
+    TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
+    TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
+
+    /* Ensure we sent the expected pair confirm. */
+    ble_hs_test_util_tx_all();
+    ble_sm_test_util_verify_tx_pair_confirm(&params->confirm_req);
+    TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
+    TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
+
+    /* Receive a pair confirm from the peer. */
+    ble_sm_test_util_rx_confirm(2, &params->confirm_rsp);
+    TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
+    TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
+
+    /* Ensure we sent the expected pair random. */
+    ble_hs_test_util_tx_all();
+    ble_sm_test_util_verify_tx_pair_random(&params->random_req);
+    TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
+    TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
+
+    /* Receive a pair random from the peer. */
+    ble_sm_test_util_rx_random(2, &params->random_rsp, 0);
+    TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
+    TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
+
+    /* Ensure keys are distributed, if necessary. */
+    if (params->has_enc_info_req) {
+        ble_sm_test_util_verify_tx_enc_info(&params->enc_info_req);
+    }
+
+    /* Ensure we sent the expected start encryption command. */
+    ble_hs_test_util_tx_all();
+    ble_sm_test_util_verify_tx_start_enc(2, params->r, params->ediv,
+                                               params->stk);
+    TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
+    TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
+
+    /* Receive an encryption changed event. */
+    ble_sm_test_util_rx_enc_change(2, 0, 1);
+
+    /* Pairing should now be complete. */
+    TEST_ASSERT(ble_sm_dbg_num_procs() == 0);
+
+    /* Verify that security callback was executed. */
+    TEST_ASSERT(ble_sm_test_gap_event == BLE_GAP_EVENT_ENC_CHANGE);
+    TEST_ASSERT(ble_sm_test_gap_status == 0);
+    TEST_ASSERT(ble_sm_test_sec_state.pair_alg == params->pair_alg);
+    TEST_ASSERT(ble_sm_test_sec_state.enc_enabled);
+    TEST_ASSERT(!ble_sm_test_sec_state.authenticated);
+
+    /* Verify that connection has correct security state. */
+    TEST_ASSERT(ble_sm_test_sec_state.pair_alg ==
+                conn->bhc_sec_state.pair_alg);
+    TEST_ASSERT(ble_sm_test_sec_state.enc_enabled ==
+                conn->bhc_sec_state.enc_enabled);
+    TEST_ASSERT(ble_sm_test_sec_state.authenticated ==
+                conn->bhc_sec_state.authenticated);
+
+    /* Verify the appropriate security material was persisted. */
+    ble_sm_test_util_verify_lgcy_persist(params);
+}
 
 static void
 ble_sm_test_util_peer_fail_inval(
@@ -822,205 +931,40 @@ ble_sm_test_util_peer_fail_inval(
     TEST_ASSERT(!conn->bhc_sec_state.authenticated);
 }
 
-TEST_CASE(ble_sm_test_case_peer_fail_inval)
+static void
+ble_sm_test_util_peer_lgcy_fail_confirm(
+    uint8_t *init_addr,
+    uint8_t *rsp_addr,
+    struct ble_sm_pair_cmd *pair_req,
+    struct ble_sm_pair_cmd *pair_rsp,
+    struct ble_sm_pair_confirm *confirm_req,
+    struct ble_sm_pair_confirm *confirm_rsp,
+    struct ble_sm_pair_random *random_req,
+    struct ble_sm_pair_random *random_rsp,
+    struct ble_sm_pair_fail *fail_rsp)
 {
-    /* Invalid role detected before other arguments. */
-    ble_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_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_sm_pair_fail[1]) { {
-            .reason = BLE_SM_ERR_CMD_NOT_SUPP,
-        } })
-    );
+    struct ble_hs_conn *conn;
 
-    /* Invalid IO capabiltiies. */
-    ble_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_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_sm_pair_fail[1]) { {
-            .reason = BLE_SM_ERR_INVAL,
-        } })
-    );
+    ble_sm_test_util_init();
+    ble_hs_test_util_set_public_addr(rsp_addr);
+    ble_sm_dbg_set_next_pair_rand(random_rsp->value);
 
-    /* Invalid OOB flag. */
-    ble_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_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_sm_pair_fail[1]) { {
-            .reason = BLE_SM_ERR_INVAL,
-        } })
-    );
+    ble_hs_test_util_create_conn(2, init_addr, ble_sm_test_util_conn_cb,
+                                 NULL);
 
-    /* Invalid authreq - reserved bonding flag. */
-    ble_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_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_sm_pair_fail[1]) { {
-            .reason = BLE_SM_ERR_INVAL,
-        } })
-    );
+    /* This test inspects and modifies the connection object after unlocking
+     * the host mutex.  It is not OK for real code to do this, but this test
+     * can assume the connection list is unchanging.
+     */
+    ble_hs_lock();
+    conn = ble_hs_conn_find(2);
+    TEST_ASSERT_FATAL(conn != NULL);
+    ble_hs_unlock();
 
-    /* Invalid authreq - reserved other flag. */
-    ble_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_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_sm_pair_fail[1]) { {
-            .reason = BLE_SM_ERR_INVAL,
-        } })
-    );
+    /* Peer is the initiator so we must be the slave. */
+    conn->bhc_flags &= ~BLE_HS_CONN_F_MASTER;
 
-    /* Invalid key size - too small. */
-    ble_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_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_sm_pair_fail[1]) { {
-            .reason = BLE_SM_ERR_INVAL,
-        } })
-    );
-
-    /* Invalid key size - too large. */
-    ble_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_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_sm_pair_fail[1]) { {
-            .reason = BLE_SM_ERR_INVAL,
-        } })
-    );
-
-    /* Invalid init key dist. */
-    ble_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_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_sm_pair_fail[1]) { {
-            .reason = BLE_SM_ERR_INVAL,
-        } })
-    );
-
-    /* Invalid resp key dist. */
-    ble_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_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_sm_pair_fail[1]) { {
-            .reason = BLE_SM_ERR_INVAL,
-        } })
-    );
-}
-
-static void
-ble_sm_test_util_peer_lgcy_fail_confirm(
-    uint8_t *init_addr,
-    uint8_t *rsp_addr,
-    struct ble_sm_pair_cmd *pair_req,
-    struct ble_sm_pair_cmd *pair_rsp,
-    struct ble_sm_pair_confirm *confirm_req,
-    struct ble_sm_pair_confirm *confirm_rsp,
-    struct ble_sm_pair_random *random_req,
-    struct ble_sm_pair_random *random_rsp,
-    struct ble_sm_pair_fail *fail_rsp)
-{
-    struct ble_hs_conn *conn;
-
-    ble_sm_test_util_init();
-    ble_hs_test_util_set_public_addr(rsp_addr);
-    ble_sm_dbg_set_next_pair_rand(random_rsp->value);
-
-    ble_hs_test_util_create_conn(2, init_addr, ble_sm_test_util_conn_cb,
-                                 NULL);
-
-    /* This test inspects and modifies the connection object after unlocking
-     * the host mutex.  It is not OK for real code to do this, but this test
-     * can assume the connection list is unchanging.
-     */
-    ble_hs_lock();
-    conn = ble_hs_conn_find(2);
-    TEST_ASSERT_FATAL(conn != NULL);
-    ble_hs_unlock();
-
-    /* Peer is the initiator so we must be the slave. */
-    conn->bhc_flags &= ~BLE_HS_CONN_F_MASTER;
-
-    TEST_ASSERT(ble_sm_dbg_num_procs() == 0);
+    TEST_ASSERT(ble_sm_dbg_num_procs() == 0);
 
     /* Receive a pair request from the peer. */
     ble_sm_test_util_rx_pair_req(2, pair_req, 0);
@@ -1069,57 +1013,6 @@ ble_sm_test_util_peer_lgcy_fail_confirm(
                 conn->bhc_sec_state.authenticated);
 }
 
-TEST_CASE(ble_sm_test_case_peer_lgcy_fail_confirm)
-{
-    ble_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_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_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_sm_pair_confirm[1]) { {
-            .value = {
-                0x0a, 0xac, 0xa2, 0xae, 0xa6, 0x98, 0xdc, 0x6d,
-                0x65, 0x84, 0x11, 0x69, 0x47, 0x36, 0x8d, 0xa0,
-            },
-        } }),
-        ((struct ble_sm_pair_confirm[1]) { {
-            .value = {
-                0x45, 0xd2, 0x2c, 0x38, 0xd8, 0x91, 0x4f, 0x19,
-                0xa2, 0xd4, 0xfc, 0x7d, 0xad, 0x37, 0x79, 0xe0
-            },
-        } }),
-        ((struct ble_sm_pair_random[1]) { {
-            .value = {
-                0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-                0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-            },
-        } }),
-        ((struct ble_sm_pair_random[1]) { {
-            .value = {
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-            },
-        } }),
-        ((struct ble_sm_pair_fail[1]) { {
-            .reason = BLE_SM_ERR_CONFIRM_MISMATCH,
-        } })
-    );
-}
-
 static void
 ble_sm_test_util_peer_lgcy_good_once(struct ble_sm_test_lgcy_params *params)
 {
@@ -1266,180 +1159,26 @@ ble_sm_test_util_peer_lgcy_good(struct ble_sm_test_lgcy_params *params)
     ble_sm_test_util_peer_lgcy_good_once(params);
 }
 
-TEST_CASE(ble_sm_test_case_peer_lgcy_jw_good)
+/**
+ * @param send_enc_req          Whether this procedure is initiated by a slave
+ *                                  security request;
+ *                                  1: We send a security request at start.
+ *                                  0: No security request; peer initiates.
+ */
+static void
+ble_sm_test_util_peer_bonding_good(int send_enc_req, uint8_t *ltk,
+                                         int authenticated,
+                                         uint16_t ediv, uint64_t rand_num)
 {
-    struct ble_sm_test_lgcy_params params;
+    struct ble_store_value_sec value_sec;
+    struct ble_hs_conn *conn;
+    int rc;
 
-    params = (struct ble_sm_test_lgcy_params) {
-        .init_addr = {0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c},
-        .rsp_addr = {0x03, 0x02, 0x01, 0x50, 0x13, 0x00},
-        .pair_req = (struct ble_sm_pair_cmd) {
-            .io_cap = 0x04,
-            .oob_data_flag = 0,
-            .authreq = 0x05,
-            .max_enc_key_size = 16,
-            .init_key_dist = 0x07,
-            .resp_key_dist = 0x07,
-        },
-        .pair_rsp = (struct ble_sm_pair_cmd) {
-            .io_cap = 3,
-            .oob_data_flag = 0,
-            .authreq = 0,
-            .max_enc_key_size = 16,
-            .init_key_dist = 0,
-            .resp_key_dist = 0,
-        },
-        .confirm_req = (struct ble_sm_pair_confirm) {
-            .value = {
-                0x0a, 0xac, 0xa2, 0xae, 0xa6, 0x98, 0xdc, 0x6d,
-                0x65, 0x84, 0x11, 0x69, 0x47, 0x36, 0x8d, 0xa0,
-            },
-        },
-        .confirm_rsp = (struct ble_sm_pair_confirm) {
-            .value = {
-                0x45, 0xd2, 0x2c, 0x38, 0xd8, 0x91, 0x4f, 0x19,
-                0xa2, 0xd4, 0xfc, 0x7d, 0xad, 0x37, 0x79, 0xe0
-            },
-        },
-        .random_req = (struct ble_sm_pair_random) {
-            .value = {
-                0x2b, 0x3b, 0x69, 0xe4, 0xef, 0xab, 0xcc, 0x48,
-                0x78, 0x20, 0x1a, 0x54, 0x7a, 0x91, 0x5d, 0xfb,
-            },
-        },
-        .random_rsp = (struct ble_sm_pair_random) {
-            .value = {
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-            },
-        },
-        .pair_alg = BLE_SM_PAIR_ALG_JW,
-        .authenticated = 0,
-        .tk = { 0 },
-        .stk = {
-            0xa4, 0x8e, 0x51, 0x0d, 0x33, 0xe7, 0x8f, 0x38,
-            0x45, 0xf0, 0x67, 0xc3, 0xd4, 0x05, 0xb3, 0xe6,
-        },
-        .r = 0,
-        .ediv = 0,
-    };
-    ble_sm_test_util_peer_lgcy_good(&params);
-}
+    ble_sm_test_util_init();
 
-TEST_CASE(ble_sm_test_case_peer_lgcy_passkey_good)
-{
-    struct ble_sm_test_lgcy_params params;
-
-    params = (struct ble_sm_test_lgcy_params) {
-        .init_addr = {0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c},
-        .rsp_addr = {0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07},
-        .pair_req = (struct ble_sm_pair_cmd) {
-            .io_cap = 0x04,
-            .oob_data_flag = 0, .authreq = 0x05,
-            .max_enc_key_size = 16,
-            .init_key_dist = 0x07,
-            .resp_key_dist = 0x07,
-        },
-        .pair_rsp = (struct ble_sm_pair_cmd) {
-            .io_cap = 0x02,
-            .oob_data_flag = 0,
-            .authreq = 0x05,
-            .max_enc_key_size = 16,
-            .init_key_dist = 0x01,
-            .resp_key_dist = 0x01,
-        },
-        .confirm_req = (struct ble_sm_pair_confirm) {
-            .value = {
-                0x54, 0xed, 0x7c, 0x65, 0xc5, 0x3a, 0xee, 0x87,
-                0x8e, 0xf8, 0x04, 0xd8, 0x93, 0xb0, 0xfa, 0xa4,
-            },
-        },
-        .confirm_rsp = (struct ble_sm_pair_confirm) {
-            .value = {
-                0xdf, 0x96, 0x88, 0x73, 0x49, 0x24, 0x3f, 0xe8,
-                0xb0, 0xaf, 0xb3, 0xf6, 0xc8, 0xf4, 0xe2, 0x36,
-            },
-        },
-        .random_req = (struct ble_sm_pair_random) {
-            .value = {
-                0x4d, 0x2c, 0xf2, 0xb7, 0x11, 0x56, 0xbd, 0x4f,
-                0xfc, 0xde, 0xa9, 0x86, 0x4d, 0xfd, 0x77, 0x03,
-            },
-        },
-        .random_rsp = {
-            .value = {
-                0x12, 0x45, 0x65, 0x2c, 0x85, 0x56, 0x32, 0x8f,
-                0xf4, 0x7f, 0x44, 0xd0, 0x17, 0x35, 0x41, 0xed
-            },
-        },
-        .pair_alg = BLE_SM_PAIR_ALG_PASSKEY,
-        .authenticated = 1,
-        .tk = {
-            0x5a, 0x7f, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00,
-            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-        },
-        .stk = {
-            0x2b, 0x9c, 0x1e, 0x42, 0xa8, 0xcb, 0xab, 0xd1,
-            0x4b, 0xde, 0x50, 0x05, 0x50, 0xd9, 0x95, 0xc6
-        },
-        .r = 4107344270811490869,
-        .ediv = 61621,
-
-        .passkey_info = {
-            .passkey = {
-                .action = BLE_SM_PKACT_INPUT,
-                .passkey = 884570,
-            },
-        },
-
-        .enc_info_req = {
-            .ltk = {
-                0x2b, 0x9c, 0x1e, 0x42, 0xa8, 0xcb, 0xab, 0xd1,
-                0x4b, 0xde, 0x50, 0x05, 0x50, 0xd9, 0x95, 0xc6
-            },
-        },
-        .has_enc_info_req = 1,
-
-        .master_id_req = {
-            .ediv = 61621,
-            .rand_val = 4107344270811490869,
-        },
-        .has_master_id_req = 1,
-
-        .enc_info_rsp = {
-            .ltk = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 }
-        },
-        .has_enc_info_rsp = 1,
-
-        .master_id_rsp = {
-            .ediv = 61621,
-            .rand_val = 4107344270811490869,
-        },
-        .has_master_id_rsp = 1,
-    };
-    ble_sm_test_util_peer_lgcy_good(&params);
-}
-
-/**
- * @param send_enc_req          Whether this procedure is initiated by a slave
- *                                  security request;
- *                                  1: We send a security request at start.
- *                                  0: No security request; peer initiates.
- */
-static void
-ble_sm_test_util_peer_bonding_good(int send_enc_req, uint8_t *ltk,
-                                         int authenticated,
-                                         uint16_t ediv, uint64_t rand_num)
-{
-    struct ble_store_value_sec value_sec;
-    struct ble_hs_conn *conn;
-    int rc;
-
-    ble_sm_test_util_init();
-
-    ble_hs_test_util_create_conn(2, ((uint8_t[6]){1,2,3,4,5,6}),
-                                 ble_sm_test_util_conn_cb,
-                                 NULL);
+    ble_hs_test_util_create_conn(2, ((uint8_t[6]){1,2,3,4,5,6}),
+                                 ble_sm_test_util_conn_cb,
+                                 NULL);
 
     /* This test inspects and modifies the connection object after unlocking
      * the host mutex.  It is not OK for real code to do this, but this test
@@ -1560,46 +1299,32 @@ ble_sm_test_util_peer_bonding_bad(uint16_t ediv, uint64_t rand_num)
     TEST_ASSERT(ble_sm_dbg_num_procs() == 0);
 }
 
-TEST_CASE(ble_sm_test_case_peer_bonding_good)
-{
-    /* Unauthenticated. */
-    ble_sm_test_util_peer_bonding_good(
-        0,
-        ((uint8_t[16]){ 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 }),
-        0,
-        0x1234,
-        0x5678);
-
-    /* Authenticated. */
-    ble_sm_test_util_peer_bonding_good(
-        0,
-        ((uint8_t[16]){ 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17 }),
-        1,
-        0x4325,
-        0x543892375);
-}
-
-TEST_CASE(ble_sm_test_case_peer_bonding_bad)
-{
-    ble_sm_test_util_peer_bonding_bad(0x5684, 32);
-    ble_sm_test_util_peer_bonding_bad(54325, 65437);
-}
-
-/*****************************************************************************
- * $us                                                                       *
- *****************************************************************************/
-
 static void
-ble_sm_test_util_us_fail_inval(
-    struct ble_sm_test_lgcy_params *params)
+ble_sm_test_util_peer_sc_good_once(struct ble_sm_test_sc_params *params)
 {
     struct ble_hs_conn *conn;
+    int num_iters;
     int rc;
+    int i;
 
     ble_sm_test_util_init();
+
+    ble_hs_cfg.sm_io_cap = params->pair_rsp.io_cap;
+    ble_hs_cfg.sm_oob_data_flag = params->pair_rsp.oob_data_flag;
+    ble_hs_cfg.sm_bonding = !!(params->pair_rsp.authreq &
+                               BLE_SM_PAIR_AUTHREQ_BOND);
+    ble_hs_cfg.sm_mitm = !!(params->pair_rsp.authreq &
+                            BLE_SM_PAIR_AUTHREQ_MITM);
+    ble_hs_cfg.sm_sc = 1;
+    ble_hs_cfg.sm_keypress = !!(params->pair_rsp.authreq &
+                                BLE_SM_PAIR_AUTHREQ_KEYPRESS);
+    ble_hs_cfg.sm_our_key_dist = params->pair_rsp.resp_key_dist;
+    ble_hs_cfg.sm_their_key_dist = params->pair_rsp.init_key_dist;
+
     ble_hs_test_util_set_public_addr(params->rsp_addr);
+    ble_sm_dbg_set_next_pair_rand(params->random_rsp[0].value);
 
-    ble_sm_dbg_set_next_pair_rand(((uint8_t[16]){0}));
+    ble_sm_dbg_set_sc_keys(params->public_key_rsp.x, params->our_priv_key);
 
     ble_hs_test_util_create_conn(2, params->init_addr,
                                  ble_sm_test_util_conn_cb,
@@ -1614,338 +1339,118 @@ ble_sm_test_util_us_fail_inval(
     TEST_ASSERT_FATAL(conn != NULL);
     ble_hs_unlock();
 
+    /* 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_sm_dbg_num_procs() == 0);
 
-    /* Initiate the pairing procedure. */
-    rc = ble_hs_test_util_security_initiate(2, 0);
-    TEST_ASSERT_FATAL(rc == 0);
+    if (params->has_sec_req) {
+        rc = ble_sm_slave_initiate(2);
+        TEST_ASSERT(rc == 0);
 
-    /* Ensure we sent the expected pair request. */
+        /* Ensure we sent the expected security request. */
+        ble_sm_test_util_verify_tx_sec_req(&params->sec_req);
+    }
+
+    /* Receive a pair request from the peer. */
+    ble_sm_test_util_rx_pair_req(2, &params->pair_req, 0);
+    TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
+    TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
+
+    /* Ensure we sent the expected pair response. */
     ble_hs_test_util_tx_all();
-    ble_sm_test_util_verify_tx_pair_req(&params->pair_req);
+    ble_sm_test_util_verify_tx_pair_rsp(&params->pair_rsp);
     TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
     TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
 
-    /* Receive a pair response from the peer. */
-    ble_sm_test_util_rx_pair_rsp(
-        2, &params->pair_rsp, BLE_HS_SM_US_ERR(BLE_SM_ERR_INVAL));
+    /* Receive a public key from the peer. */
+    ble_sm_test_util_rx_public_key(2, &params->public_key_req);
     TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
-    TEST_ASSERT(ble_sm_dbg_num_procs() == 0);
+    TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
 
-    /* Ensure we sent the expected pair fail. */
+    /* Ensure we sent the expected public key. */
     ble_hs_test_util_tx_all();
-    ble_sm_test_util_verify_tx_pair_fail(&params->pair_fail);
+    ble_sm_test_util_verify_tx_public_key(&params->public_key_rsp);
     TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
-    TEST_ASSERT(ble_sm_dbg_num_procs() == 0);
+    TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
 
-    /* Verify that security callback was not executed. */
-    TEST_ASSERT(ble_sm_test_gap_event == -1);
-    TEST_ASSERT(ble_sm_test_gap_status == -1);
+    switch (params->pair_alg) {
+    case BLE_SM_PAIR_ALG_PASSKEY:
+        num_iters = 20;
+        break;
 
-    /* Verify that connection has correct security state. */
-    TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
-    TEST_ASSERT(!conn->bhc_sec_state.authenticated);
-}
+    default:
+        num_iters = 1;
+        break;
+    }
 
-TEST_CASE(ble_sm_test_case_us_fail_inval)
-{
-    struct ble_sm_test_lgcy_params params;
+    ble_sm_test_util_io_check_pre(&params->passkey_info,
+                                  BLE_SM_PROC_STATE_CONFIRM);
 
-    /* Invalid IO capabiltiies. */
-    params = (struct ble_sm_test_lgcy_params) {
-        .init_addr = {0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c},
-        .rsp_addr = {0x03, 0x02, 0x01, 0x50, 0x13, 0x00},
-        .pair_req = (struct ble_sm_pair_cmd) {
-            .io_cap = 3,
-            .oob_data_flag = 0,
-            .authreq = 0,
-            .max_enc_key_size = 16,
-            .init_key_dist = 0,
-            .resp_key_dist = 0,
-        },
-        .pair_rsp = (struct ble_sm_pair_cmd) {
-            .io_cap = 0x14,
-            .oob_data_flag = 0,
-            .authreq = 0x05,
-            .max_enc_key_size = 16,
-            .init_key_dist = 0x07,
-            .resp_key_dist = 0x07,
-        },
-        .pair_fail = (struct ble_sm_pair_fail) {
-            .reason = BLE_SM_ERR_INVAL,
-        },
-    };
-    ble_sm_test_util_us_fail_inval(&params);
+    for (i = 0; i < num_iters; i++) {
+        if (i != 0) {
+            ble_sm_dbg_set_next_pair_rand(params->random_rsp[i].value);
+        }
 
-    /* Invalid OOB flag. */
-    params = (struct ble_sm_test_lgcy_params) {
-        .init_addr = {0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c},
-        .rsp_addr = {0x03, 0x02, 0x01, 0x50, 0x13, 0x00},
-        .pair_req = (struct ble_sm_pair_cmd) {
-            .io_cap = 3,
-            .oob_data_flag = 0,
-            .authreq = 0,
-            .max_enc_key_size = 16,
-            .init_key_dist = 0,
-            .resp_key_dist = 0,
-        },
-        .pair_rsp = (struct ble_sm_pair_cmd) {
-            .io_cap = 0x14,
-            .oob_data_flag = 2,
-            .authreq = 0x05,
-            .max_enc_key_size = 16,
-            .init_key_dist = 0x07,
-            .resp_key_dist = 0x07,
-        },
-        .pair_fail = (struct ble_sm_pair_fail) {
-            .reason = BLE_SM_ERR_INVAL,
-        },
-    };
-    ble_sm_test_util_us_fail_inval(&params);
+        if (params->pair_alg != BLE_SM_PAIR_ALG_JW      &&
+            params->pair_alg != BLE_SM_PAIR_ALG_NUMCMP) {
 
-    /* Invalid authreq - reserved bonding flag. */
-    params = (struct ble_sm_test_lgcy_params) {
-        .init_addr = {0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c},
-        .rsp_addr = {0x03, 0x02, 0x01, 0x50, 0x13, 0x00},
-        .pair_req = (struct ble_sm_pair_cmd) {
-            .io_cap = 3,
-            .oob_data_flag = 0,
-            .authreq = 0,
-            .max_enc_key_size = 16,
-            .init_key_dist = 0,
-            .resp_key_dist = 0,
-        },
-        .pair_rsp = (struct ble_sm_pair_cmd) {
-            .io_cap = 0x04,
-            .oob_data_flag = 0,
-            .authreq = 0x02,
-            .max_enc_key_size = 16,
-            .init_key_dist = 0x07,
-            .resp_key_dist = 0x07,
-        },
-        .pair_fail = (struct ble_sm_pair_fail) {
-            .reason = BLE_SM_ERR_INVAL,
-        },
-    };
-    ble_sm_test_util_us_fail_inval(&params);
+            /* Receive a pair confirm from the peer. */
+            ble_sm_test_util_rx_confirm(2, params->confirm_req + i);
+            TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
+            TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
+        }
 
-    /* Invalid authreq - reserved other flag. */
-    params = (struct ble_sm_test_lgcy_params) {
-        .init_addr = {0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c},
-        .rsp_addr = {0x03, 0x02, 0x01, 0x50, 0x13, 0x00},
-        .pair_req = (struct ble_sm_pair_cmd) {
-            .io_cap = 3,
-            .oob_data_flag = 0,
-            .authreq = 0,
-            .max_enc_key_size = 16,
-            .init_key_dist = 0,
-            .resp_key_dist = 0,
-        },
-        .pair_rsp = (struct ble_sm_pair_cmd) {
-            .io_cap = 0x04,
-            .oob_data_flag = 0,
-            .authreq = 0x20,
-            .max_enc_key_size = 16,
-            .init_key_dist = 0x07,
-            .resp_key_dist = 0x07,
-        },
-        .pair_fail = (struct ble_sm_pair_fail) {
-            .reason = BLE_SM_ERR_INVAL,
-        },
-    };
-    ble_sm_test_util_us_fail_inval(&params);
-
-    /* Invalid key size - too small. */
-    params = (struct ble_sm_test_lgcy_params) {
-        .init_addr = {0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c},
-        .rsp_addr = {0x03, 0x02, 0x01, 0x50, 0x13, 0x00},
-        .pair_req = (struct ble_sm_pair_cmd) {
-            .io_cap = 3,
-            .oob_data_flag = 0,
-            .authreq = 0,
-            .max_enc_key_size = 16,
-            .init_key_dist = 0,
-            .resp_key_dist = 0,
-        },
-        .pair_rsp = (struct ble_sm_pair_cmd) {
-            .io_cap = 0x04,
-            .oob_data_flag = 0,
-            .authreq = 0x05,
-            .max_enc_key_size = 6,
-            .init_key_dist = 0x07,
-            .resp_key_dist = 0x07,
-        },
-        .pair_fail = (struct ble_sm_pair_fail) {
-            .reason = BLE_SM_ERR_INVAL,
-        },
-    };
-    ble_sm_test_util_us_fail_inval(&params);
-
-    /* Invalid key size - too large. */
-    params = (struct ble_sm_test_lgcy_params) {
-        .init_addr = {0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c},
-        .rsp_addr = {0x03, 0x02, 0x01, 0x50, 0x13, 0x00},
-        .pair_req = (struct ble_sm_pair_cmd) {
-            .io_cap = 3,
-            .oob_data_flag = 0,
-            .authreq = 0,
-            .max_enc_key_size = 16,
-            .init_key_dist = 0,
-            .resp_key_dist = 0,
-        },
-        .pair_rsp = (struct ble_sm_pair_cmd) {
-            .io_cap = 0x04,
-            .oob_data_flag = 0,
-            .authreq = 0x05,
-            .max_enc_key_size = 17,
-            .init_key_dist = 0x07,
-            .resp_key_dist = 0x07,
-        },
-        .pair_fail = (struct ble_sm_pair_fail) {
-            .reason = BLE_SM_ERR_INVAL,
-        },
-    };
-    ble_sm_test_util_us_fail_inval(&params);
-
-    /* Invalid init key dist. */
-    params = (struct ble_sm_test_lgcy_params) {
-        .init_addr = {0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c},
-        .rsp_addr = {0x03, 0x02, 0x01, 0x50, 0x13, 0x00},
-        .pair_req = (struct ble_sm_pair_cmd) {
-            .io_cap = 3,
-            .oob_data_flag = 0,
-            .authreq = 0,
-            .max_enc_key_size = 16,
-            .init_key_dist = 0,
-            .resp_key_dist = 0,
-        },
-        .pair_rsp = (struct ble_sm_pair_cmd) {
-            .io_cap = 0x04,
-            .oob_data_flag = 0,
-            .authreq = 0x05,
-            .max_enc_key_size = 17,
-            .init_key_dist = 0x10,
-            .resp_key_dist = 0x07,
-        },
-        .pair_fail = (struct ble_sm_pair_fail) {
-            .reason = BLE_SM_ERR_INVAL,
-        },
-    };
-    ble_sm_test_util_us_fail_inval(&params);
-
-    /* Invalid resp key dist. */
-    params = (struct ble_sm_test_lgcy_params) {
-        .init_addr = {0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c},
-        .rsp_addr = {0x03, 0x02, 0x01, 0x50, 0x13, 0x00},
-        .pair_req = (struct ble_sm_pair_cmd) {
-            .io_cap = 3,
-            .oob_data_flag = 0,
-            .authreq = 0,
-            .max_enc_key_size = 16,
-            .init_key_dist = 0,
-            .resp_key_dist = 0,
-        },
-        .pair_rsp = (struct ble_sm_pair_cmd) {
-            .io_cap = 0x04,
-            .oob_data_flag = 0,
-            .authreq = 0x05,
-            .max_enc_key_size = 17,
-            .init_key_dist = 0x07,
-            .resp_key_dist = 0x10,
-        },
-        .pair_fail = (struct ble_sm_pair_fail) {
-            .reason = BLE_SM_ERR_INVAL,
-        },
-    };
-    ble_sm_test_util_us_fail_inval(&params);
-}
-
-static void
-ble_sm_test_util_us_lgcy_good(
-    struct ble_sm_test_lgcy_params *params)
-{
-    struct ble_hs_conn *conn;
-    int rc;
-
-    ble_sm_test_util_init();
-    ble_hs_test_util_set_public_addr(params->init_addr);
-    ble_sm_dbg_set_next_pair_rand(params->random_req.value);
-    ble_sm_dbg_set_next_ediv(params->ediv);
-    ble_sm_dbg_set_next_start_rand(params->r);
-
-    if (params->has_enc_info_req) {
-        ble_sm_dbg_set_next_ltk(params->enc_info_req.ltk);
-    }
+        if (i == 0) {
+            ble_sm_test_util_io_check_post(&params->passkey_info,
+                                           BLE_SM_PROC_STATE_CONFIRM);
+        }
 
-    ble_hs_test_util_create_conn(2, params->rsp_addr,
-                                 ble_sm_test_util_conn_cb,
-                                 NULL);
+        /* Ensure we sent the expected pair confirm. */
+        ble_hs_test_util_tx_all();
+        ble_sm_test_util_verify_tx_pair_confirm(params->confirm_rsp + i);
+        TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
+        TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
 
-    /* This test inspects and modifies the connection object after unlocking
-     * the host mutex.  It is not OK for real code to do this, but this test
-     * can assume the connection list is unchanging.
-     */
-    ble_hs_lock();
-    conn = ble_hs_conn_find(2);
-    TEST_ASSERT_FATAL(conn != NULL);
-    ble_hs_unlock();
+        /* Receive a pair random from the peer. */
+        ble_sm_test_util_rx_random(2, params->random_req + i, 0);
+        TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
+        TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
 
-    TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
-    TEST_ASSERT(ble_sm_dbg_num_procs() == 0);
+        /* Ensure we sent the expected pair random. */
+        ble_hs_test_util_tx_all();
+        ble_sm_test_util_verify_tx_pair_random(params->random_rsp + i);
+        TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
+        TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
 
-    ble_hs_test_util_set_ack(
-        host_hci_opcode_join(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_START_ENCRYPT), 0);
-    if (params->has_sec_req) {
-        ble_sm_test_util_rx_sec_req(2, &params->sec_req, 0);
-    } else {
-        /* Initiate the pairing procedure. */
-        rc = ble_gap_security_initiate(2);
-        TEST_ASSERT_FATAL(rc == 0);
     }
 
-    /* Ensure we sent the expected pair request. */
-    ble_hs_test_util_tx_all();
-    ble_sm_test_util_verify_tx_pair_req(&params->pair_req);
-    TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
-    TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
-
-    /* Receive a pair response from the peer. */
-    ble_sm_test_util_rx_pair_rsp(2, &params->pair_rsp, 0);
-    TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
-    TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
+    ble_sm_test_util_io_check_pre(&params->passkey_info,
+                                  BLE_SM_PROC_STATE_DHKEY_CHECK);
 
-    /* Ensure we sent the expected pair confirm. */
-    ble_hs_test_util_tx_all();
-    ble_sm_test_util_verify_tx_pair_confirm(&params->confirm_req);
+    /* Receive a dhkey check from the peer. */
+    ble_sm_test_util_rx_dhkey_check(2, &params->dhkey_check_req, 0);
     TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
     TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
 
-    /* Receive a pair confirm from the peer. */
-    ble_sm_test_util_rx_confirm(2, &params->confirm_rsp);
-    TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
-    TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
+    ble_sm_test_util_io_check_post(&params->passkey_info,
+                                   BLE_SM_PROC_STATE_DHKEY_CHECK);
 
-    /* Ensure we sent the expected pair random. */
+    /* Ensure we sent the expected dhkey check. */
     ble_hs_test_util_tx_all();
-    ble_sm_test_util_verify_tx_pair_random(&params->random_req);
+    ble_sm_test_util_verify_tx_dhkey_check(&params->dhkey_check_rsp);
     TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
     TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
 
-    /* Receive a pair random from the peer. */
-    ble_sm_test_util_rx_random(2, &params->random_rsp, 0);
+    /* Receive a long term key request from the controller. */
+    ble_sm_test_util_set_lt_key_req_reply_ack(0, 2);
+    ble_sm_test_util_rx_lt_key_req(2, 0, 0);
     TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
     TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
 
-    /* Ensure keys are distributed, if necessary. */
-    if (params->has_enc_info_req) {
-        ble_sm_test_util_verify_tx_enc_info(&params->enc_info_req);
-    }
-
-    /* Ensure we sent the expected start encryption command. */
-    ble_hs_test_util_tx_all();
-    ble_sm_test_util_verify_tx_start_enc(2, params->r, params->ediv,
-                                               params->stk);
+    /* Ensure we sent the expected long term key request reply command. */
+    ble_sm_test_util_verify_tx_lt_key_req_reply(2, params->ltk);
     TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
     TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
 
@@ -1960,7 +1465,8 @@ ble_sm_test_util_us_lgcy_good(
     TEST_ASSERT(ble_sm_test_gap_status == 0);
     TEST_ASSERT(ble_sm_test_sec_state.pair_alg == params->pair_alg);
     TEST_ASSERT(ble_sm_test_sec_state.enc_enabled);
-    TEST_ASSERT(!ble_sm_test_sec_state.authenticated);
+    TEST_ASSERT(ble_sm_test_sec_state.authenticated ==
+                params->authenticated);
 
     /* Verify that connection has correct security state. */
     TEST_ASSERT(ble_sm_test_sec_state.pair_alg ==
@@ -1971,203 +1477,77 @@ ble_sm_test_util_us_lgcy_good(
                 conn->bhc_sec_state.authenticated);
 
     /* Verify the appropriate security material was persisted. */
-    ble_sm_test_util_verify_lgcy_persist(params);
+    ble_sm_test_util_verify_sc_persist(params);
 }
 
-TEST_CASE(ble_sm_test_case_us_lgcy_jw_good)
+static void
+ble_sm_test_util_peer_sc_good(struct ble_sm_test_sc_params *params)
 {
-    struct ble_sm_test_lgcy_params params;
+    params->passkey_info.io_before_rx = 0;
+    ble_sm_test_util_peer_sc_good_once(params);
 
-    params = (struct ble_sm_test_lgcy_params) {
-        .init_addr = {0x06, 0x05, 0x04, 0x03, 0x02, 0x01},
-        .rsp_addr = {0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a},
-        .pair_req = (struct ble_sm_pair_cmd) {
-            .io_cap = 3,
-            .oob_data_flag = 0,
-            .authreq = 0,
-            .max_enc_key_size = 16,
-            .init_key_dist = 0,
-            .resp_key_dist = 0,
-        },
-        .pair_rsp = (struct ble_sm_pair_cmd) {
-            .io_cap = 3,
-            .oob_data_flag = 0,
-            .authreq = 0,
-            .max_enc_key_size = 16,
-            .init_key_dist = 0,
-            .resp_key_dist = 0,
-        },
-        .confirm_req = (struct ble_sm_pair_confirm) {
-            .value = {
-                0x04, 0x4e, 0xaf, 0xce, 0x30, 0x79, 0x2c, 0x9e,
-                0xa2, 0xeb, 0x53, 0x6a, 0xdf, 0xf7, 0x99, 0xb2,
-            },
-        },
-        .confirm_rsp = (struct ble_sm_pair_confirm) {
-            .value = {
-                0x04, 0x4e, 0xaf, 0xce, 0x30, 0x79, 0x2c, 0x9e,
-                0xa2, 0xeb, 0x53, 0x6a, 0xdf, 0xf7, 0x99, 0xb2,
-            },
-        },
-        .random_req = (struct ble_sm_pair_random) {
-            .value = {
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-            },
-        },
-        .random_rsp = (struct ble_sm_pair_random) {
-            .value = {
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-            },
-        },
-        .pair_alg = BLE_SM_PAIR_ALG_JW,
-        .tk = { 0 },
-        .stk = {
-            0x2e, 0x2b, 0x34, 0xca, 0x59, 0xfa, 0x4c, 0x88,
-            0x3b, 0x2c, 0x8a, 0xef, 0xd4, 0x4b, 0xe9, 0x66,
-        },
-        .r = 0,
-        .ediv = 0,
-    };
-
-    ble_sm_test_util_us_lgcy_good(&params);
-}
-
-TEST_CASE(ble_sm_test_case_conn_broken)
-{
-    struct hci_disconn_complete disconn_evt;
-    int rc;
-
-    ble_sm_test_util_init();
-
-    ble_sm_dbg_set_next_pair_rand(((uint8_t[16]){0}));
-
-    ble_hs_test_util_create_conn(2, ((uint8_t[6]){1,2,3,5,6,7}),
-                                 ble_sm_test_util_conn_cb, NULL);
-
-    /* Initiate the pairing procedure. */
-    rc = ble_hs_test_util_security_initiate(2, 0);
-    TEST_ASSERT_FATAL(rc == 0);
-    TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
-
-    /* Terminate the connection. */
-    disconn_evt.connection_handle = 2;
-    disconn_evt.status = 0;
-    disconn_evt.reason = BLE_ERR_REM_USER_CONN_TERM;
-    ble_gap_rx_disconn_complete(&disconn_evt);
+    params->passkey_info.io_before_rx = 1;
+    ble_sm_test_util_peer_sc_good_once(params);
 
-    /* Verify security callback got called. */
-    TEST_ASSERT(ble_sm_test_gap_status == BLE_HS_ENOTCONN);
-    TEST_ASSERT(!ble_sm_test_sec_state.enc_enabled);
-    TEST_ASSERT(!ble_sm_test_sec_state.authenticated);
 }
 
-TEST_CASE(ble_sm_test_case_peer_sec_req_inval)
+static void
+ble_sm_test_util_us_fail_inval(
+    struct ble_sm_test_lgcy_params *params)
 {
-    struct ble_sm_pair_fail fail;
-    struct ble_sm_sec_req sec_req;
+    struct ble_hs_conn *conn;
     int rc;
 
     ble_sm_test_util_init();
+    ble_hs_test_util_set_public_addr(params->rsp_addr);
 
     ble_sm_dbg_set_next_pair_rand(((uint8_t[16]){0}));
 
-    ble_hs_test_util_create_conn(2, ((uint8_t[6]){1,2,3,5,6,7}),
+    ble_hs_test_util_create_conn(2, params->init_addr,
                                  ble_sm_test_util_conn_cb,
                                  NULL);
 
-    /*** We are the slave; reject the security request. */
-    ble_hs_atomic_conn_set_flags(2, BLE_HS_CONN_F_MASTER, 0);
-
-    sec_req.authreq = 0;
-    ble_sm_test_util_rx_sec_req(
-        2, &sec_req, BLE_HS_SM_US_ERR(BLE_SM_ERR_CMD_NOT_SUPP));
-
-    ble_hs_test_util_tx_all();
+    /* This test inspects and modifies the connection object after unlocking
+     * the host mutex.  It is not OK for real code to do this, but this test
+     * can assume the connection list is unchanging.
+     */
+    ble_hs_lock();
+    conn = ble_hs_conn_find(2);
+    TEST_ASSERT_FATAL(conn != NULL);
+    ble_hs_unlock();
 
-    fail.reason = BLE_SM_ERR_CMD_NOT_SUPP;
-    ble_sm_test_util_verify_tx_pair_fail(&fail);
+    TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
+    TEST_ASSERT(ble_sm_dbg_num_procs() == 0);
 
-    /*** Pairing already in progress; ignore security request. */
-    ble_hs_atomic_conn_set_flags(2, BLE_HS_CONN_F_MASTER, 1);
-    rc = ble_sm_pair_initiate(2);
+    /* Initiate the pairing procedure. */
+    rc = ble_hs_test_util_security_initiate(2, 0);
     TEST_ASSERT_FATAL(rc == 0);
-    ble_hs_test_util_tx_all();
-    ble_hs_test_util_prev_tx_queue_clear();
 
-    ble_sm_test_util_rx_sec_req(2, &sec_req, BLE_HS_EALREADY);
+    /* Ensure we sent the expected pair request. */
     ble_hs_test_util_tx_all();
-    TEST_ASSERT(ble_hs_test_util_prev_tx_queue_sz() == 0);
-}
+    ble_sm_test_util_verify_tx_pair_req(&params->pair_req);
+    TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
+    TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
 
-/**
- * Master: us.
- * Peer sends a security request.
- * We respond by initiating the pairing procedure.
- */
-TEST_CASE(ble_sm_test_case_peer_sec_req_pair)
-{
-    struct ble_sm_test_lgcy_params params;
+    /* Receive a pair response from the peer. */
+    ble_sm_test_util_rx_pair_rsp(
+        2, &params->pair_rsp, BLE_HS_SM_US_ERR(BLE_SM_ERR_INVAL));
+    TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
+    TEST_ASSERT(ble_sm_dbg_num_procs() == 0);
 
-    params = (struct ble_sm_test_lgcy_params) {
-        .init_addr = {0x06, 0x05, 0x04, 0x03, 0x02, 0x01},
-        .rsp_addr = {0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a},
-        .sec_req = (struct ble_sm_sec_req) {
-            .authreq = 0,
-        },
-        .has_sec_req = 1,
-        .pair_req = (struct ble_sm_pair_cmd) {
-            .io_cap = 3,
-            .oob_data_flag = 0,
-            .authreq = 0,
-            .max_enc_key_size = 16,
-            .init_key_dist = 0,
-            .resp_key_dist = 0,
-        },
-        .pair_rsp = (struct ble_sm_pair_cmd) {
-            .io_cap = 3,
-            .oob_data_flag = 0,
-            .authreq = 0,
-            .max_enc_key_size = 16,
-            .init_key_dist = 0,
-            .resp_key_dist = 0,
-        },
-        .confirm_req = (struct ble_sm_pair_confirm) {
-            .value = {
-                0x04, 0x4e, 0xaf, 0xce, 0x30, 0x79, 0x2c, 0x9e,
-                0xa2, 0xeb, 0x53, 0x6a, 0xdf, 0xf7, 0x99, 0xb2,
-            },
-        },
-        .confirm_rsp = (struct ble_sm_pair_confirm) {
-            .value = {
-                0x04, 0x4e, 0xaf, 0xce, 0x30, 0x79, 0x2c, 0x9e,
-                0xa2, 0xeb, 0x53, 0x6a, 0xdf, 0xf7, 0x99, 0xb2,
-            },
-        },
-        .random_req = (struct ble_sm_pair_random) {
-            .value = {
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-            },
-        },
-        .random_rsp = (struct ble_sm_pair_random) {
-            .value = {
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-            },
-        },
-        .pair_alg = BLE_SM_PAIR_ALG_JW,
-        .tk = { 0 },
-        .stk = {
-            0x2e, 0x2b, 0x34, 0xca, 0x59, 0xfa, 0x4c, 0x88,
-            0x3b, 0x2c, 0x8a, 0xef, 0xd4, 0x4b, 0xe9, 0x66,
-        },
-        .r = 0,
-        .ediv = 0,
-    };
+    /* Ensure we sent the expected pair fail. */
+    ble_hs_test_util_tx_all();
+    ble_sm_test_util_verify_tx_pair_fail(&params->pair_fail);
+    TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
+    TEST_ASSERT(ble_sm_dbg_num_procs() == 0);
 
-    ble_sm_test_util_us_lgcy_good(&params);
+    /* Verify that security callback was not executed. */
+    TEST_ASSERT(ble_sm_test_gap_event == -1);
+    TEST_ASSERT(ble_sm_test_gap_status == -1);
+
+    /* Verify that connection has correct security state. */
+    TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
+    TEST_ASSERT(!conn->bhc_sec_state.authenticated);
 }
 
 /**
@@ -2254,38 +1634,366 @@ ble_sm_test_util_us_bonding_good(int send_enc_req, uint8_t *ltk,
                 authenticated);
 }
 
-/**
- * Master: us.
- * Peer sends a security request.
- * We respond by initiating the encryption procedure.
- */
-TEST_CASE(ble_sm_test_case_peer_sec_req_enc)
+/*****************************************************************************
+ * $misc                                                                     *
+ *****************************************************************************/
+
+TEST_CASE(ble_sm_test_case_f4)
 {
-    /* Unauthenticated. */
-    ble_sm_test_util_us_bonding_good(
-        1,
-        ((uint8_t[16]){ 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 }),
-        0,
-        0x1234,
-        0x5678);
+	uint8_t u[32] = { 0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc,
+			  0xdb, 0xfd, 0xf4, 0xac, 0x11, 0x91, 0xf4, 0xef,
+			  0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e,
+			  0x2c, 0xbe, 0x97, 0xf2, 0xd2, 0x03, 0xb0, 0x20 };
+	uint8_t v[32] = { 0xfd, 0xc5, 0x7f, 0xf4, 0x49, 0xdd, 0x4f, 0x6b,
+			  0xfb, 0x7c, 0x9d, 0xf1, 0xc2, 0x9a, 0xcb, 0x59,
+			  0x2a, 0xe7, 0xd4, 0xee, 0xfb, 0xfc, 0x0a, 0x90,
+			  0x9a, 0xbb, 0xf6, 0x32, 0x3d, 0x8b, 0x18, 0x55 };
+	uint8_t x[16] = { 0xab, 0xae, 0x2b, 0x71, 0xec, 0xb2, 0xff, 0xff,
+			  0x3e, 0x73, 0x77, 0xd1, 0x54, 0x84, 0xcb, 0xd5 };
+	uint8_t z = 0x00;
+	uint8_t exp[16] = { 0x2d, 0x87, 0x74, 0xa9, 0xbe, 0xa1, 0xed, 0xf1,
+			    0x1c, 0xbd, 0xa9, 0x07, 0xf1, 0x16, 0xc9, 0xf2 };
+	uint8_t res[16];
+	int err;
+
+	err = ble_sm_alg_f4(u, v, x, z, res);
+	TEST_ASSERT_FATAL(err == 0);
+    TEST_ASSERT(memcmp(res, exp, 16) == 0);
 }
 
-/**
- * Master: peer.
- * We send a security request.
- * We accept pairing request sent in response.
- */
-TEST_CASE(ble_sm_test_case_us_sec_req_pair)
+TEST_CASE(ble_sm_test_case_f5)
 {
-    struct ble_sm_test_lgcy_params params;
+	uint8_t w[32] = { 0x98, 0xa6, 0xbf, 0x73, 0xf3, 0x34, 0x8d, 0x86,
+			  0xf1, 0x66, 0xf8, 0xb4, 0x13, 0x6b, 0x79, 0x99,
+			  0x9b, 0x7d, 0x39, 0x0a, 0xa6, 0x10, 0x10, 0x34,
+			  0x05, 0xad, 0xc8, 0x57, 0xa3, 0x34, 0x02, 0xec };
+	uint8_t n1[16] = { 0xab, 0xae, 0x2b, 0x71, 0xec, 0xb2, 0xff, 0xff,
+			   0x3e, 0x73, 0x77, 0xd1, 0x54, 0x84, 0xcb, 0xd5 };
+	uint8_t n2[16] = { 0xcf, 0xc4, 0x3d, 0xff, 0xf7, 0x83, 0x65, 0x21,
+			   0x6e, 0x5f, 0xa7, 0x25, 0xcc, 0xe7, 0xe8, 0xa6 };
+    uint8_t a1t = 0x00;
+	uint8_t a1[6] = { 0xce, 0xbf, 0x37, 0x37, 0x12, 0x56 };
+    uint8_t a2t = 0x00;
+    uint8_t a2[6] = { 0xc1, 0xcf, 0x2d, 0x70, 0x13, 0xa7 };
+	uint8_t exp_ltk[16] = { 0x38, 0x0a, 0x75, 0x94, 0xb5, 0x22, 0x05,
+				0x98, 0x23, 0xcd, 0xd7, 0x69, 0x11, 0x79,
+				0x86, 0x69 };
+	uint8_t exp_mackey[16] = { 0x20, 0x6e, 0x63, 0xce, 0x20, 0x6a, 0x3f,
+				   0xfd, 0x02, 0x4a, 0x08, 0xa1, 0x76, 0xf1,
+				   0x65, 0x29 };
+	uint8_t mackey[16], ltk[16];
+	int err;
+
+	err = ble_sm_alg_f5(w, n1, n2, a1t, a1, a2t, a2, mackey, ltk);
+	TEST_ASSERT_FATAL(err == 0);
+    TEST_ASSERT(memcmp(mackey, exp_mackey, 16) == 0);
+    TEST_ASSERT(memcmp(ltk, exp_ltk, 16) == 0);
+}
+
+TEST_CASE(ble_sm_test_case_f6)
+{
+	uint8_t w[16] = { 0x20, 0x6e, 0x63, 0xce, 0x20, 0x6a, 0x3f, 0xfd,
+			  0x02, 0x4a, 0x08, 0xa1, 0x76, 0xf1, 0x65, 0x29 };
+	uint8_t n1[16] = { 0xab, 0xae, 0x2b, 0x71, 0xec, 0xb2, 0xff, 0xff,
+			   0x3e, 0x73, 0x77, 0xd1, 0x54, 0x84, 0xcb, 0xd5 };
+	uint8_t n2[16] = { 0xcf, 0xc4, 0x3d, 0xff, 0xf7, 0x83, 0x65, 0x21,
+			   0x6e, 0x5f, 0xa7, 0x25, 0xcc, 0xe7, 0xe8, 0xa6 };
+	uint8_t r[16] = { 0xc8, 0x0f, 0x2d, 0x0c, 0xd2, 0x42, 0xda, 0x08,
+			  0x54, 0xbb, 0x53, 0xb4, 0x3b, 0x34, 0xa3, 0x12 };
+	uint8_t io_cap[3] = { 0x02, 0x01, 0x01 };
+    uint8_t a1t = 0x00;
+	uint8_t a1[6] = { 0xce, 0xbf, 0x37, 0x37, 0x12, 0x56 };
+    uint8_t a2t = 0x00;
+    uint8_t a2[6] = { 0xc1, 0xcf, 0x2d, 0x70, 0x13, 0xa7 };
+	uint8_t exp[16] = { 0x61, 0x8f, 0x95, 0xda, 0x09, 0x0b, 0x6c, 0xd2,
+			    0xc5, 0xe8, 0xd0, 0x9c, 0x98, 0x73, 0xc4, 0xe3 };
+	uint8_t res[16];
+	int err;
+
+	err = ble_sm_alg_f6(w, n1, n2, r, io_cap, a1t, a1, a2t, a2, res);
+	TEST_ASSERT_FATAL(err == 0);
+    TEST_ASSERT(memcmp(res, exp, 16) == 0);
+}
+
+TEST_CASE(ble_sm_test_case_g2)
+{
+	uint8_t u[32] = { 0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc,
+			  0xdb, 0xfd, 0xf4, 0xac, 0x11, 0x91, 0xf4, 0xef,
+			  0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e,
+			  0x2c, 0xbe, 0x97, 0xf2, 0xd2, 0x03, 0xb0, 0x20 };
+	uint8_t v[32] = { 0xfd, 0xc5, 0x7f, 0xf4, 0x49, 0xdd, 0x4f, 0x6b,
+			  0xfb, 0x7c, 0x9d, 0xf1, 0xc2, 0x9a, 0xcb, 0x59,
+			  0x2a, 0xe7, 0xd4, 0xee, 0xfb, 0xfc, 0x0a, 0x90,
+			  0x9a, 0xbb, 0xf6, 0x32, 0x3d, 0x8b, 0x18, 0x55 };
+	uint8_t x[16] = { 0xab, 0xae, 0x2b, 0x71, 0xec, 0xb2, 0xff, 0xff,
+			  0x3e, 0x73, 0x77, 0xd1, 0x54, 0x84, 0xcb, 0xd5 };
+	uint8_t y[16] = { 0xcf, 0xc4, 0x3d, 0xff, 0xf7, 0x83, 0x65, 0x21,
+			  0x6e, 0x5f, 0xa7, 0x25, 0xcc, 0xe7, 0xe8, 0xa6 };
+	uint32_t exp_val = 0x2f9ed5ba % 1000000;
+	uint32_t val;
+	int err;
+
+	err = ble_sm_alg_g2(u, v, x, y, &val);
+	TEST_ASSERT_FATAL(err == 0);
+	TEST_ASSERT(val == exp_val);
+}
+
+TEST_CASE(ble_sm_test_case_conn_broken)
+{
+    struct hci_disconn_complete disconn_evt;
+    int rc;
+
+    ble_sm_test_util_init();
+
+    ble_sm_dbg_set_next_pair_rand(((uint8_t[16]){0}));
+
+    ble_hs_test_util_create_conn(2, ((uint8_t[6]){1,2,3,5,6,7}),
+                                 ble_sm_test_util_conn_cb, NULL);
+
+    /* Initiate the pairing procedure. */
+    rc = ble_hs_test_util_security_initiate(2, 0);
+    TEST_ASSERT_FATAL(rc == 0);
+    TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
+
+    /* Terminate the connection. */
+    disconn_evt.connection_handle = 2;
+    disconn_evt.status = 0;
+    disconn_evt.reason = BLE_ERR_REM_USER_CONN_TERM;
+    ble_gap_rx_disconn_complete(&disconn_evt);
+
+    /* Verify security callback got called. */
+    TEST_ASSERT(ble_sm_test_gap_status == BLE_HS_ENOTCONN);
+    TEST_ASSERT(!ble_sm_test_sec_state.enc_enabled);
+    TEST_ASSERT(!ble_sm_test_sec_state.authenticated);
+}
+
+/*****************************************************************************
+ * $peer                                                                     *
+ *****************************************************************************/
+
+TEST_CASE(ble_sm_test_case_peer_fail_inval)
+{
+    /* Invalid role detected before other arguments. */
+    ble_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_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_sm_pair_fail[1]) { {
+            .reason = BLE_SM_ERR_CMD_NOT_SUPP,
+        } })
+    );
+
+    /* Invalid IO capabiltiies. */
+    ble_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_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_sm_pair_fail[1]) { {
+            .reason = BLE_SM_ERR_INVAL,
+        } })
+    );
+
+    /* Invalid OOB flag. */
+    ble_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_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_sm_pair_fail[1]) { {
+            .reason = BLE_SM_ERR_INVAL,
+        } })
+    );
+
+    /* Invalid authreq - reserved bonding flag. */
+    ble_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_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_sm_pair_fail[1]) { {
+            .reason = BLE_SM_ERR_INVAL,
+        } })
+    );
+
+    /* Invalid authreq - reserved other flag. */
+    ble_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_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_sm_pair_fail[1]) { {
+            .reason = BLE_SM_ERR_INVAL,
+        } })
+    );
+
+    /* Invalid key size - too small. */
+    ble_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_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_sm_pair_fail[1]) { {
+            .reason = BLE_SM_ERR_INVAL,
+        } })
+    );
+
+    /* Invalid key size - too large. */
+    ble_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_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_sm_pair_fail[1]) { {
+            .reason = BLE_SM_ERR_INVAL,
+        } })
+    );
+
+    /* Invalid init key dist. */
+    ble_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_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_sm_pair_fail[1]) { {
+            .reason = BLE_SM_ERR_INVAL,
+        } })
+    );
+
+    /* Invalid resp key dist. */
+    ble_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_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_sm_pair_fail[1]) { {
+            .reason = BLE_SM_ERR_INVAL,
+        } })
+    );
+}
+
+TEST_CASE(ble_sm_test_case_peer_lgcy_fail_confirm)
+{
+    ble_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_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_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_sm_pair_confirm[1]) { {
+            .value = {
+                0x0a, 0xac, 0xa2, 0xae, 0xa6, 0x98, 0xdc, 0x6d,
+                0x65, 0x84, 0x11, 0x69, 0x47, 0x36, 0x8d, 0xa0,
+            },
+        } }),
+        ((struct ble_sm_pair_confirm[1]) { {
+            .value = {
+                0x45, 0xd2, 0x2c, 0x38, 0xd8, 0x91, 0x4f, 0x19,
+                0xa2, 0xd4, 0xfc, 0x7d, 0xad, 0x37, 0x79, 0xe0
+            },
+        } }),
+        ((struct ble_sm_pair_random[1]) { {
+            .value = {
+                0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+                0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+            },
+        } }),
+        ((struct ble_sm_pair_random[1]) { {
+            .value = {
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            },
+        } }),
+        ((struct ble_sm_pair_fail[1]) { {
+            .reason = BLE_SM_ERR_CONFIRM_MISMATCH,
+        } })
+    );
+}
+
+TEST_CASE(ble_sm_test_case_peer_lgcy_jw_good)
+{
+    struct ble_sm_test_lgcy_params params;
 
     params = (struct ble_sm_test_lgcy_params) {
         .init_addr = {0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c},
-        .rsp_addr = {0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07},
-        .sec_req = (struct ble_sm_sec_req) {
-            .authreq = 0x05,
-        },
-        .has_sec_req = 1,
+        .rsp_addr = {0x03, 0x02, 0x01, 0x50, 0x13, 0x00},
         .pair_req = (struct ble_sm_pair_cmd) {
             .io_cap = 0x04,
             .oob_data_flag = 0,
@@ -2295,6 +2003,65 @@ TEST_CASE(ble_sm_test_case_us_sec_req_pair)
             .resp_key_dist = 0x07,
         },
         .pair_rsp = (struct ble_sm_pair_cmd) {
+            .io_cap = 3,
+            .oob_data_flag = 0,
+            .authreq = 0,
+            .max_enc_key_size = 16,
+            .init_key_dist = 0,
+            .resp_key_dist = 0,
+        },
+        .confirm_req = (struct ble_sm_pair_confirm) {
+            .value = {
+                0x0a, 0xac, 0xa2, 0xae, 0xa6, 0x98, 0xdc, 0x6d,
+                0x65, 0x84, 0x11, 0x69, 0x47, 0x36, 0x8d, 0xa0,
+            },
+        },
+        .confirm_rsp = (struct ble_sm_pair_confirm) {
+            .value = {
+                0x45, 0xd2, 0x2c, 0x38, 0xd8, 0x91, 0x4f, 0x19,
+                0xa2, 0xd4, 0xfc, 0x7d, 0xad, 0x37, 0x79, 0xe0
+            },
+        },
+        .random_req = (struct ble_sm_pair_random) {
+            .value = {
+                0x2b, 0x3b, 0x69, 0xe4, 0xef, 0xab, 0xcc, 0x48,
+                0x78, 0x20, 0x1a, 0x54, 0x7a, 0x91, 0x5d, 0xfb,
+            },
+        },
+        .random_rsp = (struct ble_sm_pair_random) {
+            .value = {
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            },
+        },
+        .pair_alg = BLE_SM_PAIR_ALG_JW,
+        .authenticated = 0,
+        .tk = { 0 },
+        .stk = {
+            0xa4, 0x8e, 0x51, 0x0d, 0x33, 0xe7, 0x8f, 0x38,
+            0x45, 0xf0, 0x67, 0xc3, 0xd4, 0x05, 0xb3, 0xe6,
+        },
+        .r = 0,
+        .ediv = 0,
+    };
+    ble_sm_test_util_peer_lgcy_good(&params);
+}
+
+TEST_CASE(ble_sm_test_case_peer_lgcy_passkey_good)
+{
+    struct ble_sm_test_lgcy_params params;
+
+    params = (struct ble_sm_test_lgcy_params) {
+        .init_addr = {0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c},
+        .rsp_addr = {0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07},
+        .pair_req = (struct ble_sm_pair_cmd) {
+            .io_cap = 0x04,
+            .oob_data_flag = 0, .authreq = 0x05,
+            .max_enc_key_size = 16,
+            .init_key_dist = 0x07,
+            .resp_key_dist = 0x07,
+        },
+        .pair_rsp = (struct ble_sm_pair_cmd) {
             .io_cap = 0x02,
             .oob_data_flag = 0,
             .authreq = 0x05,
@@ -2344,7 +2111,6 @@ TEST_CASE(ble_sm_test_case_us_sec_req_pair)
                 .action = BLE_SM_PKACT_INPUT,
                 .passkey = 884570,
             },
-            .io_before_rx = 1,
         },
 
         .enc_info_req = {
@@ -2372,215 +2138,155 @@ TEST_CASE(ble_sm_test_case_us_sec_req_pair)
         },
         .has_master_id_rsp = 1,
     };
-
     ble_sm_test_util_peer_lgcy_good(&params);
 }
 
-/**
- * Master: peer.
- * We send a security request.
- * We accept an encryption-changed event in response.
- */
-TEST_CASE(ble_sm_test_case_us_sec_req_enc)
+TEST_CASE(ble_sm_test_case_peer_bonding_good)
 {
+    /* Unauthenticated. */
     ble_sm_test_util_peer_bonding_good(
-        1,
+        0,
+        ((uint8_t[16]){ 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 }),
+        0,
+        0x1234,
+        0x5678);
+
+    /* Authenticated. */
+    ble_sm_test_util_peer_bonding_good(
+        0,
         ((uint8_t[16]){ 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17 }),
         1,
         0x4325,
         0x543892375);
 }
 
-static void
-ble_sm_test_util_peer_sc_good_once(struct ble_sm_test_sc_params *params)
+TEST_CASE(ble_sm_test_case_peer_bonding_bad)
 {
-    struct ble_hs_conn *conn;
-    int num_iters;
+    ble_sm_test_util_peer_bonding_bad(0x5684, 32);
+    ble_sm_test_util_peer_bonding_bad(54325, 65437);
+}
+
+TEST_CASE(ble_sm_test_case_peer_sec_req_inval)
+{
+    struct ble_sm_pair_fail fail;
+    struct ble_sm_sec_req sec_req;
     int rc;
-    int i;
 
     ble_sm_test_util_init();
 
-    ble_hs_cfg.sm_io_cap = params->pair_rsp.io_cap;
-    ble_hs_cfg.sm_oob_data_flag = params->pair_rsp.oob_data_flag;
-    ble_hs_cfg.sm_bonding = !!(params->pair_rsp.authreq &
-                               BLE_SM_PAIR_AUTHREQ_BOND);
-    ble_hs_cfg.sm_mitm = !!(params->pair_rsp.authreq &
-                            BLE_SM_PAIR_AUTHREQ_MITM);
-    ble_hs_cfg.sm_sc = 1;
-    ble_hs_cfg.sm_keypress = !!(params->pair_rsp.authreq &
-                                BLE_SM_PAIR_AUTHREQ_KEYPRESS);
-    ble_hs_cfg.sm_our_key_dist = params->pair_rsp.resp_key_dist;
-    ble_hs_cfg.sm_their_key_dist = params->pair_rsp.init_key_dist;
-
-    ble_hs_test_util_set_public_addr(params->rsp_addr);
-    ble_sm_dbg_set_next_pair_rand(params->random_rsp[0].value);
-
-    ble_sm_dbg_set_sc_keys(params->public_key_rsp.x, params->our_priv_key);
+    ble_sm_dbg_set_next_pair_rand(((uint8_t[16]){0}));
 
-    ble_hs_test_util_create_conn(2, params->init_addr,
+    ble_hs_test_util_create_conn(2, ((uint8_t[6]){1,2,3,5,6,7}),
                                  ble_sm_test_util_conn_cb,
                                  NULL);
 
-    /* This test inspects and modifies the connection object after unlocking
-     * the host mutex.  It is not OK for real code to do this, but this test
-     * can assume the connection list is unchanging.
-     */
-    ble_hs_lock();
-    conn = ble_hs_conn_find(2);
-    TEST_ASSERT_FATAL(conn != NULL);
-    ble_hs_unlock();
-
-    /* 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_sm_dbg_num_procs() == 0);
-
-    if (params->has_sec_req) {
-        rc = ble_sm_slave_initiate(2);
-        TEST_ASSERT(rc == 0);
-
-        /* Ensure we sent the expected security request. */
-        ble_sm_test_util_verify_tx_sec_req(&params->sec_req);
-    }
+    /*** We are the slave; reject the security request. */
+    ble_hs_atomic_conn_set_flags(2, BLE_HS_CONN_F_MASTER, 0);
 
-    /* Receive a pair request from the peer. */
-    ble_sm_test_util_rx_pair_req(2, &params->pair_req, 0);
-    TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
-    TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
+    sec_req.authreq = 0;
+    ble_sm_test_util_rx_sec_req(
+        2, &sec_req, BLE_HS_SM_US_ERR(BLE_SM_ERR_CMD_NOT_SUPP));
 
-    /* Ensure we sent the expected pair response. */
     ble_hs_test_util_tx_all();
-    ble_sm_test_util_verify_tx_pair_rsp(&params->pair_rsp);
-    TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
-    TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
 
-    /* Receive a public key from the peer. */
-    ble_sm_test_util_rx_public_key(2, &params->public_key_req);
-    TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
-    TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
+    fail.reason = BLE_SM_ERR_CMD_NOT_SUPP;
+    ble_sm_test_util_verify_tx_pair_fail(&fail);
 
-    /* Ensure we sent the expected public key. */
+    /*** Pairing already in progress; ignore security request. */
+    ble_hs_atomic_conn_set_flags(2, BLE_HS_CONN_F_MASTER, 1);
+    rc = ble_sm_pair_initiate(2);
+    TEST_ASSERT_FATAL(rc == 0);
     ble_hs_test_util_tx_all();
-    ble_sm_test_util_verify_tx_public_key(&params->public_key_rsp);
-    TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
-    TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
-
-    switch (params->pair_alg) {
-    case BLE_SM_PAIR_ALG_PASSKEY:
-        num_iters = 20;
-        break;
-
-    default:
-        num_iters = 1;
-        break;
-    }
-
-    ble_sm_test_util_io_check_pre(&params->passkey_info,
-                                  BLE_SM_PROC_STATE_CONFIRM);
-
-    for (i = 0; i < num_iters; i++) {
-        if (i != 0) {
-            ble_sm_dbg_set_next_pair_rand(params->random_rsp[i].value);
-        }
-
-        if (params->pair_alg != BLE_SM_PAIR_ALG_JW      &&
-            params->pair_alg != BLE_SM_PAIR_ALG_NUMCMP) {
-
-            /* Receive a pair confirm from the peer. */
-            ble_sm_test_util_rx_confirm(2, params->confirm_req + i);
-            TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
-            TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
-        }
-
-        if (i == 0) {
-            ble_sm_test_util_io_check_post(&params->passkey_info,
-                                           BLE_SM_PROC_STATE_CONFIRM);
-        }
-
-        /* Ensure we sent the expected pair confirm. */
-        ble_hs_test_util_tx_all();
-        ble_sm_test_util_verify_tx_pair_confirm(params->confirm_rsp + i);
-        TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
-        TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
-
-        /* Receive a pair random from the peer. */
-        ble_sm_test_util_rx_random(2, params->random_req + i, 0);
-        TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
-        TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
-
-        /* Ensure we sent the expected pair random. */
-        ble_hs_test_util_tx_all();
-        ble_sm_test_util_verify_tx_pair_random(params->random_rsp + i);
-        TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
-        TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
-
-    }
-
-    ble_sm_test_util_io_check_pre(&params->passkey_info,
-                                  BLE_SM_PROC_STATE_DHKEY_CHECK);
-
-    /* Receive a dhkey check from the peer. */
-    ble_sm_test_util_rx_dhkey_check(2, &params->dhkey_check_req, 0);
-    TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
-    TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
-
-    ble_sm_test_util_io_check_post(&params->passkey_info,
-                                   BLE_SM_PROC_STATE_DHKEY_CHECK);
+    ble_hs_test_util_prev_tx_queue_clear();
 
-    /* Ensure we sent the expected dhkey check. */
+    ble_sm_test_util_rx_sec_req(2, &sec_req, BLE_HS_EALREADY);
     ble_hs_test_util_tx_all();
-    ble_sm_test_util_verify_tx_dhkey_check(&params->dhkey_check_rsp);
-    TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
-    TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
-
-    /* Receive a long term key request from the controller. */
-    ble_sm_test_util_set_lt_key_req_reply_ack(0, 2);
-    ble_sm_test_util_rx_lt_key_req(2, 0, 0);
-    TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
-    TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
-
-    /* Ensure we sent the expected long term key request reply command. */
-    ble_sm_test_util_verify_tx_lt_key_req_reply(2, params->ltk);
-    TEST_ASSERT(!conn->bhc_sec_state.enc_enabled);
-    TEST_ASSERT(ble_sm_dbg_num_procs() == 1);
-
-    /* Receive an encryption changed event. */
-    ble_sm_test_util_rx_enc_change(2, 0, 1);
-
-    /* Pairing should now be complete. */
-    TEST_ASSERT(ble_sm_dbg_num_procs() == 0);
+    TEST_ASSERT(ble_hs_test_util_prev_tx_queue_sz() == 0);
+}
 
-    /* Verify that security callback was executed. */
-    TEST_ASSERT(ble_sm_test_gap_event == BLE_GAP_EVENT_ENC_CHANGE);
-    TEST_ASSERT(ble_sm_test_gap_status == 0);
-    TEST_ASSERT(ble_sm_test_sec_state.pair_alg == params->pair_alg);
-    TEST_ASSERT(ble_sm_test_sec_state.enc_enabled);
-    TEST_ASSERT(ble_sm_test_sec_state.authenticated ==
-                params->authenticated);
+/**
+ * Master: us.
+ * Peer sends a security request.
+ * We respond by initiating the pairing procedure.
+ */
+TEST_CASE(ble_sm_test_case_peer_sec_req_pair)
+{
+    struct ble_sm_test_lgcy_params params;
 
-    /* Verify that connection has correct security state. */
-    TEST_ASSERT(ble_sm_test_sec_state.pair_alg ==
-                conn->bhc_sec_state.pair_alg);
-    TEST_ASSERT(ble_sm_test_sec_state.enc_enabled ==
-                conn->bhc_sec_state.enc_enabled);
-    TEST_ASSERT(ble_sm_test_sec_state.authenticated ==
-                conn->bhc_sec_state.authenticated);
+    params = (struct ble_sm_test_lgcy_params) {
+        .init_addr = {0x06, 0x05, 0x04, 0x03, 0x02, 0x01},
+        .rsp_addr = {0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a},
+        .sec_req = (struct ble_sm_sec_req) {
+            .authreq = 0,
+        },
+        .has_sec_req = 1,
+        .pair_req = (struct ble_sm_pair_cmd) {
+            .io_cap = 3,
+            .oob_data_flag = 0,
+            .authreq = 0,
+            .max_enc_key_size = 16,
+            .init_key_dist = 0,
+            .resp_key_dist = 0,
+        },
+        .pair_rsp = (struct ble_sm_pair_cmd) {
+            .io_cap = 3,
+            .oob_data_flag = 0,
+            .authreq = 0,
+            .max_enc_key_size = 16,
+            .init_key_dist = 0,
+            .resp_key_dist = 0,
+        },
+        .confirm_req = (struct ble_sm_pair_confirm) {
+            .value = {
+                0x04, 0x4e, 0xaf, 0xce, 0x30, 0x79, 0x2c, 0x9e,
+                0xa2, 0xeb, 0x53, 0x6a, 0xdf, 0xf7, 0x99, 0xb2,
+            },
+        },
+        .confirm_rsp = (struct ble_sm_pair_confirm) {
+            .value = {
+                0x04, 0x4e, 0xaf, 0xce, 0x30, 0x79, 0x2c, 0x9e,
+                0xa2, 0xeb, 0x53, 0x6a, 0xdf, 0xf7, 0x99, 0xb2,
+            },
+        },
+        .random_req = (struct ble_sm_pair_random) {
+            .value = {
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            },
+        },
+        .random_rsp = (struct ble_sm_pair_random) {
+            .value = {
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            },
+        },
+        .pair_alg = BLE_SM_PAIR_ALG_JW,
+        .tk = { 0 },
+        .stk = {
+            0x2e, 0x2b, 0x34, 0xca, 0x59, 0xfa, 0x4c, 0x88,
+            0x3b, 0x2c, 0x8a, 0xef, 0xd4, 0x4b, 0xe9, 0x66,
+        },
+        .r = 0,
+        .ediv = 0,
+    };
 
-    /* Verify the appropriate security material was persisted. */
-    ble_sm_test_util_verify_sc_persist(params);
+    ble_sm_test_util_us_lgcy_good(&params);
 }
 
-static void
-ble_sm_test_util_peer_sc_good(struct ble_sm_test_sc_params *params)
+/**
+ * Master: us.
+ * Peer sends a security request.
+ * We respond by initiating the encryption procedure.
+ */
+TEST_CASE(ble_sm_test_case_peer_sec_req_enc)
 {
-    params->passkey_info.io_before_rx = 0;
-    ble_sm_test_util_peer_sc_good_once(params);
-
-    params->passkey_info.io_before_rx = 1;
-    ble_sm_test_util_peer_sc_good_once(params);
-
+    /* Unauthenticated. */
+    ble_sm_test_util_us_bonding_good(
+        1,
+        ((uint8_t[16]){ 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 }),
+        0,
+        0x1234,
+        0x5678);
 }
 
 TEST_CASE(ble_sm_test_case_peer_sc_jw_good)
@@ -2789,29 +2495,6 @@ TEST_CASE(ble_sm_test_case_peer_sc_numcmp_good)
     ble_sm_test_util_peer_sc_good(&params);
 }
 
-TEST_CASE(ble_sm_test_case_f4)
-{
-	uint8_t u[32] = { 0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc,
-			  0xdb, 0xfd, 0xf4, 0xac, 0x11, 0x91, 0xf4, 0xef,
-			  0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e,
-			  0x2c, 0xbe, 0x97, 0xf2, 0xd2, 0x03, 0xb0, 0x20 };
-	uint8_t v[32] = { 0xfd, 0xc5, 0x7f, 0xf4, 0x49, 0xdd, 0x4f, 0x6b,
-			  0xfb, 0x7c, 0x9d, 0xf1, 0xc2, 0x9a, 0xcb, 0x59,
-			  0x2a, 0xe7, 0xd4, 0xee, 0xfb, 0xfc, 0x0a, 0x90,
-			  0x9a, 0xbb, 0xf6, 0x32, 0x3d, 0x8b, 0x18, 0x55 };
-	uint8_t x[16] = { 0xab, 0xae, 0x2b, 0x71, 0xec, 0xb2, 0xff, 0xff,
-			  0x3e, 0x73, 0x77, 0xd1, 0x54, 0x84, 0xcb, 0xd5 };
-	uint8_t z = 0x00;
-	uint8_t exp[16] = { 0x2d, 0x87, 0x74, 0xa9, 0xbe, 0xa1, 0xed, 0xf1,
-			    0x1c, 0xbd, 0xa9, 0x07, 0xf1, 0x16, 0xc9, 0xf2 };
-	uint8_t res[16];
-	int err;
-
-	err = ble_sm_alg_f4(u, v, x, z, res);
-	TEST_ASSERT_FATAL(err == 0);
-    TEST_ASSERT(memcmp(res, exp, 16) == 0);
-}
-
 TEST_CASE(ble_sm_test_case_peer_sc_passkey_good)
 {
     struct ble_sm_test_sc_params params;
@@ -2983,481 +2666,801 @@ TEST_CASE(ble_sm_test_case_peer_sc_passkey_good)
                 0xb3,0xae, 0x59, 0x92, 0xec, 0x3e, 0xe6, 0x17,
             },
         },
-        .confirm_req[5] = {
+        .confirm_req[5] = {
+            .value = {
+                0x61,0x65, 0x44, 0xa6, 0x35, 0x88, 0x34, 0x80,
+                0xeb,0xce, 0xc4, 0xc3, 0xa0, 0xf4, 0xc4, 0xdb,
+            },
+        },
+        .confirm_rsp[5] = {
+            .value = {
+                0xc5,0xdd, 0x46, 0x1c, 0x42, 0x8a, 0xe9, 0x5c,
+                0x71,0xb3, 0x55, 0x5f, 0x35, 0xdd, 0xb3, 0x79,
+            },
+        },
+        .random_req[5] = {
+            .value = {
+                0xfa,0xae, 0x45, 0x2a, 0x17, 0xff, 0xfe, 0xe1,
+                0x05,0x58, 0xa4, 0xbd, 0x40, 0x9e, 0x05, 0x0c,
+            },
+        },
+        .random_rsp[5] = {
+            .value = {
+                0x7b,0xef, 0xca, 0x4e, 0x87, 0x80, 0xef, 0xd9,
+                0x8f,0xa5, 0x61, 0x8d, 0x73, 0xb2, 0x38, 0xcd,
+            },
+        },
+        .confirm_req[6] = {
+            .value = {
+                0x38,0xfb, 0x19, 0x1e, 0xc7, 0xec, 0x11, 0xed,
+                0xaa,0xc0, 0xa5, 0xaf, 0x79, 0x8f, 0x96, 0x82,
+            },
+        },
+        .confirm_rsp[6] = {
+            .value = {
+                0x9d,0x0f, 0x44, 0x66, 0xd7, 0x05, 0x24, 0x81,
+                0xff,0x32, 0x5c, 0xda, 0x25, 0x2c, 0x92, 0xec,
+            },
+        },
+        .random_req[6] = {
+            .value = {
+                0x77,0xc3, 0x35, 0x7b, 0x78, 0xbc, 0xe4, 0xc1,
+                0x9c,0x13, 0xbd, 0xd2, 0xd2, 0xc6, 0x1e, 0x50,
+            },
+        },
+        .random_rsp[6] = {
+            .value = {
+                0x5d,0xd5, 0x12, 0x06, 0x66, 0xd1, 0x74, 0x3a,
+                0xb7,0x5e, 0x54, 0x0d, 0xa2, 0x0f, 0xa4, 0x7c,
+            },
+        },
+        .confirm_req[7] = {
+            .value = {
+                0x32,0xe8, 0xf4, 0xc9, 0xed, 0xa7, 0xd3, 0x95,
+                0x94,0x0f, 0x08, 0xfb, 0xaa, 0xce, 0x84, 0x06,
+            },
+        },
+        .confirm_rsp[7] = {
+            .value = {
+                0x5a,0x59, 0xb8, 0xbe, 0x70, 0x33, 0x99, 0xf9,
+                0x07,0xff, 0x70, 0xe2, 0x10, 0x53, 0xf6, 0xf1,
+            },
+        },
+        .random_req[7] = {
+            .value = {
+                0x2f,0x07, 0x42, 0x95, 0xb2, 0x97, 0xcf, 0xa4,
+                0xde,0x2e, 0x88, 0xa1, 0x2a, 0x3c, 0x89, 0x6e,
+            },
+        },
+        .random_rsp[7] = {
+            .value = {
+                0x23,0x21, 0x9f, 0x2f, 0xfc, 0xb1, 0x80, 0xce,
+                0x0f,0x3d, 0xe6, 0xee, 0xbe, 0xab, 0x28, 0xe2,
+            },
+        },
+        .confirm_req[8] = {
+            .value = {
+                0x20,0xc3, 0x49, 0x90, 0x13, 0xad, 0x99, 0x69,
+                0xf1,0xd3, 0x71, 0x95, 0xb0, 0x54, 0xc4, 0xce,
+            },
+        },
+        .confirm_rsp[8] = {
+            .value = {
+                0x02,0x50, 0x29, 0x57, 0xc5, 0x26, 0x1f, 0x90,
+                0x05,0x8b, 0x8c, 0x20, 0xe9, 0xf7, 0xdd, 0x03,
+            },
+        },
+        .random_req[8] = {
+            .value = {
+                0xfd,0x09, 0x39, 0xc8, 0xc6, 0x57, 0xcf, 0x09,
+                0xc7,0x89, 0xab, 0xcc, 0x05, 0xda, 0xb7, 0x05,
+            },
+        },
+        .random_rsp[8] = {
+            .value = {
+                0x0d,0xed, 0xfd, 0x38, 0x76, 0x56, 0xa0, 0xcc,
+                0xf4,0x66, 0x09, 0xcb, 0x0f, 0x8c, 0xa5, 0x6a,
+            },
+        },
+        .confirm_req[9] = {
+            .value = {
+                0xce,0x50, 0x75, 0xda, 0x6a, 0x88, 0x98, 0x00,
+                0xe5,0x4d, 0x7d, 0xcf, 0xde, 0x00, 0xc5, 0x18,
+            },
+        },
+        .confirm_rsp[9] = {
+            .value = {
+                0x0b,0xd4, 0x0c, 0xba, 0xfe, 0x9a, 0xf0, 0x31,
+                0x13,0x21, 0x70, 0x11, 0x7c, 0xde, 0x26, 0x75,
+            },
+        },
+        .random_req[9] = {
+            .value = {
+                0x24,0x85, 0x91, 0xef, 0x4b, 0x8e, 0x2b, 0x67,
+                0x39,0x93, 0x7c, 0x7e, 0x4b, 0x76, 0x10, 0x44,
+            },
+        },
+        .random_rsp[9] = {
+            .value = {
+                0x2d,0xa3, 0x52, 0xc7, 0x09, 0x0b, 0xda, 0x81,
+                0xbd,0x10, 0x30, 0x57, 0x20, 0x2c, 0x5b, 0x90,
+            },
+        },
+        .confirm_req[10] = {
+            .value = {
+                0x7a,0x3e, 0x5b, 0x55, 0x08, 0x63, 0x32, 0x65,
+                0xaa,0xf8, 0xc1, 0xd2, 0xd6, 0x01, 0x1a, 0x7e,
+            },
+        },
+        .confirm_rsp[10] = {
+            .value = {
+                0x46,0xdd, 0x55, 0x46, 0x90, 0x55, 0xc8, 0x0b,
+                0x9e,0x7b, 0x81, 0xbb, 0x71, 0x11, 0x7f, 0x58,
+            },
+        },
+        .random_req[10] = {
+            .value = {
+                0xc0,0xe0, 0xa0, 0x10, 0xfc, 0xbc, 0xd9, 0x54,
+                0x48,0xdc, 0xcf, 0x8f, 0xda, 0xe6, 0x6a, 0x5f,
+            },
+        },
+        .random_rsp[10] = {
+            .value = {
+                0x22,0x3c, 0xd5, 0x79, 0x3e, 0xb3, 0x64, 0x3c,
+                0x46,0xba, 0xbc, 0x74, 0x4a, 0xc0, 0x5c, 0x18,
+            },
+        },
+        .confirm_req[11] = {
+            .value = {
+                0x29,0x6e, 0x96, 0xb8, 0xc1, 0x74, 0x27, 0x4c,
+                0x56,0xe0, 0x3e, 0x33, 0x3a, 0xca, 0xf9, 0x68,
+            },
+        },
+        .confirm_rsp[11] = {
+            .value = {
+                0xf0,0xe5, 0x3e, 0x5b, 0x68, 0x82, 0x40, 0x53,
+                0x98,0x1b, 0x57, 0xdd, 0x4f, 0x40, 0x23, 0xa2,
+            },
+        },
+        .random_req[11] = {
+            .value = {
+                0xb8,0xd9, 0x75, 0x53, 0x65, 0x42, 0x5a, 0x0c,
+                0x82,0x74, 0x55, 0x2c, 0x40, 0x5b, 0x02, 0xed,
+            },
+        },
+        .random_rsp[11] = {
+            .value = {
+                0x3f,0x88, 0x97, 0x63, 0x72, 0xe7, 0x84, 0x29,
+                0x2d,0xcc, 0xd3, 0xc6, 0xbb, 0xa8, 0x6a, 0xb8,
+            },
+        },
+        .confirm_req[12] = {
+            .value = {
+                0x6c,0x1f, 0x97, 0xda, 0x08, 0x2c, 0x9b, 0x8b,
+                0xf2,0xb0, 0x7a, 0x3e, 0xdf, 0xbf, 0x1e, 0x70,
+            },
+        },
+        .confirm_rsp[12] = {
+            .value = {
+                0x18,0xfe, 0x73, 0x49, 0xe0, 0x7a, 0x75, 0xd3,
+                0x68,0x52, 0x2d, 0xae, 0x76, 0xf5, 0xc1, 0x4f,
+            },
+        },
+        .random_req[12] = {
+            .value = {
+                0xb3,0xf1, 0xd0, 0xa9, 0x5a, 0x69, 0xa7, 0x33,
+                0xb9,0xdd, 0x04, 0x7d, 0x19, 0xc9, 0x0e, 0xdc,
+            },
+        },
+        .random_rsp[12] = {
+            .value = {
+                0x62,0x10, 0x99, 0xae, 0xc0, 0x5c, 0x00, 0x59,
+                0xda,0x14, 0x38, 0x41, 0x8e, 0x70, 0xd9, 0x51,
+            },
+        },
+        .confirm_req[13] = {
+            .value = {
+                0x3f,0x62, 0xd8, 0x3c, 0x29, 0x25, 0xf7, 0x96,
+                0x1c,0x01, 0x4f, 0x27, 0x19, 0x89, 0x51, 0xaf,
+            },
+        },
+        .confirm_rsp[13] = {
             .value = {
-                0x61,0x65, 0x44, 0xa6, 0x35, 0x88, 0x34, 0x80,
-                0xeb,0xce, 0xc4, 0xc3, 0xa0, 0xf4, 0xc4, 0xdb,
+                0x4c,0x9f, 0xff, 0xef, 0x9c, 0x04, 0x4f, 0xa7,
+                0xb9,0x8f, 0x9b, 0x4c, 0xbb, 0xaa, 0x8c, 0x44,
             },
         },
-        .confirm_rsp[5] = {
+        .random_req[13] = {
             .value = {
-                0xc5,0xdd, 0x46, 0x1c, 0x42, 0x8a, 0xe9, 0x5c,
-                0x71,0xb3, 0x55, 0x5f, 0x35, 0xdd, 0xb3, 0x79,
+                0x73,0x5e, 0xef, 0x3b, 0x9b, 0x45, 0xf1, 0x31,
+                0xcd,0x0c, 0x26, 0x7c, 0xe9, 0xfc, 0x04, 0x5d,
             },
         },
-        .random_req[5] = {
+        .random_rsp[13] = {
             .value = {
-                0xfa,0xae, 0x45, 0x2a, 0x17, 0xff, 0xfe, 0xe1,
-                0x05,0x58, 0xa4, 0xbd, 0x40, 0x9e, 0x05, 0x0c,
+                0x38,0x53, 0x68, 0xaa, 0xdf, 0x20, 0xd4, 0xef,
+                0x11,0x2b, 0xac, 0xe2, 0x7c, 0x11, 0x00, 0x10,
             },
         },
-        .random_rsp[5] = {
+        .confirm_req[14] = {
             .value = {
-                0x7b,0xef, 0xca, 0x4e, 0x87, 0x80, 0xef, 0xd9,
-                0x8f,0xa5, 0x61, 0x8d, 0x73, 0xb2, 0x38, 0xcd,
+                0x13,0x1d, 0xc2, 0x1a, 0x39, 0x01, 0xbf, 0xf9,
+                0x87,0xdd, 0xb4, 0xd3, 0xe5, 0xe8, 0x8c, 0x42,
             },
         },
-        .confirm_req[6] = {
+        .confirm_rsp[14] = {
             .value = {
-                0x38,0xfb, 0x19, 0x1e, 0xc7, 0xec, 0x11, 0xed,
-                0xaa,0xc0, 0xa5, 0xaf, 0x79, 0x8f, 0x96, 0x82,
+                0x34,0xc5, 0xda, 0xc1, 0x4c, 0xa8, 0x47, 0x31,
+                0x76,0x5e, 0x4f, 0xcd, 0x37, 0x77, 0x04, 0x10,
             },
         },
-        .confirm_rsp[6] = {
+        .random_req[14] = {
             .value = {
-                0x9d,0x0f, 0x44, 0x66, 0xd7, 0x05, 0x24, 0x81,
-                0xff,0x32, 0x5c, 0xda, 0x25, 0x2c, 0x92, 0xec,
+                0x59,0x02, 0xa1, 0x35, 0xd7, 0x12, 0x9a, 0x51,
+                0xf4,0xad, 0x32, 0xdf, 0x3b, 0xa4, 0x3a, 0xae,
             },
         },
-        .random_req[6] = {
+        .random_rsp[14] = {
             .value = {
-                0x77,0xc3, 0x35, 0x7b, 0x78, 0xbc, 0xe4, 0xc1,
-                0x9c,0x13, 0xbd, 0xd2, 0xd2, 0xc6, 0x1e, 0x50,
+                0x47,0x9e, 0x47, 0x0f, 0x53, 0xad, 0x74, 0x57,
+                0x1a,0xdc, 0x1b, 0x5f, 0xc0, 0xf0, 0x00, 0x1a,
             },
         },
-        .random_rsp[6] = {
+        .confirm_req[15] = {
             .value = {
-                0x5d,0xd5, 0x12, 0x06, 0x66, 0xd1, 0x74, 0x3a,
-                0xb7,0x5e, 0x54, 0x0d, 0xa2, 0x0f, 0xa4, 0x7c,
+                0x4c,0xa7, 0x4f, 0x64, 0xc1, 0xb7, 0xfe, 0xa9,
+                0xcb,0x94, 0x5f, 0x39, 0x9a, 0x1e, 0xbf, 0xb4,
             },
         },
-        .confirm_req[7] = {
+        .confirm_rsp[15] = {
             .value = {
-                0x32,0xe8, 0xf4, 0xc9, 0xed, 0xa7, 0xd3, 0x95,
-                0x94,0x0f, 0x08, 0xfb, 0xaa, 0xce, 0x84, 0x06,
+                0xed,0x61, 0x96, 0xaa, 0xd5, 0x27, 0x23, 0x32,
+                0xc4,0x80, 0x52, 0x3c, 0x81, 0x45, 0x37, 0xc3,
             },
         },
-        .confirm_rsp[7] = {
+        .random_req[15] = {
             .value = {
-                0x5a,0x59, 0xb8, 0xbe, 0x70, 0x33, 0x99, 0xf9,
-                0x07,0xff, 0x70, 0xe2, 0x10, 0x53, 0xf6, 0xf1,
+                0xe4,0x2e, 0x04, 0xce, 0x7d, 0xbe, 0xb5, 0x5b,
+                0xb5,0xd5, 0xba, 0x60, 0x3f, 0x88, 0x05, 0xf1,
             },
         },
-        .random_req[7] = {
+        .random_rsp[15] = {
             .value = {
-                0x2f,0x07, 0x42, 0x95, 0xb2, 0x97, 0xcf, 0xa4,
-                0xde,0x2e, 0x88, 0xa1, 0x2a, 0x3c, 0x89, 0x6e,
+                0x64,0xa0, 0x95, 0x1f, 0x01, 0x7e, 0x00, 0x8d,
+                0x00,0x40, 0xa1, 0x2f, 0x90, 0x42, 0xcb, 0x15,
             },
         },
-        .random_rsp[7] = {
+        .confirm_req[16] = {
             .value = {
-                0x23,0x21, 0x9f, 0x2f, 0x

<TRUNCATED>