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 // Checks that thisUpdate <= verify_time < nextUpdate, and that thisUpdate >= |
| 31 // verify_time - max_age. |
| 32 bool CheckOCSPDateValid(const OCSPSingleResponse& response, |
| 33 const base::Time& verify_time, |
| 34 const base::TimeDelta& max_age) { |
| 35 if (response.has_next_update && |
| 36 (response.next_update <= response.this_update)) { |
| 37 return false; |
| 38 } |
| 39 |
| 40 // Place |verify_time| in the bounds. |
| 41 der::GeneralizedTime verify_time_der = ConvertBaseTime(verify_time); |
| 42 if (response.this_update > verify_time_der) |
| 43 return false; |
| 44 if (response.has_next_update && (response.next_update <= verify_time_der)) |
| 45 return false; |
| 46 |
| 47 // Enforce |max_age|. |
| 48 der::GeneralizedTime lower_bound = ConvertBaseTime(verify_time - max_age); |
| 49 if (response.this_update < lower_bound) |
| 50 return false; |
| 51 return true; |
| 52 } |
| 53 |
| 54 bool CompareCertIDToCertificate(const OCSPCertID& cert_id, |
| 55 const X509Certificate& certificate) { |
| 56 // TODO(dadrian): Verify name and key hashes. https://crbug.com/620005 |
| 57 der::Input serial(&certificate.serial_number()); |
| 58 return serial == cert_id.serial_number; |
| 59 } |
| 60 |
| 61 } // namespace |
| 62 |
| 63 ExpectStapleReport::ExpectStapleReport() : staple_error_(StapleError::OK) {} |
| 64 |
| 65 ExpectStapleReport::~ExpectStapleReport() {} |
| 66 |
| 67 // static |
| 68 std::unique_ptr<ExpectStapleReport> ExpectStapleReport::FromRawOCSPResponse( |
| 69 const std::string& raw_response, |
| 70 const base::Time& verify_time, |
| 71 const base::TimeDelta& max_age, |
| 72 const X509Certificate& verified_certificate) { |
| 73 std::unique_ptr<ExpectStapleReport> out(new ExpectStapleReport); |
| 74 out->verify_time_ = verify_time; |
| 75 der::Input response_der(&raw_response); |
| 76 |
| 77 OCSPResponse response; |
| 78 if (!ParseOCSPResponse(response_der, &response)) { |
| 79 out->staple_error_ = StapleError::PARSE_RESPONSE; |
| 80 return out; |
| 81 } |
| 82 |
| 83 // If the OCSP response isn't status SUCCESSFUL, don't parse the rest of the |
| 84 // data. |
| 85 if (response.status != OCSPResponse::ResponseStatus::SUCCESSFUL) { |
| 86 out->staple_error_ = StapleError::BAD_RESPONSE; |
| 87 return out; |
| 88 } |
| 89 |
| 90 OCSPResponseData response_data; |
| 91 if (!ParseOCSPResponseData(response.data, &response_data)) { |
| 92 out->staple_error_ = StapleError::PARSE_RESPONSE_DATA; |
| 93 return out; |
| 94 } |
| 95 |
| 96 // TODO(svaldez): Unify with GetOCSPCertStatus. |
| 97 bool contains_correct_response = false; |
| 98 for (const auto& single_response_der : response_data.responses) { |
| 99 OCSPSingleResponse single_response; |
| 100 if (!ParseOCSPSingleResponse(single_response_der, &single_response)) |
| 101 continue; |
| 102 SingleResult single_result; |
| 103 single_result.status = single_response.cert_status.status; |
| 104 single_result.is_date_valid = |
| 105 CheckOCSPDateValid(single_response, verify_time, max_age); |
| 106 OCSPCertID cert_id; |
| 107 if (ParseOCSPCertID(single_response.cert_id_tlv, &cert_id)) { |
| 108 single_result.is_correct_certificate = |
| 109 CompareCertIDToCertificate(cert_id, verified_certificate); |
| 110 } |
| 111 if (single_result.is_date_valid && single_result.is_correct_certificate && |
| 112 single_result.status == OCSPCertStatus::Status::GOOD) { |
| 113 contains_correct_response = true; |
| 114 } |
| 115 out->stapled_responses_.push_back(single_result); |
| 116 } |
| 117 |
| 118 if (!contains_correct_response) { |
| 119 out->staple_error_ = StapleError::NO_MATCHING_RESPONSE; |
| 120 } else { |
| 121 out->staple_error_ = StapleError::OK; |
| 122 } |
| 123 return out; |
| 124 } |
| 125 |
| 126 } // namespace net |
OLD | NEW |