From 6e7502a297204a6acb375ea4ad8f35d5658634db Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Thu, 12 Nov 2020 10:13:26 +0100 Subject: Add SMPPairingState and PairingMode mapping: getBestPairingMode(SMPAuthReqs, SMPIOCapability, SMPOOBDataFlag), getComplyingPairingModes(SMPAuthReqs) --- api/direct_bt/SMPTypes.hpp | 74 ++++++++++++++++++++++++++++++++++++++++++++++ src/direct_bt/SMPTypes.cpp | 74 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+) diff --git a/api/direct_bt/SMPTypes.hpp b/api/direct_bt/SMPTypes.hpp index 87bb8c4f..a91be5a2 100644 --- a/api/direct_bt/SMPTypes.hpp +++ b/api/direct_bt/SMPTypes.hpp @@ -36,6 +36,7 @@ #include #include "OctetTypes.hpp" +#include "BTTypes.hpp" /** * - - - - - - - - - - - - - - - @@ -90,6 +91,59 @@ namespace direct_bt { } + /** + * SMP Pairing Process state definition + *
+     * Vol 3, Part H (SM): APPENDIX C MESSAGE SEQUENCE CHARTS
+     * 
+ * @see PairingMode + */ + enum class SMPPairingState : uint8_t { + /** No pairing in process. Current PairingMode shall be PairingMode::NONE. */ + NONE = 0, + + /** Pairing failed. Current PairingMode shall be PairingMode::NONE. */ + FAILED = 1, + + /** + * Phase 0: Pairing requested by responding (slave) device via SMPSecurityReqMsg.
+ * Signals initiating (host) device to start the Pairing Feature Exchange.
+ * Current PairingMode shall be PairingMode::NEGOTIATING. + */ + REQUESTED_BY_RESPONDER = 2, + + /** + * Phase 1: Pairing requested by initiating (master) device via SMPPairingMsg.
+ * Starts the Pairing Feature Exchange.
+ * Current PairingMode shall be PairingMode::NEGOTIATING. + */ + FEATURE_EXCHANGE_STARTED = 3, + + /** + * Phase 1: Pairing responded by responding (slave) device via SMPPairingMsg.
+ * Completes the Pairing Feature Exchange. Optional user input shall be given for Phase 2.
+ * Current PairingMode shall be set to a definitive value. + */ + FEATURE_EXCHANGE_COMPLETED = 4, + + /** Phase 2: Authentication (MITM) PASSKEY expected, see PairingMode::PASSKEY_ENTRY */ + PASSKEY_EXPECTED = 5, + /** Phase 2: Authentication (MITM) Numeric Comparison Reply expected, see PairingMode::NUMERIC_COMPARISON */ + NUMERIC_REPLY_EXPECTED = 6, + /** Phase 2: Authentication (MITM) OOB data expected, see PairingMode::OUT_OF_BAND */ + OOB_EXPECTED = 7, + + /** Phase 2: Pairing process started by SMPPairConfirmMsg or SMPPairPubKeyMsg (LE Secure Connection) exchange between initiating (master) and responding (slave) device. */ + PROCESS_STARTED = 8, + + /** + * Phase 2: Pairing process is completed by responding (slave) device sending SMPPairRandMsg.
+ * The link is assumed to be encrypted from here on. + */ + PROCESS_COMPLETED = 9 + }; + std::string getSMPPairingStateString(const SMPPairingState state) noexcept; + /** * Vol 3, Part H, 2.3.2 IO capabilities */ @@ -220,6 +274,26 @@ namespace direct_bt { std::string getSMPAuthReqBitString(const SMPAuthReqs bit) noexcept; std::string getSMPAuthReqMaskString(const SMPAuthReqs mask) noexcept; + /** + * Returns the PairingMode derived from the given SMPAuthReqs + *
+     * BT Core Spec v5.2: Vol 3, Part H (SM): 2.3.1 Security Properties
+     * BT Core Spec v5.2: Vol 3, Part H (SM): 2.3.5.1 Selecting key generation method
+     * BT Core Spec v5.2: Vol 3, Part H (SM): 2.3.5.6.2 Authentication stage 1 – Just Works or Numeric Comparison
+     * BT Core Spec v5.2: Vol 3, Part H (SM): 2.3.5.6.3 Authentication stage 1 – Passkey Entry
+     * BT Core Spec v5.2: Vol 3, Part H (SM): 2.3.5.6.4 Authentication stage 1 – Out of Band
+     * 
+ */ + PairingMode getBestPairingMode(const SMPAuthReqs mask, const SMPIOCapability ioCap, const SMPOOBDataFlag oobFlag) noexcept; + + /** + * Returns a list of complying PairingMode derived from the given SMPAuthReqs + *
+     * BT Core Spec v5.2: Vol 3, Part H (SM): 2.3.1 Security Properties
+     * 
+ */ + std::vector getComplyingPairingModes(const SMPAuthReqs mask) noexcept; + /** * Handles the Security Manager Protocol (SMP) using Protocol Data Unit (PDU) * encoded messages over L2CAP channel. diff --git a/src/direct_bt/SMPTypes.cpp b/src/direct_bt/SMPTypes.cpp index 0984bc40..a8a859e9 100644 --- a/src/direct_bt/SMPTypes.cpp +++ b/src/direct_bt/SMPTypes.cpp @@ -36,6 +36,29 @@ using namespace direct_bt; +#define PAIRSTATE_ENUM(X) \ + X(NONE) \ + X(FAILED) \ + X(REQUESTED_BY_RESPONDER) \ + X(FEATURE_EXCHANGE_STARTED) \ + X(FEATURE_EXCHANGE_COMPLETED) \ + X(PASSKEY_EXPECTED) \ + X(NUMERIC_REPLY_EXPECTED) \ + X(OOB_EXPECTED) \ + X(PROCESS_STARTED) \ + X(PROCESS_COMPLETED) + +#define CASE_TO_STRING_PAIRSTATE(V) case SMPPairingState::V: return #V; + +std::string direct_bt::getSMPPairingStateString(const SMPPairingState state) noexcept { + switch(state) { + PAIRSTATE_ENUM(CASE_TO_STRING_PAIRSTATE) + default: ; // fall through intended + } + return "Unknown SMP PairingState"; +} + + #define AUTHREQ_ENUM(X) \ X(NONE) \ X(BONDING) \ @@ -73,6 +96,57 @@ std::string direct_bt::getSMPAuthReqMaskString(const SMPAuthReqs mask) noexcept return out; } +PairingMode direct_bt::getBestPairingMode(const SMPAuthReqs mask, const SMPIOCapability ioCap, const SMPOOBDataFlag oobFlag) noexcept { + // BT Core Spec v5.2: Vol 3, Part H (SM): 2.3.1 Security Properties + // BT Core Spec v5.2: Vol 3, Part H (SM): 2.3.5.1 Selecting key generation method Table 2.6 + + // Authenticated MITM + if( SMPAuthReqs::NONE != ( mask & SMPAuthReqs::MITM ) ) { + // One of: + // - PairingMode::PASSKEY_ENTRY best + // - PairingMode::NUMERIC_COMPARISON good + // - PairingMode::OUT_OF_BAND good, depending on the OOB data + if( SMPOOBDataFlag::OOB_AUTH_DATA_REMOTE_PRESENT == oobFlag ) { + return PairingMode::OUT_OF_BAND; + } + switch( ioCap ) { + case SMPIOCapability::KEYBOARD_DISPLAY: + return PairingMode::PASSKEY_ENTRY; + + case SMPIOCapability::DISPLAY_YES_NO: + return PairingMode::NUMERIC_COMPARISON; + + case SMPIOCapability::DISPLAY_ONLY: + [[fallthrough]]; + case SMPIOCapability::KEYBOARD_ONLY: + [[fallthrough]]; + case SMPIOCapability::NO_INPUT_NO_OUTPUT: + [[fallthrough]]; + default: + // impossible to comply + return PairingMode::NONE; + } + } + // Unauthenticated pairing + return PairingMode::JUST_WORKS; +} + +std::vector direct_bt::getComplyingPairingModes(const SMPAuthReqs mask) noexcept { + // BT Core Spec v5.2: Vol 3, Part H (SM): 2.3.1 Security Properties + // BT Core Spec v5.2: Vol 3, Part H (SM): 2.3.5.1 Selecting key generation method Table 2.6 + std::vector res; + + // Authenticated MITM + if( SMPAuthReqs::NONE != ( mask & SMPAuthReqs::MITM ) ) { + res.push_back(PairingMode::PASSKEY_ENTRY); + res.push_back(PairingMode::NUMERIC_COMPARISON); + res.push_back(PairingMode::OUT_OF_BAND); + return res; + } + // Unauthenticated pairing + res.push_back(PairingMode::JUST_WORKS); + return res; +} #define OPCODE_ENUM(X) \ X(UNDEFINED) \ -- cgit v1.2.3