| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/ssl/ssl_platform_key_android.h" | 5 #include "net/ssl/ssl_platform_key_android.h" |
| 6 | 6 |
| 7 #include <openssl/digest.h> | 7 #include <vector> |
| 8 #include <openssl/evp.h> | |
| 9 #include <utility> | |
| 10 | 8 |
| 9 #include "base/android/build_info.h" |
| 10 #include "base/android/scoped_java_ref.h" |
| 11 #include "base/lazy_instance.h" |
| 11 #include "base/logging.h" | 12 #include "base/logging.h" |
| 12 #include "base/macros.h" | 13 #include "base/macros.h" |
| 13 #include "crypto/scoped_openssl_types.h" | 14 #include "crypto/scoped_openssl_types.h" |
| 15 #include "net/android/keystore.h" |
| 16 #include "net/android/legacy_openssl.h" |
| 14 #include "net/base/net_errors.h" | 17 #include "net/base/net_errors.h" |
| 18 #include "net/ssl/ssl_platform_key.h" |
| 15 #include "net/ssl/ssl_platform_key_task_runner.h" | 19 #include "net/ssl/ssl_platform_key_task_runner.h" |
| 16 #include "net/ssl/ssl_private_key.h" | 20 #include "net/ssl/ssl_private_key.h" |
| 17 #include "net/ssl/threaded_ssl_private_key.h" | 21 #include "net/ssl/threaded_ssl_private_key.h" |
| 18 | 22 |
| 23 using base::android::ScopedJavaLocalRef; |
| 24 using base::android::ScopedJavaGlobalRef; |
| 25 |
| 19 namespace net { | 26 namespace net { |
| 20 | 27 |
| 21 namespace { | 28 namespace { |
| 22 | 29 |
| 30 // On Android < 4.2, the libkeystore.so ENGINE uses CRYPTO_EX_DATA and is not |
| 31 // added to the global engine list. If all references to it are dropped, OpenSSL |
| 32 // will dlclose the module, leaving a dangling function pointer in the RSA |
| 33 // CRYPTO_EX_DATA class. To work around this, leak an extra reference to the |
| 34 // ENGINE we extract in GetRsaLegacyKey. |
| 35 // |
| 36 // In 4.2, this change avoids the problem: |
| 37 // https://android.googlesource.com/platform/libcore/+/106a8928fb4249f2f3d4dba1d
ddbe73ca5cb3d61 |
| 38 // |
| 39 // https://crbug.com/381465 |
| 40 class KeystoreEngineWorkaround { |
| 41 public: |
| 42 KeystoreEngineWorkaround() {} |
| 43 |
| 44 void LeakEngine(jobject private_key) { |
| 45 if (!engine_.is_null()) |
| 46 return; |
| 47 ScopedJavaLocalRef<jobject> engine = |
| 48 android::GetOpenSSLEngineForPrivateKey(private_key); |
| 49 if (engine.is_null()) { |
| 50 NOTREACHED(); |
| 51 return; |
| 52 } |
| 53 engine_.Reset(engine); |
| 54 } |
| 55 |
| 56 private: |
| 57 ScopedJavaGlobalRef<jobject> engine_; |
| 58 }; |
| 59 |
| 60 void LeakEngine(jobject private_key) { |
| 61 static base::LazyInstance<KeystoreEngineWorkaround>::Leaky s_instance = |
| 62 LAZY_INSTANCE_INITIALIZER; |
| 63 s_instance.Get().LeakEngine(private_key); |
| 64 } |
| 65 |
| 66 android::AndroidRSA* GetLegacyRSAKey(jobject private_key) { |
| 67 const int kAndroid42ApiLevel = 17; |
| 68 |
| 69 if (base::android::BuildInfo::GetInstance()->sdk_int() >= |
| 70 kAndroid42ApiLevel) { |
| 71 return nullptr; |
| 72 } |
| 73 |
| 74 // Route around platform limitation: if Android < 4.2, then |
| 75 // base::android::RawSignDigestWithPrivateKey() cannot work, so try to get the |
| 76 // system OpenSSL's EVP_PKEY backing this PrivateKey object. |
| 77 android::AndroidEVP_PKEY* sys_pkey = |
| 78 android::GetOpenSSLSystemHandleForPrivateKey(private_key); |
| 79 if (sys_pkey == nullptr) |
| 80 return nullptr; |
| 81 |
| 82 if (sys_pkey->type != android::ANDROID_EVP_PKEY_RSA) { |
| 83 LOG(ERROR) << "Private key has wrong type!"; |
| 84 return nullptr; |
| 85 } |
| 86 |
| 87 android::AndroidRSA* sys_rsa = sys_pkey->pkey.rsa; |
| 88 if (sys_rsa->engine) { |
| 89 // |private_key| may not have an engine if the PrivateKey did not come |
| 90 // from the key store, such as in unit tests. |
| 91 if (strcmp(sys_rsa->engine->id, "keystore") == 0) { |
| 92 LeakEngine(private_key); |
| 93 } else { |
| 94 NOTREACHED(); |
| 95 } |
| 96 } |
| 97 |
| 98 return sys_rsa; |
| 99 } |
| 100 |
| 23 class SSLPlatformKeyAndroid : public ThreadedSSLPrivateKey::Delegate { | 101 class SSLPlatformKeyAndroid : public ThreadedSSLPrivateKey::Delegate { |
| 24 public: | 102 public: |
| 25 SSLPlatformKeyAndroid(crypto::ScopedEVP_PKEY key, SSLPrivateKey::Type type) | 103 SSLPlatformKeyAndroid(SSLPrivateKey::Type type, |
| 26 : key_(std::move(key)), type_(type) {} | 104 jobject key, |
| 105 size_t max_length) |
| 106 : type_(type), max_length_(max_length) { |
| 107 key_.Reset(nullptr, key); |
| 108 } |
| 27 | 109 |
| 28 ~SSLPlatformKeyAndroid() override {} | 110 ~SSLPlatformKeyAndroid() override {} |
| 29 | 111 |
| 30 SSLPrivateKey::Type GetType() override { return type_; } | 112 SSLPrivateKey::Type GetType() override { return type_; } |
| 31 | 113 |
| 32 std::vector<SSLPrivateKey::Hash> GetDigestPreferences() override { | 114 std::vector<SSLPrivateKey::Hash> GetDigestPreferences() override { |
| 33 static const SSLPrivateKey::Hash kHashes[] = { | 115 static const SSLPrivateKey::Hash kHashes[] = { |
| 34 SSLPrivateKey::Hash::SHA512, SSLPrivateKey::Hash::SHA384, | 116 SSLPrivateKey::Hash::SHA512, SSLPrivateKey::Hash::SHA384, |
| 35 SSLPrivateKey::Hash::SHA256, SSLPrivateKey::Hash::SHA1}; | 117 SSLPrivateKey::Hash::SHA256, SSLPrivateKey::Hash::SHA1}; |
| 36 return std::vector<SSLPrivateKey::Hash>(kHashes, | 118 return std::vector<SSLPrivateKey::Hash>(kHashes, |
| 37 kHashes + arraysize(kHashes)); | 119 kHashes + arraysize(kHashes)); |
| 38 } | 120 } |
| 39 | 121 |
| 40 size_t GetMaxSignatureLengthInBytes() override { | 122 size_t GetMaxSignatureLengthInBytes() override { return max_length_; } |
| 41 return EVP_PKEY_size(key_.get()); | |
| 42 } | |
| 43 | 123 |
| 44 Error SignDigest(SSLPrivateKey::Hash hash, | 124 Error SignDigest(SSLPrivateKey::Hash hash, |
| 45 const base::StringPiece& input, | 125 const base::StringPiece& input, |
| 46 std::vector<uint8_t>* signature) override { | 126 std::vector<uint8_t>* signature) override { |
| 47 crypto::ScopedEVP_PKEY_CTX ctx = | 127 const int kAndroid42ApiLevel = 17; |
| 48 crypto::ScopedEVP_PKEY_CTX(EVP_PKEY_CTX_new(key_.get(), NULL)); | 128 if (base::android::BuildInfo::GetInstance()->sdk_int() >= |
| 49 if (!ctx) | 129 kAndroid42ApiLevel) { |
| 50 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; | 130 if (!android::RawSignDigestWithPrivateKey(key_.obj(), input, signature)) { |
| 51 if (!EVP_PKEY_sign_init(ctx.get())) | 131 LOG(ERROR) << "Could not sign message"; |
| 52 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; | 132 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; |
| 53 | |
| 54 if (type_ == SSLPrivateKey::Type::RSA) { | |
| 55 const EVP_MD* digest = nullptr; | |
| 56 switch (hash) { | |
| 57 case SSLPrivateKey::Hash::MD5_SHA1: | |
| 58 digest = EVP_md5_sha1(); | |
| 59 break; | |
| 60 case SSLPrivateKey::Hash::SHA1: | |
| 61 digest = EVP_sha1(); | |
| 62 break; | |
| 63 case SSLPrivateKey::Hash::SHA256: | |
| 64 digest = EVP_sha256(); | |
| 65 break; | |
| 66 case SSLPrivateKey::Hash::SHA384: | |
| 67 digest = EVP_sha384(); | |
| 68 break; | |
| 69 case SSLPrivateKey::Hash::SHA512: | |
| 70 digest = EVP_sha512(); | |
| 71 break; | |
| 72 default: | |
| 73 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; | |
| 74 } | 133 } |
| 75 DCHECK(digest); | 134 return OK; |
| 76 if (!EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PADDING)) | |
| 77 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; | |
| 78 if (!EVP_PKEY_CTX_set_signature_md(ctx.get(), digest)) | |
| 79 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; | |
| 80 } | 135 } |
| 81 | 136 |
| 82 const uint8_t* input_ptr = reinterpret_cast<const uint8_t*>(input.data()); | 137 // Pre-4.2 Legacy Codepath |
| 83 size_t input_len = input.size(); | 138 android::AndroidRSA* legacy_rsa = GetLegacyRSAKey(key_.obj()); |
| 84 size_t sig_len = 0; | 139 signature->resize(max_length_); |
| 85 if (!EVP_PKEY_sign(ctx.get(), NULL, &sig_len, input_ptr, input_len)) | 140 int ret = legacy_rsa->meth->rsa_priv_enc( |
| 86 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; | 141 input.size(), reinterpret_cast<const uint8_t*>(input.data()), |
| 87 signature->resize(sig_len); | 142 signature->data(), legacy_rsa, android::ANDROID_RSA_PKCS1_PADDING); |
| 88 if (!EVP_PKEY_sign(ctx.get(), signature->data(), &sig_len, input_ptr, | 143 if (ret < 0) { |
| 89 input_len)) { | 144 // System OpenSSL will use a separate error queue, so it is still |
| 145 // necessary to push a new error. |
| 146 LOG(ERROR) << "Could not sign message with legacy RSA key"; |
| 90 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; | 147 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; |
| 91 } | 148 } |
| 92 | 149 signature->resize(ret); |
| 93 signature->resize(sig_len); | |
| 94 | |
| 95 return OK; | 150 return OK; |
| 96 } | 151 } |
| 97 | 152 |
| 98 private: | 153 private: |
| 99 crypto::ScopedEVP_PKEY key_; | |
| 100 SSLPrivateKey::Type type_; | 154 SSLPrivateKey::Type type_; |
| 155 ScopedJavaGlobalRef<jobject> key_; |
| 156 size_t max_length_; |
| 101 | 157 |
| 102 DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyAndroid); | 158 DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyAndroid); |
| 103 }; | 159 }; |
| 104 | 160 |
| 161 // VectorBignumSize returns the number of bytes needed to represent the bignum |
| 162 // given in |v|, i.e. the length of |v| less any leading zero bytes. |
| 163 size_t VectorBignumSize(const std::vector<uint8_t>& v) { |
| 164 size_t size = v.size(); |
| 165 // Ignore any leading zero bytes. |
| 166 for (size_t i = 0; i < v.size() && v[i] == 0; i++) { |
| 167 size--; |
| 168 } |
| 169 return size; |
| 170 } |
| 171 |
| 105 } // namespace | 172 } // namespace |
| 106 | 173 |
| 107 scoped_refptr<SSLPrivateKey> WrapOpenSSLPrivateKey(crypto::ScopedEVP_PKEY key) { | 174 scoped_refptr<SSLPrivateKey> WrapJavaPrivateKey(jobject key) { |
| 108 if (!key) | 175 if (!key) |
| 109 return nullptr; | 176 return nullptr; |
| 110 | 177 |
| 111 SSLPrivateKey::Type type; | 178 SSLPrivateKey::Type type; |
| 112 switch (EVP_PKEY_id(key.get())) { | 179 std::vector<uint8_t> key_params; |
| 113 case EVP_PKEY_RSA: | 180 switch (android::GetPrivateKeyType(key)) { |
| 181 case android::PRIVATE_KEY_TYPE_RSA: |
| 114 type = SSLPrivateKey::Type::RSA; | 182 type = SSLPrivateKey::Type::RSA; |
| 183 if (!android::GetRSAKeyModulus(key, &key_params)) { |
| 184 LOG(ERROR) << "Failed to get private key modulus"; |
| 185 return nullptr; |
| 186 } |
| 115 break; | 187 break; |
| 116 case EVP_PKEY_EC: | 188 case android::PRIVATE_KEY_TYPE_ECDSA: |
| 117 type = SSLPrivateKey::Type::ECDSA; | 189 type = SSLPrivateKey::Type::ECDSA; |
| 190 if (!android::GetECKeyOrder(key, &key_params)) { |
| 191 LOG(ERROR) << "Failed to get private key order"; |
| 192 return nullptr; |
| 193 } |
| 118 break; | 194 break; |
| 119 default: | 195 default: |
| 120 LOG(ERROR) << "Unknown key type: " << EVP_PKEY_id(key.get()); | 196 LOG(ERROR) << "Unknown key type: " << android::GetPrivateKeyType(key); |
| 121 return nullptr; | 197 return nullptr; |
| 122 } | 198 } |
| 123 return make_scoped_refptr(new ThreadedSSLPrivateKey( | 199 |
| 124 make_scoped_ptr(new SSLPlatformKeyAndroid(std::move(key), type)), | 200 return make_scoped_refptr( |
| 125 GetSSLPlatformKeyTaskRunner())); | 201 new ThreadedSSLPrivateKey(make_scoped_ptr(new SSLPlatformKeyAndroid( |
| 202 type, key, VectorBignumSize(key_params))), |
| 203 GetSSLPlatformKeyTaskRunner())); |
| 126 } | 204 } |
| 127 | 205 |
| 128 } // namespace net | 206 } // namespace net |
| OLD | NEW |