Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "expect_staple_report.h" | |
| 6 | |
| 7 #include "base/time/time.h" | |
| 8 #include "net/cert/internal/parse_ocsp.h" | |
| 9 #include "net/cert/x509_certificate.h" | |
| 10 #include "net/der/parse_values.h" | |
| 11 | |
| 12 namespace net { | |
| 13 | |
| 14 namespace { | |
| 15 | |
| 16 der::GeneralizedTime ConvertBaseTime(const base::Time& time) { | |
| 17 base::Time::Exploded exploded; | |
| 18 time.UTCExplode(&exploded); | |
| 19 | |
| 20 der::GeneralizedTime result; | |
| 21 result.year = exploded.year; | |
| 22 result.month = exploded.month; | |
| 23 result.day = exploded.day_of_month; | |
| 24 result.hours = exploded.hour; | |
| 25 result.minutes = exploded.minute; | |
| 26 result.seconds = exploded.second; | |
| 27 return result; | |
| 28 } | |
| 29 | |
| 30 bool CheckOCSPDateValid(const OCSPSingleResponse& response, | |
| 31 const base::Time& verify_time, | |
| 32 const base::TimeDelta& max_age) { | |
| 33 if (response.has_next_update && | |
| 34 !(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.
| |
| 35 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
| |
| 36 | |
| 37 // Place |verify_time| in the bounds. | |
| 38 der::GeneralizedTime verify_time_der = ConvertBaseTime(verify_time); | |
| 39 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.
| |
| 40 return false; | |
| 41 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.
| |
| 42 return false; | |
| 43 | |
| 44 // Enforce |max_age|. | |
| 45 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
| |
| 46 if (response.this_update < lower_bound) | |
| 47 return false; | |
| 48 return true; | |
| 49 } | |
| 50 | |
| 51 bool CompareCertIDToCertificate(const OCSPCertID& cert_id, | |
| 52 const X509Certificate& certificate) { | |
| 53 // TODO(dadrian): Verify name and key hashes. https://crbug.com/620005 | |
| 54 der::Input serial(&certificate.serial_number()); | |
| 55 return serial == cert_id.serial_number; | |
| 56 } | |
| 57 | |
| 58 } // namespace | |
| 59 | |
| 60 ExpectStapleReport::ExpectStapleReport() : staple_error_(StapleError::OK) {} | |
| 61 | |
| 62 ExpectStapleReport::~ExpectStapleReport() {} | |
| 63 | |
| 64 std::unique_ptr<ExpectStapleReport> ExpectStapleReport::FromRawOCSPResponse( | |
|
svaldez
2016/06/16 11:14:38
// static
dadrian
2016/06/16 19:20:18
Done.
| |
| 65 const std::string& raw_response, | |
| 66 const base::Time& verify_time, | |
| 67 const base::TimeDelta& max_age, | |
| 68 const X509Certificate& verified_certificate) { | |
| 69 std::unique_ptr<ExpectStapleReport> out(new ExpectStapleReport); | |
| 70 out->verify_time_ = verify_time; | |
| 71 der::Input response_der(&raw_response); | |
| 72 | |
| 73 OCSPResponse response; | |
| 74 if (!ParseOCSPResponse(response_der, &response)) { | |
| 75 out->staple_error_ = StapleError::PARSE_RESPONSE; | |
| 76 return out; | |
| 77 } | |
| 78 | |
| 79 // If the OCSP response isn't status SUCCESSFUL, don't parse the rest of the | |
| 80 // data. | |
| 81 if (response.status != OCSPResponse::ResponseStatus::SUCCESSFUL) { | |
| 82 out->staple_error_ = StapleError::BAD_RESPONSE; | |
| 83 return out; | |
| 84 } | |
| 85 | |
| 86 OCSPResponseData response_data; | |
| 87 if (!ParseOCSPResponseData(response.data, &response_data)) { | |
| 88 out->staple_error_ = StapleError::PARSE_RESPONSE_DATA; | |
| 89 return out; | |
| 90 } | |
| 91 | |
|
svaldez
2016/06/16 11:14:38
Add:
TODO(svaldez): Unify with GetOCSPCertStatus.
dadrian
2016/06/16 19:20:17
Done.
| |
| 92 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'
| |
| 93 for (const auto& single_response_der : response_data.responses) { | |
| 94 OCSPSingleResponse single_response; | |
| 95 if (!ParseOCSPSingleResponse(single_response_der, &single_response)) | |
| 96 continue; | |
| 97 SingleResult single_result; | |
| 98 single_result.status = single_response.cert_status.status; | |
| 99 single_result.is_date_valid = | |
| 100 CheckOCSPDateValid(single_response, verify_time, max_age); | |
| 101 OCSPCertID cert_id; | |
| 102 if (ParseOCSPCertID(single_response.cert_id_tlv, &cert_id)) { | |
| 103 single_result.is_correct_certificate = | |
| 104 CompareCertIDToCertificate(cert_id, verified_certificate); | |
| 105 } | |
| 106 if (single_result.is_date_valid && single_result.is_correct_certificate && | |
| 107 single_result.status == OCSPCertStatus::Status::GOOD) { | |
| 108 contains_correct_response = true; | |
| 109 } | |
| 110 out->stapled_responses_.push_back(single_result); | |
| 111 } | |
| 112 | |
| 113 if (!contains_correct_response) { | |
| 114 out->staple_error_ = StapleError::NO_MATCHING_RESPONSE; | |
| 115 } | |
| 116 return out; | |
|
svaldez
2016/06/16 11:14:38
Explicitly set StapleError::OK.
dadrian
2016/06/16 19:20:18
Done.
| |
| 117 } | |
| 118 | |
| 119 } // namespace net | |
| OLD | NEW |