 Chromium Code Reviews
 Chromium Code Reviews Issue 2040513003:
  Implement Expect-Staple  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master
    
  
    Issue 2040513003:
  Implement Expect-Staple  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master| Index: net/cert/ocsp_staple.cc | 
| diff --git a/net/cert/ocsp_staple.cc b/net/cert/ocsp_staple.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..1293eebea7efb81e3efb9bb73da0e4ccb4bc1f7a | 
| --- /dev/null | 
| +++ b/net/cert/ocsp_staple.cc | 
| @@ -0,0 +1,114 @@ | 
| +// 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 "ocsp_staple.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, | 
| 
estark
2016/06/14 02:10:27
nit: pass by reference (and the next arg too)
 
dadrian
2016/06/14 18:40:00
Done. (Whoops)
 | 
| + const base::TimeDelta max_age) { | 
| + if (response.has_next_update && | 
| + !(response.this_update < response.next_update)) | 
| + return false; | 
| + | 
| + // Place verify_time in the bounds | 
| 
estark
2016/06/14 02:10:27
nits: period and pipes around verify_time
 
dadrian
2016/06/14 18:40:00
Done.
 | 
| + 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 | 
| 
estark
2016/06/14 02:10:27
nit: period
 
dadrian
2016/06/14 18:40:00
Done.
 | 
| + 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 | 
| + 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 |