/** * Generates the Ri byte used in the confirm message. On success, the byte is * written to the supplied procedure object. */ static int ble_sm_sc_gen_ri(struct ble_sm_proc *proc) { int byte; int bit; int rc; switch (proc->pair_alg) { case BLE_SM_PAIR_ALG_JW: case BLE_SM_PAIR_ALG_NUMCMP: proc->ri = 0; return 0; case BLE_SM_PAIR_ALG_PASSKEY: BLE_HS_DBG_ASSERT(proc->passkey_bits_exchanged < BLE_SM_SC_PASSKEY_BITS); byte = proc->passkey_bits_exchanged / 8; bit = proc->passkey_bits_exchanged % 8; proc->ri = 0x80 | !!(proc->tk[byte] & (1 << bit)); proc->passkey_bits_exchanged++; return 0; case BLE_SM_PAIR_ALG_OOB: rc = ble_hs_hci_util_rand(&proc->ri, 1); return rc; default: BLE_HS_DBG_ASSERT(0); return BLE_HS_EUNKNOWN; } }
static const void * ble_att_init_parse(uint8_t op, const void *payload, int min_len, int actual_len) { const uint8_t *u8ptr; BLE_HS_DBG_ASSERT(actual_len >= min_len); u8ptr = payload; BLE_HS_DBG_ASSERT(u8ptr[0] == op); return u8ptr + 1; }
void ble_l2cap_sig_update_rsp_write(void *payload, int len, struct ble_l2cap_sig_update_rsp *src) { BLE_HS_DBG_ASSERT(len >= BLE_L2CAP_SIG_UPDATE_RSP_SZ); ble_l2cap_sig_update_rsp_swap(payload, src); }
void ble_l2cap_sig_update_rsp_parse(void *payload, int len, struct ble_l2cap_sig_update_rsp *dst) { BLE_HS_DBG_ASSERT(len >= BLE_L2CAP_SIG_UPDATE_RSP_SZ); ble_l2cap_sig_update_rsp_swap(dst, payload); }
static void ble_l2cap_sig_reject_write(void *payload, uint16_t len, struct ble_l2cap_sig_reject *src) { BLE_HS_DBG_ASSERT(len >= BLE_L2CAP_SIG_REJECT_MIN_SZ); ble_l2cap_sig_reject_swap(payload, src); }
static int ble_store_persist_sec(int obj_type, struct ble_store_value_sec *value_sec) { struct ble_store_key_sec key_sec; union ble_store_value *store_value; union ble_store_key *store_key; int rc; BLE_HS_DBG_ASSERT(value_sec->peer_addr_type == BLE_ADDR_TYPE_PUBLIC || value_sec->peer_addr_type == BLE_ADDR_TYPE_RANDOM); /* If the value contains no keys, delete the corresponding entry. * Otherwise, write it. */ if (!value_sec->ltk_present && !value_sec->irk_present && !value_sec->csrk_present) { ble_store_key_from_value_sec(&key_sec, value_sec); store_key = (void *)&key_sec; rc = ble_store_delete(obj_type, store_key); } else { store_value = (void *)value_sec; rc = ble_store_write(obj_type, store_value); } return rc; }
void ble_l2cap_sig_hdr_parse(void *payload, uint16_t len, struct ble_l2cap_sig_hdr *dst) { BLE_HS_DBG_ASSERT(len >= BLE_L2CAP_SIG_HDR_SZ); ble_l2cap_sig_hdr_swap(dst, payload); }
void ble_l2cap_sig_hdr_write(void *payload, uint16_t len, struct ble_l2cap_sig_hdr *src) { BLE_HS_DBG_ASSERT(len >= BLE_L2CAP_SIG_HDR_SZ); ble_l2cap_sig_hdr_swap(payload, src); }
static int ble_att_clt_init_req(uint16_t initial_sz, struct os_mbuf **out_txom) { void *buf; int rc; *out_txom = ble_hs_misc_pkthdr(); if (*out_txom == NULL) { rc = BLE_HS_ENOMEM; goto err; } buf = os_mbuf_extend(*out_txom, initial_sz); if (buf == NULL) { rc = BLE_HS_ENOMEM; goto err; } /* The caller expects the initial buffer to be at the start of the mbuf. */ BLE_HS_DBG_ASSERT(buf == (*out_txom)->om_data); return 0; err: os_mbuf_free_chain(*out_txom); *out_txom = NULL; return rc; }
/* XXX: Should not require locked. */ int ble_sm_pair_fail_tx(uint16_t conn_handle, uint8_t reason) { struct ble_sm_pair_fail cmd; struct os_mbuf *txom; int rc; BLE_HS_DBG_ASSERT(reason > 0 && reason < BLE_SM_ERR_MAX_PLUS_1); rc = ble_sm_init_req(BLE_SM_PAIR_FAIL_SZ, &txom); if (rc != BLE_HS_ENONE) { return BLE_HS_ENOMEM; } cmd.reason = reason; ble_sm_pair_fail_write(txom->om_data, txom->om_len, &cmd); BLE_SM_LOG_CMD(TRUE, "fail", conn_handle, ble_sm_pair_fail_log, &cmd); rc = ble_sm_tx(conn_handle, txom); if (rc != BLE_HS_ENONE) { return rc; } return BLE_HS_ENONE; }
void ble_sm_pair_random_parse(void *payload, int len, struct ble_sm_pair_random *cmd) { BLE_HS_DBG_ASSERT(len >= BLE_SM_PAIR_RANDOM_SZ); memcpy(cmd->value, payload, sizeof cmd->value); }
void ble_sm_pair_confirm_parse(void *payload, int len, struct ble_sm_pair_confirm *cmd) { BLE_HS_DBG_ASSERT(len >= BLE_SM_PAIR_CONFIRM_SZ); memcpy(cmd->value, payload, sizeof cmd->value); }
/* Initiator does not send a confirm when pairing algorithm is any of: * o just works * o numeric comparison * (vol. 3, part H, 2.3.5.6.2) */ static int ble_sm_sc_initiator_txes_confirm(struct ble_sm_proc *proc) { BLE_HS_DBG_ASSERT(proc->flags & BLE_SM_PROC_F_SC); return proc->pair_alg != BLE_SM_PAIR_ALG_JW && proc->pair_alg != BLE_SM_PAIR_ALG_NUMCMP; }
/* Responder does not verify the initiator's random number when pairing * algorithm is any of: * o just works * o numeric comparison * (vol. 3, part H, 2.3.5.6.2) */ static int ble_sm_sc_responder_verifies_random(struct ble_sm_proc *proc) { BLE_HS_DBG_ASSERT(proc->flags & BLE_SM_PROC_F_SC); return proc->pair_alg != BLE_SM_PAIR_ALG_JW && proc->pair_alg != BLE_SM_PAIR_ALG_NUMCMP; }
void ble_sm_sec_req_parse(void *payload, int len, struct ble_sm_sec_req *cmd) { uint8_t *u8ptr; BLE_HS_DBG_ASSERT(len >= BLE_SM_SEC_REQ_SZ); u8ptr = payload; cmd->authreq = *u8ptr; }
void ble_sm_pair_fail_parse(void *payload, int len, struct ble_sm_pair_fail *cmd) { uint8_t *u8ptr; BLE_HS_DBG_ASSERT(len >= BLE_SM_PAIR_FAIL_SZ); u8ptr = payload; cmd->reason = u8ptr[0]; }
void ble_hs_lock(void) { int rc; BLE_HS_DBG_ASSERT(!ble_hs_locked_by_cur_task()); rc = os_mutex_pend(&ble_hs_mutex, 0xffffffff); BLE_HS_DBG_ASSERT_EVAL(rc == 0 || rc == OS_NOT_STARTED); }
void ble_sm_enc_info_write(void *payload, int len, struct ble_sm_enc_info *cmd) { uint8_t *u8ptr; BLE_HS_DBG_ASSERT(len >= BLE_SM_HDR_SZ + BLE_SM_ENC_INFO_SZ); u8ptr = payload; u8ptr[0] = BLE_SM_OP_ENC_INFO; memcpy(u8ptr + 1, cmd->ltk, sizeof cmd->ltk); }
void ble_sm_id_info_write(void *payload, int len, struct ble_sm_id_info *cmd) { uint8_t *u8ptr; BLE_HS_DBG_ASSERT(len >= BLE_SM_HDR_SZ + BLE_SM_ID_INFO_SZ); u8ptr = payload; u8ptr[0] = BLE_SM_OP_IDENTITY_INFO; memcpy(u8ptr + BLE_SM_HDR_SZ, cmd->irk, sizeof cmd->irk); }
static void * ble_att_init_write(uint8_t op, void *payload, int min_len, int actual_len) { uint8_t *u8ptr; BLE_HS_DBG_ASSERT(actual_len >= min_len); u8ptr = payload; u8ptr[0] = op; return u8ptr + 1; }
void ble_sm_pair_fail_write(void *payload, int len, struct ble_sm_pair_fail *cmd) { uint8_t *u8ptr; BLE_HS_DBG_ASSERT(len >= BLE_SM_HDR_SZ + BLE_SM_PAIR_FAIL_SZ); u8ptr = payload; u8ptr[0] = BLE_SM_OP_PAIR_FAIL; u8ptr[1] = cmd->reason; }
void ble_sm_sec_req_write(void *payload, int len, struct ble_sm_sec_req *cmd) { uint8_t *u8ptr; BLE_HS_DBG_ASSERT(len >= BLE_SM_HDR_SZ + BLE_SM_SEC_REQ_SZ); u8ptr = payload; u8ptr[0] = BLE_SM_OP_SEC_REQ; u8ptr[1] = cmd->authreq; }
void ble_sm_sign_info_write(void *payload, int len, struct ble_sm_sign_info *cmd) { uint8_t *u8ptr; BLE_HS_DBG_ASSERT(len >= BLE_SM_HDR_SZ + BLE_SM_SIGN_INFO_SZ); u8ptr = payload; u8ptr[0] = BLE_SM_OP_SIGN_INFO; memcpy(u8ptr + BLE_SM_HDR_SZ, cmd->sig_key, sizeof cmd->sig_key); }
static int ble_att_clt_parse_find_info_entry(struct os_mbuf **rxom, uint8_t rsp_format, struct ble_att_find_info_idata *idata) { uint16_t uuid16; int entry_len; int rc; switch (rsp_format) { case BLE_ATT_FIND_INFO_RSP_FORMAT_16BIT: entry_len = 2 + 2; break; case BLE_ATT_FIND_INFO_RSP_FORMAT_128BIT: entry_len = 2 + 16; break; default: return BLE_HS_EBADDATA; } rc = ble_hs_misc_pullup_base(rxom, entry_len); if (rc != 0) { return rc; } idata->attr_handle = le16toh((*rxom)->om_data); switch (rsp_format) { case BLE_ATT_FIND_INFO_RSP_FORMAT_16BIT: uuid16 = le16toh((*rxom)->om_data + 2); rc = ble_uuid_16_to_128(uuid16, idata->uuid128); if (rc != 0) { return BLE_HS_EBADDATA; } break; case BLE_ATT_FIND_INFO_RSP_FORMAT_128BIT: rc = os_mbuf_copydata(*rxom, 2, 16, idata->uuid128); if (rc != 0) { return BLE_HS_EBADDATA; } break; default: BLE_HS_DBG_ASSERT(0); break; } os_mbuf_adj(*rxom, entry_len); return 0; }
void ble_sm_pair_confirm_write(void *payload, int len, struct ble_sm_pair_confirm *cmd) { uint8_t *u8ptr; BLE_HS_DBG_ASSERT(len >= BLE_SM_HDR_SZ + BLE_SM_PAIR_CONFIRM_SZ); u8ptr = payload; u8ptr[0] = BLE_SM_OP_PAIR_CONFIRM; memcpy(u8ptr + BLE_SM_HDR_SZ, cmd->value, sizeof cmd->value); }
void ble_sm_master_id_write(void *payload, int len, struct ble_sm_master_id *cmd) { uint8_t *u8ptr; BLE_HS_DBG_ASSERT(len >= BLE_SM_HDR_SZ + BLE_SM_MASTER_ID_SZ); u8ptr = payload; u8ptr[0] = BLE_SM_OP_MASTER_ID; htole16(u8ptr + 1, cmd->ediv); htole64(u8ptr + 3, cmd->rand_val); }
void ble_sm_id_addr_info_write(void *payload, int len, struct ble_sm_id_addr_info *cmd) { uint8_t *u8ptr; BLE_HS_DBG_ASSERT(len >= BLE_SM_HDR_SZ + BLE_SM_ID_ADDR_INFO_SZ); u8ptr = payload; u8ptr[0] = BLE_SM_OP_IDENTITY_ADDR_INFO; u8ptr[1] = cmd->addr_type; memcpy(u8ptr + 2, cmd->bd_addr, sizeof cmd->bd_addr); }
static void ble_l2cap_sig_reject_write(void *payload, uint16_t len, struct ble_l2cap_sig_reject *src, void *data, int data_len) { uint8_t *u8ptr; BLE_HS_DBG_ASSERT(len >= BLE_L2CAP_SIG_REJECT_MIN_SZ + data_len); ble_l2cap_sig_reject_swap(payload, src); u8ptr = payload; u8ptr += BLE_L2CAP_SIG_REJECT_MIN_SZ; memcpy(u8ptr, data, data_len); }
void ble_sm_pair_cmd_parse(void *payload, int len, struct ble_sm_pair_cmd *cmd) { uint8_t *u8ptr; BLE_HS_DBG_ASSERT(len >= BLE_SM_PAIR_CMD_SZ); u8ptr = payload; cmd->io_cap = u8ptr[0]; cmd->oob_data_flag = u8ptr[1]; cmd->authreq = u8ptr[2]; cmd->max_enc_key_size = u8ptr[3]; cmd->init_key_dist = u8ptr[4]; cmd->resp_key_dist = u8ptr[5]; }
void ble_hs_unlock(void) { int rc; #if BLE_HS_DEBUG if (!os_started()) { BLE_HS_DBG_ASSERT(ble_hs_dbg_mutex_locked); ble_hs_dbg_mutex_locked = 0; return; } #endif rc = os_mutex_release(&ble_hs_mutex); BLE_HS_DBG_ASSERT_EVAL(rc == 0 || rc == OS_NOT_STARTED); }