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.h" | 5 #include "net/ssl/ssl_platform_key_android.h" |
6 | 6 |
7 #include <openssl/digest.h> | 7 #include <openssl/ecdsa.h> |
8 #include <openssl/evp.h> | 8 #include <openssl/rsa.h> |
| 9 #include <strings.h> |
9 | 10 |
| 11 #include <memory> |
10 #include <utility> | 12 #include <utility> |
| 13 #include <vector> |
11 | 14 |
| 15 #include "base/android/build_info.h" |
| 16 #include "base/android/scoped_java_ref.h" |
| 17 #include "base/lazy_instance.h" |
12 #include "base/logging.h" | 18 #include "base/logging.h" |
13 #include "base/macros.h" | 19 #include "base/macros.h" |
14 #include "base/memory/ptr_util.h" | 20 #include "base/memory/ptr_util.h" |
15 #include "crypto/scoped_openssl_types.h" | 21 #include "crypto/scoped_openssl_types.h" |
| 22 #include "net/android/keystore.h" |
| 23 #include "net/android/legacy_openssl.h" |
16 #include "net/base/net_errors.h" | 24 #include "net/base/net_errors.h" |
17 #include "net/ssl/openssl_client_key_store.h" | 25 #include "net/ssl/openssl_client_key_store.h" |
| 26 #include "net/ssl/ssl_platform_key.h" |
18 #include "net/ssl/ssl_platform_key_task_runner.h" | 27 #include "net/ssl/ssl_platform_key_task_runner.h" |
19 #include "net/ssl/ssl_private_key.h" | |
20 #include "net/ssl/threaded_ssl_private_key.h" | 28 #include "net/ssl/threaded_ssl_private_key.h" |
21 | 29 |
| 30 using base::android::JavaRef; |
| 31 using base::android::ScopedJavaGlobalRef; |
| 32 using base::android::ScopedJavaLocalRef; |
| 33 |
22 namespace net { | 34 namespace net { |
23 | 35 |
24 namespace { | 36 namespace { |
25 | 37 |
| 38 // On Android < 4.2, the libkeystore.so ENGINE uses CRYPTO_EX_DATA and is not |
| 39 // added to the global engine list. If all references to it are dropped, OpenSSL |
| 40 // will dlclose the module, leaving a dangling function pointer in the RSA |
| 41 // CRYPTO_EX_DATA class. To work around this, leak an extra reference to the |
| 42 // ENGINE we extract in GetRsaLegacyKey. |
| 43 // |
| 44 // In 4.2, this change avoids the problem: |
| 45 // https://android.googlesource.com/platform/libcore/+/106a8928fb4249f2f3d4dba1d
ddbe73ca5cb3d61 |
| 46 // |
| 47 // https://crbug.com/381465 |
| 48 class KeystoreEngineWorkaround { |
| 49 public: |
| 50 KeystoreEngineWorkaround() {} |
| 51 |
| 52 void LeakEngine(const JavaRef<jobject>& key) { |
| 53 if (!engine_.is_null()) |
| 54 return; |
| 55 ScopedJavaLocalRef<jobject> engine = |
| 56 android::GetOpenSSLEngineForPrivateKey(key); |
| 57 if (engine.is_null()) { |
| 58 NOTREACHED(); |
| 59 return; |
| 60 } |
| 61 engine_.Reset(engine); |
| 62 } |
| 63 |
| 64 private: |
| 65 ScopedJavaGlobalRef<jobject> engine_; |
| 66 }; |
| 67 |
| 68 void LeakEngine(const JavaRef<jobject>& private_key) { |
| 69 static base::LazyInstance<KeystoreEngineWorkaround>::Leaky s_instance = |
| 70 LAZY_INSTANCE_INITIALIZER; |
| 71 s_instance.Get().LeakEngine(private_key); |
| 72 } |
| 73 |
26 class SSLPlatformKeyAndroid : public ThreadedSSLPrivateKey::Delegate { | 74 class SSLPlatformKeyAndroid : public ThreadedSSLPrivateKey::Delegate { |
27 public: | 75 public: |
28 SSLPlatformKeyAndroid(crypto::ScopedEVP_PKEY key, SSLPrivateKey::Type type) | 76 SSLPlatformKeyAndroid(SSLPrivateKey::Type type, |
29 : key_(std::move(key)), type_(type) {} | 77 const JavaRef<jobject>& key, |
| 78 size_t max_length, |
| 79 android::AndroidRSA* legacy_rsa) |
| 80 : type_(type), max_length_(max_length), legacy_rsa_(legacy_rsa) { |
| 81 key_.Reset(key); |
| 82 } |
30 | 83 |
31 ~SSLPlatformKeyAndroid() override {} | 84 ~SSLPlatformKeyAndroid() override {} |
32 | 85 |
33 SSLPrivateKey::Type GetType() override { return type_; } | 86 SSLPrivateKey::Type GetType() override { return type_; } |
34 | 87 |
35 std::vector<SSLPrivateKey::Hash> GetDigestPreferences() override { | 88 std::vector<SSLPrivateKey::Hash> GetDigestPreferences() override { |
36 static const SSLPrivateKey::Hash kHashes[] = { | 89 static const SSLPrivateKey::Hash kHashes[] = { |
37 SSLPrivateKey::Hash::SHA512, SSLPrivateKey::Hash::SHA384, | 90 SSLPrivateKey::Hash::SHA512, SSLPrivateKey::Hash::SHA384, |
38 SSLPrivateKey::Hash::SHA256, SSLPrivateKey::Hash::SHA1}; | 91 SSLPrivateKey::Hash::SHA256, SSLPrivateKey::Hash::SHA1}; |
39 return std::vector<SSLPrivateKey::Hash>(kHashes, | 92 return std::vector<SSLPrivateKey::Hash>(kHashes, |
40 kHashes + arraysize(kHashes)); | 93 kHashes + arraysize(kHashes)); |
41 } | 94 } |
42 | 95 |
43 size_t GetMaxSignatureLengthInBytes() override { | 96 size_t GetMaxSignatureLengthInBytes() override { return max_length_; } |
44 return EVP_PKEY_size(key_.get()); | |
45 } | |
46 | 97 |
47 Error SignDigest(SSLPrivateKey::Hash hash, | 98 Error SignDigest(SSLPrivateKey::Hash hash, |
48 const base::StringPiece& input, | 99 const base::StringPiece& input_in, |
49 std::vector<uint8_t>* signature) override { | 100 std::vector<uint8_t>* signature) override { |
50 crypto::ScopedEVP_PKEY_CTX ctx = | 101 base::StringPiece input = input_in; |
51 crypto::ScopedEVP_PKEY_CTX(EVP_PKEY_CTX_new(key_.get(), NULL)); | |
52 if (!ctx) | |
53 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; | |
54 if (!EVP_PKEY_sign_init(ctx.get())) | |
55 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; | |
56 | 102 |
| 103 // Prepend the DigestInfo for RSA. |
| 104 crypto::ScopedOpenSSLBytes digest_info_storage; |
57 if (type_ == SSLPrivateKey::Type::RSA) { | 105 if (type_ == SSLPrivateKey::Type::RSA) { |
58 const EVP_MD* digest = nullptr; | 106 int hash_nid = NID_undef; |
59 switch (hash) { | 107 switch (hash) { |
60 case SSLPrivateKey::Hash::MD5_SHA1: | 108 case SSLPrivateKey::Hash::MD5_SHA1: |
61 digest = EVP_md5_sha1(); | 109 hash_nid = NID_md5_sha1; |
62 break; | 110 break; |
63 case SSLPrivateKey::Hash::SHA1: | 111 case SSLPrivateKey::Hash::SHA1: |
64 digest = EVP_sha1(); | 112 hash_nid = NID_sha1; |
65 break; | 113 break; |
66 case SSLPrivateKey::Hash::SHA256: | 114 case SSLPrivateKey::Hash::SHA256: |
67 digest = EVP_sha256(); | 115 hash_nid = NID_sha256; |
68 break; | 116 break; |
69 case SSLPrivateKey::Hash::SHA384: | 117 case SSLPrivateKey::Hash::SHA384: |
70 digest = EVP_sha384(); | 118 hash_nid = NID_sha384; |
71 break; | 119 break; |
72 case SSLPrivateKey::Hash::SHA512: | 120 case SSLPrivateKey::Hash::SHA512: |
73 digest = EVP_sha512(); | 121 hash_nid = NID_sha512; |
74 break; | 122 break; |
75 default: | |
76 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; | |
77 } | 123 } |
78 DCHECK(digest); | 124 DCHECK_NE(NID_undef, hash_nid); |
79 if (!EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PADDING)) | 125 |
| 126 uint8_t* digest_info; |
| 127 size_t digest_info_len; |
| 128 int is_alloced; |
| 129 if (!RSA_add_pkcs1_prefix( |
| 130 &digest_info, &digest_info_len, &is_alloced, hash_nid, |
| 131 reinterpret_cast<const uint8_t*>(input.data()), input.size())) { |
80 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; | 132 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; |
81 if (!EVP_PKEY_CTX_set_signature_md(ctx.get(), digest)) | 133 } |
82 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; | 134 |
| 135 if (is_alloced) |
| 136 digest_info_storage.reset(digest_info); |
| 137 input = base::StringPiece(reinterpret_cast<const char*>(digest_info), |
| 138 digest_info_len); |
83 } | 139 } |
84 | 140 |
85 const uint8_t* input_ptr = reinterpret_cast<const uint8_t*>(input.data()); | 141 // Pre-4.2 legacy codepath. |
86 size_t input_len = input.size(); | 142 if (legacy_rsa_) { |
87 size_t sig_len = 0; | 143 signature->resize(max_length_); |
88 if (!EVP_PKEY_sign(ctx.get(), NULL, &sig_len, input_ptr, input_len)) | 144 int ret = legacy_rsa_->meth->rsa_priv_enc( |
89 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; | 145 input.size(), reinterpret_cast<const uint8_t*>(input.data()), |
90 signature->resize(sig_len); | 146 signature->data(), legacy_rsa_, android::ANDROID_RSA_PKCS1_PADDING); |
91 if (!EVP_PKEY_sign(ctx.get(), signature->data(), &sig_len, input_ptr, | 147 if (ret < 0) { |
92 input_len)) { | 148 LOG(WARNING) << "Could not sign message with legacy RSA key!"; |
| 149 // System OpenSSL will use a separate error queue, so it is still |
| 150 // necessary to push a new error. |
| 151 // |
| 152 // TODO(davidben): It would be good to also clear the system error queue |
| 153 // if there were some way to convince Java to do it. (Without going |
| 154 // through Java, it's difficult to get a handle on a system OpenSSL |
| 155 // function; dlopen loads a second copy.) |
| 156 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; |
| 157 } |
| 158 signature->resize(ret); |
| 159 return OK; |
| 160 } |
| 161 |
| 162 if (!android::RawSignDigestWithPrivateKey(key_, input, signature)) { |
| 163 LOG(WARNING) << "Could not sign message with private key!"; |
93 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; | 164 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; |
94 } | 165 } |
95 | |
96 signature->resize(sig_len); | |
97 | |
98 return OK; | 166 return OK; |
99 } | 167 } |
100 | 168 |
101 private: | 169 private: |
102 crypto::ScopedEVP_PKEY key_; | |
103 SSLPrivateKey::Type type_; | 170 SSLPrivateKey::Type type_; |
| 171 ScopedJavaGlobalRef<jobject> key_; |
| 172 size_t max_length_; |
| 173 android::AndroidRSA* legacy_rsa_; |
104 | 174 |
105 DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyAndroid); | 175 DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyAndroid); |
106 }; | 176 }; |
107 | 177 |
108 scoped_refptr<SSLPrivateKey> WrapOpenSSLPrivateKey(crypto::ScopedEVP_PKEY key) { | 178 // VectorBignumSize returns the number of bytes needed to represent the bignum |
109 if (!key) | 179 // given in |v|, i.e. the length of |v| less any leading zero bytes. |
| 180 size_t VectorBignumSize(const std::vector<uint8_t>& v) { |
| 181 size_t size = v.size(); |
| 182 // Ignore any leading zero bytes. |
| 183 for (size_t i = 0; i < v.size() && v[i] == 0; i++) { |
| 184 size--; |
| 185 } |
| 186 return size; |
| 187 } |
| 188 |
| 189 std::unique_ptr<SSLPlatformKeyAndroid> CreateRsaKey( |
| 190 const JavaRef<jobject>& key) { |
| 191 android::AndroidRSA* sys_rsa = nullptr; |
| 192 const int kAndroid42ApiLevel = 17; |
| 193 if (base::android::BuildInfo::GetInstance()->sdk_int() < kAndroid42ApiLevel) { |
| 194 // Route around platform limitations: if Android < 4.2, then |
| 195 // base::android::RawSignDigestWithPrivateKey() cannot work, so try to get |
| 196 // the system OpenSSL's EVP_PKEY backing this PrivateKey object. |
| 197 android::AndroidEVP_PKEY* sys_pkey = |
| 198 android::GetOpenSSLSystemHandleForPrivateKey(key); |
| 199 if (!sys_pkey) |
| 200 return nullptr; |
| 201 |
| 202 if (sys_pkey->type != android::ANDROID_EVP_PKEY_RSA) { |
| 203 LOG(ERROR) << "Private key has wrong type!"; |
| 204 return nullptr; |
| 205 } |
| 206 |
| 207 sys_rsa = sys_pkey->pkey.rsa; |
| 208 if (sys_rsa->engine) { |
| 209 // |private_key| may not have an engine if the PrivateKey did not come |
| 210 // from the key store, such as in unit tests. |
| 211 if (strcmp(sys_rsa->engine->id, "keystore") == 0) { |
| 212 LeakEngine(key); |
| 213 } else { |
| 214 NOTREACHED(); |
| 215 } |
| 216 } |
| 217 } |
| 218 |
| 219 std::vector<uint8_t> modulus; |
| 220 if (!android::GetRSAKeyModulus(key, &modulus)) { |
| 221 LOG(ERROR) << "Failed to get private key modulus"; |
110 return nullptr; | 222 return nullptr; |
| 223 } |
111 | 224 |
112 SSLPrivateKey::Type type; | 225 return base::MakeUnique<SSLPlatformKeyAndroid>( |
113 switch (EVP_PKEY_id(key.get())) { | 226 SSLPrivateKey::Type::RSA, key, VectorBignumSize(modulus), sys_rsa); |
114 case EVP_PKEY_RSA: | 227 } |
115 type = SSLPrivateKey::Type::RSA; | 228 |
116 break; | 229 std::unique_ptr<SSLPlatformKeyAndroid> CreateEcdsaKey( |
117 case EVP_PKEY_EC: | 230 const JavaRef<jobject>& key) { |
118 type = SSLPrivateKey::Type::ECDSA; | 231 std::vector<uint8_t> order; |
119 break; | 232 if (!android::GetECKeyOrder(key, &order)) { |
120 default: | 233 LOG(ERROR) << "Can't extract order parameter from EC private key"; |
121 LOG(ERROR) << "Unknown key type: " << EVP_PKEY_id(key.get()); | 234 return nullptr; |
122 return nullptr; | |
123 } | 235 } |
124 return make_scoped_refptr(new ThreadedSSLPrivateKey( | 236 |
125 base::WrapUnique(new SSLPlatformKeyAndroid(std::move(key), type)), | 237 return base::MakeUnique<SSLPlatformKeyAndroid>( |
126 GetSSLPlatformKeyTaskRunner())); | 238 SSLPrivateKey::Type::ECDSA, key, |
| 239 ECDSA_SIG_max_len(VectorBignumSize(order)), nullptr); |
127 } | 240 } |
128 | 241 |
129 } // namespace | 242 } // namespace |
130 | 243 |
| 244 scoped_refptr<SSLPrivateKey> WrapJavaPrivateKey(const JavaRef<jobject>& key) { |
| 245 std::unique_ptr<SSLPlatformKeyAndroid> delegate; |
| 246 switch (android::GetPrivateKeyType(key)) { |
| 247 case android::PRIVATE_KEY_TYPE_RSA: |
| 248 delegate = CreateRsaKey(key); |
| 249 break; |
| 250 case android::PRIVATE_KEY_TYPE_ECDSA: |
| 251 delegate = CreateEcdsaKey(key); |
| 252 break; |
| 253 default: |
| 254 LOG(WARNING) << "GetPrivateKeyType() returned invalid type"; |
| 255 return nullptr; |
| 256 } |
| 257 |
| 258 return make_scoped_refptr(new ThreadedSSLPrivateKey( |
| 259 std::move(delegate), GetSSLPlatformKeyTaskRunner())); |
| 260 } |
| 261 |
131 scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey( | 262 scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey( |
132 X509Certificate* certificate) { | 263 X509Certificate* certificate) { |
133 crypto::ScopedEVP_PKEY key = | 264 return OpenSSLClientKeyStore::GetInstance()->FetchClientCertPrivateKey( |
134 OpenSSLClientKeyStore::GetInstance()->FetchClientCertPrivateKey( | 265 certificate); |
135 certificate); | |
136 return WrapOpenSSLPrivateKey(std::move(key)); | |
137 } | 266 } |
138 | 267 |
139 } // namespace net | 268 } // namespace net |
OLD | NEW |