| Index: components/cast_certificate/cast_cert_validator.cc
|
| diff --git a/components/cast_certificate/cast_cert_validator.cc b/components/cast_certificate/cast_cert_validator.cc
|
| index 8ea624babc4f5ebd83a6024b57e23bc9899c8669..f10080e6153d74a85e5e8a1863fc1d9996a02954 100644
|
| --- a/components/cast_certificate/cast_cert_validator.cc
|
| +++ b/components/cast_certificate/cast_cert_validator.cc
|
| @@ -158,15 +158,48 @@ bool GetCommonNameFromSubject(const net::der::Input& subject_tlv,
|
| return false;
|
| }
|
|
|
| +// Cast device certificates use the policy 1.3.6.1.4.1.11129.2.5.2 to indicate
|
| +// it is *restricted* to an audio-only device whereas the absence of a policy
|
| +// means it is unrestricted.
|
| +//
|
| +// This is somewhat different than RFC 5280's notion of policies, so policies
|
| +// are checked separately outside of path building.
|
| +//
|
| +// See the unit-tests VerifyCastDeviceCertTest.Policies* for some
|
| +// concrete examples of how this works.
|
| +void DetermineDeviceCertificatePolicy(
|
| + const net::CertPathBuilder::ResultPath* result_path,
|
| + CastDeviceCertPolicy* policy) {
|
| + // Iterate over all the certificates, including the root certificate. If any
|
| + // certificate contains the audio-only policy, the whole chain is considered
|
| + // constrained to audio-only device certificates.
|
| + //
|
| + // Policy mappings are not accounted for. The expectation is that top-level
|
| + // intermediates issued with audio-only will have no mappings. If subsequent
|
| + // certificates in the chain do, it won't matter as the chain is already
|
| + // restricted to being audio-only.
|
| + bool audio_only = false;
|
| + for (const auto& cert : result_path->path.certs) {
|
| + if (cert->has_policy_oids()) {
|
| + const std::vector<net::der::Input>& policies = cert->policy_oids();
|
| + if (std::find(policies.begin(), policies.end(), AudioOnlyPolicyOid()) !=
|
| + policies.end()) {
|
| + audio_only = true;
|
| + break;
|
| + }
|
| + }
|
| + }
|
| +
|
| + *policy = audio_only ? CastDeviceCertPolicy::AUDIO_ONLY
|
| + : CastDeviceCertPolicy::NONE;
|
| +}
|
| +
|
| // Checks properties on the target certificate.
|
| //
|
| // * The Key Usage must include Digital Signature
|
| -// * May have the policy 1.3.6.1.4.1.11129.2.5.2 to indicate it
|
| -// is an audio-only device.
|
| WARN_UNUSED_RESULT bool CheckTargetCertificate(
|
| const net::ParsedCertificate* cert,
|
| - std::unique_ptr<CertVerificationContext>* context,
|
| - CastDeviceCertPolicy* policy) {
|
| + std::unique_ptr<CertVerificationContext>* context) {
|
| // Get the Key Usage extension.
|
| if (!cert->has_key_usage())
|
| return false;
|
| @@ -175,22 +208,6 @@ WARN_UNUSED_RESULT bool CheckTargetCertificate(
|
| if (!cert->key_usage().AssertsBit(net::KEY_USAGE_BIT_DIGITAL_SIGNATURE))
|
| return false;
|
|
|
| - // Check for an optional audio-only policy extension.
|
| - //
|
| - // TODO(eroman): Use |user_constrained_policy_set| that was output from
|
| - // verification instead. (Checking just the leaf certificate's policy
|
| - // assertion doesn't take into account policy restrictions on intermediates,
|
| - // policy constraints/inhibits, or policy re-mappings).
|
| - *policy = CastDeviceCertPolicy::NONE;
|
| - if (cert->has_policy_oids()) {
|
| - const std::vector<net::der::Input>& policies = cert->policy_oids();
|
| - // Look for an audio-only policy. Disregard any other policy found.
|
| - if (std::find(policies.begin(), policies.end(), AudioOnlyPolicyOid()) !=
|
| - policies.end()) {
|
| - *policy = CastDeviceCertPolicy::AUDIO_ONLY;
|
| - }
|
| - }
|
| -
|
| // Get the Common Name for the certificate.
|
| std::string common_name;
|
| if (!GetCommonNameFromSubject(cert->tbs().subject_tlv, &common_name))
|
| @@ -281,9 +298,13 @@ bool VerifyDeviceCertUsingCustomTrustStore(
|
| return false;
|
| }
|
|
|
| - // Check properties of the leaf certificate (key usage, policy), and construct
|
| - // a CertVerificationContext that uses its public key.
|
| - if (!CheckTargetCertificate(target_cert.get(), context, policy))
|
| + // Determine whether this device certificate is restricted to audio-only.
|
| + DetermineDeviceCertificatePolicy(result.GetBestValidPath(), policy);
|
| +
|
| + // Check properties of the leaf certificate not already verified by path
|
| + // building (key usage), and construct a CertVerificationContext that uses
|
| + // its public key.
|
| + if (!CheckTargetCertificate(target_cert.get(), context))
|
| return false;
|
|
|
| // Check if a CRL is available.
|
|
|