author | xuelei |
Thu, 07 Jun 2018 21:16:21 -0700 | |
branch | JDK-8145252-TLS13-branch |
changeset 56702 | 75527e40bdfd |
parent 56661 | 2a820e434f17 |
child 56703 | 33a2451070d3 |
permissions | -rw-r--r-- |
56542 | 1 |
/* |
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
2 |
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. |
56542 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
7 |
* published by the Free Software Foundation. Oracle designates this |
|
8 |
* particular file as subject to the "Classpath" exception as provided |
|
9 |
* by Oracle in the LICENSE file that accompanied this code. |
|
10 |
* |
|
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
24 |
*/ |
|
25 |
package sun.security.ssl; |
|
26 |
||
27 |
import java.io.IOException; |
|
28 |
import java.nio.ByteBuffer; |
|
29 |
import java.security.*; |
|
30 |
import java.text.MessageFormat; |
|
31 |
import java.util.List; |
|
32 |
import java.util.ArrayList; |
|
33 |
import java.util.Locale; |
|
34 |
import java.util.Arrays; |
|
35 |
import java.util.Optional; |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
36 |
import javax.crypto.Mac; |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
37 |
import javax.crypto.SecretKey; |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
38 |
import sun.security.ssl.ClientHello.ClientHelloMessage; |
56542 | 39 |
import sun.security.ssl.SSLExtension.ExtensionConsumer; |
40 |
import sun.security.ssl.SSLExtension.SSLExtensionSpec; |
|
41 |
import sun.security.ssl.SSLHandshake.HandshakeMessage; |
|
42 |
import static sun.security.ssl.SSLExtension.*; |
|
43 |
||
44 |
/** |
|
45 |
* Pack of the "pre_shared_key" extension. |
|
46 |
*/ |
|
47 |
final class PreSharedKeyExtension { |
|
48 |
static final HandshakeProducer chNetworkProducer = |
|
49 |
new CHPreSharedKeyProducer(); |
|
50 |
static final ExtensionConsumer chOnLoadConsumer = |
|
51 |
new CHPreSharedKeyConsumer(); |
|
52 |
static final HandshakeAbsence chOnLoadAbsence = |
|
53 |
new CHPreSharedKeyAbsence(); |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
54 |
static final HandshakeConsumer chOnTradeConsumer = |
56542 | 55 |
new CHPreSharedKeyUpdate(); |
56 |
||
57 |
static final HandshakeProducer shNetworkProducer = |
|
58 |
new SHPreSharedKeyProducer(); |
|
59 |
static final ExtensionConsumer shOnLoadConsumer = |
|
60 |
new SHPreSharedKeyConsumer(); |
|
61 |
static final HandshakeAbsence shOnLoadAbsence = |
|
62 |
new SHPreSharedKeyAbsence(); |
|
63 |
||
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
64 |
private static final class PskIdentity { |
56542 | 65 |
final byte[] identity; |
66 |
final int obfuscatedAge; |
|
67 |
||
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
68 |
PskIdentity(byte[] identity, int obfuscatedAge) { |
56542 | 69 |
this.identity = identity; |
70 |
this.obfuscatedAge = obfuscatedAge; |
|
71 |
} |
|
72 |
||
73 |
int getEncodedLength() { |
|
74 |
return 2 + identity.length + 4; |
|
75 |
} |
|
76 |
||
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
77 |
void writeEncoded(ByteBuffer m) throws IOException { |
56542 | 78 |
Record.putBytes16(m, identity); |
79 |
Record.putInt32(m, obfuscatedAge); |
|
80 |
} |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
81 |
|
56542 | 82 |
@Override |
83 |
public String toString() { |
|
84 |
return "{" + Utilities.toHexString(identity) + "," + |
|
85 |
obfuscatedAge + "}"; |
|
86 |
} |
|
87 |
} |
|
88 |
||
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
89 |
private static final |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
90 |
class CHPreSharedKeySpec implements SSLExtensionSpec { |
56542 | 91 |
final List<PskIdentity> identities; |
92 |
final List<byte[]> binders; |
|
93 |
||
94 |
CHPreSharedKeySpec(List<PskIdentity> identities, List<byte[]> binders) { |
|
95 |
this.identities = identities; |
|
96 |
this.binders = binders; |
|
97 |
} |
|
98 |
||
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
99 |
CHPreSharedKeySpec(HandshakeContext context, |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
100 |
ByteBuffer m) throws IOException { |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
101 |
// struct { |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
102 |
// PskIdentity identities<7..2^16-1>; |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
103 |
// PskBinderEntry binders<33..2^16-1>; |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
104 |
// } OfferedPsks; |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
105 |
if (m.remaining() < 44) { |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
106 |
context.conContext.fatal(Alert.ILLEGAL_PARAMETER, |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
107 |
"Invalid pre_shared_key extension: " + |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
108 |
"insufficient data (length=" + m.remaining() + ")"); |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
109 |
} |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
110 |
|
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
111 |
int idEncodedLength = Record.getInt16(m); |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
112 |
if (idEncodedLength < 7) { |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
113 |
context.conContext.fatal(Alert.ILLEGAL_PARAMETER, |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
114 |
"Invalid pre_shared_key extension: " + |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
115 |
"insufficient identities (length=" + idEncodedLength + ")"); |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
116 |
} |
56542 | 117 |
|
118 |
identities = new ArrayList<>(); |
|
119 |
int idReadLength = 0; |
|
120 |
while (idReadLength < idEncodedLength) { |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
121 |
byte[] id = Record.getBytes16(m); |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
122 |
if (id.length < 1) { |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
123 |
context.conContext.fatal(Alert.ILLEGAL_PARAMETER, |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
124 |
"Invalid pre_shared_key extension: " + |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
125 |
"insufficient identity (length=" + id.length + ")"); |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
126 |
} |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
127 |
int obfuscatedTicketAge = Record.getInt32(m); |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
128 |
|
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
129 |
PskIdentity pskId = new PskIdentity(id, obfuscatedTicketAge); |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
130 |
identities.add(pskId); |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
131 |
idReadLength += pskId.getEncodedLength(); |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
132 |
} |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
133 |
|
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
134 |
if (m.remaining() < 35) { |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
135 |
context.conContext.fatal(Alert.ILLEGAL_PARAMETER, |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
136 |
"Invalid pre_shared_key extension: " + |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
137 |
"insufficient binders data (length=" + |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
138 |
m.remaining() + ")"); |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
139 |
} |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
140 |
|
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
141 |
int bindersEncodedLen = Record.getInt16(m); |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
142 |
if (bindersEncodedLen < 33) { |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
143 |
context.conContext.fatal(Alert.ILLEGAL_PARAMETER, |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
144 |
"Invalid pre_shared_key extension: " + |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
145 |
"insufficient binders (length=" + |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
146 |
bindersEncodedLen + ")"); |
56542 | 147 |
} |
148 |
||
149 |
binders = new ArrayList<>(); |
|
150 |
int bindersReadLength = 0; |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
151 |
while (bindersReadLength < bindersEncodedLen) { |
56542 | 152 |
byte[] binder = Record.getBytes8(m); |
153 |
if (binder.length < 32) { |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
154 |
context.conContext.fatal(Alert.ILLEGAL_PARAMETER, |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
155 |
"Invalid pre_shared_key extension: " + |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
156 |
"insufficient binder entry (length=" + |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
157 |
binder.length + ")"); |
56542 | 158 |
} |
159 |
binders.add(binder); |
|
160 |
bindersReadLength += 1 + binder.length; |
|
161 |
} |
|
162 |
} |
|
163 |
||
164 |
int getIdsEncodedLength() { |
|
165 |
int idEncodedLength = 0; |
|
166 |
for(PskIdentity curId : identities) { |
|
167 |
idEncodedLength += curId.getEncodedLength(); |
|
168 |
} |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
169 |
|
56542 | 170 |
return idEncodedLength; |
171 |
} |
|
172 |
||
173 |
int getBindersEncodedLength() { |
|
174 |
int binderEncodedLength = 0; |
|
175 |
for (byte[] curBinder : binders) { |
|
176 |
binderEncodedLength += 1 + curBinder.length; |
|
177 |
} |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
178 |
|
56542 | 179 |
return binderEncodedLength; |
180 |
} |
|
181 |
||
182 |
byte[] getEncoded() throws IOException { |
|
183 |
int idsEncodedLength = getIdsEncodedLength(); |
|
184 |
int bindersEncodedLength = getBindersEncodedLength(); |
|
185 |
int encodedLength = 4 + idsEncodedLength + bindersEncodedLength; |
|
186 |
byte[] buffer = new byte[encodedLength]; |
|
187 |
ByteBuffer m = ByteBuffer.wrap(buffer); |
|
188 |
Record.putInt16(m, idsEncodedLength); |
|
189 |
for(PskIdentity curId : identities) { |
|
190 |
curId.writeEncoded(m); |
|
191 |
} |
|
192 |
Record.putInt16(m, bindersEncodedLength); |
|
193 |
for (byte[] curBinder : binders) { |
|
194 |
Record.putBytes8(m, curBinder); |
|
195 |
} |
|
196 |
||
197 |
return buffer; |
|
198 |
} |
|
199 |
||
200 |
@Override |
|
201 |
public String toString() { |
|
202 |
MessageFormat messageFormat = new MessageFormat( |
|
203 |
"\"PreSharedKey\": '{'\n" + |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
204 |
" \"identities\" : \"{0}\",\n" + |
56542 | 205 |
" \"binders\" : \"{1}\",\n" + |
206 |
"'}'", |
|
207 |
Locale.ENGLISH); |
|
208 |
||
209 |
Object[] messageFields = { |
|
210 |
Utilities.indent(identitiesString()), |
|
211 |
Utilities.indent(bindersString()) |
|
212 |
}; |
|
213 |
||
214 |
return messageFormat.format(messageFields); |
|
215 |
} |
|
216 |
||
217 |
String identitiesString() { |
|
218 |
StringBuilder result = new StringBuilder(); |
|
219 |
for(PskIdentity curId : identities) { |
|
220 |
result.append(curId.toString() + "\n"); |
|
221 |
} |
|
222 |
||
223 |
return result.toString(); |
|
224 |
} |
|
225 |
||
226 |
String bindersString() { |
|
227 |
StringBuilder result = new StringBuilder(); |
|
228 |
for(byte[] curBinder : binders) { |
|
229 |
result.append("{" + Utilities.toHexString(curBinder) + "}\n"); |
|
230 |
} |
|
231 |
||
232 |
return result.toString(); |
|
233 |
} |
|
234 |
} |
|
235 |
||
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
236 |
private static final |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
237 |
class SHPreSharedKeySpec implements SSLExtensionSpec { |
56542 | 238 |
final int selectedIdentity; |
239 |
||
240 |
SHPreSharedKeySpec(int selectedIdentity) { |
|
241 |
this.selectedIdentity = selectedIdentity; |
|
242 |
} |
|
243 |
||
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
244 |
SHPreSharedKeySpec(HandshakeContext context, |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
245 |
ByteBuffer m) throws IOException { |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
246 |
if (m.remaining() < 2) { |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
247 |
context.conContext.fatal(Alert.ILLEGAL_PARAMETER, |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
248 |
"Invalid pre_shared_key extension: " + |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
249 |
"insufficient selected_identity (length=" + |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
250 |
m.remaining() + ")"); |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
251 |
} |
56542 | 252 |
this.selectedIdentity = Record.getInt16(m); |
253 |
} |
|
254 |
||
255 |
byte[] getEncoded() throws IOException { |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
256 |
return new byte[] { |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
257 |
(byte)((selectedIdentity >> 8) & 0xFF), |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
258 |
(byte)(selectedIdentity & 0xFF) |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
259 |
}; |
56542 | 260 |
} |
261 |
||
262 |
@Override |
|
263 |
public String toString() { |
|
264 |
MessageFormat messageFormat = new MessageFormat( |
|
265 |
"\"PreSharedKey\": '{'\n" + |
|
266 |
" \"selected_identity\" : \"{0}\",\n" + |
|
267 |
"'}'", |
|
268 |
Locale.ENGLISH); |
|
269 |
||
270 |
Object[] messageFields = { |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
271 |
Utilities.byte16HexString(selectedIdentity) |
56542 | 272 |
}; |
273 |
||
274 |
return messageFormat.format(messageFields); |
|
275 |
} |
|
276 |
} |
|
277 |
||
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
278 |
private static final |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
279 |
class CHPreSharedKeyConsumer implements ExtensionConsumer { |
56542 | 280 |
// Prevent instantiation of this class. |
281 |
private CHPreSharedKeyConsumer() { |
|
282 |
// blank |
|
283 |
} |
|
284 |
||
285 |
@Override |
|
286 |
public void consume(ConnectionContext context, |
|
287 |
HandshakeMessage message, |
|
288 |
ByteBuffer buffer) throws IOException { |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
289 |
ServerHandshakeContext shc = (ServerHandshakeContext)context; |
56542 | 290 |
// Is it a supported and enabled extension? |
291 |
if (!shc.sslConfig.isAvailable(SSLExtension.CH_PRE_SHARED_KEY)) { |
|
292 |
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
|
293 |
SSLLogger.fine( |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
294 |
"Ignore unavailable pre_shared_key extension"); |
56542 | 295 |
} |
296 |
return; // ignore the extension |
|
297 |
} |
|
298 |
||
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
299 |
// Parse the extension. |
56542 | 300 |
CHPreSharedKeySpec pskSpec = null; |
301 |
try { |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
302 |
pskSpec = new CHPreSharedKeySpec(shc, buffer); |
56542 | 303 |
} catch (IOException ioe) { |
304 |
shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe); |
|
305 |
return; // fatal() always throws, make the compiler happy. |
|
306 |
} |
|
307 |
||
56702 | 308 |
// The "psk_key_exchange_modes" extension should have been loaded. |
309 |
if (!shc.handshakeExtensions.containsKey( |
|
310 |
SSLExtension.PSK_KEY_EXCHANGE_MODES)) { |
|
56542 | 311 |
shc.conContext.fatal(Alert.ILLEGAL_PARAMETER, |
56702 | 312 |
"Client sent PSK but not PSK modes, or the PSK " + |
313 |
"extension is not the last extension"); |
|
56542 | 314 |
} |
315 |
||
316 |
// error if id and binder lists are not the same length |
|
317 |
if (pskSpec.identities.size() != pskSpec.binders.size()) { |
|
318 |
shc.conContext.fatal(Alert.ILLEGAL_PARAMETER, |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
319 |
"PSK extension has incorrect number of binders"); |
56542 | 320 |
} |
321 |
||
56702 | 322 |
if (shc.isResumption) { // resumingSession may not be set |
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
323 |
SSLSessionContextImpl sessionCache = (SSLSessionContextImpl) |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
324 |
shc.sslContext.engineGetServerSessionContext(); |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
325 |
int idIndex = 0; |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
326 |
for (PskIdentity requestedId : pskSpec.identities) { |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
327 |
SSLSessionImpl s = sessionCache.get(requestedId.identity); |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
328 |
if (s != null && s.isRejoinable() && |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
329 |
s.getPreSharedKey().isPresent()) { |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
330 |
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
331 |
SSLLogger.fine("Resuming session: ", s); |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
332 |
} |
56542 | 333 |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
334 |
// binder will be checked later |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
335 |
shc.resumingSession = s; |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
336 |
shc.handshakeExtensions.put(SH_PRE_SHARED_KEY, |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
337 |
new SHPreSharedKeySpec(idIndex)); // for the index |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
338 |
break; |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
339 |
} |
56542 | 340 |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
341 |
++idIndex; |
56542 | 342 |
} |
343 |
||
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
344 |
if (idIndex == pskSpec.identities.size()) { |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
345 |
// no resumable session |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
346 |
shc.isResumption = false; |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
347 |
shc.resumingSession = null; |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
348 |
} |
56542 | 349 |
} |
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
350 |
|
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
351 |
// update the context |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
352 |
shc.handshakeExtensions.put( |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
353 |
SSLExtension.CH_PRE_SHARED_KEY, pskSpec); |
56542 | 354 |
} |
355 |
} |
|
356 |
||
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
357 |
private static final |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
358 |
class CHPreSharedKeyUpdate implements HandshakeConsumer { |
56542 | 359 |
// Prevent instantiation of this class. |
360 |
private CHPreSharedKeyUpdate() { |
|
361 |
// blank |
|
362 |
} |
|
363 |
||
364 |
@Override |
|
365 |
public void consume(ConnectionContext context, |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
366 |
HandshakeMessage message) throws IOException { |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
367 |
ServerHandshakeContext shc = (ServerHandshakeContext)context; |
56542 | 368 |
if (!shc.isResumption || shc.resumingSession == null) { |
369 |
// not resuming---nothing to do |
|
370 |
return; |
|
371 |
} |
|
372 |
||
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
373 |
CHPreSharedKeySpec chPsk = (CHPreSharedKeySpec) |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
374 |
shc.handshakeExtensions.get(SSLExtension.CH_PRE_SHARED_KEY); |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
375 |
SHPreSharedKeySpec shPsk = (SHPreSharedKeySpec) |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
376 |
shc.handshakeExtensions.get(SSLExtension.SH_PRE_SHARED_KEY); |
56542 | 377 |
if (chPsk == null || shPsk == null) { |
378 |
shc.conContext.fatal(Alert.INTERNAL_ERROR, |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
379 |
"Required extensions are unavailable"); |
56542 | 380 |
} |
381 |
||
382 |
byte[] binder = chPsk.binders.get(shPsk.selectedIdentity); |
|
383 |
||
384 |
// set up PSK binder hash |
|
385 |
HandshakeHash pskBinderHash = shc.handshakeHash.copy(); |
|
386 |
byte[] lastMessage = pskBinderHash.removeLastReceived(); |
|
387 |
ByteBuffer messageBuf = ByteBuffer.wrap(lastMessage); |
|
388 |
// skip the type and length |
|
389 |
messageBuf.position(4); |
|
390 |
// read to find the beginning of the binders |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
391 |
ClientHelloMessage.readPartial(shc.conContext, messageBuf); |
56542 | 392 |
int length = messageBuf.position(); |
393 |
messageBuf.position(0); |
|
394 |
pskBinderHash.receive(messageBuf, length); |
|
395 |
||
396 |
checkBinder(shc, shc.resumingSession, pskBinderHash, binder); |
|
397 |
} |
|
398 |
} |
|
399 |
||
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
400 |
private static void checkBinder(ServerHandshakeContext shc, |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
401 |
SSLSessionImpl session, |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
402 |
HandshakeHash pskBinderHash, byte[] binder) throws IOException { |
56542 | 403 |
Optional<SecretKey> pskOpt = session.getPreSharedKey(); |
404 |
if (!pskOpt.isPresent()) { |
|
405 |
shc.conContext.fatal(Alert.INTERNAL_ERROR, |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
406 |
"Session has no PSK"); |
56542 | 407 |
} |
408 |
SecretKey psk = pskOpt.get(); |
|
409 |
||
410 |
SecretKey binderKey = deriveBinderKey(psk, session); |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
411 |
byte[] computedBinder = |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
412 |
computeBinder(binderKey, session, pskBinderHash); |
56542 | 413 |
if (!Arrays.equals(binder, computedBinder)) { |
414 |
shc.conContext.fatal(Alert.ILLEGAL_PARAMETER, |
|
415 |
"Incorect PSK binder value"); |
|
416 |
} |
|
417 |
} |
|
418 |
||
419 |
// Class that produces partial messages used to compute binder hash |
|
420 |
static final class PartialClientHelloMessage extends HandshakeMessage { |
|
421 |
||
422 |
private final ClientHello.ClientHelloMessage msg; |
|
423 |
private final CHPreSharedKeySpec psk; |
|
424 |
||
425 |
PartialClientHelloMessage(HandshakeContext ctx, |
|
426 |
ClientHello.ClientHelloMessage msg, |
|
427 |
CHPreSharedKeySpec psk) { |
|
428 |
super(ctx); |
|
429 |
||
430 |
this.msg = msg; |
|
431 |
this.psk = psk; |
|
432 |
} |
|
433 |
||
434 |
@Override |
|
435 |
SSLHandshake handshakeType() { |
|
436 |
return msg.handshakeType(); |
|
437 |
} |
|
438 |
||
439 |
private int pskTotalLength() { |
|
440 |
return psk.getIdsEncodedLength() + |
|
441 |
psk.getBindersEncodedLength() + 8; |
|
442 |
} |
|
443 |
||
444 |
@Override |
|
445 |
int messageLength() { |
|
446 |
||
447 |
if (msg.extensions.get(SSLExtension.CH_PRE_SHARED_KEY) != null) { |
|
448 |
return msg.messageLength(); |
|
449 |
} else { |
|
450 |
return msg.messageLength() + pskTotalLength(); |
|
451 |
} |
|
452 |
} |
|
453 |
||
454 |
@Override |
|
455 |
void send(HandshakeOutStream hos) throws IOException { |
|
456 |
msg.sendCore(hos); |
|
457 |
||
458 |
// complete extensions |
|
459 |
int extsLen = msg.extensions.length(); |
|
460 |
if (msg.extensions.get(SSLExtension.CH_PRE_SHARED_KEY) == null) { |
|
461 |
extsLen += pskTotalLength(); |
|
462 |
} |
|
463 |
hos.putInt16(extsLen - 2); |
|
464 |
// write the complete extensions |
|
465 |
for (SSLExtension ext : SSLExtension.values()) { |
|
466 |
byte[] extData = msg.extensions.get(ext); |
|
467 |
if (extData == null) { |
|
468 |
continue; |
|
469 |
} |
|
470 |
// the PSK could be there from an earlier round |
|
471 |
if (ext == SSLExtension.CH_PRE_SHARED_KEY) { |
|
472 |
continue; |
|
473 |
} |
|
474 |
int extID = ext.id; |
|
475 |
hos.putInt16(extID); |
|
476 |
hos.putBytes16(extData); |
|
477 |
} |
|
478 |
||
479 |
// partial PSK extension |
|
480 |
int extID = SSLExtension.CH_PRE_SHARED_KEY.id; |
|
481 |
hos.putInt16(extID); |
|
482 |
byte[] encodedPsk = psk.getEncoded(); |
|
483 |
hos.putInt16(encodedPsk.length); |
|
484 |
hos.write(encodedPsk, 0, psk.getIdsEncodedLength() + 2); |
|
485 |
} |
|
486 |
} |
|
487 |
||
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
488 |
private static final |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
489 |
class CHPreSharedKeyProducer implements HandshakeProducer { |
56542 | 490 |
// Prevent instantiation of this class. |
491 |
private CHPreSharedKeyProducer() { |
|
492 |
// blank |
|
493 |
} |
|
494 |
||
495 |
@Override |
|
496 |
public byte[] produce(ConnectionContext context, |
|
497 |
HandshakeMessage message) throws IOException { |
|
498 |
||
499 |
// The producing happens in client side only. |
|
500 |
ClientHandshakeContext chc = (ClientHandshakeContext)context; |
|
501 |
if (!chc.isResumption || chc.resumingSession == null) { |
|
502 |
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
503 |
SSLLogger.fine("No session to resume."); |
56542 | 504 |
} |
505 |
return null; |
|
506 |
} |
|
507 |
||
508 |
Optional<SecretKey> pskOpt = chc.resumingSession.getPreSharedKey(); |
|
509 |
if (!pskOpt.isPresent()) { |
|
510 |
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
511 |
SSLLogger.fine("Existing session has no PSK."); |
56542 | 512 |
} |
513 |
return null; |
|
514 |
} |
|
515 |
SecretKey psk = pskOpt.get(); |
|
516 |
Optional<byte[]> pskIdOpt = chc.resumingSession.getPskIdentity(); |
|
517 |
if (!pskIdOpt.isPresent()) { |
|
518 |
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
|
519 |
SSLLogger.fine( |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
520 |
"PSK has no identity, or identity was already used"); |
56542 | 521 |
} |
522 |
return null; |
|
523 |
} |
|
524 |
byte[] pskId = pskIdOpt.get(); |
|
525 |
||
526 |
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
|
527 |
SSLLogger.fine( |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
528 |
"Found resumable session. Preparing PSK message."); |
56542 | 529 |
} |
530 |
||
531 |
List<PskIdentity> identities = new ArrayList<>(); |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
532 |
int ageMillis = (int)(System.currentTimeMillis() - |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
533 |
chc.resumingSession.getTicketCreationTime()); |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
534 |
int obfuscatedAge = |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
535 |
ageMillis + chc.resumingSession.getTicketAgeAdd(); |
56542 | 536 |
identities.add(new PskIdentity(pskId, obfuscatedAge)); |
537 |
||
538 |
SecretKey binderKey = deriveBinderKey(psk, chc.resumingSession); |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
539 |
ClientHelloMessage clientHello = (ClientHelloMessage)message; |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
540 |
CHPreSharedKeySpec pskPrototype = createPskPrototype( |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
541 |
chc.resumingSession.getSuite().hashAlg.hashLength, identities); |
56542 | 542 |
HandshakeHash pskBinderHash = chc.handshakeHash.copy(); |
543 |
||
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
544 |
byte[] binder = computeBinder(binderKey, pskBinderHash, |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
545 |
chc.resumingSession, chc, clientHello, pskPrototype); |
56542 | 546 |
|
547 |
List<byte[]> binders = new ArrayList<>(); |
|
548 |
binders.add(binder); |
|
549 |
||
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
550 |
CHPreSharedKeySpec pskMessage = |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
551 |
new CHPreSharedKeySpec(identities, binders); |
56542 | 552 |
chc.handshakeExtensions.put(CH_PRE_SHARED_KEY, pskMessage); |
553 |
return pskMessage.getEncoded(); |
|
554 |
} |
|
555 |
||
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
556 |
private CHPreSharedKeySpec createPskPrototype( |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
557 |
int hashLength, List<PskIdentity> identities) { |
56542 | 558 |
List<byte[]> binders = new ArrayList<>(); |
559 |
byte[] binderProto = new byte[hashLength]; |
|
560 |
for (PskIdentity curId : identities) { |
|
561 |
binders.add(binderProto); |
|
562 |
} |
|
563 |
||
564 |
return new CHPreSharedKeySpec(identities, binders); |
|
565 |
} |
|
566 |
} |
|
567 |
||
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
568 |
private static byte[] computeBinder(SecretKey binderKey, |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
569 |
SSLSessionImpl session, |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
570 |
HandshakeHash pskBinderHash) throws IOException { |
56542 | 571 |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
572 |
pskBinderHash.determine( |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
573 |
session.getProtocolVersion(), session.getSuite()); |
56542 | 574 |
pskBinderHash.update(); |
575 |
byte[] digest = pskBinderHash.digest(); |
|
576 |
||
577 |
return computeBinder(binderKey, session, digest); |
|
578 |
} |
|
579 |
||
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
580 |
private static byte[] computeBinder(SecretKey binderKey, |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
581 |
HandshakeHash hash, SSLSessionImpl session, |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
582 |
HandshakeContext ctx, ClientHello.ClientHelloMessage hello, |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
583 |
CHPreSharedKeySpec pskPrototype) throws IOException { |
56542 | 584 |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
585 |
PartialClientHelloMessage partialMsg = |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
586 |
new PartialClientHelloMessage(ctx, hello, pskPrototype); |
56542 | 587 |
|
588 |
SSLEngineOutputRecord record = new SSLEngineOutputRecord(hash); |
|
589 |
HandshakeOutStream hos = new HandshakeOutStream(record); |
|
590 |
partialMsg.write(hos); |
|
591 |
||
592 |
hash.determine(session.getProtocolVersion(), session.getSuite()); |
|
593 |
hash.update(); |
|
594 |
byte[] digest = hash.digest(); |
|
595 |
||
596 |
return computeBinder(binderKey, session, digest); |
|
597 |
} |
|
598 |
||
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
599 |
private static byte[] computeBinder(SecretKey binderKey, |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
600 |
SSLSessionImpl session, byte[] digest) throws IOException { |
56542 | 601 |
try { |
602 |
CipherSuite.HashAlg hashAlg = session.getSuite().hashAlg; |
|
603 |
HKDF hkdf = new HKDF(hashAlg.name); |
|
604 |
byte[] label = ("tls13 finished").getBytes(); |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
605 |
byte[] hkdfInfo = SSLSecretDerivation.createHkdfInfo( |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
606 |
label, new byte[0], hashAlg.hashLength); |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
607 |
SecretKey finishedKey = hkdf.expand( |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
608 |
binderKey, hkdfInfo, hashAlg.hashLength, "TlsBinderKey"); |
56542 | 609 |
|
610 |
String hmacAlg = |
|
611 |
"Hmac" + hashAlg.name.replace("-", ""); |
|
612 |
try { |
|
613 |
Mac hmac = JsseJce.getMac(hmacAlg); |
|
614 |
hmac.init(finishedKey); |
|
615 |
return hmac.doFinal(digest); |
|
616 |
} catch (NoSuchAlgorithmException | InvalidKeyException ex) { |
|
617 |
throw new IOException(ex); |
|
618 |
} |
|
619 |
} catch(GeneralSecurityException ex) { |
|
620 |
throw new IOException(ex); |
|
621 |
} |
|
622 |
} |
|
623 |
||
624 |
private static SecretKey deriveBinderKey(SecretKey psk, |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
625 |
SSLSessionImpl session) throws IOException { |
56542 | 626 |
try { |
627 |
CipherSuite.HashAlg hashAlg = session.getSuite().hashAlg; |
|
628 |
HKDF hkdf = new HKDF(hashAlg.name); |
|
629 |
byte[] zeros = new byte[hashAlg.hashLength]; |
|
630 |
SecretKey earlySecret = hkdf.extract(zeros, psk, "TlsEarlySecret"); |
|
631 |
||
632 |
byte[] label = ("tls13 res binder").getBytes(); |
|
633 |
MessageDigest md = MessageDigest.getInstance(hashAlg.toString());; |
|
634 |
byte[] hkdfInfo = SSLSecretDerivation.createHkdfInfo( |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
635 |
label, md.digest(new byte[0]), hashAlg.hashLength); |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
636 |
return hkdf.expand(earlySecret, |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
637 |
hkdfInfo, hashAlg.hashLength, "TlsBinderKey"); |
56542 | 638 |
} catch (GeneralSecurityException ex) { |
639 |
throw new IOException(ex); |
|
640 |
} |
|
641 |
} |
|
642 |
||
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
643 |
private static final |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
644 |
class CHPreSharedKeyAbsence implements HandshakeAbsence { |
56542 | 645 |
@Override |
646 |
public void absent(ConnectionContext context, |
|
647 |
HandshakeMessage message) throws IOException { |
|
648 |
||
649 |
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
|
650 |
SSLLogger.fine( |
|
651 |
"Handling pre_shared_key absence."); |
|
652 |
} |
|
653 |
||
654 |
ServerHandshakeContext shc = (ServerHandshakeContext)context; |
|
655 |
||
656 |
// Resumption is only determined by PSK, when enabled |
|
657 |
shc.resumingSession = null; |
|
658 |
shc.isResumption = false; |
|
659 |
} |
|
660 |
} |
|
661 |
||
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
662 |
private static final |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
663 |
class SHPreSharedKeyConsumer implements ExtensionConsumer { |
56542 | 664 |
// Prevent instantiation of this class. |
665 |
private SHPreSharedKeyConsumer() { |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
666 |
// blank |
56542 | 667 |
} |
668 |
||
669 |
@Override |
|
670 |
public void consume(ConnectionContext context, |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
671 |
HandshakeMessage message, ByteBuffer buffer) throws IOException { |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
672 |
// The consuming happens in client side only. |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
673 |
ClientHandshakeContext chc = (ClientHandshakeContext)context; |
56542 | 674 |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
675 |
// Is it a response of the specific request? |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
676 |
if (!chc.handshakeExtensions.containsKey( |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
677 |
SSLExtension.CH_PRE_SHARED_KEY)) { |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
678 |
chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
679 |
"Server sent unexpected pre_shared_key extension"); |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
680 |
} |
56542 | 681 |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
682 |
SHPreSharedKeySpec shPsk = new SHPreSharedKeySpec(chc, buffer); |
56542 | 683 |
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
684 |
SSLLogger.fine( |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
685 |
"Received pre_shared_key extension: ", shPsk); |
56542 | 686 |
} |
687 |
||
688 |
// The PSK identity should not be reused, even if it is |
|
689 |
// not selected. |
|
690 |
chc.resumingSession.consumePskIdentity(); |
|
691 |
||
692 |
if (shPsk.selectedIdentity != 0) { |
|
693 |
chc.conContext.fatal(Alert.ILLEGAL_PARAMETER, |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
694 |
"Selected identity index is not in correct range."); |
56542 | 695 |
} |
696 |
||
697 |
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
|
698 |
SSLLogger.fine( |
|
699 |
"Resuming session: ", chc.resumingSession); |
|
700 |
} |
|
701 |
||
702 |
// remove the session from the cache |
|
703 |
SSLSessionContextImpl sessionCache = (SSLSessionContextImpl) |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
704 |
chc.sslContext.engineGetClientSessionContext(); |
56542 | 705 |
sessionCache.remove(chc.resumingSession.getSessionId()); |
706 |
} |
|
707 |
} |
|
708 |
||
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
709 |
private static final |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
710 |
class SHPreSharedKeyAbsence implements HandshakeAbsence { |
56542 | 711 |
@Override |
712 |
public void absent(ConnectionContext context, |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
713 |
HandshakeMessage message) throws IOException { |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
714 |
ClientHandshakeContext chc = (ClientHandshakeContext)context; |
56542 | 715 |
|
716 |
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
717 |
SSLLogger.fine("Handling pre_shared_key absence."); |
56542 | 718 |
} |
719 |
||
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
720 |
if (chc.handshakeExtensions.containsKey( |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
721 |
SSLExtension.CH_PRE_SHARED_KEY)) { |
56608 | 722 |
// The PSK identity should not be reused, even if it is |
723 |
// not selected. |
|
724 |
chc.resumingSession.consumePskIdentity(); |
|
56542 | 725 |
} |
726 |
||
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
727 |
// The server refused to resume, or the client did not |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
728 |
// request 1.3 resumption. |
56542 | 729 |
chc.resumingSession = null; |
730 |
chc.isResumption = false; |
|
731 |
} |
|
732 |
} |
|
733 |
||
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
734 |
private static final |
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
735 |
class SHPreSharedKeyProducer implements HandshakeProducer { |
56542 | 736 |
// Prevent instantiation of this class. |
737 |
private SHPreSharedKeyProducer() { |
|
738 |
// blank |
|
739 |
} |
|
740 |
||
741 |
@Override |
|
742 |
public byte[] produce(ConnectionContext context, |
|
743 |
HandshakeMessage message) throws IOException { |
|
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
744 |
ServerHandshakeContext shc = (ServerHandshakeContext)context; |
56542 | 745 |
SHPreSharedKeySpec psk = (SHPreSharedKeySpec) |
56661
2a820e434f17
pre_shared_key extensio code cleanup, and a test update
xuelei
parents:
56608
diff
changeset
|
746 |
shc.handshakeExtensions.get(SH_PRE_SHARED_KEY); |
56542 | 747 |
if (psk == null) { |
748 |
return null; |
|
749 |
} |
|
750 |
||
751 |
return psk.getEncoded(); |
|
752 |
} |
|
753 |
} |
|
754 |
} |