| 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_openssl.h" |
| 6 | 6 |
| 7 #include <jni.h> | 7 #include <jni.h> |
| 8 #include <openssl/bn.h> | 8 #include <openssl/bn.h> |
| 9 #include <openssl/dsa.h> | 9 #include <openssl/dsa.h> |
| 10 #include <openssl/ec.h> | 10 #include <openssl/ec.h> |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 | 172 |
| 173 int RsaMethodEncrypt(RSA* rsa, | 173 int RsaMethodEncrypt(RSA* rsa, |
| 174 size_t* out_len, | 174 size_t* out_len, |
| 175 uint8_t* out, | 175 uint8_t* out, |
| 176 size_t max_out, | 176 size_t max_out, |
| 177 const uint8_t* in, | 177 const uint8_t* in, |
| 178 size_t in_len, | 178 size_t in_len, |
| 179 int padding) { | 179 int padding) { |
| 180 NOTIMPLEMENTED(); | 180 NOTIMPLEMENTED(); |
| 181 OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE); | 181 OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE); |
| 182 return 1; | 182 return 0; |
| 183 } | 183 } |
| 184 | 184 |
| 185 int RsaMethodSignRaw(RSA* rsa, | 185 int RsaMethodSignRaw(RSA* rsa, |
| 186 size_t* out_len, | 186 size_t* out_len, |
| 187 uint8_t* out, | 187 uint8_t* out, |
| 188 size_t max_out, | 188 size_t max_out, |
| 189 const uint8_t* in, | 189 const uint8_t* in, |
| 190 size_t in_len, | 190 size_t in_len, |
| 191 int padding) { | 191 int padding) { |
| 192 DCHECK_EQ(RSA_PKCS1_PADDING, padding); | 192 DCHECK_EQ(RSA_PKCS1_PADDING, padding); |
| 193 if (padding != RSA_PKCS1_PADDING) { | 193 if (padding != RSA_PKCS1_PADDING) { |
| 194 // TODO(davidben): If we need to, we can implement RSA_NO_PADDING | 194 // TODO(davidben): If we need to, we can implement RSA_NO_PADDING |
| 195 // by using javax.crypto.Cipher and picking either the | 195 // by using javax.crypto.Cipher and picking either the |
| 196 // "RSA/ECB/NoPadding" or "RSA/ECB/PKCS1Padding" transformation as | 196 // "RSA/ECB/NoPadding" or "RSA/ECB/PKCS1Padding" transformation as |
| 197 // appropriate. I believe support for both of these was added in | 197 // appropriate. I believe support for both of these was added in |
| 198 // the same Android version as the "NONEwithRSA" | 198 // the same Android version as the "NONEwithRSA" |
| 199 // java.security.Signature algorithm, so the same version checks | 199 // java.security.Signature algorithm, so the same version checks |
| 200 // for GetRsaLegacyKey should work. | 200 // for GetRsaLegacyKey should work. |
| 201 OPENSSL_PUT_ERROR(RSA, sign_raw, RSA_R_UNKNOWN_ALGORITHM_TYPE); | 201 OPENSSL_PUT_ERROR(RSA, sign_raw, RSA_R_UNKNOWN_PADDING_TYPE); |
| 202 return 0; | 202 return 0; |
| 203 } | 203 } |
| 204 | 204 |
| 205 // Retrieve private key JNI reference. | 205 // Retrieve private key JNI reference. |
| 206 const KeyExData *ex_data = RsaGetExData(rsa); | 206 const KeyExData *ex_data = RsaGetExData(rsa); |
| 207 if (!ex_data || !ex_data->private_key) { | 207 if (!ex_data || !ex_data->private_key) { |
| 208 LOG(WARNING) << "Null JNI reference passed to RsaMethodPrivEnc!"; | 208 LOG(WARNING) << "Null JNI reference passed to RsaMethodPrivEnc!"; |
| 209 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR); | 209 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR); |
| 210 return 0; | 210 return 0; |
| 211 } | 211 } |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 } | 264 } |
| 265 | 265 |
| 266 int RsaMethodDecrypt(RSA* rsa, | 266 int RsaMethodDecrypt(RSA* rsa, |
| 267 size_t* out_len, | 267 size_t* out_len, |
| 268 uint8_t* out, | 268 uint8_t* out, |
| 269 size_t max_out, | 269 size_t max_out, |
| 270 const uint8_t* in, | 270 const uint8_t* in, |
| 271 size_t in_len, | 271 size_t in_len, |
| 272 int padding) { | 272 int padding) { |
| 273 NOTIMPLEMENTED(); | 273 NOTIMPLEMENTED(); |
| 274 OPENSSL_PUT_ERROR(RSA, decrypt, RSA_R_UNKNOWN_PADDING_TYPE); | 274 OPENSSL_PUT_ERROR(RSA, decrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE); |
| 275 return 1; | 275 return 0; |
| 276 } | 276 } |
| 277 | 277 |
| 278 int RsaMethodVerifyRaw(RSA* rsa, | 278 int RsaMethodVerifyRaw(RSA* rsa, |
| 279 size_t* out_len, | 279 size_t* out_len, |
| 280 uint8_t* out, | 280 uint8_t* out, |
| 281 size_t max_out, | 281 size_t max_out, |
| 282 const uint8_t* in, | 282 const uint8_t* in, |
| 283 size_t in_len, | 283 size_t in_len, |
| 284 int padding) { | 284 int padding) { |
| 285 NOTIMPLEMENTED(); | 285 NOTIMPLEMENTED(); |
| 286 OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_UNKNOWN_ALGORITHM_TYPE); | 286 OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_UNKNOWN_ALGORITHM_TYPE); |
| 287 return 1; | 287 return 0; |
| 288 } | 288 } |
| 289 | 289 |
| 290 const RSA_METHOD android_rsa_method = { | 290 const RSA_METHOD android_rsa_method = { |
| 291 { | 291 { |
| 292 0 /* references */, | 292 0 /* references */, |
| 293 1 /* is_static */ | 293 1 /* is_static */ |
| 294 } /* common */, | 294 } /* common */, |
| 295 NULL /* app_data */, | 295 NULL /* app_data */, |
| 296 | 296 |
| 297 NULL /* init */, | 297 NULL /* init */, |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 438 // Custom ECDSA_METHOD that uses the platform APIs. | 438 // Custom ECDSA_METHOD that uses the platform APIs. |
| 439 // Note that for now, only signing through ECDSA_sign() is really supported. | 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. | 440 // all other method pointers are either stubs returning errors, or no-ops. |
| 441 | 441 |
| 442 jobject EcKeyGetKey(const EC_KEY* ec_key) { | 442 jobject EcKeyGetKey(const EC_KEY* ec_key) { |
| 443 KeyExData* ex_data = reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data( | 443 KeyExData* ex_data = reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data( |
| 444 ec_key, global_boringssl_engine.Get().ec_key_ex_index())); | 444 ec_key, global_boringssl_engine.Get().ec_key_ex_index())); |
| 445 return ex_data->private_key; | 445 return ex_data->private_key; |
| 446 } | 446 } |
| 447 | 447 |
| 448 size_t EcdsaMethodGroupOrderSize(const EC_KEY* key) { | 448 size_t EcdsaMethodGroupOrderSize(const EC_KEY* ec_key) { |
| 449 KeyExData* ex_data = reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data( | 449 KeyExData* ex_data = reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data( |
| 450 key, global_boringssl_engine.Get().ec_key_ex_index())); | 450 ec_key, global_boringssl_engine.Get().ec_key_ex_index())); |
| 451 return ex_data->cached_size; | 451 return ex_data->cached_size; |
| 452 } | 452 } |
| 453 | 453 |
| 454 int EcdsaMethodSign(const uint8_t* digest, | 454 int EcdsaMethodSign(const uint8_t* digest, |
| 455 size_t digest_len, | 455 size_t digest_len, |
| 456 uint8_t* sig, | 456 uint8_t* sig, |
| 457 unsigned int* sig_len, | 457 unsigned int* sig_len, |
| 458 EC_KEY* eckey) { | 458 EC_KEY* ec_key) { |
| 459 // Retrieve private key JNI reference. | 459 // Retrieve private key JNI reference. |
| 460 jobject private_key = EcKeyGetKey(eckey); | 460 jobject private_key = EcKeyGetKey(ec_key); |
| 461 if (!private_key) { | 461 if (!private_key) { |
| 462 LOG(WARNING) << "Null JNI reference passed to EcdsaMethodSign!"; | 462 LOG(WARNING) << "Null JNI reference passed to EcdsaMethodSign!"; |
| 463 return 0; | 463 return 0; |
| 464 } | 464 } |
| 465 // Sign message with it through JNI. | 465 // Sign message with it through JNI. |
| 466 std::vector<uint8> signature; | 466 std::vector<uint8> signature; |
| 467 base::StringPiece digest_sp(reinterpret_cast<const char*>(digest), | 467 base::StringPiece digest_sp(reinterpret_cast<const char*>(digest), |
| 468 digest_len); | 468 digest_len); |
| 469 if (!RawSignDigestWithPrivateKey(private_key, digest_sp, &signature)) { | 469 if (!RawSignDigestWithPrivateKey(private_key, digest_sp, &signature)) { |
| 470 LOG(WARNING) << "Could not sign message in EcdsaMethodSign!"; | 470 LOG(WARNING) << "Could not sign message in EcdsaMethodSign!"; |
| 471 return 0; | 471 return 0; |
| 472 } | 472 } |
| 473 | 473 |
| 474 // Note: With ECDSA, the actual signature may be smaller than | 474 // Note: With ECDSA, the actual signature may be smaller than |
| 475 // ECDSA_size(). | 475 // ECDSA_size(). |
| 476 size_t max_expected_size = ECDSA_size(eckey); | 476 size_t max_expected_size = ECDSA_size(ec_key); |
| 477 if (signature.size() > max_expected_size) { | 477 if (signature.size() > max_expected_size) { |
| 478 LOG(ERROR) << "ECDSA Signature size mismatch, actual: " | 478 LOG(ERROR) << "ECDSA Signature size mismatch, actual: " |
| 479 << signature.size() << ", expected <= " | 479 << signature.size() << ", expected <= " |
| 480 << max_expected_size; | 480 << max_expected_size; |
| 481 return 0; | 481 return 0; |
| 482 } | 482 } |
| 483 | 483 |
| 484 memcpy(sig, &signature[0], signature.size()); | 484 memcpy(sig, &signature[0], signature.size()); |
| 485 *sig_len = signature.size(); | 485 *sig_len = signature.size(); |
| 486 return 1; | 486 return 1; |
| 487 } | 487 } |
| 488 | 488 |
| 489 int EcdsaMethodVerify(const uint8_t* digest, | 489 int EcdsaMethodVerify(const uint8_t* digest, |
| 490 size_t digest_len, | 490 size_t digest_len, |
| 491 const uint8_t* sig, | 491 const uint8_t* sig, |
| 492 size_t sig_len, | 492 size_t sig_len, |
| 493 EC_KEY* eckey) { | 493 EC_KEY* ec_key) { |
| 494 NOTIMPLEMENTED(); | 494 NOTIMPLEMENTED(); |
| 495 OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ECDSA_R_NOT_IMPLEMENTED); | 495 OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ECDSA_R_NOT_IMPLEMENTED); |
| 496 return 0; | 496 return 0; |
| 497 } | 497 } |
| 498 | 498 |
| 499 // Setup an EVP_PKEY to wrap an existing platform PrivateKey object. | 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. | 500 // |private_key| is the JNI reference (local or global) to the object. |
| 501 // |pkey| is the EVP_PKEY to setup as a wrapper. | 501 // |pkey| is the EVP_PKEY to setup as a wrapper. |
| 502 // Returns true on success, false otherwise. | 502 // Returns true on success, false otherwise. |
| 503 // On success, this creates a global JNI reference to the object that | 503 // On success, this creates a global JNI reference to the object that |
| 504 // is owned by and destroyed with the EVP_PKEY. I.e. the caller shall | 504 // is owned by and destroyed with the EVP_PKEY. I.e. the caller shall |
| 505 // always free |private_key| after the call. | 505 // always free |private_key| after the call. |
| 506 bool GetEcdsaPkeyWrapper(jobject private_key, EVP_PKEY* pkey) { | 506 bool GetEcdsaPkeyWrapper(jobject private_key, EVP_PKEY* pkey) { |
| 507 crypto::ScopedEC_KEY eckey( | 507 crypto::ScopedEC_KEY ec_key( |
| 508 EC_KEY_new_method(global_boringssl_engine.Get().engine())); | 508 EC_KEY_new_method(global_boringssl_engine.Get().engine())); |
| 509 | 509 |
| 510 ScopedJavaGlobalRef<jobject> global_key; | 510 ScopedJavaGlobalRef<jobject> global_key; |
| 511 global_key.Reset(NULL, private_key); | 511 global_key.Reset(NULL, private_key); |
| 512 if (global_key.is_null()) { | 512 if (global_key.is_null()) { |
| 513 LOG(ERROR) << "Can't create global JNI reference"; | 513 LOG(ERROR) << "Can't create global JNI reference"; |
| 514 return false; | 514 return false; |
| 515 } | 515 } |
| 516 | 516 |
| 517 std::vector<uint8> order; | 517 std::vector<uint8> order; |
| 518 if (!GetECKeyOrder(private_key, &order)) { | 518 if (!GetECKeyOrder(private_key, &order)) { |
| 519 LOG(ERROR) << "Can't extract order parameter from EC private key"; | 519 LOG(ERROR) << "Can't extract order parameter from EC private key"; |
| 520 return false; | 520 return false; |
| 521 } | 521 } |
| 522 | 522 |
| 523 KeyExData* ex_data = new KeyExData; | 523 KeyExData* ex_data = new KeyExData; |
| 524 ex_data->private_key = global_key.Release(); | 524 ex_data->private_key = global_key.Release(); |
| 525 ex_data->legacy_rsa = NULL; | 525 ex_data->legacy_rsa = NULL; |
| 526 ex_data->cached_size = VectorBignumSize(order); | 526 ex_data->cached_size = VectorBignumSize(order); |
| 527 | 527 |
| 528 EC_KEY_set_ex_data( | 528 EC_KEY_set_ex_data( |
| 529 eckey.get(), global_boringssl_engine.Get().ec_key_ex_index(), ex_data); | 529 ec_key.get(), global_boringssl_engine.Get().ec_key_ex_index(), ex_data); |
| 530 | 530 |
| 531 EVP_PKEY_assign_EC_KEY(pkey, eckey.release()); | 531 EVP_PKEY_assign_EC_KEY(pkey, ec_key.release()); |
| 532 return true; | 532 return true; |
| 533 } | 533 } |
| 534 | 534 |
| 535 const ECDSA_METHOD android_ecdsa_method = { | 535 const ECDSA_METHOD android_ecdsa_method = { |
| 536 { | 536 { |
| 537 0 /* references */, | 537 0 /* references */, |
| 538 1 /* is_static */ | 538 1 /* is_static */ |
| 539 } /* common */, | 539 } /* common */, |
| 540 NULL /* app_data */, | 540 NULL /* app_data */, |
| 541 | 541 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 584 default: | 584 default: |
| 585 LOG(WARNING) | 585 LOG(WARNING) |
| 586 << "GetOpenSSLPrivateKeyWrapper() called with invalid key type"; | 586 << "GetOpenSSLPrivateKeyWrapper() called with invalid key type"; |
| 587 return NULL; | 587 return NULL; |
| 588 } | 588 } |
| 589 return pkey.release(); | 589 return pkey.release(); |
| 590 } | 590 } |
| 591 | 591 |
| 592 } // namespace android | 592 } // namespace android |
| 593 } // namespace net | 593 } // namespace net |
| OLD | NEW |