diff options
author | vitalybuka@chromium.org <vitalybuka@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-17 20:07:06 +0000 |
---|---|---|
committer | vitalybuka@chromium.org <vitalybuka@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-17 20:07:06 +0000 |
commit | 2fcd215fc3158d44935845ee86e98346848cab8b (patch) | |
tree | fbf1938a15bc6a027e1912ce9da7d1537f906ef5 | |
parent | 5657db4b4384ac2cd77c21a68afda29537811f16 (diff) | |
download | chromium_src-2fcd215fc3158d44935845ee86e98346848cab8b.zip chromium_src-2fcd215fc3158d44935845ee86e98346848cab8b.tar.gz chromium_src-2fcd215fc3158d44935845ee86e98346848cab8b.tar.bz2 |
Revert 283813 "Switch to BoringSSL."
Failed WebRtcBrowserTest on android_dbg_triggered_tests.
> Switch to BoringSSL.
>
> (This is a reland of r283542 which was reverted in r283591 because it
> broke the WebView build. The android_aosp trybots are broken[1] so this
> based on hope.)
>
> This is a much larger change than its diff suggests. If it breaks
> something, please revert first and ask questions later.
>
> [1] http://code.google.com/p/chromium/issues/detail?id=394597
>
> BUG=none
>
> Review URL: https://codereview.chromium.org/399993002
TBR=agl@chromium.org
Review URL: https://codereview.chromium.org/405503002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@283845 0039d316-1c4b-4281-b951-d872f2087c98
42 files changed, 747 insertions, 513 deletions
@@ -55,7 +55,7 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling WebRTC # and V8 without interference from each other. - "webrtc_revision": "6683", + "webrtc_revision": "6680", "jsoncpp_revision": "248", "nss_revision": "277057", # Three lines of non-changing comments so that @@ -65,7 +65,7 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openssl # and whatever else without interference from each other. - "openssl_revision": "283115", + "openssl_revision": "275836", # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. @@ -85,7 +85,7 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. - "boringssl_revision": "904a32e97582475e011a312dfaaac100c8f2df5a", + "boringssl_revision": "09020c2f08df11179b93e6548117806a4c0d0d45", } deps = { diff --git a/android_webview/buildbot/deps_whitelist.py b/android_webview/buildbot/deps_whitelist.py index 9a317f5..69bb2d7 100755 --- a/android_webview/buildbot/deps_whitelist.py +++ b/android_webview/buildbot/deps_whitelist.py @@ -32,7 +32,6 @@ class DepsWhitelist(object): # in the Android tree. self._compile_but_not_snapshot_dependencies = [ 'third_party/libaddressinput/src/cpp', - 'third_party/boringssl/src', ] # Dependencies that need to be merged into the Android tree. diff --git a/android_webview/native/webview_native.gyp b/android_webview/native/webview_native.gyp index 83f68d9..691b2de 100644 --- a/android_webview/native/webview_native.gyp +++ b/android_webview/native/webview_native.gyp @@ -23,7 +23,7 @@ '../../ui/gfx/gfx.gyp:gfx_geometry', '../../webkit/storage_browser.gyp:webkit_storage_browser', '../../webkit/storage_common.gyp:webkit_storage_common', - '../../third_party/boringssl/boringssl.gyp:boringssl', + '../../third_party/openssl/openssl.gyp:openssl', 'android_webview_native_jni', ], 'include_dirs': [ diff --git a/build/linux/system.gyp b/build/linux/system.gyp index d81b8d4..59c31a6 100644 --- a/build/linux/system.gyp +++ b/build/linux/system.gyp @@ -985,7 +985,7 @@ 'conditions': [ ['use_openssl==1', { 'dependencies': [ - '../../third_party/boringssl/boringssl.gyp:boringssl', + '../../third_party/openssl/openssl.gyp:openssl', ], }], ['use_openssl==0', { diff --git a/build/linux/unbundle/replace_gyp_files.py b/build/linux/unbundle/replace_gyp_files.py index fc7646f..28ab14f 100755 --- a/build/linux/unbundle/replace_gyp_files.py +++ b/build/linux/unbundle/replace_gyp_files.py @@ -31,7 +31,7 @@ REPLACEMENTS = { 'use_system_libxml': 'third_party/libxml/libxml.gyp', 'use_system_libxnvctrl' : 'third_party/libXNVCtrl/libXNVCtrl.gyp', 'use_system_libxslt': 'third_party/libxslt/libxslt.gyp', - 'use_system_openssl': 'third_party/boringssl/boringssl.gyp', + 'use_system_openssl': 'third_party/openssl/openssl.gyp', 'use_system_opus': 'third_party/opus/opus.gyp', 'use_system_re2': 'third_party/re2/re2.gyp', 'use_system_snappy': 'third_party/snappy/snappy.gyp', diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi index 8cd7f44..9c3ec1b 100644 --- a/chrome/chrome_browser_ui.gypi +++ b/chrome/chrome_browser_ui.gypi @@ -2773,7 +2773,7 @@ ['OS=="android"', { 'dependencies': [ '../components/components.gyp:web_contents_delegate_android', - '../third_party/boringssl/boringssl.gyp:boringssl', + '../third_party/openssl/openssl.gyp:openssl', 'chrome_browser_jni_headers', ], 'dependencies!': [ diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi index b24fd2a..5368c96 100644 --- a/chrome/chrome_common.gypi +++ b/chrome/chrome_common.gypi @@ -653,7 +653,7 @@ ], ['OS == "android"', { 'dependencies': [ - '../third_party/boringssl/boringssl.gyp:boringssl', + '../third_party/openssl/openssl.gyp:openssl', ], 'sources!': [ 'common/net/x509_certificate_model.cc', diff --git a/content/child/webcrypto/platform_crypto_openssl.cc b/content/child/webcrypto/platform_crypto_openssl.cc index 8314053..89212ea 100644 --- a/content/child/webcrypto/platform_crypto_openssl.cc +++ b/content/child/webcrypto/platform_crypto_openssl.cc @@ -53,10 +53,12 @@ class SymKey : public Key { namespace { const EVP_CIPHER* GetAESCipherByKeyLength(unsigned int key_length_bytes) { - // OpenSSL supports AES CBC ciphers for only 2 key lengths: 128, 256 bits + // OpenSSL supports AES CBC ciphers for only 3 key lengths: 128, 192, 256 bits switch (key_length_bytes) { case 16: return EVP_aes_128_cbc(); + case 24: + return EVP_aes_192_cbc(); case 32: return EVP_aes_256_cbc(); default: @@ -437,8 +439,7 @@ Status EncryptDecryptAesGcm(EncryptOrDecrypt mode, crypto::ScopedOpenSSL<EVP_AEAD_CTX, EVP_AEAD_CTX_cleanup>::Type ctx_cleanup( &ctx); - size_t len; - int ok; + ssize_t len; if (mode == DECRYPT) { if (data.byte_length() < tag_length_bytes) @@ -446,34 +447,32 @@ Status EncryptDecryptAesGcm(EncryptOrDecrypt mode, buffer->resize(data.byte_length() - tag_length_bytes); - ok = EVP_AEAD_CTX_open(&ctx, - Uint8VectorStart(buffer), - &len, - buffer->size(), - iv.bytes(), - iv.byte_length(), - data.bytes(), - data.byte_length(), - additional_data.bytes(), - additional_data.byte_length()); + len = EVP_AEAD_CTX_open(&ctx, + Uint8VectorStart(buffer), + buffer->size(), + iv.bytes(), + iv.byte_length(), + data.bytes(), + data.byte_length(), + additional_data.bytes(), + additional_data.byte_length()); } else { // No need to check for unsigned integer overflow here (seal fails if // the output buffer is too small). buffer->resize(data.byte_length() + tag_length_bytes); - ok = EVP_AEAD_CTX_seal(&ctx, - Uint8VectorStart(buffer), - &len, - buffer->size(), - iv.bytes(), - iv.byte_length(), - data.bytes(), - data.byte_length(), - additional_data.bytes(), - additional_data.byte_length()); + len = EVP_AEAD_CTX_seal(&ctx, + Uint8VectorStart(buffer), + buffer->size(), + iv.bytes(), + iv.byte_length(), + data.bytes(), + data.byte_length(), + additional_data.bytes(), + additional_data.byte_length()); } - if (!ok) + if (len < 0) return Status::OperationError(); buffer->resize(len); return Status::Success(); diff --git a/content/content_child.gypi b/content/content_child.gypi index 902713f..e17f3e6 100644 --- a/content/content_child.gypi +++ b/content/content_child.gypi @@ -297,7 +297,7 @@ '<@(webcrypto_openssl_sources)', ], 'dependencies': [ - '../third_party/boringssl/boringssl.gyp:boringssl', + '../third_party/openssl/openssl.gyp:openssl', ], }, { 'sources': [ diff --git a/crypto/BUILD.gn b/crypto/BUILD.gn index bd7f06d..30784208 100644 --- a/crypto/BUILD.gn +++ b/crypto/BUILD.gn @@ -242,7 +242,7 @@ test("crypto_unittests") { # on the current SSL library should just depend on this. group("platform") { if (use_openssl) { - deps = [ "//third_party/boringssl" ] + deps = [ "//third_party/openssl" ] } else { deps = [ "//net/third_party/nss/ssl:libssl" ] if (is_linux) { diff --git a/crypto/crypto.gyp b/crypto/crypto.gyp index 42f3cad..0c472ff 100644 --- a/crypto/crypto.gyp +++ b/crypto/crypto.gyp @@ -100,7 +100,7 @@ }], [ 'use_openssl==1', { 'dependencies': [ - '../third_party/boringssl/boringssl.gyp:boringssl', + '../third_party/openssl/openssl.gyp:openssl', ], # TODO(joth): Use a glob to match exclude patterns once the # OpenSSL file set is complete. @@ -209,7 +209,7 @@ }], [ 'use_openssl==1', { 'dependencies': [ - '../third_party/boringssl/boringssl.gyp:boringssl', + '../third_party/openssl/openssl.gyp:openssl', ], 'sources!': [ 'nss_util_unittest.cc', diff --git a/crypto/crypto_nacl.gyp b/crypto/crypto_nacl.gyp index 4451610..6ec5e83 100644 --- a/crypto/crypto_nacl.gyp +++ b/crypto/crypto_nacl.gyp @@ -22,7 +22,7 @@ 'build_pnacl_newlib': 1, }, 'dependencies': [ - '../third_party/boringssl/boringssl_nacl.gyp:boringssl_nacl', + '../third_party/openssl/openssl_nacl.gyp:openssl_nacl', '../native_client/tools.gyp:prep_toolchain', '../native_client_sdk/native_client_sdk_untrusted.gyp:nacl_io_untrusted', ], diff --git a/crypto/encryptor_openssl.cc b/crypto/encryptor_openssl.cc index 0504adb..0bf96b7 100644 --- a/crypto/encryptor_openssl.cc +++ b/crypto/encryptor_openssl.cc @@ -19,6 +19,7 @@ namespace { const EVP_CIPHER* GetCipherForKey(SymmetricKey* key) { switch (key->key().length()) { case 16: return EVP_aes_128_cbc(); + case 24: return EVP_aes_192_cbc(); case 32: return EVP_aes_256_cbc(); default: return NULL; } @@ -99,8 +100,8 @@ bool Encryptor::Crypt(bool do_encrypt, DCHECK(cipher); // Already handled in Init(); const std::string& key = key_->key(); - DCHECK_EQ(EVP_CIPHER_iv_length(cipher), iv_.length()); - DCHECK_EQ(EVP_CIPHER_key_length(cipher), key.length()); + DCHECK_EQ(EVP_CIPHER_iv_length(cipher), static_cast<int>(iv_.length())); + DCHECK_EQ(EVP_CIPHER_key_length(cipher), static_cast<int>(key.length())); ScopedCipherCTX ctx; if (!EVP_CipherInit_ex(ctx.get(), cipher, NULL, diff --git a/crypto/openssl_bio_string_unittest.cc b/crypto/openssl_bio_string_unittest.cc index 9dfa0e7..2467215 100644 --- a/crypto/openssl_bio_string_unittest.cc +++ b/crypto/openssl_bio_string_unittest.cc @@ -23,17 +23,24 @@ TEST(OpenSSLBIOString, TestWrite) { EXPECT_EQ(static_cast<int>(expected1.size()), BIO_printf(bio.get(), "a %s\nb %i\n", "one", 2)); EXPECT_EQ(expected1, s); + EXPECT_EQ(static_cast<int>(expected1.size()), BIO_tell(bio.get())); EXPECT_EQ(1, BIO_flush(bio.get())); + EXPECT_EQ(-1, BIO_seek(bio.get(), 0)); EXPECT_EQ(expected1, s); EXPECT_EQ(static_cast<int>(expected2.size()), BIO_write(bio.get(), expected2.data(), expected2.size())); EXPECT_EQ(expected1 + expected2, s); + EXPECT_EQ(static_cast<int>(expected1.size() + expected2.size()), + BIO_tell(bio.get())); EXPECT_EQ(static_cast<int>(expected3.size()), BIO_puts(bio.get(), expected3.c_str())); EXPECT_EQ(expected1 + expected2 + expected3, s); + EXPECT_EQ(static_cast<int>(expected1.size() + expected2.size() + + expected3.size()), + BIO_tell(bio.get())); } EXPECT_EQ(expected1 + expected2 + expected3, s); } diff --git a/crypto/openssl_util.cc b/crypto/openssl_util.cc index 94bf246..34af810 100644 --- a/crypto/openssl_util.cc +++ b/crypto/openssl_util.cc @@ -6,7 +6,6 @@ #include <openssl/err.h> #include <openssl/ssl.h> -#include <openssl/cpu.h> #include "base/logging.h" #include "base/memory/scoped_vector.h" @@ -23,9 +22,8 @@ namespace crypto { namespace { -void CurrentThreadId(CRYPTO_THREADID* id) { - CRYPTO_THREADID_set_numeric( - id, static_cast<unsigned long>(base::PlatformThread::CurrentId())); +unsigned long CurrentThreadId() { + return static_cast<unsigned long>(base::PlatformThread::CurrentId()); } // Singleton for initializing and cleaning up the OpenSSL library. @@ -55,7 +53,7 @@ class OpenSSLInitSingleton { for (int i = 0; i < num_locks; ++i) locks_.push_back(new base::Lock()); CRYPTO_set_locking_callback(LockingCallback); - CRYPTO_THREADID_set_callback(CurrentThreadId); + CRYPTO_set_id_callback(CurrentThreadId); #if defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL) const bool has_neon = diff --git a/crypto/rsa_private_key_openssl.cc b/crypto/rsa_private_key_openssl.cc index 8dcde61..e3cf04c 100644 --- a/crypto/rsa_private_key_openssl.cc +++ b/crypto/rsa_private_key_openssl.cc @@ -4,8 +4,6 @@ #include "crypto/rsa_private_key.h" -#include <openssl/bio.h> -#include <openssl/bn.h> #include <openssl/evp.h> #include <openssl/pkcs12.h> #include <openssl/rsa.h> diff --git a/crypto/scoped_openssl_types.h b/crypto/scoped_openssl_types.h index 19953a2..a949233 100644 --- a/crypto/scoped_openssl_types.h +++ b/crypto/scoped_openssl_types.h @@ -5,7 +5,6 @@ #ifndef CRYPTO_SCOPED_OPENSSL_TYPES_H_ #define CRYPTO_SCOPED_OPENSSL_TYPES_H_ -#include <openssl/bio.h> #include <openssl/bn.h> #include <openssl/dsa.h> #include <openssl/ec.h> diff --git a/crypto/signature_verifier_openssl.cc b/crypto/signature_verifier_openssl.cc index a855120..155a2cf3 100644 --- a/crypto/signature_verifier_openssl.cc +++ b/crypto/signature_verifier_openssl.cc @@ -26,7 +26,7 @@ const EVP_MD* ToOpenSSLDigest(SignatureVerifier::HashAlgorithm hash_alg) { case SignatureVerifier::SHA256: return EVP_sha256(); } - return NULL; + return EVP_md_null(); } } // namespace @@ -80,11 +80,8 @@ bool SignatureVerifier::VerifyInitRSAPSS(HashAlgorithm hash_alg, const uint8* public_key_info, int public_key_info_len) { OpenSSLErrStackTracer err_tracer(FROM_HERE); - const EVP_MD* const digest = ToOpenSSLDigest(hash_alg); + const EVP_MD* digest = ToOpenSSLDigest(hash_alg); DCHECK(digest); - if (!digest) { - return false; - } EVP_PKEY_CTX* pkey_ctx; if (!CommonInit(digest, signature, signature_len, public_key_info, @@ -95,12 +92,8 @@ bool SignatureVerifier::VerifyInitRSAPSS(HashAlgorithm hash_alg, int rv = EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING); if (rv != 1) return false; - const EVP_MD* const mgf_digest = ToOpenSSLDigest(mask_hash_alg); - DCHECK(mgf_digest); - if (!mgf_digest) { - return false; - } - rv = EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf_digest); + rv = EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, + ToOpenSSLDigest(mask_hash_alg)); if (rv != 1) return false; rv = EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, salt_len); diff --git a/google_apis/google_apis.gyp b/google_apis/google_apis.gyp index 73b2d11..ecc5609 100644 --- a/google_apis/google_apis.gyp +++ b/google_apis/google_apis.gyp @@ -45,7 +45,7 @@ }], ['OS=="android"', { 'dependencies': [ - '../third_party/boringssl/boringssl.gyp:boringssl', + '../third_party/openssl/openssl.gyp:openssl', ], 'sources/': [ ['exclude', 'cup/client_update_protocol_nss\.cc$'], diff --git a/net/BUILD.gn b/net/BUILD.gn index a150128..5210ca8 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn @@ -523,6 +523,10 @@ component("net") { if (!is_android_webview_build) { deps += [ ":net_jni_headers" ] + + # The net/android/keystore_openssl.cc source file needs to access an + # OpenSSL-internal header. + include_dirs = [ "//third_party/openssl" ] } } @@ -913,7 +917,7 @@ if (is_linux) { ":epoll_server", ":net", "//base", - "//third_party/boringssl", + "//third_party/openssl", ] } @@ -932,7 +936,7 @@ if (is_linux) { ":test_support", "//testing/gtest", "//testing/gmock", - "//third_party/boringssl", + "//third_party/openssl", ] } @@ -983,7 +987,7 @@ if (is_linux) { "//base", "//base/third_party/dynamic_annotations", "//crypto", - "//third_party/boringssl", + "//third_party/openssl", "//url", ] } @@ -994,7 +998,7 @@ if (is_linux) { ":quic_base", ":net", "//base", - "//third_party/boringssl", + "//third_party/openssl", ] } } @@ -1323,7 +1327,7 @@ executable("quic_server") { ":quic_tools", ":net", "//base", - "//third_party/boringssl", + "//third_party/openssl", ] } diff --git a/net/android/keystore_openssl.cc b/net/android/keystore_openssl.cc index 91c5b78..dbb3b1c 100644 --- a/net/android/keystore_openssl.cc +++ b/net/android/keystore_openssl.cc @@ -6,10 +6,16 @@ #include <jni.h> #include <openssl/bn.h> +// This include is required to get the ECDSA_METHOD structure definition +// which isn't currently part of the OpenSSL official ABI. This should +// not be a concern for Chromium which always links against its own +// version of the library on Android. +#include <openssl/crypto/ecdsa/ecs_locl.h> +// And this one is needed for the EC_GROUP definition. +#include <openssl/crypto/ec/ec_lcl.h> #include <openssl/dsa.h> #include <openssl/ec.h> #include <openssl/engine.h> -#include <openssl/err.h> #include <openssl/evp.h> #include <openssl/rsa.h> @@ -54,10 +60,41 @@ // fields point to static methods used to implement the corresponding // RSA operation using platform Android APIs. // -// However, the platform APIs require a jobject JNI reference to work. It must -// be stored in the RSA instance, or made accessible when the custom RSA -// methods are called. This is done by storing it in a |KeyExData| structure -// that's referenced by the key using |EX_DATA|. +// However, the platform APIs require a jobject JNI reference to work. +// It must be stored in the RSA instance, or made accessible when the +// custom RSA methods are called. This is done by using RSA_set_app_data() +// and RSA_get_app_data(). +// +// One can thus _directly_ create a new EVP_PKEY that uses a custom RSA +// object with the following: +// +// RSA* rsa = RSA_new() +// RSA_set_method(&custom_rsa_method); +// RSA_set_app_data(rsa, jni_private_key); +// +// EVP_PKEY* pkey = EVP_PKEY_new(); +// EVP_PKEY_assign_RSA(pkey, rsa); +// +// Note that because EVP_PKEY_assign_RSA() is used, instead of +// EVP_PKEY_set1_RSA(), the new EVP_PKEY now owns the RSA object, and +// will destroy it when it is itself destroyed. +// +// Unfortunately, such objects cannot be used with RSA_size(), which +// totally ignores the RSA_METHOD pointers. Instead, it is necessary +// to manually setup the modulus field (n) in the RSA object, with a +// value that matches the wrapped PrivateKey object. See GetRsaPkeyWrapper +// for full details. +// +// Similarly, custom DSA_METHOD and ECDSA_METHOD are defined by this source +// file, and appropriate field setups are performed to ensure that +// DSA_size() and ECDSA_size() work properly with the wrapper EVP_PKEY. +// +// Note that there is no need to define an OpenSSL ENGINE here. These +// are objects that can be used to expose custom methods (i.e. either +// RSA_METHOD, DSA_METHOD, ECDSA_METHOD, and a large number of other ones +// for types not related to this source file), and make them used by +// default for a lot of operations. Very fortunately, this is not needed +// here, which saves a lot of complexity. using base::android::ScopedJavaGlobalRef; using base::android::ScopedJavaLocalRef; @@ -67,127 +104,45 @@ namespace android { namespace { -extern const RSA_METHOD android_rsa_method; -extern const ECDSA_METHOD android_ecdsa_method; +typedef crypto::ScopedOpenSSL<EC_GROUP, EC_GROUP_free>::Type ScopedEC_GROUP; + +// Custom RSA_METHOD that uses the platform APIs. +// Note that for now, only signing through RSA_sign() is really supported. +// all other method pointers are either stubs returning errors, or no-ops. +// See <openssl/rsa.h> for exact declaration of RSA_METHOD. -// KeyExData contains the data that is contained in the EX_DATA of the RSA, DSA -// and ECDSA objects that are created to wrap Android system keys. -struct KeyExData { - // private_key contains a reference to a Java, private-key object. +struct RsaAppData { jobject private_key; - // legacy_rsa, if not NULL, points to an RSA* in the system's OpenSSL (which - // might not be ABI compatible with Chromium). AndroidRSA* legacy_rsa; - // cached_size contains the "size" of the key. This is the size of the - // modulus (in bytes) for RSA, or the group order size for (EC)DSA. This - // avoids calling into Java to calculate the size. - size_t cached_size; -}; - -// ExDataDup is called when one of the RSA, DSA or EC_KEY objects is -// duplicated. We don't support this and it should never happen. -int ExDataDup(CRYPTO_EX_DATA* to, - const CRYPTO_EX_DATA* from, - void** from_d, - int index, - long argl, - void* argp) { - CHECK(false); - return 0; -} - -// ExDataFree is called when one of the RSA, DSA or EC_KEY object is freed. -void ExDataFree(void* parent, - void* ptr, - CRYPTO_EX_DATA* ad, - int index, - long argl, - void* argp) { - // Ensure the global JNI reference created with this wrapper is - // properly destroyed with it. - KeyExData *ex_data = reinterpret_cast<KeyExData*>(ptr); - if (ex_data != NULL) { - ReleaseKey(ex_data->private_key); - delete ex_data; - } -} - -// BoringSSLEngine is a BoringSSL ENGINE that implements RSA, DSA and ECDSA by -// forwarding the requested operations to the Java libraries. -class BoringSSLEngine { - public: - BoringSSLEngine() - : rsa_index_(RSA_get_ex_new_index(0 /* argl */, - NULL /* argp */, - NULL /* new_func */, - ExDataDup, - ExDataFree)), - ec_key_index_(EC_KEY_get_ex_new_index(0 /* argl */, - NULL /* argp */, - NULL /* new_func */, - ExDataDup, - ExDataFree)), - engine_(ENGINE_new()) { - ENGINE_set_RSA_method( - engine_, &android_rsa_method, sizeof(android_rsa_method)); - ENGINE_set_ECDSA_method( - engine_, &android_ecdsa_method, sizeof(android_ecdsa_method)); - } - - int rsa_ex_index() const { return rsa_index_; } - int ec_key_ex_index() const { return ec_key_index_; } - - const ENGINE* engine() const { return engine_; } - - private: - const int rsa_index_; - const int ec_key_index_; - ENGINE* const engine_; }; -base::LazyInstance<BoringSSLEngine>::Leaky global_boringssl_engine = - LAZY_INSTANCE_INITIALIZER; - - -// VectorBignumSize returns the number of bytes needed to represent the bignum -// given in |v|, i.e. the length of |v| less any leading zero bytes. -size_t VectorBignumSize(const std::vector<uint8>& v) { - size_t size = v.size(); - // Ignore any leading zero bytes. - for (size_t i = 0; i < v.size() && v[i] == 0; i++) { - size--; - } - return size; -} - -KeyExData* RsaGetExData(const RSA* rsa) { - return reinterpret_cast<KeyExData*>( - RSA_get_ex_data(rsa, global_boringssl_engine.Get().rsa_ex_index())); -} - -size_t RsaMethodSize(const RSA *rsa) { - const KeyExData *ex_data = RsaGetExData(rsa); - return ex_data->cached_size; +int RsaMethodPubEnc(int flen, + const unsigned char* from, + unsigned char* to, + RSA* rsa, + int padding) { + NOTIMPLEMENTED(); + RSAerr(RSA_F_RSA_PUBLIC_ENCRYPT, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED); + return -1; } -int RsaMethodEncrypt(RSA* rsa, - size_t* out_len, - uint8_t* out, - size_t max_out, - const uint8_t* in, - size_t in_len, - int padding) { +int RsaMethodPubDec(int flen, + const unsigned char* from, + unsigned char* to, + RSA* rsa, + int padding) { NOTIMPLEMENTED(); - OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE); - return 1; + RSAerr(RSA_F_RSA_PUBLIC_DECRYPT, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED); + return -1; } -int RsaMethodSignRaw(RSA* rsa, - size_t* out_len, - uint8_t* out, - size_t max_out, - const uint8_t* in, - size_t in_len, +// See RSA_eay_private_encrypt in +// third_party/openssl/openssl/crypto/rsa/rsa_eay.c for the default +// implementation of this function. +int RsaMethodPrivEnc(int flen, + const unsigned char *from, + unsigned char *to, + RSA *rsa, int padding) { DCHECK_EQ(RSA_PKCS1_PADDING, padding); if (padding != RSA_PKCS1_PADDING) { @@ -198,22 +153,22 @@ int RsaMethodSignRaw(RSA* rsa, // the same Android version as the "NONEwithRSA" // java.security.Signature algorithm, so the same version checks // for GetRsaLegacyKey should work. - OPENSSL_PUT_ERROR(RSA, sign_raw, RSA_R_UNKNOWN_ALGORITHM_TYPE); - return 0; + RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE); + return -1; } // Retrieve private key JNI reference. - const KeyExData *ex_data = RsaGetExData(rsa); - if (!ex_data || !ex_data->private_key) { + RsaAppData* app_data = static_cast<RsaAppData*>(RSA_get_app_data(rsa)); + if (!app_data || !app_data->private_key) { LOG(WARNING) << "Null JNI reference passed to RsaMethodPrivEnc!"; - OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR); - return 0; + RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); + return -1; } // Pre-4.2 legacy codepath. - if (ex_data->legacy_rsa) { - int ret = ex_data->legacy_rsa->meth->rsa_priv_enc( - in_len, in, out, ex_data->legacy_rsa, ANDROID_RSA_PKCS1_PADDING); + if (app_data->legacy_rsa) { + int ret = app_data->legacy_rsa->meth->rsa_priv_enc( + flen, from, to, app_data->legacy_rsa, ANDROID_RSA_PKCS1_PADDING); if (ret < 0) { LOG(WARNING) << "Could not sign message in RsaMethodPrivEnc!"; // System OpenSSL will use a separate error queue, so it is still @@ -223,92 +178,126 @@ int RsaMethodSignRaw(RSA* rsa, // if there were some way to convince Java to do it. (Without going // through Java, it's difficult to get a handle on a system OpenSSL // function; dlopen loads a second copy.) - OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR); - return 0; + RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); + return -1; } - *out_len = ret; - return 1; + return ret; } - base::StringPiece from_piece(reinterpret_cast<const char*>(in), in_len); + base::StringPiece from_piece(reinterpret_cast<const char*>(from), flen); std::vector<uint8> result; // For RSA keys, this function behaves as RSA_private_encrypt with // PKCS#1 padding. - if (!RawSignDigestWithPrivateKey(ex_data->private_key, from_piece, &result)) { + if (!RawSignDigestWithPrivateKey(app_data->private_key, + from_piece, &result)) { LOG(WARNING) << "Could not sign message in RsaMethodPrivEnc!"; - OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR); - return 0; + RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); + return -1; } size_t expected_size = static_cast<size_t>(RSA_size(rsa)); if (result.size() > expected_size) { LOG(ERROR) << "RSA Signature size mismatch, actual: " << result.size() << ", expected <= " << expected_size; - OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR); - return 0; - } - - if (max_out < expected_size) { - OPENSSL_PUT_ERROR(RSA, sign_raw, RSA_R_DATA_TOO_LARGE); - return 0; + RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); + return -1; } // Copy result to OpenSSL-provided buffer. RawSignDigestWithPrivateKey // should pad with leading 0s, but if it doesn't, pad the result. size_t zero_pad = expected_size - result.size(); - memset(out, 0, zero_pad); - memcpy(out + zero_pad, &result[0], result.size()); - *out_len = expected_size; + memset(to, 0, zero_pad); + memcpy(to + zero_pad, &result[0], result.size()); - return 1; + return expected_size; } -int RsaMethodDecrypt(RSA* rsa, - size_t* out_len, - uint8_t* out, - size_t max_out, - const uint8_t* in, - size_t in_len, +int RsaMethodPrivDec(int flen, + const unsigned char* from, + unsigned char* to, + RSA* rsa, int padding) { NOTIMPLEMENTED(); - OPENSSL_PUT_ERROR(RSA, decrypt, RSA_R_UNKNOWN_PADDING_TYPE); - return 1; + RSAerr(RSA_F_RSA_PRIVATE_DECRYPT, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED); + return -1; } -int RsaMethodVerifyRaw(RSA* rsa, - size_t* out_len, - uint8_t* out, - size_t max_out, - const uint8_t* in, - size_t in_len, - int padding) { - NOTIMPLEMENTED(); - OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_UNKNOWN_ALGORITHM_TYPE); - return 1; +int RsaMethodInit(RSA* rsa) { + return 0; +} + +int RsaMethodFinish(RSA* rsa) { + // Ensure the global JNI reference created with this wrapper is + // properly destroyed with it. + RsaAppData* app_data = static_cast<RsaAppData*>(RSA_get_app_data(rsa)); + if (app_data != NULL) { + RSA_set_app_data(rsa, NULL); + ReleaseKey(app_data->private_key); + delete app_data; + } + // Actual return value is ignored by OpenSSL. There are no docs + // explaining what this is supposed to be. + return 0; } const RSA_METHOD android_rsa_method = { - { - 0 /* references */, - 1 /* is_static */ - } /* common */, - NULL /* app_data */, - - NULL /* init */, - NULL /* finish */, - RsaMethodSize, - NULL /* sign */, - NULL /* verify */, - RsaMethodEncrypt, - RsaMethodSignRaw, - RsaMethodDecrypt, - RsaMethodVerifyRaw, - NULL /* mod_exp */, - NULL /* bn_mod_exp */, - 0 /* flags */, - NULL /* keygen */, + /* .name = */ "Android signing-only RSA method", + /* .rsa_pub_enc = */ RsaMethodPubEnc, + /* .rsa_pub_dec = */ RsaMethodPubDec, + /* .rsa_priv_enc = */ RsaMethodPrivEnc, + /* .rsa_priv_dec = */ RsaMethodPrivDec, + /* .rsa_mod_exp = */ NULL, + /* .bn_mod_exp = */ NULL, + /* .init = */ RsaMethodInit, + /* .finish = */ RsaMethodFinish, + // This flag is necessary to tell OpenSSL to avoid checking the content + // (i.e. internal fields) of the private key. Otherwise, it will complain + // it's not valid for the certificate. + /* .flags = */ RSA_METHOD_FLAG_NO_CHECK, + /* .app_data = */ NULL, + /* .rsa_sign = */ NULL, + /* .rsa_verify = */ NULL, + /* .rsa_keygen = */ NULL, }; +// Copy the contents of an encoded big integer into an existing BIGNUM. +// This function modifies |*num| in-place. +// |new_bytes| is the byte encoding of the new value. +// |num| points to the BIGNUM which will be assigned with the new value. +// Returns true on success, false otherwise. On failure, |*num| is +// not modified. +bool CopyBigNumFromBytes(const std::vector<uint8>& new_bytes, + BIGNUM* num) { + BIGNUM* ret = BN_bin2bn( + reinterpret_cast<const unsigned char*>(&new_bytes[0]), + static_cast<int>(new_bytes.size()), + num); + return (ret != NULL); +} + +// Decode the contents of an encoded big integer and either create a new +// BIGNUM object (if |*num_ptr| is NULL on input) or copy it (if +// |*num_ptr| is not NULL). +// |new_bytes| is the byte encoding of the new value. +// |num_ptr| is the address of a BIGNUM pointer. |*num_ptr| can be NULL. +// Returns true on success, false otherwise. On failure, |*num_ptr| is +// not modified. On success, |*num_ptr| will always be non-NULL and +// point to a valid BIGNUM object. +bool SwapBigNumPtrFromBytes(const std::vector<uint8>& new_bytes, + BIGNUM** num_ptr) { + BIGNUM* old_num = *num_ptr; + BIGNUM* new_num = BN_bin2bn( + reinterpret_cast<const unsigned char*>(&new_bytes[0]), + static_cast<int>(new_bytes.size()), + old_num); + if (new_num == NULL) + return false; + + if (old_num == NULL) + *num_ptr = new_num; + return true; +} + // Setup an EVP_PKEY to wrap an existing platform RSA PrivateKey object. // |private_key| is the JNI reference (local or global) to the object. // |legacy_rsa|, if non-NULL, is a pointer to the system OpenSSL RSA object @@ -322,8 +311,24 @@ const RSA_METHOD android_rsa_method = { bool GetRsaPkeyWrapper(jobject private_key, AndroidRSA* legacy_rsa, EVP_PKEY* pkey) { - crypto::ScopedRSA rsa( - RSA_new_method(global_boringssl_engine.Get().engine())); + crypto::ScopedRSA rsa(RSA_new()); + RSA_set_method(rsa.get(), &android_rsa_method); + + // HACK: RSA_size() doesn't work with custom RSA_METHODs. To ensure that + // it will return the right value, set the 'n' field of the RSA object + // to match the private key's modulus. + // + // TODO(davidben): After switching to BoringSSL, consider making RSA_size call + // into an RSA_METHOD hook. + std::vector<uint8> modulus; + if (!GetRSAKeyModulus(private_key, &modulus)) { + LOG(ERROR) << "Failed to get private key modulus"; + return false; + } + if (!SwapBigNumPtrFromBytes(modulus, &rsa.get()->n)) { + LOG(ERROR) << "Failed to decode private key modulus"; + return false; + } ScopedJavaGlobalRef<jobject> global_key; global_key.Reset(NULL, private_key); @@ -331,19 +336,10 @@ bool GetRsaPkeyWrapper(jobject private_key, LOG(ERROR) << "Could not create global JNI reference"; return false; } - - std::vector<uint8> modulus; - if (!GetRSAKeyModulus(private_key, &modulus)) { - LOG(ERROR) << "Failed to get private key modulus"; - return false; - } - - KeyExData* ex_data = new KeyExData; - ex_data->private_key = global_key.Release(); - ex_data->legacy_rsa = legacy_rsa; - ex_data->cached_size = VectorBignumSize(modulus); - RSA_set_ex_data( - rsa.get(), global_boringssl_engine.Get().rsa_ex_index(), ex_data); + RsaAppData* app_data = new RsaAppData(); + app_data->private_key = global_key.Release(); + app_data->legacy_rsa = legacy_rsa; + RSA_set_app_data(rsa.get(), app_data); EVP_PKEY_assign_RSA(pkey, rsa.release()); return true; } @@ -402,7 +398,7 @@ EVP_PKEY* GetRsaLegacyKey(jobject private_key) { if (sys_rsa->engine) { // |private_key| may not have an engine if the PrivateKey did not come // from the key store, such as in unit tests. - if (strcmp(sys_rsa->engine->id, "keystore") == 0) { + if (!strcmp(sys_rsa->engine->id, "keystore")) { LeakEngine(private_key); } else { NOTREACHED(); @@ -435,67 +431,266 @@ EVP_PKEY* GetRsaLegacyKey(jobject private_key) { return pkey; } +// Custom DSA_METHOD that uses the platform APIs. +// Note that for now, only signing through DSA_sign() is really supported. +// all other method pointers are either stubs returning errors, or no-ops. +// See <openssl/dsa.h> for exact declaration of DSA_METHOD. +// +// Note: There is no DSA_set_app_data() and DSA_get_app_data() functions, +// but RSA_set_app_data() is defined as a simple macro that calls +// RSA_set_ex_data() with a hard-coded index of 0, so this code +// does the same thing here. + +DSA_SIG* DsaMethodDoSign(const unsigned char* dgst, + int dlen, + DSA* dsa) { + // Extract the JNI reference to the PrivateKey object. + jobject private_key = reinterpret_cast<jobject>(DSA_get_ex_data(dsa, 0)); + if (private_key == NULL) + return NULL; + + // Sign the message with it, calling platform APIs. + std::vector<uint8> signature; + if (!RawSignDigestWithPrivateKey( + private_key, + base::StringPiece( + reinterpret_cast<const char*>(dgst), + static_cast<size_t>(dlen)), + &signature)) { + return NULL; + } + + // Note: With DSA, the actual signature might be smaller than DSA_size(). + size_t max_expected_size = static_cast<size_t>(DSA_size(dsa)); + if (signature.size() > max_expected_size) { + LOG(ERROR) << "DSA Signature size mismatch, actual: " + << signature.size() << ", expected <= " + << max_expected_size; + return NULL; + } + + // Convert the signature into a DSA_SIG object. + const unsigned char* sigbuf = + reinterpret_cast<const unsigned char*>(&signature[0]); + int siglen = static_cast<size_t>(signature.size()); + DSA_SIG* dsa_sig = d2i_DSA_SIG(NULL, &sigbuf, siglen); + return dsa_sig; +} + +int DsaMethodSignSetup(DSA* dsa, + BN_CTX* ctx_in, + BIGNUM** kinvp, + BIGNUM** rp) { + NOTIMPLEMENTED(); + DSAerr(DSA_F_DSA_SIGN_SETUP, DSA_R_INVALID_DIGEST_TYPE); + return -1; +} + +int DsaMethodDoVerify(const unsigned char* dgst, + int dgst_len, + DSA_SIG* sig, + DSA* dsa) { + NOTIMPLEMENTED(); + DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_INVALID_DIGEST_TYPE); + return -1; +} + +int DsaMethodFinish(DSA* dsa) { + // Free the global JNI reference that was created with this + // wrapper key. + jobject key = reinterpret_cast<jobject>(DSA_get_ex_data(dsa,0)); + if (key != NULL) { + DSA_set_ex_data(dsa, 0, NULL); + ReleaseKey(key); + } + // Actual return value is ignored by OpenSSL. There are no docs + // explaining what this is supposed to be. + return 0; +} + +const DSA_METHOD android_dsa_method = { + /* .name = */ "Android signing-only DSA method", + /* .dsa_do_sign = */ DsaMethodDoSign, + /* .dsa_sign_setup = */ DsaMethodSignSetup, + /* .dsa_do_verify = */ DsaMethodDoVerify, + /* .dsa_mod_exp = */ NULL, + /* .bn_mod_exp = */ NULL, + /* .init = */ NULL, // nothing to do here. + /* .finish = */ DsaMethodFinish, + /* .flags = */ 0, + /* .app_data = */ NULL, + /* .dsa_paramgem = */ NULL, + /* .dsa_keygen = */ NULL +}; + +// Setup an EVP_PKEY to wrap an existing DSA platform PrivateKey object. +// |private_key| is a JNI reference (local or global) to the object. +// |pkey| is the EVP_PKEY to setup as a wrapper. +// Returns true on success, false otherwise. +// On success, this creates a global JNI reference to the same object +// that will be owned by and destroyed with the EVP_PKEY. +bool GetDsaPkeyWrapper(jobject private_key, EVP_PKEY* pkey) { + crypto::ScopedDSA dsa(DSA_new()); + DSA_set_method(dsa.get(), &android_dsa_method); + + // DSA_size() doesn't work with custom DSA_METHODs. To ensure it + // returns the right value, set the 'q' field in the DSA object to + // match the parameter from the platform key. + std::vector<uint8> q; + if (!GetDSAKeyParamQ(private_key, &q)) { + LOG(ERROR) << "Can't extract Q parameter from DSA private key"; + return false; + } + if (!SwapBigNumPtrFromBytes(q, &dsa.get()->q)) { + LOG(ERROR) << "Can't decode Q parameter from DSA private key"; + return false; + } + + ScopedJavaGlobalRef<jobject> global_key; + global_key.Reset(NULL, private_key); + if (global_key.is_null()) { + LOG(ERROR) << "Could not create global JNI reference"; + return false; + } + DSA_set_ex_data(dsa.get(), 0, global_key.Release()); + EVP_PKEY_assign_DSA(pkey, dsa.release()); + return true; +} + // Custom ECDSA_METHOD that uses the platform APIs. // Note that for now, only signing through ECDSA_sign() is really supported. // all other method pointers are either stubs returning errors, or no-ops. +// +// Note: The ECDSA_METHOD structure doesn't have init/finish +// methods. As such, the only way to to ensure the global +// JNI reference is properly released when the EVP_PKEY is +// destroyed is to use a custom EX_DATA type. + +// Used to ensure that the global JNI reference associated with a custom +// EC_KEY + ECDSA_METHOD wrapper is released when its EX_DATA is destroyed +// (this function is called when EVP_PKEY_free() is called on the wrapper). +void ExDataFree(void* parent, + void* ptr, + CRYPTO_EX_DATA* ad, + int idx, + long argl, + void* argp) { + jobject private_key = reinterpret_cast<jobject>(ptr); + if (private_key == NULL) + return; -jobject EcKeyGetKey(const EC_KEY* ec_key) { - KeyExData* ex_data = reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data( - ec_key, global_boringssl_engine.Get().ec_key_ex_index())); - return ex_data->private_key; + CRYPTO_set_ex_data(ad, idx, NULL); + ReleaseKey(private_key); +} + +int ExDataDup(CRYPTO_EX_DATA* to, + CRYPTO_EX_DATA* from, + void* from_d, + int idx, + long argl, + void* argp) { + // This callback shall never be called with the current OpenSSL + // implementation (the library only ever duplicates EX_DATA items + // for SSL and BIO objects). But provide this to catch regressions + // in the future. + CHECK(false) << "ExDataDup was called for ECDSA custom key !?"; + // Return value is currently ignored by OpenSSL. + return 0; } -size_t EcdsaMethodGroupOrderSize(const EC_KEY* key) { - KeyExData* ex_data = reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data( - key, global_boringssl_engine.Get().ec_key_ex_index())); - return ex_data->cached_size; +class EcdsaExDataIndex { +public: + int ex_data_index() { return ex_data_index_; } + + EcdsaExDataIndex() { + ex_data_index_ = ECDSA_get_ex_new_index(0, // argl + NULL, // argp + NULL, // new_func + ExDataDup, // dup_func + ExDataFree); // free_func + } + +private: + int ex_data_index_; +}; + +// Returns the index of the custom EX_DATA used to store the JNI reference. +int EcdsaGetExDataIndex(void) { + // Use a LazyInstance to perform thread-safe lazy initialization. + // Use a leaky one, since OpenSSL doesn't provide a way to release + // allocated EX_DATA indices. + static base::LazyInstance<EcdsaExDataIndex>::Leaky s_instance = + LAZY_INSTANCE_INITIALIZER; + return s_instance.Get().ex_data_index(); } -int EcdsaMethodSign(const uint8_t* digest, - size_t digest_len, - uint8_t* sig, - unsigned int* sig_len, - EC_KEY* eckey) { +ECDSA_SIG* EcdsaMethodDoSign(const unsigned char* dgst, + int dgst_len, + const BIGNUM* inv, + const BIGNUM* rp, + EC_KEY* eckey) { // Retrieve private key JNI reference. - jobject private_key = EcKeyGetKey(eckey); + jobject private_key = reinterpret_cast<jobject>( + ECDSA_get_ex_data(eckey, EcdsaGetExDataIndex())); if (!private_key) { - LOG(WARNING) << "Null JNI reference passed to EcdsaMethodSign!"; - return 0; + LOG(WARNING) << "Null JNI reference passed to EcdsaMethodDoSign!"; + return NULL; } // Sign message with it through JNI. std::vector<uint8> signature; - base::StringPiece digest_sp(reinterpret_cast<const char*>(digest), - digest_len); - if (!RawSignDigestWithPrivateKey(private_key, digest_sp, &signature)) { - LOG(WARNING) << "Could not sign message in EcdsaMethodSign!"; - return 0; + base::StringPiece digest( + reinterpret_cast<const char*>(dgst), + static_cast<size_t>(dgst_len)); + if (!RawSignDigestWithPrivateKey( + private_key, digest, &signature)) { + LOG(WARNING) << "Could not sign message in EcdsaMethodDoSign!"; + return NULL; } // Note: With ECDSA, the actual signature may be smaller than // ECDSA_size(). - size_t max_expected_size = ECDSA_size(eckey); + size_t max_expected_size = static_cast<size_t>(ECDSA_size(eckey)); if (signature.size() > max_expected_size) { LOG(ERROR) << "ECDSA Signature size mismatch, actual: " << signature.size() << ", expected <= " << max_expected_size; - return 0; + return NULL; } - memcpy(sig, &signature[0], signature.size()); - *sig_len = signature.size(); - return 1; + // Convert signature to ECDSA_SIG object + const unsigned char* sigbuf = + reinterpret_cast<const unsigned char*>(&signature[0]); + long siglen = static_cast<long>(signature.size()); + return d2i_ECDSA_SIG(NULL, &sigbuf, siglen); } -int EcdsaMethodVerify(const uint8_t* digest, - size_t digest_len, - const uint8_t* sig, - size_t sig_len, - EC_KEY* eckey) { +int EcdsaMethodSignSetup(EC_KEY* eckey, + BN_CTX* ctx, + BIGNUM** kinv, + BIGNUM** r) { NOTIMPLEMENTED(); - OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ECDSA_R_NOT_IMPLEMENTED); - return 0; + ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ECDSA_R_ERR_EC_LIB); + return -1; +} + +int EcdsaMethodDoVerify(const unsigned char* dgst, + int dgst_len, + const ECDSA_SIG* sig, + EC_KEY* eckey) { + NOTIMPLEMENTED(); + ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_ERR_EC_LIB); + return -1; } +const ECDSA_METHOD android_ecdsa_method = { + /* .name = */ "Android signing-only ECDSA method", + /* .ecdsa_do_sign = */ EcdsaMethodDoSign, + /* .ecdsa_sign_setup = */ EcdsaMethodSignSetup, + /* .ecdsa_do_verify = */ EcdsaMethodDoVerify, + /* .flags = */ 0, + /* .app_data = */ NULL, +}; + // Setup an EVP_PKEY to wrap an existing platform PrivateKey object. // |private_key| is the JNI reference (local or global) to the object. // |pkey| is the EVP_PKEY to setup as a wrapper. @@ -504,48 +699,41 @@ int EcdsaMethodVerify(const uint8_t* digest, // is owned by and destroyed with the EVP_PKEY. I.e. the caller shall // always free |private_key| after the call. bool GetEcdsaPkeyWrapper(jobject private_key, EVP_PKEY* pkey) { - crypto::ScopedEC_KEY eckey( - EC_KEY_new_method(global_boringssl_engine.Get().engine())); - - ScopedJavaGlobalRef<jobject> global_key; - global_key.Reset(NULL, private_key); - if (global_key.is_null()) { - LOG(ERROR) << "Can't create global JNI reference"; - return false; - } + crypto::ScopedEC_KEY eckey(EC_KEY_new()); + ECDSA_set_method(eckey.get(), &android_ecdsa_method); + // To ensure that ECDSA_size() works properly, craft a custom EC_GROUP + // that has the same order than the private key. std::vector<uint8> order; if (!GetECKeyOrder(private_key, &order)) { LOG(ERROR) << "Can't extract order parameter from EC private key"; return false; } + ScopedEC_GROUP group(EC_GROUP_new(EC_GFp_nist_method())); + if (!group.get()) { + LOG(ERROR) << "Can't create new EC_GROUP"; + return false; + } + if (!CopyBigNumFromBytes(order, &group.get()->order)) { + LOG(ERROR) << "Can't decode order from PrivateKey"; + return false; + } + EC_KEY_set_group(eckey.get(), group.release()); - KeyExData* ex_data = new KeyExData; - ex_data->private_key = global_key.Release(); - ex_data->legacy_rsa = NULL; - ex_data->cached_size = VectorBignumSize(order); - - EC_KEY_set_ex_data( - eckey.get(), global_boringssl_engine.Get().ec_key_ex_index(), ex_data); + ScopedJavaGlobalRef<jobject> global_key; + global_key.Reset(NULL, private_key); + if (global_key.is_null()) { + LOG(ERROR) << "Can't create global JNI reference"; + return false; + } + ECDSA_set_ex_data(eckey.get(), + EcdsaGetExDataIndex(), + global_key.Release()); EVP_PKEY_assign_EC_KEY(pkey, eckey.release()); return true; } -const ECDSA_METHOD android_ecdsa_method = { - { - 0 /* references */, - 1 /* is_static */ - } /* common */, - NULL /* app_data */, - - NULL /* init */, - NULL /* finish */, - EcdsaMethodGroupOrderSize, - EcdsaMethodSign, - EcdsaMethodVerify, -}; - } // namespace EVP_PKEY* GetOpenSSLPrivateKeyWrapper(jobject private_key) { @@ -577,6 +765,10 @@ EVP_PKEY* GetOpenSSLPrivateKeyWrapper(jobject private_key) { } } break; + case PRIVATE_KEY_TYPE_DSA: + if (!GetDsaPkeyWrapper(private_key, pkey.get())) + return NULL; + break; case PRIVATE_KEY_TYPE_ECDSA: if (!GetEcdsaPkeyWrapper(private_key, pkey.get())) return NULL; diff --git a/net/android/keystore_unittest.cc b/net/android/keystore_unittest.cc index 4fe38ab..076693f 100644 --- a/net/android/keystore_unittest.cc +++ b/net/android/keystore_unittest.cc @@ -205,6 +205,54 @@ ScopedJava GetRSATestKeyJava() { return GetPKCS8PrivateKeyJava(PRIVATE_KEY_TYPE_RSA, key); } +const char kTestDsaKeyFile[] = "android-test-key-dsa.pem"; +const char kTestDsaPublicKeyFile[] = "android-test-key-dsa-public.pem"; + +// The DSA test hash must be 20 bytes exactly. +const char kTestDsaHash[] = "0123456789ABCDEFGHIJ"; + +// Retrieve a JNI local ref for our test DSA key. +ScopedJava GetDSATestKeyJava() { + std::string key; + if (!ImportPrivateKeyFileAsPkcs8(kTestDsaKeyFile, &key)) + return ScopedJava(); + return GetPKCS8PrivateKeyJava(PRIVATE_KEY_TYPE_DSA, key); +} + +// Call this function to verify that one message signed with our +// test DSA private key is correct. Since DSA signing introduces +// random elements in the signature, it is not possible to compare +// signature bits directly. However, one can use the public key +// to do the check. +bool VerifyTestDSASignature(const base::StringPiece& message, + const base::StringPiece& signature) { + crypto::ScopedEVP_PKEY pkey(ImportPublicKeyFile(kTestDsaPublicKeyFile)); + if (!pkey.get()) + return false; + + crypto::ScopedDSA pub_key(EVP_PKEY_get1_DSA(pkey.get())); + if (!pub_key.get()) { + LOG(ERROR) << "Could not get DSA public key: " + << GetOpenSSLErrorString(); + return false; + } + + const unsigned char* digest = + reinterpret_cast<const unsigned char*>(message.data()); + int digest_len = static_cast<int>(message.size()); + const unsigned char* sigbuf = + reinterpret_cast<const unsigned char*>(signature.data()); + int siglen = static_cast<int>(signature.size()); + + int ret = DSA_verify( + 0, digest, digest_len, sigbuf, siglen, pub_key.get()); + if (ret != 1) { + LOG(ERROR) << "DSA_verify() failed: " << GetOpenSSLErrorString(); + return false; + } + return true; +} + const char kTestEcdsaKeyFile[] = "android-test-key-ecdsa.pem"; const char kTestEcdsaPublicKeyFile[] = "android-test-key-ecdsa-public.pem"; @@ -220,7 +268,7 @@ ScopedJava GetECDSATestKeyJava() { } // Call this function to verify that one message signed with our -// test ECDSA private key is correct. Since ECDSA signing introduces +// test DSA private key is correct. Since DSA signing introduces // random elements in the signature, it is not possible to compare // signature bits directly. However, one can use the public key // to do the check. @@ -290,6 +338,28 @@ bool SignWithOpenSSL(const base::StringPiece& message, signature_size = static_cast<size_t>(p_len); break; } + case EVP_PKEY_DSA: + { + crypto::ScopedDSA dsa(EVP_PKEY_get1_DSA(openssl_key)); + if (!dsa.get()) { + LOG(ERROR) << "Could not get DSA from EVP_PKEY: " + << GetOpenSSLErrorString(); + return false; + } + // Note, the actual signature can be smaller than DSA_size() + max_signature_size = static_cast<size_t>(DSA_size(dsa.get())); + unsigned char* p = OpenSSLWriteInto(&signature, + max_signature_size); + unsigned int p_len = 0; + // Note: first parameter is ignored by function. + int ret = DSA_sign(0, digest, digest_len, p, &p_len, dsa.get()); + if (ret != 1) { + LOG(ERROR) << "DSA_sign() failed: " << GetOpenSSLErrorString(); + return false; + } + signature_size = static_cast<size_t>(p_len); + break; + } case EVP_PKEY_EC: { crypto::ScopedEC_KEY ecdsa(EVP_PKEY_get1_EC_KEY(openssl_key)); @@ -449,6 +519,41 @@ TEST(AndroidKeyStore,GetRSAKeyModulus) { ASSERT_EQ(0, BN_cmp(bn.get(), rsa.get()->n)); } +TEST(AndroidKeyStore,GetDSAKeyParamQ) { + crypto::OpenSSLErrStackTracer err_trace(FROM_HERE); + InitEnv(); + + // Load the test DSA key. + crypto::ScopedEVP_PKEY pkey(ImportPrivateKeyFile(kTestDsaKeyFile)); + ASSERT_TRUE(pkey.get()); + + // Convert it to encoded PKCS#8 bytes. + std::string pkcs8_data; + ASSERT_TRUE(GetPrivateKeyPkcs8Bytes(pkey, &pkcs8_data)); + + // Create platform PrivateKey object from it. + ScopedJava key_java = GetPKCS8PrivateKeyJava(PRIVATE_KEY_TYPE_DSA, + pkcs8_data); + ASSERT_FALSE(key_java.is_null()); + + // Retrieve the corresponding Q parameter through JNI + std::vector<uint8> q_java; + ASSERT_TRUE(GetDSAKeyParamQ(key_java.obj(), &q_java)); + + // Create an OpenSSL BIGNUM from it. + crypto::ScopedBIGNUM bn( + BN_bin2bn(reinterpret_cast<const unsigned char*>(&q_java[0]), + static_cast<int>(q_java.size()), + NULL)); + ASSERT_TRUE(bn.get()); + + // Compare it to the one in the RSA key, they must be identical. + crypto::ScopedDSA dsa(EVP_PKEY_get1_DSA(pkey.get())); + ASSERT_TRUE(dsa.get()) << GetOpenSSLErrorString(); + + ASSERT_EQ(0, BN_cmp(bn.get(), dsa.get()->q)); +} + TEST(AndroidKeyStore,GetPrivateKeyTypeRSA) { crypto::OpenSSLErrStackTracer err_trace(FROM_HERE); @@ -511,6 +616,56 @@ TEST(AndroidKeyStore,SignWithWrapperKeyRSA) { CompareSignatureWithOpenSSL(message, signature, openssl_key.get())); } +TEST(AndroidKeyStore,GetPrivateKeyTypeDSA) { + crypto::OpenSSLErrStackTracer err_trace(FROM_HERE); + + ScopedJava dsa_key = GetDSATestKeyJava(); + ASSERT_FALSE(dsa_key.is_null()); + EXPECT_EQ(PRIVATE_KEY_TYPE_DSA, + GetPrivateKeyType(dsa_key.obj())); +} + +TEST(AndroidKeyStore,SignWithPrivateKeyDSA) { + ScopedJava dsa_key = GetDSATestKeyJava(); + ASSERT_FALSE(dsa_key.is_null()); + + crypto::ScopedEVP_PKEY openssl_key(ImportPrivateKeyFile(kTestDsaKeyFile)); + ASSERT_TRUE(openssl_key.get()); + + std::string message = kTestDsaHash; + ASSERT_EQ(20U, message.size()); + + std::string signature; + DoKeySigning(dsa_key.obj(), openssl_key.get(), message, &signature); + ASSERT_TRUE(VerifyTestDSASignature(message, signature)); +} + +TEST(AndroidKeyStore,SignWithWrapperKeyDSA) { + crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); + + ScopedJava dsa_key = GetDSATestKeyJava(); + ASSERT_FALSE(dsa_key.is_null()); + + crypto::ScopedEVP_PKEY wrapper_key( + GetOpenSSLPrivateKeyWrapper(dsa_key.obj())); + ASSERT_TRUE(wrapper_key.get()); + + crypto::ScopedEVP_PKEY openssl_key(ImportPrivateKeyFile(kTestDsaKeyFile)); + ASSERT_TRUE(openssl_key.get()); + + // Check that DSA_size() works correctly on the wrapper. + EXPECT_EQ(EVP_PKEY_size(openssl_key.get()), + EVP_PKEY_size(wrapper_key.get())); + + std::string message = kTestDsaHash; + std::string signature; + DoKeySigningWithWrapper(wrapper_key.get(), + openssl_key.get(), + message, + &signature); + ASSERT_TRUE(VerifyTestDSASignature(message, signature)); +} + TEST(AndroidKeyStore,GetPrivateKeyTypeECDSA) { crypto::OpenSSLErrStackTracer err_trace(FROM_HERE); diff --git a/net/cert/cert_verify_proc_openssl.cc b/net/cert/cert_verify_proc_openssl.cc index 7643240..0122fac 100644 --- a/net/cert/cert_verify_proc_openssl.cc +++ b/net/cert/cert_verify_proc_openssl.cc @@ -101,7 +101,7 @@ void GetCertChainInfo(X509_STORE_CTX* store_ctx, STACK_OF(X509)* chain = X509_STORE_CTX_get_chain(store_ctx); X509* verified_cert = NULL; std::vector<X509*> verified_chain; - for (size_t i = 0; i < sk_X509_num(chain); ++i) { + for (int i = 0; i < sk_X509_num(chain); ++i) { X509* cert = sk_X509_value(chain, i); if (i == 0) { verified_cert = cert; @@ -111,7 +111,7 @@ void GetCertChainInfo(X509_STORE_CTX* store_ctx, // Only check the algorithm status for certificates that are not in the // trust store. - if (i < static_cast<size_t>(store_ctx->last_untrusted)) { + if (i < store_ctx->last_untrusted) { int sig_alg = OBJ_obj2nid(cert->sig_alg->algorithm); if (sig_alg == NID_md2WithRSAEncryption) { verify_result->has_md2 = true; @@ -151,7 +151,7 @@ void GetCertChainInfo(X509_STORE_CTX* store_ctx, void AppendPublicKeyHashes(X509_STORE_CTX* store_ctx, HashValueVector* hashes) { STACK_OF(X509)* chain = X509_STORE_CTX_get_chain(store_ctx); - for (size_t i = 0; i < sk_X509_num(chain); ++i) { + for (int i = 0; i < sk_X509_num(chain); ++i) { X509* cert = sk_X509_value(chain, i); std::string der_data; diff --git a/net/cert/x509_certificate_openssl.cc b/net/cert/x509_certificate_openssl.cc index 504f3ae..005423ba 100644 --- a/net/cert/x509_certificate_openssl.cc +++ b/net/cert/x509_certificate_openssl.cc @@ -5,10 +5,10 @@ #include "net/cert/x509_certificate.h" #include <openssl/asn1.h> -#include <openssl/bytestring.h> #include <openssl/crypto.h> #include <openssl/obj_mac.h> #include <openssl/pem.h> +#include <openssl/pkcs7.h> #include <openssl/sha.h> #include <openssl/ssl.h> #include <openssl/x509v3.h> @@ -40,20 +40,27 @@ void CreateOSCertHandlesFromPKCS7Bytes( const char* data, int length, X509Certificate::OSCertHandles* handles) { crypto::EnsureOpenSSLInit(); - crypto::OpenSSLErrStackTracer err_cleaner(FROM_HERE); + const unsigned char* der_data = reinterpret_cast<const unsigned char*>(data); + crypto::ScopedOpenSSL<PKCS7, PKCS7_free>::Type pkcs7_cert( + d2i_PKCS7(NULL, &der_data, length)); + if (!pkcs7_cert.get()) + return; - CBS der_data; - CBS_init(&der_data, reinterpret_cast<const uint8_t*>(data), length); - STACK_OF(X509)* certs = sk_X509_new_null(); + STACK_OF(X509)* certs = NULL; + int nid = OBJ_obj2nid(pkcs7_cert.get()->type); + if (nid == NID_pkcs7_signed) { + certs = pkcs7_cert.get()->d.sign->cert; + } else if (nid == NID_pkcs7_signedAndEnveloped) { + certs = pkcs7_cert.get()->d.signed_and_enveloped->cert; + } - if (PKCS7_get_certificates(certs, &der_data)) { - for (size_t i = 0; i < sk_X509_num(certs); ++i) { + if (certs) { + for (int i = 0; i < sk_X509_num(certs); ++i) { X509* x509_cert = X509Certificate::DupOSCertHandle(sk_X509_value(certs, i)); handles->push_back(x509_cert); } } - sk_X509_pop_free(certs, X509_free); } void ParsePrincipalValues(X509_NAME* name, @@ -107,7 +114,7 @@ void ParseSubjectAltName(X509Certificate::OSCertHandle cert, if (!alt_names.get()) return; - for (size_t i = 0; i < sk_GENERAL_NAME_num(alt_names.get()); ++i) { + for (int i = 0; i < sk_GENERAL_NAME_num(alt_names.get()); ++i) { const GENERAL_NAME* name = sk_GENERAL_NAME_value(alt_names.get(), i); if (name->type == GEN_DNS && dns_names) { const unsigned char* dns_name = ASN1_STRING_data(name->d.dNSName); @@ -502,7 +509,7 @@ bool X509Certificate::IsIssuedByEncoded( // and 'cert_names'. for (size_t n = 0; n < cert_names.size(); ++n) { - for (size_t m = 0; m < sk_X509_NAME_num(issuer_names.get()); ++m) { + for (int m = 0; m < sk_X509_NAME_num(issuer_names.get()); ++m) { X509_NAME* issuer = sk_X509_NAME_value(issuer_names.get(), m); if (X509_NAME_cmp(issuer, cert_names[n]) == 0) { return true; diff --git a/net/http/des.cc b/net/http/des.cc index daac8a4..79240cf 100644 --- a/net/http/des.cc +++ b/net/http/des.cc @@ -93,10 +93,10 @@ void DESEncrypt(const uint8* key, const uint8* src, uint8* hash) { crypto::EnsureOpenSSLInit(); DES_key_schedule ks; - DES_set_key( - reinterpret_cast<const DES_cblock*>(key), &ks); + DES_set_key_unchecked( + reinterpret_cast<const_DES_cblock*>(const_cast<uint8*>(key)), &ks); - DES_ecb_encrypt(reinterpret_cast<const DES_cblock*>(src), + DES_ecb_encrypt(reinterpret_cast<const_DES_cblock*>(const_cast<uint8*>(src)), reinterpret_cast<DES_cblock*>(hash), &ks, DES_ENCRYPT); } diff --git a/net/net.gyp b/net/net.gyp index a6c4f29..fb5b853 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -255,7 +255,7 @@ 'third_party/mozilla_security_manager/nsPKCS12Blob.h', ], 'dependencies': [ - '../third_party/boringssl/boringssl.gyp:boringssl', + '../third_party/openssl/openssl.gyp:openssl', ], }, { # else !use_openssl: remove the unneeded files @@ -466,7 +466,7 @@ }], [ 'OS == "android"', { 'dependencies': [ - '../third_party/boringssl/boringssl.gyp:boringssl', + '../third_party/openssl/openssl.gyp:openssl', 'net_jni_headers', ], 'sources!': [ @@ -475,6 +475,11 @@ 'cert/cert_verify_proc_openssl.cc', 'cert/test_root_certs_openssl.cc', ], + # The net/android/keystore_openssl.cc source file needs to + # access an OpenSSL-internal header. + 'include_dirs': [ + '../third_party/openssl', + ], }, ], [ 'use_icu_alternatives_on_android == 1', { @@ -589,7 +594,7 @@ [ 'use_openssl == 1', { # Avoid compiling/linking with the system library. 'dependencies': [ - '../third_party/boringssl/boringssl.gyp:boringssl', + '../third_party/openssl/openssl.gyp:openssl', ], }, { # use_openssl == 0 'conditions': [ @@ -792,7 +797,7 @@ }], [ 'OS == "android"', { 'dependencies': [ - '../third_party/boringssl/boringssl.gyp:boringssl', + '../third_party/openssl/openssl.gyp:openssl', ], 'sources!': [ 'dns/dns_config_service_posix_unittest.cc', @@ -973,7 +978,7 @@ 'conditions': [ ['use_openssl==1', { 'dependencies': [ - '../third_party/boringssl/boringssl.gyp:boringssl', + '../third_party/openssl/openssl.gyp:openssl', ], }, { 'dependencies': [ @@ -1371,7 +1376,7 @@ ], 'dependencies': [ '../base/base.gyp:base', - '../third_party/boringssl/boringssl.gyp:boringssl', + '../third_party/openssl/openssl.gyp:openssl', 'balsa', 'epoll_server', 'net', @@ -1416,7 +1421,7 @@ 'dependencies': [ '../testing/gtest.gyp:gtest', '../testing/gmock.gyp:gmock', - '../third_party/boringssl/boringssl.gyp:boringssl', + '../third_party/openssl/openssl.gyp:openssl', 'flip_in_mem_edsm_server_base', 'net', 'net_test_support', diff --git a/net/net_nacl.gyp b/net/net_nacl.gyp index 7ca48ed..33a63d0 100644 --- a/net/net_nacl.gyp +++ b/net/net_nacl.gyp @@ -25,7 +25,7 @@ '../crypto/crypto_nacl.gyp:crypto_nacl', '../native_client/tools.gyp:prep_toolchain', '../native_client_sdk/native_client_sdk_untrusted.gyp:nacl_io_untrusted', - '../third_party/boringssl/boringssl_nacl.gyp:boringssl_nacl', + '../third_party/openssl/openssl_nacl.gyp:openssl_nacl', '../url/url_nacl.gyp:url_nacl', 'net.gyp:net_derived_sources', 'net.gyp:net_resources', diff --git a/net/quic/crypto/aead_base_decrypter_openssl.cc b/net/quic/crypto/aead_base_decrypter_openssl.cc index fad0fe1..2190bf6 100644 --- a/net/quic/crypto/aead_base_decrypter_openssl.cc +++ b/net/quic/crypto/aead_base_decrypter_openssl.cc @@ -86,18 +86,21 @@ bool AeadBaseDecrypter::Decrypt(StringPiece nonce, return false; } - if (!EVP_AEAD_CTX_open( - ctx_.get(), output, output_length, ciphertext.size(), + ssize_t len = EVP_AEAD_CTX_open( + ctx_.get(), output, ciphertext.size(), reinterpret_cast<const uint8_t*>(nonce.data()), nonce.size(), reinterpret_cast<const uint8_t*>(ciphertext.data()), ciphertext.size(), reinterpret_cast<const uint8_t*>(associated_data.data()), - associated_data.size())) { + associated_data.size()); + + if (len < 0) { // Because QuicFramer does trial decryption, decryption errors are expected // when encryption level changes. So we don't log decryption errors. ClearOpenSslErrors(); return false; } + *output_length = len; return true; } diff --git a/net/quic/crypto/aead_base_encrypter_openssl.cc b/net/quic/crypto/aead_base_encrypter_openssl.cc index 7f2d3c6..9f053ab 100644 --- a/net/quic/crypto/aead_base_encrypter_openssl.cc +++ b/net/quic/crypto/aead_base_encrypter_openssl.cc @@ -81,18 +81,14 @@ bool AeadBaseEncrypter::Encrypt(StringPiece nonce, return false; } - size_t len; - if (!EVP_AEAD_CTX_seal( - ctx_.get(), - output, - &len, - plaintext.size() + auth_tag_size_, - reinterpret_cast<const uint8_t*>(nonce.data()), - nonce.size(), - reinterpret_cast<const uint8_t*>(plaintext.data()), - plaintext.size(), - reinterpret_cast<const uint8_t*>(associated_data.data()), - associated_data.size())) { + ssize_t len = EVP_AEAD_CTX_seal( + ctx_.get(), output, plaintext.size() + auth_tag_size_, + reinterpret_cast<const uint8_t*>(nonce.data()), nonce.size(), + reinterpret_cast<const uint8_t*>(plaintext.data()), plaintext.size(), + reinterpret_cast<const uint8_t*>(associated_data.data()), + associated_data.size()); + + if (len < 0) { DLogOpenSslErrors(); return false; } diff --git a/net/socket/openssl_ssl_util.cc b/net/socket/openssl_ssl_util.cc index 231f77c..a11436c 100644 --- a/net/socket/openssl_ssl_util.cc +++ b/net/socket/openssl_ssl_util.cc @@ -4,8 +4,6 @@ #include "net/socket/openssl_ssl_util.h" -#include <errno.h> - #include <openssl/err.h> #include <openssl/ssl.h> @@ -41,16 +39,16 @@ class OpenSSLNetErrorLibSingleton { net_error_lib_ = ERR_get_next_error_library(); } - unsigned net_error_lib() const { return net_error_lib_; } + int net_error_lib() const { return net_error_lib_; } private: - unsigned net_error_lib_; + int net_error_lib_; }; base::LazyInstance<OpenSSLNetErrorLibSingleton>::Leaky g_openssl_net_error_lib = LAZY_INSTANCE_INITIALIZER; -unsigned OpenSSLNetErrorLib() { +int OpenSSLNetErrorLib() { return g_openssl_net_error_lib.Get().net_error_lib(); } @@ -164,7 +162,7 @@ void OpenSSLPutNetError(const tracked_objects::Location& location, int err) { NOTREACHED(); err = ERR_INVALID_ARGUMENT; } - ERR_put_error(OpenSSLNetErrorLib(), 0, err, + ERR_PUT_error(OpenSSLNetErrorLib(), 0, err, location.file_name(), location.line_number()); } diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc index 53e0870..0c480c9 100644 --- a/net/socket/ssl_client_socket_openssl.cc +++ b/net/socket/ssl_client_socket_openssl.cc @@ -7,8 +7,8 @@ #include "net/socket/ssl_client_socket_openssl.h" -#include <errno.h> #include <openssl/err.h> +#include <openssl/opensslv.h> #include <openssl/ssl.h> #include "base/bind.h" @@ -153,7 +153,6 @@ class SSLClientSocketOpenSSL::SSLContext { // but that is an OpenSSL issue. SSL_CTX_set_next_proto_select_cb(ssl_ctx_.get(), SelectNextProtoCallback, NULL); - ssl_ctx_->tlsext_channel_id_enabled_new = 1; } static std::string GetSessionCacheKey(const SSL* ssl) { @@ -249,7 +248,7 @@ SSLClientSocketOpenSSL::PeerCertificateChain::operator=( // Must increase the reference count manually for sk_X509_dup openssl_chain_.reset(sk_X509_dup(other.openssl_chain_.get())); - for (size_t i = 0; i < sk_X509_num(openssl_chain_.get()); ++i) { + for (int i = 0; i < sk_X509_num(openssl_chain_.get()); ++i) { X509* x = sk_X509_value(openssl_chain_.get(), i); CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); } @@ -268,7 +267,7 @@ void SSLClientSocketOpenSSL::PeerCertificateChain::Reset( return; X509Certificate::OSCertHandles intermediates; - for (size_t i = 1; i < sk_X509_num(chain); ++i) + for (int i = 1; i < sk_X509_num(chain); ++i) intermediates.push_back(sk_X509_value(chain, i)); os_chain_ = @@ -278,7 +277,7 @@ void SSLClientSocketOpenSSL::PeerCertificateChain::Reset( openssl_chain_.reset(sk_X509_dup(chain)); std::vector<base::StringPiece> der_chain; - for (size_t i = 0; i < sk_X509_num(openssl_chain_.get()); ++i) { + for (int i = 0; i < sk_X509_num(openssl_chain_.get()); ++i) { X509* x = sk_X509_value(openssl_chain_.get(), i); // Increase the reference count for the certs in openssl_chain_. CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); @@ -508,8 +507,8 @@ bool SSLClientSocketOpenSSL::IsConnectedAndIdle() const { return false; // If there is data waiting to be sent, or data read from the network that // has not yet been consumed. - if (BIO_pending(transport_bio_) > 0 || - BIO_wpending(transport_bio_) > 0) { + if (BIO_ctrl_pending(transport_bio_) > 0 || + BIO_ctrl_wpending(transport_bio_) > 0) { return false; } @@ -579,9 +578,11 @@ bool SSLClientSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) { const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl_); CHECK(cipher); ssl_info->security_bits = SSL_CIPHER_get_bits(cipher, NULL); + const COMP_METHOD* compression = SSL_get_current_compression(ssl_); ssl_info->connection_status = EncodeSSLConnectionStatus( - SSL_CIPHER_get_id(cipher), 0 /* no compression */, + SSL_CIPHER_get_id(cipher), + compression ? compression->type : 0, GetNetSSLVersion(ssl_)); bool peer_supports_renego_ext = !!SSL_get_secure_renegotiation_support(ssl_); @@ -731,7 +732,7 @@ int SSLClientSocketOpenSSL::Init() { "!aECDH:!AESGCM+AES256"); // Walk through all the installed ciphers, seeing if any need to be // appended to the cipher removal |command|. - for (size_t i = 0; i < sk_SSL_CIPHER_num(ciphers); ++i) { + for (int i = 0; i < sk_SSL_CIPHER_num(ciphers); ++i) { const SSL_CIPHER* cipher = sk_SSL_CIPHER_value(ciphers, i); const uint16 id = SSL_CIPHER_get_id(cipher); // Remove any ciphers with a strength of less than 80 bits. Note the NSS @@ -1205,7 +1206,7 @@ int SSLClientSocketOpenSSL::BufferSend(void) { if (!send_buffer_.get()) { // Get a fresh send buffer out of the send BIO. - size_t max_read = BIO_pending(transport_bio_); + size_t max_read = BIO_ctrl_pending(transport_bio_); if (!max_read) return 0; // Nothing pending in the OpenSSL write BIO. send_buffer_ = new DrainableIOBuffer(new IOBuffer(max_read), max_read); @@ -1328,7 +1329,7 @@ int SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl, // have one at hand. client_auth_cert_needed_ = true; STACK_OF(X509_NAME) *authorities = SSL_get_client_CA_list(ssl); - for (size_t i = 0; i < sk_X509_NAME_num(authorities); i++) { + for (int i = 0; i < sk_X509_NAME_num(authorities); i++) { X509_NAME *ca_name = (X509_NAME *)sk_X509_NAME_value(authorities, i); unsigned char* str = NULL; int length = i2d_X509_NAME(ca_name, &str); diff --git a/net/socket/ssl_server_socket_openssl.cc b/net/socket/ssl_server_socket_openssl.cc index 84ba622..7a1ce16 100644 --- a/net/socket/ssl_server_socket_openssl.cc +++ b/net/socket/ssl_server_socket_openssl.cc @@ -305,7 +305,7 @@ int SSLServerSocketOpenSSL::BufferSend() { if (!send_buffer_.get()) { // Get a fresh send buffer out of the send BIO. - size_t max_read = BIO_pending(transport_bio_); + size_t max_read = BIO_ctrl_pending(transport_bio_); if (!max_read) return 0; // Nothing pending in the OpenSSL write BIO. send_buffer_ = new DrainableIOBuffer(new IOBuffer(max_read), max_read); diff --git a/net/socket/ssl_session_cache_openssl_unittest.cc b/net/socket/ssl_session_cache_openssl_unittest.cc index 54b1e3b..41e195f 100644 --- a/net/socket/ssl_session_cache_openssl_unittest.cc +++ b/net/socket/ssl_session_cache_openssl_unittest.cc @@ -75,8 +75,8 @@ class SSLKeyHelper { // Called when an SSL object is copied through SSL_dup(). This needs to copy // the value as well. static int KeyDup(CRYPTO_EX_DATA* to, - const CRYPTO_EX_DATA* from, - void** from_fd, + CRYPTO_EX_DATA* from, + void* from_fd, int idx, long argl, void* argp) { diff --git a/net/tools/flip_server/acceptor_thread.cc b/net/tools/flip_server/acceptor_thread.cc index 2b65e5d..5dfece1 100644 --- a/net/tools/flip_server/acceptor_thread.cc +++ b/net/tools/flip_server/acceptor_thread.cc @@ -4,7 +4,6 @@ #include "net/tools/flip_server/acceptor_thread.h" -#include <errno.h> #include <netinet/in.h> #include <netinet/tcp.h> // For TCP_NODELAY #include <sys/socket.h> diff --git a/net/tools/flip_server/spdy_ssl.cc b/net/tools/flip_server/spdy_ssl.cc index 19ea52e..2a5cb0e 100644 --- a/net/tools/flip_server/spdy_ssl.cc +++ b/net/tools/flip_server/spdy_ssl.cc @@ -80,7 +80,6 @@ void InitSSL(SSLState* state, SSL_CTX_set_mode(state->ssl_ctx, SSL_MODE_RELEASE_BUFFERS); #endif -#if !defined(OPENSSL_IS_BORINGSSL) // Proper methods to disable compression don't exist until 0.9.9+. For now // we must manipulate the stack of compression methods directly. if (disable_ssl_compression) { @@ -91,7 +90,6 @@ void InitSSL(SSLState* state, static_cast<void>(sk_SSL_COMP_delete(ssl_comp_methods, i)); } } -#endif } SSL* CreateSSLContext(SSL_CTX* ssl_ctx) { diff --git a/remoting/host/token_validator_base.cc b/remoting/host/token_validator_base.cc index 452a182..8a5c2c3 100644 --- a/remoting/host/token_validator_base.cc +++ b/remoting/host/token_validator_base.cc @@ -120,9 +120,6 @@ void TokenValidatorBase::OnCertificateRequested( client_cert_store = new net::ClientCertStoreWin(); #elif defined(OS_MACOSX) client_cert_store = new net::ClientCertStoreMac(); -#elif defined(USE_OPENSSL) - // OpenSSL does not use the ClientCertStore infrastructure. - client_cert_store = NULL; #else #error Unknown platform. #endif diff --git a/remoting/remoting_nacl.gyp b/remoting/remoting_nacl.gyp index 0dd96b1..c2598c9 100644 --- a/remoting/remoting_nacl.gyp +++ b/remoting/remoting_nacl.gyp @@ -108,7 +108,7 @@ '../third_party/libvpx/libvpx_nacl.gyp:libvpx_nacl', '../third_party/libwebm/libwebm_nacl.gyp:libwebm_nacl', '../third_party/libyuv/libyuv_nacl.gyp:libyuv_nacl', - '../third_party/boringssl/boringssl_nacl.gyp:boringssl_nacl', + '../third_party/openssl/openssl_nacl.gyp:openssl_nacl', '../third_party/opus/opus_nacl.gyp:opus_nacl', 'remoting_proto_nacl', 'remoting_webrtc_nacl', @@ -160,7 +160,7 @@ '>(tc_lib_dir_pnacl_newlib)/libjingle_p2p_constants_nacl.a', '>(tc_lib_dir_pnacl_newlib)/libmedia_yuv_nacl.a', '>(tc_lib_dir_pnacl_newlib)/libmodp_b64_nacl.a', - '>(tc_lib_dir_pnacl_newlib)/libboringssl_nacl.a', + '>(tc_lib_dir_pnacl_newlib)/libopenssl_nacl.a', '>(tc_lib_dir_pnacl_newlib)/libopus_nacl.a', '>(tc_lib_dir_pnacl_newlib)/libppapi.a', '>(tc_lib_dir_pnacl_newlib)/libppapi_cpp.a', @@ -196,7 +196,7 @@ '../third_party/libwebm/libwebm_nacl.gyp:libwebm_nacl', '../third_party/libyuv/libyuv_nacl.gyp:libyuv_nacl', '../third_party/modp_b64/modp_b64_nacl.gyp:modp_b64_nacl', - '../third_party/boringssl/boringssl_nacl.gyp:boringssl_nacl', + '../third_party/openssl/openssl_nacl.gyp:openssl_nacl', '../url/url_nacl.gyp:url_nacl', 'remoting_client_plugin_lib_nacl', 'remoting_proto_nacl', @@ -227,7 +227,7 @@ '-lexpat_nacl', '-lmodp_b64_nacl', '-lopus_nacl', - '-lboringssl_nacl', + '-lopenssl_nacl', '-licui18n_nacl', '-licuuc_nacl', '-licudata_nacl', diff --git a/third_party/boringssl/BUILD.gn b/third_party/boringssl/BUILD.gn deleted file mode 100644 index 52a3ff3..0000000 --- a/third_party/boringssl/BUILD.gn +++ /dev/null @@ -1,65 +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. - -# Config for us and everybody else depending on BoringSSL. -config("openssl_config") { - include_dirs = [] - include_dirs += [ "src/include" ] -} - -# Config internal to this build file. -config("openssl_internal_config") { - visibility = ":*" # Only targets in this file can depend on this. -} - -# The list of BoringSSL files is kept in boringssl.gypi. -gypi_values = exec_script( - "//build/gypi_to_gn.py", - [ rebase_path("//third_party/boringssl/boringssl.gypi") ], - "scope", - [ "//third_party/boringssl/boringssl.gypi" ]) - -component("boringssl") { - sources = gypi_values.boringssl_lib_sources - - direct_dependent_configs = [ ":openssl_config" ] - - cflags = [] - - configs -= [ "//build/config/compiler:chromium_code" ] - configs += [ "//build/config/compiler:no_chromium_code" ] - - # Also gets the include dirs from :openssl_config - include_dirs = [ - "src/include", - # This is for arm_arch.h, which is needed by some asm files. Since the - # asm files are generated and kept in a different directory, they - # cannot use relative paths to find this file. - "src/crypto", - ] - - if (cpu_arch == "x64") { - if (is_mac) { - sources += gypi_values.boringssl_mac_x86_64_sources - } else if (is_linux || is_android) { - sources += gypi_values.boringssl_linux_x86_64_sources - } else if (is_win) { - sources += gypi_values.boringssl_win_x86_64_sources - } else { - defines += [ "OPENSSL_NO_ASM" ] - } - } else if (cpu_arch == "x86") { - if (is_mac) { - sources += gypi_values.boringssl_mac_x86_sources - } else if (is_linux || is_android) { - sources += gypi_values.boringssl_linux_x86_sources - } else { - defines += [ "OPENSSL_NO_ASM" ] - } - } else if (cpu_arch == "arm") { - sources += gypi_values.boringssl_linux_arm_sources - } else { - defines += [ "OPENSSL_NO_ASM" ] - } -} diff --git a/third_party/boringssl/boringssl_nacl.gyp b/third_party/boringssl/boringssl_nacl.gyp deleted file mode 100644 index 6ab4b9d..0000000 --- a/third_party/boringssl/boringssl_nacl.gyp +++ /dev/null @@ -1,50 +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. -{ - 'includes': [ - '../../native_client/build/untrusted.gypi', - ], - 'targets': [ - { - 'target_name': 'boringssl_nacl', - 'type': 'none', - 'variables': { - 'nlib_target': 'libboringssl_nacl.a', - 'build_glibc': 0, - 'build_newlib': 0, - 'build_pnacl_newlib': 1, - }, - 'dependencies': [ - '<(DEPTH)/native_client/tools.gyp:prep_toolchain', - '<(DEPTH)/native_client_sdk/native_client_sdk_untrusted.gyp:nacl_io_untrusted', - ], - 'includes': [ - # Include the auto-generated gypi file. - 'boringssl.gypi' - ], - 'sources': [ - '<@(boringssl_lib_sources)', - ], - 'defines': [ - 'OPENSSL_NO_ASM', - ], - 'include_dirs': [ - 'src/include', - # This is for arm_arch.h, which is needed by some asm files. Since the - # asm files are generated and kept in a different directory, they - # cannot use relative paths to find this file. - 'src/crypto', - ], - 'direct_dependent_settings': { - 'include_dirs': [ - 'src/include', - ], - }, - 'pnacl_compile_flags': [ - '-Wno-sometimes-uninitialized', - '-Wno-unused-variable', - ], - }, # target boringssl_nacl - ], -} diff --git a/third_party/libjingle/libjingle.gyp b/third_party/libjingle/libjingle.gyp index 4ec4641..1538305 100644 --- a/third_party/libjingle/libjingle.gyp +++ b/third_party/libjingle/libjingle.gyp @@ -158,7 +158,7 @@ 'HAVE_OPENSSL_SSL_H', ], 'dependencies': [ - '../../third_party/boringssl/boringssl.gyp:boringssl', + '../../third_party/openssl/openssl.gyp:openssl', ], }, { 'defines': [ diff --git a/third_party/libjingle/libjingle_nacl.gyp b/third_party/libjingle/libjingle_nacl.gyp index 8b1b498..dc9ef0b 100644 --- a/third_party/libjingle/libjingle_nacl.gyp +++ b/third_party/libjingle/libjingle_nacl.gyp @@ -25,7 +25,7 @@ '<(DEPTH)/native_client/tools.gyp:prep_toolchain', '<(DEPTH)/native_client_sdk/native_client_sdk_untrusted.gyp:nacl_io_untrusted', '<(DEPTH)/third_party/expat/expat_nacl.gyp:expat_nacl', - '<(DEPTH)/third_party/boringssl/boringssl_nacl.gyp:boringssl_nacl', + '<(DEPTH)/third_party/openssl/openssl_nacl.gyp:openssl_nacl', 'libjingle_p2p_constants_nacl', ], 'defines': [ diff --git a/third_party/usrsctp/usrsctp.gyp b/third_party/usrsctp/usrsctp.gyp index 04952ab..56ea9ea 100644 --- a/third_party/usrsctp/usrsctp.gyp +++ b/third_party/usrsctp/usrsctp.gyp @@ -28,7 +28,7 @@ 'SCTP_USE_OPENSSL_SHA1', ], 'dependencies': [ - '<(DEPTH)/third_party/boringssl/boringssl.gyp:boringssl', + '<(DEPTH)/third_party/openssl/openssl.gyp:openssl', ], }, { # else use_openssl==0, use NSS. |