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 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
151 for (const net::RelativeDistinguishedName& rdn : rdn_sequence) { | 151 for (const net::RelativeDistinguishedName& rdn : rdn_sequence) { |
152 for (const auto& atv : rdn) { | 152 for (const auto& atv : rdn) { |
153 if (atv.type == net::TypeCommonNameOid()) { | 153 if (atv.type == net::TypeCommonNameOid()) { |
154 return atv.ValueAsString(common_name); | 154 return atv.ValueAsString(common_name); |
155 } | 155 } |
156 } | 156 } |
157 } | 157 } |
158 return false; | 158 return false; |
159 } | 159 } |
160 | 160 |
| 161 // Cast device certificates use the policy 1.3.6.1.4.1.11129.2.5.2 to indicate |
| 162 // it is *restricted* to an audio-only device whereas the absence of a policy |
| 163 // means it is unrestricted. |
| 164 // |
| 165 // This is somewhat different than RFC 5280's notion of policies, so policies |
| 166 // are checked separately outside of path building. |
| 167 // |
| 168 // See the unit-tests VerifyCastDeviceCertTest.Policies* for some |
| 169 // concrete examples of how this works. |
| 170 void DetermineDeviceCertificatePolicy( |
| 171 const net::CertPathBuilder::ResultPath* result_path, |
| 172 CastDeviceCertPolicy* policy) { |
| 173 // Iterate over all the certificates, including the root certificate. If any |
| 174 // certificate contains the audio-only policy, the whole chain is considered |
| 175 // constrained to audio-only device certificates. |
| 176 // |
| 177 // Policy mappings are not accounted for. The expectation is that top-level |
| 178 // intermediates issued with audio-only will have no mappings. If subsequent |
| 179 // certificates in the chain do, it won't matter as the chain is already |
| 180 // restricted to being audio-only. |
| 181 bool audio_only = false; |
| 182 for (const auto& cert : result_path->path.certs) { |
| 183 if (cert->has_policy_oids()) { |
| 184 const std::vector<net::der::Input>& policies = cert->policy_oids(); |
| 185 if (std::find(policies.begin(), policies.end(), AudioOnlyPolicyOid()) != |
| 186 policies.end()) { |
| 187 audio_only = true; |
| 188 break; |
| 189 } |
| 190 } |
| 191 } |
| 192 |
| 193 *policy = audio_only ? CastDeviceCertPolicy::AUDIO_ONLY |
| 194 : CastDeviceCertPolicy::NONE; |
| 195 } |
| 196 |
161 // Checks properties on the target certificate. | 197 // Checks properties on the target certificate. |
162 // | 198 // |
163 // * The Key Usage must include Digital Signature | 199 // * The Key Usage must include Digital Signature |
164 // * May have the policy 1.3.6.1.4.1.11129.2.5.2 to indicate it | |
165 // is an audio-only device. | |
166 WARN_UNUSED_RESULT bool CheckTargetCertificate( | 200 WARN_UNUSED_RESULT bool CheckTargetCertificate( |
167 const net::ParsedCertificate* cert, | 201 const net::ParsedCertificate* cert, |
168 std::unique_ptr<CertVerificationContext>* context, | 202 std::unique_ptr<CertVerificationContext>* context) { |
169 CastDeviceCertPolicy* policy) { | |
170 // Get the Key Usage extension. | 203 // Get the Key Usage extension. |
171 if (!cert->has_key_usage()) | 204 if (!cert->has_key_usage()) |
172 return false; | 205 return false; |
173 | 206 |
174 // Ensure Key Usage contains digitalSignature. | 207 // Ensure Key Usage contains digitalSignature. |
175 if (!cert->key_usage().AssertsBit(net::KEY_USAGE_BIT_DIGITAL_SIGNATURE)) | 208 if (!cert->key_usage().AssertsBit(net::KEY_USAGE_BIT_DIGITAL_SIGNATURE)) |
176 return false; | 209 return false; |
177 | 210 |
178 // Check for an optional audio-only policy extension. | |
179 // | |
180 // TODO(eroman): Use |user_constrained_policy_set| that was output from | |
181 // verification instead. (Checking just the leaf certificate's policy | |
182 // assertion doesn't take into account policy restrictions on intermediates, | |
183 // policy constraints/inhibits, or policy re-mappings). | |
184 *policy = CastDeviceCertPolicy::NONE; | |
185 if (cert->has_policy_oids()) { | |
186 const std::vector<net::der::Input>& policies = cert->policy_oids(); | |
187 // Look for an audio-only policy. Disregard any other policy found. | |
188 if (std::find(policies.begin(), policies.end(), AudioOnlyPolicyOid()) != | |
189 policies.end()) { | |
190 *policy = CastDeviceCertPolicy::AUDIO_ONLY; | |
191 } | |
192 } | |
193 | |
194 // Get the Common Name for the certificate. | 211 // Get the Common Name for the certificate. |
195 std::string common_name; | 212 std::string common_name; |
196 if (!GetCommonNameFromSubject(cert->tbs().subject_tlv, &common_name)) | 213 if (!GetCommonNameFromSubject(cert->tbs().subject_tlv, &common_name)) |
197 return false; | 214 return false; |
198 | 215 |
199 context->reset( | 216 context->reset( |
200 new CertVerificationContextImpl(cert->tbs().spki_tlv, common_name)); | 217 new CertVerificationContextImpl(cert->tbs().spki_tlv, common_name)); |
201 return true; | 218 return true; |
202 } | 219 } |
203 | 220 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
274 net::KeyPurpose::CLIENT_AUTH, net::InitialExplicitPolicy::kFalse, | 291 net::KeyPurpose::CLIENT_AUTH, net::InitialExplicitPolicy::kFalse, |
275 {net::AnyPolicy()}, net::InitialPolicyMappingInhibit::kFalse, | 292 {net::AnyPolicy()}, net::InitialPolicyMappingInhibit::kFalse, |
276 net::InitialAnyPolicyInhibit::kFalse, &result); | 293 net::InitialAnyPolicyInhibit::kFalse, &result); |
277 path_builder.AddCertIssuerSource(&intermediate_cert_issuer_source); | 294 path_builder.AddCertIssuerSource(&intermediate_cert_issuer_source); |
278 path_builder.Run(); | 295 path_builder.Run(); |
279 if (!result.HasValidPath()) { | 296 if (!result.HasValidPath()) { |
280 // TODO(crbug.com/634443): Log error information. | 297 // TODO(crbug.com/634443): Log error information. |
281 return false; | 298 return false; |
282 } | 299 } |
283 | 300 |
284 // Check properties of the leaf certificate (key usage, policy), and construct | 301 // Determine whether this device certificate is restricted to audio-only. |
285 // a CertVerificationContext that uses its public key. | 302 DetermineDeviceCertificatePolicy(result.GetBestValidPath(), policy); |
286 if (!CheckTargetCertificate(target_cert.get(), context, policy)) | 303 |
| 304 // Check properties of the leaf certificate not already verified by path |
| 305 // building (key usage), and construct a CertVerificationContext that uses |
| 306 // its public key. |
| 307 if (!CheckTargetCertificate(target_cert.get(), context)) |
287 return false; | 308 return false; |
288 | 309 |
289 // Check if a CRL is available. | 310 // Check if a CRL is available. |
290 if (!crl) { | 311 if (!crl) { |
291 if (crl_policy == CRLPolicy::CRL_REQUIRED) { | 312 if (crl_policy == CRLPolicy::CRL_REQUIRED) { |
292 return false; | 313 return false; |
293 } | 314 } |
294 } else { | 315 } else { |
295 if (!crl->CheckRevocation(result.GetBestValidPath()->path, time)) { | 316 if (!crl->CheckRevocation(result.GetBestValidPath()->path, time)) { |
296 return false; | 317 return false; |
297 } | 318 } |
298 } | 319 } |
299 return true; | 320 return true; |
300 } | 321 } |
301 | 322 |
302 std::unique_ptr<CertVerificationContext> CertVerificationContextImplForTest( | 323 std::unique_ptr<CertVerificationContext> CertVerificationContextImplForTest( |
303 const base::StringPiece& spki) { | 324 const base::StringPiece& spki) { |
304 // Use a bogus CommonName, since this is just exposed for testing signature | 325 // Use a bogus CommonName, since this is just exposed for testing signature |
305 // verification by unittests. | 326 // verification by unittests. |
306 return base::MakeUnique<CertVerificationContextImpl>(net::der::Input(spki), | 327 return base::MakeUnique<CertVerificationContextImpl>(net::der::Input(spki), |
307 "CommonName"); | 328 "CommonName"); |
308 } | 329 } |
309 | 330 |
310 } // namespace cast_certificate | 331 } // namespace cast_certificate |
OLD | NEW |