diff options
author | Sven Gothel <[email protected]> | 2020-11-14 08:36:51 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2020-11-14 08:36:51 +0100 |
commit | 5d4e3f2856e427f6faa8c23220917ca869d990c2 (patch) | |
tree | a4549154f64b434c1b40609af77ea333561ef660 /java/org | |
parent | fc602c4dc6676def5e8b1b936bb84e6e5eda6642 (diff) |
Add SMP changed to *.java API (AdapterStatusListener devicePairingState(..), BluetoothDevice setPairing*(), add SMPPairingState; Patch examples..
Disclaimer: This is WIP and not functional yet for GATT processing!
Committed and pushed for review.
Last known well working version pre SMP: commit 17f865093d4a757f8cd9abb1c8d4b6b8e729591e
Diffstat (limited to 'java/org')
-rw-r--r-- | java/org/tinyb/AdapterStatusListener.java | 12 | ||||
-rw-r--r-- | java/org/tinyb/BluetoothDevice.java | 91 | ||||
-rw-r--r-- | java/org/tinyb/PairingMode.java | 20 | ||||
-rw-r--r-- | java/org/tinyb/SMPPairingState.java | 122 |
4 files changed, 219 insertions, 26 deletions
diff --git a/java/org/tinyb/AdapterStatusListener.java b/java/org/tinyb/AdapterStatusListener.java index 12e42e70..6004c38c 100644 --- a/java/org/tinyb/AdapterStatusListener.java +++ b/java/org/tinyb/AdapterStatusListener.java @@ -113,6 +113,18 @@ public abstract class AdapterStatusListener { public void deviceConnected(final BluetoothDevice device, final short handle, final long timestamp) { } /** + * An already connected {@link BluetoothDevice}'s {@link SMPPairingState} has changed. + * <p> + * If currentMode == {@link PairingMode#NONE}, the device is not paired, otherwise it is paired using the given {@link PairingMode}. + * </p> + * @param device the device which {@link PairingMode} has been changed. + * @param state the current {@link SMPPairingState} of the connected device, see DBTDevice::getCurrentPairingState() + * @param mode the current {@link PairingMode} of the connected device, see DBTDevice::getCurrentPairingMode() + * @param timestamp the time in monotonic milliseconds when this event occurred. See {@link BluetoothUtils#currentTimeMillis()}. + */ + public void devicePairingState(final BluetoothDevice device, final SMPPairingState state, final PairingMode mode, final long timestamp) {} + + /** * {@link BluetoothDevice} got disconnected. * @param device the device which has been disconnected with zeroed connection handle. * @param reason the {@link HCIStatusCode} reason for disconnection diff --git a/java/org/tinyb/BluetoothDevice.java b/java/org/tinyb/BluetoothDevice.java index 2cad6ac5..feee1290 100644 --- a/java/org/tinyb/BluetoothDevice.java +++ b/java/org/tinyb/BluetoothDevice.java @@ -189,50 +189,105 @@ public interface BluetoothDevice extends BluetoothObject * @implNote secure pairing with JustWorks method on direct_bt.tinyb, * but device must be {@link #connectLE(short, short, short, short, short, short)} before. * Use {@link #pair(int[])} + * @implNote not implemented in direct_bt.tinyb */ boolean pair() throws BluetoothException; /** - * The device is securely paired with PasskeyEntry or JustWorks. + * Method sets the given passkey entry, see {@link PairingMode#PASSKEY_ENTRY}. * <p> - * The device must be {@link #connectLE(short, short, short, short, short, short) connected} - * before pairing. + * Call this method if the device shall be securely paired with {@link PairingMode#PASSKEY_ENTRY}, + * when notified via {@link AdapterStatusListener#devicePairingState(BluetoothDevice, SMPPairingState, PairingMode, long) devicePairingState}. + * <p> + * If returning {@link HCIStatusCode#SUCCESS}, caller shall continue listening to + * {@link AdapterStatusListener#devicePairingState(BluetoothDevice, SMPPairingState, PairingMode, long) devicePairingState} + * to wait for either {@link SMPPairingState#PROCESS_COMPLETED} or {@link SMPPairingState#FAILED}. * </p> + * @param passkey used for {@link PairingMode#PASSKEY_ENTRY} method. + * Will be encrypted before sending to counter-party. + * + * @return {@link HCIStatusCode#SUCCESS} if the command has been accepted, otherwise {@link HCIStatusCode} may disclose reason for rejection. + * @see PairingMode + * @see SMPPairingState + * @see AdapterStatusListener#devicePairingState(BluetoothDevice, SMPPairingState, PairingMode, long) + * @see #setPairingPasskey(String) + * @see #setPairingNumericComparison(boolean) + * @see #getCurrentPairingMode() + * @see #getCurrentPairingState() + * @since 2.1.0 + * @implNote not implemented in tinyb.dbus + */ + HCIStatusCode setPairingPasskey(final int passkey); + + /** + * Method sets the numeric comparison result, see {@link PairingMode#NUMERIC_COMPARISON}. + * <p> + * Call this method if the device shall be securely paired with {@link PairingMode#NUMERIC_COMPARISON}, + * when notified via {@link AdapterStatusListener#devicePairingState(BluetoothDevice, SMPPairingState, PairingMode, long) devicePairingState}. * <p> - * If passkey is null or an empty string, JustWorks method is being used, otherwise PasskeyEntry. + * If returning {@link HCIStatusCode#SUCCESS}, caller shall continue listening to + * {@link AdapterStatusListener#devicePairingState(BluetoothDevice, SMPPairingState, PairingMode, long) devicePairingState} + * to wait for either {@link SMPPairingState#PROCESS_COMPLETED} or {@link SMPPairingState#FAILED}. * </p> - * @param passkey the optional secret used for secure PasskeyEntry method. - * Will be encrypted before sending to counterparty. - * Can be null or an empty string, in which case JustWork method is used. + * @param equal used for {@link PairingMode#NUMERIC_COMPARISON} method. + * Will be encrypted before sending to counter-party. + * * @return {@link HCIStatusCode#SUCCESS} if the command has been accepted, otherwise {@link HCIStatusCode} may disclose reason for rejection. + * @see PairingMode + * @see SMPPairingState + * @see AdapterStatusListener#devicePairingState(BluetoothDevice, SMPPairingState, PairingMode, long) + * @see #setPairingPasskey(String) + * @see #setPairingNumericComparison(boolean) + * @see #getCurrentPairingMode() + * @see #getCurrentPairingState() * @since 2.1.0 * @implNote not implemented in tinyb.dbus */ - HCIStatusCode pair(final String passkey) throws BluetoothException; + HCIStatusCode setPairingNumericComparison(final boolean equal); /** - * Returns a vector of supported PairingMode by the device. + * Returns the current {@link PairingMode} used by the device. + * <p> + * If the device is not paired, the current mode is {@link PairingMode#NONE}. + * </p> + * <p> + * If the Pairing Feature Exchange is completed, i.e. {@link SMPPairingState#FEATURE_EXCHANGE_COMPLETED} + * as notified by + * {@link AdapterStatusListener#devicePairingState(BluetoothDevice, SMPPairingState, PairingMode, long) devicePairingState} + * the current mode reflects the currently used {@link PairingMode}. + * </p> * <p> - * The device must be {@link #connectLE(short, short, short, short, short, short) connected} - * before querying this status. FIXME? + * In case the Pairing Feature Exchange is in progress, the current mode is {@link PairingMode#NEGOTIATING}. * </p> - * @return list of supported PairingMode, empty if pairing is not supported. + * @return current PairingMode. + * @see PairingMode + * @see SMPPairingState + * @see AdapterStatusListener#devicePairingState(BluetoothDevice, SMPPairingState, PairingMode, long) + * @see #setPairingPasskey(String) + * @see #setPairingNumericComparison(boolean) + * @see #getCurrentPairingMode() + * @see #getCurrentPairingState() * @since 2.1.0 * @implNote not implemented in tinyb.dbus */ - List<PairingMode> getSupportedPairingModes() throws BluetoothException; + PairingMode getCurrentPairingMode(); /** - * Returns a vector of required PairingMode by the device. + * Returns the current {@link SMPPairingState}. * <p> - * The device must be {@link #connectLE(short, short, short, short, short, short) connected} - * before querying this status. FIXME? + * If the device is not paired, the current state is {@link SMPPairingState#NONE}. * </p> - * @return list of required PairingMode, empty if pairing is not required. + * @see PairingMode + * @see SMPPairingState + * @see AdapterStatusListener#devicePairingState(BluetoothDevice, SMPPairingState, PairingMode, long) + * @see #setPairingPasskey(String) + * @see #setPairingNumericComparison(boolean) + * @see #getCurrentPairingMode() + * @see #getCurrentPairingState() * @since 2.1.0 * @implNote not implemented in tinyb.dbus */ - List<PairingMode> getRequiredPairingModes() throws BluetoothException; + SMPPairingState getCurrentPairingState(); /** * Remove this device from the system (like an unpair). diff --git a/java/org/tinyb/PairingMode.java b/java/org/tinyb/PairingMode.java index 3f06d8e3..fb657b70 100644 --- a/java/org/tinyb/PairingMode.java +++ b/java/org/tinyb/PairingMode.java @@ -33,19 +33,22 @@ package org.tinyb; * <p> * See {@link #get(int)} for its native integer mapping. * </p> + * @see SMPPairingState * @since 2.1.0 */ public enum PairingMode { /** No pairing mode, implying no secure connections, no encryption and no MITM protection. */ NONE ((byte)0), + /** Pairing mode in negotiating, i.e. Pairing Feature Exchange in progress. */ + NEGOTIATING ((byte)1), /** Just Works. Random key exchange with encryption but no MITM protection. */ - JUST_WORKS ((byte)1), + JUST_WORKS ((byte)2), /** Passkey Entry. A known digit sequence (PIN) must be given as a secret to be validated on the device. Random key exchange with additional secret (PIN) and encryption and MITM protection. */ - PASSKEY_ENTRY ((byte)2), + PASSKEY_ENTRY ((byte)3), /** Visual numeric comparison of digit sequence (PIN) shown on both devices, peripheral and host, to be answered. Random key exchange with additional secret (PIN) and encryption and MITM protection. */ - NUMERIC_COMPARISON ((byte)3), + NUMERIC_COMPARISON ((byte)4), /** Utilizing a second factor secret to be used as a secret, e.g. NFC field. Random key exchange with additional secret (2FA) and encryption and potential MITM protection. */ - OUT_OF_BAND ((byte)4); + OUT_OF_BAND ((byte)5); public final byte value; @@ -71,10 +74,11 @@ public enum PairingMode { */ public static PairingMode get(final byte value) { switch(value) { - case (byte) 0x01: return JUST_WORKS; - case (byte) 0x02: return PASSKEY_ENTRY; - case (byte) 0x03: return NUMERIC_COMPARISON; - case (byte) 0x04: return OUT_OF_BAND; + case (byte) 0x01: return NEGOTIATING; + case (byte) 0x02: return JUST_WORKS; + case (byte) 0x03: return PASSKEY_ENTRY; + case (byte) 0x04: return NUMERIC_COMPARISON; + case (byte) 0x05: return OUT_OF_BAND; default: return NONE; } } diff --git a/java/org/tinyb/SMPPairingState.java b/java/org/tinyb/SMPPairingState.java new file mode 100644 index 00000000..77cb66b1 --- /dev/null +++ b/java/org/tinyb/SMPPairingState.java @@ -0,0 +1,122 @@ +/** + * Author: Sven Gothel <[email protected]> + * Copyright (c) 2020 Gothel Software e.K. + * Copyright (c) 2020 ZAFENA AB + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package org.tinyb; + +/** + * SMP Pairing Process state definition + * <pre> + * Vol 3, Part H (SM): APPENDIX C MESSAGE SEQUENCE CHARTS + * </pre> + * <p> + * See {@link #get(int)} for its native integer mapping. + * </p> + * @see PairingMode + * @since 2.1.0 + */ +public enum SMPPairingState { + /** No pairing in process. Current {@link PairingMode} shall be {@link PairingMode#NONE}. */ + NONE((byte)0), + + /** Pairing failed. Current {@link PairingMode} shall be {@link PairingMode#NONE}. */ + FAILED((byte)1), + + /** + * Phase 0: Pairing requested by responding (slave) device via SMPSecurityReqMsg.<br> + * Signals initiating (host) device to start the Pairing Feature Exchange.<br> + * Current {@link PairingMode} shall be {@link PairingMode#NEGOTIATING}. + */ + REQUESTED_BY_RESPONDER((byte)2), + + /** + * Phase 1: Pairing requested by initiating (master) device via SMPPairingMsg.<br> + * Starts the Pairing Feature Exchange.<br> + * Current {@link PairingMode} shall be {@link PairingMode#NEGOTIATING}. + */ + FEATURE_EXCHANGE_STARTED((byte)3), + + /** + * Phase 1: Pairing responded by responding (slave) device via SMPPairingMsg.<br> + * Completes the Pairing Feature Exchange. Optional user input shall be given for Phase 2.<br> + * Current {@link PairingMode} shall be set to a definitive value. + */ + FEATURE_EXCHANGE_COMPLETED((byte)4), + + /** Phase 2: Authentication (MITM) PASSKEY expected, see {@link PairingMode#PASSKEY_ENTRY} */ + PASSKEY_EXPECTED((byte)5), + /** Phase 2: Authentication (MITM) Numeric Comparison Reply expected, see {@link PairingMode#NUMERIC_COMPARISON} */ + NUMERIC_COMPARISON_EXPECTED((byte)6), + /** Phase 2: Authentication (MITM) OOB data expected, see {@link PairingMode#OUT_OF_BAND} */ + OOB_EXPECTED((byte)7), + + /** Phase 2: Pairing process started by SMPPairConfirmMsg or SMPPairPubKeyMsg (LE Secure Connection) exchange between initiating (master) and responding (slave) device. */ + PROCESS_STARTED((byte)8), + + /** + * Phase 2: Pairing process is completed by responding (slave) device sending SMPPairRandMsg.<br> + * The link is assumed to be encrypted from here on. + */ + PROCESS_COMPLETED((byte)9); + + public final byte value; + + /** + * Maps the specified name to a constant of {@link SMPPairingState}. + * <p> + * Implementation simply returns {@link #valueOf(String)}. + * This maps the constant names itself to their respective constant. + * </p> + * @param name the string name to be mapped to a constant of this enum type. + * @return the corresponding constant of this enum type. + * @throws IllegalArgumentException if the specified name can't be mapped to a constant of this enum type + * as described above. + */ + public static SMPPairingState get(final String name) throws IllegalArgumentException { + return valueOf(name); + } + + /** + * Maps the specified integer value to a constant of {@link SMPPairingState}. + * @param value the integer value to be mapped to a constant of this enum type. + * @return the corresponding constant of this enum type, using {@link #NONE} if not supported. + */ + public static SMPPairingState get(final byte value) { + switch(value) { + case (byte) 0x01: return FAILED; + case (byte) 0x02: return REQUESTED_BY_RESPONDER; + case (byte) 0x03: return FEATURE_EXCHANGE_STARTED; + case (byte) 0x04: return FEATURE_EXCHANGE_COMPLETED; + case (byte) 0x05: return PASSKEY_EXPECTED; + case (byte) 0x06: return NUMERIC_COMPARISON_EXPECTED; + case (byte) 0x07: return OOB_EXPECTED; + case (byte) 0x08: return PROCESS_STARTED; + case (byte) 0x09: return PROCESS_COMPLETED; + default: return NONE; + } + } + + SMPPairingState(final byte v) { + value = v; + } +} |