blob: 629587365c00ade928eff50c55306597efcd43d7 [file] [log] [blame]
Adam Langley1fb05832014-09-23 17:42:36 -07001/* Copyright 2014 The Android Open Source Project
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions
5 * are met:
6 * 1. Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * 2. Redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution.
11 *
12 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
13 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
16 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
19 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
21 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
22
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +010023#define LOG_TAG "keystore-engine"
24
Adam Langley1fb05832014-09-23 17:42:36 -070025#include <UniquePtr.h>
26
27#include <sys/socket.h>
28#include <stdarg.h>
29#include <string.h>
30#include <unistd.h>
31
32#include <openssl/bn.h>
33#include <openssl/ec.h>
34#include <openssl/ec_key.h>
35#include <openssl/ecdsa.h>
36#include <openssl/engine.h>
37#include <openssl/evp.h>
38#include <openssl/rsa.h>
39#include <openssl/x509.h>
40
41#include <binder/IServiceManager.h>
42#include <keystore/keystore.h>
43#include <keystore/IKeystoreService.h>
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +010044#include <keystore/keystore_hidl_support.h>
Adam Langley1fb05832014-09-23 17:42:36 -070045
46using namespace android;
47
48namespace {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +010049using namespace keystore;
Adam Langley1fb05832014-09-23 17:42:36 -070050
51extern const RSA_METHOD keystore_rsa_method;
52extern const ECDSA_METHOD keystore_ecdsa_method;
53
54/* key_id_dup is called when one of the RSA or EC_KEY objects is duplicated. */
Kenny Rootdcca0512015-04-18 11:21:48 -070055int key_id_dup(CRYPTO_EX_DATA* /* to */,
56 const CRYPTO_EX_DATA* /* from */,
Adam Langley1fb05832014-09-23 17:42:36 -070057 void** from_d,
Kenny Rootdcca0512015-04-18 11:21:48 -070058 int /* index */,
59 long /* argl */,
60 void* /* argp */) {
Adam Langley1fb05832014-09-23 17:42:36 -070061 char *key_id = reinterpret_cast<char *>(*from_d);
62 if (key_id != NULL) {
63 *from_d = strdup(key_id);
64 }
65 return 1;
66}
67
68/* key_id_free is called when one of the RSA, DSA or EC_KEY object is freed. */
Kenny Rootdcca0512015-04-18 11:21:48 -070069void key_id_free(void* /* parent */,
Adam Langley1fb05832014-09-23 17:42:36 -070070 void* ptr,
Kenny Rootdcca0512015-04-18 11:21:48 -070071 CRYPTO_EX_DATA* /* ad */,
72 int /* index */,
73 long /* argl */,
74 void* /* argp */) {
Adam Langley1fb05832014-09-23 17:42:36 -070075 char *key_id = reinterpret_cast<char *>(ptr);
76 free(key_id);
77}
78
79/* KeystoreEngine is a BoringSSL ENGINE that implements RSA and ECDSA by
80 * forwarding the requested operations to Keystore. */
81class KeystoreEngine {
82 public:
83 KeystoreEngine()
84 : rsa_index_(RSA_get_ex_new_index(0 /* argl */,
85 NULL /* argp */,
86 NULL /* new_func */,
87 key_id_dup,
88 key_id_free)),
89 ec_key_index_(EC_KEY_get_ex_new_index(0 /* argl */,
90 NULL /* argp */,
91 NULL /* new_func */,
92 key_id_dup,
93 key_id_free)),
94 engine_(ENGINE_new()) {
95 ENGINE_set_RSA_method(
96 engine_, &keystore_rsa_method, sizeof(keystore_rsa_method));
97 ENGINE_set_ECDSA_method(
98 engine_, &keystore_ecdsa_method, sizeof(keystore_ecdsa_method));
99 }
100
101 int rsa_ex_index() const { return rsa_index_; }
102 int ec_key_ex_index() const { return ec_key_index_; }
103
104 const ENGINE* engine() const { return engine_; }
105
106 private:
107 const int rsa_index_;
108 const int ec_key_index_;
109 ENGINE* const engine_;
110};
111
112pthread_once_t g_keystore_engine_once = PTHREAD_ONCE_INIT;
113KeystoreEngine *g_keystore_engine;
114
115/* init_keystore_engine is called to initialize |g_keystore_engine|. This
116 * should only be called by |pthread_once|. */
117void init_keystore_engine() {
118 g_keystore_engine = new KeystoreEngine;
119}
120
121/* ensure_keystore_engine ensures that |g_keystore_engine| is pointing to a
122 * valid |KeystoreEngine| object and creates one if not. */
123void ensure_keystore_engine() {
124 pthread_once(&g_keystore_engine_once, init_keystore_engine);
125}
126
127/* Many OpenSSL APIs take ownership of an argument on success but don't free
128 * the argument on failure. This means we need to tell our scoped pointers when
129 * we've transferred ownership, without triggering a warning by not using the
130 * result of release(). */
131#define OWNERSHIP_TRANSFERRED(obj) \
Chih-Hung Hsieh26275ad2016-05-11 14:26:35 -0700132 typeof ((obj).release()) _dummy __attribute__((unused)) = (obj).release()
Adam Langley1fb05832014-09-23 17:42:36 -0700133
134const char* rsa_get_key_id(const RSA* rsa) {
135 return reinterpret_cast<char*>(
136 RSA_get_ex_data(rsa, g_keystore_engine->rsa_ex_index()));
137}
138
139/* rsa_private_transform takes a big-endian integer from |in|, calculates the
140 * d'th power of it, modulo the RSA modulus, and writes the result as a
141 * big-endian integer to |out|. Both |in| and |out| are |len| bytes long. It
142 * returns one on success and zero otherwise. */
143int rsa_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in, size_t len) {
144 ALOGV("rsa_private_transform(%p, %p, %p, %u)", rsa, out, in, (unsigned) len);
145
146 const char *key_id = rsa_get_key_id(rsa);
147 if (key_id == NULL) {
148 ALOGE("key had no key_id!");
149 return 0;
150 }
151
152 sp<IServiceManager> sm = defaultServiceManager();
153 sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
154 sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
155
156 if (service == NULL) {
157 ALOGE("could not contact keystore");
158 return 0;
159 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100160 auto inBlob = blob2hidlVec(in ,len);
161 hidl_vec<uint8_t> reply;
Adam Langley1fb05832014-09-23 17:42:36 -0700162
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100163 auto ret = service->sign(String16(key_id), inBlob, &reply);
164 if (!ret.isOk()) {
165 ALOGW("Error during sign from keystore: %d", int32_t(ret));
Adam Langley1fb05832014-09-23 17:42:36 -0700166 return 0;
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100167 } else if (reply.size() == 0) {
Adam Langley1fb05832014-09-23 17:42:36 -0700168 ALOGW("No valid signature returned");
Adam Langley1fb05832014-09-23 17:42:36 -0700169 return 0;
170 }
171
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100172 if (reply.size() > len) {
Adam Langley1fb05832014-09-23 17:42:36 -0700173 /* The result of the RSA operation can never be larger than the size of
174 * the modulus so we assume that the result has extra zeros on the
175 * left. This provides attackers with an oracle, but there's nothing
176 * that we can do about it here. */
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100177 memcpy(out, &reply[reply.size() - len], len);
178 } else if (reply.size() < len) {
Adam Langley1fb05832014-09-23 17:42:36 -0700179 /* If the Keystore implementation returns a short value we assume that
180 * it's because it removed leading zeros from the left side. This is
181 * bad because it provides attackers with an oracle but we cannot do
182 * anything about a broken Keystore implementation here. */
183 memset(out, 0, len);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100184 memcpy(out + len - reply.size(), &reply[0], reply.size());
Adam Langley1fb05832014-09-23 17:42:36 -0700185 } else {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100186 memcpy(out, &reply[0], len);
Adam Langley1fb05832014-09-23 17:42:36 -0700187 }
188
Adam Langley1fb05832014-09-23 17:42:36 -0700189 ALOGV("rsa=%p keystore_rsa_priv_dec successful", rsa);
190 return 1;
191}
192
193const struct rsa_meth_st keystore_rsa_method = {
194 {
195 0 /* references */,
196 1 /* is_static */,
197 },
198 NULL /* app_data */,
199
200 NULL /* init */,
201 NULL /* finish */,
202
203 NULL /* size */,
204
205 NULL /* sign */,
206 NULL /* verify */,
207
208 NULL /* encrypt */,
209 NULL /* sign_raw */,
210 NULL /* decrypt */,
211 NULL /* verify_raw */,
212
213 rsa_private_transform,
214
215 NULL /* mod_exp */,
216 NULL /* bn_mod_exp */,
217
David Benjamin30c77522016-03-28 18:00:17 -0400218 RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_OPAQUE,
Adam Langley1fb05832014-09-23 17:42:36 -0700219
220 NULL /* keygen */,
Adam Langley9eb92952015-09-02 15:28:03 -0700221 NULL /* multi_prime_keygen */,
Adam Langleyb2747fe2014-12-11 17:19:31 -0800222 NULL /* supports_digest */,
Adam Langley1fb05832014-09-23 17:42:36 -0700223};
224
225const char* ecdsa_get_key_id(const EC_KEY* ec_key) {
226 return reinterpret_cast<char*>(
227 EC_KEY_get_ex_data(ec_key, g_keystore_engine->ec_key_ex_index()));
228}
229
230/* ecdsa_sign signs |digest_len| bytes from |digest| with |ec_key| and writes
231 * the resulting signature (an ASN.1 encoded blob) to |sig|. It returns one on
232 * success and zero otherwise. */
233static int ecdsa_sign(const uint8_t* digest, size_t digest_len, uint8_t* sig,
234 unsigned int* sig_len, EC_KEY* ec_key) {
235 ALOGV("ecdsa_sign(%p, %u, %p)", digest, (unsigned) digest_len, ec_key);
236
237 const char *key_id = ecdsa_get_key_id(ec_key);
238 if (key_id == NULL) {
239 ALOGE("key had no key_id!");
240 return 0;
241 }
242
243 sp<IServiceManager> sm = defaultServiceManager();
244 sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
245 sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
246
247 if (service == NULL) {
248 ALOGE("could not contact keystore");
249 return 0;
250 }
251
252 size_t ecdsa_size = ECDSA_size(ec_key);
253
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100254 auto hidlDigest = blob2hidlVec(digest, digest_len);
255 hidl_vec<uint8_t> reply;
256 auto ret = service->sign(String16(reinterpret_cast<const char*>(key_id)),
257 hidlDigest, &reply);
258 if (!ret.isOk()) {
259 ALOGW("Error during sign from keystore: %d", int32_t(ret));
Adam Langley1fb05832014-09-23 17:42:36 -0700260 return 0;
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100261 } else if (reply.size() == 0) {
Adam Langley1fb05832014-09-23 17:42:36 -0700262 ALOGW("No valid signature returned");
Adam Langley1fb05832014-09-23 17:42:36 -0700263 return 0;
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100264 } else if (reply.size() > ecdsa_size) {
Adam Langley1fb05832014-09-23 17:42:36 -0700265 ALOGW("Signature is too large");
Adam Langley1fb05832014-09-23 17:42:36 -0700266 return 0;
267 }
268
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100269 // Reviewer: should't sig_len be checked here? Or is it just assumed that it is at least ecdsa_size?
270 memcpy(sig, &reply[0], reply.size());
271 *sig_len = reply.size();
Adam Langley1fb05832014-09-23 17:42:36 -0700272
273 ALOGV("ecdsa_sign(%p, %u, %p) => success", digest, (unsigned)digest_len,
274 ec_key);
275 return 1;
276}
277
278const ECDSA_METHOD keystore_ecdsa_method = {
279 {
280 0 /* references */,
281 1 /* is_static */
282 } /* common */,
283 NULL /* app_data */,
284
285 NULL /* init */,
286 NULL /* finish */,
287 NULL /* group_order_size */,
288 ecdsa_sign,
289 NULL /* verify */,
290 ECDSA_FLAG_OPAQUE,
291};
292
293struct EVP_PKEY_Delete {
294 void operator()(EVP_PKEY* p) const {
295 EVP_PKEY_free(p);
296 }
297};
298typedef UniquePtr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY;
299
300struct RSA_Delete {
301 void operator()(RSA* p) const {
302 RSA_free(p);
303 }
304};
305typedef UniquePtr<RSA, RSA_Delete> Unique_RSA;
306
307struct EC_KEY_Delete {
308 void operator()(EC_KEY* ec) const {
309 EC_KEY_free(ec);
310 }
311};
312typedef UniquePtr<EC_KEY, EC_KEY_Delete> Unique_EC_KEY;
313
314/* wrap_rsa returns an |EVP_PKEY| that contains an RSA key where the public
315 * part is taken from |public_rsa| and the private operations are forwarded to
316 * KeyStore and operate on the key named |key_id|. */
317static EVP_PKEY *wrap_rsa(const char *key_id, const RSA *public_rsa) {
318 Unique_RSA rsa(RSA_new_method(g_keystore_engine->engine()));
319 if (rsa.get() == NULL) {
320 return NULL;
321 }
322
323 char *key_id_copy = strdup(key_id);
324 if (key_id_copy == NULL) {
325 return NULL;
326 }
327
328 if (!RSA_set_ex_data(rsa.get(), g_keystore_engine->rsa_ex_index(),
329 key_id_copy)) {
330 free(key_id_copy);
331 return NULL;
332 }
333
334 rsa->n = BN_dup(public_rsa->n);
335 rsa->e = BN_dup(public_rsa->e);
336 if (rsa->n == NULL || rsa->e == NULL) {
337 return NULL;
338 }
339
340 Unique_EVP_PKEY result(EVP_PKEY_new());
341 if (result.get() == NULL ||
342 !EVP_PKEY_assign_RSA(result.get(), rsa.get())) {
343 return NULL;
344 }
345 OWNERSHIP_TRANSFERRED(rsa);
346
347 return result.release();
348}
349
350/* wrap_ecdsa returns an |EVP_PKEY| that contains an ECDSA key where the public
351 * part is taken from |public_rsa| and the private operations are forwarded to
352 * KeyStore and operate on the key named |key_id|. */
353static EVP_PKEY *wrap_ecdsa(const char *key_id, const EC_KEY *public_ecdsa) {
354 Unique_EC_KEY ec(EC_KEY_new_method(g_keystore_engine->engine()));
355 if (ec.get() == NULL) {
356 return NULL;
357 }
358
359 if (!EC_KEY_set_group(ec.get(), EC_KEY_get0_group(public_ecdsa)) ||
360 !EC_KEY_set_public_key(ec.get(), EC_KEY_get0_public_key(public_ecdsa))) {
361 return NULL;
362 }
363
364 char *key_id_copy = strdup(key_id);
365 if (key_id_copy == NULL) {
366 return NULL;
367 }
368
369 if (!EC_KEY_set_ex_data(ec.get(), g_keystore_engine->ec_key_ex_index(),
370 key_id_copy)) {
371 free(key_id_copy);
372 return NULL;
373 }
374
375 Unique_EVP_PKEY result(EVP_PKEY_new());
376 if (result.get() == NULL ||
377 !EVP_PKEY_assign_EC_KEY(result.get(), ec.get())) {
378 return NULL;
379 }
380 OWNERSHIP_TRANSFERRED(ec);
381
382 return result.release();
383}
384
385} /* anonymous namespace */
386
387extern "C" {
388
389EVP_PKEY* EVP_PKEY_from_keystore(const char* key_id) __attribute__((visibility("default")));
390
391/* EVP_PKEY_from_keystore returns an |EVP_PKEY| that contains either an RSA or
392 * ECDSA key where the public part of the key reflects the value of the key
393 * named |key_id| in Keystore and the private operations are forwarded onto
394 * KeyStore. */
395EVP_PKEY* EVP_PKEY_from_keystore(const char* key_id) {
396 ALOGV("EVP_PKEY_from_keystore(\"%s\")", key_id);
397
398 sp<IServiceManager> sm = defaultServiceManager();
399 sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
400 sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
401
402 if (service == NULL) {
403 ALOGE("could not contact keystore");
404 return 0;
405 }
406
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100407 hidl_vec<uint8_t> pubkey;
408 auto ret = service->get_pubkey(String16(key_id), &pubkey);
409 if (!ret.isOk()) {
410 ALOGW("keystore reports error: %d", int32_t(ret));
Adam Langley1fb05832014-09-23 17:42:36 -0700411 return NULL;
412 }
413
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100414 const uint8_t *inp = &pubkey[0];
415 Unique_EVP_PKEY pkey(d2i_PUBKEY(NULL, &inp, pubkey.size()));
Adam Langley1fb05832014-09-23 17:42:36 -0700416 if (pkey.get() == NULL) {
417 ALOGW("Cannot convert pubkey");
418 return NULL;
419 }
420
421 ensure_keystore_engine();
422
423 EVP_PKEY *result;
424 switch (EVP_PKEY_type(pkey->type)) {
425 case EVP_PKEY_RSA: {
426 Unique_RSA public_rsa(EVP_PKEY_get1_RSA(pkey.get()));
427 result = wrap_rsa(key_id, public_rsa.get());
428 break;
429 }
430 case EVP_PKEY_EC: {
431 Unique_EC_KEY public_ecdsa(EVP_PKEY_get1_EC_KEY(pkey.get()));
432 result = wrap_ecdsa(key_id, public_ecdsa.get());
433 break;
434 }
435 default:
436 ALOGE("Unsupported key type %d", EVP_PKEY_type(pkey->type));
437 result = NULL;
438 }
439
440 return result;
441}
442
443} // extern "C"