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 584