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