diff options
author | davidben <davidben@chromium.org> | 2015-10-02 09:46:39 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-10-02 16:47:29 +0000 |
commit | 9cd4b57584efba6ae7686e1b4689434e73543c96 (patch) | |
tree | 332895584a1fb755a3bd9b32bde605df88c1c760 /extensions | |
parent | ebf0bc25277c6a656337e442060fc51dfc201048 (diff) | |
download | chromium_src-9cd4b57584efba6ae7686e1b4689434e73543c96.zip chromium_src-9cd4b57584efba6ae7686e1b4689434e73543c96.tar.gz chromium_src-9cd4b57584efba6ae7686e1b4689434e73543c96.tar.bz2 |
Fold away the NSS cast_cert_validator.cc path.
All platforms with extensions may assume OpenSSL. This removes the
three-argument form of VerificationResult as it's no longer used.
BUG=519504
Review URL: https://codereview.chromium.org/1365733004
Cr-Commit-Position: refs/heads/master@{#352054}
Diffstat (limited to 'extensions')
-rw-r--r-- | extensions/browser/api/cast_channel/cast_auth_util.cc | 24 | ||||
-rw-r--r-- | extensions/browser/api/cast_channel/cast_auth_util.h | 12 | ||||
-rw-r--r-- | extensions/browser/api/cast_channel/cast_channel_api.cc | 2 | ||||
-rw-r--r-- | extensions/browser/api/cast_channel/logger.cc | 6 | ||||
-rw-r--r-- | extensions/browser/api/cast_channel/logger_unittest.cc | 21 | ||||
-rw-r--r-- | extensions/browser/api/cast_channel/logger_util.cc | 4 | ||||
-rw-r--r-- | extensions/browser/api/cast_channel/logger_util.h | 3 | ||||
-rw-r--r-- | extensions/common/BUILD.gn | 14 | ||||
-rw-r--r-- | extensions/common/api/cast_channel/logging.proto | 1 | ||||
-rw-r--r-- | extensions/common/cast/cast_cert_validator.cc | 151 | ||||
-rw-r--r-- | extensions/common/cast/cast_cert_validator.h | 12 | ||||
-rw-r--r-- | extensions/common/cast/cast_cert_validator_nss.cc | 155 | ||||
-rw-r--r-- | extensions/common/cast/cast_cert_validator_openssl.cc | 158 | ||||
-rw-r--r-- | extensions/extensions.gyp | 26 | ||||
-rw-r--r-- | extensions/extensions.gypi | 6 |
15 files changed, 159 insertions, 436 deletions
diff --git a/extensions/browser/api/cast_channel/cast_auth_util.cc b/extensions/browser/api/cast_channel/cast_auth_util.cc index 759ee7d..10c3775 100644 --- a/extensions/browser/api/cast_channel/cast_auth_util.cc +++ b/extensions/browser/api/cast_channel/cast_auth_util.cc @@ -64,7 +64,6 @@ 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; @@ -90,8 +89,10 @@ AuthResult TranslateVerificationResult( } // namespace AuthResult::AuthResult() - : error_type(ERROR_NONE), nss_error_code(0), channel_policies(POLICY_NONE) { -} + : error_type(ERROR_NONE), channel_policies(POLICY_NONE) {} + +AuthResult::AuthResult(const std::string& error_message, ErrorType error_type) + : error_message(error_message), error_type(error_type) {} AuthResult::~AuthResult() { } @@ -99,22 +100,7 @@ AuthResult::~AuthResult() { // static AuthResult AuthResult::CreateWithParseError(const std::string& error_message, ErrorType error_type) { - return AuthResult(kParseErrorPrefix + error_message, error_type, 0); -} - -// static -AuthResult AuthResult::CreateWithNSSError(const std::string& error_message, - ErrorType error_type, - int nss_error_code) { - return AuthResult(error_message, error_type, nss_error_code); -} - -AuthResult::AuthResult(const std::string& error_message, - ErrorType error_type, - int nss_error_code) - : error_message(error_message), - error_type(error_type), - nss_error_code(nss_error_code) { + return AuthResult(kParseErrorPrefix + error_message, error_type); } AuthResult AuthenticateChallengeReply(const CastMessage& challenge_reply, diff --git a/extensions/browser/api/cast_channel/cast_auth_util.h b/extensions/browser/api/cast_channel/cast_auth_util.h index a500586..e1c07f4 100644 --- a/extensions/browser/api/cast_channel/cast_auth_util.h +++ b/extensions/browser/api/cast_channel/cast_auth_util.h @@ -37,25 +37,19 @@ struct AuthResult { // Constructs a AuthResult that corresponds to success. AuthResult(); + + AuthResult(const std::string& error_message, ErrorType error_type); + ~AuthResult(); static AuthResult CreateWithParseError(const std::string& error_message, ErrorType error_type); - static AuthResult CreateWithNSSError(const std::string& error_message, - ErrorType error_type, - int nss_error_code); bool success() const { return error_type == ERROR_NONE; } std::string error_message; ErrorType error_type; - int nss_error_code; unsigned int channel_policies; - - private: - AuthResult(const std::string& error_message, - ErrorType error_type, - int nss_error_code); }; // Authenticates the given |challenge_reply|: diff --git a/extensions/browser/api/cast_channel/cast_channel_api.cc b/extensions/browser/api/cast_channel/cast_channel_api.cc index 52c4d90..0b1fa2e 100644 --- a/extensions/browser/api/cast_channel/cast_channel_api.cc +++ b/extensions/browser/api/cast_channel/cast_channel_api.cc @@ -90,8 +90,6 @@ void FillErrorInfo(ChannelError error_state, } if (last_errors.net_return_value <= 0) error_info->net_return_value.reset(new int(last_errors.net_return_value)); - if (last_errors.nss_error_code < 0) - error_info->nss_error_code.reset(new int(last_errors.nss_error_code)); } bool IsValidConnectInfoPort(const ConnectInfo& connect_info) { diff --git a/extensions/browser/api/cast_channel/logger.cc b/extensions/browser/api/cast_channel/logger.cc index 77b281f..e6d3a77 100644 --- a/extensions/browser/api/cast_channel/logger.cc +++ b/extensions/browser/api/cast_channel/logger.cc @@ -115,10 +115,6 @@ void MaybeSetLastErrors(const SocketEvent& event, LastErrors* last_errors) { event.challenge_reply_error_type(); last_errors->event_type = event.type(); } - if (event.has_nss_error_code()) { - last_errors->nss_error_code = event.nss_error_code(); - last_errors->event_type = event.type(); - } } } // namespace @@ -265,8 +261,6 @@ void Logger::LogSocketChallengeReplyEvent(int channel_id, SocketEvent event = CreateEvent(proto::AUTH_CHALLENGE_REPLY); event.set_challenge_reply_error_type( ChallegeReplyErrorToProto(auth_result.error_type)); - if (auth_result.nss_error_code != 0) - event.set_nss_error_code(auth_result.nss_error_code); LogSocketEvent(channel_id, event); } diff --git a/extensions/browser/api/cast_channel/logger_unittest.cc b/extensions/browser/api/cast_channel/logger_unittest.cc index b3a40ad..13e00b7 100644 --- a/extensions/browser/api/cast_channel/logger_unittest.cc +++ b/extensions/browser/api/cast_channel/logger_unittest.cc @@ -16,8 +16,6 @@ namespace extensions { namespace api { namespace cast_channel { -const int kTestNssErrorCode = -8164; - using proto::AggregatedSocketEvent; using proto::EventType; using proto::Log; @@ -107,9 +105,7 @@ TEST_F(CastChannelLoggerTest, BasicLogging) { clock_->Advance(base::TimeDelta::FromMicroseconds(1)); auth_result = - AuthResult::CreateWithNSSError("Parsing failed", - AuthResult::ERROR_CERT_PARSING_FAILED, - kTestNssErrorCode); + AuthResult("Parsing failed", AuthResult::ERROR_CERT_PARSING_FAILED); logger_->LogSocketChallengeReplyEvent(2, auth_result); LastErrors last_errors = logger_->GetLastErrors(2); @@ -117,7 +113,6 @@ TEST_F(CastChannelLoggerTest, BasicLogging) { EXPECT_EQ(last_errors.net_return_value, net::OK); EXPECT_EQ(last_errors.challenge_reply_error_type, proto::CHALLENGE_REPLY_ERROR_CERT_PARSING_FAILED); - EXPECT_EQ(last_errors.nss_error_code, kTestNssErrorCode); scoped_ptr<Log> log = GetLog(); ASSERT_TRUE(log); @@ -179,7 +174,7 @@ TEST_F(CastChannelLoggerTest, BasicLogging) { EXPECT_EQ(proto::CHALLENGE_REPLY_ERROR_CERT_PARSING_FAILED, event.challenge_reply_error_type()); EXPECT_FALSE(event.has_net_return_value()); - EXPECT_EQ(kTestNssErrorCode, event.nss_error_code()); + EXPECT_FALSE(event.has_nss_error_code()); } } } @@ -212,21 +207,16 @@ TEST_F(CastChannelLoggerTest, LogLastErrorEvents) { EXPECT_EQ(last_errors.net_return_value, net::OK); EXPECT_EQ(last_errors.challenge_reply_error_type, proto::CHALLENGE_REPLY_ERROR_NONE); - EXPECT_EQ(last_errors.nss_error_code, 0); - // Now log a challenge reply error with NSS error code. LastErrors will be - // set. + // Now log a challenge reply error. LastErrors will be set. clock_->Advance(base::TimeDelta::FromMicroseconds(1)); - auth_result = AuthResult::CreateWithNSSError( - "Some error", - AuthResult::ErrorType::ERROR_WRONG_PAYLOAD_TYPE, - kTestNssErrorCode); + auth_result = + AuthResult("Some error failed", AuthResult::ERROR_WRONG_PAYLOAD_TYPE); logger_->LogSocketChallengeReplyEvent(3, auth_result); last_errors = logger_->GetLastErrors(3); EXPECT_EQ(last_errors.event_type, proto::AUTH_CHALLENGE_REPLY); EXPECT_EQ(last_errors.challenge_reply_error_type, proto::CHALLENGE_REPLY_ERROR_WRONG_PAYLOAD_TYPE); - EXPECT_EQ(last_errors.nss_error_code, kTestNssErrorCode); // Logging a non-error event does not change the LastErrors for the channel. clock_->Advance(base::TimeDelta::FromMicroseconds(1)); @@ -235,7 +225,6 @@ TEST_F(CastChannelLoggerTest, LogLastErrorEvents) { EXPECT_EQ(last_errors.event_type, proto::AUTH_CHALLENGE_REPLY); EXPECT_EQ(last_errors.challenge_reply_error_type, proto::CHALLENGE_REPLY_ERROR_WRONG_PAYLOAD_TYPE); - EXPECT_EQ(last_errors.nss_error_code, kTestNssErrorCode); } TEST_F(CastChannelLoggerTest, LogSocketReadWrite) { diff --git a/extensions/browser/api/cast_channel/logger_util.cc b/extensions/browser/api/cast_channel/logger_util.cc index db5f201..35e2c10 100644 --- a/extensions/browser/api/cast_channel/logger_util.cc +++ b/extensions/browser/api/cast_channel/logger_util.cc @@ -12,9 +12,7 @@ namespace cast_channel { LastErrors::LastErrors() : event_type(proto::EVENT_TYPE_UNKNOWN), challenge_reply_error_type(proto::CHALLENGE_REPLY_ERROR_NONE), - net_return_value(net::OK), - nss_error_code(0) { -} + net_return_value(net::OK) {} LastErrors::~LastErrors() { } diff --git a/extensions/browser/api/cast_channel/logger_util.h b/extensions/browser/api/cast_channel/logger_util.h index 2a9f293..2b5de5b 100644 --- a/extensions/browser/api/cast_channel/logger_util.h +++ b/extensions/browser/api/cast_channel/logger_util.h @@ -31,9 +31,6 @@ struct LastErrors { // The most recent net_return_value logged for the socket. int net_return_value; - - // The most recent NSS error logged for the socket. - int nss_error_code; }; } // namespace cast_channel diff --git a/extensions/common/BUILD.gn b/extensions/common/BUILD.gn index c76d9b1..3a557d3 100644 --- a/extensions/common/BUILD.gn +++ b/extensions/common/BUILD.gn @@ -60,6 +60,7 @@ if (enable_extensions) { "//extensions:extensions_resources", "//ipc", "//net", + "//third_party/boringssl", "//third_party/icu", "//third_party/libxml", "//third_party/re2", @@ -69,19 +70,6 @@ if (enable_extensions) { "//url", ] - if (use_openssl) { - sources += - rebase_path(extensions_gypi_values.extensions_common_sources_openssl, - ".", - "//extensions") - deps += [ "//third_party/boringssl" ] - } else { - sources += rebase_path( - extensions_gypi_values.extensions_common_sources_nonopenssl, - ".", - "//extensions") - } - if (enable_nacl) { nacl_sources = rebase_path(extensions_gypi_values.extensions_common_sources_nacl, diff --git a/extensions/common/api/cast_channel/logging.proto b/extensions/common/api/cast_channel/logging.proto index a629aee..6ac52e4 100644 --- a/extensions/common/api/cast_channel/logging.proto +++ b/extensions/common/api/cast_channel/logging.proto @@ -142,6 +142,7 @@ message SocketEvent { optional ErrorState error_state = 10; optional ChallengeReplyErrorType challenge_reply_error_type = 11; + // No longer used. optional int32 nss_error_code = 12; } diff --git a/extensions/common/cast/cast_cert_validator.cc b/extensions/common/cast/cast_cert_validator.cc index cdd803a..5bf7300 100644 --- a/extensions/common/cast/cast_cert_validator.cc +++ b/extensions/common/cast/cast_cert_validator.cc @@ -4,27 +4,156 @@ #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" +#include "net/ssl/scoped_openssl_types.h" namespace extensions { namespace api { namespace cast_crypto { +namespace { -VerificationResult::VerificationResult() - : VerificationResult("", ERROR_NONE, 0) { -} +class CertVerificationContextImpl : public CertVerificationContext { + public: + // Takes ownership of the passed-in x509 object + explicit CertVerificationContextImpl(net::ScopedX509 x509) + : x509_(x509.Pass()) {} + + 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(), nullptr, EVP_sha1(), nullptr, + 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, + base::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: + net::ScopedX509 x509_; +}; + +} // namespace + +VerificationResult::VerificationResult() : VerificationResult("", ERROR_NONE) {} VerificationResult::VerificationResult(const std::string& in_error_message, ErrorType in_error_type) - : VerificationResult(in_error_message, in_error_type, 0) { -} + : error_type(in_error_type), error_message(in_error_message) {} -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) { +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(); + net::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) + context->reset(new CertVerificationContextImpl(device_cert_x509.Pass())); + + return VerificationResult(); } bool SetTrustedCertificateAuthoritiesForTest(const std::string& keys, diff --git a/extensions/common/cast/cast_cert_validator.h b/extensions/common/cast/cast_cert_validator.h index 720fff5..8a37fa1 100644 --- a/extensions/common/cast/cast_cert_validator.h +++ b/extensions/common/cast/cast_cert_validator.h @@ -39,25 +39,17 @@ struct 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 +// An object of this type is returned by the VerifyDeviceCert function, and can +// be used for additional certificate-related operations, using the verified // certificate. class CertVerificationContext { public: 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 47b7648..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 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 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 4e0e08b..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" -#include "net/ssl/scoped_openssl_types.h" - -namespace extensions { -namespace api { -namespace cast_crypto { -namespace { - -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, - base::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: - net::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(); - net::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 api -} // namespace extensions diff --git a/extensions/extensions.gyp b/extensions/extensions.gyp index 6e807d4..c7976da 100644 --- a/extensions/extensions.gyp +++ b/extensions/extensions.gyp @@ -59,6 +59,7 @@ '../ui/gfx/gfx.gyp:gfx_geometry', '../ui/gfx/ipc/gfx_ipc.gyp:gfx_ipc', '../url/url.gyp:url_lib', + '../third_party/boringssl/boringssl.gyp:boringssl', '../third_party/libxml/libxml.gyp:libxml', 'common/api/api.gyp:extensions_api', 'extensions_resources.gyp:extensions_resources', @@ -90,31 +91,6 @@ '<@(extensions_common_sources_nacl)', ], }], - ['use_openssl==1', { - 'sources': [ - '<@(extensions_common_sources_openssl)', - ], - 'dependencies': [ - '../third_party/boringssl/boringssl.gyp:boringssl', - ], - }, { - 'sources': [ - '<@(extensions_common_sources_nonopenssl)' - ], - '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', - ], - }], - ], - }], ], }, { diff --git a/extensions/extensions.gypi b/extensions/extensions.gypi index 575ed02..68b1b80 100644 --- a/extensions/extensions.gypi +++ b/extensions/extensions.gypi @@ -228,12 +228,6 @@ 'common/manifest_handlers/nacl_modules_handler.cc', 'common/manifest_handlers/nacl_modules_handler.h', ], - 'extensions_common_sources_openssl': [ - 'common/cast/cast_cert_validator_openssl.cc', - ], - 'extensions_common_sources_nonopenssl': [ - 'common/cast/cast_cert_validator_nss.cc', - ], 'extensions_browser_sources': [ # NOTE: When moving an API out of Chrome be sure to verify that the # Android build still compiles. See conditions below. |