blob: 0e38b50ebb7318e5464da91f6b129de333da9910 [file] [log] [blame]
Paul Stewartac0ffbf2017-03-03 16:43:33 -08001/* Copyright 2017 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
23#include "keystore_backend_binder.h"
24
Janis Danisevskise5a09aa2018-08-09 11:13:51 -070025#include <android-base/logging.h>
Rob Barnesbb6cabd2018-10-04 17:10:37 -060026#include <android/security/keystore/IKeystoreService.h>
Paul Stewartac0ffbf2017-03-03 16:43:33 -080027#include <binder/IServiceManager.h>
Janis Danisevskise5a09aa2018-08-09 11:13:51 -070028#include <keystore/KeyCharacteristics.h>
29#include <keystore/KeymasterArguments.h>
30#include <keystore/KeymasterBlob.h>
Rob Barnesbb6cabd2018-10-04 17:10:37 -060031#include <keystore/KeystoreResponse.h>
Janis Danisevskise5a09aa2018-08-09 11:13:51 -070032#include <keystore/OperationResult.h>
33#include <keystore/keymaster_types.h>
Paul Stewartac0ffbf2017-03-03 16:43:33 -080034#include <keystore/keystore.h>
Paul Stewartac0ffbf2017-03-03 16:43:33 -080035#include <keystore/keystore_hidl_support.h>
Rob Barnesbb6cabd2018-10-04 17:10:37 -060036#include <keystore/keystore_promises.h>
Janis Danisevskise5a09aa2018-08-09 11:13:51 -070037#include <keystore/keystore_return_types.h>
Paul Stewartac0ffbf2017-03-03 16:43:33 -080038
Rob Barnesbb6cabd2018-10-04 17:10:37 -060039#include <future>
40
41using android::security::keystore::IKeystoreService;
Paul Stewartac0ffbf2017-03-03 16:43:33 -080042using namespace android;
Paul Stewartac0ffbf2017-03-03 16:43:33 -080043using keystore::hidl_vec;
44
Janis Danisevskise5a09aa2018-08-09 11:13:51 -070045using android::hardware::keymaster::V4_0::Algorithm;
46using android::hardware::keymaster::V4_0::authorizationValue;
47using android::hardware::keymaster::V4_0::Digest;
48using android::hardware::keymaster::V4_0::KeyFormat;
49using android::hardware::keymaster::V4_0::KeyParameter;
50using android::hardware::keymaster::V4_0::KeyPurpose;
51using android::hardware::keymaster::V4_0::NullOr;
52using android::hardware::keymaster::V4_0::PaddingMode;
53using android::hardware::keymaster::V4_0::TAG_ALGORITHM;
54using android::hardware::keymaster::V4_0::TAG_DIGEST;
55using android::hardware::keymaster::V4_0::TAG_PADDING;
56using android::security::keymaster::ExportResult;
57using android::security::keymaster::KeyCharacteristics;
58using android::security::keymaster::KeymasterArguments;
59using android::security::keymaster::KeymasterBlob;
60using android::security::keymaster::OperationResult;
61
62using KSReturn = keystore::KeyStoreNativeReturnCode;
63
Paul Stewartac0ffbf2017-03-03 16:43:33 -080064namespace {
65const char keystore_service_name[] = "android.security.keystore";
Janis Danisevskise5a09aa2018-08-09 11:13:51 -070066constexpr int32_t UID_SELF = -1;
Rob Barnesbb6cabd2018-10-04 17:10:37 -060067
68using keystore::KeyCharacteristicsPromise;
69using keystore::KeystoreExportPromise;
70using keystore::KeystoreResponsePromise;
71using keystore::OperationResultPromise;
72
73} // namespace
Paul Stewartac0ffbf2017-03-03 16:43:33 -080074
Janis Danisevskise5a09aa2018-08-09 11:13:51 -070075#define AT __func__ << ":" << __LINE__ << " "
76
77static NullOr<const Algorithm&> getKeyAlgoritmFromKeyCharacteristics(
78 const ::android::security::keymaster::KeyCharacteristics& characteristics) {
79 for (const auto& param : characteristics.hardwareEnforced.getParameters()) {
80 auto algo = authorizationValue(TAG_ALGORITHM, param);
81 if (algo.isOk()) return algo;
82 }
83 for (const auto& param : characteristics.softwareEnforced.getParameters()) {
84 auto algo = authorizationValue(TAG_ALGORITHM, param);
85 if (algo.isOk()) return algo;
86 }
87 return {};
88}
89
Dmitry Dementyeva447b3c2017-10-27 23:09:53 -070090int32_t KeystoreBackendBinder::sign(const char* key_id, const uint8_t* in, size_t len,
91 uint8_t** reply, size_t* reply_len) {
Paul Stewartac0ffbf2017-03-03 16:43:33 -080092 sp<IServiceManager> sm = defaultServiceManager();
93 sp<IBinder> binder = sm->getService(String16(keystore_service_name));
94 sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
95
Yi Konge353f252018-07-30 01:38:39 -070096 if (service == nullptr) {
Janis Danisevskise5a09aa2018-08-09 11:13:51 -070097 LOG(ERROR) << AT << "could not contact keystore";
Paul Stewartac0ffbf2017-03-03 16:43:33 -080098 return -1;
99 }
100
Janis Danisevskise5a09aa2018-08-09 11:13:51 -0700101 String16 key_name16(key_id);
Rob Barnesbb6cabd2018-10-04 17:10:37 -0600102 int32_t error_code;
103 android::sp<KeyCharacteristicsPromise> kc_promise(new KeyCharacteristicsPromise);
104 auto kc_future = kc_promise->get_future();
105 auto binder_result = service->getKeyCharacteristics(kc_promise, key_name16, KeymasterBlob(),
106 KeymasterBlob(), UID_SELF, &error_code);
Janis Danisevskise5a09aa2018-08-09 11:13:51 -0700107 if (!binder_result.isOk()) {
108 LOG(ERROR) << AT << "communication error while calling keystore";
109 return -1;
110 }
Rob Barnesbb6cabd2018-10-04 17:10:37 -0600111 if (KSReturn(error_code).isOk()) {
112 LOG(ERROR) << AT << "getKeyCharacteristics failed: " << error_code;
113 return -1;
Janis Danisevskise5a09aa2018-08-09 11:13:51 -0700114 }
115
Rob Barnesbb6cabd2018-10-04 17:10:37 -0600116 auto [km_response, characteristics] = kc_future.get();
117
118 if (KSReturn(km_response.response_code()).isOk()) {
119 LOG(ERROR) << AT << "getKeyCharacteristics failed: " << km_response.response_code();
120 return -1;
121 }
122
123 auto algorithm = getKeyAlgoritmFromKeyCharacteristics(characteristics);
Janis Danisevskise5a09aa2018-08-09 11:13:51 -0700124 if (!algorithm.isOk()) {
125 LOG(ERROR) << AT << "could not get algorithm from key characteristics";
Paul Stewartac0ffbf2017-03-03 16:43:33 -0800126 return -1;
127 }
128
Janis Danisevskise5a09aa2018-08-09 11:13:51 -0700129 hidl_vec<KeyParameter> params(3);
130 params[0] = Authorization(TAG_DIGEST, Digest::NONE);
131 params[1] = Authorization(TAG_PADDING, PaddingMode::NONE);
132 params[2] = Authorization(TAG_ALGORITHM, algorithm.value());
133
134 android::sp<android::IBinder> token(new android::BBinder);
Rob Barnesbb6cabd2018-10-04 17:10:37 -0600135 sp<OperationResultPromise> promise(new OperationResultPromise());
136 auto future = promise->get_future();
137 binder_result = service->begin(promise, token, key_name16, (int)KeyPurpose::SIGN,
138 true /*pruneable*/, KeymasterArguments(params),
139 std::vector<uint8_t>() /* entropy */, UID_SELF, &error_code);
Janis Danisevskise5a09aa2018-08-09 11:13:51 -0700140 if (!binder_result.isOk()) {
141 LOG(ERROR) << AT << "communication error while calling keystore";
142 return -1;
143 }
Rob Barnesbb6cabd2018-10-04 17:10:37 -0600144
145 keystore::KeyStoreNativeReturnCode rc(error_code);
146 if (!rc.isOk()) {
147 LOG(ERROR) << AT << "Keystore begin returned: " << error_code;
148 return -1;
149 }
150 OperationResult result = future.get();
151
Janis Danisevskise5a09aa2018-08-09 11:13:51 -0700152 if (!result.resultCode.isOk()) {
153 LOG(ERROR) << AT << "begin failed: " << int32_t(result.resultCode);
154 return -1;
155 }
156 auto handle = std::move(result.token);
157
158 do {
Rob Barnesbb6cabd2018-10-04 17:10:37 -0600159 future = {};
160 promise = new OperationResultPromise();
161 future = promise->get_future();
162 binder_result = service->update(promise, handle, KeymasterArguments(params),
163 std::vector<uint8_t>(in, in + len), &error_code);
Janis Danisevskise5a09aa2018-08-09 11:13:51 -0700164 if (!binder_result.isOk()) {
165 LOG(ERROR) << AT << "communication error while calling keystore";
166 return -1;
167 }
Rob Barnesbb6cabd2018-10-04 17:10:37 -0600168
169 rc = keystore::KeyStoreNativeReturnCode(error_code);
170 if (!rc.isOk()) {
171 LOG(ERROR) << AT << "Keystore update returned: " << error_code;
172 return -1;
173 }
174 result = future.get();
175
Janis Danisevskise5a09aa2018-08-09 11:13:51 -0700176 if (!result.resultCode.isOk()) {
177 LOG(ERROR) << AT << "update failed: " << int32_t(result.resultCode);
178 return -1;
179 }
Rob Barnesbb6cabd2018-10-04 17:10:37 -0600180
Janis Danisevskise5a09aa2018-08-09 11:13:51 -0700181 if (result.inputConsumed > len) {
182 LOG(ERROR) << AT << "update consumed more data than provided";
Rob Barnesbb6cabd2018-10-04 17:10:37 -0600183 sp<KeystoreResponsePromise> abortPromise(new KeystoreResponsePromise);
184 auto abortFuture = abortPromise->get_future();
185 binder_result = service->abort(abortPromise, handle, &error_code);
186 if (!binder_result.isOk()) {
187 LOG(ERROR) << AT << "communication error while calling keystore";
188 return -1;
189 }
190 // This is mainly for logging since we already failed.
191 // But if abort returned OK we have to wait untill abort calls the callback
192 // hence the call to abortFuture.get().
193 if (!KSReturn(error_code).isOk()) {
194 LOG(ERROR) << AT << "abort failed: " << error_code;
195 } else if (!(rc = KSReturn(abortFuture.get().response_code())).isOk()) {
196 LOG(ERROR) << AT << "abort failed: " << int32_t(rc);
197 }
Janis Danisevskise5a09aa2018-08-09 11:13:51 -0700198 return -1;
199 }
200 len -= result.inputConsumed;
201 in += result.inputConsumed;
202 } while (len > 0);
203
Rob Barnesbb6cabd2018-10-04 17:10:37 -0600204 future = {};
205 promise = new OperationResultPromise();
206 future = promise->get_future();
207
208 binder_result = service->finish(promise, handle, KeymasterArguments(params),
209 std::vector<uint8_t>() /* signature */,
210 std::vector<uint8_t>() /* entropy */, &error_code);
211
Janis Danisevskise5a09aa2018-08-09 11:13:51 -0700212 if (!binder_result.isOk()) {
213 LOG(ERROR) << AT << "communication error while calling keystore";
214 return -1;
215 }
Rob Barnesbb6cabd2018-10-04 17:10:37 -0600216
217 rc = keystore::KeyStoreNativeReturnCode(error_code);
218 if (!rc.isOk()) {
219 LOG(ERROR) << AT << "Keystore finish returned: " << error_code;
220 return -1;
221 }
222 result = future.get();
223
Janis Danisevskise5a09aa2018-08-09 11:13:51 -0700224 if (!result.resultCode.isOk()) {
225 LOG(ERROR) << AT << "finish failed: " << int32_t(result.resultCode);
226 return -1;
227 }
228
229 hidl_vec<uint8_t> reply_hidl(result.data);
230 if (reply_len) {
231 *reply_len = reply_hidl.size();
232 }
233 if (reply) {
234 *reply = reply_hidl.releaseData();
235 }
Paul Stewartac0ffbf2017-03-03 16:43:33 -0800236 return 0;
237}
238
Dmitry Dementyeva447b3c2017-10-27 23:09:53 -0700239int32_t KeystoreBackendBinder::get_pubkey(const char* key_id, uint8_t** pubkey,
240 size_t* pubkey_len) {
Paul Stewartac0ffbf2017-03-03 16:43:33 -0800241 sp<IServiceManager> sm = defaultServiceManager();
242 sp<IBinder> binder = sm->getService(String16(keystore_service_name));
243 sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
244
Yi Konge353f252018-07-30 01:38:39 -0700245 if (service == nullptr) {
Janis Danisevskise5a09aa2018-08-09 11:13:51 -0700246 LOG(ERROR) << AT << "could not contact keystore";
Paul Stewartac0ffbf2017-03-03 16:43:33 -0800247 return -1;
248 }
249
Rob Barnesbb6cabd2018-10-04 17:10:37 -0600250 int32_t error_code;
251 android::sp<KeystoreExportPromise> promise(new KeystoreExportPromise);
252 auto future = promise->get_future();
253 auto binder_result = service->exportKey(
254 promise, String16(key_id), static_cast<int32_t>(KeyFormat::X509),
255 KeymasterBlob() /* clientId */, KeymasterBlob() /* appData */, UID_SELF, &error_code);
Janis Danisevskise5a09aa2018-08-09 11:13:51 -0700256 if (!binder_result.isOk()) {
257 LOG(ERROR) << AT << "communication error while calling keystore";
258 return -1;
259 }
Rob Barnesbb6cabd2018-10-04 17:10:37 -0600260
261 KSReturn rc(error_code);
262 if (!rc.isOk()) {
263 LOG(ERROR) << AT << "exportKey failed: " << error_code;
Paul Stewartac0ffbf2017-03-03 16:43:33 -0800264 return -1;
265 }
266
Rob Barnesbb6cabd2018-10-04 17:10:37 -0600267 auto export_result = future.get();
268 if (!export_result.resultCode.isOk()) {
269 LOG(ERROR) << AT << "exportKey failed: " << int32_t(export_result.resultCode);
270 return -1;
271 }
272
Janis Danisevskise5a09aa2018-08-09 11:13:51 -0700273 if (pubkey_len) {
Rob Barnesbb6cabd2018-10-04 17:10:37 -0600274 *pubkey_len = export_result.exportData.size();
Janis Danisevskise5a09aa2018-08-09 11:13:51 -0700275 }
276 if (pubkey) {
Rob Barnesbb6cabd2018-10-04 17:10:37 -0600277 *pubkey = export_result.exportData.releaseData();
Janis Danisevskise5a09aa2018-08-09 11:13:51 -0700278 }
Paul Stewartac0ffbf2017-03-03 16:43:33 -0800279 return 0;
280}