Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(52)

Side by Side Diff: net/android/keystore_openssl.cc

Issue 11571059: Add net/android/keystore.h (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: PEM data files + RSA_size() / DSA_size() support. Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "net/android/keystore_openssl.h"
6
7 #include <jni.h>
8 #include <openssl/bn.h>
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
11 // not be a concern for Chromium which always links against its own
12 // version of the library on Android.
13 #include <openssl/crypto/ecdsa/ecs_locl.h>
14 #include <openssl/dsa.h>
15 #include <openssl/engine.h>
16 #include <openssl/evp.h>
17 #include <openssl/rsa.h>
18
19 #include <pthread.h>
20
21 #include "base/android/build_info.h"
22 #include "base/android/jni_android.h"
23 #include "base/android/scoped_java_ref.h"
24 #include "base/basictypes.h"
25 #include "base/logging.h"
26 #include "crypto/openssl_util.h"
27 #include "net/android/keystore.h"
28 #include "net/base/ssl_client_cert_type.h"
29
30 // IMPORTANT NOTE: The following code will currently only work when used
31 // to implement client certificate support with OpenSSL. That's because
32 // only signing is implemented here.
33 //
34
35 // The OpenSSL EVP_PKEY type is a generic wrapper around key pairs.
36 // Internally, it can hold a pointer to a RSA, DSA or ECDSA structure,
37 // which model keypair implementations of each respective crypto
38 // algorithm.
39 //
40 // The RSA type has a 'method' field pointer to a vtable-like structure
41 // called a RSA_METHOD. This contains several function pointers that
42 // correspond to operations on RSA keys (e.g. decode/encode with public
43 // key, decode/encode with private key, signing, validation), as well as
44 // a few flags.
45 //
46 // For example, the RSA_sign() function will call "method->rsa_sign()" if
47 // method->rsa_sign is not NULL, otherwise, it will perform a regular
48 // signing operation using the other fields in the RSA structure (which
49 // are used to hold the typical modulus / exponent / parameters for the
50 // key pair).
51 //
52 // This source file thus defines a custom RSA_METHOD structure, which
53 // fields points to static methods used to implement the corresponding
54 // RSA operation using platform Android APIs.
55 //
56 // However, the platform APIs require a jobject JNI reference to work.
57 // It must be stored in the RSA instance, or made accessible when the
58 // custom RSA methods are called. This is done by using RSA_set_app_data()
59 // and RSA_get_app_data().
60 //
61 // One can thus _directly_ create a new EVP_PKEY that uses a custom RSA
62 // object with the following:
63 //
64 // RSA* rsa = RSA_new()
65 // RSA_set_method(&custom_rsa_method);
66 // RSA_set_app_data(rsa, jni_private_key);
67 //
68 // EVP_PKEY* pkey = EVP_PKEY_new();
69 // EVP_PKEY_assign_RSA(pkey, rsa);
70 //
71 // Note that because EVP_PKEY_assign_RSA() is used, instead of
72 // EVP_PKEY_set1_RSA(), the new EVP_PKEY now owns the RSA object, and
73 // will destroy it when it is itself destroyed.
74 //
75 // Similarly, custom DSA_METHOD and ECDSA_METHOD are defined by this source
76 // file.
77 //
78 // Note that there is no need to define an OpenSSL ENGINE here. These
79 // are objects that can be used to expose custom methods (i.e. either
80 // RSA_METHOD, DSA_METHOD, ECDSA_METHOD, and a large number of other ones
81 // for types not related to this source file), and make them used by
82 // default for a lot of operations. Very fortunately, this is not needed
83 // here, which saves a lot of complexity.
84
85 using base::android::ScopedJavaGlobalRef;
86
87 namespace {
88
89 typedef crypto::ScopedOpenSSL<EVP_PKEY, EVP_PKEY_free> ScopedEVP_PKEY;
90 typedef crypto::ScopedOpenSSL<RSA, RSA_free> ScopedRSA;
91 typedef crypto::ScopedOpenSSL<DSA, DSA_free> ScopedDSA;
92
93 ///////////////////////////////////////////////////////////////////////////
94 //
95 // Custom RSA_METHOD that uses the platform APIs.
96 // Note that for now, only signing through RSA_sign() is really supported.
97 // all other method pointers are either stubs returning errors, or no-ops.
98 //
99 // See <openssl/rsa.h> for exact declaration of RSA_METHOD.
100 //
101
102 int RsaMethodPubEnc(int flen,
103 const unsigned char* from,
104 unsigned char* to,
105 RSA* rsa,
106 int padding) {
107 NOTIMPLEMENTED();
108 RSAerr(RSA_F_RSA_PUBLIC_ENCRYPT, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED);
109 return -1;
110 }
111
112 int RsaMethodPubDec(int flen,
113 const unsigned char* from,
114 unsigned char* to,
115 RSA* rsa,
116 int padding) {
117 NOTIMPLEMENTED();
118 RSAerr(RSA_F_RSA_PUBLIC_DECRYPT, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED);
119 return -1;
120 }
121
122 int RsaMethodPrivEnc(int flen,
123 const unsigned char *from,
124 unsigned char *to,
125 RSA *rsa,
126 int padding) {
127 NOTIMPLEMENTED();
128 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED);
129 return -1;
130 }
131
132 int RsaMethodPrivDec(int flen,
133 const unsigned char* from,
134 unsigned char* to,
135 RSA* rsa,
136 int padding) {
137 NOTIMPLEMENTED();
138 RSAerr(RSA_F_RSA_PRIVATE_DECRYPT, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED);
139 return -1;
140 }
141
142 int RsaMethodInit(RSA* rsa) {
143 // Required to ensure that RsaMethodSign will be called.
144 rsa->flags |= RSA_FLAG_SIGN_VER;
145 return 0;
146 }
147
148 int RsaMethodFinish(RSA* rsa) {
149 // Ensure the global JNI reference is destroyed with this key.
150 jobject key = reinterpret_cast<jobject>(RSA_get_app_data(rsa));
151 if (key != NULL) {
152 RSA_set_app_data(rsa, NULL);
153 JNIEnv* env = base::android::AttachCurrentThread();
154 env->DeleteGlobalRef(key);
155 }
156 // Actual return value is ignored by OpenSSL. There are no docs
157 // explaining what this is supposed to be.
158 return 0;
159 }
160
161 int RsaMethodSign(int type,
162 const unsigned char* message,
163 unsigned int message_len,
164 unsigned char* signature,
165 unsigned int* signature_len,
166 const RSA* rsa) {
167 // This is only used for client certificate support, which
168 // will always pass the NID_md5_sha1 |type| value.
169 DCHECK_EQ(NID_md5_sha1, type);
170 if (type != NID_md5_sha1) {
171 RSAerr(RSA_F_RSA_SIGN, RSA_R_UNKNOWN_ALGORITHM_TYPE);
172 return 0;
173 }
174 // Retrieve private key JNI reference.
175 jobject private_key = reinterpret_cast<jobject>(RSA_get_app_data(rsa));
176 if (!private_key) {
177 LOG(WARNING) << "Null JNI reference passed to RsaMethodSign!";
178 return 0;
179 }
180 // Sign message with it through JNI.
181 base::StringPiece message_piece(reinterpret_cast<const char*>(message),
182 static_cast<size_t>(message_len));
183 std::vector<uint8> result;
184
185 if (!net::android::RawSignDigestWithPrivateKey(
186 private_key, message_piece, &result)) {
187 LOG(WARNING) << "Could not sign message in RsaMethodSign!";
188 return 0;
189 }
190
191 size_t expected_size = static_cast<size_t>(RSA_size(rsa));
192 if (expected_size != result.size()) {
193 LOG(ERROR) << "RSA Signature size mismatch, actual: " <<
194 result.size() << ", expected " << expected_size;
195 return 0;
196 }
197
198 // Copy result to OpenSSL-provided buffer
199 memcpy(signature, &result[0], result.size());
200 *signature_len = static_cast<unsigned int>(result.size());
201 return 1;
202 }
203
204 const RSA_METHOD android_rsa_method = {
205 /* .name = */ "Android signing-only RSA method",
206 /* .rsa_pub_enc = */ RsaMethodPubEnc,
207 /* .rsa_pub_dec = */ RsaMethodPubDec,
208 /* .rsa_priv_enc = */ RsaMethodPrivEnc,
209 /* .rsa_priv_dec = */ RsaMethodPrivDec,
210 /* .rsa_mod_exp = */ NULL,
211 /* .bn_mod_exp = */ NULL,
212 /* .init = */ RsaMethodInit,
213 /* .finish = */ RsaMethodFinish,
214 /* .flags = */ RSA_FLAG_SIGN_VER, // indicates that rsa_sign is usable.
215 /* .app_data = */ NULL,
216 /* .rsa_sign = */ RsaMethodSign,
217 /* .rsa_verify = */ NULL,
218 /* .rsa_keygen = */ NULL,
219 };
220
221 // This method only works on Android >= 4.2.
222 void GetRsaPkeyWrapper(ScopedEVP_PKEY& pkey,
223 ScopedJavaGlobalRef<jobject>& private_key) {
224 ScopedRSA rsa(RSA_new());
225 RSA_set_method(rsa.get(), &android_rsa_method);
226
227 // HACK: RSA_size() doesn't work with custom RSA_METHODs. To ensure that
228 // it will return the right value, set the 'n' field of the RSA object
229 // to match the private key's modulus.
230 // If this fails, simply exit, since this will let pkey.get()
231 // unchanged, it will stay at NULL.
232 std::vector<uint8> modulus;
233 if (!net::android::GetRSAKeyModulus(private_key.obj(), &modulus)) {
234 LOG(ERROR) << "Failed to get private key modulus";
235 return;
236 }
237
238 rsa.get()->n = BN_bin2bn(
239 reinterpret_cast<const unsigned char*>(&modulus[0]),
240 static_cast<int>(modulus.size()),
241 NULL
242 );
Ryan Sleevi 2013/02/01 00:51:30 style: whitespace for );
digit1 2013/02/01 21:44:36 Done.
243 if (!rsa.get()->n) {
244 LOG(ERROR) << "Failed to set private key modulus";
245 return;
246 }
247
248 RSA_set_app_data(rsa.get(), private_key.Release());
249 EVP_PKEY_assign_RSA(pkey.get(), rsa.release());
250 }
251
252 // This method can be used on Android < 4.2 instead.
253 // It first tries to get the system OpenSSL pointer directly.
254 void GetRsaLegacyKey(ScopedEVP_PKEY& pkey,
255 ScopedJavaGlobalRef<jobject>& private_key) {
256 EVP_PKEY* sys_pkey =
257 net::android::GetOpenSSLSystemHandleForPrivateKey(private_key.obj());
258 if (sys_pkey != NULL) {
259 CRYPTO_add(&sys_pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
260 } else {
261 // GetOpenSSLSystemHandleForPrivateKey() will fail on Android
262 // 4.0.3 and earlier. However, it is possible to get the key
263 // content with PrivateKey.getEncoded() on these platforms.
264 // Note that this method may return NULL on 4.0.4 and later.
265 std::vector<uint8> encoded;
266 if (!net::android::GetPrivateKeyEncodedBytes(
267 private_key.obj(), &encoded)) {
268 LOG(ERROR) << "Can't get private key data!";
269 return;
270 }
271 const unsigned char* p =
272 reinterpret_cast<const unsigned char*>(&encoded[0]);
273 int len = static_cast<int>(encoded.size());
274 sys_pkey = d2i_AutoPrivateKey(NULL, &p, len);
275 if (sys_pkey == NULL) {
276 LOG(ERROR) << "Can't convert private key data!";
277 return;
278 }
279 }
280 pkey.reset(sys_pkey);
281 }
282
283 ///////////////////////////////////////////////////////////////////////////
284 //
285 // Custom DSA_METHOD that uses the platform APIs.
286 // Note that for now, only signing through DSA_sign() is really supported.
287 // all other method pointers are either stubs returning errors, or no-ops.
288 //
289 // See <openssl/dsa.h> for exact declaration of DSA_METHOD.
290 //
291 // Note: There is no DSA_set_app_data() and DSA_get_app_data() functions,
292 // but RSA_set_app_data() is defined as a simple macro that calls
293 // RSA_set_ex_data() with a hard-coded index of 0, so this code
294 // does the same thing here.
295
296 static DSA_SIG* DsaMethodDoSign(const unsigned char* dgst,
297 int dlen,
298 DSA* dsa) {
299 // Extract the JNI reference to the PrivateKey object.
300 jobject private_key = reinterpret_cast<jobject>(DSA_get_ex_data(dsa, 0));
301 if (private_key == NULL)
302 return NULL;
303
304 // Sign the message with it, calling platform APIs.
305 std::vector<uint8> signature;
306 if (!net::android::RawSignDigestWithPrivateKey(
307 private_key,
308 base::StringPiece(
309 reinterpret_cast<const char*>(dgst),
310 static_cast<size_t>(dlen)),
311 &signature)) {
312 return NULL;
313 }
314
315 // Note: the signature length is really expected to be DSA_size() - 2.
316 size_t expected_size = static_cast<size_t>(DSA_size(dsa)) - 2U;
317 if (expected_size != signature.size()) {
318 LOG(ERROR) << "DSA Signature size mismatch, actual: " <<
319 signature.size() << ", expected " << expected_size;
320 return 0;
321 }
322
323 // Convert the signature into a DSA_SIG object.
324 const unsigned char* sigbuf =
325 reinterpret_cast<const unsigned char*>(&signature[0]);
326 int siglen = static_cast<size_t>(signature.size());
327 DSA_SIG* dsa_sig = d2i_DSA_SIG(NULL, &sigbuf, siglen);
328 return dsa_sig;
329 }
330
331 static int DsaMethodSignSetup(DSA* dsa,
332 BN_CTX* ctx_in,
333 BIGNUM** kinvp,
334 BIGNUM** rp) {
335 NOTIMPLEMENTED();
336 DSAerr(DSA_F_DSA_SIGN_SETUP, DSA_R_INVALID_DIGEST_TYPE);
337 return -1;
338 }
339
340 static int DsaMethodDoVerify(const unsigned char* dgst,
341 int dgst_len,
342 DSA_SIG* sig,
343 DSA* dsa) {
344 NOTIMPLEMENTED();
345 DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_INVALID_DIGEST_TYPE);
346 return -1;
347 }
348
349 static int DsaMethodFinish(DSA* dsa) {
350 // Free the global JNI reference.
351 jobject key = reinterpret_cast<jobject>(DSA_get_ex_data(dsa,0));
352 if (key != NULL) {
353 DSA_set_ex_data(dsa, 0, NULL);
354 JNIEnv* env = base::android::AttachCurrentThread();
355 env->DeleteGlobalRef(key);
356 }
357 // Actual return value is ignored by OpenSSL. There are no docs
358 // explaining what this is supposed to be.
359 return 0;
360 }
361
362 const DSA_METHOD android_dsa_method = {
363 /* .name = */ "Android signing-only DSA method",
364 /* .dsa_do_sign = */ DsaMethodDoSign,
365 /* .dsa_sign_setup = */ DsaMethodSignSetup,
366 /* .dsa_do_verify = */ DsaMethodDoVerify,
367 /* .dsa_mod_exp = */ NULL,
368 /* .bn_mod_exp = */ NULL,
369 /* .init = */ NULL, // nothing to do here.
370 /* .finish = */ DsaMethodFinish,
371 /* .flags = */ 0,
372 /* .app_data = */ NULL,
373 /* .dsa_paramgem = */ NULL,
374 /* .dsa_keygen = */ NULL
375 };
376
377 void GetDsaPkeyWrapper(ScopedEVP_PKEY& pkey,
378 ScopedJavaGlobalRef<jobject>& private_key) {
379 ScopedDSA dsa(DSA_new());
380 DSA_set_method(dsa.get(), &android_dsa_method);
381
382 // HACK: DSA_size() doesn't work with custom DSA_METHODs. To ensure it
383 // returns the right value, set the 'q' field in the DSA object to
384 // match the parameter from the platform key.
385 std::vector<uint8> q;
386 if (!net::android::GetDSAKeyParamQ(private_key.obj(), &q)) {
387 LOG(ERROR) << "Can't extract Q parameter from DSA private key";
388 return;
389 }
390 dsa.get()->q = BN_bin2bn(
391 reinterpret_cast<const unsigned char*>(&q[0]),
392 static_cast<int>(q.size()),
393 NULL);
394 if (!dsa.get()->q) {
395 LOG(ERROR) << "Can't decode Q parameter from DSA private key";
396 return;
397 }
398
399 DSA_set_ex_data(dsa.get(), 0, private_key.Release());
400 EVP_PKEY_assign_DSA(pkey.get(), dsa.release());
401 }
402
403 ///////////////////////////////////////////////////////////////////////////
404 //
405 // Custom ECDSA_METHOD that uses the platform APIs.
406 // Note that for now, only signing through ECDSA_sign() is really supported.
407 // all other method pointers are either stubs returning errors, or no-ops.
408 //
409 // Note: The ECDSA_METHOD structure doesn't have init/finish
410 // methods. As such, the only way to to ensure the global
411 // JNI reference is properly released when the EVP_PKEY is
412 // destroyed is to use a custom EX_DATA type.
413
414 // Used to ensure that the global JNI reference associated with a
415 // custom EC_KEY + ECDSA_METHOD is released when the key is destroyed.
416 void ExDataFree(void* parent,
417 void* ptr,
418 CRYPTO_EX_DATA* ad,
419 int idx,
420 long argl,
421 void* argp) {
422 jobject private_key = reinterpret_cast<jobject>(ptr);
423 if (private_key == NULL)
424 return;
425
426 CRYPTO_set_ex_data(ad, idx, NULL);
427
428 JNIEnv* env = base::android::AttachCurrentThread();
429 env->DeleteGlobalRef(private_key);
430 }
431
432 int ExDataDup(CRYPTO_EX_DATA* to,
433 CRYPTO_EX_DATA* from,
434 void* from_d,
435 int idx,
436 long argl,
437 void* argp) {
438 // This callback shall never be called with the current OpenSSL
439 // implementation (the library only ever duplicates EX_DATA items
440 // for SSL and BIO objects). But provide this to catch regressions
441 // in the future.
442 NOTIMPLEMENTED();
443 LOG(WARNING) << "ExDataDup for was called for ECDSA custom key !?";
444 // Return value is currently ignored by OpenSSL.
445 return 0;
446 }
447
448 int s_ecdsa_ex_data_index;
449
450 void EcdsaInitExDataIndex(void) {
451 // Note that OpenSSL does not provide a way to unregister these
452 // indices, so don't worry about releasing them on program exit.
453 // There is also no need for an ExDataNew function.
454 s_ecdsa_ex_data_index = ECDSA_get_ex_new_index(0, // argl
455 NULL, // argp
456 NULL, // new_func
457 ExDataDup, // dup_func
458 ExDataFree); // free_func
459 }
460
461 // Returns the index of the custom EX_DATA used to store the JNI reference.
462 int EcdsaGetExDataIndex(void) {
463 // The index must be initialized once per processs, and this function
464 // can be called from distinct threads. Use a pthread_once_t to perform
465 // proper lazy initialization.
466 static pthread_once_t once = PTHREAD_ONCE_INIT;
467 pthread_once(&once, EcdsaInitExDataIndex);
468 return s_ecdsa_ex_data_index;
469 }
470
471 ECDSA_SIG* EcdsaMethodDoSign(const unsigned char* dgst,
472 int dgst_len,
473 const BIGNUM* inv,
474 const BIGNUM* rp,
475 EC_KEY* eckey) {
476 // Retrieve private key JNI reference.
477 jobject private_key = reinterpret_cast<jobject>(
478 ECDSA_get_ex_data(eckey, EcdsaGetExDataIndex()));
479 if (!private_key) {
480 LOG(WARNING) << "Null JNI reference passed to EcdsaMethodDoSign!";
481 return NULL;
482 }
483 // Sign message with it through JNI.
484 std::vector<uint8> signature;
485 if (!net::android::RawSignDigestWithPrivateKey(
486 private_key,
487 base::StringPiece(
488 reinterpret_cast<const char*>(dgst),
489 static_cast<size_t>(dgst_len)),
490 &signature)) {
491 LOG(WARNING) << "Could not sign message in EcdsaMethodDoSign!";
492 return NULL;
493 }
494
495 #if 0
496 // TODO(digit): Enabled once ECDSA_size() works on the wrapper.
497 // Note: the signature length is really expected to be ECDSA_size() - 2.
498 size_t expected_size = static_cast<size_t>(ECDSA_size(eckey)) - 2U;
499 if (expected_size != signature.size()) {
500 LOG(ERROR) << "ECDSA Signature size mismatch, actual: " <<
501 signature.size() << ", expected " << expected_size;
502 return 0;
503 }
504 #endif
505
506 // Convert signature to ECDSA_SIG object
507 const unsigned char* sigbuf =
508 reinterpret_cast<const unsigned char*>(&signature[0]);
509 long siglen = static_cast<long>(signature.size());
510 return d2i_ECDSA_SIG(NULL, &sigbuf, siglen);
511 }
512
513 int EcdsaMethodSignSetup(EC_KEY* eckey,
514 BN_CTX* ctx,
515 BIGNUM** kinv,
516 BIGNUM** r) {
517 NOTIMPLEMENTED();
518 ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ECDSA_R_ERR_EC_LIB);
519 return -1;
520 }
521
522 int EcdsaMethodDoVerify(const unsigned char* dgst,
523 int dgst_len,
524 const ECDSA_SIG* sig,
525 EC_KEY* eckey) {
526 NOTIMPLEMENTED();
527 ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_ERR_EC_LIB);
528 return -1;
529 }
530
531 const ECDSA_METHOD android_ecdsa_method = {
532 /* .name = */ "Android signing-only ECDSA method",
533 /* .ecdsa_do_sign = */ EcdsaMethodDoSign,
534 /* .ecdsa_sign_setup = */ EcdsaMethodSignSetup,
535 /* .ecdsa_do_verify = */ EcdsaMethodDoVerify,
536 /* .flags = */ 0,
537 /* .app_data = */ NULL,
538 };
539
540 void GetEcdsaPkeyWrapper(ScopedEVP_PKEY& pkey,
541 ScopedJavaGlobalRef<jobject>& private_key) {
542 EC_KEY* ec_key = EC_KEY_new();
543 ECDSA_set_method(ec_key, &android_ecdsa_method);
544
545 // TODO(digit): Find a way to force ECDSA_size() to return the right
546 // value by extracting the relevant data from the private key.
547
548 ECDSA_set_ex_data(ec_key, EcdsaGetExDataIndex(), private_key.Release());
549 EVP_PKEY_assign_EC_KEY(pkey.get(), ec_key);
550 }
551
552 } // namespace
553
554
555 namespace net {
556 namespace android {
557
558 EVP_PKEY* GetOpenSSLPrivateKeyWrapper(jobject private_key) {
559 // Create scoped JNI global reference from the private key.
560 // This ensure that it will be usable from any thread, not only
561 // from the caller's.
562 //
563 // Note: "ScopedJavaGlobalRef<jobject> ref(a_jobject)" doesn't
564 // compile. Route around this by creating an empty object first,
565 // then resetting it.
566 ScopedJavaGlobalRef<jobject> global_key;
567 global_key.Reset(NULL, private_key);
568 if (global_key.is_null())
569 return NULL;
570
571 // Create new empty EVP_PKEY instance.
572 ScopedEVP_PKEY pkey(EVP_PKEY_new());
573 if (!pkey.get())
574 return NULL;
575
576 // Create sub key type, depending on private key's algorithm type.
577 PrivateKeyType key_type = GetPrivateKeyType(global_key.obj());
578 switch (key_type) {
579 case PRIVATE_KEY_TYPE_RSA:
580 {
581 // Route around platform bug: if Android < 4.2, then
582 // base::android::RawSignDigestWithPrivateKey() cannot work, so
583 // instead, obtain a raw EVP_PKEY* to the system object
584 // backing this PrivateKey object.
585 const int kAndroid42ApiLevel = 17;
586 if (base::android::BuildInfo::GetInstance()->sdk_int() <
587 kAndroid42ApiLevel) {
588 GetRsaLegacyKey(pkey, global_key);
589 } else {
590 // Running on Android 4.2.
591 GetRsaPkeyWrapper(pkey, global_key);
592 }
593 }
594 break;
595 case PRIVATE_KEY_TYPE_DSA:
596 GetDsaPkeyWrapper(pkey, global_key);
597 break;
598 case PRIVATE_KEY_TYPE_ECDSA:
599 GetEcdsaPkeyWrapper(pkey, global_key);
600 break;
601 default:
602 LOG(WARNING)
603 << "GetOpenSSLPrivateKeyWrapper() called with invalid key type";
604 return NULL;
605 }
606
607 return pkey.release();
608 }
609
610 } // namespace android
611 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698