diff --git a/keystore-engine/Android.mk b/keystore-engine/Android.mk index e65e011d..e182dbdd 100644 --- a/keystore-engine/Android.mk +++ b/keystore-engine/Android.mk @@ -24,6 +24,7 @@ LOCAL_SRC_FILES := \ LOCAL_MODULE_TAGS := optional LOCAL_CFLAGS := -fvisibility=hidden -Wall -Werror +LOCAL_CPPFLAGS += -std=c++17 LOCAL_SHARED_LIBRARIES += \ libbinder \ @@ -53,6 +54,7 @@ LOCAL_SRC_FILES := \ LOCAL_MODULE_TAGS := optional LOCAL_CFLAGS := -fvisibility=hidden -Wall -Werror -DBACKEND_WIFI_HIDL +LOCAL_CPPFLAGS += -std=c++17 LOCAL_SHARED_LIBRARIES += \ android.system.wifi.keystore@1.0 \ diff --git a/keystore-engine/android_engine.cpp b/keystore-engine/android_engine.cpp index fba2583d..856194d0 100644 --- a/keystore-engine/android_engine.cpp +++ b/keystore-engine/android_engine.cpp @@ -80,8 +80,7 @@ void key_id_free(void* /* parent */, * the argument on failure. This means we need to tell our scoped pointers when * we've transferred ownership, without triggering a warning by not using the * result of release(). */ -#define OWNERSHIP_TRANSFERRED(obj) \ - typeof ((obj).release()) _dummy __attribute__((unused)) = (obj).release() +#define OWNERSHIP_TRANSFERRED(obj) auto _dummy __attribute__((unused)) = (obj).release() const char* rsa_get_key_id(const RSA* rsa); diff --git a/keystore-engine/keystore_backend_binder.cpp b/keystore-engine/keystore_backend_binder.cpp index cd407c84..0e38b50e 100644 --- a/keystore-engine/keystore_backend_binder.cpp +++ b/keystore-engine/keystore_backend_binder.cpp @@ -23,18 +23,22 @@ #include "keystore_backend_binder.h" #include -#include +#include #include #include #include #include +#include #include #include #include #include +#include #include -using android::security::IKeystoreService; +#include + +using android::security::keystore::IKeystoreService; using namespace android; using keystore::hidl_vec; @@ -60,7 +64,13 @@ using KSReturn = keystore::KeyStoreNativeReturnCode; namespace { const char keystore_service_name[] = "android.security.keystore"; constexpr int32_t UID_SELF = -1; -}; + +using keystore::KeyCharacteristicsPromise; +using keystore::KeystoreExportPromise; +using keystore::KeystoreResponsePromise; +using keystore::OperationResultPromise; + +} // namespace #define AT __func__ << ":" << __LINE__ << " " @@ -88,20 +98,29 @@ int32_t KeystoreBackendBinder::sign(const char* key_id, const uint8_t* in, size_ return -1; } - KeyCharacteristics keyCharacteristics; String16 key_name16(key_id); - int32_t aidl_result; - auto binder_result = service->getKeyCharacteristics( - key_name16, KeymasterBlob(), KeymasterBlob(), UID_SELF, &keyCharacteristics, &aidl_result); + int32_t error_code; + android::sp kc_promise(new KeyCharacteristicsPromise); + auto kc_future = kc_promise->get_future(); + auto binder_result = service->getKeyCharacteristics(kc_promise, key_name16, KeymasterBlob(), + KeymasterBlob(), UID_SELF, &error_code); if (!binder_result.isOk()) { LOG(ERROR) << AT << "communication error while calling keystore"; return -1; } - if (KSReturn(aidl_result).isOk()) { - LOG(ERROR) << AT << "getKeyCharacteristics failed: " << aidl_result; + if (KSReturn(error_code).isOk()) { + LOG(ERROR) << AT << "getKeyCharacteristics failed: " << error_code; + return -1; } - auto algorithm = getKeyAlgoritmFromKeyCharacteristics(keyCharacteristics); + auto [km_response, characteristics] = kc_future.get(); + + if (KSReturn(km_response.response_code()).isOk()) { + LOG(ERROR) << AT << "getKeyCharacteristics failed: " << km_response.response_code(); + return -1; + } + + auto algorithm = getKeyAlgoritmFromKeyCharacteristics(characteristics); if (!algorithm.isOk()) { LOG(ERROR) << AT << "could not get algorithm from key characteristics"; return -1; @@ -113,14 +132,23 @@ int32_t KeystoreBackendBinder::sign(const char* key_id, const uint8_t* in, size_ params[2] = Authorization(TAG_ALGORITHM, algorithm.value()); android::sp token(new android::BBinder); - OperationResult result; - binder_result = service->begin(token, key_name16, (int)KeyPurpose::SIGN, true /*pruneable*/, - KeymasterArguments(params), std::vector() /* entropy */, - UID_SELF, &result); + sp promise(new OperationResultPromise()); + auto future = promise->get_future(); + binder_result = service->begin(promise, token, key_name16, (int)KeyPurpose::SIGN, + true /*pruneable*/, KeymasterArguments(params), + std::vector() /* entropy */, UID_SELF, &error_code); if (!binder_result.isOk()) { LOG(ERROR) << AT << "communication error while calling keystore"; return -1; } + + keystore::KeyStoreNativeReturnCode rc(error_code); + if (!rc.isOk()) { + LOG(ERROR) << AT << "Keystore begin returned: " << error_code; + return -1; + } + OperationResult result = future.get(); + if (!result.resultCode.isOk()) { LOG(ERROR) << AT << "begin failed: " << int32_t(result.resultCode); return -1; @@ -128,32 +156,71 @@ int32_t KeystoreBackendBinder::sign(const char* key_id, const uint8_t* in, size_ auto handle = std::move(result.token); do { - binder_result = service->update(handle, KeymasterArguments(params), - std::vector(in, in + len), &result); + future = {}; + promise = new OperationResultPromise(); + future = promise->get_future(); + binder_result = service->update(promise, handle, KeymasterArguments(params), + std::vector(in, in + len), &error_code); if (!binder_result.isOk()) { LOG(ERROR) << AT << "communication error while calling keystore"; return -1; } + + rc = keystore::KeyStoreNativeReturnCode(error_code); + if (!rc.isOk()) { + LOG(ERROR) << AT << "Keystore update returned: " << error_code; + return -1; + } + result = future.get(); + if (!result.resultCode.isOk()) { LOG(ERROR) << AT << "update failed: " << int32_t(result.resultCode); return -1; } + if (result.inputConsumed > len) { LOG(ERROR) << AT << "update consumed more data than provided"; - service->abort(handle, &aidl_result); + sp abortPromise(new KeystoreResponsePromise); + auto abortFuture = abortPromise->get_future(); + binder_result = service->abort(abortPromise, handle, &error_code); + if (!binder_result.isOk()) { + LOG(ERROR) << AT << "communication error while calling keystore"; + return -1; + } + // This is mainly for logging since we already failed. + // But if abort returned OK we have to wait untill abort calls the callback + // hence the call to abortFuture.get(). + if (!KSReturn(error_code).isOk()) { + LOG(ERROR) << AT << "abort failed: " << error_code; + } else if (!(rc = KSReturn(abortFuture.get().response_code())).isOk()) { + LOG(ERROR) << AT << "abort failed: " << int32_t(rc); + } return -1; } len -= result.inputConsumed; in += result.inputConsumed; } while (len > 0); - binder_result = - service->finish(handle, KeymasterArguments(params), std::vector() /* signature */, - std::vector() /* entropy */, &result); + future = {}; + promise = new OperationResultPromise(); + future = promise->get_future(); + + binder_result = service->finish(promise, handle, KeymasterArguments(params), + std::vector() /* signature */, + std::vector() /* entropy */, &error_code); + if (!binder_result.isOk()) { LOG(ERROR) << AT << "communication error while calling keystore"; return -1; } + + rc = keystore::KeyStoreNativeReturnCode(error_code); + if (!rc.isOk()) { + LOG(ERROR) << AT << "Keystore finish returned: " << error_code; + return -1; + } + result = future.get(); + if (!result.resultCode.isOk()) { LOG(ERROR) << AT << "finish failed: " << int32_t(result.resultCode); return -1; @@ -180,25 +247,34 @@ int32_t KeystoreBackendBinder::get_pubkey(const char* key_id, uint8_t** pubkey, return -1; } - ExportResult result; - auto binder_result = service->exportKey(String16(key_id), static_cast(KeyFormat::X509), - KeymasterBlob() /* clientId */, - KeymasterBlob() /* appData */, UID_SELF, &result); + int32_t error_code; + android::sp promise(new KeystoreExportPromise); + auto future = promise->get_future(); + auto binder_result = service->exportKey( + promise, String16(key_id), static_cast(KeyFormat::X509), + KeymasterBlob() /* clientId */, KeymasterBlob() /* appData */, UID_SELF, &error_code); if (!binder_result.isOk()) { LOG(ERROR) << AT << "communication error while calling keystore"; return -1; } - if (!result.resultCode.isOk()) { - LOG(ERROR) << AT << "exportKey failed: " << int32_t(result.resultCode); + + KSReturn rc(error_code); + if (!rc.isOk()) { + LOG(ERROR) << AT << "exportKey failed: " << error_code; + return -1; + } + + auto export_result = future.get(); + if (!export_result.resultCode.isOk()) { + LOG(ERROR) << AT << "exportKey failed: " << int32_t(export_result.resultCode); return -1; } - hidl_vec reply_hidl(result.exportData); if (pubkey_len) { - *pubkey_len = reply_hidl.size(); + *pubkey_len = export_result.exportData.size(); } if (pubkey) { - *pubkey = reply_hidl.releaseData(); + *pubkey = export_result.exportData.releaseData(); } return 0; } diff --git a/keystore/Android.bp b/keystore/Android.bp index 1168e909..295d6055 100644 --- a/keystore/Android.bp +++ b/keystore/Android.bp @@ -139,10 +139,10 @@ cc_library_shared { "KeyAttestationApplicationId.cpp", "KeyAttestationPackageInfo.cpp", "KeymasterArguments.cpp", - "KeystoreArguments.cpp", + "keystore_aidl_hidl_marshalling_utils.cpp", + "KeystoreResponse.cpp", "OperationResult.cpp", "Signature.cpp", - "keystore_aidl_hidl_marshalling_utils.cpp", ], shared_libs: [ "android.hardware.keymaster@4.0", @@ -269,7 +269,12 @@ filegroup { name: "keystore_aidl", srcs: [ "binder/android/security/IConfirmationPromptCallback.aidl", - "binder/android/security/IKeystoreService.aidl", + "binder/android/security/keystore/IKeystoreCertificateChainCallback.aidl", + "binder/android/security/keystore/IKeystoreExportKeyCallback.aidl", + "binder/android/security/keystore/IKeystoreKeyCharacteristicsCallback.aidl", + "binder/android/security/keystore/IKeystoreOperationResultCallback.aidl", + "binder/android/security/keystore/IKeystoreResponseCallback.aidl", + "binder/android/security/keystore/IKeystoreService.aidl", ], path: "binder", } diff --git a/keystore/KeyStore.cpp b/keystore/KeyStore.cpp index 8c4844fd..75302435 100644 --- a/keystore/KeyStore.cpp +++ b/keystore/KeyStore.cpp @@ -28,7 +28,7 @@ #include #include -#include +#include #include #include diff --git a/keystore/KeystoreArguments.cpp b/keystore/KeystoreArguments.cpp deleted file mode 100644 index 6b29e786..00000000 --- a/keystore/KeystoreArguments.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* -** -** Copyright 2017, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#include "include/keystore/KeystoreArguments.h" -#include "keystore_aidl_hidl_marshalling_utils.h" - -#include - -namespace android { -namespace security { - -using ::android::security::KeystoreArg; -using ::android::security::KeystoreArguments; - -const ssize_t MAX_GENERATE_ARGS = 3; -status_t KeystoreArguments::readFromParcel(const android::Parcel* in) { - ssize_t numArgs = in->readInt32(); - if (numArgs > MAX_GENERATE_ARGS) { - return BAD_VALUE; - } - if (numArgs > 0) { - for (size_t i = 0; i < static_cast(numArgs); i++) { - ssize_t inSize = in->readInt32(); - if (inSize >= 0 && static_cast(inSize) <= in->dataAvail()) { - sp arg = new KeystoreArg(in->readInplace(inSize), inSize); - args.push_back(arg); - } else { - args.push_back(nullptr); - } - } - } - return OK; -}; - -status_t KeystoreArguments::writeToParcel(android::Parcel* out) const { - out->writeInt32(args.size()); - for (sp item : args) { - size_t keyLength = item->size(); - out->writeInt32(keyLength); - void* buf = out->writeInplace(keyLength); - memcpy(buf, item->data(), keyLength); - } - return OK; -} - -} // namespace security -} // namespace android diff --git a/keystore/KeystoreResponse.cpp b/keystore/KeystoreResponse.cpp new file mode 100644 index 00000000..c46973a5 --- /dev/null +++ b/keystore/KeystoreResponse.cpp @@ -0,0 +1,43 @@ +/* +** +** Copyright 2018, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#include +#include +#include +#include + +#include "include/keystore/KeystoreResponse.h" + +namespace android { +namespace security { +namespace keystore { + +status_t KeystoreResponse::readFromParcel(const Parcel* in) { + auto rc = in->readInt32(&response_code_); + if (rc != NO_ERROR) return rc; + return in->readString16(&error_msg_); +} + +status_t KeystoreResponse::writeToParcel(Parcel* out) const { + auto rc = out->writeInt32(response_code_); + if (rc != NO_ERROR) return rc; + return out->writeString16(error_msg_); +} + +} // namespace keystore +} // namespace security +} // namespace android diff --git a/keystore/binder/android/security/keystore/IKeystoreCertificateChainCallback.aidl b/keystore/binder/android/security/keystore/IKeystoreCertificateChainCallback.aidl new file mode 100644 index 00000000..dca928d9 --- /dev/null +++ b/keystore/binder/android/security/keystore/IKeystoreCertificateChainCallback.aidl @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2018, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.keystore; + +import android.security.keystore.KeystoreResponse; +import android.security.keymaster.KeymasterCertificateChain; + +/** + * @hide + */ +oneway interface IKeystoreCertificateChainCallback { + void onFinished(in KeystoreResponse response, in KeymasterCertificateChain chain); +} \ No newline at end of file diff --git a/keystore/binder/android/security/keystore/IKeystoreExportKeyCallback.aidl b/keystore/binder/android/security/keystore/IKeystoreExportKeyCallback.aidl new file mode 100644 index 00000000..e42e9274 --- /dev/null +++ b/keystore/binder/android/security/keystore/IKeystoreExportKeyCallback.aidl @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2018, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.keystore; + +import android.security.keystore.KeystoreResponse; +import android.security.keymaster.ExportResult; + +/** + * @hide + */ +oneway interface IKeystoreExportKeyCallback { + void onFinished(in ExportResult result); +} \ No newline at end of file diff --git a/keystore/binder/android/security/keystore/IKeystoreKeyCharacteristicsCallback.aidl b/keystore/binder/android/security/keystore/IKeystoreKeyCharacteristicsCallback.aidl new file mode 100644 index 00000000..e1f0ffed --- /dev/null +++ b/keystore/binder/android/security/keystore/IKeystoreKeyCharacteristicsCallback.aidl @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2018, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.keystore; + +import android.security.keystore.KeystoreResponse; +import android.security.keymaster.KeyCharacteristics; + +/** + * @hide + */ +oneway interface IKeystoreKeyCharacteristicsCallback { + void onFinished(in KeystoreResponse response, in KeyCharacteristics charactersistics); +} \ No newline at end of file diff --git a/keystore/binder/android/security/keystore/IKeystoreOperationResultCallback.aidl b/keystore/binder/android/security/keystore/IKeystoreOperationResultCallback.aidl new file mode 100644 index 00000000..0a515113 --- /dev/null +++ b/keystore/binder/android/security/keystore/IKeystoreOperationResultCallback.aidl @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2018, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.keystore; + +import android.security.keystore.KeystoreResponse; +import android.security.keymaster.OperationResult; + +/** + * @hide + */ +oneway interface IKeystoreOperationResultCallback { + void onFinished(in OperationResult result); +} \ No newline at end of file diff --git a/keystore/binder/android/security/keystore/IKeystoreResponseCallback.aidl b/keystore/binder/android/security/keystore/IKeystoreResponseCallback.aidl new file mode 100644 index 00000000..912e6054 --- /dev/null +++ b/keystore/binder/android/security/keystore/IKeystoreResponseCallback.aidl @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2018, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.keystore; + +import android.security.keystore.KeystoreResponse; + +/** + * @hide + */ +oneway interface IKeystoreResponseCallback { + void onFinished(in KeystoreResponse response); +} \ No newline at end of file diff --git a/keystore/binder/android/security/IKeystoreService.aidl b/keystore/binder/android/security/keystore/IKeystoreService.aidl similarity index 53% rename from keystore/binder/android/security/IKeystoreService.aidl rename to keystore/binder/android/security/keystore/IKeystoreService.aidl index c490eda8..a7601388 100644 --- a/keystore/binder/android/security/IKeystoreService.aidl +++ b/keystore/binder/android/security/keystore/IKeystoreService.aidl @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015, The Android Open Source Project + * Copyright (c) 2018, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,20 +14,18 @@ * limitations under the License. */ -package android.security; +package android.security.keystore; -import android.security.keymaster.ExportResult; -import android.security.keymaster.KeyCharacteristics; import android.security.keymaster.KeymasterArguments; -import android.security.keymaster.KeymasterCertificateChain; import android.security.keymaster.KeymasterBlob; import android.security.keymaster.OperationResult; -import android.security.KeystoreArguments; +import android.security.keystore.IKeystoreResponseCallback; +import android.security.keystore.IKeystoreKeyCharacteristicsCallback; +import android.security.keystore.IKeystoreExportKeyCallback; +import android.security.keystore.IKeystoreOperationResultCallback; +import android.security.keystore.IKeystoreCertificateChainCallback; /** - * This must be kept manually in sync with system/security/keystore until AIDL - * can generate both Java and C++ bindings. - * * @hide */ interface IKeystoreService { @@ -48,32 +46,30 @@ interface IKeystoreService { int is_hardware_backed(String string); int clear_uid(long uid); - // Keymaster 0.4 methods - int addRngEntropy(in byte[] data, int flags); - int generateKey(String alias, in KeymasterArguments arguments, in byte[] entropy, int uid, - int flags, out KeyCharacteristics characteristics); - int getKeyCharacteristics(String alias, in KeymasterBlob clientId, in KeymasterBlob appData, - int uid, out KeyCharacteristics characteristics); - int importKey(String alias, in KeymasterArguments arguments, int format, - in byte[] keyData, int uid, int flags, out KeyCharacteristics characteristics); - ExportResult exportKey(String alias, int format, in KeymasterBlob clientId, + int addRngEntropy(IKeystoreResponseCallback cb, in byte[] data, int flags); + int generateKey(IKeystoreKeyCharacteristicsCallback cb, String alias, in KeymasterArguments arguments, in byte[] entropy, int uid, + int flags); + int getKeyCharacteristics (IKeystoreKeyCharacteristicsCallback cb, String alias, in KeymasterBlob clientId, in KeymasterBlob appData, + int uid); + int importKey(IKeystoreKeyCharacteristicsCallback cb, String alias, in KeymasterArguments arguments, int format, + in byte[] keyData, int uid, int flags); + int exportKey(IKeystoreExportKeyCallback cb, String alias, int format, in KeymasterBlob clientId, in KeymasterBlob appData, int uid); - OperationResult begin(IBinder appToken, String alias, int purpose, boolean pruneable, + int begin(in IKeystoreOperationResultCallback cb, IBinder appToken, String alias, int purpose, boolean pruneable, in KeymasterArguments params, in byte[] entropy, int uid); - OperationResult update(IBinder token, in KeymasterArguments params, in byte[] input); - OperationResult finish(IBinder token, in KeymasterArguments params, in byte[] signature, + int update(in IKeystoreOperationResultCallback cb, IBinder token, in KeymasterArguments params, in byte[] input); + int finish(in IKeystoreOperationResultCallback cb, IBinder token, in KeymasterArguments params, in byte[] signature, in byte[] entropy); - int abort(IBinder handle); + int abort(in IKeystoreResponseCallback cb, IBinder token); int addAuthToken(in byte[] authToken); int onUserAdded(int userId, int parentId); int onUserRemoved(int userId); - int attestKey(String alias, in KeymasterArguments params, out KeymasterCertificateChain chain); - int attestDeviceIds(in KeymasterArguments params, out KeymasterCertificateChain chain); + int attestKey(in IKeystoreCertificateChainCallback cb, String alias, in KeymasterArguments params); + int attestDeviceIds(in IKeystoreCertificateChainCallback cb, in KeymasterArguments params); int onDeviceOffBody(); - int importWrappedKey(in String wrappedKeyAlias, in byte[] wrappedKey, + int importWrappedKey(in IKeystoreKeyCharacteristicsCallback cb, String wrappedKeyAlias, in byte[] wrappedKey, in String wrappingKeyAlias, in byte[] maskingKey, in KeymasterArguments arguments, - in long rootSid, in long fingerprintSid, - out KeyCharacteristics characteristics); + in long rootSid, in long fingerprintSid); int presentConfirmationPrompt(IBinder listener, String promptText, in byte[] extraData, in String locale, in int uiOptionsAsFlags); int cancelConfirmationPrompt(IBinder listener); diff --git a/keystore/binder/android/security/KeystoreArguments.aidl b/keystore/binder/android/security/keystore/KeystoreResponse.aidl similarity index 71% rename from keystore/binder/android/security/KeystoreArguments.aidl rename to keystore/binder/android/security/keystore/KeystoreResponse.aidl index dc8ed501..128b4569 100644 --- a/keystore/binder/android/security/KeystoreArguments.aidl +++ b/keystore/binder/android/security/keystore/KeystoreResponse.aidl @@ -1,11 +1,11 @@ -/** - * Copyright (c) 2015, The Android Open Source Project +/* + * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.security; +package android.security.keystore; /* @hide */ -parcelable KeystoreArguments cpp_header "keystore/KeystoreArguments.h"; +parcelable KeystoreResponse cpp_header "keystore/KeystoreResponse.h"; diff --git a/keystore/include/keystore/KeyCharacteristics.h b/keystore/include/keystore/KeyCharacteristics.h index 33c5c3a6..40d495c6 100644 --- a/keystore/include/keystore/KeyCharacteristics.h +++ b/keystore/include/keystore/KeyCharacteristics.h @@ -27,11 +27,11 @@ namespace keymaster { // Parcelable version of keystore::KeyCharacteristics struct KeyCharacteristics : public ::android::Parcelable { KeyCharacteristics(){}; - KeyCharacteristics(keystore::KeyCharacteristics&& other) { + KeyCharacteristics(::keystore::KeyCharacteristics&& other) { softwareEnforced = std::move(other.softwareEnforced); hardwareEnforced = std::move(other.hardwareEnforced); } - explicit KeyCharacteristics(const keystore::KeyCharacteristics& other) { + explicit KeyCharacteristics(const ::keystore::KeyCharacteristics& other) { softwareEnforced = KeymasterArguments(other.softwareEnforced); hardwareEnforced = KeymasterArguments(other.hardwareEnforced); } diff --git a/keystore/include/keystore/KeymasterArguments.h b/keystore/include/keystore/KeymasterArguments.h index fb35ee7b..b453b113 100644 --- a/keystore/include/keystore/KeymasterArguments.h +++ b/keystore/include/keystore/KeymasterArguments.h @@ -26,16 +26,18 @@ namespace keymaster { // struct for serializing/deserializing a list of KeyParameters struct KeymasterArguments : public Parcelable { KeymasterArguments(){}; - KeymasterArguments(hardware::hidl_vec&& other); - explicit KeymasterArguments(const hardware::hidl_vec& other); + KeymasterArguments(hardware::hidl_vec<::keystore::KeyParameter>&& other); + explicit KeymasterArguments(const hardware::hidl_vec<::keystore::KeyParameter>& other); status_t readFromParcel(const Parcel* in) override; status_t writeToParcel(Parcel* out) const override; - const inline hardware::hidl_vec& getParameters() const { return data_; } + const inline hardware::hidl_vec<::keystore::KeyParameter>& getParameters() const { + return data_; + } private: - hardware::hidl_vec data_; + hardware::hidl_vec<::keystore::KeyParameter> data_; }; } // namespace keymaster diff --git a/keystore/include/keystore/KeymasterCertificateChain.h b/keystore/include/keystore/KeymasterCertificateChain.h index 132862c3..f251d084 100644 --- a/keystore/include/keystore/KeymasterCertificateChain.h +++ b/keystore/include/keystore/KeymasterCertificateChain.h @@ -16,6 +16,7 @@ #define KEYSTORE_INCLUDE_KEYSTORE_KEYMASTERCERTIFICATECHAIN_H_ #include +#include namespace android { namespace security { diff --git a/keystore/include/keystore/KeystoreArg.h b/keystore/include/keystore/KeystoreArg.h deleted file mode 100644 index a5e68f2b..00000000 --- a/keystore/include/keystore/KeystoreArg.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef KEYSTORE_INCLUDE_KEYSTORE_KEYSTOREARG_H -#define KEYSTORE_INCLUDE_KEYSTORE_KEYSTOREARG_H - -#include - -namespace android { -namespace security { - -// Simple pair of generic pointer and length of corresponding data structure. -class KeystoreArg : public RefBase { - public: - KeystoreArg(const void* data, size_t len) : mData(data), mSize(len) {} - ~KeystoreArg() {} - - const void* data() const { return mData; } - size_t size() const { return mSize; } - - private: - const void* mData; // provider of the data must handle memory clean-up. - size_t mSize; -}; - -} // namespace security -} // namespace android - -#endif // KEYSTORE_INCLUDE_KEYSTORE_KEYSTOREARG_H diff --git a/keystore/include/keystore/KeystoreArguments.h b/keystore/include/keystore/KeystoreArguments.h deleted file mode 100644 index c0a8b0a2..00000000 --- a/keystore/include/keystore/KeystoreArguments.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2017 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef KEYSTORE_INCLUDE_KEYSTORE_KEYSTOREARGUMENTS_H_ -#define KEYSTORE_INCLUDE_KEYSTORE_KEYSTOREARGUMENTS_H_ - -#include -#include -#include - -#include "KeystoreArg.h" -#include "keystore_return_types.h" - -namespace android { -namespace security { - -// Parcelable KeystoreArguments.java which simply holds byte[][]. -struct KeystoreArguments : public ::android::Parcelable, public RefBase { - status_t readFromParcel(const Parcel* in) override; - status_t writeToParcel(Parcel* out) const override; - - const Vector>& getArguments() const { return args; } - - private: - Vector> args; -}; - -} // namespace security -} // namespace android - -#endif // KEYSTORE_INCLUDE_KEYSTORE_KEYSTOREARGUMENTS_H_ diff --git a/keystore/include/keystore/KeystoreResponse.h b/keystore/include/keystore/KeystoreResponse.h new file mode 100644 index 00000000..f8925851 --- /dev/null +++ b/keystore/include/keystore/KeystoreResponse.h @@ -0,0 +1,62 @@ +// Copyright 2018 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef KEYSTORE_INCLUDE_KEYSTORE_RESPONSE_H_ +#define KEYSTORE_INCLUDE_KEYSTORE_RESPONSE_H_ + +#include +#include +#include + +#include "keystore_return_types.h" + +namespace android { +namespace security { +namespace keystore { + +// struct for holding response code and optionally an error message for keystore +// AIDL callbacks +struct KeystoreResponse : public ::android::Parcelable { + public: + KeystoreResponse() = default; + explicit KeystoreResponse(const int response_code, const String16& error_msg) + : response_code_(response_code), error_msg_(std::make_unique(error_msg)) {} + explicit KeystoreResponse(const int response_code) + : response_code_(response_code), error_msg_() {} + KeystoreResponse(const ::keystore::KeyStoreServiceReturnCode& rc) + : response_code_(int32_t(rc)), error_msg_() {} + KeystoreResponse(const KeystoreResponse& other) + : response_code_(other.response_code_), error_msg_() { + if (other.error_msg_) { + error_msg_ = std::make_unique(*other.error_msg_); + } + } + KeystoreResponse(KeystoreResponse&& other) = default; + + status_t readFromParcel(const Parcel* in) override; + status_t writeToParcel(Parcel* out) const override; + + int response_code() const { return response_code_; } + const String16* error_msg() const { return error_msg_.get(); } + + private: + int response_code_; + std::unique_ptr error_msg_; +}; + +} // namespace keystore +} // namespace security +} // namespace android + +#endif // KEYSTORE_INCLUDE_KEYSTORE_RESPONSE_H_ diff --git a/keystore/include/keystore/keystore_client_impl.h b/keystore/include/keystore/keystore_client_impl.h index 9edd0824..0bcef98c 100644 --- a/keystore/include/keystore/keystore_client_impl.h +++ b/keystore/include/keystore/keystore_client_impl.h @@ -17,11 +17,12 @@ #include "keystore_client.h" +#include #include #include #include -#include +#include #include #include #include @@ -109,7 +110,7 @@ class KeystoreClientImpl : public KeystoreClient { android::sp service_manager_; android::sp keystore_binder_; - android::sp keystore_; + android::sp keystore_; uint64_t next_virtual_handle_ = 1; std::map> active_operations_; diff --git a/keystore/include/keystore/keystore_promises.h b/keystore/include/keystore/keystore_promises.h new file mode 100644 index 00000000..3d45016e --- /dev/null +++ b/keystore/include/keystore/keystore_promises.h @@ -0,0 +1,72 @@ +/* +** +** Copyright 2018, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#ifndef KEYSTORE_INCLUDE_KEYSTORE_KEYSTORE_PROMISES_H_ +#define KEYSTORE_INCLUDE_KEYSTORE_KEYSTORE_PROMISES_H_ + +#include +#include +#include +#include +#include +#include + +namespace keystore { + +template +class CallbackPromise : public BnInterface, public std::promise { + public: + ::android::binder::Status onFinished(const Result& result) override { + this->set_value(result); + return ::android::binder::Status::ok(); + } +}; + +template +class CallbackPromise> + : public BnInterface, public std::promise> { + public: + ::android::binder::Status onFinished(const Results&... results) override { + this->set_value({results...}); + return ::android::binder::Status::ok(); + } +}; + +using OperationResultPromise = + CallbackPromise<::android::security::keystore::BnKeystoreOperationResultCallback, + ::android::security::keymaster::OperationResult>; + +using KeystoreResponsePromise = + CallbackPromise<::android::security::keystore::BnKeystoreResponseCallback, + ::android::security::keystore::KeystoreResponse>; + +using KeyCharacteristicsPromise = + CallbackPromise<::android::security::keystore::BnKeystoreKeyCharacteristicsCallback, + std::tuple<::android::security::keystore::KeystoreResponse, + ::android::security::keymaster::KeyCharacteristics>>; +using KeystoreExportPromise = + CallbackPromise<::android::security::keystore::BnKeystoreExportKeyCallback, + ::android::security::keymaster::ExportResult>; + +using KeyCertChainPromise = + CallbackPromise<::android::security::keystore::BnKeystoreCertificateChainCallback, + std::tuple<::android::security::keystore::KeystoreResponse, + ::android::security::keymaster::KeymasterCertificateChain>>; + +} // namespace keystore + +#endif // KEYSTORE_INCLUDE_KEYSTORE_KEYSTORE_PROMISES_H_ diff --git a/keystore/key_store_service.cpp b/keystore/key_store_service.cpp index 7ce58ca9..2f07fbf4 100644 --- a/keystore/key_store_service.cpp +++ b/keystore/key_store_service.cpp @@ -17,7 +17,6 @@ #define LOG_TAG "keystore" #include "key_store_service.h" -#include "include/keystore/KeystoreArg.h" #include #include @@ -57,7 +56,6 @@ using namespace android; namespace { using ::android::binder::Status; -using android::security::KeystoreArg; using android::security::keymaster::ExportResult; using android::security::keymaster::KeymasterArguments; using android::security::keymaster::KeymasterBlob; @@ -65,6 +63,9 @@ using android::security::keymaster::KeymasterCertificateChain; using android::security::keymaster::operationFailed; using android::security::keymaster::OperationResult; using ConfirmationResponseCode = android::hardware::confirmationui::V1_0::ResponseCode; +using ::android::security::keystore::IKeystoreOperationResultCallback; +using ::android::security::keystore::IKeystoreResponseCallback; +using ::android::security::keystore::KeystoreResponse; constexpr double kIdRotationPeriod = 30 * 24 * 60 * 60; /* Thirty days, in seconds */ const char* kTimestampFilePath = "timestamp"; @@ -82,6 +83,9 @@ bool containsTag(const hidl_vec& params, Tag tag) { [&](const KeyParameter& param) { return param.tag == tag; }); } +#define AIDL_RETURN(rc) \ + (*_aidl_return = static_cast(KeyStoreServiceReturnCode(rc)), Status::ok()) + std::pair hadFactoryResetSinceIdRotation() { struct stat sbuf; if (stat(kTimestampFilePath, &sbuf) == 0) { @@ -545,113 +549,93 @@ Status KeyStoreService::clear_uid(int64_t targetUid64, int32_t* aidl_return) { return Status::ok(); } -Status KeyStoreService::addRngEntropy(const ::std::vector& entropy, int32_t flags, - int32_t* aidl_return) { +Status KeyStoreService::addRngEntropy( + const ::android::sp<::android::security::keystore::IKeystoreResponseCallback>& cb, + const ::std::vector& entropy, int32_t flags, int32_t* _aidl_return) { auto device = mKeyStore->getDevice(flagsToSecurityLevel(flags)); if (!device) { - *aidl_return = static_cast(ErrorCode::HARDWARE_TYPE_UNAVAILABLE); - return Status::ok(); + return AIDL_RETURN(ErrorCode::HARDWARE_TYPE_UNAVAILABLE); } - std::promise resultPromise; - auto resultFuture = resultPromise.get_future(); - device->addRngEntropy( - entropy, [&](Return rc) { resultPromise.set_value(KS_HANDLE_HIDL_ERROR(rc)); }); - resultFuture.wait(); - *aidl_return = int32_t(resultFuture.get()); - return Status::ok(); + device->addRngEntropy(entropy, [cb](Return rc) { + cb->onFinished(KeyStoreServiceReturnCode(KS_HANDLE_HIDL_ERROR(rc))); + }); + + return AIDL_RETURN(ResponseCode::NO_ERROR); } -Status -KeyStoreService::generateKey(const String16& name, const KeymasterArguments& params, - const ::std::vector& entropy, int uid, int flags, - android::security::keymaster::KeyCharacteristics* outCharacteristics, - int32_t* aidl_return) { +Status KeyStoreService::generateKey( + const ::android::sp<::android::security::keystore::IKeystoreKeyCharacteristicsCallback>& cb, + const String16& name, const KeymasterArguments& params, const ::std::vector& entropy, + int uid, int flags, int32_t* _aidl_return) { // TODO(jbires): remove this getCallingUid call upon implementation of b/25646100 uid_t originalUid = IPCThreadState::self()->getCallingUid(); uid = getEffectiveUid(uid); auto logOnScopeExit = android::base::make_scope_guard([&] { if (__android_log_security()) { android_log_event_list(SEC_TAG_AUTH_KEY_GENERATED) - << int32_t(*aidl_return == static_cast(ResponseCode::NO_ERROR)) + << int32_t(*_aidl_return == static_cast(ResponseCode::NO_ERROR)) << String8(name) << int32_t(uid) << LOG_ID_SECURITY; } }); KeyStoreServiceReturnCode rc = checkBinderPermissionAndKeystoreState(P_INSERT, uid, flags & KEYSTORE_FLAG_ENCRYPTED); if (!rc.isOk()) { - *aidl_return = static_cast(rc); - return Status::ok(); + return AIDL_RETURN(rc); } if ((flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION) && get_app_id(uid) != AID_SYSTEM) { ALOGE("Non-system uid %d cannot set FLAG_CRITICAL_TO_DEVICE_ENCRYPTION", uid); - *aidl_return = static_cast(ResponseCode::PERMISSION_DENIED); - return Status::ok(); + return AIDL_RETURN(ResponseCode::PERMISSION_DENIED); } if (containsTag(params.getParameters(), Tag::INCLUDE_UNIQUE_ID)) { // TODO(jbires): remove uid checking upon implementation of b/25646100 if (!checkBinderPermission(P_GEN_UNIQUE_ID) || originalUid != IPCThreadState::self()->getCallingUid()) { - *aidl_return = static_cast(ResponseCode::PERMISSION_DENIED); - return Status::ok(); + return AIDL_RETURN(ResponseCode::PERMISSION_DENIED); } } SecurityLevel securityLevel = flagsToSecurityLevel(flags); auto dev = mKeyStore->getDevice(securityLevel); if (!dev) { - *aidl_return = static_cast(ErrorCode::HARDWARE_TYPE_UNAVAILABLE); - return Status::ok(); + return AIDL_RETURN(ErrorCode::HARDWARE_TYPE_UNAVAILABLE); } String8 name8(name); auto lockedEntry = mKeyStore->getLockedBlobEntryIfNotExists(name8.string(), uid); if (!lockedEntry) { - *aidl_return = static_cast(ResponseCode::KEY_ALREADY_EXISTS); - return Status::ok(); + return AIDL_RETURN(ResponseCode::KEY_ALREADY_EXISTS); } logOnScopeExit.Disable(); - std::promise resultPromise; - auto resultFuture = resultPromise.get_future(); + dev->generateKey( + std::move(lockedEntry), params.getParameters(), entropy, flags, + [cb, uid, name](KeyStoreServiceReturnCode rc, KeyCharacteristics keyCharacteristics) { + if (__android_log_security()) { + android_log_event_list(SEC_TAG_AUTH_KEY_GENERATED) + << rc.isOk() << String8(name) << int32_t(uid) << LOG_ID_SECURITY; + } + cb->onFinished(rc, + android::security::keymaster::KeyCharacteristics(keyCharacteristics)); + }); - dev->generateKey(std::move(lockedEntry), params.getParameters(), entropy, flags, - [&, uid](KeyStoreServiceReturnCode rc, KeyCharacteristics keyCharacteristics) { - if (outCharacteristics && rc.isOk()) { - *outCharacteristics = android::security::keymaster::KeyCharacteristics( - keyCharacteristics); - } - if (__android_log_security()) { - android_log_event_list(SEC_TAG_AUTH_KEY_GENERATED) - << rc.isOk() << String8(name) << int32_t(uid) << LOG_ID_SECURITY; - } - resultPromise.set_value(rc); - }); - - resultFuture.wait(); - *aidl_return = int32_t(resultFuture.get()); - return Status::ok(); + return AIDL_RETURN(ResponseCode::NO_ERROR); } Status KeyStoreService::getKeyCharacteristics( + const ::android::sp<::android::security::keystore::IKeystoreKeyCharacteristicsCallback>& cb, const String16& name, const ::android::security::keymaster::KeymasterBlob& clientId, const ::android::security::keymaster::KeymasterBlob& appData, int32_t uid, - ::android::security::keymaster::KeyCharacteristics* outCharacteristics, int32_t* aidl_return) { - if (!outCharacteristics) { - *aidl_return = - static_cast(KeyStoreServiceReturnCode(ErrorCode::UNEXPECTED_NULL_POINTER)); - return Status::ok(); - } + int32_t* _aidl_return) { uid_t targetUid = getEffectiveUid(uid); uid_t callingUid = IPCThreadState::self()->getCallingUid(); if (!is_granted_to(callingUid, targetUid)) { ALOGW("uid %d not permitted to act for uid %d in getKeyCharacteristics", callingUid, targetUid); - *aidl_return = static_cast(ResponseCode::PERMISSION_DENIED); - return Status::ok(); + return AIDL_RETURN(ResponseCode::PERMISSION_DENIED); } String8 name8(name); @@ -665,47 +649,37 @@ Status KeyStoreService::getKeyCharacteristics( mKeyStore->getKeyForName(name8, targetUid, TYPE_KEYMASTER_10); if (rc != ResponseCode::NO_ERROR) { - *aidl_return = static_cast(rc); - return Status::ok(); + return AIDL_RETURN(rc); } auto dev = mKeyStore->getDevice(keyBlob); if (!dev) { - *aidl_return = static_cast(ResponseCode::SYSTEM_ERROR); - return Status::ok(); + return AIDL_RETURN(ResponseCode::SYSTEM_ERROR); } // If the charBlob is up to date, it simply moves the argument blobs to the returned blobs // and extracts the characteristics on the way. Otherwise it updates the cache file with data // from keymaster. It may also upgrade the key blob. - std::promise resultPromise; - auto resultFuture = resultPromise.get_future(); - dev->getKeyCharacteristics( std::move(lockedEntry), clientId.getData(), appData.getData(), std::move(keyBlob), std::move(charBlob), - [&](KeyStoreServiceReturnCode rc, KeyCharacteristics keyCharacteristics) { - if (outCharacteristics && rc.isOk()) { - *outCharacteristics = std::move(keyCharacteristics); - } - resultPromise.set_value(rc); + [cb](KeyStoreServiceReturnCode rc, KeyCharacteristics keyCharacteristics) { + cb->onFinished(rc, + android::security::keymaster::KeyCharacteristics(keyCharacteristics)); }); - resultFuture.wait(); - *aidl_return = int32_t(resultFuture.get()); - return Status::ok(); + return AIDL_RETURN(ResponseCode::NO_ERROR); } -Status -KeyStoreService::importKey(const String16& name, const KeymasterArguments& params, int32_t format, - const ::std::vector& keyData, int uid, int flags, - ::android::security::keymaster::KeyCharacteristics* outCharacteristics, - int32_t* aidl_return) { +Status KeyStoreService::importKey( + const ::android::sp<::android::security::keystore::IKeystoreKeyCharacteristicsCallback>& cb, + const String16& name, const KeymasterArguments& params, int32_t format, + const ::std::vector& keyData, int uid, int flags, int32_t* _aidl_return) { uid = getEffectiveUid(uid); auto logOnScopeExit = android::base::make_scope_guard([&] { if (__android_log_security()) { android_log_event_list(SEC_TAG_KEY_IMPORTED) - << int32_t(*aidl_return == static_cast(ResponseCode::NO_ERROR)) + << int32_t(*_aidl_return == static_cast(ResponseCode::NO_ERROR)) << String8(name) << int32_t(uid) << LOG_ID_SECURITY; } }); @@ -713,21 +687,18 @@ KeyStoreService::importKey(const String16& name, const KeymasterArguments& param checkBinderPermissionAndKeystoreState(P_INSERT, uid, flags & KEYSTORE_FLAG_ENCRYPTED); if (!rc.isOk()) { LOG(ERROR) << "permissission denied"; - *aidl_return = static_cast(rc); - return Status::ok(); + return AIDL_RETURN(rc); } if ((flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION) && get_app_id(uid) != AID_SYSTEM) { ALOGE("Non-system uid %d cannot set FLAG_CRITICAL_TO_DEVICE_ENCRYPTION", uid); - *aidl_return = static_cast(ResponseCode::PERMISSION_DENIED); - return Status::ok(); + return AIDL_RETURN(ResponseCode::PERMISSION_DENIED); } SecurityLevel securityLevel = flagsToSecurityLevel(flags); auto dev = mKeyStore->getDevice(securityLevel); if (!dev) { LOG(ERROR) << "importKey - cound not get keymaster device"; - *aidl_return = static_cast(ErrorCode::HARDWARE_TYPE_UNAVAILABLE); - return Status::ok(); + return AIDL_RETURN(ErrorCode::HARDWARE_TYPE_UNAVAILABLE); } String8 name8(name); @@ -735,44 +706,37 @@ KeyStoreService::importKey(const String16& name, const KeymasterArguments& param if (!lockedEntry) { LOG(ERROR) << "importKey - key: " << name8.string() << " " << int(uid) << " already exists."; - *aidl_return = static_cast(ResponseCode::KEY_ALREADY_EXISTS); - return Status::ok(); + return AIDL_RETURN(ResponseCode::KEY_ALREADY_EXISTS); } logOnScopeExit.Disable(); - std::promise resultPromise; - auto resultFuture = resultPromise.get_future(); + dev->importKey( + std::move(lockedEntry), params.getParameters(), KeyFormat(format), keyData, flags, + [cb, uid, name](KeyStoreServiceReturnCode rc, KeyCharacteristics keyCharacteristics) { + if (__android_log_security()) { + android_log_event_list(SEC_TAG_KEY_IMPORTED) + << rc.isOk() << String8(name) << int32_t(uid) << LOG_ID_SECURITY; + } + cb->onFinished(rc, + android::security::keymaster::KeyCharacteristics(keyCharacteristics)); + }); - dev->importKey(std::move(lockedEntry), params.getParameters(), KeyFormat(format), keyData, - flags, - [&, uid](KeyStoreServiceReturnCode rc, KeyCharacteristics keyCharacteristics) { - if (outCharacteristics && rc.isOk()) { - *outCharacteristics = std::move(keyCharacteristics); - } - if (__android_log_security()) { - android_log_event_list(SEC_TAG_KEY_IMPORTED) - << rc.isOk() << String8(name) << int32_t(uid) << LOG_ID_SECURITY; - } - resultPromise.set_value(rc); - }); - - resultFuture.wait(); - *aidl_return = int32_t(resultFuture.get()); - return Status::ok(); + return AIDL_RETURN(ResponseCode::NO_ERROR); } -Status KeyStoreService::exportKey(const String16& name, int32_t format, - const ::android::security::keymaster::KeymasterBlob& clientId, - const ::android::security::keymaster::KeymasterBlob& appData, - int32_t uid, ExportResult* result) { +Status KeyStoreService::exportKey( + const ::android::sp<::android::security::keystore::IKeystoreExportKeyCallback>& cb, + const String16& name, int32_t format, + const ::android::security::keymaster::KeymasterBlob& clientId, + const ::android::security::keymaster::KeymasterBlob& appData, int32_t uid, + int32_t* _aidl_return) { uid_t targetUid = getEffectiveUid(uid); uid_t callingUid = IPCThreadState::self()->getCallingUid(); if (!is_granted_to(callingUid, targetUid)) { ALOGW("uid %d not permitted to act for uid %d in exportKey", callingUid, targetUid); - result->resultCode = ResponseCode::PERMISSION_DENIED; - return Status::ok(); + return AIDL_RETURN(ResponseCode::PERMISSION_DENIED); } String8 name8(name); @@ -785,43 +749,35 @@ Status KeyStoreService::exportKey(const String16& name, int32_t format, std::tie(rc, keyBlob, charBlob, lockedEntry) = mKeyStore->getKeyForName(name8, targetUid, TYPE_KEYMASTER_10); if (!rc) { - result->resultCode = rc; - return Status::ok(); + return AIDL_RETURN(rc); } auto dev = mKeyStore->getDevice(keyBlob); - std::promise resultPromise; - auto resultFuture = resultPromise.get_future(); dev->exportKey(std::move(lockedEntry), KeyFormat(format), clientId.getData(), appData.getData(), - std::move(keyBlob), std::move(charBlob), [&](ExportResult exportResult) { - *result = std::move(exportResult); - resultPromise.set_value(); - }); + std::move(keyBlob), std::move(charBlob), + [cb](ExportResult exportResult) { cb->onFinished(exportResult); }); - resultFuture.wait(); - return Status::ok(); + return AIDL_RETURN(ResponseCode::NO_ERROR); } -Status KeyStoreService::begin(const sp& appToken, const String16& name, int32_t purpose, +Status KeyStoreService::begin(const sp& cb, + const sp& appToken, const String16& name, int32_t purpose, bool pruneable, const KeymasterArguments& params, const ::std::vector& entropy, int32_t uid, - OperationResult* result) { + int32_t* _aidl_return) { uid_t callingUid = IPCThreadState::self()->getCallingUid(); uid_t targetUid = getEffectiveUid(uid); if (!is_granted_to(callingUid, targetUid)) { ALOGW("uid %d not permitted to act for uid %d in begin", callingUid, targetUid); - result->resultCode = ResponseCode::PERMISSION_DENIED; - return Status::ok(); + return AIDL_RETURN(ResponseCode::PERMISSION_DENIED); } if (!pruneable && get_app_id(callingUid) != AID_SYSTEM) { ALOGE("Non-system uid %d trying to start non-pruneable operation", callingUid); - result->resultCode = ResponseCode::PERMISSION_DENIED; - return Status::ok(); + return AIDL_RETURN(ResponseCode::PERMISSION_DENIED); } if (!checkAllowedOperationParams(params.getParameters())) { - result->resultCode = ErrorCode::INVALID_ARGUMENT; - return Status::ok(); + return AIDL_RETURN(ErrorCode::INVALID_ARGUMENT); } String8 name8(name); @@ -834,104 +790,85 @@ Status KeyStoreService::begin(const sp& appToken, const String16& name, mKeyStore->getKeyForName(name8, targetUid, TYPE_KEYMASTER_10); if (rc == ResponseCode::LOCKED && keyBlob.isSuperEncrypted()) { - return result->resultCode = ErrorCode::KEY_USER_NOT_AUTHENTICATED, Status::ok(); + return AIDL_RETURN(ErrorCode::KEY_USER_NOT_AUTHENTICATED); } - if (rc != ResponseCode::NO_ERROR) return result->resultCode = rc, Status::ok(); + if (rc != ResponseCode::NO_ERROR) return AIDL_RETURN(rc); auto dev = mKeyStore->getDevice(keyBlob); AuthorizationSet opParams = params.getParameters(); - KeyCharacteristics characteristics; - - std::promise resultPromise; - auto resultFuture = resultPromise.get_future(); dev->begin(std::move(lockedEntry), appToken, std::move(keyBlob), std::move(charBlob), pruneable, static_cast(purpose), std::move(opParams), entropy, - [&, this](OperationResult result_) { + [this, cb, dev](OperationResult result_) { if (result_.resultCode.isOk() || result_.resultCode == ResponseCode::OP_AUTH_NEEDED) { addOperationDevice(result_.token, dev); } - if (result) *result = std::move(result_); - resultPromise.set_value(); + cb->onFinished(result_); }); - resultFuture.wait(); - return Status::ok(); + return AIDL_RETURN(ResponseCode::NO_ERROR); } -Status KeyStoreService::update(const sp& token, const KeymasterArguments& params, - const ::std::vector& data, OperationResult* result) { +Status KeyStoreService::update(const ::android::sp& cb, + const ::android::sp<::android::IBinder>& token, + const ::android::security::keymaster::KeymasterArguments& params, + const ::std::vector& input, int32_t* _aidl_return) { if (!checkAllowedOperationParams(params.getParameters())) { - result->resultCode = ErrorCode::INVALID_ARGUMENT; - return Status::ok(); + return AIDL_RETURN(ErrorCode::INVALID_ARGUMENT); } - std::promise resultPromise; - auto resultFuture = resultPromise.get_future(); - auto dev = getOperationDevice(token); if (!dev) { - *result = operationFailed(ErrorCode::INVALID_OPERATION_HANDLE); - return Status::ok(); + return AIDL_RETURN(ErrorCode::INVALID_OPERATION_HANDLE); } - dev->update(token, params.getParameters(), data, [&](OperationResult result_) { + dev->update(token, params.getParameters(), input, [this, cb, token](OperationResult result_) { if (!result_.resultCode.isOk()) { removeOperationDevice(token); } - if (result) *result = std::move(result_); - resultPromise.set_value(); + cb->onFinished(result_); }); - resultFuture.wait(); - return Status::ok(); + return AIDL_RETURN(ResponseCode::NO_ERROR); } -Status KeyStoreService::finish(const sp& token, const KeymasterArguments& params, +Status KeyStoreService::finish(const ::android::sp& cb, + const ::android::sp<::android::IBinder>& token, + const ::android::security::keymaster::KeymasterArguments& params, const ::std::vector& signature, - const ::std::vector& entropy, OperationResult* result) { + const ::std::vector& entropy, int32_t* _aidl_return) { if (!checkAllowedOperationParams(params.getParameters())) { - result->resultCode = ErrorCode::INVALID_ARGUMENT; - return Status::ok(); + return AIDL_RETURN(ErrorCode::INVALID_ARGUMENT); } - std::promise resultPromise; - auto resultFuture = resultPromise.get_future(); - auto dev = getOperationDevice(token); if (!dev) { - *result = operationFailed(ErrorCode::INVALID_OPERATION_HANDLE); - return Status::ok(); + return AIDL_RETURN(ErrorCode::INVALID_OPERATION_HANDLE); } dev->finish(token, params.getParameters(), {}, signature, entropy, - [&](OperationResult result_) { + [this, cb, token](OperationResult result_) { if (!result_.resultCode.isOk()) { removeOperationDevice(token); } - if (result) *result = std::move(result_); - resultPromise.set_value(); + cb->onFinished(result_); }); - resultFuture.wait(); - return Status::ok(); + return AIDL_RETURN(ResponseCode::NO_ERROR); } -Status KeyStoreService::abort(const sp& token, int32_t* aidl_return) { +Status KeyStoreService::abort(const ::android::sp& cb, + const ::android::sp<::android::IBinder>& token, + int32_t* _aidl_return) { auto dev = getOperationDevice(token); if (!dev) { - *aidl_return = static_cast(ErrorCode::INVALID_OPERATION_HANDLE); - return Status::ok(); + return AIDL_RETURN(ErrorCode::INVALID_OPERATION_HANDLE); } - std::promise resultPromise; - auto resultFuture = resultPromise.get_future(); - dev->abort(token, [&](KeyStoreServiceReturnCode rc) { resultPromise.set_value(rc); }); + dev->abort(token, [cb](KeyStoreServiceReturnCode rc) { cb->onFinished(rc); }); - resultFuture.wait(); - *aidl_return = int32_t(resultFuture.get()); - return Status::ok(); + return AIDL_RETURN(ResponseCode::NO_ERROR); } Status KeyStoreService::addAuthToken(const ::std::vector& authTokenAsVector, @@ -987,13 +924,12 @@ int isDeviceIdAttestationRequested(const KeymasterArguments& params) { return result; } -Status KeyStoreService::attestKey(const String16& name, const KeymasterArguments& params, - ::android::security::keymaster::KeymasterCertificateChain* chain, - int32_t* aidl_return) { +Status KeyStoreService::attestKey( + const ::android::sp<::android::security::keystore::IKeystoreCertificateChainCallback>& cb, + const String16& name, const KeymasterArguments& params, int32_t* _aidl_return) { // check null output if method signature is updated and return ErrorCode::OUTPUT_PARAMETER_NULL if (!checkAllowedOperationParams(params.getParameters())) { - *aidl_return = static_cast(KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT)); - return Status::ok(); + return AIDL_RETURN(ErrorCode::INVALID_ARGUMENT); } uid_t callingUid = IPCThreadState::self()->getCallingUid(); @@ -1007,15 +943,13 @@ Status KeyStoreService::attestKey(const String16& name, const KeymasterArguments // unique device ID. if ((needsIdAttestation && !isSomeUserSystemUid) || (needsUniqueIdAttestation && !isPrimaryUserSystemUid)) { - *aidl_return = static_cast(KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT)); - return Status::ok(); + return AIDL_RETURN(KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT)); } AuthorizationSet mutableParams = params.getParameters(); KeyStoreServiceReturnCode rc = updateParamsForAttestation(callingUid, &mutableParams); if (!rc.isOk()) { - *aidl_return = static_cast(rc); - return Status::ok(); + return AIDL_RETURN(rc); } String8 name8(name); @@ -1026,75 +960,67 @@ Status KeyStoreService::attestKey(const String16& name, const KeymasterArguments std::tie(rc, keyBlob, charBlob, lockedEntry) = mKeyStore->getKeyForName(name8, callingUid, TYPE_KEYMASTER_10); - std::promise resultPromise; - auto resultFuture = resultPromise.get_future(); - - auto worker_cb = [&](Return rc, - std::tuple>>&& hidlResult) { - auto& [ret, certChain] = hidlResult; - if (!rc.isOk()) { - resultPromise.set_value(ResponseCode::SYSTEM_ERROR); - return; - } - if (ret == ErrorCode::OK && chain) { - *chain = KeymasterCertificateChain(certChain); - } - resultPromise.set_value(ret); - }; auto dev = mKeyStore->getDevice(keyBlob); auto hidlKey = blob2hidlVec(keyBlob); - dev->attestKey(std::move(hidlKey), mutableParams.hidl_data(), worker_cb); + dev->attestKey( + std::move(hidlKey), mutableParams.hidl_data(), + [cb](Return rc, std::tuple>>&& hidlResult) { + auto& [ret, certChain] = hidlResult; + if (!rc.isOk()) { + cb->onFinished(KeyStoreServiceReturnCode(ResponseCode::SYSTEM_ERROR), {}); + } else if (ret != ErrorCode::OK) { + cb->onFinished(KeyStoreServiceReturnCode(ret), {}); + } else { + cb->onFinished(KeyStoreServiceReturnCode(ret), + KeymasterCertificateChain(std::move(certChain))); + } + }); - resultFuture.wait(); - *aidl_return = static_cast(resultFuture.get()); - return Status::ok(); + return AIDL_RETURN(ResponseCode::NO_ERROR); } -Status -KeyStoreService::attestDeviceIds(const KeymasterArguments& params, - ::android::security::keymaster::KeymasterCertificateChain* chain, - int32_t* aidl_return) { +// My IDE defines "CAPTURE_MOVE(x) x" because it does not understand generalized lambda captures. +// It should never be redefined by a build system though. +#ifndef CAPTURE_MOVE +#define CAPTURE_MOVE(x) x = std::move(x) +#endif + +Status KeyStoreService::attestDeviceIds( + const ::android::sp<::android::security::keystore::IKeystoreCertificateChainCallback>& cb, + const KeymasterArguments& params, int32_t* _aidl_return) { // check null output if method signature is updated and return ErrorCode::OUTPUT_PARAMETER_NULL if (!checkAllowedOperationParams(params.getParameters())) { - *aidl_return = static_cast(KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT)); - return Status::ok(); + return AIDL_RETURN(ErrorCode::INVALID_ARGUMENT); } if (!isDeviceIdAttestationRequested(params)) { // There is an attestKey() method for attesting keys without device ID attestation. - *aidl_return = static_cast(KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT)); - return Status::ok(); + return AIDL_RETURN(ErrorCode::INVALID_ARGUMENT); } uid_t callingUid = IPCThreadState::self()->getCallingUid(); sp binder = defaultServiceManager()->getService(String16("permission")); if (binder == nullptr) { - *aidl_return = - static_cast(KeyStoreServiceReturnCode(ErrorCode::CANNOT_ATTEST_IDS)); - return Status::ok(); + return AIDL_RETURN(ErrorCode::CANNOT_ATTEST_IDS); } if (!interface_cast(binder)->checkPermission( String16("android.permission.READ_PRIVILEGED_PHONE_STATE"), IPCThreadState::self()->getCallingPid(), callingUid)) { - *aidl_return = - static_cast(KeyStoreServiceReturnCode(ErrorCode::CANNOT_ATTEST_IDS)); - return Status::ok(); + return AIDL_RETURN(ErrorCode::CANNOT_ATTEST_IDS); } AuthorizationSet mutableParams = params.getParameters(); KeyStoreServiceReturnCode rc = updateParamsForAttestation(callingUid, &mutableParams); if (!rc.isOk()) { - *aidl_return = static_cast(rc); - return Status::ok(); + return AIDL_RETURN(rc); } // Generate temporary key. auto dev = mKeyStore->getDevice(SecurityLevel::TRUSTED_ENVIRONMENT); if (!dev) { - *aidl_return = static_cast(ResponseCode::SYSTEM_ERROR); - return Status::ok(); + return AIDL_RETURN(ResponseCode::SYSTEM_ERROR); } @@ -1110,44 +1036,45 @@ KeyStoreService::attestDeviceIds(const KeymasterArguments& params, dev->generateKey( keyCharacteristics.hidl_data(), - [&, dev](Return rc, - std::tuple, KeyCharacteristics>&& hidlResult) { + [cb, dev, CAPTURE_MOVE(mutableParams)]( + Return rc, + std::tuple, KeyCharacteristics>&& hidlResult) { auto& [ret, hidlKeyBlob_, dummyCharacteristics] = hidlResult; auto hidlKeyBlob = std::move(hidlKeyBlob_); if (!rc.isOk()) { - resultPromise.set_value(ResponseCode::SYSTEM_ERROR); + cb->onFinished(KeyStoreServiceReturnCode(ResponseCode::SYSTEM_ERROR), {}); return; } if (ret != ErrorCode::OK) { - resultPromise.set_value(ret); + cb->onFinished(KeyStoreServiceReturnCode(ret), {}); return; } dev->attestKey( hidlKeyBlob, mutableParams.hidl_data(), - [&, dev, + [cb, dev, hidlKeyBlob](Return rc, std::tuple>>&& hidlResult) { auto& [ret, certChain] = hidlResult; - // shedule temp key for deletion + // schedule temp key for deletion dev->deleteKey(std::move(hidlKeyBlob), [](Return rc) { // log error but don't return an error KS_HANDLE_HIDL_ERROR(rc); }); if (!rc.isOk()) { - resultPromise.set_value(ResponseCode::SYSTEM_ERROR); + cb->onFinished(KeyStoreServiceReturnCode(ResponseCode::SYSTEM_ERROR), {}); return; } - if (ret == ErrorCode::OK && chain) { - *chain = - ::android::security::keymaster::KeymasterCertificateChain(certChain); + if (ret == ErrorCode::OK) { + cb->onFinished( + KeyStoreServiceReturnCode(ret), + ::android::security::keymaster::KeymasterCertificateChain(certChain)); + } else { + cb->onFinished(KeyStoreServiceReturnCode(ret), {}); } - resultPromise.set_value(ret); }); }); - resultFuture.wait(); - *aidl_return = static_cast(resultFuture.get()); - return Status::ok(); + return AIDL_RETURN(ResponseCode::NO_ERROR); } Status KeyStoreService::onDeviceOffBody(int32_t* aidl_return) { @@ -1157,14 +1084,12 @@ Status KeyStoreService::onDeviceOffBody(int32_t* aidl_return) { return Status::ok(); } -#define AIDL_RETURN(rc) \ - (*_aidl_return = static_cast(KeyStoreServiceReturnCode(rc)), Status::ok()) - Status KeyStoreService::importWrappedKey( + const ::android::sp<::android::security::keystore::IKeystoreKeyCharacteristicsCallback>& cb, const ::android::String16& wrappedKeyAlias, const ::std::vector& wrappedKey, const ::android::String16& wrappingKeyAlias, const ::std::vector& maskingKey, const KeymasterArguments& params, int64_t rootSid, int64_t fingerprintSid, - ::android::security::keymaster::KeyCharacteristics* outCharacteristics, int32_t* _aidl_return) { + int32_t* _aidl_return) { uid_t callingUid = IPCThreadState::self()->getCallingUid(); @@ -1198,22 +1123,15 @@ Status KeyStoreService::importWrappedKey( return AIDL_RETURN(ErrorCode::HARDWARE_TYPE_UNAVAILABLE); } - std::promise resultPromise; - auto resultFuture = resultPromise.get_future(); - dev->importWrappedKey( std::move(wrappingLockedEntry), std::move(wrappedLockedEntry), wrappedKey, maskingKey, params.getParameters(), std::move(wrappingKeyBlob), std::move(wrappingCharBlob), rootSid, - fingerprintSid, [&](KeyStoreServiceReturnCode rc, KeyCharacteristics keyCharacteristics) { - if (rc.isOk() && outCharacteristics) { - *outCharacteristics = - ::android::security::keymaster::KeyCharacteristics(keyCharacteristics); - } - resultPromise.set_value(rc); + fingerprintSid, [cb](KeyStoreServiceReturnCode rc, KeyCharacteristics keyCharacteristics) { + cb->onFinished(rc, + ::android::security::keymaster::KeyCharacteristics(keyCharacteristics)); }); - resultFuture.wait(); - return AIDL_RETURN(resultFuture.get()); + return AIDL_RETURN(ResponseCode::NO_ERROR); } Status KeyStoreService::presentConfirmationPrompt(const sp& listener, diff --git a/keystore/key_store_service.h b/keystore/key_store_service.h index 29369d05..601ed211 100644 --- a/keystore/key_store_service.h +++ b/keystore/key_store_service.h @@ -17,7 +17,7 @@ #ifndef KEYSTORE_KEYSTORE_SERVICE_H_ #define KEYSTORE_KEYSTORE_SERVICE_H_ -#include +#include #include "auth_token_table.h" #include "confirmation_manager.h" @@ -42,7 +42,7 @@ namespace keystore { // java/android/security/IKeystoreService.aidl Note that all generated methods return binder::Status // and use last arguments to send actual result to the caller. Private methods don't need to handle // binder::Status. Input parameters cannot be null unless annotated with @nullable in .aidl file. -class KeyStoreService : public android::security::BnKeystoreService { +class KeyStoreService : public android::security::keystore::BnKeystoreService { public: explicit KeyStoreService(sp keyStore) : mKeyStore(keyStore) {} virtual ~KeyStoreService() = default; @@ -78,71 +78,76 @@ class KeyStoreService : public android::security::BnKeystoreService { ::android::binder::Status is_hardware_backed(const ::android::String16& string, int32_t* _aidl_return) override; ::android::binder::Status clear_uid(int64_t uid, int32_t* _aidl_return) override; - ::android::binder::Status addRngEntropy(const ::std::vector& data, int32_t flags, - int32_t* _aidl_return) override; ::android::binder::Status - generateKey(const ::android::String16& alias, - const ::android::security::keymaster::KeymasterArguments& arguments, - const ::std::vector& entropy, int32_t uid, int32_t flags, - ::android::security::keymaster::KeyCharacteristics* characteristics, - int32_t* _aidl_return) override; + addRngEntropy(const ::android::sp<::android::security::keystore::IKeystoreResponseCallback>& cb, + const ::std::vector& data, int32_t flags, + int32_t* _aidl_return) override; + ::android::binder::Status generateKey( + const ::android::sp<::android::security::keystore::IKeystoreKeyCharacteristicsCallback>& cb, + const ::android::String16& alias, + const ::android::security::keymaster::KeymasterArguments& arguments, + const ::std::vector& entropy, int32_t uid, int32_t flags, + int32_t* _aidl_return) override; + ::android::binder::Status getKeyCharacteristics( + const ::android::sp<::android::security::keystore::IKeystoreKeyCharacteristicsCallback>& cb, + const ::android::String16& alias, + const ::android::security::keymaster::KeymasterBlob& clientId, + const ::android::security::keymaster::KeymasterBlob& appId, int32_t uid, + int32_t* _aidl_return) override; + ::android::binder::Status importKey( + const ::android::sp<::android::security::keystore::IKeystoreKeyCharacteristicsCallback>& cb, + const ::android::String16& alias, + const ::android::security::keymaster::KeymasterArguments& arguments, int32_t format, + const ::std::vector& keyData, int32_t uid, int32_t flags, + int32_t* _aidl_return) override; ::android::binder::Status - getKeyCharacteristics(const ::android::String16& alias, - const ::android::security::keymaster::KeymasterBlob& clientId, - const ::android::security::keymaster::KeymasterBlob& appId, int32_t uid, - ::android::security::keymaster::KeyCharacteristics* characteristics, - int32_t* _aidl_return) override; - ::android::binder::Status - importKey(const ::android::String16& alias, - const ::android::security::keymaster::KeymasterArguments& arguments, int32_t format, - const ::std::vector& keyData, int32_t uid, int32_t flags, - ::android::security::keymaster::KeyCharacteristics* characteristics, - int32_t* _aidl_return) override; - ::android::binder::Status - exportKey(const ::android::String16& alias, int32_t format, + exportKey(const ::android::sp<::android::security::keystore::IKeystoreExportKeyCallback>& cb, + const ::android::String16& alias, int32_t format, const ::android::security::keymaster::KeymasterBlob& clientId, const ::android::security::keymaster::KeymasterBlob& appId, int32_t uid, - ::android::security::keymaster::ExportResult* _aidl_return) override; + int32_t* _aidl_return) override; ::android::binder::Status - begin(const ::android::sp<::android::IBinder>& appToken, const ::android::String16& alias, + begin(const ::android::sp<::android::security::keystore::IKeystoreOperationResultCallback>& cb, + const ::android::sp<::android::IBinder>& appToken, const ::android::String16& alias, int32_t purpose, bool pruneable, const ::android::security::keymaster::KeymasterArguments& params, - const ::std::vector& entropy, int32_t uid, - ::android::security::keymaster::OperationResult* _aidl_return) override; + const ::std::vector& entropy, int32_t uid, int32_t* _aidl_return) override; ::android::binder::Status - update(const ::android::sp<::android::IBinder>& token, + update(const ::android::sp<::android::security::keystore::IKeystoreOperationResultCallback>& cb, + const ::android::sp<::android::IBinder>& token, const ::android::security::keymaster::KeymasterArguments& params, - const ::std::vector& input, - ::android::security::keymaster::OperationResult* _aidl_return) override; + const ::std::vector& input, int32_t* _aidl_return) override; ::android::binder::Status - finish(const ::android::sp<::android::IBinder>& token, + finish(const ::android::sp<::android::security::keystore::IKeystoreOperationResultCallback>& cb, + const ::android::sp<::android::IBinder>& token, const ::android::security::keymaster::KeymasterArguments& params, const ::std::vector& signature, const ::std::vector& entropy, - ::android::security::keymaster::OperationResult* _aidl_return) override; - ::android::binder::Status abort(const ::android::sp<::android::IBinder>& handle, - int32_t* _aidl_return) override; + int32_t* _aidl_return) override; + ::android::binder::Status + abort(const ::android::sp<::android::security::keystore::IKeystoreResponseCallback>& cb, + const ::android::sp<::android::IBinder>& token, int32_t* _aidl_return) override; ::android::binder::Status addAuthToken(const ::std::vector& authToken, int32_t* _aidl_return) override; ::android::binder::Status onUserAdded(int32_t userId, int32_t parentId, int32_t* _aidl_return) override; ::android::binder::Status onUserRemoved(int32_t userId, int32_t* _aidl_return) override; - ::android::binder::Status - attestKey(const ::android::String16& alias, - const ::android::security::keymaster::KeymasterArguments& params, - ::android::security::keymaster::KeymasterCertificateChain* chain, - int32_t* _aidl_return) override; - ::android::binder::Status - attestDeviceIds(const ::android::security::keymaster::KeymasterArguments& params, - ::android::security::keymaster::KeymasterCertificateChain* chain, - int32_t* _aidl_return) override; + ::android::binder::Status attestKey( + const ::android::sp<::android::security::keystore::IKeystoreCertificateChainCallback>& cb, + const ::android::String16& alias, + const ::android::security::keymaster::KeymasterArguments& params, + int32_t* _aidl_return) override; + ::android::binder::Status attestDeviceIds( + const ::android::sp<::android::security::keystore::IKeystoreCertificateChainCallback>& cb, + const ::android::security::keymaster::KeymasterArguments& params, + int32_t* _aidl_return) override; ::android::binder::Status onDeviceOffBody(int32_t* _aidl_return) override; ::android::binder::Status importWrappedKey( + const ::android::sp<::android::security::keystore::IKeystoreKeyCharacteristicsCallback>& cb, const ::android::String16& wrappedKeyAlias, const ::std::vector& wrappedKey, const ::android::String16& wrappingKeyAlias, const ::std::vector& maskingKey, const ::android::security::keymaster::KeymasterArguments& params, int64_t rootSid, - int64_t fingerprintSid, ::android::security::keymaster::KeyCharacteristics* characteristics, - int32_t* _aidl_return) override; + int64_t fingerprintSid, int32_t* _aidl_return) override; ::android::binder::Status presentConfirmationPrompt( const ::android::sp<::android::IBinder>& listener, const ::android::String16& promptText, diff --git a/keystore/keymaster_worker.cpp b/keystore/keymaster_worker.cpp index 1002b8d5..f3bf71fd 100644 --- a/keystore/keymaster_worker.cpp +++ b/keystore/keymaster_worker.cpp @@ -37,34 +37,31 @@ using android::security::keymaster::ExportResult; using android::security::keymaster::operationFailed; using android::security::keymaster::OperationResult; -Worker::Worker() { - worker_ = std::thread([this] { - std::unique_lock lock(pending_requests_mutex_); - running_ = true; - while (running_) { - pending_requests_cond_var_.wait( - lock, [this]() { return !pending_requests_.empty() || !running_; }); - if (!running_) break; - auto request = std::move(pending_requests_.front()); - pending_requests_.pop(); - lock.unlock(); - request(); - lock.lock(); - } - }); -} +Worker::Worker() {} Worker::~Worker() { - if (worker_.joinable()) { - running_ = false; - pending_requests_cond_var_.notify_all(); - worker_.join(); - } + std::unique_lock lock(pending_requests_mutex_); + pending_requests_cond_var_.wait(lock, [this] { return pending_requests_.empty(); }); } void Worker::addRequest(WorkerTask request) { std::unique_lock lock(pending_requests_mutex_); + bool start_thread = pending_requests_.empty(); pending_requests_.push(std::move(request)); lock.unlock(); - pending_requests_cond_var_.notify_all(); + if (start_thread) { + auto worker = std::thread([this] { + std::unique_lock lock(pending_requests_mutex_); + running_ = true; + while (!pending_requests_.empty()) { + auto request = std::move(pending_requests_.front()); + lock.unlock(); + request(); + lock.lock(); + pending_requests_.pop(); + pending_requests_cond_var_.notify_all(); + } + }); + worker.detach(); + } } KeymasterWorker::KeymasterWorker(sp keymasterDevice, KeyStore* keyStore) diff --git a/keystore/keymaster_worker.h b/keystore/keymaster_worker.h index b39ae83a..2a35977a 100644 --- a/keystore/keymaster_worker.h +++ b/keystore/keymaster_worker.h @@ -113,7 +113,6 @@ class Worker { std::queue pending_requests_; std::mutex pending_requests_mutex_; std::condition_variable pending_requests_cond_var_; - std::thread worker_; bool running_ = false; public: diff --git a/keystore/keystore_aidl_hidl_marshalling_utils.cpp b/keystore/keystore_aidl_hidl_marshalling_utils.cpp index db9b9838..cdeaf321 100644 --- a/keystore/keystore_aidl_hidl_marshalling_utils.cpp +++ b/keystore/keystore_aidl_hidl_marshalling_utils.cpp @@ -21,14 +21,13 @@ #include #include #include -#include #include #include namespace keystore { // reads byte[] -hidl_vec readKeymasterBlob(const android::Parcel& in, bool inPlace) { +hidl_vec readKeymasterBlob(const android::Parcel& in) { ssize_t length = in.readInt32(); if (length <= 0) { @@ -38,7 +37,7 @@ hidl_vec readKeymasterBlob(const android::Parcel& in, bool inPlace) { const void* buf = in.readInplace(length); if (!buf) return {}; - return blob2hidlVec(reinterpret_cast(buf), size_t(length), inPlace); + return blob2hidlVec(reinterpret_cast(buf), size_t(length)); } android::status_t writeKeymasterBlob(const hidl_vec& blob, android::Parcel* out) { @@ -235,7 +234,7 @@ status_t KeyCharacteristics::writeToParcel(Parcel* out) const { } status_t KeymasterBlob::readFromParcel(const Parcel* in) { - data_ = keystore::readKeymasterBlob(*in, true /* in place */); + data_ = keystore::readKeymasterBlob(*in); return OK; } diff --git a/keystore/keystore_aidl_hidl_marshalling_utils.h b/keystore/keystore_aidl_hidl_marshalling_utils.h index 13edbd25..ea72197a 100644 --- a/keystore/keystore_aidl_hidl_marshalling_utils.h +++ b/keystore/keystore_aidl_hidl_marshalling_utils.h @@ -60,7 +60,7 @@ inline android::status_t nullable(android::Parcel* out) { /** * makes a copy only if inPlace is false */ -hidl_vec readKeymasterBlob(const android::Parcel& in, bool inPlace = true); +hidl_vec readKeymasterBlob(const android::Parcel& in); android::status_t writeKeymasterBlob(const hidl_vec& blob, android::Parcel* out); NullOr> readBlobAsByteArray(const android::Parcel& in, bool inPlace = true); diff --git a/keystore/keystore_cli.cpp b/keystore/keystore_cli.cpp index b58735e2..2705a194 100644 --- a/keystore/keystore_cli.cpp +++ b/keystore/keystore_cli.cpp @@ -20,7 +20,7 @@ #include #include -#include +#include #include #include @@ -28,7 +28,7 @@ using namespace android; using namespace keystore; -using android::security::IKeystoreService; +using android::security::keystore::IKeystoreService; static const char* responses[] = { nullptr, diff --git a/keystore/keystore_cli_v2.cpp b/keystore/keystore_cli_v2.cpp index 157417f8..0981f1eb 100644 --- a/keystore/keystore_cli_v2.cpp +++ b/keystore/keystore_cli_v2.cpp @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include @@ -41,7 +41,7 @@ using keystore::KeystoreClient; using android::sp; using android::String16; -using android::security::IKeystoreService; +using android::security::keystore::IKeystoreService; using base::CommandLine; using ConfirmationResponseCode = android::hardware::confirmationui::V1_0::ResponseCode; diff --git a/keystore/keystore_client_impl.cpp b/keystore/keystore_client_impl.cpp index 6d998ada..18e9eb11 100644 --- a/keystore/keystore_client_impl.cpp +++ b/keystore/keystore_client_impl.cpp @@ -16,10 +16,11 @@ #include "keystore/keystore_client_impl.h" +#include #include #include -#include +#include #include #include #include @@ -30,6 +31,7 @@ #include #include +#include #include "keystore_client.pb.h" @@ -46,6 +48,7 @@ constexpr uint32_t kHMACOutputSize = 256; // bits using android::String16; using android::security::keymaster::ExportResult; using android::security::keymaster::OperationResult; +using android::security::keystore::KeystoreResponse; using keystore::AuthorizationSet; using keystore::AuthorizationSetBuilder; using keystore::KeyCharacteristics; @@ -57,7 +60,8 @@ namespace keystore { KeystoreClientImpl::KeystoreClientImpl() { service_manager_ = android::defaultServiceManager(); keystore_binder_ = service_manager_->getService(String16("android.security.keystore")); - keystore_ = android::interface_cast(keystore_binder_); + keystore_ = + android::interface_cast(keystore_binder_); } bool KeystoreClientImpl::encryptWithAuthentication(const std::string& key_name, @@ -180,10 +184,21 @@ bool KeystoreClientImpl::oneShotOperation(KeyPurpose purpose, const std::string& KeyStoreNativeReturnCode KeystoreClientImpl::addRandomNumberGeneratorEntropy(const std::string& entropy, int32_t flags) { - int32_t result; - auto binder_result = keystore_->addRngEntropy(blob2hidlVec(entropy), flags, &result); + int32_t error_code; + + android::sp promise(new KeystoreResponsePromise()); + auto future = promise->get_future(); + + auto binder_result = + keystore_->addRngEntropy(promise, blob2hidlVec(entropy), flags, &error_code); if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR; - return KeyStoreNativeReturnCode(result); + + KeyStoreNativeReturnCode rc(error_code); + if (!rc.isOk()) return rc; + + auto result = future.get(); + + return KeyStoreNativeReturnCode(result.response_code()); } KeyStoreNativeReturnCode @@ -191,19 +206,26 @@ KeystoreClientImpl::generateKey(const std::string& key_name, const Authorization int32_t flags, AuthorizationSet* hardware_enforced_characteristics, AuthorizationSet* software_enforced_characteristics) { String16 key_name16(key_name.data(), key_name.size()); - ::android::security::keymaster::KeyCharacteristics characteristics; - int32_t result; + int32_t error_code; + android::sp promise(new KeyCharacteristicsPromise); + auto future = promise->get_future(); auto binder_result = keystore_->generateKey( - key_name16, ::android::security::keymaster::KeymasterArguments(key_parameters.hidl_data()), - hidl_vec() /* entropy */, kDefaultUID, flags, &characteristics, &result); + promise, key_name16, + ::android::security::keymaster::KeymasterArguments(key_parameters.hidl_data()), + hidl_vec() /* entropy */, kDefaultUID, flags, &error_code); if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR; + KeyStoreNativeReturnCode rc(error_code); + if (!rc.isOk()) return rc; + + auto [km_response, characteristics] = future.get(); + /* assignment (hidl_vec -> AuthorizationSet) makes a deep copy. * There are no references to Parcel memory after that, and ownership of the newly acquired * memory is with the AuthorizationSet objects. */ *hardware_enforced_characteristics = characteristics.hardwareEnforced.getParameters(); *software_enforced_characteristics = characteristics.softwareEnforced.getParameters(); - return KeyStoreNativeReturnCode(result); + return KeyStoreNativeReturnCode(km_response.response_code()); } KeyStoreNativeReturnCode @@ -211,18 +233,25 @@ KeystoreClientImpl::getKeyCharacteristics(const std::string& key_name, AuthorizationSet* hardware_enforced_characteristics, AuthorizationSet* software_enforced_characteristics) { String16 key_name16(key_name.data(), key_name.size()); - ::android::security::keymaster::KeyCharacteristics characteristics; - int32_t result; + int32_t error_code; + android::sp promise(new KeyCharacteristicsPromise); + auto future = promise->get_future(); auto binder_result = keystore_->getKeyCharacteristics( - key_name16, android::security::keymaster::KeymasterBlob(), - android::security::keymaster::KeymasterBlob(), kDefaultUID, &characteristics, &result); + promise, key_name16, android::security::keymaster::KeymasterBlob(), + android::security::keymaster::KeymasterBlob(), kDefaultUID, &error_code); + if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR; + + KeyStoreNativeReturnCode rc(error_code); + if (!rc.isOk()) return rc; + + auto [km_response, characteristics] = future.get(); /* assignment (hidl_vec -> AuthorizationSet) makes a deep copy. * There are no references to Parcel memory after that, and ownership of the newly acquired * memory is with the AuthorizationSet objects. */ *hardware_enforced_characteristics = characteristics.hardwareEnforced.getParameters(); *software_enforced_characteristics = characteristics.softwareEnforced.getParameters(); - return KeyStoreNativeReturnCode(result); + return KeyStoreNativeReturnCode(km_response.response_code()); } KeyStoreNativeReturnCode @@ -232,29 +261,48 @@ KeystoreClientImpl::importKey(const std::string& key_name, const AuthorizationSe AuthorizationSet* software_enforced_characteristics) { String16 key_name16(key_name.data(), key_name.size()); auto hidlKeyData = blob2hidlVec(key_data); - ::android::security::keymaster::KeyCharacteristics characteristics; - int32_t result; + int32_t error_code; + android::sp promise(new KeyCharacteristicsPromise); + auto future = promise->get_future(); auto binder_result = keystore_->importKey( - key_name16, ::android::security::keymaster::KeymasterArguments(key_parameters.hidl_data()), - (int)key_format, hidlKeyData, kDefaultUID, KEYSTORE_FLAG_NONE, &characteristics, &result); + promise, key_name16, + ::android::security::keymaster::KeymasterArguments(key_parameters.hidl_data()), + (int)key_format, hidlKeyData, kDefaultUID, KEYSTORE_FLAG_NONE, &error_code); + if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR; + + KeyStoreNativeReturnCode rc(error_code); + if (!rc.isOk()) return rc; + + auto [km_response, characteristics] = future.get(); + /* assignment (hidl_vec -> AuthorizationSet) makes a deep copy. * There are no references to Parcel memory after that, and ownership of the newly acquired * memory is with the AuthorizationSet objects. */ *hardware_enforced_characteristics = characteristics.hardwareEnforced.getParameters(); *software_enforced_characteristics = characteristics.softwareEnforced.getParameters(); - return KeyStoreNativeReturnCode(result); + return KeyStoreNativeReturnCode(km_response.response_code()); } KeyStoreNativeReturnCode KeystoreClientImpl::exportKey(KeyFormat export_format, const std::string& key_name, std::string* export_data) { String16 key_name16(key_name.data(), key_name.size()); - ExportResult export_result; + int32_t error_code; + android::sp promise(new KeystoreExportPromise); + auto future = promise->get_future(); auto binder_result = keystore_->exportKey( - key_name16, (int)export_format, android::security::keymaster::KeymasterBlob(), - android::security::keymaster::KeymasterBlob(), kDefaultUID, &export_result); + promise, key_name16, (int)export_format, android::security::keymaster::KeymasterBlob(), + android::security::keymaster::KeymasterBlob(), kDefaultUID, &error_code); if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR; + + KeyStoreNativeReturnCode rc(error_code); + if (!rc.isOk()) return rc; + + auto export_result = future.get(); + if (!export_result.resultCode.isOk()) return export_result.resultCode; + *export_data = hidlVec2String(export_result.exportData); + return export_result.resultCode; } @@ -279,12 +327,18 @@ KeystoreClientImpl::beginOperation(KeyPurpose purpose, const std::string& key_na AuthorizationSet* output_parameters, uint64_t* handle) { android::sp token(new android::BBinder); String16 key_name16(key_name.data(), key_name.size()); - OperationResult result; + int32_t error_code; + android::sp promise(new OperationResultPromise{}); + auto future = promise->get_future(); auto binder_result = keystore_->begin( - token, key_name16, (int)purpose, true /*pruneable*/, + promise, token, key_name16, (int)purpose, true /*pruneable*/, android::security::keymaster::KeymasterArguments(input_parameters.hidl_data()), - hidl_vec() /* entropy */, kDefaultUID, &result); + hidl_vec() /* entropy */, kDefaultUID, &error_code); if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR; + KeyStoreNativeReturnCode rc(error_code); + if (!rc.isOk()) return rc; + + OperationResult result = future.get(); if (result.resultCode.isOk()) { *handle = getNextVirtualHandle(); active_operations_[*handle] = result.token; @@ -302,13 +356,19 @@ KeystoreClientImpl::updateOperation(uint64_t handle, const AuthorizationSet& inp if (active_operations_.count(handle) == 0) { return ErrorCode::INVALID_OPERATION_HANDLE; } - OperationResult result; auto hidlInputData = blob2hidlVec(input_data); + int32_t error_code; + android::sp promise(new OperationResultPromise{}); + auto future = promise->get_future(); auto binder_result = keystore_->update( - active_operations_[handle], + promise, active_operations_[handle], android::security::keymaster::KeymasterArguments(input_parameters.hidl_data()), - hidlInputData, &result); + hidlInputData, &error_code); if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR; + KeyStoreNativeReturnCode rc(error_code); + if (!rc.isOk()) return rc; + + OperationResult result = future.get(); if (result.resultCode.isOk()) { *num_input_bytes_consumed = result.inputConsumed; @@ -328,14 +388,19 @@ KeystoreClientImpl::finishOperation(uint64_t handle, const AuthorizationSet& inp if (active_operations_.count(handle) == 0) { return ErrorCode::INVALID_OPERATION_HANDLE; } - OperationResult result; + int32_t error_code; auto hidlSignature = blob2hidlVec(signature_to_verify); + android::sp promise(new OperationResultPromise{}); + auto future = promise->get_future(); auto binder_result = keystore_->finish( - active_operations_[handle], + promise, active_operations_[handle], android::security::keymaster::KeymasterArguments(input_parameters.hidl_data()), - (std::vector)hidlSignature, hidl_vec(), &result); + (std::vector)hidlSignature, hidl_vec(), &error_code); if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR; + KeyStoreNativeReturnCode rc(error_code); + if (!rc.isOk()) return rc; + OperationResult result = future.get(); if (result.resultCode.isOk()) { if (result.outParams.size()) { *output_parameters = result.outParams; @@ -352,13 +417,18 @@ KeyStoreNativeReturnCode KeystoreClientImpl::abortOperation(uint64_t handle) { return ErrorCode::INVALID_OPERATION_HANDLE; } int32_t result; + android::sp promise(new KeystoreResponsePromise{}); + auto future = promise->get_future(); // Current implementation does not return exceptions in android::binder::Status - auto binder_result = keystore_->abort(active_operations_[handle], &result); + auto binder_result = keystore_->abort(promise, active_operations_[handle], &result); if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR; - if (KeyStoreNativeReturnCode(result).isOk()) { + KeyStoreNativeReturnCode rc(result); + if (!rc.isOk()) return rc; + rc = KeyStoreNativeReturnCode(future.get().response_code()); + if (rc.isOk()) { active_operations_.erase(handle); } - return KeyStoreNativeReturnCode(result); + return rc; } bool KeystoreClientImpl::doesKeyExist(const std::string& key_name) { diff --git a/keystore/keystore_get.cpp b/keystore/keystore_get.cpp index fec36c4c..a6f87557 100644 --- a/keystore/keystore_get.cpp +++ b/keystore/keystore_get.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include +#include #include #include @@ -26,8 +26,8 @@ using namespace keystore; ssize_t keystore_get(const char* key, size_t keyLength, uint8_t** value) { sp sm = defaultServiceManager(); sp binder = sm->getService(String16("android.security.keystore")); - sp service = - interface_cast(binder); + sp service = + interface_cast(binder); if (service == nullptr) { return -1; diff --git a/keystore/keystore_main.cpp b/keystore/keystore_main.cpp index c05d1428..409ac837 100644 --- a/keystore/keystore_main.cpp +++ b/keystore/keystore_main.cpp @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include #include diff --git a/keystore/keystore_utils.cpp b/keystore/keystore_utils.cpp index 71e8ed2e..78056d64 100644 --- a/keystore/keystore_utils.cpp +++ b/keystore/keystore_utils.cpp @@ -107,8 +107,7 @@ void log_key_integrity_violation(const char* name, uid_t uid) { namespace keystore { hidl_vec blob2hidlVec(const Blob& blob) { - hidl_vec result; - result.setToExternal(const_cast(blob.getValue()), blob.getLength()); + hidl_vec result(blob.getValue(), blob.getValue() + blob.getLength()); return result; } diff --git a/keystore/legacy_keymaster_device_wrapper.cpp b/keystore/legacy_keymaster_device_wrapper.cpp index 1f1aa968..4073b42e 100644 --- a/keystore/legacy_keymaster_device_wrapper.cpp +++ b/keystore/legacy_keymaster_device_wrapper.cpp @@ -132,14 +132,18 @@ inline static keymaster_key_blob_t hidlVec2KmKeyBlob(const hidl_vec& bl } inline static hidl_vec kmBlob2hidlVec(const keymaster_key_blob_t& blob) { - hidl_vec result; - result.setToExternal(const_cast(blob.key_material), blob.key_material_size); - return result; + if (blob.key_material == nullptr || blob.key_material_size == 0) { + return {}; + } else { + return hidl_vec(blob.key_material, blob.key_material + blob.key_material_size); + } } inline static hidl_vec kmBlob2hidlVec(const keymaster_blob_t& blob) { - hidl_vec result; - result.setToExternal(const_cast(blob.data), blob.data_length); - return result; + if (blob.data == nullptr || blob.data_length == 0) { + return {}; + } else { + return hidl_vec(blob.data, blob.data + blob.data_length); + } } inline static hidl_vec> @@ -186,8 +190,7 @@ static inline hidl_vec kmParamSet2Hidl(const keymaster_key_param_s break; case KM_BIGNUM: case KM_BYTES: - result[i].blob.setToExternal(const_cast(params[i].blob.data), - params[i].blob.data_length); + result[i].blob = kmBlob2hidlVec(params[i].blob); break; case KM_INVALID: default: