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 |