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, &not_before, &not_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