aboutsummaryrefslogtreecommitdiffstats
path: root/java/org
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2020-11-14 08:36:51 +0100
committerSven Gothel <[email protected]>2020-11-14 08:36:51 +0100
commit5d4e3f2856e427f6faa8c23220917ca869d990c2 (patch)
treea4549154f64b434c1b40609af77ea333561ef660 /java/org
parentfc602c4dc6676def5e8b1b936bb84e6e5eda6642 (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.java12
-rw-r--r--java/org/tinyb/BluetoothDevice.java91
-rw-r--r--java/org/tinyb/PairingMode.java20
-rw-r--r--java/org/tinyb/SMPPairingState.java122
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;
+ }
+}