/* * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.security.provider.certpath; import java.security.AlgorithmConstraints; import java.security.CryptoPrimitive; import java.security.Timestamp; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.Set; import java.util.EnumSet; import java.math.BigInteger; import java.security.PublicKey; import java.security.KeyFactory; import java.security.AlgorithmParameters; import java.security.GeneralSecurityException; import java.security.cert.Certificate; import java.security.cert.X509CRL; import java.security.cert.X509Certificate; import java.security.cert.PKIXCertPathChecker; import java.security.cert.TrustAnchor; import java.security.cert.CRLException; import java.security.cert.CertificateException; import java.security.cert.CertPathValidatorException; import java.security.cert.CertPathValidatorException.BasicReason; import java.security.cert.PKIXReason; import java.security.interfaces.DSAParams; import java.security.interfaces.DSAPublicKey; import java.security.spec.DSAPublicKeySpec; import sun.security.util.AnchorCertificates; import sun.security.util.CertConstraintParameters; import sun.security.util.Debug; import sun.security.util.DisabledAlgorithmConstraints; import sun.security.x509.X509CertImpl; import sun.security.x509.X509CRLImpl; import sun.security.x509.AlgorithmId; /** * A {@code PKIXCertPathChecker} implementation to check whether a * specified certificate contains the required algorithm constraints. *
* Certificate fields such as the subject public key, the signature
* algorithm, key usage, extended key usage, etc. need to conform to
* the specified algorithm constraints.
*
* @see PKIXCertPathChecker
* @see PKIXParameters
*/
public final class AlgorithmChecker extends PKIXCertPathChecker {
private static final Debug debug = Debug.getInstance("certpath");
private final AlgorithmConstraints constraints;
private final PublicKey trustedPubKey;
private final Date pkixdate;
private PublicKey prevPubKey;
private final Timestamp jarTimestamp;
private static final Set
* Note that this constructor will be used to check a certification
* path where the trust anchor is unknown, or a certificate list which may
* contain the trust anchor. This constructor is used by SunJSSE.
*
* @param constraints the algorithm constraints (or null)
*/
public AlgorithmChecker(AlgorithmConstraints constraints) {
this.prevPubKey = null;
this.trustedPubKey = null;
this.constraints = constraints;
this.pkixdate = null;
this.jarTimestamp = null;
}
/**
* Create a new {@code AlgorithmChecker} with the given
* {@code Timestamp}.
*
* Note that this constructor will be used to check a certification
* path for signed JAR files that are timestamped.
*
* @param jarTimestamp Timestamp passed for JAR timestamp constraint
* checking. Set to null if not applicable.
*/
public AlgorithmChecker(Timestamp jarTimestamp) {
this.prevPubKey = null;
this.trustedPubKey = null;
this.constraints = certPathDefaultConstraints;
if (jarTimestamp == null) {
throw new IllegalArgumentException(
"Timestamp cannot be null");
}
this.pkixdate = jarTimestamp.getTimestamp();
this.jarTimestamp = jarTimestamp;
}
/**
* Create a new {@code AlgorithmChecker} with the
* given {@code TrustAnchor} and {@code AlgorithmConstraints}.
*
* @param anchor the trust anchor selected to validate the target
* certificate
* @param constraints the algorithm constraints (or null)
* @param pkixdate Date the constraints are checked against. The value is
* either the PKIXParameter date or null for the current date.
*
* @throws IllegalArgumentException if the {@code anchor} is null
*/
public AlgorithmChecker(TrustAnchor anchor,
AlgorithmConstraints constraints,
Date pkixdate) {
if (anchor != null) {
if (anchor.getTrustedCert() != null) {
this.trustedPubKey = anchor.getTrustedCert().getPublicKey();
// Check for anchor certificate restrictions
trustedMatch = checkFingerprint(anchor.getTrustedCert());
if (trustedMatch && debug != null) {
debug.println("trustedMatch = true");
}
} else {
this.trustedPubKey = anchor.getCAPublicKey();
}
} else {
this.trustedPubKey = null;
if (debug != null) {
debug.println("TrustAnchor is null, trustedMatch is false.");
}
}
this.prevPubKey = trustedPubKey;
this.constraints = constraints;
this.pkixdate = pkixdate;
this.jarTimestamp = null;
}
/**
* Create a new {@code AlgorithmChecker} with the
* given {@code TrustAnchor} and {@code PKIXParameter} date.
*
* @param anchor the trust anchor selected to validate the target
* certificate
* @param pkixdate Date the constraints are checked against. The value is
* either the PKIXParameter date or null for the current date.
*
* @throws IllegalArgumentException if the {@code anchor} is null
*/
public AlgorithmChecker(TrustAnchor anchor, Date pkixdate) {
this(anchor, certPathDefaultConstraints, pkixdate);
}
// Check this 'cert' for restrictions in the AnchorCertificates
// trusted certificates list
private static boolean checkFingerprint(X509Certificate cert) {
if (!publicCALimits) {
return false;
}
if (debug != null) {
debug.println("AlgorithmChecker.contains: " + cert.getSigAlgName());
}
return AnchorCertificates.contains(cert);
}
Timestamp getJarTimestamp() {
return jarTimestamp;
}
@Override
public void init(boolean forward) throws CertPathValidatorException {
// Note that this class does not support forward mode.
if (!forward) {
if (trustedPubKey != null) {
prevPubKey = trustedPubKey;
} else {
prevPubKey = null;
}
} else {
throw new
CertPathValidatorException("forward checking not supported");
}
}
@Override
public boolean isForwardCheckingSupported() {
// Note that as this class does not support forward mode, the method
// will always returns false.
return false;
}
@Override
public Set
* If there is no trust anchor specified and the checker has not started,
* set the trust anchor.
*
* @param anchor the trust anchor selected to validate the target
* certificate
*/
void trySetTrustAnchor(TrustAnchor anchor) {
// Don't bother if the check has started or trust anchor has already
// specified.
if (prevPubKey == null) {
if (anchor == null) {
throw new IllegalArgumentException(
"The trust anchor cannot be null");
}
// Don't bother to change the trustedPubKey.
if (anchor.getTrustedCert() != null) {
prevPubKey = anchor.getTrustedCert().getPublicKey();
// Check for anchor certificate restrictions
trustedMatch = checkFingerprint(anchor.getTrustedCert());
if (trustedMatch && debug != null) {
debug.println("trustedMatch = true");
}
} else {
prevPubKey = anchor.getCAPublicKey();
}
}
}
/**
* Check the signature algorithm with the specified public key.
*
* @param key the public key to verify the CRL signature
* @param crl the target CRL
*/
static void check(PublicKey key, X509CRL crl)
throws CertPathValidatorException {
X509CRLImpl x509CRLImpl = null;
try {
x509CRLImpl = X509CRLImpl.toImpl(crl);
} catch (CRLException ce) {
throw new CertPathValidatorException(ce);
}
AlgorithmId algorithmId = x509CRLImpl.getSigAlgId();
check(key, algorithmId);
}
/**
* Check the signature algorithm with the specified public key.
*
* @param key the public key to verify the CRL signature
* @param algorithmId signature algorithm Algorithm ID
*/
static void check(PublicKey key, AlgorithmId algorithmId)
throws CertPathValidatorException {
String sigAlgName = algorithmId.getName();
AlgorithmParameters sigAlgParams = algorithmId.getParameters();
if (!certPathDefaultConstraints.permits(
SIGNATURE_PRIMITIVE_SET, sigAlgName, key, sigAlgParams)) {
throw new CertPathValidatorException(
"Algorithm constraints check failed on signature algorithm: " +
sigAlgName + " is disabled",
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
}
}
}