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

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

Issue 345063006: Switch to BoringSSL. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: g try Created 6 years, 5 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 | Annotate | Revision Log
OLDNEW
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 #include <openssl/bytestring.h>
davidben 2014/07/16 21:58:54 Nit: Is this include being used?
agl 2014/07/16 22:08:01 Good point. Was included to build an ASN.1 signatu
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 // And this one is needed for the EC_GROUP definition.
15 #include <openssl/crypto/ec/ec_lcl.h>
16 #include <openssl/dsa.h> 10 #include <openssl/dsa.h>
17 #include <openssl/ec.h> 11 #include <openssl/ec.h>
18 #include <openssl/engine.h> 12 #include <openssl/engine.h>
13 #include <openssl/err.h>
19 #include <openssl/evp.h> 14 #include <openssl/evp.h>
20 #include <openssl/rsa.h> 15 #include <openssl/rsa.h>
21 16
22 #include "base/android/build_info.h" 17 #include "base/android/build_info.h"
23 #include "base/android/jni_android.h" 18 #include "base/android/jni_android.h"
24 #include "base/android/scoped_java_ref.h" 19 #include "base/android/scoped_java_ref.h"
25 #include "base/basictypes.h" 20 #include "base/basictypes.h"
26 #include "base/lazy_instance.h" 21 #include "base/lazy_instance.h"
27 #include "base/logging.h" 22 #include "base/logging.h"
28 #include "crypto/openssl_util.h" 23 #include "crypto/openssl_util.h"
(...skipping 24 matching lines...) Expand all
53 // For example, the RSA_sign() function will call "method->rsa_sign()" if 48 // For example, the RSA_sign() function will call "method->rsa_sign()" if
54 // method->rsa_sign is not NULL, otherwise, it will perform a regular 49 // method->rsa_sign is not NULL, otherwise, it will perform a regular
55 // signing operation using the other fields in the RSA structure (which 50 // signing operation using the other fields in the RSA structure (which
56 // are used to hold the typical modulus / exponent / parameters for the 51 // are used to hold the typical modulus / exponent / parameters for the
57 // key pair). 52 // key pair).
58 // 53 //
59 // This source file thus defines a custom RSA_METHOD structure whose 54 // This source file thus defines a custom RSA_METHOD structure whose
60 // fields point to static methods used to implement the corresponding 55 // fields point to static methods used to implement the corresponding
61 // RSA operation using platform Android APIs. 56 // RSA operation using platform Android APIs.
62 // 57 //
63 // However, the platform APIs require a jobject JNI reference to work. 58 // However, the platform APIs require a jobject JNI reference to work. It must
64 // It must be stored in the RSA instance, or made accessible when the 59 // be stored in the RSA instance, or made accessible when the custom RSA
65 // custom RSA methods are called. This is done by using RSA_set_app_data() 60 // methods are called. This is done by storing it in a |KeyExData| structure
66 // and RSA_get_app_data(). 61 // that's referenced by the key using |EX_DATA|.
67 //
68 // One can thus _directly_ create a new EVP_PKEY that uses a custom RSA
69 // object with the following:
70 //
71 // RSA* rsa = RSA_new()
72 // RSA_set_method(&custom_rsa_method);
73 // RSA_set_app_data(rsa, jni_private_key);
74 //
75 // EVP_PKEY* pkey = EVP_PKEY_new();
76 // EVP_PKEY_assign_RSA(pkey, rsa);
77 //
78 // Note that because EVP_PKEY_assign_RSA() is used, instead of
79 // EVP_PKEY_set1_RSA(), the new EVP_PKEY now owns the RSA object, and
80 // will destroy it when it is itself destroyed.
81 //
82 // Unfortunately, such objects cannot be used with RSA_size(), which
83 // totally ignores the RSA_METHOD pointers. Instead, it is necessary
84 // to manually setup the modulus field (n) in the RSA object, with a
85 // value that matches the wrapped PrivateKey object. See GetRsaPkeyWrapper
86 // for full details.
87 //
88 // Similarly, custom DSA_METHOD and ECDSA_METHOD are defined by this source
89 // file, and appropriate field setups are performed to ensure that
90 // DSA_size() and ECDSA_size() work properly with the wrapper EVP_PKEY.
91 //
92 // Note that there is no need to define an OpenSSL ENGINE here. These
93 // are objects that can be used to expose custom methods (i.e. either
94 // RSA_METHOD, DSA_METHOD, ECDSA_METHOD, and a large number of other ones
95 // for types not related to this source file), and make them used by
96 // default for a lot of operations. Very fortunately, this is not needed
97 // here, which saves a lot of complexity.
98 62
99 using base::android::ScopedJavaGlobalRef; 63 using base::android::ScopedJavaGlobalRef;
100 using base::android::ScopedJavaLocalRef; 64 using base::android::ScopedJavaLocalRef;
101 65
102 namespace net { 66 namespace net {
103 namespace android { 67 namespace android {
104 68
105 namespace { 69 namespace {
106 70
107 typedef crypto::ScopedOpenSSL<EC_GROUP, EC_GROUP_free>::Type ScopedEC_GROUP; 71 extern const RSA_METHOD android_rsa_method;
72 extern const ECDSA_METHOD android_ecdsa_method;
108 73
109 // Custom RSA_METHOD that uses the platform APIs. 74 // KeyExData contains the data that is contained in the EX_DATA of the RSA, DSA
110 // Note that for now, only signing through RSA_sign() is really supported. 75 // and ECDSA objects that are created to wrap Android system keys.
111 // all other method pointers are either stubs returning errors, or no-ops. 76 struct KeyExData {
112 // See <openssl/rsa.h> for exact declaration of RSA_METHOD. 77 // private_key contains a reference to a Java, private-key object.
113
114 struct RsaAppData {
115 jobject private_key; 78 jobject private_key;
79 // legacy_rsa, if not NULL, points to an RSA* in the system's OpenSSL (which
80 // might not be ABI compatible with Chromium).
116 AndroidRSA* legacy_rsa; 81 AndroidRSA* legacy_rsa;
82 // cached_size contains the "size" of the key. This is the size of the
83 // modulus (in bytes) for RSA, or the group order size for (EC)DSA. This
84 // avoids calling into Java to calculate the size.
85 size_t cached_size;
117 }; 86 };
118 87
119 int RsaMethodPubEnc(int flen, 88 // ExDataDup is called when one of the RSA, DSA or EC_KEY objects is
120 const unsigned char* from, 89 // duplicated. We don't support this and it should never happen.
121 unsigned char* to, 90 int ExDataDup(CRYPTO_EX_DATA* to,
122 RSA* rsa, 91 const CRYPTO_EX_DATA* from,
123 int padding) { 92 void** from_d,
124 NOTIMPLEMENTED(); 93 int index,
125 RSAerr(RSA_F_RSA_PUBLIC_ENCRYPT, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED); 94 long argl,
126 return -1; 95 void* argp) {
96 CHECK(false);
97 return 0;
127 } 98 }
128 99
129 int RsaMethodPubDec(int flen, 100 // ExDataFree is called when one of the RSA, DSA or EC_KEY object is freed.
130 const unsigned char* from, 101 void ExDataFree(void* parent,
131 unsigned char* to, 102 void* ptr,
132 RSA* rsa, 103 CRYPTO_EX_DATA* ad,
133 int padding) { 104 int index,
134 NOTIMPLEMENTED(); 105 long argl,
135 RSAerr(RSA_F_RSA_PUBLIC_DECRYPT, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED); 106 void* argp) {
136 return -1; 107 // Ensure the global JNI reference created with this wrapper is
108 // properly destroyed with it.
109 KeyExData *ex_data = reinterpret_cast<KeyExData*>(ptr);
110 if (ex_data != NULL) {
111 ReleaseKey(ex_data->private_key);
112 delete ex_data;
113 }
137 } 114 }
138 115
139 // See RSA_eay_private_encrypt in 116 // BoringSSLEngine is a BoringSSL ENGINE that implements RSA, DSA and ECDSA by
140 // third_party/openssl/openssl/crypto/rsa/rsa_eay.c for the default 117 // forwarding the requested operations to the Java libraries.
141 // implementation of this function. 118 class BoringSSLEngine {
142 int RsaMethodPrivEnc(int flen, 119 public:
143 const unsigned char *from, 120 BoringSSLEngine()
144 unsigned char *to, 121 : rsa_index_(RSA_get_ex_new_index(0 /* argl */,
145 RSA *rsa, 122 NULL /* argp */,
123 NULL /* new_func */,
124 ExDataDup,
125 ExDataFree)),
126 ec_key_index_(EC_KEY_get_ex_new_index(0 /* argl */,
127 NULL /* argp */,
128 NULL /* new_func */,
129 ExDataDup,
130 ExDataFree)),
131 engine_(ENGINE_new()) {
132 ENGINE_set_RSA_method(
133 engine_, &android_rsa_method, sizeof(android_rsa_method));
134 ENGINE_set_ECDSA_method(
135 engine_, &android_ecdsa_method, sizeof(android_ecdsa_method));
136 }
137
138 int rsa_ex_index() const { return rsa_index_; }
139 int ec_key_ex_index() const { return ec_key_index_; }
140
141 const ENGINE* engine() const { return engine_; }
142
143 private:
144 const int rsa_index_;
145 const int ec_key_index_;
146 ENGINE* const engine_;
147 };
148
149 base::LazyInstance<BoringSSLEngine>::Leaky global_boringssl_engine =
150 LAZY_INSTANCE_INITIALIZER;
151
152
153 // VectorBignumSize returns the number of bytes needed to represent the bignum
154 // given in |v|, i.e. the length of |v| less any leading zero bytes.
155 size_t VectorBignumSize(const std::vector<uint8>& v) {
156 size_t size = v.size();
157 // Ignore any leading zero bytes.
158 for (size_t i = 0; i < v.size() && v[i] == 0; i++) {
159 size--;
160 }
161 return size;
162 }
163
164 KeyExData* RsaGetExData(const RSA* rsa) {
165 return reinterpret_cast<KeyExData*>(
166 RSA_get_ex_data(rsa, global_boringssl_engine.Get().rsa_ex_index()));
167 }
168
169 size_t RsaMethodSize(const RSA *rsa) {
170 const KeyExData *ex_data = RsaGetExData(rsa);
171 return ex_data->cached_size;
172 }
173
174 int RsaMethodEncrypt(RSA* rsa,
175 size_t* out_len,
176 uint8_t* out,
177 size_t max_out,
178 const uint8_t* in,
179 size_t in_len,
180 int padding) {
181 NOTIMPLEMENTED();
182 OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE);
183 return 1;
184 }
185
186 int RsaMethodSignRaw(RSA* rsa,
187 size_t* out_len,
188 uint8_t* out,
189 size_t max_out,
190 const uint8_t* in,
191 size_t in_len,
146 int padding) { 192 int padding) {
147 DCHECK_EQ(RSA_PKCS1_PADDING, padding); 193 DCHECK_EQ(RSA_PKCS1_PADDING, padding);
148 if (padding != RSA_PKCS1_PADDING) { 194 if (padding != RSA_PKCS1_PADDING) {
149 // TODO(davidben): If we need to, we can implement RSA_NO_PADDING 195 // TODO(davidben): If we need to, we can implement RSA_NO_PADDING
150 // by using javax.crypto.Cipher and picking either the 196 // by using javax.crypto.Cipher and picking either the
151 // "RSA/ECB/NoPadding" or "RSA/ECB/PKCS1Padding" transformation as 197 // "RSA/ECB/NoPadding" or "RSA/ECB/PKCS1Padding" transformation as
152 // appropriate. I believe support for both of these was added in 198 // appropriate. I believe support for both of these was added in
153 // the same Android version as the "NONEwithRSA" 199 // the same Android version as the "NONEwithRSA"
154 // java.security.Signature algorithm, so the same version checks 200 // java.security.Signature algorithm, so the same version checks
155 // for GetRsaLegacyKey should work. 201 // for GetRsaLegacyKey should work.
156 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE); 202 OPENSSL_PUT_ERROR(RSA, sign_raw, RSA_R_UNKNOWN_ALGORITHM_TYPE);
157 return -1; 203 return 0;
158 } 204 }
159 205
160 // Retrieve private key JNI reference. 206 // Retrieve private key JNI reference.
161 RsaAppData* app_data = static_cast<RsaAppData*>(RSA_get_app_data(rsa)); 207 const KeyExData *ex_data = RsaGetExData(rsa);
162 if (!app_data || !app_data->private_key) { 208 if (!ex_data || !ex_data->private_key) {
163 LOG(WARNING) << "Null JNI reference passed to RsaMethodPrivEnc!"; 209 LOG(WARNING) << "Null JNI reference passed to RsaMethodPrivEnc!";
164 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); 210 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
165 return -1; 211 return 0;
166 } 212 }
167 213
168 // Pre-4.2 legacy codepath. 214 // Pre-4.2 legacy codepath.
169 if (app_data->legacy_rsa) { 215 if (ex_data->legacy_rsa) {
170 int ret = app_data->legacy_rsa->meth->rsa_priv_enc( 216 int ret = ex_data->legacy_rsa->meth->rsa_priv_enc(
171 flen, from, to, app_data->legacy_rsa, ANDROID_RSA_PKCS1_PADDING); 217 in_len, in, out, ex_data->legacy_rsa, ANDROID_RSA_PKCS1_PADDING);
172 if (ret < 0) { 218 if (ret < 0) {
173 LOG(WARNING) << "Could not sign message in RsaMethodPrivEnc!"; 219 LOG(WARNING) << "Could not sign message in RsaMethodPrivEnc!";
174 // System OpenSSL will use a separate error queue, so it is still 220 // System OpenSSL will use a separate error queue, so it is still
175 // necessary to push a new error. 221 // necessary to push a new error.
176 // 222 //
177 // TODO(davidben): It would be good to also clear the system error queue 223 // TODO(davidben): It would be good to also clear the system error queue
178 // if there were some way to convince Java to do it. (Without going 224 // if there were some way to convince Java to do it. (Without going
179 // through Java, it's difficult to get a handle on a system OpenSSL 225 // through Java, it's difficult to get a handle on a system OpenSSL
180 // function; dlopen loads a second copy.) 226 // function; dlopen loads a second copy.)
181 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); 227 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
182 return -1; 228 return 0;
183 } 229 }
184 return ret; 230 *out_len = ret;
231 return 1;
185 } 232 }
186 233
187 base::StringPiece from_piece(reinterpret_cast<const char*>(from), flen); 234 base::StringPiece from_piece(reinterpret_cast<const char*>(in), in_len);
188 std::vector<uint8> result; 235 std::vector<uint8> result;
189 // For RSA keys, this function behaves as RSA_private_encrypt with 236 // For RSA keys, this function behaves as RSA_private_encrypt with
190 // PKCS#1 padding. 237 // PKCS#1 padding.
191 if (!RawSignDigestWithPrivateKey(app_data->private_key, 238 if (!RawSignDigestWithPrivateKey(ex_data->private_key, from_piece, &result)) {
192 from_piece, &result)) {
193 LOG(WARNING) << "Could not sign message in RsaMethodPrivEnc!"; 239 LOG(WARNING) << "Could not sign message in RsaMethodPrivEnc!";
194 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); 240 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
195 return -1; 241 return 0;
196 } 242 }
197 243
198 size_t expected_size = static_cast<size_t>(RSA_size(rsa)); 244 size_t expected_size = static_cast<size_t>(RSA_size(rsa));
199 if (result.size() > expected_size) { 245 if (result.size() > expected_size) {
200 LOG(ERROR) << "RSA Signature size mismatch, actual: " 246 LOG(ERROR) << "RSA Signature size mismatch, actual: "
201 << result.size() << ", expected <= " << expected_size; 247 << result.size() << ", expected <= " << expected_size;
202 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); 248 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
203 return -1; 249 return 0;
250 }
251
252 if (max_out < expected_size) {
253 OPENSSL_PUT_ERROR(RSA, sign_raw, RSA_R_DATA_TOO_LARGE);
254 return 0;
204 } 255 }
205 256
206 // Copy result to OpenSSL-provided buffer. RawSignDigestWithPrivateKey 257 // Copy result to OpenSSL-provided buffer. RawSignDigestWithPrivateKey
207 // should pad with leading 0s, but if it doesn't, pad the result. 258 // should pad with leading 0s, but if it doesn't, pad the result.
208 size_t zero_pad = expected_size - result.size(); 259 size_t zero_pad = expected_size - result.size();
209 memset(to, 0, zero_pad); 260 memset(out, 0, zero_pad);
210 memcpy(to + zero_pad, &result[0], result.size()); 261 memcpy(out + zero_pad, &result[0], result.size());
262 *out_len = expected_size;
211 263
212 return expected_size; 264 return 1;
213 } 265 }
214 266
215 int RsaMethodPrivDec(int flen, 267 int RsaMethodDecrypt(RSA* rsa,
216 const unsigned char* from, 268 size_t* out_len,
217 unsigned char* to, 269 uint8_t* out,
218 RSA* rsa, 270 size_t max_out,
271 const uint8_t* in,
272 size_t in_len,
219 int padding) { 273 int padding) {
220 NOTIMPLEMENTED(); 274 NOTIMPLEMENTED();
221 RSAerr(RSA_F_RSA_PRIVATE_DECRYPT, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED); 275 OPENSSL_PUT_ERROR(RSA, decrypt, RSA_R_UNKNOWN_PADDING_TYPE);
222 return -1; 276 return 1;
223 } 277 }
224 278
225 int RsaMethodInit(RSA* rsa) { 279 int RsaMethodVerifyRaw(RSA* rsa,
226 return 0; 280 size_t* out_len,
227 } 281 uint8_t* out,
228 282 size_t max_out,
229 int RsaMethodFinish(RSA* rsa) { 283 const uint8_t* in,
230 // Ensure the global JNI reference created with this wrapper is 284 size_t in_len,
231 // properly destroyed with it. 285 int padding) {
232 RsaAppData* app_data = static_cast<RsaAppData*>(RSA_get_app_data(rsa)); 286 NOTIMPLEMENTED();
233 if (app_data != NULL) { 287 OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_UNKNOWN_ALGORITHM_TYPE);
234 RSA_set_app_data(rsa, NULL); 288 return 1;
235 ReleaseKey(app_data->private_key);
236 delete app_data;
237 }
238 // Actual return value is ignored by OpenSSL. There are no docs
239 // explaining what this is supposed to be.
240 return 0;
241 } 289 }
242 290
243 const RSA_METHOD android_rsa_method = { 291 const RSA_METHOD android_rsa_method = {
244 /* .name = */ "Android signing-only RSA method", 292 {
245 /* .rsa_pub_enc = */ RsaMethodPubEnc, 293 0 /* references */,
246 /* .rsa_pub_dec = */ RsaMethodPubDec, 294 1 /* is_static */
247 /* .rsa_priv_enc = */ RsaMethodPrivEnc, 295 } /* common */,
248 /* .rsa_priv_dec = */ RsaMethodPrivDec, 296 NULL /* app_data */,
249 /* .rsa_mod_exp = */ NULL, 297
250 /* .bn_mod_exp = */ NULL, 298 NULL /* init */,
251 /* .init = */ RsaMethodInit, 299 NULL /* finish */,
252 /* .finish = */ RsaMethodFinish, 300 RsaMethodSize,
253 // This flag is necessary to tell OpenSSL to avoid checking the content 301 NULL /* sign */,
254 // (i.e. internal fields) of the private key. Otherwise, it will complain 302 NULL /* verify */,
255 // it's not valid for the certificate. 303 RsaMethodEncrypt,
256 /* .flags = */ RSA_METHOD_FLAG_NO_CHECK, 304 RsaMethodSignRaw,
257 /* .app_data = */ NULL, 305 RsaMethodDecrypt,
258 /* .rsa_sign = */ NULL, 306 RsaMethodVerifyRaw,
259 /* .rsa_verify = */ NULL, 307 NULL /* mod_exp */,
260 /* .rsa_keygen = */ NULL, 308 NULL /* bn_mod_exp */,
309 0 /* flags */,
310 NULL /* keygen */,
261 }; 311 };
262 312
263 // Copy the contents of an encoded big integer into an existing BIGNUM.
264 // This function modifies |*num| in-place.
265 // |new_bytes| is the byte encoding of the new value.
266 // |num| points to the BIGNUM which will be assigned with the new value.
267 // Returns true on success, false otherwise. On failure, |*num| is
268 // not modified.
269 bool CopyBigNumFromBytes(const std::vector<uint8>& new_bytes,
270 BIGNUM* num) {
271 BIGNUM* ret = BN_bin2bn(
272 reinterpret_cast<const unsigned char*>(&new_bytes[0]),
273 static_cast<int>(new_bytes.size()),
274 num);
275 return (ret != NULL);
276 }
277
278 // Decode the contents of an encoded big integer and either create a new
279 // BIGNUM object (if |*num_ptr| is NULL on input) or copy it (if
280 // |*num_ptr| is not NULL).
281 // |new_bytes| is the byte encoding of the new value.
282 // |num_ptr| is the address of a BIGNUM pointer. |*num_ptr| can be NULL.
283 // Returns true on success, false otherwise. On failure, |*num_ptr| is
284 // not modified. On success, |*num_ptr| will always be non-NULL and
285 // point to a valid BIGNUM object.
286 bool SwapBigNumPtrFromBytes(const std::vector<uint8>& new_bytes,
287 BIGNUM** num_ptr) {
288 BIGNUM* old_num = *num_ptr;
289 BIGNUM* new_num = BN_bin2bn(
290 reinterpret_cast<const unsigned char*>(&new_bytes[0]),
291 static_cast<int>(new_bytes.size()),
292 old_num);
293 if (new_num == NULL)
294 return false;
295
296 if (old_num == NULL)
297 *num_ptr = new_num;
298 return true;
299 }
300
301 // Setup an EVP_PKEY to wrap an existing platform RSA PrivateKey object. 313 // Setup an EVP_PKEY to wrap an existing platform RSA PrivateKey object.
302 // |private_key| is the JNI reference (local or global) to the object. 314 // |private_key| is the JNI reference (local or global) to the object.
303 // |legacy_rsa|, if non-NULL, is a pointer to the system OpenSSL RSA object 315 // |legacy_rsa|, if non-NULL, is a pointer to the system OpenSSL RSA object
304 // backing |private_key|. This parameter is only used for Android < 4.2 to 316 // backing |private_key|. This parameter is only used for Android < 4.2 to
305 // implement key operations not exposed by the platform. 317 // implement key operations not exposed by the platform.
306 // |pkey| is the EVP_PKEY to setup as a wrapper. 318 // |pkey| is the EVP_PKEY to setup as a wrapper.
307 // Returns true on success, false otherwise. 319 // Returns true on success, false otherwise.
308 // On success, this creates a new global JNI reference to the object 320 // On success, this creates a new global JNI reference to the object
309 // that is owned by and destroyed with the EVP_PKEY. I.e. caller can 321 // that is owned by and destroyed with the EVP_PKEY. I.e. caller can
310 // free |private_key| after the call. 322 // free |private_key| after the call.
311 bool GetRsaPkeyWrapper(jobject private_key, 323 bool GetRsaPkeyWrapper(jobject private_key,
312 AndroidRSA* legacy_rsa, 324 AndroidRSA* legacy_rsa,
313 EVP_PKEY* pkey) { 325 EVP_PKEY* pkey) {
314 crypto::ScopedRSA rsa(RSA_new()); 326 crypto::ScopedRSA rsa(
315 RSA_set_method(rsa.get(), &android_rsa_method); 327 RSA_new_method(global_boringssl_engine.Get().engine()));
316
317 // HACK: RSA_size() doesn't work with custom RSA_METHODs. To ensure that
318 // it will return the right value, set the 'n' field of the RSA object
319 // to match the private key's modulus.
320 //
321 // TODO(davidben): After switching to BoringSSL, consider making RSA_size call
322 // into an RSA_METHOD hook.
323 std::vector<uint8> modulus;
324 if (!GetRSAKeyModulus(private_key, &modulus)) {
325 LOG(ERROR) << "Failed to get private key modulus";
326 return false;
327 }
328 if (!SwapBigNumPtrFromBytes(modulus, &rsa.get()->n)) {
329 LOG(ERROR) << "Failed to decode private key modulus";
330 return false;
331 }
332 328
333 ScopedJavaGlobalRef<jobject> global_key; 329 ScopedJavaGlobalRef<jobject> global_key;
334 global_key.Reset(NULL, private_key); 330 global_key.Reset(NULL, private_key);
335 if (global_key.is_null()) { 331 if (global_key.is_null()) {
336 LOG(ERROR) << "Could not create global JNI reference"; 332 LOG(ERROR) << "Could not create global JNI reference";
337 return false; 333 return false;
338 } 334 }
339 RsaAppData* app_data = new RsaAppData(); 335
340 app_data->private_key = global_key.Release(); 336 std::vector<uint8> modulus;
341 app_data->legacy_rsa = legacy_rsa; 337 if (!GetRSAKeyModulus(private_key, &modulus)) {
342 RSA_set_app_data(rsa.get(), app_data); 338 LOG(ERROR) << "Failed to get private key modulus";
339 return false;
340 }
341
342 KeyExData* ex_data = new KeyExData;
343 ex_data->private_key = global_key.Release();
344 ex_data->legacy_rsa = legacy_rsa;
345 ex_data->cached_size = VectorBignumSize(modulus);
346 RSA_set_ex_data(
347 rsa.get(), global_boringssl_engine.Get().rsa_ex_index(), ex_data);
343 EVP_PKEY_assign_RSA(pkey, rsa.release()); 348 EVP_PKEY_assign_RSA(pkey, rsa.release());
344 return true; 349 return true;
345 } 350 }
346 351
347 // On Android < 4.2, the libkeystore.so ENGINE uses CRYPTO_EX_DATA and is not 352 // On Android < 4.2, the libkeystore.so ENGINE uses CRYPTO_EX_DATA and is not
348 // added to the global engine list. If all references to it are dropped, OpenSSL 353 // added to the global engine list. If all references to it are dropped, OpenSSL
349 // will dlclose the module, leaving a dangling function pointer in the RSA 354 // will dlclose the module, leaving a dangling function pointer in the RSA
350 // CRYPTO_EX_DATA class. To work around this, leak an extra reference to the 355 // CRYPTO_EX_DATA class. To work around this, leak an extra reference to the
351 // ENGINE we extract in GetRsaLegacyKey. 356 // ENGINE we extract in GetRsaLegacyKey.
352 // 357 //
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
391 if (sys_pkey != NULL) { 396 if (sys_pkey != NULL) {
392 if (sys_pkey->type != ANDROID_EVP_PKEY_RSA) { 397 if (sys_pkey->type != ANDROID_EVP_PKEY_RSA) {
393 LOG(ERROR) << "Private key has wrong type!"; 398 LOG(ERROR) << "Private key has wrong type!";
394 return NULL; 399 return NULL;
395 } 400 }
396 401
397 AndroidRSA* sys_rsa = sys_pkey->pkey.rsa; 402 AndroidRSA* sys_rsa = sys_pkey->pkey.rsa;
398 if (sys_rsa->engine) { 403 if (sys_rsa->engine) {
399 // |private_key| may not have an engine if the PrivateKey did not come 404 // |private_key| may not have an engine if the PrivateKey did not come
400 // from the key store, such as in unit tests. 405 // from the key store, such as in unit tests.
401 if (!strcmp(sys_rsa->engine->id, "keystore")) { 406 if (strcmp(sys_rsa->engine->id, "keystore") == 0) {
402 LeakEngine(private_key); 407 LeakEngine(private_key);
403 } else { 408 } else {
404 NOTREACHED(); 409 NOTREACHED();
405 } 410 }
406 } 411 }
407 412
408 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new()); 413 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new());
409 if (!GetRsaPkeyWrapper(private_key, sys_rsa, pkey.get())) 414 if (!GetRsaPkeyWrapper(private_key, sys_rsa, pkey.get()))
410 return NULL; 415 return NULL;
411 return pkey.release(); 416 return pkey.release();
(...skipping 12 matching lines...) Expand all
424 reinterpret_cast<const unsigned char*>(&encoded[0]); 429 reinterpret_cast<const unsigned char*>(&encoded[0]);
425 int len = static_cast<int>(encoded.size()); 430 int len = static_cast<int>(encoded.size());
426 EVP_PKEY* pkey = d2i_AutoPrivateKey(NULL, &p, len); 431 EVP_PKEY* pkey = d2i_AutoPrivateKey(NULL, &p, len);
427 if (pkey == NULL) { 432 if (pkey == NULL) {
428 LOG(ERROR) << "Can't convert private key data!"; 433 LOG(ERROR) << "Can't convert private key data!";
429 return NULL; 434 return NULL;
430 } 435 }
431 return pkey; 436 return pkey;
432 } 437 }
433 438
434 // Custom DSA_METHOD that uses the platform APIs.
435 // Note that for now, only signing through DSA_sign() is really supported.
436 // all other method pointers are either stubs returning errors, or no-ops.
437 // See <openssl/dsa.h> for exact declaration of DSA_METHOD.
438 //
439 // Note: There is no DSA_set_app_data() and DSA_get_app_data() functions,
440 // but RSA_set_app_data() is defined as a simple macro that calls
441 // RSA_set_ex_data() with a hard-coded index of 0, so this code
442 // does the same thing here.
443
444 DSA_SIG* DsaMethodDoSign(const unsigned char* dgst,
445 int dlen,
446 DSA* dsa) {
447 // Extract the JNI reference to the PrivateKey object.
448 jobject private_key = reinterpret_cast<jobject>(DSA_get_ex_data(dsa, 0));
449 if (private_key == NULL)
450 return NULL;
451
452 // Sign the message with it, calling platform APIs.
453 std::vector<uint8> signature;
454 if (!RawSignDigestWithPrivateKey(
455 private_key,
456 base::StringPiece(
457 reinterpret_cast<const char*>(dgst),
458 static_cast<size_t>(dlen)),
459 &signature)) {
460 return NULL;
461 }
462
463 // Note: With DSA, the actual signature might be smaller than DSA_size().
464 size_t max_expected_size = static_cast<size_t>(DSA_size(dsa));
465 if (signature.size() > max_expected_size) {
466 LOG(ERROR) << "DSA Signature size mismatch, actual: "
467 << signature.size() << ", expected <= "
468 << max_expected_size;
469 return NULL;
470 }
471
472 // Convert the signature into a DSA_SIG object.
473 const unsigned char* sigbuf =
474 reinterpret_cast<const unsigned char*>(&signature[0]);
475 int siglen = static_cast<size_t>(signature.size());
476 DSA_SIG* dsa_sig = d2i_DSA_SIG(NULL, &sigbuf, siglen);
477 return dsa_sig;
478 }
479
480 int DsaMethodSignSetup(DSA* dsa,
481 BN_CTX* ctx_in,
482 BIGNUM** kinvp,
483 BIGNUM** rp) {
484 NOTIMPLEMENTED();
485 DSAerr(DSA_F_DSA_SIGN_SETUP, DSA_R_INVALID_DIGEST_TYPE);
486 return -1;
487 }
488
489 int DsaMethodDoVerify(const unsigned char* dgst,
490 int dgst_len,
491 DSA_SIG* sig,
492 DSA* dsa) {
493 NOTIMPLEMENTED();
494 DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_INVALID_DIGEST_TYPE);
495 return -1;
496 }
497
498 int DsaMethodFinish(DSA* dsa) {
499 // Free the global JNI reference that was created with this
500 // wrapper key.
501 jobject key = reinterpret_cast<jobject>(DSA_get_ex_data(dsa,0));
502 if (key != NULL) {
503 DSA_set_ex_data(dsa, 0, NULL);
504 ReleaseKey(key);
505 }
506 // Actual return value is ignored by OpenSSL. There are no docs
507 // explaining what this is supposed to be.
508 return 0;
509 }
510
511 const DSA_METHOD android_dsa_method = {
512 /* .name = */ "Android signing-only DSA method",
513 /* .dsa_do_sign = */ DsaMethodDoSign,
514 /* .dsa_sign_setup = */ DsaMethodSignSetup,
515 /* .dsa_do_verify = */ DsaMethodDoVerify,
516 /* .dsa_mod_exp = */ NULL,
517 /* .bn_mod_exp = */ NULL,
518 /* .init = */ NULL, // nothing to do here.
519 /* .finish = */ DsaMethodFinish,
520 /* .flags = */ 0,
521 /* .app_data = */ NULL,
522 /* .dsa_paramgem = */ NULL,
523 /* .dsa_keygen = */ NULL
524 };
525
526 // Setup an EVP_PKEY to wrap an existing DSA platform PrivateKey object.
527 // |private_key| is a JNI reference (local or global) to the object.
528 // |pkey| is the EVP_PKEY to setup as a wrapper.
529 // Returns true on success, false otherwise.
530 // On success, this creates a global JNI reference to the same object
531 // that will be owned by and destroyed with the EVP_PKEY.
532 bool GetDsaPkeyWrapper(jobject private_key, EVP_PKEY* pkey) {
533 crypto::ScopedDSA dsa(DSA_new());
534 DSA_set_method(dsa.get(), &android_dsa_method);
535
536 // DSA_size() doesn't work with custom DSA_METHODs. To ensure it
537 // returns the right value, set the 'q' field in the DSA object to
538 // match the parameter from the platform key.
539 std::vector<uint8> q;
540 if (!GetDSAKeyParamQ(private_key, &q)) {
541 LOG(ERROR) << "Can't extract Q parameter from DSA private key";
542 return false;
543 }
544 if (!SwapBigNumPtrFromBytes(q, &dsa.get()->q)) {
545 LOG(ERROR) << "Can't decode Q parameter from DSA private key";
546 return false;
547 }
548
549 ScopedJavaGlobalRef<jobject> global_key;
550 global_key.Reset(NULL, private_key);
551 if (global_key.is_null()) {
552 LOG(ERROR) << "Could not create global JNI reference";
553 return false;
554 }
555 DSA_set_ex_data(dsa.get(), 0, global_key.Release());
556 EVP_PKEY_assign_DSA(pkey, dsa.release());
557 return true;
558 }
559
560 // Custom ECDSA_METHOD that uses the platform APIs. 439 // Custom ECDSA_METHOD that uses the platform APIs.
561 // Note that for now, only signing through ECDSA_sign() is really supported. 440 // Note that for now, only signing through ECDSA_sign() is really supported.
562 // all other method pointers are either stubs returning errors, or no-ops. 441 // all other method pointers are either stubs returning errors, or no-ops.
563 //
564 // Note: The ECDSA_METHOD structure doesn't have init/finish
565 // methods. As such, the only way to to ensure the global
566 // JNI reference is properly released when the EVP_PKEY is
567 // destroyed is to use a custom EX_DATA type.
568 442
569 // Used to ensure that the global JNI reference associated with a custom 443 jobject EcKeyGetKey(const EC_KEY* ec_key) {
570 // EC_KEY + ECDSA_METHOD wrapper is released when its EX_DATA is destroyed 444 KeyExData* ex_data = reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data(
571 // (this function is called when EVP_PKEY_free() is called on the wrapper). 445 ec_key, global_boringssl_engine.Get().ec_key_ex_index()));
572 void ExDataFree(void* parent, 446 return ex_data->private_key;
573 void* ptr,
574 CRYPTO_EX_DATA* ad,
575 int idx,
576 long argl,
577 void* argp) {
578 jobject private_key = reinterpret_cast<jobject>(ptr);
579 if (private_key == NULL)
580 return;
581
582 CRYPTO_set_ex_data(ad, idx, NULL);
583 ReleaseKey(private_key);
584 } 447 }
585 448
586 int ExDataDup(CRYPTO_EX_DATA* to, 449 size_t EcdsaMethodGroupOrderSize(const EC_KEY* key) {
587 CRYPTO_EX_DATA* from, 450 KeyExData* ex_data = reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data(
588 void* from_d, 451 key, global_boringssl_engine.Get().ec_key_ex_index()));
589 int idx, 452 return ex_data->cached_size;
590 long argl,
591 void* argp) {
592 // This callback shall never be called with the current OpenSSL
593 // implementation (the library only ever duplicates EX_DATA items
594 // for SSL and BIO objects). But provide this to catch regressions
595 // in the future.
596 CHECK(false) << "ExDataDup was called for ECDSA custom key !?";
597 // Return value is currently ignored by OpenSSL.
598 return 0;
599 } 453 }
600 454
601 class EcdsaExDataIndex { 455 int EcdsaMethodSign(const uint8_t* digest,
602 public: 456 size_t digest_len,
603 int ex_data_index() { return ex_data_index_; } 457 uint8_t* sig,
604 458 unsigned int* sig_len,
605 EcdsaExDataIndex() { 459 EC_KEY* eckey) {
606 ex_data_index_ = ECDSA_get_ex_new_index(0, // argl
607 NULL, // argp
608 NULL, // new_func
609 ExDataDup, // dup_func
610 ExDataFree); // free_func
611 }
612
613 private:
614 int ex_data_index_;
615 };
616
617 // Returns the index of the custom EX_DATA used to store the JNI reference.
618 int EcdsaGetExDataIndex(void) {
619 // Use a LazyInstance to perform thread-safe lazy initialization.
620 // Use a leaky one, since OpenSSL doesn't provide a way to release
621 // allocated EX_DATA indices.
622 static base::LazyInstance<EcdsaExDataIndex>::Leaky s_instance =
623 LAZY_INSTANCE_INITIALIZER;
624 return s_instance.Get().ex_data_index();
625 }
626
627 ECDSA_SIG* EcdsaMethodDoSign(const unsigned char* dgst,
628 int dgst_len,
629 const BIGNUM* inv,
630 const BIGNUM* rp,
631 EC_KEY* eckey) {
632 // Retrieve private key JNI reference. 460 // Retrieve private key JNI reference.
633 jobject private_key = reinterpret_cast<jobject>( 461 jobject private_key = EcKeyGetKey(eckey);
634 ECDSA_get_ex_data(eckey, EcdsaGetExDataIndex()));
635 if (!private_key) { 462 if (!private_key) {
636 LOG(WARNING) << "Null JNI reference passed to EcdsaMethodDoSign!"; 463 LOG(WARNING) << "Null JNI reference passed to EcdsaMethodSign!";
637 return NULL; 464 return 0;
638 } 465 }
639 // Sign message with it through JNI. 466 // Sign message with it through JNI.
640 std::vector<uint8> signature; 467 std::vector<uint8> signature;
641 base::StringPiece digest( 468 base::StringPiece digest_sp(reinterpret_cast<const char*>(digest),
642 reinterpret_cast<const char*>(dgst), 469 digest_len);
643 static_cast<size_t>(dgst_len)); 470 if (!RawSignDigestWithPrivateKey(private_key, digest_sp, &signature)) {
644 if (!RawSignDigestWithPrivateKey( 471 LOG(WARNING) << "Could not sign message in EcdsaMethodSign!";
645 private_key, digest, &signature)) { 472 return 0;
646 LOG(WARNING) << "Could not sign message in EcdsaMethodDoSign!";
647 return NULL;
648 } 473 }
649 474
650 // Note: With ECDSA, the actual signature may be smaller than 475 // Note: With ECDSA, the actual signature may be smaller than
651 // ECDSA_size(). 476 // ECDSA_size().
652 size_t max_expected_size = static_cast<size_t>(ECDSA_size(eckey)); 477 size_t max_expected_size = ECDSA_size(eckey);
653 if (signature.size() > max_expected_size) { 478 if (signature.size() > max_expected_size) {
654 LOG(ERROR) << "ECDSA Signature size mismatch, actual: " 479 LOG(ERROR) << "ECDSA Signature size mismatch, actual: "
655 << signature.size() << ", expected <= " 480 << signature.size() << ", expected <= "
656 << max_expected_size; 481 << max_expected_size;
657 return NULL; 482 return 0;
658 } 483 }
659 484
660 // Convert signature to ECDSA_SIG object 485 memcpy(sig, &signature[0], signature.size());
661 const unsigned char* sigbuf = 486 *sig_len = signature.size();
662 reinterpret_cast<const unsigned char*>(&signature[0]); 487 return 1;
663 long siglen = static_cast<long>(signature.size());
664 return d2i_ECDSA_SIG(NULL, &sigbuf, siglen);
665 } 488 }
666 489
667 int EcdsaMethodSignSetup(EC_KEY* eckey, 490 int EcdsaMethodVerify(const uint8_t* digest,
668 BN_CTX* ctx, 491 size_t digest_len,
669 BIGNUM** kinv, 492 const uint8_t* sig,
670 BIGNUM** r) { 493 size_t sig_len,
494 EC_KEY* eckey) {
671 NOTIMPLEMENTED(); 495 NOTIMPLEMENTED();
672 ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ECDSA_R_ERR_EC_LIB); 496 OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ECDSA_R_NOT_IMPLEMENTED);
673 return -1; 497 return 0;
674 } 498 }
675 499
676 int EcdsaMethodDoVerify(const unsigned char* dgst,
677 int dgst_len,
678 const ECDSA_SIG* sig,
679 EC_KEY* eckey) {
680 NOTIMPLEMENTED();
681 ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_ERR_EC_LIB);
682 return -1;
683 }
684
685 const ECDSA_METHOD android_ecdsa_method = {
686 /* .name = */ "Android signing-only ECDSA method",
687 /* .ecdsa_do_sign = */ EcdsaMethodDoSign,
688 /* .ecdsa_sign_setup = */ EcdsaMethodSignSetup,
689 /* .ecdsa_do_verify = */ EcdsaMethodDoVerify,
690 /* .flags = */ 0,
691 /* .app_data = */ NULL,
692 };
693
694 // Setup an EVP_PKEY to wrap an existing platform PrivateKey object. 500 // Setup an EVP_PKEY to wrap an existing platform PrivateKey object.
695 // |private_key| is the JNI reference (local or global) to the object. 501 // |private_key| is the JNI reference (local or global) to the object.
696 // |pkey| is the EVP_PKEY to setup as a wrapper. 502 // |pkey| is the EVP_PKEY to setup as a wrapper.
697 // Returns true on success, false otherwise. 503 // Returns true on success, false otherwise.
698 // On success, this creates a global JNI reference to the object that 504 // On success, this creates a global JNI reference to the object that
699 // is owned by and destroyed with the EVP_PKEY. I.e. the caller shall 505 // is owned by and destroyed with the EVP_PKEY. I.e. the caller shall
700 // always free |private_key| after the call. 506 // always free |private_key| after the call.
701 bool GetEcdsaPkeyWrapper(jobject private_key, EVP_PKEY* pkey) { 507 bool GetEcdsaPkeyWrapper(jobject private_key, EVP_PKEY* pkey) {
702 crypto::ScopedEC_KEY eckey(EC_KEY_new()); 508 crypto::ScopedEC_KEY eckey(
703 ECDSA_set_method(eckey.get(), &android_ecdsa_method); 509 EC_KEY_new_method(global_boringssl_engine.Get().engine()));
704
705 // To ensure that ECDSA_size() works properly, craft a custom EC_GROUP
706 // that has the same order than the private key.
707 std::vector<uint8> order;
708 if (!GetECKeyOrder(private_key, &order)) {
709 LOG(ERROR) << "Can't extract order parameter from EC private key";
710 return false;
711 }
712 ScopedEC_GROUP group(EC_GROUP_new(EC_GFp_nist_method()));
713 if (!group.get()) {
714 LOG(ERROR) << "Can't create new EC_GROUP";
715 return false;
716 }
717 if (!CopyBigNumFromBytes(order, &group.get()->order)) {
718 LOG(ERROR) << "Can't decode order from PrivateKey";
719 return false;
720 }
721 EC_KEY_set_group(eckey.get(), group.release());
722 510
723 ScopedJavaGlobalRef<jobject> global_key; 511 ScopedJavaGlobalRef<jobject> global_key;
724 global_key.Reset(NULL, private_key); 512 global_key.Reset(NULL, private_key);
725 if (global_key.is_null()) { 513 if (global_key.is_null()) {
726 LOG(ERROR) << "Can't create global JNI reference"; 514 LOG(ERROR) << "Can't create global JNI reference";
727 return false; 515 return false;
728 } 516 }
729 ECDSA_set_ex_data(eckey.get(), 517
730 EcdsaGetExDataIndex(), 518 std::vector<uint8> order;
731 global_key.Release()); 519 if (!GetECKeyOrder(private_key, &order)) {
520 LOG(ERROR) << "Can't extract order parameter from EC private key";
521 return false;
522 }
523
524 KeyExData* ex_data = new KeyExData;
525 ex_data->private_key = global_key.Release();
526 ex_data->legacy_rsa = NULL;
527 ex_data->cached_size = VectorBignumSize(order);
528
529 EC_KEY_set_ex_data(
530 eckey.get(), global_boringssl_engine.Get().ec_key_ex_index(), ex_data);
732 531
733 EVP_PKEY_assign_EC_KEY(pkey, eckey.release()); 532 EVP_PKEY_assign_EC_KEY(pkey, eckey.release());
734 return true; 533 return true;
735 } 534 }
736 535
536 const ECDSA_METHOD android_ecdsa_method = {
537 {
538 0 /* references */,
539 1 /* is_static */
540 } /* common */,
541 NULL /* app_data */,
542
543 NULL /* init */,
544 NULL /* finish */,
545 EcdsaMethodGroupOrderSize,
546 EcdsaMethodSign,
547 EcdsaMethodVerify,
548 };
549
737 } // namespace 550 } // namespace
738 551
739 EVP_PKEY* GetOpenSSLPrivateKeyWrapper(jobject private_key) { 552 EVP_PKEY* GetOpenSSLPrivateKeyWrapper(jobject private_key) {
740 // Create new empty EVP_PKEY instance. 553 // Create new empty EVP_PKEY instance.
741 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new()); 554 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new());
742 if (!pkey.get()) 555 if (!pkey.get())
743 return NULL; 556 return NULL;
744 557
745 // Create sub key type, depending on private key's algorithm type. 558 // Create sub key type, depending on private key's algorithm type.
746 PrivateKeyType key_type = GetPrivateKeyType(private_key); 559 PrivateKeyType key_type = GetPrivateKeyType(private_key);
(...skipping 11 matching lines...) Expand all
758 if (legacy_key == NULL) 571 if (legacy_key == NULL)
759 return NULL; 572 return NULL;
760 pkey.reset(legacy_key); 573 pkey.reset(legacy_key);
761 } else { 574 } else {
762 // Running on Android 4.2. 575 // Running on Android 4.2.
763 if (!GetRsaPkeyWrapper(private_key, NULL, pkey.get())) 576 if (!GetRsaPkeyWrapper(private_key, NULL, pkey.get()))
764 return NULL; 577 return NULL;
765 } 578 }
766 } 579 }
767 break; 580 break;
768 case PRIVATE_KEY_TYPE_DSA:
769 if (!GetDsaPkeyWrapper(private_key, pkey.get()))
770 return NULL;
771 break;
772 case PRIVATE_KEY_TYPE_ECDSA: 581 case PRIVATE_KEY_TYPE_ECDSA:
773 if (!GetEcdsaPkeyWrapper(private_key, pkey.get())) 582 if (!GetEcdsaPkeyWrapper(private_key, pkey.get()))
774 return NULL; 583 return NULL;
775 break; 584 break;
776 default: 585 default:
777 LOG(WARNING) 586 LOG(WARNING)
778 << "GetOpenSSLPrivateKeyWrapper() called with invalid key type"; 587 << "GetOpenSSLPrivateKeyWrapper() called with invalid key type";
779 return NULL; 588 return NULL;
780 } 589 }
781 return pkey.release(); 590 return pkey.release();
782 } 591 }
783 592
784 } // namespace android 593 } // namespace android
785 } // namespace net 594 } // namespace net
OLDNEW
« no previous file with comments | « google_apis/google_apis.gyp ('k') | net/android/keystore_unittest.cc » ('j') | net/http/des.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698