Direct-BT  2.3.1
Direct-BT - Direct Bluetooth Programming.
SMPLongTermKeyInfo.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 /**
29  * SMP Long Term Key Info, used for platform agnostic persistence.
30  * <p>
31  * Notable: No endian wise conversion shall occur on this data,
32  * since the encryption values are interpreted as a byte stream.
33  * </p>
34  * <p>
35  * Byte layout must be synchronized with native direct_bt::SMPLongTermKeyInfo
36  * </p>
37  * @since 2.2.0
38  */
39 public class SMPLongTermKeyInfo {
40  /**
41  * {@link SMPLongTermKeyInfo} Property Bits
42  */
43  static public enum PropertyType {
44  /** No specific property */
45  NONE((byte)0),
46  /** Responder Key (LL slave). Absence indicates Initiator Key (LL master). */
47  RESPONDER((byte)0x01),
48  /** Authentication used. */
49  AUTH((byte)0x02),
50  /** Secure Connection used. */
51  SC((byte)0x04);
52 
53  public final byte value;
54 
55  /**
56  * Maps the specified name to a constant of {@link PropertyType}.
57  * <p>
58  * Implementation simply returns {@link #valueOf(String)}.
59  * This maps the constant names itself to their respective constant.
60  * </p>
61  * @param name the string name to be mapped to a constant of this enum type.
62  * @return the corresponding constant of this enum type.
63  * @throws IllegalArgumentException if the specified name can't be mapped to a constant of this enum type
64  * as described above.
65  */
66  public static PropertyType get(final String name) throws IllegalArgumentException {
67  return valueOf(name);
68  }
69 
70  /**
71  * Maps the specified integer value to a constant of {@link PropertyType}.
72  * @param value the integer value to be mapped to a constant of this enum type.
73  * @return the corresponding constant of this enum type, using {@link #NONE} if not supported.
74  */
75  public static PropertyType get(final byte value) {
76  switch(value) {
77  case (byte) 0x01: return RESPONDER;
78  case (byte) 0x02: return AUTH;
79  case (byte) 0x04: return SC;
80  default: return NONE;
81  }
82  }
83 
84  PropertyType(final byte v) {
85  value = v;
86  }
87  }
88 
89  /**
90  * {@link SMPLongTermKeyInfo} {@link PropertyType} Bit Mask
91  */
92  static public class Properties {
93  /** The {@link PropertyType} bit mask */
94  public byte mask;
95 
96  public Properties(final byte v) {
97  mask = v;
98  }
99 
100  public boolean isEmpty() { return 0 == mask; }
101  public boolean isSet(final PropertyType bit) { return 0 != ( mask & bit.value ); }
102  public void set(final PropertyType bit) { mask = (byte) ( mask | bit.value ); }
103 
104  @Override
105  public String toString() {
106  int count = 0;
107  final StringBuilder out = new StringBuilder();
108  if( isSet(PropertyType.RESPONDER) ) {
109  out.append(PropertyType.RESPONDER.name()); count++;
110  }
111  if( isSet(PropertyType.AUTH) ) {
112  if( 0 < count ) { out.append(", "); }
113  out.append(PropertyType.AUTH.name()); count++;
114  }
115  if( isSet(PropertyType.SC) ) {
116  if( 0 < count ) { out.append(", "); }
117  out.append(PropertyType.SC.name()); count++;
118  }
119  return "["+out.toString()+"]";
120  }
121  }
122 
123  /** {@link Properties} bit mask. 1 octet or 8 bits. */
125 
126  /** Encryption Size, 1 octets or 8 bits. Is zero if key is invalid. */
127  public byte enc_size;
128  /** Encryption Diversifier, 2 octets or 16 bits. */
129  public byte ediv[/*2*/];
130  /** Random Number, 8 octets or 64 bits. */
131  public byte rand[/*8*/];
132  /** Long Term Key (LTK), 16 octets or 128 bits. */
133  public byte ltk[/*16*/];
134 
135  /**
136  * Size of the byte stream representation in bytes (28)
137  * @see #getStream(byte[], int)
138  */
139  public static final int byte_size = 1+1+2+8+16;
140 
141  /** Construct instance via given source byte array */
142  public SMPLongTermKeyInfo(final byte source[], final int pos) {
143  if( byte_size > ( source.length - pos ) ) {
144  throw new IllegalArgumentException("Stream ( "+source.length+" - "+pos+" ) < "+byte_size+" bytes");
145  }
146  ediv = new byte[2];
147  rand = new byte[8];
148  ltk = new byte[16];
149  putStream(source, pos);
150  }
151 
152  /** Construct emoty unset instance. */
154  properties = new Properties((byte)0);
155  enc_size = (byte)0;
156  ediv = new byte[2];
157  rand = new byte[8];
158  ltk = new byte[16];
159  }
160 
161  /**
162  * Method transfers all bytes representing a SMPLongTermKeyInfo from the given
163  * source array at the given position into this instance.
164  * <p>
165  * Implementation is consistent with {@link #getStream(byte[], int)}.
166  * </p>
167  * @param source the source array
168  * @param pos starting position in the source array
169  * @see #getStream(byte[], int)
170  */
171  public void putStream(final byte[] source, int pos) {
172  if( byte_size > ( source.length - pos ) ) {
173  throw new IllegalArgumentException("Stream ( "+source.length+" - "+pos+" ) < "+byte_size+" bytes");
174  }
175  properties = new Properties(source[pos++]);
176  enc_size = source[pos++];
177  ediv[0] = source[pos++];
178  ediv[1] = source[pos++];
179  System.arraycopy(source, pos, rand, 0, 8); pos+=8;
180  System.arraycopy(source, pos, ltk, 0, 16); pos+=16;
181  }
182 
183  /**
184  * Method transfers all bytes representing this instance into the given
185  * destination array at the given position.
186  * <p>
187  * Implementation is consistent with {@link #SMPLongTermKeyInfo(byte[], int)}.
188  * </p>
189  * @param sink the destination array
190  * @param pos starting position in the destination array
191  * @see #SMPLongTermKeyInfo(byte[], int)
192  * @see #putStream(byte[], int)
193  */
194  public final void getStream(final byte[] sink, int pos) {
195  if( byte_size > ( sink.length - pos ) ) {
196  throw new IllegalArgumentException("Stream ( "+sink.length+" - "+pos+" ) < "+byte_size+" bytes");
197  }
198  sink[pos++] = properties.mask;
199  sink[pos++] = enc_size;
200  sink[pos++] = ediv[0];
201  sink[pos++] = ediv[1];
202  System.arraycopy(rand, 0, sink, pos, 8); pos+=8;
203  System.arraycopy(ltk, 0, sink, pos, 16); pos+=16;
204  }
205 
206  public final boolean isValid() { return 0 != enc_size; }
207 
208  public final boolean isResponder() { return properties.isSet(PropertyType.RESPONDER); }
209 
210  @Override
211  public String toString() { // hex-fmt aligned with btmon
212  return "LTK[props "+properties.toString()+", enc_size "+enc_size+
213  ", ediv "+BTUtils.bytesHexString(ediv, 0, -1, false /* lsbFirst */)+
214  ", rand "+BTUtils.bytesHexString(rand, 0, -1, false /* lsbFirst */)+
215  ", ltk "+BTUtils.bytesHexString(ltk, 0, -1, true /* lsbFirst */)+
216  ", valid "+isValid()+
217  "]";
218  }
219 
220 };
org.direct_bt.SMPLongTermKeyInfo.putStream
void putStream(final byte[] source, int pos)
Method transfers all bytes representing a SMPLongTermKeyInfo from the given source array at the given...
Definition: SMPLongTermKeyInfo.java:171
org.direct_bt.SMPLongTermKeyInfo.Properties.isSet
boolean isSet(final PropertyType bit)
Definition: SMPLongTermKeyInfo.java:101
org.direct_bt.SMPLongTermKeyInfo.byte_size
static final int byte_size
Size of the byte stream representation in bytes (28)
Definition: SMPLongTermKeyInfo.java:139
org.direct_bt.SMPLongTermKeyInfo.rand
byte rand[]
Random Number, 8 octets or 64 bits.
Definition: SMPLongTermKeyInfo.java:131
org.direct_bt.SMPLongTermKeyInfo
SMP Long Term Key Info, used for platform agnostic persistence.
Definition: SMPLongTermKeyInfo.java:39
org.direct_bt.SMPLongTermKeyInfo.PropertyType.NONE
NONE
No specific property.
Definition: SMPLongTermKeyInfo.java:45
org.direct_bt.SMPLongTermKeyInfo.PropertyType
SMPLongTermKeyInfo Property Bits
Definition: SMPLongTermKeyInfo.java:43
org.direct_bt.SMPLongTermKeyInfo.Properties
SMPLongTermKeyInfo PropertyType Bit Mask
Definition: SMPLongTermKeyInfo.java:92
org.direct_bt.SMPLongTermKeyInfo.enc_size
byte enc_size
Encryption Size, 1 octets or 8 bits.
Definition: SMPLongTermKeyInfo.java:127
org.direct_bt.SMPLongTermKeyInfo.Properties.Properties
Properties(final byte v)
Definition: SMPLongTermKeyInfo.java:96
org.direct_bt.SMPLongTermKeyInfo.Properties.mask
byte mask
The PropertyType bit mask.
Definition: SMPLongTermKeyInfo.java:94
org.direct_bt.BTUtils
Definition: BTUtils.java:29
org.direct_bt.SMPLongTermKeyInfo.toString
String toString()
Definition: SMPLongTermKeyInfo.java:211
org.direct_bt.SMPLongTermKeyInfo.Properties.isEmpty
boolean isEmpty()
Definition: SMPLongTermKeyInfo.java:100
org.direct_bt.SMPLongTermKeyInfo.Properties.toString
String toString()
Definition: SMPLongTermKeyInfo.java:105
org.direct_bt.SMPLongTermKeyInfo.isResponder
final boolean isResponder()
Definition: SMPLongTermKeyInfo.java:208
org.direct_bt.SMPLongTermKeyInfo.SMPLongTermKeyInfo
SMPLongTermKeyInfo(final byte source[], final int pos)
Construct instance via given source byte array.
Definition: SMPLongTermKeyInfo.java:142
org.direct_bt.SMPLongTermKeyInfo.PropertyType.RESPONDER
RESPONDER
Responder Key (LL slave).
Definition: SMPLongTermKeyInfo.java:47
org.direct_bt.SMPLongTermKeyInfo.ltk
byte ltk[]
Long Term Key (LTK), 16 octets or 128 bits.
Definition: SMPLongTermKeyInfo.java:133
org.direct_bt.SMPLongTermKeyInfo.ediv
byte ediv[]
Encryption Diversifier, 2 octets or 16 bits.
Definition: SMPLongTermKeyInfo.java:129
org.direct_bt.SMPLongTermKeyInfo.properties
Properties properties
Properties bit mask.
Definition: SMPLongTermKeyInfo.java:124
org.direct_bt.SMPLongTermKeyInfo.PropertyType.AUTH
AUTH
Authentication used.
Definition: SMPLongTermKeyInfo.java:49
org.direct_bt.SMPLongTermKeyInfo.isValid
final boolean isValid()
Definition: SMPLongTermKeyInfo.java:206
org.direct_bt.BTUtils.bytesHexString
static String bytesHexString(final byte[] bytes, final int offset, final int length, final boolean lsbFirst)
Produce a lower-case hexadecimal string representation of the given byte values.
Definition: BTUtils.java:123
org.direct_bt.SMPLongTermKeyInfo.PropertyType.SC
SC
Secure Connection used.
Definition: SMPLongTermKeyInfo.java:51
org.direct_bt.SMPLongTermKeyInfo.PropertyType.PropertyType
PropertyType(final byte v)
Definition: SMPLongTermKeyInfo.java:84
org.direct_bt.SMPLongTermKeyInfo.getStream
final void getStream(final byte[] sink, int pos)
Method transfers all bytes representing this instance into the given destination array at the given p...
Definition: SMPLongTermKeyInfo.java:194
org.direct_bt.SMPLongTermKeyInfo.PropertyType.value
final byte value
Definition: SMPLongTermKeyInfo.java:53
org.direct_bt.SMPLongTermKeyInfo.SMPLongTermKeyInfo
SMPLongTermKeyInfo()
Construct emoty unset instance.
Definition: SMPLongTermKeyInfo.java:153