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

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: ... 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/err.h>
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>
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"
(...skipping 27 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 DSA_METHOD android_dsa_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;
117 }; 82 };
118 83
119 int RsaMethodPubEnc(int flen, 84 // ExDataDup is called when one of the RSA, DSA or EC_KEY objects is
120 const unsigned char* from, 85 // duplicated. We don't support this and it should never happen.
121 unsigned char* to, 86 int ExDataDup(CRYPTO_EX_DATA* to,
122 RSA* rsa, 87 const CRYPTO_EX_DATA* from,
123 int padding) { 88 void** from_d,
124 NOTIMPLEMENTED(); 89 int index,
125 RSAerr(RSA_F_RSA_PUBLIC_ENCRYPT, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED); 90 long argl,
126 return -1; 91 void* argp) {
92 CHECK(false);
93 return 0;
127 } 94 }
128 95
129 int RsaMethodPubDec(int flen, 96 // ExDataFree is called when one of the RSA, DSA or EC_KEY object is freed.
130 const unsigned char* from, 97 void ExDataFree(void* parent,
131 unsigned char* to, 98 void* ptr,
132 RSA* rsa, 99 CRYPTO_EX_DATA* ad,
133 int padding) { 100 int index,
134 NOTIMPLEMENTED(); 101 long argl,
135 RSAerr(RSA_F_RSA_PUBLIC_DECRYPT, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED); 102 void* argp) {
136 return -1; 103 // Ensure the global JNI reference created with this wrapper is
104 // properly destroyed with it.
105 KeyExData *ex_data = reinterpret_cast<KeyExData*>(ptr);
106 if (ex_data != NULL) {
107 ReleaseKey(ex_data->private_key);
108 delete ex_data;
109 }
137 } 110 }
138 111
139 // See RSA_eay_private_encrypt in 112 // 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 113 // forwarding the requested operations to the Java libraries.
141 // implementation of this function. 114 class BoringSSLEngine {
142 int RsaMethodPrivEnc(int flen, 115 public:
143 const unsigned char *from, 116 BoringSSLEngine()
144 unsigned char *to, 117 : rsa_index_(RSA_get_ex_new_index(0 /* argl */,
145 RSA *rsa, 118 NULL /* argp */,
119 NULL /* new_func */,
120 ExDataDup,
121 ExDataFree)),
122 dsa_index_(DSA_get_ex_new_index(0 /* argl */,
123 NULL /* argp */,
124 NULL /* new_func */,
125 ExDataDup,
126 ExDataFree)),
127 ec_key_index_(EC_KEY_get_ex_new_index(0 /* argl */,
128 NULL /* argp */,
129 NULL /* new_func */,
130 ExDataDup,
131 ExDataFree)),
132 engine_(ENGINE_new()) {
133 ENGINE_set_RSA_method(
134 engine_, &android_rsa_method, sizeof(android_rsa_method));
135 ENGINE_set_DSA_method(
136 engine_, &android_dsa_method, sizeof(android_dsa_method));
137 ENGINE_set_ECDSA_method(
138 engine_, &android_ecdsa_method, sizeof(android_ecdsa_method));
139 }
140
141 int rsa_ex_index() const { return rsa_index_; }
142 int dsa_ex_index() const { return dsa_index_; }
143 int ec_key_ex_index() const { return ec_key_index_; }
144
145 const ENGINE* engine() const { return engine_; }
146
147 private:
148 const int rsa_index_;
149 const int dsa_index_;
150 const int ec_key_index_;
151 ENGINE* const engine_;
152 };
153
154 base::LazyInstance<BoringSSLEngine>::Leaky global_boringssl_engine =
155 LAZY_INSTANCE_INITIALIZER;
156
157 KeyExData* RsaGetExData(const RSA* rsa) {
158 return reinterpret_cast<KeyExData*>(
159 RSA_get_ex_data(rsa, global_boringssl_engine.Get().rsa_ex_index()));
160 }
161
162 size_t RsaMethodSize(const RSA *rsa) {
163 const KeyExData *ex_data = RsaGetExData(rsa);
164
165 std::vector<uint8> modulus;
166 if (!GetRSAKeyModulus(ex_data->private_key, &modulus)) {
167 LOG(ERROR) << "Failed to get private key modulus";
168 return false;
169 }
170
171 size_t size = modulus.size();
172 // Ignore any leading zero bytes.
173 for (size_t i = 0; i < modulus.size() && modulus[i] == 0; i++) {
174 size--;
175 }
176 return size;
177 }
178
179 int RsaMethodEncrypt(RSA* rsa,
180 size_t* out_len,
181 uint8_t* out,
182 size_t max_out,
183 const uint8_t* in,
184 size_t in_len,
185 int padding) {
186 NOTIMPLEMENTED();
187 OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE);
188 return 1;
189 }
190
191 int RsaMethodSignRaw(RSA* rsa,
192 size_t* out_len,
193 uint8_t* out,
194 size_t max_out,
195 const uint8_t* in,
196 size_t in_len,
146 int padding) { 197 int padding) {
147 DCHECK_EQ(RSA_PKCS1_PADDING, padding); 198 DCHECK_EQ(RSA_PKCS1_PADDING, padding);
148 if (padding != RSA_PKCS1_PADDING) { 199 if (padding != RSA_PKCS1_PADDING) {
149 // TODO(davidben): If we need to, we can implement RSA_NO_PADDING 200 // TODO(davidben): If we need to, we can implement RSA_NO_PADDING
150 // by using javax.crypto.Cipher and picking either the 201 // by using javax.crypto.Cipher and picking either the
151 // "RSA/ECB/NoPadding" or "RSA/ECB/PKCS1Padding" transformation as 202 // "RSA/ECB/NoPadding" or "RSA/ECB/PKCS1Padding" transformation as
152 // appropriate. I believe support for both of these was added in 203 // appropriate. I believe support for both of these was added in
153 // the same Android version as the "NONEwithRSA" 204 // the same Android version as the "NONEwithRSA"
154 // java.security.Signature algorithm, so the same version checks 205 // java.security.Signature algorithm, so the same version checks
155 // for GetRsaLegacyKey should work. 206 // for GetRsaLegacyKey should work.
156 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE); 207 OPENSSL_PUT_ERROR(RSA, sign_raw, RSA_R_UNKNOWN_ALGORITHM_TYPE);
157 return -1; 208 return 0;
158 } 209 }
159 210
160 // Retrieve private key JNI reference. 211 // Retrieve private key JNI reference.
161 RsaAppData* app_data = static_cast<RsaAppData*>(RSA_get_app_data(rsa)); 212 const KeyExData *ex_data = RsaGetExData(rsa);
162 if (!app_data || !app_data->private_key) { 213 if (!ex_data || !ex_data->private_key) {
163 LOG(WARNING) << "Null JNI reference passed to RsaMethodPrivEnc!"; 214 LOG(WARNING) << "Null JNI reference passed to RsaMethodPrivEnc!";
164 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); 215 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
165 return -1; 216 return 0;
166 } 217 }
167 218
168 // Pre-4.2 legacy codepath. 219 // Pre-4.2 legacy codepath.
169 if (app_data->legacy_rsa) { 220 if (ex_data->legacy_rsa) {
170 int ret = app_data->legacy_rsa->meth->rsa_priv_enc( 221 int ret = ex_data->legacy_rsa->meth->rsa_priv_enc(
171 flen, from, to, app_data->legacy_rsa, ANDROID_RSA_PKCS1_PADDING); 222 in_len, in, out, ex_data->legacy_rsa, ANDROID_RSA_PKCS1_PADDING);
172 if (ret < 0) { 223 if (ret < 0) {
173 LOG(WARNING) << "Could not sign message in RsaMethodPrivEnc!"; 224 LOG(WARNING) << "Could not sign message in RsaMethodPrivEnc!";
174 // System OpenSSL will use a separate error queue, so it is still 225 // System OpenSSL will use a separate error queue, so it is still
175 // necessary to push a new error. 226 // necessary to push a new error.
176 // 227 //
177 // TODO(davidben): It would be good to also clear the system error queue 228 // 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 229 // 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 230 // through Java, it's difficult to get a handle on a system OpenSSL
180 // function; dlopen loads a second copy.) 231 // function; dlopen loads a second copy.)
181 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); 232 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
182 return -1; 233 return 0;
183 } 234 }
184 return ret; 235 *out_len = ret;
236 return 1;
185 } 237 }
186 238
187 base::StringPiece from_piece(reinterpret_cast<const char*>(from), flen); 239 base::StringPiece from_piece(reinterpret_cast<const char*>(in), in_len);
188 std::vector<uint8> result; 240 std::vector<uint8> result;
189 // For RSA keys, this function behaves as RSA_private_encrypt with 241 // For RSA keys, this function behaves as RSA_private_encrypt with
190 // PKCS#1 padding. 242 // PKCS#1 padding.
191 if (!RawSignDigestWithPrivateKey(app_data->private_key, 243 if (!RawSignDigestWithPrivateKey(ex_data->private_key, from_piece, &result)) {
192 from_piece, &result)) {
193 LOG(WARNING) << "Could not sign message in RsaMethodPrivEnc!"; 244 LOG(WARNING) << "Could not sign message in RsaMethodPrivEnc!";
194 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); 245 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
195 return -1; 246 return 0;
196 } 247 }
197 248
198 size_t expected_size = static_cast<size_t>(RSA_size(rsa)); 249 size_t expected_size = static_cast<size_t>(RSA_size(rsa));
199 if (result.size() > expected_size) { 250 if (result.size() > expected_size) {
200 LOG(ERROR) << "RSA Signature size mismatch, actual: " 251 LOG(ERROR) << "RSA Signature size mismatch, actual: "
201 << result.size() << ", expected <= " << expected_size; 252 << result.size() << ", expected <= " << expected_size;
202 RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); 253 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
203 return -1; 254 return 0;
255 }
256
257 if (max_out < expected_size) {
258 OPENSSL_PUT_ERROR(RSA, sign_raw, RSA_R_DATA_TOO_LARGE);
259 return 0;
204 } 260 }
205 261
206 // Copy result to OpenSSL-provided buffer. RawSignDigestWithPrivateKey 262 // Copy result to OpenSSL-provided buffer. RawSignDigestWithPrivateKey
207 // should pad with leading 0s, but if it doesn't, pad the result. 263 // should pad with leading 0s, but if it doesn't, pad the result.
208 size_t zero_pad = expected_size - result.size(); 264 size_t zero_pad = expected_size - result.size();
209 memset(to, 0, zero_pad); 265 memset(out, 0, zero_pad);
210 memcpy(to + zero_pad, &result[0], result.size()); 266 memcpy(out + zero_pad, &result[0], result.size());
267 *out_len = expected_size;
211 268
212 return expected_size; 269 return 1;
213 } 270 }
214 271
215 int RsaMethodPrivDec(int flen, 272 int RsaMethodDecrypt(RSA* rsa,
216 const unsigned char* from, 273 size_t* out_len,
217 unsigned char* to, 274 uint8_t* out,
218 RSA* rsa, 275 size_t max_out,
276 const uint8_t* in,
277 size_t in_len,
219 int padding) { 278 int padding) {
220 NOTIMPLEMENTED(); 279 NOTIMPLEMENTED();
221 RSAerr(RSA_F_RSA_PRIVATE_DECRYPT, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED); 280 OPENSSL_PUT_ERROR(RSA, decrypt, RSA_R_UNKNOWN_PADDING_TYPE);
222 return -1; 281 return 1;
223 } 282 }
224 283
225 int RsaMethodInit(RSA* rsa) { 284 int RsaMethodVerifyRaw(RSA* rsa,
226 return 0; 285 size_t* out_len,
227 } 286 uint8_t* out,
228 287 size_t max_out,
229 int RsaMethodFinish(RSA* rsa) { 288 const uint8_t* in,
230 // Ensure the global JNI reference created with this wrapper is 289 size_t in_len,
231 // properly destroyed with it. 290 int padding) {
232 RsaAppData* app_data = static_cast<RsaAppData*>(RSA_get_app_data(rsa)); 291 NOTIMPLEMENTED();
233 if (app_data != NULL) { 292 OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_UNKNOWN_ALGORITHM_TYPE);
234 RSA_set_app_data(rsa, NULL); 293 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 } 294 }
242 295
243 const RSA_METHOD android_rsa_method = { 296 const RSA_METHOD android_rsa_method = {
244 /* .name = */ "Android signing-only RSA method", 297 {
245 /* .rsa_pub_enc = */ RsaMethodPubEnc, 298 0 /* references */,
246 /* .rsa_pub_dec = */ RsaMethodPubDec, 299 1 /* is_static */
247 /* .rsa_priv_enc = */ RsaMethodPrivEnc, 300 } /* common */,
248 /* .rsa_priv_dec = */ RsaMethodPrivDec, 301 NULL /* app_data */,
249 /* .rsa_mod_exp = */ NULL, 302
250 /* .bn_mod_exp = */ NULL, 303 NULL /* init */,
251 /* .init = */ RsaMethodInit, 304 NULL /* finish */,
252 /* .finish = */ RsaMethodFinish, 305 RsaMethodSize,
253 // This flag is necessary to tell OpenSSL to avoid checking the content 306 NULL /* sign */,
254 // (i.e. internal fields) of the private key. Otherwise, it will complain 307 NULL /* verify */,
255 // it's not valid for the certificate. 308 RsaMethodEncrypt,
256 /* .flags = */ RSA_METHOD_FLAG_NO_CHECK, 309 RsaMethodSignRaw,
257 /* .app_data = */ NULL, 310 RsaMethodDecrypt,
258 /* .rsa_sign = */ NULL, 311 RsaMethodVerifyRaw,
259 /* .rsa_verify = */ NULL, 312 NULL /* mod_exp */,
260 /* .rsa_keygen = */ NULL, 313 NULL /* bn_mod_exp */,
314 0 /* flags */,
315 NULL /* keygen */,
261 }; 316 };
262 317
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. 318 // 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. 319 // |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 320 // |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 321 // backing |private_key|. This parameter is only used for Android < 4.2 to
305 // implement key operations not exposed by the platform. 322 // implement key operations not exposed by the platform.
306 // |pkey| is the EVP_PKEY to setup as a wrapper. 323 // |pkey| is the EVP_PKEY to setup as a wrapper.
307 // Returns true on success, false otherwise. 324 // Returns true on success, false otherwise.
308 // On success, this creates a new global JNI reference to the object 325 // 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 326 // that is owned by and destroyed with the EVP_PKEY. I.e. caller can
310 // free |private_key| after the call. 327 // free |private_key| after the call.
311 bool GetRsaPkeyWrapper(jobject private_key, 328 bool GetRsaPkeyWrapper(jobject private_key,
312 AndroidRSA* legacy_rsa, 329 AndroidRSA* legacy_rsa,
313 EVP_PKEY* pkey) { 330 EVP_PKEY* pkey) {
314 crypto::ScopedRSA rsa(RSA_new()); 331 crypto::ScopedRSA rsa(
315 RSA_set_method(rsa.get(), &android_rsa_method); 332 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 333
333 ScopedJavaGlobalRef<jobject> global_key; 334 ScopedJavaGlobalRef<jobject> global_key;
334 global_key.Reset(NULL, private_key); 335 global_key.Reset(NULL, private_key);
335 if (global_key.is_null()) { 336 if (global_key.is_null()) {
336 LOG(ERROR) << "Could not create global JNI reference"; 337 LOG(ERROR) << "Could not create global JNI reference";
337 return false; 338 return false;
338 } 339 }
339 RsaAppData* app_data = new RsaAppData(); 340 KeyExData* ex_data = new KeyExData;
340 app_data->private_key = global_key.Release(); 341 ex_data->private_key = global_key.Release();
341 app_data->legacy_rsa = legacy_rsa; 342 ex_data->legacy_rsa = legacy_rsa;
342 RSA_set_app_data(rsa.get(), app_data); 343 RSA_set_ex_data(
344 rsa.get(), global_boringssl_engine.Get().rsa_ex_index(), ex_data);
343 EVP_PKEY_assign_RSA(pkey, rsa.release()); 345 EVP_PKEY_assign_RSA(pkey, rsa.release());
344 return true; 346 return true;
345 } 347 }
346 348
347 // On Android < 4.2, the libkeystore.so ENGINE uses CRYPTO_EX_DATA and is not 349 // 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 350 // 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 351 // 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 352 // CRYPTO_EX_DATA class. To work around this, leak an extra reference to the
351 // ENGINE we extract in GetRsaLegacyKey. 353 // ENGINE we extract in GetRsaLegacyKey.
352 // 354 //
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
391 if (sys_pkey != NULL) { 393 if (sys_pkey != NULL) {
392 if (sys_pkey->type != ANDROID_EVP_PKEY_RSA) { 394 if (sys_pkey->type != ANDROID_EVP_PKEY_RSA) {
393 LOG(ERROR) << "Private key has wrong type!"; 395 LOG(ERROR) << "Private key has wrong type!";
394 return NULL; 396 return NULL;
395 } 397 }
396 398
397 AndroidRSA* sys_rsa = sys_pkey->pkey.rsa; 399 AndroidRSA* sys_rsa = sys_pkey->pkey.rsa;
398 if (sys_rsa->engine) { 400 if (sys_rsa->engine) {
399 // |private_key| may not have an engine if the PrivateKey did not come 401 // |private_key| may not have an engine if the PrivateKey did not come
400 // from the key store, such as in unit tests. 402 // from the key store, such as in unit tests.
401 if (!strcmp(sys_rsa->engine->id, "keystore")) { 403 if (strcmp(sys_rsa->engine->id, "keystore") == 0) {
402 LeakEngine(private_key); 404 LeakEngine(private_key);
403 } else { 405 } else {
404 NOTREACHED(); 406 NOTREACHED();
405 } 407 }
406 } 408 }
407 409
408 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new()); 410 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new());
409 if (!GetRsaPkeyWrapper(private_key, sys_rsa, pkey.get())) 411 if (!GetRsaPkeyWrapper(private_key, sys_rsa, pkey.get()))
410 return NULL; 412 return NULL;
411 return pkey.release(); 413 return pkey.release();
(...skipping 16 matching lines...) Expand all
428 LOG(ERROR) << "Can't convert private key data!"; 430 LOG(ERROR) << "Can't convert private key data!";
429 return NULL; 431 return NULL;
430 } 432 }
431 return pkey; 433 return pkey;
432 } 434 }
433 435
434 // Custom DSA_METHOD that uses the platform APIs. 436 // Custom DSA_METHOD that uses the platform APIs.
435 // Note that for now, only signing through DSA_sign() is really supported. 437 // 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. 438 // all other method pointers are either stubs returning errors, or no-ops.
437 // See <openssl/dsa.h> for exact declaration of DSA_METHOD. 439 // 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 440
444 DSA_SIG* DsaMethodDoSign(const unsigned char* dgst, 441 jobject DsaGetKey(const DSA *dsa) {
445 int dlen, 442 KeyExData* ex_data = reinterpret_cast<KeyExData*>(
446 DSA* dsa) { 443 DSA_get_ex_data(dsa, global_boringssl_engine.Get().dsa_ex_index()));
447 // Extract the JNI reference to the PrivateKey object. 444 return ex_data->private_key;
448 jobject private_key = reinterpret_cast<jobject>(DSA_get_ex_data(dsa, 0)); 445 }
446
447 DSA_SIG* DsaMethodSign(const uint8_t* digest, size_t digest_len, DSA* dsa) {
448 jobject private_key = DsaGetKey(dsa);
449 if (private_key == NULL) 449 if (private_key == NULL)
450 return NULL; 450 return NULL;
451 451
452 // Sign the message with it, calling platform APIs. 452 // Sign the message with it, calling platform APIs.
453 std::vector<uint8> signature; 453 std::vector<uint8> signature;
454 if (!RawSignDigestWithPrivateKey( 454 if (!RawSignDigestWithPrivateKey(
455 private_key, 455 private_key,
456 base::StringPiece( 456 base::StringPiece(reinterpret_cast<const char*>(digest), digest_len),
457 reinterpret_cast<const char*>(dgst),
458 static_cast<size_t>(dlen)),
459 &signature)) { 457 &signature)) {
460 return NULL; 458 return NULL;
461 } 459 }
462 460
463 // Note: With DSA, the actual signature might be smaller than DSA_size(). 461 // 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)); 462 size_t max_expected_size = static_cast<size_t>(DSA_size(dsa));
465 if (signature.size() > max_expected_size) { 463 if (signature.size() > max_expected_size) {
466 LOG(ERROR) << "DSA Signature size mismatch, actual: " 464 LOG(ERROR) << "DSA Signature size mismatch, actual: "
467 << signature.size() << ", expected <= " 465 << signature.size() << ", expected <= "
468 << max_expected_size; 466 << max_expected_size;
469 return NULL; 467 return NULL;
470 } 468 }
471 469
472 // Convert the signature into a DSA_SIG object. 470 // Convert the signature into a DSA_SIG object.
473 const unsigned char* sigbuf = 471 const unsigned char* sigbuf =
474 reinterpret_cast<const unsigned char*>(&signature[0]); 472 reinterpret_cast<const unsigned char*>(&signature[0]);
475 int siglen = static_cast<size_t>(signature.size()); 473 int siglen = static_cast<size_t>(signature.size());
476 DSA_SIG* dsa_sig = d2i_DSA_SIG(NULL, &sigbuf, siglen); 474 DSA_SIG* dsa_sig = d2i_DSA_SIG(NULL, &sigbuf, siglen);
477 return dsa_sig; 475 return dsa_sig;
478 } 476 }
479 477
480 int DsaMethodSignSetup(DSA* dsa, 478 int DsaMethodSignSetup(const DSA* dsa,
481 BN_CTX* ctx_in, 479 BN_CTX* ctx_in,
482 BIGNUM** kinvp, 480 BIGNUM** kinvp,
483 BIGNUM** rp) { 481 BIGNUM** rp,
482 const uint8_t* digest,
483 size_t digest_len) {
484 NOTIMPLEMENTED(); 484 NOTIMPLEMENTED();
485 DSAerr(DSA_F_DSA_SIGN_SETUP, DSA_R_INVALID_DIGEST_TYPE); 485 OPENSSL_PUT_ERROR(DSA, sign_setup, DSA_R_MISSING_PARAMETERS);
486 return -1; 486 return 0;
487 } 487 }
488 488
489 int DsaMethodDoVerify(const unsigned char* dgst, 489 int DsaMethodVerify(int* out_valid,
490 int dgst_len, 490 const uint8_t* digest,
491 DSA_SIG* sig, 491 size_t digest_len,
492 DSA* dsa) { 492 DSA_SIG* sig,
493 const DSA* dsa) {
494 *out_valid = 0;
493 NOTIMPLEMENTED(); 495 NOTIMPLEMENTED();
494 DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_INVALID_DIGEST_TYPE); 496 OPENSSL_PUT_ERROR(DSA, verify, DSA_R_MISSING_PARAMETERS);
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; 497 return 0;
509 } 498 }
510 499
511 const DSA_METHOD android_dsa_method = { 500 const DSA_METHOD android_dsa_method = {
512 /* .name = */ "Android signing-only DSA method", 501 {
513 /* .dsa_do_sign = */ DsaMethodDoSign, 502 0 /* references */,
514 /* .dsa_sign_setup = */ DsaMethodSignSetup, 503 1 /* is_static */
515 /* .dsa_do_verify = */ DsaMethodDoVerify, 504 } /* common */,
516 /* .dsa_mod_exp = */ NULL, 505 NULL /* app_data */,
517 /* .bn_mod_exp = */ NULL, 506
518 /* .init = */ NULL, // nothing to do here. 507 NULL /* init */,
519 /* .finish = */ DsaMethodFinish, 508 NULL /* finish */,
520 /* .flags = */ 0, 509 DsaMethodSign,
521 /* .app_data = */ NULL, 510 DsaMethodSignSetup,
522 /* .dsa_paramgem = */ NULL, 511 DsaMethodVerify,
523 /* .dsa_keygen = */ NULL 512 NULL /* generate_parameters */,
513 NULL /* keygen */,
524 }; 514 };
525 515
516 // Decode the contents of an encoded big integer and either create a new
517 // BIGNUM object (if |*num_ptr| is NULL on input) or copy it (if
518 // |*num_ptr| is not NULL).
519 // |new_bytes| is the byte encoding of the new value.
520 // |num_ptr| is the address of a BIGNUM pointer. |*num_ptr| can be NULL.
521 // Returns true on success, false otherwise. On failure, |*num_ptr| is
522 // not modified. On success, |*num_ptr| will always be non-NULL and
523 // point to a valid BIGNUM object.
524 bool SwapBigNumPtrFromBytes(const std::vector<uint8>& new_bytes,
525 BIGNUM** num_ptr) {
526 BIGNUM* old_num = *num_ptr;
527 BIGNUM* new_num = BN_bin2bn(
528 reinterpret_cast<const unsigned char*>(&new_bytes[0]),
529 static_cast<int>(new_bytes.size()),
530 old_num);
531 if (new_num == NULL)
532 return false;
533
534 if (old_num == NULL)
535 *num_ptr = new_num;
536 return true;
537 }
538
526 // Setup an EVP_PKEY to wrap an existing DSA platform PrivateKey object. 539 // 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. 540 // |private_key| is a JNI reference (local or global) to the object.
528 // |pkey| is the EVP_PKEY to setup as a wrapper. 541 // |pkey| is the EVP_PKEY to setup as a wrapper.
529 // Returns true on success, false otherwise. 542 // Returns true on success, false otherwise.
530 // On success, this creates a global JNI reference to the same object 543 // On success, this creates a global JNI reference to the same object
531 // that will be owned by and destroyed with the EVP_PKEY. 544 // that will be owned by and destroyed with the EVP_PKEY.
532 bool GetDsaPkeyWrapper(jobject private_key, EVP_PKEY* pkey) { 545 bool GetDsaPkeyWrapper(jobject private_key, EVP_PKEY* pkey) {
533 crypto::ScopedDSA dsa(DSA_new()); 546 crypto::ScopedDSA dsa(
534 DSA_set_method(dsa.get(), &android_dsa_method); 547 DSA_new_method(global_boringssl_engine.Get().engine()));
535 548
536 // DSA_size() doesn't work with custom DSA_METHODs. To ensure it 549 // 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 550 // returns the right value, set the 'q' field in the DSA object to
538 // match the parameter from the platform key. 551 // match the parameter from the platform key.
539 std::vector<uint8> q; 552 std::vector<uint8> q;
540 if (!GetDSAKeyParamQ(private_key, &q)) { 553 if (!GetDSAKeyParamQ(private_key, &q)) {
541 LOG(ERROR) << "Can't extract Q parameter from DSA private key"; 554 LOG(ERROR) << "Can't extract Q parameter from DSA private key";
542 return false; 555 return false;
543 } 556 }
544 if (!SwapBigNumPtrFromBytes(q, &dsa.get()->q)) { 557 if (!SwapBigNumPtrFromBytes(q, &dsa.get()->q)) {
545 LOG(ERROR) << "Can't decode Q parameter from DSA private key"; 558 LOG(ERROR) << "Can't decode Q parameter from DSA private key";
546 return false; 559 return false;
547 } 560 }
548 561
549 ScopedJavaGlobalRef<jobject> global_key; 562 ScopedJavaGlobalRef<jobject> global_key;
550 global_key.Reset(NULL, private_key); 563 global_key.Reset(NULL, private_key);
551 if (global_key.is_null()) { 564 if (global_key.is_null()) {
552 LOG(ERROR) << "Could not create global JNI reference"; 565 LOG(ERROR) << "Could not create global JNI reference";
553 return false; 566 return false;
554 } 567 }
555 DSA_set_ex_data(dsa.get(), 0, global_key.Release()); 568 KeyExData* ex_data = new KeyExData;
569 ex_data->private_key = global_key.Release();
570 ex_data->legacy_rsa = NULL;
571 DSA_set_ex_data(
572 dsa.get(), global_boringssl_engine.Get().dsa_ex_index(), ex_data);
556 EVP_PKEY_assign_DSA(pkey, dsa.release()); 573 EVP_PKEY_assign_DSA(pkey, dsa.release());
davidben 2014/07/15 21:53:35 This function will currently always fail, leaking
557 return true; 574 return true;
558 } 575 }
559 576
577
560 // Custom ECDSA_METHOD that uses the platform APIs. 578 // Custom ECDSA_METHOD that uses the platform APIs.
561 // Note that for now, only signing through ECDSA_sign() is really supported. 579 // 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. 580 // 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 581
569 // Used to ensure that the global JNI reference associated with a custom 582 jobject EcKeyGetKey(const EC_KEY* ec_key) {
570 // EC_KEY + ECDSA_METHOD wrapper is released when its EX_DATA is destroyed 583 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). 584 ec_key, global_boringssl_engine.Get().ec_key_ex_index()));
572 void ExDataFree(void* parent, 585 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 } 586 }
585 587
586 int ExDataDup(CRYPTO_EX_DATA* to, 588 size_t EcdsaMethodSize(const EC_KEY* key) {
587 CRYPTO_EX_DATA* from, 589 jobject private_key = EcKeyGetKey(key);
588 void* from_d, 590 std::vector<uint8> order;
589 int idx, 591 if (!GetECKeyOrder(private_key, &order)) {
590 long argl, 592 LOG(ERROR) << "Can't extract order parameter from EC private key";
591 void* argp) { 593 return false;
592 // This callback shall never be called with the current OpenSSL 594 }
593 // implementation (the library only ever duplicates EX_DATA items 595 return order.size();
davidben 2014/07/15 21:53:34 The size hook is, as documented, supposed to retur
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 } 596 }
600 597
601 class EcdsaExDataIndex { 598 int EcdsaMethodSign(const uint8_t* digest,
602 public: 599 size_t digest_len,
603 int ex_data_index() { return ex_data_index_; } 600 uint8_t* sig,
604 601 unsigned int* sig_len,
605 EcdsaExDataIndex() { 602 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. 603 // Retrieve private key JNI reference.
633 jobject private_key = reinterpret_cast<jobject>( 604 jobject private_key = EcKeyGetKey(eckey);
634 ECDSA_get_ex_data(eckey, EcdsaGetExDataIndex()));
635 if (!private_key) { 605 if (!private_key) {
636 LOG(WARNING) << "Null JNI reference passed to EcdsaMethodDoSign!"; 606 LOG(WARNING) << "Null JNI reference passed to EcdsaMethodSign!";
637 return NULL; 607 return 0;
638 } 608 }
639 // Sign message with it through JNI. 609 // Sign message with it through JNI.
640 std::vector<uint8> signature; 610 std::vector<uint8> signature;
641 base::StringPiece digest( 611 base::StringPiece digest_sp(reinterpret_cast<const char*>(digest),
642 reinterpret_cast<const char*>(dgst), 612 digest_len);
643 static_cast<size_t>(dgst_len)); 613 if (!RawSignDigestWithPrivateKey(private_key, digest_sp, &signature)) {
644 if (!RawSignDigestWithPrivateKey( 614 LOG(WARNING) << "Could not sign message in EcdsaMethodSign!";
645 private_key, digest, &signature)) { 615 return 0;
646 LOG(WARNING) << "Could not sign message in EcdsaMethodDoSign!";
647 return NULL;
648 } 616 }
649 617
650 // Note: With ECDSA, the actual signature may be smaller than 618 // Note: With ECDSA, the actual signature may be smaller than
651 // ECDSA_size(). 619 // ECDSA_size().
652 size_t max_expected_size = static_cast<size_t>(ECDSA_size(eckey)); 620 size_t max_expected_size = ECDSA_size(eckey);
653 if (signature.size() > max_expected_size) { 621 if (signature.size() > max_expected_size) {
654 LOG(ERROR) << "ECDSA Signature size mismatch, actual: " 622 LOG(ERROR) << "ECDSA Signature size mismatch, actual: "
655 << signature.size() << ", expected <= " 623 << signature.size() << ", expected <= "
656 << max_expected_size; 624 << max_expected_size;
657 return NULL; 625 return 0;
658 } 626 }
659 627
660 // Convert signature to ECDSA_SIG object 628 memcpy(sig, &signature[0], signature.size());
661 const unsigned char* sigbuf = 629 *sig_len = signature.size();
662 reinterpret_cast<const unsigned char*>(&signature[0]); 630 return 1;
663 long siglen = static_cast<long>(signature.size());
664 return d2i_ECDSA_SIG(NULL, &sigbuf, siglen);
665 } 631 }
666 632
667 int EcdsaMethodSignSetup(EC_KEY* eckey, 633 int EcdsaMethodVerify(const uint8_t* digest,
668 BN_CTX* ctx, 634 size_t digest_len,
669 BIGNUM** kinv, 635 const uint8_t* sig,
670 BIGNUM** r) { 636 size_t sig_len,
637 EC_KEY* eckey) {
671 NOTIMPLEMENTED(); 638 NOTIMPLEMENTED();
672 ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ECDSA_R_ERR_EC_LIB); 639 OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ECDSA_R_NOT_IMPLEMENTED);
673 return -1; 640 return 0;
674 } 641 }
675 642
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. 643 // Setup an EVP_PKEY to wrap an existing platform PrivateKey object.
695 // |private_key| is the JNI reference (local or global) to the object. 644 // |private_key| is the JNI reference (local or global) to the object.
696 // |pkey| is the EVP_PKEY to setup as a wrapper. 645 // |pkey| is the EVP_PKEY to setup as a wrapper.
697 // Returns true on success, false otherwise. 646 // Returns true on success, false otherwise.
698 // On success, this creates a global JNI reference to the object that 647 // 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 648 // is owned by and destroyed with the EVP_PKEY. I.e. the caller shall
700 // always free |private_key| after the call. 649 // always free |private_key| after the call.
701 bool GetEcdsaPkeyWrapper(jobject private_key, EVP_PKEY* pkey) { 650 bool GetEcdsaPkeyWrapper(jobject private_key, EVP_PKEY* pkey) {
702 crypto::ScopedEC_KEY eckey(EC_KEY_new()); 651 crypto::ScopedEC_KEY eckey(
703 ECDSA_set_method(eckey.get(), &android_ecdsa_method); 652 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 653
723 ScopedJavaGlobalRef<jobject> global_key; 654 ScopedJavaGlobalRef<jobject> global_key;
724 global_key.Reset(NULL, private_key); 655 global_key.Reset(NULL, private_key);
725 if (global_key.is_null()) { 656 if (global_key.is_null()) {
726 LOG(ERROR) << "Can't create global JNI reference"; 657 LOG(ERROR) << "Can't create global JNI reference";
727 return false; 658 return false;
728 } 659 }
729 ECDSA_set_ex_data(eckey.get(), 660
730 EcdsaGetExDataIndex(), 661 KeyExData* ex_data = new KeyExData;
731 global_key.Release()); 662 ex_data->private_key = global_key.Release();
663 ex_data->legacy_rsa = NULL;
664
665 EC_KEY_set_ex_data(
666 eckey.get(), global_boringssl_engine.Get().ec_key_ex_index(), ex_data);
732 667
733 EVP_PKEY_assign_EC_KEY(pkey, eckey.release()); 668 EVP_PKEY_assign_EC_KEY(pkey, eckey.release());
734 return true; 669 return true;
735 } 670 }
736 671
672 const ECDSA_METHOD android_ecdsa_method = {
673 {
674 0 /* references */,
675 1 /* is_static */
676 } /* common */,
677 NULL /* app_data */,
678
679 NULL /* init */,
680 NULL /* finish */,
681 EcdsaMethodSize,
682 EcdsaMethodSign,
683 EcdsaMethodVerify,
684 };
685
737 } // namespace 686 } // namespace
738 687
739 EVP_PKEY* GetOpenSSLPrivateKeyWrapper(jobject private_key) { 688 EVP_PKEY* GetOpenSSLPrivateKeyWrapper(jobject private_key) {
740 // Create new empty EVP_PKEY instance. 689 // Create new empty EVP_PKEY instance.
741 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new()); 690 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new());
742 if (!pkey.get()) 691 if (!pkey.get())
743 return NULL; 692 return NULL;
744 693
745 // Create sub key type, depending on private key's algorithm type. 694 // Create sub key type, depending on private key's algorithm type.
746 PrivateKeyType key_type = GetPrivateKeyType(private_key); 695 PrivateKeyType key_type = GetPrivateKeyType(private_key);
(...skipping 29 matching lines...) Expand all
776 default: 725 default:
777 LOG(WARNING) 726 LOG(WARNING)
778 << "GetOpenSSLPrivateKeyWrapper() called with invalid key type"; 727 << "GetOpenSSLPrivateKeyWrapper() called with invalid key type";
779 return NULL; 728 return NULL;
780 } 729 }
781 return pkey.release(); 730 return pkey.release();
782 } 731 }
783 732
784 } // namespace android 733 } // namespace android
785 } // namespace net 734 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698