Direct-BT  2.3.1
Direct-BT - Direct Bluetooth Programming.
BTSecurityRegistry.java
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 package org.direct_bt;
27 
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.Iterator;
31 import java.util.List;
32 
33 /**
34  * Application toolkit providing BT security setup and its device association
35  * on a pattern matching basis, i.e. EUI48Sub or name-sub.
36  */
37 public class BTSecurityRegistry {
38  public static final int NO_PASSKEY = -1;
39 
40  /**
41  * Entry specifying SMP security details associated to a device query via {@link EUI48Sub} or {@code nameSub}.
42  */
43  public static class Entry {
44  public EUI48Sub addrSub;
45  public String nameSub;
46 
50  public int passkey = NO_PASSKEY;
51 
52  public Entry(final EUI48Sub addrSub) {
53  this.addrSub = addrSub;
54  this.nameSub = "";
55  }
56  public Entry(final String nameSub) {
57  this.addrSub = EUI48Sub.ALL_DEVICE;
58  this.nameSub = nameSub;
59  }
60 
61  public boolean isSecLevelOrIOCapSet() {
63  }
64  public BTSecurityLevel getSecLevel() { return sec_level; }
65  public SMPIOCapability getIOCap() { return io_cap; }
66 
67  public boolean isSecurityAutoEnabled() { return SMPIOCapability.UNSET != io_cap_auto; }
69 
70  public int getPairingPasskey() { return passkey; }
71 
72  public boolean getPairingNumericComparison() { return true; }
73 
74  @Override
75  public String toString() {
76  final String id = EUI48Sub.ALL_DEVICE.equals(addrSub) ? "'"+nameSub+"'" : addrSub.toString();
77  return "BTSecurityDetail["+id+", lvl "+sec_level+", io "+io_cap+", auto-io "+io_cap_auto+", passkey "+passkey+"]";
78  }
79  }
80  static private List<BTSecurityRegistry.Entry> devicesSecDetails = new ArrayList<BTSecurityRegistry.Entry>();
81 
82  /**
83  * Interface for user defined {@link EUI48} address and name {@link BTSecurityRegistry.Entry} matching criteria and algorithm.
84  */
85  public static interface AddressNameEntryMatch {
86  /**
87  * Return {@code true} if the given {@code address} or {@code name} matches
88  * with the {@link BTSecurityRegistry.Entry}.
89  *
90  * @param address {@link EUI48} address
91  * @param name optional name, maybe empty
92  * @param e {@link BTSecurityRegistry.Entry} entry
93  */
94  public boolean match(final EUI48 address, final String name, final BTSecurityRegistry.Entry e);
95  }
96  /**
97  * Interface for user defined {@link EUI48Sub} addressSub and name {@link BTSecurityRegistry.Entry} matching criteria and algorithm.
98  */
99  public static interface AddressSubNameEntryMatch {
100  /**
101  * Return {@code true} if the given {@code addressSub} or {@code name} matches
102  * with the {@link BTSecurityRegistry.Entry}.
103  *
104  * @param addressSub {@link EUI48Sub} address
105  * @param name optional name, maybe empty
106  * @param e {@link BTSecurityRegistry.Entry} entry
107  */
108  public boolean match(final EUI48Sub addressSub, final String name, final BTSecurityRegistry.Entry e);
109  }
110  /**
111  * Interface for user defined name {@link BTSecurityRegistry.Entry} matching criteria and algorithm.
112  */
113  public static interface NameEntryMatch {
114  /**
115  * Return {@code true} if the given {@code name} matches
116  * with the {@link BTSecurityRegistry.Entry}.
117  *
118  * @param name
119  * @param e {@link BTSecurityRegistry.Entry} entry
120  */
121  public boolean match(final String name, final BTSecurityRegistry.Entry e);
122  }
123 
124  /**
125  * Returns a matching {@link BTSecurityRegistry.Entry} with the given {@code addr} and/or {@code name}
126  * <p>
127  * Matching criteria and algorithm is defined by the given {@link AddressNameEntryMatch}.
128  * </p>
129  */
130  public static BTSecurityRegistry.Entry get(final EUI48 addr, final String name, final AddressNameEntryMatch m) {
131  for(final Iterator<BTSecurityRegistry.Entry> i=devicesSecDetails.iterator(); i.hasNext(); ) {
132  final BTSecurityRegistry.Entry sd = i.next();
133  if( m.match(addr, name, sd) ) {
134  return sd;
135  }
136  }
137  return null;
138  }
139  /**
140  * Returns a matching {@link BTSecurityRegistry.Entry} with the given {@code addrSub} and/or {@code name}.
141  * <p>
142  * Matching criteria and algorithm is defined by the given {@link AddressSubNameEntryMatch}.
143  * </p>
144  */
145  public static BTSecurityRegistry.Entry get(final EUI48Sub addrSub, final String name, final AddressSubNameEntryMatch m) {
146  for(final Iterator<BTSecurityRegistry.Entry> i=devicesSecDetails.iterator(); i.hasNext(); ) {
147  final BTSecurityRegistry.Entry sd = i.next();
148  if( m.match(addrSub, name, sd) ) {
149  return sd;
150  }
151  }
152  return null;
153  }
154  /**
155  * Returns a matching {@link BTSecurityRegistry.Entry} with the given {@code name}.
156  * <p>
157  * Matching criteria and algorithm is defined by the given {@link NameEntryMatch}.
158  * </p>
159  */
160  public static BTSecurityRegistry.Entry get(final String name, final NameEntryMatch m) {
161  for(final Iterator<BTSecurityRegistry.Entry> i=devicesSecDetails.iterator(); i.hasNext(); ) {
162  final BTSecurityRegistry.Entry sd = i.next();
163  if( m.match(name, sd) ) {
164  return sd;
165  }
166  }
167  return null;
168  }
169 
170  /**
171  * Returns a matching {@link BTSecurityRegistry.Entry},
172  * - which {@link BTSecurityRegistry.Entry#addrSub} is set and the given {@code addr} starts with {@link BTSecurityRegistry.Entry#addrSub}, or
173  * - which {@link BTSecurityRegistry.Entry#nameSub} is set and the given {@code name} starts with {@link BTSecurityRegistry.Entry#nameSub}.
174  *
175  * Otherwise {@code null} is returned.
176  */
177  public static BTSecurityRegistry.Entry getStartOf(final EUI48 addr, final String name) {
178  return get(addr, name, (final EUI48 a, final String n, final BTSecurityRegistry.Entry e) -> {
179  return ( e.addrSub.length > 0 && 0 == a.indexOf(e.addrSub) ) ||
180  (e.nameSub.length() > 0 && n.startsWith(e.nameSub) );
181  });
182  }
183  /**
184  * Returns a matching {@link BTSecurityRegistry.Entry},
185  * - which {@link BTSecurityRegistry.Entry#addrSub} is set and the given {@code addrSub} starts with {@link BTSecurityRegistry.Entry#addrSub}, or
186  * - which {@link BTSecurityRegistry.Entry#nameSub} is set and the given {@code name} starts with {@link BTSecurityRegistry.Entry#nameSub}.
187  *
188  * Otherwise {@code null} is returned.
189  */
190  public static BTSecurityRegistry.Entry getStartOf(final EUI48Sub addrSub, final String name) {
191  return get(addrSub, name, (final EUI48Sub as, final String n, final BTSecurityRegistry.Entry e) -> {
192  return ( e.addrSub.length > 0 && 0 == as.indexOf(e.addrSub) ) ||
193  ( e.nameSub.length() > 0 && n.startsWith(e.nameSub) );
194  });
195  }
196  /**
197  * Returns a matching {@link BTSecurityRegistry.Entry},
198  * - which {@link BTSecurityRegistry.Entry#nameSub} is set and the given {@code name} starts with {@link BTSecurityRegistry.Entry#nameSub}.
199  *
200  * Otherwise {@code null} is returned.
201  */
202  public static BTSecurityRegistry.Entry getStartOf(final String name) {
203  return get(name, (final String n, final BTSecurityRegistry.Entry e) -> {
204  return e.nameSub.length() > 0 && n.startsWith(e.nameSub);
205  });
206  }
207 
208  /**
209  * Returns a matching {@link BTSecurityRegistry.Entry},
210  * - which {@link BTSecurityRegistry.Entry#addrSub} is set and the given {@code addrSub} is equal with {@link BTSecurityRegistry.Entry#addrSub}, or
211  * - which {@link BTSecurityRegistry.Entry#nameSub} is set and the given {@code name} is equal with {@link BTSecurityRegistry.Entry#nameSub}.
212  *
213  * Otherwise {@code null} is returned.
214  */
215  public static BTSecurityRegistry.Entry getEqual(final EUI48Sub addrSub, final String name) {
216  return get(addrSub, name, (final EUI48Sub as, final String n, final BTSecurityRegistry.Entry e) -> {
217  return ( e.addrSub.length > 0 && as.equals(e.addrSub) ) ||
218  ( e.nameSub.length() > 0 && n.equals(e.nameSub) );
219  });
220  }
221  /**
222  * Returns a matching {@link BTSecurityRegistry.Entry},
223  * - which {@link BTSecurityRegistry.Entry#nameSub} is set and the given {@code name} is equal with {@link BTSecurityRegistry.Entry#nameSub}.
224  *
225  * Otherwise {@code null} is returned.
226  */
227  public static BTSecurityRegistry.Entry getEqual(final String name) {
228  return get(name, (final String n, final BTSecurityRegistry.Entry e) -> {
229  return e.nameSub.length() > 0 && n.equals(e.nameSub);
230  });
231  }
232 
233  /**
234  * Returns the reference of the current list of {@link BTSecurityRegistry.Entry}, not a copy.
235  */
236  public static List<BTSecurityRegistry.Entry> getEntries() {
237  return devicesSecDetails;
238  }
239 
240  /**
241  * Determines whether the given {@code addrOrNameSub} is a {@link EUI48Sub} or just a {@code name}
242  * and retrieves an entry. If no entry exists, creates a new entry.
243  * <p>
244  * Implementation uses {@link #getEqual(EUI48Sub, String)} to find a pre-existing entry.
245  * </p>
246  * @param addrOrNameSub either a {@link EUI48Sub} or just a name
247  * @return new or existing instance
248  */
249  public static BTSecurityRegistry.Entry getOrCreate(final String addrOrNameSub) {
250  final EUI48Sub addr1 = new EUI48Sub();
251  final StringBuilder errmsg = new StringBuilder();
252  BTSecurityRegistry.Entry sec = null;
253  if( EUI48Sub.scanEUI48Sub(addrOrNameSub, addr1, errmsg) ) {
254  sec = getEqual(addr1, "");
255  if( null == sec ) {
256  sec = new BTSecurityRegistry.Entry( addr1 );
257  devicesSecDetails.add(sec);
258  }
259  } else {
260  sec = getEqual(addrOrNameSub);
261  if( null == sec ) {
262  sec = new BTSecurityRegistry.Entry( addrOrNameSub );
263  devicesSecDetails.add(sec);
264  }
265  }
266  return sec;
267  }
268 
269  /**
270  * Clears internal list
271  */
272  public static void clear() {
273  devicesSecDetails.clear();
274  }
275 
276  public static String allToString() {
277  return Arrays.toString( devicesSecDetails.toArray() );
278  }
279 }
org.direct_bt.BTSecurityRegistry.Entry.getSecLevel
BTSecurityLevel getSecLevel()
Definition: BTSecurityRegistry.java:64
org.direct_bt.BTSecurityRegistry.Entry
Entry specifying SMP security details associated to a device query via EUI48Sub or.
Definition: BTSecurityRegistry.java:43
org.direct_bt.BTSecurityRegistry.Entry.sec_level
BTSecurityLevel sec_level
Definition: BTSecurityRegistry.java:47
org.direct_bt.BTSecurityRegistry.AddressNameEntryMatch
Interface for user defined EUI48 address and name BTSecurityRegistry.Entry matching criteria and algo...
Definition: BTSecurityRegistry.java:85
org.direct_bt.SMPIOCapability
SMP IO Capability value.
Definition: SMPIOCapability.java:37
org.direct_bt.BTSecurityRegistry.NO_PASSKEY
static final int NO_PASSKEY
Definition: BTSecurityRegistry.java:38
org.direct_bt.BTSecurityLevel
Bluetooth Security Level.
Definition: BTSecurityLevel.java:38
org.direct_bt.BTSecurityRegistry.Entry.toString
String toString()
Definition: BTSecurityRegistry.java:75
org.direct_bt.EUI48Sub
A 48 bit EUI-48 sub-identifier, see EUI48.
Definition: EUI48Sub.java:31
org.direct_bt.EUI48
A packed 48 bit EUI-48 identifier, formerly known as MAC-48 or simply network device MAC address (Med...
Definition: EUI48.java:37
org.direct_bt.BTSecurityRegistry.Entry.passkey
int passkey
Definition: BTSecurityRegistry.java:50
org.direct_bt.BTSecurityRegistry.getStartOf
static BTSecurityRegistry.Entry getStartOf(final String name)
Returns a matching BTSecurityRegistry.Entry,.
Definition: BTSecurityRegistry.java:202
org.direct_bt.EUI48Sub.ALL_DEVICE
static final EUI48Sub ALL_DEVICE
EUI48Sub MAC address matching all device, i.e.
Definition: EUI48Sub.java:35
org.direct_bt.EUI48Sub.equals
final boolean equals(final Object obj)
Definition: EUI48Sub.java:138
org.direct_bt.BTSecurityRegistry.Entry.io_cap
SMPIOCapability io_cap
Definition: BTSecurityRegistry.java:48
org.direct_bt.BTSecurityRegistry.getStartOf
static BTSecurityRegistry.Entry getStartOf(final EUI48 addr, final String name)
Returns a matching BTSecurityRegistry.Entry,.
Definition: BTSecurityRegistry.java:177
org.direct_bt.BTSecurityRegistry.Entry.isSecurityAutoEnabled
boolean isSecurityAutoEnabled()
Definition: BTSecurityRegistry.java:67
org.direct_bt.SMPIOCapability.UNSET
UNSET
Denoting unset value, i.e.
Definition: SMPIOCapability.java:49
org.direct_bt.BTSecurityRegistry.Entry.isSecLevelOrIOCapSet
boolean isSecLevelOrIOCapSet()
Definition: BTSecurityRegistry.java:61
org.direct_bt.BTSecurityRegistry.allToString
static String allToString()
Definition: BTSecurityRegistry.java:276
org.direct_bt.BTSecurityRegistry.Entry.getSecurityAutoIOCap
SMPIOCapability getSecurityAutoIOCap()
Definition: BTSecurityRegistry.java:68
org.direct_bt.BTSecurityRegistry.getOrCreate
static BTSecurityRegistry.Entry getOrCreate(final String addrOrNameSub)
Determines whether the given.
Definition: BTSecurityRegistry.java:249
org.direct_bt.BTSecurityRegistry.Entry.nameSub
String nameSub
Definition: BTSecurityRegistry.java:45
org.direct_bt.BTSecurityLevel.UNSET
UNSET
Security Level not set, value 0.
Definition: BTSecurityLevel.java:40
org.direct_bt.BTSecurityRegistry.Entry.io_cap_auto
SMPIOCapability io_cap_auto
Definition: BTSecurityRegistry.java:49
org.direct_bt.BTSecurityRegistry.Entry.getIOCap
SMPIOCapability getIOCap()
Definition: BTSecurityRegistry.java:65
org.direct_bt.BTSecurityRegistry
Application toolkit providing BT security setup and its device association on a pattern matching basi...
Definition: BTSecurityRegistry.java:37
org.direct_bt.BTSecurityRegistry.NameEntryMatch.match
boolean match(final String name, final BTSecurityRegistry.Entry e)
Return.
org.direct_bt.EUI48Sub.scanEUI48Sub
static boolean scanEUI48Sub(final String str, final EUI48Sub dest, final StringBuilder errmsg)
Fills given EUI48Sub instance via given string representation.
Definition: EUI48Sub.java:64
org.direct_bt.BTSecurityRegistry.getEqual
static BTSecurityRegistry.Entry getEqual(final String name)
Returns a matching BTSecurityRegistry.Entry,.
Definition: BTSecurityRegistry.java:227
org.direct_bt.BTSecurityRegistry.AddressNameEntryMatch.match
boolean match(final EUI48 address, final String name, final BTSecurityRegistry.Entry e)
Return.
org.direct_bt.BTSecurityRegistry.getEqual
static BTSecurityRegistry.Entry getEqual(final EUI48Sub addrSub, final String name)
Returns a matching BTSecurityRegistry.Entry,.
Definition: BTSecurityRegistry.java:215
org.direct_bt.BTSecurityRegistry.getEntries
static List< BTSecurityRegistry.Entry > getEntries()
Returns the reference of the current list of BTSecurityRegistry.Entry, not a copy.
Definition: BTSecurityRegistry.java:236
org.direct_bt.BTSecurityRegistry.clear
static void clear()
Clears internal list.
Definition: BTSecurityRegistry.java:272
org.direct_bt.EUI48Sub.toString
final String toString()
Definition: EUI48Sub.java:259
org.direct_bt.BTSecurityRegistry.getStartOf
static BTSecurityRegistry.Entry getStartOf(final EUI48Sub addrSub, final String name)
Returns a matching BTSecurityRegistry.Entry,.
Definition: BTSecurityRegistry.java:190
org.direct_bt.BTSecurityRegistry.NameEntryMatch
Interface for user defined name BTSecurityRegistry.Entry matching criteria and algorithm.
Definition: BTSecurityRegistry.java:113
org.direct_bt.BTSecurityRegistry.Entry.addrSub
EUI48Sub addrSub
Definition: BTSecurityRegistry.java:44
org.direct_bt.BTSecurityRegistry.Entry.getPairingPasskey
int getPairingPasskey()
Definition: BTSecurityRegistry.java:70
org.direct_bt.BTSecurityRegistry.Entry.Entry
Entry(final EUI48Sub addrSub)
Definition: BTSecurityRegistry.java:52
org.direct_bt.BTSecurityRegistry.Entry.Entry
Entry(final String nameSub)
Definition: BTSecurityRegistry.java:56
org.direct_bt.BTSecurityRegistry.AddressSubNameEntryMatch.match
boolean match(final EUI48Sub addressSub, final String name, final BTSecurityRegistry.Entry e)
Return.
org.direct_bt.BTSecurityRegistry.Entry.getPairingNumericComparison
boolean getPairingNumericComparison()
Definition: BTSecurityRegistry.java:72
org.direct_bt.BTSecurityRegistry.AddressSubNameEntryMatch
Interface for user defined EUI48Sub addressSub and name BTSecurityRegistry.Entry matching criteria an...
Definition: BTSecurityRegistry.java:99