OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |