blob: 028f40470f38dd75432432fa25bc70192057f3dc [file] [log] [blame]
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001// 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
3// found in the LICENSE file.
4
5#include "net/android/keystore_openssl.h"
6
7#include <jni.h>
8#include <openssl/bn.h>
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009#include <openssl/dsa.h>
10#include <openssl/ec.h>
11#include <openssl/engine.h>
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +010012#include <openssl/err.h>
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000013#include <openssl/evp.h>
14#include <openssl/rsa.h>
15
16#include "base/android/build_info.h"
17#include "base/android/jni_android.h"
18#include "base/android/scoped_java_ref.h"
19#include "base/basictypes.h"
20#include "base/lazy_instance.h"
21#include "base/logging.h"
22#include "crypto/openssl_util.h"
Ben Murdoch116680a2014-07-20 18:25:52 -070023#include "crypto/scoped_openssl_types.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000024#include "net/android/keystore.h"
Ben Murdoch116680a2014-07-20 18:25:52 -070025#include "net/android/legacy_openssl.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000026#include "net/ssl/ssl_client_cert_type.h"
27
28// IMPORTANT NOTE: The following code will currently only work when used
29// to implement client certificate support with OpenSSL. That's because
30// only the signing operations used in this use case are implemented here.
31//
32// Generally speaking, OpenSSL provides many different ways to sign
33// digests. This code doesn't support all these cases, only the ones that
Torne (Richard Coles)d0247b12013-09-19 22:36:51 +010034// are required to sign the digest during the OpenSSL handshake for TLS.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000035//
36// The OpenSSL EVP_PKEY type is a generic wrapper around key pairs.
37// Internally, it can hold a pointer to a RSA, DSA or ECDSA structure,
38// which model keypair implementations of each respective crypto
39// algorithm.
40//
41// The RSA type has a 'method' field pointer to a vtable-like structure
42// called a RSA_METHOD. This contains several function pointers that
43// correspond to operations on RSA keys (e.g. decode/encode with public
44// key, decode/encode with private key, signing, validation), as well as
45// a few flags.
46//
47// 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
49// signing operation using the other fields in the RSA structure (which
50// are used to hold the typical modulus / exponent / parameters for the
51// key pair).
52//
Torne (Richard Coles)58537e22013-09-12 12:10:22 +010053// This source file thus defines a custom RSA_METHOD structure whose
54// fields point to static methods used to implement the corresponding
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000055// RSA operation using platform Android APIs.
56//
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +010057// However, the platform APIs require a jobject JNI reference to work. It must
58// be stored in the RSA instance, or made accessible when the custom RSA
59// methods are called. This is done by storing it in a |KeyExData| structure
60// that's referenced by the key using |EX_DATA|.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000061
62using base::android::ScopedJavaGlobalRef;
Ben Murdoch116680a2014-07-20 18:25:52 -070063using base::android::ScopedJavaLocalRef;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000064
65namespace net {
66namespace android {
67
68namespace {
69
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +010070extern const RSA_METHOD android_rsa_method;
71extern const ECDSA_METHOD android_ecdsa_method;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000072
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +010073// KeyExData contains the data that is contained in the EX_DATA of the RSA, DSA
74// and ECDSA objects that are created to wrap Android system keys.
75struct KeyExData {
76 // private_key contains a reference to a Java, private-key object.
Ben Murdoch116680a2014-07-20 18:25:52 -070077 jobject private_key;
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +010078 // legacy_rsa, if not NULL, points to an RSA* in the system's OpenSSL (which
79 // might not be ABI compatible with Chromium).
Ben Murdoch116680a2014-07-20 18:25:52 -070080 AndroidRSA* legacy_rsa;
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +010081 // 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;
Ben Murdoch116680a2014-07-20 18:25:52 -070085};
86
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +010087// ExDataDup is called when one of the RSA, DSA or EC_KEY objects is
88// duplicated. We don't support this and it should never happen.
89int ExDataDup(CRYPTO_EX_DATA* to,
90 const CRYPTO_EX_DATA* from,
91 void** from_d,
92 int index,
93 long argl,
94 void* argp) {
95 CHECK(false);
96 return 0;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000097}
98
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +010099// ExDataFree is called when one of the RSA, DSA or EC_KEY object is freed.
100void ExDataFree(void* parent,
101 void* ptr,
102 CRYPTO_EX_DATA* ad,
103 int index,
104 long argl,
105 void* argp) {
106 // Ensure the global JNI reference created with this wrapper is
107 // properly destroyed with it.
108 KeyExData *ex_data = reinterpret_cast<KeyExData*>(ptr);
109 if (ex_data != NULL) {
110 ReleaseKey(ex_data->private_key);
111 delete ex_data;
112 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000113}
114
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100115// BoringSSLEngine is a BoringSSL ENGINE that implements RSA, DSA and ECDSA by
116// forwarding the requested operations to the Java libraries.
117class BoringSSLEngine {
118 public:
119 BoringSSLEngine()
120 : rsa_index_(RSA_get_ex_new_index(0 /* argl */,
121 NULL /* argp */,
122 NULL /* new_func */,
123 ExDataDup,
124 ExDataFree)),
125 ec_key_index_(EC_KEY_get_ex_new_index(0 /* argl */,
126 NULL /* argp */,
127 NULL /* new_func */,
128 ExDataDup,
129 ExDataFree)),
130 engine_(ENGINE_new()) {
131 ENGINE_set_RSA_method(
132 engine_, &android_rsa_method, sizeof(android_rsa_method));
133 ENGINE_set_ECDSA_method(
134 engine_, &android_ecdsa_method, sizeof(android_ecdsa_method));
135 }
136
137 int rsa_ex_index() const { return rsa_index_; }
138 int ec_key_ex_index() const { return ec_key_index_; }
139
140 const ENGINE* engine() const { return engine_; }
141
142 private:
143 const int rsa_index_;
144 const int ec_key_index_;
145 ENGINE* const engine_;
146};
147
148base::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.
154size_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
163KeyExData* RsaGetExData(const RSA* rsa) {
164 return reinterpret_cast<KeyExData*>(
165 RSA_get_ex_data(rsa, global_boringssl_engine.Get().rsa_ex_index()));
166}
167
168size_t RsaMethodSize(const RSA *rsa) {
169 const KeyExData *ex_data = RsaGetExData(rsa);
170 return ex_data->cached_size;
171}
172
173int RsaMethodEncrypt(RSA* rsa,
174 size_t* out_len,
175 uint8_t* out,
176 size_t max_out,
177 const uint8_t* in,
178 size_t in_len,
179 int padding) {
180 NOTIMPLEMENTED();
181 OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE);
182 return 0;
183}
184
185int 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,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000191 int padding) {
Torne (Richard Coles)d0247b12013-09-19 22:36:51 +0100192 DCHECK_EQ(RSA_PKCS1_PADDING, padding);
193 if (padding != RSA_PKCS1_PADDING) {
194 // TODO(davidben): If we need to, we can implement RSA_NO_PADDING
195 // by using javax.crypto.Cipher and picking either the
196 // "RSA/ECB/NoPadding" or "RSA/ECB/PKCS1Padding" transformation as
197 // appropriate. I believe support for both of these was added in
198 // the same Android version as the "NONEwithRSA"
199 // java.security.Signature algorithm, so the same version checks
200 // for GetRsaLegacyKey should work.
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100201 OPENSSL_PUT_ERROR(RSA, sign_raw, RSA_R_UNKNOWN_PADDING_TYPE);
202 return 0;
Torne (Richard Coles)d0247b12013-09-19 22:36:51 +0100203 }
204
205 // Retrieve private key JNI reference.
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100206 const KeyExData *ex_data = RsaGetExData(rsa);
207 if (!ex_data || !ex_data->private_key) {
Torne (Richard Coles)d0247b12013-09-19 22:36:51 +0100208 LOG(WARNING) << "Null JNI reference passed to RsaMethodPrivEnc!";
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100209 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
210 return 0;
Torne (Richard Coles)d0247b12013-09-19 22:36:51 +0100211 }
212
Ben Murdoch116680a2014-07-20 18:25:52 -0700213 // Pre-4.2 legacy codepath.
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100214 if (ex_data->legacy_rsa) {
215 int ret = ex_data->legacy_rsa->meth->rsa_priv_enc(
216 in_len, in, out, ex_data->legacy_rsa, ANDROID_RSA_PKCS1_PADDING);
Ben Murdoch116680a2014-07-20 18:25:52 -0700217 if (ret < 0) {
218 LOG(WARNING) << "Could not sign message in RsaMethodPrivEnc!";
219 // System OpenSSL will use a separate error queue, so it is still
220 // necessary to push a new error.
221 //
222 // 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
224 // through Java, it's difficult to get a handle on a system OpenSSL
225 // function; dlopen loads a second copy.)
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100226 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
227 return 0;
Ben Murdoch116680a2014-07-20 18:25:52 -0700228 }
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100229 *out_len = ret;
230 return 1;
Ben Murdoch116680a2014-07-20 18:25:52 -0700231 }
232
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100233 base::StringPiece from_piece(reinterpret_cast<const char*>(in), in_len);
Torne (Richard Coles)d0247b12013-09-19 22:36:51 +0100234 std::vector<uint8> result;
235 // For RSA keys, this function behaves as RSA_private_encrypt with
236 // PKCS#1 padding.
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100237 if (!RawSignDigestWithPrivateKey(ex_data->private_key, from_piece, &result)) {
Torne (Richard Coles)d0247b12013-09-19 22:36:51 +0100238 LOG(WARNING) << "Could not sign message in RsaMethodPrivEnc!";
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100239 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
240 return 0;
Torne (Richard Coles)d0247b12013-09-19 22:36:51 +0100241 }
242
243 size_t expected_size = static_cast<size_t>(RSA_size(rsa));
244 if (result.size() > expected_size) {
245 LOG(ERROR) << "RSA Signature size mismatch, actual: "
246 << result.size() << ", expected <= " << expected_size;
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100247 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
248 return 0;
249 }
250
251 if (max_out < expected_size) {
252 OPENSSL_PUT_ERROR(RSA, sign_raw, RSA_R_DATA_TOO_LARGE);
253 return 0;
Torne (Richard Coles)d0247b12013-09-19 22:36:51 +0100254 }
255
256 // Copy result to OpenSSL-provided buffer. RawSignDigestWithPrivateKey
257 // should pad with leading 0s, but if it doesn't, pad the result.
258 size_t zero_pad = expected_size - result.size();
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100259 memset(out, 0, zero_pad);
260 memcpy(out + zero_pad, &result[0], result.size());
261 *out_len = expected_size;
Torne (Richard Coles)d0247b12013-09-19 22:36:51 +0100262
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100263 return 1;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000264}
265
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100266int RsaMethodDecrypt(RSA* rsa,
267 size_t* out_len,
268 uint8_t* out,
269 size_t max_out,
270 const uint8_t* in,
271 size_t in_len,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000272 int padding) {
273 NOTIMPLEMENTED();
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100274 OPENSSL_PUT_ERROR(RSA, decrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000275 return 0;
276}
277
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100278int RsaMethodVerifyRaw(RSA* rsa,
279 size_t* out_len,
280 uint8_t* out,
281 size_t max_out,
282 const uint8_t* in,
283 size_t in_len,
284 int padding) {
285 NOTIMPLEMENTED();
286 OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_UNKNOWN_ALGORITHM_TYPE);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000287 return 0;
288}
289
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000290const RSA_METHOD android_rsa_method = {
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100291 {
292 0 /* references */,
293 1 /* is_static */
294 } /* common */,
295 NULL /* app_data */,
296
297 NULL /* init */,
298 NULL /* finish */,
299 RsaMethodSize,
300 NULL /* sign */,
301 NULL /* verify */,
302 RsaMethodEncrypt,
303 RsaMethodSignRaw,
304 RsaMethodDecrypt,
305 RsaMethodVerifyRaw,
Torne (Richard Coles)03b57e02014-08-28 12:05:23 +0100306 NULL /* private_transform */,
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100307 NULL /* mod_exp */,
308 NULL /* bn_mod_exp */,
309 RSA_FLAG_OPAQUE,
310 NULL /* keygen */,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000311};
312
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000313// Setup an EVP_PKEY to wrap an existing platform RSA PrivateKey object.
314// |private_key| is the JNI reference (local or global) to the object.
Ben Murdoch116680a2014-07-20 18:25:52 -0700315// |legacy_rsa|, if non-NULL, is a pointer to the system OpenSSL RSA object
316// backing |private_key|. This parameter is only used for Android < 4.2 to
317// implement key operations not exposed by the platform.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000318// |pkey| is the EVP_PKEY to setup as a wrapper.
319// Returns true on success, false otherwise.
320// On success, this creates a new global JNI reference to the object
321// that is owned by and destroyed with the EVP_PKEY. I.e. caller can
322// free |private_key| after the call.
Ben Murdoch116680a2014-07-20 18:25:52 -0700323bool GetRsaPkeyWrapper(jobject private_key,
324 AndroidRSA* legacy_rsa,
325 EVP_PKEY* pkey) {
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100326 crypto::ScopedRSA rsa(
327 RSA_new_method(global_boringssl_engine.Get().engine()));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000328
329 ScopedJavaGlobalRef<jobject> global_key;
330 global_key.Reset(NULL, private_key);
331 if (global_key.is_null()) {
332 LOG(ERROR) << "Could not create global JNI reference";
333 return false;
334 }
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100335
336 std::vector<uint8> modulus;
337 if (!GetRSAKeyModulus(private_key, &modulus)) {
338 LOG(ERROR) << "Failed to get private key modulus";
339 return false;
340 }
341
342 KeyExData* ex_data = new KeyExData;
343 ex_data->private_key = global_key.Release();
344 ex_data->legacy_rsa = legacy_rsa;
345 ex_data->cached_size = VectorBignumSize(modulus);
346 RSA_set_ex_data(
347 rsa.get(), global_boringssl_engine.Get().rsa_ex_index(), ex_data);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000348 EVP_PKEY_assign_RSA(pkey, rsa.release());
349 return true;
350}
351
Torne (Richard Coles)6d86b772014-06-25 10:30:53 +0100352// On Android < 4.2, the libkeystore.so ENGINE uses CRYPTO_EX_DATA and is not
353// added to the global engine list. If all references to it are dropped, OpenSSL
354// will dlclose the module, leaving a dangling function pointer in the RSA
355// CRYPTO_EX_DATA class. To work around this, leak an extra reference to the
356// ENGINE we extract in GetRsaLegacyKey.
357//
358// In 4.2, this change avoids the problem:
359// https://android.googlesource.com/platform/libcore/+/106a8928fb4249f2f3d4dba1dddbe73ca5cb3d61
360//
361// https://crbug.com/381465
362class KeystoreEngineWorkaround {
363 public:
Ben Murdoch116680a2014-07-20 18:25:52 -0700364 KeystoreEngineWorkaround() {}
Torne (Richard Coles)6d86b772014-06-25 10:30:53 +0100365
Ben Murdoch116680a2014-07-20 18:25:52 -0700366 void LeakEngine(jobject private_key) {
367 if (!engine_.is_null())
Torne (Richard Coles)6d86b772014-06-25 10:30:53 +0100368 return;
Ben Murdoch116680a2014-07-20 18:25:52 -0700369 ScopedJavaLocalRef<jobject> engine =
370 GetOpenSSLEngineForPrivateKey(private_key);
371 if (engine.is_null()) {
Torne (Richard Coles)6d86b772014-06-25 10:30:53 +0100372 NOTREACHED();
373 return;
374 }
Ben Murdoch116680a2014-07-20 18:25:52 -0700375 engine_.Reset(engine);
Torne (Richard Coles)6d86b772014-06-25 10:30:53 +0100376 }
377
378 private:
Ben Murdoch116680a2014-07-20 18:25:52 -0700379 ScopedJavaGlobalRef<jobject> engine_;
Torne (Richard Coles)6d86b772014-06-25 10:30:53 +0100380};
381
Ben Murdoch116680a2014-07-20 18:25:52 -0700382void LeakEngine(jobject private_key) {
Torne (Richard Coles)6d86b772014-06-25 10:30:53 +0100383 static base::LazyInstance<KeystoreEngineWorkaround>::Leaky s_instance =
384 LAZY_INSTANCE_INITIALIZER;
Ben Murdoch116680a2014-07-20 18:25:52 -0700385 s_instance.Get().LeakEngine(private_key);
Torne (Richard Coles)6d86b772014-06-25 10:30:53 +0100386}
387
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000388// Setup an EVP_PKEY to wrap an existing platform RSA PrivateKey object
389// for Android 4.0 to 4.1.x. Must only be used on Android < 4.2.
390// |private_key| is a JNI reference (local or global) to the object.
391// |pkey| is the EVP_PKEY to setup as a wrapper.
392// Returns true on success, false otherwise.
393EVP_PKEY* GetRsaLegacyKey(jobject private_key) {
Ben Murdoch116680a2014-07-20 18:25:52 -0700394 AndroidEVP_PKEY* sys_pkey =
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000395 GetOpenSSLSystemHandleForPrivateKey(private_key);
396 if (sys_pkey != NULL) {
Ben Murdoch116680a2014-07-20 18:25:52 -0700397 if (sys_pkey->type != ANDROID_EVP_PKEY_RSA) {
398 LOG(ERROR) << "Private key has wrong type!";
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000399 return NULL;
400 }
Ben Murdoch116680a2014-07-20 18:25:52 -0700401
402 AndroidRSA* sys_rsa = sys_pkey->pkey.rsa;
403 if (sys_rsa->engine) {
404 // |private_key| may not have an engine if the PrivateKey did not come
405 // from the key store, such as in unit tests.
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100406 if (strcmp(sys_rsa->engine->id, "keystore") == 0) {
Ben Murdoch116680a2014-07-20 18:25:52 -0700407 LeakEngine(private_key);
408 } else {
409 NOTREACHED();
410 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000411 }
Ben Murdoch116680a2014-07-20 18:25:52 -0700412
413 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new());
414 if (!GetRsaPkeyWrapper(private_key, sys_rsa, pkey.get()))
415 return NULL;
416 return pkey.release();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000417 }
Ben Murdoch116680a2014-07-20 18:25:52 -0700418
419 // GetOpenSSLSystemHandleForPrivateKey() will fail on Android 4.0.3 and
420 // earlier. However, it is possible to get the key content with
421 // PrivateKey.getEncoded() on these platforms. Note that this method may
422 // return NULL on 4.0.4 and later.
423 std::vector<uint8> encoded;
424 if (!GetPrivateKeyEncodedBytes(private_key, &encoded)) {
425 LOG(ERROR) << "Can't get private key data!";
426 return NULL;
427 }
428 const unsigned char* p =
429 reinterpret_cast<const unsigned char*>(&encoded[0]);
430 int len = static_cast<int>(encoded.size());
431 EVP_PKEY* pkey = d2i_AutoPrivateKey(NULL, &p, len);
432 if (pkey == NULL) {
433 LOG(ERROR) << "Can't convert private key data!";
434 return NULL;
435 }
436 return pkey;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000437}
438
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000439// Custom ECDSA_METHOD that uses the platform APIs.
440// Note that for now, only signing through ECDSA_sign() is really supported.
441// all other method pointers are either stubs returning errors, or no-ops.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000442
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100443jobject EcKeyGetKey(const EC_KEY* ec_key) {
444 KeyExData* ex_data = reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data(
445 ec_key, global_boringssl_engine.Get().ec_key_ex_index()));
446 return ex_data->private_key;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000447}
448
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100449size_t EcdsaMethodGroupOrderSize(const EC_KEY* ec_key) {
450 KeyExData* ex_data = reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data(
451 ec_key, global_boringssl_engine.Get().ec_key_ex_index()));
452 return ex_data->cached_size;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000453}
454
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100455int EcdsaMethodSign(const uint8_t* digest,
456 size_t digest_len,
457 uint8_t* sig,
458 unsigned int* sig_len,
459 EC_KEY* ec_key) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000460 // Retrieve private key JNI reference.
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100461 jobject private_key = EcKeyGetKey(ec_key);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000462 if (!private_key) {
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100463 LOG(WARNING) << "Null JNI reference passed to EcdsaMethodSign!";
464 return 0;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000465 }
466 // Sign message with it through JNI.
467 std::vector<uint8> signature;
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100468 base::StringPiece digest_sp(reinterpret_cast<const char*>(digest),
469 digest_len);
470 if (!RawSignDigestWithPrivateKey(private_key, digest_sp, &signature)) {
471 LOG(WARNING) << "Could not sign message in EcdsaMethodSign!";
472 return 0;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000473 }
474
475 // Note: With ECDSA, the actual signature may be smaller than
476 // ECDSA_size().
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100477 size_t max_expected_size = ECDSA_size(ec_key);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000478 if (signature.size() > max_expected_size) {
479 LOG(ERROR) << "ECDSA Signature size mismatch, actual: "
480 << signature.size() << ", expected <= "
481 << max_expected_size;
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100482 return 0;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000483 }
484
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100485 memcpy(sig, &signature[0], signature.size());
486 *sig_len = signature.size();
487 return 1;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000488}
489
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100490int EcdsaMethodVerify(const uint8_t* digest,
491 size_t digest_len,
492 const uint8_t* sig,
493 size_t sig_len,
494 EC_KEY* ec_key) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000495 NOTIMPLEMENTED();
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100496 OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ECDSA_R_NOT_IMPLEMENTED);
497 return 0;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000498}
499
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000500// Setup an EVP_PKEY to wrap an existing platform PrivateKey object.
501// |private_key| is the JNI reference (local or global) to the object.
502// |pkey| is the EVP_PKEY to setup as a wrapper.
503// Returns true on success, false otherwise.
504// On success, this creates a global JNI reference to the object that
505// is owned by and destroyed with the EVP_PKEY. I.e. the caller shall
506// always free |private_key| after the call.
507bool GetEcdsaPkeyWrapper(jobject private_key, EVP_PKEY* pkey) {
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100508 crypto::ScopedEC_KEY ec_key(
509 EC_KEY_new_method(global_boringssl_engine.Get().engine()));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000510
511 ScopedJavaGlobalRef<jobject> global_key;
512 global_key.Reset(NULL, private_key);
513 if (global_key.is_null()) {
514 LOG(ERROR) << "Can't create global JNI reference";
515 return false;
516 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000517
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100518 std::vector<uint8> order;
519 if (!GetECKeyOrder(private_key, &order)) {
520 LOG(ERROR) << "Can't extract order parameter from EC private key";
521 return false;
522 }
523
524 KeyExData* ex_data = new KeyExData;
525 ex_data->private_key = global_key.Release();
526 ex_data->legacy_rsa = NULL;
527 ex_data->cached_size = VectorBignumSize(order);
528
529 EC_KEY_set_ex_data(
530 ec_key.get(), global_boringssl_engine.Get().ec_key_ex_index(), ex_data);
531
532 EVP_PKEY_assign_EC_KEY(pkey, ec_key.release());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000533 return true;
534}
535
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100536const ECDSA_METHOD android_ecdsa_method = {
537 {
538 0 /* references */,
539 1 /* is_static */
540 } /* common */,
541 NULL /* app_data */,
542
543 NULL /* init */,
544 NULL /* finish */,
545 EcdsaMethodGroupOrderSize,
546 EcdsaMethodSign,
547 EcdsaMethodVerify,
548 ECDSA_FLAG_OPAQUE,
549};
550
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000551} // namespace
552
553EVP_PKEY* GetOpenSSLPrivateKeyWrapper(jobject private_key) {
554 // Create new empty EVP_PKEY instance.
Ben Murdoch116680a2014-07-20 18:25:52 -0700555 crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000556 if (!pkey.get())
557 return NULL;
558
559 // Create sub key type, depending on private key's algorithm type.
560 PrivateKeyType key_type = GetPrivateKeyType(private_key);
561 switch (key_type) {
562 case PRIVATE_KEY_TYPE_RSA:
563 {
564 // Route around platform bug: if Android < 4.2, then
565 // base::android::RawSignDigestWithPrivateKey() cannot work, so
566 // instead, obtain a raw EVP_PKEY* to the system object
567 // backing this PrivateKey object.
568 const int kAndroid42ApiLevel = 17;
569 if (base::android::BuildInfo::GetInstance()->sdk_int() <
570 kAndroid42ApiLevel) {
571 EVP_PKEY* legacy_key = GetRsaLegacyKey(private_key);
572 if (legacy_key == NULL)
573 return NULL;
574 pkey.reset(legacy_key);
575 } else {
576 // Running on Android 4.2.
Ben Murdoch116680a2014-07-20 18:25:52 -0700577 if (!GetRsaPkeyWrapper(private_key, NULL, pkey.get()))
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000578 return NULL;
579 }
580 }
581 break;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000582 case PRIVATE_KEY_TYPE_ECDSA:
583 if (!GetEcdsaPkeyWrapper(private_key, pkey.get()))
584 return NULL;
585 break;
586 default:
587 LOG(WARNING)
588 << "GetOpenSSLPrivateKeyWrapper() called with invalid key type";
589 return NULL;
590 }
591 return pkey.release();
592}
593
594} // namespace android
595} // namespace net