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

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

Issue 401153002: Switch to BoringSSL. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase across DEPS change 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
« no previous file with comments | « net/BUILD.gn ('k') | net/android/keystore_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
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> 9 #include <openssl/dsa.h>
17 #include <openssl/ec.h> 10 #include <openssl/ec.h>
18 #include <openssl/engine.h> 11 #include <openssl/engine.h>
12 #include <openssl/err.h>
19 #include <openssl/evp.h> 13 #include <openssl/evp.h>
20 #include <openssl/rsa.h> 14 #include <openssl/rsa.h>
21 15
22 #include "base/android/build_info.h" 16 #include "base/android/build_info.h"
23 #include "base/android/jni_android.h" 17 #include "base/android/jni_android.h"
24 #include "base/android/scoped_java_ref.h" 18 #include "base/android/scoped_java_ref.h"
25 #include "base/basictypes.h" 19 #include "base/basictypes.h"
26 #include "base/lazy_instance.h" 20 #include "base/lazy_instance.h"
27 #include "base/logging.h" 21 #include "base/logging.h"
28 #include "crypto/openssl_util.h" 22 #include "crypto/openssl_util.h"
(...skipping 24 matching lines...) Expand all
53 // For example, the RSA_sign() function will call "method->rsa_sign()" if 47 // 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 48 // method->rsa_sign is not NULL, otherwise, it will perform a regular
55 // signing operation using the other fields in the RSA structure (which 49 // signing operation using the other fields in the RSA structure (which
56 // are used to hold the typical modulus / exponent / parameters for the 50 // are used to hold the typical modulus / exponent / parameters for the
57 // key pair). 51 // key pair).
58 // 52 //
59 // This source file thus defines a custom RSA_METHOD structure whose 53 // This source file thus defines a custom RSA_METHOD structure whose
60 // fields point to static methods used to implement the corresponding 54 // fields point to static methods used to implement the corresponding
61 // RSA operation using platform Android APIs. 55 // RSA operation using platform Android APIs.
62 // 56 //
63 // However, the platform APIs require a jobject JNI reference to work. 57 // 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 58 // 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() 59 // methods are called. This is done by storing it in a |KeyExData| structure
66 // and RSA_get_app_data(). 60 // 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 61
99 using base::android::ScopedJavaGlobalRef; 62 using base::android::ScopedJavaGlobalRef;
100 using base::android::ScopedJavaLocalRef; 63 using base::android::ScopedJavaLocalRef;
101 64
102 namespace net { 65 namespace net {
103 namespace android { 66 namespace android {
104 67
105 namespace { 68 namespace {
106 69
107 typedef crypto::ScopedOpenSSL<EC_GROUP, EC_GROUP_free>::Type ScopedEC_GROUP; 70 extern const RSA_METHOD android_rsa_method;
71 extern const ECDSA_METHOD android_ecdsa_method;
108 72
109 // Custom RSA_METHOD that uses the platform APIs. 73 // 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. 74 // and ECDSA objects that are created to wrap Android system keys.
111 // all other method pointers are either stubs returning errors, or no-ops. 75 struct KeyExData {
112 // See <openssl/rsa.h> for exact declaration of RSA_METHOD. 76 // private_key contains a reference to a Java, private-key object.
113
114 struct RsaAppData {
115 jobject private_key; 77 jobject private_key;
78 // legacy_rsa, if not NULL, points to an RSA* in the system's OpenSSL (which
79 // might not be ABI compatible with Chromium).
116 AndroidRSA* legacy_rsa; 80 AndroidRSA* legacy_rsa;
81 // cached_size contains the "size" of the key. This is the size of the
82 // modulus (in bytes) for RSA, or the group order size for (EC)DSA. This
83 // avoids calling into Java to calculate the size.
84 size_t cached_size;
117 }; 85 };
118 86
119 int RsaMethodPubEnc(int flen, 87 // ExDataDup is called when one of the RSA, DSA or EC_KEY objects is
120 const unsigned char* from, 88 // duplicated. We don't support this and it should never happen.
121 unsigned char* to, 89 int ExDataDup(CRYPTO_EX_DATA* to,
122 RSA* rsa, 90 const CRYPTO_EX_DATA* from,
123 int padding) { 91 void** from_d,
124 NOTIMPLEMENTED(); 92 int index,
125 RSAerr(RSA_F_RSA_PUBLIC_ENCRYPT, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED); 93 long argl,
126 return -1; 94 void* argp) {
95 CHECK(false);
96 return 0;
127 } 97 }
128 98
129 int RsaMethodPubDec(int flen, 99 // ExDataFree is called when one of the RSA, DSA or EC_KEY object is freed.
130 const unsigned char* from, 100 void ExDataFree(void* parent,
131 unsigned char* to, 101 void* ptr,
132 RSA* rsa, 102 CRYPTO_EX_DATA* ad,
133 int padding) { 103 int index,
134 NOTIMPLEMENTED(); 104 long argl,
135 RSAerr(RSA_F_RSA_PUBLIC_DECRYPT, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED); 105 void* argp) {
136 return -1; 106 // Ensure the global JNI reference created with this wrapper is
107 // properly destroyed with it.
108 KeyExData *ex_data = reinterpret_cast<KeyExData*>(ptr);
109 if (ex_data != NULL) {
110 ReleaseKey(ex_data->private_key);
111 delete ex_data;
112 }
137 } 113 }
138 114
139 // See RSA_eay_private_encrypt in 115 // 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 116 // forwarding the requested operations to the Java libraries.
141 // implementation of this function. 117 class BoringSSLEngine {
142 int RsaMethodPrivEnc(int flen, 118 public:
143 const unsigned char *from, 119 BoringSSLEngine()
144 unsigned char *to, 120 : rsa_index_(RSA_get_ex_new_index(0 /* argl */,
145 RSA *rsa, 121 NULL /* argp */,
122 NULL /* new_func */,
123 ExDataDup,
124 ExDataFree)),
125 ec_key_index_(EC_KEY_get_ex_new_index(0 /* argl */,
126 NULL /* argp */,
127 NULL /* new_func */,
128 ExDataDup,
129 ExDataFree)),
130 engine_(ENGINE_new()) {
131 ENGINE_set_RSA_method(
132 engine_, &android_rsa_method, sizeof(android_rsa_method));
133 ENGINE_set_ECDSA_method(
134 engine_, &android_ecdsa_method, sizeof(android_ecdsa_method));
135 }
136
137 int rsa_ex_index() const { return rsa_index_; }
138 int ec_key_ex_index() const { return ec_key_index_; }
139
140 const ENGINE* engine() const { return engine_; }
141
142 private:
143 const int rsa_index_;
144 const int ec_key_index_;
145 ENGINE* const engine_;
146 };
147
148 base::LazyInstance<BoringSSLEngine>::Leaky global_boringssl_engine =
149 LAZY_INSTANCE_INITIALIZER;
150
151
152 // VectorBignumSize returns the number of bytes needed to represent the bignum
153 // given in |v|, i.e. the length of |v| less any leading zero bytes.
154 size_t VectorBignumSize(const std::vector<uint8>& v) {
155 size_t size = v.size();
156 // Ignore any leading zero bytes.
157 for (size_t i = 0; i < v.size() && v[i] == 0; i++) {
158 size--;
159 }
160 return size;
161 }
162
163 KeyExData* RsaGetExData(const RSA* rsa) {
164 return reinterpret_cast<KeyExData*>(
165 RSA_get_ex_data(rsa, global_boringssl_engine.Get().rsa_ex_index()));
166 }
167
168 size_t RsaMethodSize(const RSA *rsa) {
169 const KeyExData *ex_data = RsaGetExData(rsa);
170 return ex_data->cached_size;
171 }
172
173 int RsaMethodEncrypt(RSA* rsa,
174 size_t* out_len,
175 uint8_t* out,
176 size_t max_out,
177 const uint8_t* in,
178 size_t in_len,
179 int padding) {
180 NOTIMPLEMENTED();
181 OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE);
182 return 0;
183 }
184
185 int RsaMethodSignRaw(RSA* rsa,
186 size_t* out_len,
187 uint8_t* out,
188 size_t max_out,
189 const uint8_t* in,
190 size_t in_len,
146 int padding) { 191 int padding) {
147 DCHECK_EQ(RSA_PKCS1_PADDING, padding); 192 DCHECK_EQ(RSA_PKCS1_PADDING, padding);
148 if (padding != RSA_PKCS1_PADDING) { 193 if (padding != RSA_PKCS1_PADDING) {
149 // TODO(davidben): If we need to, we can implement RSA_NO_PADDING 194 // TODO(davidben): If we need to, we can implement RSA_NO_PADDING
150 // by using javax.crypto.Cipher and picking either the 195 // by using javax.crypto.Cipher and picking either the
151 // "RSA/ECB/NoPadding" or "RSA/ECB/PKCS1Padding" transformation as 196 // "RSA/ECB/NoPadding" or "RSA/ECB/PKCS1Padding" transformation as
152 // appropriate. I believe support for both of these was added in 197 // appropriate. I believe support for both of these was added in
153 // the same Android version as the "NONEwithRSA" 198 // the same Android version as the "NONEwithRSA"
154 // java.security.Signature algorithm, so the same version checks 199 // java.security.Signature algorithm, so the same version checks
155 // for GetRsaLegacyKey should work. 200 // for GetRsaLegacyKey should work.
156 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE); 201 OPENSSL_PUT_ERROR(RSA, sign_raw, RSA_R_UNKNOWN_PADDING_TYPE);
157 return -1; 202 return 0;
158 } 203 }
159 204
160 // Retrieve private key JNI reference. 205 // Retrieve private key JNI reference.
161 RsaAppData* app_data = static_cast<RsaAppData*>(RSA_get_app_data(rsa)); 206 const KeyExData *ex_data = RsaGetExData(rsa);
162 if (!app_data || !app_data->private_key) { 207 if (!ex_data || !ex_data->private_key) {
163 LOG(WARNING) << "Null JNI reference passed to RsaMethodPrivEnc!"; 208 LOG(WARNING) << "Null JNI reference passed to RsaMethodPrivEnc!";
164 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); 209 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
165 return -1; 210 return 0;
166 } 211 }
167 212
168 // Pre-4.2 legacy codepath. 213 // Pre-4.2 legacy codepath.
169 if (app_data->legacy_rsa) { 214 if (ex_data->legacy_rsa) {
170 int ret = app_data->legacy_rsa->meth->rsa_priv_enc( 215 int ret = ex_data->legacy_rsa->meth->rsa_priv_enc(
171 flen, from, to, app_data->legacy_rsa, ANDROID_RSA_PKCS1_PADDING); 216 in_len, in, out, ex_data->legacy_rsa, ANDROID_RSA_PKCS1_PADDING);
172 if (ret < 0) { 217 if (ret < 0) {
173 LOG(WARNING) << "Could not sign message in RsaMethodPrivEnc!"; 218 LOG(WARNING) << "Could not sign message in RsaMethodPrivEnc!";
174 // System OpenSSL will use a separate error queue, so it is still 219 // System OpenSSL will use a separate error queue, so it is still
175 // necessary to push a new error. 220 // necessary to push a new error.
176 // 221 //
177 // TODO(davidben): It would be good to also clear the system error queue 222 // 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 223 // 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 224 // through Java, it's difficult to get a handle on a system OpenSSL
180 // function; dlopen loads a second copy.) 225 // function; dlopen loads a second copy.)
181 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); 226 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
182 return -1; 227 return 0;
183 } 228 }
184 return ret; 229 *out_len = ret;
230 return 1;
185 } 231 }
186 232
187 base::StringPiece from_piece(reinterpret_cast<const char*>(from), flen); 233 base::StringPiece from_piece(reinterpret_cast<const char*>(in), in_len);
188 std::vector<uint8> result; 234 std::vector<uint8> result;
189 // For RSA keys, this function behaves as RSA_private_encrypt with 235 // For RSA keys, this function behaves as RSA_private_encrypt with
190 // PKCS#1 padding. 236 // PKCS#1 padding.
191 if (!RawSignDigestWithPrivateKey(app_data->private_key, 237 if (!RawSignDigestWithPrivateKey(ex_data->private_key, from_piece, &result)) {
192 from_piece, &result)) {
193 LOG(WARNING) << "Could not sign message in RsaMethodPrivEnc!"; 238 LOG(WARNING) << "Could not sign message in RsaMethodPrivEnc!";
194 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); 239 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
195 return -1; 240 return 0;
196 } 241 }
197 242
198 size_t expected_size = static_cast<size_t>(RSA_size(rsa)); 243 size_t expected_size = static_cast<size_t>(RSA_size(rsa));
199 if (result.size() > expected_size) { 244 if (result.size() > expected_size) {
200 LOG(ERROR) << "RSA Signature size mismatch, actual: " 245 LOG(ERROR) << "RSA Signature size mismatch, actual: "
201 << result.size() << ", expected <= " << expected_size; 246 << result.size() << ", expected <= " << expected_size;
202 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); 247 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
203 return -1; 248 return 0;
249 }
250
251 if (max_out < expected_size) {
252 OPENSSL_PUT_ERROR(RSA, sign_raw, RSA_R_DATA_TOO_LARGE);
253 return 0;
204 } 254 }
205 255
206 // Copy result to OpenSSL-provided buffer. RawSignDigestWithPrivateKey 256 // Copy result to OpenSSL-provided buffer. RawSignDigestWithPrivateKey
207 // should pad with leading 0s, but if it doesn't, pad the result. 257 // should pad with leading 0s, but if it doesn't, pad the result.
208 size_t zero_pad = expected_size - result.size(); 258 size_t zero_pad = expected_size - result.size();
209 memset(to, 0, zero_pad); 259 memset(out, 0, zero_pad);
210 memcpy(to + zero_pad, &result[0], result.size()); 260 memcpy(out + zero_pad, &result[0], result.size());
261 *out_len = expected_size;
211 262
212 return expected_size; 263 return 1;
213 } 264 }
214 265
215 int RsaMethodPrivDec(int flen, 266 int RsaMethodDecrypt(RSA* rsa,
216 const unsigned char* from, 267 size_t* out_len,
217 unsigned char* to, 268 uint8_t* out,
218 RSA* rsa, 269 size_t max_out,
270 const uint8_t* in,
271 size_t in_len,
219 int padding) { 272 int padding) {
220 NOTIMPLEMENTED(); 273 NOTIMPLEMENTED();
221 RSAerr(RSA_F_RSA_PRIVATE_DECRYPT, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED); 274 OPENSSL_PUT_ERROR(RSA, decrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE);
222 return -1;
223 }
224
225 int RsaMethodInit(RSA* rsa) {
226 return 0; 275 return 0;
227 } 276 }
228 277
229 int RsaMethodFinish(RSA* rsa) { 278 int RsaMethodVerifyRaw(RSA* rsa,
230 // Ensure the global JNI reference created with this wrapper is 279 size_t* out_len,
231 // properly destroyed with it. 280 uint8_t* out,
232 RsaAppData* app_data = static_cast<RsaAppData*>(RSA_get_app_data(rsa)); 281 size_t max_out,
233 if (app_data != NULL) { 282 const uint8_t* in,
234 RSA_set_app_data(rsa, NULL); 283 size_t in_len,
235 ReleaseKey(app_data->private_key); 284 int padding) {
236 delete app_data; 285 NOTIMPLEMENTED();
237 } 286 OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_UNKNOWN_ALGORITHM_TYPE);
238 // Actual return value is ignored by OpenSSL. There are no docs
239 // explaining what this is supposed to be.
240 return 0; 287 return 0;
241 } 288 }
242 289
243 const RSA_METHOD android_rsa_method = { 290 const RSA_METHOD android_rsa_method = {
244 /* .name = */ "Android signing-only RSA method", 291 {
245 /* .rsa_pub_enc = */ RsaMethodPubEnc, 292 0 /* references */,
246 /* .rsa_pub_dec = */ RsaMethodPubDec, 293 1 /* is_static */
247 /* .rsa_priv_enc = */ RsaMethodPrivEnc, 294 } /* common */,
248 /* .rsa_priv_dec = */ RsaMethodPrivDec, 295 NULL /* app_data */,
249 /* .rsa_mod_exp = */ NULL, 296
250 /* .bn_mod_exp = */ NULL, 297 NULL /* init */,
251 /* .init = */ RsaMethodInit, 298 NULL /* finish */,
252 /* .finish = */ RsaMethodFinish, 299 RsaMethodSize,
253 // This flag is necessary to tell OpenSSL to avoid checking the content 300 NULL /* sign */,
254 // (i.e. internal fields) of the private key. Otherwise, it will complain 301 NULL /* verify */,
255 // it's not valid for the certificate. 302 RsaMethodEncrypt,
256 /* .flags = */ RSA_METHOD_FLAG_NO_CHECK, 303 RsaMethodSignRaw,
257 /* .app_data = */ NULL, 304 RsaMethodDecrypt,
258 /* .rsa_sign = */ NULL, 305 RsaMethodVerifyRaw,
259 /* .rsa_verify = */ NULL, 306 NULL /* mod_exp */,
260 /* .rsa_keygen = */ NULL, 307 NULL /* bn_mod_exp */,
308 RSA_FLAG_OPAQUE,
309 NULL /* keygen */,
261 }; 310 };
262 311
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. 312 // 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. 313 // |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 314 // |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 315 // backing |private_key|. This parameter is only used for Android < 4.2 to
305 // implement key operations not exposed by the platform. 316 // implement key operations not exposed by the platform.
306 // |pkey| is the EVP_PKEY to setup as a wrapper. 317 // |pkey| is the EVP_PKEY to setup as a wrapper.
307 // Returns true on success, false otherwise. 318 // Returns true on success, false otherwise.
308 // On success, this creates a new global JNI reference to the object 319 // 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 320 // that is owned by and destroyed with the EVP_PKEY. I.e. caller can
310 // free |private_key| after the call. 321 // free |private_key| after the call.
311 bool GetRsaPkeyWrapper(jobject private_key, 322 bool GetRsaPkeyWrapper(jobject private_key,
312 AndroidRSA* legacy_rsa, 323 AndroidRSA* legacy_rsa,
313 EVP_PKEY* pkey) { 324 EVP_PKEY* pkey) {
314 crypto::ScopedRSA rsa(RSA_new()); 325 crypto::ScopedRSA rsa(
315 RSA_set_method(rsa.get(), &android_rsa_method); 326 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 327
333 ScopedJavaGlobalRef<jobject> global_key; 328 ScopedJavaGlobalRef<jobject> global_key;
334 global_key.Reset(NULL, private_key); 329 global_key.Reset(NULL, private_key);
335 if (global_key.is_null()) { 330 if (global_key.is_null()) {
336 LOG(ERROR) << "Could not create global JNI reference"; 331 LOG(ERROR) << "Could not create global JNI reference";
337 return false; 332 return false;
338 } 333 }
339 RsaAppData* app_data = new RsaAppData(); 334
340 app_data->private_key = global_key.Release(); 335 std::vector<uint8> modulus;
341 app_data->legacy_rsa = legacy_rsa; 336 if (!GetRSAKeyModulus(private_key, &modulus)) {
342 RSA_set_app_data(rsa.get(), app_data); 337 LOG(ERROR) << "Failed to get private key modulus";
338 return false;
339 }
340
341 KeyExData* ex_data = new KeyExData;
342 ex_data->private_key = global_key.Release();
343 ex_data->legacy_rsa = legacy_rsa;
344 ex_data->cached_size = VectorBignumSize(modulus);
345 RSA_set_ex_data(
346 rsa.get(), global_boringssl_engine.Get().rsa_ex_index(), ex_data);
343 EVP_PKEY_assign_RSA(pkey, rsa.release()); 347 EVP_PKEY_assign_RSA(pkey, rsa.release());
344 return true; 348 return true;
345 } 349 }
346 350
347 // On Android < 4.2, the libkeystore.so ENGINE uses CRYPTO_EX_DATA and is not 351 // 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 352 // 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 353 // 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 354 // CRYPTO_EX_DATA class. To work around this, leak an extra reference to the
351 // ENGINE we extract in GetRsaLegacyKey. 355 // ENGINE we extract in GetRsaLegacyKey.
352 // 356 //
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
391 if (sys_pkey != NULL) { 395 if (sys_pkey != NULL) {
392 if (sys_pkey->type != ANDROID_EVP_PKEY_RSA) { 396 if (sys_pkey->type != ANDROID_EVP_PKEY_RSA) {
393 LOG(ERROR) << "Private key has wrong type!"; 397 LOG(ERROR) << "Private key has wrong type!";
394 return NULL; 398 return NULL;
395 } 399 }
396 400
397 AndroidRSA* sys_rsa = sys_pkey->pkey.rsa; 401 AndroidRSA* sys_rsa = sys_pkey->pkey.rsa;
398 if (sys_rsa->engine) { 402 if (sys_rsa->engine) {
399 // |private_key| may not have an engine if the PrivateKey did not come 403 // |private_key| may not have an engine if the PrivateKey did not come
400 // from the key store, such as in unit tests. 404 // from the key store, such as in unit tests.
401 if (!strcmp(sys_rsa->engine->id, "keystore")) { 405 if (strcmp(sys_rsa->engine->id, "keystore") == 0) {
402 LeakEngine(private_key); 406 LeakEngine(private_key);
403 } else { 407 } else {
404 NOTREACHED(); 408 NOTREACHED();
405 } 409 }
406 } 410 }
407 411
408 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new()); 412 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new());
409 if (!GetRsaPkeyWrapper(private_key, sys_rsa, pkey.get())) 413 if (!GetRsaPkeyWrapper(private_key, sys_rsa, pkey.get()))
410 return NULL; 414 return NULL;
411 return pkey.release(); 415 return pkey.release();
(...skipping 12 matching lines...) Expand all
424 reinterpret_cast<const unsigned char*>(&encoded[0]); 428 reinterpret_cast<const unsigned char*>(&encoded[0]);
425 int len = static_cast<int>(encoded.size()); 429 int len = static_cast<int>(encoded.size());
426 EVP_PKEY* pkey = d2i_AutoPrivateKey(NULL, &p, len); 430 EVP_PKEY* pkey = d2i_AutoPrivateKey(NULL, &p, len);
427 if (pkey == NULL) { 431 if (pkey == NULL) {
428 LOG(ERROR) << "Can't convert private key data!"; 432 LOG(ERROR) << "Can't convert private key data!";
429 return NULL; 433 return NULL;
430 } 434 }
431 return pkey; 435 return pkey;
432 } 436 }
433 437
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. 438 // Custom ECDSA_METHOD that uses the platform APIs.
561 // Note that for now, only signing through ECDSA_sign() is really supported. 439 // Note that for now, only signing through ECDSA_sign() is really supported.
562 // all other method pointers are either stubs returning errors, or no-ops. 440 // all other method pointers are either stubs returning errors, or no-ops.
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 441
569 // Used to ensure that the global JNI reference associated with a custom 442 jobject EcKeyGetKey(const EC_KEY* ec_key) {
570 // EC_KEY + ECDSA_METHOD wrapper is released when its EX_DATA is destroyed 443 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). 444 ec_key, global_boringssl_engine.Get().ec_key_ex_index()));
572 void ExDataFree(void* parent, 445 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 } 446 }
585 447
586 int ExDataDup(CRYPTO_EX_DATA* to, 448 size_t EcdsaMethodGroupOrderSize(const EC_KEY* ec_key) {
587 CRYPTO_EX_DATA* from, 449 KeyExData* ex_data = reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data(
588 void* from_d, 450 ec_key, global_boringssl_engine.Get().ec_key_ex_index()));
589 int idx, 451 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 } 452 }
600 453
601 class EcdsaExDataIndex { 454 int EcdsaMethodSign(const uint8_t* digest,
602 public: 455 size_t digest_len,
603 int ex_data_index() { return ex_data_index_; } 456 uint8_t* sig,
604 457 unsigned int* sig_len,
605 EcdsaExDataIndex() { 458 EC_KEY* ec_key) {
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. 459 // Retrieve private key JNI reference.
633 jobject private_key = reinterpret_cast<jobject>( 460 jobject private_key = EcKeyGetKey(ec_key);
634 ECDSA_get_ex_data(eckey, EcdsaGetExDataIndex()));
635 if (!private_key) { 461 if (!private_key) {
636 LOG(WARNING) << "Null JNI reference passed to EcdsaMethodDoSign!"; 462 LOG(WARNING) << "Null JNI reference passed to EcdsaMethodSign!";
637 return NULL; 463 return 0;
638 } 464 }
639 // Sign message with it through JNI. 465 // Sign message with it through JNI.
640 std::vector<uint8> signature; 466 std::vector<uint8> signature;
641 base::StringPiece digest( 467 base::StringPiece digest_sp(reinterpret_cast<const char*>(digest),
642 reinterpret_cast<const char*>(dgst), 468 digest_len);
643 static_cast<size_t>(dgst_len)); 469 if (!RawSignDigestWithPrivateKey(private_key, digest_sp, &signature)) {
644 if (!RawSignDigestWithPrivateKey( 470 LOG(WARNING) << "Could not sign message in EcdsaMethodSign!";
645 private_key, digest, &signature)) { 471 return 0;
646 LOG(WARNING) << "Could not sign message in EcdsaMethodDoSign!";
647 return NULL;
648 } 472 }
649 473
650 // Note: With ECDSA, the actual signature may be smaller than 474 // Note: With ECDSA, the actual signature may be smaller than
651 // ECDSA_size(). 475 // ECDSA_size().
652 size_t max_expected_size = static_cast<size_t>(ECDSA_size(eckey)); 476 size_t max_expected_size = ECDSA_size(ec_key);
653 if (signature.size() > max_expected_size) { 477 if (signature.size() > max_expected_size) {
654 LOG(ERROR) << "ECDSA Signature size mismatch, actual: " 478 LOG(ERROR) << "ECDSA Signature size mismatch, actual: "
655 << signature.size() << ", expected <= " 479 << signature.size() << ", expected <= "
656 << max_expected_size; 480 << max_expected_size;
657 return NULL; 481 return 0;
658 } 482 }
659 483
660 // Convert signature to ECDSA_SIG object 484 memcpy(sig, &signature[0], signature.size());
661 const unsigned char* sigbuf = 485 *sig_len = signature.size();
662 reinterpret_cast<const unsigned char*>(&signature[0]); 486 return 1;
663 long siglen = static_cast<long>(signature.size());
664 return d2i_ECDSA_SIG(NULL, &sigbuf, siglen);
665 } 487 }
666 488
667 int EcdsaMethodSignSetup(EC_KEY* eckey, 489 int EcdsaMethodVerify(const uint8_t* digest,
668 BN_CTX* ctx, 490 size_t digest_len,
669 BIGNUM** kinv, 491 const uint8_t* sig,
670 BIGNUM** r) { 492 size_t sig_len,
493 EC_KEY* ec_key) {
671 NOTIMPLEMENTED(); 494 NOTIMPLEMENTED();
672 ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ECDSA_R_ERR_EC_LIB); 495 OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ECDSA_R_NOT_IMPLEMENTED);
673 return -1; 496 return 0;
674 } 497 }
675 498
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. 499 // Setup an EVP_PKEY to wrap an existing platform PrivateKey object.
695 // |private_key| is the JNI reference (local or global) to the object. 500 // |private_key| is the JNI reference (local or global) to the object.
696 // |pkey| is the EVP_PKEY to setup as a wrapper. 501 // |pkey| is the EVP_PKEY to setup as a wrapper.
697 // Returns true on success, false otherwise. 502 // Returns true on success, false otherwise.
698 // On success, this creates a global JNI reference to the object that 503 // On success, this creates a global JNI reference to the object that
699 // is owned by and destroyed with the EVP_PKEY. I.e. the caller shall 504 // is owned by and destroyed with the EVP_PKEY. I.e. the caller shall
700 // always free |private_key| after the call. 505 // always free |private_key| after the call.
701 bool GetEcdsaPkeyWrapper(jobject private_key, EVP_PKEY* pkey) { 506 bool GetEcdsaPkeyWrapper(jobject private_key, EVP_PKEY* pkey) {
702 crypto::ScopedEC_KEY eckey(EC_KEY_new()); 507 crypto::ScopedEC_KEY ec_key(
703 ECDSA_set_method(eckey.get(), &android_ecdsa_method); 508 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 509
723 ScopedJavaGlobalRef<jobject> global_key; 510 ScopedJavaGlobalRef<jobject> global_key;
724 global_key.Reset(NULL, private_key); 511 global_key.Reset(NULL, private_key);
725 if (global_key.is_null()) { 512 if (global_key.is_null()) {
726 LOG(ERROR) << "Can't create global JNI reference"; 513 LOG(ERROR) << "Can't create global JNI reference";
727 return false; 514 return false;
728 } 515 }
729 ECDSA_set_ex_data(eckey.get(),
730 EcdsaGetExDataIndex(),
731 global_key.Release());
732 516
733 EVP_PKEY_assign_EC_KEY(pkey, eckey.release()); 517 std::vector<uint8> order;
518 if (!GetECKeyOrder(private_key, &order)) {
519 LOG(ERROR) << "Can't extract order parameter from EC private key";
520 return false;
521 }
522
523 KeyExData* ex_data = new KeyExData;
524 ex_data->private_key = global_key.Release();
525 ex_data->legacy_rsa = NULL;
526 ex_data->cached_size = VectorBignumSize(order);
527
528 EC_KEY_set_ex_data(
529 ec_key.get(), global_boringssl_engine.Get().ec_key_ex_index(), ex_data);
530
531 EVP_PKEY_assign_EC_KEY(pkey, ec_key.release());
734 return true; 532 return true;
735 } 533 }
736 534
535 const ECDSA_METHOD android_ecdsa_method = {
536 {
537 0 /* references */,
538 1 /* is_static */
539 } /* common */,
540 NULL /* app_data */,
541
542 NULL /* init */,
543 NULL /* finish */,
544 EcdsaMethodGroupOrderSize,
545 EcdsaMethodSign,
546 EcdsaMethodVerify,
547 ECDSA_FLAG_OPAQUE,
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 | « net/BUILD.gn ('k') | net/android/keystore_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698