/* BlueZ - Bluetooth protocol stack for Linux Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation;
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS SOFTWARE IS DISCLAIMED.
*/
/* Low-level debug macros to be used for stuff that we don't want * accidentally in dmesg, i.e. the values of the various crypto keys * and the inputs & outputs of crypto functions.
*/ #ifdef DEBUG #define SMP_DBG(fmt, ...) printk(KERN_DEBUG "%s: " fmt, __func__, \ ##__VA_ARGS__) #else #define SMP_DBG(fmt, ...) no_printk(KERN_DEBUG "%s: " fmt, __func__, \ ##__VA_ARGS__) #endif
err = aes_cmac(tfm_cmac, x, m, sizeof(m), res); if (err) return err;
SMP_DBG("res %16phN", res);
return err;
}
staticint smp_f5(struct crypto_shash *tfm_cmac, const u8 w[32], const u8 n1[16], const u8 n2[16], const u8 a1[7], const u8 a2[7], u8 mackey[16], u8 ltk[16])
{ /* The btle, salt and length "magic" values are as defined in * the SMP section of the Bluetooth core specification. In ASCII * the btle value ends up being 'btle'. The salt is just a * random number whereas length is the value 256 in little * endian format.
*/ const u8 btle[4] = { 0x65, 0x6c, 0x74, 0x62 }; const u8 salt[16] = { 0xbe, 0x83, 0x60, 0x5a, 0xdb, 0x0b, 0x37, 0x60,
0x38, 0xa5, 0xf5, 0xaa, 0x91, 0x83, 0x88, 0x6c }; const u8 length[2] = { 0x00, 0x01 };
u8 m[53], t[16]; int err;
/* The output of the random address function ah is: * ah(k, r) = e(k, r') mod 2^24 * The output of the security function e is then truncated to 24 bits * by taking the least significant 24 bits of the output of e as the * result of ah.
*/
memcpy(res, _res, 3);
int smp_generate_oob(struct hci_dev *hdev, u8 hash[16], u8 rand[16])
{ struct l2cap_chan *chan = hdev->smp_data; struct smp_dev *smp; int err;
if (!chan || !chan->data) return -EOPNOTSUPP;
smp = chan->data;
if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS)) {
bt_dev_dbg(hdev, "Using debug keys");
err = set_ecdh_privkey(smp->tfm_ecdh, debug_sk); if (err) return err;
memcpy(smp->local_pk, debug_pk, 64);
smp->debug_key = true;
} else { while (true) { /* Generate key pair for Secure Connections */
err = generate_ecdh_keys(smp->tfm_ecdh, smp->local_pk); if (err) return err;
/* This is unlikely, but we need to check that * we didn't accidentally generate a debug key.
*/ if (crypto_memneq(smp->local_pk, debug_pk, 64)) break;
}
smp->debug_key = false;
}
SMP_DBG("OOB Public Key X: %32phN", smp->local_pk);
SMP_DBG("OOB Public Key Y: %32phN", smp->local_pk + 32);
/* Ensure that we don't leave any debug key around if debug key * support hasn't been explicitly enabled.
*/ if (smp->ltk && smp->ltk->type == SMP_LTK_P256_DEBUG &&
!hci_dev_test_flag(hcon->hdev, HCI_KEEP_DEBUG_KEYS)) {
list_del_rcu(&smp->ltk->list);
kfree_rcu(smp->ltk, rcu);
smp->ltk = NULL;
}
/* If pairing failed clean up any keys we might have */ if (!complete) { if (smp->ltk) {
list_del_rcu(&smp->ltk->list);
kfree_rcu(smp->ltk, rcu);
}
if (smp->responder_ltk) {
list_del_rcu(&smp->responder_ltk->list);
kfree_rcu(smp->responder_ltk, rcu);
}
if (smp->remote_irk) {
list_del_rcu(&smp->remote_irk->list);
kfree_rcu(smp->remote_irk, rcu);
}
}
static u8 get_auth_method(struct smp_chan *smp, u8 local_io, u8 remote_io)
{ /* If either side has unknown io_caps, use JUST_CFM (which gets * converted later to JUST_WORKS if we're initiators.
*/ if (local_io > SMP_IO_KEYBOARD_DISPLAY ||
remote_io > SMP_IO_KEYBOARD_DISPLAY) return JUST_CFM;
if (test_bit(SMP_FLAG_SC, &smp->flags)) return sc_method[remote_io][local_io];
/* If neither side wants MITM, either "just" confirm an incoming * request or use just-works for outgoing ones. The JUST_CFM * will be converted to JUST_WORKS if necessary later in this * function. If either side has MITM look up the method from the * table.
*/ if (!(auth & SMP_AUTH_MITM))
smp->method = JUST_CFM; else
smp->method = get_auth_method(smp, local_io, remote_io);
/* Don't bother user space with no IO capabilities */ if (smp->method == JUST_CFM &&
hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT)
smp->method = JUST_WORKS;
/* If Just Works, Continue with Zero TK and ask user-space for
* confirmation */ if (smp->method == JUST_WORKS) {
ret = mgmt_user_confirm_request(hcon->hdev, &hcon->dst,
hcon->type,
hcon->dst_type,
passkey, 1); if (ret) return ret;
set_bit(SMP_FLAG_WAIT_USER, &smp->flags); return 0;
}
/* If this function is used for SC -> legacy fallback we * can only recover the just-works case.
*/ if (test_bit(SMP_FLAG_SC, &smp->flags)) return -EINVAL;
/* Not Just Works/Confirm results in MITM Authentication */ if (smp->method != JUST_CFM) {
set_bit(SMP_FLAG_MITM_AUTH, &smp->flags); if (hcon->pending_sec_level < BT_SECURITY_HIGH)
hcon->pending_sec_level = BT_SECURITY_HIGH;
}
/* If both devices have Keyboard-Display I/O, the initiator * Confirms and the responder Enters the passkey.
*/ if (smp->method == OVERLAP) { if (test_bit(SMP_FLAG_INITIATOR, &smp->flags))
smp->method = CFM_PASSKEY; else
smp->method = REQ_PASSKEY;
}
/* Even though there's no _RESPONDER suffix this is the * responder STK we're adding for later lookup (the initiator * STK never needs to be stored).
*/
hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
SMP_STK, auth, stk, smp->enc_key_size, ediv, rand);
}
if (hcon->type == ACL_LINK) { if (hcon->key_type == HCI_LK_DEBUG_COMBINATION)
persistent = false; else
persistent = !test_bit(HCI_CONN_FLUSH_KEY,
&hcon->flags);
} else { /* The LTKs, IRKs and CSRKs should be persistent only if * both sides had the bonding bit set in their * authentication requests.
*/
persistent = !!((req->auth_req & rsp->auth_req) &
SMP_AUTH_BONDING);
}
if (smp->remote_irk) {
mgmt_new_irk(hdev, smp->remote_irk, persistent);
/* Now that user space can be considered to know the * identity address track the connection based on it * from now on (assuming this is an LE link).
*/ if (hcon->type == LE_LINK) {
bacpy(&hcon->dst, &smp->remote_irk->bdaddr);
hcon->dst_type = smp->remote_irk->addr_type; /* Use a short delay to make sure the new address is * propagated _before_ the channels.
*/
queue_delayed_work(hdev->workqueue,
&conn->id_addr_timer,
ID_ADDR_TIMEOUT);
}
}
if (smp->link_key) { struct link_key *key;
u8 type;
if (test_bit(SMP_FLAG_DEBUG_KEY, &smp->flags))
type = HCI_LK_DEBUG_COMBINATION; elseif (hcon->sec_level == BT_SECURITY_FIPS)
type = HCI_LK_AUTH_COMBINATION_P256; else
type = HCI_LK_UNAUTH_COMBINATION_P256;
/* Don't keep debug keys around if the relevant * flag is not set.
*/ if (!hci_dev_test_flag(hdev, HCI_KEEP_DEBUG_KEYS) &&
key->type == HCI_LK_DEBUG_COMBINATION) {
list_del_rcu(&key->list);
kfree_rcu(key, rcu);
}
}
}
}
staticvoid smp_allow_key_dist(struct smp_chan *smp)
{ /* Allow the first expected phase 3 PDU. The rest of the PDUs * will be allowed in each PDU handler to ensure we receive * them in the correct order.
*/ if (smp->remote_key_dist & SMP_DIST_ENC_KEY)
SMP_ALLOW_CMD(smp, SMP_CMD_ENCRYPT_INFO); elseif (smp->remote_key_dist & SMP_DIST_ID_KEY)
SMP_ALLOW_CMD(smp, SMP_CMD_IDENT_INFO); elseif (smp->remote_key_dist & SMP_DIST_SIGN)
SMP_ALLOW_CMD(smp, SMP_CMD_SIGN_INFO);
}
staticvoid sc_generate_ltk(struct smp_chan *smp)
{ /* From core spec. Spells out in ASCII as 'brle'. */ const u8 brle[4] = { 0x65, 0x6c, 0x72, 0x62 }; struct hci_conn *hcon = smp->conn->hcon; struct hci_dev *hdev = hcon->hdev; struct link_key *key;
key = hci_find_link_key(hdev, &hcon->dst); if (!key) {
bt_dev_err(hdev, "no Link Key found to generate LTK"); return;
}
if (key->type == HCI_LK_DEBUG_COMBINATION)
set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags);
if (test_bit(SMP_FLAG_CT2, &smp->flags)) { /* SALT = 0x000000000000000000000000746D7032 */ const u8 salt[16] = { 0x32, 0x70, 0x6d, 0x74 };
if (smp_h7(smp->tfm_cmac, key->val, salt, smp->tk)) return;
} else { /* From core spec. Spells out in ASCII as 'tmp2'. */ const u8 tmp2[4] = { 0x32, 0x70, 0x6d, 0x74 };
if (smp_h6(smp->tfm_cmac, key->val, tmp2, smp->tk)) return;
}
if (smp_h6(smp->tfm_cmac, smp->tk, brle, smp->tk)) return;
/* The responder sends its keys first */ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags) &&
(smp->remote_key_dist & KEY_DIST_MASK)) {
smp_allow_key_dist(smp); return;
}
/* Make sure we generate only the significant amount of * bytes based on the encryption key size, and set the rest * of the value to zeroes.
*/
get_random_bytes(enc.ltk, smp->enc_key_size);
memset(enc.ltk + smp->enc_key_size, 0, sizeof(enc.ltk) - smp->enc_key_size);
/* The hci_conn contains the local identity address * after the connection has been established. * * This is true even when the connection has been * established using a resolvable random address.
*/
bacpy(&addrinfo.bdaddr, &hcon->src);
addrinfo.addr_type = hcon->src_type;
/* Ignore the PDU if we've already done 20 rounds (0 - 19) */ if (smp->passkey_round >= 20) return 0;
switch (smp_op) { case SMP_CMD_PAIRING_RANDOM:
r = ((hcon->passkey_notify >> smp->passkey_round) & 0x01);
r |= 0x80;
if (smp_f4(smp->tfm_cmac, smp->remote_pk, smp->local_pk,
smp->rrnd, r, cfm)) return SMP_UNSPECIFIED;
if (crypto_memneq(smp->pcnf, cfm, 16)) return SMP_CONFIRM_FAILED;
smp->passkey_round++;
if (smp->passkey_round == 20) { /* Generate MacKey and LTK */ if (sc_mackey_and_ltk(smp, smp->mackey, smp->tk)) return SMP_UNSPECIFIED;
}
/* The round is only complete when the initiator * receives pairing random.
*/ if (!test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd), smp->prnd); if (smp->passkey_round == 20)
SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK); else
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM); return 0;
}
/* Start the next round */ if (smp->passkey_round != 20) return sc_passkey_round(smp, 0);
switch (mgmt_op) { case MGMT_OP_USER_PASSKEY_REPLY:
value = le32_to_cpu(passkey);
memset(smp->tk, 0, sizeof(smp->tk));
bt_dev_dbg(conn->hcon->hdev, "PassKey: %u", value);
put_unaligned_le32(value, smp->tk);
fallthrough; case MGMT_OP_USER_CONFIRM_REPLY:
set_bit(SMP_FLAG_TK_VALID, &smp->flags); break; case MGMT_OP_USER_PASSKEY_NEG_REPLY: case MGMT_OP_USER_CONFIRM_NEG_REPLY:
smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED);
err = 0; goto unlock; default:
smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED);
err = -EOPNOTSUPP; goto unlock;
}
err = 0;
/* If it is our turn to send Pairing Confirm, do so now */ if (test_bit(SMP_FLAG_CFM_PENDING, &smp->flags)) {
u8 rsp = smp_confirm(smp); if (rsp)
smp_failure(conn, rsp);
}
/* If the remote side's OOB flag is set it means it has * successfully received our local OOB data - therefore set the * flag to indicate that local OOB is in use.
*/ if (req->oob_flag == SMP_OOB_PRESENT && SMP_DEV(hdev)->local_oob)
set_bit(SMP_FLAG_LOCAL_OOB, &smp->flags);
/* SMP over BR/EDR requires special treatment */ if (conn->hcon->type == ACL_LINK) { /* We must have a BR/EDR SC link */ if (!test_bit(HCI_CONN_AES_CCM, &conn->hcon->flags) &&
!hci_dev_test_flag(hdev, HCI_FORCE_BREDR_SMP)) return SMP_CROSS_TRANSP_NOT_ALLOWED;
set_bit(SMP_FLAG_SC, &smp->flags);
build_bredr_pairing_cmd(smp, req, &rsp);
if (req->auth_req & SMP_AUTH_CT2)
set_bit(SMP_FLAG_CT2, &smp->flags);
key_size = min(req->max_key_size, rsp.max_key_size); if (check_enc_key_size(conn, key_size)) return SMP_ENC_KEY_SIZE;
/* Clear bits which are generated but not distributed */
smp->remote_key_dist &= ~SMP_SC_NO_DIST;
/* Strictly speaking we shouldn't allow Pairing Confirm for the * SC case, however some implementations incorrectly copy RFU auth * req bits from our security request, which may create a false * positive SC enablement.
*/
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
if (test_bit(SMP_FLAG_SC, &smp->flags)) {
SMP_ALLOW_CMD(smp, SMP_CMD_PUBLIC_KEY); /* Clear bits which are generated but not distributed */
smp->remote_key_dist &= ~SMP_SC_NO_DIST; /* Wait for Public Key from Initiating Device */ return 0;
}
/* Request setup of TK */
ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability); if (ret) return SMP_UNSPECIFIED;
if (smp_dev->debug_key)
set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags);
goto done;
}
if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS)) {
bt_dev_dbg(hdev, "Using debug keys"); if (set_ecdh_privkey(smp->tfm_ecdh, debug_sk)) return SMP_UNSPECIFIED;
memcpy(smp->local_pk, debug_pk, 64);
set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags);
} else { while (true) { /* Generate key pair for Secure Connections */ if (generate_ecdh_keys(smp->tfm_ecdh, smp->local_pk)) return SMP_UNSPECIFIED;
/* This is unlikely, but we need to check that * we didn't accidentally generate a debug key.
*/ if (crypto_memneq(smp->local_pk, debug_pk, 64)) break;
}
}
done:
SMP_DBG("Local Public Key X: %32phN", smp->local_pk);
SMP_DBG("Local Public Key Y: %32phN", smp->local_pk + 32);
if (skb->len < sizeof(*rsp)) return SMP_INVALID_PARAMS;
if (!test_bit(SMP_FLAG_INITIATOR, &smp->flags)) return SMP_CMD_NOTSUPP;
skb_pull(skb, sizeof(*rsp));
req = (void *) &smp->preq[1];
key_size = min(req->max_key_size, rsp->max_key_size); if (check_enc_key_size(conn, key_size)) return SMP_ENC_KEY_SIZE;
auth = rsp->auth_req & AUTH_REQ_MASK(hdev);
if (hci_dev_test_flag(hdev, HCI_SC_ONLY) && !(auth & SMP_AUTH_SC)) return SMP_AUTH_REQUIREMENTS;
/* If the remote side's OOB flag is set it means it has * successfully received our local OOB data - therefore set the * flag to indicate that local OOB is in use.
*/ if (rsp->oob_flag == SMP_OOB_PRESENT && SMP_DEV(hdev)->local_oob)
set_bit(SMP_FLAG_LOCAL_OOB, &smp->flags);
/* Update remote key distribution in case the remote cleared * some bits that we had enabled in our request.
*/
smp->remote_key_dist &= rsp->resp_key_dist;
if ((req->auth_req & SMP_AUTH_CT2) && (auth & SMP_AUTH_CT2))
set_bit(SMP_FLAG_CT2, &smp->flags);
/* For BR/EDR this means we're done and can start phase 3 */ if (conn->hcon->type == ACL_LINK) { /* Clear bits which are generated but not distributed */
smp->remote_key_dist &= ~SMP_SC_NO_DIST;
smp_distribute_keys(smp); return 0;
}
/* Update remote key distribution in case the remote cleared * some bits that we had enabled in our request.
*/
smp->remote_key_dist &= rsp->resp_key_dist;
if (test_bit(SMP_FLAG_SC, &smp->flags)) { /* Clear bits which are generated but not distributed */
smp->remote_key_dist &= ~SMP_SC_NO_DIST;
SMP_ALLOW_CMD(smp, SMP_CMD_PUBLIC_KEY); return sc_send_public_key(smp);
}
auth |= req->auth_req;
ret = tk_request(conn, 0, auth, req->io_capability, rsp->io_capability); if (ret) return SMP_UNSPECIFIED;
set_bit(SMP_FLAG_CFM_PENDING, &smp->flags);
/* Can't compose response until we have been confirmed */ if (test_bit(SMP_FLAG_TK_VALID, &smp->flags)) return smp_confirm(smp);
/* Work-around for some implementations that incorrectly copy RFU bits * from our security request and thereby create the impression that * we're doing SC when in fact the remote doesn't support it.
*/ staticint fixup_sc_false_positive(struct smp_chan *smp)
{ struct l2cap_conn *conn = smp->conn; struct hci_conn *hcon = conn->hcon; struct hci_dev *hdev = hcon->hdev; struct smp_cmd_pairing *req, *rsp;
u8 auth;
/* The issue is only observed when we're in responder role */ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) return SMP_UNSPECIFIED;
if (hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
bt_dev_err(hdev, "refusing legacy fallback in SC-only mode"); return SMP_UNSPECIFIED;
}
bt_dev_err(hdev, "trying to fall back to legacy SMP");
/* Rebuild key dist flags which may have been cleared for SC */
smp->remote_key_dist = (req->init_key_dist & rsp->resp_key_dist);
auth = req->auth_req & AUTH_REQ_MASK(hdev);
if (tk_request(conn, 0, auth, rsp->io_capability, req->io_capability)) {
bt_dev_err(hdev, "failed to fall back to legacy SMP"); return SMP_UNSPECIFIED;
}
/* Only Just-Works pairing requires extra checks */ if (smp->method != JUST_WORKS) goto mackey_and_ltk;
/* If there already exists long term key in local host, leave * the decision to user space since the remote device could * be legitimate or malicious.
*/ if (hci_find_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
hcon->role)) { /* Set passkey to 0. The value can be any number since * it'll be ignored anyway.
*/
passkey = 0;
confirm_hint = 1; goto confirm;
}
}
mackey_and_ltk: /* Generate MacKey and LTK */
err = sc_mackey_and_ltk(smp, smp->mackey, smp->tk); if (err) return SMP_UNSPECIFIED;
if (smp->method == REQ_OOB) { if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
sc_dhkey_check(smp);
SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
} return 0;
}
/* If we're encrypted with an STK but the caller prefers using * LTK claim insufficient security. This way we allow the * connection to be re-encrypted with an LTK, even if the LTK * provides the same level of security. Only exception is if we * don't have an LTK (e.g. because of key distribution bits).
*/ if (key_pref == SMP_USE_LTK &&
test_bit(HCI_CONN_STK_ENCRYPT, &hcon->flags) &&
hci_find_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, hcon->role)) returnfalse;
if (smp_sufficient_security(hcon, sec_level, SMP_USE_LTK)) { /* If link is already encrypted with sufficient security we * still need refresh encryption as per Core Spec 5.0 Vol 3, * Part H 2.4.6
*/
smp_ltk_encrypt(conn, hcon->sec_level); return 0;
}
if (sec_level > hcon->pending_sec_level)
hcon->pending_sec_level = sec_level;
if (smp_ltk_encrypt(conn, hcon->pending_sec_level)) return 0;
smp = smp_chan_create(conn); if (!smp) return SMP_UNSPECIFIED;
if (!hci_dev_test_flag(hdev, HCI_BONDABLE) &&
(auth & SMP_AUTH_BONDING)) return SMP_PAIRING_NOTSUPP;
/* This may be NULL if there's an unexpected disconnection */ if (!conn) return 1;
if (!hci_dev_test_flag(hcon->hdev, HCI_LE_ENABLED)) return 1;
if (smp_sufficient_security(hcon, sec_level, SMP_USE_LTK)) return 1;
if (sec_level > hcon->pending_sec_level)
hcon->pending_sec_level = sec_level;
if (hcon->role == HCI_ROLE_MASTER) if (smp_ltk_encrypt(conn, hcon->pending_sec_level)) return 0;
chan = conn->smp; if (!chan) {
bt_dev_err(hcon->hdev, "security requested but not available"); return 1;
}
l2cap_chan_lock(chan);
/* If SMP is already in progress ignore this request */ if (chan->data) {
ret = 0; goto unlock;
}
smp = smp_chan_create(conn); if (!smp) {
ret = 1; goto unlock;
}
authreq = seclevel_to_authreq(sec_level);
if (hci_dev_test_flag(hcon->hdev, HCI_SC_ENABLED)) {
authreq |= SMP_AUTH_SC; if (hci_dev_test_flag(hcon->hdev, HCI_SSP_ENABLED))
authreq |= SMP_AUTH_CT2;
}
/* Don't attempt to set MITM if setting is overridden by debugfs * Needed to pass certification test SM/MAS/PKE/BV-01-C
*/ if (!hci_dev_test_flag(hcon->hdev, HCI_FORCE_NO_MITM)) { /* Require MITM if IO Capability allows or the security level * requires it.
*/ if (hcon->io_capability != HCI_IO_NO_INPUT_OUTPUT ||
hcon->pending_sec_level > BT_SECURITY_MEDIUM)
authreq |= SMP_AUTH_MITM;
}
if (hcon->role == HCI_ROLE_MASTER)
smp_send_pairing_req(smp, authreq); else
smp_send_security_req(smp, authreq);
hcon = hci_conn_hash_lookup_le(hdev, bdaddr, addr_type); if (!hcon) goto done;
conn = hcon->l2cap_data; if (!conn) goto done;
chan = conn->smp; if (!chan) goto done;
l2cap_chan_lock(chan);
smp = chan->data; if (smp) { /* Set keys to NULL to make sure smp_failure() does not try to
* remove and free already invalidated rcu list entries. */
smp->ltk = NULL;
smp->responder_ltk = NULL;
smp->remote_irk = NULL;
if (skb->len < sizeof(*rp)) return SMP_INVALID_PARAMS;
/* Pairing is aborted if any blocked keys are distributed */ if (hci_is_blocked_key(conn->hcon->hdev, HCI_BLOCKED_KEY_TYPE_LTK,
rp->ltk)) {
bt_dev_warn_ratelimited(conn->hcon->hdev, "LTK blocked for %pMR",
&conn->hcon->dst); return SMP_INVALID_PARAMS;
}
if (skb->len < sizeof(*info)) return SMP_INVALID_PARAMS;
/* Pairing is aborted if any blocked keys are distributed */ if (hci_is_blocked_key(conn->hcon->hdev, HCI_BLOCKED_KEY_TYPE_IRK,
info->irk)) {
bt_dev_warn_ratelimited(conn->hcon->hdev, "Identity key blocked for %pMR",
&conn->hcon->dst); return SMP_INVALID_PARAMS;
}
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.32Angebot
Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.