Index: net/cert/ocsp_parser.cc |
diff --git a/net/cert/ocsp_parser.cc b/net/cert/ocsp_parser.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..8672dbff9157436b8ddf902e28596366d57a1499 |
--- /dev/null |
+++ b/net/cert/ocsp_parser.cc |
@@ -0,0 +1,255 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "net/cert/ocsp_parser.h" |
+ |
+namespace net { |
+ |
+namespace ct { |
+ |
+namespace { |
+ |
+bool ParseOCSPSingleResponse(der::Parser* parser, OCSPSingleResponse* data) { |
+ der::Input cert_id; |
+ if (!parser->ReadTag(der::kSequence, &cert_id)) |
+ return false; |
+ data->cert_id = cert_id.AsString(); |
+ der::Tag status_tag; |
+ der::Input status; |
+ if (!parser->ReadTagAndValue(&status_tag, &status)) |
+ return false; |
+ if (status_tag == der::ContextSpecificPrimitive(0)) { |
+ data->cert_status = OCSP_CERT_GOOD; |
+ } else if (status_tag == der::ContextSpecificPrimitive(1)) { |
+ data->cert_status = OCSP_CERT_REVOKED; |
+ der::Parser revoked_info_parser(status); |
+ der::Input revocation_time; |
+ der::Input revocation_reason; |
+ if (!revoked_info_parser.ReadTag(der::kGeneralizedTime, &revocation_time)) |
+ return false; |
+ if (!der::ParseGeneralizedTime(revocation_time, &(data->revocation_time))) |
+ return false; |
+ if (!revoked_info_parser.ReadTag(der::kEnumerated, &revocation_reason)) |
+ return false; |
+ uint8_t revocation_reason_value; |
+ if (!der::ParseUint8(revocation_reason, &revocation_reason_value)) |
+ return false; |
+ data->revocation_reason = |
+ static_cast<OCSPRevocationReason>(revocation_reason_value); |
+ } else if (status_tag == der::ContextSpecificPrimitive(2)) { |
+ data->cert_status = OCSP_CERT_UNKNOWN; |
+ } |
Ryan Sleevi
2015/12/30 18:55:18
BUG: Fail to handle other status tags.
svaldez
2015/12/30 19:31:37
Done.
|
+ |
+ der::Input this_update; |
+ if (!parser->ReadTag(der::kGeneralizedTime, &this_update)) |
+ return false; |
+ if (!der::ParseGeneralizedTime(this_update, &(data->this_update))) |
+ return false; |
+ der::Input next_update_input; |
+ bool next_update_present; |
+ if (!parser->ReadOptionalTag(der::ContextSpecificConstructed(0), |
+ &next_update_input, &next_update_present)) { |
+ return false; |
+ } |
+ |
+ if (next_update_present) { |
+ der::Parser next_update_parser(next_update_input); |
+ der::Input next_update; |
+ if (!next_update_parser.ReadTag(der::kGeneralizedTime, &next_update)) |
+ return false; |
+ if (!der::ParseGeneralizedTime(next_update, &(data->next_update))) |
+ return false; |
+ } |
+ der::Input extensions_input; |
+ bool extensions_present; |
+ if (!parser->ReadOptionalTag(der::ContextSpecificConstructed(1), |
+ &extensions_input, &extensions_present)) { |
+ return false; |
+ } |
+ |
+ if (!extensions_present) |
+ return true; |
+ der::Parser extensions_input_parser(extensions_input); |
+ der::Parser extensions_parser; |
+ if (!extensions_input_parser.ReadSequence(&extensions_parser)) |
+ return false; |
+ while (extensions_parser.HasMore()) { |
+ ParsedExtension extension; |
+ der::Input extension_tlv; |
+ if (!extensions_parser.ReadRawTLV(&extension_tlv)) |
+ return false; |
+ if (!ParseExtension(extension_tlv, &extension)) |
+ return false; |
+ data->extensions.push_back(extension); |
+ } |
+ return true; |
+} |
+ |
+bool ParseOCSPResponseData(der::Parser* parser, OCSPResponseData* data) { |
+ der::Input version_input; |
+ bool version_present; |
+ if (!parser->ReadOptionalTag(der::ContextSpecificConstructed(0), |
+ &version_input, &version_present)) { |
+ return false; |
+ } |
+ if (version_present) { |
Ryan Sleevi
2015/12/30 18:55:18
newline
svaldez
2015/12/30 19:31:37
Done.
|
+ der::Parser version_parser(version_input); |
+ der::Input version; |
+ if (!version_parser.ReadTag(der::kInteger, &version)) |
+ return false; |
+ if (!der::ParseUint8(version, &(data->version))) |
+ return false; |
+ } else { |
+ data->version = 0; |
+ } |
+ |
+ der::Tag id_tag; |
+ der::Input responder_id; |
+ if (!parser->ReadTagAndValue(&id_tag, &responder_id)) |
+ return false; |
+ if (id_tag == der::ContextSpecificConstructed(1)) { |
+ data->responder_id_name = responder_id.AsString(); |
+ } else if (id_tag == der::ContextSpecificConstructed(2)) { |
+ der::Parser key_parser(responder_id); |
+ der::Input responder_key; |
+ if (!key_parser.ReadTag(der::kOctetString, &responder_key)) |
+ return false; |
+ data->responder_id_key = responder_key.AsString(); |
+ } else { |
+ return false; |
+ } |
+ |
+ der::Input produced_at; |
+ if (!parser->ReadTag(der::kGeneralizedTime, &produced_at)) |
+ return false; |
+ if (!der::ParseGeneralizedTime(produced_at, &(data->produced_at))) |
+ return false; |
+ |
+ der::Parser responses_parser; |
+ if (!parser->ReadSequence(&responses_parser)) |
+ return false; |
+ while (responses_parser.HasMore()) { |
+ OCSPSingleResponse single_response; |
+ der::Parser response_parser; |
+ if (!responses_parser.ReadSequence(&response_parser)) |
+ return false; |
+ if (!ParseOCSPSingleResponse(&response_parser, &single_response)) |
+ return false; |
+ data->responses.push_back(single_response); |
+ } |
+ |
+ der::Input extensions_input; |
+ bool extensions_present; |
+ if (!parser->ReadOptionalTag(der::ContextSpecificConstructed(1), |
+ &extensions_input, &extensions_present)) { |
+ return false; |
+ } |
+ |
+ if (!extensions_present) |
+ return true; |
+ der::Parser extensions_input_parser(extensions_input); |
+ der::Parser extensions_parser; |
+ if (!extensions_input_parser.ReadSequence(&extensions_parser)) |
+ return false; |
+ while (extensions_parser.HasMore()) { |
+ ParsedExtension extension; |
+ der::Input extension_tlv; |
+ if (!extensions_parser.ReadRawTLV(&extension_tlv)) |
+ return false; |
+ if (!ParseExtension(extension_tlv, &extension)) |
+ return false; |
+ data->extensions.push_back(extension); |
+ } |
+ return true; |
+} |
+ |
+} // namespace |
+ |
+OCSPSingleResponse::OCSPSingleResponse() {} |
+OCSPSingleResponse::~OCSPSingleResponse() {} |
+ |
+OCSPResponseData::OCSPResponseData() {} |
+OCSPResponseData::~OCSPResponseData() {} |
+ |
+OCSPResponse::OCSPResponse() {} |
+OCSPResponse::~OCSPResponse() {} |
+ |
+bool ParseOCSPResponse(const std::string& ocsp_response, |
+ OCSPResponse* response) { |
+ der::Parser parser( |
+ der::Input(reinterpret_cast<const uint8_t*>(ocsp_response.data()), |
+ ocsp_response.size())); |
+ der::Input response_status; |
+ der::Parser ocsp_response_parser; |
+ if (!parser.ReadSequence(&ocsp_response_parser)) |
+ return false; |
+ if (!ocsp_response_parser.ReadTag(der::kEnumerated, &response_status)) |
+ return false; |
+ uint8_t response_status_value; |
+ if (!der::ParseUint8(response_status, &response_status_value)) |
+ return false; |
+ response->status = static_cast<OCSPResponseStatus>(response_status_value); |
+ if (response->status != OCSP_SUCCESSFUL) |
+ return true; |
+ |
+ der::Input response_type_oid; |
+ der::Input response_string; |
+ der::Parser response_bytes_input_parser; |
+ der::Parser response_bytes_parser; |
+ if (!ocsp_response_parser.ReadConstructed(der::ContextSpecificConstructed(0), |
+ &response_bytes_input_parser)) { |
+ return false; |
+ } |
+ if (!response_bytes_input_parser.ReadSequence(&response_bytes_parser)) |
+ return false; |
+ if (!response_bytes_parser.ReadTag(der::kOid, &response_type_oid)) |
+ return false; |
+ if (!response_type_oid.Equals(der::Input(kOidPkixOcspBasic))) |
+ return false; |
+ if (!response_bytes_parser.ReadTag(der::kOctetString, &response_string)) |
+ return false; |
+ |
+ der::Parser response_parser(response_string); |
+ der::Parser basic_response_parser; |
+ der::Parser response_data_parser; |
+ der::Input sigalg_tlv; |
+ if (!response_parser.ReadSequence(&basic_response_parser)) |
+ return false; |
+ if (!basic_response_parser.ReadSequence(&response_data_parser)) |
+ return false; |
+ if (!ParseOCSPResponseData(&response_data_parser, &(response->data))) |
+ return false; |
+ if (!basic_response_parser.ReadRawTLV(&sigalg_tlv)) |
+ return false; |
+ response->signature_algorithm = SignatureAlgorithm::CreateFromDer(sigalg_tlv); |
+ if (!basic_response_parser.ReadBitString(&(response->signature))) |
+ return false; |
+ der::Input certs_input; |
+ bool certs_present; |
+ if (!basic_response_parser.ReadOptionalTag(der::ContextSpecificConstructed(0), |
+ &certs_input, &certs_present)) { |
+ return false; |
+ } |
+ |
+ if (!certs_present) |
+ return true; |
+ der::Parser certs_input_parser(certs_input); |
+ der::Parser certs_parser; |
+ if (!certs_input_parser.ReadSequence(&certs_parser)) |
+ return false; |
+ while (certs_parser.HasMore()) { |
+ ParsedCertificate parsed_cert; |
+ der::Input cert_tlv; |
+ if (!certs_parser.ReadRawTLV(&cert_tlv)) |
+ return false; |
+ if (!ParseCertificate(cert_tlv, &parsed_cert)) |
+ return false; |
+ response->certs.push_back(parsed_cert); |
+ } |
+ return true; |
+} |
+ |
+} // namespace cert |
+ |
+} // namespace net |