use of org.xipki.common.qa.ValidationIssue in project xipki by xipki.
the class BatchOcspQaStatusCmd method processOcspQuery.
private ValidationResult processOcspQuery(OcspQa ocspQa, BigInteger serialNumber, OcspCertStatus status, Date revTime, File messageDir, File detailsDir, URL serverUrl, X509Certificate respIssuer, X509Certificate issuerCert, IssuerHash issuerHash, RequestOptions requestOptions) throws Exception {
if (unknownAsGood && status == OcspCertStatus.unknown) {
status = OcspCertStatus.good;
}
RequestResponseDebug debug = null;
if (saveReq || saveResp) {
debug = new RequestResponseDebug(saveReq, saveResp);
}
OCSPResp response;
try {
response = requestor.ask(issuerCert, serialNumber, serverUrl, requestOptions, debug);
} finally {
if (debug != null && debug.size() > 0) {
RequestResponsePair reqResp = debug.get(0);
String filename = serialNumber.toString(16);
if (saveReq) {
byte[] bytes = reqResp.getRequest();
if (bytes != null) {
IoUtil.save(new File(messageDir, filename + FILE_SEP + "request.der"), bytes);
}
}
if (saveResp) {
byte[] bytes = reqResp.getResponse();
if (bytes != null) {
IoUtil.save(new File(messageDir, filename + FILE_SEP + "response.der"), bytes);
}
}
}
// end if
}
// end finally
// analyze the result
OcspResponseOption responseOption = new OcspResponseOption();
responseOption.setNextUpdateOccurrence(expectedNextUpdateOccurrence);
responseOption.setCerthashOccurrence(expectedCerthashOccurrence);
responseOption.setNonceOccurrence(expectedNonceOccurrence);
responseOption.setRespIssuer(respIssuer);
responseOption.setSignatureAlgName(sigAlg);
if (isNotBlank(certhashAlg)) {
responseOption.setCerthashAlgId(AlgorithmUtil.getHashAlg(certhashAlg));
}
ValidationResult ret = ocspQa.checkOcsp(response, issuerHash, serialNumber, null, null, status, responseOption, revTime, noSigVerify.booleanValue());
String validity = ret.isAllSuccessful() ? "valid" : "invalid";
String hexSerial = serialNumber.toString(16);
StringBuilder sb = new StringBuilder(50);
sb.append("OCSP response for ").append(serialNumber).append(" (0x").append(hexSerial).append(") is ").append(validity);
for (ValidationIssue issue : ret.getValidationIssues()) {
sb.append("\n");
OcspQaStatusCmd.format(issue, " ", sb);
}
IoUtil.save(new File(detailsDir, hexSerial + "." + validity), sb.toString().getBytes());
return ret;
}
use of org.xipki.common.qa.ValidationIssue in project xipki by xipki.
the class OcspQaStatusCmd method processResponse.
// method checkParameters
@Override
protected Object processResponse(OCSPResp response, X509Certificate respIssuer, IssuerHash issuerHash, List<BigInteger> serialNumbers, Map<BigInteger, byte[]> encodedCerts) throws Exception {
OcspResponseOption responseOption = new OcspResponseOption();
responseOption.setNextUpdateOccurrence(expectedNextUpdateOccurrence);
responseOption.setCerthashOccurrence(expectedCerthashOccurrence);
responseOption.setNonceOccurrence(expectedNonceOccurrence);
responseOption.setRespIssuer(respIssuer);
responseOption.setSignatureAlgName(sigAlg);
if (isNotBlank(certhashAlg)) {
responseOption.setCerthashAlgId(AlgorithmUtil.getHashAlg(certhashAlg));
}
if (ocspQa == null) {
ocspQa = new OcspQa(securityFactory);
}
ValidationResult result = ocspQa.checkOcsp(response, issuerHash, serialNumbers, encodedCerts, expectedOcspError, expectedStatuses, expecteRevTimes, responseOption, noSigVerify);
StringBuilder sb = new StringBuilder(50);
sb.append("OCSP response is ");
String txt = result.isAllSuccessful() ? "valid" : "invalid";
sb.append(txt);
if (verbose.booleanValue()) {
for (ValidationIssue issue : result.getValidationIssues()) {
sb.append("\n");
format(issue, " ", sb);
}
}
println(sb.toString());
if (!result.isAllSuccessful()) {
throw new CmdFailure("OCSP response is invalid");
}
return null;
}
use of org.xipki.common.qa.ValidationIssue in project xipki by xipki.
the class CheckCertCmd method execute0.
@Override
protected Object execute0() throws Exception {
Set<String> issuerNames = qaSystemManager.getIssuerNames();
if (isEmpty(issuerNames)) {
throw new IllegalCmdParamException("no issuer is configured");
}
if (issuerName == null) {
if (issuerNames.size() != 1) {
throw new IllegalCmdParamException("no issuer is specified");
}
issuerName = issuerNames.iterator().next();
}
if (!issuerNames.contains(issuerName)) {
throw new IllegalCmdParamException("issuer " + issuerName + " is not within the configured issuers " + issuerNames);
}
X509IssuerInfo issuerInfo = qaSystemManager.getIssuer(issuerName);
X509CertprofileQa qa = qaSystemManager.getCertprofile(profileName);
if (qa == null) {
throw new IllegalCmdParamException("found no certificate profile named '" + profileName + "'");
}
CertificationRequest csr = CertificationRequest.getInstance(IoUtil.read(csrFile));
Extensions extensions = null;
CertificationRequestInfo reqInfo = csr.getCertificationRequestInfo();
ASN1Set attrs = reqInfo.getAttributes();
for (int i = 0; i < attrs.size(); i++) {
Attribute attr = Attribute.getInstance(attrs.getObjectAt(i));
if (PKCSObjectIdentifiers.pkcs_9_at_extensionRequest.equals(attr.getAttrType())) {
extensions = Extensions.getInstance(attr.getAttributeValues()[0]);
}
}
byte[] certBytes = IoUtil.read(certFile);
ValidationResult result = qa.checkCert(certBytes, issuerInfo, reqInfo.getSubject(), reqInfo.getSubjectPublicKeyInfo(), extensions);
StringBuilder sb = new StringBuilder();
sb.append(certFile).append(" (certprofile ").append(profileName).append(")\n");
sb.append("\tcertificate is ");
sb.append(result.isAllSuccessful() ? "valid" : "invalid");
if (verbose.booleanValue()) {
for (ValidationIssue issue : result.getValidationIssues()) {
sb.append("\n");
format(issue, " ", sb);
}
}
println(sb.toString());
if (!result.isAllSuccessful()) {
throw new CmdFailure("certificate is invalid");
}
return null;
}
use of org.xipki.common.qa.ValidationIssue in project xipki by xipki.
the class OcspQa method checkOcsp.
public ValidationResult checkOcsp(OCSPResp response, IssuerHash issuerHash, List<BigInteger> serialNumbers, Map<BigInteger, byte[]> encodedCerts, OcspError expectedOcspError, Map<BigInteger, OcspCertStatus> expectedOcspStatuses, Map<BigInteger, Date> expectedRevTimes, OcspResponseOption responseOption, boolean noSigVerify) {
ParamUtil.requireNonNull("response", response);
ParamUtil.requireNonEmpty("serialNumbers", serialNumbers);
ParamUtil.requireNonEmpty("expectedOcspStatuses", expectedOcspStatuses);
ParamUtil.requireNonNull("responseOption", responseOption);
List<ValidationIssue> resultIssues = new LinkedList<ValidationIssue>();
int status = response.getStatus();
// Response status
ValidationIssue issue = new ValidationIssue("OCSP.STATUS", "response.status");
resultIssues.add(issue);
if (expectedOcspError != null) {
if (status != expectedOcspError.getStatus()) {
issue.setFailureMessage("is '" + status + "', but expected '" + expectedOcspError.getStatus() + "'");
}
} else {
if (status != 0) {
issue.setFailureMessage("is '" + status + "', but expected '0'");
}
}
if (status != 0) {
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);
String expectedSigalgo = responseOption.getSignatureAlgName();
if (expectedSigalgo != null) {
AlgorithmIdentifier sigAlg = basicResp.getSignatureAlgorithmID();
try {
String sigAlgName = AlgorithmUtil.getSignatureAlgoName(sigAlg);
if (!AlgorithmUtil.equalsAlgoName(sigAlgName, expectedSigalgo)) {
issue.setFailureMessage("is '" + sigAlgName + "', but expected '" + expectedSigalgo + "'");
}
} 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
X509Certificate respIssuer = responseOption.getRespIssuer();
if (!issue.isFailed() && respIssuer != null) {
X509Certificate jceRespSigner;
try {
jceRespSigner = X509Util.toX509Cert(respSigner.toASN1Structure());
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.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.getCerthashAlgId());
resultIssues.addAll(issues);
}
return new ValidationResult(resultIssues);
}
use of org.xipki.common.qa.ValidationIssue in project xipki by xipki.
the class PublicKeyChecker method checkPublicKey.
public List<ValidationIssue> checkPublicKey(SubjectPublicKeyInfo publicKey, SubjectPublicKeyInfo requestedPublicKey) {
ParamUtil.requireNonNull("publicKey", publicKey);
ParamUtil.requireNonNull("requestedPublicKey", requestedPublicKey);
List<ValidationIssue> resultIssues = new LinkedList<>();
if (keyAlgorithms != null) {
ValidationIssue issue = new ValidationIssue("X509.PUBKEY.SYN", "whether the public key in certificate is permitted");
resultIssues.add(issue);
try {
checkPublicKey(publicKey);
} catch (BadCertTemplateException ex) {
issue.setFailureMessage(ex.getMessage());
}
}
ValidationIssue issue = new ValidationIssue("X509.PUBKEY.REQ", "whether public key matches the request one");
resultIssues.add(issue);
SubjectPublicKeyInfo c14nRequestedPublicKey;
try {
c14nRequestedPublicKey = X509Util.toRfc3279Style(requestedPublicKey);
if (!c14nRequestedPublicKey.equals(publicKey)) {
issue.setFailureMessage("public key in the certificate does not equal the requested one");
}
} catch (InvalidKeySpecException ex) {
issue.setFailureMessage("public key in request is invalid");
}
return resultIssues;
}
Aggregations