use of org.xipki.qa.ValidationResult in project xipki by xipki.
the class OcspQa method checkOcsp.
// method checkOcsp
public ValidationResult checkOcsp(OCSPResp response, IssuerHash issuerHash, List<BigInteger> serialNumbers, Map<BigInteger, byte[]> encodedCerts, Map<BigInteger, OcspCertStatus> expectedOcspStatuses, Map<BigInteger, Date> expectedRevTimes, OcspResponseOption responseOption, boolean noSigVerify) {
notNull(response, "response");
notEmpty(serialNumbers, "serialNumbers");
notEmpty(expectedOcspStatuses, "expectedOcspStatuses");
notNull(responseOption, "responseOption");
List<ValidationIssue> resultIssues = new LinkedList<>();
int status = response.getStatus();
// Response status
ValidationIssue issue = new ValidationIssue("OCSP.STATUS", "response.status");
resultIssues.add(issue);
if (status != 0) {
issue.setFailureMessage("is '" + Unsuccessful.getStatusText(status) + "', but expected 'successful'");
return new ValidationResult(resultIssues);
}
ValidationIssue encodingIssue = new ValidationIssue("OCSP.ENCODING", "response encoding");
resultIssues.add(encodingIssue);
BasicOCSPResp basicResp;
try {
basicResp = (BasicOCSPResp) response.getResponseObject();
} catch (OCSPException ex) {
encodingIssue.setFailureMessage(ex.getMessage());
return new ValidationResult(resultIssues);
}
SingleResp[] singleResponses = basicResp.getResponses();
issue = new ValidationIssue("OCSP.RESPONSES.NUM", "number of single responses");
resultIssues.add(issue);
if (singleResponses == null || singleResponses.length == 0) {
issue.setFailureMessage("received no status from server");
return new ValidationResult(resultIssues);
}
final int n = singleResponses.length;
if (n != serialNumbers.size()) {
issue.setFailureMessage("is '" + n + "', but expected '" + serialNumbers.size() + "'");
return new ValidationResult(resultIssues);
}
boolean hasSignature = basicResp.getSignature() != null;
// check the signature if available
if (noSigVerify) {
issue = new ValidationIssue("OCSP.SIG", (hasSignature ? "signature presence (Ignore)" : "signature presence"));
} else {
issue = new ValidationIssue("OCSP.SIG", "signature presence");
}
resultIssues.add(issue);
if (!hasSignature) {
issue.setFailureMessage("response is not signed");
}
if (hasSignature && !noSigVerify) {
// signature algorithm
issue = new ValidationIssue("OCSP.SIG.ALG", "signature algorithm");
resultIssues.add(issue);
SignAlgo expectedSigalgo = responseOption.getSignatureAlg();
if (expectedSigalgo != null) {
try {
SignAlgo signAlgo = SignAlgo.getInstance(basicResp.getSignatureAlgorithmID());
if (signAlgo != expectedSigalgo) {
issue.setFailureMessage("is '" + signAlgo.getJceName() + "', but expected '" + expectedSigalgo.getJceName() + "'");
}
} catch (NoSuchAlgorithmException ex) {
issue.setFailureMessage("could not extract the signature algorithm");
}
}
// end if (expectedSigalgo != null)
// signer certificate
ValidationIssue sigSignerCertIssue = new ValidationIssue("OCSP.SIGNERCERT", "signer certificate");
resultIssues.add(sigSignerCertIssue);
// signature validation
ValidationIssue sigValIssue = new ValidationIssue("OCSP.SIG.VALIDATION", "signature validation");
resultIssues.add(sigValIssue);
X509CertificateHolder respSigner = null;
X509CertificateHolder[] responderCerts = basicResp.getCerts();
if (responderCerts == null || responderCerts.length < 1) {
sigSignerCertIssue.setFailureMessage("no responder certificate is contained in the response");
sigValIssue.setFailureMessage("could not find certificate to validate signature");
} else {
ResponderID respId = basicResp.getResponderId().toASN1Primitive();
X500Name respIdByName = respId.getName();
byte[] respIdByKey = respId.getKeyHash();
for (X509CertificateHolder cert : responderCerts) {
if (respIdByName != null) {
if (cert.getSubject().equals(respIdByName)) {
respSigner = cert;
}
} else {
byte[] spkiSha1 = HashAlgo.SHA1.hash(cert.getSubjectPublicKeyInfo().getPublicKeyData().getBytes());
if (Arrays.equals(respIdByKey, spkiSha1)) {
respSigner = cert;
}
}
if (respSigner != null) {
break;
}
}
if (respSigner == null) {
sigSignerCertIssue.setFailureMessage("no responder certificate match the ResponderId");
sigValIssue.setFailureMessage("could not find certificate matching the" + " ResponderId to validate signature");
}
}
if (respSigner != null) {
issue = new ValidationIssue("OCSP.SIGNERCERT.TRUST", "signer certificate validation");
resultIssues.add(issue);
for (int i = 0; i < singleResponses.length; i++) {
SingleResp singleResp = singleResponses[i];
if (!respSigner.isValidOn(singleResp.getThisUpdate())) {
issue.setFailureMessage(String.format("responder certificate is not valid on the thisUpdate[%d]: %s", i, singleResp.getThisUpdate()));
}
}
// end for
X509Cert respIssuer = responseOption.getRespIssuer();
if (!issue.isFailed() && respIssuer != null) {
X509Cert jceRespSigner;
try {
jceRespSigner = new X509Cert(respSigner);
if (X509Util.issues(respIssuer, jceRespSigner)) {
jceRespSigner.verify(respIssuer.getPublicKey());
} else {
issue.setFailureMessage("responder signer is not trusted");
}
} catch (Exception ex) {
issue.setFailureMessage("responder signer is not trusted");
}
}
try {
PublicKey responderPubKey = KeyUtil.generatePublicKey(respSigner.getSubjectPublicKeyInfo());
ContentVerifierProvider cvp = securityFactory.getContentVerifierProvider(responderPubKey);
boolean sigValid = basicResp.isSignatureValid(cvp);
if (!sigValid) {
sigValIssue.setFailureMessage("signature is invalid");
}
} catch (Exception ex) {
sigValIssue.setFailureMessage("could not validate signature");
}
}
// end if
}
// end if (hasSignature)
// nonce
Extension nonceExtn = basicResp.getExtension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce);
resultIssues.add(checkOccurrence("OCSP.NONCE", nonceExtn, responseOption.getNonceOccurrence()));
boolean extendedRevoke = basicResp.getExtension(ObjectIdentifiers.Extn.id_pkix_ocsp_extendedRevoke) != null;
for (int i = 0; i < singleResponses.length; i++) {
SingleResp singleResp = singleResponses[i];
BigInteger serialNumber = singleResp.getCertID().getSerialNumber();
OcspCertStatus expectedStatus = expectedOcspStatuses.get(serialNumber);
Date expectedRevTime = null;
if (expectedRevTimes != null) {
expectedRevTime = expectedRevTimes.get(serialNumber);
}
byte[] encodedCert = null;
if (encodedCerts != null) {
encodedCert = encodedCerts.get(serialNumber);
}
List<ValidationIssue> issues = checkSingleCert(i, singleResp, issuerHash, expectedStatus, encodedCert, expectedRevTime, extendedRevoke, responseOption.getNextUpdateOccurrence(), responseOption.getCerthashOccurrence(), responseOption.getCerthashAlg());
resultIssues.addAll(issues);
}
return new ValidationResult(resultIssues);
}
use of org.xipki.qa.ValidationResult in project xipki by xipki.
the class CertprofileQa method checkCert.
// constructor
public ValidationResult checkCert(byte[] certBytes, IssuerInfo issuerInfo, X500Name requestedSubject, SubjectPublicKeyInfo requestedPublicKey, Extensions requestedExtensions) {
notNull(certBytes, "certBytes");
notNull(issuerInfo, "issuerInfo");
notNull(requestedSubject, "requestedSubject");
notNull(requestedPublicKey, "requestedPublicKey");
List<ValidationIssue> resultIssues = new LinkedList<>();
// certificate size
ValidationIssue issue = new ValidationIssue("X509.SIZE", "certificate size");
resultIssues.add(issue);
certBytes = X509Util.toDerEncoded(certBytes);
Integer maxSize = certprofile.getMaxSize();
if (maxSize != 0) {
int size = certBytes.length;
if (size > maxSize) {
issue.setFailureMessage(String.format("certificate exceeds the maximal allowed size: %d > %d", size, maxSize));
}
}
// certificate encoding
issue = new ValidationIssue("X509.ENCODING", "certificate encoding");
resultIssues.add(issue);
Certificate bcCert = Certificate.getInstance(certBytes);
TBSCertificate tbsCert = bcCert.getTBSCertificate();
X509Cert cert = new X509Cert(bcCert, certBytes);
// syntax version
issue = new ValidationIssue("X509.VERSION", "certificate version");
resultIssues.add(issue);
int versionNumber = tbsCert.getVersion().intPositiveValueExact();
X509CertVersion expVersion = certprofile.getVersion();
if (versionNumber != expVersion.getVersionNumber()) {
issue.setFailureMessage("is '" + versionNumber + "' but expected '" + expVersion.getVersionNumber() + "'");
}
// serialNumber
issue = new ValidationIssue("X509.serialNumber", "certificate serial number");
resultIssues.add(issue);
BigInteger serialNumber = tbsCert.getSerialNumber().getValue();
if (serialNumber.signum() != 1) {
issue.setFailureMessage("not positive");
} else {
if (serialNumber.bitLength() >= 160) {
issue.setFailureMessage("serial number has more than 20 octets");
}
}
// signatureAlgorithm
List<SignAlgo> signatureAlgorithms = certprofile.getSignatureAlgorithms();
if (CollectionUtil.isNotEmpty(signatureAlgorithms)) {
issue = new ValidationIssue("X509.SIGALG", "signature algorithm");
resultIssues.add(issue);
AlgorithmIdentifier sigAlgId = bcCert.getSignatureAlgorithm();
AlgorithmIdentifier tbsSigAlgId = tbsCert.getSignature();
if (!tbsSigAlgId.equals(sigAlgId)) {
issue.setFailureMessage("Certificate.tbsCertificate.signature != Certificate.signatureAlgorithm");
}
try {
if (!issue.isFailed()) {
SignAlgo signAlgo = SignAlgo.getInstance(sigAlgId);
if (!signatureAlgorithms.contains(signAlgo)) {
issue.setFailureMessage("signatureAlgorithm '" + signAlgo + "' is not allowed");
}
if (!issue.isFailed()) {
if (!sigAlgId.equals(signAlgo.getAlgorithmIdentifier())) {
issue.setFailureMessage("signatureAlgorithm has invalid content");
}
}
}
} catch (NoSuchAlgorithmException ex) {
issue.setFailureMessage("unsupported signature algorithm " + sigAlgId.getAlgorithm().getId());
}
}
// notBefore encoding
issue = new ValidationIssue("X509.NOTBEFORE.ENCODING", "notBefore encoding");
checkTime(tbsCert.getStartDate(), issue);
// notAfter encoding
issue = new ValidationIssue("X509.NOTAFTER.ENCODING", "notAfter encoding");
checkTime(tbsCert.getStartDate(), issue);
if (certprofile.getNotBeforeOption().getMidNightTimeZone() != null) {
issue = new ValidationIssue("X509.NOTBEFORE", "notBefore midnight");
resultIssues.add(issue);
Calendar cal = Calendar.getInstance(UTC);
cal.setTime(cert.getNotBefore());
int minute = cal.get(Calendar.MINUTE);
int second = cal.get(Calendar.SECOND);
if (minute != 0 || second != 0) {
issue.setFailureMessage(" '" + cert.getNotBefore() + "' is not midnight time");
}
}
// validity
issue = new ValidationIssue("X509.VALIDITY", "cert validity");
resultIssues.add(issue);
if (cert.getNotAfter().before(cert.getNotBefore())) {
issue.setFailureMessage("notAfter may not be before notBefore");
} else if (cert.getNotBefore().before(issuerInfo.getCaNotBefore())) {
issue.setFailureMessage("notBefore may not be before CA's notBefore");
} else {
Validity validity = certprofile.getValidity();
Date expectedNotAfter = validity.add(cert.getNotBefore());
if (expectedNotAfter.getTime() > MAX_CERT_TIME_MS) {
expectedNotAfter = new Date(MAX_CERT_TIME_MS);
}
if (issuerInfo.isCutoffNotAfter() && expectedNotAfter.after(issuerInfo.getCaNotAfter())) {
expectedNotAfter = issuerInfo.getCaNotAfter();
}
if (Math.abs(expectedNotAfter.getTime() - cert.getNotAfter().getTime()) > 60 * SECOND) {
issue.setFailureMessage("cert validity is not within " + validity.toString());
}
}
// subjectPublicKeyInfo
resultIssues.addAll(publicKeyChecker.checkPublicKey(bcCert.getSubjectPublicKeyInfo(), requestedPublicKey));
// Signature
issue = new ValidationIssue("X509.SIG", "whether certificate is signed by CA");
resultIssues.add(issue);
try {
cert.verify(issuerInfo.getCert().getPublicKey(), "BC");
} catch (NoSuchAlgorithmException ex) {
try {
cert.verify(issuerInfo.getCert().getPublicKey());
} catch (Exception ex1) {
issue.setFailureMessage("invalid signature");
}
} catch (Exception ex) {
issue.setFailureMessage("invalid signature");
}
// issuer
issue = new ValidationIssue("X509.ISSUER", "certificate issuer");
resultIssues.add(issue);
if (!cert.getIssuer().equals(issuerInfo.getCert().getSubject())) {
issue.setFailureMessage("issue in certificate does not equal the subject of CA certificate");
}
// subject
resultIssues.addAll(subjectChecker.checkSubject(bcCert.getSubject(), requestedSubject));
// issuerUniqueID
issue = new ValidationIssue("X509.IssuerUniqueID", "issuerUniqueID");
resultIssues.add(issue);
if (tbsCert.getIssuerUniqueId() != null) {
issue.setFailureMessage("is present but not permitted");
}
// subjectUniqueID
issue = new ValidationIssue("X509.SubjectUniqueID", "subjectUniqueID");
resultIssues.add(issue);
if (tbsCert.getSubjectUniqueId() != null) {
issue.setFailureMessage("is present but not permitted");
}
// extensions
issue = new ValidationIssue("X509.GrantedSubject", "grantedSubject");
resultIssues.add(issue);
resultIssues.addAll(extensionsChecker.checkExtensions(bcCert, issuerInfo, requestedExtensions, requestedSubject));
return new ValidationResult(resultIssues);
}
use of org.xipki.qa.ValidationResult in project xipki by xipki.
the class OcspQa method checkOcsp.
// method checkOcsp
public ValidationResult checkOcsp(OCSPResp response, OcspError expectedOcspError) {
notNull(response, "response");
notNull(expectedOcspError, "expectedOcspError");
List<ValidationIssue> resultIssues = new LinkedList<>();
int status = response.getStatus();
// Response status
ValidationIssue issue = new ValidationIssue("OCSP.STATUS", "response.status");
resultIssues.add(issue);
if (status != expectedOcspError.getStatus()) {
issue.setFailureMessage("is '" + Unsuccessful.getStatusText(status) + "', but expected '" + Unsuccessful.getStatusText(expectedOcspError.getStatus()) + "'");
}
return new ValidationResult(resultIssues);
}
Aggregations