Example #1
0
// BasicOCSPResponse       ::= SEQUENCE {
//    tbsResponseData      ResponseData,
//    signatureAlgorithm   AlgorithmIdentifier,
//    signature            BIT STRING,
//    certs            [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
Result
BasicResponse(Reader& input, Context& context)
{
  Reader tbsResponseData;
  SignedDataWithSignature signedData;
  Result rv = der::SignedData(input, tbsResponseData, signedData);
  if (rv != Success) {
    if (rv == Result::ERROR_BAD_SIGNATURE) {
      return Result::ERROR_OCSP_BAD_SIGNATURE;
    }
    return rv;
  }

  // Parse certificates, if any

  NonOwningDERArray certs;
  if (!input.AtEnd()) {
    // We ignore the lengths of the wrappers because we'll detect bad lengths
    // during parsing--too short and we'll run out of input for parsing a cert,
    // and too long and we'll have leftover data that won't parse as a cert.

    // [0] wrapper
    Reader wrapped;
    rv = der::ExpectTagAndGetValue(
          input, der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 0, wrapped);
    if (rv != Success) {
      return rv;
    }
    rv = der::End(input);
    if (rv != Success) {
      return rv;
    }

    // SEQUENCE wrapper
    Reader certsSequence;
    rv = der::ExpectTagAndGetValue(wrapped, der::SEQUENCE, certsSequence);
    if (rv != Success) {
      return rv;
    }
    rv = der::End(wrapped);
    if (rv != Success) {
      return rv;
    }

    // sequence of certificates
    while (!certsSequence.AtEnd()) {
      Input cert;
      rv = der::ExpectTagAndGetTLV(certsSequence, der::SEQUENCE, cert);
      if (rv != Success) {
        return rv;
      }
      rv = certs.Append(cert);
      if (rv != Success) {
        return rv;
      }
    }
  }

  return ResponseData(tbsResponseData, context, signedData, certs);
}
Example #2
0
// BasicOCSPResponse       ::= SEQUENCE {
//    tbsResponseData      ResponseData,
//    signatureAlgorithm   AlgorithmIdentifier,
//    signature            BIT STRING,
//    certs            [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
Result
BasicResponse(Input& input, Context& context)
{
  Input tbsResponseData;
  SignedDataWithSignature signedData;
  Result rv = der::SignedData(input, tbsResponseData, signedData);
  if (rv != Success) {
    if (PR_GetError() == SEC_ERROR_BAD_SIGNATURE) {
      return Fail(RecoverableError, SEC_ERROR_OCSP_BAD_SIGNATURE);
    }
    return rv;
  }

  // Parse certificates, if any

  SECItem certs[8];
  size_t numCerts = 0;

  if (!input.AtEnd()) {
    // We ignore the lengths of the wrappers because we'll detect bad lengths
    // during parsing--too short and we'll run out of input for parsing a cert,
    // and too long and we'll have leftover data that won't parse as a cert.

    // [0] wrapper
    rv = der::ExpectTagAndSkipLength(
          input, der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 0);
    if (rv != Success) {
      return rv;
    }

    // SEQUENCE wrapper
    rv = der::ExpectTagAndSkipLength(input, der::SEQUENCE);
    if (rv != Success) {
      return rv;
    }

    // sequence of certificates
    while (!input.AtEnd()) {
      if (numCerts == PR_ARRAY_SIZE(certs)) {
        return Fail(SEC_ERROR_BAD_DER);
      }

      rv = der::ExpectTagAndGetTLV(input, der::SEQUENCE, certs[numCerts]);
      if (rv != Success) {
        return rv;
      }
      ++numCerts;
    }
  }

  return ResponseData(tbsResponseData, context, signedData, certs, numCerts);
}
Example #3
0
void Impl::ParseResponse( Response * response )
{
    // This function uses return defines for readability and maintainability.
#   define return_error(error_type, error_message)                             \
    {                                                                          \
        SetError(response, error_type, error_message);                         \
        return;                                                                \
    }

    // Always have response_data on success.
    response->response_data = ResponseData();

#   undef return_error
}
Example #4
0
// BasicOCSPResponse       ::= SEQUENCE {
//    tbsResponseData      ResponseData,
//    signatureAlgorithm   AlgorithmIdentifier,
//    signature            BIT STRING,
//    certs            [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
der::Result
BasicResponse(der::Input& input, Context& context)
{
  der::Input::Mark mark(input.GetMark());

  uint16_t length;
  if (der::ExpectTagAndGetLength(input, der::SEQUENCE, length)
        != der::Success) {
    return der::Failure;
  }

  // The signature covers the entire DER encoding of tbsResponseData, including
  // the beginning tag and length. However, when we're parsing tbsResponseData,
  // we want to strip off the tag and length because we don't need it after
  // we've confirmed it's there and figured out what length it is.

  der::Input tbsResponseData;

  if (input.Skip(length, tbsResponseData) != der::Success) {
    return der::Failure;
  }

  CERTSignedData signedData;

  input.GetSECItem(siBuffer, mark, signedData.data);

  if (der::Nested(input, der::SEQUENCE,
                  bind(der::AlgorithmIdentifier, _1,
                       ref(signedData.signatureAlgorithm))) != der::Success) {
    return der::Failure;
  }

  if (der::Skip(input, der::BIT_STRING, signedData.signature) != der::Success) {
    return der::Failure;
  }
  if (signedData.signature.len == 0) {
    return der::Fail(SEC_ERROR_OCSP_BAD_SIGNATURE);
  }
  unsigned int unusedBitsAtEnd = signedData.signature.data[0];
  // XXX: Really the constraint should be that unusedBitsAtEnd must be less
  // than 7. But, we suspect there are no valid OCSP response signatures with
  // non-zero unused bits. It seems like NSS assumes this in various places, so
  // we enforce it. If we find compatibility issues, we'll know we're wrong.
  if (unusedBitsAtEnd != 0) {
    return der::Fail(SEC_ERROR_OCSP_BAD_SIGNATURE);
  }
  ++signedData.signature.data;
  --signedData.signature.len;
  signedData.signature.len = (signedData.signature.len << 3); // Bytes to bits

  // Parse certificates, if any

  SECItem certs[8];
  size_t numCerts = 0;

  if (!input.AtEnd()) {
    // We ignore the lengths of the wrappers because we'll detect bad lengths
    // during parsing--too short and we'll run out of input for parsing a cert,
    // and too long and we'll have leftover data that won't parse as a cert.

    // [0] wrapper
    if (der::ExpectTagAndIgnoreLength(
          input, der::CONSTRUCTED | der::CONTEXT_SPECIFIC | 0)
        != der::Success) {
      return der::Failure;
    }

    // SEQUENCE wrapper
    if (der::ExpectTagAndIgnoreLength(input, der::SEQUENCE) != der::Success) {
      return der::Failure;
    }

    // sequence of certificates
    while (!input.AtEnd()) {
      if (numCerts == PR_ARRAY_SIZE(certs)) {
        return der::Fail(SEC_ERROR_BAD_DER);
      }

      // Unwrap the SEQUENCE that contains the certificate, which is itself a
      // SEQUENCE.
      der::Input::Mark mark(input.GetMark());
      if (der::Skip(input, der::SEQUENCE) != der::Success) {
        return der::Failure;
      }

      input.GetSECItem(siBuffer, mark, certs[numCerts]);
      ++numCerts;
    }
  }

  return ResponseData(tbsResponseData, context, signedData, certs, numCerts);
}