| Index: net/cert/expect_staple_report.cc
|
| diff --git a/net/cert/expect_staple_report.cc b/net/cert/expect_staple_report.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..5bce801e5fa401e6d6a381b8495440a3da50ae8b
|
| --- /dev/null
|
| +++ b/net/cert/expect_staple_report.cc
|
| @@ -0,0 +1,115 @@
|
| +// Copyright 2016 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 "expect_staple_report.h"
|
| +
|
| +namespace net {
|
| +
|
| +namespace {
|
| +
|
| +der::GeneralizedTime ConvertBaseTime(const base::Time& time) {
|
| + base::Time::Exploded exploded;
|
| + time.UTCExplode(&exploded);
|
| +
|
| + der::GeneralizedTime result;
|
| + result.year = exploded.year;
|
| + result.month = exploded.month;
|
| + result.day = exploded.day_of_month;
|
| + result.hours = exploded.hour;
|
| + result.minutes = exploded.minute;
|
| + result.seconds = exploded.second;
|
| + return result;
|
| +}
|
| +
|
| +bool CheckOCSPDateValid(const OCSPSingleResponse& response,
|
| + const base::Time& verify_time,
|
| + const base::TimeDelta& max_age) {
|
| + if (response.has_next_update &&
|
| + !(response.this_update < response.next_update))
|
| + return false;
|
| +
|
| + // Place |verify_time| in the bounds.
|
| + der::GeneralizedTime verify_time_der = ConvertBaseTime(verify_time);
|
| + if (!(response.this_update < verify_time_der))
|
| + return false;
|
| + if (response.has_next_update && !(verify_time_der < response.next_update))
|
| + return false;
|
| +
|
| + // Enforce |max_age|.
|
| + der::GeneralizedTime lower_bound = ConvertBaseTime(verify_time - max_age);
|
| + if (response.this_update < lower_bound)
|
| + return false;
|
| + return true;
|
| +}
|
| +
|
| +bool CompareCertIDToCertificate(const OCSPCertID& cert_id,
|
| + const X509Certificate& certificate) {
|
| + // TODO(dadrian): Verify name and key hashes. https://crbug.com/620005
|
| + der::Input serial(&certificate.serial_number());
|
| + return serial == cert_id.serial_number;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +ExpectStapleReport::ExpectStapleReport() : staple_error_(StapleError::OK) {}
|
| +
|
| +ExpectStapleReport::~ExpectStapleReport() {}
|
| +
|
| +std::unique_ptr<ExpectStapleReport> ExpectStapleReport::FromRawOCSPResponse(
|
| + const std::string& raw_response,
|
| + const base::Time& verify_time,
|
| + const base::TimeDelta& max_age,
|
| + const X509Certificate& verified_certificate) {
|
| + std::unique_ptr<ExpectStapleReport> out(new ExpectStapleReport);
|
| + out->verify_time_ = verify_time;
|
| + der::Input response_der(&raw_response);
|
| +
|
| + OCSPResponse response;
|
| + if (!ParseOCSPResponse(response_der, &response)) {
|
| + out->staple_error_ = StapleError::PARSE_RESPONSE;
|
| + return out;
|
| + }
|
| +
|
| + // If the OCSP response isn't status SUCCESSFUL, don't parse the rest of the
|
| + // data.
|
| + if (response.status != OCSPResponse::ResponseStatus::SUCCESSFUL) {
|
| + out->staple_error_ = StapleError::BAD_RESPONSE;
|
| + return out;
|
| + }
|
| +
|
| + OCSPResponseData response_data;
|
| + if (!ParseOCSPResponseData(response.data, &response_data)) {
|
| + out->staple_error_ = StapleError::PARSE_RESPONSE_DATA;
|
| + return out;
|
| + }
|
| +
|
| + bool contains_correct_response = false;
|
| + for (const auto& single_response_der : response_data.responses) {
|
| + OCSPSingleResponse single_response;
|
| + if (!ParseOCSPSingleResponse(single_response_der, &single_response))
|
| + continue;
|
| + SingleResult single_result;
|
| + single_result.status = single_response.cert_status.status;
|
| + single_result.is_date_valid =
|
| + CheckOCSPDateValid(single_response, verify_time, max_age);
|
| + OCSPCertID cert_id;
|
| + if (ParseOCSPCertID(single_response.cert_id_tlv, &cert_id)) {
|
| + single_result.is_correct_certificate =
|
| + CompareCertIDToCertificate(cert_id, verified_certificate);
|
| + }
|
| + if (single_result.is_date_valid && single_result.is_correct_certificate &&
|
| + single_result.status == OCSPCertStatus::Status::GOOD) {
|
| + contains_correct_response = true;
|
| + }
|
| + out->stapled_responses_.push_back(single_result);
|
| + }
|
| +
|
| + if (!contains_correct_response) {
|
| + out->staple_error_ = StapleError::NO_MATCHING_RESPONSE;
|
| + return out;
|
| + }
|
| + return out;
|
| +}
|
| +
|
| +} // namespace net
|
|
|