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 // This include is required to get the ECDSA_METHOD structure definition | 9 // This include is required to get the ECDSA_METHOD structure definition |
10 // which isn't currently part of the OpenSSL official ABI. This should | 10 // which isn't currently part of the OpenSSL official ABI. This should |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 int padding) { | 129 int padding) { |
130 NOTIMPLEMENTED(); | 130 NOTIMPLEMENTED(); |
131 RSAerr(RSA_F_RSA_PUBLIC_DECRYPT, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED); | 131 RSAerr(RSA_F_RSA_PUBLIC_DECRYPT, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED); |
132 return -1; | 132 return -1; |
133 } | 133 } |
134 | 134 |
135 // See RSA_eay_private_encrypt in | 135 // See RSA_eay_private_encrypt in |
136 // third_party/openssl/openssl/crypto/rsa/rsa_eay.c for the default | 136 // third_party/openssl/openssl/crypto/rsa/rsa_eay.c for the default |
137 // implementation of this function. | 137 // implementation of this function. |
138 int RsaMethodPrivEnc(int flen, | 138 int RsaMethodPrivEnc(int flen, |
139 const unsigned char *from, | 139 const unsigned char* from, |
140 unsigned char *to, | 140 unsigned char* to, |
141 RSA *rsa, | 141 RSA* rsa, |
142 int padding) { | 142 int padding) { |
143 DCHECK_EQ(RSA_PKCS1_PADDING, padding); | 143 DCHECK_EQ(RSA_PKCS1_PADDING, padding); |
144 if (padding != RSA_PKCS1_PADDING) { | 144 if (padding != RSA_PKCS1_PADDING) { |
145 // TODO(davidben): If we need to, we can implement RSA_NO_PADDING | 145 // TODO(davidben): If we need to, we can implement RSA_NO_PADDING |
146 // by using javax.crypto.Cipher and picking either the | 146 // by using javax.crypto.Cipher and picking either the |
147 // "RSA/ECB/NoPadding" or "RSA/ECB/PKCS1Padding" transformation as | 147 // "RSA/ECB/NoPadding" or "RSA/ECB/PKCS1Padding" transformation as |
148 // appropriate. I believe support for both of these was added in | 148 // appropriate. I believe support for both of these was added in |
149 // the same Android version as the "NONEwithRSA" | 149 // the same Android version as the "NONEwithRSA" |
150 // java.security.Signature algorithm, so the same version checks | 150 // java.security.Signature algorithm, so the same version checks |
151 // for GetRsaLegacyKey should work. | 151 // for GetRsaLegacyKey should work. |
(...skipping 14 matching lines...) Expand all Loading... |
166 // For RSA keys, this function behaves as RSA_private_encrypt with | 166 // For RSA keys, this function behaves as RSA_private_encrypt with |
167 // PKCS#1 padding. | 167 // PKCS#1 padding. |
168 if (!RawSignDigestWithPrivateKey(private_key, from_piece, &result)) { | 168 if (!RawSignDigestWithPrivateKey(private_key, from_piece, &result)) { |
169 LOG(WARNING) << "Could not sign message in RsaMethodPrivEnc!"; | 169 LOG(WARNING) << "Could not sign message in RsaMethodPrivEnc!"; |
170 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); | 170 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); |
171 return -1; | 171 return -1; |
172 } | 172 } |
173 | 173 |
174 size_t expected_size = static_cast<size_t>(RSA_size(rsa)); | 174 size_t expected_size = static_cast<size_t>(RSA_size(rsa)); |
175 if (result.size() > expected_size) { | 175 if (result.size() > expected_size) { |
176 LOG(ERROR) << "RSA Signature size mismatch, actual: " | 176 LOG(ERROR) << "RSA Signature size mismatch, actual: " << result.size() |
177 << result.size() << ", expected <= " << expected_size; | 177 << ", expected <= " << expected_size; |
178 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); | 178 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); |
179 return -1; | 179 return -1; |
180 } | 180 } |
181 | 181 |
182 // Copy result to OpenSSL-provided buffer. RawSignDigestWithPrivateKey | 182 // Copy result to OpenSSL-provided buffer. RawSignDigestWithPrivateKey |
183 // should pad with leading 0s, but if it doesn't, pad the result. | 183 // should pad with leading 0s, but if it doesn't, pad the result. |
184 size_t zero_pad = expected_size - result.size(); | 184 size_t zero_pad = expected_size - result.size(); |
185 memset(to, 0, zero_pad); | 185 memset(to, 0, zero_pad); |
186 memcpy(to + zero_pad, &result[0], result.size()); | 186 memcpy(to + zero_pad, &result[0], result.size()); |
187 | 187 |
(...skipping 21 matching lines...) Expand all Loading... |
209 if (key != NULL) { | 209 if (key != NULL) { |
210 RSA_set_app_data(rsa, NULL); | 210 RSA_set_app_data(rsa, NULL); |
211 ReleaseKey(key); | 211 ReleaseKey(key); |
212 } | 212 } |
213 // Actual return value is ignored by OpenSSL. There are no docs | 213 // Actual return value is ignored by OpenSSL. There are no docs |
214 // explaining what this is supposed to be. | 214 // explaining what this is supposed to be. |
215 return 0; | 215 return 0; |
216 } | 216 } |
217 | 217 |
218 const RSA_METHOD android_rsa_method = { | 218 const RSA_METHOD android_rsa_method = { |
219 /* .name = */ "Android signing-only RSA method", | 219 /* .name = */ "Android signing-only RSA method", |
220 /* .rsa_pub_enc = */ RsaMethodPubEnc, | 220 /* .rsa_pub_enc = */ RsaMethodPubEnc, |
221 /* .rsa_pub_dec = */ RsaMethodPubDec, | 221 /* .rsa_pub_dec = */ RsaMethodPubDec, |
222 /* .rsa_priv_enc = */ RsaMethodPrivEnc, | 222 /* .rsa_priv_enc = */ RsaMethodPrivEnc, |
223 /* .rsa_priv_dec = */ RsaMethodPrivDec, | 223 /* .rsa_priv_dec = */ RsaMethodPrivDec, |
224 /* .rsa_mod_exp = */ NULL, | 224 /* .rsa_mod_exp = */ NULL, |
225 /* .bn_mod_exp = */ NULL, | 225 /* .bn_mod_exp = */ NULL, |
226 /* .init = */ RsaMethodInit, | 226 /* .init = */ RsaMethodInit, |
227 /* .finish = */ RsaMethodFinish, | 227 /* .finish = */ RsaMethodFinish, |
228 // This flag is necessary to tell OpenSSL to avoid checking the content | 228 // This flag is necessary to tell OpenSSL to avoid checking the content |
229 // (i.e. internal fields) of the private key. Otherwise, it will complain | 229 // (i.e. internal fields) of the private key. Otherwise, it will complain |
230 // it's not valid for the certificate. | 230 // it's not valid for the certificate. |
231 /* .flags = */ RSA_METHOD_FLAG_NO_CHECK, | 231 /* .flags = */ RSA_METHOD_FLAG_NO_CHECK, |
232 /* .app_data = */ NULL, | 232 /* .app_data = */ NULL, |
233 /* .rsa_sign = */ NULL, | 233 /* .rsa_sign = */ NULL, |
234 /* .rsa_verify = */ NULL, | 234 /* .rsa_verify = */ NULL, |
235 /* .rsa_keygen = */ NULL, | 235 /* .rsa_keygen = */ NULL, |
236 }; | 236 }; |
237 | 237 |
238 // Copy the contents of an encoded big integer into an existing BIGNUM. | 238 // Copy the contents of an encoded big integer into an existing BIGNUM. |
239 // This function modifies |*num| in-place. | 239 // This function modifies |*num| in-place. |
240 // |new_bytes| is the byte encoding of the new value. | 240 // |new_bytes| is the byte encoding of the new value. |
241 // |num| points to the BIGNUM which will be assigned with the new value. | 241 // |num| points to the BIGNUM which will be assigned with the new value. |
242 // Returns true on success, false otherwise. On failure, |*num| is | 242 // Returns true on success, false otherwise. On failure, |*num| is |
243 // not modified. | 243 // not modified. |
244 bool CopyBigNumFromBytes(const std::vector<uint8>& new_bytes, | 244 bool CopyBigNumFromBytes(const std::vector<uint8>& new_bytes, BIGNUM* num) { |
245 BIGNUM* num) { | 245 BIGNUM* ret = BN_bin2bn(reinterpret_cast<const unsigned char*>(&new_bytes[0]), |
246 BIGNUM* ret = BN_bin2bn( | 246 static_cast<int>(new_bytes.size()), |
247 reinterpret_cast<const unsigned char*>(&new_bytes[0]), | 247 num); |
248 static_cast<int>(new_bytes.size()), | |
249 num); | |
250 return (ret != NULL); | 248 return (ret != NULL); |
251 } | 249 } |
252 | 250 |
253 // Decode the contents of an encoded big integer and either create a new | 251 // Decode the contents of an encoded big integer and either create a new |
254 // BIGNUM object (if |*num_ptr| is NULL on input) or copy it (if | 252 // BIGNUM object (if |*num_ptr| is NULL on input) or copy it (if |
255 // |*num_ptr| is not NULL). | 253 // |*num_ptr| is not NULL). |
256 // |new_bytes| is the byte encoding of the new value. | 254 // |new_bytes| is the byte encoding of the new value. |
257 // |num_ptr| is the address of a BIGNUM pointer. |*num_ptr| can be NULL. | 255 // |num_ptr| is the address of a BIGNUM pointer. |*num_ptr| can be NULL. |
258 // Returns true on success, false otherwise. On failure, |*num_ptr| is | 256 // Returns true on success, false otherwise. On failure, |*num_ptr| is |
259 // not modified. On success, |*num_ptr| will always be non-NULL and | 257 // not modified. On success, |*num_ptr| will always be non-NULL and |
260 // point to a valid BIGNUM object. | 258 // point to a valid BIGNUM object. |
261 bool SwapBigNumPtrFromBytes(const std::vector<uint8>& new_bytes, | 259 bool SwapBigNumPtrFromBytes(const std::vector<uint8>& new_bytes, |
262 BIGNUM** num_ptr) { | 260 BIGNUM** num_ptr) { |
263 BIGNUM* old_num = *num_ptr; | 261 BIGNUM* old_num = *num_ptr; |
264 BIGNUM* new_num = BN_bin2bn( | 262 BIGNUM* new_num = |
265 reinterpret_cast<const unsigned char*>(&new_bytes[0]), | 263 BN_bin2bn(reinterpret_cast<const unsigned char*>(&new_bytes[0]), |
266 static_cast<int>(new_bytes.size()), | 264 static_cast<int>(new_bytes.size()), |
267 old_num); | 265 old_num); |
268 if (new_num == NULL) | 266 if (new_num == NULL) |
269 return false; | 267 return false; |
270 | 268 |
271 if (old_num == NULL) | 269 if (old_num == NULL) |
272 *num_ptr = new_num; | 270 *num_ptr = new_num; |
273 return true; | 271 return true; |
274 } | 272 } |
275 | 273 |
276 // Setup an EVP_PKEY to wrap an existing platform RSA PrivateKey object. | 274 // Setup an EVP_PKEY to wrap an existing platform RSA PrivateKey object. |
277 // |private_key| is the JNI reference (local or global) to the object. | 275 // |private_key| is the JNI reference (local or global) to the object. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
309 EVP_PKEY_assign_RSA(pkey, rsa.release()); | 307 EVP_PKEY_assign_RSA(pkey, rsa.release()); |
310 return true; | 308 return true; |
311 } | 309 } |
312 | 310 |
313 // Setup an EVP_PKEY to wrap an existing platform RSA PrivateKey object | 311 // Setup an EVP_PKEY to wrap an existing platform RSA PrivateKey object |
314 // for Android 4.0 to 4.1.x. Must only be used on Android < 4.2. | 312 // for Android 4.0 to 4.1.x. Must only be used on Android < 4.2. |
315 // |private_key| is a JNI reference (local or global) to the object. | 313 // |private_key| is a JNI reference (local or global) to the object. |
316 // |pkey| is the EVP_PKEY to setup as a wrapper. | 314 // |pkey| is the EVP_PKEY to setup as a wrapper. |
317 // Returns true on success, false otherwise. | 315 // Returns true on success, false otherwise. |
318 EVP_PKEY* GetRsaLegacyKey(jobject private_key) { | 316 EVP_PKEY* GetRsaLegacyKey(jobject private_key) { |
319 EVP_PKEY* sys_pkey = | 317 EVP_PKEY* sys_pkey = GetOpenSSLSystemHandleForPrivateKey(private_key); |
320 GetOpenSSLSystemHandleForPrivateKey(private_key); | |
321 if (sys_pkey != NULL) { | 318 if (sys_pkey != NULL) { |
322 CRYPTO_add(&sys_pkey->references, 1, CRYPTO_LOCK_EVP_PKEY); | 319 CRYPTO_add(&sys_pkey->references, 1, CRYPTO_LOCK_EVP_PKEY); |
323 } else { | 320 } else { |
324 // GetOpenSSLSystemHandleForPrivateKey() will fail on Android | 321 // GetOpenSSLSystemHandleForPrivateKey() will fail on Android |
325 // 4.0.3 and earlier. However, it is possible to get the key | 322 // 4.0.3 and earlier. However, it is possible to get the key |
326 // content with PrivateKey.getEncoded() on these platforms. | 323 // content with PrivateKey.getEncoded() on these platforms. |
327 // Note that this method may return NULL on 4.0.4 and later. | 324 // Note that this method may return NULL on 4.0.4 and later. |
328 std::vector<uint8> encoded; | 325 std::vector<uint8> encoded; |
329 if (!GetPrivateKeyEncodedBytes(private_key, &encoded)) { | 326 if (!GetPrivateKeyEncodedBytes(private_key, &encoded)) { |
330 LOG(ERROR) << "Can't get private key data!"; | 327 LOG(ERROR) << "Can't get private key data!"; |
(...skipping 14 matching lines...) Expand all Loading... |
345 // Custom DSA_METHOD that uses the platform APIs. | 342 // Custom DSA_METHOD that uses the platform APIs. |
346 // Note that for now, only signing through DSA_sign() is really supported. | 343 // Note that for now, only signing through DSA_sign() is really supported. |
347 // all other method pointers are either stubs returning errors, or no-ops. | 344 // all other method pointers are either stubs returning errors, or no-ops. |
348 // See <openssl/dsa.h> for exact declaration of DSA_METHOD. | 345 // See <openssl/dsa.h> for exact declaration of DSA_METHOD. |
349 // | 346 // |
350 // Note: There is no DSA_set_app_data() and DSA_get_app_data() functions, | 347 // Note: There is no DSA_set_app_data() and DSA_get_app_data() functions, |
351 // but RSA_set_app_data() is defined as a simple macro that calls | 348 // but RSA_set_app_data() is defined as a simple macro that calls |
352 // RSA_set_ex_data() with a hard-coded index of 0, so this code | 349 // RSA_set_ex_data() with a hard-coded index of 0, so this code |
353 // does the same thing here. | 350 // does the same thing here. |
354 | 351 |
355 DSA_SIG* DsaMethodDoSign(const unsigned char* dgst, | 352 DSA_SIG* DsaMethodDoSign(const unsigned char* dgst, int dlen, DSA* dsa) { |
356 int dlen, | |
357 DSA* dsa) { | |
358 // Extract the JNI reference to the PrivateKey object. | 353 // Extract the JNI reference to the PrivateKey object. |
359 jobject private_key = reinterpret_cast<jobject>(DSA_get_ex_data(dsa, 0)); | 354 jobject private_key = reinterpret_cast<jobject>(DSA_get_ex_data(dsa, 0)); |
360 if (private_key == NULL) | 355 if (private_key == NULL) |
361 return NULL; | 356 return NULL; |
362 | 357 |
363 // Sign the message with it, calling platform APIs. | 358 // Sign the message with it, calling platform APIs. |
364 std::vector<uint8> signature; | 359 std::vector<uint8> signature; |
365 if (!RawSignDigestWithPrivateKey( | 360 if (!RawSignDigestWithPrivateKey( |
366 private_key, | 361 private_key, |
367 base::StringPiece( | 362 base::StringPiece(reinterpret_cast<const char*>(dgst), |
368 reinterpret_cast<const char*>(dgst), | 363 static_cast<size_t>(dlen)), |
369 static_cast<size_t>(dlen)), | |
370 &signature)) { | 364 &signature)) { |
371 return NULL; | 365 return NULL; |
372 } | 366 } |
373 | 367 |
374 // Note: With DSA, the actual signature might be smaller than DSA_size(). | 368 // Note: With DSA, the actual signature might be smaller than DSA_size(). |
375 size_t max_expected_size = static_cast<size_t>(DSA_size(dsa)); | 369 size_t max_expected_size = static_cast<size_t>(DSA_size(dsa)); |
376 if (signature.size() > max_expected_size) { | 370 if (signature.size() > max_expected_size) { |
377 LOG(ERROR) << "DSA Signature size mismatch, actual: " | 371 LOG(ERROR) << "DSA Signature size mismatch, actual: " << signature.size() |
378 << signature.size() << ", expected <= " | 372 << ", expected <= " << max_expected_size; |
379 << max_expected_size; | |
380 return NULL; | 373 return NULL; |
381 } | 374 } |
382 | 375 |
383 // Convert the signature into a DSA_SIG object. | 376 // Convert the signature into a DSA_SIG object. |
384 const unsigned char* sigbuf = | 377 const unsigned char* sigbuf = |
385 reinterpret_cast<const unsigned char*>(&signature[0]); | 378 reinterpret_cast<const unsigned char*>(&signature[0]); |
386 int siglen = static_cast<size_t>(signature.size()); | 379 int siglen = static_cast<size_t>(signature.size()); |
387 DSA_SIG* dsa_sig = d2i_DSA_SIG(NULL, &sigbuf, siglen); | 380 DSA_SIG* dsa_sig = d2i_DSA_SIG(NULL, &sigbuf, siglen); |
388 return dsa_sig; | 381 return dsa_sig; |
389 } | 382 } |
390 | 383 |
391 int DsaMethodSignSetup(DSA* dsa, | 384 int DsaMethodSignSetup(DSA* dsa, BN_CTX* ctx_in, BIGNUM** kinvp, BIGNUM** rp) { |
392 BN_CTX* ctx_in, | |
393 BIGNUM** kinvp, | |
394 BIGNUM** rp) { | |
395 NOTIMPLEMENTED(); | 385 NOTIMPLEMENTED(); |
396 DSAerr(DSA_F_DSA_SIGN_SETUP, DSA_R_INVALID_DIGEST_TYPE); | 386 DSAerr(DSA_F_DSA_SIGN_SETUP, DSA_R_INVALID_DIGEST_TYPE); |
397 return -1; | 387 return -1; |
398 } | 388 } |
399 | 389 |
400 int DsaMethodDoVerify(const unsigned char* dgst, | 390 int DsaMethodDoVerify(const unsigned char* dgst, |
401 int dgst_len, | 391 int dgst_len, |
402 DSA_SIG* sig, | 392 DSA_SIG* sig, |
403 DSA* dsa) { | 393 DSA* dsa) { |
404 NOTIMPLEMENTED(); | 394 NOTIMPLEMENTED(); |
405 DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_INVALID_DIGEST_TYPE); | 395 DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_INVALID_DIGEST_TYPE); |
406 return -1; | 396 return -1; |
407 } | 397 } |
408 | 398 |
409 int DsaMethodFinish(DSA* dsa) { | 399 int DsaMethodFinish(DSA* dsa) { |
410 // Free the global JNI reference that was created with this | 400 // Free the global JNI reference that was created with this |
411 // wrapper key. | 401 // wrapper key. |
412 jobject key = reinterpret_cast<jobject>(DSA_get_ex_data(dsa,0)); | 402 jobject key = reinterpret_cast<jobject>(DSA_get_ex_data(dsa, 0)); |
413 if (key != NULL) { | 403 if (key != NULL) { |
414 DSA_set_ex_data(dsa, 0, NULL); | 404 DSA_set_ex_data(dsa, 0, NULL); |
415 ReleaseKey(key); | 405 ReleaseKey(key); |
416 } | 406 } |
417 // Actual return value is ignored by OpenSSL. There are no docs | 407 // Actual return value is ignored by OpenSSL. There are no docs |
418 // explaining what this is supposed to be. | 408 // explaining what this is supposed to be. |
419 return 0; | 409 return 0; |
420 } | 410 } |
421 | 411 |
422 const DSA_METHOD android_dsa_method = { | 412 const DSA_METHOD android_dsa_method = { |
423 /* .name = */ "Android signing-only DSA method", | 413 /* .name = */ "Android signing-only DSA method", |
424 /* .dsa_do_sign = */ DsaMethodDoSign, | 414 /* .dsa_do_sign = */ DsaMethodDoSign, |
425 /* .dsa_sign_setup = */ DsaMethodSignSetup, | 415 /* .dsa_sign_setup = */ DsaMethodSignSetup, |
426 /* .dsa_do_verify = */ DsaMethodDoVerify, | 416 /* .dsa_do_verify = */ DsaMethodDoVerify, |
427 /* .dsa_mod_exp = */ NULL, | 417 /* .dsa_mod_exp = */ NULL, |
428 /* .bn_mod_exp = */ NULL, | 418 /* .bn_mod_exp = */ NULL, |
429 /* .init = */ NULL, // nothing to do here. | 419 /* .init = */ NULL, // nothing to do here. |
430 /* .finish = */ DsaMethodFinish, | 420 /* .finish = */ DsaMethodFinish, |
431 /* .flags = */ 0, | 421 /* .flags = */ 0, |
432 /* .app_data = */ NULL, | 422 /* .app_data = */ NULL, |
433 /* .dsa_paramgem = */ NULL, | 423 /* .dsa_paramgem = */ NULL, |
434 /* .dsa_keygen = */ NULL | 424 /* .dsa_keygen = */ NULL}; |
435 }; | |
436 | 425 |
437 // Setup an EVP_PKEY to wrap an existing DSA platform PrivateKey object. | 426 // Setup an EVP_PKEY to wrap an existing DSA platform PrivateKey object. |
438 // |private_key| is a JNI reference (local or global) to the object. | 427 // |private_key| is a JNI reference (local or global) to the object. |
439 // |pkey| is the EVP_PKEY to setup as a wrapper. | 428 // |pkey| is the EVP_PKEY to setup as a wrapper. |
440 // Returns true on success, false otherwise. | 429 // Returns true on success, false otherwise. |
441 // On success, this creates a global JNI reference to the same object | 430 // On success, this creates a global JNI reference to the same object |
442 // that will be owned by and destroyed with the EVP_PKEY. | 431 // that will be owned by and destroyed with the EVP_PKEY. |
443 bool GetDsaPkeyWrapper(jobject private_key, EVP_PKEY* pkey) { | 432 bool GetDsaPkeyWrapper(jobject private_key, EVP_PKEY* pkey) { |
444 ScopedDSA dsa(DSA_new()); | 433 ScopedDSA dsa(DSA_new()); |
445 DSA_set_method(dsa.get(), &android_dsa_method); | 434 DSA_set_method(dsa.get(), &android_dsa_method); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 // This callback shall never be called with the current OpenSSL | 492 // This callback shall never be called with the current OpenSSL |
504 // implementation (the library only ever duplicates EX_DATA items | 493 // implementation (the library only ever duplicates EX_DATA items |
505 // for SSL and BIO objects). But provide this to catch regressions | 494 // for SSL and BIO objects). But provide this to catch regressions |
506 // in the future. | 495 // in the future. |
507 CHECK(false) << "ExDataDup was called for ECDSA custom key !?"; | 496 CHECK(false) << "ExDataDup was called for ECDSA custom key !?"; |
508 // Return value is currently ignored by OpenSSL. | 497 // Return value is currently ignored by OpenSSL. |
509 return 0; | 498 return 0; |
510 } | 499 } |
511 | 500 |
512 class EcdsaExDataIndex { | 501 class EcdsaExDataIndex { |
513 public: | 502 public: |
514 int ex_data_index() { return ex_data_index_; } | 503 int ex_data_index() { return ex_data_index_; } |
515 | 504 |
516 EcdsaExDataIndex() { | 505 EcdsaExDataIndex() { |
517 ex_data_index_ = ECDSA_get_ex_new_index(0, // argl | 506 ex_data_index_ = ECDSA_get_ex_new_index(0, // argl |
518 NULL, // argp | 507 NULL, // argp |
519 NULL, // new_func | 508 NULL, // new_func |
520 ExDataDup, // dup_func | 509 ExDataDup, // dup_func |
521 ExDataFree); // free_func | 510 ExDataFree); // free_func |
522 } | 511 } |
523 | 512 |
524 private: | 513 private: |
525 int ex_data_index_; | 514 int ex_data_index_; |
526 }; | 515 }; |
527 | 516 |
528 // Returns the index of the custom EX_DATA used to store the JNI reference. | 517 // Returns the index of the custom EX_DATA used to store the JNI reference. |
529 int EcdsaGetExDataIndex(void) { | 518 int EcdsaGetExDataIndex(void) { |
530 // Use a LazyInstance to perform thread-safe lazy initialization. | 519 // Use a LazyInstance to perform thread-safe lazy initialization. |
531 // Use a leaky one, since OpenSSL doesn't provide a way to release | 520 // Use a leaky one, since OpenSSL doesn't provide a way to release |
532 // allocated EX_DATA indices. | 521 // allocated EX_DATA indices. |
533 static base::LazyInstance<EcdsaExDataIndex>::Leaky s_instance = | 522 static base::LazyInstance<EcdsaExDataIndex>::Leaky s_instance = |
534 LAZY_INSTANCE_INITIALIZER; | 523 LAZY_INSTANCE_INITIALIZER; |
535 return s_instance.Get().ex_data_index(); | 524 return s_instance.Get().ex_data_index(); |
536 } | 525 } |
537 | 526 |
538 ECDSA_SIG* EcdsaMethodDoSign(const unsigned char* dgst, | 527 ECDSA_SIG* EcdsaMethodDoSign(const unsigned char* dgst, |
539 int dgst_len, | 528 int dgst_len, |
540 const BIGNUM* inv, | 529 const BIGNUM* inv, |
541 const BIGNUM* rp, | 530 const BIGNUM* rp, |
542 EC_KEY* eckey) { | 531 EC_KEY* eckey) { |
543 // Retrieve private key JNI reference. | 532 // Retrieve private key JNI reference. |
544 jobject private_key = reinterpret_cast<jobject>( | 533 jobject private_key = reinterpret_cast<jobject>( |
545 ECDSA_get_ex_data(eckey, EcdsaGetExDataIndex())); | 534 ECDSA_get_ex_data(eckey, EcdsaGetExDataIndex())); |
546 if (!private_key) { | 535 if (!private_key) { |
547 LOG(WARNING) << "Null JNI reference passed to EcdsaMethodDoSign!"; | 536 LOG(WARNING) << "Null JNI reference passed to EcdsaMethodDoSign!"; |
548 return NULL; | 537 return NULL; |
549 } | 538 } |
550 // Sign message with it through JNI. | 539 // Sign message with it through JNI. |
551 std::vector<uint8> signature; | 540 std::vector<uint8> signature; |
552 base::StringPiece digest( | 541 base::StringPiece digest(reinterpret_cast<const char*>(dgst), |
553 reinterpret_cast<const char*>(dgst), | 542 static_cast<size_t>(dgst_len)); |
554 static_cast<size_t>(dgst_len)); | 543 if (!RawSignDigestWithPrivateKey(private_key, digest, &signature)) { |
555 if (!RawSignDigestWithPrivateKey( | |
556 private_key, digest, &signature)) { | |
557 LOG(WARNING) << "Could not sign message in EcdsaMethodDoSign!"; | 544 LOG(WARNING) << "Could not sign message in EcdsaMethodDoSign!"; |
558 return NULL; | 545 return NULL; |
559 } | 546 } |
560 | 547 |
561 // Note: With ECDSA, the actual signature may be smaller than | 548 // Note: With ECDSA, the actual signature may be smaller than |
562 // ECDSA_size(). | 549 // ECDSA_size(). |
563 size_t max_expected_size = static_cast<size_t>(ECDSA_size(eckey)); | 550 size_t max_expected_size = static_cast<size_t>(ECDSA_size(eckey)); |
564 if (signature.size() > max_expected_size) { | 551 if (signature.size() > max_expected_size) { |
565 LOG(ERROR) << "ECDSA Signature size mismatch, actual: " | 552 LOG(ERROR) << "ECDSA Signature size mismatch, actual: " << signature.size() |
566 << signature.size() << ", expected <= " | 553 << ", expected <= " << max_expected_size; |
567 << max_expected_size; | |
568 return NULL; | 554 return NULL; |
569 } | 555 } |
570 | 556 |
571 // Convert signature to ECDSA_SIG object | 557 // Convert signature to ECDSA_SIG object |
572 const unsigned char* sigbuf = | 558 const unsigned char* sigbuf = |
573 reinterpret_cast<const unsigned char*>(&signature[0]); | 559 reinterpret_cast<const unsigned char*>(&signature[0]); |
574 long siglen = static_cast<long>(signature.size()); | 560 long siglen = static_cast<long>(signature.size()); |
575 return d2i_ECDSA_SIG(NULL, &sigbuf, siglen); | 561 return d2i_ECDSA_SIG(NULL, &sigbuf, siglen); |
576 } | 562 } |
577 | 563 |
578 int EcdsaMethodSignSetup(EC_KEY* eckey, | 564 int EcdsaMethodSignSetup(EC_KEY* eckey, |
579 BN_CTX* ctx, | 565 BN_CTX* ctx, |
580 BIGNUM** kinv, | 566 BIGNUM** kinv, |
581 BIGNUM** r) { | 567 BIGNUM** r) { |
582 NOTIMPLEMENTED(); | 568 NOTIMPLEMENTED(); |
583 ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ECDSA_R_ERR_EC_LIB); | 569 ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ECDSA_R_ERR_EC_LIB); |
584 return -1; | 570 return -1; |
585 } | 571 } |
586 | 572 |
587 int EcdsaMethodDoVerify(const unsigned char* dgst, | 573 int EcdsaMethodDoVerify(const unsigned char* dgst, |
588 int dgst_len, | 574 int dgst_len, |
589 const ECDSA_SIG* sig, | 575 const ECDSA_SIG* sig, |
590 EC_KEY* eckey) { | 576 EC_KEY* eckey) { |
591 NOTIMPLEMENTED(); | 577 NOTIMPLEMENTED(); |
592 ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_ERR_EC_LIB); | 578 ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_ERR_EC_LIB); |
593 return -1; | 579 return -1; |
594 } | 580 } |
595 | 581 |
596 const ECDSA_METHOD android_ecdsa_method = { | 582 const ECDSA_METHOD android_ecdsa_method = { |
597 /* .name = */ "Android signing-only ECDSA method", | 583 /* .name = */ "Android signing-only ECDSA method", |
598 /* .ecdsa_do_sign = */ EcdsaMethodDoSign, | 584 /* .ecdsa_do_sign = */ EcdsaMethodDoSign, |
599 /* .ecdsa_sign_setup = */ EcdsaMethodSignSetup, | 585 /* .ecdsa_sign_setup = */ EcdsaMethodSignSetup, |
600 /* .ecdsa_do_verify = */ EcdsaMethodDoVerify, | 586 /* .ecdsa_do_verify = */ EcdsaMethodDoVerify, |
601 /* .flags = */ 0, | 587 /* .flags = */ 0, |
602 /* .app_data = */ NULL, | 588 /* .app_data = */ NULL, |
603 }; | 589 }; |
604 | 590 |
605 // Setup an EVP_PKEY to wrap an existing platform PrivateKey object. | 591 // Setup an EVP_PKEY to wrap an existing platform PrivateKey object. |
606 // |private_key| is the JNI reference (local or global) to the object. | 592 // |private_key| is the JNI reference (local or global) to the object. |
607 // |pkey| is the EVP_PKEY to setup as a wrapper. | 593 // |pkey| is the EVP_PKEY to setup as a wrapper. |
608 // Returns true on success, false otherwise. | 594 // Returns true on success, false otherwise. |
609 // On success, this creates a global JNI reference to the object that | 595 // On success, this creates a global JNI reference to the object that |
610 // is owned by and destroyed with the EVP_PKEY. I.e. the caller shall | 596 // is owned by and destroyed with the EVP_PKEY. I.e. the caller shall |
611 // always free |private_key| after the call. | 597 // always free |private_key| after the call. |
612 bool GetEcdsaPkeyWrapper(jobject private_key, EVP_PKEY* pkey) { | 598 bool GetEcdsaPkeyWrapper(jobject private_key, EVP_PKEY* pkey) { |
(...skipping 17 matching lines...) Expand all Loading... |
630 return false; | 616 return false; |
631 } | 617 } |
632 EC_KEY_set_group(eckey.get(), group.release()); | 618 EC_KEY_set_group(eckey.get(), group.release()); |
633 | 619 |
634 ScopedJavaGlobalRef<jobject> global_key; | 620 ScopedJavaGlobalRef<jobject> global_key; |
635 global_key.Reset(NULL, private_key); | 621 global_key.Reset(NULL, private_key); |
636 if (global_key.is_null()) { | 622 if (global_key.is_null()) { |
637 LOG(ERROR) << "Can't create global JNI reference"; | 623 LOG(ERROR) << "Can't create global JNI reference"; |
638 return false; | 624 return false; |
639 } | 625 } |
640 ECDSA_set_ex_data(eckey.get(), | 626 ECDSA_set_ex_data(eckey.get(), EcdsaGetExDataIndex(), global_key.Release()); |
641 EcdsaGetExDataIndex(), | |
642 global_key.Release()); | |
643 | 627 |
644 EVP_PKEY_assign_EC_KEY(pkey, eckey.release()); | 628 EVP_PKEY_assign_EC_KEY(pkey, eckey.release()); |
645 return true; | 629 return true; |
646 } | 630 } |
647 | 631 |
648 } // namespace | 632 } // namespace |
649 | 633 |
650 EVP_PKEY* GetOpenSSLPrivateKeyWrapper(jobject private_key) { | 634 EVP_PKEY* GetOpenSSLPrivateKeyWrapper(jobject private_key) { |
651 // Create new empty EVP_PKEY instance. | 635 // Create new empty EVP_PKEY instance. |
652 ScopedEVP_PKEY pkey(EVP_PKEY_new()); | 636 ScopedEVP_PKEY pkey(EVP_PKEY_new()); |
653 if (!pkey.get()) | 637 if (!pkey.get()) |
654 return NULL; | 638 return NULL; |
655 | 639 |
656 // Create sub key type, depending on private key's algorithm type. | 640 // Create sub key type, depending on private key's algorithm type. |
657 PrivateKeyType key_type = GetPrivateKeyType(private_key); | 641 PrivateKeyType key_type = GetPrivateKeyType(private_key); |
658 switch (key_type) { | 642 switch (key_type) { |
659 case PRIVATE_KEY_TYPE_RSA: | 643 case PRIVATE_KEY_TYPE_RSA: { |
660 { | 644 // Route around platform bug: if Android < 4.2, then |
661 // Route around platform bug: if Android < 4.2, then | 645 // base::android::RawSignDigestWithPrivateKey() cannot work, so |
662 // base::android::RawSignDigestWithPrivateKey() cannot work, so | 646 // instead, obtain a raw EVP_PKEY* to the system object |
663 // instead, obtain a raw EVP_PKEY* to the system object | 647 // backing this PrivateKey object. |
664 // backing this PrivateKey object. | 648 const int kAndroid42ApiLevel = 17; |
665 const int kAndroid42ApiLevel = 17; | 649 if (base::android::BuildInfo::GetInstance()->sdk_int() < |
666 if (base::android::BuildInfo::GetInstance()->sdk_int() < | 650 kAndroid42ApiLevel) { |
667 kAndroid42ApiLevel) { | 651 EVP_PKEY* legacy_key = GetRsaLegacyKey(private_key); |
668 EVP_PKEY* legacy_key = GetRsaLegacyKey(private_key); | 652 if (legacy_key == NULL) |
669 if (legacy_key == NULL) | 653 return NULL; |
670 return NULL; | 654 pkey.reset(legacy_key); |
671 pkey.reset(legacy_key); | 655 } else { |
672 } else { | 656 // Running on Android 4.2. |
673 // Running on Android 4.2. | 657 if (!GetRsaPkeyWrapper(private_key, pkey.get())) |
674 if (!GetRsaPkeyWrapper(private_key, pkey.get())) | 658 return NULL; |
675 return NULL; | |
676 } | |
677 } | 659 } |
678 break; | 660 } break; |
679 case PRIVATE_KEY_TYPE_DSA: | 661 case PRIVATE_KEY_TYPE_DSA: |
680 if (!GetDsaPkeyWrapper(private_key, pkey.get())) | 662 if (!GetDsaPkeyWrapper(private_key, pkey.get())) |
681 return NULL; | 663 return NULL; |
682 break; | 664 break; |
683 case PRIVATE_KEY_TYPE_ECDSA: | 665 case PRIVATE_KEY_TYPE_ECDSA: |
684 if (!GetEcdsaPkeyWrapper(private_key, pkey.get())) | 666 if (!GetEcdsaPkeyWrapper(private_key, pkey.get())) |
685 return NULL; | 667 return NULL; |
686 break; | 668 break; |
687 default: | 669 default: |
688 LOG(WARNING) | 670 LOG(WARNING) |
689 << "GetOpenSSLPrivateKeyWrapper() called with invalid key type"; | 671 << "GetOpenSSLPrivateKeyWrapper() called with invalid key type"; |
690 return NULL; | 672 return NULL; |
691 } | 673 } |
692 return pkey.release(); | 674 return pkey.release(); |
693 } | 675 } |
694 | 676 |
695 } // namespace android | 677 } // namespace android |
696 } // namespace net | 678 } // namespace net |
OLD | NEW |