jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java
changeset 12860 9ffbd4e43413
parent 10336 0bb1999251f8
child 13402 794d9fb379d2
equal deleted inserted replaced
11673:5fe35861f07e 12860:9ffbd4e43413
     1 /*
     1 /*
     2  * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    31 import java.security.cert.CertificateParsingException;
    31 import java.security.cert.CertificateParsingException;
    32 import java.security.cert.CertPathValidatorException;
    32 import java.security.cert.CertPathValidatorException;
    33 import java.security.cert.CRLReason;
    33 import java.security.cert.CRLReason;
    34 import java.security.cert.TrustAnchor;
    34 import java.security.cert.TrustAnchor;
    35 import java.security.cert.X509Certificate;
    35 import java.security.cert.X509Certificate;
       
    36 import java.util.ArrayList;
       
    37 import java.util.Arrays;
    36 import java.util.Collections;
    38 import java.util.Collections;
    37 import java.util.Date;
    39 import java.util.Date;
    38 import java.util.HashMap;
    40 import java.util.HashMap;
    39 import java.util.List;
    41 import java.util.List;
    40 import java.util.Map;
    42 import java.util.Map;
       
    43 import javax.security.auth.x500.X500Principal;
       
    44 
    41 import sun.misc.HexDumpEncoder;
    45 import sun.misc.HexDumpEncoder;
    42 import sun.security.x509.*;
    46 import sun.security.x509.*;
    43 import sun.security.util.*;
    47 import sun.security.util.*;
    44 
    48 
    45 /**
    49 /**
   123         SIG_REQUIRED,          // Must sign the request
   127         SIG_REQUIRED,          // Must sign the request
   124         UNAUTHORIZED           // Request unauthorized
   128         UNAUTHORIZED           // Request unauthorized
   125     };
   129     };
   126     private static ResponseStatus[] rsvalues = ResponseStatus.values();
   130     private static ResponseStatus[] rsvalues = ResponseStatus.values();
   127 
   131 
   128     private static final Debug DEBUG = Debug.getInstance("certpath");
   132     private static final Debug debug = Debug.getInstance("certpath");
   129     private static final boolean dump = false;
   133     private static final boolean dump = false;
   130     private static final ObjectIdentifier OCSP_BASIC_RESPONSE_OID =
   134     private static final ObjectIdentifier OCSP_BASIC_RESPONSE_OID =
   131         ObjectIdentifier.newInternal(new int[] { 1, 3, 6, 1, 5, 5, 7, 48, 1, 1});
   135         ObjectIdentifier.newInternal(new int[] { 1, 3, 6, 1, 5, 5, 7, 48, 1, 1});
   132     private static final ObjectIdentifier OCSP_NONCE_EXTENSION_OID =
       
   133         ObjectIdentifier.newInternal(new int[] { 1, 3, 6, 1, 5, 5, 7, 48, 1, 2});
       
   134 
       
   135     private static final int CERT_STATUS_GOOD = 0;
   136     private static final int CERT_STATUS_GOOD = 0;
   136     private static final int CERT_STATUS_REVOKED = 1;
   137     private static final int CERT_STATUS_REVOKED = 1;
   137     private static final int CERT_STATUS_UNKNOWN = 2;
   138     private static final int CERT_STATUS_UNKNOWN = 2;
   138 
   139 
   139     // ResponderID CHOICE tags
   140     // ResponderID CHOICE tags
   141     private static final int KEY_TAG = 2;
   142     private static final int KEY_TAG = 2;
   142 
   143 
   143     // Object identifier for the OCSPSigning key purpose
   144     // Object identifier for the OCSPSigning key purpose
   144     private static final String KP_OCSP_SIGNING_OID = "1.3.6.1.5.5.7.3.9";
   145     private static final String KP_OCSP_SIGNING_OID = "1.3.6.1.5.5.7.3.9";
   145 
   146 
   146     private final ResponseStatus responseStatus;
       
   147     private final Map<CertId, SingleResponse> singleResponseMap;
       
   148 
       
   149     // Maximum clock skew in milliseconds (15 minutes) allowed when checking
   147     // Maximum clock skew in milliseconds (15 minutes) allowed when checking
   150     // validity of OCSP responses
   148     // validity of OCSP responses
   151     private static final long MAX_CLOCK_SKEW = 900000;
   149     private static final long MAX_CLOCK_SKEW = 900000;
   152 
   150 
   153     // an array of all of the CRLReasons (used in SingleResponse)
   151     // an array of all of the CRLReasons (used in SingleResponse)
   154     private static CRLReason[] values = CRLReason.values();
   152     private static CRLReason[] values = CRLReason.values();
   155 
   153 
       
   154     private final ResponseStatus responseStatus;
       
   155     private final Map<CertId, SingleResponse> singleResponseMap;
       
   156     private final List<X509CertImpl> certs;
       
   157     private final AlgorithmId sigAlgId;
       
   158     private final byte[] signature;
       
   159     private final byte[] tbsResponseData;
       
   160     private final X500Principal responderName;
       
   161     private final byte[] responderKey;
       
   162     private final byte[] responseNonce;
       
   163 
   156     /*
   164     /*
   157      * Create an OCSP response from its ASN.1 DER encoding.
   165      * Create an OCSP response from its ASN.1 DER encoding.
   158      */
   166      */
   159     OCSPResponse(byte[] bytes, Date dateCheckedAgainst,
   167     OCSPResponse(byte[] bytes) throws IOException {
   160         X509Certificate responderCert)
       
   161         throws IOException, CertPathValidatorException {
       
   162 
       
   163         // OCSPResponse
       
   164         if (dump) {
   168         if (dump) {
   165             HexDumpEncoder hexEnc = new HexDumpEncoder();
   169             HexDumpEncoder hexEnc = new HexDumpEncoder();
   166             System.out.println("OCSPResponse bytes are...");
   170             System.out.println("OCSPResponse bytes are...");
   167             System.out.println(hexEnc.encode(bytes));
   171             System.out.println(hexEnc.encode(bytes));
   168         }
   172         }
   179             responseStatus = rsvalues[status];
   183             responseStatus = rsvalues[status];
   180         } else {
   184         } else {
   181             // unspecified responseStatus
   185             // unspecified responseStatus
   182             throw new IOException("Unknown OCSPResponse status: " + status);
   186             throw new IOException("Unknown OCSPResponse status: " + status);
   183         }
   187         }
   184         if (DEBUG != null) {
   188         if (debug != null) {
   185             DEBUG.println("OCSP response status: " + responseStatus);
   189             debug.println("OCSP response status: " + responseStatus);
   186         }
   190         }
   187         if (responseStatus != ResponseStatus.SUCCESSFUL) {
   191         if (responseStatus != ResponseStatus.SUCCESSFUL) {
   188             // no need to continue, responseBytes are not set.
   192             // no need to continue, responseBytes are not set.
   189             singleResponseMap = Collections.emptyMap();
   193             singleResponseMap = Collections.emptyMap();
       
   194             certs = Collections.<X509CertImpl>emptyList();
       
   195             sigAlgId = null;
       
   196             signature = null;
       
   197             tbsResponseData = null;
       
   198             responderName = null;
       
   199             responderKey = null;
       
   200             responseNonce = null;
   190             return;
   201             return;
   191         }
   202         }
   192 
   203 
   193         // responseBytes
   204         // responseBytes
   194         der = derIn.getDerValue();
   205         der = derIn.getDerValue();
   204 
   215 
   205         // responseType
   216         // responseType
   206         derIn = tmp.data;
   217         derIn = tmp.data;
   207         ObjectIdentifier responseType = derIn.getOID();
   218         ObjectIdentifier responseType = derIn.getOID();
   208         if (responseType.equals((Object)OCSP_BASIC_RESPONSE_OID)) {
   219         if (responseType.equals((Object)OCSP_BASIC_RESPONSE_OID)) {
   209             if (DEBUG != null) {
   220             if (debug != null) {
   210                 DEBUG.println("OCSP response type: basic");
   221                 debug.println("OCSP response type: basic");
   211             }
   222             }
   212         } else {
   223         } else {
   213             if (DEBUG != null) {
   224             if (debug != null) {
   214                 DEBUG.println("OCSP response type: " + responseType);
   225                 debug.println("OCSP response type: " + responseType);
   215             }
   226             }
   216             throw new IOException("Unsupported OCSP response type: " +
   227             throw new IOException("Unsupported OCSP response type: " +
   217                 responseType);
   228                                   responseType);
   218         }
   229         }
   219 
   230 
   220         // BasicOCSPResponse
   231         // BasicOCSPResponse
   221         DerInputStream basicOCSPResponse =
   232         DerInputStream basicOCSPResponse =
   222             new DerInputStream(derIn.getOctetString());
   233             new DerInputStream(derIn.getOctetString());
   227         }
   238         }
   228 
   239 
   229         DerValue responseData = seqTmp[0];
   240         DerValue responseData = seqTmp[0];
   230 
   241 
   231         // Need the DER encoded ResponseData to verify the signature later
   242         // Need the DER encoded ResponseData to verify the signature later
   232         byte[] responseDataDer = seqTmp[0].toByteArray();
   243         tbsResponseData = seqTmp[0].toByteArray();
   233 
   244 
   234         // tbsResponseData
   245         // tbsResponseData
   235         if (responseData.tag != DerValue.tag_Sequence) {
   246         if (responseData.tag != DerValue.tag_Sequence) {
   236             throw new IOException("Bad encoding in tbsResponseData " +
   247             throw new IOException("Bad encoding in tbsResponseData " +
   237                 "element of OCSP response: expected ASN.1 SEQUENCE tag.");
   248                 "element of OCSP response: expected ASN.1 SEQUENCE tag.");
   255         }
   266         }
   256 
   267 
   257         // responderID
   268         // responderID
   258         short tag = (byte)(seq.tag & 0x1f);
   269         short tag = (byte)(seq.tag & 0x1f);
   259         if (tag == NAME_TAG) {
   270         if (tag == NAME_TAG) {
   260             if (DEBUG != null) {
   271             responderName =
   261                 X500Name responderName = new X500Name(seq.getData());
   272                 new X500Principal(new ByteArrayInputStream(seq.toByteArray()));
   262                 DEBUG.println("OCSP Responder name: " + responderName);
   273             if (debug != null) {
   263             }
   274                 debug.println("OCSP Responder name: " + responderName);
       
   275             }
       
   276             responderKey = null;
   264         } else if (tag == KEY_TAG) {
   277         } else if (tag == KEY_TAG) {
   265             // Ignore, for now
   278             responderKey = seq.getOctetString();
       
   279             responderName = null;
   266         } else {
   280         } else {
   267             throw new IOException("Bad encoding in responderID element of " +
   281             throw new IOException("Bad encoding in responderID element of " +
   268                 "OCSP response: expected ASN.1 context specific tag 0 or 1");
   282                 "OCSP response: expected ASN.1 context specific tag 0 or 1");
   269         }
   283         }
   270 
   284 
   271         // producedAt
   285         // producedAt
   272         seq = seqDerIn.getDerValue();
   286         seq = seqDerIn.getDerValue();
   273         if (DEBUG != null) {
   287         if (debug != null) {
   274             Date producedAtDate = seq.getGeneralizedTime();
   288             Date producedAtDate = seq.getGeneralizedTime();
   275             DEBUG.println("OCSP response produced at: " + producedAtDate);
   289             debug.println("OCSP response produced at: " + producedAtDate);
   276         }
   290         }
   277 
   291 
   278         // responses
   292         // responses
   279         DerValue[] singleResponseDer = seqDerIn.getSequence(1);
   293         DerValue[] singleResponseDer = seqDerIn.getSequence(1);
   280         singleResponseMap
   294         singleResponseMap = new HashMap<>(singleResponseDer.length);
   281             = new HashMap<CertId, SingleResponse>(singleResponseDer.length);
   295         if (debug != null) {
   282         if (DEBUG != null) {
   296             debug.println("OCSP number of SingleResponses: "
   283             DEBUG.println("OCSP number of SingleResponses: "
   297                           + singleResponseDer.length);
   284                 + singleResponseDer.length);
       
   285         }
   298         }
   286         for (int i = 0; i < singleResponseDer.length; i++) {
   299         for (int i = 0; i < singleResponseDer.length; i++) {
   287             SingleResponse singleResponse
   300             SingleResponse singleResponse =
   288                 = new SingleResponse(singleResponseDer[i]);
   301                 new SingleResponse(singleResponseDer[i]);
   289             singleResponseMap.put(singleResponse.getCertId(), singleResponse);
   302             singleResponseMap.put(singleResponse.getCertId(), singleResponse);
   290         }
   303         }
   291 
   304 
   292         // responseExtensions
   305         // responseExtensions
       
   306         byte[] nonce = null;
   293         if (seqDerIn.available() > 0) {
   307         if (seqDerIn.available() > 0) {
   294             seq = seqDerIn.getDerValue();
   308             seq = seqDerIn.getDerValue();
   295             if (seq.isContextSpecific((byte)1)) {
   309             if (seq.isContextSpecific((byte)1)) {
   296                 DerValue[] responseExtDer = seq.data.getSequence(3);
   310                 DerValue[] responseExtDer = seq.data.getSequence(3);
   297                 for (int i = 0; i < responseExtDer.length; i++) {
   311                 for (int i = 0; i < responseExtDer.length; i++) {
   298                     Extension responseExtension
   312                     Extension ext = new Extension(responseExtDer[i]);
   299                         = new Extension(responseExtDer[i]);
   313                     if (debug != null) {
   300                     if (DEBUG != null) {
   314                         debug.println("OCSP extension: " + ext);
   301                         DEBUG.println("OCSP extension: " + responseExtension);
       
   302                     }
   315                     }
   303                     if (responseExtension.getExtensionId().equals((Object)
   316                     // Only the NONCE extension is recognized
   304                         OCSP_NONCE_EXTENSION_OID)) {
   317                     if (ext.getExtensionId().equals((Object)
   305                         /*
   318                         OCSP.NONCE_EXTENSION_OID))
   306                         ocspNonce =
   319                     {
   307                             responseExtension[i].getExtensionValue();
   320                         nonce = ext.getExtensionValue();
   308                          */
   321                     } else if (ext.isCritical())  {
   309                     } else if (responseExtension.isCritical())  {
       
   310                         throw new IOException(
   322                         throw new IOException(
   311                             "Unsupported OCSP critical extension: " +
   323                             "Unsupported OCSP critical extension: " +
   312                             responseExtension.getExtensionId());
   324                             ext.getExtensionId());
   313                     }
   325                     }
   314                 }
   326                 }
   315             }
   327             }
   316         }
   328         }
       
   329         responseNonce = nonce;
   317 
   330 
   318         // signatureAlgorithmId
   331         // signatureAlgorithmId
   319         AlgorithmId sigAlgId = AlgorithmId.parse(seqTmp[1]);
   332         sigAlgId = AlgorithmId.parse(seqTmp[1]);
   320 
   333 
   321         // signature
   334         // signature
   322         byte[] signature = seqTmp[2].getBitString();
   335         signature = seqTmp[2].getBitString();
   323         X509CertImpl[] x509Certs = null;
       
   324 
   336 
   325         // if seq[3] is available , then it is a sequence of certificates
   337         // if seq[3] is available , then it is a sequence of certificates
   326         if (seqTmp.length > 3) {
   338         if (seqTmp.length > 3) {
   327             // certs are available
   339             // certs are available
   328             DerValue seqCert = seqTmp[3];
   340             DerValue seqCert = seqTmp[3];
   329             if (!seqCert.isContextSpecific((byte)0)) {
   341             if (!seqCert.isContextSpecific((byte)0)) {
   330                 throw new IOException("Bad encoding in certs element of " +
   342                 throw new IOException("Bad encoding in certs element of " +
   331                     "OCSP response: expected ASN.1 context specific tag 0.");
   343                     "OCSP response: expected ASN.1 context specific tag 0.");
   332             }
   344             }
   333             DerValue[] certs = seqCert.getData().getSequence(3);
   345             DerValue[] derCerts = seqCert.getData().getSequence(3);
   334             x509Certs = new X509CertImpl[certs.length];
   346             certs = new ArrayList<X509CertImpl>(derCerts.length);
   335             try {
   347             try {
   336                 for (int i = 0; i < certs.length; i++) {
   348                 for (int i = 0; i < derCerts.length; i++) {
   337                     x509Certs[i] = new X509CertImpl(certs[i].toByteArray());
   349                     certs.add(new X509CertImpl(derCerts[i].toByteArray()));
   338                 }
   350                 }
   339             } catch (CertificateException ce) {
   351             } catch (CertificateException ce) {
   340                 throw new IOException("Bad encoding in X509 Certificate", ce);
   352                 throw new IOException("Bad encoding in X509 Certificate", ce);
   341             }
   353             }
   342         }
   354         } else {
       
   355             certs = Collections.<X509CertImpl>emptyList();
       
   356         }
       
   357     }
       
   358 
       
   359     void verify(List<CertId> certIds, X509Certificate responderCert,
       
   360                 Date date, byte[] nonce)
       
   361         throws CertPathValidatorException
       
   362     {
       
   363         if (responseStatus != ResponseStatus.SUCCESSFUL) {
       
   364             throw new CertPathValidatorException
       
   365                 ("OCSP response error: " + responseStatus);
       
   366         }
       
   367 
       
   368         // Check that the response includes a response for all of the
       
   369         // certs that were supplied in the request
       
   370         for (CertId certId : certIds) {
       
   371             SingleResponse sr = getSingleResponse(certId);
       
   372             if (sr == null) {
       
   373                 if (debug != null) {
       
   374                     debug.println("No response found for CertId: " + certId);
       
   375                 }
       
   376                 throw new CertPathValidatorException(
       
   377                     "OCSP response does not include a response for a " +
       
   378                     "certificate supplied in the OCSP request");
       
   379             }
       
   380             if (debug != null) {
       
   381                 debug.println("Status of certificate (with serial number " +
       
   382                     certId.getSerialNumber() + ") is: " + sr.getCertStatus());
       
   383             }
       
   384         }
       
   385 
   343 
   386 
   344         // Check whether the cert returned by the responder is trusted
   387         // Check whether the cert returned by the responder is trusted
   345         if (x509Certs != null && x509Certs[0] != null) {
   388         if (!certs.isEmpty()) {
   346             X509CertImpl cert = x509Certs[0];
   389             X509CertImpl cert = certs.get(0);
   347 
   390             // First check if the cert matches the expected responder cert
   348             // First check if the cert matches the responder cert which
       
   349             // was set locally.
       
   350             if (cert.equals(responderCert)) {
   391             if (cert.equals(responderCert)) {
   351                 // cert is trusted, now verify the signed response
   392                 // cert is trusted, now verify the signed response
   352 
   393 
   353             // Next check if the cert was issued by the responder cert
   394             // Next check if the cert was issued by the responder cert
   354             // which was set locally.
   395             // which was set locally.
   355             } else if (cert.getIssuerX500Principal().equals(
   396             } else if (cert.getIssuerX500Principal().equals(
   356                 responderCert.getSubjectX500Principal())) {
   397                        responderCert.getSubjectX500Principal())) {
   357 
   398 
   358                 // Check for the OCSPSigning key purpose
   399                 // Check for the OCSPSigning key purpose
   359                 try {
   400                 try {
   360                     List<String> keyPurposes = cert.getExtendedKeyUsage();
   401                     List<String> keyPurposes = cert.getExtendedKeyUsage();
   361                     if (keyPurposes == null ||
   402                     if (keyPurposes == null ||
   378                 algChecker.init(false);
   419                 algChecker.init(false);
   379                 algChecker.check(cert, Collections.<String>emptySet());
   420                 algChecker.check(cert, Collections.<String>emptySet());
   380 
   421 
   381                 // check the validity
   422                 // check the validity
   382                 try {
   423                 try {
   383                     if (dateCheckedAgainst == null) {
   424                     if (date == null) {
   384                         cert.checkValidity();
   425                         cert.checkValidity();
   385                     } else {
   426                     } else {
   386                         cert.checkValidity(dateCheckedAgainst);
   427                         cert.checkValidity(date);
   387                     }
   428                     }
   388                 } catch (GeneralSecurityException e) {
   429                 } catch (CertificateException e) {
   389                     throw new CertPathValidatorException(
   430                     throw new CertPathValidatorException(
   390                         "Responder's certificate not within the " +
   431                         "Responder's certificate not within the " +
   391                         "validity period", e);
   432                         "validity period", e);
   392                 }
   433                 }
   393 
   434 
   399                 // extension id-pkix-ocsp-nocheck.
   440                 // extension id-pkix-ocsp-nocheck.
   400                 //
   441                 //
   401                 Extension noCheck =
   442                 Extension noCheck =
   402                     cert.getExtension(PKIXExtensions.OCSPNoCheck_Id);
   443                     cert.getExtension(PKIXExtensions.OCSPNoCheck_Id);
   403                 if (noCheck != null) {
   444                 if (noCheck != null) {
   404                     if (DEBUG != null) {
   445                     if (debug != null) {
   405                         DEBUG.println("Responder's certificate includes " +
   446                         debug.println("Responder's certificate includes " +
   406                             "the extension id-pkix-ocsp-nocheck.");
   447                             "the extension id-pkix-ocsp-nocheck.");
   407                     }
   448                     }
   408                 } else {
   449                 } else {
   409                     // we should do the revocation checking of the
   450                     // we should do the revocation checking of the
   410                     // authorized responder in a future update.
   451                     // authorized responder in a future update.
   431         if (responderCert != null) {
   472         if (responderCert != null) {
   432             // Check algorithm constraints specified in security property
   473             // Check algorithm constraints specified in security property
   433             // "jdk.certpath.disabledAlgorithms".
   474             // "jdk.certpath.disabledAlgorithms".
   434             AlgorithmChecker.check(responderCert.getPublicKey(), sigAlgId);
   475             AlgorithmChecker.check(responderCert.getPublicKey(), sigAlgId);
   435 
   476 
   436             if (!verifyResponse(responseDataDer, responderCert,
   477             if (!verifySignature(responderCert)) {
   437                 sigAlgId, signature)) {
       
   438                 throw new CertPathValidatorException(
   478                 throw new CertPathValidatorException(
   439                     "Error verifying OCSP Responder's signature");
   479                     "Error verifying OCSP Response's signature");
   440             }
   480             }
   441         } else {
   481         } else {
   442             // Need responder's cert in order to verify the signature
   482             // Need responder's cert in order to verify the signature
   443             throw new CertPathValidatorException(
   483             throw new CertPathValidatorException(
   444                 "Unable to verify OCSP Responder's signature");
   484                 "Unable to verify OCSP Response's signature");
       
   485         }
       
   486 
       
   487         // Check freshness of OCSPResponse
       
   488         if (nonce != null) {
       
   489             if (responseNonce != null && !Arrays.equals(nonce, responseNonce)) {
       
   490                 throw new CertPathValidatorException("Nonces don't match");
       
   491             }
       
   492         }
       
   493 
       
   494         long now = (date == null) ? System.currentTimeMillis() : date.getTime();
       
   495         Date nowPlusSkew = new Date(now + MAX_CLOCK_SKEW);
       
   496         Date nowMinusSkew = new Date(now - MAX_CLOCK_SKEW);
       
   497         for (SingleResponse sr : singleResponseMap.values()) {
       
   498             if (debug != null) {
       
   499                 String until = "";
       
   500                 if (sr.nextUpdate != null) {
       
   501                     until = " until " + sr.nextUpdate;
       
   502                 }
       
   503                 debug.println("Response's validity interval is from " +
       
   504                               sr.thisUpdate + until);
       
   505             }
       
   506 
       
   507             // Check that the test date is within the validity interval
       
   508             if ((sr.thisUpdate != null && nowPlusSkew.before(sr.thisUpdate)) ||
       
   509                 (sr.nextUpdate != null && nowMinusSkew.after(sr.nextUpdate)))
       
   510             {
       
   511                 throw new CertPathValidatorException(
       
   512                                       "Response is unreliable: its validity " +
       
   513                                       "interval is out-of-date");
       
   514             }
   445         }
   515         }
   446     }
   516     }
   447 
   517 
   448     /**
   518     /**
   449      * Returns the OCSP ResponseStatus.
   519      * Returns the OCSP ResponseStatus.
   454 
   524 
   455     /*
   525     /*
   456      * Verify the signature of the OCSP response.
   526      * Verify the signature of the OCSP response.
   457      * The responder's cert is implicitly trusted.
   527      * The responder's cert is implicitly trusted.
   458      */
   528      */
   459     private boolean verifyResponse(byte[] responseData, X509Certificate cert,
   529     private boolean verifySignature(X509Certificate cert)
   460         AlgorithmId sigAlgId, byte[] signBytes)
       
   461         throws CertPathValidatorException {
   530         throws CertPathValidatorException {
   462 
   531 
   463         try {
   532         try {
   464             Signature respSignature = Signature.getInstance(sigAlgId.getName());
   533             Signature respSignature = Signature.getInstance(sigAlgId.getName());
   465             respSignature.initVerify(cert);
   534             respSignature.initVerify(cert);
   466             respSignature.update(responseData);
   535             respSignature.update(tbsResponseData);
   467 
   536 
   468             if (respSignature.verify(signBytes)) {
   537             if (respSignature.verify(signature)) {
   469                 if (DEBUG != null) {
   538                 if (debug != null) {
   470                     DEBUG.println("Verified signature of OCSP Responder");
   539                     debug.println("Verified signature of OCSP Response");
   471                 }
   540                 }
   472                 return true;
   541                 return true;
   473 
   542 
   474             } else {
   543             } else {
   475                 if (DEBUG != null) {
   544                 if (debug != null) {
   476                     DEBUG.println(
   545                     debug.println(
   477                         "Error verifying signature of OCSP Responder");
   546                         "Error verifying signature of OCSP Response");
   478                 }
   547                 }
   479                 return false;
   548                 return false;
   480             }
   549             }
   481         } catch (InvalidKeyException ike) {
   550         } catch (InvalidKeyException | NoSuchAlgorithmException |
   482             throw new CertPathValidatorException(ike);
   551                  SignatureException e)
   483         } catch (NoSuchAlgorithmException nsae) {
   552         {
   484             throw new CertPathValidatorException(nsae);
   553             throw new CertPathValidatorException(e);
   485         } catch (SignatureException se) {
       
   486             throw new CertPathValidatorException(se);
       
   487         }
   554         }
   488     }
   555     }
   489 
   556 
   490     /**
   557     /**
   491      * Returns the SingleResponse of the specified CertId, or null if
   558      * Returns the SingleResponse of the specified CertId, or null if
   535                     }
   602                     }
   536                 } else {
   603                 } else {
   537                     revocationReason = CRLReason.UNSPECIFIED;
   604                     revocationReason = CRLReason.UNSPECIFIED;
   538                 }
   605                 }
   539                 // RevokedInfo
   606                 // RevokedInfo
   540                 if (DEBUG != null) {
   607                 if (debug != null) {
   541                     DEBUG.println("Revocation time: " + revocationTime);
   608                     debug.println("Revocation time: " + revocationTime);
   542                     DEBUG.println("Revocation reason: " + revocationReason);
   609                     debug.println("Revocation reason: " + revocationReason);
   543                 }
   610                 }
   544             } else {
   611             } else {
   545                 revocationTime = null;
   612                 revocationTime = null;
   546                 revocationReason = CRLReason.UNSPECIFIED;
   613                 revocationReason = CRLReason.UNSPECIFIED;
   547                 if (tag == CERT_STATUS_GOOD) {
   614                 if (tag == CERT_STATUS_GOOD) {
   583                     singleExtensions =
   650                     singleExtensions =
   584                         new HashMap<String, java.security.cert.Extension>
   651                         new HashMap<String, java.security.cert.Extension>
   585                             (singleExtDer.length);
   652                             (singleExtDer.length);
   586                     for (int i = 0; i < singleExtDer.length; i++) {
   653                     for (int i = 0; i < singleExtDer.length; i++) {
   587                         Extension ext = new Extension(singleExtDer[i]);
   654                         Extension ext = new Extension(singleExtDer[i]);
   588                         if (DEBUG != null) {
   655                         if (debug != null) {
   589                             DEBUG.println("OCSP single extension: " + ext);
   656                             debug.println("OCSP single extension: " + ext);
   590                         }
   657                         }
   591                         // We don't support any extensions yet. Therefore, if it
   658                         // We don't support any extensions yet. Therefore, if it
   592                         // is critical we must throw an exception because we
   659                         // is critical we must throw an exception because we
   593                         // don't know how to process it.
   660                         // don't know how to process it.
   594                         if (ext.isCritical()) {
   661                         if (ext.isCritical()) {
   602                     singleExtensions = Collections.emptyMap();
   669                     singleExtensions = Collections.emptyMap();
   603                 }
   670                 }
   604             } else {
   671             } else {
   605                 singleExtensions = Collections.emptyMap();
   672                 singleExtensions = Collections.emptyMap();
   606             }
   673             }
   607 
       
   608             long now = System.currentTimeMillis();
       
   609             Date nowPlusSkew = new Date(now + MAX_CLOCK_SKEW);
       
   610             Date nowMinusSkew = new Date(now - MAX_CLOCK_SKEW);
       
   611             if (DEBUG != null) {
       
   612                 String until = "";
       
   613                 if (nextUpdate != null) {
       
   614                     until = " until " + nextUpdate;
       
   615                 }
       
   616                 DEBUG.println("Response's validity interval is from " +
       
   617                     thisUpdate + until);
       
   618             }
       
   619             // Check that the test date is within the validity interval
       
   620             if ((thisUpdate != null && nowPlusSkew.before(thisUpdate)) ||
       
   621                 (nextUpdate != null && nowMinusSkew.after(nextUpdate))) {
       
   622 
       
   623                 if (DEBUG != null) {
       
   624                     DEBUG.println("Response is unreliable: its validity " +
       
   625                         "interval is out-of-date");
       
   626                 }
       
   627                 throw new IOException("Response is unreliable: its validity " +
       
   628                     "interval is out-of-date");
       
   629             }
       
   630         }
   674         }
   631 
   675 
   632         /*
   676         /*
   633          * Return the certificate's revocation status code
   677          * Return the certificate's revocation status code
   634          */
   678          */