diff --git a/nimble/host/src/ble_sm.c b/nimble/host/src/ble_sm.c index 67e8728de..a49c3d20e 100644 --- a/nimble/host/src/ble_sm.c +++ b/nimble/host/src/ble_sm.c @@ -314,11 +314,14 @@ ble_sm_gen_ltk(struct ble_sm_proc *proc, uint8_t *ltk) } #endif - rc = ble_hs_hci_util_rand(ltk, 16); + rc = ble_hs_hci_util_rand(ltk, proc->key_size); if (rc != 0) { return rc; } + /* Ensure proper key size */ + memset(ltk + proc->key_size, 0, sizeof proc->ltk - proc->key_size); + return 0; } @@ -495,7 +498,7 @@ ble_sm_persist_keys(struct ble_sm_proc *proc) { struct ble_store_value_sec value_sec; struct ble_hs_conn *conn; - uint8_t peer_addr[8]; + uint8_t peer_addr[6]; uint8_t peer_addr_type; int authenticated; @@ -1377,6 +1380,9 @@ ble_sm_pair_cfg(struct ble_sm_proc *proc) if (rx_key_dist & BLE_SM_PAIR_KEY_DIST_SIGN) { proc->rx_key_flags |= BLE_SM_KE_F_SIGN_INFO; } + + proc->key_size = min(proc->pair_req.max_enc_key_size, + proc->pair_rsp.max_enc_key_size); } static void @@ -1393,7 +1399,7 @@ ble_sm_pair_exec(struct ble_sm_proc *proc, struct ble_sm_result *res, cmd.io_cap = ble_hs_cfg.sm_io_cap; cmd.oob_data_flag = ble_hs_cfg.sm_oob_data_flag; cmd.authreq = ble_sm_build_authreq(); - cmd.max_enc_key_size = 16; + cmd.max_enc_key_size = BLE_SM_PAIR_KEY_SZ_MAX; if (is_req) { cmd.init_key_dist = ble_hs_cfg.sm_our_key_dist; @@ -1487,9 +1493,12 @@ ble_sm_pair_req_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om, if (conn->bhc_flags & BLE_HS_CONN_F_MASTER) { res->sm_err = BLE_SM_ERR_CMD_NOT_SUPP; res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_CMD_NOT_SUPP); - } else if (!ble_sm_pair_cmd_is_valid(&req)) { + } else if (req.max_enc_key_size < BLE_SM_PAIR_KEY_SZ_MIN) { + res->sm_err = BLE_SM_ERR_ENC_KEY_SZ; + res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_ENC_KEY_SZ); + } else if (req.max_enc_key_size > BLE_SM_PAIR_KEY_SZ_MAX) { res->sm_err = BLE_SM_ERR_INVAL; - res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_INVAL); + res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_INVAL); } else { res->execute = 1; } @@ -1520,7 +1529,10 @@ ble_sm_pair_rsp_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om, proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_PAIR, 1, &prev); if (proc != NULL) { proc->pair_rsp = rsp; - if (!ble_sm_pair_cmd_is_valid(&rsp)) { + if (rsp.max_enc_key_size < BLE_SM_PAIR_KEY_SZ_MIN) { + res->sm_err = BLE_SM_ERR_ENC_KEY_SZ; + res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_ENC_KEY_SZ); + } else if (rsp.max_enc_key_size > BLE_SM_PAIR_KEY_SZ_MAX) { res->sm_err = BLE_SM_ERR_INVAL; res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_INVAL); } else { diff --git a/nimble/host/src/ble_sm_cmd.c b/nimble/host/src/ble_sm_cmd.c index 34609c6c8..67fa1b098 100644 --- a/nimble/host/src/ble_sm_cmd.c +++ b/nimble/host/src/ble_sm_cmd.c @@ -90,38 +90,6 @@ ble_sm_pair_cmd_parse(void *payload, int len, struct ble_sm_pair_cmd *cmd) cmd->resp_key_dist = u8ptr[5]; } -int -ble_sm_pair_cmd_is_valid(struct ble_sm_pair_cmd *cmd) -{ - if (cmd->io_cap >= BLE_SM_IO_CAP_RESERVED) { - return 0; - } - - if (cmd->oob_data_flag >= BLE_SM_PAIR_OOB_RESERVED) { - return 0; - } - - if (cmd->authreq & BLE_SM_PAIR_AUTHREQ_RESERVED) { - return 0; - } - - if (cmd->max_enc_key_size < BLE_SM_PAIR_KEY_SZ_MIN || - cmd->max_enc_key_size > BLE_SM_PAIR_KEY_SZ_MAX) { - - return 0; - } - - if (cmd->init_key_dist & BLE_SM_PAIR_KEY_DIST_RESERVED) { - return 0; - } - - if (cmd->resp_key_dist & BLE_SM_PAIR_KEY_DIST_RESERVED) { - return 0; - } - - return 1; -} - void ble_sm_pair_cmd_write(void *payload, int len, int is_req, struct ble_sm_pair_cmd *cmd) @@ -155,7 +123,6 @@ ble_sm_pair_cmd_tx(uint16_t conn_handle, int is_req, ble_sm_pair_cmd_write(txom->om_data, txom->om_len, is_req, cmd); BLE_SM_LOG_CMD(1, is_req ? "pair req" : "pair rsp", conn_handle, ble_sm_pair_cmd_log, cmd); - BLE_HS_DBG_ASSERT(ble_sm_pair_cmd_is_valid(cmd)); rc = ble_sm_tx(conn_handle, txom); if (rc != 0) { diff --git a/nimble/host/src/ble_sm_lgcy.c b/nimble/host/src/ble_sm_lgcy.c index ddc666de9..54a2ecb15 100644 --- a/nimble/host/src/ble_sm_lgcy.c +++ b/nimble/host/src/ble_sm_lgcy.c @@ -65,12 +65,16 @@ ble_sm_lgcy_io_action(struct ble_sm_proc *proc) { int action; - if (proc->pair_req.oob_data_flag && proc->pair_rsp.oob_data_flag) { + if (proc->pair_req.oob_data_flag == BLE_SM_PAIR_OOB_YES && + proc->pair_rsp.oob_data_flag == BLE_SM_PAIR_OOB_YES) { action = BLE_SM_IOACT_OOB; } else if (!(proc->pair_req.authreq & BLE_SM_PAIR_AUTHREQ_MITM) && !(proc->pair_rsp.authreq & BLE_SM_PAIR_AUTHREQ_MITM)) { action = BLE_SM_IOACT_NONE; + } else if (proc->pair_req.io_cap >= BLE_SM_IO_CAP_RESERVED || + proc->pair_rsp.io_cap >= BLE_SM_IO_CAP_RESERVED) { + action = BLE_SM_IOACT_NONE; } else if (proc->flags & BLE_SM_PROC_F_INITIATOR) { action = ble_sm_lgcy_init_ioa[proc->pair_rsp.io_cap] [proc->pair_req.io_cap]; @@ -177,7 +181,10 @@ ble_sm_gen_stk(struct ble_sm_proc *proc) return rc; } - memcpy(proc->ltk, key, sizeof key); + memcpy(proc->ltk, key, proc->key_size); + + /* Ensure proper key size */ + memset(proc->ltk + proc->key_size, 0, sizeof key - proc->key_size); return 0; } diff --git a/nimble/host/src/ble_sm_priv.h b/nimble/host/src/ble_sm_priv.h index 7d96164b0..d75d4756e 100644 --- a/nimble/host/src/ble_sm_priv.h +++ b/nimble/host/src/ble_sm_priv.h @@ -257,6 +257,7 @@ struct ble_sm_proc { uint8_t pair_alg; uint8_t state; uint8_t rx_key_flags; + uint8_t key_size; struct ble_sm_pair_cmd pair_req; struct ble_sm_pair_cmd pair_rsp; diff --git a/nimble/host/src/ble_sm_sc.c b/nimble/host/src/ble_sm_sc.c index 11b29a1c8..647160766 100644 --- a/nimble/host/src/ble_sm_sc.c +++ b/nimble/host/src/ble_sm_sc.c @@ -112,12 +112,16 @@ ble_sm_sc_io_action(struct ble_sm_proc *proc) { int action; - if (proc->pair_req.oob_data_flag || proc->pair_rsp.oob_data_flag) { + if (proc->pair_req.oob_data_flag == BLE_SM_PAIR_OOB_YES || + proc->pair_rsp.oob_data_flag == BLE_SM_PAIR_OOB_YES) { action = BLE_SM_IOACT_OOB; } else if (!(proc->pair_req.authreq & BLE_SM_PAIR_AUTHREQ_MITM) && !(proc->pair_rsp.authreq & BLE_SM_PAIR_AUTHREQ_MITM)) { action = BLE_SM_IOACT_NONE; + } else if (proc->pair_req.io_cap >= BLE_SM_IO_CAP_RESERVED || + proc->pair_rsp.io_cap >= BLE_SM_IO_CAP_RESERVED) { + action = BLE_SM_IOACT_NONE; } else if (proc->flags & BLE_SM_PROC_F_INITIATOR) { action = ble_sm_sc_init_ioa[proc->pair_rsp.io_cap] [proc->pair_req.io_cap]; @@ -436,6 +440,9 @@ ble_sm_sc_random_rx(struct ble_sm_proc *proc, struct ble_sm_result *res) return; } + /* Ensure proper key size */ + memset(proc->ltk + proc->key_size, 0, sizeof proc->ltk - proc->key_size); + /* Ensure the ltk gets persisted when the pairing procedure succeeds. */ memcpy(proc->our_keys.ltk, proc->ltk, sizeof proc->our_keys.ltk); proc->our_keys.ltk_valid = 1; diff --git a/nimble/host/test/src/ble_sm_test.c b/nimble/host/test/src/ble_sm_test.c index a98f4bb11..0580821b3 100644 --- a/nimble/host/test/src/ble_sm_test.c +++ b/nimble/host/test/src/ble_sm_test.c @@ -188,78 +188,6 @@ TEST_CASE(ble_sm_test_case_peer_fail_inval) } }) ); - /* 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, @@ -274,7 +202,7 @@ TEST_CASE(ble_sm_test_case_peer_fail_inval) .resp_key_dist = 0x07, } }), ((struct ble_sm_pair_fail[1]) { { - .reason = BLE_SM_ERR_INVAL, + .reason = BLE_SM_ERR_ENC_KEY_SZ, } }) ); @@ -295,42 +223,6 @@ TEST_CASE(ble_sm_test_case_peer_fail_inval) .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) @@ -436,110 +328,6 @@ TEST_CASE(ble_sm_test_case_us_fail_inval) { struct ble_sm_test_params params; - /* Invalid IO capabiltiies. */ - params = (struct ble_sm_test_params) { - .init_id_addr = {0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c}, - .resp_id_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(¶ms); - - /* Invalid OOB flag. */ - params = (struct ble_sm_test_params) { - .init_id_addr = {0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c}, - .resp_id_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(¶ms); - - /* Invalid authreq - reserved bonding flag. */ - params = (struct ble_sm_test_params) { - .init_id_addr = {0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c}, - .resp_id_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(¶ms); - - /* Invalid authreq - reserved other flag. */ - params = (struct ble_sm_test_params) { - .init_id_addr = {0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c}, - .resp_id_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(¶ms); - /* Invalid key size - too small. */ params = (struct ble_sm_test_params) { .init_id_addr = {0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c}, @@ -561,7 +349,7 @@ TEST_CASE(ble_sm_test_case_us_fail_inval) .resp_key_dist = 0x07, }, .pair_fail = (struct ble_sm_pair_fail) { - .reason = BLE_SM_ERR_INVAL, + .reason = BLE_SM_ERR_ENC_KEY_SZ, }, }; ble_sm_test_util_us_fail_inval(¶ms); @@ -591,58 +379,6 @@ TEST_CASE(ble_sm_test_case_us_fail_inval) }, }; ble_sm_test_util_us_fail_inval(¶ms); - - /* Invalid init key dist. */ - params = (struct ble_sm_test_params) { - .init_id_addr = {0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c}, - .resp_id_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(¶ms); - - /* Invalid resp key dist. */ - params = (struct ble_sm_test_params) { - .init_id_addr = {0xe1, 0xfc, 0xda, 0xf4, 0xb7, 0x6c}, - .resp_id_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 = 16, - .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(¶ms); } TEST_SUITE(ble_sm_gen_test_suite) diff --git a/nimble/host/test/src/ble_sm_test_util.c b/nimble/host/test/src/ble_sm_test_util.c index 7f40ff930..faa38ff61 100644 --- a/nimble/host/test/src/ble_sm_test_util.c +++ b/nimble/host/test/src/ble_sm_test_util.c @@ -2408,7 +2408,7 @@ ble_sm_test_util_us_fail_inval(struct ble_sm_test_params *params) /* Receive a pair response from the peer. */ ble_sm_test_util_rx_pair_rsp( - 2, ¶ms->pair_rsp, BLE_HS_SM_US_ERR(BLE_SM_ERR_INVAL)); + 2, ¶ms->pair_rsp, BLE_HS_SM_US_ERR(params->pair_fail.reason)); TEST_ASSERT(!conn->bhc_sec_state.encrypted); TEST_ASSERT(ble_sm_dbg_num_procs() == 0);