blob: cd407c84ad39b5fd15a020958eede52bb9094064 [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>
Dmitry Dementyeva447b3c2017-10-27 23:09:53 -070026#include <android/security/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>
31#include <keystore/OperationResult.h>
32#include <keystore/keymaster_types.h>
Paul Stewartac0ffbf2017-03-03 16:43:33 -080033#include <keystore/keystore.h>
Paul Stewartac0ffbf2017-03-03 16:43:33 -080034#include <keystore/keystore_hidl_support.h>
Janis Danisevskise5a09aa2018-08-09 11:13:51 -070035#include <keystore/keystore_return_types.h>
Paul Stewartac0ffbf2017-03-03 16:43:33 -080036
Dmitry Dementyeva447b3c2017-10-27 23:09:53 -070037using android::security::IKeystoreService;
Paul Stewartac0ffbf2017-03-03 16:43:33 -080038using namespace android;
Paul Stewartac0ffbf2017-03-03 16:43:33 -080039using keystore::hidl_vec;
40
Janis Danisevskise5a09aa2018-08-09 11:13:51 -070041using android::hardware::keymaster::V4_0::Algorithm;
42using android::hardware::keymaster::V4_0::authorizationValue;
43using android::hardware::keymaster::V4_0::Digest;
44using android::hardware::keymaster::V4_0::KeyFormat;
45using android::hardware::keymaster::V4_0::KeyParameter;
46using android::hardware::keymaster::V4_0::KeyPurpose;
47using android::hardware::keymaster::V4_0::NullOr;
48using android::hardware::keymaster::V4_0::PaddingMode;
49using android::hardware::keymaster::V4_0::TAG_ALGORITHM;
50using android::hardware::keymaster::V4_0::TAG_DIGEST;
51using android::hardware::keymaster::V4_0::TAG_PADDING;
52using android::security::keymaster::ExportResult;
53using android::security::keymaster::KeyCharacteristics;
54using android::security::keymaster::KeymasterArguments;
55using android::security::keymaster::KeymasterBlob;
56using android::security::keymaster::OperationResult;
57
58using KSReturn = keystore::KeyStoreNativeReturnCode;
59
Paul Stewartac0ffbf2017-03-03 16:43:33 -080060namespace {
61const char keystore_service_name[] = "android.security.keystore";
Janis Danisevskise5a09aa2018-08-09 11:13:51 -070062constexpr int32_t UID_SELF = -1;
Paul Stewartac0ffbf2017-03-03 16:43:33 -080063};
64
Janis Danisevskise5a09aa2018-08-09 11:13:51 -070065#define AT __func__ << ":" << __LINE__ << " "
66
67static NullOr<const Algorithm&> getKeyAlgoritmFromKeyCharacteristics(
68 const ::android::security::keymaster::KeyCharacteristics& characteristics) {
69 for (const auto& param : characteristics.hardwareEnforced.getParameters()) {
70 auto algo = authorizationValue(TAG_ALGORITHM, param);
71 if (algo.isOk()) return algo;
72 }
73 for (const auto& param : characteristics.softwareEnforced.getParameters()) {
74 auto algo = authorizationValue(TAG_ALGORITHM, param);
75 if (algo.isOk()) return algo;
76 }
77 return {};
78}
79
Dmitry Dementyeva447b3c2017-10-27 23:09:53 -070080int32_t KeystoreBackendBinder::sign(const char* key_id, const uint8_t* in, size_t len,
81 uint8_t** reply, size_t* reply_len) {
Paul Stewartac0ffbf2017-03-03 16:43:33 -080082 sp<IServiceManager> sm = defaultServiceManager();
83 sp<IBinder> binder = sm->getService(String16(keystore_service_name));
84 sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
85
Yi Konge353f252018-07-30 01:38:39 -070086 if (service == nullptr) {
Janis Danisevskise5a09aa2018-08-09 11:13:51 -070087 LOG(ERROR) << AT << "could not contact keystore";
Paul Stewartac0ffbf2017-03-03 16:43:33 -080088 return -1;
89 }
90
Janis Danisevskise5a09aa2018-08-09 11:13:51 -070091 KeyCharacteristics keyCharacteristics;
92 String16 key_name16(key_id);
93 int32_t aidl_result;
94 auto binder_result = service->getKeyCharacteristics(
95 key_name16, KeymasterBlob(), KeymasterBlob(), UID_SELF, &keyCharacteristics, &aidl_result);
96 if (!binder_result.isOk()) {
97 LOG(ERROR) << AT << "communication error while calling keystore";
98 return -1;
99 }
100 if (KSReturn(aidl_result).isOk()) {
101 LOG(ERROR) << AT << "getKeyCharacteristics failed: " << aidl_result;
102 }
103
104 auto algorithm = getKeyAlgoritmFromKeyCharacteristics(keyCharacteristics);
105 if (!algorithm.isOk()) {
106 LOG(ERROR) << AT << "could not get algorithm from key characteristics";
Paul Stewartac0ffbf2017-03-03 16:43:33 -0800107 return -1;
108 }
109
Janis Danisevskise5a09aa2018-08-09 11:13:51 -0700110 hidl_vec<KeyParameter> params(3);
111 params[0] = Authorization(TAG_DIGEST, Digest::NONE);
112 params[1] = Authorization(TAG_PADDING, PaddingMode::NONE);
113 params[2] = Authorization(TAG_ALGORITHM, algorithm.value());
114
115 android::sp<android::IBinder> token(new android::BBinder);
116 OperationResult result;
117 binder_result = service->begin(token, key_name16, (int)KeyPurpose::SIGN, true /*pruneable*/,
118 KeymasterArguments(params), std::vector<uint8_t>() /* entropy */,
119 UID_SELF, &result);
120 if (!binder_result.isOk()) {
121 LOG(ERROR) << AT << "communication error while calling keystore";
122 return -1;
123 }
124 if (!result.resultCode.isOk()) {
125 LOG(ERROR) << AT << "begin failed: " << int32_t(result.resultCode);
126 return -1;
127 }
128 auto handle = std::move(result.token);
129
130 do {
131 binder_result = service->update(handle, KeymasterArguments(params),
132 std::vector<uint8_t>(in, in + len), &result);
133 if (!binder_result.isOk()) {
134 LOG(ERROR) << AT << "communication error while calling keystore";
135 return -1;
136 }
137 if (!result.resultCode.isOk()) {
138 LOG(ERROR) << AT << "update failed: " << int32_t(result.resultCode);
139 return -1;
140 }
141 if (result.inputConsumed > len) {
142 LOG(ERROR) << AT << "update consumed more data than provided";
143 service->abort(handle, &aidl_result);
144 return -1;
145 }
146 len -= result.inputConsumed;
147 in += result.inputConsumed;
148 } while (len > 0);
149
150 binder_result =
151 service->finish(handle, KeymasterArguments(params), std::vector<uint8_t>() /* signature */,
152 std::vector<uint8_t>() /* entropy */, &result);
153 if (!binder_result.isOk()) {
154 LOG(ERROR) << AT << "communication error while calling keystore";
155 return -1;
156 }
157 if (!result.resultCode.isOk()) {
158 LOG(ERROR) << AT << "finish failed: " << int32_t(result.resultCode);
159 return -1;
160 }
161
162 hidl_vec<uint8_t> reply_hidl(result.data);
163 if (reply_len) {
164 *reply_len = reply_hidl.size();
165 }
166 if (reply) {
167 *reply = reply_hidl.releaseData();
168 }
Paul Stewartac0ffbf2017-03-03 16:43:33 -0800169 return 0;
170}
171
Dmitry Dementyeva447b3c2017-10-27 23:09:53 -0700172int32_t KeystoreBackendBinder::get_pubkey(const char* key_id, uint8_t** pubkey,
173 size_t* pubkey_len) {
Paul Stewartac0ffbf2017-03-03 16:43:33 -0800174 sp<IServiceManager> sm = defaultServiceManager();
175 sp<IBinder> binder = sm->getService(String16(keystore_service_name));
176 sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
177
Yi Konge353f252018-07-30 01:38:39 -0700178 if (service == nullptr) {
Janis Danisevskise5a09aa2018-08-09 11:13:51 -0700179 LOG(ERROR) << AT << "could not contact keystore";
Paul Stewartac0ffbf2017-03-03 16:43:33 -0800180 return -1;
181 }
182
Janis Danisevskise5a09aa2018-08-09 11:13:51 -0700183 ExportResult result;
184 auto binder_result = service->exportKey(String16(key_id), static_cast<int32_t>(KeyFormat::X509),
185 KeymasterBlob() /* clientId */,
186 KeymasterBlob() /* appData */, UID_SELF, &result);
187 if (!binder_result.isOk()) {
188 LOG(ERROR) << AT << "communication error while calling keystore";
189 return -1;
190 }
191 if (!result.resultCode.isOk()) {
192 LOG(ERROR) << AT << "exportKey failed: " << int32_t(result.resultCode);
Paul Stewartac0ffbf2017-03-03 16:43:33 -0800193 return -1;
194 }
195
Janis Danisevskise5a09aa2018-08-09 11:13:51 -0700196 hidl_vec<uint8_t> reply_hidl(result.exportData);
197 if (pubkey_len) {
198 *pubkey_len = reply_hidl.size();
199 }
200 if (pubkey) {
201 *pubkey = reply_hidl.releaseData();
202 }
Paul Stewartac0ffbf2017-03-03 16:43:33 -0800203 return 0;
204}