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 |