723 lines
27 KiB
Java
723 lines
27 KiB
Java
/* WolfCryptPKIXCertPathValidator.java
|
|
*
|
|
* Copyright (C) 2006-2025 wolfSSL Inc.
|
|
*
|
|
* This file is part of wolfSSL.
|
|
*
|
|
* wolfSSL is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* wolfSSL 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 for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
|
*/
|
|
|
|
package com.wolfssl.provider.jce;
|
|
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
import java.util.Collection;
|
|
import java.util.ArrayList;
|
|
import java.security.InvalidAlgorithmParameterException;
|
|
import java.security.cert.Certificate;
|
|
import java.security.cert.X509Certificate;
|
|
import java.security.cert.TrustAnchor;
|
|
import java.security.cert.CertPathValidatorSpi;
|
|
import java.security.cert.CertPathValidatorResult;
|
|
import java.security.cert.CertPath;
|
|
import java.security.cert.CertPathChecker;
|
|
import java.security.cert.CertPathParameters;
|
|
import java.security.cert.CertPathValidatorException;
|
|
import java.security.cert.CertSelector;
|
|
import java.security.cert.CertStore;
|
|
import java.security.cert.CertStoreException;
|
|
import java.security.cert.X509CertSelector;
|
|
import java.security.cert.PKIXParameters;
|
|
import java.security.cert.PKIXCertPathChecker;
|
|
import java.security.cert.PKIXCertPathValidatorResult;
|
|
import java.security.cert.CRL;
|
|
import java.security.cert.X509CRL;
|
|
import java.security.cert.X509CRLSelector;
|
|
import javax.security.auth.x500.X500Principal;
|
|
|
|
import com.wolfssl.wolfcrypt.Fips;
|
|
import com.wolfssl.wolfcrypt.WolfCrypt;
|
|
import com.wolfssl.wolfcrypt.WolfSSLCertManager;
|
|
import com.wolfssl.wolfcrypt.WolfCryptException;
|
|
|
|
/**
|
|
* wolfJCE implementation of CertPathValidator for PKIX (X.509)
|
|
*
|
|
* This implementation supports most of CertPathValidator, but not the
|
|
* following items. If needed, please contact support@wolfssl.com
|
|
* with details of required support.
|
|
*
|
|
* A. Certificate policies, and this related setters/getters. As such,
|
|
* validation will not return PolicyNode in CertPathValidatorResult
|
|
* B. Overriding current date for validation (PKIXParameters.setDate())
|
|
* C. getRevocationChecker() throws UnsupportedOperationException.
|
|
* Internal revocation is done with CRL if
|
|
* PKIXParameters.isRevocationEnabled() is true and appropriate CRLs
|
|
* have been loaded into CertStore Set
|
|
*/
|
|
public class WolfCryptPKIXCertPathValidator extends CertPathValidatorSpi {
|
|
|
|
/**
|
|
* Create new WolfCryptPKIXCertPathValidator object.
|
|
*/
|
|
public WolfCryptPKIXCertPathValidator() {
|
|
log("created new WolfCryptPKIXCertPathValidator");
|
|
}
|
|
|
|
/**
|
|
* Check CertPathParameters matches our requirements.
|
|
* 1. Not null
|
|
* 2. Is an instance of PKIXParameters
|
|
*
|
|
* @throws InvalidAlgorithmParameterException if null or not an instance
|
|
* of PKIXParameters
|
|
*/
|
|
private void sanitizeCertPathParameters(CertPathParameters params)
|
|
throws InvalidAlgorithmParameterException {
|
|
|
|
log("sanitizing CertPathParameters");
|
|
|
|
if (params == null) {
|
|
throw new InvalidAlgorithmParameterException(
|
|
"CertPathParameters is null");
|
|
}
|
|
|
|
/* Check params is of type PKIXParameters */
|
|
if (!(params instanceof PKIXParameters)) {
|
|
throw new InvalidAlgorithmParameterException(
|
|
"params not of type PKIXParameters");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check CertPath matches our requirements.
|
|
* 1. CertPath.getType() is "X.509"
|
|
* 2. CertPath.getEncoding() contains "PkiPath"
|
|
*
|
|
* @throws InvalidAlgorithmParametersException if type is not X.509
|
|
* @throws CertPathValidatorException if PkiPath encoding is not supported
|
|
*/
|
|
private void sanitizeCertPath(CertPath path)
|
|
throws InvalidAlgorithmParameterException, CertPathValidatorException {
|
|
|
|
boolean pkiPathEncodingSupported = false;
|
|
Iterator<String> supportedCertEncodings = null;
|
|
|
|
log("sanitizing CertPath");
|
|
|
|
/* Verify CertPath type is X.509 */
|
|
if (!path.getType().equals("X.509")) {
|
|
throw new InvalidAlgorithmParameterException(
|
|
"PKIX CertPathValidator only supports X.509");
|
|
}
|
|
|
|
/* Check that PkiPath encoding is supported, which is an
|
|
* ASN.1 DER encoded sequence of the cert */
|
|
supportedCertEncodings = path.getEncodings();
|
|
while (supportedCertEncodings.hasNext()) {
|
|
if (supportedCertEncodings.next().equals("PkiPath")) {
|
|
pkiPathEncodingSupported = true;
|
|
}
|
|
}
|
|
if (!pkiPathEncodingSupported) {
|
|
throw new CertPathValidatorException(
|
|
"PkiPath CertPath encoding not supported but required");
|
|
}
|
|
}
|
|
|
|
private void checkTargetCertConstraints(X509Certificate cert,
|
|
int certIdx, CertPath path, PKIXParameters params)
|
|
throws CertPathValidatorException {
|
|
|
|
CertSelector selector = null;
|
|
X509CertSelector x509Selector = null;
|
|
|
|
if (cert == null || params == null) {
|
|
throw new CertPathValidatorException(
|
|
"X509Certificate in chain or PKIXParameters is null");
|
|
}
|
|
|
|
/* Only check leaf/peer certificate against constraints */
|
|
if (certIdx != 0) {
|
|
return;
|
|
}
|
|
|
|
/* Use CertSelector to check target cert */
|
|
selector = params.getTargetCertConstraints();
|
|
if (selector != null) {
|
|
log("checking target cert constraints against CertSelector");
|
|
|
|
if (!(selector instanceof X509CertSelector)) {
|
|
throw new CertPathValidatorException(
|
|
"CertSelector not of type X509CertSelector");
|
|
}
|
|
x509Selector = (X509CertSelector)selector;
|
|
|
|
if (!x509Selector.match(cert)) {
|
|
throw new CertPathValidatorException(
|
|
"Target certificate did not pass CertConstraints check");
|
|
}
|
|
}
|
|
else {
|
|
log("no cert constraints in params, not checking CertSelector");
|
|
}
|
|
}
|
|
|
|
private void disallowCertPolicyUse(PKIXParameters params)
|
|
throws CertPathValidatorException {
|
|
|
|
if (params == null) {
|
|
throw new CertPathValidatorException(
|
|
"PKIXParameters is null when checking for cert policies");
|
|
}
|
|
|
|
if (!params.getInitialPolicies().isEmpty()) {
|
|
throw new CertPathValidatorException(
|
|
"Certificate policies not supported by wolfJCE " +
|
|
"CertPathValidator, PKIXParameters.getInitialPolicies() is " +
|
|
"not empty");
|
|
}
|
|
|
|
/* Ignored, but log for debugging */
|
|
log("PKIXParameters.getPolicyQualifiersRejected(): " +
|
|
params.getPolicyQualifiersRejected());
|
|
log("PKIXParameters.isPolicyMappingInhibited(): " +
|
|
params.isPolicyMappingInhibited());
|
|
|
|
/* Should the any policy OID be processed if it is included in
|
|
* a certificate? Default is false, don't allow enablement since
|
|
* not supported here yet */
|
|
if (params.isAnyPolicyInhibited()) {
|
|
throw new CertPathValidatorException(
|
|
"Certificate policies not supported by wolfJCE " +
|
|
"CertPathValidator. PKIXParameters.setAnyPolicyInhibited() " +
|
|
"must be set to false (default)");
|
|
}
|
|
|
|
/* If true an acceptable policy needs to be explicitly identified in
|
|
* every certificate. Default is false, don't allow enablement since
|
|
* not supported here yet */
|
|
if (params.isExplicitPolicyRequired()) {
|
|
throw new CertPathValidatorException(
|
|
"Certificate policies not supported by wolfJCE " +
|
|
"CertPathValidator. PKIXParameters.setExplicitPolicy" +
|
|
"Required() must be set to false (default)");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check X509Certificate against constraints or settings inside
|
|
* PKIXParameters.
|
|
*
|
|
* @param cert certificate to check
|
|
* @param certIdx index of certificate, used when throwing exception
|
|
* @param path CertPath used when throwing exception
|
|
* @param params parameters used to get constraints from
|
|
*
|
|
* @throws CertPathValidatorException if checks on certificate fail
|
|
*/
|
|
private void sanitizeX509Certificate(X509Certificate cert,
|
|
int certIdx, CertPath path, PKIXParameters params)
|
|
throws CertPathValidatorException {
|
|
|
|
if (cert == null || params == null) {
|
|
throw new CertPathValidatorException(
|
|
"X509Certificate in chain or PKIXParameters is null");
|
|
}
|
|
|
|
/* Check target cert constraints, if set in parameters */
|
|
checkTargetCertConstraints(cert, certIdx, path, params);
|
|
|
|
/* Certificate policies are not currently supported by this
|
|
* CertPathValidator implementation, throw exceptions when
|
|
* user tries to use them. */
|
|
disallowCertPolicyUse(params);
|
|
}
|
|
|
|
/**
|
|
* Call all PKIXCertPathCheckers that have been registered into
|
|
* PKIXParameters. This allows users to do additional verification
|
|
* steps on certificates if needed.
|
|
*
|
|
* @param cert certificate to be checked
|
|
* @param params parameters from which to get PKIXCertPathChecker list
|
|
*
|
|
* @throws CertPathValidatorException if a checker fails validation on
|
|
* the given Certificate
|
|
*/
|
|
private void callCertPathCheckers(X509Certificate cert,
|
|
PKIXParameters params) throws CertPathValidatorException {
|
|
|
|
int i = 0;
|
|
List<PKIXCertPathChecker> pathCheckers = null;
|
|
|
|
if (cert == null || params == null) {
|
|
throw new CertPathValidatorException(
|
|
"X509Certificate in chain or PKIXParameters is null");
|
|
}
|
|
|
|
pathCheckers = params.getCertPathCheckers();
|
|
if (pathCheckers == null) {
|
|
/* Spec says this cannot be null */
|
|
throw new CertPathValidatorException(
|
|
"PKIXParameters.getCertPathCheckers() should not return null");
|
|
}
|
|
if (pathCheckers.isEmpty()) {
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < pathCheckers.size(); i++) {
|
|
log("calling CertPathChecker: " + pathCheckers.get(i));
|
|
|
|
/* Throws CertPathValidatorException on error */
|
|
pathCheckers.get(i).check((Certificate)cert);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load TrustAnchors from PKIXParameters into WolfSSLCertManager as
|
|
* trusted CA certificates.
|
|
*
|
|
* @param params PKIXParameters from which to get TrustAnchor Set
|
|
* @param cm WolfSSLCertManager to load TrustAnchors into as trusted roots
|
|
*
|
|
* @throws CertPathValidatorException on failure to load trust anchors
|
|
*/
|
|
private void loadTrustAnchorsIntoCertManager(
|
|
PKIXParameters params, WolfSSLCertManager cm)
|
|
throws CertPathValidatorException {
|
|
|
|
Set<TrustAnchor> trustAnchors = null;
|
|
Iterator<TrustAnchor> trustIterator = null;
|
|
|
|
log("loading TrustAnchors into native WolfSSLCertManager");
|
|
|
|
if (params == null || cm == null) {
|
|
throw new CertPathValidatorException(
|
|
"PKIXParameters or WolfSSLCertManager are null when loading " +
|
|
"TrustAnchors");
|
|
}
|
|
|
|
/* Load trust anchors into CertManager from PKIXParameters */
|
|
trustAnchors = params.getTrustAnchors();
|
|
if (trustAnchors == null || trustAnchors.isEmpty()) {
|
|
throw new CertPathValidatorException(
|
|
"No TrustAnchors in PKIXParameters");
|
|
}
|
|
|
|
/* Iterate through TrustAnchors, load as CAs into CertManager */
|
|
trustIterator = trustAnchors.iterator();
|
|
while (trustIterator.hasNext()) {
|
|
TrustAnchor anchor = trustIterator.next();
|
|
X509Certificate anchorCert = anchor.getTrustedCert();
|
|
if (anchorCert != null) {
|
|
try {
|
|
cm.CertManagerLoadCA(anchorCert);
|
|
|
|
log("loaded TrustAnchor: " +
|
|
anchorCert.getSubjectX500Principal().getName());
|
|
|
|
} catch (WolfCryptException e) {
|
|
throw new CertPathValidatorException(e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Verify X509Certificate chain from top down, ending with peer/leaf
|
|
* cert last.
|
|
*
|
|
*/
|
|
private void verifyCertChain(CertPath path, PKIXParameters params,
|
|
List<X509Certificate> certs, WolfSSLCertManager cm)
|
|
throws CertPathValidatorException {
|
|
|
|
int i = 0;
|
|
X509Certificate cert = null;
|
|
|
|
if (path == null || params == null || certs == null || cm == null) {
|
|
throw new CertPathValidatorException(
|
|
"Input args to verifyCertChain are null");
|
|
}
|
|
|
|
log("verifying certificate chain (chain size: " + certs.size() + ")");
|
|
|
|
/* Process certs from List in reverse order (top to peer) */
|
|
for (i = certs.size()-1; i >= 0; i--) {
|
|
cert = certs.get(i);
|
|
|
|
try {
|
|
/* Try to verify cert */
|
|
cm.CertManagerVerify(cert);
|
|
|
|
log("verified chain [" + i + "]: " +
|
|
cert.getSubjectX500Principal().getName());
|
|
|
|
} catch (WolfCryptException e) {
|
|
log("failed verification chain [" + i + "]: " +
|
|
cert.getSubjectX500Principal().getName());
|
|
|
|
throw new CertPathValidatorException(
|
|
"Failed verification on certificate", e, path, i);
|
|
}
|
|
|
|
/* Verified successfully. If this is a CA and we have more
|
|
* certs, load this as trusted (intermediate) */
|
|
if (i > 0 && cert.getBasicConstraints() >= 0) {
|
|
try {
|
|
cm.CertManagerLoadCA(cert);
|
|
|
|
log("chain [" + i + "] is intermediate, loading as root");
|
|
|
|
} catch (WolfCryptException e) {
|
|
|
|
log("chain [" + i + "] is CA, but failed to load as " +
|
|
"trusted root, not loading");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Search TrustAnchors in PKIXParameters for one that verifies the provided
|
|
* X509Certificate.
|
|
*
|
|
* @param params PKIXParameters to get TrustAnchors from
|
|
* @param cert X509Certificate for which to find signer cert
|
|
*
|
|
* @return TrustAnchor that signs provided cert
|
|
*
|
|
* @throws CertPathValidatorException if the search for TrustAnchor fails
|
|
*/
|
|
public TrustAnchor findTrustAnchor(PKIXParameters params,
|
|
X509Certificate cert) throws CertPathValidatorException {
|
|
|
|
Set<TrustAnchor> trustAnchors = null;
|
|
Iterator<TrustAnchor> trustIterator = null;
|
|
TrustAnchor anchorFound = null;
|
|
X500Principal issuer = null;
|
|
WolfSSLCertManager cm = null;
|
|
|
|
if (params == null || cert == null) {
|
|
throw new CertPathValidatorException(
|
|
"Input parameters are null to findTrustAnchor");
|
|
}
|
|
|
|
/* Issuer name we need to match */
|
|
issuer = cert.getIssuerX500Principal();
|
|
if (issuer == null) {
|
|
throw new CertPathValidatorException(
|
|
"Unable to get expected issuer name");
|
|
}
|
|
|
|
/* Get all TrustAnchors in PKIXParameters */
|
|
trustAnchors = params.getTrustAnchors();
|
|
if (trustAnchors == null || trustAnchors.isEmpty()) {
|
|
throw new CertPathValidatorException(
|
|
"No TrustAnchors in PKIXParameters");
|
|
}
|
|
|
|
try {
|
|
cm = new WolfSSLCertManager();
|
|
} catch (WolfCryptException e) {
|
|
throw new CertPathValidatorException(
|
|
"Failed to create native WolfSSLCertManager");
|
|
}
|
|
|
|
/* Iterate through TrustAnchors and check for match */
|
|
trustIterator = trustAnchors.iterator();
|
|
while (trustIterator.hasNext()) {
|
|
TrustAnchor anchor = trustIterator.next();
|
|
X509Certificate anchorCert = anchor.getTrustedCert();
|
|
if (anchorCert == null) {
|
|
/* Skip to next */
|
|
continue;
|
|
}
|
|
|
|
if (!anchorCert.getSubjectX500Principal().equals(issuer)) {
|
|
/* Isser name doesn't match, skip to next */
|
|
continue;
|
|
}
|
|
|
|
try {
|
|
/* Unload any CAs in CertManager */
|
|
cm.CertManagerUnloadCAs();
|
|
} catch (WolfCryptException e) {
|
|
cm.free();
|
|
throw new CertPathValidatorException(
|
|
"Unable to unload CAs from native WolfSSLCertManager");
|
|
}
|
|
|
|
try {
|
|
/* Load anchor as CA */
|
|
cm.CertManagerLoadCA(anchorCert);
|
|
} catch (WolfCryptException e) {
|
|
/* error loading CA, skip to next */
|
|
continue;
|
|
}
|
|
|
|
try {
|
|
/* Try to verify cert, mark found if successful */
|
|
cm.CertManagerVerify(cert);
|
|
anchorFound = anchor;
|
|
} catch (WolfCryptException e) {
|
|
/* Does not verify, skip to next */
|
|
continue;
|
|
}
|
|
}
|
|
|
|
/* Free native WolfSSLCertManager resources */
|
|
cm.free();
|
|
|
|
return anchorFound;
|
|
}
|
|
|
|
/**
|
|
* Check if revocation has been enabled in PKIXParameters, and if so
|
|
* find and load any CRLs in params.getCertStores().
|
|
*
|
|
* @param params parameters used to check if revocation is enabled
|
|
* and if so load any CRLs available
|
|
* @param cm WolfSSLCertManager to load CRLs into
|
|
* @param targetCert peer/leaf cert used to find matching CRL
|
|
*
|
|
* @throws CertPathValidatorException if error is encountered during
|
|
* revocation checking or CRL loading
|
|
*/
|
|
private void checkRevocationEnabledAndLoadCRLs(
|
|
PKIXParameters params, WolfSSLCertManager cm,
|
|
X509Certificate targetCert)
|
|
throws CertPathValidatorException {
|
|
|
|
int i = 0;
|
|
int loadedCount = 0;
|
|
List<CertStore> stores = null;
|
|
Collection<? extends CRL> crls = null;
|
|
|
|
if (params == null || cm == null) {
|
|
throw new CertPathValidatorException(
|
|
"PKIXParameters or WolfSSLCertManager is null");
|
|
}
|
|
|
|
if (params.isRevocationEnabled()) {
|
|
log("revocation enabled in PKIXParameters, checking " +
|
|
"for CRLs to load");
|
|
|
|
if (!WolfCrypt.CrlEnabled()) {
|
|
throw new CertPathValidatorException(
|
|
"Revocation enabled in PKIXParameters but native " +
|
|
"wolfCrypt CRL not compiled in");
|
|
}
|
|
|
|
/* Enable CRL in native WolfSSLCertManager */
|
|
cm.CertManagerEnableCRL(WolfCrypt.WOLFSSL_CRL_CHECK);
|
|
|
|
log("CRL support enabled in native WolfSSLCertManager");
|
|
|
|
stores = params.getCertStores();
|
|
if (stores == null || stores.isEmpty()) {
|
|
log("no CertStores in PKIXParameters to load CRLs");
|
|
return;
|
|
}
|
|
|
|
/* Create CRL selector to help match target X509Certificate */
|
|
X509CRLSelector selector = new X509CRLSelector();
|
|
selector.setCertificateChecking(targetCert);
|
|
|
|
try {
|
|
/* Find and load any matching CRLs */
|
|
for (i = 0; i < stores.size(); i++) {
|
|
crls = stores.get(i).getCRLs(selector);
|
|
for (CRL crl: crls) {
|
|
if (crl instanceof X509CRL) {
|
|
cm.CertManagerLoadCRL((X509CRL)crl);
|
|
loadedCount++;
|
|
}
|
|
}
|
|
}
|
|
} catch (CertStoreException e) {
|
|
throw new CertPathValidatorException(e);
|
|
}
|
|
|
|
log("loaded " + loadedCount + " CRLs into WolfSSLCertManager");
|
|
}
|
|
else {
|
|
log("revocation not enabled in PKIXParameters");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Validates the specified certification path using the provided
|
|
* algorithm parameter set.
|
|
*
|
|
* General validation process follows:
|
|
* 1. Sanitize CertPathParameters
|
|
* a. Verify not null and instanceof PKIXParameters
|
|
* 2. Sanitize CertPath
|
|
* a. CertPath.getType() is "X.509"
|
|
* b. CertPath.getEncoding() contains "PkiPath"
|
|
* 3. If wolfCrypt FIPS, verify params.getSigProvider() is wolfJCE
|
|
* 4. Sanitize Certificate objects in CertPath chain
|
|
* a. Check target certificate constraints meet target cert
|
|
* b. Check cert policies are not used (not supported)
|
|
* 5. Call any registered CertPathCheckers
|
|
* 6. Load TrustAnchors into WolfSSLCertManager
|
|
* 7. Enable CRL if requested, load CRLs from getCertStores()
|
|
* 8. Verify X.509 certificate chain
|
|
* 9. Find top-most TrustAnchor for return object
|
|
*
|
|
* @param certPath the CertPath to be validated. CertPath entries are
|
|
* ordered from leaf/peer up the chain to CA/root last.
|
|
* The certificate representing the last/final TrustAnchor
|
|
* should not be part of the CertPath.
|
|
* @param params the algorithm parameters to be used for validation
|
|
*
|
|
* @return the result of the validation
|
|
*
|
|
* @throws CertPathValidatorException if the CertPath does not validate
|
|
* @throws InvalidAlgorithmParameterException if the parameters or type
|
|
* specified are unsupported or inappropriate for this
|
|
* CertPathValidator implementation.
|
|
*/
|
|
@Override
|
|
public CertPathValidatorResult engineValidate(
|
|
CertPath certPath, CertPathParameters params)
|
|
throws CertPathValidatorException, InvalidAlgorithmParameterException {
|
|
|
|
int i = 0;
|
|
PKIXParameters pkixParams = null;
|
|
List<X509Certificate> certs = null;
|
|
WolfSSLCertManager cm = null;
|
|
TrustAnchor trustAnchor = null;
|
|
|
|
log("entered engineValidate(), FIPS enabled: " + Fips.enabled);
|
|
|
|
sanitizeCertPathParameters(params);
|
|
sanitizeCertPath(certPath);
|
|
|
|
pkixParams = (PKIXParameters)params;
|
|
|
|
/* If we are in FIPS mode, verify wolfJCE is the Signature provider
|
|
* to help maintain FIPS compliance */
|
|
if (Fips.enabled && pkixParams.getSigProvider() != "wolfJCE") {
|
|
if (pkixParams.getSigProvider() == null) {
|
|
/* Preferred Signature provider not set, set to wolfJCE */
|
|
pkixParams.setSigProvider("wolfJCE");
|
|
}
|
|
else {
|
|
throw new CertPathValidatorException(
|
|
"CertPathParameters Signature Provider must be wolfJCE " +
|
|
"when using wolfCrypt FIPS: " +
|
|
pkixParams.getSigProvider());
|
|
}
|
|
}
|
|
|
|
/* Use wolfSSL CertManager to facilitate chain verification */
|
|
try {
|
|
cm = new WolfSSLCertManager();
|
|
} catch (WolfCryptException e) {
|
|
throw new CertPathValidatorException(
|
|
"Failed to create native WolfSSLCertManager");
|
|
}
|
|
|
|
try {
|
|
if (pkixParams.getDate() != null) {
|
|
/* TODO: If pkixParams.getDate() is not null, we should
|
|
* use that time for verification instead of current time.
|
|
* Will need to wrap/register/use native time callback
|
|
* with wc_SetTimeCb() */
|
|
throw new CertPathValidatorException(
|
|
"Overriding date not supported with wolfJCE " +
|
|
"CertPathValidator implementation yet");
|
|
}
|
|
|
|
/* Get List of Certificate objects in CertPath, sanity check
|
|
* that they are X509Certificate instances. */
|
|
certs = new ArrayList<>();
|
|
for (Certificate cert : certPath.getCertificates()) {
|
|
if (cert instanceof X509Certificate) {
|
|
certs.add((X509Certificate) cert);
|
|
}
|
|
}
|
|
if (certs.size() == 0) {
|
|
throw new CertPathValidatorException(
|
|
"No Certificate objects in CertPath");
|
|
}
|
|
|
|
/* Sanity checks on certs from PKIXParameters constraints */
|
|
for (i = 0; i < certs.size(); i++) {
|
|
sanitizeX509Certificate(certs.get(i), i, certPath, pkixParams);
|
|
callCertPathCheckers(certs.get(i), pkixParams);
|
|
}
|
|
|
|
/* Load trust anchors into CertManager from PKIXParameters */
|
|
loadTrustAnchorsIntoCertManager(pkixParams, cm);
|
|
|
|
/* Enable CRL if PKIXParameters.isRevocationEnabled(), load
|
|
* any CRLs found in PKIXParameters.getCertStores(). Needs to
|
|
* happen after trust anchors are loaded, since native wolfSSL
|
|
* will try to find/verify CRL against trusted roots on load */
|
|
checkRevocationEnabledAndLoadCRLs(pkixParams, cm, certs.get(0));
|
|
|
|
/* Verify cert chain */
|
|
verifyCertChain(certPath, pkixParams, certs, cm);
|
|
|
|
/* Cert chain has been verified, find TrustAnchor to return
|
|
* in PKIXCertPathValidatorResult */
|
|
trustAnchor = findTrustAnchor(
|
|
pkixParams, certs.get(certs.size() - 1));
|
|
|
|
} finally {
|
|
/* Free native WolfSSLCertManager resources */
|
|
cm.free();
|
|
}
|
|
|
|
/* PolicyNode not returned, since certificate policies are not
|
|
* yet supported */
|
|
return new PKIXCertPathValidatorResult(trustAnchor, null,
|
|
certs.get(0).getPublicKey());
|
|
}
|
|
|
|
/**
|
|
* Returns a CertPathChecker that this implementation uses to check the
|
|
* revocation status of certificates.
|
|
*
|
|
* Not currently implemented in wolfJCE.
|
|
*
|
|
* @return a CertPathChecker object that this implementation uses to
|
|
* check the revocation status of certificates.
|
|
* @throws UnsupportedOperationException if this method is not implemented
|
|
*/
|
|
@Override
|
|
public CertPathChecker engineGetRevocationChecker()
|
|
throws UnsupportedOperationException {
|
|
|
|
throw new UnsupportedOperationException(
|
|
"getRevocationChecker() not supported by wolfJCE");
|
|
}
|
|
|
|
/**
|
|
* Internal log function, called when debug is enabled.
|
|
*
|
|
* @param msg Log message to be printed
|
|
*/
|
|
private void log(String msg) {
|
|
WolfCryptDebug.print("[CertPathValidator] " + msg);
|
|
}
|
|
}
|
|
|