All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.tencent.kona.sun.security.provider.certpath.RevocationChecker Maven / Gradle / Ivy

Go to download

A Java security provider for supporting ShangMi algorithms in public key infrastructure

There is a newer version: 1.0.15
Show newest version
/*
 * Copyright (c) 2012, 2023, 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 com.tencent.kona.sun.security.provider.certpath;

import java.io.IOException;
import java.math.BigInteger;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.AccessController;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivilegedAction;
import java.security.PublicKey;
import java.security.Security;
import java.security.cert.CertPathValidatorException.BasicReason;
import java.security.cert.Extension;
import java.security.cert.*;
import java.util.*;
import javax.security.auth.x500.X500Principal;

import com.tencent.kona.pkix.PKIXInsts;
import com.tencent.kona.sun.security.util.CollectionUtil;

import com.tencent.kona.sun.security.util.Debug;
import com.tencent.kona.sun.security.util.KnownOIDs;
import com.tencent.kona.sun.security.x509.AccessDescription;
import com.tencent.kona.sun.security.x509.AuthorityInfoAccessExtension;
import com.tencent.kona.sun.security.x509.CRLDistributionPointsExtension;
import com.tencent.kona.sun.security.x509.DistributionPoint;
import com.tencent.kona.sun.security.x509.GeneralName;
import com.tencent.kona.sun.security.x509.GeneralNames;
import com.tencent.kona.sun.security.x509.PKIXExtensions;
import com.tencent.kona.sun.security.x509.X500Name;
import com.tencent.kona.sun.security.x509.X509CRLEntryImpl;
import com.tencent.kona.sun.security.x509.X509CertImpl;
import com.tencent.kona.java.util.HexFormat;

class RevocationChecker extends PKIXRevocationChecker {

    private static final Debug debug = Debug.getInstance("certpath");

    private TrustAnchor anchor;
    private PKIX.ValidatorParams params;
    private boolean onlyEE;
    private boolean softFail;
    private boolean crlDP;
    private URI responderURI;
    private X509Certificate responderCert;
    private List certStores;
    private Map ocspResponses;
    private List ocspExtensions;
    private final boolean legacy;
    private final LinkedList softFailExceptions =
            new LinkedList<>();

    // state variables
    private OCSPResponse.IssuerInfo issuerInfo;
    private PublicKey prevPubKey;
    private boolean crlSignFlag;
    private int certIndex;

    private enum Mode { PREFER_OCSP, PREFER_CRLS, ONLY_CRLS, ONLY_OCSP }
    private Mode mode = Mode.PREFER_OCSP;

    private static class RevocationProperties {
        boolean onlyEE;
        boolean ocspEnabled;
        boolean crlDPEnabled;
        String ocspUrl;
        String ocspSubject;
        String ocspIssuer;
        String ocspSerial;
        boolean ocspNonce;
    }
    private RevocationProperties rp;
    private static final int DEFAULT_NONCE_BYTES = 16;

    RevocationChecker() {
        legacy = false;
    }

    RevocationChecker(TrustAnchor anchor, PKIX.ValidatorParams params)
            throws CertPathValidatorException
    {
        legacy = true;
        init(anchor, params);
    }

    void init(TrustAnchor anchor, PKIX.ValidatorParams params)
            throws CertPathValidatorException
    {
        rp = getRevocationProperties();
        URI uri = getOcspResponder();
        responderURI = (uri == null) ? toURI(rp.ocspUrl) : uri;
        X509Certificate cert = getOcspResponderCert();
        responderCert = (cert == null)
                ? getResponderCert(rp, params.trustAnchors(),
                params.certStores())
                : cert;
        Set

* Note that this does not provide support for indirect CRLs, * only CRLs signed with a different key (but the same issuer * name) as the certificate being checked. * * @param cert the X509Certificate to be checked * @param prevKey the PublicKey that failed * @param signFlag true if that key was trusted to sign CRLs * @param stackedCerts a Set of X509Certificates * whose revocation status depends on the * non-revoked status of this cert. To avoid * circular dependencies, we assume they're * revoked while checking the revocation * status of this cert. * @throws CertPathValidatorException if the cert's revocation status * cannot be verified successfully with another key */ private void verifyWithSeparateSigningKey(X509Certificate cert, PublicKey prevKey, boolean signFlag, Set stackedCerts) throws CertPathValidatorException { String msg = "revocation status"; if (debug != null) { debug.println( "RevocationChecker.verifyWithSeparateSigningKey()" + " ---checking " + msg + "..."); } // Reject circular dependencies - RFC 5280 is not explicit on how // to handle this, but does suggest that they can be a security // risk and can create unresolvable dependencies if ((stackedCerts != null) && stackedCerts.contains(cert)) { if (debug != null) { debug.println( "RevocationChecker.verifyWithSeparateSigningKey()" + " circular dependency"); } throw new CertPathValidatorException ("Could not determine revocation status", null, null, -1, BasicReason.UNDETERMINED_REVOCATION_STATUS); } // Try to find another key that might be able to sign // CRLs vouching for this cert. // If prevKey wasn't trusted, maybe we just didn't have the right // path to it. Don't rule that key out. if (!signFlag) { buildToNewKey(cert, null, stackedCerts); } else { buildToNewKey(cert, prevKey, stackedCerts); } } private static final boolean [] CRL_SIGN_USAGE = { false, false, false, false, false, false, true }; /** * Tries to find a CertPath that establishes a key that can be * used to verify the revocation status of a given certificate. * Ignores keys that have previously been tried. Throws a * CertPathValidatorException if no such key could be found. * * @param currCert the X509Certificate to be checked * @param prevKey the PublicKey of the certificate whose key * cannot be used to vouch for the CRL and should be ignored * @param stackedCerts a Set of X509Certificates> * whose revocation status depends on the * establishment of this path. * @throws CertPathValidatorException on failure */ private void buildToNewKey(X509Certificate currCert, PublicKey prevKey, Set stackedCerts) throws CertPathValidatorException { if (debug != null) { debug.println("RevocationChecker.buildToNewKey()" + " starting work"); } Set badKeys = new HashSet<>(); if (prevKey != null) { badKeys.add(prevKey); } X509CertSelector certSel = new RejectKeySelector(badKeys); certSel.setSubject(currCert.getIssuerX500Principal()); certSel.setKeyUsage(CRL_SIGN_USAGE); Set newAnchors = anchor == null ? params.trustAnchors() : Collections.singleton(anchor); PKIXBuilderParameters builderParams; try { builderParams = new PKIXBuilderParameters(newAnchors, certSel); } catch (InvalidAlgorithmParameterException iape) { throw new RuntimeException(iape); // should never occur } builderParams.setInitialPolicies(params.initialPolicies()); builderParams.setCertStores(certStores); builderParams.setExplicitPolicyRequired (params.explicitPolicyRequired()); builderParams.setPolicyMappingInhibited (params.policyMappingInhibited()); builderParams.setAnyPolicyInhibited(params.anyPolicyInhibited()); // Policy qualifiers must be rejected, since we don't have // any way to convey them back to the application. // That's the default, so no need to write code. builderParams.setDate(params.date()); builderParams.setCertPathCheckers(params.certPathCheckers()); builderParams.setSigProvider(params.sigProvider()); // Skip revocation during this build to detect circular // references. But check revocation afterwards, using the // key (or any other that works). builderParams.setRevocationEnabled(false); // check for AuthorityInformationAccess extension if (Builder.USE_AIA) { X509CertImpl currCertImpl = null; try { currCertImpl = X509CertImpl.toImpl(currCert); } catch (CertificateException ce) { // ignore but log it if (debug != null) { debug.println("RevocationChecker.buildToNewKey: " + "error decoding cert: " + ce); } } AuthorityInfoAccessExtension aiaExt = null; if (currCertImpl != null) { aiaExt = currCertImpl.getAuthorityInfoAccessExtension(); } if (aiaExt != null) { List adList = aiaExt.getAccessDescriptions(); if (adList != null) { for (AccessDescription ad : adList) { CertStore cs = URICertStore.getInstance(ad); if (cs != null) { if (debug != null) { debug.println("adding AIAext CertStore"); } builderParams.addCertStore(cs); } } } } } CertPathBuilder builder; try { builder = PKIXInsts.getCertPathBuilder("PKIX"); } catch (NoSuchAlgorithmException nsae) { throw new CertPathValidatorException(nsae); } while (true) { try { if (debug != null) { debug.println("RevocationChecker.buildToNewKey()" + " about to try build ..."); } PKIXCertPathBuilderResult cpbr = (PKIXCertPathBuilderResult)builder.build(builderParams); if (debug != null) { debug.println("RevocationChecker.buildToNewKey()" + " about to check revocation ..."); } // Now check revocation of all certs in path, assuming that // the stackedCerts are revoked. if (stackedCerts == null) { stackedCerts = new HashSet<>(); } stackedCerts.add(currCert); TrustAnchor ta = cpbr.getTrustAnchor(); PublicKey prevKey2 = ta.getCAPublicKey(); if (prevKey2 == null) { prevKey2 = ta.getTrustedCert().getPublicKey(); } boolean signFlag = true; List cpList = cpbr.getCertPath().getCertificates(); try { for (int i = cpList.size() - 1; i >= 0; i--) { X509Certificate cert = (X509Certificate) cpList.get(i); if (debug != null) { debug.println("RevocationChecker.buildToNewKey()" + " index " + i + " checking " + cert); } checkCRLs(cert, prevKey2, null, signFlag, true, stackedCerts, newAnchors); signFlag = certCanSignCrl(cert); prevKey2 = cert.getPublicKey(); } } catch (CertPathValidatorException cpve) { // ignore it and try to get another key badKeys.add(cpbr.getPublicKey()); continue; } if (debug != null) { debug.println("RevocationChecker.buildToNewKey()" + " got key " + cpbr.getPublicKey()); } // Now check revocation on the current cert using that key and // the corresponding certificate. // If it doesn't check out, try to find a different key. // And if we can't find a key, then return false. PublicKey newKey = cpbr.getPublicKey(); X509Certificate newCert = cpList.isEmpty() ? null : (X509Certificate) cpList.get(0); try { checkCRLs(currCert, newKey, newCert, true, false, null, params.trustAnchors()); // If that passed, the cert is OK! return; } catch (CertPathValidatorException cpve) { // If it is revoked, rethrow exception if (cpve.getReason() == BasicReason.REVOKED) { throw cpve; } // Otherwise, ignore the exception and // try to get another key. } badKeys.add(newKey); } catch (InvalidAlgorithmParameterException iape) { throw new CertPathValidatorException(iape); } catch (CertPathBuilderException cpbe) { throw new CertPathValidatorException ("Could not determine revocation status", null, null, -1, BasicReason.UNDETERMINED_REVOCATION_STATUS); } } } /* * This inner class extends the X509CertSelector to add an additional * check to make sure the subject public key isn't on a particular list. * This class is used by buildToNewKey() to make sure the builder doesn't * end up with a CertPath to a public key that has already been rejected. */ private static class RejectKeySelector extends X509CertSelector { private final Set badKeySet; /** * Creates a new RejectKeySelector. * * @param badPublicKeys a Set of * PublicKeys that * should be rejected (or null * if no such check should be done) */ RejectKeySelector(Set badPublicKeys) { this.badKeySet = badPublicKeys; } /** * Decides whether a Certificate should be selected. * * @param cert the Certificate to be checked * @return true if the Certificate should be * selected, false otherwise */ @Override public boolean match(Certificate cert) { if (!super.match(cert)) return false; if (badKeySet.contains(cert.getPublicKey())) { if (debug != null) debug.println("RejectKeySelector.match: bad key"); return false; } if (debug != null) debug.println("RejectKeySelector.match: returning true"); return true; } /** * Return a printable representation of the CertSelector. * * @return a String describing the contents of the * CertSelector */ @Override public String toString() { return "RejectKeySelector: [\n" + super.toString() + badKeySet + "]"; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy