Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/cast_certificate/cast_cert_validator.h" | 5 #include "components/cast_certificate/cast_cert_validator.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 153 for (const net::RelativeDistinguishedName& rdn : rdn_sequence) { | 153 for (const net::RelativeDistinguishedName& rdn : rdn_sequence) { |
| 154 for (const auto& atv : rdn) { | 154 for (const auto& atv : rdn) { |
| 155 if (atv.type == net::TypeCommonNameOid()) { | 155 if (atv.type == net::TypeCommonNameOid()) { |
| 156 return atv.ValueAsString(common_name); | 156 return atv.ValueAsString(common_name); |
| 157 } | 157 } |
| 158 } | 158 } |
| 159 } | 159 } |
| 160 return false; | 160 return false; |
| 161 } | 161 } |
| 162 | 162 |
| 163 // Returns true if the extended key usage list |ekus| contains client auth. | |
| 164 bool HasClientAuth(const std::vector<net::der::Input>& ekus) { | |
| 165 for (const auto& oid : ekus) { | |
| 166 if (oid == net::ClientAuth()) | |
| 167 return true; | |
| 168 } | |
| 169 return false; | |
| 170 } | |
| 171 | |
| 172 // Checks properties on the target certificate. | 163 // Checks properties on the target certificate. |
| 173 // | 164 // |
| 174 // * The Key Usage must include Digital Signature | 165 // * The Key Usage must include Digital Signature |
| 175 // * The Extended Key Usage must include TLS Client Auth | |
| 176 // * May have the policy 1.3.6.1.4.1.11129.2.5.2 to indicate it | 166 // * May have the policy 1.3.6.1.4.1.11129.2.5.2 to indicate it |
| 177 // is an audio-only device. | 167 // is an audio-only device. |
| 178 WARN_UNUSED_RESULT bool CheckTargetCertificate( | 168 WARN_UNUSED_RESULT bool CheckTargetCertificate( |
| 179 const net::ParsedCertificate* cert, | 169 const net::ParsedCertificate* cert, |
| 180 std::unique_ptr<CertVerificationContext>* context, | 170 std::unique_ptr<CertVerificationContext>* context, |
| 181 CastDeviceCertPolicy* policy) { | 171 CastDeviceCertPolicy* policy) { |
| 182 // Get the Key Usage extension. | 172 // Get the Key Usage extension. |
| 183 if (!cert->has_key_usage()) | 173 if (!cert->has_key_usage()) |
| 184 return false; | 174 return false; |
| 185 | 175 |
| 186 // Ensure Key Usage contains digitalSignature. | 176 // Ensure Key Usage contains digitalSignature. |
| 187 if (!cert->key_usage().AssertsBit(net::KEY_USAGE_BIT_DIGITAL_SIGNATURE)) | 177 if (!cert->key_usage().AssertsBit(net::KEY_USAGE_BIT_DIGITAL_SIGNATURE)) |
| 188 return false; | 178 return false; |
| 189 | 179 |
| 190 // Ensure Extended Key Usage contains client auth. | 180 // TODO(delete before landing): Doug/Cast OWNERs: the behavior after my |
|
ryanchung
2017/04/07 02:02:47
These changes look fine.
I guess the clientAuth EK
| |
| 191 if (!cert->has_extended_key_usage() || | 181 // change is a bit different than what we had before (but more |
| 192 !HasClientAuth(cert->extended_key_usage())) | 182 // standards compliant). I don't think this will cause any problems for |
| 193 return false; | 183 // Cast, but want to be explicit on what changed so you can properly review: |
| 184 // | |
| 185 // * [less strict] The EKU can now be omitted in the target | |
| 186 // certificate (will be considered a match for clientAuth per RFC | |
| 187 // 5280). Previously the extension needed to be present. | |
| 188 // | |
| 189 // * [less strict] The OID anyExtendedKeyUsage will also be considered a | |
| 190 // match for clientAuth, per RFC 5280. | |
| 191 // | |
| 192 // * [MORE strict] An extended Key Usage on an intermediate | |
| 193 // restricts the EKU on target certificate. This is NOT part of RFC | |
| 194 // 5280, however is the de-facto standard that both CryptoAPI and | |
| 195 // NSS use, and for Web PKI is now part of the Baseline | |
| 196 // Requirements. More details at | |
| 197 // https://wiki.mozilla.org/CA:CertificatePolicyV2.1#Frequently_Asked_Ques tions | |
| 198 // I don't expect Cast was setting an EKU on intermediates in the | |
| 199 // first place, and if they were hopefully it wasn't inconsistent | |
| 200 // with the end entity certificate. | |
| 194 | 201 |
| 195 // Check for an optional audio-only policy extension. | 202 // Check for an optional audio-only policy extension. |
| 196 *policy = CastDeviceCertPolicy::NONE; | 203 *policy = CastDeviceCertPolicy::NONE; |
| 197 if (cert->has_policy_oids()) { | 204 if (cert->has_policy_oids()) { |
| 198 const std::vector<net::der::Input>& policies = cert->policy_oids(); | 205 const std::vector<net::der::Input>& policies = cert->policy_oids(); |
| 199 // Look for an audio-only policy. Disregard any other policy found. | 206 // Look for an audio-only policy. Disregard any other policy found. |
| 200 if (std::find(policies.begin(), policies.end(), AudioOnlyPolicyOid()) != | 207 if (std::find(policies.begin(), policies.end(), AudioOnlyPolicyOid()) != |
| 201 policies.end()) { | 208 policies.end()) { |
| 202 *policy = CastDeviceCertPolicy::AUDIO_ONLY; | 209 *policy = CastDeviceCertPolicy::AUDIO_ONLY; |
| 203 } | 210 } |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 274 | 281 |
| 275 // Use a signature policy compatible with Cast's PKI. | 282 // Use a signature policy compatible with Cast's PKI. |
| 276 auto signature_policy = CreateCastSignaturePolicy(); | 283 auto signature_policy = CreateCastSignaturePolicy(); |
| 277 | 284 |
| 278 // Do path building and RFC 5280 compatible certificate verification using the | 285 // Do path building and RFC 5280 compatible certificate verification using the |
| 279 // two Cast trust anchors and Cast signature policy. | 286 // two Cast trust anchors and Cast signature policy. |
| 280 net::der::GeneralizedTime verification_time; | 287 net::der::GeneralizedTime verification_time; |
| 281 if (!net::der::EncodeTimeAsGeneralizedTime(time, &verification_time)) | 288 if (!net::der::EncodeTimeAsGeneralizedTime(time, &verification_time)) |
| 282 return false; | 289 return false; |
| 283 net::CertPathBuilder::Result result; | 290 net::CertPathBuilder::Result result; |
| 284 net::CertPathBuilder path_builder(target_cert.get(), trust_store, | 291 net::CertPathBuilder path_builder( |
| 285 signature_policy.get(), verification_time, | 292 target_cert.get(), trust_store, signature_policy.get(), verification_time, |
| 286 &result); | 293 net::KeyPurpose::KEY_PURPOSE_CLIENT_AUTH, &result); |
| 287 path_builder.AddCertIssuerSource(&intermediate_cert_issuer_source); | 294 path_builder.AddCertIssuerSource(&intermediate_cert_issuer_source); |
| 288 path_builder.Run(); | 295 path_builder.Run(); |
| 289 if (!result.HasValidPath()) { | 296 if (!result.HasValidPath()) { |
| 290 // TODO(crbug.com/634443): Log error information. | 297 // TODO(crbug.com/634443): Log error information. |
| 291 return false; | 298 return false; |
| 292 } | 299 } |
| 293 | 300 |
| 294 // Check properties of the leaf certificate (key usage, policy), and construct | 301 // Check properties of the leaf certificate (key usage, policy), and construct |
| 295 // a CertVerificationContext that uses its public key. | 302 // a CertVerificationContext that uses its public key. |
| 296 if (!CheckTargetCertificate(target_cert.get(), context, policy)) | 303 if (!CheckTargetCertificate(target_cert.get(), context, policy)) |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 311 | 318 |
| 312 std::unique_ptr<CertVerificationContext> CertVerificationContextImplForTest( | 319 std::unique_ptr<CertVerificationContext> CertVerificationContextImplForTest( |
| 313 const base::StringPiece& spki) { | 320 const base::StringPiece& spki) { |
| 314 // Use a bogus CommonName, since this is just exposed for testing signature | 321 // Use a bogus CommonName, since this is just exposed for testing signature |
| 315 // verification by unittests. | 322 // verification by unittests. |
| 316 return base::MakeUnique<CertVerificationContextImpl>(net::der::Input(spki), | 323 return base::MakeUnique<CertVerificationContextImpl>(net::der::Input(spki), |
| 317 "CommonName"); | 324 "CommonName"); |
| 318 } | 325 } |
| 319 | 326 |
| 320 } // namespace cast_certificate | 327 } // namespace cast_certificate |
| OLD | NEW |