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 | |
| 26 | #include <keystore.h> |
| 27 | |
| 28 | #include <UniquePtr.h> |
| 29 | |
| 30 | #include <sys/socket.h> |
| 31 | #include <stdarg.h> |
| 32 | #include <string.h> |
| 33 | |
| 34 | #include <openssl/objects.h> |
| 35 | #include <openssl/engine.h> |
| 36 | #include <openssl/evp.h> |
| 37 | |
| 38 | #define LOG_NDEBUG 0 |
| 39 | #define LOG_TAG "OpenSSL-keystore" |
| 40 | #include <cutils/log.h> |
| 41 | |
| 42 | #include <keystore_client.h> |
| 43 | |
| 44 | |
| 45 | #define DYNAMIC_ENGINE |
| 46 | #define KEYSTORE_ENGINE_ID "keystore" |
| 47 | #define KEYSTORE_ENGINE_NAME "Android keystore engine" |
| 48 | |
| 49 | /** |
| 50 | * Many OpenSSL APIs take ownership of an argument on success but don't free the argument |
| 51 | * on failure. This means we need to tell our scoped pointers when we've transferred ownership, |
| 52 | * without triggering a warning by not using the result of release(). |
| 53 | */ |
| 54 | #define OWNERSHIP_TRANSFERRED(obj) \ |
| 55 | typeof (obj.release()) _dummy __attribute__((unused)) = obj.release() |
| 56 | |
| 57 | struct ENGINE_Delete { |
| 58 | void operator()(ENGINE* p) const { |
| 59 | ENGINE_free(p); |
| 60 | } |
| 61 | }; |
| 62 | typedef UniquePtr<ENGINE, ENGINE_Delete> Unique_ENGINE; |
| 63 | |
| 64 | struct EVP_PKEY_Delete { |
| 65 | void operator()(EVP_PKEY* p) const { |
| 66 | EVP_PKEY_free(p); |
| 67 | } |
| 68 | }; |
| 69 | typedef UniquePtr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY; |
| 70 | |
| 71 | struct RSA_Delete { |
| 72 | void operator()(RSA* p) const { |
| 73 | RSA_free(p); |
| 74 | } |
| 75 | }; |
| 76 | typedef UniquePtr<RSA, RSA_Delete> Unique_RSA; |
| 77 | |
| 78 | |
| 79 | /* |
| 80 | * RSA ex_data index for keystore's key handle. |
| 81 | */ |
| 82 | static int rsa_key_handle; |
| 83 | |
| 84 | |
| 85 | /** |
| 86 | * Execute a keystore command. The number of arguments should be passed in |
| 87 | * "numArgs" and be preceeded by the length as a size_t. |
| 88 | * |
| 89 | * If a reply is expected, the "reply" field must be of size |
| 90 | * KEYSTORE_MESSAGE_SIZE. |
| 91 | * |
| 92 | * Example for numArgs == 2: |
| 93 | * keystore_cmd(cmd, reply, 2, size_t, char*, size_t, char*); |
| 94 | * |
| 95 | * The return value will be the length of the reply stored in "reply." |
| 96 | * If an error occurs, the return value will be -1. |
| 97 | */ |
| 98 | |
| 99 | /** |
| 100 | * Makes sure the ex_data for the keyhandle is initially set to NULL. |
| 101 | */ |
| 102 | int keyhandle_new(void*, void*, CRYPTO_EX_DATA* ad, int idx, long, void*) { |
| 103 | return CRYPTO_set_ex_data(ad, idx, NULL); |
| 104 | } |
| 105 | |
| 106 | /** |
| 107 | * Frees a previously allocated keyhandle stored in ex_data. |
| 108 | */ |
| 109 | void keyhandle_free(void *, void *ptr, CRYPTO_EX_DATA*, int, long, void*) { |
| 110 | char* keyhandle = reinterpret_cast<char*>(ptr); |
| 111 | if (keyhandle != NULL) { |
| 112 | free(keyhandle); |
| 113 | } |
| 114 | } |
| 115 | |
| 116 | /** |
| 117 | * Duplicates a keyhandle stored in ex_data in case we copy a key. |
| 118 | */ |
| 119 | int keyhandle_dup(CRYPTO_EX_DATA* to, CRYPTO_EX_DATA*, void *ptrRef, int idx, long, void *) { |
| 120 | // This appears to be a bug in OpenSSL. |
| 121 | void** ptr = reinterpret_cast<void**>(ptrRef); |
| 122 | char* keyhandle = reinterpret_cast<char*>(*ptr); |
| 123 | if (keyhandle != NULL) { |
| 124 | char* keyhandle_copy = strdup(keyhandle); |
| 125 | *ptr = keyhandle_copy; |
| 126 | |
| 127 | // Call this in case OpenSSL is fixed in the future. |
| 128 | (void) CRYPTO_set_ex_data(to, idx, keyhandle_copy); |
| 129 | } |
| 130 | return 1; |
| 131 | } |
| 132 | |
| 133 | int keystore_rsa_priv_enc(int flen, const unsigned char* from, unsigned char* to, RSA* rsa, |
| 134 | int padding) { |
| 135 | ALOGV("keystore_rsa_sign(%d, %p, %p, %p, %d)", flen, from, to, rsa, padding); |
| 136 | |
| 137 | int num = RSA_size(rsa); |
| 138 | UniquePtr<uint8_t> padded(new uint8_t[num]); |
| 139 | if (padded.get() == NULL) { |
| 140 | ALOGE("could not allocate padded signature"); |
| 141 | return 0; |
| 142 | } |
| 143 | |
| 144 | switch (padding) { |
| 145 | case RSA_PKCS1_PADDING: |
| 146 | if (!RSA_padding_add_PKCS1_type_1(padded.get(), num, from, flen)) { |
| 147 | return 0; |
| 148 | } |
| 149 | break; |
| 150 | case RSA_X931_PADDING: |
| 151 | if (!RSA_padding_add_X931(padded.get(), num, from, flen)) { |
| 152 | return 0; |
| 153 | } |
| 154 | break; |
| 155 | case RSA_NO_PADDING: |
| 156 | if (!RSA_padding_add_none(padded.get(), num, from, flen)) { |
| 157 | return 0; |
| 158 | } |
| 159 | break; |
| 160 | default: |
| 161 | ALOGE("Unknown padding type: %d", padding); |
| 162 | return 0; |
| 163 | } |
| 164 | |
| 165 | uint8_t* key_id = reinterpret_cast<uint8_t*>(RSA_get_ex_data(rsa, rsa_key_handle)); |
| 166 | if (key_id == NULL) { |
| 167 | ALOGE("key had no key_id!"); |
| 168 | return 0; |
| 169 | } |
| 170 | |
| 171 | Keystore_Reply reply; |
| 172 | if (keystore_cmd(CommandCodes[SIGN], &reply, 2, strlen(reinterpret_cast<const char*>(key_id)), |
| 173 | key_id, static_cast<size_t>(num), reinterpret_cast<const uint8_t*>(padded.get())) |
| 174 | != NO_ERROR) { |
| 175 | ALOGE("There was an error during rsa_mod_exp"); |
| 176 | return 0; |
| 177 | } |
| 178 | |
| 179 | const size_t replyLen = reply.length(); |
| 180 | if (replyLen <= 0) { |
| 181 | ALOGW("No valid signature returned"); |
| 182 | return 0; |
| 183 | } |
| 184 | |
| 185 | memcpy(to, reply.get(), replyLen); |
| 186 | |
| 187 | ALOGV("rsa=%p keystore_rsa_sign => returning %p len %llu", rsa, to, |
| 188 | (unsigned long long) replyLen); |
| 189 | return static_cast<int>(replyLen); |
| 190 | } |
| 191 | |
| 192 | static RSA_METHOD keystore_rsa_meth = { |
| 193 | KEYSTORE_ENGINE_NAME, |
| 194 | NULL, /* rsa_pub_enc */ |
| 195 | NULL, /* rsa_pub_dec (verification) */ |
| 196 | keystore_rsa_priv_enc, /* rsa_priv_enc (signing) */ |
| 197 | NULL, /* rsa_priv_dec */ |
| 198 | NULL, /* rsa_mod_exp */ |
| 199 | NULL, /* bn_mod_exp */ |
| 200 | NULL, /* init */ |
| 201 | NULL, /* finish */ |
| 202 | RSA_FLAG_EXT_PKEY | RSA_FLAG_NO_BLINDING, /* flags */ |
| 203 | NULL, /* app_data */ |
| 204 | NULL, /* rsa_sign */ |
| 205 | NULL, /* rsa_verify */ |
| 206 | NULL, /* rsa_keygen */ |
| 207 | }; |
| 208 | |
| 209 | static int register_rsa_methods() { |
| 210 | const RSA_METHOD* rsa_meth = RSA_PKCS1_SSLeay(); |
| 211 | |
| 212 | keystore_rsa_meth.rsa_pub_enc = rsa_meth->rsa_pub_enc; |
| 213 | keystore_rsa_meth.rsa_pub_dec = rsa_meth->rsa_pub_dec; |
| 214 | keystore_rsa_meth.rsa_priv_dec = rsa_meth->rsa_priv_dec; |
| 215 | keystore_rsa_meth.rsa_mod_exp = rsa_meth->rsa_mod_exp; |
| 216 | keystore_rsa_meth.bn_mod_exp = rsa_meth->bn_mod_exp; |
| 217 | |
| 218 | return 1; |
| 219 | } |
| 220 | |
| 221 | static EVP_PKEY* keystore_loadkey(ENGINE* e, const char* key_id, UI_METHOD *ui_method, |
| 222 | void *callback_data) { |
| 223 | ALOGV("keystore_loadkey(%p, \"%s\", %p, %p)", e, key_id, ui_method, callback_data); |
| 224 | |
| 225 | Keystore_Reply reply; |
| 226 | if (keystore_cmd(CommandCodes[GET_PUBKEY], &reply, 1, strlen(key_id), key_id) != NO_ERROR) { |
| 227 | ALOGV("Cannot get public key for %s", key_id); |
| 228 | return NULL; |
| 229 | } |
| 230 | |
| 231 | const unsigned char* tmp = reinterpret_cast<const unsigned char*>(reply.get()); |
| 232 | Unique_EVP_PKEY pkey(d2i_PUBKEY(NULL, &tmp, reply.length())); |
| 233 | if (pkey.get() == NULL) { |
| 234 | ALOGW("Cannot convert pubkey"); |
| 235 | return NULL; |
| 236 | } |
| 237 | |
| 238 | switch (EVP_PKEY_type(pkey->type)) { |
| 239 | case EVP_PKEY_RSA: { |
| 240 | Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey.get())); |
| 241 | if (!RSA_set_ex_data(rsa.get(), rsa_key_handle, reinterpret_cast<void*>(strdup(key_id)))) { |
| 242 | ALOGW("Could not set ex_data for loaded RSA key"); |
| 243 | return NULL; |
| 244 | } |
| 245 | |
| 246 | RSA_set_method(rsa.get(), &keystore_rsa_meth); |
| 247 | RSA_blinding_off(rsa.get()); |
| 248 | |
| 249 | /* |
| 250 | * This should probably be an OpenSSL API, but EVP_PKEY_free calls |
| 251 | * ENGINE_finish(), so we need to call ENGINE_init() here. |
| 252 | */ |
| 253 | ENGINE_init(e); |
| 254 | rsa->engine = e; |
| 255 | rsa->flags |= RSA_FLAG_EXT_PKEY; |
| 256 | |
| 257 | break; |
| 258 | } |
| 259 | default: |
| 260 | ALOGE("Unsupported key type %d", EVP_PKEY_type(pkey->type)); |
| 261 | return NULL; |
| 262 | } |
| 263 | |
| 264 | return pkey.release(); |
| 265 | } |
| 266 | |
| 267 | static const ENGINE_CMD_DEFN keystore_cmd_defns[] = { |
| 268 | {0, NULL, NULL, 0} |
| 269 | }; |
| 270 | |
| 271 | static int keystore_engine_setup(ENGINE* e) { |
| 272 | ALOGV("keystore_engine_setup"); |
| 273 | |
| 274 | if (!ENGINE_set_id(e, KEYSTORE_ENGINE_ID) |
| 275 | || !ENGINE_set_name(e, KEYSTORE_ENGINE_NAME) |
| 276 | || !ENGINE_set_load_privkey_function(e, keystore_loadkey) |
| 277 | || !ENGINE_set_load_pubkey_function(e, keystore_loadkey) |
| 278 | || !ENGINE_set_cmd_defns(e, keystore_cmd_defns)) { |
| 279 | ALOGE("Could not set up keystore engine"); |
| 280 | return 0; |
| 281 | } |
| 282 | |
| 283 | if (!ENGINE_set_RSA(e, &keystore_rsa_meth) |
| 284 | || !register_rsa_methods()) { |
| 285 | ALOGE("Could not set up keystore RSA methods"); |
| 286 | return 0; |
| 287 | } |
| 288 | |
| 289 | /* We need a handle in the RSA keys as well for keygen. */ |
| 290 | rsa_key_handle = RSA_get_ex_new_index(0, NULL, keyhandle_new, keyhandle_dup, keyhandle_free); |
| 291 | if (rsa_key_handle < 0) { |
| 292 | ALOGE("Could not set up RSA ex_data index"); |
| 293 | return 0; |
| 294 | } |
| 295 | |
| 296 | return 1; |
| 297 | } |
| 298 | |
| 299 | ENGINE* ENGINE_keystore() { |
| 300 | ALOGV("ENGINE_keystore"); |
| 301 | |
| 302 | Unique_ENGINE engine(ENGINE_new()); |
| 303 | if (engine.get() == NULL) { |
| 304 | return NULL; |
| 305 | } |
| 306 | |
| 307 | if (!keystore_engine_setup(engine.get())) { |
| 308 | return NULL; |
| 309 | } |
| 310 | |
| 311 | return engine.release(); |
| 312 | } |
| 313 | |
| 314 | static int keystore_bind_fn(ENGINE *e, const char *id) { |
| 315 | ALOGV("keystore_bind_fn"); |
| 316 | |
| 317 | if (!id) { |
| 318 | return 0; |
| 319 | } |
| 320 | |
| 321 | if (strcmp(id, KEYSTORE_ENGINE_ID)) { |
| 322 | return 0; |
| 323 | } |
| 324 | |
| 325 | if (!keystore_engine_setup(e)) { |
| 326 | return 0; |
| 327 | } |
| 328 | |
| 329 | return 1; |
| 330 | } |
| 331 | |
| 332 | extern "C" { |
| 333 | #undef OPENSSL_EXPORT |
| 334 | #define OPENSSL_EXPORT extern __attribute__ ((visibility ("default"))) |
| 335 | |
| 336 | IMPLEMENT_DYNAMIC_CHECK_FN() |
| 337 | IMPLEMENT_DYNAMIC_BIND_FN(keystore_bind_fn) |
| 338 | }; |