Search in sources :

Example 1 with ValidationIssue

use of org.xipki.common.qa.ValidationIssue in project xipki by xipki.

the class OcspQa method checkSingleCert.

// method checkOcsp
private List<ValidationIssue> checkSingleCert(int index, SingleResp singleResp, IssuerHash issuerHash, OcspCertStatus expectedStatus, byte[] encodedCert, Date expectedRevTime, boolean extendedRevoke, Occurrence nextupdateOccurrence, Occurrence certhashOccurrence, ASN1ObjectIdentifier certhashAlg) {
    if (expectedStatus == OcspCertStatus.unknown || expectedStatus == OcspCertStatus.issuerUnknown) {
        certhashOccurrence = Occurrence.forbidden;
    }
    List<ValidationIssue> issues = new LinkedList<>();
    // issuer hash
    ValidationIssue issue = new ValidationIssue("OCSP.RESPONSE." + index + ".ISSUER", "certificate issuer");
    issues.add(issue);
    CertificateID certId = singleResp.getCertID();
    HashAlgo hashAlgo = HashAlgo.getInstance(certId.getHashAlgOID());
    if (hashAlgo == null) {
        issue.setFailureMessage("unknown hash algorithm " + certId.getHashAlgOID().getId());
    } else {
        if (!issuerHash.match(hashAlgo, certId.getIssuerNameHash(), certId.getIssuerKeyHash())) {
            issue.setFailureMessage("issuer not match");
        }
    }
    // status
    issue = new ValidationIssue("OCSP.RESPONSE." + index + ".STATUS", "certificate status");
    issues.add(issue);
    CertificateStatus singleCertStatus = singleResp.getCertStatus();
    OcspCertStatus status = null;
    Long revTimeSec = null;
    if (singleCertStatus == null) {
        status = OcspCertStatus.good;
    } else if (singleCertStatus instanceof RevokedStatus) {
        RevokedStatus revStatus = (RevokedStatus) singleCertStatus;
        revTimeSec = revStatus.getRevocationTime().getTime() / 1000;
        if (revStatus.hasRevocationReason()) {
            int reason = revStatus.getRevocationReason();
            if (extendedRevoke && reason == CrlReason.CERTIFICATE_HOLD.getCode() && revTimeSec == 0) {
                status = OcspCertStatus.unknown;
                revTimeSec = null;
            } else {
                CrlReason revocationReason = CrlReason.forReasonCode(reason);
                switch(revocationReason) {
                    case UNSPECIFIED:
                        status = OcspCertStatus.unspecified;
                        break;
                    case KEY_COMPROMISE:
                        status = OcspCertStatus.keyCompromise;
                        break;
                    case CA_COMPROMISE:
                        status = OcspCertStatus.cACompromise;
                        break;
                    case AFFILIATION_CHANGED:
                        status = OcspCertStatus.affiliationChanged;
                        break;
                    case SUPERSEDED:
                        status = OcspCertStatus.superseded;
                        break;
                    case CERTIFICATE_HOLD:
                        status = OcspCertStatus.certificateHold;
                        break;
                    case REMOVE_FROM_CRL:
                        status = OcspCertStatus.removeFromCRL;
                        break;
                    case PRIVILEGE_WITHDRAWN:
                        status = OcspCertStatus.privilegeWithdrawn;
                        break;
                    case AA_COMPROMISE:
                        status = OcspCertStatus.aACompromise;
                        break;
                    case CESSATION_OF_OPERATION:
                        status = OcspCertStatus.cessationOfOperation;
                        break;
                    default:
                        issue.setFailureMessage("should not reach here, unknown CRLReason " + revocationReason);
                        break;
                }
            }
        // end if
        } else {
            status = OcspCertStatus.rev_noreason;
        }
    // end if (revStatus.hasRevocationReason())
    } else if (singleCertStatus instanceof UnknownStatus) {
        status = extendedRevoke ? OcspCertStatus.issuerUnknown : OcspCertStatus.unknown;
    } else {
        issue.setFailureMessage("unknown certstatus: " + singleCertStatus.getClass().getName());
    }
    if (!issue.isFailed() && expectedStatus != status) {
        issue.setFailureMessage("is='" + status + "', but expected='" + expectedStatus + "'");
    }
    // revocation time
    issue = new ValidationIssue("OCSP.RESPONSE." + index + ".REVTIME", "certificate time");
    issues.add(issue);
    if (expectedRevTime != null) {
        if (revTimeSec == null) {
            issue.setFailureMessage("is='null', but expected='" + formatTime(expectedRevTime) + "'");
        } else if (revTimeSec != expectedRevTime.getTime() / 1000) {
            issue.setFailureMessage("is='" + formatTime(new Date(revTimeSec * 1000)) + "', but expected='" + formatTime(expectedRevTime) + "'");
        }
    }
    // nextUpdate
    Date nextUpdate = singleResp.getNextUpdate();
    issue = checkOccurrence("OCSP.RESPONSE." + index + ".NEXTUPDATE", nextUpdate, nextupdateOccurrence);
    issues.add(issue);
    Extension extension = singleResp.getExtension(ISISMTTObjectIdentifiers.id_isismtt_at_certHash);
    issue = checkOccurrence("OCSP.RESPONSE." + index + ".CERTHASH", extension, certhashOccurrence);
    issues.add(issue);
    if (extension != null) {
        ASN1Encodable extensionValue = extension.getParsedValue();
        CertHash certHash = CertHash.getInstance(extensionValue);
        ASN1ObjectIdentifier hashAlgOid = certHash.getHashAlgorithm().getAlgorithm();
        if (certhashAlg != null) {
            // certHash algorithm
            issue = new ValidationIssue("OCSP.RESPONSE." + index + ".CHASH.ALG", "certhash algorithm");
            issues.add(issue);
            ASN1ObjectIdentifier is = certHash.getHashAlgorithm().getAlgorithm();
            if (!certhashAlg.equals(is)) {
                issue.setFailureMessage("is '" + is.getId() + "', but expected '" + certhashAlg.getId() + "'");
            }
        }
        byte[] hashValue = certHash.getCertificateHash();
        if (encodedCert != null) {
            issue = new ValidationIssue("OCSP.RESPONSE." + index + ".CHASH.VALIDITY", "certhash validity");
            issues.add(issue);
            try {
                MessageDigest md = MessageDigest.getInstance(hashAlgOid.getId());
                byte[] expectedHashValue = md.digest(encodedCert);
                if (!Arrays.equals(expectedHashValue, hashValue)) {
                    issue.setFailureMessage("certhash does not match the requested certificate");
                }
            } catch (NoSuchAlgorithmException ex) {
                issue.setFailureMessage("NoSuchAlgorithm " + hashAlgOid.getId());
            }
        }
    // end if(encodedCert != null)
    }
    return issues;
}
Also used : CertHash(org.bouncycastle.asn1.isismtt.ocsp.CertHash) CertificateID(org.bouncycastle.cert.ocsp.CertificateID) HashAlgo(org.xipki.security.HashAlgo) CertificateStatus(org.bouncycastle.cert.ocsp.CertificateStatus) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) ValidationIssue(org.xipki.common.qa.ValidationIssue) LinkedList(java.util.LinkedList) Date(java.util.Date) UnknownStatus(org.bouncycastle.cert.ocsp.UnknownStatus) Extension(org.bouncycastle.asn1.x509.Extension) RevokedStatus(org.bouncycastle.cert.ocsp.RevokedStatus) CrlReason(org.xipki.security.CrlReason) ASN1Encodable(org.bouncycastle.asn1.ASN1Encodable) MessageDigest(java.security.MessageDigest) ASN1ObjectIdentifier(org.bouncycastle.asn1.ASN1ObjectIdentifier)

Example 2 with ValidationIssue

use of org.xipki.common.qa.ValidationIssue in project xipki by xipki.

the class ExtensionsChecker method createExtensionIssue.

// method getExensionTypes
private ValidationIssue createExtensionIssue(ASN1ObjectIdentifier extId) {
    ValidationIssue issue;
    String extName = ObjectIdentifiers.getName(extId);
    if (extName == null) {
        extName = extId.getId().replace('.', '_');
        issue = new ValidationIssue("X509.EXT." + extName, "extension " + extId.getId());
    } else {
        issue = new ValidationIssue("X509.EXT." + extName, "extension " + extName + " (" + extId.getId() + ")");
    }
    return issue;
}
Also used : ASN1OctetString(org.bouncycastle.asn1.ASN1OctetString) DERBMPString(org.bouncycastle.asn1.DERBMPString) DERPrintableString(org.bouncycastle.asn1.DERPrintableString) DERUTF8String(org.bouncycastle.asn1.DERUTF8String) ASN1String(org.bouncycastle.asn1.ASN1String) DirectoryString(org.bouncycastle.asn1.x500.DirectoryString) QaDirectoryString(org.xipki.ca.qa.internal.QaDirectoryString) DEROctetString(org.bouncycastle.asn1.DEROctetString) DERIA5String(org.bouncycastle.asn1.DERIA5String) DERT61String(org.bouncycastle.asn1.DERT61String) ValidationIssue(org.xipki.common.qa.ValidationIssue)

Example 3 with ValidationIssue

use of org.xipki.common.qa.ValidationIssue in project xipki by xipki.

the class SubjectChecker method checkSubjectAttributeMultiValued.

// method checkSubjectAttributeNotMultiValued
private ValidationIssue checkSubjectAttributeMultiValued(ASN1ObjectIdentifier type, X500Name subject, X500Name requestedSubject) throws BadCertTemplateException {
    ValidationIssue issue = createSubjectIssue(type);
    RDN[] rdns = subject.getRDNs(type);
    int rdnsSize = (rdns == null) ? 0 : rdns.length;
    RDN[] requestedRdns = requestedSubject.getRDNs(type);
    if (rdnsSize != 1) {
        if (rdnsSize == 0) {
            // check optional attribute but is present in requestedSubject
            if (requestedRdns != null && requestedRdns.length > 0) {
                issue.setFailureMessage("is absent but expected present");
            }
        } else {
            issue.setFailureMessage("number of RDNs '" + rdnsSize + "' is not 1");
        }
        return issue;
    }
    // control
    final RdnControl rdnControl = subjectControl.getControl(type);
    // check the encoding
    StringType stringType = null;
    if (rdnControl != null) {
        stringType = rdnControl.getStringType();
    }
    List<String> requestedCoreAtvTextValues = new LinkedList<>();
    if (requestedRdns != null) {
        for (RDN requestedRdn : requestedRdns) {
            String textValue = getRdnTextValueOfRequest(requestedRdn);
            requestedCoreAtvTextValues.add(textValue);
        }
        if (rdnControl != null && rdnControl.getPatterns() != null) {
            // sort the requestedRDNs
            requestedCoreAtvTextValues = sort(requestedCoreAtvTextValues, rdnControl.getPatterns());
        }
    }
    if (rdns == null) {
        // return always false, only to make the null checker happy
        return issue;
    }
    StringBuilder failureMsg = new StringBuilder();
    AttributeTypeAndValue[] li = rdns[0].getTypesAndValues();
    List<AttributeTypeAndValue> atvs = new LinkedList<>();
    for (AttributeTypeAndValue m : li) {
        if (type.equals(m.getType())) {
            atvs.add(m);
        }
    }
    final int atvsSize = atvs.size();
    int minOccurs = (rdnControl == null) ? 0 : rdnControl.getMinOccurs();
    int maxOccurs = (rdnControl == null) ? 0 : rdnControl.getMaxOccurs();
    if (atvsSize < minOccurs || atvsSize > maxOccurs) {
        issue.setFailureMessage("number of AttributeTypeAndValuess '" + atvsSize + "' is not within [" + minOccurs + ", " + maxOccurs + "]");
        return issue;
    }
    for (int i = 0; i < atvsSize; i++) {
        AttributeTypeAndValue atv = atvs.get(i);
        String atvTextValue = getAtvValueString("AttributeTypeAndValue[" + i + "]", atv, stringType, failureMsg);
        if (atvTextValue == null) {
            continue;
        }
        checkAttributeTypeAndValue("AttributeTypeAndValue[" + i + "]", type, atvTextValue, rdnControl, requestedCoreAtvTextValues, i, failureMsg);
    }
    int len = failureMsg.length();
    if (len > 2) {
        failureMsg.delete(len - 2, len);
        issue.setFailureMessage(failureMsg.toString());
    }
    return issue;
}
Also used : StringType(org.xipki.ca.api.profile.StringType) DERBMPString(org.bouncycastle.asn1.DERBMPString) DERIA5String(org.bouncycastle.asn1.DERIA5String) DERUTF8String(org.bouncycastle.asn1.DERUTF8String) DERT61String(org.bouncycastle.asn1.DERT61String) DERPrintableString(org.bouncycastle.asn1.DERPrintableString) ValidationIssue(org.xipki.common.qa.ValidationIssue) LinkedList(java.util.LinkedList) AttributeTypeAndValue(org.bouncycastle.asn1.x500.AttributeTypeAndValue) RdnControl(org.xipki.ca.api.profile.RdnControl) RDN(org.bouncycastle.asn1.x500.RDN)

Example 4 with ValidationIssue

use of org.xipki.common.qa.ValidationIssue in project xipki by xipki.

the class SubjectChecker method createSubjectIssue.

private static ValidationIssue createSubjectIssue(ASN1ObjectIdentifier subjectAttrType) {
    ValidationIssue issue;
    String attrName = ObjectIdentifiers.getName(subjectAttrType);
    if (attrName == null) {
        attrName = subjectAttrType.getId().replace('.', '_');
        issue = new ValidationIssue("X509.SUBJECT." + attrName, "attribute " + subjectAttrType.getId());
    } else {
        issue = new ValidationIssue("X509.SUBJECT." + attrName, "attribute " + attrName + " (" + subjectAttrType.getId() + ")");
    }
    return issue;
}
Also used : DERBMPString(org.bouncycastle.asn1.DERBMPString) DERIA5String(org.bouncycastle.asn1.DERIA5String) DERUTF8String(org.bouncycastle.asn1.DERUTF8String) DERT61String(org.bouncycastle.asn1.DERT61String) DERPrintableString(org.bouncycastle.asn1.DERPrintableString) ValidationIssue(org.xipki.common.qa.ValidationIssue)

Example 5 with ValidationIssue

use of org.xipki.common.qa.ValidationIssue in project xipki by xipki.

the class ExtensionsChecker method checkExtensions.

// constructor
public List<ValidationIssue> checkExtensions(Certificate cert, X509IssuerInfo issuerInfo, Extensions requestedExtensions, X500Name requestedSubject) {
    ParamUtil.requireNonNull("cert", cert);
    ParamUtil.requireNonNull("issuerInfo", issuerInfo);
    X509Certificate jceCert;
    try {
        jceCert = X509Util.toX509Cert(cert);
    } catch (CertificateException ex) {
        throw new IllegalArgumentException("invalid cert: " + ex.getMessage());
    }
    List<ValidationIssue> result = new LinkedList<>();
    // detect the list of extension types in certificate
    Set<ASN1ObjectIdentifier> presentExtenionTypes = getExensionTypes(cert, issuerInfo, requestedExtensions);
    Extensions extensions = cert.getTBSCertificate().getExtensions();
    ASN1ObjectIdentifier[] oids = extensions.getExtensionOIDs();
    if (oids == null) {
        ValidationIssue issue = new ValidationIssue("X509.EXT.GEN", "extension general");
        result.add(issue);
        issue.setFailureMessage("no extension is present");
        return result;
    }
    List<ASN1ObjectIdentifier> certExtTypes = Arrays.asList(oids);
    for (ASN1ObjectIdentifier extType : presentExtenionTypes) {
        if (!certExtTypes.contains(extType)) {
            ValidationIssue issue = createExtensionIssue(extType);
            result.add(issue);
            issue.setFailureMessage("extension is absent but is required");
        }
    }
    Map<ASN1ObjectIdentifier, ExtensionControl> extensionControls = certProfile.getExtensionControls();
    for (ASN1ObjectIdentifier oid : certExtTypes) {
        ValidationIssue issue = createExtensionIssue(oid);
        result.add(issue);
        if (!presentExtenionTypes.contains(oid)) {
            issue.setFailureMessage("extension is present but is not permitted");
            continue;
        }
        Extension ext = extensions.getExtension(oid);
        StringBuilder failureMsg = new StringBuilder();
        ExtensionControl extControl = extensionControls.get(oid);
        if (extControl.isCritical() != ext.isCritical()) {
            addViolation(failureMsg, "critical", ext.isCritical(), extControl.isCritical());
        }
        byte[] extensionValue = ext.getExtnValue().getOctets();
        try {
            if (Extension.authorityKeyIdentifier.equals(oid)) {
                // AuthorityKeyIdentifier
                checkExtensionIssuerKeyIdentifier(failureMsg, extensionValue, issuerInfo);
            } else if (Extension.subjectKeyIdentifier.equals(oid)) {
                // SubjectKeyIdentifier
                checkExtensionSubjectKeyIdentifier(failureMsg, extensionValue, cert.getSubjectPublicKeyInfo());
            } else if (Extension.keyUsage.equals(oid)) {
                // KeyUsage
                checkExtensionKeyUsage(failureMsg, extensionValue, jceCert.getKeyUsage(), requestedExtensions, extControl);
            } else if (Extension.certificatePolicies.equals(oid)) {
                // CertificatePolicies
                checkExtensionCertificatePolicies(failureMsg, extensionValue, requestedExtensions, extControl);
            } else if (Extension.policyMappings.equals(oid)) {
                // Policy Mappings
                checkExtensionPolicyMappings(failureMsg, extensionValue, requestedExtensions, extControl);
            } else if (Extension.subjectAlternativeName.equals(oid)) {
                // SubjectAltName
                checkExtensionSubjectAltName(failureMsg, extensionValue, requestedExtensions, extControl, requestedSubject);
            } else if (Extension.subjectDirectoryAttributes.equals(oid)) {
                // SubjectDirectoryAttributes
                checkExtensionSubjectDirAttrs(failureMsg, extensionValue, requestedExtensions, extControl);
            } else if (Extension.issuerAlternativeName.equals(oid)) {
                // IssuerAltName
                checkExtensionIssuerAltNames(failureMsg, extensionValue, issuerInfo);
            } else if (Extension.basicConstraints.equals(oid)) {
                // Basic Constraints
                checkExtensionBasicConstraints(failureMsg, extensionValue);
            } else if (Extension.nameConstraints.equals(oid)) {
                // Name Constraints
                checkExtensionNameConstraints(failureMsg, extensionValue, extensions, extControl);
            } else if (Extension.policyConstraints.equals(oid)) {
                // PolicyConstrains
                checkExtensionPolicyConstraints(failureMsg, extensionValue, requestedExtensions, extControl);
            } else if (Extension.extendedKeyUsage.equals(oid)) {
                // ExtendedKeyUsage
                checkExtensionExtendedKeyUsage(failureMsg, extensionValue, requestedExtensions, extControl);
            } else if (Extension.cRLDistributionPoints.equals(oid)) {
                // CRL Distribution Points
                checkExtensionCrlDistributionPoints(failureMsg, extensionValue, issuerInfo);
            } else if (Extension.inhibitAnyPolicy.equals(oid)) {
                // Inhibit anyPolicy
                checkExtensionInhibitAnyPolicy(failureMsg, extensionValue, extensions, extControl);
            } else if (Extension.freshestCRL.equals(oid)) {
                // Freshest CRL
                checkExtensionDeltaCrlDistributionPoints(failureMsg, extensionValue, issuerInfo);
            } else if (Extension.authorityInfoAccess.equals(oid)) {
                // Authority Information Access
                checkExtensionAuthorityInfoAccess(failureMsg, extensionValue, issuerInfo);
            } else if (Extension.subjectInfoAccess.equals(oid)) {
                // SubjectInfoAccess
                checkExtensionSubjectInfoAccess(failureMsg, extensionValue, requestedExtensions, extControl);
            } else if (ObjectIdentifiers.id_extension_admission.equals(oid)) {
                // Admission
                checkExtensionAdmission(failureMsg, extensionValue, requestedExtensions, extControl);
            } else if (ObjectIdentifiers.id_extension_pkix_ocsp_nocheck.equals(oid)) {
                // ocsp-nocheck
                checkExtensionOcspNocheck(failureMsg, extensionValue);
            } else if (ObjectIdentifiers.id_extension_restriction.equals(oid)) {
                // restriction
                checkExtensionRestriction(failureMsg, extensionValue, requestedExtensions, extControl);
            } else if (ObjectIdentifiers.id_extension_additionalInformation.equals(oid)) {
                // additionalInformation
                checkExtensionAdditionalInformation(failureMsg, extensionValue, requestedExtensions, extControl);
            } else if (ObjectIdentifiers.id_extension_validityModel.equals(oid)) {
                // validityModel
                checkExtensionValidityModel(failureMsg, extensionValue, requestedExtensions, extControl);
            } else if (Extension.privateKeyUsagePeriod.equals(oid)) {
                // privateKeyUsagePeriod
                checkExtensionPrivateKeyUsagePeriod(failureMsg, extensionValue, jceCert.getNotBefore(), jceCert.getNotAfter());
            } else if (Extension.qCStatements.equals(oid)) {
                // qCStatements
                checkExtensionQcStatements(failureMsg, extensionValue, requestedExtensions, extControl);
            } else if (Extension.biometricInfo.equals(oid)) {
                // biometricInfo
                checkExtensionBiometricInfo(failureMsg, extensionValue, requestedExtensions, extControl);
            } else if (ObjectIdentifiers.id_pe_tlsfeature.equals(oid)) {
                // tlsFeature
                checkExtensionTlsFeature(failureMsg, extensionValue, requestedExtensions, extControl);
            } else if (ObjectIdentifiers.id_xipki_ext_authorizationTemplate.equals(oid)) {
                // authorizationTemplate
                checkExtensionAuthorizationTemplate(failureMsg, extensionValue, requestedExtensions, extControl);
            } else {
                byte[] expected;
                if (ObjectIdentifiers.id_smimeCapabilities.equals(oid)) {
                    // SMIMECapabilities
                    expected = smimeCapabilities.getValue();
                } else {
                    expected = getExpectedExtValue(oid, requestedExtensions, extControl);
                }
                if (!Arrays.equals(expected, extensionValue)) {
                    addViolation(failureMsg, "extension valus", hex(extensionValue), (expected == null) ? "not present" : hex(expected));
                }
            }
            if (failureMsg.length() > 0) {
                issue.setFailureMessage(failureMsg.toString());
            }
        } catch (IllegalArgumentException | ClassCastException | ArrayIndexOutOfBoundsException ex) {
            LOG.debug("extension value does not have correct syntax", ex);
            issue.setFailureMessage("extension value does not have correct syntax");
        }
    }
    return result;
}
Also used : CertificateException(java.security.cert.CertificateException) Extensions(org.bouncycastle.asn1.x509.Extensions) ValidationIssue(org.xipki.common.qa.ValidationIssue) X509Certificate(java.security.cert.X509Certificate) LinkedList(java.util.LinkedList) Extension(org.bouncycastle.asn1.x509.Extension) ExtensionControl(org.xipki.ca.api.profile.ExtensionControl) ASN1ObjectIdentifier(org.bouncycastle.asn1.ASN1ObjectIdentifier)

Aggregations

ValidationIssue (org.xipki.common.qa.ValidationIssue)13 LinkedList (java.util.LinkedList)8 DERBMPString (org.bouncycastle.asn1.DERBMPString)5 DERIA5String (org.bouncycastle.asn1.DERIA5String)5 DERPrintableString (org.bouncycastle.asn1.DERPrintableString)5 DERT61String (org.bouncycastle.asn1.DERT61String)5 DERUTF8String (org.bouncycastle.asn1.DERUTF8String)5 ValidationResult (org.xipki.common.qa.ValidationResult)5 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)3 X509Certificate (java.security.cert.X509Certificate)3 Date (java.util.Date)3 ASN1ObjectIdentifier (org.bouncycastle.asn1.ASN1ObjectIdentifier)3 RDN (org.bouncycastle.asn1.x500.RDN)3 Extension (org.bouncycastle.asn1.x509.Extension)3 BigInteger (java.math.BigInteger)2 CertificateException (java.security.cert.CertificateException)2 AttributeTypeAndValue (org.bouncycastle.asn1.x500.AttributeTypeAndValue)2 AlgorithmIdentifier (org.bouncycastle.asn1.x509.AlgorithmIdentifier)2 Extensions (org.bouncycastle.asn1.x509.Extensions)2 BadCertTemplateException (org.xipki.ca.api.BadCertTemplateException)2