diff options
author | Bartosz Fabianowski <bartfab@google.com> | 2017-04-27 04:21:23 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2017-04-27 04:21:23 +0000 |
commit | 4dac5a998d744bf09bc3a801af3aac9904a86be5 (patch) | |
tree | 0f08100ed68a4cce283a45c0379e7f61825415e8 | |
parent | 4e26514ca3fc895df0c43d6a12b2d51e5adfe5e3 (diff) | |
parent | 77485b71fb58dde5281bca004f2aa06b445dd0d1 (diff) | |
download | security-4dac5a998d744bf09bc3a801af3aac9904a86be5.tar.gz |
Add device ID attestation method to keymaster am: 5aa93e08a8
am: 77485b71fb
Change-Id: Id6cdf7e95e16f12ab0cfdc9fcd47feeac3a34ee3
-rw-r--r-- | keystore/IKeystoreService.cpp | 38 | ||||
-rw-r--r-- | keystore/include/keystore/IKeystoreService.h | 7 | ||||
-rw-r--r-- | keystore/key_store_service.cpp | 165 | ||||
-rw-r--r-- | keystore/key_store_service.h | 3 |
4 files changed, 165 insertions, 48 deletions
diff --git a/keystore/IKeystoreService.cpp b/keystore/IKeystoreService.cpp index 4c26b60d..344687bd 100644 --- a/keystore/IKeystoreService.cpp +++ b/keystore/IKeystoreService.cpp @@ -878,6 +878,31 @@ class BpKeystoreService : public BpInterface<IKeystoreService> { return ret; } + KeyStoreServiceReturnCode attestDeviceIds(const hidl_vec<KeyParameter>& params, + hidl_vec<hidl_vec<uint8_t>>* outChain) override { + if (!outChain) return ErrorCode::OUTPUT_PARAMETER_NULL; + + Parcel data, reply; + data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); + nullable(writeParamSetToParcel, params, &data); + + status_t status = remote()->transact(BnKeystoreService::ATTEST_DEVICE_IDS, data, &reply); + if (status != NO_ERROR) { + ALOGD("attestDeviceIds() count not contact remote: %d\n", status); + return ResponseCode::SYSTEM_ERROR; + } + int32_t err = reply.readExceptionCode(); + ResponseCode ret = ResponseCode(reply.readInt32()); + if (err < 0) { + ALOGD("attestDeviceIds() caught exception %d\n", err); + return ResponseCode::SYSTEM_ERROR; + } + if (reply.readInt32() != 0) { + *outChain = readCertificateChainFromParcel(reply); + } + return ret; + } + KeyStoreServiceReturnCode onDeviceOffBody() override { Parcel data, reply; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); @@ -1305,6 +1330,19 @@ status_t BnKeystoreService::onTransact(uint32_t code, const Parcel& data, Parcel return NO_ERROR; } + + case ATTEST_DEVICE_IDS: { + CHECK_INTERFACE(IKeystoreService, data, reply); + auto params = nullable(readParamSetFromParcel, data); + hidl_vec<hidl_vec<uint8_t>> chain; + int ret = attestDeviceIds(params.value(), &chain); + reply->writeNoException(); + reply->writeInt32(ret); + nullable(writeCertificateChainToParcel, chain, reply); + + return NO_ERROR; + } + case ON_DEVICE_OFF_BODY: { CHECK_INTERFACE(IKeystoreService, data, reply); int32_t ret = onDeviceOffBody(); diff --git a/keystore/include/keystore/IKeystoreService.h b/keystore/include/keystore/IKeystoreService.h index 5d885645..18bd8eb7 100644 --- a/keystore/include/keystore/IKeystoreService.h +++ b/keystore/include/keystore/IKeystoreService.h @@ -112,7 +112,8 @@ class IKeystoreService : public IInterface { ON_USER_ADDED = IBinder::FIRST_CALL_TRANSACTION + 33, ON_USER_REMOVED = IBinder::FIRST_CALL_TRANSACTION + 34, ATTEST_KEY = IBinder::FIRST_CALL_TRANSACTION + 35, - ON_DEVICE_OFF_BODY = IBinder::FIRST_CALL_TRANSACTION + 36, + ATTEST_DEVICE_IDS = IBinder::FIRST_CALL_TRANSACTION + 36, + ON_DEVICE_OFF_BODY = IBinder::FIRST_CALL_TRANSACTION + 37, }; DECLARE_META_INTERFACE(KeystoreService); @@ -234,6 +235,10 @@ class IKeystoreService : public IInterface { attestKey(const String16& name, const ::keystore::hidl_vec<::keystore::KeyParameter>& params, ::keystore::hidl_vec<::keystore::hidl_vec<uint8_t>>* outChain) = 0; + virtual ::keystore::KeyStoreServiceReturnCode attestDeviceIds( + const ::keystore::hidl_vec<::keystore::KeyParameter>& params, + ::keystore::hidl_vec<::keystore::hidl_vec<uint8_t>>* outChain) = 0; + virtual ::keystore::KeyStoreServiceReturnCode onDeviceOffBody() = 0; }; diff --git a/keystore/key_store_service.cpp b/keystore/key_store_service.cpp index a509eeaa..95c01092 100644 --- a/keystore/key_store_service.cpp +++ b/keystore/key_store_service.cpp @@ -89,6 +89,36 @@ std::pair<KeyStoreServiceReturnCode, bool> hadFactoryResetSinceIdRotation() { return {ResponseCode::NO_ERROR, true}; } +constexpr size_t KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE = 1024; + +KeyStoreServiceReturnCode updateParamsForAttestation(uid_t callingUid, AuthorizationSet* params) { + KeyStoreServiceReturnCode responseCode; + bool factoryResetSinceIdRotation; + std::tie(responseCode, factoryResetSinceIdRotation) = hadFactoryResetSinceIdRotation(); + + if (!responseCode.isOk()) return responseCode; + if (factoryResetSinceIdRotation) params->push_back(TAG_RESET_SINCE_ID_ROTATION); + + auto asn1_attestation_id_result = security::gather_attestation_application_id(callingUid); + if (!asn1_attestation_id_result.isOk()) { + ALOGE("failed to gather attestation_id"); + return ErrorCode::ATTESTATION_APPLICATION_ID_MISSING; + } + std::vector<uint8_t>& asn1_attestation_id = asn1_attestation_id_result; + + /* + * The attestation application ID cannot be longer than + * KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE, so we truncate if too long. + */ + if (asn1_attestation_id.size() > KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE) { + asn1_attestation_id.resize(KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE); + } + + params->push_back(TAG_ATTESTATION_APPLICATION_ID, asn1_attestation_id); + + return ResponseCode::NO_ERROR; +} + } // anonymous namespace void KeyStoreService::binderDied(const wp<IBinder>& who) { @@ -1304,8 +1334,6 @@ KeyStoreServiceReturnCode KeyStoreService::addAuthToken(const uint8_t* token, si return ResponseCode::NO_ERROR; } -constexpr size_t KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE = 1024; - bool isDeviceIdAttestationRequested(const hidl_vec<KeyParameter>& params) { for (size_t i = 0; i < params.size(); ++i) { switch (params[i].tag) { @@ -1336,74 +1364,117 @@ KeyStoreServiceReturnCode KeyStoreService::attestKey(const String16& name, return ErrorCode::INVALID_ARGUMENT; } + if (isDeviceIdAttestationRequested(params)) { + // There is a dedicated attestDeviceIds() method for device ID attestation. + return ErrorCode::INVALID_ARGUMENT; + } + uid_t callingUid = IPCThreadState::self()->getCallingUid(); - bool attestingDeviceIds = isDeviceIdAttestationRequested(params); - if (attestingDeviceIds) { - sp<IBinder> binder = defaultServiceManager()->getService(String16("permission")); - if (binder == 0) { - return ErrorCode::CANNOT_ATTEST_IDS; - } - if (!interface_cast<IPermissionController>(binder)->checkPermission( - String16("android.permission.READ_PRIVILEGED_PHONE_STATE"), - IPCThreadState::self()->getCallingPid(), callingUid)) { - return ErrorCode::CANNOT_ATTEST_IDS; - } + AuthorizationSet mutableParams = params; + KeyStoreServiceReturnCode rc = updateParamsForAttestation(callingUid, &mutableParams); + if (!rc.isOk()) { + return rc; } - AuthorizationSet mutableParams = params; + Blob keyBlob; + String8 name8(name); + rc = mKeyStore->getKeyForName(&keyBlob, name8, callingUid, TYPE_KEYMASTER_10); + if (!rc.isOk()) { + return rc; + } - KeyStoreServiceReturnCode responseCode; - bool factoryResetSinceIdRotation; - std::tie(responseCode, factoryResetSinceIdRotation) = hadFactoryResetSinceIdRotation(); + KeyStoreServiceReturnCode error; + auto hidlCb = [&](ErrorCode ret, const hidl_vec<hidl_vec<uint8_t>>& certChain) { + error = ret; + if (!error.isOk()) { + return; + } + if (outChain) *outChain = certChain; + }; - if (!responseCode.isOk()) return responseCode; - if (factoryResetSinceIdRotation) mutableParams.push_back(TAG_RESET_SINCE_ID_ROTATION); + auto hidlKey = blob2hidlVec(keyBlob); + auto& dev = mKeyStore->getDevice(keyBlob); + rc = KS_HANDLE_HIDL_ERROR(dev->attestKey(hidlKey, mutableParams.hidl_data(), hidlCb)); + if (!rc.isOk()) { + return rc; + } + return error; +} - Blob keyBlob; - String8 name8(name); - responseCode = mKeyStore->getKeyForName(&keyBlob, name8, callingUid, TYPE_KEYMASTER_10); - if (!responseCode.isOk()) { - return responseCode; +KeyStoreServiceReturnCode KeyStoreService::attestDeviceIds(const hidl_vec<KeyParameter>& params, + hidl_vec<hidl_vec<uint8_t>>* outChain) { + if (!outChain) { + return ErrorCode::OUTPUT_PARAMETER_NULL; } - auto asn1_attestation_id_result = security::gather_attestation_application_id(callingUid); - if (!asn1_attestation_id_result.isOk()) { - ALOGE("failed to gather attestation_id"); - return ErrorCode::ATTESTATION_APPLICATION_ID_MISSING; + if (!checkAllowedOperationParams(params)) { + return ErrorCode::INVALID_ARGUMENT; } - std::vector<uint8_t>& asn1_attestation_id = asn1_attestation_id_result; - /* - * The attestation application ID cannot be longer than - * KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE, so we truncate if too long. - */ - if (asn1_attestation_id.size() > KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE) { - asn1_attestation_id.resize(KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE); + if (!isDeviceIdAttestationRequested(params)) { + // There is an attestKey() method for attesting keys without device ID attestation. + return ErrorCode::INVALID_ARGUMENT; } - mutableParams.push_back(TAG_ATTESTATION_APPLICATION_ID, blob2hidlVec(asn1_attestation_id)); + uid_t callingUid = IPCThreadState::self()->getCallingUid(); + sp<IBinder> binder = defaultServiceManager()->getService(String16("permission")); + if (binder == 0) { + return ErrorCode::CANNOT_ATTEST_IDS; + } + if (!interface_cast<IPermissionController>(binder)->checkPermission( + String16("android.permission.READ_PRIVILEGED_PHONE_STATE"), + IPCThreadState::self()->getCallingPid(), callingUid)) { + return ErrorCode::CANNOT_ATTEST_IDS; + } + AuthorizationSet mutableParams = params; + KeyStoreServiceReturnCode rc = updateParamsForAttestation(callingUid, &mutableParams); + if (!rc.isOk()) { + return rc; + } + + // Generate temporary key. + auto& dev = mKeyStore->getDevice(); KeyStoreServiceReturnCode error; - auto hidlCb = [&](ErrorCode ret, const hidl_vec<hidl_vec<uint8_t>>& certChain) { + hidl_vec<uint8_t> hidlKey; + + AuthorizationSet keyCharacteristics; + keyCharacteristics.push_back(TAG_PURPOSE, KeyPurpose::VERIFY); + keyCharacteristics.push_back(TAG_ALGORITHM, Algorithm::EC); + keyCharacteristics.push_back(TAG_DIGEST, Digest::SHA_2_256); + keyCharacteristics.push_back(TAG_NO_AUTH_REQUIRED); + keyCharacteristics.push_back(TAG_EC_CURVE, EcCurve::P_256); + auto generateHidlCb = [&](ErrorCode ret, const hidl_vec<uint8_t>& hidlKeyBlob, + const KeyCharacteristics&) { error = ret; if (!error.isOk()) { return; } - if (outChain) *outChain = certChain; + hidlKey = hidlKeyBlob; }; - auto hidlKey = blob2hidlVec(keyBlob); - auto& dev = mKeyStore->getDevice(keyBlob); + rc = KS_HANDLE_HIDL_ERROR(dev->generateKey(keyCharacteristics.hidl_data(), generateHidlCb)); + if (!rc.isOk()) { + return rc; + } + if (!error.isOk()) { + return error; + } + + // Attest key and device IDs. + auto attestHidlCb = [&](ErrorCode ret, const hidl_vec<hidl_vec<uint8_t>>& certChain) { + error = ret; + if (!error.isOk()) { + return; + } + *outChain = certChain; + }; KeyStoreServiceReturnCode attestationRc = - KS_HANDLE_HIDL_ERROR(dev->attestKey(hidlKey, mutableParams.hidl_data(), hidlCb)); + KS_HANDLE_HIDL_ERROR(dev->attestKey(hidlKey, mutableParams.hidl_data(), attestHidlCb)); - KeyStoreServiceReturnCode deletionRc; - if (attestingDeviceIds) { - // When performing device id attestation, treat the key as ephemeral and delete it straight - // away. - deletionRc = del(name, callingUid); - } + // Delete temporary key. + KeyStoreServiceReturnCode deletionRc = KS_HANDLE_HIDL_ERROR(dev->deleteKey(hidlKey)); if (!attestationRc.isOk()) { return attestationRc; diff --git a/keystore/key_store_service.h b/keystore/key_store_service.h index 432e7808..3b4ef85b 100644 --- a/keystore/key_store_service.h +++ b/keystore/key_store_service.h @@ -131,6 +131,9 @@ class KeyStoreService : public android::BnKeystoreService, public android::IBind const hidl_vec<KeyParameter>& params, hidl_vec<hidl_vec<uint8_t>>* outChain) override; + KeyStoreServiceReturnCode attestDeviceIds(const hidl_vec<KeyParameter>& params, + hidl_vec<hidl_vec<uint8_t>>* outChain) override; + KeyStoreServiceReturnCode onDeviceOffBody() override; private: |