List of usage examples for org.bouncycastle.asn1.isismtt ISISMTTObjectIdentifiers id_isismtt_at_certHash
ASN1ObjectIdentifier id_isismtt_at_certHash
To view the source code for org.bouncycastle.asn1.isismtt ISISMTTObjectIdentifiers id_isismtt_at_certHash.
Click Source Link
From source file:org.xipki.ocsp.client.shell.OCSPStatusCommand.java
License:Open Source License
@Override protected Object processResponse(final OCSPResp response, final X509Certificate respIssuer, final X509Certificate issuer, final List<BigInteger> serialNumbers, final Map<BigInteger, byte[]> encodedCerts) throws Exception { BasicOCSPResp basicResp = OCSPUtils.extractBasicOCSPResp(response); boolean extendedRevoke = basicResp.getExtension(OCSPRequestor.id_pkix_ocsp_extendedRevoke) != null; SingleResp[] singleResponses = basicResp.getResponses(); int n = singleResponses == null ? 0 : singleResponses.length; if (n == 0) { throw new CmdFailure("received no status from server"); }//from w ww. java2s . com if (n != serialNumbers.size()) { throw new CmdFailure("received status with " + n + " single responses from server, but " + serialNumbers.size() + " were requested"); } Date[] thisUpdates = new Date[n]; for (int i = 0; i < n; i++) { thisUpdates[i] = singleResponses[i].getThisUpdate(); } // check the signature if available if (null == basicResp.getSignature()) { out("response is not signed"); } else { X509CertificateHolder[] responderCerts = basicResp.getCerts(); if (responderCerts == null || responderCerts.length < 1) { throw new CmdFailure("no responder certificate is contained in the response"); } X509CertificateHolder respSigner = responderCerts[0]; boolean validOn = true; for (Date thisUpdate : thisUpdates) { validOn = respSigner.isValidOn(thisUpdate); if (validOn == false) { throw new CmdFailure("responder certificate is not valid on " + thisUpdate); } } if (validOn) { PublicKey responderPubKey = KeyUtil.generatePublicKey(respSigner.getSubjectPublicKeyInfo()); ContentVerifierProvider cvp = KeyUtil.getContentVerifierProvider(responderPubKey); boolean sigValid = basicResp.isSignatureValid(cvp); if (sigValid == false) { throw new CmdFailure("response is equipped with invalid signature"); } // verify the OCSPResponse signer if (respIssuer != null) { boolean certValid = true; X509Certificate jceRespSigner = new X509CertificateObject(respSigner.toASN1Structure()); if (X509Util.issues(respIssuer, jceRespSigner)) { try { jceRespSigner.verify(respIssuer.getPublicKey()); } catch (SignatureException e) { certValid = false; } } if (certValid == false) { throw new CmdFailure( "response is equipped with valid signature but the OCSP signer is not trusted"); } } else { out("response is equipped with valid signature"); } } if (verbose.booleanValue()) { out("responder is " + X509Util.getRFC4519Name(responderCerts[0].getSubject())); } } for (int i = 0; i < n; i++) { if (n > 1) { out("---------------------------- " + i + " ----------------------------"); } SingleResp singleResp = singleResponses[i]; BigInteger serialNumber = singleResp.getCertID().getSerialNumber(); CertificateStatus singleCertStatus = singleResp.getCertStatus(); String status; if (singleCertStatus == null) { status = "good"; } else if (singleCertStatus instanceof RevokedStatus) { RevokedStatus revStatus = (RevokedStatus) singleCertStatus; Date revTime = revStatus.getRevocationTime(); Date invTime = null; Extension ext = singleResp.getExtension(Extension.invalidityDate); if (ext != null) { invTime = ASN1GeneralizedTime.getInstance(ext.getParsedValue()).getDate(); } if (revStatus.hasRevocationReason()) { int reason = revStatus.getRevocationReason(); if (extendedRevoke && reason == CRLReason.CERTIFICATE_HOLD.getCode() && revTime.getTime() == 0) { status = "unknown (RFC6960)"; } else { StringBuilder sb = new StringBuilder("revoked, reason = "); sb.append(CRLReason.forReasonCode(reason).getDescription()); sb.append(", revocationTime = "); sb.append(revTime); if (invTime != null) { sb.append(", invalidityTime = "); sb.append(invTime); } status = sb.toString(); } } else { status = "revoked, no reason, revocationTime = " + revTime; } } else if (singleCertStatus instanceof UnknownStatus) { status = "unknown (RFC2560)"; } else { status = "ERROR"; } StringBuilder msg = new StringBuilder(); msg.append("serialNumber: ").append(serialNumber); msg.append("\nCertificate status: ").append(status); if (verbose.booleanValue()) { msg.append("\nthisUpdate: " + singleResp.getThisUpdate()); msg.append("\nnextUpdate: " + singleResp.getNextUpdate()); Extension extension = singleResp.getExtension(ISISMTTObjectIdentifiers.id_isismtt_at_certHash); if (extension != null) { msg.append("\nCertHash is provided:\n"); ASN1Encodable extensionValue = extension.getParsedValue(); CertHash certHash = CertHash.getInstance(extensionValue); ASN1ObjectIdentifier hashAlgOid = certHash.getHashAlgorithm().getAlgorithm(); byte[] hashValue = certHash.getCertificateHash(); msg.append("\tHash algo : ").append(hashAlgOid.getId()).append("\n"); msg.append("\tHash value: ").append(Hex.toHexString(hashValue)).append("\n"); if (encodedCerts != null) { byte[] encodedCert = encodedCerts.get(serialNumber); MessageDigest md = MessageDigest.getInstance(hashAlgOid.getId()); byte[] expectedHashValue = md.digest(encodedCert); if (Arrays.equals(expectedHashValue, hashValue)) { msg.append("\tThis matches the requested certificate"); } else { msg.append("\tThis differs from the requested certificate"); } } } extension = singleResp.getExtension(OCSPObjectIdentifiers.id_pkix_ocsp_archive_cutoff); if (extension != null) { ASN1Encodable extensionValue = extension.getParsedValue(); ASN1GeneralizedTime time = ASN1GeneralizedTime.getInstance(extensionValue); msg.append("\nArchive-CutOff: "); msg.append(time.getTimeString()); } AlgorithmIdentifier sigAlg = basicResp.getSignatureAlgorithmID(); if (sigAlg == null) { msg.append(("\nresponse is not signed")); } else { String sigAlgName = AlgorithmUtil.getSignatureAlgoName(sigAlg); if (sigAlgName == null) { sigAlgName = "unknown"; } msg.append("\nresponse is signed with ").append(sigAlgName); } // extensions msg.append("\nExtensions: "); List<?> extensionOIDs = basicResp.getExtensionOIDs(); if (extensionOIDs == null || extensionOIDs.size() == 0) { msg.append("-"); } else { int size = extensionOIDs.size(); for (int j = 0; j < size; j++) { ASN1ObjectIdentifier extensionOID = (ASN1ObjectIdentifier) extensionOIDs.get(j); String name = extensionOidNameMap.get(extensionOID); msg.append(name == null ? extensionOID.getId() : name); if (j != size - 1) { msg.append(", "); } } } } out(msg.toString()); } out(""); return null; }
From source file:org.xipki.ocsp.qa.impl.OcspQAImpl.java
License:Open Source License
private List<ValidationIssue> checkSingleCert(final int index, final SingleResp singleResp, final OcspCertStatus expectedStatus, final byte[] encodedCert, final boolean extendedRevoke, final Occurrence nextupdateOccurrence, final Occurrence certhashOccurrence, final ASN1ObjectIdentifier certhashAlg) { List<ValidationIssue> issues = new LinkedList<>(); {// ww w . j av a 2 s. c o m // status ValidationIssue issue = new ValidationIssue("OCSP.RESPONSE." + index + ".STATUS", "certificate status"); issues.add(issue); CertificateStatus singleCertStatus = singleResp.getCertStatus(); OcspCertStatus status = null; if (singleCertStatus == null) { status = OcspCertStatus.good; } else if (singleCertStatus instanceof RevokedStatus) { RevokedStatus revStatus = (RevokedStatus) singleCertStatus; Date revTime = revStatus.getRevocationTime(); if (revStatus.hasRevocationReason()) { int reason = revStatus.getRevocationReason(); if (extendedRevoke && reason == CRLReason.CERTIFICATE_HOLD.getCode() && revTime.getTime() == 0) { status = OcspCertStatus.unknown; } 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; default: issue.setFailureMessage("should not reach here, unknwon CRLReason " + revocationReason); break; } } } else { status = OcspCertStatus.rev_noreason; } } else if (singleCertStatus instanceof UnknownStatus) { status = OcspCertStatus.issuerUnknown; } else { issue.setFailureMessage("unknown certstatus: " + singleCertStatus.getClass().getName()); } if (issue.isFailed() == false && expectedStatus != status) { issue.setFailureMessage("is='" + status + "', but expected='" + expectedStatus + "'"); } } { // nextUpdate Date nextUpdate = singleResp.getNextUpdate(); checkOccurrence("OCSP.RESPONSE." + index + ".NEXTUPDATE", nextUpdate, nextupdateOccurrence); } Extension extension = singleResp.getExtension(ISISMTTObjectIdentifiers.id_isismtt_at_certHash); { checkOccurrence("OCSP.RESPONSE." + index + ".CERTHASh", extension, certhashOccurrence); } if (extension != null) { ASN1Encodable extensionValue = extension.getParsedValue(); CertHash certHash = CertHash.getInstance(extensionValue); ASN1ObjectIdentifier hashAlgOid = certHash.getHashAlgorithm().getAlgorithm(); if (certhashAlg != null) { // certHash algorithm ValidationIssue issue = new ValidationIssue("OCSP.RESPONSE." + index + ".CERTHASH.ALG", "certhash algorithm"); issues.add(issue); ASN1ObjectIdentifier is = certHash.getHashAlgorithm().getAlgorithm(); if (certhashAlg.equals(is) == false) { issue.setFailureMessage("is '" + is.getId() + "', but expected '" + certhashAlg.getId() + "'"); } } byte[] hashValue = certHash.getCertificateHash(); if (encodedCert != null) { ValidationIssue issue = new ValidationIssue("OCSP.RESPONSE." + index + ".CERTHASH.VALIDITY", "certhash validity"); issues.add(issue); try { MessageDigest md = MessageDigest.getInstance(hashAlgOid.getId()); byte[] expectedHashValue = md.digest(encodedCert); if (Arrays.equals(expectedHashValue, hashValue) == false) { issue.setFailureMessage("certHash does not match the requested certificate"); } } catch (NoSuchAlgorithmException e) { issue.setFailureMessage("NoSuchAlgorithm " + hashAlgOid.getId()); } } } return issues; }
From source file:org.xipki.ocsp.server.impl.OcspServer.java
License:Open Source License
public OcspRespWithCacheInfo answer(final Responder responder, final OCSPReq request, final AuditEvent auditEvent, final boolean viaGet) { ResponderOption responderOption = responder.getResponderOption(); RequestOption requestOption = responder.getRequestOption(); ResponseOption responseOption = responder.getResponseOption(); ResponderSigner signer = responder.getSigner(); AuditOption auditOption = responder.getAuditOption(); CertprofileOption certprofileOption = responder.getCertprofileOption(); int version = request.getVersionNumber(); if (requestOption.isVersionAllowed(version) == false) { String message = "invalid request version " + version; LOG.warn(message);/*from w w w . j a v a2 s.c o m*/ if (auditEvent != null) { fillAuditEvent(auditEvent, AuditLevel.INFO, AuditStatus.FAILED, message); } return createUnsuccessfullOCSPResp(OcspResponseStatus.malformedRequest); } try { OcspRespWithCacheInfo resp = checkSignature(request, requestOption, auditEvent); if (resp != null) { return resp; } boolean couldCacheInfo = viaGet; List<Extension> responseExtensions = new ArrayList<>(2); Req[] requestList = request.getRequestList(); int n = requestList.length; Set<ASN1ObjectIdentifier> criticalExtensionOIDs = new HashSet<>(); Set<?> tmp = request.getCriticalExtensionOIDs(); if (tmp != null) { for (Object oid : tmp) { criticalExtensionOIDs.add((ASN1ObjectIdentifier) oid); } } RespID respID = new RespID(signer.getResponderId()); BasicOCSPRespBuilder basicOcspBuilder = new BasicOCSPRespBuilder(respID); ASN1ObjectIdentifier extensionType = OCSPObjectIdentifiers.id_pkix_ocsp_nonce; criticalExtensionOIDs.remove(extensionType); Extension nonceExtn = request.getExtension(extensionType); if (nonceExtn != null) { byte[] nonce = nonceExtn.getExtnValue().getOctets(); int len = nonce.length; int min = requestOption.getNonceMinLen(); int max = requestOption.getNonceMaxLen(); if (len < min || len > max) { LOG.warn("length of nonce {} not within [{},{}]", new Object[] { len, min, max }); if (auditEvent != null) { StringBuilder sb = new StringBuilder(); sb.append("length of nonce ").append(len); sb.append(" not within [").append(min).append(", ").append(max); fillAuditEvent(auditEvent, AuditLevel.INFO, AuditStatus.FAILED, sb.toString()); } return createUnsuccessfullOCSPResp(OcspResponseStatus.malformedRequest); } couldCacheInfo = false; responseExtensions.add(nonceExtn); } else if (requestOption.isNonceRequired()) { String message = "nonce required, but is not present in the request"; LOG.warn(message); if (auditEvent != null) { fillAuditEvent(auditEvent, AuditLevel.INFO, AuditStatus.FAILED, message); } return createUnsuccessfullOCSPResp(OcspResponseStatus.malformedRequest); } boolean includeExtendedRevokeExtension = false; long cacheThisUpdate = 0; long cacheNextUpdate = Long.MAX_VALUE; for (int i = 0; i < n; i++) { AuditChildEvent childAuditEvent = null; if (auditEvent != null) { childAuditEvent = new AuditChildEvent(); auditEvent.addChildAuditEvent(childAuditEvent); } Req req = requestList[i]; CertificateID certID = req.getCertID(); String certIdHashAlgo = certID.getHashAlgOID().getId(); HashAlgoType reqHashAlgo = HashAlgoType.getHashAlgoType(certIdHashAlgo); if (reqHashAlgo == null) { LOG.warn("unknown CertID.hashAlgorithm {}", certIdHashAlgo); if (childAuditEvent != null) { fillAuditEvent(childAuditEvent, AuditLevel.INFO, AuditStatus.FAILED, "unknown CertID.hashAlgorithm " + certIdHashAlgo); } return createUnsuccessfullOCSPResp(OcspResponseStatus.malformedRequest); } else if (requestOption.allows(reqHashAlgo) == false) { LOG.warn("CertID.hashAlgorithm {} not allowed", certIdHashAlgo); if (childAuditEvent != null) { fillAuditEvent(childAuditEvent, AuditLevel.INFO, AuditStatus.FAILED, "CertID.hashAlgorithm " + certIdHashAlgo + " not allowed"); } return createUnsuccessfullOCSPResp(OcspResponseStatus.malformedRequest); } CertStatusInfo certStatusInfo = null; CertStatusStore answeredStore = null; boolean exceptionOccurs = false; for (CertStatusStore store : responder.getStores()) { try { certStatusInfo = store.getCertStatus(reqHashAlgo, certID.getIssuerNameHash(), certID.getIssuerKeyHash(), certID.getSerialNumber(), responseOption.isIncludeCerthash(), responseOption.getCertHashAlgo(), certprofileOption); if (certStatusInfo.getCertStatus() != CertStatus.ISSUER_UNKNOWN) { answeredStore = store; break; } } catch (CertStatusStoreException e) { exceptionOccurs = true; final String message = "getCertStatus() of CertStatusStore " + store.getName(); if (LOG.isErrorEnabled()) { LOG.error(LogUtil.buildExceptionLogFormat(message), e.getClass().getName(), e.getMessage()); } LOG.debug(message, e); } } if (certStatusInfo == null) { if (childAuditEvent != null) { fillAuditEvent(childAuditEvent, AuditLevel.ERROR, AuditStatus.FAILED, "no CertStatusStore can answer the request"); } if (exceptionOccurs) { return createUnsuccessfullOCSPResp(OcspResponseStatus.tryLater); } else { certStatusInfo = CertStatusInfo.getIssuerUnknownCertStatusInfo(new Date(), null); } } else if (answeredStore != null) { if (responderOption.isInheritCaRevocation()) { CertRevocationInfo caRevInfo = answeredStore.getCARevocationInfo(reqHashAlgo, certID.getIssuerNameHash(), certID.getIssuerKeyHash()); if (caRevInfo != null) { CertStatus certStatus = certStatusInfo.getCertStatus(); boolean replaced = false; if (certStatus == CertStatus.GOOD || certStatus == CertStatus.UNKNOWN) { replaced = true; } else if (certStatus == CertStatus.REVOKED) { if (certStatusInfo.getRevocationInfo().getRevocationTime() .after(caRevInfo.getRevocationTime())) { replaced = true; } } if (replaced) { CertRevocationInfo newRevInfo; if (caRevInfo.getReason() == CRLReason.CA_COMPROMISE) { newRevInfo = caRevInfo; } else { newRevInfo = new CertRevocationInfo(CRLReason.CA_COMPROMISE, caRevInfo.getRevocationTime(), caRevInfo.getInvalidityTime()); } certStatusInfo = CertStatusInfo.getRevokedCertStatusInfo(newRevInfo, certStatusInfo.getCertHashAlgo(), certStatusInfo.getCertHash(), certStatusInfo.getThisUpdate(), certStatusInfo.getNextUpdate(), certStatusInfo.getCertprofile()); } } } } if (childAuditEvent != null) { String certprofile = certStatusInfo.getCertprofile(); String auditCertType; if (certprofile != null) { auditCertType = auditOption.getCertprofileMapping().get(certprofile); if (auditCertType == null) { auditCertType = certprofile; } } else { auditCertType = "UNKNOWN"; } childAuditEvent.addEventData(new AuditEventData("certType", auditCertType)); } // certStatusInfo could not be null in any case, since at least one store is configured Date thisUpdate = certStatusInfo.getThisUpdate(); if (thisUpdate == null) { thisUpdate = new Date(); } Date nextUpdate = certStatusInfo.getNextUpdate(); List<Extension> extensions = new LinkedList<>(); boolean unknownAsRevoked = false; CertificateStatus bcCertStatus = null; switch (certStatusInfo.getCertStatus()) { case GOOD: bcCertStatus = null; break; case ISSUER_UNKNOWN: couldCacheInfo = false; bcCertStatus = new UnknownStatus(); break; case UNKNOWN: case IGNORE: couldCacheInfo = false; if (responderOption.getMode() == OCSPMode.RFC2560) { bcCertStatus = new UnknownStatus(); } else// (ocspMode == OCSPMode.RFC6960) { unknownAsRevoked = true; includeExtendedRevokeExtension = true; bcCertStatus = new RevokedStatus(new Date(0L), CRLReason.CERTIFICATE_HOLD.getCode()); } break; case REVOKED: CertRevocationInfo revInfo = certStatusInfo.getRevocationInfo(); ASN1GeneralizedTime revTime = new ASN1GeneralizedTime(revInfo.getRevocationTime()); org.bouncycastle.asn1.x509.CRLReason _reason = null; if (responseOption.isIncludeRevReason()) { _reason = org.bouncycastle.asn1.x509.CRLReason.lookup(revInfo.getReason().getCode()); } RevokedInfo _revInfo = new RevokedInfo(revTime, _reason); bcCertStatus = new RevokedStatus(_revInfo); Date invalidityDate = revInfo.getInvalidityTime(); if (responseOption.isIncludeInvalidityDate() && invalidityDate != null && invalidityDate.equals(revTime) == false) { Extension extension = new Extension(Extension.invalidityDate, false, new ASN1GeneralizedTime(invalidityDate).getEncoded()); extensions.add(extension); } break; } byte[] certHash = certStatusInfo.getCertHash(); if (certHash != null) { ASN1ObjectIdentifier hashAlgoOid = new ASN1ObjectIdentifier( certStatusInfo.getCertHashAlgo().getOid()); AlgorithmIdentifier aId = new AlgorithmIdentifier(hashAlgoOid, DERNull.INSTANCE); CertHash bcCertHash = new CertHash(aId, certHash); byte[] encodedCertHash; try { encodedCertHash = bcCertHash.getEncoded(); } catch (IOException e) { final String message = "answer() bcCertHash.getEncoded"; if (LOG.isErrorEnabled()) { LOG.error(LogUtil.buildExceptionLogFormat(message), e.getClass().getName(), e.getMessage()); } LOG.debug(message, e); if (childAuditEvent != null) { fillAuditEvent(childAuditEvent, AuditLevel.ERROR, AuditStatus.FAILED, "CertHash.getEncoded() with IOException"); } return createUnsuccessfullOCSPResp(OcspResponseStatus.internalError); } Extension extension = new Extension(ISISMTTObjectIdentifiers.id_isismtt_at_certHash, false, encodedCertHash); extensions.add(extension); } if (certStatusInfo.getArchiveCutOff() != null) { Extension extension = new Extension(OCSPObjectIdentifiers.id_pkix_ocsp_archive_cutoff, false, new ASN1GeneralizedTime(certStatusInfo.getArchiveCutOff()).getEncoded()); extensions.add(extension); } String certStatusText; if (bcCertStatus instanceof UnknownStatus) { certStatusText = "unknown"; } else if (bcCertStatus instanceof RevokedStatus) { certStatusText = unknownAsRevoked ? "unknown_as_revoked" : "revoked"; } else if (bcCertStatus == null) { certStatusText = "good"; } else { certStatusText = "should-not-happen"; } if (childAuditEvent != null) { childAuditEvent.setLevel(AuditLevel.INFO); childAuditEvent.setStatus(AuditStatus.SUCCESSFUL); childAuditEvent.addEventData(new AuditEventData("certStatus", certStatusText)); } if (LOG.isDebugEnabled()) { StringBuilder sb = new StringBuilder(); sb.append("certHashAlgo: ").append(certID.getHashAlgOID().getId()).append(", "); String hexCertHash = null; if (certHash != null) { hexCertHash = Hex.toHexString(certHash).toUpperCase(); } sb.append("issuerKeyHash: ").append(Hex.toHexString(certID.getIssuerKeyHash()).toUpperCase()) .append(", "); sb.append("issuerNameHash: ").append(Hex.toHexString(certID.getIssuerNameHash()).toUpperCase()) .append(", "); sb.append("serialNumber: ").append(certID.getSerialNumber()).append(", "); sb.append("certStatus: ").append(certStatusText).append(", "); sb.append("thisUpdate: ").append(thisUpdate).append(", "); sb.append("nextUpdate: ").append(nextUpdate).append(", "); sb.append("certHash: ").append(hexCertHash); LOG.debug(sb.toString()); } basicOcspBuilder.addResponse(certID, bcCertStatus, thisUpdate, nextUpdate, CollectionUtil.isEmpty(extensions) ? null : new Extensions(extensions.toArray(new Extension[0]))); cacheThisUpdate = Math.max(cacheThisUpdate, thisUpdate.getTime()); if (nextUpdate != null) { cacheNextUpdate = Math.min(cacheNextUpdate, nextUpdate.getTime()); } } if (includeExtendedRevokeExtension) { responseExtensions.add(new Extension(ObjectIdentifiers.id_pkix_ocsp_extendedRevoke, true, DERNull.INSTANCE.getEncoded())); } if (CollectionUtil.isNotEmpty(responseExtensions)) { basicOcspBuilder .setResponseExtensions(new Extensions(responseExtensions.toArray(new Extension[0]))); } ConcurrentContentSigner concurrentSigner = null; if (responderOption.getMode() != OCSPMode.RFC2560) { extensionType = ObjectIdentifiers.id_pkix_ocsp_prefSigAlgs; criticalExtensionOIDs.remove(extensionType); Extension ext = request.getExtension(extensionType); if (ext != null) { ASN1Sequence preferredSigAlgs = ASN1Sequence.getInstance(ext.getParsedValue()); concurrentSigner = signer.getSignerForPreferredSigAlgs(preferredSigAlgs); } } if (CollectionUtil.isNotEmpty(criticalExtensionOIDs)) { return createUnsuccessfullOCSPResp(OcspResponseStatus.malformedRequest); } if (concurrentSigner == null) { concurrentSigner = signer.getFirstSigner(); } ContentSigner singleSigner; try { singleSigner = concurrentSigner.borrowContentSigner(); } catch (NoIdleSignerException e) { return createUnsuccessfullOCSPResp(OcspResponseStatus.tryLater); } X509CertificateHolder[] certsInResp; EmbedCertsMode certsMode = responseOption.getEmbedCertsMode(); if (certsMode == null || certsMode == EmbedCertsMode.SIGNER) { certsInResp = new X509CertificateHolder[] { signer.getBcCertificate() }; } else if (certsMode == EmbedCertsMode.SIGNER_AND_CA) { certsInResp = signer.getBcCertificateChain(); } else { // NONE certsInResp = null; } BasicOCSPResp basicOcspResp; try { basicOcspResp = basicOcspBuilder.build(singleSigner, certsInResp, new Date()); } catch (OCSPException e) { final String message = "answer() basicOcspBuilder.build"; if (LOG.isErrorEnabled()) { LOG.error(LogUtil.buildExceptionLogFormat(message), e.getClass().getName(), e.getMessage()); } LOG.debug(message, e); if (auditEvent != null) { fillAuditEvent(auditEvent, AuditLevel.ERROR, AuditStatus.FAILED, "BasicOCSPRespBuilder.build() with OCSPException"); } return createUnsuccessfullOCSPResp(OcspResponseStatus.internalError); } finally { concurrentSigner.returnContentSigner(singleSigner); } OCSPRespBuilder ocspRespBuilder = new OCSPRespBuilder(); try { OCSPResp ocspResp = ocspRespBuilder.build(OcspResponseStatus.successfull.getStatus(), basicOcspResp); if (couldCacheInfo) { ResponseCacheInfo cacheInfo = new ResponseCacheInfo(cacheThisUpdate); if (cacheNextUpdate != Long.MAX_VALUE) { cacheInfo.setNextUpdate(cacheNextUpdate); } return new OcspRespWithCacheInfo(ocspResp, cacheInfo); } else { return new OcspRespWithCacheInfo(ocspResp, null); } } catch (OCSPException e) { final String message = "answer() ocspRespBuilder.build"; if (LOG.isErrorEnabled()) { LOG.error(LogUtil.buildExceptionLogFormat(message), e.getClass().getName(), e.getMessage()); } LOG.debug(message, e); if (auditEvent != null) { fillAuditEvent(auditEvent, AuditLevel.ERROR, AuditStatus.FAILED, "OCSPRespBuilder.build() with OCSPException"); } return createUnsuccessfullOCSPResp(OcspResponseStatus.internalError); } } catch (Throwable t) { final String message = "Throwable"; if (LOG.isErrorEnabled()) { LOG.error(LogUtil.buildExceptionLogFormat(message), t.getClass().getName(), t.getMessage()); } LOG.debug(message, t); if (auditEvent != null) { fillAuditEvent(auditEvent, AuditLevel.ERROR, AuditStatus.FAILED, "internal error"); } return createUnsuccessfullOCSPResp(OcspResponseStatus.internalError); } }
From source file:org.xipki.pki.ocsp.client.shell.OcspStatusCmd.java
License:Open Source License
@Override protected Object processResponse(final OCSPResp response, final X509Certificate respIssuer, final IssuerHash issuerHash, final List<BigInteger> serialNumbers, final Map<BigInteger, byte[]> encodedCerts) throws Exception { ParamUtil.requireNonNull("response", response); ParamUtil.requireNonNull("issuerHash", issuerHash); ParamUtil.requireNonNull("serialNumbers", serialNumbers); BasicOCSPResp basicResp = OcspUtils.extractBasicOcspResp(response); boolean extendedRevoke = basicResp.getExtension(ObjectIdentifiers.id_pkix_ocsp_extendedRevoke) != null; SingleResp[] singleResponses = basicResp.getResponses(); if (singleResponses == null || singleResponses.length == 0) { throw new CmdFailure("received no status from server"); }//from w w w .j av a 2s .c o m final int n = singleResponses.length; if (n != serialNumbers.size()) { throw new CmdFailure("received status with " + n + " single responses from server, but " + serialNumbers.size() + " were requested"); } Date[] thisUpdates = new Date[n]; for (int i = 0; i < n; i++) { thisUpdates[i] = singleResponses[i].getThisUpdate(); } // check the signature if available if (null == basicResp.getSignature()) { println("response is not signed"); } else { X509CertificateHolder[] responderCerts = basicResp.getCerts(); if (responderCerts == null || responderCerts.length < 1) { throw new CmdFailure("no responder certificate is contained in the response"); } ResponderID respId = basicResp.getResponderId().toASN1Primitive(); X500Name respIdByName = respId.getName(); byte[] respIdByKey = respId.getKeyHash(); X509CertificateHolder respSigner = null; for (X509CertificateHolder cert : responderCerts) { if (respIdByName != null) { if (cert.getSubject().equals(respIdByName)) { respSigner = cert; } } else { byte[] spkiSha1 = HashAlgoType.SHA1 .hash(cert.getSubjectPublicKeyInfo().getPublicKeyData().getBytes()); if (Arrays.equals(respIdByKey, spkiSha1)) { respSigner = cert; } } if (respSigner != null) { break; } } if (respSigner == null) { throw new CmdFailure("no responder certificate match the ResponderId"); } boolean validOn = true; for (Date thisUpdate : thisUpdates) { validOn = respSigner.isValidOn(thisUpdate); if (!validOn) { throw new CmdFailure("responder certificate is not valid on " + thisUpdate); } } if (validOn) { PublicKey responderPubKey = KeyUtil.generatePublicKey(respSigner.getSubjectPublicKeyInfo()); ContentVerifierProvider cvp = securityFactory.getContentVerifierProvider(responderPubKey); boolean sigValid = basicResp.isSignatureValid(cvp); if (!sigValid) { throw new CmdFailure("response is equipped with invalid signature"); } // verify the OCSPResponse signer if (respIssuer != null) { boolean certValid = true; X509Certificate jceRespSigner = X509Util.toX509Cert(respSigner.toASN1Structure()); if (X509Util.issues(respIssuer, jceRespSigner)) { try { jceRespSigner.verify(respIssuer.getPublicKey()); } catch (SignatureException ex) { certValid = false; } } if (!certValid) { throw new CmdFailure("response is equipped with valid signature but the" + " OCSP signer is not trusted"); } } else { println("response is equipped with valid signature"); } // end if(respIssuer) } // end if(validOn) if (verbose.booleanValue()) { println("responder is " + X509Util.getRfc4519Name(responderCerts[0].getSubject())); } } // end if for (int i = 0; i < n; i++) { if (n > 1) { println("---------------------------- " + i + "----------------------------"); } SingleResp singleResp = singleResponses[i]; CertificateStatus singleCertStatus = singleResp.getCertStatus(); String status; if (singleCertStatus == null) { status = "good"; } else if (singleCertStatus instanceof RevokedStatus) { RevokedStatus revStatus = (RevokedStatus) singleCertStatus; Date revTime = revStatus.getRevocationTime(); Date invTime = null; Extension ext = singleResp.getExtension(Extension.invalidityDate); if (ext != null) { invTime = ASN1GeneralizedTime.getInstance(ext.getParsedValue()).getDate(); } if (revStatus.hasRevocationReason()) { int reason = revStatus.getRevocationReason(); if (extendedRevoke && reason == CrlReason.CERTIFICATE_HOLD.getCode() && revTime.getTime() == 0) { status = "unknown (RFC6960)"; } else { StringBuilder sb = new StringBuilder("revoked, reason = "); sb.append(CrlReason.forReasonCode(reason).getDescription()); sb.append(", revocationTime = ").append(revTime); if (invTime != null) { sb.append(", invalidityTime = ").append(invTime); } status = sb.toString(); } } else { status = "revoked, no reason, revocationTime = " + revTime; } } else if (singleCertStatus instanceof UnknownStatus) { status = "unknown (RFC2560)"; } else { status = "ERROR"; } StringBuilder msg = new StringBuilder(); CertificateID certId = singleResp.getCertID(); HashAlgoType hashAlgo = HashAlgoType.getNonNullHashAlgoType(certId.getHashAlgOID()); boolean issuerMatch = issuerHash.match(hashAlgo, certId.getIssuerNameHash(), certId.getIssuerKeyHash()); BigInteger serialNumber = certId.getSerialNumber(); msg.append("issuer matched: ").append(issuerMatch); msg.append("\nserialNumber: ").append(LogUtil.formatCsn(serialNumber)); msg.append("\nCertificate status: ").append(status); if (verbose.booleanValue()) { msg.append("\nthisUpdate: ").append(singleResp.getThisUpdate()); msg.append("\nnextUpdate: ").append(singleResp.getNextUpdate()); Extension extension = singleResp.getExtension(ISISMTTObjectIdentifiers.id_isismtt_at_certHash); if (extension != null) { msg.append("\nCertHash is provided:\n"); ASN1Encodable extensionValue = extension.getParsedValue(); CertHash certHash = CertHash.getInstance(extensionValue); ASN1ObjectIdentifier hashAlgOid = certHash.getHashAlgorithm().getAlgorithm(); byte[] hashValue = certHash.getCertificateHash(); msg.append("\tHash algo : ").append(hashAlgOid.getId()).append("\n"); msg.append("\tHash value: ").append(Hex.toHexString(hashValue)).append("\n"); if (encodedCerts != null) { byte[] encodedCert = encodedCerts.get(serialNumber); MessageDigest md = MessageDigest.getInstance(hashAlgOid.getId()); byte[] expectedHashValue = md.digest(encodedCert); if (Arrays.equals(expectedHashValue, hashValue)) { msg.append("\tThis matches the requested certificate"); } else { msg.append("\tThis differs from the requested certificate"); } } } // end if (extension != null) extension = singleResp.getExtension(OCSPObjectIdentifiers.id_pkix_ocsp_archive_cutoff); if (extension != null) { ASN1Encodable extensionValue = extension.getParsedValue(); ASN1GeneralizedTime time = ASN1GeneralizedTime.getInstance(extensionValue); msg.append("\nArchive-CutOff: "); msg.append(time.getTimeString()); } AlgorithmIdentifier sigAlg = basicResp.getSignatureAlgorithmID(); if (sigAlg == null) { msg.append(("\nresponse is not signed")); } else { String sigAlgName = AlgorithmUtil.getSignatureAlgoName(sigAlg); if (sigAlgName == null) { sigAlgName = "unknown"; } msg.append("\nresponse is signed with ").append(sigAlgName); } // extensions msg.append("\nExtensions: "); List<?> extensionOids = basicResp.getExtensionOIDs(); if (extensionOids == null || extensionOids.size() == 0) { msg.append("-"); } else { int size = extensionOids.size(); for (int j = 0; j < size; j++) { ASN1ObjectIdentifier extensionOid = (ASN1ObjectIdentifier) extensionOids.get(j); String name = EXTENSION_OIDNAME_MAP.get(extensionOid); if (name == null) { msg.append(extensionOid.getId()); } else { msg.append(name); } if (j != size - 1) { msg.append(", "); } } } } // end if (verbose.booleanValue()) println(msg.toString()); } // end for println(""); return null; }
From source file:org.xipki.pki.ocsp.qa.OcspQa.java
License:Open Source License
private List<ValidationIssue> checkSingleCert(final int index, final SingleResp singleResp, final IssuerHash issuerHash, final OcspCertStatus expectedStatus, final byte[] encodedCert, final boolean extendedRevoke, final Occurrence nextupdateOccurrence, final Occurrence certhashOccurrence, final ASN1ObjectIdentifier certhashAlg) { List<ValidationIssue> issues = new LinkedList<>(); // issuer hash ValidationIssue issue = new ValidationIssue("OCSP.RESPONSE." + index + ".ISSUER", "certificate issuer"); issues.add(issue);// w w w .ja va 2 s .c o m CertificateID certId = singleResp.getCertID(); HashAlgoType hashAlgo = HashAlgoType.getHashAlgoType(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; if (singleCertStatus == null) { status = OcspCertStatus.good; } else if (singleCertStatus instanceof RevokedStatus) { RevokedStatus revStatus = (RevokedStatus) singleCertStatus; Date revTime = revStatus.getRevocationTime(); if (revStatus.hasRevocationReason()) { int reason = revStatus.getRevocationReason(); if (extendedRevoke && reason == CrlReason.CERTIFICATE_HOLD.getCode() && revTime.getTime() == 0) { status = OcspCertStatus.unknown; } 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; 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 = OcspCertStatus.issuerUnknown; } else { issue.setFailureMessage("unknown certstatus: " + singleCertStatus.getClass().getName()); } if (!issue.isFailed() && expectedStatus != status) { issue.setFailureMessage("is='" + status + "', but expected='" + expectedStatus + "'"); } // nextUpdate Date nextUpdate = singleResp.getNextUpdate(); checkOccurrence("OCSP.RESPONSE." + index + ".NEXTUPDATE", nextUpdate, nextupdateOccurrence); Extension extension = singleResp.getExtension(ISISMTTObjectIdentifiers.id_isismtt_at_certHash); checkOccurrence("OCSP.RESPONSE." + index + ".CERTHASH", extension, certhashOccurrence); 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) } // end if (extension != null) return issues; }
From source file:org.xipki.pki.ocsp.server.impl.OcspServer.java
License:Open Source License
private OcspRespWithCacheInfo processCertReq(Req req, BasicOCSPRespBuilder builder, Responder responder, RequestOption reqOpt, ResponseOption repOpt, OcspRespControl repControl, AuditEvent event) throws IOException { CertificateID certId = req.getCertID(); String certIdHashAlgo = certId.getHashAlgOID().getId(); HashAlgoType reqHashAlgo = HashAlgoType.getHashAlgoType(certIdHashAlgo); if (reqHashAlgo == null) { LOG.warn("unknown CertID.hashAlgorithm {}", certIdHashAlgo); if (event != null) { fillAuditEvent(event, AuditLevel.INFO, AuditStatus.FAILED, "unknown CertID.hashAlgorithm " + certIdHashAlgo); }//from www. j a v a 2 s. com return createUnsuccessfulOcspResp(OcspResponseStatus.malformedRequest); } else if (!reqOpt.allows(reqHashAlgo)) { LOG.warn("CertID.hashAlgorithm {} not allowed", certIdHashAlgo); if (event != null) { fillAuditEvent(event, AuditLevel.INFO, AuditStatus.FAILED, "not allowed CertID.hashAlgorithm " + certIdHashAlgo); } return createUnsuccessfulOcspResp(OcspResponseStatus.malformedRequest); } if (event != null) { event.addEventData(OcspAuditConstants.NAME_serial, certId.getSerialNumber()); } CertStatusInfo certStatusInfo = null; OcspStore answeredStore = null; boolean exceptionOccurs = false; Date now = new Date(); for (OcspStore store : responder.getStores()) { try { certStatusInfo = store.getCertStatus(now, reqHashAlgo, certId.getIssuerNameHash(), certId.getIssuerKeyHash(), certId.getSerialNumber(), repOpt.isIncludeCerthash(), repOpt.getCertHashAlgo(), responder.getCertprofileOption()); if (certStatusInfo != null && certStatusInfo.getCertStatus() != CertStatus.ISSUER_UNKNOWN) { answeredStore = store; break; } } catch (OcspStoreException ex) { exceptionOccurs = true; LogUtil.error(LOG, ex, "getCertStatus() of CertStatusStore " + store.getName()); } // end try } // end for if (certStatusInfo == null) { if (exceptionOccurs) { fillAuditEvent(event, AuditLevel.INFO, AuditStatus.FAILED, "no CertStatusStore can answer the request"); return createUnsuccessfulOcspResp(OcspResponseStatus.tryLater); } else { certStatusInfo = CertStatusInfo.getIssuerUnknownCertStatusInfo(new Date(), null); } } else if (answeredStore != null && responder.getResponderOption().isInheritCaRevocation()) { CertRevocationInfo caRevInfo = answeredStore.getCaRevocationInfo(reqHashAlgo, certId.getIssuerNameHash(), certId.getIssuerKeyHash()); if (caRevInfo != null) { CertStatus certStatus = certStatusInfo.getCertStatus(); boolean replaced = false; if (certStatus == CertStatus.GOOD || certStatus == CertStatus.UNKNOWN) { replaced = true; } else if (certStatus == CertStatus.REVOKED) { if (certStatusInfo.getRevocationInfo().getRevocationTime() .after(caRevInfo.getRevocationTime())) { replaced = true; } } if (replaced) { CertRevocationInfo newRevInfo; if (caRevInfo.getReason() == CrlReason.CA_COMPROMISE) { newRevInfo = caRevInfo; } else { newRevInfo = new CertRevocationInfo(CrlReason.CA_COMPROMISE, caRevInfo.getRevocationTime(), caRevInfo.getInvalidityTime()); } certStatusInfo = CertStatusInfo.getRevokedCertStatusInfo(newRevInfo, certStatusInfo.getCertHashAlgo(), certStatusInfo.getCertHash(), certStatusInfo.getThisUpdate(), certStatusInfo.getNextUpdate(), certStatusInfo.getCertprofile()); } // end if(replaced) } // end if } // end if if (event != null) { String certprofile = certStatusInfo.getCertprofile(); String auditCertType; if (certprofile != null) { auditCertType = responder.getAuditOption().getCertprofileMapping().get(certprofile); if (auditCertType == null) { auditCertType = certprofile; } } else { auditCertType = "UNKNOWN"; } event.addEventData(OcspAuditConstants.NAME_type, auditCertType); } // certStatusInfo must not be null in any case, since at least one store // is configured Date thisUpdate = certStatusInfo.getThisUpdate(); if (thisUpdate == null) { thisUpdate = new Date(); } Date nextUpdate = certStatusInfo.getNextUpdate(); List<Extension> extensions = new LinkedList<>(); boolean unknownAsRevoked = false; CertificateStatus bcCertStatus; switch (certStatusInfo.getCertStatus()) { case GOOD: bcCertStatus = null; break; case ISSUER_UNKNOWN: repControl.couldCacheInfo = false; bcCertStatus = new UnknownStatus(); break; case UNKNOWN: case IGNORE: repControl.couldCacheInfo = false; if (responder.getResponderOption().getMode() == OcspMode.RFC2560) { bcCertStatus = new UnknownStatus(); } else { // (ocspMode == OCSPMode.RFC6960) unknownAsRevoked = true; repControl.includeExtendedRevokeExtension = true; bcCertStatus = new RevokedStatus(new Date(0L), CrlReason.CERTIFICATE_HOLD.getCode()); } break; case REVOKED: CertRevocationInfo revInfo = certStatusInfo.getRevocationInfo(); ASN1GeneralizedTime revTime = new ASN1GeneralizedTime(revInfo.getRevocationTime()); org.bouncycastle.asn1.x509.CRLReason tmpReason = null; if (repOpt.isIncludeRevReason()) { tmpReason = org.bouncycastle.asn1.x509.CRLReason.lookup(revInfo.getReason().getCode()); } RevokedInfo tmpRevInfo = new RevokedInfo(revTime, tmpReason); bcCertStatus = new RevokedStatus(tmpRevInfo); Date invalidityDate = revInfo.getInvalidityTime(); if (repOpt.isIncludeInvalidityDate() && invalidityDate != null && !invalidityDate.equals(revInfo.getRevocationTime())) { Extension extension = new Extension(Extension.invalidityDate, false, new ASN1GeneralizedTime(invalidityDate).getEncoded()); extensions.add(extension); } break; default: throw new RuntimeException("unknown CertificateStatus:" + certStatusInfo.getCertStatus()); } // end switch byte[] certHash = certStatusInfo.getCertHash(); if (certHash != null) { ASN1ObjectIdentifier hashAlgOid = certStatusInfo.getCertHashAlgo().getOid(); AlgorithmIdentifier hashAlgId = new AlgorithmIdentifier(hashAlgOid, DERNull.INSTANCE); CertHash bcCertHash = new CertHash(hashAlgId, certHash); byte[] encodedCertHash; try { encodedCertHash = bcCertHash.getEncoded(); } catch (IOException ex) { LogUtil.error(LOG, ex, "answer() bcCertHash.getEncoded"); if (event != null) { fillAuditEvent(event, AuditLevel.ERROR, AuditStatus.FAILED, "CertHash.getEncoded() with IOException"); } return createUnsuccessfulOcspResp(OcspResponseStatus.internalError); } Extension extension = new Extension(ISISMTTObjectIdentifiers.id_isismtt_at_certHash, false, encodedCertHash); extensions.add(extension); } // end if(certHash != null) if (certStatusInfo.getArchiveCutOff() != null) { Extension extension = new Extension(OCSPObjectIdentifiers.id_pkix_ocsp_archive_cutoff, false, new ASN1GeneralizedTime(certStatusInfo.getArchiveCutOff()).getEncoded()); extensions.add(extension); } String certStatusText; if (bcCertStatus instanceof UnknownStatus) { certStatusText = "unknown"; } else if (bcCertStatus instanceof RevokedStatus) { certStatusText = unknownAsRevoked ? "unknown_as_revoked" : "revoked"; } else if (bcCertStatus == null) { certStatusText = "good"; } else { certStatusText = "should-not-happen"; } if (event != null) { event.setLevel(AuditLevel.INFO); event.setStatus(AuditStatus.SUCCESSFUL); event.addEventData(OcspAuditConstants.NAME_status, certStatusText); } if (LOG.isDebugEnabled()) { StringBuilder sb = new StringBuilder(250); sb.append("certHashAlgo: ").append(certId.getHashAlgOID().getId()).append(", "); sb.append("issuerNameHash: ").append(Hex.toHexString(certId.getIssuerNameHash()).toUpperCase()) .append(", "); sb.append("issuerKeyHash: ").append(Hex.toHexString(certId.getIssuerKeyHash()).toUpperCase()) .append(", "); sb.append("serialNumber: ").append(LogUtil.formatCsn(certId.getSerialNumber())).append(", "); sb.append("certStatus: ").append(certStatusText).append(", "); sb.append("thisUpdate: ").append(thisUpdate).append(", "); sb.append("nextUpdate: ").append(nextUpdate); if (certHash != null) { sb.append(", certHash: ").append(Hex.toHexString(certHash).toUpperCase()); } LOG.debug(sb.toString()); } Extensions extns = null; if (CollectionUtil.isNonEmpty(extensions)) { extns = new Extensions(extensions.toArray(new Extension[0])); } builder.addResponse(certId, bcCertStatus, thisUpdate, nextUpdate, extns); repControl.cacheThisUpdate = Math.max(repControl.cacheThisUpdate, thisUpdate.getTime()); if (nextUpdate != null) { repControl.cacheNextUpdate = Math.min(repControl.cacheNextUpdate, nextUpdate.getTime()); } return null; }