Delete chrome.mediaGalleriesPrivate because the functionality unique to it has since...
[chromium-blink-merge.git] / net / android / keystore_openssl.cc
blob886b9ee67f8c51b141a997facf6ee4bba0d2cfc3
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/ssl_client_cert_type.h"
28 // IMPORTANT NOTE: The following code will currently only work when used
29 // to implement client certificate support with OpenSSL. That's because
30 // only the signing operations used in this use case are implemented here.
32 // Generally speaking, OpenSSL provides many different ways to sign
33 // digests. This code doesn't support all these cases, only the ones that
34 // are required to sign the digest during the OpenSSL handshake for TLS.
36 // The OpenSSL EVP_PKEY type is a generic wrapper around key pairs.
37 // Internally, it can hold a pointer to a RSA, DSA or ECDSA structure,
38 // which model keypair implementations of each respective crypto
39 // algorithm.
41 // The RSA type has a 'method' field pointer to a vtable-like structure
42 // called a RSA_METHOD. This contains several function pointers that
43 // correspond to operations on RSA keys (e.g. decode/encode with public
44 // key, decode/encode with private key, signing, validation), as well as
45 // a few flags.
47 // For example, the RSA_sign() function will call "method->rsa_sign()" if
48 // method->rsa_sign is not NULL, otherwise, it will perform a regular
49 // signing operation using the other fields in the RSA structure (which
50 // are used to hold the typical modulus / exponent / parameters for the
51 // key pair).
53 // This source file thus defines a custom RSA_METHOD structure whose
54 // fields point to static methods used to implement the corresponding
55 // RSA operation using platform Android APIs.
57 // However, the platform APIs require a jobject JNI reference to work. It must
58 // be stored in the RSA instance, or made accessible when the custom RSA
59 // methods are called. This is done by storing it in a |KeyExData| structure
60 // that's referenced by the key using |EX_DATA|.
62 using base::android::ScopedJavaGlobalRef;
63 using base::android::ScopedJavaLocalRef;
65 namespace net {
66 namespace android {
68 namespace {
70 using ScopedPKCS8_PRIV_KEY_INFO =
71 crypto::ScopedOpenSSL<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free>::Type;
73 extern const RSA_METHOD android_rsa_method;
74 extern const ECDSA_METHOD android_ecdsa_method;
76 // KeyExData contains the data that is contained in the EX_DATA of the RSA, DSA
77 // and ECDSA objects that are created to wrap Android system keys.
78 struct KeyExData {
79 // private_key contains a reference to a Java, private-key object.
80 jobject private_key;
81 // legacy_rsa, if not NULL, points to an RSA* in the system's OpenSSL (which
82 // might not be ABI compatible with Chromium).
83 AndroidRSA* legacy_rsa;
84 // cached_size contains the "size" of the key. This is the size of the
85 // modulus (in bytes) for RSA, or the group order size for (EC)DSA. This
86 // avoids calling into Java to calculate the size.
87 size_t cached_size;
90 // ExDataDup is called when one of the RSA, DSA or EC_KEY objects is
91 // duplicated. We don't support this and it should never happen.
92 int ExDataDup(CRYPTO_EX_DATA* to,
93 const CRYPTO_EX_DATA* from,
94 void** from_d,
95 int index,
96 long argl,
97 void* argp) {
98 CHECK_EQ((void*)NULL, *from_d);
99 return 0;
102 // ExDataFree is called when one of the RSA, DSA or EC_KEY objects is freed.
103 void ExDataFree(void* parent,
104 void* ptr,
105 CRYPTO_EX_DATA* ad,
106 int index,
107 long argl,
108 void* argp) {
109 // Ensure the global JNI reference created with this wrapper is
110 // properly destroyed with it.
111 KeyExData *ex_data = reinterpret_cast<KeyExData*>(ptr);
112 if (ex_data != NULL) {
113 ReleaseKey(ex_data->private_key);
114 delete ex_data;
118 // BoringSSLEngine is a BoringSSL ENGINE that implements RSA, DSA and ECDSA by
119 // forwarding the requested operations to the Java libraries.
120 class BoringSSLEngine {
121 public:
122 BoringSSLEngine()
123 : rsa_index_(RSA_get_ex_new_index(0 /* argl */,
124 NULL /* argp */,
125 NULL /* new_func */,
126 ExDataDup,
127 ExDataFree)),
128 ec_key_index_(EC_KEY_get_ex_new_index(0 /* argl */,
129 NULL /* argp */,
130 NULL /* new_func */,
131 ExDataDup,
132 ExDataFree)),
133 engine_(ENGINE_new()) {
134 ENGINE_set_RSA_method(
135 engine_, &android_rsa_method, sizeof(android_rsa_method));
136 ENGINE_set_ECDSA_method(
137 engine_, &android_ecdsa_method, sizeof(android_ecdsa_method));
140 int rsa_ex_index() const { return rsa_index_; }
141 int ec_key_ex_index() const { return ec_key_index_; }
143 const ENGINE* engine() const { return engine_; }
145 private:
146 const int rsa_index_;
147 const int ec_key_index_;
148 ENGINE* const engine_;
151 base::LazyInstance<BoringSSLEngine>::Leaky global_boringssl_engine =
152 LAZY_INSTANCE_INITIALIZER;
155 // VectorBignumSize returns the number of bytes needed to represent the bignum
156 // given in |v|, i.e. the length of |v| less any leading zero bytes.
157 size_t VectorBignumSize(const std::vector<uint8>& v) {
158 size_t size = v.size();
159 // Ignore any leading zero bytes.
160 for (size_t i = 0; i < v.size() && v[i] == 0; i++) {
161 size--;
163 return size;
166 KeyExData* RsaGetExData(const RSA* rsa) {
167 return reinterpret_cast<KeyExData*>(
168 RSA_get_ex_data(rsa, global_boringssl_engine.Get().rsa_ex_index()));
171 size_t RsaMethodSize(const RSA *rsa) {
172 const KeyExData *ex_data = RsaGetExData(rsa);
173 return ex_data->cached_size;
176 int RsaMethodEncrypt(RSA* rsa,
177 size_t* out_len,
178 uint8_t* out,
179 size_t max_out,
180 const uint8_t* in,
181 size_t in_len,
182 int padding) {
183 NOTIMPLEMENTED();
184 OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE);
185 return 0;
188 int RsaMethodSignRaw(RSA* rsa,
189 size_t* out_len,
190 uint8_t* out,
191 size_t max_out,
192 const uint8_t* in,
193 size_t in_len,
194 int padding) {
195 DCHECK_EQ(RSA_PKCS1_PADDING, padding);
196 if (padding != RSA_PKCS1_PADDING) {
197 // TODO(davidben): If we need to, we can implement RSA_NO_PADDING
198 // by using javax.crypto.Cipher and picking either the
199 // "RSA/ECB/NoPadding" or "RSA/ECB/PKCS1Padding" transformation as
200 // appropriate. I believe support for both of these was added in
201 // the same Android version as the "NONEwithRSA"
202 // java.security.Signature algorithm, so the same version checks
203 // for GetRsaLegacyKey should work.
204 OPENSSL_PUT_ERROR(RSA, sign_raw, RSA_R_UNKNOWN_PADDING_TYPE);
205 return 0;
208 // Retrieve private key JNI reference.
209 const KeyExData *ex_data = RsaGetExData(rsa);
210 if (!ex_data || !ex_data->private_key) {
211 LOG(WARNING) << "Null JNI reference passed to RsaMethodSignRaw!";
212 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
213 return 0;
216 // Pre-4.2 legacy codepath.
217 if (ex_data->legacy_rsa) {
218 int ret = ex_data->legacy_rsa->meth->rsa_priv_enc(
219 in_len, in, out, ex_data->legacy_rsa, ANDROID_RSA_PKCS1_PADDING);
220 if (ret < 0) {
221 LOG(WARNING) << "Could not sign message in RsaMethodSignRaw!";
222 // System OpenSSL will use a separate error queue, so it is still
223 // necessary to push a new error.
225 // TODO(davidben): It would be good to also clear the system error queue
226 // if there were some way to convince Java to do it. (Without going
227 // through Java, it's difficult to get a handle on a system OpenSSL
228 // function; dlopen loads a second copy.)
229 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
230 return 0;
232 *out_len = ret;
233 return 1;
236 base::StringPiece from_piece(reinterpret_cast<const char*>(in), in_len);
237 std::vector<uint8> result;
238 // For RSA keys, this function behaves as RSA_private_encrypt with
239 // PKCS#1 padding.
240 if (!RawSignDigestWithPrivateKey(ex_data->private_key, from_piece, &result)) {
241 LOG(WARNING) << "Could not sign message in RsaMethodSignRaw!";
242 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
243 return 0;
246 size_t expected_size = static_cast<size_t>(RSA_size(rsa));
247 if (result.size() > expected_size) {
248 LOG(ERROR) << "RSA Signature size mismatch, actual: "
249 << result.size() << ", expected <= " << expected_size;
250 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
251 return 0;
254 if (max_out < expected_size) {
255 OPENSSL_PUT_ERROR(RSA, sign_raw, RSA_R_DATA_TOO_LARGE);
256 return 0;
259 // Copy result to OpenSSL-provided buffer. RawSignDigestWithPrivateKey
260 // should pad with leading 0s, but if it doesn't, pad the result.
261 size_t zero_pad = expected_size - result.size();
262 memset(out, 0, zero_pad);
263 memcpy(out + zero_pad, &result[0], result.size());
264 *out_len = expected_size;
266 return 1;
269 int RsaMethodDecrypt(RSA* rsa,
270 size_t* out_len,
271 uint8_t* out,
272 size_t max_out,
273 const uint8_t* in,
274 size_t in_len,
275 int padding) {
276 NOTIMPLEMENTED();
277 OPENSSL_PUT_ERROR(RSA, decrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE);
278 return 0;
281 int RsaMethodVerifyRaw(RSA* rsa,
282 size_t* out_len,
283 uint8_t* out,
284 size_t max_out,
285 const uint8_t* in,
286 size_t in_len,
287 int padding) {
288 NOTIMPLEMENTED();
289 OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_UNKNOWN_ALGORITHM_TYPE);
290 return 0;
293 const RSA_METHOD android_rsa_method = {
295 0 /* references */,
296 1 /* is_static */
297 } /* common */,
298 NULL /* app_data */,
300 NULL /* init */,
301 NULL /* finish */,
302 RsaMethodSize,
303 NULL /* sign */,
304 NULL /* verify */,
305 RsaMethodEncrypt,
306 RsaMethodSignRaw,
307 RsaMethodDecrypt,
308 RsaMethodVerifyRaw,
309 NULL /* private_transform */,
310 NULL /* mod_exp */,
311 NULL /* bn_mod_exp */,
312 RSA_FLAG_OPAQUE,
313 NULL /* keygen */,
316 // Setup an EVP_PKEY to wrap an existing platform RSA PrivateKey object.
317 // |private_key| is the JNI reference (local or global) to the object.
318 // |legacy_rsa|, if non-NULL, is a pointer to the system OpenSSL RSA object
319 // backing |private_key|. This parameter is only used for Android < 4.2 to
320 // implement key operations not exposed by the platform.
321 // Returns a new EVP_PKEY on success, NULL otherwise.
322 // On success, this creates a new global JNI reference to the object
323 // that is owned by and destroyed with the EVP_PKEY. I.e. caller can
324 // free |private_key| after the call.
325 crypto::ScopedEVP_PKEY CreateRsaPkeyWrapper(
326 jobject private_key,
327 AndroidRSA* legacy_rsa,
328 const crypto::OpenSSLErrStackTracer& tracer) {
329 crypto::ScopedRSA rsa(
330 RSA_new_method(global_boringssl_engine.Get().engine()));
332 ScopedJavaGlobalRef<jobject> global_key;
333 global_key.Reset(NULL, private_key);
334 if (global_key.is_null()) {
335 LOG(ERROR) << "Could not create global JNI reference";
336 return crypto::ScopedEVP_PKEY();
339 std::vector<uint8> modulus;
340 if (!GetRSAKeyModulus(private_key, &modulus)) {
341 LOG(ERROR) << "Failed to get private key modulus";
342 return crypto::ScopedEVP_PKEY();
345 KeyExData* ex_data = new KeyExData;
346 ex_data->private_key = global_key.Release();
347 ex_data->legacy_rsa = legacy_rsa;
348 ex_data->cached_size = VectorBignumSize(modulus);
349 RSA_set_ex_data(
350 rsa.get(), global_boringssl_engine.Get().rsa_ex_index(), ex_data);
352 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new());
353 if (!pkey ||
354 !EVP_PKEY_set1_RSA(pkey.get(), rsa.get())) {
355 return crypto::ScopedEVP_PKEY();
357 return pkey.Pass();
360 // On Android < 4.2, the libkeystore.so ENGINE uses CRYPTO_EX_DATA and is not
361 // added to the global engine list. If all references to it are dropped, OpenSSL
362 // will dlclose the module, leaving a dangling function pointer in the RSA
363 // CRYPTO_EX_DATA class. To work around this, leak an extra reference to the
364 // ENGINE we extract in GetRsaLegacyKey.
366 // In 4.2, this change avoids the problem:
367 // https://android.googlesource.com/platform/libcore/+/106a8928fb4249f2f3d4dba1dddbe73ca5cb3d61
369 // https://crbug.com/381465
370 class KeystoreEngineWorkaround {
371 public:
372 KeystoreEngineWorkaround() {}
374 void LeakEngine(jobject private_key) {
375 if (!engine_.is_null())
376 return;
377 ScopedJavaLocalRef<jobject> engine =
378 GetOpenSSLEngineForPrivateKey(private_key);
379 if (engine.is_null()) {
380 NOTREACHED();
381 return;
383 engine_.Reset(engine);
386 private:
387 ScopedJavaGlobalRef<jobject> engine_;
390 void LeakEngine(jobject private_key) {
391 static base::LazyInstance<KeystoreEngineWorkaround>::Leaky s_instance =
392 LAZY_INSTANCE_INITIALIZER;
393 s_instance.Get().LeakEngine(private_key);
396 // Creates an EVP_PKEY wrapper corresponding to the RSA key
397 // |private_key|. Returns nullptr on failure.
398 crypto::ScopedEVP_PKEY GetRsaPkeyWrapper(jobject private_key) {
399 const int kAndroid42ApiLevel = 17;
400 crypto::OpenSSLErrStackTracer tracer(FROM_HERE);
402 if (base::android::BuildInfo::GetInstance()->sdk_int() >=
403 kAndroid42ApiLevel) {
404 return CreateRsaPkeyWrapper(private_key, nullptr, tracer);
407 // Route around platform bug: if Android < 4.2, then
408 // base::android::RawSignDigestWithPrivateKey() cannot work, so instead, try
409 // to get the system OpenSSL's EVP_PKEY begin this PrivateKey object.
410 AndroidEVP_PKEY* sys_pkey =
411 GetOpenSSLSystemHandleForPrivateKey(private_key);
412 if (sys_pkey != NULL) {
413 if (sys_pkey->type != ANDROID_EVP_PKEY_RSA) {
414 LOG(ERROR) << "Private key has wrong type!";
415 return nullptr;
418 AndroidRSA* sys_rsa = sys_pkey->pkey.rsa;
419 if (sys_rsa->engine) {
420 // |private_key| may not have an engine if the PrivateKey did not come
421 // from the key store, such as in unit tests.
422 if (strcmp(sys_rsa->engine->id, "keystore") == 0) {
423 LeakEngine(private_key);
424 } else {
425 NOTREACHED();
429 return CreateRsaPkeyWrapper(private_key, sys_rsa, tracer);
432 // GetOpenSSLSystemHandleForPrivateKey() will fail on Android 4.0.3 and
433 // earlier. However, it is possible to get the key content with
434 // PrivateKey.getEncoded() on these platforms. Note that this method may
435 // return false on 4.0.4 and later.
436 std::vector<uint8_t> encoded;
437 if (!GetPrivateKeyEncodedBytes(private_key, &encoded) || encoded.empty()) {
438 LOG(ERROR) << "Can't get private key data!";
439 return nullptr;
441 const uint8_t* p = &encoded[0];
442 ScopedPKCS8_PRIV_KEY_INFO pkcs8(
443 d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, encoded.size()));
444 if (!pkcs8.get() || p != &encoded[0] + encoded.size()) {
445 LOG(ERROR) << "Can't decode PrivateKeyInfo";
446 return nullptr;
448 crypto::ScopedEVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
449 if (!pkey || EVP_PKEY_id(pkey.get()) != EVP_PKEY_RSA) {
450 LOG(ERROR) << "Can't decode RSA key";
451 return nullptr;
453 return pkey.Pass();
456 // Custom ECDSA_METHOD that uses the platform APIs.
457 // Note that for now, only signing through ECDSA_sign() is really supported.
458 // all other method pointers are either stubs returning errors, or no-ops.
460 jobject EcKeyGetKey(const EC_KEY* ec_key) {
461 KeyExData* ex_data = reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data(
462 ec_key, global_boringssl_engine.Get().ec_key_ex_index()));
463 return ex_data->private_key;
466 size_t EcdsaMethodGroupOrderSize(const EC_KEY* ec_key) {
467 KeyExData* ex_data = reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data(
468 ec_key, global_boringssl_engine.Get().ec_key_ex_index()));
469 return ex_data->cached_size;
472 int EcdsaMethodSign(const uint8_t* digest,
473 size_t digest_len,
474 uint8_t* sig,
475 unsigned int* sig_len,
476 EC_KEY* ec_key) {
477 // Retrieve private key JNI reference.
478 jobject private_key = EcKeyGetKey(ec_key);
479 if (!private_key) {
480 LOG(WARNING) << "Null JNI reference passed to EcdsaMethodSign!";
481 return 0;
483 // Sign message with it through JNI.
484 std::vector<uint8> signature;
485 base::StringPiece digest_sp(reinterpret_cast<const char*>(digest),
486 digest_len);
487 if (!RawSignDigestWithPrivateKey(private_key, digest_sp, &signature)) {
488 LOG(WARNING) << "Could not sign message in EcdsaMethodSign!";
489 return 0;
492 // Note: With ECDSA, the actual signature may be smaller than
493 // ECDSA_size().
494 size_t max_expected_size = ECDSA_size(ec_key);
495 if (signature.size() > max_expected_size) {
496 LOG(ERROR) << "ECDSA Signature size mismatch, actual: "
497 << signature.size() << ", expected <= "
498 << max_expected_size;
499 return 0;
502 memcpy(sig, &signature[0], signature.size());
503 *sig_len = signature.size();
504 return 1;
507 int EcdsaMethodVerify(const uint8_t* digest,
508 size_t digest_len,
509 const uint8_t* sig,
510 size_t sig_len,
511 EC_KEY* ec_key) {
512 NOTIMPLEMENTED();
513 OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ECDSA_R_NOT_IMPLEMENTED);
514 return 0;
517 // Setup an EVP_PKEY to wrap an existing platform PrivateKey object.
518 // |private_key| is the JNI reference (local or global) to the object.
519 // Returns a new EVP_PKEY on success, NULL otherwise.
520 // On success, this creates a global JNI reference to the object that
521 // is owned by and destroyed with the EVP_PKEY. I.e. the caller shall
522 // always free |private_key| after the call.
523 crypto::ScopedEVP_PKEY GetEcdsaPkeyWrapper(jobject private_key) {
524 crypto::OpenSSLErrStackTracer tracer(FROM_HERE);
525 crypto::ScopedEC_KEY ec_key(
526 EC_KEY_new_method(global_boringssl_engine.Get().engine()));
528 ScopedJavaGlobalRef<jobject> global_key;
529 global_key.Reset(NULL, private_key);
530 if (global_key.is_null()) {
531 LOG(ERROR) << "Can't create global JNI reference";
532 return crypto::ScopedEVP_PKEY();
535 std::vector<uint8> order;
536 if (!GetECKeyOrder(private_key, &order)) {
537 LOG(ERROR) << "Can't extract order parameter from EC private key";
538 return crypto::ScopedEVP_PKEY();
541 KeyExData* ex_data = new KeyExData;
542 ex_data->private_key = global_key.Release();
543 ex_data->legacy_rsa = NULL;
544 ex_data->cached_size = VectorBignumSize(order);
546 EC_KEY_set_ex_data(
547 ec_key.get(), global_boringssl_engine.Get().ec_key_ex_index(), ex_data);
549 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new());
550 if (!pkey ||
551 !EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get())) {
552 return crypto::ScopedEVP_PKEY();
554 return pkey.Pass();
557 const ECDSA_METHOD android_ecdsa_method = {
559 0 /* references */,
560 1 /* is_static */
561 } /* common */,
562 NULL /* app_data */,
564 NULL /* init */,
565 NULL /* finish */,
566 EcdsaMethodGroupOrderSize,
567 EcdsaMethodSign,
568 EcdsaMethodVerify,
569 ECDSA_FLAG_OPAQUE,
572 } // namespace
574 crypto::ScopedEVP_PKEY GetOpenSSLPrivateKeyWrapper(jobject private_key) {
575 // Create sub key type, depending on private key's algorithm type.
576 PrivateKeyType key_type = GetPrivateKeyType(private_key);
577 switch (key_type) {
578 case PRIVATE_KEY_TYPE_RSA:
579 return GetRsaPkeyWrapper(private_key);
580 case PRIVATE_KEY_TYPE_ECDSA:
581 return GetEcdsaPkeyWrapper(private_key);
582 default:
583 LOG(WARNING)
584 << "GetOpenSSLPrivateKeyWrapper() called with invalid key type";
585 return nullptr;
589 } // namespace android
590 } // namespace net