| 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, the behavior after my change is a |
| 191 if (!cert->has_extended_key_usage() || | 181 // bit more permissive than what we had before, please confirm that |
| 192 !HasClientAuth(cert->extended_key_usage())) | 182 // this is acceptable (if not I can leave previous check in place). |
| 193 return false; | 183 // |
| 184 // * The EKU can now be omitted in the target certificate (will be |
| 185 // considered a match for clientAuth). |
| 186 // |
| 187 // * anyExtendedKeyUsage will also be considered a match for clientAuth |
| 194 | 188 |
| 195 // Check for an optional audio-only policy extension. | 189 // Check for an optional audio-only policy extension. |
| 196 *policy = CastDeviceCertPolicy::NONE; | 190 *policy = CastDeviceCertPolicy::NONE; |
| 197 if (cert->has_policy_oids()) { | 191 if (cert->has_policy_oids()) { |
| 198 const std::vector<net::der::Input>& policies = cert->policy_oids(); | 192 const std::vector<net::der::Input>& policies = cert->policy_oids(); |
| 199 // Look for an audio-only policy. Disregard any other policy found. | 193 // Look for an audio-only policy. Disregard any other policy found. |
| 200 if (std::find(policies.begin(), policies.end(), AudioOnlyPolicyOid()) != | 194 if (std::find(policies.begin(), policies.end(), AudioOnlyPolicyOid()) != |
| 201 policies.end()) { | 195 policies.end()) { |
| 202 *policy = CastDeviceCertPolicy::AUDIO_ONLY; | 196 *policy = CastDeviceCertPolicy::AUDIO_ONLY; |
| 203 } | 197 } |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 274 | 268 |
| 275 // Use a signature policy compatible with Cast's PKI. | 269 // Use a signature policy compatible with Cast's PKI. |
| 276 auto signature_policy = CreateCastSignaturePolicy(); | 270 auto signature_policy = CreateCastSignaturePolicy(); |
| 277 | 271 |
| 278 // Do path building and RFC 5280 compatible certificate verification using the | 272 // Do path building and RFC 5280 compatible certificate verification using the |
| 279 // two Cast trust anchors and Cast signature policy. | 273 // two Cast trust anchors and Cast signature policy. |
| 280 net::der::GeneralizedTime verification_time; | 274 net::der::GeneralizedTime verification_time; |
| 281 if (!net::der::EncodeTimeAsGeneralizedTime(time, &verification_time)) | 275 if (!net::der::EncodeTimeAsGeneralizedTime(time, &verification_time)) |
| 282 return false; | 276 return false; |
| 283 net::CertPathBuilder::Result result; | 277 net::CertPathBuilder::Result result; |
| 284 net::CertPathBuilder path_builder(target_cert.get(), trust_store, | 278 net::CertPathBuilder path_builder( |
| 285 signature_policy.get(), verification_time, | 279 target_cert.get(), trust_store, signature_policy.get(), verification_time, |
| 286 &result); | 280 net::KeyPurpose::KEY_PURPOSE_CLIENT_AUTH, &result); |
| 287 path_builder.AddCertIssuerSource(&intermediate_cert_issuer_source); | 281 path_builder.AddCertIssuerSource(&intermediate_cert_issuer_source); |
| 288 path_builder.Run(); | 282 path_builder.Run(); |
| 289 if (!result.HasValidPath()) { | 283 if (!result.HasValidPath()) { |
| 290 // TODO(crbug.com/634443): Log error information. | 284 // TODO(crbug.com/634443): Log error information. |
| 291 return false; | 285 return false; |
| 292 } | 286 } |
| 293 | 287 |
| 294 // Check properties of the leaf certificate (key usage, policy), and construct | 288 // Check properties of the leaf certificate (key usage, policy), and construct |
| 295 // a CertVerificationContext that uses its public key. | 289 // a CertVerificationContext that uses its public key. |
| 296 if (!CheckTargetCertificate(target_cert.get(), context, policy)) | 290 if (!CheckTargetCertificate(target_cert.get(), context, policy)) |
| (...skipping 14 matching lines...) Expand all Loading... |
| 311 | 305 |
| 312 std::unique_ptr<CertVerificationContext> CertVerificationContextImplForTest( | 306 std::unique_ptr<CertVerificationContext> CertVerificationContextImplForTest( |
| 313 const base::StringPiece& spki) { | 307 const base::StringPiece& spki) { |
| 314 // Use a bogus CommonName, since this is just exposed for testing signature | 308 // Use a bogus CommonName, since this is just exposed for testing signature |
| 315 // verification by unittests. | 309 // verification by unittests. |
| 316 return base::MakeUnique<CertVerificationContextImpl>(net::der::Input(spki), | 310 return base::MakeUnique<CertVerificationContextImpl>(net::der::Input(spki), |
| 317 "CommonName"); | 311 "CommonName"); |
| 318 } | 312 } |
| 319 | 313 |
| 320 } // namespace cast_certificate | 314 } // namespace cast_certificate |
| OLD | NEW |