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...) 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...) 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...) 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...) 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 |