jdk/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java
changeset 37726 bbecfff95ec3
parent 33297 5970d160cbc0
child 38576 ccaac80108c5
equal deleted inserted replaced
37725:04ee31f1c2a9 37726:bbecfff95ec3
     1 /*
     1 /*
     2  * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2009, 2016, 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
    29 import java.security.CryptoPrimitive;
    29 import java.security.CryptoPrimitive;
    30 import java.util.Collection;
    30 import java.util.Collection;
    31 import java.util.Collections;
    31 import java.util.Collections;
    32 import java.util.Set;
    32 import java.util.Set;
    33 import java.util.EnumSet;
    33 import java.util.EnumSet;
    34 import java.util.HashSet;
       
    35 import java.math.BigInteger;
    34 import java.math.BigInteger;
    36 import java.security.PublicKey;
    35 import java.security.PublicKey;
    37 import java.security.KeyFactory;
    36 import java.security.KeyFactory;
    38 import java.security.AlgorithmParameters;
    37 import java.security.AlgorithmParameters;
    39 import java.security.NoSuchAlgorithmException;
       
    40 import java.security.GeneralSecurityException;
    38 import java.security.GeneralSecurityException;
    41 import java.security.cert.Certificate;
    39 import java.security.cert.Certificate;
    42 import java.security.cert.X509CRL;
    40 import java.security.cert.X509CRL;
    43 import java.security.cert.X509Certificate;
    41 import java.security.cert.X509Certificate;
    44 import java.security.cert.PKIXCertPathChecker;
    42 import java.security.cert.PKIXCertPathChecker;
    46 import java.security.cert.CRLException;
    44 import java.security.cert.CRLException;
    47 import java.security.cert.CertificateException;
    45 import java.security.cert.CertificateException;
    48 import java.security.cert.CertPathValidatorException;
    46 import java.security.cert.CertPathValidatorException;
    49 import java.security.cert.CertPathValidatorException.BasicReason;
    47 import java.security.cert.CertPathValidatorException.BasicReason;
    50 import java.security.cert.PKIXReason;
    48 import java.security.cert.PKIXReason;
    51 import java.io.IOException;
    49 import java.security.interfaces.DSAParams;
    52 import java.security.interfaces.*;
    50 import java.security.interfaces.DSAPublicKey;
    53 import java.security.spec.*;
    51 import java.security.spec.DSAPublicKeySpec;
    54 
    52 
       
    53 import sun.security.util.AnchorCertificates;
       
    54 import sun.security.util.CertConstraintParameters;
       
    55 import sun.security.util.Debug;
    55 import sun.security.util.DisabledAlgorithmConstraints;
    56 import sun.security.util.DisabledAlgorithmConstraints;
    56 import sun.security.x509.X509CertImpl;
    57 import sun.security.x509.X509CertImpl;
    57 import sun.security.x509.X509CRLImpl;
    58 import sun.security.x509.X509CRLImpl;
    58 import sun.security.x509.AlgorithmId;
    59 import sun.security.x509.AlgorithmId;
    59 
    60 
    67  *
    68  *
    68  * @see PKIXCertPathChecker
    69  * @see PKIXCertPathChecker
    69  * @see PKIXParameters
    70  * @see PKIXParameters
    70  */
    71  */
    71 public final class AlgorithmChecker extends PKIXCertPathChecker {
    72 public final class AlgorithmChecker extends PKIXCertPathChecker {
       
    73     private static final Debug debug = Debug.getInstance("certpath");
    72 
    74 
    73     private final AlgorithmConstraints constraints;
    75     private final AlgorithmConstraints constraints;
    74     private final PublicKey trustedPubKey;
    76     private final PublicKey trustedPubKey;
    75     private PublicKey prevPubKey;
    77     private PublicKey prevPubKey;
    76 
    78 
    86 
    88 
    87     private static final DisabledAlgorithmConstraints
    89     private static final DisabledAlgorithmConstraints
    88         certPathDefaultConstraints = new DisabledAlgorithmConstraints(
    90         certPathDefaultConstraints = new DisabledAlgorithmConstraints(
    89             DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS);
    91             DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS);
    90 
    92 
       
    93     // If there is no "cacerts" keyword, then disable anchor checking
       
    94     private static final boolean publicCALimits =
       
    95             certPathDefaultConstraints.checkProperty("jdkCA");
       
    96 
       
    97     // If anchor checking enabled, this will be true if the trust anchor
       
    98     // has a match in the cacerts file
       
    99     private boolean trustedMatch = false;
       
   100 
    91     /**
   101     /**
    92      * Create a new <code>AlgorithmChecker</code> with the algorithm
   102      * Create a new <code>AlgorithmChecker</code> with the algorithm
    93      * constraints specified in security property
   103      * constraints specified in security property
    94      * "jdk.certpath.disabledAlgorithms".
   104      * "jdk.certpath.disabledAlgorithms".
    95      *
   105      *
   134                         "The trust anchor cannot be null");
   144                         "The trust anchor cannot be null");
   135         }
   145         }
   136 
   146 
   137         if (anchor.getTrustedCert() != null) {
   147         if (anchor.getTrustedCert() != null) {
   138             this.trustedPubKey = anchor.getTrustedCert().getPublicKey();
   148             this.trustedPubKey = anchor.getTrustedCert().getPublicKey();
       
   149             // Check for anchor certificate restrictions
       
   150             trustedMatch = checkFingerprint(anchor.getTrustedCert());
       
   151             if (trustedMatch && debug != null) {
       
   152                 debug.println("trustedMatch = true");
       
   153             }
   139         } else {
   154         } else {
   140             this.trustedPubKey = anchor.getCAPublicKey();
   155             this.trustedPubKey = anchor.getCAPublicKey();
   141         }
   156         }
   142 
   157 
   143         this.prevPubKey = trustedPubKey;
   158         this.prevPubKey = trustedPubKey;
   144         this.constraints = constraints;
   159         this.constraints = constraints;
       
   160     }
       
   161 
       
   162     // Check this 'cert' for restrictions in the AnchorCertificates
       
   163     // trusted certificates list
       
   164     private static boolean checkFingerprint(X509Certificate cert) {
       
   165         if (!publicCALimits) {
       
   166             return false;
       
   167         }
       
   168 
       
   169         if (debug != null) {
       
   170             debug.println("AlgorithmChecker.contains: " + cert.getSigAlgName());
       
   171         }
       
   172         return AnchorCertificates.contains(cert);
   145     }
   173     }
   146 
   174 
   147     @Override
   175     @Override
   148     public void init(boolean forward) throws CertPathValidatorException {
   176     public void init(boolean forward) throws CertPathValidatorException {
   149         //  Note that this class does not support forward mode.
   177         //  Note that this class does not support forward mode.
   179         if (!(cert instanceof X509Certificate) || constraints == null) {
   207         if (!(cert instanceof X509Certificate) || constraints == null) {
   180             // ignore the check for non-x.509 certificate or null constraints
   208             // ignore the check for non-x.509 certificate or null constraints
   181             return;
   209             return;
   182         }
   210         }
   183 
   211 
   184         X509CertImpl x509Cert = null;
       
   185         try {
       
   186             x509Cert = X509CertImpl.toImpl((X509Certificate)cert);
       
   187         } catch (CertificateException ce) {
       
   188             throw new CertPathValidatorException(ce);
       
   189         }
       
   190 
       
   191         PublicKey currPubKey = x509Cert.getPublicKey();
       
   192         String currSigAlg = x509Cert.getSigAlgName();
       
   193 
       
   194         AlgorithmId algorithmId = null;
       
   195         try {
       
   196             algorithmId = (AlgorithmId)x509Cert.get(X509CertImpl.SIG_ALG);
       
   197         } catch (CertificateException ce) {
       
   198             throw new CertPathValidatorException(ce);
       
   199         }
       
   200 
       
   201         AlgorithmParameters currSigAlgParams = algorithmId.getParameters();
       
   202 
       
   203         // Check the current signature algorithm
       
   204         if (!constraints.permits(
       
   205                 SIGNATURE_PRIMITIVE_SET,
       
   206                 currSigAlg, currSigAlgParams)) {
       
   207             throw new CertPathValidatorException(
       
   208                 "Algorithm constraints check failed: " + currSigAlg,
       
   209                 null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
       
   210         }
       
   211 
       
   212         // check the key usage and key size
   212         // check the key usage and key size
   213         boolean[] keyUsage = x509Cert.getKeyUsage();
   213         boolean[] keyUsage = ((X509Certificate) cert).getKeyUsage();
   214         if (keyUsage != null && keyUsage.length < 9) {
   214         if (keyUsage != null && keyUsage.length < 9) {
   215             throw new CertPathValidatorException(
   215             throw new CertPathValidatorException(
   216                 "incorrect KeyUsage extension",
   216                 "incorrect KeyUsage extension",
   217                 null, null, -1, PKIXReason.INVALID_KEY_USAGE);
   217                 null, null, -1, PKIXReason.INVALID_KEY_USAGE);
   218         }
   218         }
   246             // KeyUsage.encipherOnly and KeyUsage.decipherOnly are
   246             // KeyUsage.encipherOnly and KeyUsage.decipherOnly are
   247             // undefined in the absence of the keyAgreement bit.
   247             // undefined in the absence of the keyAgreement bit.
   248 
   248 
   249             if (primitives.isEmpty()) {
   249             if (primitives.isEmpty()) {
   250                 throw new CertPathValidatorException(
   250                 throw new CertPathValidatorException(
   251                     "incorrect KeyUsage extension",
   251                     "incorrect KeyUsage extension bits",
   252                     null, null, -1, PKIXReason.INVALID_KEY_USAGE);
   252                     null, null, -1, PKIXReason.INVALID_KEY_USAGE);
   253             }
   253             }
   254         }
   254         }
   255 
   255 
   256         if (!constraints.permits(primitives, currPubKey)) {
   256         PublicKey currPubKey = cert.getPublicKey();
   257             throw new CertPathValidatorException(
   257 
   258                 "algorithm constraints check failed",
   258         // Check against DisabledAlgorithmConstraints certpath constraints.
   259                 null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
   259         // permits() will throw exception on failure.
       
   260         certPathDefaultConstraints.permits(primitives,
       
   261                 new CertConstraintParameters((X509Certificate)cert,
       
   262                         trustedMatch));
       
   263                 // new CertConstraintParameters(x509Cert, trustedMatch));
       
   264         // If there is no previous key, set one and exit
       
   265         if (prevPubKey == null) {
       
   266             prevPubKey = currPubKey;
       
   267             return;
       
   268         }
       
   269 
       
   270         X509CertImpl x509Cert;
       
   271         AlgorithmId algorithmId;
       
   272         try {
       
   273             x509Cert = X509CertImpl.toImpl((X509Certificate)cert);
       
   274             algorithmId = (AlgorithmId)x509Cert.get(X509CertImpl.SIG_ALG);
       
   275         } catch (CertificateException ce) {
       
   276             throw new CertPathValidatorException(ce);
       
   277         }
       
   278 
       
   279         AlgorithmParameters currSigAlgParams = algorithmId.getParameters();
       
   280         String currSigAlg = x509Cert.getSigAlgName();
       
   281 
       
   282         // If 'constraints' is not of DisabledAlgorithmConstraints, check all
       
   283         // everything individually
       
   284         if (!(constraints instanceof DisabledAlgorithmConstraints)) {
       
   285             // Check the current signature algorithm
       
   286             if (!constraints.permits(
       
   287                     SIGNATURE_PRIMITIVE_SET,
       
   288                     currSigAlg, currSigAlgParams)) {
       
   289                 throw new CertPathValidatorException(
       
   290                         "Algorithm constraints check failed on signature " +
       
   291                                 "algorithm: " + currSigAlg, null, null, -1,
       
   292                         BasicReason.ALGORITHM_CONSTRAINED);
       
   293             }
       
   294 
       
   295             if (!constraints.permits(primitives, currPubKey)) {
       
   296                 throw new CertPathValidatorException(
       
   297                         "Algorithm constraints check failed on keysize: " +
       
   298                                 sun.security.util.KeyUtil.getKeySize(currPubKey),
       
   299                         null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
       
   300             }
   260         }
   301         }
   261 
   302 
   262         // Check with previous cert for signature algorithm and public key
   303         // Check with previous cert for signature algorithm and public key
   263         if (prevPubKey != null) {
   304         if (prevPubKey != null) {
   264             if (currSigAlg != null) {
   305             if (!constraints.permits(
   265                 if (!constraints.permits(
   306                     SIGNATURE_PRIMITIVE_SET,
   266                         SIGNATURE_PRIMITIVE_SET,
   307                     currSigAlg, prevPubKey, currSigAlgParams)) {
   267                         currSigAlg, prevPubKey, currSigAlgParams)) {
   308                 throw new CertPathValidatorException(
   268                     throw new CertPathValidatorException(
   309                     "Algorithm constraints check failed on " +
   269                         "Algorithm constraints check failed: " + currSigAlg,
   310                             "signature algorithm: " + currSigAlg,
   270                         null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
   311                     null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
   271                 }
       
   272             }
   312             }
   273 
   313 
   274             // Inherit key parameters from previous key
   314             // Inherit key parameters from previous key
   275             if (PKIX.isDSAPublicKeyWithoutParams(currPubKey)) {
   315             if (PKIX.isDSAPublicKeyWithoutParams(currPubKey)) {
   276                 // Inherit DSA parameters from previous key
   316                 // Inherit DSA parameters from previous key
   280                 }
   320                 }
   281 
   321 
   282                 DSAParams params = ((DSAPublicKey)prevPubKey).getParams();
   322                 DSAParams params = ((DSAPublicKey)prevPubKey).getParams();
   283                 if (params == null) {
   323                 if (params == null) {
   284                     throw new CertPathValidatorException(
   324                     throw new CertPathValidatorException(
   285                                     "Key parameters missing");
   325                         "Key parameters missing from public key.");
   286                 }
   326                 }
   287 
   327 
   288                 try {
   328                 try {
   289                     BigInteger y = ((DSAPublicKey)currPubKey).getY();
   329                     BigInteger y = ((DSAPublicKey)currPubKey).getY();
   290                     KeyFactory kf = KeyFactory.getInstance("DSA");
   330                     KeyFactory kf = KeyFactory.getInstance("DSA");
   328             }
   368             }
   329 
   369 
   330             // Don't bother to change the trustedPubKey.
   370             // Don't bother to change the trustedPubKey.
   331             if (anchor.getTrustedCert() != null) {
   371             if (anchor.getTrustedCert() != null) {
   332                 prevPubKey = anchor.getTrustedCert().getPublicKey();
   372                 prevPubKey = anchor.getTrustedCert().getPublicKey();
       
   373                 // Check for anchor certificate restrictions
       
   374                 trustedMatch = checkFingerprint(anchor.getTrustedCert());
       
   375                 if (trustedMatch && debug != null) {
       
   376                     debug.println("trustedMatch = true");
       
   377                 }
   333             } else {
   378             } else {
   334                 prevPubKey = anchor.getCAPublicKey();
   379                 prevPubKey = anchor.getCAPublicKey();
   335             }
   380             }
   336         }
   381         }
   337     }
   382     }
   368         AlgorithmParameters sigAlgParams = algorithmId.getParameters();
   413         AlgorithmParameters sigAlgParams = algorithmId.getParameters();
   369 
   414 
   370         if (!certPathDefaultConstraints.permits(
   415         if (!certPathDefaultConstraints.permits(
   371                 SIGNATURE_PRIMITIVE_SET, sigAlgName, key, sigAlgParams)) {
   416                 SIGNATURE_PRIMITIVE_SET, sigAlgName, key, sigAlgParams)) {
   372             throw new CertPathValidatorException(
   417             throw new CertPathValidatorException(
   373                 "algorithm check failed: " + sigAlgName + " is disabled",
   418                 "Algorithm constraints check failed on signature algorithm: " +
       
   419                 sigAlgName + " is disabled",
   374                 null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
   420                 null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
   375         }
   421         }
   376     }
   422     }
   377 
   423 
   378 }
   424 }