src/java.base/share/classes/sun/security/ssl/X509KeyManagerImpl.java
changeset 50768 68fa3d4026ea
parent 47216 71c04702a3d5
child 57950 4612a3cfb927
equal deleted inserted replaced
50767:356eaea05bf0 50768:68fa3d4026ea
     1 /*
     1 /*
     2  * Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    24  */
    24  */
    25 
    25 
    26 package sun.security.ssl;
    26 package sun.security.ssl;
    27 
    27 
    28 import java.lang.ref.*;
    28 import java.lang.ref.*;
       
    29 import java.net.Socket;
       
    30 import java.security.AlgorithmConstraints;
       
    31 import java.security.KeyStore;
       
    32 import java.security.KeyStore.Builder;
       
    33 import java.security.KeyStore.Entry;
       
    34 import java.security.KeyStore.PrivateKeyEntry;
       
    35 import java.security.Principal;
       
    36 import java.security.PrivateKey;
       
    37 import java.security.cert.CertPathValidatorException;
       
    38 import java.security.cert.Certificate;
       
    39 import java.security.cert.CertificateException;
       
    40 import java.security.cert.X509Certificate;
    29 import java.util.*;
    41 import java.util.*;
    30 import static java.util.Locale.ENGLISH;
       
    31 import java.util.concurrent.atomic.AtomicLong;
    42 import java.util.concurrent.atomic.AtomicLong;
    32 import java.net.Socket;
       
    33 
       
    34 import java.security.*;
       
    35 import java.security.KeyStore.*;
       
    36 import java.security.cert.*;
       
    37 import java.security.cert.Certificate;
       
    38 
       
    39 import javax.net.ssl.*;
    43 import javax.net.ssl.*;
    40 
       
    41 import sun.security.provider.certpath.AlgorithmChecker;
    44 import sun.security.provider.certpath.AlgorithmChecker;
    42 import sun.security.validator.Validator;
    45 import sun.security.validator.Validator;
    43 
    46 
    44 /**
    47 /**
    45  * The new X509 key manager implementation. The main differences to the
    48  * The new X509 key manager implementation. The main differences to the
    59  * @author  Andreas Sterbenz
    62  * @author  Andreas Sterbenz
    60  */
    63  */
    61 final class X509KeyManagerImpl extends X509ExtendedKeyManager
    64 final class X509KeyManagerImpl extends X509ExtendedKeyManager
    62         implements X509KeyManager {
    65         implements X509KeyManager {
    63 
    66 
    64     private static final Debug debug = Debug.getInstance("ssl");
       
    65 
       
    66     private static final boolean useDebug =
       
    67                             (debug != null) && Debug.isOn("keymanager");
       
    68 
       
    69     // for unit testing only, set via privileged reflection
    67     // for unit testing only, set via privileged reflection
    70     private static Date verificationDate;
    68     private static Date verificationDate;
    71 
    69 
    72     // list of the builders
    70     // list of the builders
    73     private final List<Builder> builders;
    71     private final List<Builder> builders;
   187 
   185 
   188             SSLSocket sslSocket = (SSLSocket)socket;
   186             SSLSocket sslSocket = (SSLSocket)socket;
   189             SSLSession session = sslSocket.getHandshakeSession();
   187             SSLSession session = sslSocket.getHandshakeSession();
   190 
   188 
   191             if (session != null) {
   189             if (session != null) {
   192                 ProtocolVersion protocolVersion =
   190                 if (ProtocolVersion.useTLS12PlusSpec(session.getProtocol())) {
   193                     ProtocolVersion.valueOf(session.getProtocol());
       
   194                 if (protocolVersion.useTLS12PlusSpec()) {
       
   195                     String[] peerSupportedSignAlgs = null;
   191                     String[] peerSupportedSignAlgs = null;
   196 
   192 
   197                     if (session instanceof ExtendedSSLSession) {
   193                     if (session instanceof ExtendedSSLSession) {
   198                         ExtendedSSLSession extSession =
   194                         ExtendedSSLSession extSession =
   199                             (ExtendedSSLSession)session;
   195                             (ExtendedSSLSession)session;
   215     // Gets algorithm constraints of the engine.
   211     // Gets algorithm constraints of the engine.
   216     private AlgorithmConstraints getAlgorithmConstraints(SSLEngine engine) {
   212     private AlgorithmConstraints getAlgorithmConstraints(SSLEngine engine) {
   217         if (engine != null) {
   213         if (engine != null) {
   218             SSLSession session = engine.getHandshakeSession();
   214             SSLSession session = engine.getHandshakeSession();
   219             if (session != null) {
   215             if (session != null) {
   220                 ProtocolVersion protocolVersion =
   216                 if (ProtocolVersion.useTLS12PlusSpec(session.getProtocol())) {
   221                     ProtocolVersion.valueOf(session.getProtocol());
       
   222                 if (protocolVersion.useTLS12PlusSpec()) {
       
   223                     String[] peerSupportedSignAlgs = null;
   217                     String[] peerSupportedSignAlgs = null;
   224 
   218 
   225                     if (session instanceof ExtendedSSLSession) {
   219                     if (session instanceof ExtendedSSLSession) {
   226                         ExtendedSSLSession extSession =
   220                         ExtendedSSLSession extSession =
   227                             (ExtendedSSLSession)session;
   221                             (ExtendedSSLSession)session;
   295         final String keyAlgorithm;
   289         final String keyAlgorithm;
   296 
   290 
   297         // In TLS 1.2, the signature algorithm  has been obsoleted by the
   291         // In TLS 1.2, the signature algorithm  has been obsoleted by the
   298         // supported_signature_algorithms, and the certificate type no longer
   292         // supported_signature_algorithms, and the certificate type no longer
   299         // restricts the algorithm used to sign the certificate.
   293         // restricts the algorithm used to sign the certificate.
       
   294         //
   300         // However, because we don't support certificate type checking other
   295         // However, because we don't support certificate type checking other
   301         // than rsa_sign, dss_sign and ecdsa_sign, we don't have to check the
   296         // than rsa_sign, dss_sign and ecdsa_sign, we don't have to check the
   302         // protocol version here.
   297         // protocol version here.
   303         final String sigKeyAlgorithm;
   298         final String sigKeyAlgorithm;
   304 
   299 
   326                         chain[1].getPublicKey().getAlgorithm());
   321                         chain[1].getPublicKey().getAlgorithm());
   327             } else {
   322             } else {
   328                 // Check the signature algorithm of the certificate itself.
   323                 // Check the signature algorithm of the certificate itself.
   329                 // Look for the "withRSA" in "SHA1withRSA", etc.
   324                 // Look for the "withRSA" in "SHA1withRSA", etc.
   330                 X509Certificate issuer = (X509Certificate)chain[0];
   325                 X509Certificate issuer = (X509Certificate)chain[0];
   331                 String sigAlgName = issuer.getSigAlgName().toUpperCase(ENGLISH);
   326                 String sigAlgName =
   332                 String pattern = "WITH" + sigKeyAlgorithm.toUpperCase(ENGLISH);
   327                         issuer.getSigAlgName().toUpperCase(Locale.ENGLISH);
       
   328                 String pattern =
       
   329                         "WITH" + sigKeyAlgorithm.toUpperCase(Locale.ENGLISH);
   333                 return sigAlgName.contains(pattern);
   330                 return sigAlgName.contains(pattern);
   334             }
   331             }
   335         }
   332         }
   336     }
   333     }
   337 
   334 
   386                     // the results will either be a single perfect match
   383                     // the results will either be a single perfect match
   387                     // or 1 or more imperfect matches
   384                     // or 1 or more imperfect matches
   388                     // if it's a perfect match, return immediately
   385                     // if it's a perfect match, return immediately
   389                     EntryStatus status = results.get(0);
   386                     EntryStatus status = results.get(0);
   390                     if (status.checkResult == CheckResult.OK) {
   387                     if (status.checkResult == CheckResult.OK) {
   391                         if (useDebug) {
   388                         if (SSLLogger.isOn && SSLLogger.isOn("keymanager")) {
   392                             debug.println("KeyMgr: choosing key: " + status);
   389                             SSLLogger.fine("KeyMgr: choosing key: " + status);
   393                         }
   390                         }
   394                         return makeAlias(status);
   391                         return makeAlias(status);
   395                     }
   392                     }
   396                     if (allResults == null) {
   393                     if (allResults == null) {
   397                         allResults = new ArrayList<EntryStatus>();
   394                         allResults = new ArrayList<EntryStatus>();
   401             } catch (Exception e) {
   398             } catch (Exception e) {
   402                 // ignore
   399                 // ignore
   403             }
   400             }
   404         }
   401         }
   405         if (allResults == null) {
   402         if (allResults == null) {
   406             if (useDebug) {
   403             if (SSLLogger.isOn && SSLLogger.isOn("keymanager")) {
   407                 debug.println("KeyMgr: no matching key found");
   404                 SSLLogger.fine("KeyMgr: no matching key found");
   408             }
   405             }
   409             return null;
   406             return null;
   410         }
   407         }
   411         Collections.sort(allResults);
   408         Collections.sort(allResults);
   412         if (useDebug) {
   409         if (SSLLogger.isOn && SSLLogger.isOn("keymanager")) {
   413             debug.println("KeyMgr: no good matching key found, "
   410             SSLLogger.fine(
   414                         + "returning best match out of:");
   411                     "KeyMgr: no good matching key found, "
   415             debug.println(allResults.toString());
   412                     + "returning best match out of", allResults);
   416         }
   413         }
   417         return makeAlias(allResults.get(0));
   414         return makeAlias(allResults.get(0));
   418     }
   415     }
   419 
   416 
   420     /*
   417     /*
   437                 List<EntryStatus> results = getAliases(i, keyTypeList,
   434                 List<EntryStatus> results = getAliases(i, keyTypeList,
   438                                     issuerSet, true, checkType, constraints,
   435                                     issuerSet, true, checkType, constraints,
   439                                     null, null);
   436                                     null, null);
   440                 if (results != null) {
   437                 if (results != null) {
   441                     if (allResults == null) {
   438                     if (allResults == null) {
   442                         allResults = new ArrayList<EntryStatus>();
   439                         allResults = new ArrayList<>();
   443                     }
   440                     }
   444                     allResults.addAll(results);
   441                     allResults.addAll(results);
   445                 }
   442                 }
   446             } catch (Exception e) {
   443             } catch (Exception e) {
   447                 // ignore
   444                 // ignore
   448             }
   445             }
   449         }
   446         }
   450         if (allResults == null || allResults.isEmpty()) {
   447         if (allResults == null || allResults.isEmpty()) {
   451             if (useDebug) {
   448             if (SSLLogger.isOn && SSLLogger.isOn("keymanager")) {
   452                 debug.println("KeyMgr: no matching alias found");
   449                 SSLLogger.fine("KeyMgr: no matching alias found");
   453             }
   450             }
   454             return null;
   451             return null;
   455         }
   452         }
   456         Collections.sort(allResults);
   453         Collections.sort(allResults);
   457         if (useDebug) {
   454         if (SSLLogger.isOn && SSLLogger.isOn("keymanager")) {
   458             debug.println("KeyMgr: getting aliases: " + allResults);
   455             SSLLogger.fine("KeyMgr: getting aliases", allResults);
   459         }
   456         }
   460         return toAliases(allResults);
   457         return toAliases(allResults);
   461     }
   458     }
   462 
   459 
   463     // turn candidate entries into unique aliases we can return to JSSE
   460     // turn candidate entries into unique aliases we can return to JSSE
   542 
   539 
   543         private static boolean getBit(boolean[] keyUsage, int bit) {
   540         private static boolean getBit(boolean[] keyUsage, int bit) {
   544             return (bit < keyUsage.length) && keyUsage[bit];
   541             return (bit < keyUsage.length) && keyUsage[bit];
   545         }
   542         }
   546 
   543 
   547         // check if this certificate is appropriate for this type of use
   544         // Check if this certificate is appropriate for this type of use
   548         // first check extensions, if they match, check expiration
   545         // first check extensions, if they match, check expiration.
   549         // note: we may want to move this code into the sun.security.validator
   546         //
       
   547         // Note: we may want to move this code into the sun.security.validator
   550         // package
   548         // package
   551         CheckResult check(X509Certificate cert, Date date,
   549         CheckResult check(X509Certificate cert, Date date,
   552                 List<SNIServerName> serverNames, String idAlgorithm) {
   550                 List<SNIServerName> serverNames, String idAlgorithm) {
   553 
   551 
   554             if (this == NONE) {
   552             if (this == NONE) {
   568 
   566 
   569                 // check key usage
   567                 // check key usage
   570                 boolean[] ku = cert.getKeyUsage();
   568                 boolean[] ku = cert.getKeyUsage();
   571                 if (ku != null) {
   569                 if (ku != null) {
   572                     String algorithm = cert.getPublicKey().getAlgorithm();
   570                     String algorithm = cert.getPublicKey().getAlgorithm();
   573                     boolean kuSignature = getBit(ku, 0);
   571                     boolean supportsDigitalSignature = getBit(ku, 0);
   574                     switch (algorithm) {
   572                     switch (algorithm) {
   575                         case "RSA":
   573                         case "RSA":
   576                             // require either signature bit
   574                             // require either signature bit
   577                             // or if server also allow key encipherment bit
   575                             // or if server also allow key encipherment bit
   578                             if (kuSignature == false) {
   576                             if (!supportsDigitalSignature) {
   579                                 if ((this == CLIENT) || (getBit(ku, 2) == false)) {
   577                                 if (this == CLIENT || getBit(ku, 2) == false) {
   580                                     return CheckResult.EXTENSION_MISMATCH;
   578                                     return CheckResult.EXTENSION_MISMATCH;
   581                                 }
   579                                 }
   582                             }
   580                             }
   583                             break;
   581                             break;
       
   582                         case "RSASSA-PSS":
       
   583                             if (!supportsDigitalSignature && (this == SERVER)) {
       
   584                                 return CheckResult.EXTENSION_MISMATCH;
       
   585                             }
       
   586                             break;
   584                         case "DSA":
   587                         case "DSA":
   585                             // require signature bit
   588                             // require signature bit
   586                             if (kuSignature == false) {
   589                             if (!supportsDigitalSignature) {
   587                                 return CheckResult.EXTENSION_MISMATCH;
   590                                 return CheckResult.EXTENSION_MISMATCH;
   588                             }
   591                             }
   589                             break;
   592                             break;
   590                         case "DH":
   593                         case "DH":
   591                             // require keyagreement bit
   594                             // require keyagreement bit
   593                                 return CheckResult.EXTENSION_MISMATCH;
   596                                 return CheckResult.EXTENSION_MISMATCH;
   594                             }
   597                             }
   595                             break;
   598                             break;
   596                         case "EC":
   599                         case "EC":
   597                             // require signature bit
   600                             // require signature bit
   598                             if (kuSignature == false) {
   601                             if (!supportsDigitalSignature) {
   599                                 return CheckResult.EXTENSION_MISMATCH;
   602                                 return CheckResult.EXTENSION_MISMATCH;
   600                             }
   603                             }
   601                             // For servers, also require key agreement.
   604                             // For servers, also require key agreement.
   602                             // This is not totally accurate as the keyAgreement
   605                             // This is not totally accurate as the keyAgreement
   603                             // bit is only necessary for static ECDH key
   606                             // bit is only necessary for static ECDH key
   629                             try {
   632                             try {
   630                                 serverName =
   633                                 serverName =
   631                                     new SNIHostName(serverName.getEncoded());
   634                                     new SNIHostName(serverName.getEncoded());
   632                             } catch (IllegalArgumentException iae) {
   635                             } catch (IllegalArgumentException iae) {
   633                                 // unlikely to happen, just in case ...
   636                                 // unlikely to happen, just in case ...
   634                                 if (useDebug) {
   637                                 if (SSLLogger.isOn &&
   635                                     debug.println(
   638                                         SSLLogger.isOn("keymanager")) {
       
   639                                     SSLLogger.fine(
   636                                        "Illegal server name: " + serverName);
   640                                        "Illegal server name: " + serverName);
   637                                 }
   641                                 }
   638 
   642 
   639                                 return CheckResult.INSENSITIVE;
   643                                 return CheckResult.INSENSITIVE;
   640                             }
   644                             }
   644 
   648 
   645                         try {
   649                         try {
   646                             X509TrustManagerImpl.checkIdentity(hostname,
   650                             X509TrustManagerImpl.checkIdentity(hostname,
   647                                                         cert, idAlgorithm);
   651                                                         cert, idAlgorithm);
   648                         } catch (CertificateException e) {
   652                         } catch (CertificateException e) {
   649                             if (useDebug) {
   653                             if (SSLLogger.isOn &&
   650                                 debug.println(
   654                                     SSLLogger.isOn("keymanager")) {
   651                                    "Certificate identity does not match " +
   655                                 SSLLogger.fine(
   652                                    "Server Name Inidication (SNI): " +
   656                                     "Certificate identity does not match " +
   653                                    hostname);
   657                                     "Server Name Inidication (SNI): " +
       
   658                                     hostname);
   654                             }
   659                             }
   655                             return CheckResult.INSENSITIVE;
   660                             return CheckResult.INSENSITIVE;
   656                         }
   661                         }
   657 
   662 
   658                         break;
   663                         break;
   722         Date date = verificationDate;
   727         Date date = verificationDate;
   723         boolean preferred = false;
   728         boolean preferred = false;
   724         for (Enumeration<String> e = ks.aliases(); e.hasMoreElements(); ) {
   729         for (Enumeration<String> e = ks.aliases(); e.hasMoreElements(); ) {
   725             String alias = e.nextElement();
   730             String alias = e.nextElement();
   726             // check if it is a key entry (private key or secret key)
   731             // check if it is a key entry (private key or secret key)
   727             if (ks.isKeyEntry(alias) == false) {
   732             if (!ks.isKeyEntry(alias)) {
   728                 continue;
   733                 continue;
   729             }
   734             }
   730 
   735 
   731             Certificate[] chain = ks.getCertificateChain(alias);
   736             Certificate[] chain = ks.getCertificateChain(alias);
   732             if ((chain == null) || (chain.length == 0)) {
   737             if ((chain == null) || (chain.length == 0)) {
   755                     break;
   760                     break;
   756                 }
   761                 }
   757                 j++;
   762                 j++;
   758             }
   763             }
   759             if (keyIndex == -1) {
   764             if (keyIndex == -1) {
   760                 if (useDebug) {
   765                 if (SSLLogger.isOn && SSLLogger.isOn("keymanager")) {
   761                     debug.println("Ignoring alias " + alias
   766                     SSLLogger.fine("Ignore alias " + alias
   762                                 + ": key algorithm does not match");
   767                                 + ": key algorithm does not match");
   763                 }
   768                 }
   764                 continue;
   769                 continue;
   765             }
   770             }
   766             // check issuers
   771             // check issuers
   772                         found = true;
   777                         found = true;
   773                         break;
   778                         break;
   774                     }
   779                     }
   775                 }
   780                 }
   776                 if (found == false) {
   781                 if (found == false) {
   777                     if (useDebug) {
   782                     if (SSLLogger.isOn && SSLLogger.isOn("keymanager")) {
   778                         debug.println("Ignoring alias " + alias
   783                         SSLLogger.fine(
   779                                     + ": issuers do not match");
   784                                 "Ignore alias " + alias
       
   785                                 + ": issuers do not match");
   780                     }
   786                     }
   781                     continue;
   787                     continue;
   782                 }
   788                 }
   783             }
   789             }
   784 
   790 
   785             // check the algorithm constraints
   791             // check the algorithm constraints
   786             if (constraints != null &&
   792             if (constraints != null &&
   787                     !conformsToAlgorithmConstraints(constraints, chain,
   793                     !conformsToAlgorithmConstraints(constraints, chain,
   788                             checkType.getValidator())) {
   794                             checkType.getValidator())) {
   789 
   795 
   790                 if (useDebug) {
   796                 if (SSLLogger.isOn && SSLLogger.isOn("keymanager")) {
   791                     debug.println("Ignoring alias " + alias +
   797                     SSLLogger.fine("Ignore alias " + alias +
   792                             ": certificate list does not conform to " +
   798                             ": certificate list does not conform to " +
   793                             "algorithm constraints");
   799                             "algorithm constraints");
   794                 }
   800                 }
   795                 continue;
   801                 continue;
   796             }
   802             }
   811                 // if we have a good match and do not need all matches,
   817                 // if we have a good match and do not need all matches,
   812                 // return immediately
   818                 // return immediately
   813                 return Collections.singletonList(status);
   819                 return Collections.singletonList(status);
   814             } else {
   820             } else {
   815                 if (results == null) {
   821                 if (results == null) {
   816                     results = new ArrayList<EntryStatus>();
   822                     results = new ArrayList<>();
   817                 }
   823                 }
   818                 results.add(status);
   824                 results.add(status);
   819             }
   825             }
   820         }
   826         }
   821         return results;
   827         return results;
   823 
   829 
   824     private static boolean conformsToAlgorithmConstraints(
   830     private static boolean conformsToAlgorithmConstraints(
   825             AlgorithmConstraints constraints, Certificate[] chain,
   831             AlgorithmConstraints constraints, Certificate[] chain,
   826             String variant) {
   832             String variant) {
   827 
   833 
   828         AlgorithmChecker checker = new AlgorithmChecker(constraints, null, variant);
   834         AlgorithmChecker checker =
       
   835                 new AlgorithmChecker(constraints, null, variant);
   829         try {
   836         try {
   830             checker.init(false);
   837             checker.init(false);
   831         } catch (CertPathValidatorException cpve) {
   838         } catch (CertPathValidatorException cpve) {
   832             // unlikely to happen
   839             // unlikely to happen
   833             if (useDebug) {
   840             if (SSLLogger.isOn && SSLLogger.isOn("keymanager")) {
   834                 debug.println(
   841                 SSLLogger.fine(
   835                     "Cannot initialize algorithm constraints checker: " + cpve);
   842                     "Cannot initialize algorithm constraints checker", cpve);
   836             }
   843             }
   837 
   844 
   838             return false;
   845             return false;
   839         }
   846         }
   840 
   847 
   843             Certificate cert = chain[i];
   850             Certificate cert = chain[i];
   844             try {
   851             try {
   845                 // We don't care about the unresolved critical extensions.
   852                 // We don't care about the unresolved critical extensions.
   846                 checker.check(cert, Collections.<String>emptySet());
   853                 checker.check(cert, Collections.<String>emptySet());
   847             } catch (CertPathValidatorException cpve) {
   854             } catch (CertPathValidatorException cpve) {
   848                 if (useDebug) {
   855                 if (SSLLogger.isOn && SSLLogger.isOn("keymanager")) {
   849                     debug.println("Certificate (" + cert +
   856                     SSLLogger.fine("Certificate does not conform to " +
   850                         ") does not conform to algorithm constraints: " + cpve);
   857                             "algorithm constraints", cert, cpve);
   851                 }
   858                 }
   852 
   859 
   853                 return false;
   860                 return false;
   854             }
   861             }
   855         }
   862         }
   856 
   863 
   857         return true;
   864         return true;
   858     }
   865     }
   859 
       
   860 }
   866 }