30 import java.text.MessageFormat; |
30 import java.text.MessageFormat; |
31 import java.util.List; |
31 import java.util.List; |
32 import java.util.ArrayList; |
32 import java.util.ArrayList; |
33 import java.util.Locale; |
33 import java.util.Locale; |
34 import java.util.Arrays; |
34 import java.util.Arrays; |
35 import java.util.Objects; |
|
36 import java.util.Collection; |
35 import java.util.Collection; |
37 import javax.crypto.Mac; |
36 import javax.crypto.Mac; |
38 import javax.crypto.SecretKey; |
37 import javax.crypto.SecretKey; |
39 import javax.net.ssl.SSLPeerUnverifiedException; |
38 import javax.net.ssl.SSLPeerUnverifiedException; |
40 import static sun.security.ssl.ClientAuthType.CLIENT_AUTH_REQUIRED; |
39 import static sun.security.ssl.ClientAuthType.CLIENT_AUTH_REQUIRED; |
41 import sun.security.ssl.ClientHello.ClientHelloMessage; |
40 import sun.security.ssl.ClientHello.ClientHelloMessage; |
42 import sun.security.ssl.SSLExtension.ExtensionConsumer; |
41 import sun.security.ssl.SSLExtension.ExtensionConsumer; |
43 import sun.security.ssl.SSLExtension.SSLExtensionSpec; |
42 import sun.security.ssl.SSLExtension.SSLExtensionSpec; |
44 import sun.security.ssl.SSLHandshake.HandshakeMessage; |
43 import sun.security.ssl.SSLHandshake.HandshakeMessage; |
|
44 import sun.security.ssl.SessionTicketExtension.SessionTicketSpec; |
|
45 import sun.security.util.HexDumpEncoder; |
|
46 |
45 import static sun.security.ssl.SSLExtension.*; |
47 import static sun.security.ssl.SSLExtension.*; |
46 |
48 |
47 /** |
49 /** |
48 * Pack of the "pre_shared_key" extension. |
50 * Pack of the "pre_shared_key" extension. |
49 */ |
51 */ |
206 |
208 |
207 @Override |
209 @Override |
208 public String toString() { |
210 public String toString() { |
209 MessageFormat messageFormat = new MessageFormat( |
211 MessageFormat messageFormat = new MessageFormat( |
210 "\"PreSharedKey\": '{'\n" + |
212 "\"PreSharedKey\": '{'\n" + |
211 " \"identities\" : \"{0}\",\n" + |
213 " \"identities\": '{'\n" + |
212 " \"binders\" : \"{1}\",\n" + |
214 "{0}\n" + |
|
215 " '}'" + |
|
216 " \"binders\": \"{1}\",\n" + |
213 "'}'", |
217 "'}'", |
214 Locale.ENGLISH); |
218 Locale.ENGLISH); |
215 |
219 |
216 Object[] messageFields = { |
220 Object[] messageFields = { |
217 Utilities.indent(identitiesString()), |
221 Utilities.indent(identitiesString()), |
220 |
224 |
221 return messageFormat.format(messageFields); |
225 return messageFormat.format(messageFields); |
222 } |
226 } |
223 |
227 |
224 String identitiesString() { |
228 String identitiesString() { |
|
229 HexDumpEncoder hexEncoder = new HexDumpEncoder(); |
|
230 |
225 StringBuilder result = new StringBuilder(); |
231 StringBuilder result = new StringBuilder(); |
226 for (PskIdentity curId : identities) { |
232 for (PskIdentity curId : identities) { |
227 result.append(curId.toString() + "\n"); |
233 result.append(" {\n"+ Utilities.indent( |
|
234 hexEncoder.encode(curId.identity), " ") + |
|
235 "\n }\n"); |
228 } |
236 } |
229 |
237 |
230 return result.toString(); |
238 return result.toString(); |
231 } |
239 } |
232 |
240 |
276 m.remaining() + ")"); |
284 m.remaining() + ")"); |
277 } |
285 } |
278 this.selectedIdentity = Record.getInt16(m); |
286 this.selectedIdentity = Record.getInt16(m); |
279 } |
287 } |
280 |
288 |
281 byte[] getEncoded() throws IOException { |
289 byte[] getEncoded() { |
282 return new byte[] { |
290 return new byte[] { |
283 (byte)((selectedIdentity >> 8) & 0xFF), |
291 (byte)((selectedIdentity >> 8) & 0xFF), |
284 (byte)(selectedIdentity & 0xFF) |
292 (byte)(selectedIdentity & 0xFF) |
285 }; |
293 }; |
286 } |
294 } |
366 |
374 |
367 if (shc.isResumption) { // resumingSession may not be set |
375 if (shc.isResumption) { // resumingSession may not be set |
368 SSLSessionContextImpl sessionCache = (SSLSessionContextImpl) |
376 SSLSessionContextImpl sessionCache = (SSLSessionContextImpl) |
369 shc.sslContext.engineGetServerSessionContext(); |
377 shc.sslContext.engineGetServerSessionContext(); |
370 int idIndex = 0; |
378 int idIndex = 0; |
|
379 SSLSessionImpl s = null; |
|
380 |
371 for (PskIdentity requestedId : pskSpec.identities) { |
381 for (PskIdentity requestedId : pskSpec.identities) { |
372 SSLSessionImpl s = sessionCache.get(requestedId.identity); |
382 // If we are keeping state, see if the identity is in the cache |
|
383 if (requestedId.identity.length == SessionId.MAX_LENGTH) { |
|
384 s = sessionCache.get(requestedId.identity); |
|
385 } |
|
386 // See if the identity is a stateless ticket |
|
387 if (s == null && |
|
388 requestedId.identity.length > SessionId.MAX_LENGTH && |
|
389 sessionCache.statelessEnabled()) { |
|
390 ByteBuffer b = |
|
391 new SessionTicketSpec(requestedId.identity). |
|
392 decrypt(shc); |
|
393 if (b != null) { |
|
394 try { |
|
395 s = new SSLSessionImpl(shc, b); |
|
396 } catch (IOException | RuntimeException e) { |
|
397 s = null; |
|
398 } |
|
399 } |
|
400 if (b == null || s == null) { |
|
401 if (SSLLogger.isOn && |
|
402 SSLLogger.isOn("ssl,handshake")) { |
|
403 SSLLogger.fine( |
|
404 "Stateless session ticket invalid"); |
|
405 } |
|
406 } |
|
407 } |
|
408 |
373 if (s != null && canRejoin(clientHello, shc, s)) { |
409 if (s != null && canRejoin(clientHello, shc, s)) { |
374 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
410 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
375 SSLLogger.fine("Resuming session: ", s); |
411 SSLLogger.fine("Resuming session: ", s); |
376 } |
412 } |
377 |
413 |
389 // no resumable session |
425 // no resumable session |
390 shc.isResumption = false; |
426 shc.isResumption = false; |
391 shc.resumingSession = null; |
427 shc.resumingSession = null; |
392 } |
428 } |
393 } |
429 } |
394 |
|
395 // update the context |
430 // update the context |
396 shc.handshakeExtensions.put( |
431 shc.handshakeExtensions.put( |
397 SSLExtension.CH_PRE_SHARED_KEY, pskSpec); |
432 SSLExtension.CH_PRE_SHARED_KEY, pskSpec); |
398 } |
433 } |
399 } |
434 } |
706 |
741 |
707 private CHPreSharedKeySpec createPskPrototype( |
742 private CHPreSharedKeySpec createPskPrototype( |
708 int hashLength, List<PskIdentity> identities) { |
743 int hashLength, List<PskIdentity> identities) { |
709 List<byte[]> binders = new ArrayList<>(); |
744 List<byte[]> binders = new ArrayList<>(); |
710 byte[] binderProto = new byte[hashLength]; |
745 byte[] binderProto = new byte[hashLength]; |
711 for (PskIdentity curId : identities) { |
746 int i = identities.size(); |
|
747 while (i-- > 0) { |
712 binders.add(binderProto); |
748 binders.add(binderProto); |
713 } |
749 } |
714 |
750 |
715 return new CHPreSharedKeySpec(identities, binders); |
751 return new CHPreSharedKeySpec(identities, binders); |
716 } |
752 } |