Direct-BT v3.3.0-1-gc2d430c
Direct-BT - Direct Bluetooth Programming.
SMPIdentityResolvingKey.java
Go to the documentation of this file.
1/**
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2021 Gothel Software e.K.
4 * Copyright (c) 2021 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 java.nio.ByteOrder;
29
30import org.jau.net.EUI48;
31import org.jau.util.BasicTypes;
32
33/**
34 * SMP Identity Resolving Key, used for platform agnostic persistence.
35 * <p>
36 * Notable: No endian wise conversion shall occur on this data,
37 * since the encryption values are interpreted as a byte stream.
38 * </p>
39 * <p>
40 * Byte layout must be synchronized with native direct_bt::SMPIdentityResolvingKeyInfo
41 * </p>
42 * @since 2.4.0
43 */
44public final class SMPIdentityResolvingKey {
45 /**
46 * {@link SMPIdentityResolvingKey} Property Bits
47 */
48 static public enum PropertyType {
49 /** No specific property */
50 NONE((byte)0),
51 /** Responder Key (LL slave). Absence indicates Initiator Key (LL master). */
52 RESPONDER((byte)0x01),
53 /** Authentication used. */
54 AUTH((byte)0x02);
55
56 public final byte value;
57
58 /**
59 * Maps the specified name to a constant of {@link PropertyType}.
60 * <p>
61 * Implementation simply returns {@link #valueOf(String)}.
62 * This maps the constant names itself to their respective constant.
63 * </p>
64 * @param name the string name to be mapped to a constant of this enum type.
65 * @return the corresponding constant of this enum type.
66 * @throws IllegalArgumentException if the specified name can't be mapped to a constant of this enum type
67 * as described above.
68 */
69 public static PropertyType get(final String name) throws IllegalArgumentException {
70 return valueOf(name);
71 }
72
73 /**
74 * Maps the specified integer value to a constant of {@link PropertyType}.
75 * @param value the integer value to be mapped to a constant of this enum type.
76 * @return the corresponding constant of this enum type, using {@link #NONE} if not supported.
77 */
78 public static PropertyType get(final byte value) {
79 switch(value) {
80 case (byte) 0x01: return RESPONDER;
81 case (byte) 0x02: return AUTH;
82 default: return NONE;
83 }
84 }
85
86 PropertyType(final byte v) {
87 value = v;
88 }
89 }
90
91 /**
92 * {@link SMPIdentityResolvingKey} {@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 return "["+out.toString()+"]";
118 }
119 }
120
121 /** {@link Properties} bit mask. 1 octet or 8 bits. */
123
124 /** Identity Resolving Key (IRK) */
125 public byte irk[/*16*/];
126
127 /** Identity Address for the IRK */
128 public EUI48 id_address;
129
130 /**
131 * Size of the byte stream representation in bytes
132 * @see #put(byte[], int)
133 */
134 public static final int byte_size = 1+16+6;
135
136 /** Construct instance via given source byte array */
137 public SMPIdentityResolvingKey(final byte source[], final int pos) {
138 irk = new byte[16];
139 get(source, pos);
140 }
141
142 /** Construct emoty unset instance. */
144 properties = new Properties((byte)0);
145 irk = new byte[16];
146 id_address = new EUI48();
147 }
148
149 /**
150 * Method transfers all bytes representing a SMPIdentityResolvingKeyInfo from the given
151 * source array at the given position into this instance.
152 * <p>
153 * Implementation is consistent with {@link #put(byte[], int)}.
154 * </p>
155 * @param source the source array
156 * @param pos starting position in the source array
157 * @see #put(byte[], int)
158 */
159 public void get(final byte[] source, int pos) {
160 if( byte_size > ( source.length - pos ) ) {
161 throw new IllegalArgumentException("Stream ( "+source.length+" - "+pos+" ) < "+byte_size+" bytes");
162 }
163 properties = new Properties(source[pos++]);
164 System.arraycopy(source, pos, irk, 0, 16); pos+=16;
165 id_address = new EUI48(source, pos, ByteOrder.nativeOrder()); pos+=6;
166 }
167
168 /**
169 * Method transfers all bytes representing this instance into the given
170 * destination array at the given position.
171 * <p>
172 * Implementation is consistent with {@link #SMPIdentityResolvingKeyInfo(byte[], int)}.
173 * </p>
174 * @param sink the destination array
175 * @param pos starting position in the destination array
176 * @see #SMPIdentityResolvingKeyInfo(byte[], int)
177 * @see #get(byte[], int)
178 */
179 public final void put(final byte[] sink, int pos) {
180 if( byte_size > ( sink.length - pos ) ) {
181 throw new IllegalArgumentException("Stream ( "+sink.length+" - "+pos+" ) < "+byte_size+" bytes");
182 }
183 sink[pos++] = properties.mask;
184 System.arraycopy(irk, 0, sink, pos, 16); pos+=16;
185 System.arraycopy(id_address.b, 0, sink, pos, 6); pos+=6;
186 }
187
188 public final boolean isResponder() { return properties.isSet(PropertyType.RESPONDER); }
189
190 /** Returns true if this IRK matches the given random private address (RPA). */
191 public native boolean matches(final EUI48 rpa);
192
193 @Override
194 public String toString() { // hex-fmt aligned with btmon
195 return "IRK[props "+properties.toString()+
196 ", id "+id_address+", irk "+BasicTypes.bytesHexString(irk, 0, -1, true /* lsbFirst */)+
197 "]";
198 }
199
200};
SMPIdentityResolvingKey PropertyType Bit Mask
SMP Identity Resolving Key, used for platform agnostic persistence.
EUI48 id_address
Identity Address for the IRK.
SMPIdentityResolvingKey()
Construct emoty unset instance.
static final int byte_size
Size of the byte stream representation in bytes.
final void put(final byte[] sink, int pos)
Method transfers all bytes representing this instance into the given destination array at the given p...
native boolean matches(final EUI48 rpa)
Returns true if this IRK matches the given random private address (RPA).
SMPIdentityResolvingKey(final byte source[], final int pos)
Construct instance via given source byte array.
byte irk[]
Identity Resolving Key (IRK)