cast_cert_validator.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  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
  3. // found in the LICENSE file.
  4. #include "components/cast_certificate/cast_cert_validator.h"
  5. #include <stddef.h>
  6. #include <stdint.h>
  7. #include <algorithm>
  8. #include <memory>
  9. #include <utility>
  10. #include "base/containers/contains.h"
  11. #include "base/containers/span.h"
  12. #include "base/logging.h"
  13. #include "base/no_destructor.h"
  14. #include "base/strings/string_piece.h"
  15. #include "base/synchronization/lock.h"
  16. #include "base/task/task_traits.h"
  17. #include "base/task/thread_pool.h"
  18. #include "components/cast_certificate/cast_crl.h"
  19. #include "net/cert/pki/cert_issuer_source_static.h"
  20. #include "net/cert/pki/certificate_policies.h"
  21. #include "net/cert/pki/common_cert_errors.h"
  22. #include "net/cert/pki/parse_certificate.h"
  23. #include "net/cert/pki/parse_name.h"
  24. #include "net/cert/pki/parsed_certificate.h"
  25. #include "net/cert/pki/path_builder.h"
  26. #include "net/cert/pki/simple_path_builder_delegate.h"
  27. #include "net/cert/pki/trust_store_in_memory.h"
  28. #include "net/cert/x509_util.h"
  29. #include "net/der/encode_values.h"
  30. #include "net/der/input.h"
  31. #include "third_party/boringssl/src/include/openssl/bytestring.h"
  32. #include "third_party/boringssl/src/include/openssl/digest.h"
  33. #include "third_party/boringssl/src/include/openssl/evp.h"
  34. // Used specifically when CAST_ALLOW_DEVELOPER_CERTIFICATE is true:
  35. #include "base/command_line.h"
  36. #include "base/memory/weak_ptr.h"
  37. #include "base/path_service.h"
  38. #include "components/cast_certificate/cast_cert_reader.h"
  39. #include "components/cast_certificate/switches.h"
  40. namespace cast_certificate {
  41. namespace {
  42. #define RETURN_STRING_LITERAL(x) \
  43. case x: \
  44. return #x;
  45. // -------------------------------------------------------------------------
  46. // Cast trust anchors.
  47. // -------------------------------------------------------------------------
  48. // There are two trusted roots for Cast certificate chains:
  49. //
  50. // (1) CN=Cast Root CA (kCastRootCaDer)
  51. // (2) CN=Eureka Root CA (kEurekaRootCaDer)
  52. //
  53. // These constants are defined by the files included next:
  54. #include "components/cast_certificate/cast_root_ca_cert_der-inc.h"
  55. #include "components/cast_certificate/eureka_root_ca_der-inc.h"
  56. class CastTrustStore {
  57. public:
  58. using AccessCallback = base::OnceCallback<void(net::TrustStore*)>;
  59. CastTrustStore(const CastTrustStore&) = delete;
  60. CastTrustStore& operator=(const CastTrustStore&) = delete;
  61. static void AccessInstance(AccessCallback callback) {
  62. CastTrustStore* instance = GetInstance();
  63. const base::AutoLock guard(instance->lock_);
  64. std::move(callback).Run(&instance->store_);
  65. }
  66. private:
  67. friend class base::NoDestructor<CastTrustStore>;
  68. static CastTrustStore* GetInstance() {
  69. static base::NoDestructor<CastTrustStore> instance;
  70. return instance.get();
  71. }
  72. CastTrustStore() {
  73. AddAnchor(kCastRootCaDer);
  74. AddAnchor(kEurekaRootCaDer);
  75. // Adding developer certificates must be done off of the IO thread due
  76. // to blocking file access.
  77. #if defined(CAST_ALLOW_DEVELOPER_CERTIFICATE)
  78. base::ThreadPool::PostTask(
  79. FROM_HERE, {base::MayBlock()},
  80. // NOTE: the singleton instance is never destroyed, so we can use
  81. // Unretained here instead of a weak pointer.
  82. base::BindOnce(&CastTrustStore::AddDeveloperCertificates,
  83. base::Unretained(this)));
  84. }
  85. // Check for custom root developer certificate and create a trust store
  86. // from it if present and enabled.
  87. void AddDeveloperCertificates() {
  88. base::AutoLock guard(lock_);
  89. auto* command_line = base::CommandLine::ForCurrentProcess();
  90. std::string cert_path_arg = command_line->GetSwitchValueASCII(
  91. switches::kCastDeveloperCertificatePath);
  92. if (!cert_path_arg.empty()) {
  93. base::FilePath cert_path(cert_path_arg);
  94. if (!cert_path.IsAbsolute()) {
  95. base::FilePath path;
  96. base::PathService::Get(base::DIR_CURRENT, &path);
  97. cert_path = path.Append(cert_path);
  98. }
  99. VLOG(1) << "Using cast developer certificate path " << cert_path;
  100. if (!PopulateStoreWithCertsFromPath(&store_, cert_path)) {
  101. LOG(WARNING) << "No developer certs added to store, only official"
  102. "Google root CA certificates will work.";
  103. }
  104. }
  105. #endif
  106. }
  107. // Adds a trust anchor given a DER-encoded certificate from static
  108. // storage.
  109. template <size_t N>
  110. void AddAnchor(const uint8_t (&data)[N]) {
  111. net::CertErrors errors;
  112. scoped_refptr<net::ParsedCertificate> cert = net::ParsedCertificate::Create(
  113. net::x509_util::CreateCryptoBufferFromStaticDataUnsafe(data), {},
  114. &errors);
  115. CHECK(cert) << errors.ToDebugString();
  116. // Enforce pathlen constraints and policies defined on the root certificate.
  117. base::AutoLock guard(lock_);
  118. store_.AddTrustAnchorWithConstraints(std::move(cert));
  119. }
  120. base::Lock lock_;
  121. net::TrustStoreInMemory store_ GUARDED_BY(lock_);
  122. };
  123. // Returns the OID for the Audio-Only Cast policy
  124. // (1.3.6.1.4.1.11129.2.5.2) in DER form.
  125. net::der::Input AudioOnlyPolicyOid() {
  126. static const uint8_t kAudioOnlyPolicy[] = {0x2B, 0x06, 0x01, 0x04, 0x01,
  127. 0xD6, 0x79, 0x02, 0x05, 0x02};
  128. return net::der::Input(kAudioOnlyPolicy);
  129. }
  130. // Cast certificates rely on RSASSA-PKCS#1 v1.5 with SHA-1 for signatures.
  131. //
  132. // The following delegate will allow signature algorithms of:
  133. //
  134. // * ECDSA, RSA-SSA, and RSA-PSS
  135. // * Supported EC curves: P-256, P-384, P-521.
  136. // * Hashes: All SHA hashes including SHA-1 (despite being known weak).
  137. //
  138. // It will also require RSA keys have a modulus at least 2048-bits long.
  139. class CastPathBuilderDelegate : public net::SimplePathBuilderDelegate {
  140. public:
  141. CastPathBuilderDelegate()
  142. : SimplePathBuilderDelegate(
  143. 2048,
  144. SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1) {}
  145. };
  146. class CertVerificationContextImpl : public CertVerificationContext {
  147. public:
  148. // Save a copy of the passed in public key and common name (text).
  149. CertVerificationContextImpl(bssl::UniquePtr<EVP_PKEY> key,
  150. base::StringPiece common_name)
  151. : key_(std::move(key)), common_name_(common_name) {}
  152. bool VerifySignatureOverData(
  153. const base::StringPiece& signature,
  154. const base::StringPiece& data,
  155. CastDigestAlgorithm digest_algorithm) const override {
  156. const EVP_MD* digest = nullptr;
  157. switch (digest_algorithm) {
  158. case CastDigestAlgorithm::SHA1:
  159. digest = EVP_sha1();
  160. break;
  161. case CastDigestAlgorithm::SHA256:
  162. digest = EVP_sha256();
  163. break;
  164. };
  165. // Verify with RSASSA-PKCS1-v1_5 and |digest|.
  166. auto signature_bytes = base::as_bytes(base::make_span(signature));
  167. auto data_bytes = base::as_bytes(base::make_span(data));
  168. bssl::ScopedEVP_MD_CTX ctx;
  169. return EVP_PKEY_id(key_.get()) == EVP_PKEY_RSA &&
  170. EVP_DigestVerifyInit(ctx.get(), nullptr, digest, nullptr,
  171. key_.get()) &&
  172. EVP_DigestVerify(ctx.get(), signature_bytes.data(),
  173. signature_bytes.size(), data_bytes.data(),
  174. data_bytes.size());
  175. }
  176. std::string GetCommonName() const override { return common_name_; }
  177. private:
  178. bssl::UniquePtr<EVP_PKEY> key_;
  179. std::string common_name_;
  180. };
  181. // Helper that extracts the Common Name from a certificate's subject field. On
  182. // success |common_name| contains the text for the attribute (UTF-8, but for
  183. // Cast device certs it should be ASCII).
  184. bool GetCommonNameFromSubject(const net::der::Input& subject_tlv,
  185. std::string* common_name) {
  186. net::RDNSequence rdn_sequence;
  187. if (!net::ParseName(subject_tlv, &rdn_sequence))
  188. return false;
  189. for (const net::RelativeDistinguishedName& rdn : rdn_sequence) {
  190. for (const auto& atv : rdn) {
  191. if (atv.type == net::der::Input(net::kTypeCommonNameOid)) {
  192. return atv.ValueAsString(common_name);
  193. }
  194. }
  195. }
  196. return false;
  197. }
  198. // Cast device certificates use the policy 1.3.6.1.4.1.11129.2.5.2 to indicate
  199. // it is *restricted* to an audio-only device whereas the absence of a policy
  200. // means it is unrestricted.
  201. //
  202. // This is somewhat different than RFC 5280's notion of policies, so policies
  203. // are checked separately outside of path building.
  204. //
  205. // See the unit-tests VerifyCastDeviceCertTest.Policies* for some
  206. // concrete examples of how this works.
  207. void DetermineDeviceCertificatePolicy(
  208. const net::CertPathBuilderResultPath* result_path,
  209. CastDeviceCertPolicy* policy) {
  210. // Iterate over all the certificates, including the root certificate. If any
  211. // certificate contains the audio-only policy, the whole chain is considered
  212. // constrained to audio-only device certificates.
  213. //
  214. // Policy mappings are not accounted for. The expectation is that top-level
  215. // intermediates issued with audio-only will have no mappings. If subsequent
  216. // certificates in the chain do, it won't matter as the chain is already
  217. // restricted to being audio-only.
  218. bool audio_only = false;
  219. for (const auto& cert : result_path->certs) {
  220. if (cert->has_policy_oids()) {
  221. const std::vector<net::der::Input>& policies = cert->policy_oids();
  222. if (base::Contains(policies, AudioOnlyPolicyOid())) {
  223. audio_only = true;
  224. break;
  225. }
  226. }
  227. }
  228. *policy = audio_only ? CastDeviceCertPolicy::AUDIO_ONLY
  229. : CastDeviceCertPolicy::NONE;
  230. }
  231. // Checks properties on the target certificate.
  232. //
  233. // * The Key Usage must include Digital Signature
  234. [[nodiscard]] bool CheckTargetCertificate(
  235. const net::ParsedCertificate* cert,
  236. std::unique_ptr<CertVerificationContext>* context) {
  237. // Get the Key Usage extension.
  238. if (!cert->has_key_usage())
  239. return false;
  240. // Ensure Key Usage contains digitalSignature.
  241. if (!cert->key_usage().AssertsBit(net::KEY_USAGE_BIT_DIGITAL_SIGNATURE))
  242. return false;
  243. // Get the Common Name for the certificate.
  244. std::string common_name;
  245. if (!GetCommonNameFromSubject(cert->tbs().subject_tlv, &common_name))
  246. return false;
  247. // Get the public key for the certificate.
  248. CBS spki;
  249. CBS_init(&spki, cert->tbs().spki_tlv.UnsafeData(),
  250. cert->tbs().spki_tlv.Length());
  251. bssl::UniquePtr<EVP_PKEY> key(EVP_parse_public_key(&spki));
  252. if (!key || CBS_len(&spki) != 0)
  253. return false;
  254. *context = std::make_unique<CertVerificationContextImpl>(std::move(key),
  255. common_name);
  256. return true;
  257. }
  258. // Returns the parsing options used for Cast certificates.
  259. net::ParseCertificateOptions GetCertParsingOptions() {
  260. net::ParseCertificateOptions options;
  261. // Some cast intermediate certificates contain serial numbers that are
  262. // 21 octets long, and might also not use valid DER encoding for an
  263. // INTEGER (non-minimal encoding).
  264. //
  265. // Allow these sorts of serial numbers.
  266. //
  267. // TODO(eroman): At some point in the future this workaround will no longer be
  268. // necessary. Should revisit this for removal in 2017 if not earlier.
  269. options.allow_invalid_serial_numbers = true;
  270. return options;
  271. }
  272. // Returns the CastCertError for the failed path building.
  273. // This function must only be called if path building failed.
  274. CastCertError MapToCastError(const net::CertPathBuilder::Result& result) {
  275. DCHECK(!result.HasValidPath());
  276. if (result.paths.empty())
  277. return CastCertError::ERR_CERTS_VERIFY_GENERIC;
  278. const net::CertPathErrors& path_errors =
  279. result.paths.at(result.best_result_index)->errors;
  280. if (path_errors.ContainsError(net::cert_errors::kValidityFailedNotAfter) ||
  281. path_errors.ContainsError(net::cert_errors::kValidityFailedNotBefore)) {
  282. return CastCertError::ERR_CERTS_DATE_INVALID;
  283. }
  284. return CastCertError::ERR_CERTS_VERIFY_GENERIC;
  285. }
  286. } // namespace
  287. CastCertError VerifyDeviceCert(
  288. const std::vector<std::string>& certs,
  289. const base::Time& time,
  290. std::unique_ptr<CertVerificationContext>* context,
  291. CastDeviceCertPolicy* policy,
  292. const CastCRL* crl,
  293. CRLPolicy crl_policy) {
  294. CastCertError verification_result;
  295. CastTrustStore::AccessInstance(base::BindOnce(
  296. [](const std::vector<std::string>& certs, const base::Time& time,
  297. std::unique_ptr<CertVerificationContext>* context,
  298. CastDeviceCertPolicy* policy, const CastCRL* crl, CRLPolicy crl_policy,
  299. CastCertError* result, net::TrustStore* store) {
  300. *result = VerifyDeviceCertUsingCustomTrustStore(
  301. certs, time, context, policy, crl, crl_policy, store);
  302. },
  303. certs, time, context, policy, crl, crl_policy, &verification_result));
  304. return verification_result;
  305. }
  306. CastCertError VerifyDeviceCertUsingCustomTrustStore(
  307. const std::vector<std::string>& certs,
  308. const base::Time& time,
  309. std::unique_ptr<CertVerificationContext>* context,
  310. CastDeviceCertPolicy* policy,
  311. const CastCRL* crl,
  312. CRLPolicy crl_policy,
  313. net::TrustStore* trust_store) {
  314. if (!trust_store)
  315. return VerifyDeviceCert(certs, time, context, policy, crl, crl_policy);
  316. if (certs.empty())
  317. return CastCertError::ERR_CERTS_MISSING;
  318. // Fail early if CRL is required but not provided.
  319. if (!crl && crl_policy == CRLPolicy::CRL_REQUIRED)
  320. return CastCertError::ERR_CRL_INVALID;
  321. net::CertErrors errors;
  322. scoped_refptr<net::ParsedCertificate> target_cert;
  323. net::CertIssuerSourceStatic intermediate_cert_issuer_source;
  324. for (size_t i = 0; i < certs.size(); ++i) {
  325. scoped_refptr<net::ParsedCertificate> cert(net::ParsedCertificate::Create(
  326. net::x509_util::CreateCryptoBuffer(certs[i]), GetCertParsingOptions(),
  327. &errors));
  328. if (!cert)
  329. return CastCertError::ERR_CERTS_PARSE;
  330. if (i == 0)
  331. target_cert = std::move(cert);
  332. else
  333. intermediate_cert_issuer_source.AddCert(std::move(cert));
  334. }
  335. CastPathBuilderDelegate path_builder_delegate;
  336. // Do path building and RFC 5280 compatible certificate verification using the
  337. // two Cast trust anchors and Cast signature policy.
  338. net::der::GeneralizedTime verification_time;
  339. if (!net::der::EncodeTimeAsGeneralizedTime(time, &verification_time))
  340. return CastCertError::ERR_UNEXPECTED;
  341. net::CertPathBuilder path_builder(
  342. target_cert.get(), trust_store, &path_builder_delegate, verification_time,
  343. net::KeyPurpose::CLIENT_AUTH, net::InitialExplicitPolicy::kFalse,
  344. {net::der::Input(net::kAnyPolicyOid)},
  345. net::InitialPolicyMappingInhibit::kFalse,
  346. net::InitialAnyPolicyInhibit::kFalse);
  347. path_builder.AddCertIssuerSource(&intermediate_cert_issuer_source);
  348. net::CertPathBuilder::Result result = path_builder.Run();
  349. if (!result.HasValidPath())
  350. return MapToCastError(result);
  351. // Determine whether this device certificate is restricted to audio-only.
  352. DetermineDeviceCertificatePolicy(result.GetBestValidPath(), policy);
  353. // Check properties of the leaf certificate not already verified by path
  354. // building (key usage), and construct a CertVerificationContext that uses
  355. // its public key.
  356. if (!CheckTargetCertificate(target_cert.get(), context))
  357. return CastCertError::ERR_CERTS_RESTRICTIONS;
  358. // Check for revocation.
  359. if (crl && !crl->CheckRevocation(result.GetBestValidPath()->certs, time))
  360. return CastCertError::ERR_CERTS_REVOKED;
  361. return CastCertError::OK;
  362. }
  363. std::string CastCertErrorToString(CastCertError error) {
  364. switch (error) {
  365. RETURN_STRING_LITERAL(CastCertError::ERR_CERTS_MISSING);
  366. RETURN_STRING_LITERAL(CastCertError::ERR_CERTS_PARSE);
  367. RETURN_STRING_LITERAL(CastCertError::ERR_CERTS_DATE_INVALID);
  368. RETURN_STRING_LITERAL(CastCertError::ERR_CERTS_VERIFY_GENERIC);
  369. RETURN_STRING_LITERAL(CastCertError::ERR_CERTS_RESTRICTIONS);
  370. RETURN_STRING_LITERAL(CastCertError::ERR_CRL_INVALID);
  371. RETURN_STRING_LITERAL(CastCertError::ERR_CERTS_REVOKED);
  372. RETURN_STRING_LITERAL(CastCertError::ERR_UNEXPECTED);
  373. RETURN_STRING_LITERAL(CastCertError::OK);
  374. }
  375. return "CastCertError::UNKNOWN";
  376. }
  377. } // namespace cast_certificate