Commit ee9d35aa authored by jochen's avatar jochen Committed by Commit bot

Revert of Refactoring of Cast-related crypto code (patchset #19 id:350001 of...

Revert of Refactoring of Cast-related crypto code (patchset #19 id:350001 of https://codereview.chromium.org/792353002/)

Reason for revert:
fails to compile on Linux ChromiumOS GN https://build.chromium.org/p/chromium.chromiumos/builders/Linux%20ChromiumOS%20GN/builds/6146/steps/compile/logs/stdio

Original issue's description:
> 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/ed1e90f4f980709cef6a8a9c7e0f64cfe5578cdd
> Cr-Commit-Position: refs/heads/master@{#311460}

TBR=stevenjb@chromium.org,mef@chromium.org,rsleevi@chromium.org,vadimgo@chromium.org,mfoltz@chromium.org,kmarshall@chromium.org,rockot@chromium.org,brettw@chromium.org,sheretov@chromium.org
NOTREECHECKS=true
NOTRY=true
BUG=442650

Review URL: https://codereview.chromium.org/853663003

Cr-Commit-Position: refs/heads/master@{#311461}
parent ed1e90f4
......@@ -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;
......
......@@ -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;
......
......@@ -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();
......
// 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
// 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
// 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_
......@@ -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;
......
......@@ -351,23 +351,21 @@
'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',
'browser/extensions/api/networking_private/networking_private_event_router.h',
'browser/extensions/api/networking_private/networking_private_event_router_chromeos.cc',
'browser/extensions/api/networking_private/networking_private_credentials_getter_chromeos.cc',
'browser/extensions/api/networking_private/networking_private_event_router_factory.cc',
'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',
......
......@@ -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',
......@@ -350,15 +343,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"', {
......
......@@ -2428,11 +2428,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',
......
......@@ -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 +=
......
......@@ -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",
......
......@@ -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
......@@ -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_
......@@ -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) {
......
......@@ -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) {
......
......@@ -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.
......
......@@ -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")
......
......@@ -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")
......
......@@ -519,6 +519,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 += [
......
......@@ -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
// 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
// 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
......@@ -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) {
......
......@@ -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("//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",
......
// 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
// 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_
// 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
// 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
......@@ -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',
],
}],
],
}],
],
},
{
......@@ -845,6 +818,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',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment