Clean up URLFetcher unit tests, part 8.
[chromium-blink-merge.git] / net / android / keystore_openssl.cc
blobff794dbbdd12715f46ec24dfb2cbe5eb6b2ca761
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
3 // found in the LICENSE file.
5 #include "net/android/keystore_openssl.h"
7 #include <jni.h>
8 #include <openssl/bn.h>
9 #include <openssl/dsa.h>
10 #include <openssl/ec.h>
11 #include <openssl/engine.h>
12 #include <openssl/err.h>
13 #include <openssl/evp.h>
14 #include <openssl/rsa.h>
15 #include <openssl/x509.h>
17 #include "base/android/build_info.h"
18 #include "base/android/jni_android.h"
19 #include "base/android/scoped_java_ref.h"
20 #include "base/basictypes.h"
21 #include "base/lazy_instance.h"
22 #include "base/logging.h"
23 #include "crypto/openssl_util.h"
24 #include "net/android/keystore.h"
25 #include "net/android/legacy_openssl.h"
26 #include "net/ssl/scoped_openssl_types.h"
27 #include "net/ssl/ssl_client_cert_type.h"
29 // IMPORTANT NOTE: The following code will currently only work when used
30 // to implement client certificate support with OpenSSL. That's because
31 // only the signing operations used in this use case are implemented here.
33 // Generally speaking, OpenSSL provides many different ways to sign
34 // digests. This code doesn't support all these cases, only the ones that
35 // are required to sign the digest during the OpenSSL handshake for TLS.
37 // The OpenSSL EVP_PKEY type is a generic wrapper around key pairs.
38 // Internally, it can hold a pointer to a RSA, DSA or ECDSA structure,
39 // which model keypair implementations of each respective crypto
40 // algorithm.
42 // The RSA type has a 'method' field pointer to a vtable-like structure
43 // called a RSA_METHOD. This contains several function pointers that
44 // correspond to operations on RSA keys (e.g. decode/encode with public
45 // key, decode/encode with private key, signing, validation), as well as
46 // a few flags.
48 // For example, the RSA_sign() function will call "method->rsa_sign()" if
49 // method->rsa_sign is not NULL, otherwise, it will perform a regular
50 // signing operation using the other fields in the RSA structure (which
51 // are used to hold the typical modulus / exponent / parameters for the
52 // key pair).
54 // This source file thus defines a custom RSA_METHOD structure whose
55 // fields point to static methods used to implement the corresponding
56 // RSA operation using platform Android APIs.
58 // However, the platform APIs require a jobject JNI reference to work. It must
59 // be stored in the RSA instance, or made accessible when the custom RSA
60 // methods are called. This is done by storing it in a |KeyExData| structure
61 // that's referenced by the key using |EX_DATA|.
63 using base::android::ScopedJavaGlobalRef;
64 using base::android::ScopedJavaLocalRef;
66 namespace net {
67 namespace android {
69 namespace {
71 extern const RSA_METHOD android_rsa_method;
72 extern const ECDSA_METHOD android_ecdsa_method;
74 // KeyExData contains the data that is contained in the EX_DATA of the RSA, DSA
75 // and ECDSA objects that are created to wrap Android system keys.
76 struct KeyExData {
77 // private_key contains a reference to a Java, private-key object.
78 jobject private_key;
79 // legacy_rsa, if not NULL, points to an RSA* in the system's OpenSSL (which
80 // might not be ABI compatible with Chromium).
81 AndroidRSA* legacy_rsa;
82 // cached_size contains the "size" of the key. This is the size of the
83 // modulus (in bytes) for RSA, or the group order size for (EC)DSA. This
84 // avoids calling into Java to calculate the size.
85 size_t cached_size;
88 // ExDataDup is called when one of the RSA, DSA or EC_KEY objects is
89 // duplicated. We don't support this and it should never happen.
90 int ExDataDup(CRYPTO_EX_DATA* to,
91 const CRYPTO_EX_DATA* from,
92 void** from_d,
93 int index,
94 long argl,
95 void* argp) {
96 CHECK_EQ((void*)NULL, *from_d);
97 return 0;
100 // ExDataFree is called when one of the RSA, DSA or EC_KEY objects is freed.
101 void ExDataFree(void* parent,
102 void* ptr,
103 CRYPTO_EX_DATA* ad,
104 int index,
105 long argl,
106 void* argp) {
107 // Ensure the global JNI reference created with this wrapper is
108 // properly destroyed with it.
109 KeyExData *ex_data = reinterpret_cast<KeyExData*>(ptr);
110 if (ex_data != NULL) {
111 ReleaseKey(ex_data->private_key);
112 delete ex_data;
116 // BoringSSLEngine is a BoringSSL ENGINE that implements RSA, DSA and ECDSA by
117 // forwarding the requested operations to the Java libraries.
118 class BoringSSLEngine {
119 public:
120 BoringSSLEngine()
121 : rsa_index_(RSA_get_ex_new_index(0 /* argl */,
122 NULL /* argp */,
123 NULL /* new_func */,
124 ExDataDup,
125 ExDataFree)),
126 ec_key_index_(EC_KEY_get_ex_new_index(0 /* argl */,
127 NULL /* argp */,
128 NULL /* new_func */,
129 ExDataDup,
130 ExDataFree)),
131 engine_(ENGINE_new()) {
132 ENGINE_set_RSA_method(
133 engine_, &android_rsa_method, sizeof(android_rsa_method));
134 ENGINE_set_ECDSA_method(
135 engine_, &android_ecdsa_method, sizeof(android_ecdsa_method));
138 int rsa_ex_index() const { return rsa_index_; }
139 int ec_key_ex_index() const { return ec_key_index_; }
141 const ENGINE* engine() const { return engine_; }
143 private:
144 const int rsa_index_;
145 const int ec_key_index_;
146 ENGINE* const engine_;
149 base::LazyInstance<BoringSSLEngine>::Leaky global_boringssl_engine =
150 LAZY_INSTANCE_INITIALIZER;
153 // VectorBignumSize returns the number of bytes needed to represent the bignum
154 // given in |v|, i.e. the length of |v| less any leading zero bytes.
155 size_t VectorBignumSize(const std::vector<uint8>& v) {
156 size_t size = v.size();
157 // Ignore any leading zero bytes.
158 for (size_t i = 0; i < v.size() && v[i] == 0; i++) {
159 size--;
161 return size;
164 KeyExData* RsaGetExData(const RSA* rsa) {
165 return reinterpret_cast<KeyExData*>(
166 RSA_get_ex_data(rsa, global_boringssl_engine.Get().rsa_ex_index()));
169 size_t RsaMethodSize(const RSA *rsa) {
170 const KeyExData *ex_data = RsaGetExData(rsa);
171 return ex_data->cached_size;
174 int RsaMethodEncrypt(RSA* rsa,
175 size_t* out_len,
176 uint8_t* out,
177 size_t max_out,
178 const uint8_t* in,
179 size_t in_len,
180 int padding) {
181 NOTIMPLEMENTED();
182 OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE);
183 return 0;
186 int RsaMethodSignRaw(RSA* rsa,
187 size_t* out_len,
188 uint8_t* out,
189 size_t max_out,
190 const uint8_t* in,
191 size_t in_len,
192 int padding) {
193 DCHECK_EQ(RSA_PKCS1_PADDING, padding);
194 if (padding != RSA_PKCS1_PADDING) {
195 // TODO(davidben): If we need to, we can implement RSA_NO_PADDING
196 // by using javax.crypto.Cipher and picking either the
197 // "RSA/ECB/NoPadding" or "RSA/ECB/PKCS1Padding" transformation as
198 // appropriate. I believe support for both of these was added in
199 // the same Android version as the "NONEwithRSA"
200 // java.security.Signature algorithm, so the same version checks
201 // for GetRsaLegacyKey should work.
202 OPENSSL_PUT_ERROR(RSA, sign_raw, RSA_R_UNKNOWN_PADDING_TYPE);
203 return 0;
206 // Retrieve private key JNI reference.
207 const KeyExData *ex_data = RsaGetExData(rsa);
208 if (!ex_data || !ex_data->private_key) {
209 LOG(WARNING) << "Null JNI reference passed to RsaMethodSignRaw!";
210 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
211 return 0;
214 // Pre-4.2 legacy codepath.
215 if (ex_data->legacy_rsa) {
216 int ret = ex_data->legacy_rsa->meth->rsa_priv_enc(
217 in_len, in, out, ex_data->legacy_rsa, ANDROID_RSA_PKCS1_PADDING);
218 if (ret < 0) {
219 LOG(WARNING) << "Could not sign message in RsaMethodSignRaw!";
220 // System OpenSSL will use a separate error queue, so it is still
221 // necessary to push a new error.
223 // TODO(davidben): It would be good to also clear the system error queue
224 // if there were some way to convince Java to do it. (Without going
225 // through Java, it's difficult to get a handle on a system OpenSSL
226 // function; dlopen loads a second copy.)
227 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
228 return 0;
230 *out_len = ret;
231 return 1;
234 base::StringPiece from_piece(reinterpret_cast<const char*>(in), in_len);
235 std::vector<uint8> result;
236 // For RSA keys, this function behaves as RSA_private_encrypt with
237 // PKCS#1 padding.
238 if (!RawSignDigestWithPrivateKey(ex_data->private_key, from_piece, &result)) {
239 LOG(WARNING) << "Could not sign message in RsaMethodSignRaw!";
240 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
241 return 0;
244 size_t expected_size = static_cast<size_t>(RSA_size(rsa));
245 if (result.size() > expected_size) {
246 LOG(ERROR) << "RSA Signature size mismatch, actual: "
247 << result.size() << ", expected <= " << expected_size;
248 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
249 return 0;
252 if (max_out < expected_size) {
253 OPENSSL_PUT_ERROR(RSA, sign_raw, RSA_R_DATA_TOO_LARGE);
254 return 0;
257 // Copy result to OpenSSL-provided buffer. RawSignDigestWithPrivateKey
258 // should pad with leading 0s, but if it doesn't, pad the result.
259 size_t zero_pad = expected_size - result.size();
260 memset(out, 0, zero_pad);
261 memcpy(out + zero_pad, &result[0], result.size());
262 *out_len = expected_size;
264 return 1;
267 int RsaMethodDecrypt(RSA* rsa,
268 size_t* out_len,
269 uint8_t* out,
270 size_t max_out,
271 const uint8_t* in,
272 size_t in_len,
273 int padding) {
274 NOTIMPLEMENTED();
275 OPENSSL_PUT_ERROR(RSA, decrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE);
276 return 0;
279 int RsaMethodVerifyRaw(RSA* rsa,
280 size_t* out_len,
281 uint8_t* out,
282 size_t max_out,
283 const uint8_t* in,
284 size_t in_len,
285 int padding) {
286 NOTIMPLEMENTED();
287 OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_UNKNOWN_ALGORITHM_TYPE);
288 return 0;
291 const RSA_METHOD android_rsa_method = {
293 0 /* references */,
294 1 /* is_static */
295 } /* common */,
296 NULL /* app_data */,
298 NULL /* init */,
299 NULL /* finish */,
300 RsaMethodSize,
301 NULL /* sign */,
302 NULL /* verify */,
303 RsaMethodEncrypt,
304 RsaMethodSignRaw,
305 RsaMethodDecrypt,
306 RsaMethodVerifyRaw,
307 NULL /* private_transform */,
308 NULL /* mod_exp */,
309 NULL /* bn_mod_exp */,
310 RSA_FLAG_OPAQUE,
311 NULL /* keygen */,
314 // Setup an EVP_PKEY to wrap an existing platform RSA PrivateKey object.
315 // |private_key| is the JNI reference (local or global) to the object.
316 // |legacy_rsa|, if non-NULL, is a pointer to the system OpenSSL RSA object
317 // backing |private_key|. This parameter is only used for Android < 4.2 to
318 // implement key operations not exposed by the platform.
319 // Returns a new EVP_PKEY on success, NULL otherwise.
320 // On success, this creates a new global JNI reference to the object
321 // that is owned by and destroyed with the EVP_PKEY. I.e. caller can
322 // free |private_key| after the call.
323 crypto::ScopedEVP_PKEY CreateRsaPkeyWrapper(
324 jobject private_key,
325 AndroidRSA* legacy_rsa,
326 const crypto::OpenSSLErrStackTracer& tracer) {
327 crypto::ScopedRSA rsa(
328 RSA_new_method(global_boringssl_engine.Get().engine()));
330 ScopedJavaGlobalRef<jobject> global_key;
331 global_key.Reset(NULL, private_key);
332 if (global_key.is_null()) {
333 LOG(ERROR) << "Could not create global JNI reference";
334 return crypto::ScopedEVP_PKEY();
337 std::vector<uint8> modulus;
338 if (!GetRSAKeyModulus(private_key, &modulus)) {
339 LOG(ERROR) << "Failed to get private key modulus";
340 return crypto::ScopedEVP_PKEY();
343 KeyExData* ex_data = new KeyExData;
344 ex_data->private_key = global_key.Release();
345 ex_data->legacy_rsa = legacy_rsa;
346 ex_data->cached_size = VectorBignumSize(modulus);
347 RSA_set_ex_data(
348 rsa.get(), global_boringssl_engine.Get().rsa_ex_index(), ex_data);
350 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new());
351 if (!pkey ||
352 !EVP_PKEY_set1_RSA(pkey.get(), rsa.get())) {
353 return crypto::ScopedEVP_PKEY();
355 return pkey.Pass();
358 // On Android < 4.2, the libkeystore.so ENGINE uses CRYPTO_EX_DATA and is not
359 // added to the global engine list. If all references to it are dropped, OpenSSL
360 // will dlclose the module, leaving a dangling function pointer in the RSA
361 // CRYPTO_EX_DATA class. To work around this, leak an extra reference to the
362 // ENGINE we extract in GetRsaLegacyKey.
364 // In 4.2, this change avoids the problem:
365 // https://android.googlesource.com/platform/libcore/+/106a8928fb4249f2f3d4dba1dddbe73ca5cb3d61
367 // https://crbug.com/381465
368 class KeystoreEngineWorkaround {
369 public:
370 KeystoreEngineWorkaround() {}
372 void LeakEngine(jobject private_key) {
373 if (!engine_.is_null())
374 return;
375 ScopedJavaLocalRef<jobject> engine =
376 GetOpenSSLEngineForPrivateKey(private_key);
377 if (engine.is_null()) {
378 NOTREACHED();
379 return;
381 engine_.Reset(engine);
384 private:
385 ScopedJavaGlobalRef<jobject> engine_;
388 void LeakEngine(jobject private_key) {
389 static base::LazyInstance<KeystoreEngineWorkaround>::Leaky s_instance =
390 LAZY_INSTANCE_INITIALIZER;
391 s_instance.Get().LeakEngine(private_key);
394 // Creates an EVP_PKEY wrapper corresponding to the RSA key
395 // |private_key|. Returns nullptr on failure.
396 crypto::ScopedEVP_PKEY GetRsaPkeyWrapper(jobject private_key) {
397 const int kAndroid42ApiLevel = 17;
398 crypto::OpenSSLErrStackTracer tracer(FROM_HERE);
400 if (base::android::BuildInfo::GetInstance()->sdk_int() >=
401 kAndroid42ApiLevel) {
402 return CreateRsaPkeyWrapper(private_key, nullptr, tracer);
405 // Route around platform bug: if Android < 4.2, then
406 // base::android::RawSignDigestWithPrivateKey() cannot work, so instead, try
407 // to get the system OpenSSL's EVP_PKEY begin this PrivateKey object.
408 AndroidEVP_PKEY* sys_pkey =
409 GetOpenSSLSystemHandleForPrivateKey(private_key);
410 if (sys_pkey != NULL) {
411 if (sys_pkey->type != ANDROID_EVP_PKEY_RSA) {
412 LOG(ERROR) << "Private key has wrong type!";
413 return nullptr;
416 AndroidRSA* sys_rsa = sys_pkey->pkey.rsa;
417 if (sys_rsa->engine) {
418 // |private_key| may not have an engine if the PrivateKey did not come
419 // from the key store, such as in unit tests.
420 if (strcmp(sys_rsa->engine->id, "keystore") == 0) {
421 LeakEngine(private_key);
422 } else {
423 NOTREACHED();
427 return CreateRsaPkeyWrapper(private_key, sys_rsa, tracer);
430 // GetOpenSSLSystemHandleForPrivateKey() will fail on Android 4.0.3 and
431 // earlier. However, it is possible to get the key content with
432 // PrivateKey.getEncoded() on these platforms. Note that this method may
433 // return false on 4.0.4 and later.
434 std::vector<uint8_t> encoded;
435 if (!GetPrivateKeyEncodedBytes(private_key, &encoded) || encoded.empty()) {
436 LOG(ERROR) << "Can't get private key data!";
437 return nullptr;
439 const uint8_t* p = &encoded[0];
440 ScopedPKCS8_PRIV_KEY_INFO pkcs8(
441 d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, encoded.size()));
442 if (!pkcs8.get() || p != &encoded[0] + encoded.size()) {
443 LOG(ERROR) << "Can't decode PrivateKeyInfo";
444 return nullptr;
446 crypto::ScopedEVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
447 if (!pkey || EVP_PKEY_id(pkey.get()) != EVP_PKEY_RSA) {
448 LOG(ERROR) << "Can't decode RSA key";
449 return nullptr;
451 return pkey.Pass();
454 // Custom ECDSA_METHOD that uses the platform APIs.
455 // Note that for now, only signing through ECDSA_sign() is really supported.
456 // all other method pointers are either stubs returning errors, or no-ops.
458 jobject EcKeyGetKey(const EC_KEY* ec_key) {
459 KeyExData* ex_data = reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data(
460 ec_key, global_boringssl_engine.Get().ec_key_ex_index()));
461 return ex_data->private_key;
464 size_t EcdsaMethodGroupOrderSize(const EC_KEY* ec_key) {
465 KeyExData* ex_data = reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data(
466 ec_key, global_boringssl_engine.Get().ec_key_ex_index()));
467 return ex_data->cached_size;
470 int EcdsaMethodSign(const uint8_t* digest,
471 size_t digest_len,
472 uint8_t* sig,
473 unsigned int* sig_len,
474 EC_KEY* ec_key) {
475 // Retrieve private key JNI reference.
476 jobject private_key = EcKeyGetKey(ec_key);
477 if (!private_key) {
478 LOG(WARNING) << "Null JNI reference passed to EcdsaMethodSign!";
479 return 0;
481 // Sign message with it through JNI.
482 std::vector<uint8> signature;
483 base::StringPiece digest_sp(reinterpret_cast<const char*>(digest),
484 digest_len);
485 if (!RawSignDigestWithPrivateKey(private_key, digest_sp, &signature)) {
486 LOG(WARNING) << "Could not sign message in EcdsaMethodSign!";
487 return 0;
490 // Note: With ECDSA, the actual signature may be smaller than
491 // ECDSA_size().
492 size_t max_expected_size = ECDSA_size(ec_key);
493 if (signature.size() > max_expected_size) {
494 LOG(ERROR) << "ECDSA Signature size mismatch, actual: "
495 << signature.size() << ", expected <= "
496 << max_expected_size;
497 return 0;
500 memcpy(sig, &signature[0], signature.size());
501 *sig_len = signature.size();
502 return 1;
505 int EcdsaMethodVerify(const uint8_t* digest,
506 size_t digest_len,
507 const uint8_t* sig,
508 size_t sig_len,
509 EC_KEY* ec_key) {
510 NOTIMPLEMENTED();
511 OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ECDSA_R_NOT_IMPLEMENTED);
512 return 0;
515 // Setup an EVP_PKEY to wrap an existing platform PrivateKey object.
516 // |private_key| is the JNI reference (local or global) to the object.
517 // Returns a new EVP_PKEY on success, NULL otherwise.
518 // On success, this creates a global JNI reference to the object that
519 // is owned by and destroyed with the EVP_PKEY. I.e. the caller shall
520 // always free |private_key| after the call.
521 crypto::ScopedEVP_PKEY GetEcdsaPkeyWrapper(jobject private_key) {
522 crypto::OpenSSLErrStackTracer tracer(FROM_HERE);
523 crypto::ScopedEC_KEY ec_key(
524 EC_KEY_new_method(global_boringssl_engine.Get().engine()));
526 ScopedJavaGlobalRef<jobject> global_key;
527 global_key.Reset(NULL, private_key);
528 if (global_key.is_null()) {
529 LOG(ERROR) << "Can't create global JNI reference";
530 return crypto::ScopedEVP_PKEY();
533 std::vector<uint8> order;
534 if (!GetECKeyOrder(private_key, &order)) {
535 LOG(ERROR) << "Can't extract order parameter from EC private key";
536 return crypto::ScopedEVP_PKEY();
539 KeyExData* ex_data = new KeyExData;
540 ex_data->private_key = global_key.Release();
541 ex_data->legacy_rsa = NULL;
542 ex_data->cached_size = VectorBignumSize(order);
544 EC_KEY_set_ex_data(
545 ec_key.get(), global_boringssl_engine.Get().ec_key_ex_index(), ex_data);
547 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new());
548 if (!pkey ||
549 !EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get())) {
550 return crypto::ScopedEVP_PKEY();
552 return pkey.Pass();
555 const ECDSA_METHOD android_ecdsa_method = {
557 0 /* references */,
558 1 /* is_static */
559 } /* common */,
560 NULL /* app_data */,
562 NULL /* init */,
563 NULL /* finish */,
564 EcdsaMethodGroupOrderSize,
565 EcdsaMethodSign,
566 EcdsaMethodVerify,
567 ECDSA_FLAG_OPAQUE,
570 } // namespace
572 crypto::ScopedEVP_PKEY GetOpenSSLPrivateKeyWrapper(jobject private_key) {
573 // Create sub key type, depending on private key's algorithm type.
574 PrivateKeyType key_type = GetPrivateKeyType(private_key);
575 switch (key_type) {
576 case PRIVATE_KEY_TYPE_RSA:
577 return GetRsaPkeyWrapper(private_key);
578 case PRIVATE_KEY_TYPE_ECDSA:
579 return GetEcdsaPkeyWrapper(private_key);
580 default:
581 LOG(WARNING)
582 << "GetOpenSSLPrivateKeyWrapper() called with invalid key type";
583 return nullptr;
587 } // namespace android
588 } // namespace net