summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsergeyv <sergeyv@chromium.org>2015-01-21 07:27:39 -0800
committerCommit bot <commit-bot@chromium.org>2015-01-21 15:28:39 +0000
commitf752426485290ebf878ef5af21b6335ad5a47141 (patch)
tree6c4273ea035fa474a4adbe38893f13b821d95c98
parente98e8e7654b7e51f98e92514897f8e1284eaa571 (diff)
downloadchromium_src-f752426485290ebf878ef5af21b6335ad5a47141.zip
chromium_src-f752426485290ebf878ef5af21b6335ad5a47141.tar.gz
chromium_src-f752426485290ebf878ef5af21b6335ad5a47141.tar.bz2
Revert of Re-landing of issue 792353002 (patchset #1 id:1 of https://codereview.chromium.org/854693002/)
Reason for revert: Speculative revert. I suppose that now it is breaking Linux GN: http://build.chromium.org/p/chromium.linux/builders/Linux%20GN%20%28dbg%29/builds/20625/steps/compile/logs/stdio Original issue's description: > The purpose of this CL is to re-land issue 792353002 (https://codereview.chromium.org/792353002/), which landed, but was reverted due to a ChromiumOS GN build failure. The failure was caused by a double inclusion of networking_private_credentials_getter_chromeos.cc.cc file in chrome_browser_extensions.gypi. This CL includes the original patch and the fix of the build failure. > > Original CL description follows: > > Refactoring of Cast-related crypto code to use the same certificate validation logic in chrome.networkingPrivate API and Cast Channel authentication. > > Here's what's being done here: > * Code from cast_auth_util_nss/openssl formed the basis a common Cast device validation component in /src/extensions/common/cast/cast_cert_validator*, and is now being extensively cleaned up in response to rsleevi's comments in this CL. > * Both networking_private_crypto* and cast_auth_util* have been updated to use the new common code. > * The current D-Bus-based implementation of VerifyDestination is going away per discussion with ChromeOS team, and is replaced with in-Chrome code in networking_private crypto*. > > BUG=442650 > > Committed: https://crrev.com/57988d1f46e6ce2a2d65aa87c01b29b2732a110f > Cr-Commit-Position: refs/heads/master@{#312369} TBR=rockot@chromium.org,stevenjb@chromium.org,brettw@chromium.org,mfoltz@chromium.org,vadimgo@chromium.org,mef@chromium.org,kmarshall@chromium.org,rsleevi@chromium.org,sheretov@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=442650 Review URL: https://codereview.chromium.org/865583003 Cr-Commit-Position: refs/heads/master@{#312391}
-rw-r--r--chrome/browser/extensions/api/networking_private/crypto_verify_impl.cc6
-rw-r--r--chrome/browser/extensions/api/networking_private/crypto_verify_impl.h1
-rw-r--r--chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc43
-rw-r--r--chrome/browser/extensions/api/networking_private/networking_private_credentials_getter_chromeos.cc43
-rw-r--r--chrome/browser/extensions/api/networking_private/networking_private_verify_delegate_chromeos.cc114
-rw-r--r--chrome/browser/extensions/api/networking_private/networking_private_verify_delegate_chromeos.h38
-rw-r--r--chrome/browser/extensions/api/networking_private/networking_private_verify_delegate_factory_impl.cc8
-rw-r--r--chrome/chrome_browser_extensions.gypi5
-rw-r--r--chrome/chrome_common.gypi33
-rw-r--r--chrome/chrome_tests_unit.gypi5
-rw-r--r--chrome/common/BUILD.gn14
-rw-r--r--chrome/common/extensions/api/networking_private.json10
-rw-r--r--chrome/common/extensions/api/networking_private/networking_private_crypto.cc101
-rw-r--r--chrome/common/extensions/api/networking_private/networking_private_crypto.h16
-rw-r--r--chrome/common/extensions/api/networking_private/networking_private_crypto_nss.cc88
-rw-r--r--chrome/common/extensions/api/networking_private/networking_private_crypto_openssl.cc103
-rw-r--r--chrome/common/extensions/api/networking_private/networking_private_crypto_unittest.cc51
-rw-r--r--chrome/test/data/extensions/api_test/networking/test.js1
-rw-r--r--chrome/test/data/extensions/api_test/networking_private/test.js1
-rw-r--r--extensions/browser/BUILD.gn6
-rw-r--r--extensions/browser/api/cast_channel/cast_auth_util.cc57
-rw-r--r--extensions/browser/api/cast_channel/cast_auth_util_nss.cc142
-rw-r--r--extensions/browser/api/cast_channel/cast_auth_util_openssl.cc144
-rw-r--r--extensions/browser/api/cast_channel/cast_auth_util_unittest.cc3
-rw-r--r--extensions/common/BUILD.gn9
-rw-r--r--extensions/common/cast/cast_cert_validator.cc30
-rw-r--r--extensions/common/cast/cast_cert_validator.h96
-rw-r--r--extensions/common/cast/cast_cert_validator_nss.cc155
-rw-r--r--extensions/common/cast/cast_cert_validator_openssl.cc158
-rw-r--r--extensions/extensions.gyp53
30 files changed, 737 insertions, 797 deletions
diff --git a/chrome/browser/extensions/api/networking_private/crypto_verify_impl.cc b/chrome/browser/extensions/api/networking_private/crypto_verify_impl.cc
index 1960a12..da34f3f 100644
--- a/chrome/browser/extensions/api/networking_private/crypto_verify_impl.cc
+++ b/chrome/browser/extensions/api/networking_private/crypto_verify_impl.cc
@@ -38,8 +38,8 @@ bool DecodeAndVerifyCredentials(
return false;
}
*verified = networking_private_crypto::VerifyCredentials(
- credentials.certificate, credentials.intermediate_certificates,
- decoded_signed_data, credentials.unsigned_data, credentials.device_bssid);
+ credentials.certificate, decoded_signed_data, credentials.unsigned_data,
+ credentials.device_bssid);
return true;
}
@@ -158,8 +158,6 @@ void VerifyAndEncryptCredentialsCompleted(
CryptoVerifyImpl::Credentials::Credentials(
const VerificationProperties& properties) {
certificate = properties.certificate;
- if (properties.intermediate_certificates.get())
- intermediate_certificates = *properties.intermediate_certificates;
signed_data = properties.signed_data;
std::vector<std::string> data_parts;
diff --git a/chrome/browser/extensions/api/networking_private/crypto_verify_impl.h b/chrome/browser/extensions/api/networking_private/crypto_verify_impl.h
index b35021a..bacdc5a 100644
--- a/chrome/browser/extensions/api/networking_private/crypto_verify_impl.h
+++ b/chrome/browser/extensions/api/networking_private/crypto_verify_impl.h
@@ -29,7 +29,6 @@ class CryptoVerifyImpl : public NetworkingPrivateDelegate::VerifyDelegate {
~Credentials();
std::string certificate;
- std::vector<std::string> intermediate_certificates;
std::string signed_data;
std::string unsigned_data;
std::string device_bssid;
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc b/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
index d2aa61c..ac57b5d 100644
--- a/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
+++ b/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
@@ -9,9 +9,6 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/login/helper.h"
#include "chrome/browser/chromeos/net/network_portal_detector_test_impl.h"
-#include "chrome/browser/extensions/api/networking_private/networking_private_chromeos.h"
-#include "chrome/browser/extensions/api/networking_private/networking_private_credentials_getter.h"
-#include "chrome/browser/extensions/api/networking_private/networking_private_delegate_factory.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/dbus/cryptohome_client.h"
@@ -64,10 +61,6 @@ using chromeos::ShillManagerClient;
using chromeos::ShillProfileClient;
using chromeos::ShillServiceClient;
-using extensions::NetworkingPrivateDelegate;
-using extensions::NetworkingPrivateDelegateFactory;
-using extensions::NetworkingPrivateChromeOS;
-
namespace {
const char kUser1ProfilePath[] = "/profile/user1/shill";
@@ -75,33 +68,6 @@ const char kWifiDevicePath[] = "/device/stub_wifi_device1";
const char kCellularDevicePath[] = "/device/stub_cellular_device1";
const char kIPConfigPath[] = "/ipconfig/ipconfig1";
-// Stub Verify* methods implementation to satisfy expectations of
-// networking_private_apitest.
-class CryptoVerifyStub : public NetworkingPrivateDelegate::VerifyDelegate {
- void VerifyDestination(
- const VerificationProperties& verification_properties,
- const BoolCallback& success_callback,
- const FailureCallback& failure_callback) override {
- success_callback.Run(true);
- }
-
- void VerifyAndEncryptCredentials(
- const std::string& guid,
- const VerificationProperties& verification_properties,
- const StringCallback& success_callback,
- const FailureCallback& failure_callback) override {
- success_callback.Run("encrypted_credentials");
- }
-
- void VerifyAndEncryptData(
- const VerificationProperties& verification_properties,
- const std::string& data,
- const StringCallback& success_callback,
- const FailureCallback& failure_callback) override {
- success_callback.Run("encrypted_data");
- }
-};
-
class TestListener : public content::NotificationObserver {
public:
TestListener(const std::string& message, const base::Closure& callback)
@@ -230,12 +196,6 @@ class NetworkingPrivateChromeOSApiTest : public ExtensionApiTest {
true /* add_to_visible */);
}
- static KeyedService* CreateNetworkingPrivateServiceClient(
- content::BrowserContext* profile) {
- scoped_ptr<CryptoVerifyStub> crypto_verify(new CryptoVerifyStub);
- return new NetworkingPrivateChromeOS(profile, crypto_verify.Pass());
- }
-
void SetUpOnMainThread() override {
detector_ = new NetworkPortalDetectorTestImpl();
NetworkPortalDetector::InitializeForTesting(detector_);
@@ -243,9 +203,6 @@ class NetworkingPrivateChromeOSApiTest : public ExtensionApiTest {
ExtensionApiTest::SetUpOnMainThread();
content::RunAllPendingInMessageLoop();
- NetworkingPrivateDelegateFactory::GetInstance()->SetTestingFactory(
- profile(), &CreateNetworkingPrivateServiceClient);
-
InitializeSanitizedUsername();
DBusThreadManager* dbus_manager = DBusThreadManager::Get();
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter_chromeos.cc b/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter_chromeos.cc
deleted file mode 100644
index a47b2e9..0000000
--- a/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter_chromeos.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/api/networking_private/networking_private_credentials_getter.h"
-
-const char kErrorNotImplemented[] = "Error.NotImplemented";
-
-namespace extensions {
-
-class NetworkingPrivateCredentialsGetterChromeos
- : public NetworkingPrivateCredentialsGetter {
- public:
- NetworkingPrivateCredentialsGetterChromeos() {}
-
- void Start(const std::string& network_guid,
- const std::string& public_key,
- const CredentialsCallback& callback) override;
-
- private:
- ~NetworkingPrivateCredentialsGetterChromeos() override;
-
- DISALLOW_COPY_AND_ASSIGN(NetworkingPrivateCredentialsGetterChromeos);
-};
-
-NetworkingPrivateCredentialsGetterChromeos::
- ~NetworkingPrivateCredentialsGetterChromeos() {
-}
-
-void NetworkingPrivateCredentialsGetterChromeos::Start(
- const std::string& network_guid,
- const std::string& public_key,
- const CredentialsCallback& callback) {
- // TODO(sheretov) add credential slurping from sync.
- callback.Run(std::string(), kErrorNotImplemented);
-}
-
-NetworkingPrivateCredentialsGetter*
-NetworkingPrivateCredentialsGetter::Create() {
- return new NetworkingPrivateCredentialsGetterChromeos();
-}
-
-} // namespace extensions
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_verify_delegate_chromeos.cc b/chrome/browser/extensions/api/networking_private/networking_private_verify_delegate_chromeos.cc
new file mode 100644
index 0000000..a4d06a1
--- /dev/null
+++ b/chrome/browser/extensions/api/networking_private/networking_private_verify_delegate_chromeos.cc
@@ -0,0 +1,114 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/networking_private/networking_private_verify_delegate_chromeos.h"
+
+#include "base/bind.h"
+#include "chrome/browser/extensions/api/networking_private/networking_private_api.h"
+#include "chrome/common/extensions/api/networking_private.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/shill_manager_client.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
+
+using chromeos::ShillManagerClient;
+
+namespace {
+
+ShillManagerClient* GetShillManagerClient() {
+ return chromeos::DBusThreadManager::Get()->GetShillManagerClient();
+}
+
+bool GetServicePathFromGuid(const std::string& guid,
+ std::string* service_path,
+ std::string* error) {
+ const chromeos::NetworkState* network = chromeos::NetworkHandler::Get()
+ ->network_state_handler()
+ ->GetNetworkStateFromGuid(guid);
+ if (!network) {
+ *error = extensions::networking_private::kErrorInvalidNetworkGuid;
+ return false;
+ }
+ *service_path = network->path();
+ return true;
+}
+
+ShillManagerClient::VerificationProperties ConvertVerificationProperties(
+ const extensions::api::networking_private::VerificationProperties& input) {
+ ShillManagerClient::VerificationProperties output;
+ output.certificate = input.certificate;
+ output.public_key = input.public_key;
+ output.nonce = input.nonce;
+ output.signed_data = input.signed_data;
+ output.device_serial = input.device_serial;
+ output.device_ssid = input.device_ssid;
+ output.device_bssid = input.device_bssid;
+ return output;
+}
+
+void ShillFailureCallback(
+ const extensions::NetworkingPrivateDelegate::FailureCallback& callback,
+ const std::string& error_name,
+ const std::string& error_message) {
+ callback.Run(error_name);
+}
+
+} // namespace
+
+namespace extensions {
+
+NetworkingPrivateVerifyDelegateChromeOS::
+ NetworkingPrivateVerifyDelegateChromeOS() {
+}
+
+NetworkingPrivateVerifyDelegateChromeOS::
+ ~NetworkingPrivateVerifyDelegateChromeOS() {
+}
+
+void NetworkingPrivateVerifyDelegateChromeOS::VerifyDestination(
+ const VerificationProperties& verification_properties,
+ const BoolCallback& success_callback,
+ const FailureCallback& failure_callback) {
+ ShillManagerClient::VerificationProperties verification_property_struct =
+ ConvertVerificationProperties(verification_properties);
+
+ GetShillManagerClient()->VerifyDestination(
+ verification_property_struct, success_callback,
+ base::Bind(&ShillFailureCallback, failure_callback));
+}
+
+void NetworkingPrivateVerifyDelegateChromeOS::VerifyAndEncryptCredentials(
+ const std::string& guid,
+ const VerificationProperties& verification_properties,
+ const StringCallback& success_callback,
+ const FailureCallback& failure_callback) {
+ std::string service_path, error;
+ if (!GetServicePathFromGuid(guid, &service_path, &error)) {
+ failure_callback.Run(error);
+ return;
+ }
+
+ ShillManagerClient::VerificationProperties verification_property_struct =
+ ConvertVerificationProperties(verification_properties);
+
+ GetShillManagerClient()->VerifyAndEncryptCredentials(
+ verification_property_struct, service_path, success_callback,
+ base::Bind(&ShillFailureCallback, failure_callback));
+}
+
+void NetworkingPrivateVerifyDelegateChromeOS::VerifyAndEncryptData(
+ const VerificationProperties& verification_properties,
+ const std::string& data,
+ const StringCallback& success_callback,
+ const FailureCallback& failure_callback) {
+ ShillManagerClient::VerificationProperties verification_property_struct =
+ ConvertVerificationProperties(verification_properties);
+
+ GetShillManagerClient()->VerifyAndEncryptData(
+ verification_property_struct, data, success_callback,
+ base::Bind(&ShillFailureCallback, failure_callback));
+}
+
+} // namespace extensions
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_verify_delegate_chromeos.h b/chrome/browser/extensions/api/networking_private/networking_private_verify_delegate_chromeos.h
new file mode 100644
index 0000000..dbef880
--- /dev/null
+++ b/chrome/browser/extensions/api/networking_private/networking_private_verify_delegate_chromeos.h
@@ -0,0 +1,38 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_API_NETWORKING_PRIVATE_NETWORKING_PRIVATE_VERIFY_DELEGATE_CHROMEOS_H_
+#define CHROME_BROWSER_EXTENSIONS_API_NETWORKING_PRIVATE_NETWORKING_PRIVATE_VERIFY_DELEGATE_CHROMEOS_H_
+
+#include "chrome/browser/extensions/api/networking_private/networking_private_delegate.h"
+
+namespace extensions {
+
+class NetworkingPrivateVerifyDelegateChromeOS
+ : public NetworkingPrivateDelegate::VerifyDelegate {
+ public:
+ NetworkingPrivateVerifyDelegateChromeOS();
+ ~NetworkingPrivateVerifyDelegateChromeOS() override;
+
+ void VerifyDestination(const VerificationProperties& verification_properties,
+ const BoolCallback& success_callback,
+ const FailureCallback& failure_callback) override;
+ void VerifyAndEncryptCredentials(
+ const std::string& guid,
+ const VerificationProperties& verification_properties,
+ const StringCallback& success_callback,
+ const FailureCallback& failure_callback) override;
+ void VerifyAndEncryptData(
+ const VerificationProperties& verification_properties,
+ const std::string& data,
+ const StringCallback& success_callback,
+ const FailureCallback& failure_callback) override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NetworkingPrivateVerifyDelegateChromeOS);
+};
+
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_API_NETWORKING_PRIVATE_NETWORKING_PRIVATE_VERIFY_DELEGATE_CHROMEOS_H_
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_verify_delegate_factory_impl.cc b/chrome/browser/extensions/api/networking_private/networking_private_verify_delegate_factory_impl.cc
index 44226d5..f2884d0 100644
--- a/chrome/browser/extensions/api/networking_private/networking_private_verify_delegate_factory_impl.cc
+++ b/chrome/browser/extensions/api/networking_private/networking_private_verify_delegate_factory_impl.cc
@@ -4,7 +4,11 @@
#include "chrome/browser/extensions/api/networking_private/networking_private_verify_delegate_factory_impl.h"
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/extensions/api/networking_private/networking_private_verify_delegate_chromeos.h"
+#elif defined(OS_WIN) || defined(OSMACOSX)
#include "chrome/browser/extensions/api/networking_private/crypto_verify_impl.h"
+#endif
namespace extensions {
@@ -18,7 +22,9 @@ NetworkingPrivateVerifyDelegateFactoryImpl::
scoped_ptr<NetworkingPrivateDelegate::VerifyDelegate>
NetworkingPrivateVerifyDelegateFactoryImpl::CreateDelegate() {
-#if defined(OS_CHROMEOS) || defined(OS_WIN) || defined(OS_MACOSX)
+#if defined(OS_CHROMEOS)
+ return make_scoped_ptr(new NetworkingPrivateVerifyDelegateChromeOS());
+#elif defined(OS_WIN) || defined(OSMACOSX)
return make_scoped_ptr(new CryptoVerifyImpl());
#else
return nullptr;
diff --git a/chrome/chrome_browser_extensions.gypi b/chrome/chrome_browser_extensions.gypi
index 1100287..3d5a783 100644
--- a/chrome/chrome_browser_extensions.gypi
+++ b/chrome/chrome_browser_extensions.gypi
@@ -343,13 +343,10 @@
'browser/extensions/api/music_manager_private/device_id_win.cc',
'browser/extensions/api/music_manager_private/music_manager_private_api.cc',
'browser/extensions/api/music_manager_private/music_manager_private_api.h',
- 'browser/extensions/api/networking_private/crypto_verify_impl.cc',
- 'browser/extensions/api/networking_private/crypto_verify_impl.h',
'browser/extensions/api/networking_private/networking_private_api.cc',
'browser/extensions/api/networking_private/networking_private_api.h',
'browser/extensions/api/networking_private/networking_private_chromeos.cc',
'browser/extensions/api/networking_private/networking_private_chromeos.h',
- 'browser/extensions/api/networking_private/networking_private_credentials_getter_chromeos.cc',
'browser/extensions/api/networking_private/networking_private_delegate.cc',
'browser/extensions/api/networking_private/networking_private_delegate.h',
'browser/extensions/api/networking_private/networking_private_delegate_observer.h',
@@ -359,6 +356,8 @@
'browser/extensions/api/networking_private/networking_private_event_router_factory.h',
'browser/extensions/api/networking_private/networking_private_delegate_factory.cc',
'browser/extensions/api/networking_private/networking_private_delegate_factory.h',
+ 'browser/extensions/api/networking_private/networking_private_verify_delegate_chromeos.cc',
+ 'browser/extensions/api/networking_private/networking_private_verify_delegate_chromeos.h',
'browser/extensions/api/networking_private/networking_private_verify_delegate_factory_impl.cc',
'browser/extensions/api/networking_private/networking_private_verify_delegate_factory_impl.h',
'browser/extensions/api/notification_provider/notification_provider_api.cc',
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi
index 028de4f..83a320d 100644
--- a/chrome/chrome_common.gypi
+++ b/chrome/chrome_common.gypi
@@ -252,23 +252,16 @@
'common/service_process_util_win.cc',
],
'chrome_common_win_mac_sources': [
+ 'common/extensions/api/networking_private/networking_private_crypto_nss.cc',
+ 'common/extensions/api/networking_private/networking_private_crypto_openssl.cc',
+ 'common/extensions/api/networking_private/networking_private_crypto.cc',
+ 'common/extensions/api/networking_private/networking_private_crypto.h',
'common/media_galleries/itunes_library.cc',
'common/media_galleries/itunes_library.h',
'common/media_galleries/picasa_types.cc',
'common/media_galleries/picasa_types.h',
'common/media_galleries/pmp_constants.h',
],
- 'chrome_common_networking_private_sources_openssl' : [
- 'common/extensions/api/networking_private/networking_private_crypto_openssl.cc',
- 'common/extensions/api/networking_private/networking_private_crypto.cc',
- 'common/extensions/api/networking_private/networking_private_crypto.h',
- ],
- 'chrome_common_networking_private_sources_nss' : [
- 'common/extensions/api/networking_private/networking_private_crypto_nss.cc',
- 'common/extensions/api/networking_private/networking_private_crypto.cc',
- 'common/extensions/api/networking_private/networking_private_crypto.h',
- ],
-
'chrome_common_mac_sources': [
'common/media_galleries/iphoto_library.cc',
'common/media_galleries/iphoto_library.h',
@@ -351,15 +344,12 @@
['OS=="win" or OS=="mac"', {
'sources': [ '<@(chrome_common_win_mac_sources)' ],
}],
- ['(OS=="win" or OS=="mac" or chromeos==1) and use_openssl==1', {
- 'sources': [ '<@(chrome_common_networking_private_sources_openssl)' ],
+ ['(OS=="win" or OS=="mac") and use_openssl==1', {
+ # networking_private_crypto_openssl.cc depends on boringssl.
'dependencies': [
'../third_party/boringssl/boringssl.gyp:boringssl',
],
}],
- ['(OS=="win" or OS=="mac" or chromeos==1) and use_openssl!=1', {
- 'sources': [ '<@(chrome_common_networking_private_sources_nss)' ],
- }],
['OS=="mac"', {
'sources': [ '<@(chrome_common_mac_sources)' ],
}],
@@ -503,6 +493,17 @@
['safe_browsing==2', {
'defines': [ 'MOBILE_SAFE_BROWSING' ],
}],
+ ['use_openssl==1', {
+ 'sources!': [
+ 'common/extensions/api/networking_private/networking_private_crypto_nss.cc',
+ ],
+ },
+ { # else !use_openssl
+ 'sources!': [
+ 'common/extensions/api/networking_private/networking_private_crypto_openssl.cc',
+ ],
+ },
+ ],
],
'target_conditions': [
['OS == "ios"', {
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index d66a6e5..546cffa 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -2422,11 +2422,6 @@
['OS=="win" or OS=="mac"', {
'sources': [ '<@(chrome_unit_tests_win_mac_sources)' ],
}],
- ['OS=="win" or OS=="mac" or chromeos==1', {
- 'sources': [
- 'common/extensions/api/networking_private/networking_private_crypto_unittest.cc',
- ],
- }],
['enable_rlz!=0', {
'dependencies': [
'../rlz/rlz.gyp:test_support_rlz',
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn
index d6a03e0..6fd6111 100644
--- a/chrome/common/BUILD.gn
+++ b/chrome/common/BUILD.gn
@@ -114,23 +114,15 @@ static_library("common") {
if (is_win || is_mac) {
sources +=
rebase_path(gypi_values.chrome_common_win_mac_sources, ".", "//chrome")
- deps += [ "//breakpad:client" ]
- }
- if (is_win || is_mac || is_chromeos) {
if (use_openssl) {
- sources += rebase_path(
- gypi_values.chrome_common_networking_private_sources_openssl,
- ".",
- "//chrome")
+ sources -= [ "extensions/api/networking_private/networking_private_crypto_nss.cc" ]
# networking_private_crypto_openssl.cc depends on boringssl.
deps += [ "//third_party/boringssl" ]
} else {
- sources +=
- rebase_path(gypi_values.chrome_common_networking_private_sources_nss,
- ".",
- "//chrome")
+ sources -= [ "extensions/api/networking_private/networking_private_crypto_openssl.cc" ]
}
+ deps += [ "//breakpad:client" ]
}
if (is_mac) {
sources +=
diff --git a/chrome/common/extensions/api/networking_private.json b/chrome/common/extensions/api/networking_private.json
index 8e73463..bac9fea 100644
--- a/chrome/common/extensions/api/networking_private.json
+++ b/chrome/common/extensions/api/networking_private.json
@@ -27,17 +27,11 @@
"properties": {
"certificate": {
"type": "string",
- "description": "A string containing a PEM-encoded (including the \"BEGIN CERTIFICATE\" header and \"END CERTIFICATE\" footer) X.509 certificate for use in verifying the signed data."
- },
- "intermediateCertificates": {
- "type": "array",
- "items": { "type": "string" },
- "optional": true,
- "description": "An array of PEM-encoded X.509 intermediate certificate authority certificates. Each PEM-encoded certificate is expected to have the \"BEGIN CERTIFICATE\" header and \"END CERTIFICATE\" footer."
+ "description": "A string containing a PEM-encoded X.509 certificate for use in verifying the signed data."
},
"publicKey": {
"type": "string",
- "description": "A string containing a Base64-encoded RSAPublicKey ASN.1 structure, representing the public key to be used by verifyAndEncryptCredentials and verifyAndEncryptData methods."
+ "description": "A string containing a PEM-encoded RSA public key to be used to compare with the one in signedData"
},
"nonce": {
"type": "string",
diff --git a/chrome/common/extensions/api/networking_private/networking_private_crypto.cc b/chrome/common/extensions/api/networking_private/networking_private_crypto.cc
index 66af2f9..34c2776 100644
--- a/chrome/common/extensions/api/networking_private/networking_private_crypto.cc
+++ b/chrome/common/extensions/api/networking_private/networking_private_crypto.cc
@@ -4,82 +4,33 @@
#include "chrome/common/extensions/api/networking_private/networking_private_crypto.h"
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/string_util.h"
-#include "extensions/common/cast/cast_cert_validator.h"
-#include "net/cert/pem_tokenizer.h"
-
-namespace {
-
-namespace cast_crypto = ::extensions::core_api::cast_crypto;
-
-} // namespace
-
namespace networking_private_crypto {
-bool VerifyCredentials(
- const std::string& certificate,
- const std::vector<std::string>& intermediate_certificates,
- const std::string& signature,
- const std::string& data,
- const std::string& connected_mac) {
- static const char kErrorPrefix[] = "Device verification failed. ";
-
- std::vector<std::string> headers;
- headers.push_back("CERTIFICATE");
-
- // Convert certificate from PEM to raw DER
- net::PEMTokenizer pem_tok(certificate, headers);
- if (!pem_tok.GetNext()) {
- LOG(ERROR) << kErrorPrefix << "Failed to parse device certificate.";
- return false;
- }
- std::string der_certificate = pem_tok.data();
-
- // Convert intermediate certificates from PEM to raw DER
- std::vector<std::string> der_intermediate_certificates;
- for (size_t idx = 0; idx < intermediate_certificates.size(); ++idx) {
- net::PEMTokenizer ica_pem_tok(intermediate_certificates[idx], headers);
- if (ica_pem_tok.GetNext()) {
- der_intermediate_certificates.push_back(ica_pem_tok.data());
- } else {
- LOG(WARNING) << "Failed to parse intermediate certificates.";
- }
- }
-
- // Verify device certificate
- scoped_ptr<cast_crypto::CertVerificationContext> verification_context;
- cast_crypto::VerificationResult verification_result =
- cast_crypto::VerifyDeviceCert(der_certificate,
- der_intermediate_certificates,
- &verification_context);
-
- if (verification_result.Failure()) {
- LOG(ERROR) << kErrorPrefix << verification_result.GetLogString();
- return false;
- }
-
- // Check that the device listed in the certificate is correct.
- // Something like evt_e161 001a11ffacdf
- std::string common_name = verification_context->GetCommonName();
- std::string translated_mac;
- base::RemoveChars(connected_mac, ":", &translated_mac);
- if (!EndsWith(common_name, translated_mac, false)) {
- LOG(ERROR) << kErrorPrefix << "MAC addresses don't match.";
- return false;
- }
-
- // Use the public key from verified certificate to verify |signature| over
- // |data|.
- verification_result =
- verification_context->VerifySignatureOverData(signature, data);
-
- if (verification_result.Failure()) {
- LOG(ERROR) << kErrorPrefix << verification_result.GetLogString();
- return false;
- }
- return true;
-}
+const uint8 kTrustedCAPublicKeyDER[] = {
+ 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xbc, 0x22, 0x80,
+ 0xbd, 0x80, 0xf6, 0x3a, 0x21, 0x00, 0x3b, 0xae, 0x76, 0x5e, 0x35, 0x7f,
+ 0x3d, 0xc3, 0x64, 0x5c, 0x55, 0x94, 0x86, 0x34, 0x2f, 0x05, 0x87, 0x28,
+ 0xcd, 0xf7, 0x69, 0x8c, 0x17, 0xb3, 0x50, 0xa7, 0xb8, 0x82, 0xfa, 0xdf,
+ 0xc7, 0x43, 0x2d, 0xd6, 0x7e, 0xab, 0xa0, 0x6f, 0xb7, 0x13, 0x72, 0x80,
+ 0xa4, 0x47, 0x15, 0xc1, 0x20, 0x99, 0x50, 0xcd, 0xec, 0x14, 0x62, 0x09,
+ 0x5b, 0xa4, 0x98, 0xcd, 0xd2, 0x41, 0xb6, 0x36, 0x4e, 0xff, 0xe8, 0x2e,
+ 0x32, 0x30, 0x4a, 0x81, 0xa8, 0x42, 0xa3, 0x6c, 0x9b, 0x33, 0x6e, 0xca,
+ 0xb2, 0xf5, 0x53, 0x66, 0xe0, 0x27, 0x53, 0x86, 0x1a, 0x85, 0x1e, 0xa7,
+ 0x39, 0x3f, 0x4a, 0x77, 0x8e, 0xfb, 0x54, 0x66, 0x66, 0xfb, 0x58, 0x54,
+ 0xc0, 0x5e, 0x39, 0xc7, 0xf5, 0x50, 0x06, 0x0b, 0xe0, 0x8a, 0xd4, 0xce,
+ 0xe1, 0x6a, 0x55, 0x1f, 0x8b, 0x17, 0x00, 0xe6, 0x69, 0xa3, 0x27, 0xe6,
+ 0x08, 0x25, 0x69, 0x3c, 0x12, 0x9d, 0x8d, 0x05, 0x2c, 0xd6, 0x2e, 0xa2,
+ 0x31, 0xde, 0xb4, 0x52, 0x50, 0xd6, 0x20, 0x49, 0xde, 0x71, 0xa0, 0xf9,
+ 0xad, 0x20, 0x40, 0x12, 0xf1, 0xdd, 0x25, 0xeb, 0xd5, 0xe6, 0xb8, 0x36,
+ 0xf4, 0xd6, 0x8f, 0x7f, 0xca, 0x43, 0xdc, 0xd7, 0x10, 0x5b, 0xe6, 0x3f,
+ 0x51, 0x8a, 0x85, 0xb3, 0xf3, 0xff, 0xf6, 0x03, 0x2d, 0xcb, 0x23, 0x4f,
+ 0x9c, 0xad, 0x18, 0xe7, 0x93, 0x05, 0x8c, 0xac, 0x52, 0x9a, 0xf7, 0x4c,
+ 0xe9, 0x99, 0x7a, 0xbe, 0x6e, 0x7e, 0x4d, 0x0a, 0xe3, 0xc6, 0x1c, 0xa9,
+ 0x93, 0xfa, 0x3a, 0xa5, 0x91, 0x5d, 0x1c, 0xbd, 0x66, 0xeb, 0xcc, 0x60,
+ 0xdc, 0x86, 0x74, 0xca, 0xcf, 0xf8, 0x92, 0x1c, 0x98, 0x7d, 0x57, 0xfa,
+ 0x61, 0x47, 0x9e, 0xab, 0x80, 0xb7, 0xe4, 0x48, 0x80, 0x2a, 0x92, 0xc5,
+ 0x1b, 0x02, 0x03, 0x01, 0x00, 0x01};
+
+const size_t kTrustedCAPublicKeyDERLength = sizeof(kTrustedCAPublicKeyDER);
} // namespace networking_private_crypto
diff --git a/chrome/common/extensions/api/networking_private/networking_private_crypto.h b/chrome/common/extensions/api/networking_private/networking_private_crypto.h
index 8940c0b..e613293 100644
--- a/chrome/common/extensions/api/networking_private/networking_private_crypto.h
+++ b/chrome/common/extensions/api/networking_private/networking_private_crypto.h
@@ -20,12 +20,10 @@ namespace networking_private_crypto {
// 2) The certificate is a valid PEM encoded certificate signed by trusted CA.
// 3) |signature| is a valid signature for |data|, using the public key in
// |certificate|
-bool VerifyCredentials(
- const std::string& certificate,
- const std::vector<std::string>& intermediate_certificates,
- const std::string& signature,
- const std::string& data,
- const std::string& connected_mac);
+bool VerifyCredentials(const std::string& certificate,
+ const std::string& signature,
+ const std::string& data,
+ const std::string& connected_mac);
// Encrypt |data| with |public_key|. |public_key| is a DER-encoded
// RSAPublicKey. |data| is some string of bytes that is smaller than the
@@ -46,6 +44,12 @@ bool DecryptByteString(const std::string& private_key_pem,
const std::vector<uint8_t>& encrypted_data,
std::string* decrypted_output);
+// The trusted public key as a DER-encoded PKCS#1 RSAPublicKey structure.
+extern const uint8_t kTrustedCAPublicKeyDER[];
+
+// The length of |kTrustedCAPublicKeyDER| in bytes.
+extern const size_t kTrustedCAPublicKeyDERLength;
+
} // namespace networking_private_crypto
#endif // CHROME_COMMON_EXTENSIONS_API_NETWORKING_PRIVATE_NETWORKING_PRIVATE_CRYPTO_H_
diff --git a/chrome/common/extensions/api/networking_private/networking_private_crypto_nss.cc b/chrome/common/extensions/api/networking_private/networking_private_crypto_nss.cc
index 0839762..2cdc33b 100644
--- a/chrome/common/extensions/api/networking_private/networking_private_crypto_nss.cc
+++ b/chrome/common/extensions/api/networking_private/networking_private_crypto_nss.cc
@@ -46,6 +46,94 @@ bool GetDERFromPEM(const std::string& pem_data,
namespace networking_private_crypto {
+bool VerifyCredentials(const std::string& certificate,
+ const std::string& signature,
+ const std::string& data,
+ const std::string& connected_mac) {
+ crypto::EnsureNSSInit();
+
+ std::vector<uint8_t> cert_data;
+ if (!GetDERFromPEM(certificate, "CERTIFICATE", &cert_data)) {
+ LOG(ERROR) << "Failed to parse certificate.";
+ return false;
+ }
+ SECItem der_cert;
+ der_cert.type = siDERCertBuffer;
+ der_cert.data = cert_data.data();
+ der_cert.len = cert_data.size();
+
+ // Parse into a certificate structure.
+ typedef scoped_ptr<
+ CERTCertificate,
+ crypto::NSSDestroyer<CERTCertificate, CERT_DestroyCertificate> >
+ ScopedCERTCertificate;
+ ScopedCERTCertificate cert(CERT_NewTempCertificate(
+ CERT_GetDefaultCertDB(), &der_cert, NULL, PR_FALSE, PR_TRUE));
+ if (!cert.get()) {
+ LOG(ERROR) << "Failed to parse certificate.";
+ return false;
+ }
+
+ // Check that the certificate is signed by trusted CA.
+ SECItem trusted_ca_key_der_item;
+ trusted_ca_key_der_item.type = siDERCertBuffer;
+ trusted_ca_key_der_item.data =
+ const_cast<unsigned char*>(kTrustedCAPublicKeyDER);
+ trusted_ca_key_der_item.len = kTrustedCAPublicKeyDERLength;
+ crypto::ScopedSECKEYPublicKey ca_public_key(
+ SECKEY_ImportDERPublicKey(&trusted_ca_key_der_item, CKK_RSA));
+ SECStatus verified = CERT_VerifySignedDataWithPublicKey(
+ &cert->signatureWrap, ca_public_key.get(), NULL);
+ if (verified != SECSuccess) {
+ LOG(ERROR) << "Certificate is not issued by the trusted CA.";
+ return false;
+ }
+
+ // Check that the device listed in the certificate is correct.
+ // Something like evt_e161 001a11ffacdf
+ char* common_name = CERT_GetCommonName(&cert->subject);
+ if (!common_name) {
+ LOG(ERROR) << "Certificate does not have common name.";
+ return false;
+ }
+
+ std::string subject_name(common_name);
+ PORT_Free(common_name);
+ std::string translated_mac;
+ base::RemoveChars(connected_mac, ":", &translated_mac);
+ if (!EndsWith(subject_name, translated_mac, false)) {
+ LOG(ERROR) << "MAC addresses don't match.";
+ return false;
+ }
+
+ // Make sure that the certificate matches the unsigned data presented.
+ // Verify that the |signature| matches |data|.
+ crypto::ScopedSECKEYPublicKey public_key(CERT_ExtractPublicKey(cert.get()));
+ if (!public_key.get()) {
+ LOG(ERROR) << "Unable to extract public key from certificate.";
+ return false;
+ }
+ SECItem signature_item;
+ signature_item.type = siBuffer;
+ signature_item.data =
+ reinterpret_cast<unsigned char*>(const_cast<char*>(signature.c_str()));
+ signature_item.len = static_cast<unsigned int>(signature.size());
+ verified = VFY_VerifyDataDirect(
+ reinterpret_cast<unsigned char*>(const_cast<char*>(data.c_str())),
+ data.size(),
+ public_key.get(),
+ &signature_item,
+ SEC_OID_PKCS1_RSA_ENCRYPTION,
+ SEC_OID_SHA1,
+ NULL,
+ NULL);
+ if (verified != SECSuccess) {
+ LOG(ERROR) << "Signed blobs did not match.";
+ return false;
+ }
+ return true;
+}
+
bool EncryptByteString(const std::vector<uint8_t>& pub_key_der,
const std::string& data,
std::vector<uint8_t>* encrypted_output) {
diff --git a/chrome/common/extensions/api/networking_private/networking_private_crypto_openssl.cc b/chrome/common/extensions/api/networking_private/networking_private_crypto_openssl.cc
index 2a22065..e08b51d 100644
--- a/chrome/common/extensions/api/networking_private/networking_private_crypto_openssl.cc
+++ b/chrome/common/extensions/api/networking_private/networking_private_crypto_openssl.cc
@@ -10,6 +10,7 @@
#include <openssl/x509.h>
#include "base/logging.h"
+#include "base/strings/string_util.h"
#include "crypto/openssl_util.h"
#include "crypto/rsa_private_key.h"
#include "crypto/scoped_openssl_types.h"
@@ -17,6 +18,8 @@
namespace {
+typedef crypto::ScopedOpenSSL<X509, X509_free>::Type ScopedX509;
+
// Parses |pem_data| for a PEM block of |pem_type|.
// Returns true if a |pem_type| block is found, storing the decoded result in
// |der_output|.
@@ -38,6 +41,106 @@ bool GetDERFromPEM(const std::string& pem_data,
namespace networking_private_crypto {
+bool VerifyCredentials(const std::string& certificate,
+ const std::string& signature,
+ const std::string& data,
+ const std::string& connected_mac) {
+ crypto::EnsureOpenSSLInit();
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+
+ std::vector<uint8_t> cert_data;
+ if (!GetDERFromPEM(certificate, "CERTIFICATE", &cert_data)) {
+ LOG(ERROR) << "Failed to parse certificate.";
+ return false;
+ }
+
+ // Parse into an OpenSSL X509.
+ const uint8_t* ptr = cert_data.empty() ? NULL : &cert_data[0];
+ const uint8_t* end = ptr + cert_data.size();
+ ScopedX509 cert(d2i_X509(NULL, &ptr, cert_data.size()));
+ if (!cert || ptr != end) {
+ LOG(ERROR) << "Failed to parse certificate.";
+ return false;
+ }
+
+ // Import the trusted public key.
+ ptr = kTrustedCAPublicKeyDER;
+ crypto::ScopedRSA ca_public_key_rsa(
+ d2i_RSAPublicKey(NULL, &ptr, kTrustedCAPublicKeyDERLength));
+ if (!ca_public_key_rsa ||
+ ptr != kTrustedCAPublicKeyDER + kTrustedCAPublicKeyDERLength) {
+ NOTREACHED();
+ LOG(ERROR) << "Failed to import trusted public key.";
+ return false;
+ }
+ crypto::ScopedEVP_PKEY ca_public_key(EVP_PKEY_new());
+ if (!ca_public_key ||
+ !EVP_PKEY_set1_RSA(ca_public_key.get(), ca_public_key_rsa.get())) {
+ LOG(ERROR) << "Failed to initialize EVP_PKEY";
+ return false;
+ }
+
+ // Check that the certificate is signed by the trusted public key.
+ if (X509_verify(cert.get(), ca_public_key.get()) <= 0) {
+ LOG(ERROR) << "Certificate is not issued by the trusted CA.";
+ return false;
+ }
+
+ // Check that the device listed in the certificate is correct.
+ // Something like evt_e161 001a11ffacdf
+ std::string common_name;
+ int common_name_length = X509_NAME_get_text_by_NID(
+ cert->cert_info->subject, NID_commonName, NULL, 0);
+ if (common_name_length < 0) {
+ LOG(ERROR) << "Certificate does not have common name.";
+ return false;
+ }
+ if (common_name_length > 0) {
+ common_name_length = X509_NAME_get_text_by_NID(
+ cert->cert_info->subject,
+ NID_commonName,
+ WriteInto(&common_name, common_name_length + 1),
+ common_name_length + 1);
+ DCHECK_EQ((int)common_name.size(), common_name_length);
+ if (common_name_length < 0) {
+ LOG(ERROR) << "Certificate does not have common name.";
+ return false;
+ }
+ common_name.resize(common_name_length);
+ }
+
+ std::string translated_mac;
+ base::RemoveChars(connected_mac, ":", &translated_mac);
+ if (!EndsWith(common_name, translated_mac, false)) {
+ LOG(ERROR) << "MAC addresses don't match.";
+ return false;
+ }
+
+ // Make sure that the certificate matches the unsigned data presented.
+ // Verify that the |signature| matches |data|.
+ crypto::ScopedEVP_PKEY public_key(X509_get_pubkey(cert.get()));
+ if (!public_key) {
+ LOG(ERROR) << "Unable to extract public key from certificate.";
+ return false;
+ }
+
+ crypto::ScopedEVP_MD_CTX ctx(EVP_MD_CTX_create());
+ if (!ctx) {
+ LOG(ERROR) << "Unable to allocate EVP_MD_CTX.";
+ return false;
+ }
+ if (EVP_DigestVerifyInit(
+ ctx.get(), NULL, EVP_sha1(), NULL, public_key.get()) <= 0 ||
+ EVP_DigestVerifyUpdate(ctx.get(), data.data(), data.size()) <= 0 ||
+ EVP_DigestVerifyFinal(ctx.get(),
+ reinterpret_cast<const uint8_t*>(signature.data()),
+ signature.size()) <= 0) {
+ LOG(ERROR) << "Signed blobs did not match.";
+ return false;
+ }
+ return true;
+}
+
bool EncryptByteString(const std::vector<uint8_t>& pub_key_der,
const std::string& data,
std::vector<uint8_t>* encrypted_output) {
diff --git a/chrome/common/extensions/api/networking_private/networking_private_crypto_unittest.cc b/chrome/common/extensions/api/networking_private/networking_private_crypto_unittest.cc
index 15bd935..d482d59 100644
--- a/chrome/common/extensions/api/networking_private/networking_private_crypto_unittest.cc
+++ b/chrome/common/extensions/api/networking_private/networking_private_crypto_unittest.cc
@@ -46,30 +46,6 @@ TEST_F(NetworkingPrivateCryptoTest, VerifyCredentials) {
"wM9asRj3tJA5VRFbLbsit1VI7IaRCk9rsSKkpBUaVeKbPLz+y/Z6JonXXT6AxsfgUSKDd4B7"
"MYLrTwMQfGuUaaaKko6ldKIrovjrcPloQr1Hxb2bipFcjLmG7nxQLoS6vQ=="
"-----END CERTIFICATE-----";
- static const char kICAData[] =
- "-----BEGIN CERTIFICATE-----"
- "MIIDzTCCArWgAwIBAgIBAzANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQGEwJVUzET"
- "MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzETMBEG"
- "A1UECgwKR29vZ2xlIEluYzENMAsGA1UECwwEQ2FzdDEVMBMGA1UEAwwMQ2FzdCBS"
- "b290IENBMB4XDTE0MDQwMjIwNTg1NFoXDTE5MDQwMjIwNTg1NFowfTELMAkGA1UE"
- "BhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZp"
- "ZXcxEzARBgNVBAoMCkdvb2dsZSBJbmMxEjAQBgNVBAsMCUdvb2dsZSBUVjEYMBYG"
- "A1UEAwwPRXVyZWthIEdlbjEgSUNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB"
- "CgKCAQEAvCKAvYD2OiEAO652XjV/PcNkXFWUhjQvBYcozfdpjBezUKe4gvrfx0Mt"
- "1n6roG+3E3KApEcVwSCZUM3sFGIJW6SYzdJBtjZO/+guMjBKgahCo2ybM27KsvVT"
- "ZuAnU4YahR6nOT9Kd477VGZm+1hUwF45x/VQBgvgitTO4WpVH4sXAOZpoyfmCCVp"
- "PBKdjQUs1i6iMd60UlDWIEnecaD5rSBAEvHdJevV5rg29NaPf8pD3NcQW+Y/UYqF"
- "s/P/9gMtyyNPnK0Y55MFjKxSmvdM6Zl6vm5+TQrjxhypk/o6pZFdHL1m68xg3IZ0"
- "ys/4khyYfVf6YUeeq4C35EiAKpLFGwIDAQABo2AwXjAPBgNVHRMECDAGAQH/AgEA"
- "MB0GA1UdDgQWBBQyr35sod0oQuWz4VmnWjnJ/4pinzAfBgNVHSMEGDAWgBR8mh59"
- "33lUvNfMXsqZhkV5ZXQoGTALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEB"
- "ABPENY9iGt6qsc5yq4JOO6EEqYbKVtkSf1AqW2yJc4M4EZ65eA6bpj9EVIKvDxYq"
- "NI7q40f7jCXiS+Y73OXFaC3Xue8+DV7WVjAvf9QYy79ohnbqadA4U/Sb7vw4AzwT"
- "KCMlH2fUJ5PCNFfTj6lAkeZOhxtegnEMTIB8zvXEb42H0hN4UxRRhCeKS9tIlAmI"
- "Ql1ib0jTDDN6IgQYslrx0dyZzBAsRocq/d3ycXX71iMykoIHZ7rNJ2bDMddRdFk2"
- "D0Ljj4fZjrQNyD4mot/9mqSrF1Q2/AdWQO3pJONcXRWRynJ4Ian3sWdq2B5Dq8Iz"
- "kqrjM7lOq9YEQ+hMRdmOHP4="
- "-----END CERTIFICATE-----";
static const char kName[] = "eureka8997";
static const char kSsdpUdn[] = "c5b2a83b-5958-7ce6-b179-e1f44699429b";
static const char kHotspotBssid[] = "00:1A:11:FF:AC:DF";
@@ -115,43 +91,26 @@ TEST_F(NetworkingPrivateCryptoTest, VerifyCredentials) {
// Checking basic verification operation.
EXPECT_TRUE(networking_private_crypto::VerifyCredentials(
- kCertData, std::vector<std::string>(), signed_data, unsigned_data,
- kHotspotBssid));
-
- // Checking verification operation with an ICA
- std::vector<std::string> icas;
- icas.push_back(kICAData);
- EXPECT_TRUE(networking_private_crypto::VerifyCredentials(
- kCertData, icas, signed_data, unsigned_data, kHotspotBssid));
+ kCertData, signed_data, unsigned_data, kHotspotBssid));
// Checking that verification fails when the certificate is signed, but
// subject is malformed.
EXPECT_FALSE(networking_private_crypto::VerifyCredentials(
- kBadSubjectCertData, std::vector<std::string>(), signed_data,
- unsigned_data, kHotspotBssid));
+ kBadSubjectCertData, signed_data, unsigned_data, kHotspotBssid));
// Checking that verification fails when certificate has invalid format.
EXPECT_FALSE(networking_private_crypto::VerifyCredentials(
- kBadCertData, std::vector<std::string>(), signed_data, unsigned_data,
- kHotspotBssid));
-
- // Checking that verification fails if we supply a bad ICA.
- std::vector<std::string> bad_icas;
- bad_icas.push_back(kCertData);
- EXPECT_FALSE(networking_private_crypto::VerifyCredentials(
- kCertData, bad_icas, signed_data, unsigned_data, kHotspotBssid));
+ kBadCertData, signed_data, unsigned_data, kHotspotBssid));
// Checking that verification fails when Hotspot Bssid is invalid.
EXPECT_FALSE(networking_private_crypto::VerifyCredentials(
- kCertData, std::vector<std::string>(), signed_data, unsigned_data,
- kBadHotspotBssid));
+ kCertData, signed_data, unsigned_data, kBadHotspotBssid));
// Checking that verification fails when there is bad nonce in unsigned_data.
unsigned_data = base::StringPrintf(
"%s,%s,%s,%s,%s", kName, kSsdpUdn, kHotspotBssid, kPublicKey, kBadNonce);
EXPECT_FALSE(networking_private_crypto::VerifyCredentials(
- kCertData, std::vector<std::string>(), signed_data, unsigned_data,
- kHotspotBssid));
+ kCertData, signed_data, unsigned_data, kHotspotBssid));
}
// Test that networking_private_crypto::EncryptByteString behaves as expected.
diff --git a/chrome/test/data/extensions/api_test/networking/test.js b/chrome/test/data/extensions/api_test/networking/test.js
index 6bd2292..9024129 100644
--- a/chrome/test/data/extensions/api_test/networking/test.js
+++ b/chrome/test/data/extensions/api_test/networking/test.js
@@ -15,7 +15,6 @@ var assertEq = chrome.test.assertEq;
// Test properties for the verification API.
var verificationProperties = {
"certificate": "certificate",
- "intermediateCertificates": ["ica1", "ica2", "ica3"],
"publicKey": "cHVibGljX2tleQ==", // Base64("public_key")
"nonce": "nonce",
"signedData": "c2lnbmVkX2RhdGE=", // Base64("signed_data")
diff --git a/chrome/test/data/extensions/api_test/networking_private/test.js b/chrome/test/data/extensions/api_test/networking_private/test.js
index 336018d..0af2e86 100644
--- a/chrome/test/data/extensions/api_test/networking_private/test.js
+++ b/chrome/test/data/extensions/api_test/networking_private/test.js
@@ -14,7 +14,6 @@ var kGuid = 'SOME_GUID';
// Test properties for the verification API.
var verificationProperties = {
"certificate": "certificate",
- "intermediateCertificates": ["ica1", "ica2", "ica3"],
"publicKey": "cHVibGljX2tleQ==", // Base64("public_key")
"nonce": "nonce",
"signedData": "c2lnbmVkX2RhdGE=", // Base64("signed_data")
diff --git a/extensions/browser/BUILD.gn b/extensions/browser/BUILD.gn
index 63eb6e0..a04436b 100644
--- a/extensions/browser/BUILD.gn
+++ b/extensions/browser/BUILD.gn
@@ -533,6 +533,12 @@ source_set("browser") {
"//extensions/common/api/cast_channel:cast_channel_proto",
]
+ if (use_openssl) {
+ sources += [ "api/cast_channel/cast_auth_util_openssl.cc" ]
+ } else {
+ sources += [ "api/cast_channel/cast_auth_util_nss.cc" ]
+ }
+
if (is_chromeos) {
deps += [ "//chromeos" ]
sources += [
diff --git a/extensions/browser/api/cast_channel/cast_auth_util.cc b/extensions/browser/api/cast_channel/cast_auth_util.cc
index e2beca1..e863a57 100644
--- a/extensions/browser/api/cast_channel/cast_auth_util.cc
+++ b/extensions/browser/api/cast_channel/cast_auth_util.cc
@@ -4,14 +4,11 @@
#include "extensions/browser/api/cast_channel/cast_auth_util.h"
-#include <vector>
-
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "extensions/browser/api/cast_channel/cast_message_util.h"
#include "extensions/common/api/cast_channel/cast_channel.pb.h"
-#include "extensions/common/cast/cast_cert_validator.h"
namespace extensions {
namespace core_api {
@@ -23,8 +20,6 @@ const char* const kParseErrorPrefix = "Failed to parse auth message: ";
const unsigned char kAudioOnlyPolicy[] =
{0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0xD6, 0x79, 0x02, 0x05, 0x02};
-namespace cast_crypto = ::extensions::core_api::cast_crypto;
-
// Extracts an embedded DeviceAuthMessage payload from an auth challenge reply
// message.
AuthResult ParseAuthMessage(const CastMessage& challenge_reply,
@@ -60,33 +55,6 @@ AuthResult ParseAuthMessage(const CastMessage& challenge_reply,
return AuthResult();
}
-AuthResult TranslateVerificationResult(
- const cast_crypto::VerificationResult& result) {
- AuthResult translated;
- translated.error_message = result.error_message;
- translated.nss_error_code = result.library_error_code;
- switch (result.error_type) {
- case cast_crypto::VerificationResult::ERROR_NONE:
- translated.error_type = AuthResult::ERROR_NONE;
- break;
- case cast_crypto::VerificationResult::ERROR_CERT_INVALID:
- translated.error_type = AuthResult::ERROR_CERT_PARSING_FAILED;
- break;
- case cast_crypto::VerificationResult::ERROR_CERT_UNTRUSTED:
- translated.error_type = AuthResult::ERROR_CERT_NOT_SIGNED_BY_TRUSTED_CA;
- break;
- case cast_crypto::VerificationResult::ERROR_SIGNATURE_INVALID:
- translated.error_type = AuthResult::ERROR_SIGNED_BLOBS_MISMATCH;
- break;
- case cast_crypto::VerificationResult::ERROR_INTERNAL:
- translated.error_type = AuthResult::ERROR_UNEXPECTED_AUTH_LIBRARY_RESULT;
- break;
- default:
- translated.error_type = AuthResult::ERROR_CERT_NOT_SIGNED_BY_TRUSTED_CA;
- };
- return translated;
-}
-
} // namespace
AuthResult::AuthResult()
@@ -145,31 +113,6 @@ AuthResult AuthenticateChallengeReply(const CastMessage& challenge_reply,
return result;
}
-// This function does the following
-// * Verifies that the trusted CA |response.intermediate_certificate| is
-// whitelisted for use.
-// * Verifies that |response.client_auth_certificate| is signed
-// by the trusted CA certificate.
-// * Verifies that |response.signature| matches the signature
-// of |peer_cert| by |response.client_auth_certificate|'s public
-// key.
-AuthResult VerifyCredentials(const AuthResponse& response,
- const std::string& peer_cert) {
- // Verify the certificate
- scoped_ptr<cast_crypto::CertVerificationContext> verification_context;
- cast_crypto::VerificationResult ret = cast_crypto::VerifyDeviceCert(
- response.client_auth_certificate(),
- std::vector<std::string>(response.intermediate_certificate().begin(),
- response.intermediate_certificate().end()),
- &verification_context);
-
- if (ret.Success())
- ret = verification_context->VerifySignatureOverData(response.signature(),
- peer_cert);
-
- return TranslateVerificationResult(ret);
-}
-
} // namespace cast_channel
} // namespace core_api
} // namespace extensions
diff --git a/extensions/browser/api/cast_channel/cast_auth_util_nss.cc b/extensions/browser/api/cast_channel/cast_auth_util_nss.cc
new file mode 100644
index 0000000..97f16d7
--- /dev/null
+++ b/extensions/browser/api/cast_channel/cast_auth_util_nss.cc
@@ -0,0 +1,142 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/browser/api/cast_channel/cast_auth_util.h"
+
+#include <cert.h>
+#include <cryptohi.h>
+#include <pk11pub.h>
+#include <seccomon.h>
+#include <string>
+
+#include "base/logging.h"
+#include "base/strings/string_piece.h"
+#include "crypto/nss_util.h"
+#include "crypto/scoped_nss_types.h"
+#include "extensions/browser/api/cast_channel/cast_auth_ica.h"
+#include "extensions/browser/api/cast_channel/cast_message_util.h"
+#include "extensions/common/api/cast_channel/cast_channel.pb.h"
+#include "net/base/hash_value.h"
+#include "net/cert/x509_certificate.h"
+
+namespace extensions {
+namespace core_api {
+namespace cast_channel {
+namespace {
+
+typedef scoped_ptr<
+ CERTCertificate,
+ crypto::NSSDestroyer<CERTCertificate, CERT_DestroyCertificate> >
+ ScopedCERTCertificate;
+
+} // namespace
+
+// Authenticates the given credentials:
+// 1. |signature| verification of |peer_cert| using |certificate|.
+// 2. |certificate| is signed by a trusted CA.
+AuthResult VerifyCredentials(const AuthResponse& response,
+ const std::string& peer_cert) {
+ const std::string kErrorPrefix("Failed to verify credentials: ");
+ const std::string& certificate = response.client_auth_certificate();
+ const std::string& signature = response.signature();
+
+ // If the list of intermediates is empty then use kPublicKeyICA1 as
+ // the trusted CA (legacy case).
+ // Otherwise, use the first intermediate in the list as long as it
+ // is in the allowed list of intermediates.
+ int num_intermediates = response.intermediate_certificate_size();
+
+ VLOG(1) << "Response has " << num_intermediates << " intermediates";
+
+ base::StringPiece ica;
+ if (num_intermediates <= 0) {
+ ica = GetDefaultTrustedICAPublicKey();
+ } else {
+ ica = GetTrustedICAPublicKey(response.intermediate_certificate(0));
+ }
+ if (ica.empty()) {
+ return AuthResult::CreateWithParseError(
+ "Disallowed intermediate cert",
+ AuthResult::ERROR_FINGERPRINT_NOT_FOUND);
+ }
+
+ SECItem trusted_ca_key_der;
+ trusted_ca_key_der.type = SECItemType::siDERCertBuffer;
+ trusted_ca_key_der.data =
+ const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(ica.data()));
+ trusted_ca_key_der.len = ica.size();
+
+ crypto::EnsureNSSInit();
+ SECItem der_cert;
+ der_cert.type = siDERCertBuffer;
+ // Make a copy of certificate string so it is safe to type cast.
+ der_cert.data = reinterpret_cast<unsigned char*>(const_cast<char*>(
+ certificate.data()));
+ der_cert.len = certificate.length();
+
+ // Parse into a certificate structure.
+ ScopedCERTCertificate cert(CERT_NewTempCertificate(
+ CERT_GetDefaultCertDB(), &der_cert, NULL, PR_FALSE, PR_TRUE));
+ if (!cert.get()) {
+ return AuthResult::CreateWithNSSError(
+ "Failed to parse certificate.",
+ AuthResult::ERROR_CERT_PARSING_FAILED, PORT_GetError());
+ }
+
+ // Check that the certificate is signed by trusted CA.
+ // NOTE: We const_cast trusted_ca_key_der since on some platforms
+ // SECKEY_ImportDERPublicKey API takes in SECItem* and not const
+ // SECItem*.
+ crypto::ScopedSECKEYPublicKey ca_public_key(
+ SECKEY_ImportDERPublicKey(&trusted_ca_key_der, CKK_RSA));
+ if (!ca_public_key) {
+ return AuthResult::CreateWithNSSError(
+ "Failed to import public key from CA certificate.",
+ AuthResult::ERROR_CERT_PARSING_FAILED, PORT_GetError());
+ }
+ SECStatus verified = CERT_VerifySignedDataWithPublicKey(
+ &cert->signatureWrap, ca_public_key.get(), NULL);
+ if (verified != SECSuccess) {
+ return AuthResult::CreateWithNSSError(
+ "Cert not signed by trusted CA",
+ AuthResult::ERROR_CERT_NOT_SIGNED_BY_TRUSTED_CA, PORT_GetError());
+ }
+
+ VLOG(1) << "Cert signed by trusted CA";
+
+ // Verify that the |signature| matches |peer_cert|.
+ crypto::ScopedSECKEYPublicKey public_key(CERT_ExtractPublicKey(cert.get()));
+ if (!public_key.get()) {
+ return AuthResult::CreateWithNSSError(
+ "Unable to extract public key from certificate",
+ AuthResult::ERROR_CANNOT_EXTRACT_PUBLIC_KEY, PORT_GetError());
+ }
+ SECItem signature_item;
+ signature_item.type = siBuffer;
+ signature_item.data = reinterpret_cast<unsigned char*>(
+ const_cast<char*>(signature.data()));
+ signature_item.len = signature.length();
+ verified = VFY_VerifyDataDirect(
+ reinterpret_cast<unsigned char*>(const_cast<char*>(peer_cert.data())),
+ peer_cert.size(),
+ public_key.get(),
+ &signature_item,
+ SEC_OID_PKCS1_RSA_ENCRYPTION,
+ SEC_OID_SHA1, NULL, NULL);
+
+ if (verified != SECSuccess) {
+ return AuthResult::CreateWithNSSError(
+ "Signed blobs did not match",
+ AuthResult::ERROR_SIGNED_BLOBS_MISMATCH,
+ PORT_GetError());
+ }
+
+ VLOG(1) << "Signature verification succeeded";
+
+ return AuthResult();
+}
+
+} // namespace cast_channel
+} // namespace core_api
+} // namespace extensions
diff --git a/extensions/browser/api/cast_channel/cast_auth_util_openssl.cc b/extensions/browser/api/cast_channel/cast_auth_util_openssl.cc
new file mode 100644
index 0000000..b662840
--- /dev/null
+++ b/extensions/browser/api/cast_channel/cast_auth_util_openssl.cc
@@ -0,0 +1,144 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/browser/api/cast_channel/cast_auth_util.h"
+
+#include <openssl/evp.h>
+#include <openssl/rsa.h>
+#include <openssl/x509.h>
+#include <stddef.h>
+
+#include "base/logging.h"
+#include "base/strings/stringprintf.h"
+#include "crypto/openssl_util.h"
+#include "crypto/scoped_openssl_types.h"
+#include "extensions/browser/api/cast_channel/cast_auth_ica.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"
+#include "net/cert/x509_util_openssl.h"
+
+namespace extensions {
+namespace core_api {
+namespace cast_channel {
+namespace {
+
+typedef crypto::ScopedOpenSSL<X509, X509_free>::Type ScopedX509;
+
+} // namespace
+
+// This function does the following
+// * Verifies that the trusted CA |response.intermediate_certificate| is
+// whitelisted for use.
+// * Verifies that |response.client_auth_certificate| is signed
+// by the trusted CA certificate.
+// * Verifies that |response.signature| matches the signature
+// of |peer_cert| by |response.client_auth_certificate|'s public
+// key.
+//
+// TODO(kmarshall): Report fine-grained errors from OpenSSL.
+AuthResult VerifyCredentials(const AuthResponse& response,
+ const std::string& peer_cert) {
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+
+ // Get the public key of the ICA that was used to sign the client's cert.
+ base::StringPiece ca_public_key_bytes;
+ if (response.intermediate_certificate().size() <= 0) {
+ ca_public_key_bytes = GetDefaultTrustedICAPublicKey();
+ } else {
+ ca_public_key_bytes =
+ GetTrustedICAPublicKey(response.intermediate_certificate(0));
+ if (ca_public_key_bytes.empty()) {
+ LOG(ERROR) << "Couldn't find trusted ICA.";
+ return AuthResult::CreateWithParseError(
+ "failed to verify credentials: cert not signed by trusted CA",
+ AuthResult::ERROR_FINGERPRINT_NOT_FOUND);
+ }
+ }
+
+ // Parse the CA public key.
+ const uint8_t* ca_ptr =
+ reinterpret_cast<const uint8_t*>(ca_public_key_bytes.data());
+ const uint8_t* ca_public_key_end = ca_ptr + ca_public_key_bytes.size();
+ crypto::ScopedRSA ca_public_key_rsa(
+ d2i_RSAPublicKey(NULL, &ca_ptr, ca_public_key_bytes.size()));
+ if (!ca_public_key_rsa || ca_ptr != ca_public_key_end) {
+ LOG(ERROR) << "Failed to import trusted public key.";
+ return AuthResult::CreateWithParseError(
+ "failed to import trusted public key.",
+ AuthResult::ERROR_CERT_PARSING_FAILED);
+ }
+ crypto::ScopedEVP_PKEY ca_public_key(EVP_PKEY_new());
+ if (!ca_public_key ||
+ !EVP_PKEY_set1_RSA(ca_public_key.get(), ca_public_key_rsa.get())) {
+ LOG(ERROR) << "Failed to initialize EVP_PKEY";
+ return AuthResult::CreateWithParseError(
+ "failed to initialize EVP_PKEY.",
+ AuthResult::ERROR_CANNOT_EXTRACT_PUBLIC_KEY);
+ }
+
+ // Parse the client auth certificate.
+ const uint8_t* client_cert_ptr = reinterpret_cast<const uint8_t*>(
+ response.client_auth_certificate().data());
+ const uint8_t* client_cert_end =
+ client_cert_ptr +
+ response.client_auth_certificate().size();
+ const ScopedX509 client_cert(
+ d2i_X509(NULL, &client_cert_ptr,
+ response.client_auth_certificate().size()));
+ if (!client_cert || client_cert_ptr != client_cert_end) {
+ LOG(ERROR) << "Failed to parse certificate.";
+ return AuthResult::CreateWithParseError(
+ "failed to parse client_auth_certificate.",
+ AuthResult::ERROR_CERT_PARSING_FAILED);
+ }
+
+ // Verify that the client auth certificate was signed by a trusted CA.
+ if (X509_verify(client_cert.get(), ca_public_key.get()) <= 0) {
+ LOG(ERROR) << "Certificate is not issued by a trusted CA.";
+ return AuthResult::CreateWithParseError(
+ "cert not signed by trusted CA",
+ AuthResult::ERROR_CERT_NOT_SIGNED_BY_TRUSTED_CA);
+ }
+
+ // Get the client auth certificate's public key.
+ const crypto::ScopedEVP_PKEY client_public_key(
+ X509_get_pubkey(client_cert.get()));
+ const int client_public_key_type = EVP_PKEY_id(client_public_key.get());
+ if (client_public_key_type != EVP_PKEY_RSA) {
+ LOG(ERROR) << "Expected RSA key type for client certificate, got "
+ << client_public_key_type << " instead.";
+ return AuthResult::CreateWithParseError(
+ "couldn't extract public_key from client cert.",
+ AuthResult::ERROR_CANNOT_EXTRACT_PUBLIC_KEY);
+ }
+
+ // Check that the SSL peer certificate was signed using the client's public
+ // key.
+ const crypto::ScopedEVP_MD_CTX ctx(EVP_MD_CTX_create());
+ if (!ctx ||
+ !EVP_DigestVerifyInit(ctx.get(), NULL, EVP_sha1(), NULL,
+ client_public_key.get()) ||
+ !EVP_DigestVerifyUpdate(ctx.get(), peer_cert.data(), peer_cert.size())) {
+ return AuthResult::CreateWithParseError(
+ "error initializing payload verification operation.",
+ AuthResult::ERROR_UNEXPECTED_AUTH_LIBRARY_RESULT);
+ }
+ const std::string& signature = response.signature();
+ if (EVP_DigestVerifyFinal(
+ ctx.get(),
+ reinterpret_cast<uint8_t*>(const_cast<char*>(signature.data())),
+ signature.size()) <= 0) {
+ return AuthResult::CreateWithParseError(
+ "payload verification failed.",
+ AuthResult::ERROR_SIGNED_BLOBS_MISMATCH);
+ }
+
+ return AuthResult();
+}
+
+} // namespace cast_channel
+} // namespace core_api
+} // namespace extensions
+
diff --git a/extensions/browser/api/cast_channel/cast_auth_util_unittest.cc b/extensions/browser/api/cast_channel/cast_auth_util_unittest.cc
index 6d56f683..0e3bcd3 100644
--- a/extensions/browser/api/cast_channel/cast_auth_util_unittest.cc
+++ b/extensions/browser/api/cast_channel/cast_auth_util_unittest.cc
@@ -354,7 +354,8 @@ TEST_F(CastAuthUtilTest, VerifyBadCA) {
AuthResult result = VerifyCredentials(
auth_response, CreatePeerCert());
EXPECT_FALSE(result.success());
- EXPECT_EQ(AuthResult::ERROR_CERT_NOT_SIGNED_BY_TRUSTED_CA, result.error_type);
+ EXPECT_EQ(AuthResult::ERROR_FINGERPRINT_NOT_FOUND,
+ result.error_type);
}
TEST_F(CastAuthUtilTest, VerifyBadClientAuthCert) {
diff --git a/extensions/common/BUILD.gn b/extensions/common/BUILD.gn
index 76e932d..f6dcd00 100644
--- a/extensions/common/BUILD.gn
+++ b/extensions/common/BUILD.gn
@@ -2,7 +2,6 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import("//build/config/crypto.gni")
import("//build/config/features.gni")
import("//third_party/mojo/src/mojo/public/tools/bindings/mojom.gni")
@@ -42,8 +41,6 @@ if (enable_extensions) {
"api/sockets/sockets_manifest_handler.h",
"api/sockets/sockets_manifest_permission.cc",
"api/sockets/sockets_manifest_permission.h",
- "cast/cast_cert_validator.cc",
- "cast/cast_cert_validator.h",
"common_manifest_handlers.cc",
"common_manifest_handlers.h",
"csp_validator.cc",
@@ -252,12 +249,6 @@ if (enable_extensions) {
"//url",
]
- if (use_openssl) {
- sources += [ "cast/cast_cert_validator_openssl.cc" ]
- } else {
- sources += [ "cast/cast_cert_validator_nss.cc" ]
- }
-
if (enable_nacl) {
sources += [
"manifest_handlers/nacl_modules_handler.cc",
diff --git a/extensions/common/cast/cast_cert_validator.cc b/extensions/common/cast/cast_cert_validator.cc
deleted file mode 100644
index e4f0440..0000000
--- a/extensions/common/cast/cast_cert_validator.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "extensions/common/cast/cast_cert_validator.h"
-
-namespace extensions {
-namespace core_api {
-namespace cast_crypto {
-
-VerificationResult::VerificationResult()
- : VerificationResult("", ERROR_NONE, 0) {
-}
-
-VerificationResult::VerificationResult(const std::string& in_error_message,
- ErrorType in_error_type)
- : VerificationResult(in_error_message, in_error_type, 0) {
-}
-
-VerificationResult::VerificationResult(const std::string& in_error_message,
- ErrorType in_error_type,
- int in_error_code)
- : error_type(in_error_type),
- error_message(in_error_message),
- library_error_code(in_error_code) {
-}
-
-} // namespace cast_crypto
-} // namespace core_api
-} // namespace extensions
diff --git a/extensions/common/cast/cast_cert_validator.h b/extensions/common/cast/cast_cert_validator.h
deleted file mode 100644
index b9d2cf6..0000000
--- a/extensions/common/cast/cast_cert_validator.h
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef EXTENSIONS_COMMON_CAST_CAST_CERT_VALIDATOR_H_
-#define EXTENSIONS_COMMON_CAST_CAST_CERT_VALIDATOR_H_
-
-#include <string>
-#include <vector>
-
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/string_piece.h"
-
-namespace extensions {
-namespace core_api {
-namespace cast_crypto {
-
-// Status of a certificate or certificate verification operation.
-struct VerificationResult {
- // Mapped to extensions::core_api::cast_channel::AuthResult::ErrorType in
- // cast_auto_util.cc. Update the mapping code when modifying this enum.
- enum ErrorType {
- // Verification has succeeded.
- ERROR_NONE = 0,
- // There was a problem with the certificate, such as invalid or corrupt
- // certificate data or invalid issuing certificate signature.
- ERROR_CERT_INVALID,
- // Certificate may be valid, but not trusted in this context.
- ERROR_CERT_UNTRUSTED,
- // Signature verification failed
- ERROR_SIGNATURE_INVALID,
- // Catch-all for internal errors that are not covered by the other error
- // types.
- ERROR_INTERNAL
- };
-
- // Constructs a VerificationResult that corresponds to success.
- VerificationResult();
-
- // Construct error-related objects
- VerificationResult(const std::string& error_message, ErrorType error_type);
- VerificationResult(const std::string& error_message,
- ErrorType error_type,
- int error_code);
-
- bool Success() const { return error_type == ERROR_NONE; }
- bool Failure() const { return error_type != ERROR_NONE; }
-
- // Generates a string representation of this object for logging.
- std::string GetLogString() const;
-
- ErrorType error_type;
- // Human-readable description of the problem if error_type != ERROR_NONE
- std::string error_message;
- // May contain the underlying crypto library error code.
- int library_error_code;
-};
-
-// An object of this type is returned by the VerifyCert function, and can be
-// used for additional certificate-related operations, using the verified
-// certificate.
-class CertVerificationContext {
- public:
- CertVerificationContext() {}
- virtual ~CertVerificationContext() {}
-
- // Use the public key from the verified certificate to verify a
- // sha1WithRSAEncryption |signature| over arbitrary |data|. Both |signature|
- // and |data| hold raw binary data.
- virtual VerificationResult VerifySignatureOverData(
- const base::StringPiece& signature,
- const base::StringPiece& data) const = 0;
-
- // Retrieve the Common Name attribute of the subject's distinguished name from
- // the verified certificate, if present. Returns an empty string if no Common
- // Name is found.
- virtual std::string GetCommonName() const = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(CertVerificationContext);
-};
-
-// Verify a cast device certificate, using optional intermediate certificate
-// authority certificates. |context| will be populated with an instance of
-// CertVerificationContext, which allows to perform additional verification
-// steps as required.
-VerificationResult VerifyDeviceCert(
- const base::StringPiece& device_cert,
- const std::vector<std::string>& ica_certs,
- scoped_ptr<CertVerificationContext>* context);
-
-} // namespace cast_crypto
-} // namespace core_api
-} // namespace extensions
-
-#endif // EXTENSIONS_COMMON_CAST_CAST_CERT_VALIDATOR_H_
diff --git a/extensions/common/cast/cast_cert_validator_nss.cc b/extensions/common/cast/cast_cert_validator_nss.cc
deleted file mode 100644
index 425da28..0000000
--- a/extensions/common/cast/cast_cert_validator_nss.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "extensions/common/cast/cast_cert_validator.h"
-
-#include <cert.h>
-#include <cryptohi.h>
-#include <pk11pub.h>
-#include <seccomon.h>
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/string_number_conversions.h"
-#include "crypto/nss_util.h"
-#include "crypto/scoped_nss_types.h"
-#include "extensions/browser/api/cast_channel/cast_auth_ica.h"
-
-namespace extensions {
-namespace core_api {
-namespace cast_crypto {
-
-namespace {
-
-typedef scoped_ptr<
- CERTCertificate,
- crypto::NSSDestroyer<CERTCertificate, CERT_DestroyCertificate>>
- ScopedCERTCertificate;
-
-class CertVerificationContextNSS : public CertVerificationContext {
- public:
- explicit CertVerificationContextNSS(CERTCertificate* certificate)
- : certificate_(certificate) {}
-
- VerificationResult VerifySignatureOverData(
- const base::StringPiece& signature,
- const base::StringPiece& data) const override {
- // Retrieve public key object
- crypto::ScopedSECKEYPublicKey public_key_obj(
- CERT_ExtractPublicKey(certificate_.get()));
- if (!public_key_obj.get()) {
- return VerificationResult(
- "Failed to extract device certificate public key.",
- VerificationResult::ERROR_CERT_INVALID);
- }
- // Verify signature.
- SECItem signature_item;
- signature_item.type = siBuffer;
- signature_item.data =
- reinterpret_cast<unsigned char*>(const_cast<char*>(signature.data()));
- signature_item.len = signature.length();
- if (VFY_VerifyDataDirect(
- reinterpret_cast<unsigned char*>(const_cast<char*>(data.data())),
- data.size(), public_key_obj.get(), &signature_item,
- SEC_OID_PKCS1_RSA_ENCRYPTION, SEC_OID_SHA1, NULL,
- NULL) != SECSuccess) {
- return VerificationResult("Signature verification failed.",
- VerificationResult::ERROR_SIGNATURE_INVALID,
- PORT_GetError());
- }
- return VerificationResult();
- }
-
- std::string GetCommonName() const override {
- char* common_name = CERT_GetCommonName(&certificate_->subject);
- if (!common_name)
- return std::string();
-
- std::string result(common_name);
- PORT_Free(common_name);
- return result;
- }
-
- private:
- ScopedCERTCertificate certificate_;
-};
-
-} // namespace
-
-VerificationResult VerifyDeviceCert(
- const base::StringPiece& device_cert,
- const std::vector<std::string>& ica_certs,
- scoped_ptr<CertVerificationContext>* context) {
- crypto::EnsureNSSInit();
-
- // If the list of intermediates is empty then use kPublicKeyICA1 as
- // the trusted CA (legacy case).
- // Otherwise, use the first intermediate in the list as long as it
- // is in the allowed list of intermediates.
- base::StringPiece ica_public_key_der =
- (ica_certs.size() == 0)
- ? cast_channel::GetDefaultTrustedICAPublicKey()
- : cast_channel::GetTrustedICAPublicKey(ica_certs[0]);
-
- if (ica_public_key_der.empty()) {
- return VerificationResult(
- "Device certificate is not signed by a trusted CA",
- VerificationResult::ERROR_CERT_UNTRUSTED);
- }
- // Initialize the ICA public key.
- SECItem ica_public_key_der_item;
- ica_public_key_der_item.type = SECItemType::siDERCertBuffer;
- ica_public_key_der_item.data = const_cast<uint8_t*>(
- reinterpret_cast<const uint8_t*>(ica_public_key_der.data()));
- ica_public_key_der_item.len = ica_public_key_der.size();
-
- crypto::ScopedSECKEYPublicKey ica_public_key_obj(
- SECKEY_ImportDERPublicKey(&ica_public_key_der_item, CKK_RSA));
- if (!ica_public_key_obj) {
- return VerificationResult("Failed to import trusted public key.",
- VerificationResult::ERROR_INTERNAL,
- PORT_GetError());
- }
- SECItem device_cert_der_item;
- device_cert_der_item.type = siDERCertBuffer;
- // Make a copy of certificate string so it is safe to type cast.
- device_cert_der_item.data =
- reinterpret_cast<unsigned char*>(const_cast<char*>(device_cert.data()));
- device_cert_der_item.len = device_cert.length();
-
- // Parse into a certificate structure.
- ScopedCERTCertificate device_cert_obj(CERT_NewTempCertificate(
- CERT_GetDefaultCertDB(), &device_cert_der_item, NULL, PR_FALSE, PR_TRUE));
- if (!device_cert_obj.get()) {
- return VerificationResult("Failed to parse device certificate.",
- VerificationResult::ERROR_CERT_INVALID,
- PORT_GetError());
- }
- if (CERT_VerifySignedDataWithPublicKey(&device_cert_obj->signatureWrap,
- ica_public_key_obj.get(),
- NULL) != SECSuccess) {
- return VerificationResult("Signature verification failed.",
- VerificationResult::ERROR_SIGNATURE_INVALID,
- PORT_GetError());
- }
- if (context) {
- scoped_ptr<CertVerificationContext> tmp_context(
- new CertVerificationContextNSS(device_cert_obj.release()));
- tmp_context.swap(*context);
- }
-
- return VerificationResult();
-}
-
-std::string VerificationResult::GetLogString() const {
- std::string nssError = "NSS Error Code: ";
- nssError += base::IntToString(library_error_code);
- return error_message.size()
- ? std::string("Error: ") + error_message + ", " + nssError
- : nssError;
-}
-
-} // namespace cast_crypto
-} // namespace core_api
-} // namespace extensions
diff --git a/extensions/common/cast/cast_cert_validator_openssl.cc b/extensions/common/cast/cast_cert_validator_openssl.cc
deleted file mode 100644
index 8c2e4c0..0000000
--- a/extensions/common/cast/cast_cert_validator_openssl.cc
+++ /dev/null
@@ -1,158 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "extensions/common/cast/cast_cert_validator.h"
-
-#include <openssl/digest.h>
-#include <openssl/evp.h>
-#include <openssl/rsa.h>
-#include <openssl/x509.h>
-
-#include "base/logging.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "crypto/openssl_util.h"
-#include "crypto/scoped_openssl_types.h"
-#include "extensions/browser/api/cast_channel/cast_auth_ica.h"
-#include "net/cert/x509_certificate.h"
-#include "net/cert/x509_util_openssl.h"
-
-namespace extensions {
-namespace core_api {
-namespace cast_crypto {
-namespace {
-
-typedef crypto::ScopedOpenSSL<X509, X509_free>::Type ScopedX509;
-
-class CertVerificationContextOpenSSL : public CertVerificationContext {
- public:
- // Takes ownership of the passed-in x509 object
- explicit CertVerificationContextOpenSSL(X509* x509) : x509_(x509) {}
-
- VerificationResult VerifySignatureOverData(
- const base::StringPiece& signature,
- const base::StringPiece& data) const override {
- // Retrieve public key object.
- crypto::ScopedEVP_PKEY public_key(X509_get_pubkey(x509_.get()));
- if (!public_key) {
- return VerificationResult(
- "Failed to extract device certificate public key.",
- VerificationResult::ERROR_CERT_INVALID);
- }
- // Make sure the key is RSA.
- const int public_key_type = EVP_PKEY_id(public_key.get());
- if (public_key_type != EVP_PKEY_RSA) {
- return VerificationResult(
- std::string("Expected RSA key type for client certificate, got ") +
- base::IntToString(public_key_type) + " instead.",
- VerificationResult::ERROR_CERT_INVALID);
- }
- // Verify signature.
- const crypto::ScopedEVP_MD_CTX ctx(EVP_MD_CTX_create());
- if (!ctx ||
- !EVP_DigestVerifyInit(ctx.get(), NULL, EVP_sha1(), NULL,
- public_key.get()) ||
- !EVP_DigestVerifyUpdate(ctx.get(), data.data(), data.size()) ||
- !EVP_DigestVerifyFinal(
- ctx.get(), reinterpret_cast<const uint8_t*>(signature.data()),
- signature.size())) {
- return VerificationResult("Signature verification failed.",
- VerificationResult::ERROR_SIGNATURE_INVALID);
- }
- return VerificationResult();
- }
-
- std::string GetCommonName() const override {
- int common_name_length = X509_NAME_get_text_by_NID(
- x509_->cert_info->subject, NID_commonName, NULL, 0);
- if (common_name_length < 0)
- return std::string();
- std::string common_name;
- common_name_length = X509_NAME_get_text_by_NID(
- x509_->cert_info->subject, NID_commonName,
- WriteInto(&common_name, static_cast<size_t>(common_name_length) + 1),
- common_name_length + 1);
- if (common_name_length < 0)
- return std::string();
- return common_name;
- }
-
- private:
- ScopedX509 x509_;
-};
-
-} // namespace
-
-VerificationResult VerifyDeviceCert(
- const base::StringPiece& device_cert,
- const std::vector<std::string>& ica_certs,
- scoped_ptr<CertVerificationContext>* context) {
- crypto::EnsureOpenSSLInit();
- crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
-
- // If the list of intermediates is empty then use kPublicKeyICA1 as
- // the trusted CA (legacy case).
- // Otherwise, use the first intermediate in the list as long as it
- // is in the allowed list of intermediates.
- base::StringPiece ica_public_key_der =
- (ica_certs.size() == 0)
- ? cast_channel::GetDefaultTrustedICAPublicKey()
- : cast_channel::GetTrustedICAPublicKey(ica_certs[0]);
-
- if (ica_public_key_der.empty()) {
- return VerificationResult(
- "Device certificate is not signed by a trusted CA",
- VerificationResult::ERROR_CERT_UNTRUSTED);
- }
- // Initialize the ICA public key.
- const uint8_t* ica_public_key_der_ptr =
- reinterpret_cast<const uint8_t*>(ica_public_key_der.data());
- const uint8_t* ica_public_key_der_end =
- ica_public_key_der_ptr + ica_public_key_der.size();
- crypto::ScopedRSA ica_public_key_rsa(d2i_RSAPublicKey(
- NULL, &ica_public_key_der_ptr, ica_public_key_der.size()));
- if (!ica_public_key_rsa || ica_public_key_der_ptr != ica_public_key_der_end) {
- return VerificationResult("Failed to import trusted public key.",
- VerificationResult::ERROR_INTERNAL);
- }
- crypto::ScopedEVP_PKEY ica_public_key_evp(EVP_PKEY_new());
- if (!ica_public_key_evp ||
- !EVP_PKEY_set1_RSA(ica_public_key_evp.get(), ica_public_key_rsa.get())) {
- return VerificationResult("Failed to import trusted public key.",
- VerificationResult::ERROR_INTERNAL);
- }
- // Parse the device certificate.
- const uint8_t* device_cert_der_ptr =
- reinterpret_cast<const uint8_t*>(device_cert.data());
- const uint8_t* device_cert_der_end = device_cert_der_ptr + device_cert.size();
- ScopedX509 device_cert_x509(
- d2i_X509(NULL, &device_cert_der_ptr, device_cert.size()));
- if (!device_cert_x509 || device_cert_der_ptr != device_cert_der_end) {
- return VerificationResult("Failed to parse device certificate.",
- VerificationResult::ERROR_CERT_INVALID);
- }
- // Verify device certificate.
- if (X509_verify(device_cert_x509.get(), ica_public_key_evp.get()) != 1) {
- return VerificationResult(
- "Device certificate signature verification failed.",
- VerificationResult::ERROR_CERT_INVALID);
- }
-
- if (context) {
- scoped_ptr<CertVerificationContext> tmp_context(
- new CertVerificationContextOpenSSL(device_cert_x509.release()));
- tmp_context.swap(*context);
- }
-
- return VerificationResult();
-}
-
-std::string VerificationResult::GetLogString() const {
- return error_message;
-}
-
-} // namespace cast_crypto
-} // namespace core_api
-} // namespace extensions
diff --git a/extensions/extensions.gyp b/extensions/extensions.gyp
index 1015f9f..1d3a8c9 100644
--- a/extensions/extensions.gyp
+++ b/extensions/extensions.gyp
@@ -84,8 +84,6 @@
'common/api/sockets/sockets_manifest_handler.h',
'common/api/sockets/sockets_manifest_permission.cc',
'common/api/sockets/sockets_manifest_permission.h',
- 'common/cast/cast_cert_validator.cc',
- 'common/cast/cast_cert_validator.h',
'common/common_manifest_handlers.cc',
'common/common_manifest_handlers.h',
'common/csp_validator.cc',
@@ -283,31 +281,6 @@
'common/manifest_handlers/nacl_modules_handler.h',
],
}],
- ['use_openssl==1', {
- 'sources': [
- 'common/cast/cast_cert_validator_openssl.cc',
- ],
- 'dependencies': [
- '../third_party/boringssl/boringssl.gyp:boringssl',
- ],
- }, {
- 'sources': [
- 'common/cast/cast_cert_validator_nss.cc',
- ],
- 'conditions': [
- ['os_posix == 1 and OS != "mac" and OS != "ios" and OS != "android"', {
- 'dependencies': [
- '../build/linux/system.gyp:ssl',
- ],
- }],
- ['OS == "mac" or OS == "ios" or OS == "win"', {
- 'dependencies': [
- '../third_party/nss/nss.gyp:nspr',
- '../third_party/nss/nss.gyp:nss',
- ],
- }],
- ],
- }],
],
},
{
@@ -859,6 +832,32 @@
'browser/api/vpn_provider/vpn_service_factory.h'
]
}],
+ ['use_openssl==1', {
+ 'sources': [
+ 'browser/api/cast_channel/cast_auth_util_openssl.cc',
+ ],
+ 'dependencies': [
+ '../third_party/boringssl/boringssl.gyp:boringssl',
+ ],
+ }, {
+ 'sources': [
+ # cast_auth_util_nss.cc uses NSS functions.
+ 'browser/api/cast_channel/cast_auth_util_nss.cc',
+ ],
+ 'conditions': [
+ ['os_posix == 1 and OS != "mac" and OS != "ios" and OS != "android"', {
+ 'dependencies': [
+ '../build/linux/system.gyp:ssl',
+ ],
+ }],
+ ['OS == "mac" or OS == "ios" or OS == "win"', {
+ 'dependencies': [
+ '../third_party/nss/nss.gyp:nspr',
+ '../third_party/nss/nss.gyp:nss',
+ ],
+ }],
+ ],
+ }],
['OS != "linux"', {
'sources': [
'browser/api/audio/audio_service.cc',