This closes #130.

Merge remote-tracking branch 'andrzej-kaczmarek/nimble-fixing' into develop

* andrzej-kaczmarek/nimble-fixing:
  bletiny: Add characteristic with auth required permission
  nimble/sm: Fix obvious array size mismatch
  nimble/sm: Use proper key size for encryption
  nimble/sm: Improve pairing req/rsp validation
  nimble/sm: Fix AuthReq/KeyDist validation in pairing req/rsp
  nimble/test: Remove invalid SM test cases
  nimble/test: Fix expected error for key size lower than minimum
  nimble/test: Fix expected value in ble_sm_test_util_us_fail_inval

X-Original-Commit: 7c218f67ee8dcec6dd8fe755198793747bc282f4
This commit is contained in:
Christopher Collins
2016-12-12 19:07:04 -08:00
7 changed files with 39 additions and 309 deletions
+18 -6
View File
@@ -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 {
-33
View File
@@ -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) {
+9 -2
View File
@@ -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;
}
+1
View File
@@ -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;
+8 -1
View File
@@ -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;
+2 -266
View File
@@ -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(&params);
/* 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(&params);
/* 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(&params);
/* 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(&params);
/* 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(&params);
@@ -591,58 +379,6 @@ TEST_CASE(ble_sm_test_case_us_fail_inval)
},
};
ble_sm_test_util_us_fail_inval(&params);
/* 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(&params);
/* 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(&params);
}
TEST_SUITE(ble_sm_gen_test_suite)
+1 -1
View File
@@ -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, &params->pair_rsp, BLE_HS_SM_US_ERR(BLE_SM_ERR_INVAL));
2, &params->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);