| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/android/keystore_openssl.h" | 5 #include "net/android/keystore_impl.h" |
| 6 | 6 |
| 7 #include <jni.h> | 7 #include <jni.h> |
| 8 #include <openssl/bn.h> | 8 #include <openssl/bn.h> |
| 9 #include <openssl/ec.h> | 9 #include <openssl/ec.h> |
| 10 #include <openssl/engine.h> | 10 #include <openssl/engine.h> |
| 11 #include <openssl/err.h> | 11 #include <openssl/err.h> |
| 12 #include <openssl/evp.h> | 12 #include <openssl/evp.h> |
| 13 #include <openssl/rsa.h> | 13 #include <openssl/rsa.h> |
| 14 #include <stdint.h> | 14 #include <stdint.h> |
| 15 | 15 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 | 97 |
| 98 // ExDataFree is called when one of the RSA or EC_KEY objects is freed. | 98 // ExDataFree is called when one of the RSA or EC_KEY objects is freed. |
| 99 void ExDataFree(void* parent, | 99 void ExDataFree(void* parent, |
| 100 void* ptr, | 100 void* ptr, |
| 101 CRYPTO_EX_DATA* ad, | 101 CRYPTO_EX_DATA* ad, |
| 102 int index, | 102 int index, |
| 103 long argl, | 103 long argl, |
| 104 void* argp) { | 104 void* argp) { |
| 105 // Ensure the global JNI reference created with this wrapper is | 105 // Ensure the global JNI reference created with this wrapper is |
| 106 // properly destroyed with it. | 106 // properly destroyed with it. |
| 107 KeyExData *ex_data = reinterpret_cast<KeyExData*>(ptr); | 107 KeyExData* ex_data = reinterpret_cast<KeyExData*>(ptr); |
| 108 delete ex_data; | 108 delete ex_data; |
| 109 } | 109 } |
| 110 | 110 |
| 111 // BoringSSLEngine is a BoringSSL ENGINE that implements RSA and ECDSA by | 111 // BoringSSLEngine is a BoringSSL ENGINE that implements RSA and ECDSA by |
| 112 // forwarding the requested operations to the Java libraries. | 112 // forwarding the requested operations to the Java libraries. |
| 113 class BoringSSLEngine { | 113 class BoringSSLEngine { |
| 114 public: | 114 public: |
| 115 BoringSSLEngine() | 115 BoringSSLEngine() |
| 116 : rsa_index_(RSA_get_ex_new_index(0 /* argl */, | 116 : rsa_index_(RSA_get_ex_new_index(0 /* argl */, |
| 117 NULL /* argp */, | 117 NULL /* argp */, |
| 118 NULL /* new_func */, | 118 NULL /* new_func */, |
| 119 ExDataDup, | 119 ExDataDup, |
| 120 ExDataFree)), | 120 ExDataFree)), |
| 121 ec_key_index_(EC_KEY_get_ex_new_index(0 /* argl */, | 121 ec_key_index_(EC_KEY_get_ex_new_index(0 /* argl */, |
| 122 NULL /* argp */, | 122 NULL /* argp */, |
| 123 NULL /* new_func */, | 123 NULL /* new_func */, |
| 124 ExDataDup, | 124 ExDataDup, |
| 125 ExDataFree)), | 125 ExDataFree)), |
| 126 engine_(ENGINE_new()) { | 126 engine_(ENGINE_new()) { |
| 127 ENGINE_set_RSA_method( | 127 ENGINE_set_RSA_method(engine_, &android_rsa_method, |
| 128 engine_, &android_rsa_method, sizeof(android_rsa_method)); | 128 sizeof(android_rsa_method)); |
| 129 ENGINE_set_ECDSA_method( | 129 ENGINE_set_ECDSA_method(engine_, &android_ecdsa_method, |
| 130 engine_, &android_ecdsa_method, sizeof(android_ecdsa_method)); | 130 sizeof(android_ecdsa_method)); |
| 131 } | 131 } |
| 132 | 132 |
| 133 int rsa_ex_index() const { return rsa_index_; } | 133 int rsa_ex_index() const { return rsa_index_; } |
| 134 int ec_key_ex_index() const { return ec_key_index_; } | 134 int ec_key_ex_index() const { return ec_key_index_; } |
| 135 | 135 |
| 136 const ENGINE* engine() const { return engine_; } | 136 const ENGINE* engine() const { return engine_; } |
| 137 | 137 |
| 138 private: | 138 private: |
| 139 const int rsa_index_; | 139 const int rsa_index_; |
| 140 const int ec_key_index_; | 140 const int ec_key_index_; |
| 141 ENGINE* const engine_; | 141 ENGINE* const engine_; |
| 142 }; | 142 }; |
| 143 | 143 |
| 144 base::LazyInstance<BoringSSLEngine>::Leaky global_boringssl_engine = | 144 base::LazyInstance<BoringSSLEngine>::Leaky global_boringssl_engine = |
| 145 LAZY_INSTANCE_INITIALIZER; | 145 LAZY_INSTANCE_INITIALIZER; |
| 146 | 146 |
| 147 | |
| 148 // VectorBignumSize returns the number of bytes needed to represent the bignum | 147 // VectorBignumSize returns the number of bytes needed to represent the bignum |
| 149 // given in |v|, i.e. the length of |v| less any leading zero bytes. | 148 // given in |v|, i.e. the length of |v| less any leading zero bytes. |
| 150 size_t VectorBignumSize(const std::vector<uint8_t>& v) { | 149 size_t VectorBignumSize(const std::vector<uint8_t>& v) { |
| 151 size_t size = v.size(); | 150 size_t size = v.size(); |
| 152 // Ignore any leading zero bytes. | 151 // Ignore any leading zero bytes. |
| 153 for (size_t i = 0; i < v.size() && v[i] == 0; i++) { | 152 for (size_t i = 0; i < v.size() && v[i] == 0; i++) { |
| 154 size--; | 153 size--; |
| 155 } | 154 } |
| 156 return size; | 155 return size; |
| 157 } | 156 } |
| 158 | 157 |
| 159 KeyExData* RsaGetExData(const RSA* rsa) { | 158 KeyExData* RsaGetExData(const RSA* rsa) { |
| 160 return reinterpret_cast<KeyExData*>( | 159 return reinterpret_cast<KeyExData*>( |
| 161 RSA_get_ex_data(rsa, global_boringssl_engine.Get().rsa_ex_index())); | 160 RSA_get_ex_data(rsa, global_boringssl_engine.Get().rsa_ex_index())); |
| 162 } | 161 } |
| 163 | 162 |
| 164 size_t RsaMethodSize(const RSA *rsa) { | 163 size_t RsaMethodSize(const RSA* rsa) { |
| 165 const KeyExData *ex_data = RsaGetExData(rsa); | 164 const KeyExData* ex_data = RsaGetExData(rsa); |
| 166 return ex_data->cached_size; | 165 return ex_data->cached_size; |
| 167 } | 166 } |
| 168 | 167 |
| 169 int RsaMethodEncrypt(RSA* rsa, | 168 int RsaMethodEncrypt(RSA* rsa, |
| 170 size_t* out_len, | 169 size_t* out_len, |
| 171 uint8_t* out, | 170 uint8_t* out, |
| 172 size_t max_out, | 171 size_t max_out, |
| 173 const uint8_t* in, | 172 const uint8_t* in, |
| 174 size_t in_len, | 173 size_t in_len, |
| 175 int padding) { | 174 int padding) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 192 // "RSA/ECB/NoPadding" or "RSA/ECB/PKCS1Padding" transformation as | 191 // "RSA/ECB/NoPadding" or "RSA/ECB/PKCS1Padding" transformation as |
| 193 // appropriate. I believe support for both of these was added in | 192 // appropriate. I believe support for both of these was added in |
| 194 // the same Android version as the "NONEwithRSA" | 193 // the same Android version as the "NONEwithRSA" |
| 195 // java.security.Signature algorithm, so the same version checks | 194 // java.security.Signature algorithm, so the same version checks |
| 196 // for GetRsaLegacyKey should work. | 195 // for GetRsaLegacyKey should work. |
| 197 OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE); | 196 OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE); |
| 198 return 0; | 197 return 0; |
| 199 } | 198 } |
| 200 | 199 |
| 201 // Retrieve private key JNI reference. | 200 // Retrieve private key JNI reference. |
| 202 const KeyExData *ex_data = RsaGetExData(rsa); | 201 const KeyExData* ex_data = RsaGetExData(rsa); |
| 203 if (!ex_data || !ex_data->private_key.obj()) { | 202 if (!ex_data || !ex_data->private_key.obj()) { |
| 204 LOG(WARNING) << "Null JNI reference passed to RsaMethodSignRaw!"; | 203 LOG(WARNING) << "Null JNI reference passed to RsaMethodSignRaw!"; |
| 205 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); | 204 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); |
| 206 return 0; | 205 return 0; |
| 207 } | 206 } |
| 208 | 207 |
| 209 // Pre-4.2 legacy codepath. | 208 // Pre-4.2 legacy codepath. |
| 210 if (ex_data->legacy_rsa) { | 209 if (ex_data->legacy_rsa) { |
| 211 int ret = ex_data->legacy_rsa->meth->rsa_priv_enc( | 210 int ret = ex_data->legacy_rsa->meth->rsa_priv_enc( |
| 212 in_len, in, out, ex_data->legacy_rsa, ANDROID_RSA_PKCS1_PADDING); | 211 in_len, in, out, ex_data->legacy_rsa, ANDROID_RSA_PKCS1_PADDING); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 232 // PKCS#1 padding. | 231 // PKCS#1 padding. |
| 233 if (!RawSignDigestWithPrivateKey(ex_data->private_key.obj(), from_piece, | 232 if (!RawSignDigestWithPrivateKey(ex_data->private_key.obj(), from_piece, |
| 234 &result)) { | 233 &result)) { |
| 235 LOG(WARNING) << "Could not sign message in RsaMethodSignRaw!"; | 234 LOG(WARNING) << "Could not sign message in RsaMethodSignRaw!"; |
| 236 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); | 235 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); |
| 237 return 0; | 236 return 0; |
| 238 } | 237 } |
| 239 | 238 |
| 240 size_t expected_size = static_cast<size_t>(RSA_size(rsa)); | 239 size_t expected_size = static_cast<size_t>(RSA_size(rsa)); |
| 241 if (result.size() > expected_size) { | 240 if (result.size() > expected_size) { |
| 242 LOG(ERROR) << "RSA Signature size mismatch, actual: " | 241 LOG(ERROR) << "RSA Signature size mismatch, actual: " << result.size() |
| 243 << result.size() << ", expected <= " << expected_size; | 242 << ", expected <= " << expected_size; |
| 244 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); | 243 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); |
| 245 return 0; | 244 return 0; |
| 246 } | 245 } |
| 247 | 246 |
| 248 if (max_out < expected_size) { | 247 if (max_out < expected_size) { |
| 249 OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE); | 248 OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE); |
| 250 return 0; | 249 return 0; |
| 251 } | 250 } |
| 252 | 251 |
| 253 // Copy result to OpenSSL-provided buffer. RawSignDigestWithPrivateKey | 252 // Copy result to OpenSSL-provided buffer. RawSignDigestWithPrivateKey |
| (...skipping 25 matching lines...) Expand all Loading... |
| 279 const uint8_t* in, | 278 const uint8_t* in, |
| 280 size_t in_len, | 279 size_t in_len, |
| 281 int padding) { | 280 int padding) { |
| 282 NOTIMPLEMENTED(); | 281 NOTIMPLEMENTED(); |
| 283 OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_ALGORITHM_TYPE); | 282 OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_ALGORITHM_TYPE); |
| 284 return 0; | 283 return 0; |
| 285 } | 284 } |
| 286 | 285 |
| 287 const RSA_METHOD android_rsa_method = { | 286 const RSA_METHOD android_rsa_method = { |
| 288 { | 287 { |
| 289 0 /* references */, | 288 0 /* references */, 1 /* is_static */ |
| 290 1 /* is_static */ | |
| 291 } /* common */, | 289 } /* common */, |
| 292 nullptr /* app_data */, | 290 nullptr /* app_data */, |
| 293 | 291 |
| 294 nullptr /* init */, | 292 nullptr /* init */, |
| 295 nullptr /* finish */, | 293 nullptr /* finish */, |
| 296 RsaMethodSize, | 294 RsaMethodSize, |
| 297 nullptr /* sign */, | 295 nullptr /* sign */, |
| 298 nullptr /* verify */, | 296 nullptr /* verify */, |
| 299 RsaMethodEncrypt, | 297 RsaMethodEncrypt, |
| 300 RsaMethodSignRaw, | 298 RsaMethodSignRaw, |
| (...skipping 14 matching lines...) Expand all Loading... |
| 315 // backing |private_key|. This parameter is only used for Android < 4.2 to | 313 // backing |private_key|. This parameter is only used for Android < 4.2 to |
| 316 // implement key operations not exposed by the platform. | 314 // implement key operations not exposed by the platform. |
| 317 // Returns a new EVP_PKEY on success, NULL otherwise. | 315 // Returns a new EVP_PKEY on success, NULL otherwise. |
| 318 // On success, this creates a new global JNI reference to the object | 316 // 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 | 317 // that is owned by and destroyed with the EVP_PKEY. I.e. caller can |
| 320 // free |private_key| after the call. | 318 // free |private_key| after the call. |
| 321 crypto::ScopedEVP_PKEY CreateRsaPkeyWrapper( | 319 crypto::ScopedEVP_PKEY CreateRsaPkeyWrapper( |
| 322 jobject private_key, | 320 jobject private_key, |
| 323 AndroidRSA* legacy_rsa, | 321 AndroidRSA* legacy_rsa, |
| 324 const crypto::OpenSSLErrStackTracer& tracer) { | 322 const crypto::OpenSSLErrStackTracer& tracer) { |
| 325 crypto::ScopedRSA rsa( | 323 crypto::ScopedRSA rsa(RSA_new_method(global_boringssl_engine.Get().engine())); |
| 326 RSA_new_method(global_boringssl_engine.Get().engine())); | |
| 327 | 324 |
| 328 std::vector<uint8_t> modulus; | 325 std::vector<uint8_t> modulus; |
| 329 if (!GetRSAKeyModulus(private_key, &modulus)) { | 326 if (!GetRSAKeyModulus(private_key, &modulus)) { |
| 330 LOG(ERROR) << "Failed to get private key modulus"; | 327 LOG(ERROR) << "Failed to get private key modulus"; |
| 331 return nullptr; | 328 return nullptr; |
| 332 } | 329 } |
| 333 | 330 |
| 334 std::unique_ptr<KeyExData> ex_data(new KeyExData); | 331 std::unique_ptr<KeyExData> ex_data(new KeyExData); |
| 335 ex_data->private_key.Reset(nullptr, private_key); | 332 ex_data->private_key.Reset(nullptr, private_key); |
| 336 if (ex_data->private_key.is_null()) { | 333 if (ex_data->private_key.is_null()) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 392 crypto::OpenSSLErrStackTracer tracer(FROM_HERE); | 389 crypto::OpenSSLErrStackTracer tracer(FROM_HERE); |
| 393 | 390 |
| 394 if (base::android::BuildInfo::GetInstance()->sdk_int() >= | 391 if (base::android::BuildInfo::GetInstance()->sdk_int() >= |
| 395 kAndroid42ApiLevel) { | 392 kAndroid42ApiLevel) { |
| 396 return CreateRsaPkeyWrapper(private_key, nullptr, tracer); | 393 return CreateRsaPkeyWrapper(private_key, nullptr, tracer); |
| 397 } | 394 } |
| 398 | 395 |
| 399 // Route around platform limitation: if Android < 4.2, then | 396 // Route around platform limitation: if Android < 4.2, then |
| 400 // base::android::RawSignDigestWithPrivateKey() cannot work, so try to get the | 397 // base::android::RawSignDigestWithPrivateKey() cannot work, so try to get the |
| 401 // system OpenSSL's EVP_PKEY backing this PrivateKey object. | 398 // system OpenSSL's EVP_PKEY backing this PrivateKey object. |
| 402 AndroidEVP_PKEY* sys_pkey = | 399 AndroidEVP_PKEY* sys_pkey = GetOpenSSLSystemHandleForPrivateKey(private_key); |
| 403 GetOpenSSLSystemHandleForPrivateKey(private_key); | |
| 404 if (sys_pkey == nullptr) | 400 if (sys_pkey == nullptr) |
| 405 return nullptr; | 401 return nullptr; |
| 406 | 402 |
| 407 if (sys_pkey->type != ANDROID_EVP_PKEY_RSA) { | 403 if (sys_pkey->type != ANDROID_EVP_PKEY_RSA) { |
| 408 LOG(ERROR) << "Private key has wrong type!"; | 404 LOG(ERROR) << "Private key has wrong type!"; |
| 409 return nullptr; | 405 return nullptr; |
| 410 } | 406 } |
| 411 | 407 |
| 412 AndroidRSA* sys_rsa = sys_pkey->pkey.rsa; | 408 AndroidRSA* sys_rsa = sys_pkey->pkey.rsa; |
| 413 if (sys_rsa->engine) { | 409 if (sys_rsa->engine) { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 456 digest_len); | 452 digest_len); |
| 457 if (!RawSignDigestWithPrivateKey(private_key, digest_sp, &signature)) { | 453 if (!RawSignDigestWithPrivateKey(private_key, digest_sp, &signature)) { |
| 458 LOG(WARNING) << "Could not sign message in EcdsaMethodSign!"; | 454 LOG(WARNING) << "Could not sign message in EcdsaMethodSign!"; |
| 459 return 0; | 455 return 0; |
| 460 } | 456 } |
| 461 | 457 |
| 462 // Note: With ECDSA, the actual signature may be smaller than | 458 // Note: With ECDSA, the actual signature may be smaller than |
| 463 // ECDSA_size(). | 459 // ECDSA_size(). |
| 464 size_t max_expected_size = ECDSA_size(ec_key); | 460 size_t max_expected_size = ECDSA_size(ec_key); |
| 465 if (signature.size() > max_expected_size) { | 461 if (signature.size() > max_expected_size) { |
| 466 LOG(ERROR) << "ECDSA Signature size mismatch, actual: " | 462 LOG(ERROR) << "ECDSA Signature size mismatch, actual: " << signature.size() |
| 467 << signature.size() << ", expected <= " | 463 << ", expected <= " << max_expected_size; |
| 468 << max_expected_size; | |
| 469 return 0; | 464 return 0; |
| 470 } | 465 } |
| 471 | 466 |
| 472 memcpy(sig, &signature[0], signature.size()); | 467 memcpy(sig, &signature[0], signature.size()); |
| 473 *sig_len = signature.size(); | 468 *sig_len = signature.size(); |
| 474 return 1; | 469 return 1; |
| 475 } | 470 } |
| 476 | 471 |
| 477 int EcdsaMethodVerify(const uint8_t* digest, | 472 int EcdsaMethodVerify(const uint8_t* digest, |
| 478 size_t digest_len, | 473 size_t digest_len, |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 515 ex_data.release()); | 510 ex_data.release()); |
| 516 | 511 |
| 517 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new()); | 512 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new()); |
| 518 if (!pkey || !EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get())) | 513 if (!pkey || !EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get())) |
| 519 return nullptr; | 514 return nullptr; |
| 520 return pkey; | 515 return pkey; |
| 521 } | 516 } |
| 522 | 517 |
| 523 const ECDSA_METHOD android_ecdsa_method = { | 518 const ECDSA_METHOD android_ecdsa_method = { |
| 524 { | 519 { |
| 525 0 /* references */, | 520 0 /* references */, 1 /* is_static */ |
| 526 1 /* is_static */ | |
| 527 } /* common */, | 521 } /* common */, |
| 528 NULL /* app_data */, | 522 NULL /* app_data */, |
| 529 | 523 |
| 530 NULL /* init */, | 524 NULL /* init */, |
| 531 NULL /* finish */, | 525 NULL /* finish */, |
| 532 EcdsaMethodGroupOrderSize, | 526 EcdsaMethodGroupOrderSize, |
| 533 EcdsaMethodSign, | 527 EcdsaMethodSign, |
| 534 EcdsaMethodVerify, | 528 EcdsaMethodVerify, |
| 535 ECDSA_FLAG_OPAQUE, | 529 ECDSA_FLAG_OPAQUE, |
| 536 }; | 530 }; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 547 return GetEcdsaPkeyWrapper(private_key); | 541 return GetEcdsaPkeyWrapper(private_key); |
| 548 default: | 542 default: |
| 549 LOG(WARNING) | 543 LOG(WARNING) |
| 550 << "GetOpenSSLPrivateKeyWrapper() called with invalid key type"; | 544 << "GetOpenSSLPrivateKeyWrapper() called with invalid key type"; |
| 551 return nullptr; | 545 return nullptr; |
| 552 } | 546 } |
| 553 } | 547 } |
| 554 | 548 |
| 555 } // namespace android | 549 } // namespace android |
| 556 } // namespace net | 550 } // namespace net |
| OLD | NEW |