Direct-BT v3.3.0-1-gc2d430c
Direct-BT - Direct Bluetooth Programming.
SMPTypes.hpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2020 Gothel Software e.K.
4 * Copyright (c) 2020 ZAFENA AB
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26#ifndef SMP_TYPES_HPP_
27#define SMP_TYPES_HPP_
28
29#include <cstring>
30#include <string>
31#include <cstdint>
32#include <cmath>
33
34#include <algorithm>
35#include <mutex>
36
37#include <jau/basic_types.hpp>
38#include <jau/octets.hpp>
39
40#include "BTTypes0.hpp"
41
42/**
43 * - - - - - - - - - - - - - - -
44 *
45 * SMPTypes.hpp Module for SMPPDUMsg Types, SMPAuthReqs etc:
46 *
47 * - BT Core Spec v5.2: Vol 3, Part H Security Manager Specification (SM): 2 Security Manager (SM)
48 * - BT Core Spec v5.2: Vol 3, Part H Security Manager Specification (SM): 3 Security Manager Protocol (SMP)
49 *
50 */
51namespace direct_bt {
52
53 /** \addtogroup DBTSystemAPI
54 *
55 * @{
56 */
57
59 protected:
60 SMPException(std::string type, std::string const& m, const char* file, int line) noexcept
61 : RuntimeException(std::move(type), m, file, line) {}
62
63 public:
64 SMPException(std::string const& m, const char* file, int line) noexcept
65 : RuntimeException("HCIException", m, file, line) {}
66 };
67
69 public:
70 SMPPacketException(std::string const& m, const char* file, int line) noexcept
71 : SMPException("SMPPacketException", m, file, line) {}
72 };
74 public:
75 SMPOpcodeException(std::string const& m, const char* file, int line) noexcept
76 : SMPException("SMPOpcodeException", m, file, line) {}
77 };
78
80 public:
81 SMPValueException(std::string const& m, const char* file, int line) noexcept
82 : SMPException("SMPValueException", m, file, line) {}
83 };
84
85 enum class SMPConstInt : int32_t {
86 };
87 constexpr int32_t number(const SMPConstInt rhs) noexcept {
88 return static_cast<int>(rhs);
89 }
90
91 enum class SMPConstU16 : uint16_t {
92 /** SMP Timeout Vol 3, Part H (SM): 3.4 */
93 SMP_TIMEOUT_MS = 30000
94 };
95 constexpr uint16_t number(const SMPConstU16 rhs) noexcept {
96 return static_cast<uint16_t>(rhs);
97 }
98
99
100 /**
101 * SMP Pairing Process state definition
102 * <pre>
103 * Vol 3, Part H (SM): APPENDIX C MESSAGE SEQUENCE CHARTS
104 * </pre>
105 * @see PairingMode
106 */
107 enum class SMPPairingState : uint8_t {
108 /** No pairing in process. Current PairingMode shall be PairingMode::NONE. */
109 NONE = 0,
110
111 /** Pairing failed. Current PairingMode shall be PairingMode::NONE. */
112 FAILED = 1,
113
114 /**
115 * Phase 0: Pairing requested by responding (slave) device via SMPSecurityReqMsg.<br>
116 * Signals initiating (host) device to start the Pairing Feature Exchange.<br>
117 * Current PairingMode shall be PairingMode::NEGOTIATING.
118 */
120
121 /**
122 * Phase 1: Pairing requested by initiating (master) device via SMPPairingMsg.<br>
123 * Starts the Pairing Feature Exchange.<br>
124 * Current PairingMode shall be PairingMode::NEGOTIATING.
125 */
127
128 /**
129 * Phase 1: Pairing responded by responding (slave) device via SMPPairingMsg.<br>
130 * Completes the Pairing Feature Exchange. Optional user input shall be given for Phase 2.<br>
131 * Current PairingMode shall be set to a definitive value.
132 */
134
135 /** Phase 2: Authentication (MITM) PASSKEY expected now, see PairingMode::PASSKEY_ENTRY_ini */
137 /** Phase 2: Authentication (MITM) Numeric Comparison Reply expected now, see PairingMode::NUMERIC_COMPARE_ini */
139 /**
140 * Phase 2: Authentication (MITM) PASSKEY (produced by this responder adapter, acting as peripheral GATT server) and shall be displayed for the initiating remote device, see PairingMode::PASSKEY_ENTRY_ini.<br>
141 * User application shall display BTDevice::getResponderSMPPassKeyString().
142 */
143 PASSKEY_NOTIFY = 7,
144 /** Phase 2: Authentication (MITM) OOB data expected now, see PairingMode::OUT_OF_BAND */
145 OOB_EXPECTED = 8,
146
147 /** Phase 3: Key & value distribution started after SMPPairConfirmMsg or SMPPairPubKeyMsg (LE Secure Connection) exchange between initiating (master) and responding (slave) device. */
149
150 /**
151 * Phase 3: Key & value distribution completed by responding (slave) device sending SMPIdentInfoMsg (#1) , SMPIdentAddrInfoMsg (#2) or SMPSignInfoMsg (#3),<br>
152 * depending on the key distribution field SMPKeyDistFormat SMPPairingMsg::getInitKeyDist() and SMPPairingMsg::getRespKeyDist().<br>
153 * <p>
154 * The link is assumed to be encrypted from here on and AdapterStatusListener::deviceReady() gets called on all listener.
155 * </p>
156 */
157 COMPLETED = 10
158 };
159 std::string to_string(const SMPPairingState state) noexcept;
160
161 /** Returns given passKey ranging [0..999999] as a canonical string, e.g. '012345'. */
162 std::string toPassKeyString(const std::uint32_t passKey) noexcept;
163
164 /**
165 * Returns true if the given SMPPairingState indicates an active pairing process,
166 * i.e. none of the following terminal states: ::SMPPairingState::COMPLETED, ::SMPPairingState::FAILED or ::SMPPairingState::NONE
167 */
168 constexpr bool isSMPPairingActive(const SMPPairingState state) noexcept {
169 return SMPPairingState::COMPLETED != state &&
170 SMPPairingState::FAILED != state &&
171 SMPPairingState::NONE != state;
172 }
173
174 /**
175 * Returns true if the given SMPPairingState indicates a finished pairing process,
176 * i.e. one of the following terminal states: ::SMPPairingState::COMPLETED or ::SMPPairingState::FAILED
177 */
178 constexpr bool hasSMPPairingFinished(const SMPPairingState state) noexcept {
179 return SMPPairingState::COMPLETED == state ||
181 }
182
183 /**
184 * Returns true if the given SMPPairingState indicates expected user interaction,
185 * i.e. one of the following states: ::SMPPairingState::PASSKEY_EXPECTED, ::SMPPairingState::NUMERIC_COMPARE_EXPECTED or ::SMPPairingState::OOB_EXPECTED
186 */
187 constexpr bool isSMPPairingUserInteraction(const SMPPairingState state) noexcept {
188 return SMPPairingState::PASSKEY_EXPECTED == state ||
191 }
192
193 /**
194 * Returns true if the given SMPPairingState indicates a pairing process waiting for user input,
195 * i.e. one of the following terminal states: ::SMPPairingState::FEATURE_EXCHANGE_STARTED,
196 * ::SMPPairingState::FEATURE_EXCHANGE_COMPLETED or the given `inputSpec`.
197 *
198 * @param inputSpec should be one of ::SMPPairingState::PASSKEY_EXPECTED, ::SMPPairingState::NUMERIC_COMPARE_EXPECTED or ::SMPPairingState::OOB_EXPECTED.
199 */
200 constexpr bool isSMPPairingAllowingInput(const SMPPairingState state, const SMPPairingState inputSpec) noexcept {
203 inputSpec == state;
204 }
205
206 /**
207 * Vol 3, Part H, 2.3.2 IO capabilities
208 */
209 enum class SMPIOCapability : uint8_t {
210 /** Display output only, value 0. */
211 DISPLAY_ONLY = 0x00,
212 /** Display output and boolean confirmation input keys only, value 1. */
213 DISPLAY_YES_NO = 0x01,
214 /** Keyboard input only, value 2. */
215 KEYBOARD_ONLY = 0x02,
216 /** No input not output, value 3. */
217 NO_INPUT_NO_OUTPUT = 0x03,
218 /** Display output and keyboard input, value 4. */
219 KEYBOARD_DISPLAY = 0x04,
220 /** Denoting unset value, i.e. not defined. */
221 UNSET = 0xFF,
222 };
223 constexpr SMPIOCapability to_SMPIOCapability(const uint8_t v) noexcept {
224 if( v <= 4 ) {
225 return static_cast<SMPIOCapability>(v);
226 }
228 }
229 constexpr uint8_t number(const SMPIOCapability rhs) noexcept {
230 return static_cast<uint8_t>(rhs);
231 }
232 std::string to_string(const SMPIOCapability ioc) noexcept;
233 constexpr bool hasSMPIOCapabilityAnyIO(const SMPIOCapability ioc) noexcept {
234 return ioc == SMPIOCapability::DISPLAY_ONLY ||
238 }
239 constexpr bool hasSMPIOCapabilityBinaryInput(const SMPIOCapability ioc) noexcept {
240 return ioc == SMPIOCapability::DISPLAY_YES_NO ||
243 }
244 constexpr bool hasSMPIOCapabilityFullInput(const SMPIOCapability ioc) noexcept {
245 return ioc == SMPIOCapability::KEYBOARD_ONLY ||
247 }
248
249 /**
250 * Vol 3, Part H, 2.3.3 OOB authentication data
251 *
252 */
253 enum class SMPOOBDataFlag : uint8_t {
254 OOB_AUTH_DATA_NOT_PRESENT = 0x00,/**< OOB_AUTH_DATA_NOT_PRESENT */
255 OOB_AUTH_DATA_REMOTE_PRESENT = 0x01 /**< OOB_AUTH_DATA_REMOTE_PRESENT */
256 };
257 constexpr uint8_t number(const SMPOOBDataFlag rhs) noexcept {
258 return static_cast<uint8_t>(rhs);
259 }
260 std::string to_string(const SMPOOBDataFlag v) noexcept;
261
262 /**
263 * SMP Authentication Requirements Bits, denotes specific bits or whole protocol uint8_t bit-mask.
264 * <pre>
265 * BT Core Spec v5.2: Vol 3, Part H (SM): 3.5.1 SMP Pairing Request
266 * BT Core Spec v5.2: Vol 3, Part H (SM): 3.5.2 SMP Pairing Response
267 * BT Core Spec v5.2: Vol 3, Part H (SM): 3.6.7 SMP Security Request
268 *
269 * BT Core Spec v5.2: Vol 1, Part A, 5.4 LE SECURITY
270 * BT Core Spec v5.2: Vol 3, Part H (SM): 2.3.1 Security Properties
271 * BT Core Spec v5.2: Vol 3, Part H (SM): 2.3.5.1 Selecting key generation method
272 * BT Core Spec v5.2: Vol 3, Part H (SM): 2.3.5.6.2 Authentication stage 1 – Just Works or Numeric Comparison
273 * BT Core Spec v5.2: Vol 3, Part H (SM): 2.3.5.6.3 Authentication stage 1 – Passkey Entry
274 * BT Core Spec v5.2: Vol 3, Part H (SM): 2.3.5.6.4 Authentication stage 1 – Out of Band
275 *
276 * </pre>
277 *
278 * Layout LSB -> MSB
279 * <pre>
280 * uint8_t bonding_flags : 2, mitm : 1, sc : 1, keypress : 1, ct2 : 1, rfu : 2;
281 * </pre>
282 */
283 enum class SMPAuthReqs : uint8_t {
284 NONE = 0,
285 /**
286 * Indicate bonding being requested by the initiating device.
287 */
288 BONDING = 0b00000001,
289 /** Reserved for future use */
290 BONDING_RFU = 0b00000010,
291 /**
292 * A device sets the MITM flag to one to request an Authenticated security property
293 * for the STK when using LE legacy pairing
294 * and the LTK when using LE Secure Connections.
295 * <p>
296 * MITM protection can be secured by the following authenticated PairingMode
297 * <pre>
298 * - PairingMode::PASSKEY_ENTRY best
299 * - PairingMode::NUMERIC_COMPARISON good
300 * - PairingMode::OUT_OF_BAND good, depending on the OOB data
301 * </pre>
302 * </p>
303 * <p>
304 * Unauthenticated PairingMode::JUST_WORKS gives no MITM protection.
305 * </p>
306 * BT Core Spec v5.2: Vol 3, Part H (SM): 2.3.1 Security Properties
307 */
308 MITM = 0b00000100,
309 /**
310 * If LE Secure Connections pairing is supported by
311 * the device, then the SC field shall be set to 1, otherwise it shall be set to 0.
312 * If both devices support LE Secure Connections pairing,
313 * then LE Secure Connections pairing shall be used,
314 * otherwise LE Legacy pairing shall be used.
315 */
316 SECURE_CONNECTIONS = 0b00001000,
317 /**
318 * The keypress field is used only in the Passkey Entry
319 * protocol and shall be ignored in other protocols.
320 * When both sides set that field to one,
321 * Keypress notifications shall be generated and sent using SMP
322 * Pairing Keypress Notification PDUs.
323 */
324 KEYPRESS = 0b00010000,
325 /**
326 * The CT2 field shall be set to 1 upon transmission to indicate
327 * support for the h7 function.
328 * <pre>
329 * See sections:
330 * - 2.4.2.4 Derivation of BR/EDR link key from LE LTK
331 * - 2.4.2.5 Derivation of LE LTK from BR/EDR link key
332 * </pre>
333 */
334 CT2_H7_FUNC_SUPPORT = 0b00100000,
335 /** Reserved for future use */
336 RFU_1 = 0b01000000,
337 /** Reserved for future use */
338 RFU_2 = 0b10000000
339 };
340 constexpr SMPAuthReqs operator ^(const SMPAuthReqs lhs, const SMPAuthReqs rhs) noexcept {
341 return static_cast<SMPAuthReqs> ( static_cast<uint8_t>(lhs) ^ static_cast<uint8_t>(rhs) );
342 }
343 constexpr SMPAuthReqs operator |(const SMPAuthReqs lhs, const SMPAuthReqs rhs) noexcept {
344 return static_cast<SMPAuthReqs> ( static_cast<uint8_t>(lhs) | static_cast<uint8_t>(rhs) );
345 }
346 constexpr SMPAuthReqs operator &(const SMPAuthReqs lhs, const SMPAuthReqs rhs) noexcept {
347 return static_cast<SMPAuthReqs> ( static_cast<uint8_t>(lhs) & static_cast<uint8_t>(rhs) );
348 }
349 constexpr bool operator ==(const SMPAuthReqs lhs, const SMPAuthReqs rhs) noexcept {
350 return static_cast<uint8_t>(lhs) == static_cast<uint8_t>(rhs);
351 }
352 constexpr bool operator !=(const SMPAuthReqs lhs, const SMPAuthReqs rhs) noexcept {
353 return !( lhs == rhs );
354 }
355 constexpr uint8_t number(const SMPAuthReqs rhs) noexcept {
356 return static_cast<uint8_t>(rhs);
357 }
358 constexpr bool is_set(const SMPAuthReqs mask, const SMPAuthReqs bit) noexcept {
359 return bit == ( mask & bit );
360 }
361 std::string to_string(const SMPAuthReqs mask) noexcept;
362
363 /**
364 * Returns the PairingMode derived from both devices' sets of SMPAuthReqs, SMPIOCapability and SMPOOBDataFlag
365 * <pre>
366 * BT Core Spec v5.2: Vol 3, Part H (SM): 2.3.5.1 Selecting key generation method Table 2.6 (STK, le_sc_all_supported==false)
367 * BT Core Spec v5.2: Vol 3, Part H (SM): 2.3.5.1 Selecting key generation method Table 2.7 (LTK, le_sc_all_supported==true)
368 *
369 * BT Core Spec v5.2: Vol 3, Part H (SM): 2.3.1 Security Properties
370 * BT Core Spec v5.2: Vol 3, Part H (SM): 2.3.5.1 Selecting key generation method
371 * BT Core Spec v5.2: Vol 3, Part H (SM): 2.3.5.6.2 Authentication stage 1 – Just Works or Numeric Comparison
372 * BT Core Spec v5.2: Vol 3, Part H (SM): 2.3.5.6.3 Authentication stage 1 – Passkey Entry
373 * BT Core Spec v5.2: Vol 3, Part H (SM): 2.3.5.6.4 Authentication stage 1 – Out of Band
374 * </pre>
375 *
376 * @param use_sc true if both devices support Secure Connections pairing, otherwise false for legacy pairing.
377 * @param authReqs_ini SMPAuthReqs of initiator
378 * @param ioCap_ini SMPIOCapability of initiator
379 * @param oobFlag_ini SMPOOBDataFlag of initiator
380 * @param authReqs_res SMPAuthReqs of responder
381 * @param ioCap_res SMPIOCapability of responder
382 * @param oobFlag_res SMPOOBDataFlag of responder
383 * @return resulting PairingMode
384 */
385 PairingMode getPairingMode(const bool use_sc,
386 const SMPAuthReqs authReqs_ini, const SMPIOCapability ioCap_ini, const SMPOOBDataFlag oobFlag_ini,
387 const SMPAuthReqs authReqs_res, const SMPIOCapability ioCap_res, const SMPOOBDataFlag oobFlag_res) noexcept;
388
389 /**
390 * Returns the PairingMode derived from both devices' SMPIOCapability
391 * <pre>
392 * BT Core Spec v5.2: Vol 3, Part H (SM): 2.3.5.1 Selecting key generation method Table 2.8
393 * </pre>
394 *
395 * @param use_sc true if both devices support Secure Connections pairing, otherwise false for legacy pairing.
396 * @param ioCap_ini SMPIOCapability of initiator
397 * @param ioCap_res SMPIOCapability of responder
398 * @return resulting PairingMode
399 */
400 PairingMode getPairingMode(const bool use_sc,
401 const SMPIOCapability ioCap_ini, const SMPIOCapability ioCap_res) noexcept;
402
403 /**
404 * SMP Key Type for Distribution, indicates keys distributed in the Transport Specific Key Distribution phase.
405 * <pre>
406 * Field format and usage: Vol 3, Part H, 3.6.1 SMP - LE Security - Key distribution and generation.
407 * See also Vol 3, Part H, 2.4.3 SM - LE Security - Distribution of keys.
408 * </pre>
409 * </p>
410 * Layout LSB -> MSB
411 * <pre>
412 * uint8_t EncKey : 1, IdKey : 1, SignKey : 1, LinkKey : 1, RFU : 4;
413 * </pre>
414 */
415 enum class SMPKeyType : uint8_t {
416 NONE = 0,
417 /**
418 * LE legacy pairing: Indicates device shall distribute LTK using the Encryption Information command,
419 * followed by EDIV and Rand using the Master Identification command.
420 * <p>
421 * LE Secure Connections pairing (SMP on LE transport): Ignored,
422 * EDIV and Rand shall be zero and shall not be distributed.
423 * </p>
424 * <p>
425 * SMP on BR/EDR transport: Indicates device likes to derive LTK from BR/EDR Link Key.<br>
426 * When EncKey is set to 1 by both devices in the initiator and responder Key Distribution / Generation fields,
427 * the procedures for calculating the LTK from the BR/EDR Link Key shall be used.
428 * </p>
429 */
430 ENC_KEY = 0b00000001,
431 /**
432 * Indicates that the device shall distribute IRK using the Identity Information command
433 * followed by its public device or status random address using Identity Address Information.
434 */
435 ID_KEY = 0b00000010,
436 /**
437 * Indicates that the device shall distribute CSRK using the Signing Information command.
438 */
439 SIGN_KEY = 0b00000100,
440 /**
441 * SMP on the LE transport: Indicate that the device would like to derive the Link Key from the LTK.<br>
442 * When LinkKey is set to 1 by both devices in the initiator and responder Key Distribution / Generation fields,
443 * the procedures for calculating the BR/EDR link key from the LTK shall be used.<br>
444 * Devices not supporting LE Secure Connections shall set this bit to zero and ignore it on reception.
445 * <p>
446 * SMP on BR/EDR transport: Reserved for future use.
447 * </p>
448 */
449 LINK_KEY = 0b00001000,
450 /** Reserved for future use */
451 RFU_1 = 0b00010000,
452 /** Reserved for future use */
453 RFU_2 = 0b00100000,
454 /** Reserved for future use */
455 RFU_3 = 0b01000000,
456 /** Reserved for future use */
457 RFU_4 = 0b10000000
458 };
459 constexpr SMPKeyType operator ^(const SMPKeyType lhs, const SMPKeyType rhs) noexcept {
460 return static_cast<SMPKeyType> ( static_cast<uint8_t>(lhs) ^ static_cast<uint8_t>(rhs) );
461 }
462 constexpr SMPKeyType& operator ^=(SMPKeyType& store, const SMPKeyType& rhs) noexcept {
463 store = static_cast<SMPKeyType> ( static_cast<uint8_t>(store) ^ static_cast<uint8_t>(rhs) );
464 return store;
465 }
466 constexpr SMPKeyType operator |(const SMPKeyType lhs, const SMPKeyType rhs) noexcept {
467 return static_cast<SMPKeyType> ( static_cast<uint8_t>(lhs) | static_cast<uint8_t>(rhs) );
468 }
469 constexpr SMPKeyType& operator |=(SMPKeyType& store, const SMPKeyType& rhs) noexcept {
470 store = static_cast<SMPKeyType> ( static_cast<uint8_t>(store) | static_cast<uint8_t>(rhs) );
471 return store;
472 }
473 constexpr SMPKeyType operator &(const SMPKeyType lhs, const SMPKeyType rhs) noexcept {
474 return static_cast<SMPKeyType> ( static_cast<uint8_t>(lhs) & static_cast<uint8_t>(rhs) );
475 }
476 constexpr SMPKeyType& operator &=(SMPKeyType& store, const SMPKeyType& rhs) noexcept {
477 store = static_cast<SMPKeyType> ( static_cast<uint8_t>(store) & static_cast<uint8_t>(rhs) );
478 return store;
479 }
480 constexpr bool operator ==(const SMPKeyType lhs, const SMPKeyType rhs) noexcept {
481 return static_cast<uint8_t>(lhs) == static_cast<uint8_t>(rhs);
482 }
483 constexpr bool operator !=(const SMPKeyType lhs, const SMPKeyType rhs) noexcept {
484 return !( lhs == rhs );
485 }
486 constexpr uint8_t number(const SMPKeyType rhs) noexcept {
487 return static_cast<uint8_t>(rhs);
488 }
489 constexpr bool is_set(const SMPKeyType mask, const SMPKeyType bit) noexcept {
490 return bit == ( mask & bit );
491 }
492 std::string to_string(const SMPKeyType mask) noexcept;
493
494 /**
495 * SMP Long Term Key, used for platform agnostic persistence.
496 * <p>
497 * Notable: No endian wise conversion shall occur on this data,
498 * since the encryption values are interpreted as little-endian or as a byte stream.
499 * </p>
500 * <p>
501 * Byte layout must be synchronized with java org.tinyb.SMPLongTermKey
502 * </p>
503 */
504 __pack( struct SMPLongTermKey {
505 /**
506 * SMPLongTermKey Property Bits
507 */
508 enum class Property : uint8_t {
509 /** No specific property */
510 NONE = 0x00,
511 /** Responder Key (LL slave). Absence indicates Initiator Key (LL master). */
512 RESPONDER = 0x01,
513 /** Authentication used. */
514 AUTH = 0x02,
515 /** Secure Connection used. */
516 SC = 0x04
517 };
518 static constexpr uint8_t number(const Property rhs) noexcept {
519 return static_cast<uint8_t>(rhs);
520 }
521 static std::string getPropertyString(const Property mask) noexcept;
522
523 /** SMPLongTermKey::Property bit mask. */
524 Property properties;
525 /** Encryption Size, zero if key is invalid. */
526 uint8_t enc_size;
527 /** Encryption Diversifier */
528 uint16_t ediv;
529 /** Random Number */
530 uint64_t rand;
531 /** Long Term Key (LTK) */
533
534 // 28 bytes
535
536 constexpr bool isValid() const noexcept { return 0 != enc_size; }
537
538 bool isResponder() const noexcept;
539
540 void clear() noexcept {
541 bzero(reinterpret_cast<void *>(this), sizeof(SMPLongTermKey));
542 }
543
544 std::string toString() const noexcept { // hex-fmt aligned with btmon
545 return "LTK[props "+getPropertyString(properties)+", enc_size "+std::to_string(enc_size)+
546 ", ediv "+jau::bytesHexString(reinterpret_cast<const uint8_t *>(&ediv), 0, sizeof(ediv), true /* lsbFirst */)+
547 ", rand "+jau::bytesHexString(reinterpret_cast<const uint8_t *>(&rand), 0, sizeof(rand), true /* lsbFirst */)+
548 ", ltk "+jau::bytesHexString(ltk.data, 0, sizeof(ltk), true /* lsbFirst */)+
549 ", valid "+std::to_string(isValid())+
550 "]";
551 }
552 } );
554 return static_cast<SMPLongTermKey::Property> ( ~static_cast<uint8_t>(rhs) );
555 }
557 return static_cast<SMPLongTermKey::Property> ( static_cast<uint8_t>(lhs) ^ static_cast<uint8_t>(rhs) );
558 }
560 store = static_cast<SMPLongTermKey::Property> ( static_cast<uint8_t>(store) ^ static_cast<uint8_t>(rhs) );
561 return store;
562 }
564 return static_cast<SMPLongTermKey::Property> ( static_cast<uint8_t>(lhs) | static_cast<uint8_t>(rhs) );
565 }
567 store = static_cast<SMPLongTermKey::Property> ( static_cast<uint8_t>(store) | static_cast<uint8_t>(rhs) );
568 return store;
569 }
571 return static_cast<SMPLongTermKey::Property> ( static_cast<uint8_t>(lhs) & static_cast<uint8_t>(rhs) );
572 }
574 store = static_cast<SMPLongTermKey::Property> ( static_cast<uint8_t>(store) & static_cast<uint8_t>(rhs) );
575 return store;
576 }
577 constexpr bool operator ==(const SMPLongTermKey::Property lhs, const SMPLongTermKey::Property rhs) noexcept {
578 return static_cast<uint8_t>(lhs) == static_cast<uint8_t>(rhs);
579 }
580 constexpr bool operator !=(const SMPLongTermKey::Property lhs, const SMPLongTermKey::Property rhs) noexcept {
581 return !( lhs == rhs );
582 }
583 inline std::string to_String(const SMPLongTermKey& ltk) noexcept { return ltk.toString(); }
584
585 /**
586 * SMP Identity Resolving Key, used for platform agnostic persistence.
587 * <p>
588 * Notable: No endian wise conversion shall occur on this data,
589 * since the encryption values are interpreted as little-endian or as a byte stream.
590 * </p>
591 * <p>
592 * Byte layout must be synchronized with java org.tinyb.SMPIdentityResolvingKey
593 * </p>
594 */
595 __pack( struct SMPIdentityResolvingKey {
596 /**
597 * SMPIdentityResolvingKey Property Bits
598 */
599 enum class Property : uint8_t {
600 /** No specific property */
601 NONE = 0x00,
602 /** Responder Key (LL slave). Absence indicates Initiator Key (LL master). */
603 RESPONDER = 0x01,
604 /** Authentication used. */
605 AUTH = 0x02
606 };
607 static constexpr uint8_t number(const Property rhs) noexcept {
608 return static_cast<uint8_t>(rhs);
609 }
610 static std::string getPropertyString(const Property mask) noexcept;
611
612 /** SMPIdentityResolvingKey::Property bit mask. */
613 Property properties;
614 /** Identity Resolving Key (IRK) */
616 /** Identity Address for the IRK */
617 EUI48 id_address;
618
619 bool isResponder() const noexcept;
620
621 /** Returns true if this IRK matches the given random private address (RPA). */
622 bool matches(const EUI48& rpa) noexcept;
623
624 /** Returns true if the given IRK matches the given random private address (RPA). This static variant is a helper for the Java binding, use matches(). */
625 static bool matches(const jau::uint128dp_t& irk, const EUI48& rpa) noexcept;
626
627 void clear() noexcept {
628 bzero(reinterpret_cast<void *>(this), sizeof(SMPIdentityResolvingKey));
629 }
630
631 std::string toString() const noexcept { // hex-fmt aligned with btmon
632 return "IRK[props "+getPropertyString(properties)+
633 ", id "+id_address.toString()+", irk "+jau::bytesHexString(irk.data, 0, sizeof(irk), true /* lsbFirst */)+
634 "]";
635 }
636 } );
638 return static_cast<SMPIdentityResolvingKey::Property> ( static_cast<uint8_t>(lhs) ^ static_cast<uint8_t>(rhs) );
639 }
641 store = static_cast<SMPIdentityResolvingKey::Property> ( static_cast<uint8_t>(store) ^ static_cast<uint8_t>(rhs) );
642 return store;
643 }
645 return static_cast<SMPIdentityResolvingKey::Property> ( static_cast<uint8_t>(lhs) | static_cast<uint8_t>(rhs) );
646 }
648 store = static_cast<SMPIdentityResolvingKey::Property> ( static_cast<uint8_t>(store) | static_cast<uint8_t>(rhs) );
649 return store;
650 }
652 return static_cast<SMPIdentityResolvingKey::Property> ( static_cast<uint8_t>(lhs) & static_cast<uint8_t>(rhs) );
653 }
655 store = static_cast<SMPIdentityResolvingKey::Property> ( static_cast<uint8_t>(store) & static_cast<uint8_t>(rhs) );
656 return store;
657 }
659 return static_cast<uint8_t>(lhs) == static_cast<uint8_t>(rhs);
660 }
662 return !( lhs == rhs );
663 }
664 inline std::string to_String(const SMPIdentityResolvingKey& csrk) noexcept { return csrk.toString(); }
665
666 /**
667 * SMP Signature Resolving Key, used for platform agnostic persistence.
668 * <p>
669 * One way for ATT Signed Write.
670 * </p>
671 * <p>
672 * Notable: No endian wise conversion shall occur on this data,
673 * since the encryption values are interpreted as little-endian or as a byte stream.
674 * </p>
675 * <p>
676 * Byte layout must be synchronized with java org.tinyb.SMPSignatureResolvingKey
677 * </p>
678 */
679 __pack( struct SMPSignatureResolvingKey {
680 /**
681 * SMPSignatureResolvingKey Property Bits
682 */
683 enum class Property : uint8_t {
684 /** No specific property */
685 NONE = 0x00,
686 /** Responder Key (LL slave). Absence indicates Initiator Key (LL master). */
687 RESPONDER = 0x01,
688 /** Authentication used. */
689 AUTH = 0x02
690 };
691 static constexpr uint8_t number(const Property rhs) noexcept {
692 return static_cast<uint8_t>(rhs);
693 }
694 static std::string getPropertyString(const Property mask) noexcept;
695
696 /** SMPSignatureResolvingKey::Property bit mask. */
697 Property properties;
698 /** Connection Signature Resolving Key (CSRK) */
699 jau::uint128dp_t csrk;
700
701 bool isResponder() const noexcept;
702
703 void clear() noexcept {
704 bzero(reinterpret_cast<void *>(this), sizeof(SMPSignatureResolvingKey));
705 }
706
707 std::string toString() const noexcept { // hex-fmt aligned with btmon
708 return "CSRK[props "+getPropertyString(properties)+
709 ", csrk "+jau::bytesHexString(csrk.data, 0, sizeof(csrk), true /* lsbFirst */)+
710 "]";
711 }
712 } );
714 return static_cast<SMPSignatureResolvingKey::Property> ( static_cast<uint8_t>(lhs) ^ static_cast<uint8_t>(rhs) );
715 }
717 store = static_cast<SMPSignatureResolvingKey::Property> ( static_cast<uint8_t>(store) ^ static_cast<uint8_t>(rhs) );
718 return store;
719 }
721 return static_cast<SMPSignatureResolvingKey::Property> ( static_cast<uint8_t>(lhs) | static_cast<uint8_t>(rhs) );
722 }
724 store = static_cast<SMPSignatureResolvingKey::Property> ( static_cast<uint8_t>(store) | static_cast<uint8_t>(rhs) );
725 return store;
726 }
728 return static_cast<SMPSignatureResolvingKey::Property> ( static_cast<uint8_t>(lhs) & static_cast<uint8_t>(rhs) );
729 }
731 store = static_cast<SMPSignatureResolvingKey::Property> ( static_cast<uint8_t>(store) & static_cast<uint8_t>(rhs) );
732 return store;
733 }
735 return static_cast<uint8_t>(lhs) == static_cast<uint8_t>(rhs);
736 }
738 return !( lhs == rhs );
739 }
740 inline std::string to_String(const SMPSignatureResolvingKey& csrk) noexcept { return csrk.toString(); }
741
742 /**
743 * Local SMP Link Key, used for platform agnostic persistence,
744 * mapping to platform specific MgmtLoadLinkKeyCmd and MgmtEvtNewLinkKey.
745 * <p>
746 * Notable: No endian wise conversion shall occur on this data,
747 * since the encryption values are interpreted as little-endian or as a byte stream.
748 * </p>
749 * <p>
750 * Byte layout must be synchronized with java org.tinyb.SMPLinkKey
751 * </p>
752 */
753 __pack( struct SMPLinkKey {
754 /**
755 * Link Key type compatible with Mgmt's MgmtLinkKeyType and hence MgmtLinkKeyInfo
756 */
757 enum class KeyType : uint8_t {
758 /** Combination key */
759 COMBI = 0x00,
760 /** Local Unit key */
761 LOCAL_UNIT = 0x01,
762 /** Remote Unit key */
763 REMOTE_UNIT = 0x02,
764 /** Debug Combination key */
765 DBG_COMBI = 0x03,
766 /** Unauthenticated Combination key from P-192 */
767 UNAUTH_COMBI_P192 = 0x04,
768 /** Authenticated Combination key from P-192 */
769 AUTH_COMBI_P192 = 0x05,
770 /** Changed Combination key */
771 CHANGED_COMBI = 0x06,
772 /** Unauthenticated Combination key from P-256 */
773 UNAUTH_COMBI_P256 = 0x07,
774 /** Authenticated Combination key from P-256 */
775 AUTH_COMBI_P256 = 0x08,
776 /** Denoting no or invalid link key type */
777 NONE = 0xff
778 };
779 static constexpr uint8_t number(const KeyType rhs) noexcept {
780 return static_cast<uint8_t>(rhs);
781 }
782 static std::string getTypeString(const KeyType type) noexcept;
783
784 bool responder;
785 KeyType type;
787 uint8_t pin_length;
788
789 constexpr bool isValid() const noexcept { return KeyType::NONE != type; }
790
791 /**
792 * Returns true if the type is a combination key,
793 * i.e. used for BTRole::Master and BTRole::Slave.
794 *
795 * This is usally being true when using Secure Connections (SC).
796 */
797 constexpr bool isCombiKey() const noexcept {
798 switch(type) {
799 case KeyType::COMBI:
800 case KeyType::DBG_COMBI:
801 case KeyType::UNAUTH_COMBI_P192:
802 case KeyType::AUTH_COMBI_P192:
803 case KeyType::CHANGED_COMBI:
804 case KeyType::UNAUTH_COMBI_P256:
805 case KeyType::AUTH_COMBI_P256:
806 return true;
807 default:
808 return false;
809 }
810 }
811
812 bool isResponder() const noexcept { return responder; }
813
814 void clear() noexcept {
815 bzero(reinterpret_cast<void *>(this), sizeof(SMPLinkKey));
816 }
817
818 std::string toString() const noexcept { // hex-fmt aligned with btmon
819 return "LK[resp "+std::to_string(responder)+", type "+getTypeString(type)+
820 ", key "+jau::bytesHexString(key.data, 0, sizeof(key), true /* lsbFirst */)+
821 ", plen "+std::to_string(pin_length)+
822 "]";
823 }
824 } );
825
826 /**
827 * Handles the Security Manager Protocol (SMP) using Protocol Data Unit (PDU)
828 * encoded messages over L2CAP channel.
829 * <p>
830 * Vol 3 (Host), Part H (SM): 3 (SMP), 3.3 Command Format
831 * </p>
832 * <p>
833 * Message format between both devices, negotiating security details.
834 * </p>
835 * <p>
836 * Vol 3 (Host), Part H Security Manager Specification (SM): 1.2.1 Bit and byte ordering conventions<br>
837 * Little-Endian: Multiple-octet fields shall be transmitted with the least significant octet first.
838 * </p>
839 * @see SMPAuthReqs
840 */
842 {
843 public:
844 /** SMP Command Codes Vol 3, Part H (SM): 3.3 */
845 enum class Opcode : uint8_t {
846 UNDEFINED = 0x00, // our own pseudo opcode, indicating no ATT PDU message
847
848 PAIRING_REQUEST = 0x01,
849 PAIRING_RESPONSE = 0x02,
850 PAIRING_CONFIRM = 0x03,
851 PAIRING_RANDOM = 0x04,
852 PAIRING_FAILED = 0x05,
853
854 ENCRYPTION_INFORMATION = 0x06,
855 MASTER_IDENTIFICATION = 0x07,
856 IDENTITY_INFORMATION = 0x08,
857 IDENTITY_ADDRESS_INFORMATION = 0x09,
858 SIGNING_INFORMATION = 0x0A,
859 SECURITY_REQUEST = 0x0B,
860
861 PAIRING_PUBLIC_KEY = 0x0C,
862 PAIRING_DHKEY_CHECK = 0x0D,
863 PAIRING_KEYPRESS_NOTIFICATION = 0x0E
864 };
865 static constexpr uint8_t number(const Opcode rhs) noexcept {
866 return static_cast<uint8_t>(rhs);
867 }
868 static std::string getOpcodeString(const Opcode opc) noexcept;
869
870 protected:
871 friend class SMPHandler;
872
873 void check_range() {
875 }
876
877 void checkOpcode(const Opcode expected) const
878 {
879 const Opcode has = getOpcode();
880 if( expected != has ) {
881 throw SMPOpcodeException("Has opcode "+jau::to_hexstring(number(has))+" "+getOpcodeString(has)+
882 ", but expected "+jau::to_hexstring(number(expected))+" "+getOpcodeString(expected), E_FILE_LINE);
883 }
884 }
885 void checkOpcode(const Opcode exp1, const Opcode exp2) const
886 {
887 const Opcode has = getOpcode();
888 if( exp1 != has && exp2 != has ) {
889 throw SMPOpcodeException("Has opcode "+jau::to_hexstring(number(has))+" "+getOpcodeString(has)+
890 ", but expected either "+jau::to_hexstring(number(exp1))+" "+getOpcodeString(exp1)+
891 " or "+jau::to_hexstring(number(exp1))+" "+getOpcodeString(exp1), E_FILE_LINE);
892 }
893 }
894
895 virtual std::string baseString() const noexcept {
896 return "opcode="+jau::to_hexstring(number(getOpcode()))+" "+getOpcodeString(getOpcode())+
897 ", size[total="+std::to_string(pdu.size())+", param "+std::to_string(getPDUParamSize())+"]";
898 }
899 virtual std::string valueString() const noexcept {
900 return "size "+std::to_string(getDataSize())+", data "
901 +jau::bytesHexString(pdu.get_ptr(), getDataOffset(), getDataSize(), true /* lsbFirst */);
902 }
903
904 /** actual received PDU */
906
907 /** creation timestamp in milliseconds */
908 uint64_t ts_creation;
909
910 public:
911 /**
912 * Return a newly created specialized instance pointer to base class.
913 * <p>
914 * Returned memory reference is managed by caller (delete etc)
915 * </p>
916 */
917 static std::unique_ptr<const SMPPDUMsg> getSpecialized(const uint8_t * buffer, jau::nsize_t const buffer_size) noexcept;
918
919 /** Persistent memory, w/ ownership ..*/
920 SMPPDUMsg(const uint8_t* source, const jau::nsize_t size)
921 : pdu(source, std::max<jau::nsize_t>(1, size), jau::lb_endian_t::little),
923 { }
924
925 /** Persistent memory, w/ ownership ..*/
926 SMPPDUMsg(const uint8_t* source, const jau::nsize_t size, const jau::nsize_t min_size)
927 : pdu(source, std::max<jau::nsize_t>(1, size), jau::lb_endian_t::little),
929 {
930 pdu.check_range(0, std::max<jau::nsize_t>(1, min_size), E_FILE_LINE);
931 }
932
933 /** Persistent memory, w/ ownership ..*/
934 SMPPDUMsg(const Opcode opc, const jau::nsize_t size)
935 : pdu(std::max<jau::nsize_t>(1, size), jau::lb_endian_t::little),
937 {
938 pdu.put_uint8_nc(0, number(opc));
939 }
940
941 virtual ~SMPPDUMsg() noexcept = default;
942
943 /**
944 * Clone template for convenience, based on derived class's copy-constructor.
945 * <pre>
946 * const SMPPDUMsg & smpPDU;
947 * const SMPSignInfoMsg * signInfo = static_cast<const SMPSignInfoMsg *>(&smpPDU);
948 * SMPPDUMsg* b1 = SMPPDUMsg::clone(*signInfo);
949 * SMPSignInfoMsg* b2 = SMPPDUMsg::clone(*signInfo);
950 * </pre>
951 * @tparam T The derived definite class type, deducible by source argument
952 * @param source the source to be copied
953 * @return a new instance.
954 */
955 template<class T>
956 static T* clone(const T& source) noexcept { return new T(source); }
957
958 constexpr uint64_t getTimestamp() const noexcept { return ts_creation; }
959
960 /** SMP Command Codes Vol 3, Part H (SM): 3.3 */
961 constexpr Opcode getOpcode() const noexcept {
962 return static_cast<Opcode>(pdu.get_uint8_nc(0));
963 }
964
965 /**
966 * Returns the actual PDU size less one octet for the opcode,
967 * which should result in 0-22 octets or 64 octets.
968 * <p>
969 * Note that the PDU parameter include the data value below.
970 * </p>
971 * <p>
972 * Use getDataSize() for the actual required data size
973 * according to the specific packet.
974 * </p>
975 *
976 * @see SMPPDUMsg::getDataSize()
977 */
978 constexpr jau::nsize_t getPDUParamSize() const noexcept {
979 return pdu.size() - 1 /* opcode */;
980 }
981
982 /**
983 * Returns the required data size according to the specified packet,
984 * which should be within 0-22 or 64 octets.
985 *
986 * @see SMPPDUMsg::getPDUParamSize()
987 */
988 constexpr_cxx20 virtual jau::nsize_t getDataSize() const noexcept {
989 return getPDUParamSize();
990 }
991
992
993 /**
994 * Returns the octet offset to the data segment in this PDU
995 * including the mandatory opcode,
996 * i.e. the number of octets until the first value octet.
997 */
998 constexpr jau::nsize_t getDataOffset() const noexcept { return 1; /* default: opcode */ }
999
1000 virtual std::string getName() const noexcept {
1001 return "SMPPDUMsg";
1002 }
1003
1004 virtual std::string toString() const noexcept{
1005 return getName()+"["+baseString()+", value["+valueString()+"]]";
1006 }
1007 };
1008 inline std::string to_String(const SMPPDUMsg& m) noexcept { return m.toString(); }
1009
1010 /**
1011 * Tag type to group all SMP messages covering encryption keys,
1012 * treated as byte stream (all of them).
1013 * <p>
1014 * Notable: No endian wise conversion shall occur on this data,
1015 * since the encryption values are interpreted as little-endian or as a byte stream.
1016 * </p>
1017 */
1019 {
1020 public:
1021 /** Persistent memory, w/ ownership ..*/
1022 SMPEncKeyByteStream(const uint8_t* source, const jau::nsize_t size)
1023 : SMPPDUMsg(source, size) { }
1024
1025 /** Persistent memory, w/ ownership ..*/
1027 : SMPPDUMsg(opc, size) { }
1028
1029 ~SMPEncKeyByteStream() noexcept override = default;
1030 };
1031
1032 /**
1033 * Vol 3, Part H: 3.5.1 Pairing Request message.<br>
1034 * Vol 3, Part H: 3.5.2 Pairing Response message.
1035 * <pre>
1036 * Vol 3 (Host), Part H (SM): 3 (SMP), 3.5 Pairing Methods
1037 * Vol 3 (Host), Part H (SM): 2 (SM), 2.3 Pairing Methods
1038 * </pre>
1039 *
1040 * Opcode::PAIRING_REQUEST or Opcode::PAIRING_RESPONSE
1041 *
1042 * <pre>
1043 * [uint8_t opcode]
1044 * uint8_t io_capability
1045 * uint8_t oob_data_flag
1046 * uint8_t auth_req_mask
1047 * uint8_t max_encryption_key_size
1048 * uint8_t initiator_key_distribution
1049 * uint8_t responder_key_distribution
1050 * </pre>
1051 *
1052 * <br>
1053 * SMP Pairing Request Vol 3, Part H (SM): 3.5.1
1054 * <p>
1055 * Initiator starts the Pairing Feature Exchange
1056 * by sending a Pairing Request command to the responding device.
1057 * </p>
1058 * <p>
1059 * The rules for handing a collision between a pairing procedure
1060 * on the LE transport and a pairing procedure on the BR/EDR transport
1061 * are defined in Vol 3, Part C (GAP): 14.2 BRD/EDR/LE security aspects - Collision Handling.
1062 * </p>
1063 *
1064 * <br>
1065 * SMP Pairing Response Vol 3, Part H (SM): 3.5.2
1066 * <p>
1067 * Command is used by the responding device to complete the Pairing Feature Exchange
1068 * after it has received a Pairing Request command from the initiating device,
1069 * if the responding device allows pairing.
1070 * </p>
1071 * <p>
1072 * If a Pairing Request is received over the BR/EDR transport
1073 * when either cross-transport key derivation/generation is not supported
1074 * or the BR/EDR transport is not encrypted using a Link Key generated using P256,
1075 * a Pairing Failed shall be sent with the error code
1076 * SMPPairFailedMsg::ReasonCode::CROSSXPORT_KEY_DERIGEN_NOT_ALLOWED (Cross-Transport Key Derivation/Generation Not Allowed).
1077 * </p>
1078 * <p>
1079 * The rules for handing a collision between a pairing procedure
1080 * on the LE transport and a pairing procedure on the BR/EDR transport
1081 * are defined in Vol 3, Part C (GAP): 14.2 BRD/EDR/LE security aspects - Collision Handling.
1082 * </p>
1083 */
1084 class SMPPairingMsg final : public SMPPDUMsg
1085 {
1086 private:
1087 const bool request;
1088 const SMPAuthReqs authReqMask;
1089 const SMPKeyType initiator_key_dist;
1090 const SMPKeyType responder_key_dist;
1091
1092 public:
1093 SMPPairingMsg(const bool request_, const uint8_t* source, const jau::nsize_t length)
1094 : SMPPDUMsg(source, length, 7),
1095 request(request_),
1096 authReqMask(static_cast<SMPAuthReqs>( pdu.get_uint8_nc(3) )),
1097 initiator_key_dist(static_cast<SMPKeyType>(pdu.get_uint8_nc(5))),
1098 responder_key_dist(static_cast<SMPKeyType>(pdu.get_uint8_nc(6)))
1099 {
1101 check_range();
1102 }
1103
1104 SMPPairingMsg(const bool request_,
1105 const SMPIOCapability ioc, const SMPOOBDataFlag odf,
1106 const SMPAuthReqs auth_req_mask, const uint8_t maxEncKeySize,
1107 const SMPKeyType initiator_key_dist_,
1108 const SMPKeyType responder_key_dist_)
1109 : SMPPDUMsg(request_? Opcode::PAIRING_REQUEST : Opcode::PAIRING_RESPONSE, 1+6),
1110 request(request_),
1111 authReqMask(auth_req_mask), initiator_key_dist(initiator_key_dist_), responder_key_dist(responder_key_dist_)
1112 {
1115 pdu.put_uint8(3, direct_bt::number(authReqMask));
1116 pdu.put_uint8(4, maxEncKeySize);
1117 pdu.put_uint8(5, direct_bt::number(initiator_key_dist));
1118 pdu.put_uint8(6, direct_bt::number(responder_key_dist));
1119 check_range();
1120 }
1121
1122 constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override {
1123 return 6;
1124 }
1125
1126 /**
1127 * Returns the IO capability bit field.
1128 * <pre>
1129 * Vol 3, Part H, 2.3.2 IO capabilities
1130 * </pre>
1131 * @see IOCapability
1132 */
1133 constexpr SMPIOCapability getIOCapability() const noexcept {
1134 return static_cast<SMPIOCapability>(pdu.get_uint8_nc(1));
1135 }
1136
1137 /**
1138 * Returns the OBB authenticate data flag
1139 * <pre>
1140 * Vol 3, Part H, 2.3.3 OOB authentication data
1141 * </pre>
1142 * @see OOBDataFlag
1143 */
1144 constexpr SMPOOBDataFlag getOOBDataFlag() const noexcept {
1145 return static_cast<SMPOOBDataFlag>(pdu.get_uint8_nc(2));
1146 }
1147
1148 /**
1149 * Returns the Authentication Requirements mask.
1150 * <pre>
1151 * SMP Pairing Request Vol 3, Part H (SM): 3.5.1
1152 * SMP Pairing Response Vol 3, Part H (SM): 3.5.2
1153 * </pre>
1154 * @see AuthRequirements
1155 */
1156 constexpr SMPAuthReqs getAuthReqMask() const noexcept {
1157 return authReqMask;
1158 }
1159 constexpr bool isAuthRequirementBitSet(const SMPAuthReqs bit) const noexcept {
1160 return is_set(authReqMask, bit);
1161 }
1162
1163 /**
1164 * This value defines the maximum encryption key size in octets that the device
1165 * can support. The maximum key size shall be in the range 7 to 16 octets.
1166 */
1167 constexpr uint8_t getMaxEncryptionKeySize() const noexcept {
1168 return pdu.get_uint8_nc(4);
1169 }
1170 /**
1171 * Returns the Initiator Key Distribution field,
1172 * which defines which keys the initiator shall
1173 * distribute and use during the Transport Specific Key Distribution phase.
1174 * <pre>
1175 * See Vol 3, Part H, 2.4.3 SM - LE Security - Distribution of keys.
1176 * Field format and usage: Vol 3, Part H, 3.6.1 SMP - LE Security - Key distribution and generation.
1177 * </pre>
1178 * @see SMPKeyDistFormat
1179 */
1180 constexpr SMPKeyType getInitKeyDist() const noexcept {
1181 return initiator_key_dist;
1182 }
1183 /**
1184 * Return the Responder Key Distribution field,
1185 * which defines which keys the responder shall
1186 * distribute and use during the Transport Specific Key Distribution phase.
1187 * <p>
1188 * See Vol 3, Part H, 2.4.3 SM - LE Security - Distribution of keys.
1189 * Field format and usage: Vol 3, Part H, 3.6.1 SMP - LE Security - Key distribution and generation.
1190 * </p>
1191 * @see SMPKeyDistFormat
1192 */
1193 constexpr SMPKeyType getRespKeyDist() const noexcept {
1194 return responder_key_dist;
1195 }
1196
1197 std::string getName() const noexcept override {
1198 return "SMPPairingMsg";
1199 }
1200
1201 protected:
1202 std::string valueString() const noexcept override {
1203 return "iocap "+to_string(getIOCapability())+
1204 ", oob "+to_string(getOOBDataFlag())+
1205 ", auth_req "+to_string(getAuthReqMask())+
1206 ", max_keysz "+std::to_string(getMaxEncryptionKeySize())+
1207 ", key_dist[init "+to_string(getInitKeyDist())+
1208 ", resp "+to_string(getRespKeyDist())+
1209 "]";
1210 }
1211 };
1212
1213 /**
1214 * Vol 3, Part H: 3.5.3 Pairing Confirm message.
1215 * <pre>
1216 * Vol 3 (Host), Part H (SM): 3 (SMP), 3.5 Pairing Methods
1217 * </pre>
1218 *
1219 * Opcode::PAIRING_CONFIRM
1220 *
1221 * <pre>
1222 * [uint8_t opcode]
1223 * jau::uint128_t confirm_value
1224 * </pre>
1225 *
1226 * Used following a successful Pairing Feature Exchange to start
1227 * STK Generation for LE legacy pairing and LTK Generation for LE Secure Connections pairing.
1228 * <p>
1229 * Command is used by both devices to send the confirm value to the peer device,<br>
1230 * see Vol 3, Part H, 2.3.5.5 SM - Pairing algo - LE legacy pairing phase 2 and<br>
1231 * and Vol 3, Part H, 2.3.5.6 SM - Pairing algo - LE Secure Connections pairing phase 2.
1232 * </p>
1233 * <p>
1234 * The initiating device starts key generation by sending the Pairing Confirm command to the responding device.<br>
1235 * If the initiating device wants to abort pairing it can transmit a Pairing Failed command instead.
1236 * </p>
1237 * <p>
1238 * The responding device sends the Pairing Confirm command
1239 * after it has received a Pairing Confirm command from the initiating device.
1240 * </p>
1241 * <p>
1242 * Notable: No endian wise conversion shall occur on this data,
1243 * since the encryption values are interpreted as little-endian or as a byte stream.
1244 * </p>
1245 */
1247 {
1248 public:
1249 SMPPairConfirmMsg(const uint8_t* source, const jau::nsize_t length)
1250 : SMPEncKeyByteStream(source, length)
1251 {
1252 check_range();
1254 }
1255
1257 : SMPEncKeyByteStream(Opcode::PAIRING_CONFIRM, 1+16)
1258 {
1259 jau::put_uint128(pdu.get_wptr() + 1, confirm_value);
1260 check_range();
1261 }
1262
1263 constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override {
1264 return 16;
1265 }
1266
1267 /**
1268 * Returns the 128-bit Confirm value (16 octets)
1269 * <p>
1270 * In LE legacy pairing, the initiating device sends Mconfirm and the
1271 * responding device sends Sconfirm as defined in
1272 * Vol 3, Part H, 2.3.5.5 SM - Pairing algo - LE legacy pairing phase 2
1273 * </p>
1274 * <p>
1275 * In LE Secure Connections, Ca and Cb are defined in
1276 * Vol 3, Part H, Section 2.2.6 SM - Crypto Toolbox - LE Secure Connections confirm value generation function f4.<br>
1277 * See Vol 3, Part H, 2.3.5.6 SM - Pairing algo - LE Secure Connections pairing phase 2.
1278 * </p>
1279 */
1280 constexpr jau::uint128dp_t getConfirmValue() const noexcept { return jau::get_uint128(pdu.get_ptr() + 1); }
1281
1282 std::string getName() const noexcept override {
1283 return "SMPPairConfirm";
1284 }
1285
1286 protected:
1287 std::string valueString() const noexcept override { // hex-fmt aligned with btmon
1288 return "size "+std::to_string(getDataSize())+", value "+
1289 jau::bytesHexString(pdu.get_ptr_nc(1), 0, getDataSize(), true /* lsbFirst */);
1290 }
1291 };
1292
1293 /**
1294 * Vol 3, Part H: 3.5.4 Pairing Random message.
1295 * <pre>
1296 * Vol 3 (Host), Part H (SM): 3 (SMP), 3.5 Pairing Methods
1297 * </pre>
1298 *
1299 * Opcode::PAIRING_RANDOM
1300 *
1301 * <pre>
1302 * [uint8_t opcode]
1303 * jau::uint128_t random_value
1304 * </pre>
1305 *
1306 * Used by the initiating and responding device to send the
1307 * random number used to calculate the Confirm value sent in the Pairing Confirm command.
1308 * <p>
1309 * The initiating device sends a Pairing Random command
1310 * after it has received a Pairing Confirm command from the responding device.
1311 * </p>
1312 * <p>
1313 * LE legacy pairing: Responding device sends a Pairing Random command
1314 * after receiving a Pairing Random command from the initiating device
1315 * if the Confirm value calculated on the responding device matches the
1316 * Confirm value received from the initiating device.<br>
1317 * If the calculated Confirm value does not match
1318 * then the responding device shall respond with the Pairing Failed command.
1319 * </p>
1320 * <p>
1321 * LE Secure Connections: Responding device sends a Pairing Random command
1322 * after it has received a Pairing Random command from the initiating device
1323 * <i>if the Confirm value calculated on the responding device matches the
1324 * Confirm value received from the initiating device(?)</i>.<br>
1325 * If the calculated Confirm value does not match then the responding device
1326 * shall respond with the Pairing Failed command.
1327 * </p>
1328 * <p>
1329 * The initiating device shall encrypt the link using
1330 * the generated key (STK in LE legacy pairing or LTK in LE Secure Connections)
1331 * if the Confirm value calculated on the initiating device matches
1332 * the Confirm value received from the responding device.<br>
1333 * The successful encryption or re-encryption of the link is the signal
1334 * to the responding device that key generation has completed successfully.<br>
1335 * If the calculated Confirm value does not match then
1336 * the initiating device shall respond with the Pairing Failed command.
1337 * </p>
1338 * <p>
1339 * Notable: No endian wise conversion shall occur on this data,
1340 * since the encryption values are interpreted as little-endian or as a byte stream.
1341 * </p>
1342 */
1344 {
1345 public:
1346 SMPPairRandMsg(const uint8_t* source, const jau::nsize_t length)
1347 : SMPEncKeyByteStream(source, length)
1348 {
1349 check_range();
1351 }
1352
1353 SMPPairRandMsg(const jau::uint128dp_t & random_value)
1354 : SMPEncKeyByteStream(Opcode::PAIRING_RANDOM, 1+16)
1355 {
1356 jau::put_uint128(pdu.get_wptr() + 1, random_value);
1357 check_range();
1358 }
1359
1360 constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override {
1361 return 16;
1362 }
1363
1364 /**
1365 * Returns the 128-bit Random value (16 octets)
1366 * <p>
1367 * In LE legacy pairing, the initiating device sends Mrand and the
1368 * responding device sends Srand as defined in
1369 * Vol 3, Part H, 2.3.5.5 SM - Pairing algo - LE legacy pairing phase 2
1370 * </p>
1371 * <p>
1372 * In LE Secure Connections,
1373 * the initiating device sends Na and the responding device sends Nb.
1374 * </p>
1375 */
1376 constexpr jau::uint128dp_t getRand() const noexcept { return jau::get_uint128(pdu.get_ptr() + 1); }
1377
1378 std::string getName() const noexcept override {
1379 return "SMPPairRand";
1380 }
1381
1382 protected:
1383 std::string valueString() const noexcept override { // hex-fmt aligned with btmon
1384 return "size "+std::to_string(getDataSize())+", rand "+
1385 jau::bytesHexString(pdu.get_ptr_nc(1), 0, getDataSize(), true /* lsbFirst */);
1386 }
1387 };
1388
1389 /**
1390 * Vol 3, Part H: 3.5.5 Pairing Failed message.
1391 * <pre>
1392 * Vol 3 (Host), Part H (SM): 3 (SMP), 3.5 Pairing Methods
1393 * </pre>
1394 *
1395 * Opcode::PAIRING_FAILED
1396 *
1397 * <pre>
1398 * [uint8_t opcode]
1399 * uint8_t reason_code
1400 * </pre>
1401 */
1402 class SMPPairFailedMsg final : public SMPPDUMsg
1403 {
1404 public:
1405 enum class ReasonCode : uint8_t {
1406 UNDEFINED = 0x00,
1407 PASSKEY_ENTRY_FAILED = 0x01,
1408 OOB_NOT_AVAILABLE = 0x02,
1409 AUTHENTICATION_REQUIREMENTS = 0x03,
1410 CONFIRM_VALUE_FAILED = 0x04,
1411 PAIRING_NOT_SUPPORTED = 0x05,
1412 ENCRYPTION_KEY_SIZE = 0x06,
1413 COMMON_NOT_SUPPORTED = 0x07,
1414 UNSPECIFIED_REASON = 0x08,
1415 REPEATED_ATTEMPTS = 0x09,
1416 INVALID_PARAMTERS = 0x0A,
1417 DHKEY_CHECK_FAILED = 0x0B,
1418 NUMERIC_COMPARISON_FAILED = 0x0C,
1419 BREDR_PAIRING_IN_PROGRESS = 0x0D,
1420 CROSSXPORT_KEY_DERIGEN_NOT_ALLOWED = 0x0E
1421 };
1422 static constexpr uint8_t number(const ReasonCode rhs) noexcept {
1423 return static_cast<uint8_t>(rhs);
1424 }
1425 static std::string getReasonCodeString(const ReasonCode reasonCode) noexcept;
1426
1427 SMPPairFailedMsg(const uint8_t* source, const jau::nsize_t length)
1428 : SMPPDUMsg(source, length)
1429 {
1430 check_range();
1432 }
1433
1435 : SMPPDUMsg(Opcode::PAIRING_FAILED, 1+1)
1436 {
1437 pdu.put_uint8(1, number(rc));
1438 check_range();
1439 }
1440
1441 constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override {
1442 return 1;
1443 }
1444
1445 constexpr ReasonCode getReasonCode() const noexcept {
1446 return static_cast<ReasonCode>(pdu.get_uint8_nc(1));
1447 }
1448
1449 std::string getName() const noexcept override {
1450 return "SMPPairFailed";
1451 }
1452
1453 protected:
1454 std::string valueString() const noexcept override {
1455 const ReasonCode ec = getReasonCode();
1456 return jau::to_hexstring(number(ec)) + ": " + getReasonCodeString(ec);
1457 }
1458 };
1459
1460
1461 /**
1462 * Vol 3, Part H: 3.5.6 Pairing Public Key message.
1463 * <pre>
1464 * Vol 3 (Host), Part H (SM): 3 (SMP), 3.5.6 Pairing Public Key
1465 * </pre>
1466 *
1467 * Opcode::PAIRING_PUBLIC_KEY
1468 *
1469 * <pre>
1470 * [uint8_t opcode]
1471 * jau::uint256_t public_key_x_value
1472 * jau::uint256_t public_key_y_value
1473 * </pre>
1474 *
1475 * Message is used to transfer the device’s local public key (X and Y coordinates) to the remote device.<br>
1476 * This message is used by both the initiator and responder.<br>
1477 * This PDU is only used for LE Secure Connections.
1478 * <p>
1479 * Notable: No endian wise conversion shall occur on this data,
1480 * since the encryption values are interpreted as little-endian or as a byte stream.
1481 * </p>
1482 */
1484 {
1485 public:
1486 SMPPairPubKeyMsg(const uint8_t* source, const jau::nsize_t length)
1487 : SMPEncKeyByteStream(source, length)
1488 {
1489 check_range();
1491 }
1492
1493 SMPPairPubKeyMsg(const jau::uint256dp_t & pub_key_x, const jau::uint256dp_t & pub_key_y)
1494 : SMPEncKeyByteStream(Opcode::PAIRING_PUBLIC_KEY, 1+32+32)
1495 {
1496 jau::put_uint256(pdu.get_wptr() + 1, pub_key_x);
1497 jau::put_uint256(pdu.get_wptr() + 1+32, pub_key_y);
1498 check_range();
1499 }
1500
1501 constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override {
1502 return 32+32;
1503 }
1504
1505 /**
1506 * Returns the 256-bit Public Key X value (32 octets)
1507 */
1508 constexpr jau::uint256dp_t getPubKeyX() const noexcept { return jau::get_uint256(pdu.get_ptr() + 1); }
1509
1510 /**
1511 * Returns the 256-bit Public Key Y value (32 octets)
1512 */
1513 constexpr jau::uint256dp_t getPubKeyY() const noexcept { return jau::get_uint256(pdu.get_ptr() + 1+32); }
1514
1515 std::string getName() const noexcept override {
1516 return "SMPPairPubKey";
1517 }
1518
1519 protected:
1520 std::string valueString() const noexcept override {
1521 return "size "+std::to_string(getDataSize())+", pk_x "+
1522 jau::bytesHexString(pdu.get_ptr_nc(1), 0, 32, true /* lsbFirst */)+
1523 ", pk_y "+
1524 jau::bytesHexString(pdu.get_ptr_nc(1+32), 0, 32, true /* lsbFirst */);
1525 }
1526 };
1527
1528 /**
1529 * Vol 3, Part H: 3.5.7 Pairing DHKey Check message.
1530 * <pre>
1531 * Vol 3 (Host), Part H (SM): 3 (SMP), 3.5 Pairing Methods
1532 * </pre>
1533 *
1534 * Opcode::PAIRING_DHKEY_CHECK
1535 *
1536 * <pre>
1537 * [uint8_t opcode]
1538 * jau::uint128_t dhkey_check_values
1539 * </pre>
1540 *
1541 * Message is used to transmit the 128-bit DHKey Check values (Ea/Eb) generated using f6.<br>
1542 * This message is used by both initiator and responder.<br>
1543 * This PDU is only used for LE Secure Connections.
1544 * <p>
1545 * Notable: No endian wise conversion shall occur on this data,
1546 * since the encryption values are interpreted as little-endian or as a byte stream.
1547 * </p>
1548 */
1550 {
1551 public:
1552 SMPPairDHKeyCheckMsg(const uint8_t* source, const jau::nsize_t length)
1553 : SMPEncKeyByteStream(source, length)
1554 {
1555 check_range();
1557 }
1558
1559 SMPPairDHKeyCheckMsg(const jau::uint128dp_t & dhkey_check_values)
1560 : SMPEncKeyByteStream(Opcode::PAIRING_DHKEY_CHECK, 1+16)
1561 {
1562 jau::put_uint128(pdu.get_wptr() + 1, dhkey_check_values);
1563 check_range();
1564 }
1565
1566 constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override {
1567 return 16;
1568 }
1569
1570 /**
1571 * Returns the 128-bit DHKey Check value (16 octets)
1572 */
1573 constexpr jau::uint128dp_t getDHKeyCheck() const noexcept { return jau::get_uint128(pdu.get_ptr() + 1); }
1574
1575 std::string getName() const noexcept override {
1576 return "SMPPairDHKeyCheck";
1577 }
1578
1579 protected:
1580 std::string valueString() const noexcept override {
1581 return "size "+std::to_string(getDataSize())+", dhkey_chk "+
1582 jau::bytesHexString(pdu.get_ptr_nc(1), 0, getDataSize(), true /* lsbFirst */);
1583 }
1584 };
1585
1586 /**
1587 * Vol 3, Part H: 3.5.8 Passkey Entry: Keypress notification messages.
1588 * <pre>
1589 * Vol 3 (Host), Part H (SM): 3 (SMP), 3.5 Pairing Methods
1590 * </pre>
1591 *
1592 * Opcode::PAIRING_KEYPRESS_NOTIFICATION
1593 *
1594 * <pre>
1595 * [uint8_t opcode]
1596 * uint8_t notification_type
1597 * </pre>
1598 *
1599 * Message is used during the Passkey Entry protocol by a device with KeyboardOnly IO capabilities
1600 * to inform the remote device when keys have been entered or erased.
1601 */
1603 {
1604 public:
1605 enum class TypeCode : uint8_t {
1606 PASSKEY_ENTRY_STARTED = 0x00,
1607 PASSKEY_DIGIT_ENTERED = 0x01,
1608 PASSKEY_DIGIT_ERASED = 0x02,
1609 PASSKEY_CLEARED = 0x03,
1610 PASSKEY_ENTRY_COMPLETED = 0x04
1611 };
1612 static constexpr uint8_t number(const TypeCode rhs) noexcept {
1613 return static_cast<uint8_t>(rhs);
1614 }
1615 static std::string getTypeCodeString(const TypeCode tc) noexcept;
1616
1617 SMPPasskeyNotification(const uint8_t* source, const jau::nsize_t length)
1618 : SMPPDUMsg(source, length)
1619 {
1620 check_range();
1622 }
1623
1625 : SMPPDUMsg(Opcode::PAIRING_KEYPRESS_NOTIFICATION, 1+1)
1626 {
1627 pdu.put_uint8_nc(1, number(tc));
1628 check_range();
1629 }
1630
1631 constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override {
1632 return 1;
1633 }
1634
1635 constexpr TypeCode getTypeCode() const noexcept {
1636 return static_cast<TypeCode>(pdu.get_uint8_nc(1));
1637 }
1638
1639 std::string getName() const noexcept override {
1640 return "SMPPasskeyNotify";
1641 }
1642
1643 protected:
1644 std::string valueString() const noexcept override {
1645 const TypeCode ec = getTypeCode();
1646 return jau::to_hexstring(number(ec)) + ": " + getTypeCodeString(ec);
1647 }
1648 };
1649
1650 /**
1651 * Vol 3, Part H: 3.6.2 Encryption Information message.
1652 * <pre>
1653 * Vol 3 (Host), Part H (SM): 3 (SMP), 3.6 SECURITY IN BLUETOOTH LOW ENERGY
1654 * Vol 3 (Host), Part H (SM): 3 (SMP), 3.6.1 Key distribution and generation
1655 * Vol 3 (Host), Part H (SM): 2 (SM), 2.4.1 Definition of keys and values
1656 * </pre>
1657 *
1658 * Opcode::ENCRYPTION_INFORMATION
1659 *
1660 * <pre>
1661 * [uint8_t opcode]
1662 * jau::uint128_t long_term_key
1663 * </pre>
1664 *
1665 * Message is used in the LE legacy pairing Transport Specific Key Distribution
1666 * to distribute Long Term Key (LTK) that is used when encrypting future connections.
1667 * <p>
1668 * The message shall only be sent when the link has been encrypted or re-encrypted using the generated LTK.
1669 * </p>
1670 * <p>
1671 * Legacy: #1 in distribution, first value.
1672 * </p>
1673 * <p>
1674 * Notable: No endian wise conversion shall occur on this data,
1675 * since the encryption values are interpreted as little-endian or as a byte stream.
1676 * </p>
1677 */
1679 {
1680 public:
1681 SMPEncInfoMsg(const uint8_t* source, const jau::nsize_t length)
1682 : SMPEncKeyByteStream(source, length)
1683 {
1684 check_range();
1686 }
1687
1688 SMPEncInfoMsg(const jau::uint128dp_t & long_term_key)
1689 : SMPEncKeyByteStream(Opcode::ENCRYPTION_INFORMATION, 1+16)
1690 {
1691 jau::put_uint128(pdu.get_wptr() + 1, long_term_key);
1692 check_range();
1693 }
1694
1695 constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override {
1696 return 16;
1697 }
1698
1699 /**
1700 * Returns the 128-bit Long Term Key (16 octets)
1701 * <p>
1702 * The generated LTK value being distributed,
1703 * see Vol 3, Part H, 2.4.2.3 SM - LE legacy pairing - generation of LTK, EDIV and Rand.
1704 * </p>
1705 */
1706 constexpr jau::uint128dp_t getLTK() const noexcept { return jau::get_uint128(pdu.get_ptr() + 1); }
1707
1708 std::string getName() const noexcept override {
1709 return "SMPEncInfo";
1710 }
1711
1712 protected:
1713 std::string valueString() const noexcept override { // hex-fmt aligned with btmon
1714 return "size "+std::to_string(getDataSize())+", ltk "+
1715 jau::bytesHexString(pdu.get_ptr_nc(1), 0, getDataSize(), true /* lsbFirst */);
1716 }
1717 };
1718
1719 /**
1720 * Vol 3, Part H: 3.6.3 Master Identification message.
1721 * <pre>
1722 * Vol 3 (Host), Part H (SM): 3 (SMP), 3.6 SECURITY IN BLUETOOTH LOW ENERGY
1723 * Vol 3 (Host), Part H (SM): 3 (SMP), 3.6.1 Key distribution and generation
1724 * Vol 3 (Host), Part H (SM): 2 (SM), 2.4.1 Definition of keys and values
1725 * </pre>
1726 *
1727 * Opcode::MASTER_IDENTIFICATION
1728 *
1729 * <pre>
1730 * [uint8_t opcode]
1731 * uint16_t ediv
1732 * uint64_t rand
1733 * </pre>
1734 *
1735 * Message is used in the LE legacy pairing Transport Specific Key Distribution phase
1736 * to distribute Encrypted Diversifier (EDIV) and Random Number (Rand) which are used when encrypting future connections.
1737 *
1738 * <p>
1739 * The message shall only be sent when the link has been encrypted or re-encrypted using the generated LTK.
1740 * </p>
1741 * <p>
1742 * Legacy: #2 in distribution
1743 * </p>
1744 * <p>
1745 * Notable: No endian wise conversion shall occur on this data,
1746 * since the encryption values are interpreted as little-endian or as a byte stream.
1747 * </p>
1748 */
1750 {
1751 public:
1752 SMPMasterIdentMsg(const uint8_t* source, const jau::nsize_t length)
1753 : SMPEncKeyByteStream(source, length)
1754 {
1755 check_range();
1757 }
1758
1759 SMPMasterIdentMsg(const uint16_t ediv, const uint64_t & rand)
1760 : SMPEncKeyByteStream(Opcode::MASTER_IDENTIFICATION, 1+2+8)
1761 {
1762 jau::put_uint16(pdu.get_wptr() + 1, ediv);
1763 jau::put_uint64(pdu.get_wptr() + 1+2, rand);
1764 check_range();
1765 }
1766
1767 constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override {
1768 return 10;
1769 }
1770
1771 /**
1772 * Returns the 16-bit EDIV value (2 octets) being distributed
1773 * <p>
1774 * See Vol 3, Part H, 2.4.2.3 SM - Generation of CSRK - LE legacy pairing - generation of LTK, EDIV and Rand.
1775 * </p>
1776 */
1777 constexpr uint16_t getEDIV() const noexcept { return jau::get_uint16(pdu.get_ptr() + 1); }
1778
1779 /**
1780 * Returns the 64-bit Rand value (8 octets) being distributed
1781 * <p>
1782 * See Vol 3, Part H, 2.4.2.3 SM - Generation of CSRK - LE legacy pairing - generation of LTK, EDIV and Rand.
1783 * </p>
1784 */
1785 constexpr uint64_t getRand() const noexcept { return jau::get_uint64(pdu.get_ptr() + 1+2); }
1786
1787 std::string getName() const noexcept override {
1788 return "SMPMasterIdent";
1789 }
1790
1791 protected:
1792 std::string valueString() const noexcept override { // hex-fmt aligned with btmon
1793 return "size "+std::to_string(getDataSize())+", ediv "+
1794 jau::bytesHexString(pdu.get_ptr_nc(1), 0, 2, false /* lsbFirst */)+
1795 ", rand "+
1796 jau::bytesHexString(pdu.get_ptr_nc(1+2), 0, 8, false /* lsbFirst */);
1797 }
1798 };
1799
1800 /**
1801 * Vol 3, Part H: 3.6.4 Identify Information message.
1802 * <pre>
1803 * Vol 3 (Host), Part H (SM): 3 (SMP), 3.6 SECURITY IN BLUETOOTH LOW ENERGY
1804 * Vol 3 (Host), Part H (SM): 3 (SMP), 3.6.1 Key distribution and generation
1805 * Vol 3 (Host), Part H (SM): 2 (SM), 2.4.1 Definition of keys and values
1806 * Vol 3 (Host), Part H (SM): 2 (SM), 2.4.2.1 Generation of IRK
1807 * </pre>
1808 *
1809 * Opcode::IDENTITY_INFORMATION
1810 *
1811 * <pre>
1812 * [uint8_t opcode]
1813 * jau::uint128_t identity_resolving_key
1814 * </pre>
1815 *
1816 * Message is used in the Transport Specific Key Distribution phase to distribute Identity Resolving Key (IRK).
1817 * <p>
1818 * The message shall only be sent when the link has been encrypted or re-encrypted using the generated key.
1819 * </p>
1820 * <p>
1821 * Legacy: #3 in distribution<br>
1822 * Secure Connection: #1 in distribution, first value.
1823 * </p>
1824 * <p>
1825 * Notable: No endian wise conversion shall occur on this data,
1826 * since the encryption values are interpreted as little-endian or as a byte stream.
1827 * </p>
1828 */
1830 {
1831 public:
1832 SMPIdentInfoMsg(const uint8_t* source, const jau::nsize_t length)
1833 : SMPEncKeyByteStream(source, length)
1834 {
1835 check_range();
1837 }
1838
1839 SMPIdentInfoMsg(const jau::uint128dp_t & identity_resolving_key)
1840 : SMPEncKeyByteStream(Opcode::IDENTITY_INFORMATION, 1+16)
1841 {
1842 jau::put_uint128(pdu.get_wptr() + 1, identity_resolving_key);
1843 check_range();
1844 }
1845
1846 constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override {
1847 return 16;
1848 }
1849
1850 /**
1851 * Returns the 128-bit Identity Resolving Key (IRK, 16 octets)
1852 * <p>
1853 * The 128-bit IRK value being distributed,
1854 * see Vol 3, Part H, 2.4.2.1 SM - Definition of keys and values - Generation of IRK.
1855 * </p>
1856 */
1857 constexpr jau::uint128dp_t getIRK() const noexcept { return jau::get_uint128(pdu.get_ptr() + 1); }
1858
1859 std::string getName() const noexcept override {
1860 return "SMPIdentInfo";
1861 }
1862
1863 protected:
1864 std::string valueString() const noexcept override {
1865 return "size "+std::to_string(getDataSize())+", irk "+
1866 jau::bytesHexString(pdu.get_ptr_nc(1), 0, getDataSize(), true /* lsbFirst */);
1867 }
1868 };
1869
1870
1871 /**
1872 * Vol 3, Part H: 3.6.5 Identity Address Information message.
1873 * <pre>
1874 * Vol 3 (Host), Part H (SM): 3 (SMP), 3.6 SECURITY IN BLUETOOTH LOW ENERGY
1875 * Vol 3 (Host), Part H (SM): 3 (SMP), 3.6.1 Key distribution and generation
1876 * </pre>
1877 *
1878 * Opcode::IDENTITY_ADDRESS_INFORMATION
1879 *
1880 * <pre>
1881 * [uint8_t opcode]
1882 * uint8_t address_type (0x01 static random, 0x00 public)
1883 * EUI48 address
1884 * </pre>
1885 *
1886 * Message is used in the Transport Specific Key Distribution phase
1887 * to distribute its public device address or static random address.
1888 * <p>
1889 * The message shall only be sent when the link has been encrypted or re-encrypted using the generated key.
1890 * </p>
1891 * <p>
1892 * Legacy: #4 in distribution<br>
1893 * Secure Connection: #2 in distribution
1894 * </p>
1895 */
1896 class SMPIdentAddrInfoMsg final : public SMPPDUMsg
1897 {
1898 public:
1899 SMPIdentAddrInfoMsg(const uint8_t* source, const jau::nsize_t length)
1900 : SMPPDUMsg(source, length)
1901 {
1902 check_range();
1904 }
1905
1906 SMPIdentAddrInfoMsg(const bool addrIsStaticRandom, const EUI48 & addr)
1907 : SMPPDUMsg(Opcode::IDENTITY_ADDRESS_INFORMATION, 1+1+6)
1908 {
1909 pdu.put_uint8(1, addrIsStaticRandom ? 0x01 : 0x00);
1910 pdu.put_eui48(1+1, addr);
1911 check_range();
1912 }
1913
1914 constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override {
1915 return 1+6;
1916 }
1917
1918 /**
1919 * Returns whether the device address is static random (true) or public (false).
1920 */
1921 constexpr bool isStaticRandomAddress() const noexcept { return pdu.get_uint16_nc(1) == 0x01; }
1922
1923 /**
1924 * Returns the device address
1925 */
1926 inline EUI48 getAddress() const noexcept { return pdu.get_eui48_nc(1+1); }
1927
1928 std::string getName() const noexcept override {
1929 return "SMPIdentAddrInfo";
1930 }
1931
1932 protected:
1933 std::string valueString() const noexcept override {
1934 const std::string ats = isStaticRandomAddress() ? "static-random" : "public";
1935 return "address["+getAddress().toString()+", "+ats+"]";
1936 }
1937 };
1938
1939 /**
1940 * Vol 3, Part H: 3.6.6 Signing Information message.
1941 * <pre>
1942 * Vol 3 (Host), Part H (SM): 3 (SMP), 3.6 SECURITY IN BLUETOOTH LOW ENERGY
1943 * Vol 3 (Host), Part H (SM): 3 (SMP), 3.6.1 Key distribution and generation
1944 * Vol 3 (Host), Part H (SM): 2 (SM), 2.4.1 Definition of keys and values
1945 * Vol 3 (Host), Part H (SM): 2 (SM), 2.4.2.2 Generation of CSRK
1946 * </pre>
1947 *
1948 * Opcode::SIGNING_INFORMATION
1949 *
1950 * <pre>
1951 * [uint8_t opcode]
1952 * jau::uint128_t signature_key
1953 * </pre>
1954 *
1955 * Message is used in the Transport Specific Key Distribution
1956 * to distribute the Connection Signature Resolving Key (CSRK), which a device uses to sign data (ATT Signed Write).
1957 * <p>
1958 * The message shall only be sent when the link has been encrypted or re-encrypted using the generated key.
1959 * </p>
1960 * <p>
1961 * Legacy: #5 in distribution, last value.<br>
1962 * Secure Connection: #3 in distribution, last value.
1963 * </p>
1964 * <p>
1965 * Notable: No endian wise conversion shall occur on this data,
1966 * since the encryption values are interpreted as little-endian or as a byte stream.
1967 * </p>
1968 */
1970 {
1971 public:
1972 SMPSignInfoMsg(const uint8_t* source, const jau::nsize_t length)
1973 : SMPEncKeyByteStream(source, length)
1974 {
1975 check_range();
1977 }
1978
1979 SMPSignInfoMsg(const jau::uint128dp_t & signature_key)
1980 : SMPEncKeyByteStream(Opcode::SIGNING_INFORMATION, 1+16)
1981 {
1982 jau::put_uint128(pdu.get_wptr() + 1, signature_key);
1983 check_range();
1984 }
1985
1986 constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override {
1987 return 16;
1988 }
1989
1990 /**
1991 * Returns the 128-bit Connection Signature Resolving Key (CSRK, 16 octets)
1992 * <p>
1993 * The 128-bit CSRK value being distributed,
1994 * see Vol 3, Part H, 2.4.2.2 SM - Definition of keys and values - Generation of CSRK.
1995 * </p>
1996 */
1997 constexpr jau::uint128dp_t getCSRK() const noexcept { return jau::get_uint128(pdu.get_ptr() + 1); }
1998
1999 std::string getName() const noexcept override {
2000 return "SMPSignInfo";
2001 }
2002
2003 protected:
2004 std::string valueString() const noexcept override { // hex-fmt aligned with btmon
2005 return "size "+std::to_string(getDataSize())+", csrk "+
2006 jau::bytesHexString(pdu.get_ptr_nc(1), 0, getDataSize(), true /* lsbFirst */);
2007 }
2008 };
2009
2010 /**
2011 * Vol 3, Part H: 3.6.7 Security Request message.
2012 * <pre>
2013 * Vol 3 (Host), Part H (SM): 3 (SMP), 3.6 SECURITY IN BLUETOOTH LOW ENERGY
2014 * </pre>
2015 *
2016 * Opcode::SECURITY_REQUEST
2017 *
2018 * <pre>
2019 * [uint8_t opcode]
2020 * uint8_t auth_req_mask
2021 * </pre>
2022 *
2023 * Message is used by the slave to request that the master initiates security with the requested security properties,<br>
2024 * see Vol 3 (Host), Part H (SM): 2 (SM), 2.4 SECURITY IN BLUETOOTH LOW ENERGY, 2.4.6 Slave Security Request
2025 */
2026 class SMPSecurityReqMsg final : public SMPPDUMsg
2027 {
2028 private:
2029 SMPAuthReqs authReqMask;
2030 public:
2031 SMPSecurityReqMsg(const uint8_t* source, const jau::nsize_t length)
2032 : SMPPDUMsg(source, length, 2),
2033 authReqMask(static_cast<SMPAuthReqs>( pdu.get_uint8_nc(1) ))
2034 {
2035 check_range();
2037 }
2038
2039 SMPSecurityReqMsg(const SMPAuthReqs auth_req_mask)
2040 : SMPPDUMsg(Opcode::SECURITY_REQUEST, 1+1), authReqMask(auth_req_mask)
2041 {
2042 pdu.put_uint8(1, direct_bt::number(authReqMask));
2043 check_range();
2044 }
2045
2046 constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override {
2047 return 1;
2048 }
2049
2050 /**
2051 * Returns the SMPPairingMsg::AuthRequirements (1 octet)
2052 * <p>
2053 * The AuthReq field is a bit field that indicates the requested security properties,<br>
2054 * see Vol 3 (Host), Part H (SM): 2 (SM), 2.3 Pairing Methods, 2.3.1 Security Properties,<br>
2055 * for the STK or LTK and GAP bonding information,<br>
2056 * see Vol 3 (Host), Part C (GAP): 9.4 Bonding Modes and Procedures<br>
2057 * </p>
2058 */
2059 constexpr SMPAuthReqs getAuthReqMask() const noexcept {
2060 return authReqMask;
2061 }
2062 constexpr bool isAuthRequirementBitSet(const SMPAuthReqs bit) const noexcept {
2063 return is_set(authReqMask, bit);
2064 }
2065
2066 std::string getName() const noexcept override {
2067 return "SMPSecurityReq";
2068 }
2069
2070 protected:
2071 std::string valueString() const noexcept override {
2072 return "auth_req "+to_string(getAuthReqMask());
2073 }
2074 };
2075
2076 /**@}*/
2077
2078} // namespace direct_bt
2079
2080#endif /* SMP_TYPES_HPP_ */
#define E_FILE_LINE
Vol 3, Part H: 3.6.2 Encryption Information message.
Definition: SMPTypes.hpp:1679
constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override
Returns the required data size according to the specified packet, which should be within 0-22 or 64 o...
Definition: SMPTypes.hpp:1695
std::string getName() const noexcept override
Definition: SMPTypes.hpp:1708
constexpr jau::uint128dp_t getLTK() const noexcept
Returns the 128-bit Long Term Key (16 octets)
Definition: SMPTypes.hpp:1706
SMPEncInfoMsg(const jau::uint128dp_t &long_term_key)
Definition: SMPTypes.hpp:1688
SMPEncInfoMsg(const uint8_t *source, const jau::nsize_t length)
Definition: SMPTypes.hpp:1681
std::string valueString() const noexcept override
Definition: SMPTypes.hpp:1713
Tag type to group all SMP messages covering encryption keys, treated as byte stream (all of them).
Definition: SMPTypes.hpp:1019
~SMPEncKeyByteStream() noexcept override=default
SMPEncKeyByteStream(const Opcode opc, const jau::nsize_t size)
Persistent memory, w/ ownership .
Definition: SMPTypes.hpp:1026
SMPEncKeyByteStream(const uint8_t *source, const jau::nsize_t size)
Persistent memory, w/ ownership .
Definition: SMPTypes.hpp:1022
SMPException(std::string const &m, const char *file, int line) noexcept
Definition: SMPTypes.hpp:64
SMPException(std::string type, std::string const &m, const char *file, int line) noexcept
Definition: SMPTypes.hpp:60
A thread safe SMP handler associated to one device via one L2CAP connection.
Definition: SMPHandler.hpp:163
Vol 3, Part H: 3.6.5 Identity Address Information message.
Definition: SMPTypes.hpp:1897
constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override
Returns the required data size according to the specified packet, which should be within 0-22 or 64 o...
Definition: SMPTypes.hpp:1914
constexpr bool isStaticRandomAddress() const noexcept
Returns whether the device address is static random (true) or public (false).
Definition: SMPTypes.hpp:1921
std::string getName() const noexcept override
Definition: SMPTypes.hpp:1928
SMPIdentAddrInfoMsg(const bool addrIsStaticRandom, const EUI48 &addr)
Definition: SMPTypes.hpp:1906
EUI48 getAddress() const noexcept
Returns the device address.
Definition: SMPTypes.hpp:1926
std::string valueString() const noexcept override
Definition: SMPTypes.hpp:1933
SMPIdentAddrInfoMsg(const uint8_t *source, const jau::nsize_t length)
Definition: SMPTypes.hpp:1899
Vol 3, Part H: 3.6.4 Identify Information message.
Definition: SMPTypes.hpp:1830
std::string valueString() const noexcept override
Definition: SMPTypes.hpp:1864
std::string getName() const noexcept override
Definition: SMPTypes.hpp:1859
SMPIdentInfoMsg(const uint8_t *source, const jau::nsize_t length)
Definition: SMPTypes.hpp:1832
constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override
Returns the required data size according to the specified packet, which should be within 0-22 or 64 o...
Definition: SMPTypes.hpp:1846
constexpr jau::uint128dp_t getIRK() const noexcept
Returns the 128-bit Identity Resolving Key (IRK, 16 octets)
Definition: SMPTypes.hpp:1857
SMPIdentInfoMsg(const jau::uint128dp_t &identity_resolving_key)
Definition: SMPTypes.hpp:1839
Vol 3, Part H: 3.6.3 Master Identification message.
Definition: SMPTypes.hpp:1750
constexpr uint16_t getEDIV() const noexcept
Returns the 16-bit EDIV value (2 octets) being distributed.
Definition: SMPTypes.hpp:1777
constexpr uint64_t getRand() const noexcept
Returns the 64-bit Rand value (8 octets) being distributed.
Definition: SMPTypes.hpp:1785
constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override
Returns the required data size according to the specified packet, which should be within 0-22 or 64 o...
Definition: SMPTypes.hpp:1767
std::string getName() const noexcept override
Definition: SMPTypes.hpp:1787
std::string valueString() const noexcept override
Definition: SMPTypes.hpp:1792
SMPMasterIdentMsg(const uint8_t *source, const jau::nsize_t length)
Definition: SMPTypes.hpp:1752
SMPMasterIdentMsg(const uint16_t ediv, const uint64_t &rand)
Definition: SMPTypes.hpp:1759
SMPOpcodeException(std::string const &m, const char *file, int line) noexcept
Definition: SMPTypes.hpp:75
Handles the Security Manager Protocol (SMP) using Protocol Data Unit (PDU) encoded messages over L2CA...
Definition: SMPTypes.hpp:842
static std::string getOpcodeString(const Opcode opc) noexcept
Definition: SMPTypes.cpp:379
virtual ~SMPPDUMsg() noexcept=default
constexpr Opcode getOpcode() const noexcept
SMP Command Codes Vol 3, Part H (SM): 3.3.
Definition: SMPTypes.hpp:961
jau::POctets pdu
actual received PDU
Definition: SMPTypes.hpp:905
constexpr uint64_t getTimestamp() const noexcept
Definition: SMPTypes.hpp:958
virtual std::string getName() const noexcept
Definition: SMPTypes.hpp:1000
constexpr jau::nsize_t getPDUParamSize() const noexcept
Returns the actual PDU size less one octet for the opcode, which should result in 0-22 octets or 64 o...
Definition: SMPTypes.hpp:978
static std::unique_ptr< const SMPPDUMsg > getSpecialized(const uint8_t *buffer, jau::nsize_t const buffer_size) noexcept
Return a newly created specialized instance pointer to base class.
Definition: SMPTypes.cpp:426
virtual std::string valueString() const noexcept
Definition: SMPTypes.hpp:899
virtual constexpr_cxx20 jau::nsize_t getDataSize() const noexcept
Returns the required data size according to the specified packet, which should be within 0-22 or 64 o...
Definition: SMPTypes.hpp:988
static constexpr uint8_t number(const Opcode rhs) noexcept
Definition: SMPTypes.hpp:865
void checkOpcode(const Opcode exp1, const Opcode exp2) const
Definition: SMPTypes.hpp:885
SMPPDUMsg(const uint8_t *source, const jau::nsize_t size, const jau::nsize_t min_size)
Persistent memory, w/ ownership .
Definition: SMPTypes.hpp:926
virtual std::string baseString() const noexcept
Definition: SMPTypes.hpp:895
virtual std::string toString() const noexcept
Definition: SMPTypes.hpp:1004
Opcode
SMP Command Codes Vol 3, Part H (SM): 3.3.
Definition: SMPTypes.hpp:845
SMPPDUMsg(const Opcode opc, const jau::nsize_t size)
Persistent memory, w/ ownership .
Definition: SMPTypes.hpp:934
SMPPDUMsg(const uint8_t *source, const jau::nsize_t size)
Persistent memory, w/ ownership .
Definition: SMPTypes.hpp:920
constexpr jau::nsize_t getDataOffset() const noexcept
Returns the octet offset to the data segment in this PDU including the mandatory opcode,...
Definition: SMPTypes.hpp:998
uint64_t ts_creation
creation timestamp in milliseconds
Definition: SMPTypes.hpp:908
void checkOpcode(const Opcode expected) const
Definition: SMPTypes.hpp:877
static T * clone(const T &source) noexcept
Clone template for convenience, based on derived class's copy-constructor.
Definition: SMPTypes.hpp:956
SMPPacketException(std::string const &m, const char *file, int line) noexcept
Definition: SMPTypes.hpp:70
Vol 3, Part H: 3.5.3 Pairing Confirm message.
Definition: SMPTypes.hpp:1247
std::string valueString() const noexcept override
Definition: SMPTypes.hpp:1287
constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override
Returns the required data size according to the specified packet, which should be within 0-22 or 64 o...
Definition: SMPTypes.hpp:1263
constexpr jau::uint128dp_t getConfirmValue() const noexcept
Returns the 128-bit Confirm value (16 octets)
Definition: SMPTypes.hpp:1280
SMPPairConfirmMsg(const uint8_t *source, const jau::nsize_t length)
Definition: SMPTypes.hpp:1249
SMPPairConfirmMsg(const jau::uint128dp_t &confirm_value)
Definition: SMPTypes.hpp:1256
std::string getName() const noexcept override
Definition: SMPTypes.hpp:1282
Vol 3, Part H: 3.5.7 Pairing DHKey Check message.
Definition: SMPTypes.hpp:1550
constexpr jau::uint128dp_t getDHKeyCheck() const noexcept
Returns the 128-bit DHKey Check value (16 octets)
Definition: SMPTypes.hpp:1573
std::string valueString() const noexcept override
Definition: SMPTypes.hpp:1580
SMPPairDHKeyCheckMsg(const jau::uint128dp_t &dhkey_check_values)
Definition: SMPTypes.hpp:1559
SMPPairDHKeyCheckMsg(const uint8_t *source, const jau::nsize_t length)
Definition: SMPTypes.hpp:1552
constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override
Returns the required data size according to the specified packet, which should be within 0-22 or 64 o...
Definition: SMPTypes.hpp:1566
std::string getName() const noexcept override
Definition: SMPTypes.hpp:1575
Vol 3, Part H: 3.5.5 Pairing Failed message.
Definition: SMPTypes.hpp:1403
static constexpr uint8_t number(const ReasonCode rhs) noexcept
Definition: SMPTypes.hpp:1422
std::string valueString() const noexcept override
Definition: SMPTypes.hpp:1454
SMPPairFailedMsg(const uint8_t *source, const jau::nsize_t length)
Definition: SMPTypes.hpp:1427
SMPPairFailedMsg(const ReasonCode rc)
Definition: SMPTypes.hpp:1434
constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override
Returns the required data size according to the specified packet, which should be within 0-22 or 64 o...
Definition: SMPTypes.hpp:1441
constexpr ReasonCode getReasonCode() const noexcept
Definition: SMPTypes.hpp:1445
std::string getName() const noexcept override
Definition: SMPTypes.hpp:1449
Vol 3, Part H: 3.5.6 Pairing Public Key message.
Definition: SMPTypes.hpp:1484
constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override
Returns the required data size according to the specified packet, which should be within 0-22 or 64 o...
Definition: SMPTypes.hpp:1501
SMPPairPubKeyMsg(const jau::uint256dp_t &pub_key_x, const jau::uint256dp_t &pub_key_y)
Definition: SMPTypes.hpp:1493
std::string valueString() const noexcept override
Definition: SMPTypes.hpp:1520
constexpr jau::uint256dp_t getPubKeyY() const noexcept
Returns the 256-bit Public Key Y value (32 octets)
Definition: SMPTypes.hpp:1513
SMPPairPubKeyMsg(const uint8_t *source, const jau::nsize_t length)
Definition: SMPTypes.hpp:1486
constexpr jau::uint256dp_t getPubKeyX() const noexcept
Returns the 256-bit Public Key X value (32 octets)
Definition: SMPTypes.hpp:1508
std::string getName() const noexcept override
Definition: SMPTypes.hpp:1515
Vol 3, Part H: 3.5.4 Pairing Random message.
Definition: SMPTypes.hpp:1344
SMPPairRandMsg(const uint8_t *source, const jau::nsize_t length)
Definition: SMPTypes.hpp:1346
constexpr jau::uint128dp_t getRand() const noexcept
Returns the 128-bit Random value (16 octets)
Definition: SMPTypes.hpp:1376
SMPPairRandMsg(const jau::uint128dp_t &random_value)
Definition: SMPTypes.hpp:1353
std::string getName() const noexcept override
Definition: SMPTypes.hpp:1378
constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override
Returns the required data size according to the specified packet, which should be within 0-22 or 64 o...
Definition: SMPTypes.hpp:1360
std::string valueString() const noexcept override
Definition: SMPTypes.hpp:1383
Vol 3, Part H: 3.5.1 Pairing Request message.
Definition: SMPTypes.hpp:1085
constexpr SMPAuthReqs getAuthReqMask() const noexcept
Returns the Authentication Requirements mask.
Definition: SMPTypes.hpp:1156
constexpr SMPKeyType getInitKeyDist() const noexcept
Returns the Initiator Key Distribution field, which defines which keys the initiator shall distribute...
Definition: SMPTypes.hpp:1180
SMPPairingMsg(const bool request_, const uint8_t *source, const jau::nsize_t length)
Definition: SMPTypes.hpp:1093
constexpr bool isAuthRequirementBitSet(const SMPAuthReqs bit) const noexcept
Definition: SMPTypes.hpp:1159
std::string valueString() const noexcept override
Definition: SMPTypes.hpp:1202
constexpr SMPKeyType getRespKeyDist() const noexcept
Return the Responder Key Distribution field, which defines which keys the responder shall distribute ...
Definition: SMPTypes.hpp:1193
constexpr SMPIOCapability getIOCapability() const noexcept
Returns the IO capability bit field.
Definition: SMPTypes.hpp:1133
std::string getName() const noexcept override
Definition: SMPTypes.hpp:1197
constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override
Returns the required data size according to the specified packet, which should be within 0-22 or 64 o...
Definition: SMPTypes.hpp:1122
constexpr uint8_t getMaxEncryptionKeySize() const noexcept
This value defines the maximum encryption key size in octets that the device can support.
Definition: SMPTypes.hpp:1167
SMPPairingMsg(const bool request_, const SMPIOCapability ioc, const SMPOOBDataFlag odf, const SMPAuthReqs auth_req_mask, const uint8_t maxEncKeySize, const SMPKeyType initiator_key_dist_, const SMPKeyType responder_key_dist_)
Definition: SMPTypes.hpp:1104
constexpr SMPOOBDataFlag getOOBDataFlag() const noexcept
Returns the OBB authenticate data flag.
Definition: SMPTypes.hpp:1144
Vol 3, Part H: 3.5.8 Passkey Entry: Keypress notification messages.
Definition: SMPTypes.hpp:1603
static constexpr uint8_t number(const TypeCode rhs) noexcept
Definition: SMPTypes.hpp:1612
std::string getName() const noexcept override
Definition: SMPTypes.hpp:1639
constexpr TypeCode getTypeCode() const noexcept
Definition: SMPTypes.hpp:1635
std::string valueString() const noexcept override
Definition: SMPTypes.hpp:1644
SMPPasskeyNotification(const TypeCode tc)
Definition: SMPTypes.hpp:1624
constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override
Returns the required data size according to the specified packet, which should be within 0-22 or 64 o...
Definition: SMPTypes.hpp:1631
SMPPasskeyNotification(const uint8_t *source, const jau::nsize_t length)
Definition: SMPTypes.hpp:1617
Vol 3, Part H: 3.6.7 Security Request message.
Definition: SMPTypes.hpp:2027
constexpr SMPAuthReqs getAuthReqMask() const noexcept
Returns the SMPPairingMsg::AuthRequirements (1 octet)
Definition: SMPTypes.hpp:2059
SMPSecurityReqMsg(const uint8_t *source, const jau::nsize_t length)
Definition: SMPTypes.hpp:2031
SMPSecurityReqMsg(const SMPAuthReqs auth_req_mask)
Definition: SMPTypes.hpp:2039
std::string getName() const noexcept override
Definition: SMPTypes.hpp:2066
std::string valueString() const noexcept override
Definition: SMPTypes.hpp:2071
constexpr bool isAuthRequirementBitSet(const SMPAuthReqs bit) const noexcept
Definition: SMPTypes.hpp:2062
constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override
Returns the required data size according to the specified packet, which should be within 0-22 or 64 o...
Definition: SMPTypes.hpp:2046
Vol 3, Part H: 3.6.6 Signing Information message.
Definition: SMPTypes.hpp:1970
constexpr_cxx20 jau::nsize_t getDataSize() const noexcept override
Returns the required data size according to the specified packet, which should be within 0-22 or 64 o...
Definition: SMPTypes.hpp:1986
std::string getName() const noexcept override
Definition: SMPTypes.hpp:1999
SMPSignInfoMsg(const uint8_t *source, const jau::nsize_t length)
Definition: SMPTypes.hpp:1972
std::string valueString() const noexcept override
Definition: SMPTypes.hpp:2004
SMPSignInfoMsg(const jau::uint128dp_t &signature_key)
Definition: SMPTypes.hpp:1979
constexpr jau::uint128dp_t getCSRK() const noexcept
Returns the 128-bit Connection Signature Resolving Key (CSRK, 16 octets)
Definition: SMPTypes.hpp:1997
SMPValueException(std::string const &m, const char *file, int line) noexcept
Definition: SMPTypes.hpp:81
Persistent endian aware octet data, i.e.
Definition: octets.hpp:560
RuntimeException(std::string type, std::string const &m, const char *file, int line) noexcept
void put_eui48(const nsize_t i, const EUI48 &v)
Definition: octets.hpp:355
constexpr void put_uint8_nc(const nsize_t i, const uint8_t v) noexcept
Definition: octets.hpp:335
uint8_t * get_wptr() noexcept
Definition: octets.hpp:474
void put_uint8(const nsize_t i, const uint8_t v)
Definition: octets.hpp:331
constexpr uint16_t get_uint16_nc(const nsize_t i) const noexcept
Definition: octets.hpp:184
constexpr nsize_t size() const noexcept
Returns the used memory size for read and write operations, may be zero.
Definition: octets.hpp:162
EUI48 get_eui48_nc(const nsize_t i) const noexcept
Definition: octets.hpp:200
void check_range(const nsize_t i, const nsize_t count, const char *file, int line) const
Definition: octets.hpp:148
constexpr uint8_t get_uint8_nc(const nsize_t i) const noexcept
Definition: octets.hpp:168
constexpr uint8_t const * get_ptr() const noexcept
Definition: octets.hpp:272
constexpr uint8_t const * get_ptr_nc(const nsize_t i) const noexcept
Definition: octets.hpp:277
static bool matches(const BTDeviceRef &device)
constexpr uint128dp_t get_uint128(uint8_t const *buffer) noexcept
See get_uint16() for reference.
Definition: byte_util.hpp:765
constexpr void put_uint256(uint8_t *buffer, const uint256dp_t &v) noexcept
See put_uint16() for reference.
Definition: byte_util.hpp:815
constexpr uint16_t get_uint16(uint8_t const *buffer) noexcept
Returns a uint16_t value from the given byte address using packed_t to resolve a potential memory ali...
Definition: byte_util.hpp:661
constexpr uint256dp_t get_uint256(uint8_t const *buffer) noexcept
See get_uint16() for reference.
Definition: byte_util.hpp:831
lb_endian_t
Simplified reduced endian type only covering little- and big-endian.
Definition: byte_util.hpp:227
constexpr void put_uint64(uint8_t *buffer, const uint64_t &v) noexcept
See put_uint16() for reference.
Definition: byte_util.hpp:716
constexpr void put_uint16(uint8_t *buffer, const uint16_t v) noexcept
Put the given uint16_t value into the given byte address using packed_t to resolve a potential memory...
Definition: byte_util.hpp:638
constexpr void put_uint128(uint8_t *buffer, const uint128dp_t &v) noexcept
See put_uint16() for reference.
Definition: byte_util.hpp:749
constexpr uint64_t get_uint64(uint8_t const *buffer) noexcept
See get_uint16() for reference.
Definition: byte_util.hpp:732
#define constexpr_cxx20
constexpr qualifier replacement for C++20 constexpr.
constexpr bool hasSMPPairingFinished(const SMPPairingState state) noexcept
Returns true if the given SMPPairingState indicates a finished pairing process, i....
Definition: SMPTypes.hpp:178
constexpr bool hasSMPIOCapabilityFullInput(const SMPIOCapability ioc) noexcept
Definition: SMPTypes.hpp:244
SMPAuthReqs
SMP Authentication Requirements Bits, denotes specific bits or whole protocol uint8_t bit-mask.
Definition: SMPTypes.hpp:283
constexpr bool isSMPPairingAllowingInput(const SMPPairingState state, const SMPPairingState inputSpec) noexcept
Returns true if the given SMPPairingState indicates a pairing process waiting for user input,...
Definition: SMPTypes.hpp:200
SMPPairingState
SMP Pairing Process state definition.
Definition: SMPTypes.hpp:107
constexpr bool isSMPPairingUserInteraction(const SMPPairingState state) noexcept
Returns true if the given SMPPairingState indicates expected user interaction, i.e.
Definition: SMPTypes.hpp:187
constexpr bool isSMPPairingActive(const SMPPairingState state) noexcept
Returns true if the given SMPPairingState indicates an active pairing process, i.e.
Definition: SMPTypes.hpp:168
constexpr SMPKeyType & operator&=(SMPKeyType &store, const SMPKeyType &rhs) noexcept
Definition: SMPTypes.hpp:476
constexpr SMPKeyType & operator^=(SMPKeyType &store, const SMPKeyType &rhs) noexcept
Definition: SMPTypes.hpp:462
SMPKeyType
SMP Key Type for Distribution, indicates keys distributed in the Transport Specific Key Distribution ...
Definition: SMPTypes.hpp:415
constexpr bool hasSMPIOCapabilityAnyIO(const SMPIOCapability ioc) noexcept
Definition: SMPTypes.hpp:233
std::string toPassKeyString(const std::uint32_t passKey) noexcept
Returns given passKey ranging [0..999999] as a canonical string, e.g.
Definition: SMPTypes.cpp:72
constexpr SMPKeyType & operator|=(SMPKeyType &store, const SMPKeyType &rhs) noexcept
Definition: SMPTypes.hpp:469
std::string to_String(const SMPLongTermKey &ltk) noexcept
Definition: SMPTypes.hpp:583
constexpr SMPIOCapability to_SMPIOCapability(const uint8_t v) noexcept
Definition: SMPTypes.hpp:223
SMPOOBDataFlag
Vol 3, Part H, 2.3.3 OOB authentication data.
Definition: SMPTypes.hpp:253
SMPIOCapability
Vol 3, Part H, 2.3.2 IO capabilities.
Definition: SMPTypes.hpp:209
std::string to_string(const SMPKeyType mask) noexcept
Definition: SMPTypes.cpp:273
PairingMode getPairingMode(const bool use_sc, const SMPAuthReqs authReqs_ini, const SMPIOCapability ioCap_ini, const SMPOOBDataFlag oobFlag_ini, const SMPAuthReqs authReqs_res, const SMPIOCapability ioCap_res, const SMPOOBDataFlag oobFlag_res) noexcept
Returns the PairingMode derived from both devices' sets of SMPAuthReqs, SMPIOCapability and SMPOOBDat...
Definition: SMPTypes.cpp:153
constexpr bool hasSMPIOCapabilityBinaryInput(const SMPIOCapability ioc) noexcept
Definition: SMPTypes.hpp:239
@ SECURE_CONNECTIONS
If LE Secure Connections pairing is supported by the device, then the SC field shall be set to 1,...
@ RFU_2
Reserved for future use.
@ MITM
A device sets the MITM flag to one to request an Authenticated security property for the STK when usi...
@ BONDING
Indicate bonding being requested by the initiating device.
@ BONDING_RFU
Reserved for future use.
@ KEYPRESS
The keypress field is used only in the Passkey Entry protocol and shall be ignored in other protocols...
@ CT2_H7_FUNC_SUPPORT
The CT2 field shall be set to 1 upon transmission to indicate support for the h7 function.
@ RFU_1
Reserved for future use.
@ OOB_EXPECTED
Phase 2: Authentication (MITM) OOB data expected now, see PairingMode::OUT_OF_BAND.
@ REQUESTED_BY_RESPONDER
Phase 0: Pairing requested by responding (slave) device via SMPSecurityReqMsg.
@ PASSKEY_NOTIFY
Phase 2: Authentication (MITM) PASSKEY (produced by this responder adapter, acting as peripheral GATT...
@ COMPLETED
Phase 3: Key & value distribution completed by responding (slave) device sending SMPIdentInfoMsg (#1)...
@ NUMERIC_COMPARE_EXPECTED
Phase 2: Authentication (MITM) Numeric Comparison Reply expected now, see PairingMode::NUMERIC_COMPAR...
@ NONE
No pairing in process.
@ PASSKEY_EXPECTED
Phase 2: Authentication (MITM) PASSKEY expected now, see PairingMode::PASSKEY_ENTRY_ini.
@ FAILED
Pairing failed.
@ FEATURE_EXCHANGE_STARTED
Phase 1: Pairing requested by initiating (master) device via SMPPairingMsg.
@ FEATURE_EXCHANGE_COMPLETED
Phase 1: Pairing responded by responding (slave) device via SMPPairingMsg.
@ KEY_DISTRIBUTION
Phase 3: Key & value distribution started after SMPPairConfirmMsg or SMPPairPubKeyMsg (LE Secure Conn...
@ LINK_KEY
SMP on the LE transport: Indicate that the device would like to derive the Link Key from the LTK.
@ RFU_4
Reserved for future use.
@ SIGN_KEY
Indicates that the device shall distribute CSRK using the Signing Information command.
@ ENC_KEY
LE legacy pairing: Indicates device shall distribute LTK using the Encryption Information command,...
@ ID_KEY
Indicates that the device shall distribute IRK using the Identity Information command followed by its...
@ RFU_3
Reserved for future use.
@ OOB_AUTH_DATA_REMOTE_PRESENT
OOB_AUTH_DATA_REMOTE_PRESENT.
@ OOB_AUTH_DATA_NOT_PRESENT
OOB_AUTH_DATA_NOT_PRESENT.
@ KEYBOARD_ONLY
Keyboard input only, value 2.
@ UNSET
Denoting unset value, i.e.
@ NO_INPUT_NO_OUTPUT
No input not output, value 3.
@ DISPLAY_ONLY
Display output only, value 0.
@ DISPLAY_YES_NO
Display output and boolean confirmation input keys only, value 1.
@ KEYBOARD_DISPLAY
Display output and keyboard input, value 4.
@ SMP_TIMEOUT_MS
SMP Timeout Vol 3, Part H (SM): 3.4.
constexpr LE_Features operator^(const LE_Features lhs, const LE_Features rhs) noexcept
Definition: BTTypes0.hpp:204
bool operator==(const BTAdapter &lhs, const BTAdapter &rhs) noexcept
Definition: BTAdapter.hpp:1348
void clear() noexcept
Clears internal list.
std::string to_string(const DiscoveryPolicy v) noexcept
Definition: BTAdapter.cpp:58
constexpr ScanType operator~(const ScanType val) noexcept
Definition: BTTypes0.hpp:359
PairingMode
Bluetooth secure pairing mode.
Definition: BTTypes0.hpp:317
bool operator!=(const BTAdapter &lhs, const BTAdapter &rhs) noexcept
Definition: BTAdapter.hpp:1351
constexpr bool is_set(const LE_Features mask, const LE_Features bit) noexcept
Definition: BTTypes0.hpp:219
constexpr uint8_t number(const DiscoveryPolicy rhs) noexcept
Definition: BTAdapter.hpp:100
@ UNSET
Security Level not set, value 0.
constexpr BTGattChar::PropertyBitVal operator&(const BTGattChar::PropertyBitVal lhs, const BTGattChar::PropertyBitVal rhs) noexcept
Definition: BTGattChar.hpp:424
constexpr BTGattChar::PropertyBitVal operator|(const BTGattChar::PropertyBitVal lhs, const BTGattChar::PropertyBitVal rhs) noexcept
Definition: BTGattChar.hpp:421
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
Definition: int_types.hpp:53
constexpr T max(const T x, const T y) noexcept
Returns the maximum of two integrals (w/ branching) in O(1)
Definition: base_math.hpp:191
std::string bytesHexString(const void *data, const nsize_t offset, const nsize_t length, const bool lsbFirst, const bool lowerCase=true) noexcept
Produce a hexadecimal string representation of the given byte values.
std::string to_hexstring(value_type const &v) noexcept
Produce a lower-case hexadecimal string representation of the given pointer.
__pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros.
Definition: backtrace.hpp:32
uint64_t getCurrentMilliseconds() noexcept
Returns current monotonic time in milliseconds.
Definition: basic_types.cpp:64
STL namespace.
SMP Identity Resolving Key, used for platform agnostic persistence.
Definition: SMPTypes.hpp:636
SMP Long Term Key, used for platform agnostic persistence.
Definition: SMPTypes.hpp:552
SMP Signature Resolving Key, used for platform agnostic persistence.
Definition: SMPTypes.hpp:712
A packed 48 bit EUI-48 identifier, formerly known as MAC-48 or simply network device MAC address (Med...
Definition: eui48.hpp:324
std::string toString() const noexcept
Definition: eui48.cpp:167
A 128-bit packed uint8_t data array.
Definition: int_types.hpp:114
uint8_t data[16]
Definition: int_types.hpp:114
A 256-bit packed uint8_t data array.
Definition: int_types.hpp:158