/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* This class is used to process an OCSP response.
* The OCSP Response is defined
* in RFC 2560 and the ASN.1 encoding is as follows:
* <pre>
*
* OCSPResponse ::= SEQUENCE {
* responseStatus OCSPResponseStatus,
* responseBytes [0] EXPLICIT ResponseBytes OPTIONAL }
*
* OCSPResponseStatus ::= ENUMERATED {
* successful (0), --Response has valid confirmations
* malformedRequest (1), --Illegal confirmation request
* internalError (2), --Internal error in issuer
* tryLater (3), --Try again later
* --(4) is not used
* sigRequired (5), --Must sign the request
* unauthorized (6) --Request unauthorized
* }
*
* ResponseBytes ::= SEQUENCE {
* responseType OBJECT IDENTIFIER,
* response OCTET STRING }
*
* BasicOCSPResponse ::= SEQUENCE {
* tbsResponseData ResponseData,
* signatureAlgorithm AlgorithmIdentifier,
* signature BIT STRING,
* certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
*
* The value for signature SHALL be computed on the hash of the DER
* encoding ResponseData.
*
* ResponseData ::= SEQUENCE {
* version [0] EXPLICIT Version DEFAULT v1,
* responderID ResponderID,
* producedAt GeneralizedTime,
* responses SEQUENCE OF SingleResponse,
* responseExtensions [1] EXPLICIT Extensions OPTIONAL }
*
* ResponderID ::= CHOICE {
* byName [1] Name,
* byKey [2] KeyHash }
*
* KeyHash ::= OCTET STRING -- SHA-1 hash of responder's public key
* (excluding the tag and length fields)
*
* SingleResponse ::= SEQUENCE {
* certID CertID,
* certStatus CertStatus,
* thisUpdate GeneralizedTime,
* nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL,
* singleExtensions [1] EXPLICIT Extensions OPTIONAL }
*
* CertStatus ::= CHOICE {
* good [0] IMPLICIT NULL,
* revoked [1] IMPLICIT RevokedInfo,
* unknown [2] IMPLICIT UnknownInfo }
*
* RevokedInfo ::= SEQUENCE {
* revocationTime GeneralizedTime,
* revocationReason [0] EXPLICIT CRLReason OPTIONAL }
*
* UnknownInfo ::= NULL -- this can be replaced with an enumeration
*
* </pre>
*
* @author Ram Marti
*/
public final class OCSPResponse {
public enum ResponseStatus {
};
// ResponderID CHOICE tags
// Object identifier for the OCSPSigning key purpose
// Default maximum clock skew in milliseconds (15 minutes)
// allowed when checking validity of OCSP responses
/**
* Integer value indicating the maximum allowable clock skew, in seconds,
* to be used for the OCSP check.
*/
/**
* Initialize the maximum allowable clock skew by getting the OCSP
* clock skew system property. If the property has not been set, or if its
* value is negative, set the skew to the default.
*/
private static int initializeClockSkew() {
new GetIntegerAction("com.sun.security.ocsp.clockSkew"));
return DEFAULT_MAX_CLOCK_SKEW;
}
// Convert to milliseconds, as the system property will be
// specified in seconds
return tmp * 1000;
}
// an array of all of the CRLReasons (used in SingleResponse)
/*
* Create an OCSP response from its ASN.1 DER encoding.
*/
throws IOException, CertPathValidatorException {
// OCSPResponse
if (dump) {
}
throw new IOException("Bad encoding in OCSP response: " +
"expected ASN.1 SEQUENCE tag.");
}
// responseStatus
} else {
// unspecified responseStatus
}
}
// no need to continue, responseBytes are not set.
return;
}
// responseBytes
throw new IOException("Bad encoding in responseBytes element " +
"of OCSP response: expected ASN.1 context specific tag 0.");
}
throw new IOException("Bad encoding in responseBytes element " +
"of OCSP response: expected ASN.1 SEQUENCE tag.");
}
// responseType
}
} else {
}
throw new IOException("Unsupported OCSP response type: " +
}
// BasicOCSPResponse
throw new IOException("Unexpected BasicOCSPResponse value");
}
// Need the DER encoded ResponseData to verify the signature later
// tbsResponseData
throw new IOException("Bad encoding in tbsResponseData " +
"element of OCSP response: expected ASN.1 SEQUENCE tag.");
}
// version
// seq[0] is version
//System.out.println ("version is available");
throw new IOException("Bad encoding in version " +
" element of OCSP response: bad format");
}
}
}
// responderID
}
}
} else {
throw new IOException("Bad encoding in responderID element of " +
"OCSP response: expected ASN.1 context specific tag 1 or 2");
}
// producedAt
}
// responses
}
}
// responseExtensions
= new Extension(responseExtDer[i]);
}
/*
ocspNonce =
responseExtension[i].getExtensionValue();
*/
} else if (responseExtension.isCritical()) {
throw new IOException(
"Unsupported OCSP critical extension: " +
}
}
}
}
// signatureAlgorithmId
// signature
// if seq[3] is available , then it is a sequence of certificates
// certs are available
throw new IOException("Bad encoding in certs element of " +
"OCSP response: expected ASN.1 context specific tag 0.");
}
try {
}
} catch (CertificateException ce) {
}
}
// By default, the OCSP responder's cert is the same as the issuer of
// the cert being validated. The issuer cert is the first in the list.
// Check whether the signer cert returned by the responder is trusted
if (signerKeyId != null) {
}
}
byte[] certIssuerKeyId = null;
// First check if signer cert matches a trusted responder cert
// signer cert is trusted, now verify the signed response
"responder");
}
break;
// Next check if signer cert was issued by a trusted responder
// cert
// Retrieve the issuer's key identifier
if (certIssuerKeyId == null) {
if (certIssuerKeyId == null) {
+ "in the signer certificate");
}
}
}
// Check that the key identifiers match, if both are present
byte[] responderKeyId = null;
if (certIssuerKeyId != null &&
continue; // try next cert
}
}
}
// Check for the OCSPSigning key purpose
try {
if (keyPurposes == null ||
continue; // try next cert
}
} catch (CertificateParsingException cpe) {
continue; // try next cert
}
// Check algorithm constraints specified in security
// property "jdk.certpath.disabledAlgorithms".
algChecker.init(false);
// Check the date validity
try {
if (dateCheckedAgainst == null) {
} else {
}
} catch (GeneralSecurityException e) {
" the validity period " + e);
}
continue; // try next cert
}
// Check for revocation
//
// A CA may specify that an OCSP client can trust a
// responder for the lifetime of the responder's
// certificate. The CA does so by including the
// extension id-pkix-ocsp-nocheck.
//
"the extension id-pkix-ocsp-nocheck.");
}
} else {
// we should do the revocation checking of the
// authorized responder in a future update.
}
// Verify the signature
try {
// cert is trusted, now verify the signed response
"a trusted responder");
}
break;
} catch (GeneralSecurityException e) {
}
}
}
}
// Confirm that the signed response was generated using the public
// key from the trusted responder cert
if (trustedResponderCert != null) {
// Check algorithm constraints specified in security property
// "jdk.certpath.disabledAlgorithms".
sigAlgId);
throw new CertPathValidatorException(
"Error verifying OCSP Responder's signature");
}
} else {
// Need responder's cert in order to verify the signature
throw new CertPathValidatorException(
"Responder's certificate is not trusted for signing " +
"OCSP responses");
}
}
/**
* Returns the OCSP ResponseStatus.
*/
return responseStatus;
}
/*
* Verify the signature of the OCSP response.
* The responder's cert is implicitly trusted.
*/
throws CertPathValidatorException {
try {
}
return true;
} else {
"Error verifying signature of OCSP Responder");
}
return false;
}
} catch (InvalidKeyException ike) {
throw new CertPathValidatorException(ike);
} catch (NoSuchAlgorithmException nsae) {
throw new CertPathValidatorException(nsae);
} catch (SignatureException se) {
throw new CertPathValidatorException(se);
}
}
/**
* Returns the SingleResponse of the specified CertId, or null if
* there is no response for that CertId.
*/
}
/*
* A class representing a single OCSP response.
*/
}
throws IOException {
throw new IOException("Bad ASN.1 encoding in SingleResponse");
}
if (tag == CERT_STATUS_REVOKED) {
if (tag == 0) {
// if reason out-of-range just leave as UNSPECIFIED
} else {
}
} else {
}
} else {
}
// RevokedInfo
}
} else {
if (tag == CERT_STATUS_GOOD) {
} else if (tag == CERT_STATUS_UNKNOWN) {
} else {
throw new IOException("Invalid certificate status");
}
}
// we are done
nextUpdate = null;
} else {
if (tag == 0) {
// next update
// we are done
} else {
}
} else {
nextUpdate = null;
}
}
// singleExtensions
}
// We don't support any extensions yet. Therefore, if it
// is critical we must throw an exception because we
// don't know how to process it.
if (ext.isCritical()) {
throw new IOException(
"Unsupported OCSP critical extension: " +
ext.getExtensionId());
}
}
} else {
}
} else {
}
if (nextUpdate != null) {
}
thisUpdate + until);
}
// Check that the test date is within the validity interval
"interval is out-of-date");
}
throw new IOException("Response is unreliable: its validity " +
"interval is out-of-date");
}
}
/*
* Return the certificate's revocation status code
*/
return certStatus;
}
return certId;
}
}
return revocationReason;
}
}
/**
* Construct a string representation of a single OCSP response.
*/
}
if (nextUpdate != null) {
}
}
}
}