Kenny Root | 70e3a86 | 2012-02-15 17:20:23 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2012 The Android Open Source Project |
| 3 | * |
| 4 | * Redistribution and use in source and binary forms, with or without |
| 5 | * modification, are permitted provided that the following conditions |
| 6 | * are met: |
| 7 | * 1. Redistributions of source code must retain the above copyright |
| 8 | * notice, this list of conditions and the following disclaimer. |
| 9 | * 2. Redistributions in binary form must reproduce the above copyright |
| 10 | * notice, this list of conditions and the following disclaimer in the |
| 11 | * documentation and/or other materials provided with the distribution. |
| 12 | * |
| 13 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY |
| 14 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 15 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| 16 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY |
| 17 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 18 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| 19 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| 20 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 21 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| 22 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 23 | * |
| 24 | */ |
| 25 | |
Colin Cross | 98c2f8f | 2012-03-28 09:44:09 -0700 | [diff] [blame] | 26 | #include <utils/UniquePtr.h> |
Kenny Root | 70e3a86 | 2012-02-15 17:20:23 -0800 | [diff] [blame] | 27 | |
| 28 | #include <sys/socket.h> |
| 29 | #include <stdarg.h> |
| 30 | #include <string.h> |
Kenny Root | bef8083 | 2012-05-03 11:19:28 -0700 | [diff] [blame] | 31 | #include <unistd.h> |
Kenny Root | 70e3a86 | 2012-02-15 17:20:23 -0800 | [diff] [blame] | 32 | |
| 33 | #include <openssl/objects.h> |
| 34 | #include <openssl/engine.h> |
| 35 | #include <openssl/evp.h> |
| 36 | |
Brian Carlstrom | a8c703d | 2012-07-17 14:43:46 -0700 | [diff] [blame] | 37 | //#define LOG_NDEBUG 0 |
Kenny Root | 70e3a86 | 2012-02-15 17:20:23 -0800 | [diff] [blame] | 38 | #define LOG_TAG "OpenSSL-keystore" |
| 39 | #include <cutils/log.h> |
| 40 | |
Kenny Root | 07438c8 | 2012-11-02 15:41:02 -0700 | [diff] [blame] | 41 | #include <binder/IServiceManager.h> |
| 42 | #include <keystore/keystore.h> |
| 43 | #include <keystore/IKeystoreService.h> |
Kenny Root | 70e3a86 | 2012-02-15 17:20:23 -0800 | [diff] [blame] | 44 | |
Kenny Root | 07438c8 | 2012-11-02 15:41:02 -0700 | [diff] [blame] | 45 | using namespace android; |
Kenny Root | 70e3a86 | 2012-02-15 17:20:23 -0800 | [diff] [blame] | 46 | |
| 47 | #define DYNAMIC_ENGINE |
| 48 | #define KEYSTORE_ENGINE_ID "keystore" |
| 49 | #define KEYSTORE_ENGINE_NAME "Android keystore engine" |
| 50 | |
| 51 | /** |
| 52 | * Many OpenSSL APIs take ownership of an argument on success but don't free the argument |
| 53 | * on failure. This means we need to tell our scoped pointers when we've transferred ownership, |
| 54 | * without triggering a warning by not using the result of release(). |
| 55 | */ |
| 56 | #define OWNERSHIP_TRANSFERRED(obj) \ |
| 57 | typeof (obj.release()) _dummy __attribute__((unused)) = obj.release() |
| 58 | |
| 59 | struct ENGINE_Delete { |
| 60 | void operator()(ENGINE* p) const { |
| 61 | ENGINE_free(p); |
| 62 | } |
| 63 | }; |
| 64 | typedef UniquePtr<ENGINE, ENGINE_Delete> Unique_ENGINE; |
| 65 | |
| 66 | struct EVP_PKEY_Delete { |
| 67 | void operator()(EVP_PKEY* p) const { |
| 68 | EVP_PKEY_free(p); |
| 69 | } |
| 70 | }; |
| 71 | typedef UniquePtr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY; |
| 72 | |
| 73 | struct RSA_Delete { |
| 74 | void operator()(RSA* p) const { |
| 75 | RSA_free(p); |
| 76 | } |
| 77 | }; |
| 78 | typedef UniquePtr<RSA, RSA_Delete> Unique_RSA; |
| 79 | |
| 80 | |
| 81 | /* |
| 82 | * RSA ex_data index for keystore's key handle. |
| 83 | */ |
| 84 | static int rsa_key_handle; |
| 85 | |
Kenny Root | bef8083 | 2012-05-03 11:19:28 -0700 | [diff] [blame] | 86 | /* |
| 87 | * Only initialize the rsa_key_handle once. |
Kenny Root | 70e3a86 | 2012-02-15 17:20:23 -0800 | [diff] [blame] | 88 | */ |
Kenny Root | bef8083 | 2012-05-03 11:19:28 -0700 | [diff] [blame] | 89 | static pthread_once_t rsa_key_handle_control = PTHREAD_ONCE_INIT; |
| 90 | |
Kenny Root | 70e3a86 | 2012-02-15 17:20:23 -0800 | [diff] [blame] | 91 | |
| 92 | /** |
| 93 | * Makes sure the ex_data for the keyhandle is initially set to NULL. |
| 94 | */ |
| 95 | int keyhandle_new(void*, void*, CRYPTO_EX_DATA* ad, int idx, long, void*) { |
| 96 | return CRYPTO_set_ex_data(ad, idx, NULL); |
| 97 | } |
| 98 | |
| 99 | /** |
| 100 | * Frees a previously allocated keyhandle stored in ex_data. |
| 101 | */ |
| 102 | void keyhandle_free(void *, void *ptr, CRYPTO_EX_DATA*, int, long, void*) { |
| 103 | char* keyhandle = reinterpret_cast<char*>(ptr); |
| 104 | if (keyhandle != NULL) { |
| 105 | free(keyhandle); |
| 106 | } |
| 107 | } |
| 108 | |
| 109 | /** |
| 110 | * Duplicates a keyhandle stored in ex_data in case we copy a key. |
| 111 | */ |
| 112 | int keyhandle_dup(CRYPTO_EX_DATA* to, CRYPTO_EX_DATA*, void *ptrRef, int idx, long, void *) { |
| 113 | // This appears to be a bug in OpenSSL. |
| 114 | void** ptr = reinterpret_cast<void**>(ptrRef); |
| 115 | char* keyhandle = reinterpret_cast<char*>(*ptr); |
| 116 | if (keyhandle != NULL) { |
| 117 | char* keyhandle_copy = strdup(keyhandle); |
| 118 | *ptr = keyhandle_copy; |
| 119 | |
| 120 | // Call this in case OpenSSL is fixed in the future. |
| 121 | (void) CRYPTO_set_ex_data(to, idx, keyhandle_copy); |
| 122 | } |
| 123 | return 1; |
| 124 | } |
| 125 | |
| 126 | int keystore_rsa_priv_enc(int flen, const unsigned char* from, unsigned char* to, RSA* rsa, |
| 127 | int padding) { |
Kenny Root | b51c47d | 2013-02-01 10:22:21 -0800 | [diff] [blame^] | 128 | ALOGV("keystore_rsa_priv_enc(%d, %p, %p, %p, %d)", flen, from, to, rsa, padding); |
Kenny Root | 70e3a86 | 2012-02-15 17:20:23 -0800 | [diff] [blame] | 129 | |
| 130 | int num = RSA_size(rsa); |
| 131 | UniquePtr<uint8_t> padded(new uint8_t[num]); |
| 132 | if (padded.get() == NULL) { |
| 133 | ALOGE("could not allocate padded signature"); |
| 134 | return 0; |
| 135 | } |
| 136 | |
| 137 | switch (padding) { |
| 138 | case RSA_PKCS1_PADDING: |
| 139 | if (!RSA_padding_add_PKCS1_type_1(padded.get(), num, from, flen)) { |
| 140 | return 0; |
| 141 | } |
| 142 | break; |
| 143 | case RSA_X931_PADDING: |
| 144 | if (!RSA_padding_add_X931(padded.get(), num, from, flen)) { |
| 145 | return 0; |
| 146 | } |
| 147 | break; |
| 148 | case RSA_NO_PADDING: |
| 149 | if (!RSA_padding_add_none(padded.get(), num, from, flen)) { |
| 150 | return 0; |
| 151 | } |
| 152 | break; |
| 153 | default: |
| 154 | ALOGE("Unknown padding type: %d", padding); |
| 155 | return 0; |
| 156 | } |
| 157 | |
| 158 | uint8_t* key_id = reinterpret_cast<uint8_t*>(RSA_get_ex_data(rsa, rsa_key_handle)); |
| 159 | if (key_id == NULL) { |
| 160 | ALOGE("key had no key_id!"); |
| 161 | return 0; |
| 162 | } |
| 163 | |
Kenny Root | 07438c8 | 2012-11-02 15:41:02 -0700 | [diff] [blame] | 164 | sp<IServiceManager> sm = defaultServiceManager(); |
| 165 | sp<IBinder> binder = sm->getService(String16("android.security.keystore")); |
| 166 | sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder); |
| 167 | |
| 168 | if (service == NULL) { |
| 169 | ALOGE("could not contact keystore"); |
Kenny Root | 70e3a86 | 2012-02-15 17:20:23 -0800 | [diff] [blame] | 170 | return 0; |
| 171 | } |
| 172 | |
Kenny Root | 07438c8 | 2012-11-02 15:41:02 -0700 | [diff] [blame] | 173 | uint8_t* reply = NULL; |
| 174 | size_t replyLen; |
| 175 | int32_t ret = service->sign(String16(reinterpret_cast<const char*>(key_id)), padded.get(), |
| 176 | num, &reply, &replyLen); |
| 177 | if (ret < 0) { |
Kenny Root | b51c47d | 2013-02-01 10:22:21 -0800 | [diff] [blame^] | 178 | ALOGW("There was an error during signing: could not connect"); |
Kenny Root | 07438c8 | 2012-11-02 15:41:02 -0700 | [diff] [blame] | 179 | free(reply); |
| 180 | return 0; |
| 181 | } else if (ret != 0) { |
Kenny Root | b51c47d | 2013-02-01 10:22:21 -0800 | [diff] [blame^] | 182 | ALOGW("Error during signing from keystore: %d", ret); |
Kenny Root | 07438c8 | 2012-11-02 15:41:02 -0700 | [diff] [blame] | 183 | free(reply); |
| 184 | return 0; |
| 185 | } else if (replyLen <= 0) { |
Kenny Root | 70e3a86 | 2012-02-15 17:20:23 -0800 | [diff] [blame] | 186 | ALOGW("No valid signature returned"); |
| 187 | return 0; |
| 188 | } |
| 189 | |
Kenny Root | 07438c8 | 2012-11-02 15:41:02 -0700 | [diff] [blame] | 190 | memcpy(to, reply, replyLen); |
Kenny Root | b51c47d | 2013-02-01 10:22:21 -0800 | [diff] [blame^] | 191 | free(reply); |
Kenny Root | 70e3a86 | 2012-02-15 17:20:23 -0800 | [diff] [blame] | 192 | |
Kenny Root | b51c47d | 2013-02-01 10:22:21 -0800 | [diff] [blame^] | 193 | ALOGV("rsa=%p keystore_rsa_priv_enc => returning %p len %llu", rsa, to, |
Kenny Root | 70e3a86 | 2012-02-15 17:20:23 -0800 | [diff] [blame] | 194 | (unsigned long long) replyLen); |
| 195 | return static_cast<int>(replyLen); |
| 196 | } |
| 197 | |
Kenny Root | b51c47d | 2013-02-01 10:22:21 -0800 | [diff] [blame^] | 198 | int keystore_rsa_priv_dec(int flen, const unsigned char* from, unsigned char* to, RSA* rsa, |
| 199 | int padding) { |
| 200 | ALOGV("keystore_rsa_priv_dec(%d, %p, %p, %p, %d)", flen, from, to, rsa, padding); |
| 201 | |
| 202 | uint8_t* key_id = reinterpret_cast<uint8_t*>(RSA_get_ex_data(rsa, rsa_key_handle)); |
| 203 | if (key_id == NULL) { |
| 204 | ALOGE("key had no key_id!"); |
| 205 | return 0; |
| 206 | } |
| 207 | |
| 208 | sp<IServiceManager> sm = defaultServiceManager(); |
| 209 | sp<IBinder> binder = sm->getService(String16("android.security.keystore")); |
| 210 | sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder); |
| 211 | |
| 212 | if (service == NULL) { |
| 213 | ALOGE("could not contact keystore"); |
| 214 | return 0; |
| 215 | } |
| 216 | |
| 217 | int num = RSA_size(rsa); |
| 218 | |
| 219 | uint8_t* reply = NULL; |
| 220 | size_t replyLen; |
| 221 | int32_t ret = service->sign(String16(reinterpret_cast<const char*>(key_id)), from, |
| 222 | flen, &reply, &replyLen); |
| 223 | if (ret < 0) { |
| 224 | ALOGW("There was an error during rsa_mod_exp: could not connect"); |
| 225 | return 0; |
| 226 | } else if (ret != 0) { |
| 227 | ALOGW("Error during sign from keystore: %d", ret); |
| 228 | return 0; |
| 229 | } else if (replyLen <= 0) { |
| 230 | ALOGW("No valid signature returned"); |
| 231 | return 0; |
| 232 | } |
| 233 | |
| 234 | /* Trim off the top zero if it's there */ |
| 235 | uint8_t* alignedReply; |
| 236 | if (*reply == 0x00) { |
| 237 | alignedReply = reply + 1; |
| 238 | replyLen--; |
| 239 | } else { |
| 240 | alignedReply = reply; |
| 241 | } |
| 242 | |
| 243 | int outSize; |
| 244 | switch (padding) { |
| 245 | case RSA_PKCS1_PADDING: |
| 246 | outSize = RSA_padding_check_PKCS1_type_2(to, num, alignedReply, replyLen, num); |
| 247 | break; |
| 248 | case RSA_X931_PADDING: |
| 249 | outSize = RSA_padding_check_X931(to, num, alignedReply, replyLen, num); |
| 250 | break; |
| 251 | case RSA_NO_PADDING: |
| 252 | outSize = RSA_padding_check_none(to, num, alignedReply, replyLen, num); |
| 253 | break; |
| 254 | default: |
| 255 | ALOGE("Unknown padding type: %d", padding); |
| 256 | outSize = -1; |
| 257 | break; |
| 258 | } |
| 259 | |
| 260 | free(reply); |
| 261 | |
| 262 | ALOGV("rsa=%p keystore_rsa_priv_dec => returning %p len %llu", rsa, to, outSize); |
| 263 | return outSize; |
| 264 | } |
| 265 | |
Kenny Root | 70e3a86 | 2012-02-15 17:20:23 -0800 | [diff] [blame] | 266 | static RSA_METHOD keystore_rsa_meth = { |
| 267 | KEYSTORE_ENGINE_NAME, |
Kenny Root | b51c47d | 2013-02-01 10:22:21 -0800 | [diff] [blame^] | 268 | NULL, /* rsa_pub_enc (wrap) */ |
Kenny Root | 70e3a86 | 2012-02-15 17:20:23 -0800 | [diff] [blame] | 269 | NULL, /* rsa_pub_dec (verification) */ |
| 270 | keystore_rsa_priv_enc, /* rsa_priv_enc (signing) */ |
Kenny Root | b51c47d | 2013-02-01 10:22:21 -0800 | [diff] [blame^] | 271 | keystore_rsa_priv_dec, /* rsa_priv_dec (unwrap) */ |
Kenny Root | 70e3a86 | 2012-02-15 17:20:23 -0800 | [diff] [blame] | 272 | NULL, /* rsa_mod_exp */ |
| 273 | NULL, /* bn_mod_exp */ |
| 274 | NULL, /* init */ |
| 275 | NULL, /* finish */ |
| 276 | RSA_FLAG_EXT_PKEY | RSA_FLAG_NO_BLINDING, /* flags */ |
| 277 | NULL, /* app_data */ |
| 278 | NULL, /* rsa_sign */ |
| 279 | NULL, /* rsa_verify */ |
| 280 | NULL, /* rsa_keygen */ |
| 281 | }; |
| 282 | |
| 283 | static int register_rsa_methods() { |
| 284 | const RSA_METHOD* rsa_meth = RSA_PKCS1_SSLeay(); |
| 285 | |
| 286 | keystore_rsa_meth.rsa_pub_enc = rsa_meth->rsa_pub_enc; |
| 287 | keystore_rsa_meth.rsa_pub_dec = rsa_meth->rsa_pub_dec; |
Kenny Root | 70e3a86 | 2012-02-15 17:20:23 -0800 | [diff] [blame] | 288 | keystore_rsa_meth.rsa_mod_exp = rsa_meth->rsa_mod_exp; |
| 289 | keystore_rsa_meth.bn_mod_exp = rsa_meth->bn_mod_exp; |
| 290 | |
| 291 | return 1; |
| 292 | } |
| 293 | |
Brian Carlstrom | a8c703d | 2012-07-17 14:43:46 -0700 | [diff] [blame] | 294 | static EVP_PKEY* keystore_loadkey(ENGINE* e, const char* key_id, UI_METHOD* ui_method, |
| 295 | void* callback_data) { |
| 296 | #if LOG_NDEBUG |
| 297 | (void)ui_method; |
| 298 | (void)callback_data; |
| 299 | #else |
Kenny Root | 70e3a86 | 2012-02-15 17:20:23 -0800 | [diff] [blame] | 300 | ALOGV("keystore_loadkey(%p, \"%s\", %p, %p)", e, key_id, ui_method, callback_data); |
Brian Carlstrom | a8c703d | 2012-07-17 14:43:46 -0700 | [diff] [blame] | 301 | #endif |
Kenny Root | 70e3a86 | 2012-02-15 17:20:23 -0800 | [diff] [blame] | 302 | |
Kenny Root | 07438c8 | 2012-11-02 15:41:02 -0700 | [diff] [blame] | 303 | sp<IServiceManager> sm = defaultServiceManager(); |
| 304 | sp<IBinder> binder = sm->getService(String16("android.security.keystore")); |
| 305 | sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder); |
| 306 | |
| 307 | if (service == NULL) { |
| 308 | ALOGE("could not contact keystore"); |
| 309 | return 0; |
| 310 | } |
| 311 | |
| 312 | uint8_t *pubkey = NULL; |
| 313 | size_t pubkeyLen; |
| 314 | int32_t ret = service->get_pubkey(String16(key_id), &pubkey, &pubkeyLen); |
| 315 | if (ret < 0) { |
| 316 | ALOGW("could not contact keystore"); |
| 317 | free(pubkey); |
| 318 | return NULL; |
| 319 | } else if (ret != 0) { |
| 320 | ALOGW("keystore reports error: %d", ret); |
| 321 | free(pubkey); |
Kenny Root | 70e3a86 | 2012-02-15 17:20:23 -0800 | [diff] [blame] | 322 | return NULL; |
| 323 | } |
| 324 | |
Kenny Root | 07438c8 | 2012-11-02 15:41:02 -0700 | [diff] [blame] | 325 | const unsigned char* tmp = reinterpret_cast<const unsigned char*>(pubkey); |
| 326 | Unique_EVP_PKEY pkey(d2i_PUBKEY(NULL, &tmp, pubkeyLen)); |
| 327 | free(pubkey); |
Kenny Root | 70e3a86 | 2012-02-15 17:20:23 -0800 | [diff] [blame] | 328 | if (pkey.get() == NULL) { |
| 329 | ALOGW("Cannot convert pubkey"); |
| 330 | return NULL; |
| 331 | } |
| 332 | |
| 333 | switch (EVP_PKEY_type(pkey->type)) { |
| 334 | case EVP_PKEY_RSA: { |
| 335 | Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey.get())); |
| 336 | if (!RSA_set_ex_data(rsa.get(), rsa_key_handle, reinterpret_cast<void*>(strdup(key_id)))) { |
| 337 | ALOGW("Could not set ex_data for loaded RSA key"); |
| 338 | return NULL; |
| 339 | } |
| 340 | |
| 341 | RSA_set_method(rsa.get(), &keystore_rsa_meth); |
| 342 | RSA_blinding_off(rsa.get()); |
| 343 | |
| 344 | /* |
| 345 | * This should probably be an OpenSSL API, but EVP_PKEY_free calls |
| 346 | * ENGINE_finish(), so we need to call ENGINE_init() here. |
| 347 | */ |
| 348 | ENGINE_init(e); |
| 349 | rsa->engine = e; |
| 350 | rsa->flags |= RSA_FLAG_EXT_PKEY; |
| 351 | |
| 352 | break; |
| 353 | } |
| 354 | default: |
| 355 | ALOGE("Unsupported key type %d", EVP_PKEY_type(pkey->type)); |
| 356 | return NULL; |
| 357 | } |
| 358 | |
| 359 | return pkey.release(); |
| 360 | } |
| 361 | |
| 362 | static const ENGINE_CMD_DEFN keystore_cmd_defns[] = { |
| 363 | {0, NULL, NULL, 0} |
| 364 | }; |
| 365 | |
Kenny Root | bef8083 | 2012-05-03 11:19:28 -0700 | [diff] [blame] | 366 | /** |
| 367 | * Called to initialize RSA's ex_data for the key_id handle. This should |
| 368 | * only be called when protected by a lock. |
| 369 | */ |
| 370 | static void init_rsa_key_handle() { |
| 371 | rsa_key_handle = RSA_get_ex_new_index(0, NULL, keyhandle_new, keyhandle_dup, |
| 372 | keyhandle_free); |
| 373 | } |
| 374 | |
Kenny Root | 70e3a86 | 2012-02-15 17:20:23 -0800 | [diff] [blame] | 375 | static int keystore_engine_setup(ENGINE* e) { |
| 376 | ALOGV("keystore_engine_setup"); |
| 377 | |
| 378 | if (!ENGINE_set_id(e, KEYSTORE_ENGINE_ID) |
| 379 | || !ENGINE_set_name(e, KEYSTORE_ENGINE_NAME) |
| 380 | || !ENGINE_set_load_privkey_function(e, keystore_loadkey) |
| 381 | || !ENGINE_set_load_pubkey_function(e, keystore_loadkey) |
Kenny Root | 938a991 | 2012-08-15 22:19:25 -0700 | [diff] [blame] | 382 | || !ENGINE_set_flags(e, 0) |
Kenny Root | 70e3a86 | 2012-02-15 17:20:23 -0800 | [diff] [blame] | 383 | || !ENGINE_set_cmd_defns(e, keystore_cmd_defns)) { |
| 384 | ALOGE("Could not set up keystore engine"); |
| 385 | return 0; |
| 386 | } |
| 387 | |
| 388 | if (!ENGINE_set_RSA(e, &keystore_rsa_meth) |
| 389 | || !register_rsa_methods()) { |
| 390 | ALOGE("Could not set up keystore RSA methods"); |
| 391 | return 0; |
| 392 | } |
| 393 | |
Kenny Root | bef8083 | 2012-05-03 11:19:28 -0700 | [diff] [blame] | 394 | /* We need a handle in the RSA keys as well for keygen if it's not already initialized. */ |
| 395 | pthread_once(&rsa_key_handle_control, init_rsa_key_handle); |
Kenny Root | 70e3a86 | 2012-02-15 17:20:23 -0800 | [diff] [blame] | 396 | if (rsa_key_handle < 0) { |
| 397 | ALOGE("Could not set up RSA ex_data index"); |
| 398 | return 0; |
| 399 | } |
| 400 | |
| 401 | return 1; |
| 402 | } |
| 403 | |
| 404 | ENGINE* ENGINE_keystore() { |
| 405 | ALOGV("ENGINE_keystore"); |
| 406 | |
| 407 | Unique_ENGINE engine(ENGINE_new()); |
| 408 | if (engine.get() == NULL) { |
| 409 | return NULL; |
| 410 | } |
| 411 | |
| 412 | if (!keystore_engine_setup(engine.get())) { |
| 413 | return NULL; |
| 414 | } |
| 415 | |
| 416 | return engine.release(); |
| 417 | } |
| 418 | |
| 419 | static int keystore_bind_fn(ENGINE *e, const char *id) { |
| 420 | ALOGV("keystore_bind_fn"); |
| 421 | |
| 422 | if (!id) { |
| 423 | return 0; |
| 424 | } |
| 425 | |
| 426 | if (strcmp(id, KEYSTORE_ENGINE_ID)) { |
| 427 | return 0; |
| 428 | } |
| 429 | |
| 430 | if (!keystore_engine_setup(e)) { |
| 431 | return 0; |
| 432 | } |
| 433 | |
| 434 | return 1; |
| 435 | } |
| 436 | |
| 437 | extern "C" { |
| 438 | #undef OPENSSL_EXPORT |
| 439 | #define OPENSSL_EXPORT extern __attribute__ ((visibility ("default"))) |
| 440 | |
| 441 | IMPLEMENT_DYNAMIC_CHECK_FN() |
| 442 | IMPLEMENT_DYNAMIC_BIND_FN(keystore_bind_fn) |
| 443 | }; |