summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBartosz Fabianowski <bartfab@google.com>2017-04-27 04:21:23 +0000
committerandroid-build-merger <android-build-merger@google.com>2017-04-27 04:21:23 +0000
commit4dac5a998d744bf09bc3a801af3aac9904a86be5 (patch)
tree0f08100ed68a4cce283a45c0379e7f61825415e8
parent4e26514ca3fc895df0c43d6a12b2d51e5adfe5e3 (diff)
parent77485b71fb58dde5281bca004f2aa06b445dd0d1 (diff)
downloadsecurity-4dac5a998d744bf09bc3a801af3aac9904a86be5.tar.gz
Add device ID attestation method to keymaster am: 5aa93e08a8
am: 77485b71fb Change-Id: Id6cdf7e95e16f12ab0cfdc9fcd47feeac3a34ee3
-rw-r--r--keystore/IKeystoreService.cpp38
-rw-r--r--keystore/include/keystore/IKeystoreService.h7
-rw-r--r--keystore/key_store_service.cpp165
-rw-r--r--keystore/key_store_service.h3
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: