Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / net / android / keystore_openssl.cc
blobfb0365c6a8d53f9500631b2be276b0acbde6dda0
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/ec.h>
10 #include <openssl/engine.h>
11 #include <openssl/err.h>
12 #include <openssl/evp.h>
13 #include <openssl/rsa.h>
14 #include <stdint.h>
16 #include "base/android/build_info.h"
17 #include "base/android/jni_android.h"
18 #include "base/android/scoped_java_ref.h"
19 #include "base/lazy_instance.h"
20 #include "base/logging.h"
21 #include "crypto/openssl_util.h"
22 #include "net/android/keystore.h"
23 #include "net/android/legacy_openssl.h"
24 #include "net/ssl/scoped_openssl_types.h"
25 #include "net/ssl/ssl_client_cert_type.h"
27 // IMPORTANT NOTE: The following code will currently only work when used
28 // to implement client certificate support with OpenSSL. That's because
29 // only the signing operations used in this use case are implemented here.
31 // Generally speaking, OpenSSL provides many different ways to sign
32 // digests. This code doesn't support all these cases, only the ones that
33 // are required to sign the digest during the OpenSSL handshake for TLS.
35 // The OpenSSL EVP_PKEY type is a generic wrapper around key pairs.
36 // Internally, it can hold a pointer to a RSA or ECDSA structure, which model
37 // keypair implementations of each respective crypto algorithm.
39 // The RSA type has a 'method' field pointer to a vtable-like structure
40 // called a RSA_METHOD. This contains several function pointers that
41 // correspond to operations on RSA keys (e.g. decode/encode with public
42 // key, decode/encode with private key, signing, validation), as well as
43 // a few flags.
45 // For example, the RSA_sign() function will call "method->rsa_sign()" if
46 // method->rsa_sign is not NULL, otherwise, it will perform a regular
47 // signing operation using the other fields in the RSA structure (which
48 // are used to hold the typical modulus / exponent / parameters for the
49 // key pair).
51 // This source file thus defines a custom RSA_METHOD structure whose
52 // fields point to static methods used to implement the corresponding
53 // RSA operation using platform Android APIs.
55 // However, the platform APIs require a jobject JNI reference to work. It must
56 // be stored in the RSA instance, or made accessible when the custom RSA
57 // methods are called. This is done by storing it in a |KeyExData| structure
58 // that's referenced by the key using |EX_DATA|.
60 using base::android::ScopedJavaGlobalRef;
61 using base::android::ScopedJavaLocalRef;
63 namespace net {
64 namespace android {
66 namespace {
68 extern const RSA_METHOD android_rsa_method;
69 extern const ECDSA_METHOD android_ecdsa_method;
71 // KeyExData contains the data that is contained in the EX_DATA of the RSA and
72 // EC_KEY objects that are created to wrap Android system keys.
73 struct KeyExData {
74 // private_key contains a reference to a Java, private-key object.
75 jobject private_key;
76 // legacy_rsa, if not NULL, points to an RSA* in the system's OpenSSL (which
77 // might not be ABI compatible with Chromium).
78 AndroidRSA* legacy_rsa;
79 // cached_size contains the "size" of the key. This is the size of the
80 // modulus (in bytes) for RSA, or the group order size for ECDSA. This
81 // avoids calling into Java to calculate the size.
82 size_t cached_size;
85 // ExDataDup is called when one of the RSA or EC_KEY objects is duplicated. We
86 // don't support this and it should never happen.
87 int ExDataDup(CRYPTO_EX_DATA* to,
88 const CRYPTO_EX_DATA* from,
89 void** from_d,
90 int index,
91 long argl,
92 void* argp) {
93 CHECK_EQ((void*)NULL, *from_d);
94 return 0;
97 // ExDataFree is called when one of the RSA or EC_KEY objects is freed.
98 void ExDataFree(void* parent,
99 void* ptr,
100 CRYPTO_EX_DATA* ad,
101 int index,
102 long argl,
103 void* argp) {
104 // Ensure the global JNI reference created with this wrapper is
105 // properly destroyed with it.
106 KeyExData *ex_data = reinterpret_cast<KeyExData*>(ptr);
107 if (ex_data != NULL) {
108 ReleaseKey(ex_data->private_key);
109 delete ex_data;
113 // BoringSSLEngine is a BoringSSL ENGINE that implements RSA and ECDSA by
114 // forwarding the requested operations to the Java libraries.
115 class BoringSSLEngine {
116 public:
117 BoringSSLEngine()
118 : rsa_index_(RSA_get_ex_new_index(0 /* argl */,
119 NULL /* argp */,
120 NULL /* new_func */,
121 ExDataDup,
122 ExDataFree)),
123 ec_key_index_(EC_KEY_get_ex_new_index(0 /* argl */,
124 NULL /* argp */,
125 NULL /* new_func */,
126 ExDataDup,
127 ExDataFree)),
128 engine_(ENGINE_new()) {
129 ENGINE_set_RSA_method(
130 engine_, &android_rsa_method, sizeof(android_rsa_method));
131 ENGINE_set_ECDSA_method(
132 engine_, &android_ecdsa_method, sizeof(android_ecdsa_method));
135 int rsa_ex_index() const { return rsa_index_; }
136 int ec_key_ex_index() const { return ec_key_index_; }
138 const ENGINE* engine() const { return engine_; }
140 private:
141 const int rsa_index_;
142 const int ec_key_index_;
143 ENGINE* const engine_;
146 base::LazyInstance<BoringSSLEngine>::Leaky global_boringssl_engine =
147 LAZY_INSTANCE_INITIALIZER;
150 // VectorBignumSize returns the number of bytes needed to represent the bignum
151 // given in |v|, i.e. the length of |v| less any leading zero bytes.
152 size_t VectorBignumSize(const std::vector<uint8_t>& v) {
153 size_t size = v.size();
154 // Ignore any leading zero bytes.
155 for (size_t i = 0; i < v.size() && v[i] == 0; i++) {
156 size--;
158 return size;
161 KeyExData* RsaGetExData(const RSA* rsa) {
162 return reinterpret_cast<KeyExData*>(
163 RSA_get_ex_data(rsa, global_boringssl_engine.Get().rsa_ex_index()));
166 size_t RsaMethodSize(const RSA *rsa) {
167 const KeyExData *ex_data = RsaGetExData(rsa);
168 return ex_data->cached_size;
171 int RsaMethodEncrypt(RSA* rsa,
172 size_t* out_len,
173 uint8_t* out,
174 size_t max_out,
175 const uint8_t* in,
176 size_t in_len,
177 int padding) {
178 NOTIMPLEMENTED();
179 OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_ALGORITHM_TYPE);
180 return 0;
183 int RsaMethodSignRaw(RSA* rsa,
184 size_t* out_len,
185 uint8_t* out,
186 size_t max_out,
187 const uint8_t* in,
188 size_t in_len,
189 int padding) {
190 DCHECK_EQ(RSA_PKCS1_PADDING, padding);
191 if (padding != RSA_PKCS1_PADDING) {
192 // TODO(davidben): If we need to, we can implement RSA_NO_PADDING
193 // by using javax.crypto.Cipher and picking either the
194 // "RSA/ECB/NoPadding" or "RSA/ECB/PKCS1Padding" transformation as
195 // appropriate. I believe support for both of these was added in
196 // the same Android version as the "NONEwithRSA"
197 // java.security.Signature algorithm, so the same version checks
198 // for GetRsaLegacyKey should work.
199 OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE);
200 return 0;
203 // Retrieve private key JNI reference.
204 const KeyExData *ex_data = RsaGetExData(rsa);
205 if (!ex_data || !ex_data->private_key) {
206 LOG(WARNING) << "Null JNI reference passed to RsaMethodSignRaw!";
207 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
208 return 0;
211 // Pre-4.2 legacy codepath.
212 if (ex_data->legacy_rsa) {
213 int ret = ex_data->legacy_rsa->meth->rsa_priv_enc(
214 in_len, in, out, ex_data->legacy_rsa, ANDROID_RSA_PKCS1_PADDING);
215 if (ret < 0) {
216 LOG(WARNING) << "Could not sign message in RsaMethodSignRaw!";
217 // System OpenSSL will use a separate error queue, so it is still
218 // necessary to push a new error.
220 // TODO(davidben): It would be good to also clear the system error queue
221 // if there were some way to convince Java to do it. (Without going
222 // through Java, it's difficult to get a handle on a system OpenSSL
223 // function; dlopen loads a second copy.)
224 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
225 return 0;
227 *out_len = ret;
228 return 1;
231 base::StringPiece from_piece(reinterpret_cast<const char*>(in), in_len);
232 std::vector<uint8_t> result;
233 // For RSA keys, this function behaves as RSA_private_encrypt with
234 // PKCS#1 padding.
235 if (!RawSignDigestWithPrivateKey(ex_data->private_key, from_piece, &result)) {
236 LOG(WARNING) << "Could not sign message in RsaMethodSignRaw!";
237 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
238 return 0;
241 size_t expected_size = static_cast<size_t>(RSA_size(rsa));
242 if (result.size() > expected_size) {
243 LOG(ERROR) << "RSA Signature size mismatch, actual: "
244 << result.size() << ", expected <= " << expected_size;
245 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
246 return 0;
249 if (max_out < expected_size) {
250 OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
251 return 0;
254 // Copy result to OpenSSL-provided buffer. RawSignDigestWithPrivateKey
255 // should pad with leading 0s, but if it doesn't, pad the result.
256 size_t zero_pad = expected_size - result.size();
257 memset(out, 0, zero_pad);
258 memcpy(out + zero_pad, &result[0], result.size());
259 *out_len = expected_size;
261 return 1;
264 int RsaMethodDecrypt(RSA* rsa,
265 size_t* out_len,
266 uint8_t* out,
267 size_t max_out,
268 const uint8_t* in,
269 size_t in_len,
270 int padding) {
271 NOTIMPLEMENTED();
272 OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_ALGORITHM_TYPE);
273 return 0;
276 int RsaMethodVerifyRaw(RSA* rsa,
277 size_t* out_len,
278 uint8_t* out,
279 size_t max_out,
280 const uint8_t* in,
281 size_t in_len,
282 int padding) {
283 NOTIMPLEMENTED();
284 OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_ALGORITHM_TYPE);
285 return 0;
288 const RSA_METHOD android_rsa_method = {
290 0 /* references */,
291 1 /* is_static */
292 } /* common */,
293 nullptr /* app_data */,
295 nullptr /* init */,
296 nullptr /* finish */,
297 RsaMethodSize,
298 nullptr /* sign */,
299 nullptr /* verify */,
300 RsaMethodEncrypt,
301 RsaMethodSignRaw,
302 RsaMethodDecrypt,
303 RsaMethodVerifyRaw,
304 nullptr /* private_transform */,
305 nullptr /* mod_exp */,
306 nullptr /* bn_mod_exp */,
307 RSA_FLAG_OPAQUE,
308 nullptr /* keygen */,
309 nullptr /* multi_prime_keygen */,
310 nullptr /* supports_digest */,
313 // Setup an EVP_PKEY to wrap an existing platform RSA PrivateKey object.
314 // |private_key| is the JNI reference (local or global) to the object.
315 // |legacy_rsa|, if non-NULL, is a pointer to the system OpenSSL RSA object
316 // backing |private_key|. This parameter is only used for Android < 4.2 to
317 // implement key operations not exposed by the platform.
318 // Returns a new EVP_PKEY on success, NULL otherwise.
319 // On success, this creates a new global JNI reference to the object
320 // that is owned by and destroyed with the EVP_PKEY. I.e. caller can
321 // free |private_key| after the call.
322 crypto::ScopedEVP_PKEY CreateRsaPkeyWrapper(
323 jobject private_key,
324 AndroidRSA* legacy_rsa,
325 const crypto::OpenSSLErrStackTracer& tracer) {
326 crypto::ScopedRSA rsa(
327 RSA_new_method(global_boringssl_engine.Get().engine()));
329 ScopedJavaGlobalRef<jobject> global_key;
330 global_key.Reset(NULL, private_key);
331 if (global_key.is_null()) {
332 LOG(ERROR) << "Could not create global JNI reference";
333 return crypto::ScopedEVP_PKEY();
336 std::vector<uint8_t> modulus;
337 if (!GetRSAKeyModulus(private_key, &modulus)) {
338 LOG(ERROR) << "Failed to get private key modulus";
339 return crypto::ScopedEVP_PKEY();
342 KeyExData* ex_data = new KeyExData;
343 ex_data->private_key = global_key.Release();
344 ex_data->legacy_rsa = legacy_rsa;
345 ex_data->cached_size = VectorBignumSize(modulus);
346 RSA_set_ex_data(
347 rsa.get(), global_boringssl_engine.Get().rsa_ex_index(), ex_data);
349 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new());
350 if (!pkey ||
351 !EVP_PKEY_set1_RSA(pkey.get(), rsa.get())) {
352 return crypto::ScopedEVP_PKEY();
354 return pkey.Pass();
357 // On Android < 4.2, the libkeystore.so ENGINE uses CRYPTO_EX_DATA and is not
358 // added to the global engine list. If all references to it are dropped, OpenSSL
359 // will dlclose the module, leaving a dangling function pointer in the RSA
360 // CRYPTO_EX_DATA class. To work around this, leak an extra reference to the
361 // ENGINE we extract in GetRsaLegacyKey.
363 // In 4.2, this change avoids the problem:
364 // https://android.googlesource.com/platform/libcore/+/106a8928fb4249f2f3d4dba1dddbe73ca5cb3d61
366 // https://crbug.com/381465
367 class KeystoreEngineWorkaround {
368 public:
369 KeystoreEngineWorkaround() {}
371 void LeakEngine(jobject private_key) {
372 if (!engine_.is_null())
373 return;
374 ScopedJavaLocalRef<jobject> engine =
375 GetOpenSSLEngineForPrivateKey(private_key);
376 if (engine.is_null()) {
377 NOTREACHED();
378 return;
380 engine_.Reset(engine);
383 private:
384 ScopedJavaGlobalRef<jobject> engine_;
387 void LeakEngine(jobject private_key) {
388 static base::LazyInstance<KeystoreEngineWorkaround>::Leaky s_instance =
389 LAZY_INSTANCE_INITIALIZER;
390 s_instance.Get().LeakEngine(private_key);
393 // Creates an EVP_PKEY wrapper corresponding to the RSA key
394 // |private_key|. Returns nullptr on failure.
395 crypto::ScopedEVP_PKEY GetRsaPkeyWrapper(jobject private_key) {
396 const int kAndroid42ApiLevel = 17;
397 crypto::OpenSSLErrStackTracer tracer(FROM_HERE);
399 if (base::android::BuildInfo::GetInstance()->sdk_int() >=
400 kAndroid42ApiLevel) {
401 return CreateRsaPkeyWrapper(private_key, nullptr, tracer);
404 // Route around platform limitation: if Android < 4.2, then
405 // base::android::RawSignDigestWithPrivateKey() cannot work, so try to get the
406 // system OpenSSL's EVP_PKEY backing this PrivateKey object.
407 AndroidEVP_PKEY* sys_pkey =
408 GetOpenSSLSystemHandleForPrivateKey(private_key);
409 if (sys_pkey == nullptr)
410 return nullptr;
412 if (sys_pkey->type != ANDROID_EVP_PKEY_RSA) {
413 LOG(ERROR) << "Private key has wrong type!";
414 return nullptr;
417 AndroidRSA* sys_rsa = sys_pkey->pkey.rsa;
418 if (sys_rsa->engine) {
419 // |private_key| may not have an engine if the PrivateKey did not come
420 // from the key store, such as in unit tests.
421 if (strcmp(sys_rsa->engine->id, "keystore") == 0) {
422 LeakEngine(private_key);
423 } else {
424 NOTREACHED();
428 return CreateRsaPkeyWrapper(private_key, sys_rsa, tracer);
431 // Custom ECDSA_METHOD that uses the platform APIs.
432 // Note that for now, only signing through ECDSA_sign() is really supported.
433 // all other method pointers are either stubs returning errors, or no-ops.
435 jobject EcKeyGetKey(const EC_KEY* ec_key) {
436 KeyExData* ex_data = reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data(
437 ec_key, global_boringssl_engine.Get().ec_key_ex_index()));
438 return ex_data->private_key;
441 size_t EcdsaMethodGroupOrderSize(const EC_KEY* ec_key) {
442 KeyExData* ex_data = reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data(
443 ec_key, global_boringssl_engine.Get().ec_key_ex_index()));
444 return ex_data->cached_size;
447 int EcdsaMethodSign(const uint8_t* digest,
448 size_t digest_len,
449 uint8_t* sig,
450 unsigned int* sig_len,
451 EC_KEY* ec_key) {
452 // Retrieve private key JNI reference.
453 jobject private_key = EcKeyGetKey(ec_key);
454 if (!private_key) {
455 LOG(WARNING) << "Null JNI reference passed to EcdsaMethodSign!";
456 return 0;
458 // Sign message with it through JNI.
459 std::vector<uint8_t> signature;
460 base::StringPiece digest_sp(reinterpret_cast<const char*>(digest),
461 digest_len);
462 if (!RawSignDigestWithPrivateKey(private_key, digest_sp, &signature)) {
463 LOG(WARNING) << "Could not sign message in EcdsaMethodSign!";
464 return 0;
467 // Note: With ECDSA, the actual signature may be smaller than
468 // ECDSA_size().
469 size_t max_expected_size = ECDSA_size(ec_key);
470 if (signature.size() > max_expected_size) {
471 LOG(ERROR) << "ECDSA Signature size mismatch, actual: "
472 << signature.size() << ", expected <= "
473 << max_expected_size;
474 return 0;
477 memcpy(sig, &signature[0], signature.size());
478 *sig_len = signature.size();
479 return 1;
482 int EcdsaMethodVerify(const uint8_t* digest,
483 size_t digest_len,
484 const uint8_t* sig,
485 size_t sig_len,
486 EC_KEY* ec_key) {
487 NOTIMPLEMENTED();
488 OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_NOT_IMPLEMENTED);
489 return 0;
492 // Setup an EVP_PKEY to wrap an existing platform PrivateKey object.
493 // |private_key| is the JNI reference (local or global) to the object.
494 // Returns a new EVP_PKEY on success, NULL otherwise.
495 // On success, this creates a global JNI reference to the object that
496 // is owned by and destroyed with the EVP_PKEY. I.e. the caller shall
497 // always free |private_key| after the call.
498 crypto::ScopedEVP_PKEY GetEcdsaPkeyWrapper(jobject private_key) {
499 crypto::OpenSSLErrStackTracer tracer(FROM_HERE);
500 crypto::ScopedEC_KEY ec_key(
501 EC_KEY_new_method(global_boringssl_engine.Get().engine()));
503 ScopedJavaGlobalRef<jobject> global_key;
504 global_key.Reset(NULL, private_key);
505 if (global_key.is_null()) {
506 LOG(ERROR) << "Can't create global JNI reference";
507 return crypto::ScopedEVP_PKEY();
510 std::vector<uint8_t> order;
511 if (!GetECKeyOrder(private_key, &order)) {
512 LOG(ERROR) << "Can't extract order parameter from EC private key";
513 return crypto::ScopedEVP_PKEY();
516 KeyExData* ex_data = new KeyExData;
517 ex_data->private_key = global_key.Release();
518 ex_data->legacy_rsa = NULL;
519 ex_data->cached_size = VectorBignumSize(order);
521 EC_KEY_set_ex_data(
522 ec_key.get(), global_boringssl_engine.Get().ec_key_ex_index(), ex_data);
524 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new());
525 if (!pkey ||
526 !EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get())) {
527 return crypto::ScopedEVP_PKEY();
529 return pkey.Pass();
532 const ECDSA_METHOD android_ecdsa_method = {
534 0 /* references */,
535 1 /* is_static */
536 } /* common */,
537 NULL /* app_data */,
539 NULL /* init */,
540 NULL /* finish */,
541 EcdsaMethodGroupOrderSize,
542 EcdsaMethodSign,
543 EcdsaMethodVerify,
544 ECDSA_FLAG_OPAQUE,
547 } // namespace
549 crypto::ScopedEVP_PKEY GetOpenSSLPrivateKeyWrapper(jobject private_key) {
550 // Create sub key type, depending on private key's algorithm type.
551 PrivateKeyType key_type = GetPrivateKeyType(private_key);
552 switch (key_type) {
553 case PRIVATE_KEY_TYPE_RSA:
554 return GetRsaPkeyWrapper(private_key);
555 case PRIVATE_KEY_TYPE_ECDSA:
556 return GetEcdsaPkeyWrapper(private_key);
557 default:
558 LOG(WARNING)
559 << "GetOpenSSLPrivateKeyWrapper() called with invalid key type";
560 return nullptr;
564 } // namespace android
565 } // namespace net