OLD | NEW |
---|---|
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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/android/keystore_openssl.h" | 5 #include "net/android/keystore_openssl.h" |
6 | 6 |
7 #include <jni.h> | 7 #include <jni.h> |
8 #include <openssl/bn.h> | 8 #include <openssl/bn.h> |
9 // This include is required to get the ECDSA_METHOD structure definition | 9 // This include is required to get the ECDSA_METHOD structure definition |
10 // which isn't currently part of the OpenSSL official ABI. This should | 10 // which isn't currently part of the OpenSSL official ABI. This should |
11 // not be a concern for Chromium which always links against its own | 11 // not be a concern for Chromium which always links against its own |
12 // version of the library on Android. | 12 // version of the library on Android. |
13 #include <openssl/crypto/ecdsa/ecs_locl.h> | 13 #include <openssl/crypto/ecdsa/ecs_locl.h> |
14 // And this one is needed for the EC_GROUP definition. | 14 // And this one is needed for the EC_GROUP definition. |
15 #include <openssl/crypto/ec/ec_lcl.h> | 15 #include <openssl/crypto/ec/ec_lcl.h> |
16 #include <openssl/dsa.h> | 16 #include <openssl/dsa.h> |
17 #include <openssl/ec.h> | 17 #include <openssl/ec.h> |
18 #include <openssl/engine.h> | 18 #include <openssl/engine.h> |
19 #include <openssl/evp.h> | 19 #include <openssl/evp.h> |
20 #include <openssl/rsa.h> | 20 #include <openssl/rsa.h> |
21 | 21 |
22 #include "base/android/build_info.h" | 22 #include "base/android/build_info.h" |
23 #include "base/android/jni_android.h" | 23 #include "base/android/jni_android.h" |
24 #include "base/android/scoped_java_ref.h" | 24 #include "base/android/scoped_java_ref.h" |
25 #include "base/basictypes.h" | 25 #include "base/basictypes.h" |
26 #include "base/lazy_instance.h" | 26 #include "base/lazy_instance.h" |
27 #include "base/logging.h" | 27 #include "base/logging.h" |
28 #include "crypto/openssl_util.h" | 28 #include "crypto/openssl_util.h" |
29 #include "net/android/keystore.h" | 29 #include "net/android/keystore.h" |
30 #include "net/android/legacy_openssl.h" | |
30 #include "net/ssl/ssl_client_cert_type.h" | 31 #include "net/ssl/ssl_client_cert_type.h" |
31 | 32 |
32 // IMPORTANT NOTE: The following code will currently only work when used | 33 // IMPORTANT NOTE: The following code will currently only work when used |
33 // to implement client certificate support with OpenSSL. That's because | 34 // to implement client certificate support with OpenSSL. That's because |
34 // only the signing operations used in this use case are implemented here. | 35 // only the signing operations used in this use case are implemented here. |
35 // | 36 // |
36 // Generally speaking, OpenSSL provides many different ways to sign | 37 // Generally speaking, OpenSSL provides many different ways to sign |
37 // digests. This code doesn't support all these cases, only the ones that | 38 // digests. This code doesn't support all these cases, only the ones that |
38 // are required to sign the digest during the OpenSSL handshake for TLS. | 39 // are required to sign the digest during the OpenSSL handshake for TLS. |
39 // | 40 // |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
88 // DSA_size() and ECDSA_size() work properly with the wrapper EVP_PKEY. | 89 // DSA_size() and ECDSA_size() work properly with the wrapper EVP_PKEY. |
89 // | 90 // |
90 // Note that there is no need to define an OpenSSL ENGINE here. These | 91 // Note that there is no need to define an OpenSSL ENGINE here. These |
91 // are objects that can be used to expose custom methods (i.e. either | 92 // are objects that can be used to expose custom methods (i.e. either |
92 // RSA_METHOD, DSA_METHOD, ECDSA_METHOD, and a large number of other ones | 93 // RSA_METHOD, DSA_METHOD, ECDSA_METHOD, and a large number of other ones |
93 // for types not related to this source file), and make them used by | 94 // for types not related to this source file), and make them used by |
94 // default for a lot of operations. Very fortunately, this is not needed | 95 // default for a lot of operations. Very fortunately, this is not needed |
95 // here, which saves a lot of complexity. | 96 // here, which saves a lot of complexity. |
96 | 97 |
97 using base::android::ScopedJavaGlobalRef; | 98 using base::android::ScopedJavaGlobalRef; |
99 using base::android::ScopedJavaLocalRef; | |
98 | 100 |
99 namespace net { | 101 namespace net { |
100 namespace android { | 102 namespace android { |
101 | 103 |
102 namespace { | 104 namespace { |
103 | 105 |
104 typedef crypto::ScopedOpenSSL<EVP_PKEY, EVP_PKEY_free> ScopedEVP_PKEY; | 106 typedef crypto::ScopedOpenSSL<EVP_PKEY, EVP_PKEY_free> ScopedEVP_PKEY; |
105 typedef crypto::ScopedOpenSSL<RSA, RSA_free> ScopedRSA; | 107 typedef crypto::ScopedOpenSSL<RSA, RSA_free> ScopedRSA; |
106 typedef crypto::ScopedOpenSSL<DSA, DSA_free> ScopedDSA; | 108 typedef crypto::ScopedOpenSSL<DSA, DSA_free> ScopedDSA; |
107 typedef crypto::ScopedOpenSSL<EC_KEY, EC_KEY_free> ScopedEC_KEY; | 109 typedef crypto::ScopedOpenSSL<EC_KEY, EC_KEY_free> ScopedEC_KEY; |
108 typedef crypto::ScopedOpenSSL<EC_GROUP, EC_GROUP_free> ScopedEC_GROUP; | 110 typedef crypto::ScopedOpenSSL<EC_GROUP, EC_GROUP_free> ScopedEC_GROUP; |
109 | 111 |
110 // Custom RSA_METHOD that uses the platform APIs. | 112 // Custom RSA_METHOD that uses the platform APIs. |
111 // Note that for now, only signing through RSA_sign() is really supported. | 113 // Note that for now, only signing through RSA_sign() is really supported. |
112 // all other method pointers are either stubs returning errors, or no-ops. | 114 // all other method pointers are either stubs returning errors, or no-ops. |
113 // See <openssl/rsa.h> for exact declaration of RSA_METHOD. | 115 // See <openssl/rsa.h> for exact declaration of RSA_METHOD. |
114 | 116 |
117 struct RsaAppData { | |
118 jobject private_key; | |
119 AndroidRSA* legacy_rsa; | |
120 }; | |
121 | |
115 int RsaMethodPubEnc(int flen, | 122 int RsaMethodPubEnc(int flen, |
116 const unsigned char* from, | 123 const unsigned char* from, |
117 unsigned char* to, | 124 unsigned char* to, |
118 RSA* rsa, | 125 RSA* rsa, |
119 int padding) { | 126 int padding) { |
120 NOTIMPLEMENTED(); | 127 NOTIMPLEMENTED(); |
121 RSAerr(RSA_F_RSA_PUBLIC_ENCRYPT, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED); | 128 RSAerr(RSA_F_RSA_PUBLIC_ENCRYPT, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED); |
122 return -1; | 129 return -1; |
123 } | 130 } |
124 | 131 |
(...skipping 22 matching lines...) Expand all Loading... | |
147 // "RSA/ECB/NoPadding" or "RSA/ECB/PKCS1Padding" transformation as | 154 // "RSA/ECB/NoPadding" or "RSA/ECB/PKCS1Padding" transformation as |
148 // appropriate. I believe support for both of these was added in | 155 // appropriate. I believe support for both of these was added in |
149 // the same Android version as the "NONEwithRSA" | 156 // the same Android version as the "NONEwithRSA" |
150 // java.security.Signature algorithm, so the same version checks | 157 // java.security.Signature algorithm, so the same version checks |
151 // for GetRsaLegacyKey should work. | 158 // for GetRsaLegacyKey should work. |
152 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE); | 159 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE); |
153 return -1; | 160 return -1; |
154 } | 161 } |
155 | 162 |
156 // Retrieve private key JNI reference. | 163 // Retrieve private key JNI reference. |
157 jobject private_key = reinterpret_cast<jobject>(RSA_get_app_data(rsa)); | 164 RsaAppData* app_data = static_cast<RsaAppData*>(RSA_get_app_data(rsa)); |
158 if (!private_key) { | 165 if (!app_data || !app_data->private_key) { |
159 LOG(WARNING) << "Null JNI reference passed to RsaMethodPrivEnc!"; | 166 LOG(WARNING) << "Null JNI reference passed to RsaMethodPrivEnc!"; |
160 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); | 167 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); |
161 return -1; | 168 return -1; |
162 } | 169 } |
163 | 170 |
171 // Pre-4.2 legacy codepath. | |
172 if (app_data->legacy_rsa) { | |
173 int ret = app_data->legacy_rsa->meth->rsa_priv_enc( | |
174 flen, from, to, app_data->legacy_rsa, ANDROID_RSA_PKCS1_PADDING); | |
175 if (ret < 0) { | |
176 LOG(WARNING) << "Could not sign message in RsaMethodPrivEnc!"; | |
177 // System OpenSSL will use a separate error queue, so it is still | |
178 // necessary to push a new error. | |
179 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); | |
agl
2014/07/10 16:33:44
Do we need to clear the system's error queue?
davidben
2014/07/10 21:47:07
Added a TODO, but doing so seems to be difficult.
| |
180 return -1; | |
181 } | |
182 return ret; | |
183 } | |
184 | |
164 base::StringPiece from_piece(reinterpret_cast<const char*>(from), flen); | 185 base::StringPiece from_piece(reinterpret_cast<const char*>(from), flen); |
165 std::vector<uint8> result; | 186 std::vector<uint8> result; |
166 // For RSA keys, this function behaves as RSA_private_encrypt with | 187 // For RSA keys, this function behaves as RSA_private_encrypt with |
167 // PKCS#1 padding. | 188 // PKCS#1 padding. |
168 if (!RawSignDigestWithPrivateKey(private_key, from_piece, &result)) { | 189 if (!RawSignDigestWithPrivateKey(app_data->private_key, |
190 from_piece, &result)) { | |
169 LOG(WARNING) << "Could not sign message in RsaMethodPrivEnc!"; | 191 LOG(WARNING) << "Could not sign message in RsaMethodPrivEnc!"; |
170 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); | 192 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); |
171 return -1; | 193 return -1; |
172 } | 194 } |
173 | 195 |
174 size_t expected_size = static_cast<size_t>(RSA_size(rsa)); | 196 size_t expected_size = static_cast<size_t>(RSA_size(rsa)); |
175 if (result.size() > expected_size) { | 197 if (result.size() > expected_size) { |
176 LOG(ERROR) << "RSA Signature size mismatch, actual: " | 198 LOG(ERROR) << "RSA Signature size mismatch, actual: " |
177 << result.size() << ", expected <= " << expected_size; | 199 << result.size() << ", expected <= " << expected_size; |
178 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); | 200 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); |
(...skipping 19 matching lines...) Expand all Loading... | |
198 return -1; | 220 return -1; |
199 } | 221 } |
200 | 222 |
201 int RsaMethodInit(RSA* rsa) { | 223 int RsaMethodInit(RSA* rsa) { |
202 return 0; | 224 return 0; |
203 } | 225 } |
204 | 226 |
205 int RsaMethodFinish(RSA* rsa) { | 227 int RsaMethodFinish(RSA* rsa) { |
206 // Ensure the global JNI reference created with this wrapper is | 228 // Ensure the global JNI reference created with this wrapper is |
207 // properly destroyed with it. | 229 // properly destroyed with it. |
208 jobject key = reinterpret_cast<jobject>(RSA_get_app_data(rsa)); | 230 RsaAppData* app_data = static_cast<RsaAppData*>(RSA_get_app_data(rsa)); |
209 if (key != NULL) { | 231 if (app_data != NULL) { |
210 RSA_set_app_data(rsa, NULL); | 232 RSA_set_app_data(rsa, NULL); |
211 ReleaseKey(key); | 233 ReleaseKey(app_data->private_key); |
234 delete app_data; | |
212 } | 235 } |
213 // Actual return value is ignored by OpenSSL. There are no docs | 236 // Actual return value is ignored by OpenSSL. There are no docs |
214 // explaining what this is supposed to be. | 237 // explaining what this is supposed to be. |
215 return 0; | 238 return 0; |
216 } | 239 } |
217 | 240 |
218 const RSA_METHOD android_rsa_method = { | 241 const RSA_METHOD android_rsa_method = { |
219 /* .name = */ "Android signing-only RSA method", | 242 /* .name = */ "Android signing-only RSA method", |
220 /* .rsa_pub_enc = */ RsaMethodPubEnc, | 243 /* .rsa_pub_enc = */ RsaMethodPubEnc, |
221 /* .rsa_pub_dec = */ RsaMethodPubDec, | 244 /* .rsa_pub_dec = */ RsaMethodPubDec, |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
267 old_num); | 290 old_num); |
268 if (new_num == NULL) | 291 if (new_num == NULL) |
269 return false; | 292 return false; |
270 | 293 |
271 if (old_num == NULL) | 294 if (old_num == NULL) |
272 *num_ptr = new_num; | 295 *num_ptr = new_num; |
273 return true; | 296 return true; |
274 } | 297 } |
275 | 298 |
276 // Setup an EVP_PKEY to wrap an existing platform RSA PrivateKey object. | 299 // Setup an EVP_PKEY to wrap an existing platform RSA PrivateKey object. |
277 // |private_key| is the JNI reference (local or global) to the object. | 300 // |private_key| is the JNI reference (local or global) to the object. |
agl
2014/07/10 16:33:44
Probably needs to mention |legacy_rsa|.
davidben
2014/07/10 21:47:07
Done.
| |
278 // |pkey| is the EVP_PKEY to setup as a wrapper. | 301 // |pkey| is the EVP_PKEY to setup as a wrapper. |
279 // Returns true on success, false otherwise. | 302 // Returns true on success, false otherwise. |
280 // On success, this creates a new global JNI reference to the object | 303 // On success, this creates a new global JNI reference to the object |
281 // that is owned by and destroyed with the EVP_PKEY. I.e. caller can | 304 // that is owned by and destroyed with the EVP_PKEY. I.e. caller can |
282 // free |private_key| after the call. | 305 // free |private_key| after the call. |
283 // IMPORTANT: The EVP_PKEY will *only* work on Android >= 4.2. For older | 306 // IMPORTANT: The EVP_PKEY will *only* work on Android >= 4.2. For older |
284 // platforms, use GetRsaLegacyKey() instead. | 307 // platforms, use GetRsaLegacyKey() instead. |
285 bool GetRsaPkeyWrapper(jobject private_key, EVP_PKEY* pkey) { | 308 bool GetRsaPkeyWrapper(jobject private_key, |
309 AndroidRSA* legacy_rsa, | |
310 EVP_PKEY* pkey) { | |
286 ScopedRSA rsa(RSA_new()); | 311 ScopedRSA rsa(RSA_new()); |
287 RSA_set_method(rsa.get(), &android_rsa_method); | 312 RSA_set_method(rsa.get(), &android_rsa_method); |
288 | 313 |
289 // HACK: RSA_size() doesn't work with custom RSA_METHODs. To ensure that | 314 // HACK: RSA_size() doesn't work with custom RSA_METHODs. To ensure that |
290 // it will return the right value, set the 'n' field of the RSA object | 315 // it will return the right value, set the 'n' field of the RSA object |
291 // to match the private key's modulus. | 316 // to match the private key's modulus. |
317 // | |
318 // TODO(davidben): After switching to BoringSSL, consider making RSA_size call | |
319 // into an RSA_METHOD hook. | |
292 std::vector<uint8> modulus; | 320 std::vector<uint8> modulus; |
293 if (!GetRSAKeyModulus(private_key, &modulus)) { | 321 if (!GetRSAKeyModulus(private_key, &modulus)) { |
294 LOG(ERROR) << "Failed to get private key modulus"; | 322 LOG(ERROR) << "Failed to get private key modulus"; |
295 return false; | 323 return false; |
296 } | 324 } |
297 if (!SwapBigNumPtrFromBytes(modulus, &rsa.get()->n)) { | 325 if (!SwapBigNumPtrFromBytes(modulus, &rsa.get()->n)) { |
298 LOG(ERROR) << "Failed to decode private key modulus"; | 326 LOG(ERROR) << "Failed to decode private key modulus"; |
299 return false; | 327 return false; |
300 } | 328 } |
301 | 329 |
302 ScopedJavaGlobalRef<jobject> global_key; | 330 ScopedJavaGlobalRef<jobject> global_key; |
303 global_key.Reset(NULL, private_key); | 331 global_key.Reset(NULL, private_key); |
304 if (global_key.is_null()) { | 332 if (global_key.is_null()) { |
305 LOG(ERROR) << "Could not create global JNI reference"; | 333 LOG(ERROR) << "Could not create global JNI reference"; |
306 return false; | 334 return false; |
307 } | 335 } |
308 RSA_set_app_data(rsa.get(), global_key.Release()); | 336 RsaAppData* app_data = new RsaAppData(); |
337 app_data->private_key = global_key.Release(); | |
338 app_data->legacy_rsa = legacy_rsa; | |
339 RSA_set_app_data(rsa.get(), app_data); | |
309 EVP_PKEY_assign_RSA(pkey, rsa.release()); | 340 EVP_PKEY_assign_RSA(pkey, rsa.release()); |
310 return true; | 341 return true; |
311 } | 342 } |
312 | 343 |
313 // On Android < 4.2, the libkeystore.so ENGINE uses CRYPTO_EX_DATA and is not | 344 // On Android < 4.2, the libkeystore.so ENGINE uses CRYPTO_EX_DATA and is not |
314 // added to the global engine list. If all references to it are dropped, OpenSSL | 345 // added to the global engine list. If all references to it are dropped, OpenSSL |
315 // will dlclose the module, leaving a dangling function pointer in the RSA | 346 // will dlclose the module, leaving a dangling function pointer in the RSA |
316 // CRYPTO_EX_DATA class. To work around this, leak an extra reference to the | 347 // CRYPTO_EX_DATA class. To work around this, leak an extra reference to the |
317 // ENGINE we extract in GetRsaLegacyKey. | 348 // ENGINE we extract in GetRsaLegacyKey. |
318 // | 349 // |
319 // In 4.2, this change avoids the problem: | 350 // In 4.2, this change avoids the problem: |
320 // https://android.googlesource.com/platform/libcore/+/106a8928fb4249f2f3d4dba1d ddbe73ca5cb3d61 | 351 // https://android.googlesource.com/platform/libcore/+/106a8928fb4249f2f3d4dba1d ddbe73ca5cb3d61 |
321 // | 352 // |
322 // https://crbug.com/381465 | 353 // https://crbug.com/381465 |
323 class KeystoreEngineWorkaround { | 354 class KeystoreEngineWorkaround { |
324 public: | 355 public: |
325 KeystoreEngineWorkaround() : leaked_engine_(false) {} | 356 KeystoreEngineWorkaround() {} |
326 | 357 |
327 void LeakRsaEngine(EVP_PKEY* pkey) { | 358 void LeakEngine(jobject private_key) { |
328 if (leaked_engine_) | 359 if (!engine_.is_null()) |
329 return; | 360 return; |
330 ScopedRSA rsa(EVP_PKEY_get1_RSA(pkey)); | 361 ScopedJavaLocalRef<jobject> engine = |
331 if (!rsa.get() || | 362 GetOpenSSLEngineForPrivateKey(private_key); |
332 !rsa.get()->engine || | 363 if (engine.is_null()) { |
333 strcmp(ENGINE_get_id(rsa.get()->engine), "keystore") || | |
334 !ENGINE_init(rsa.get()->engine)) { | |
335 NOTREACHED(); | 364 NOTREACHED(); |
336 return; | 365 return; |
337 } | 366 } |
338 leaked_engine_ = true; | 367 engine_.Reset(engine); |
339 } | 368 } |
340 | 369 |
341 private: | 370 private: |
342 bool leaked_engine_; | 371 ScopedJavaGlobalRef<jobject> engine_; |
343 }; | 372 }; |
344 | 373 |
345 void LeakRsaEngine(EVP_PKEY* pkey) { | 374 void LeakEngine(jobject private_key) { |
346 static base::LazyInstance<KeystoreEngineWorkaround>::Leaky s_instance = | 375 static base::LazyInstance<KeystoreEngineWorkaround>::Leaky s_instance = |
347 LAZY_INSTANCE_INITIALIZER; | 376 LAZY_INSTANCE_INITIALIZER; |
348 s_instance.Get().LeakRsaEngine(pkey); | 377 s_instance.Get().LeakEngine(private_key); |
349 } | 378 } |
350 | 379 |
351 // Setup an EVP_PKEY to wrap an existing platform RSA PrivateKey object | 380 // Setup an EVP_PKEY to wrap an existing platform RSA PrivateKey object |
352 // for Android 4.0 to 4.1.x. Must only be used on Android < 4.2. | 381 // for Android 4.0 to 4.1.x. Must only be used on Android < 4.2. |
353 // |private_key| is a JNI reference (local or global) to the object. | 382 // |private_key| is a JNI reference (local or global) to the object. |
354 // |pkey| is the EVP_PKEY to setup as a wrapper. | 383 // |pkey| is the EVP_PKEY to setup as a wrapper. |
355 // Returns true on success, false otherwise. | 384 // Returns true on success, false otherwise. |
356 EVP_PKEY* GetRsaLegacyKey(jobject private_key) { | 385 EVP_PKEY* GetRsaLegacyKey(jobject private_key) { |
357 EVP_PKEY* sys_pkey = | 386 AndroidEVP_PKEY* sys_pkey = |
358 GetOpenSSLSystemHandleForPrivateKey(private_key); | 387 GetOpenSSLSystemHandleForPrivateKey(private_key); |
359 if (sys_pkey != NULL) { | 388 if (sys_pkey != NULL) { |
360 CRYPTO_add(&sys_pkey->references, 1, CRYPTO_LOCK_EVP_PKEY); | 389 if (sys_pkey->type != ANDROID_EVP_PKEY_RSA) { |
361 LeakRsaEngine(sys_pkey); | 390 LOG(ERROR) << "Private key has wrong type!"; |
362 } else { | |
363 // GetOpenSSLSystemHandleForPrivateKey() will fail on Android | |
364 // 4.0.3 and earlier. However, it is possible to get the key | |
365 // content with PrivateKey.getEncoded() on these platforms. | |
366 // Note that this method may return NULL on 4.0.4 and later. | |
367 std::vector<uint8> encoded; | |
368 if (!GetPrivateKeyEncodedBytes(private_key, &encoded)) { | |
369 LOG(ERROR) << "Can't get private key data!"; | |
370 return NULL; | 391 return NULL; |
371 } | 392 } |
372 const unsigned char* p = | 393 |
373 reinterpret_cast<const unsigned char*>(&encoded[0]); | 394 AndroidRSA* sys_rsa = sys_pkey->pkey.rsa; |
374 int len = static_cast<int>(encoded.size()); | 395 if (sys_rsa->engine) { |
375 sys_pkey = d2i_AutoPrivateKey(NULL, &p, len); | 396 // |private_key| may not have an engine if the PrivateKey did not come |
376 if (sys_pkey == NULL) { | 397 // from the key store, such as in unit tests. |
377 LOG(ERROR) << "Can't convert private key data!"; | 398 if (!strcmp(sys_rsa->engine->id, "keystore")) { |
399 LeakEngine(private_key); | |
400 } else { | |
401 NOTREACHED(); | |
402 } | |
403 } | |
404 | |
405 ScopedEVP_PKEY pkey(EVP_PKEY_new()); | |
406 if (!GetRsaPkeyWrapper(private_key, sys_rsa, pkey.get())) | |
378 return NULL; | 407 return NULL; |
379 } | 408 return pkey.release(); |
380 } | 409 } |
381 return sys_pkey; | 410 |
411 // GetOpenSSLSystemHandleForPrivateKey() will fail on Android 4.0.3 and | |
412 // earlier. However, it is possible to get the key content with | |
413 // PrivateKey.getEncoded() on these platforms. Note that this method may | |
414 // return NULL on 4.0.4 and later. | |
415 std::vector<uint8> encoded; | |
416 if (!GetPrivateKeyEncodedBytes(private_key, &encoded)) { | |
417 LOG(ERROR) << "Can't get private key data!"; | |
418 return NULL; | |
419 } | |
420 const unsigned char* p = | |
421 reinterpret_cast<const unsigned char*>(&encoded[0]); | |
422 int len = static_cast<int>(encoded.size()); | |
423 EVP_PKEY* pkey = d2i_AutoPrivateKey(NULL, &p, len); | |
424 if (pkey == NULL) { | |
425 LOG(ERROR) << "Can't convert private key data!"; | |
426 return NULL; | |
427 } | |
428 return pkey; | |
382 } | 429 } |
383 | 430 |
384 // Custom DSA_METHOD that uses the platform APIs. | 431 // Custom DSA_METHOD that uses the platform APIs. |
385 // Note that for now, only signing through DSA_sign() is really supported. | 432 // Note that for now, only signing through DSA_sign() is really supported. |
386 // all other method pointers are either stubs returning errors, or no-ops. | 433 // all other method pointers are either stubs returning errors, or no-ops. |
387 // See <openssl/dsa.h> for exact declaration of DSA_METHOD. | 434 // See <openssl/dsa.h> for exact declaration of DSA_METHOD. |
388 // | 435 // |
389 // Note: There is no DSA_set_app_data() and DSA_get_app_data() functions, | 436 // Note: There is no DSA_set_app_data() and DSA_get_app_data() functions, |
390 // but RSA_set_app_data() is defined as a simple macro that calls | 437 // but RSA_set_app_data() is defined as a simple macro that calls |
391 // RSA_set_ex_data() with a hard-coded index of 0, so this code | 438 // RSA_set_ex_data() with a hard-coded index of 0, so this code |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
703 // backing this PrivateKey object. | 750 // backing this PrivateKey object. |
704 const int kAndroid42ApiLevel = 17; | 751 const int kAndroid42ApiLevel = 17; |
705 if (base::android::BuildInfo::GetInstance()->sdk_int() < | 752 if (base::android::BuildInfo::GetInstance()->sdk_int() < |
706 kAndroid42ApiLevel) { | 753 kAndroid42ApiLevel) { |
707 EVP_PKEY* legacy_key = GetRsaLegacyKey(private_key); | 754 EVP_PKEY* legacy_key = GetRsaLegacyKey(private_key); |
708 if (legacy_key == NULL) | 755 if (legacy_key == NULL) |
709 return NULL; | 756 return NULL; |
710 pkey.reset(legacy_key); | 757 pkey.reset(legacy_key); |
711 } else { | 758 } else { |
712 // Running on Android 4.2. | 759 // Running on Android 4.2. |
713 if (!GetRsaPkeyWrapper(private_key, pkey.get())) | 760 if (!GetRsaPkeyWrapper(private_key, NULL, pkey.get())) |
714 return NULL; | 761 return NULL; |
715 } | 762 } |
716 } | 763 } |
717 break; | 764 break; |
718 case PRIVATE_KEY_TYPE_DSA: | 765 case PRIVATE_KEY_TYPE_DSA: |
719 if (!GetDsaPkeyWrapper(private_key, pkey.get())) | 766 if (!GetDsaPkeyWrapper(private_key, pkey.get())) |
720 return NULL; | 767 return NULL; |
721 break; | 768 break; |
722 case PRIVATE_KEY_TYPE_ECDSA: | 769 case PRIVATE_KEY_TYPE_ECDSA: |
723 if (!GetEcdsaPkeyWrapper(private_key, pkey.get())) | 770 if (!GetEcdsaPkeyWrapper(private_key, pkey.get())) |
724 return NULL; | 771 return NULL; |
725 break; | 772 break; |
726 default: | 773 default: |
727 LOG(WARNING) | 774 LOG(WARNING) |
728 << "GetOpenSSLPrivateKeyWrapper() called with invalid key type"; | 775 << "GetOpenSSLPrivateKeyWrapper() called with invalid key type"; |
729 return NULL; | 776 return NULL; |
730 } | 777 } |
731 return pkey.release(); | 778 return pkey.release(); |
732 } | 779 } |
733 | 780 |
734 } // namespace android | 781 } // namespace android |
735 } // namespace net | 782 } // namespace net |
OLD | NEW |