Chromium Code Reviews| 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..2977635b4b2db4e56c290a35157770ade8564220 |
| --- /dev/null |
| +++ b/net/cert/expect_staple_report.cc |
| @@ -0,0 +1,119 @@ |
| +// 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" |
| + |
| +#include "base/time/time.h" |
| +#include "net/cert/internal/parse_ocsp.h" |
| +#include "net/cert/x509_certificate.h" |
| +#include "net/der/parse_values.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)) |
|
svaldez
2016/06/16 11:14:38
this_update >= next_update?
dadrian
2016/06/16 19:20:18
I was using operator< because it's the only one im
svaldez
2016/06/16 19:56:23
https://codereview.chromium.org/2075783002/ adds t
dadrian
2016/06/16 21:36:18
Done.
|
| + return false; |
|
svaldez
2016/06/16 11:14:38
Multiline conditionals should have braces.
(I thi
dadrian
2016/06/16 19:20:17
Done. Good to know, I think I've seen it both ways
|
| + |
| + // Place |verify_time| in the bounds. |
| + der::GeneralizedTime verify_time_der = ConvertBaseTime(verify_time); |
| + if (!(response.this_update < verify_time_der)) |
|
svaldez
2016/06/16 11:14:38
verify_time_der < response.this_update
dadrian
2016/06/16 19:20:18
Done.
|
| + return false; |
| + if (response.has_next_update && !(verify_time_der < response.next_update)) |
|
svaldez
2016/06/16 11:14:38
next_update < verify_time_der
or
verify_time_der
dadrian
2016/06/16 19:20:17
Done.
|
| + return false; |
| + |
| + // Enforce |max_age|. |
| + der::GeneralizedTime lower_bound = ConvertBaseTime(verify_time - max_age); |
|
svaldez
2016/06/16 11:14:38
return this_update >= lower_bound?
dadrian
2016/06/16 19:20:18
I wrote it this way to make all the error checks e
|
| + 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( |
|
svaldez
2016/06/16 11:14:38
// static
dadrian
2016/06/16 19:20:18
Done.
|
| + 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; |
| + } |
| + |
|
svaldez
2016/06/16 11:14:38
Add:
TODO(svaldez): Unify with GetOCSPCertStatus.
dadrian
2016/06/16 19:20:17
Done.
|
| + bool contains_correct_response = false; |
|
svaldez
2016/06/16 11:14:38
This should fail out immediately if any of the res
dadrian
2016/06/16 19:20:17
If this was just verification, sure. But since we'
|
| + 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; |
|
svaldez
2016/06/16 11:14:38
Explicitly set StapleError::OK.
dadrian
2016/06/16 19:20:18
Done.
|
| +} |
| + |
| +} // namespace net |