1 /* 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 25 #include <android-base/logging.h> 26 #include <android/security/keystore/IKeystoreService.h> 27 #include <binder/IServiceManager.h> 28 #include <binder/ProcessState.h> 29 #include <keystore/KeyCharacteristics.h> 30 #include <keystore/KeymasterArguments.h> 31 #include <keystore/KeymasterBlob.h> 32 #include <keystore/KeystoreResponse.h> 33 #include <keystore/OperationResult.h> 34 #include <keystore/keymaster_types.h> 35 #include <keystore/keystore.h> 36 #include <keystore/keystore_hidl_support.h> 37 #include <keystore/keystore_promises.h> 38 #include <keystore/keystore_return_types.h> 39 40 #include <future> 41 #include <thread> 42 43 using android::security::keystore::IKeystoreService; 44 using namespace android; 45 using keystore::hidl_vec; 46 47 using android::hardware::keymaster::V4_0::Algorithm; 48 using android::hardware::keymaster::V4_0::authorizationValue; 49 using android::hardware::keymaster::V4_0::Digest; 50 using android::hardware::keymaster::V4_0::KeyFormat; 51 using android::hardware::keymaster::V4_0::KeyParameter; 52 using android::hardware::keymaster::V4_0::KeyPurpose; 53 using android::hardware::keymaster::V4_0::NullOr; 54 using android::hardware::keymaster::V4_0::PaddingMode; 55 using android::hardware::keymaster::V4_0::TAG_ALGORITHM; 56 using android::hardware::keymaster::V4_0::TAG_DIGEST; 57 using android::hardware::keymaster::V4_0::TAG_PADDING; 58 using android::security::keymaster::ExportResult; 59 using android::security::keymaster::KeyCharacteristics; 60 using android::security::keymaster::KeymasterArguments; 61 using android::security::keymaster::KeymasterBlob; 62 using android::security::keymaster::OperationResult; 63 64 using KSReturn = keystore::KeyStoreNativeReturnCode; 65 66 namespace { 67 const char keystore_service_name[] = "android.security.keystore"; 68 constexpr int32_t UID_SELF = -1; 69 70 using keystore::KeyCharacteristicsPromise; 71 using keystore::KeystoreExportPromise; 72 using keystore::KeystoreResponsePromise; 73 using keystore::OperationResultPromise; 74 75 } // namespace 76 77 #define AT __func__ << ":" << __LINE__ << " " 78 79 static NullOr<const Algorithm&> getKeyAlgoritmFromKeyCharacteristics( 80 const ::android::security::keymaster::KeyCharacteristics& characteristics) { 81 for (const auto& param : characteristics.hardwareEnforced.getParameters()) { 82 auto algo = authorizationValue(TAG_ALGORITHM, param); 83 if (algo.isOk()) return algo; 84 } 85 for (const auto& param : characteristics.softwareEnforced.getParameters()) { 86 auto algo = authorizationValue(TAG_ALGORITHM, param); 87 if (algo.isOk()) return algo; 88 } 89 return {}; 90 } 91 92 KeystoreBackendBinder::KeystoreBackendBinder() { 93 android::ProcessState::self()->startThreadPool(); 94 } 95 96 int32_t KeystoreBackendBinder::sign(const char* key_id, const uint8_t* in, size_t len, 97 uint8_t** reply, size_t* reply_len) { 98 sp<IServiceManager> sm = defaultServiceManager(); 99 sp<IBinder> binder = sm->getService(String16(keystore_service_name)); 100 sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder); 101 102 if (service == nullptr) { 103 LOG(ERROR) << AT << "could not contact keystore"; 104 return -1; 105 } 106 107 String16 key_name16(key_id); 108 int32_t error_code; 109 android::sp<KeyCharacteristicsPromise> kc_promise(new KeyCharacteristicsPromise); 110 auto kc_future = kc_promise->get_future(); 111 auto binder_result = service->getKeyCharacteristics(kc_promise, key_name16, KeymasterBlob(), 112 KeymasterBlob(), UID_SELF, &error_code); 113 if (!binder_result.isOk()) { 114 LOG(ERROR) << AT << "communication error while calling keystore"; 115 return -1; 116 } 117 if (!KSReturn(error_code).isOk()) { 118 LOG(ERROR) << AT << "getKeyCharacteristics failed: " << error_code; 119 return -1; 120 } 121 122 auto [km_response, characteristics] = kc_future.get(); 123 124 if (!KSReturn(km_response.response_code()).isOk()) { 125 LOG(ERROR) << AT << "getKeyCharacteristics failed: " << km_response.response_code(); 126 return -1; 127 } 128 129 auto algorithm = getKeyAlgoritmFromKeyCharacteristics(characteristics); 130 if (!algorithm.isOk()) { 131 LOG(ERROR) << AT << "could not get algorithm from key characteristics"; 132 return -1; 133 } 134 135 hidl_vec<KeyParameter> params(3); 136 params[0] = Authorization(TAG_DIGEST, Digest::NONE); 137 params[1] = Authorization(TAG_PADDING, PaddingMode::NONE); 138 params[2] = Authorization(TAG_ALGORITHM, algorithm.value()); 139 140 android::sp<android::IBinder> token(new android::BBinder); 141 sp<OperationResultPromise> promise(new OperationResultPromise()); 142 auto future = promise->get_future(); 143 binder_result = service->begin(promise, token, key_name16, (int)KeyPurpose::SIGN, 144 true /*pruneable*/, KeymasterArguments(params), 145 std::vector<uint8_t>() /* entropy */, UID_SELF, &error_code); 146 if (!binder_result.isOk()) { 147 LOG(ERROR) << AT << "communication error while calling keystore"; 148 return -1; 149 } 150 151 keystore::KeyStoreNativeReturnCode rc(error_code); 152 if (!rc.isOk()) { 153 LOG(ERROR) << AT << "Keystore begin returned: " << error_code; 154 return -1; 155 } 156 OperationResult result = future.get(); 157 158 if (!result.resultCode.isOk()) { 159 LOG(ERROR) << AT << "begin failed: " << result.resultCode; 160 return -1; 161 } 162 auto handle = std::move(result.token); 163 164 do { 165 future = {}; 166 promise = new OperationResultPromise(); 167 future = promise->get_future(); 168 binder_result = service->update(promise, handle, KeymasterArguments(params), 169 std::vector<uint8_t>(in, in + len), &error_code); 170 if (!binder_result.isOk()) { 171 LOG(ERROR) << AT << "communication error while calling keystore"; 172 return -1; 173 } 174 175 rc = keystore::KeyStoreNativeReturnCode(error_code); 176 if (!rc.isOk()) { 177 LOG(ERROR) << AT << "Keystore update returned: " << error_code; 178 return -1; 179 } 180 result = future.get(); 181 182 if (!result.resultCode.isOk()) { 183 LOG(ERROR) << AT << "update failed: " << result.resultCode; 184 return -1; 185 } 186 187 if (result.inputConsumed > len) { 188 LOG(ERROR) << AT << "update consumed more data than provided"; 189 sp<KeystoreResponsePromise> abortPromise(new KeystoreResponsePromise); 190 auto abortFuture = abortPromise->get_future(); 191 binder_result = service->abort(abortPromise, handle, &error_code); 192 if (!binder_result.isOk()) { 193 LOG(ERROR) << AT << "communication error while calling keystore"; 194 return -1; 195 } 196 // This is mainly for logging since we already failed. 197 // But if abort returned OK we have to wait untill abort calls the callback 198 // hence the call to abortFuture.get(). 199 if (!KSReturn(error_code).isOk()) { 200 LOG(ERROR) << AT << "abort failed: " << error_code; 201 } else if (!(rc = KSReturn(abortFuture.get().response_code())).isOk()) { 202 LOG(ERROR) << AT << "abort failed: " << rc; 203 } 204 return -1; 205 } 206 len -= result.inputConsumed; 207 in += result.inputConsumed; 208 } while (len > 0); 209 210 future = {}; 211 promise = new OperationResultPromise(); 212 future = promise->get_future(); 213 214 binder_result = service->finish( 215 promise, handle, KeymasterArguments(params), std::vector<uint8_t>() /* input */, 216 std::vector<uint8_t>() /* signature */, std::vector<uint8_t>() /* entropy */, &error_code); 217 218 if (!binder_result.isOk()) { 219 LOG(ERROR) << AT << "communication error while calling keystore"; 220 return -1; 221 } 222 223 rc = keystore::KeyStoreNativeReturnCode(error_code); 224 if (!rc.isOk()) { 225 LOG(ERROR) << AT << "Keystore finish returned: " << error_code; 226 return -1; 227 } 228 result = future.get(); 229 230 if (!result.resultCode.isOk()) { 231 LOG(ERROR) << AT << "finish failed: " << result.resultCode; 232 return -1; 233 } 234 235 hidl_vec<uint8_t> reply_hidl(result.data); 236 if (reply_len) { 237 *reply_len = reply_hidl.size(); 238 } 239 if (reply) { 240 *reply = reply_hidl.releaseData(); 241 } 242 return 0; 243 } 244 245 int32_t KeystoreBackendBinder::get_pubkey(const char* key_id, uint8_t** pubkey, 246 size_t* pubkey_len) { 247 sp<IServiceManager> sm = defaultServiceManager(); 248 sp<IBinder> binder = sm->getService(String16(keystore_service_name)); 249 sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder); 250 251 if (service == nullptr) { 252 LOG(ERROR) << AT << "could not contact keystore"; 253 return -1; 254 } 255 256 int32_t error_code; 257 android::sp<KeystoreExportPromise> promise(new KeystoreExportPromise); 258 auto future = promise->get_future(); 259 auto binder_result = service->exportKey( 260 promise, String16(key_id), static_cast<int32_t>(KeyFormat::X509), 261 KeymasterBlob() /* clientId */, KeymasterBlob() /* appData */, UID_SELF, &error_code); 262 if (!binder_result.isOk()) { 263 LOG(ERROR) << AT << "communication error while calling keystore"; 264 return -1; 265 } 266 267 KSReturn rc(error_code); 268 if (!rc.isOk()) { 269 LOG(ERROR) << AT << "exportKey failed: " << error_code; 270 return -1; 271 } 272 273 auto export_result = future.get(); 274 if (!export_result.resultCode.isOk()) { 275 LOG(ERROR) << AT << "exportKey failed: " << export_result.resultCode; 276 return -1; 277 } 278 279 if (pubkey_len) { 280 *pubkey_len = export_result.exportData.size(); 281 } 282 if (pubkey) { 283 *pubkey = export_result.exportData.releaseData(); 284 } 285 return 0; 286 } 287