Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3258)

Unified Diff: extensions/browser/api/cast_channel/cast_auth_util.cc

Issue 2303673004: Hook up Chrome Cast sender to Cast CRL. (Closed)
Patch Set: VerifyDeviceCertUsingCustomTrustStore and ParseAndVerifyCRLUsingCustomTrustStore Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: extensions/browser/api/cast_channel/cast_auth_util.cc
diff --git a/extensions/browser/api/cast_channel/cast_auth_util.cc b/extensions/browser/api/cast_channel/cast_auth_util.cc
index 0e5c38844cbe1e84e1e8210a4c4bbd56a9ac34ea..ababaa82fb3723cf2fd2f181ecbaf1e8a92e37e9 100644
--- a/extensions/browser/api/cast_channel/cast_auth_util.cc
+++ b/extensions/browser/api/cast_channel/cast_auth_util.cc
@@ -8,9 +8,12 @@
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/singleton.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "components/cast_certificate/cast_cert_validator.h"
+#include "components/cast_certificate/cast_crl.h"
+#include "crypto/sha2.h"
#include "extensions/browser/api/cast_channel/cast_message_util.h"
#include "extensions/common/api/cast_channel/cast_channel.pb.h"
#include "net/cert/x509_certificate.h"
@@ -26,6 +29,10 @@ const char* const kParseErrorPrefix = "Failed to parse auth message: ";
// The maximum number of days a cert can live for.
const int kMaxSelfSignedCertLifetimeInDays = 4;
+// Enforce certificate revocation when set to true.
+// If set to false, then any revocation failures are ignored.
+const bool kEnforceRevocationCheck = false;
eroman 2016/09/10 01:03:23 Who is the intended consumer that would set this t
ryanchung 2016/09/14 18:53:39 This is for a future switchover. Eventually, we'll
+
namespace cast_crypto = ::cast_certificate;
// Extracts an embedded DeviceAuthMessage payload from an auth challenge reply
@@ -126,17 +133,72 @@ AuthResult AuthenticateChallengeReply(const CastMessage& challenge_reply,
return VerifyCredentials(response, peer_cert_der);
}
+// Singleton for the Cast CRL cache.
+class CastCRLCache {
+ public:
+ static CastCRLCache* GetInstance() {
+ return base::Singleton<CastCRLCache,
+ base::LeakySingletonTraits<CastCRLCache>>::get();
+ }
+
+ static cast_crypto::CastCRL* Get(const std::string& crl_bundle) {
+ if (crl_bundle.empty())
+ return nullptr;
+ CastCRLCache* cache = GetInstance();
+ std::string crl_bundle_hash = crypto::SHA256HashString(crl_bundle);
+ if (cache->hash_.compare(crl_bundle_hash) == 0) {
eroman 2016/09/10 01:03:23 Does this work: cache->hash == crl_bundle_hash
ryanchung 2016/09/14 18:53:39 Done.
+ return cache->crl_.get();
+ } else {
+ return nullptr;
+ }
+ }
+
+ static cast_crypto::CastCRL* Put(const std::string& crl_bundle,
+ std::unique_ptr<cast_crypto::CastCRL> crl) {
+ if (crl_bundle.empty() || crl == nullptr)
+ return nullptr;
+ CastCRLCache* cache = GetInstance();
+ cache->hash_ = crypto::SHA256HashString(crl_bundle);
+ cache->crl_ = std::move(crl);
+ return cache->crl_.get();
+ }
+
+ private:
+ friend struct base::DefaultSingletonTraits<CastCRLCache>;
+
+ CastCRLCache() : crl_(nullptr), hash_() {}
+
+ std::unique_ptr<cast_crypto::CastCRL> crl_;
+ std::string hash_;
+ DISALLOW_COPY_AND_ASSIGN(CastCRLCache);
+};
+
// This function does the following
//
// * Verifies that the certificate chain |response.client_auth_certificate| +
// |response.intermediate_certificate| is valid and chains to a trusted
-// Cast root.
+// Cast root. The list of trusted Cast roots can be overrided by providing a
+// non-nullptr |cast_trust_store|. The certificate is verified at
+// |cert_verification_time|.
+//
+// * Verifies that none of the certificates in the chain are revoked based on
+// the CRL provided in the response |response.crl|. The CRL is verified to be
+// valid and its issuer certificate chains to a trusted Cast CRL root. The
+// list of trusted Cast CRL roots can be overrided by providing a non-nullptr
+// |crl_trust_store|. If |crl_policy| is CRL_OPTIONAL then the result of
+// revocation checking is ignored. The CRL is verified at
+// |crl_verification_time|.
//
// * Verifies that |response.signature| matches the signature
// of |signature_input| by |response.client_auth_certificate|'s public
// key.
-AuthResult VerifyCredentials(const AuthResponse& response,
- const std::string& signature_input) {
+AuthResult VerifyCredentialsImpl(const AuthResponse& response,
+ const std::string& signature_input,
+ const cast_crypto::CRLPolicy& crl_policy,
+ net::TrustStore* cast_trust_store,
+ net::TrustStore* crl_trust_store,
+ const base::Time& cert_verification_time,
+ const base::Time& crl_verification_time) {
// Verify the certificate
std::unique_ptr<cast_crypto::CertVerificationContext> verification_context;
@@ -147,19 +209,64 @@ AuthResult VerifyCredentials(const AuthResponse& response,
response.intermediate_certificate().begin(),
response.intermediate_certificate().end());
- // Use the current time when checking certificate validity.
- base::Time now = base::Time::Now();
+ // Parse the CRL.
+ cast_crypto::CastCRL* crl = CastCRLCache::Get(response.crl());
+ if (crl == nullptr) {
+ std::unique_ptr<cast_crypto::CastCRL> crl_parsed;
+ if (crl_trust_store) {
+ crl_parsed = cast_crypto::ParseAndVerifyCRLUsingCustomTrustStore(
+ response.crl(), crl_verification_time, crl_trust_store);
+ } else {
+ crl_parsed =
+ cast_crypto::ParseAndVerifyCRL(response.crl(), crl_verification_time);
+ }
- // CRL should not be enforced until it is served.
- cast_crypto::CastDeviceCertPolicy device_policy;
- if (!cast_crypto::VerifyDeviceCert(
- cert_chain, now, &verification_context, &device_policy, nullptr,
- cast_certificate::CRLPolicy::CRL_OPTIONAL)) {
- // TODO(eroman): The error information was lost; this error is ambiguous.
- return AuthResult("Failed verifying cast device certificate",
- AuthResult::ERROR_CERT_NOT_SIGNED_BY_TRUSTED_CA);
+ crl = CastCRLCache::Put(response.crl(), std::move(crl_parsed));
+ }
+ if (!crl && crl_policy == cast_crypto::CRLPolicy::CRL_REQUIRED) {
+ // CRL is invalid.
+ return AuthResult("Failed verifying Cast CRL.",
+ AuthResult::ERROR_CRL_INVALID);
}
+ cast_crypto::CastDeviceCertPolicy device_policy;
+ bool verification_success;
+ if (cast_trust_store) {
+ verification_success = cast_crypto::VerifyDeviceCertUsingCustomTrustStore(
+ cert_chain, cert_verification_time, &verification_context,
+ &device_policy, crl, crl_policy, cast_trust_store);
+ } else {
+ verification_success = cast_crypto::VerifyDeviceCert(
+ cert_chain, cert_verification_time, &verification_context,
+ &device_policy, crl, crl_policy);
+ }
+ if (!verification_success) {
+ // TODO(ryanchung): Once this feature is completely rolled-out, remove the
+ // reverification step and use error reporting to get verification errors
+ // for metrics.
+ bool verification_no_crl_success;
+ if (cast_trust_store) {
+ verification_no_crl_success =
+ cast_crypto::VerifyDeviceCertUsingCustomTrustStore(
+ cert_chain, cert_verification_time, &verification_context,
+ &device_policy, nullptr, cast_crypto::CRLPolicy::CRL_OPTIONAL,
+ cast_trust_store);
+ } else {
+ verification_no_crl_success = cast_crypto::VerifyDeviceCert(
+ cert_chain, cert_verification_time, &verification_context,
+ &device_policy, nullptr, cast_crypto::CRLPolicy::CRL_OPTIONAL);
+ }
+ if (!verification_no_crl_success) {
+ // TODO(eroman): The error information was lost; this error is ambiguous.
+ return AuthResult("Failed verifying cast device certificate",
+ AuthResult::ERROR_CERT_NOT_SIGNED_BY_TRUSTED_CA);
+ }
+ if (crl_policy == cast_crypto::CRLPolicy::CRL_REQUIRED) {
+ // Device is revoked.
+ return AuthResult("Failed certificate revocation check.",
+ AuthResult::ERROR_CERT_REVOKED);
+ }
+ }
if (!verification_context->VerifySignatureOverData(response.signature(),
signature_input)) {
return AuthResult("Failed verifying signature over data",
@@ -181,6 +288,29 @@ AuthResult VerifyCredentials(const AuthResponse& response,
return success;
}
+AuthResult VerifyCredentials(const AuthResponse& response,
+ const std::string& signature_input) {
+ base::Time now = base::Time::Now();
+ cast_crypto::CRLPolicy policy = cast_crypto::CRLPolicy::CRL_REQUIRED;
+ if (!kEnforceRevocationCheck) {
+ policy = cast_crypto::CRLPolicy::CRL_OPTIONAL;
+ }
+ return VerifyCredentialsImpl(response, signature_input, policy, nullptr,
+ nullptr, now, now);
+}
+
+AuthResult VerifyCredentialsForTest(const AuthResponse& response,
+ const std::string& signature_input,
+ const cast_crypto::CRLPolicy& crl_policy,
+ net::TrustStore* cast_trust_store,
+ net::TrustStore* crl_trust_store,
+ const base::Time& cert_verification_time,
+ const base::Time& crl_verification_time) {
+ return VerifyCredentialsImpl(response, signature_input, crl_policy,
+ cast_trust_store, crl_trust_store,
+ cert_verification_time, crl_verification_time);
+}
+
} // namespace cast_channel
} // namespace api
} // namespace extensions

Powered by Google App Engine
This is Rietveld 408576698