1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "cast/common/certificate/cast_cert_validator_internal.h"
6
7 #include <openssl/asn1.h>
8 #include <openssl/evp.h>
9 #include <openssl/x509.h>
10 #include <openssl/x509v3.h>
11 #include <time.h>
12
13 #include <vector>
14
15 #include "cast/common/certificate/types.h"
16 #include "util/logging.h"
17
18 namespace openscreen {
19 namespace cast {
20 namespace {
21
22 constexpr static int32_t kMinRsaModulusLengthBits = 2048;
23
24 // Stores intermediate state while attempting to find a valid certificate chain
25 // from a set of trusted certificates to a target certificate. Together, a
26 // sequence of these forms a certificate chain to be verified as well as a stack
27 // that can be unwound for searching more potential paths.
28 struct CertPathStep {
29 X509* cert;
30
31 // The next index that can be checked in |trust_store| if the choice |cert| on
32 // the path needs to be reverted.
33 uint32_t trust_store_index;
34
35 // The next index that can be checked in |intermediate_certs| if the choice
36 // |cert| on the path needs to be reverted.
37 uint32_t intermediate_cert_index;
38 };
39
40 // These values are bit positions from RFC 5280 4.2.1.3 and will be passed to
41 // ASN1_BIT_STRING_get_bit.
42 enum KeyUsageBits {
43 kDigitalSignature = 0,
44 kKeyCertSign = 5,
45 };
46
CertInPath(X509_NAME * name,const std::vector<CertPathStep> & steps,uint32_t start,uint32_t stop)47 bool CertInPath(X509_NAME* name,
48 const std::vector<CertPathStep>& steps,
49 uint32_t start,
50 uint32_t stop) {
51 for (uint32_t i = start; i < stop; ++i) {
52 if (X509_NAME_cmp(name, X509_get_subject_name(steps[i].cert)) == 0) {
53 return true;
54 }
55 }
56 return false;
57 }
58
59 // Parse the data in |time| at |index| as a two-digit ascii number.
ParseAsn1TimeDoubleDigit(ASN1_GENERALIZEDTIME * time,int index)60 uint8_t ParseAsn1TimeDoubleDigit(ASN1_GENERALIZEDTIME* time, int index) {
61 return (time->data[index] - '0') * 10 + (time->data[index + 1] - '0');
62 }
63
VerifyCertTime(X509 * cert,const DateTime & time)64 Error::Code VerifyCertTime(X509* cert, const DateTime& time) {
65 DateTime not_before;
66 DateTime not_after;
67 if (!GetCertValidTimeRange(cert, ¬_before, ¬_after)) {
68 return Error::Code::kErrCertsVerifyGeneric;
69 }
70 if ((time < not_before) || (not_after < time)) {
71 return Error::Code::kErrCertsDateInvalid;
72 }
73 return Error::Code::kNone;
74 }
75
VerifyPublicKeyLength(EVP_PKEY * public_key)76 bool VerifyPublicKeyLength(EVP_PKEY* public_key) {
77 return EVP_PKEY_bits(public_key) >= kMinRsaModulusLengthBits;
78 }
79
GetKeyUsage(X509 * cert)80 bssl::UniquePtr<ASN1_BIT_STRING> GetKeyUsage(X509* cert) {
81 int pos = X509_get_ext_by_NID(cert, NID_key_usage, -1);
82 if (pos == -1) {
83 return nullptr;
84 }
85 X509_EXTENSION* key_usage = X509_get_ext(cert, pos);
86 const uint8_t* value = key_usage->value->data;
87 ASN1_BIT_STRING* key_usage_bit_string = nullptr;
88 if (!d2i_ASN1_BIT_STRING(&key_usage_bit_string, &value,
89 key_usage->value->length)) {
90 return nullptr;
91 }
92 return bssl::UniquePtr<ASN1_BIT_STRING>{key_usage_bit_string};
93 }
94
VerifyCertificateChain(const std::vector<CertPathStep> & path,uint32_t step_index,const DateTime & time)95 Error::Code VerifyCertificateChain(const std::vector<CertPathStep>& path,
96 uint32_t step_index,
97 const DateTime& time) {
98 // Default max path length is the number of intermediate certificates.
99 int max_pathlen = path.size() - 2;
100
101 std::vector<NAME_CONSTRAINTS*> path_name_constraints;
102 Error::Code error = Error::Code::kNone;
103 uint32_t i = step_index;
104 for (; i < path.size() - 1; ++i) {
105 X509* subject = path[i + 1].cert;
106 X509* issuer = path[i].cert;
107 bool is_root = (i == step_index);
108 if (!is_root) {
109 if ((error = VerifyCertTime(issuer, time)) != Error::Code::kNone) {
110 return error;
111 }
112 if (X509_NAME_cmp(X509_get_subject_name(issuer),
113 X509_get_issuer_name(issuer)) != 0) {
114 if (max_pathlen == 0) {
115 return Error::Code::kErrCertsPathlen;
116 }
117 --max_pathlen;
118 } else {
119 issuer->ex_flags |= EXFLAG_SI;
120 }
121 } else {
122 issuer->ex_flags |= EXFLAG_SI;
123 }
124
125 bssl::UniquePtr<ASN1_BIT_STRING> key_usage = GetKeyUsage(issuer);
126 if (key_usage) {
127 const int bit =
128 ASN1_BIT_STRING_get_bit(key_usage.get(), KeyUsageBits::kKeyCertSign);
129 if (bit == 0) {
130 return Error::Code::kErrCertsVerifyGeneric;
131 }
132 }
133
134 // Check that basicConstraints is present, specifies the CA bit, and use
135 // pathLenConstraint if present.
136 const int basic_constraints_index =
137 X509_get_ext_by_NID(issuer, NID_basic_constraints, -1);
138 if (basic_constraints_index == -1) {
139 return Error::Code::kErrCertsVerifyGeneric;
140 }
141 X509_EXTENSION* const basic_constraints_extension =
142 X509_get_ext(issuer, basic_constraints_index);
143 bssl::UniquePtr<BASIC_CONSTRAINTS> basic_constraints{
144 reinterpret_cast<BASIC_CONSTRAINTS*>(
145 X509V3_EXT_d2i(basic_constraints_extension))};
146
147 if (!basic_constraints || !basic_constraints->ca) {
148 return Error::Code::kErrCertsVerifyGeneric;
149 }
150
151 if (basic_constraints->pathlen) {
152 if (basic_constraints->pathlen->length != 1) {
153 return Error::Code::kErrCertsVerifyGeneric;
154 } else {
155 const int pathlen = *basic_constraints->pathlen->data;
156 if (pathlen < 0) {
157 return Error::Code::kErrCertsVerifyGeneric;
158 }
159 if (pathlen < max_pathlen) {
160 max_pathlen = pathlen;
161 }
162 }
163 }
164
165 if (X509_ALGOR_cmp(issuer->sig_alg, issuer->cert_info->signature) != 0) {
166 return Error::Code::kErrCertsVerifyGeneric;
167 }
168
169 bssl::UniquePtr<EVP_PKEY> public_key{X509_get_pubkey(issuer)};
170 if (!VerifyPublicKeyLength(public_key.get())) {
171 return Error::Code::kErrCertsVerifyGeneric;
172 }
173
174 // NOTE: (!self-issued || target) -> verify name constraints. Target case
175 // is after the loop.
176 const bool is_self_issued = issuer->ex_flags & EXFLAG_SI;
177 if (!is_self_issued) {
178 for (NAME_CONSTRAINTS* name_constraints : path_name_constraints) {
179 if (NAME_CONSTRAINTS_check(subject, name_constraints) != X509_V_OK) {
180 return Error::Code::kErrCertsVerifyGeneric;
181 }
182 }
183 }
184
185 if (issuer->nc) {
186 path_name_constraints.push_back(issuer->nc);
187 } else {
188 const int index = X509_get_ext_by_NID(issuer, NID_name_constraints, -1);
189 if (index != -1) {
190 X509_EXTENSION* ext = X509_get_ext(issuer, index);
191 auto* nc = reinterpret_cast<NAME_CONSTRAINTS*>(X509V3_EXT_d2i(ext));
192 if (nc) {
193 issuer->nc = nc;
194 path_name_constraints.push_back(nc);
195 } else {
196 return Error::Code::kErrCertsVerifyGeneric;
197 }
198 }
199 }
200
201 // Check that any policy mappings present are _not_ the anyPolicy OID. Even
202 // though we don't otherwise handle policies, this is required by RFC 5280
203 // 6.1.4(a).
204 const int policy_mappings_index =
205 X509_get_ext_by_NID(issuer, NID_policy_mappings, -1);
206 if (policy_mappings_index != -1) {
207 X509_EXTENSION* policy_mappings_extension =
208 X509_get_ext(issuer, policy_mappings_index);
209 auto* policy_mappings = reinterpret_cast<POLICY_MAPPINGS*>(
210 X509V3_EXT_d2i(policy_mappings_extension));
211 const uint32_t policy_mapping_count =
212 sk_POLICY_MAPPING_num(policy_mappings);
213 const ASN1_OBJECT* any_policy = OBJ_nid2obj(NID_any_policy);
214 for (uint32_t i = 0; i < policy_mapping_count; ++i) {
215 POLICY_MAPPING* policy_mapping =
216 sk_POLICY_MAPPING_value(policy_mappings, i);
217 const bool either_matches =
218 ((OBJ_cmp(policy_mapping->issuerDomainPolicy, any_policy) == 0) ||
219 (OBJ_cmp(policy_mapping->subjectDomainPolicy, any_policy) == 0));
220 if (either_matches) {
221 error = Error::Code::kErrCertsVerifyGeneric;
222 break;
223 }
224 }
225 sk_POLICY_MAPPING_free(policy_mappings);
226 if (error != Error::Code::kNone) {
227 return error;
228 }
229 }
230
231 // Check that we don't have any unhandled extensions marked as critical.
232 int extension_count = X509_get_ext_count(issuer);
233 for (int i = 0; i < extension_count; ++i) {
234 X509_EXTENSION* extension = X509_get_ext(issuer, i);
235 if (extension->critical > 0) {
236 const int nid = OBJ_obj2nid(extension->object);
237 if (nid != NID_name_constraints && nid != NID_basic_constraints &&
238 nid != NID_key_usage) {
239 return Error::Code::kErrCertsVerifyGeneric;
240 }
241 }
242 }
243
244 int nid = OBJ_obj2nid(subject->sig_alg->algorithm);
245 const EVP_MD* digest;
246 switch (nid) {
247 case NID_sha1WithRSAEncryption:
248 digest = EVP_sha1();
249 break;
250 case NID_sha256WithRSAEncryption:
251 digest = EVP_sha256();
252 break;
253 case NID_sha384WithRSAEncryption:
254 digest = EVP_sha384();
255 break;
256 case NID_sha512WithRSAEncryption:
257 digest = EVP_sha512();
258 break;
259 default:
260 return Error::Code::kErrCertsVerifyGeneric;
261 }
262 if (!VerifySignedData(
263 digest, public_key.get(),
264 {subject->cert_info->enc.enc,
265 static_cast<uint32_t>(subject->cert_info->enc.len)},
266 {subject->signature->data,
267 static_cast<uint32_t>(subject->signature->length)})) {
268 return Error::Code::kErrCertsVerifyGeneric;
269 }
270 }
271 // NOTE: Other half of ((!self-issued || target) -> check name constraints).
272 for (NAME_CONSTRAINTS* name_constraints : path_name_constraints) {
273 if (NAME_CONSTRAINTS_check(path.back().cert, name_constraints) !=
274 X509_V_OK) {
275 return Error::Code::kErrCertsVerifyGeneric;
276 }
277 }
278 return error;
279 }
280
ParseX509Der(const std::string & der)281 X509* ParseX509Der(const std::string& der) {
282 const uint8_t* data = reinterpret_cast<const uint8_t*>(der.data());
283 return d2i_X509(nullptr, &data, der.size());
284 }
285
286 } // namespace
287
288 // Parses DateTime with additional restrictions laid out by RFC 5280
289 // 4.1.2.5.2.
ParseAsn1GeneralizedTime(ASN1_GENERALIZEDTIME * time,DateTime * out)290 bool ParseAsn1GeneralizedTime(ASN1_GENERALIZEDTIME* time, DateTime* out) {
291 static constexpr uint8_t kDaysPerMonth[] = {
292 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
293 };
294
295 if (time->length != 15) {
296 return false;
297 }
298 if (time->data[14] != 'Z') {
299 return false;
300 }
301 for (int i = 0; i < 14; ++i) {
302 if (time->data[i] < '0' || time->data[i] > '9') {
303 return false;
304 }
305 }
306 out->year = ParseAsn1TimeDoubleDigit(time, 0) * 100 +
307 ParseAsn1TimeDoubleDigit(time, 2);
308 out->month = ParseAsn1TimeDoubleDigit(time, 4);
309 out->day = ParseAsn1TimeDoubleDigit(time, 6);
310 out->hour = ParseAsn1TimeDoubleDigit(time, 8);
311 out->minute = ParseAsn1TimeDoubleDigit(time, 10);
312 out->second = ParseAsn1TimeDoubleDigit(time, 12);
313 if (out->month == 0 || out->month > 12) {
314 return false;
315 }
316 int days_per_month = kDaysPerMonth[out->month - 1];
317 if (out->month == 2) {
318 if (out->year % 4 == 0 && (out->year % 100 != 0 || out->year % 400 == 0)) {
319 days_per_month = 29;
320 } else {
321 days_per_month = 28;
322 }
323 }
324 if (out->day == 0 || out->day > days_per_month) {
325 return false;
326 }
327 if (out->hour > 23) {
328 return false;
329 }
330 if (out->minute > 59) {
331 return false;
332 }
333 // Leap seconds are allowed.
334 if (out->second > 60) {
335 return false;
336 }
337 return true;
338 }
339
GetCertValidTimeRange(X509 * cert,DateTime * not_before,DateTime * not_after)340 bool GetCertValidTimeRange(X509* cert,
341 DateTime* not_before,
342 DateTime* not_after) {
343 ASN1_GENERALIZEDTIME* not_before_asn1 = ASN1_TIME_to_generalizedtime(
344 cert->cert_info->validity->notBefore, nullptr);
345 ASN1_GENERALIZEDTIME* not_after_asn1 = ASN1_TIME_to_generalizedtime(
346 cert->cert_info->validity->notAfter, nullptr);
347 if (!not_before_asn1 || !not_after_asn1) {
348 return false;
349 }
350 bool times_valid = ParseAsn1GeneralizedTime(not_before_asn1, not_before) &&
351 ParseAsn1GeneralizedTime(not_after_asn1, not_after);
352 ASN1_GENERALIZEDTIME_free(not_before_asn1);
353 ASN1_GENERALIZEDTIME_free(not_after_asn1);
354 return times_valid;
355 }
356
VerifySignedData(const EVP_MD * digest,EVP_PKEY * public_key,const ConstDataSpan & data,const ConstDataSpan & signature)357 bool VerifySignedData(const EVP_MD* digest,
358 EVP_PKEY* public_key,
359 const ConstDataSpan& data,
360 const ConstDataSpan& signature) {
361 // This code assumes the signature algorithm was RSASSA PKCS#1 v1.5 with
362 // |digest|.
363 bssl::ScopedEVP_MD_CTX ctx;
364 if (!EVP_DigestVerifyInit(ctx.get(), nullptr, digest, nullptr, public_key)) {
365 return false;
366 }
367 return (EVP_DigestVerify(ctx.get(), signature.data, signature.length,
368 data.data, data.length) == 1);
369 }
370
FindCertificatePath(const std::vector<std::string> & der_certs,const DateTime & time,CertificatePathResult * result_path,TrustStore * trust_store)371 Error FindCertificatePath(const std::vector<std::string>& der_certs,
372 const DateTime& time,
373 CertificatePathResult* result_path,
374 TrustStore* trust_store) {
375 if (der_certs.empty()) {
376 return Error::Code::kErrCertsMissing;
377 }
378
379 bssl::UniquePtr<X509>& target_cert = result_path->target_cert;
380 std::vector<bssl::UniquePtr<X509>>& intermediate_certs =
381 result_path->intermediate_certs;
382 target_cert.reset(ParseX509Der(der_certs[0]));
383 if (!target_cert) {
384 return Error::Code::kErrCertsParse;
385 }
386 for (size_t i = 1; i < der_certs.size(); ++i) {
387 intermediate_certs.emplace_back(ParseX509Der(der_certs[i]));
388 if (!intermediate_certs.back()) {
389 return Error::Code::kErrCertsParse;
390 }
391 }
392
393 // Basic checks on the target certificate.
394 Error::Code error = VerifyCertTime(target_cert.get(), time);
395 if (error != Error::Code::kNone) {
396 return error;
397 }
398 bssl::UniquePtr<EVP_PKEY> public_key{X509_get_pubkey(target_cert.get())};
399 if (!VerifyPublicKeyLength(public_key.get())) {
400 return Error::Code::kErrCertsVerifyGeneric;
401 }
402 if (X509_ALGOR_cmp(target_cert.get()->sig_alg,
403 target_cert.get()->cert_info->signature) != 0) {
404 return Error::Code::kErrCertsVerifyGeneric;
405 }
406 bssl::UniquePtr<ASN1_BIT_STRING> key_usage = GetKeyUsage(target_cert.get());
407 if (!key_usage) {
408 return Error::Code::kErrCertsRestrictions;
409 }
410 int bit =
411 ASN1_BIT_STRING_get_bit(key_usage.get(), KeyUsageBits::kDigitalSignature);
412 if (bit == 0) {
413 return Error::Code::kErrCertsRestrictions;
414 }
415
416 X509* path_head = target_cert.get();
417 std::vector<CertPathStep> path;
418
419 // This vector isn't used as resizable, so instead we allocate the largest
420 // possible single path up front. This would be a single trusted cert, all
421 // the intermediate certs used once, and the target cert.
422 path.resize(1 + intermediate_certs.size() + 1);
423
424 // Additionally, the path is slightly simpler to deal with if the list is
425 // sorted from trust->target, so the path is actually built starting from the
426 // end.
427 uint32_t first_index = path.size() - 1;
428 path[first_index].cert = path_head;
429
430 // Index into |path| of the current frontier of path construction.
431 uint32_t path_index = first_index;
432
433 // Whether |path| has reached a certificate in |trust_store| and is ready for
434 // verification.
435 bool path_cert_in_trust_store = false;
436
437 // Attempt to build a valid certificate chain from |target_cert| to a
438 // certificate in |trust_store|. This loop tries all possible paths in a
439 // depth-first-search fashion. If no valid paths are found, the error
440 // returned is whatever the last error was from the last path tried.
441 uint32_t trust_store_index = 0;
442 uint32_t intermediate_cert_index = 0;
443 Error::Code last_error = Error::Code::kNone;
444 for (;;) {
445 X509_NAME* target_issuer_name = X509_get_issuer_name(path_head);
446
447 // The next issuer certificate to add to the current path.
448 X509* next_issuer = nullptr;
449
450 for (uint32_t i = trust_store_index; i < trust_store->certs.size(); ++i) {
451 X509* trust_store_cert = trust_store->certs[i].get();
452 X509_NAME* trust_store_cert_name =
453 X509_get_subject_name(trust_store_cert);
454 if (X509_NAME_cmp(trust_store_cert_name, target_issuer_name) == 0) {
455 CertPathStep& next_step = path[--path_index];
456 next_step.cert = trust_store_cert;
457 next_step.trust_store_index = i + 1;
458 next_step.intermediate_cert_index = 0;
459 next_issuer = trust_store_cert;
460 path_cert_in_trust_store = true;
461 break;
462 }
463 }
464 trust_store_index = 0;
465 if (!next_issuer) {
466 for (uint32_t i = intermediate_cert_index; i < intermediate_certs.size();
467 ++i) {
468 X509* intermediate_cert = intermediate_certs[i].get();
469 X509_NAME* intermediate_cert_name =
470 X509_get_subject_name(intermediate_cert);
471 if (X509_NAME_cmp(intermediate_cert_name, target_issuer_name) == 0 &&
472 !CertInPath(intermediate_cert_name, path, path_index,
473 first_index)) {
474 CertPathStep& next_step = path[--path_index];
475 next_step.cert = intermediate_cert;
476 next_step.trust_store_index = trust_store->certs.size();
477 next_step.intermediate_cert_index = i + 1;
478 next_issuer = intermediate_cert;
479 break;
480 }
481 }
482 }
483 intermediate_cert_index = 0;
484 if (!next_issuer) {
485 if (path_index == first_index) {
486 // There are no more paths to try. Ensure an error is returned.
487 if (last_error == Error::Code::kNone) {
488 return Error::Code::kErrCertsVerifyGeneric;
489 }
490 return last_error;
491 } else {
492 CertPathStep& last_step = path[path_index++];
493 trust_store_index = last_step.trust_store_index;
494 intermediate_cert_index = last_step.intermediate_cert_index;
495 continue;
496 }
497 }
498
499 if (path_cert_in_trust_store) {
500 last_error = VerifyCertificateChain(path, path_index, time);
501 if (last_error != Error::Code::kNone) {
502 CertPathStep& last_step = path[path_index++];
503 trust_store_index = last_step.trust_store_index;
504 intermediate_cert_index = last_step.intermediate_cert_index;
505 path_cert_in_trust_store = false;
506 } else {
507 break;
508 }
509 }
510 path_head = next_issuer;
511 }
512
513 result_path->path.reserve(path.size() - path_index);
514 for (uint32_t i = path_index; i < path.size(); ++i) {
515 result_path->path.push_back(path[i].cert);
516 }
517
518 return Error::Code::kNone;
519 }
520
521 } // namespace cast
522 } // namespace openscreen
523