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

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

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