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