blob: 8324b559006b0d4f906f682314a183c32d89796d [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"
Paul Stewartac0ffbf2017-03-03 16:43:33 -080024#include "keystore_backend_binder.h"
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +010025
Adam Langley1fb05832014-09-23 17:42:36 -070026#include <UniquePtr.h>
27
Paul Stewartac0ffbf2017-03-03 16:43:33 -080028#include <pthread.h>
Adam Langley1fb05832014-09-23 17:42:36 -070029#include <sys/socket.h>
30#include <stdarg.h>
31#include <string.h>
32#include <unistd.h>
33
Paul Stewartac0ffbf2017-03-03 16:43:33 -080034#include <cutils/log.h>
35
Adam Langley1fb05832014-09-23 17:42:36 -070036#include <openssl/bn.h>
37#include <openssl/ec.h>
38#include <openssl/ec_key.h>
39#include <openssl/ecdsa.h>
40#include <openssl/engine.h>
41#include <openssl/evp.h>
42#include <openssl/rsa.h>
43#include <openssl/x509.h>
44
Adam Langley1fb05832014-09-23 17:42:36 -070045namespace {
Adam Langley1fb05832014-09-23 17:42:36 -070046extern const RSA_METHOD keystore_rsa_method;
47extern const ECDSA_METHOD keystore_ecdsa_method;
48
49/* key_id_dup is called when one of the RSA or EC_KEY objects is duplicated. */
Kenny Rootdcca0512015-04-18 11:21:48 -070050int key_id_dup(CRYPTO_EX_DATA* /* to */,
51 const CRYPTO_EX_DATA* /* from */,
Adam Langley1fb05832014-09-23 17:42:36 -070052 void** from_d,
Kenny Rootdcca0512015-04-18 11:21:48 -070053 int /* index */,
54 long /* argl */,
55 void* /* argp */) {
Adam Langley1fb05832014-09-23 17:42:36 -070056 char *key_id = reinterpret_cast<char *>(*from_d);
57 if (key_id != NULL) {
58 *from_d = strdup(key_id);
59 }
60 return 1;
61}
62
63/* key_id_free is called when one of the RSA, DSA or EC_KEY object is freed. */
Kenny Rootdcca0512015-04-18 11:21:48 -070064void key_id_free(void* /* parent */,
Adam Langley1fb05832014-09-23 17:42:36 -070065 void* ptr,
Kenny Rootdcca0512015-04-18 11:21:48 -070066 CRYPTO_EX_DATA* /* ad */,
67 int /* index */,
68 long /* argl */,
69 void* /* argp */) {
Adam Langley1fb05832014-09-23 17:42:36 -070070 char *key_id = reinterpret_cast<char *>(ptr);
71 free(key_id);
72}
73
74/* KeystoreEngine is a BoringSSL ENGINE that implements RSA and ECDSA by
75 * forwarding the requested operations to Keystore. */
76class KeystoreEngine {
77 public:
78 KeystoreEngine()
79 : rsa_index_(RSA_get_ex_new_index(0 /* argl */,
80 NULL /* argp */,
81 NULL /* new_func */,
82 key_id_dup,
83 key_id_free)),
84 ec_key_index_(EC_KEY_get_ex_new_index(0 /* argl */,
85 NULL /* argp */,
86 NULL /* new_func */,
87 key_id_dup,
88 key_id_free)),
89 engine_(ENGINE_new()) {
90 ENGINE_set_RSA_method(
91 engine_, &keystore_rsa_method, sizeof(keystore_rsa_method));
92 ENGINE_set_ECDSA_method(
93 engine_, &keystore_ecdsa_method, sizeof(keystore_ecdsa_method));
94 }
95
96 int rsa_ex_index() const { return rsa_index_; }
97 int ec_key_ex_index() const { return ec_key_index_; }
98
99 const ENGINE* engine() const { return engine_; }
100
101 private:
102 const int rsa_index_;
103 const int ec_key_index_;
104 ENGINE* const engine_;
105};
106
107pthread_once_t g_keystore_engine_once = PTHREAD_ONCE_INIT;
108KeystoreEngine *g_keystore_engine;
Paul Stewartac0ffbf2017-03-03 16:43:33 -0800109KeystoreBackend *g_keystore_backend;
Adam Langley1fb05832014-09-23 17:42:36 -0700110
111/* init_keystore_engine is called to initialize |g_keystore_engine|. This
112 * should only be called by |pthread_once|. */
113void init_keystore_engine() {
114 g_keystore_engine = new KeystoreEngine;
Paul Stewartac0ffbf2017-03-03 16:43:33 -0800115 g_keystore_backend = new KeystoreBackendBinder;
Adam Langley1fb05832014-09-23 17:42:36 -0700116}
117
118/* ensure_keystore_engine ensures that |g_keystore_engine| is pointing to a
119 * valid |KeystoreEngine| object and creates one if not. */
120void ensure_keystore_engine() {
121 pthread_once(&g_keystore_engine_once, init_keystore_engine);
122}
123
124/* Many OpenSSL APIs take ownership of an argument on success but don't free
125 * the argument on failure. This means we need to tell our scoped pointers when
126 * we've transferred ownership, without triggering a warning by not using the
127 * result of release(). */
128#define OWNERSHIP_TRANSFERRED(obj) \
Chih-Hung Hsieh26275ad2016-05-11 14:26:35 -0700129 typeof ((obj).release()) _dummy __attribute__((unused)) = (obj).release()
Adam Langley1fb05832014-09-23 17:42:36 -0700130
131const char* rsa_get_key_id(const RSA* rsa) {
132 return reinterpret_cast<char*>(
133 RSA_get_ex_data(rsa, g_keystore_engine->rsa_ex_index()));
134}
135
136/* rsa_private_transform takes a big-endian integer from |in|, calculates the
137 * d'th power of it, modulo the RSA modulus, and writes the result as a
138 * big-endian integer to |out|. Both |in| and |out| are |len| bytes long. It
139 * returns one on success and zero otherwise. */
140int rsa_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in, size_t len) {
141 ALOGV("rsa_private_transform(%p, %p, %p, %u)", rsa, out, in, (unsigned) len);
142
143 const char *key_id = rsa_get_key_id(rsa);
144 if (key_id == NULL) {
145 ALOGE("key had no key_id!");
146 return 0;
147 }
148
Paul Stewartac0ffbf2017-03-03 16:43:33 -0800149 uint8_t* reply = NULL;
150 size_t reply_len;
151 int32_t ret = g_keystore_backend->sign(key_id, in, len, &reply, &reply_len);
152 if (ret < 0) {
153 ALOGW("There was an error during rsa_decrypt: could not connect");
Adam Langley1fb05832014-09-23 17:42:36 -0700154 return 0;
Paul Stewartac0ffbf2017-03-03 16:43:33 -0800155 } else if (ret != 0) {
156 ALOGW("Error during sign from keystore: %d", ret);
Adam Langley1fb05832014-09-23 17:42:36 -0700157 return 0;
Paul Stewartac0ffbf2017-03-03 16:43:33 -0800158 } else if (reply_len == 0 || reply == NULL) {
Adam Langley1fb05832014-09-23 17:42:36 -0700159 ALOGW("No valid signature returned");
Adam Langley1fb05832014-09-23 17:42:36 -0700160 return 0;
161 }
162
Paul Stewartac0ffbf2017-03-03 16:43:33 -0800163 if (reply_len > len) {
Adam Langley1fb05832014-09-23 17:42:36 -0700164 /* The result of the RSA operation can never be larger than the size of
165 * the modulus so we assume that the result has extra zeros on the
166 * left. This provides attackers with an oracle, but there's nothing
167 * that we can do about it here. */
Paul Stewartac0ffbf2017-03-03 16:43:33 -0800168 ALOGW("Reply len %zu greater than expected %zu", reply_len, len);
169 memcpy(out, &reply[reply_len - len], len);
170 } else if (reply_len < len) {
Adam Langley1fb05832014-09-23 17:42:36 -0700171 /* If the Keystore implementation returns a short value we assume that
172 * it's because it removed leading zeros from the left side. This is
173 * bad because it provides attackers with an oracle but we cannot do
174 * anything about a broken Keystore implementation here. */
Paul Stewartac0ffbf2017-03-03 16:43:33 -0800175 ALOGW("Reply len %zu lesser than expected %zu", reply_len, len);
Adam Langley1fb05832014-09-23 17:42:36 -0700176 memset(out, 0, len);
Paul Stewartac0ffbf2017-03-03 16:43:33 -0800177 memcpy(out + len - reply_len, &reply[0], reply_len);
Adam Langley1fb05832014-09-23 17:42:36 -0700178 } else {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100179 memcpy(out, &reply[0], len);
Adam Langley1fb05832014-09-23 17:42:36 -0700180 }
181
Adam Langley1fb05832014-09-23 17:42:36 -0700182 ALOGV("rsa=%p keystore_rsa_priv_dec successful", rsa);
183 return 1;
184}
185
186const struct rsa_meth_st keystore_rsa_method = {
187 {
188 0 /* references */,
189 1 /* is_static */,
190 },
191 NULL /* app_data */,
192
193 NULL /* init */,
194 NULL /* finish */,
195
196 NULL /* size */,
197
198 NULL /* sign */,
199 NULL /* verify */,
200
201 NULL /* encrypt */,
202 NULL /* sign_raw */,
203 NULL /* decrypt */,
204 NULL /* verify_raw */,
205
206 rsa_private_transform,
207
208 NULL /* mod_exp */,
209 NULL /* bn_mod_exp */,
210
David Benjamin30c77522016-03-28 18:00:17 -0400211 RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_OPAQUE,
Adam Langley1fb05832014-09-23 17:42:36 -0700212
213 NULL /* keygen */,
Adam Langley9eb92952015-09-02 15:28:03 -0700214 NULL /* multi_prime_keygen */,
Adam Langleyb2747fe2014-12-11 17:19:31 -0800215 NULL /* supports_digest */,
Adam Langley1fb05832014-09-23 17:42:36 -0700216};
217
218const char* ecdsa_get_key_id(const EC_KEY* ec_key) {
219 return reinterpret_cast<char*>(
220 EC_KEY_get_ex_data(ec_key, g_keystore_engine->ec_key_ex_index()));
221}
222
223/* ecdsa_sign signs |digest_len| bytes from |digest| with |ec_key| and writes
224 * the resulting signature (an ASN.1 encoded blob) to |sig|. It returns one on
225 * success and zero otherwise. */
226static int ecdsa_sign(const uint8_t* digest, size_t digest_len, uint8_t* sig,
227 unsigned int* sig_len, EC_KEY* ec_key) {
228 ALOGV("ecdsa_sign(%p, %u, %p)", digest, (unsigned) digest_len, ec_key);
229
230 const char *key_id = ecdsa_get_key_id(ec_key);
231 if (key_id == NULL) {
232 ALOGE("key had no key_id!");
233 return 0;
234 }
235
Adam Langley1fb05832014-09-23 17:42:36 -0700236 size_t ecdsa_size = ECDSA_size(ec_key);
237
Paul Stewartac0ffbf2017-03-03 16:43:33 -0800238 uint8_t* reply = NULL;
239 size_t reply_len;
240 int32_t ret = g_keystore_backend->sign(
241 key_id, digest, digest_len, &reply, &reply_len);
242 if (ret < 0) {
243 ALOGW("There was an error during ecdsa_sign: could not connect");
Adam Langley1fb05832014-09-23 17:42:36 -0700244 return 0;
Paul Stewartac0ffbf2017-03-03 16:43:33 -0800245 } else if (reply_len == 0 || reply == NULL) {
Adam Langley1fb05832014-09-23 17:42:36 -0700246 ALOGW("No valid signature returned");
Adam Langley1fb05832014-09-23 17:42:36 -0700247 return 0;
Paul Stewartac0ffbf2017-03-03 16:43:33 -0800248 } else if (reply_len > ecdsa_size) {
Adam Langley1fb05832014-09-23 17:42:36 -0700249 ALOGW("Signature is too large");
Adam Langley1fb05832014-09-23 17:42:36 -0700250 return 0;
251 }
252
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100253 // Reviewer: should't sig_len be checked here? Or is it just assumed that it is at least ecdsa_size?
Paul Stewartac0ffbf2017-03-03 16:43:33 -0800254 memcpy(sig, &reply[0], reply_len);
255 *sig_len = reply_len;
Adam Langley1fb05832014-09-23 17:42:36 -0700256
257 ALOGV("ecdsa_sign(%p, %u, %p) => success", digest, (unsigned)digest_len,
258 ec_key);
259 return 1;
260}
261
262const ECDSA_METHOD keystore_ecdsa_method = {
263 {
264 0 /* references */,
265 1 /* is_static */
266 } /* common */,
267 NULL /* app_data */,
268
269 NULL /* init */,
270 NULL /* finish */,
271 NULL /* group_order_size */,
272 ecdsa_sign,
273 NULL /* verify */,
274 ECDSA_FLAG_OPAQUE,
275};
276
277struct EVP_PKEY_Delete {
278 void operator()(EVP_PKEY* p) const {
279 EVP_PKEY_free(p);
280 }
281};
282typedef UniquePtr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY;
283
284struct RSA_Delete {
285 void operator()(RSA* p) const {
286 RSA_free(p);
287 }
288};
289typedef UniquePtr<RSA, RSA_Delete> Unique_RSA;
290
291struct EC_KEY_Delete {
292 void operator()(EC_KEY* ec) const {
293 EC_KEY_free(ec);
294 }
295};
296typedef UniquePtr<EC_KEY, EC_KEY_Delete> Unique_EC_KEY;
297
298/* wrap_rsa returns an |EVP_PKEY| that contains an RSA key where the public
299 * part is taken from |public_rsa| and the private operations are forwarded to
300 * KeyStore and operate on the key named |key_id|. */
301static EVP_PKEY *wrap_rsa(const char *key_id, const RSA *public_rsa) {
302 Unique_RSA rsa(RSA_new_method(g_keystore_engine->engine()));
303 if (rsa.get() == NULL) {
304 return NULL;
305 }
306
307 char *key_id_copy = strdup(key_id);
308 if (key_id_copy == NULL) {
309 return NULL;
310 }
311
312 if (!RSA_set_ex_data(rsa.get(), g_keystore_engine->rsa_ex_index(),
313 key_id_copy)) {
314 free(key_id_copy);
315 return NULL;
316 }
317
318 rsa->n = BN_dup(public_rsa->n);
319 rsa->e = BN_dup(public_rsa->e);
320 if (rsa->n == NULL || rsa->e == NULL) {
321 return NULL;
322 }
323
324 Unique_EVP_PKEY result(EVP_PKEY_new());
325 if (result.get() == NULL ||
326 !EVP_PKEY_assign_RSA(result.get(), rsa.get())) {
327 return NULL;
328 }
329 OWNERSHIP_TRANSFERRED(rsa);
330
331 return result.release();
332}
333
334/* wrap_ecdsa returns an |EVP_PKEY| that contains an ECDSA key where the public
335 * part is taken from |public_rsa| and the private operations are forwarded to
336 * KeyStore and operate on the key named |key_id|. */
337static EVP_PKEY *wrap_ecdsa(const char *key_id, const EC_KEY *public_ecdsa) {
338 Unique_EC_KEY ec(EC_KEY_new_method(g_keystore_engine->engine()));
339 if (ec.get() == NULL) {
340 return NULL;
341 }
342
343 if (!EC_KEY_set_group(ec.get(), EC_KEY_get0_group(public_ecdsa)) ||
344 !EC_KEY_set_public_key(ec.get(), EC_KEY_get0_public_key(public_ecdsa))) {
345 return NULL;
346 }
347
348 char *key_id_copy = strdup(key_id);
349 if (key_id_copy == NULL) {
350 return NULL;
351 }
352
353 if (!EC_KEY_set_ex_data(ec.get(), g_keystore_engine->ec_key_ex_index(),
354 key_id_copy)) {
355 free(key_id_copy);
356 return NULL;
357 }
358
359 Unique_EVP_PKEY result(EVP_PKEY_new());
360 if (result.get() == NULL ||
361 !EVP_PKEY_assign_EC_KEY(result.get(), ec.get())) {
362 return NULL;
363 }
364 OWNERSHIP_TRANSFERRED(ec);
365
366 return result.release();
367}
368
369} /* anonymous namespace */
370
371extern "C" {
372
373EVP_PKEY* EVP_PKEY_from_keystore(const char* key_id) __attribute__((visibility("default")));
374
375/* EVP_PKEY_from_keystore returns an |EVP_PKEY| that contains either an RSA or
376 * ECDSA key where the public part of the key reflects the value of the key
377 * named |key_id| in Keystore and the private operations are forwarded onto
378 * KeyStore. */
379EVP_PKEY* EVP_PKEY_from_keystore(const char* key_id) {
380 ALOGV("EVP_PKEY_from_keystore(\"%s\")", key_id);
381
Paul Stewartac0ffbf2017-03-03 16:43:33 -0800382 uint8_t *pubkey = NULL;
383 size_t pubkey_len;
384 int32_t ret = g_keystore_backend->get_pubkey(key_id, &pubkey, &pubkey_len);
385 if (ret < 0) {
386 ALOGW("could not contact keystore");
387 return NULL;
388 } else if (ret != 0) {
389 ALOGW("keystore reports error: %d", ret);
Adam Langley1fb05832014-09-23 17:42:36 -0700390 return NULL;
391 }
392
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100393 const uint8_t *inp = &pubkey[0];
Paul Stewartac0ffbf2017-03-03 16:43:33 -0800394 Unique_EVP_PKEY pkey(d2i_PUBKEY(NULL, &inp, pubkey_len));
Adam Langley1fb05832014-09-23 17:42:36 -0700395 if (pkey.get() == NULL) {
396 ALOGW("Cannot convert pubkey");
397 return NULL;
398 }
399
400 ensure_keystore_engine();
401
402 EVP_PKEY *result;
403 switch (EVP_PKEY_type(pkey->type)) {
404 case EVP_PKEY_RSA: {
405 Unique_RSA public_rsa(EVP_PKEY_get1_RSA(pkey.get()));
406 result = wrap_rsa(key_id, public_rsa.get());
407 break;
408 }
409 case EVP_PKEY_EC: {
410 Unique_EC_KEY public_ecdsa(EVP_PKEY_get1_EC_KEY(pkey.get()));
411 result = wrap_ecdsa(key_id, public_ecdsa.get());
412 break;
413 }
414 default:
415 ALOGE("Unsupported key type %d", EVP_PKEY_type(pkey->type));
416 result = NULL;
417 }
418
419 return result;
420}
421
422} // extern "C"