Chromium Code Reviews| Index: net/cert/internal/parse_ocsp.cc |
| diff --git a/net/cert/internal/parse_ocsp.cc b/net/cert/internal/parse_ocsp.cc |
| index e06b29abe616346278fa917ea2e43073448ed192..c899d6116fc399d7530c29e43076cd7901a70da8 100644 |
| --- a/net/cert/internal/parse_ocsp.cc |
| +++ b/net/cert/internal/parse_ocsp.cc |
| @@ -2,11 +2,16 @@ |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| +#include "net/cert/internal/parse_ocsp.h" |
| + |
| #include <algorithm> |
| #include "base/sha1.h" |
| #include "crypto/sha2.h" |
| -#include "net/cert/internal/parse_ocsp.h" |
| +#include "net/cert/internal/extended_key_usage.h" |
| +#include "net/cert/internal/signature_policy.h" |
| +#include "net/cert/internal/verify_name_match.h" |
| +#include "net/cert/internal/verify_signed_data.h" |
| namespace net { |
| @@ -529,4 +534,97 @@ bool GetOCSPCertStatus(const OCSPResponseData& response_data, |
| return found; |
| } |
| +namespace { |
| + |
| +// Checks that the ResponderID |id| matches the certificate |cert|. |
|
eroman
2016/05/02 22:36:50
Same comment here -- justify what parts of the sta
svaldez
2016/05/04 15:31:20
Done.
|
| +bool CheckResponder(const OCSPResponseData::ResponderID& id, |
| + const ParsedTbsCertificate& cert) { |
|
eroman
2016/05/02 22:36:50
WARN_UNUSED_RESULT
svaldez
2016/05/04 15:31:19
Done.
|
| + if (id.type == OCSPResponseData::ResponderType::NAME) { |
| + der::Input name_rdn; |
| + der::Input cert_rdn; |
| + if (!der::Parser(id.name).ReadTag(der::kSequence, &name_rdn) || |
|
eroman
2016/05/02 22:36:50
Is this sufficient?
The assumption is that id.name
svaldez
2016/05/04 15:31:19
The outer name I believe is guaranteed to be a sin
|
| + !der::Parser(cert.subject_tlv).ReadTag(der::kSequence, &cert_rdn)) |
| + return false; |
| + return VerifyNameMatch(name_rdn, cert_rdn); |
| + } else { |
|
eroman
2016/05/02 22:36:50
don't include the else after a short-circuit.
Als
svaldez
2016/05/04 15:31:19
Fixed. Due to the lack of extensability with the A
|
| + der::Parser parser(cert.spki_tlv); |
| + der::Parser spki_parser; |
| + der::BitString key_bits; |
| + if (!parser.ReadSequence(&spki_parser)) |
|
eroman
2016/05/02 22:36:50
Same thing as elsewhere -- describe intent.
Looks
svaldez
2016/05/04 15:31:19
Done.
|
| + return false; |
| + if (!spki_parser.SkipTag(der::kSequence)) |
| + return false; |
| + if (!spki_parser.ReadBitString(&key_bits)) |
| + return false; |
| + |
| + der::Input key = key_bits.bytes(); |
| + HashValue key_hash(HASH_VALUE_SHA1); |
|
eroman
2016/05/02 22:36:51
I am not familiar with OCSP (beyond what I read to
svaldez
2016/05/04 15:31:20
This is safe since we are only using the Responder
|
| + base::SHA1HashBytes(key.UnsafeData(), key.Length(), key_hash.data()); |
| + return key_hash.Equals(id.key_hash); |
| + } |
| +} |
| + |
| +} // namespace |
| + |
| +bool VerifyOCSPResponse(const OCSPResponse& response, |
|
eroman
2016/05/02 22:36:51
Please documentation throughout this implementatio
svaldez
2016/05/04 15:31:20
Done.
|
| + const ParsedCertificate& issuer_cert) { |
| + SimpleSignaturePolicy signature_policy(1024); |
|
eroman
2016/05/02 22:36:51
Why this signature policy? 1024-bit RSA is weak. D
svaldez
2016/05/04 15:31:19
Done.
|
| + |
| + OCSPResponseData response_data; |
|
eroman
2016/05/02 22:36:50
I didn't review the rest of this in detail -- will
svaldez
2016/05/04 15:31:19
Done.
|
| + if (!ParseOCSPResponseData(response.data, &response_data)) |
| + return false; |
| + |
| + ParsedTbsCertificate issuer; |
| + ParsedTbsCertificate responder; |
| + if (!ParseTbsCertificate(issuer_cert.tbs_certificate_tlv, &issuer)) |
| + return false; |
| + |
| + if (CheckResponder(response_data.responder_id, issuer)) { |
| + responder = issuer; |
| + } else { |
| + bool found = false; |
| + for (const auto& responder_cert_tlv : response.certs) { |
| + ParsedCertificate responder_cert; |
| + ParsedTbsCertificate tbs_cert; |
| + if (!ParseCertificate(responder_cert_tlv, &responder_cert)) |
| + return false; |
| + if (!ParseTbsCertificate(responder_cert.tbs_certificate_tlv, &tbs_cert)) |
| + return false; |
| + |
| + if (CheckResponder(response_data.responder_id, tbs_cert)) { |
| + found = true; |
| + responder = tbs_cert; |
| + |
| + scoped_ptr<SignatureAlgorithm> signature_algorithm = |
| + SignatureAlgorithm::CreateFromDer( |
| + responder_cert.signature_algorithm_tlv); |
| + if (!signature_algorithm) |
| + return false; |
| + der::Input issuer_spki = issuer.spki_tlv; |
| + if (!VerifySignedData(*signature_algorithm, |
| + responder_cert.tbs_certificate_tlv, |
| + responder_cert.signature_value, issuer_spki, |
| + &signature_policy)) { |
| + return false; |
| + } |
| + |
| + std::map<der::Input, ParsedExtension> extensions; |
| + std::vector<der::Input> eku; |
| + if (!ParseExtensions(responder.extensions_tlv, &extensions)) |
| + return false; |
| + if (!ParseEKUExtension(extensions[ExtKeyUsageOid()].value, &eku)) |
| + return false; |
| + if (std::find(eku.begin(), eku.end(), OCSPSigning()) == eku.end()) |
| + return false; |
| + break; |
| + } |
| + } |
| + if (!found) |
| + return false; |
| + } |
| + return VerifySignedData(*(response.signature_algorithm), response.data, |
| + response.signature, responder.spki_tlv, |
| + &signature_policy); |
| +} |
| + |
| } // namespace net |