/*
   * Create an OCSP response from its ASN.1 DER encoding.
   */
  OCSPResponse(byte[] bytes) throws IOException {
    if (dump) {
      HexDumpEncoder hexEnc = new HexDumpEncoder();
      System.out.println("OCSPResponse bytes are...");
      System.out.println(hexEnc.encode(bytes));
    }
    DerValue der = new DerValue(bytes);
    if (der.tag != DerValue.tag_Sequence) {
      throw new IOException("Bad encoding in OCSP response: " + "expected ASN.1 SEQUENCE tag.");
    }
    DerInputStream derIn = der.getData();

    // responseStatus
    int status = derIn.getEnumerated();
    if (status >= 0 && status < rsvalues.length) {
      responseStatus = rsvalues[status];
    } else {
      // unspecified responseStatus
      throw new IOException("Unknown OCSPResponse status: " + status);
    }
    if (debug != null) {
      debug.println("OCSP response status: " + responseStatus);
    }
    if (responseStatus != ResponseStatus.SUCCESSFUL) {
      // no need to continue, responseBytes are not set.
      singleResponseMap = Collections.emptyMap();
      certs = Collections.<X509CertImpl>emptyList();
      sigAlgId = null;
      signature = null;
      tbsResponseData = null;
      responseNonce = null;
      return;
    }

    // responseBytes
    der = derIn.getDerValue();
    if (!der.isContextSpecific((byte) 0)) {
      throw new IOException(
          "Bad encoding in responseBytes element "
              + "of OCSP response: expected ASN.1 context specific tag 0.");
    }
    DerValue tmp = der.data.getDerValue();
    if (tmp.tag != DerValue.tag_Sequence) {
      throw new IOException(
          "Bad encoding in responseBytes element "
              + "of OCSP response: expected ASN.1 SEQUENCE tag.");
    }

    // responseType
    derIn = tmp.data;
    ObjectIdentifier responseType = derIn.getOID();
    if (responseType.equals((Object) OCSP_BASIC_RESPONSE_OID)) {
      if (debug != null) {
        debug.println("OCSP response type: basic");
      }
    } else {
      if (debug != null) {
        debug.println("OCSP response type: " + responseType);
      }
      throw new IOException("Unsupported OCSP response type: " + responseType);
    }

    // BasicOCSPResponse
    DerInputStream basicOCSPResponse = new DerInputStream(derIn.getOctetString());

    DerValue[] seqTmp = basicOCSPResponse.getSequence(2);
    if (seqTmp.length < 3) {
      throw new IOException("Unexpected BasicOCSPResponse value");
    }

    DerValue responseData = seqTmp[0];

    // Need the DER encoded ResponseData to verify the signature later
    tbsResponseData = seqTmp[0].toByteArray();

    // tbsResponseData
    if (responseData.tag != DerValue.tag_Sequence) {
      throw new IOException(
          "Bad encoding in tbsResponseData "
              + "element of OCSP response: expected ASN.1 SEQUENCE tag.");
    }
    DerInputStream seqDerIn = responseData.data;
    DerValue seq = seqDerIn.getDerValue();

    // version
    if (seq.isContextSpecific((byte) 0)) {
      // seq[0] is version
      if (seq.isConstructed() && seq.isContextSpecific()) {
        // System.out.println ("version is available");
        seq = seq.data.getDerValue();
        int version = seq.getInteger();
        if (seq.data.available() != 0) {
          throw new IOException(
              "Bad encoding in version " + " element of OCSP response: bad format");
        }
        seq = seqDerIn.getDerValue();
      }
    }

    // responderID
    short tag = (byte) (seq.tag & 0x1f);
    if (tag == NAME_TAG) {
      if (debug != null) {
        X500Principal responderName = new X500Principal(seq.getData().toByteArray());
        debug.println("OCSP Responder name: " + responderName);
      }
    } else if (tag == KEY_TAG) {
      if (debug != null) {
        byte[] responderKey = seq.getData().getOctetString();
        debug.println("OCSP Responder key: " + Debug.toString(responderKey));
      }
    } else {
      throw new IOException(
          "Bad encoding in responderID element of "
              + "OCSP response: expected ASN.1 context specific tag 0 or 1");
    }

    // producedAt
    seq = seqDerIn.getDerValue();
    if (debug != null) {
      Date producedAtDate = seq.getGeneralizedTime();
      debug.println("OCSP response produced at: " + producedAtDate);
    }

    // responses
    DerValue[] singleResponseDer = seqDerIn.getSequence(1);
    singleResponseMap = new HashMap<>(singleResponseDer.length);
    if (debug != null) {
      debug.println("OCSP number of SingleResponses: " + singleResponseDer.length);
    }
    for (int i = 0; i < singleResponseDer.length; i++) {
      SingleResponse singleResponse = new SingleResponse(singleResponseDer[i]);
      singleResponseMap.put(singleResponse.getCertId(), singleResponse);
    }

    // responseExtensions
    byte[] nonce = null;
    if (seqDerIn.available() > 0) {
      seq = seqDerIn.getDerValue();
      if (seq.isContextSpecific((byte) 1)) {
        DerValue[] responseExtDer = seq.data.getSequence(3);
        for (int i = 0; i < responseExtDer.length; i++) {
          Extension ext = new Extension(responseExtDer[i]);
          if (debug != null) {
            debug.println("OCSP extension: " + ext);
          }
          // Only the NONCE extension is recognized
          if (ext.getExtensionId().equals((Object) OCSP.NONCE_EXTENSION_OID)) {
            nonce = ext.getExtensionValue();
          } else if (ext.isCritical()) {
            throw new IOException("Unsupported OCSP critical extension: " + ext.getExtensionId());
          }
        }
      }
    }
    responseNonce = nonce;

    // signatureAlgorithmId
    sigAlgId = AlgorithmId.parse(seqTmp[1]);

    // signature
    signature = seqTmp[2].getBitString();

    // if seq[3] is available , then it is a sequence of certificates
    if (seqTmp.length > 3) {
      // certs are available
      DerValue seqCert = seqTmp[3];
      if (!seqCert.isContextSpecific((byte) 0)) {
        throw new IOException(
            "Bad encoding in certs element of "
                + "OCSP response: expected ASN.1 context specific tag 0.");
      }
      DerValue[] derCerts = seqCert.getData().getSequence(3);
      certs = new ArrayList<X509CertImpl>(derCerts.length);
      try {
        for (int i = 0; i < derCerts.length; i++) {
          certs.add(new X509CertImpl(derCerts[i].toByteArray()));
        }
      } catch (CertificateException ce) {
        throw new IOException("Bad encoding in X509 Certificate", ce);
      }
    } else {
      certs = Collections.<X509CertImpl>emptyList();
    }
  }
Example #2
0
  private void parse(DerValue val) throws CRLException, IOException {

    if (readOnly) {
      throw new CRLException("cannot over-write existing CRL");
    }

    if (val.getData() == null || val.tag != DerValue.tag_Sequence) {
      throw new CRLException("Invalid DER-encoded CRL data");
    }

    signedCRL = val.toByteArray();
    DerValue seq[] = new DerValue[3];

    seq[0] = val.data.getDerValue();
    seq[1] = val.data.getDerValue();
    seq[2] = val.data.getDerValue();

    if (val.data.available() != 0) {
      throw new CRLException("signed overrun, bytes = " + val.data.available());
    }

    if (seq[0].tag != DerValue.tag_Sequence) {
      throw new CRLException("signed CRL fields invalid");
    }

    sigAlgId = AlgorithmId.parse(seq[1]);
    signature = seq[2].getBitString();

    if (seq[1].data.available() != 0) {
      throw new CRLException("AlgorithmId field overrun");
    }

    if (seq[2].data.available() != 0) {
      throw new CRLException("Signature field overrun");
    }

    tbsCertList = seq[0].toByteArray();

    DerInputStream derStrm = seq[0].data;
    DerValue tmp;
    byte nextByte;

    version = 0;

    nextByte = (byte) derStrm.peekByte();
    if (nextByte == DerValue.tag_Integer) {
      version = derStrm.getInteger();
      if (version != 1) {

        throw new CRLException("Invalid version");
      }
    }
    tmp = derStrm.getDerValue();

    AlgorithmId tmpId = AlgorithmId.parse(tmp);

    if (!tmpId.equals(sigAlgId)) {
      throw new CRLException("Signature algorithm mismatch");
    }
    infoSigAlgId = tmpId;

    issuer = new X500Name(derStrm);
    if (issuer.isEmpty()) {
      throw new CRLException("Empty issuer DN not allowed in X509CRLs");
    }

    nextByte = (byte) derStrm.peekByte();
    if (nextByte == DerValue.tag_UtcTime) {
      thisUpdate = derStrm.getUTCTime();
    } else if (nextByte == DerValue.tag_GeneralizedTime) {
      thisUpdate = derStrm.getGeneralizedTime();
    } else {
      throw new CRLException("Invalid encoding for thisUpdate" + " (tag=" + nextByte + ")");
    }

    if (derStrm.available() == 0) {
      return;
    }

    nextByte = (byte) derStrm.peekByte();
    if (nextByte == DerValue.tag_UtcTime) {
      nextUpdate = derStrm.getUTCTime();
    } else if (nextByte == DerValue.tag_GeneralizedTime) {
      nextUpdate = derStrm.getGeneralizedTime();
    }

    if (derStrm.available() == 0) {
      return;
    }

    nextByte = (byte) derStrm.peekByte();
    if ((nextByte == DerValue.tag_SequenceOf) && (!((nextByte & 0x0c0) == 0x080))) {
      DerValue[] badCerts = derStrm.getSequence(4);

      X500Principal crlIssuer = getIssuerX500Principal();
      X500Principal badCertIssuer = crlIssuer;
      for (int i = 0; i < badCerts.length; i++) {
        X509CRLEntryImpl entry = new X509CRLEntryImpl(badCerts[i]);
        badCertIssuer = getCertIssuer(entry, badCertIssuer);
        entry.setCertificateIssuer(crlIssuer, badCertIssuer);
        X509IssuerSerial issuerSerial =
            new X509IssuerSerial(badCertIssuer, entry.getSerialNumber());
        revokedMap.put(issuerSerial, entry);
        revokedList.add(entry);
      }
    }

    if (derStrm.available() == 0) {
      return;
    }

    tmp = derStrm.getDerValue();
    if (tmp.isConstructed() && tmp.isContextSpecific((byte) 0)) {
      extensions = new CRLExtensions(tmp.data);
    }
    readOnly = true;
  }