src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java
changeset 51134 a0de9a3a6766
parent 50768 68fa3d4026ea
child 52170 2990f1e1c325
equal deleted inserted replaced
51133:e15cd424736d 51134:a0de9a3a6766
    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.Optional;
    35 import java.util.Optional;
       
    36 import java.util.Collection;
    36 import javax.crypto.Mac;
    37 import javax.crypto.Mac;
    37 import javax.crypto.SecretKey;
    38 import javax.crypto.SecretKey;
       
    39 import javax.net.ssl.SSLPeerUnverifiedException;
       
    40 import static sun.security.ssl.ClientAuthType.CLIENT_AUTH_REQUIRED;
    38 import sun.security.ssl.ClientHello.ClientHelloMessage;
    41 import sun.security.ssl.ClientHello.ClientHelloMessage;
    39 import sun.security.ssl.SSLExtension.ExtensionConsumer;
    42 import sun.security.ssl.SSLExtension.ExtensionConsumer;
    40 import sun.security.ssl.SSLExtension.SSLExtensionSpec;
    43 import sun.security.ssl.SSLExtension.SSLExtensionSpec;
    41 import sun.security.ssl.SSLHandshake.HandshakeMessage;
    44 import sun.security.ssl.SSLHandshake.HandshakeMessage;
    42 import static sun.security.ssl.SSLExtension.*;
    45 import static sun.security.ssl.SSLExtension.*;
   165             }
   168             }
   166         }
   169         }
   167 
   170 
   168         int getIdsEncodedLength() {
   171         int getIdsEncodedLength() {
   169             int idEncodedLength = 0;
   172             int idEncodedLength = 0;
   170             for(PskIdentity curId : identities) {
   173             for (PskIdentity curId : identities) {
   171                 idEncodedLength += curId.getEncodedLength();
   174                 idEncodedLength += curId.getEncodedLength();
   172             }
   175             }
   173 
   176 
   174             return idEncodedLength;
   177             return idEncodedLength;
   175         }
   178         }
   188             int bindersEncodedLength = getBindersEncodedLength();
   191             int bindersEncodedLength = getBindersEncodedLength();
   189             int encodedLength = 4 + idsEncodedLength + bindersEncodedLength;
   192             int encodedLength = 4 + idsEncodedLength + bindersEncodedLength;
   190             byte[] buffer = new byte[encodedLength];
   193             byte[] buffer = new byte[encodedLength];
   191             ByteBuffer m = ByteBuffer.wrap(buffer);
   194             ByteBuffer m = ByteBuffer.wrap(buffer);
   192             Record.putInt16(m, idsEncodedLength);
   195             Record.putInt16(m, idsEncodedLength);
   193             for(PskIdentity curId : identities) {
   196             for (PskIdentity curId : identities) {
   194                 curId.writeEncoded(m);
   197                 curId.writeEncoded(m);
   195             }
   198             }
   196             Record.putInt16(m, bindersEncodedLength);
   199             Record.putInt16(m, bindersEncodedLength);
   197             for (byte[] curBinder : binders) {
   200             for (byte[] curBinder : binders) {
   198                 Record.putBytes8(m, curBinder);
   201                 Record.putBytes8(m, curBinder);
   218             return messageFormat.format(messageFields);
   221             return messageFormat.format(messageFields);
   219         }
   222         }
   220 
   223 
   221         String identitiesString() {
   224         String identitiesString() {
   222             StringBuilder result = new StringBuilder();
   225             StringBuilder result = new StringBuilder();
   223             for(PskIdentity curId : identities) {
   226             for (PskIdentity curId : identities) {
   224                 result.append(curId.toString() + "\n");
   227                 result.append(curId.toString() + "\n");
   225             }
   228             }
   226 
   229 
   227             return result.toString();
   230             return result.toString();
   228         }
   231         }
   229 
   232 
   230         String bindersString() {
   233         String bindersString() {
   231             StringBuilder result = new StringBuilder();
   234             StringBuilder result = new StringBuilder();
   232             for(byte[] curBinder : binders) {
   235             for (byte[] curBinder : binders) {
   233                 result.append("{" + Utilities.toHexString(curBinder) + "}\n");
   236                 result.append("{" + Utilities.toHexString(curBinder) + "}\n");
   234             }
   237             }
   235 
   238 
   236             return result.toString();
   239             return result.toString();
   237         }
   240         }
   326 
   329 
   327         @Override
   330         @Override
   328         public void consume(ConnectionContext context,
   331         public void consume(ConnectionContext context,
   329                             HandshakeMessage message,
   332                             HandshakeMessage message,
   330                             ByteBuffer buffer) throws IOException {
   333                             ByteBuffer buffer) throws IOException {
       
   334             ClientHelloMessage clientHello = (ClientHelloMessage) message;
   331             ServerHandshakeContext shc = (ServerHandshakeContext)context;
   335             ServerHandshakeContext shc = (ServerHandshakeContext)context;
   332             // Is it a supported and enabled extension?
   336             // Is it a supported and enabled extension?
   333             if (!shc.sslConfig.isAvailable(SSLExtension.CH_PRE_SHARED_KEY)) {
   337             if (!shc.sslConfig.isAvailable(SSLExtension.CH_PRE_SHARED_KEY)) {
   334                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
   338                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
   335                     SSLLogger.fine(
   339                     SSLLogger.fine(
   365                 SSLSessionContextImpl sessionCache = (SSLSessionContextImpl)
   369                 SSLSessionContextImpl sessionCache = (SSLSessionContextImpl)
   366                         shc.sslContext.engineGetServerSessionContext();
   370                         shc.sslContext.engineGetServerSessionContext();
   367                 int idIndex = 0;
   371                 int idIndex = 0;
   368                 for (PskIdentity requestedId : pskSpec.identities) {
   372                 for (PskIdentity requestedId : pskSpec.identities) {
   369                     SSLSessionImpl s = sessionCache.get(requestedId.identity);
   373                     SSLSessionImpl s = sessionCache.get(requestedId.identity);
   370                     if (s != null && s.isRejoinable() &&
   374                     if (s != null && canRejoin(clientHello, shc, s)) {
   371                             s.getPreSharedKey().isPresent()) {
       
   372                         if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
   375                         if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
   373                             SSLLogger.fine("Resuming session: ", s);
   376                             SSLLogger.fine("Resuming session: ", s);
   374                         }
   377                         }
   375 
   378 
   376                         // binder will be checked later
   379                         // binder will be checked later
   390                 }
   393                 }
   391             }
   394             }
   392 
   395 
   393             // update the context
   396             // update the context
   394             shc.handshakeExtensions.put(
   397             shc.handshakeExtensions.put(
   395                     SSLExtension.CH_PRE_SHARED_KEY, pskSpec);
   398                 SSLExtension.CH_PRE_SHARED_KEY, pskSpec);
   396         }
   399         }
       
   400     }
       
   401 
       
   402     private static boolean canRejoin(ClientHelloMessage clientHello,
       
   403         ServerHandshakeContext shc, SSLSessionImpl s) {
       
   404 
       
   405         boolean result = s.isRejoinable() && s.getPreSharedKey().isPresent();
       
   406 
       
   407         // Check protocol version
       
   408         if (result && s.getProtocolVersion() != shc.negotiatedProtocol) {
       
   409             if (SSLLogger.isOn &&
       
   410                 SSLLogger.isOn("ssl,handshake,verbose")) {
       
   411 
       
   412                 SSLLogger.finest("Can't resume, incorrect protocol version");
       
   413             }
       
   414             result = false;
       
   415         }
       
   416 
       
   417         // Validate the required client authentication.
       
   418         if (result &&
       
   419             (shc.sslConfig.clientAuthType == CLIENT_AUTH_REQUIRED)) {
       
   420             try {
       
   421                 s.getPeerPrincipal();
       
   422             } catch (SSLPeerUnverifiedException e) {
       
   423                 if (SSLLogger.isOn &&
       
   424                         SSLLogger.isOn("ssl,handshake,verbose")) {
       
   425                     SSLLogger.finest(
       
   426                         "Can't resume, " +
       
   427                         "client authentication is required");
       
   428                 }
       
   429                 result = false;
       
   430             }
       
   431 
       
   432             // Make sure the list of supported signature algorithms matches
       
   433             Collection<SignatureScheme> sessionSigAlgs =
       
   434                 s.getLocalSupportedSignatureSchemes();
       
   435             if (result &&
       
   436                 !shc.localSupportedSignAlgs.containsAll(sessionSigAlgs)) {
       
   437 
       
   438                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   439                     SSLLogger.fine("Can't resume. Session uses different " +
       
   440                         "signature algorithms");
       
   441                 }
       
   442                 result = false;
       
   443             }
       
   444         }
       
   445 
       
   446         // Ensure cipher suite can be negotiated
       
   447         if (result && (!shc.isNegotiable(s.getSuite()) ||
       
   448             !clientHello.cipherSuites.contains(s.getSuite()))) {
       
   449             if (SSLLogger.isOn &&
       
   450                     SSLLogger.isOn("ssl,handshake,verbose")) {
       
   451                 SSLLogger.finest(
       
   452                     "Can't resume, unavailable session cipher suite");
       
   453             }
       
   454             result = false;
       
   455         }
       
   456 
       
   457         return result;
   397     }
   458     }
   398 
   459 
   399     private static final
   460     private static final
   400             class CHPreSharedKeyUpdate implements HandshakeConsumer {
   461             class CHPreSharedKeyUpdate implements HandshakeConsumer {
   401         // Prevent instantiation of this class.
   462         // Prevent instantiation of this class.
   545                     SSLLogger.fine("No session to resume.");
   606                     SSLLogger.fine("No session to resume.");
   546                 }
   607                 }
   547                 return null;
   608                 return null;
   548             }
   609             }
   549 
   610 
       
   611             // Make sure the list of supported signature algorithms matches
       
   612             Collection<SignatureScheme> sessionSigAlgs =
       
   613                 chc.resumingSession.getLocalSupportedSignatureSchemes();
       
   614             if (!chc.localSupportedSignAlgs.containsAll(sessionSigAlgs)) {
       
   615                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   616                     SSLLogger.fine("Existing session uses different " +
       
   617                         "signature algorithms");
       
   618                 }
       
   619                 return null;
       
   620             }
       
   621 
       
   622             // The session must have a pre-shared key
   550             Optional<SecretKey> pskOpt = chc.resumingSession.getPreSharedKey();
   623             Optional<SecretKey> pskOpt = chc.resumingSession.getPreSharedKey();
   551             if (!pskOpt.isPresent()) {
   624             if (!pskOpt.isPresent()) {
   552                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
   625                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
   553                     SSLLogger.fine("Existing session has no PSK.");
   626                     SSLLogger.fine("Existing session has no PSK.");
   554                 }
   627                 }
   656                 hmac.init(finishedKey);
   729                 hmac.init(finishedKey);
   657                 return hmac.doFinal(digest);
   730                 return hmac.doFinal(digest);
   658             } catch (NoSuchAlgorithmException | InvalidKeyException ex) {
   731             } catch (NoSuchAlgorithmException | InvalidKeyException ex) {
   659                 throw new IOException(ex);
   732                 throw new IOException(ex);
   660             }
   733             }
   661         } catch(GeneralSecurityException ex) {
   734         } catch (GeneralSecurityException ex) {
   662             throw new IOException(ex);
   735             throw new IOException(ex);
   663         }
   736         }
   664     }
   737     }
   665 
   738 
   666     private static SecretKey deriveBinderKey(SecretKey psk,
   739     private static SecretKey deriveBinderKey(SecretKey psk,