| 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.
 | 
| 
 |