List of usage examples for org.bouncycastle.cert.ocsp SingleResp getNextUpdate
public Date getNextUpdate()
From source file:be.fedict.trust.ocsp.OcspTrustLinker.java
License:Open Source License
@Override public TrustLinkerResult hasTrustLink(X509Certificate childCertificate, X509Certificate certificate, Date validationDate, RevocationData revocationData, AlgorithmPolicy algorithmPolicy) throws TrustLinkerResultException, Exception { URI ocspUri = getOcspUri(childCertificate); if (null == ocspUri) { return TrustLinkerResult.UNDECIDED; }//from ww w .j ava2 s.co m LOG.debug("OCSP URI: " + ocspUri); OCSPResp ocspResp = this.ocspRepository.findOcspResponse(ocspUri, childCertificate, certificate, validationDate); if (null == ocspResp) { LOG.debug("OCSP response not found"); return TrustLinkerResult.UNDECIDED; } int ocspRespStatus = ocspResp.getStatus(); if (OCSPResponseStatus.SUCCESSFUL != ocspRespStatus) { LOG.debug("OCSP response status: " + ocspRespStatus); return TrustLinkerResult.UNDECIDED; } Object responseObject = ocspResp.getResponseObject(); BasicOCSPResp basicOCSPResp = (BasicOCSPResp) responseObject; X509CertificateHolder[] responseCertificates = basicOCSPResp.getCerts(); for (X509CertificateHolder responseCertificate : responseCertificates) { LOG.debug("OCSP response cert: " + responseCertificate.getSubject()); LOG.debug("OCSP response cert issuer: " + responseCertificate.getIssuer()); } algorithmPolicy.checkSignatureAlgorithm(basicOCSPResp.getSignatureAlgOID().getId(), validationDate); if (0 == responseCertificates.length) { /* * This means that the OCSP response has been signed by the issuing * CA itself. */ ContentVerifierProvider contentVerifierProvider = new JcaContentVerifierProviderBuilder() .setProvider(BouncyCastleProvider.PROVIDER_NAME).build(certificate.getPublicKey()); boolean verificationResult = basicOCSPResp.isSignatureValid(contentVerifierProvider); if (false == verificationResult) { LOG.debug("OCSP response signature invalid"); return TrustLinkerResult.UNDECIDED; } } else { /* * We're dealing with a dedicated authorized OCSP Responder * certificate, or of course with a CA that issues the OCSP * Responses itself. */ X509CertificateHolder ocspResponderCertificate = responseCertificates[0]; ContentVerifierProvider contentVerifierProvider = new JcaContentVerifierProviderBuilder() .setProvider(BouncyCastleProvider.PROVIDER_NAME).build(ocspResponderCertificate); boolean verificationResult = basicOCSPResp.isSignatureValid(contentVerifierProvider); if (false == verificationResult) { LOG.debug("OCSP Responser response signature invalid"); return TrustLinkerResult.UNDECIDED; } if (false == Arrays.equals(certificate.getEncoded(), ocspResponderCertificate.getEncoded())) { // check certificate signature algorithm algorithmPolicy.checkSignatureAlgorithm( ocspResponderCertificate.getSignatureAlgorithm().getAlgorithm().getId(), validationDate); X509Certificate issuingCaCertificate; if (responseCertificates.length < 2) { // so the OCSP certificate chain only contains a single // entry LOG.debug("OCSP responder complete certificate chain missing"); /* * Here we assume that the OCSP Responder is directly signed * by the CA. */ issuingCaCertificate = certificate; } else { CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); issuingCaCertificate = (X509Certificate) certificateFactory .generateCertificate(new ByteArrayInputStream(responseCertificates[1].getEncoded())); /* * Is next check really required? */ if (false == certificate.equals(issuingCaCertificate)) { LOG.debug("OCSP responder certificate not issued by CA"); return TrustLinkerResult.UNDECIDED; } } // check certificate signature algorithmPolicy.checkSignatureAlgorithm(issuingCaCertificate.getSigAlgOID(), validationDate); PublicKeyTrustLinker publicKeyTrustLinker = new PublicKeyTrustLinker(); CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); X509Certificate x509OcspResponderCertificate = (X509Certificate) certificateFactory .generateCertificate(new ByteArrayInputStream(ocspResponderCertificate.getEncoded())); LOG.debug("OCSP Responder public key fingerprint: " + DigestUtils.sha1Hex(x509OcspResponderCertificate.getPublicKey().getEncoded())); publicKeyTrustLinker.hasTrustLink(x509OcspResponderCertificate, issuingCaCertificate, validationDate, revocationData, algorithmPolicy); if (null == x509OcspResponderCertificate .getExtensionValue(OCSPObjectIdentifiers.id_pkix_ocsp_nocheck.getId())) { LOG.debug("OCSP Responder certificate should have id-pkix-ocsp-nocheck"); /* * TODO: perform CRL validation on the OCSP Responder * certificate. On the other hand, do we really want to * check the checker? */ return TrustLinkerResult.UNDECIDED; } List<String> extendedKeyUsage = x509OcspResponderCertificate.getExtendedKeyUsage(); if (null == extendedKeyUsage) { LOG.debug("OCSP Responder certificate has no extended key usage extension"); return TrustLinkerResult.UNDECIDED; } if (false == extendedKeyUsage.contains(KeyPurposeId.id_kp_OCSPSigning.getId())) { LOG.debug("OCSP Responder certificate should have a OCSPSigning extended key usage"); return TrustLinkerResult.UNDECIDED; } } else { LOG.debug("OCSP Responder certificate equals the CA certificate"); // and the CA certificate is already trusted at this point } } DigestCalculatorProvider digCalcProv = new JcaDigestCalculatorProviderBuilder() .setProvider(BouncyCastleProvider.PROVIDER_NAME).build(); CertificateID certificateId = new CertificateID(digCalcProv.get(CertificateID.HASH_SHA1), new JcaX509CertificateHolder(certificate), childCertificate.getSerialNumber()); SingleResp[] singleResps = basicOCSPResp.getResponses(); for (SingleResp singleResp : singleResps) { CertificateID responseCertificateId = singleResp.getCertID(); if (false == certificateId.equals(responseCertificateId)) { continue; } DateTime thisUpdate = new DateTime(singleResp.getThisUpdate()); DateTime nextUpdate; if (null != singleResp.getNextUpdate()) { nextUpdate = new DateTime(singleResp.getNextUpdate()); } else { LOG.debug("no OCSP nextUpdate"); nextUpdate = thisUpdate; } LOG.debug("OCSP thisUpdate: " + thisUpdate); LOG.debug("(OCSP) nextUpdate: " + nextUpdate); DateTime beginValidity = thisUpdate.minus(this.freshnessInterval); DateTime endValidity = nextUpdate.plus(this.freshnessInterval); DateTime validationDateTime = new DateTime(validationDate); if (validationDateTime.isBefore(beginValidity)) { LOG.warn("OCSP response not yet valid"); continue; } if (validationDateTime.isAfter(endValidity)) { LOG.warn("OCSP response expired"); continue; } if (null == singleResp.getCertStatus()) { LOG.debug("OCSP OK for: " + childCertificate.getSubjectX500Principal()); addRevocationData(revocationData, ocspResp, ocspUri); return TrustLinkerResult.TRUSTED; } else { LOG.debug("OCSP certificate status: " + singleResp.getCertStatus().getClass().getName()); if (singleResp.getCertStatus() instanceof RevokedStatus) { LOG.debug("OCSP status revoked"); } addRevocationData(revocationData, ocspResp, ocspUri); throw new TrustLinkerResultException(TrustLinkerResultReason.INVALID_REVOCATION_STATUS, "certificate revoked by OCSP"); } } LOG.debug("no matching OCSP response entry"); return TrustLinkerResult.UNDECIDED; }
From source file:ee.ria.xroad.common.ocsp.OcspVerifier.java
License:Open Source License
private void verifyValidityAt(Date atDate, SingleResp singleResp) { // 5. The time at which the status being indicated is known // to be correct (thisUpdate) is sufficiently recent. if (isExpired(singleResp, atDate)) { throw new CodedException(X_INCORRECT_VALIDATION_INFO, "OCSP response is too old (thisUpdate: %s)", singleResp.getThisUpdate()); }//from ww w . ja v a2 s.c om if (options.isVerifyNextUpdate()) { // 6. When available, the time at or before which newer information will // be available about the status of the certificate (nextUpdate) is // greater than the current time. log.debug("Verify OCSP nextUpdate, atDate: {} nextUpdate: {}", atDate, singleResp.getNextUpdate()); if (singleResp.getNextUpdate() != null && singleResp.getNextUpdate().before(atDate)) { SimpleDateFormat fmt = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"); throw new CodedException(X_INCORRECT_VALIDATION_INFO, String.format("OCSP nextUpdate is too old, atDate: %s nextUpdate: %s", fmt.format(atDate), fmt.format(singleResp.getNextUpdate()))); } } else { log.debug("OCSP nextUpdate verification is turned off"); } }
From source file:eu.europa.ec.markt.dss.validation102853.OCSPCertificateVerifier.java
License:Open Source License
@Override public RevocationToken check(final CertificateToken toCheckToken) { if (ocspSource == null) { LOG.warn("OCSPSource null"); toCheckToken.extraInfo().infoOCSPSourceIsNull(); return null; }/*from ww w . jav a2 s .c om*/ try { final X509Certificate issuerCert = toCheckToken.getIssuerToken().getCertificate(); final X509Certificate toCheckCert = toCheckToken.getCertificate(); final BasicOCSPResp basicOCSPResp = ocspSource.getOCSPResponse(toCheckCert, issuerCert); if (basicOCSPResp == null) { String uri = ""; if (ocspSource instanceof OnlineOCSPSource) { uri = ((OnlineOCSPSource) ocspSource).getAccessLocation(toCheckCert); toCheckToken.extraInfo().infoNoOCSPResponse(uri); } if (LOG.isInfoEnabled()) { LOG.info("OCSP response not found for " + toCheckToken.getDSSIdAsString() + " [" + uri + "]"); } return null; } final BigInteger serialNumber = toCheckCert.getSerialNumber(); final X509CertificateHolder x509CertificateHolder = new X509CertificateHolder( DSSUtils.getEncoded(issuerCert)); final DigestCalculator digestCalculator = DSSUtils.getSHA1DigestCalculator(); final CertificateID certificateId = new CertificateID(digestCalculator, x509CertificateHolder, serialNumber); final SingleResp[] singleResps = basicOCSPResp.getResponses(); for (final SingleResp singleResp : singleResps) { if (!DSSRevocationUtils.matches(certificateId, singleResp)) { continue; } if (LOG.isDebugEnabled()) { LOG.debug("OCSP thisUpdate: " + singleResp.getThisUpdate()); LOG.debug("OCSP nextUpdate: " + singleResp.getNextUpdate()); } final OCSPToken ocspToken = new OCSPToken(basicOCSPResp, validationCertPool); if (ocspSource instanceof OnlineOCSPSource) { ocspToken.setSourceURI(((OnlineOCSPSource) ocspSource).getAccessLocation(toCheckCert)); } ocspToken.setIssuingTime(basicOCSPResp.getProducedAt()); toCheckToken.setRevocationToken(ocspToken); final Object certStatus = singleResp.getCertStatus(); if (certStatus == null) { if (LOG.isInfoEnabled()) { LOG.info("OCSP OK for: " + toCheckToken.getDSSIdAsString()); if (LOG.isTraceEnabled()) { LOG.trace("CertificateToken:\n{}", toCheckToken.toString()); } } ocspToken.setStatus(true); } else { if (LOG.isInfoEnabled()) { LOG.info("OCSP certificate status: " + certStatus.getClass().getName()); } if (certStatus instanceof RevokedStatus) { if (LOG.isInfoEnabled()) { LOG.info("OCSP status revoked"); } final RevokedStatus revokedStatus = (RevokedStatus) certStatus; ocspToken.setStatus(false); ocspToken.setRevocationDate(revokedStatus.getRevocationTime()); final int reasonId = revokedStatus.getRevocationReason(); final CRLReason crlReason = CRLReason.lookup(reasonId); ocspToken.setReason(crlReason.toString()); } else if (certStatus instanceof UnknownStatus) { if (LOG.isInfoEnabled()) { LOG.info("OCSP status unknown"); } ocspToken.setReason("OCSP status: unknown"); } } return ocspToken; } } catch (DSSException e) { LOG.error("OCSP DSS Exception: " + e.getMessage(), e); toCheckToken.extraInfo().infoOCSPException(e); return null; } catch (OCSPException e) { LOG.error("OCSP Exception: " + e.getMessage()); toCheckToken.extraInfo().infoOCSPException(e); throw new DSSException(e); } catch (IOException e) { throw new DSSException(e); } if (LOG.isInfoEnabled()) { LOG.debug("No matching OCSP response entry"); } toCheckToken.extraInfo().infoNoOCSPResponse(null); return null; }
From source file:io.netty.example.ocsp.OcspServerExample.java
License:Apache License
public static void main(String[] args) throws Exception { // We assume there's a private key. PrivateKey privateKey = null; // Step 1: Load the certificate chain for netty.io. We'll need the certificate // and the issuer's certificate and we don't need any of the intermediate certs. // The array is assumed to be a certain order to keep things simple. X509Certificate[] keyCertChain = parseCertificates(OcspServerExample.class, "netty_io_chain.pem"); X509Certificate certificate = keyCertChain[0]; X509Certificate issuer = keyCertChain[keyCertChain.length - 1]; // Step 2: We need the URL of the CA's OCSP responder server. It's somewhere encoded // into the certificate! Notice that it's a HTTP URL. URI uri = OcspUtils.ocspUri(certificate); System.out.println("OCSP Responder URI: " + uri); if (uri == null) { throw new IllegalStateException("The CA/certificate doesn't have an OCSP responder"); }//from ww w . j a v a 2 s.c o m // Step 3: Construct the OCSP request OCSPReq request = new OcspRequestBuilder().certificate(certificate).issuer(issuer).build(); // Step 4: Do the request to the CA's OCSP responder OCSPResp response = OcspUtils.request(uri, request, 5L, TimeUnit.SECONDS); if (response.getStatus() != OCSPResponseStatus.SUCCESSFUL) { throw new IllegalStateException("response-status=" + response.getStatus()); } // Step 5: Is my certificate any good or has the CA revoked it? BasicOCSPResp basicResponse = (BasicOCSPResp) response.getResponseObject(); SingleResp first = basicResponse.getResponses()[0]; CertificateStatus status = first.getCertStatus(); System.out.println("Status: " + (status == CertificateStatus.GOOD ? "Good" : status)); System.out.println("This Update: " + first.getThisUpdate()); System.out.println("Next Update: " + first.getNextUpdate()); if (status != null) { throw new IllegalStateException("certificate-status=" + status); } BigInteger certSerial = certificate.getSerialNumber(); BigInteger ocspSerial = first.getCertID().getSerialNumber(); if (!certSerial.equals(ocspSerial)) { throw new IllegalStateException("Bad Serials=" + certSerial + " vs. " + ocspSerial); } // Step 6: Cache the OCSP response and use it as long as it's not // expired. The exact semantics are beyond the scope of this example. if (!OpenSsl.isAvailable()) { throw new IllegalStateException("OpenSSL is not available!"); } if (!OpenSsl.isOcspSupported()) { throw new IllegalStateException("OCSP is not supported!"); } if (privateKey == null) { throw new IllegalStateException( "Because we don't have a PrivateKey we can't continue past this point."); } ReferenceCountedOpenSslContext context = (ReferenceCountedOpenSslContext) SslContextBuilder .forServer(privateKey, keyCertChain).sslProvider(SslProvider.OPENSSL).enableOcsp(true).build(); try { ServerBootstrap bootstrap = new ServerBootstrap().childHandler(newServerHandler(context, response)); // so on and so forth... } finally { context.release(); } }
From source file:org.ejbca.core.protocol.ocsp.ProtocolOcspHttpStandaloneTest.java
License:Open Source License
/** * Tests the ocsp.revoked.untilNextUpdate configuration. * /*from www .ja v a 2 s . com*/ * The test sets ocsp.untilNextUpdate and ocsp.revoked.untilNextUpdate to different values and then verified that the response's next update value matches * the setting of ocsp.revoked.untilNextUpdate and not ocsp.untilNextUpdate * * @throws Exception * error */ @Test public void testRevokedNextUpdate() throws Exception { ocspResponseGeneratorTestSession.reloadOcspSigningCache(); final X509Certificate ocspTestCert = getRevokedTestCert(); final String oldConfigurationValue1 = configurationSession.getConfigurationValue( "ocsp." + CertificateProfileConstants.CERTPROFILE_FIXED_OCSPSIGNER + ".untilNextUpdate"); final String oldConfigurationValue2 = configurationSession.getConfigurationValue( "ocsp." + CertificateProfileConstants.CERTPROFILE_FIXED_OCSPSIGNER + ".revoked.untilNextUpdate"); configurationSession.setConfigurationValue( "ocsp." + CertificateProfileConstants.CERTPROFILE_FIXED_OCSPSIGNER + ".untilNextUpdate", "7"); configurationSession.setConfigurationValue( "ocsp." + CertificateProfileConstants.CERTPROFILE_FIXED_OCSPSIGNER + ".revoked.untilNextUpdate", "5"); // Make sure that we run the test with a CA where this is no OcspKeyBinding OcspTestUtils.setInternalKeyBindingStatus(authenticationToken, internalKeyBindingId, InternalKeyBindingStatus.DISABLED); ocspResponseGeneratorTestSession.reloadOcspSigningCache(); try { // And an OCSP request OCSPReqBuilder gen = new OCSPReqBuilder(); gen.addRequest(new JcaCertificateID(SHA1DigestCalculator.buildSha1Instance(), getCaCert(ocspTestCert), ocspTestCert.getSerialNumber())); OCSPReq req = gen.build(); // Send the request and receive a singleResponse SingleResp[] singleResps = helper.sendOCSPPost(req.getEncoded(), null, 0, 200); assertEquals("No of SingResps should be 1.", 1, singleResps.length); SingleResp singleResp = singleResps[0]; CertificateID certId = singleResp.getCertID(); assertEquals("Serno in response does not match serno in request.", certId.getSerialNumber(), ocspTestCert.getSerialNumber()); Object status = singleResp.getCertStatus(); assertTrue("Status (" + status + ") is not RevokedStatus", status instanceof RevokedStatus); RevokedStatus rev = (RevokedStatus) status; assertTrue("Status does not have reason", rev.hasRevocationReason()); Date thisUpdate = singleResp.getThisUpdate(); Date nextUpdate = singleResp.getNextUpdate(); assertNotNull("thisUpdate was not set.", thisUpdate); assertNotNull( "nextUpdate was not set. (This test requires ocsp.revoked.untilNextUpdate to be configured.)", nextUpdate); long diff = nextUpdate.getTime() - thisUpdate.getTime(); assertEquals("The nextUpdate value was not taken from ocsp.revoked.untilNextUpdate", 5000L, diff); } finally { configurationSession.setConfigurationValue( "ocsp." + CertificateProfileConstants.CERTPROFILE_FIXED_OCSPSIGNER + ".untilNextUpdate", oldConfigurationValue1); configurationSession.setConfigurationValue( "ocsp." + CertificateProfileConstants.CERTPROFILE_FIXED_OCSPSIGNER + ".revoked.untilNextUpdate", oldConfigurationValue2); OcspTestUtils.setInternalKeyBindingStatus(authenticationToken, internalKeyBindingId, InternalKeyBindingStatus.ACTIVE); } }
From source file:org.jruby.ext.openssl.OCSPBasicResponse.java
License:Common Public License
@JRubyMethod(name = "sign", rest = true) public IRubyObject sign(final ThreadContext context, IRubyObject[] args) { Ruby runtime = context.getRuntime(); int flag = 0; IRubyObject additionalCerts = context.nil; IRubyObject flags = context.nil;//from w w w . j ava 2 s .c o m IRubyObject digest = context.nil; Digest digestInstance = new Digest(runtime, _Digest(runtime)); List<X509CertificateHolder> addlCerts = new ArrayList<X509CertificateHolder>(); switch (Arity.checkArgumentCount(runtime, args, 2, 5)) { case 3: additionalCerts = args[2]; break; case 4: additionalCerts = args[2]; flags = args[3]; break; case 5: additionalCerts = args[2]; flags = args[3]; digest = args[4]; break; default: break; } if (digest.isNil()) digest = digestInstance.initialize(context, new IRubyObject[] { RubyString.newString(runtime, "SHA1") }); if (!flags.isNil()) flag = RubyFixnum.fix2int(flags); if (additionalCerts.isNil()) flag |= RubyFixnum.fix2int((RubyFixnum) _OCSP(runtime).getConstant(OCSP_NOCERTS)); X509Cert signer = (X509Cert) args[0]; PKey signerKey = (PKey) args[1]; String keyAlg = signerKey.getAlgorithm(); String digAlg = ((Digest) digest).getShortAlgorithm(); JcaContentSignerBuilder signerBuilder = new JcaContentSignerBuilder(digAlg + "with" + keyAlg); signerBuilder.setProvider("BC"); ContentSigner contentSigner = null; try { contentSigner = signerBuilder.build(signerKey.getPrivateKey()); } catch (OperatorCreationException e) { throw newOCSPError(runtime, e); } BasicOCSPRespBuilder respBuilder = null; try { if ((flag & RubyFixnum.fix2int((RubyFixnum) _OCSP(runtime).getConstant(OCSP_RESPID_KEY))) != 0) { JcaDigestCalculatorProviderBuilder dcpb = new JcaDigestCalculatorProviderBuilder(); dcpb.setProvider("BC"); DigestCalculatorProvider dcp = dcpb.build(); DigestCalculator calculator = dcp.get(contentSigner.getAlgorithmIdentifier()); respBuilder = new BasicOCSPRespBuilder( SubjectPublicKeyInfo.getInstance(signerKey.getPublicKey().getEncoded()), calculator); } else { respBuilder = new BasicOCSPRespBuilder(new RespID(signer.getSubject().getX500Name())); } } catch (Exception e) { throw newOCSPError(runtime, e); } X509CertificateHolder[] chain = null; try { if ((flag & RubyFixnum.fix2int((RubyFixnum) _OCSP(runtime).getConstant(OCSP_NOCERTS))) == 0) { addlCerts.add(new X509CertificateHolder(signer.getAuxCert().getEncoded())); if (!additionalCerts.isNil()) { Iterator<java.security.cert.Certificate> rubyAddlCerts = ((RubyArray) additionalCerts) .iterator(); while (rubyAddlCerts.hasNext()) { java.security.cert.Certificate cert = rubyAddlCerts.next(); addlCerts.add(new X509CertificateHolder(cert.getEncoded())); } } chain = addlCerts.toArray(new X509CertificateHolder[addlCerts.size()]); } } catch (Exception e) { throw newOCSPError(runtime, e); } Date producedAt = null; if ((flag & RubyFixnum.fix2int((RubyFixnum) _OCSP(runtime).getConstant(OCSP_NOTIME))) == 0) { producedAt = new Date(); } for (OCSPSingleResponse resp : singleResponses) { SingleResp singleResp = new SingleResp(resp.getBCSingleResp()); respBuilder.addResponse(singleResp.getCertID(), singleResp.getCertStatus(), singleResp.getThisUpdate(), singleResp.getNextUpdate(), resp.getBCSingleResp().getSingleExtensions()); } try { Extension[] respExtAry = new Extension[extensions.size()]; Extensions respExtensions = new Extensions(extensions.toArray(respExtAry)); BasicOCSPResp bcBasicOCSPResp = respBuilder.setResponseExtensions(respExtensions).build(contentSigner, chain, producedAt); asn1BCBasicOCSPResp = BasicOCSPResponse.getInstance(bcBasicOCSPResp.getEncoded()); } catch (Exception e) { throw newOCSPError(runtime, e); } return this; }
From source file:org.keycloak.common.util.OCSPUtils.java
License:Apache License
private static void verifyResponse(BasicOCSPResp basicOcspResponse, X509Certificate issuerCertificate, X509Certificate responderCertificate, byte[] requestNonce, Date date) throws NoSuchProviderException, NoSuchAlgorithmException, CertificateNotYetValidException, CertificateExpiredException, CertPathValidatorException { List<X509CertificateHolder> certs = new ArrayList<>(Arrays.asList(basicOcspResponse.getCerts())); X509Certificate signingCert = null; try {/* ww w. j a v a 2s . co m*/ certs.add(new JcaX509CertificateHolder(issuerCertificate)); if (responderCertificate != null) { certs.add(new JcaX509CertificateHolder(responderCertificate)); } } catch (CertificateEncodingException e) { e.printStackTrace(); } if (certs.size() > 0) { X500Name responderName = basicOcspResponse.getResponderId().toASN1Primitive().getName(); byte[] responderKey = basicOcspResponse.getResponderId().toASN1Primitive().getKeyHash(); if (responderName != null) { logger.log(Level.INFO, "Responder Name: {0}", responderName.toString()); for (X509CertificateHolder certHolder : certs) { try { X509Certificate tempCert = new JcaX509CertificateConverter().setProvider("BC") .getCertificate(certHolder); X500Name respName = new X500Name(tempCert.getSubjectX500Principal().getName()); if (responderName.equals(respName)) { signingCert = tempCert; logger.log(Level.INFO, "Found a certificate whose principal \"{0}\" matches the responder name \"{1}\"", new Object[] { tempCert.getSubjectDN().getName(), responderName.toString() }); break; } } catch (CertificateException e) { logger.log(Level.FINE, e.getMessage()); } } } else if (responderKey != null) { SubjectKeyIdentifier responderSubjectKey = new SubjectKeyIdentifier(responderKey); logger.log(Level.INFO, "Responder Key: {0}", Arrays.toString(responderKey)); for (X509CertificateHolder certHolder : certs) { try { X509Certificate tempCert = new JcaX509CertificateConverter().setProvider("BC") .getCertificate(certHolder); SubjectKeyIdentifier subjectKeyIdentifier = null; if (certHolder.getExtensions() != null) { subjectKeyIdentifier = SubjectKeyIdentifier.fromExtensions(certHolder.getExtensions()); } if (subjectKeyIdentifier != null) { logger.log(Level.INFO, "Certificate: {0}\nSubject Key Id: {1}", new Object[] { tempCert.getSubjectDN().getName(), Arrays.toString(subjectKeyIdentifier.getKeyIdentifier()) }); } if (subjectKeyIdentifier != null && responderSubjectKey.equals(subjectKeyIdentifier)) { signingCert = tempCert; logger.log(Level.INFO, "Found a signer certificate \"{0}\" with the subject key extension value matching the responder key", signingCert.getSubjectDN().getName()); break; } subjectKeyIdentifier = new JcaX509ExtensionUtils() .createSubjectKeyIdentifier(tempCert.getPublicKey()); if (responderSubjectKey.equals(subjectKeyIdentifier)) { signingCert = tempCert; logger.log(Level.INFO, "Found a certificate \"{0}\" with the subject key matching the OCSP responder key", signingCert.getSubjectDN().getName()); break; } } catch (CertificateException e) { logger.log(Level.FINE, e.getMessage()); } } } } if (signingCert != null) { if (signingCert.equals(issuerCertificate)) { logger.log(Level.INFO, "OCSP response is signed by the target''s Issuing CA"); } else if (responderCertificate != null && signingCert.equals(responderCertificate)) { // https://www.ietf.org/rfc/rfc2560.txt // 2.6 OCSP Signature Authority Delegation // - The responder certificate is issued to the responder by CA logger.log(Level.INFO, "OCSP response is signed by an authorized responder certificate"); } else { // 4.2.2.2 Authorized Responders // 3. Includes a value of id-ad-ocspSigning in an ExtendedKeyUsage // extension and is issued by the CA that issued the certificate in // question." if (!signingCert.getIssuerX500Principal().equals(issuerCertificate.getSubjectX500Principal())) { logger.log(Level.INFO, "Signer certificate''s Issuer: {0}\nIssuer certificate''s Subject: {1}", new Object[] { signingCert.getIssuerX500Principal().getName(), issuerCertificate.getSubjectX500Principal().getName() }); throw new CertPathValidatorException( "Responder\'s certificate is not authorized to sign OCSP responses"); } try { List<String> purposes = signingCert.getExtendedKeyUsage(); if (purposes != null && !purposes.contains(KeyPurposeId.id_kp_OCSPSigning.getId())) { logger.log(Level.INFO, "OCSPSigning extended usage is not set"); throw new CertPathValidatorException( "Responder\'s certificate not valid for signing OCSP responses"); } } catch (CertificateParsingException e) { logger.log(Level.FINE, "Failed to get certificate''s extended key usage extension\n{0}", e.getMessage()); } if (date == null) { signingCert.checkValidity(); } else { signingCert.checkValidity(date); } try { Extension noOCSPCheck = new JcaX509CertificateHolder(signingCert) .getExtension(OCSPObjectIdentifiers.id_pkix_ocsp_nocheck); // TODO If the extension is present, the OCSP client can trust the // responder's certificate for the lifetime of the certificate. logger.log(Level.INFO, "OCSP no-check extension is {0} present", noOCSPCheck == null ? "not" : ""); } catch (CertificateEncodingException e) { logger.log(Level.FINE, "Certificate encoding exception: {0}", e.getMessage()); } try { signingCert.verify(issuerCertificate.getPublicKey()); logger.log(Level.INFO, "OCSP response is signed by an Authorized Responder"); } catch (GeneralSecurityException ex) { signingCert = null; } } } if (signingCert == null) { throw new CertPathValidatorException("Unable to verify OCSP Response\'s signature"); } else { if (!verifySignature(basicOcspResponse, signingCert)) { throw new CertPathValidatorException("Error verifying OCSP Response\'s signature"); } else { Extension responseNonce = basicOcspResponse.getExtension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce); if (responseNonce != null && requestNonce != null && !Arrays.equals(requestNonce, responseNonce.getExtnValue().getOctets())) { throw new CertPathValidatorException("Nonces do not match."); } else { // See Sun's OCSP implementation. // https://www.ietf.org/rfc/rfc2560.txt, if nextUpdate is not set, // the responder is indicating that newer update is avilable all the time long current = date == null ? System.currentTimeMillis() : date.getTime(); Date stop = new Date(current + (long) TIME_SKEW); Date start = new Date(current - (long) TIME_SKEW); Iterator<SingleResp> iter = Arrays.asList(basicOcspResponse.getResponses()).iterator(); SingleResp singleRes = null; do { if (!iter.hasNext()) { return; } singleRes = iter.next(); } while (!stop.before(singleRes.getThisUpdate()) && !start.after(singleRes.getNextUpdate() != null ? singleRes.getNextUpdate() : singleRes.getThisUpdate())); throw new CertPathValidatorException( "Response is unreliable: its validity interval is out-of-date"); } } } }
From source file:org.signserver.module.xades.validator.AbstractCustomCertPathChecker.java
License:Open Source License
/** * Parses received response bytes to form basic ocsp response object and verifies ocsp response * If returns , ocsp response is successfully verified, otherwise throws exception detailing problem * /*from ww w .j ava 2 s . c o m*/ * @param x509Cert - certificate originally passed to validator for validation * @param ocspresp - ocsp response received from ocsp responder * @throws OCSPException * @throws NoSuchProviderException * @throws IOException * @throws CertStoreException * @throws NoSuchAlgorithmException * @throws SignServerException * @throws CertificateParsingException * @throws CryptoTokenOfflineException * @throws IllegalRequestException */ protected void parseAndVerifyOCSPResponse(X509Certificate x509Cert, OCSPResp ocspresp, X509Certificate cACert) throws NoSuchProviderException, OCSPException, NoSuchAlgorithmException, CertStoreException, IOException, SignServerException, CertificateParsingException, IllegalRequestException, CryptoTokenOfflineException, OperatorCreationException, CertificateEncodingException { if (ocspresp.getStatus() != OCSPRespStatus.SUCCESSFUL) { throw new SignServerException( "Unexpected ocsp response status. Response Status Received : " + ocspresp.getStatus()); } // we currently support only basic ocsp response BasicOCSPResp basicOCSPResponse = (BasicOCSPResp) ocspresp.getResponseObject(); if (basicOCSPResponse == null) { throw new SignServerException( "Could not construct BasicOCSPResp object from response. Only BasicOCSPResponse as defined in RFC 2560 is supported."); } //OCSP response might be signed by CA issuing the certificate or //the Authorized OCSP responder certificate containing the id-kp-OCSPSigning extended key usage extension X509Certificate ocspRespSignerCertificate = null; //first check if CA issuing certificate signed the response //since it is expected to be the most common case if (basicOCSPResponse.isSignatureValid( new JcaContentVerifierProviderBuilder().setProvider("BC").build(cACert.getPublicKey()))) { ocspRespSignerCertificate = cACert; } //if CA did not sign the ocsp response, look for authorized ocsp responses from properties or from certificate chain received with response if (ocspRespSignerCertificate == null) { //look for existence of Authorized OCSP responder inside the cert chain in ocsp response ocspRespSignerCertificate = getAuthorizedOCSPRespondersCertificateFromOCSPResponse(basicOCSPResponse); //could not find the certificate signing the OCSP response in the ocsp response if (ocspRespSignerCertificate == null) { throw new SignServerException( "Certificate signing the ocsp response is not found in ocsp response's certificate chain received and is not signed by CA issuing certificate"); } } LOG.debug("OCSP response signed by : " + CertTools.getSubjectDN(ocspRespSignerCertificate)); // validating ocsp signers certificate // Check if responders certificate has id-pkix-ocsp-nocheck extension, in which case we do not validateUsingCRL (perform revocation check on ) ocsp certs for lifetime of certificate // using CRL RFC 2560 sect 4.2.2.2.1 // TODO : RFC States the extension value should be NULL, so maybe bare existence of the extension is not sufficient ?? if (ocspRespSignerCertificate .getExtensionValue(OCSPObjectIdentifiers.id_pkix_ocsp_nocheck.getId()) != null) { //check if lifetime of certificate is ok try { ocspRespSignerCertificate.checkValidity(); } catch (CertificateExpiredException e) { throw new SignServerException( "Certificate signing the ocsp response has expired. OCSP Responder Certificate Subject DN : " + CertTools.getSubjectDN(ocspRespSignerCertificate)); } catch (CertificateNotYetValidException e) { throw new SignServerException( "Certificate signing the ocsp response is not yet valid. OCSP Responder Certificate Subject DN : " + CertTools.getSubjectDN(ocspRespSignerCertificate)); } } else if (ocspRespSignerCertificate.equals(cACert)) { LOG.debug("Not performing revocation check on issuer certificate"); } else { // TODO: Could try to use CRL if available throw new SignServerException("Revokation check of OCSP certificate not yet supported"); } //get the response we requested for for (SingleResp singleResponse : basicOCSPResponse.getResponses()) { if (singleResponse.getCertID().getSerialNumber().equals(x509Cert.getSerialNumber())) { //found our response //check if response is OK, and if not throw OCSPStatusNotGoodException if (singleResponse.getCertStatus() != null) { throw new OCSPStatusNotGoodException( "Responce for queried certificate is not good. Certificate status returned : " + singleResponse.getCertStatus(), singleResponse.getCertStatus()); } //check the dates ThisUpdate and NextUpdate RFC 2560 sect : 4.2.2.1 if (singleResponse.getNextUpdate() != null && (new Date()).compareTo(singleResponse.getNextUpdate()) >= 0) { throw new SignServerException( "Unreliable response received. Response reported a nextupdate as : " + singleResponse.getNextUpdate().toString() + " which is earlier than current date."); } if (singleResponse.getThisUpdate() != null && (new Date()).compareTo(singleResponse.getThisUpdate()) <= 0) { throw new SignServerException( "Unreliable response received. Response reported a thisupdate as : " + singleResponse.getThisUpdate().toString() + " which is earlier than current date."); } break; } } }
From source file:org.signserver.validationservice.server.OCSPPathChecker.java
License:Open Source License
/** * Parses received response bytes to form basic ocsp response object and verifies ocsp response * If returns , ocsp response is successfully verified, otherwise throws exception detailing problem * // ww w . j a va 2 s . c o m * @param x509Cert - certificate originally passed to validator for validation * @param derocspresponse - der formatted ocsp response received from ocsp responder * @throws OCSPException * @throws NoSuchProviderException * @throws IOException * @throws CertStoreException * @throws NoSuchAlgorithmException * @throws NoSuchAlgorithmException * @throws SignServerException * @throws CertificateParsingException * @throws CryptoTokenOfflineException * @throws IllegalRequestException */ protected void parseAndVerifyOCSPResponse(X509Certificate x509Cert, byte[] derocspresponse) throws NoSuchProviderException, OCSPException, NoSuchAlgorithmException, CertStoreException, IOException, SignServerException, CertificateParsingException, IllegalRequestException, CryptoTokenOfflineException, OperatorCreationException, CertificateEncodingException { //parse received ocsp response OCSPResp ocspresp = new OCSPResp(derocspresponse); if (ocspresp.getStatus() != OCSPRespStatus.SUCCESSFUL) { throw new SignServerException( "Unexpected ocsp response status. Response Status Received : " + ocspresp.getStatus()); } // we currently support only basic ocsp response BasicOCSPResp basicOCSPResponse = (BasicOCSPResp) ocspresp.getResponseObject(); if (basicOCSPResponse == null) { throw new SignServerException( "Could not construct BasicOCSPResp object from response. Only BasicOCSPResponse as defined in RFC 2560 is supported."); } //OCSP response might be signed by CA issuing the certificate or //the Authorized OCSP responder certificate containing the id-kp-OCSPSigning extended key usage extension X509Certificate ocspRespSignerCertificate = null; //first check if CA issuing certificate signed the response //since it is expected to be the most common case if (basicOCSPResponse.isSignatureValid( new JcaContentVerifierProviderBuilder().setProvider("BC").build(cACert.getPublicKey()))) { ocspRespSignerCertificate = cACert; } //if CA did not sign the ocsp response, look for authorized ocsp responses from properties or from certificate chain received with response if (ocspRespSignerCertificate == null) { log.debug("OCSP Response is not signed by issuing CA. Looking for authorized responders"); if (basicOCSPResponse.getCerts() == null) { log.debug( "OCSP Response does not contain certificate chain, trying to verify response using one of configured authorized ocsp responders"); //certificate chain is not present in response received //try to verify using one of the configured AuthorizedOCSPResponderCerts ocspRespSignerCertificate = getAuthorizedOCSPRespondersCertificateFromProperties(basicOCSPResponse); if (ocspRespSignerCertificate == null) { throw new SignServerException( "OCSP Response does not contain certificate chain, and response is not signed by any of the configured Authorized OCSP Responders or CA issuing certificate."); } } else { //look for existence of Authorized OCSP responder inside the cert chain in ocsp response ocspRespSignerCertificate = getAuthorizedOCSPRespondersCertificateFromOCSPResponse( basicOCSPResponse); //could not find the certificate signing the OCSP response in the ocsp response if (ocspRespSignerCertificate == null) { throw new SignServerException( "Certificate signing the ocsp response is not found in ocsp response's certificate chain received and is not signed by CA issuing certificate"); } } } log.debug("OCSP response signed by : " + CertTools.getSubjectDN(ocspRespSignerCertificate)); // validating ocsp signers certificate // Check if responders certificate has id-pkix-ocsp-nocheck extension, in which case we do not validate (perform revocation check on ) ocsp certs for lifetime of certificate // using CRL RFC 2560 sect 4.2.2.2.1 // TODO : RFC States the extension value should be NULL, so maybe bare existence of the extension is not sufficient ?? if (ocspRespSignerCertificate .getExtensionValue(OCSPObjectIdentifiers.id_pkix_ocsp_nocheck.getId()) != null) { //check if lifetime of certificate is ok try { ocspRespSignerCertificate.checkValidity(); } catch (CertificateExpiredException e) { throw new SignServerException( "Certificate signing the ocsp response has expired. OCSP Responder Certificate Subject DN : " + CertTools.getSubjectDN(ocspRespSignerCertificate)); } catch (CertificateNotYetValidException e) { throw new SignServerException( "Certificate signing the ocsp response is not yet valid. OCSP Responder Certificate Subject DN : " + CertTools.getSubjectDN(ocspRespSignerCertificate)); } } else { // check if CDP exists in ocsp signers certificate // TODO : ?? add property for issuer whether to accept the OCSP response if the CDPs are not available (or use preconfigured CRLs) on signing certificate CRL RFC 2560 sect 4.2.2.2.1 if (CertTools.getCrlDistributionPoint(ocspRespSignerCertificate) == null) { throw new SignServerException( "CRL Distribution Point extension missing in ocsp signer's certificate."); } //verify certificate using CRL Validator //TODO : refactor Validators to follow factory pattern (discuss) CRLValidator crlValidator = new CRLValidator(); Validation valresult = crlValidator.validate(ocspRespSignerCertificate, this.props); if (valresult.getStatus() != Validation.Status.VALID) { throw new SignServerException( "Validation of ocsp signer's certificate failed. Status message received : " + valresult.getStatusMessage()); } } //get the response we requested for for (SingleResp singleResponse : basicOCSPResponse.getResponses()) { if (singleResponse.getCertID().getSerialNumber().equals(x509Cert.getSerialNumber())) { //found our response //check if response is OK, and if not throw OCSPStatusNotGoodException if (singleResponse.getCertStatus() != null) { throw new OCSPStatusNotGoodException( "Responce for queried certificate is not good. Certificate status returned : " + singleResponse.getCertStatus(), singleResponse.getCertStatus()); } //check the dates ThisUpdate and NextUpdate RFC 2560 sect : 4.2.2.1 if (singleResponse.getNextUpdate() != null && (new Date()).compareTo(singleResponse.getNextUpdate()) >= 0) { throw new SignServerException( "Unreliable response received. Response reported a nextupdate as : " + singleResponse.getNextUpdate().toString() + " which is earlier than current date."); } if (singleResponse.getThisUpdate() != null && (new Date()).compareTo(singleResponse.getThisUpdate()) <= 0) { throw new SignServerException( "Unreliable response received. Response reported a thisupdate as : " + singleResponse.getThisUpdate().toString() + " which is earlier than current date."); } break; } } }
From source file:org.xdi.oxauth.cert.validation.OCSPCertificateVerifier.java
License:MIT License
@Override public ValidationStatus validate(X509Certificate certificate, List<X509Certificate> issuers, Date validationDate) {/*from w ww .j av a2 s . c o m*/ X509Certificate issuer = issuers.get(0); ValidationStatus status = new ValidationStatus(certificate, issuer, validationDate, ValidatorSourceType.OCSP, CertificateValidity.UNKNOWN); try { Principal subjectX500Principal = certificate.getSubjectX500Principal(); String ocspUrl = getOCSPUrl(certificate); if (ocspUrl == null) { log.error("OCSP URL for '" + subjectX500Principal + "' is empty"); return status; } log.debug("OCSP URL for '" + subjectX500Principal + "' is '" + ocspUrl + "'"); DigestCalculator digestCalculator = new JcaDigestCalculatorProviderBuilder().build() .get(CertificateID.HASH_SHA1); CertificateID certificateId = new CertificateID(digestCalculator, new JcaX509CertificateHolder(certificate), certificate.getSerialNumber()); // Generate OCSP request OCSPReq ocspReq = generateOCSPRequest(certificateId); // Get OCSP response from server OCSPResp ocspResp = requestOCSPResponse(ocspUrl, ocspReq); if (ocspResp.getStatus() != OCSPRespBuilder.SUCCESSFUL) { log.error("OCSP response is invalid!"); status.setValidity(CertificateValidity.INVALID); return status; } boolean foundResponse = false; BasicOCSPResp basicOCSPResp = (BasicOCSPResp) ocspResp.getResponseObject(); SingleResp[] singleResps = basicOCSPResp.getResponses(); for (SingleResp singleResp : singleResps) { CertificateID responseCertificateId = singleResp.getCertID(); if (!certificateId.equals(responseCertificateId)) { continue; } foundResponse = true; log.debug("OCSP validationDate: " + validationDate); log.debug("OCSP thisUpdate: " + singleResp.getThisUpdate()); log.debug("OCSP nextUpdate: " + singleResp.getNextUpdate()); status.setRevocationObjectIssuingTime(basicOCSPResp.getProducedAt()); Object certStatus = singleResp.getCertStatus(); if (certStatus == CertificateStatus.GOOD) { log.debug("OCSP status is valid for '" + certificate.getSubjectX500Principal() + "'"); status.setValidity(CertificateValidity.VALID); } else { if (singleResp.getCertStatus() instanceof RevokedStatus) { log.warn("OCSP status is revoked for: " + subjectX500Principal); if (validationDate .before(((RevokedStatus) singleResp.getCertStatus()).getRevocationTime())) { log.warn("OCSP revocation time after the validation date, the certificate '" + subjectX500Principal + "' was valid at " + validationDate); status.setValidity(CertificateValidity.VALID); } else { Date revocationDate = ((RevokedStatus) singleResp.getCertStatus()).getRevocationTime(); log.info("OCSP for certificate '" + subjectX500Principal + "' is revoked since " + revocationDate); status.setRevocationDate(revocationDate); status.setRevocationObjectIssuingTime(singleResp.getThisUpdate()); status.setValidity(CertificateValidity.REVOKED); } } } } if (!foundResponse) { log.error("There is no matching OCSP response entries"); } } catch (Exception ex) { log.error("OCSP exception: ", ex); } return status; }