blob: c1d643ce5517b47ccaec7aee378b9fbac3e80183 [file] [log] [blame]
Kenny Root9d422a52013-06-27 09:14:46 -07001/*
2 * Copyright 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 <utils/UniquePtr.h>
27
28//#define LOG_NDEBUG 0
29#define LOG_TAG "OpenSSL-keystore-rsa"
30#include <cutils/log.h>
31
32#include <binder/IServiceManager.h>
33#include <keystore/IKeystoreService.h>
34
35#include <openssl/rsa.h>
36#include <openssl/engine.h>
37
38#include "methods.h"
39
40
41/*
42 * RSA ex_data index for keystore's key handle.
43 */
44static int rsa_key_handle;
45
46/*
47 * Only initialize the rsa_key_handle once.
48 */
49static pthread_once_t rsa_key_handle_control = PTHREAD_ONCE_INIT;
50
51struct RSA_Delete {
52 void operator()(RSA* p) const {
53 RSA_free(p);
54 }
55};
56typedef UniquePtr<RSA, RSA_Delete> Unique_RSA;
57
58
59using namespace android;
60
61/**
62 * Called to initialize RSA's ex_data for the key_id handle. This should
63 * only be called when protected by a lock.
64 */
65static void init_rsa_key_handle() {
66 rsa_key_handle = RSA_get_ex_new_index(0, NULL, keyhandle_new, keyhandle_dup,
67 keyhandle_free);
68}
69
70int keystore_rsa_priv_enc(int flen, const unsigned char* from, unsigned char* to, RSA* rsa,
71 int padding) {
72 ALOGV("keystore_rsa_priv_enc(%d, %p, %p, %p, %d)", flen, from, to, rsa, padding);
73
74 int num = RSA_size(rsa);
75 UniquePtr<uint8_t> padded(new uint8_t[num]);
76 if (padded.get() == NULL) {
77 ALOGE("could not allocate padded signature");
78 return 0;
79 }
80
81 switch (padding) {
82 case RSA_PKCS1_PADDING:
83 if (!RSA_padding_add_PKCS1_type_1(padded.get(), num, from, flen)) {
84 return 0;
85 }
86 break;
87 case RSA_X931_PADDING:
88 if (!RSA_padding_add_X931(padded.get(), num, from, flen)) {
89 return 0;
90 }
91 break;
92 case RSA_NO_PADDING:
93 if (!RSA_padding_add_none(padded.get(), num, from, flen)) {
94 return 0;
95 }
96 break;
97 default:
98 ALOGE("Unknown padding type: %d", padding);
99 return 0;
100 }
101
102 uint8_t* key_id = reinterpret_cast<uint8_t*>(RSA_get_ex_data(rsa, rsa_key_handle));
103 if (key_id == NULL) {
104 ALOGE("key had no key_id!");
105 return 0;
106 }
107
108 sp<IServiceManager> sm = defaultServiceManager();
109 sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
110 sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
111
112 if (service == NULL) {
113 ALOGE("could not contact keystore");
114 return 0;
115 }
116
117 uint8_t* reply = NULL;
118 size_t replyLen;
119 int32_t ret = service->sign(String16(reinterpret_cast<const char*>(key_id)), padded.get(),
120 num, &reply, &replyLen);
121 if (ret < 0) {
122 ALOGW("There was an error during signing: could not connect");
123 free(reply);
124 return 0;
125 } else if (ret != 0) {
126 ALOGW("Error during signing from keystore: %d", ret);
127 free(reply);
128 return 0;
129 } else if (replyLen <= 0) {
130 ALOGW("No valid signature returned");
131 return 0;
132 }
133
134 memcpy(to, reply, replyLen);
135 free(reply);
136
137 ALOGV("rsa=%p keystore_rsa_priv_enc => returning %p len %llu", rsa, to,
138 (unsigned long long) replyLen);
139 return static_cast<int>(replyLen);
140}
141
142int keystore_rsa_priv_dec(int flen, const unsigned char* from, unsigned char* to, RSA* rsa,
143 int padding) {
144 ALOGV("keystore_rsa_priv_dec(%d, %p, %p, %p, %d)", flen, from, to, rsa, padding);
145
146 uint8_t* key_id = reinterpret_cast<uint8_t*>(RSA_get_ex_data(rsa, rsa_key_handle));
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 }
160
161 int num = RSA_size(rsa);
162
163 uint8_t* reply = NULL;
164 size_t replyLen;
165 int32_t ret = service->sign(String16(reinterpret_cast<const char*>(key_id)), from,
166 flen, &reply, &replyLen);
167 if (ret < 0) {
168 ALOGW("There was an error during rsa_mod_exp: could not connect");
169 return 0;
170 } else if (ret != 0) {
171 ALOGW("Error during sign from keystore: %d", ret);
172 return 0;
173 } else if (replyLen <= 0) {
174 ALOGW("No valid signature returned");
175 return 0;
176 }
177
178 /* Trim off the top zero if it's there */
179 uint8_t* alignedReply;
180 if (*reply == 0x00) {
181 alignedReply = reply + 1;
182 replyLen--;
183 } else {
184 alignedReply = reply;
185 }
186
187 int outSize;
188 switch (padding) {
189 case RSA_PKCS1_PADDING:
190 outSize = RSA_padding_check_PKCS1_type_2(to, num, alignedReply, replyLen, num);
191 break;
192 case RSA_X931_PADDING:
193 outSize = RSA_padding_check_X931(to, num, alignedReply, replyLen, num);
194 break;
195 case RSA_NO_PADDING:
196 outSize = RSA_padding_check_none(to, num, alignedReply, replyLen, num);
197 break;
198 default:
199 ALOGE("Unknown padding type: %d", padding);
200 outSize = -1;
201 break;
202 }
203
204 free(reply);
205
206 ALOGV("rsa=%p keystore_rsa_priv_dec => returning %p len %llu", rsa, to, outSize);
207 return outSize;
208}
209
210static RSA_METHOD keystore_rsa_meth = {
211 kKeystoreEngineId,
212 NULL, /* rsa_pub_enc (wrap) */
213 NULL, /* rsa_pub_dec (verification) */
214 keystore_rsa_priv_enc, /* rsa_priv_enc (signing) */
215 keystore_rsa_priv_dec, /* rsa_priv_dec (unwrap) */
216 NULL, /* rsa_mod_exp */
217 NULL, /* bn_mod_exp */
218 NULL, /* init */
219 NULL, /* finish */
220 RSA_FLAG_EXT_PKEY | RSA_FLAG_NO_BLINDING, /* flags */
221 NULL, /* app_data */
222 NULL, /* rsa_sign */
223 NULL, /* rsa_verify */
224 NULL, /* rsa_keygen */
225};
226
227static int register_rsa_methods() {
228 const RSA_METHOD* rsa_meth = RSA_PKCS1_SSLeay();
229
230 keystore_rsa_meth.rsa_pub_enc = rsa_meth->rsa_pub_enc;
231 keystore_rsa_meth.rsa_pub_dec = rsa_meth->rsa_pub_dec;
232 keystore_rsa_meth.rsa_mod_exp = rsa_meth->rsa_mod_exp;
233 keystore_rsa_meth.bn_mod_exp = rsa_meth->bn_mod_exp;
234
235 return 1;
236}
237
238int rsa_pkey_setup(ENGINE *e, EVP_PKEY *pkey, const char *key_id) {
239 Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey));
240 if (!RSA_set_ex_data(rsa.get(), rsa_key_handle, reinterpret_cast<void*>(strdup(key_id)))) {
241 ALOGW("Could not set ex_data for loaded RSA key");
242 return 0;
243 }
244
245 RSA_set_method(rsa.get(), &keystore_rsa_meth);
246 RSA_blinding_off(rsa.get());
247
248 /*
249 * This should probably be an OpenSSL API, but EVP_PKEY_free calls
250 * ENGINE_finish(), so we need to call ENGINE_init() here.
251 */
252 ENGINE_init(e);
253 rsa->engine = e;
254 rsa->flags |= RSA_FLAG_EXT_PKEY;
255
256 return 1;
257}
258
259int rsa_register(ENGINE* e) {
260 if (!ENGINE_set_RSA(e, &keystore_rsa_meth)
261 || !register_rsa_methods()) {
262 ALOGE("Could not set up keystore RSA methods");
263 return 0;
264 }
265
266 /* We need a handle in the RSA keys as well for keygen if it's not already initialized. */
267 pthread_once(&rsa_key_handle_control, init_rsa_key_handle);
268 if (rsa_key_handle < 0) {
269 ALOGE("Could not set up RSA ex_data index");
270 return 0;
271 }
272
273 return 1;
274}