summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Willden <swillden@google.com>2015-06-18 18:23:54 -0600
committerShawn Willden <swillden@google.com>2015-06-19 20:02:22 -0600
commit9221bff2f13451ef330135bb32ea96de2a8b09cc (patch)
treee824126f98cb26ee895af41448a914bf595eecf4
parent84c14f0957b365fd33534b88b7eec97b287b67b9 (diff)
downloadandroid_system_security-9221bff2f13451ef330135bb32ea96de2a8b09cc.tar.gz
android_system_security-9221bff2f13451ef330135bb32ea96de2a8b09cc.tar.bz2
android_system_security-9221bff2f13451ef330135bb32ea96de2a8b09cc.zip
Add keymaster authorization policy enforcement to keystore.
Bug: 19511945 Change-Id: I76c04e8d3253ba490cedac53bbc75943ec68df1d
-rw-r--r--keystore/Android.mk3
-rw-r--r--keystore/keystore.cpp68
-rw-r--r--keystore/keystore_keymaster_enforcement.h65
-rw-r--r--keystore/operation.cpp9
-rw-r--r--keystore/operation.h14
5 files changed, 142 insertions, 17 deletions
diff --git a/keystore/Android.mk b/keystore/Android.mk
index 9463f3d..e18b2d8 100644
--- a/keystore/Android.mk
+++ b/keystore/Android.mk
@@ -33,7 +33,8 @@ LOCAL_SHARED_LIBRARIES := \
libutils \
libselinux \
libsoftkeymasterdevice \
- libkeymaster_messages
+ libkeymaster_messages \
+ libkeymaster1
LOCAL_MODULE := keystore
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUES := system/keymaster/
diff --git a/keystore/keystore.cpp b/keystore/keystore.cpp
index ae3b1e4..b36f65f 100644
--- a/keystore/keystore.cpp
+++ b/keystore/keystore.cpp
@@ -67,6 +67,7 @@
#include "auth_token_table.h"
#include "defaults.h"
+#include "keystore_keymaster_enforcement.h"
#include "operation.h"
/* KeyStore is a secured storage for key-value pairs. In this implementation,
@@ -2480,6 +2481,26 @@ public:
keymaster_key_param_set_t outParams = {NULL, 0};
err = dev->begin(dev, purpose, &key, &inParams, &outParams, &handle);
+ // Create a keyid for this key.
+ keymaster::km_id_t keyid;
+ if (!enforcement_policy.CreateKeyId(key, &keyid)) {
+ ALOGE("Failed to create a key ID for authorization checking.");
+ result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+ return;
+ }
+
+ // Check that all key authorization policy requirements are met.
+ keymaster::AuthorizationSet key_auths(characteristics->hw_enforced);
+ key_auths.push_back(characteristics->sw_enforced);
+ keymaster::AuthorizationSet operation_params(inParams);
+ err = enforcement_policy.AuthorizeOperation(purpose, keyid, key_auths, operation_params,
+ 0 /* op_handle */,
+ true /* is_begin_operation */);
+ if (err) {
+ result->resultCode = err;
+ return;
+ }
+
// If there are too many operations abort the oldest operation that was
// started as pruneable and try again.
while (err == KM_ERROR_TOO_MANY_OPERATIONS && mOperationMap.hasPruneableOperation()) {
@@ -2495,8 +2516,8 @@ public:
return;
}
- sp<IBinder> operationToken = mOperationMap.addOperation(handle, purpose, dev, appToken,
- characteristics.release(),
+ sp<IBinder> operationToken = mOperationMap.addOperation(handle, keyid, purpose, dev,
+ appToken, characteristics.release(),
pruneable);
if (authToken) {
mOperationMap.setOperationAuthToken(operationToken, authToken);
@@ -2524,7 +2545,9 @@ public:
const keymaster1_device_t* dev;
keymaster_operation_handle_t handle;
keymaster_purpose_t purpose;
- if (!mOperationMap.getOperation(token, &handle, &purpose, &dev, NULL)) {
+ keymaster::km_id_t keyid;
+ const keymaster_key_characteristics_t* characteristics;
+ if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
result->resultCode = KM_ERROR_INVALID_OPERATION_HANDLE;
return;
}
@@ -2540,6 +2563,18 @@ public:
keymaster_blob_t output = {NULL, 0};
keymaster_key_param_set_t outParams = {NULL, 0};
+ // Check that all key authorization policy requirements are met.
+ keymaster::AuthorizationSet key_auths(characteristics->hw_enforced);
+ key_auths.push_back(characteristics->sw_enforced);
+ keymaster::AuthorizationSet operation_params(inParams);
+ result->resultCode =
+ enforcement_policy.AuthorizeOperation(purpose, keyid, key_auths,
+ operation_params, handle,
+ false /* is_begin_operation */);
+ if (result->resultCode) {
+ return;
+ }
+
keymaster_error_t err = dev->update(dev, handle, &inParams, &input, &consumed, &outParams,
&output);
result->data.reset(const_cast<uint8_t*>(output.data));
@@ -2562,7 +2597,9 @@ public:
const keymaster1_device_t* dev;
keymaster_operation_handle_t handle;
keymaster_purpose_t purpose;
- if (!mOperationMap.getOperation(token, &handle, &purpose, &dev, NULL)) {
+ keymaster::km_id_t keyid;
+ const keymaster_key_characteristics_t* characteristics;
+ if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
result->resultCode = KM_ERROR_INVALID_OPERATION_HANDLE;
return;
}
@@ -2589,6 +2626,18 @@ public:
keymaster_blob_t input = {signature, signatureLength};
keymaster_blob_t output = {NULL, 0};
keymaster_key_param_set_t outParams = {NULL, 0};
+
+ // Check that all key authorization policy requirements are met.
+ keymaster::AuthorizationSet key_auths(characteristics->hw_enforced);
+ key_auths.push_back(characteristics->sw_enforced);
+ keymaster::AuthorizationSet operation_params(inParams);
+ err = enforcement_policy.AuthorizeOperation(purpose, keyid, key_auths, operation_params,
+ handle, false /* is_begin_operation */);
+ if (err) {
+ result->resultCode = err;
+ return;
+ }
+
err = dev->finish(dev, handle, &inParams, &input, &outParams, &output);
// Remove the operation regardless of the result
mOperationMap.removeOperation(token);
@@ -2607,7 +2656,8 @@ public:
const keymaster1_device_t* dev;
keymaster_operation_handle_t handle;
keymaster_purpose_t purpose;
- if (!mOperationMap.getOperation(token, &handle, &purpose, &dev, NULL)) {
+ keymaster::km_id_t keyid;
+ if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, NULL)) {
return KM_ERROR_INVALID_OPERATION_HANDLE;
}
mOperationMap.removeOperation(token);
@@ -2629,7 +2679,8 @@ public:
keymaster_operation_handle_t handle;
const keymaster_key_characteristics_t* characteristics;
keymaster_purpose_t purpose;
- if (!mOperationMap.getOperation(token, &handle, &purpose, &dev, &characteristics)) {
+ keymaster::km_id_t keyid;
+ if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
return false;
}
const hw_auth_token_t* authToken = NULL;
@@ -2894,7 +2945,9 @@ private:
keymaster_operation_handle_t handle;
const keymaster_key_characteristics_t* characteristics = NULL;
keymaster_purpose_t purpose;
- if (!mOperationMap.getOperation(token, &handle, &purpose, &dev, &characteristics)) {
+ keymaster::km_id_t keyid;
+ if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev,
+ &characteristics)) {
return KM_ERROR_INVALID_OPERATION_HANDLE;
}
int32_t result = getAuthToken(characteristics, handle, purpose, &authToken);
@@ -3034,6 +3087,7 @@ private:
::KeyStore* mKeyStore;
OperationMap mOperationMap;
keymaster::AuthTokenTable mAuthTokenTable;
+ KeystoreKeymasterEnforcement enforcement_policy;
};
}; // namespace android
diff --git a/keystore/keystore_keymaster_enforcement.h b/keystore/keystore_keymaster_enforcement.h
new file mode 100644
index 0000000..904bf66
--- /dev/null
+++ b/keystore/keystore_keymaster_enforcement.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2015 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_KEYMASTER_ENFORCEMENT_H_
+#define KEYSTORE_KEYMASTER_ENFORCEMENT_H_
+
+#include <time.h>
+
+#include <keymaster/keymaster_enforcement.h>
+
+/**
+ * This is a specialization of the KeymasterEnforcement class to be used by Keystore to enforce
+ * keymaster requirements on all key operation.
+ */
+class KeystoreKeymasterEnforcement : public keymaster::KeymasterEnforcement {
+ public:
+ KeystoreKeymasterEnforcement() : KeymasterEnforcement(64, 64) {}
+
+ uint32_t get_current_time() const override {
+ struct timespec tp;
+ int err = clock_gettime(CLOCK_MONOTONIC, &tp);
+ if (err || tp.tv_sec < 0)
+ return 0;
+ return static_cast<uint32_t>(tp.tv_sec);
+ }
+
+ bool activation_date_valid(uint64_t activation_date) const override {
+ // Convert java date to time_t, non-portably.
+ time_t activation_time = activation_date / 1000;
+ return difftime(time(NULL), activation_time) >= 0;
+ }
+
+ bool expiration_date_passed(uint64_t expiration_date) const override {
+ // Convert jave date to time_t, non-portably.
+ time_t expiration_time = expiration_date / 1000;
+ return difftime(time(NULL), expiration_time) > 0;
+ }
+
+ bool auth_token_timed_out(const hw_auth_token_t&, uint32_t) const {
+ // Non-secure world cannot check token timeouts because it doesn't have access to the secure
+ // clock. Assume the token is good.
+ return true;
+ }
+
+ bool ValidateTokenSignature(const hw_auth_token_t&) const override {
+ // Non-secure world cannot validate token signatures because it doesn't have access to the
+ // signing key. Assume the token is good.
+ return true;
+ }
+};
+
+#endif // KEYSTORE_KEYMASTER_ENFORCEMENT_H_
diff --git a/keystore/operation.cpp b/keystore/operation.cpp
index 087beff..aa37101 100644
--- a/keystore/operation.cpp
+++ b/keystore/operation.cpp
@@ -25,13 +25,13 @@ OperationMap::OperationMap(IBinder::DeathRecipient* deathRecipient)
}
sp<IBinder> OperationMap::addOperation(keymaster_operation_handle_t handle,
- keymaster_purpose_t purpose,
+ uint64_t keyid, keymaster_purpose_t purpose,
const keymaster1_device_t* dev,
sp<IBinder> appToken,
keymaster_key_characteristics_t* characteristics,
bool pruneable) {
sp<IBinder> token = new BBinder();
- mMap[token] = std::move(Operation(handle, purpose, dev, characteristics, appToken));
+ mMap[token] = std::move(Operation(handle, keyid, purpose, dev, characteristics, appToken));
if (pruneable) {
mLru.push_back(token);
}
@@ -43,7 +43,7 @@ sp<IBinder> OperationMap::addOperation(keymaster_operation_handle_t handle,
}
bool OperationMap::getOperation(sp<IBinder> token, keymaster_operation_handle_t* outHandle,
- keymaster_purpose_t* outPurpose,
+ uint64_t* outKeyid, keymaster_purpose_t* outPurpose,
const keymaster1_device_t** outDevice,
const keymaster_key_characteristics_t** outCharacteristics) {
if (!outHandle || !outDevice) {
@@ -56,6 +56,7 @@ bool OperationMap::getOperation(sp<IBinder> token, keymaster_operation_handle_t*
updateLru(token);
*outHandle = entry->second.handle;
+ *outKeyid = entry->second.keyid;
*outPurpose = entry->second.purpose;
*outDevice = entry->second.device;
if (outCharacteristics) {
@@ -142,11 +143,13 @@ std::vector<sp<IBinder>> OperationMap::getOperationsForToken(sp<IBinder> appToke
}
OperationMap::Operation::Operation(keymaster_operation_handle_t handle_,
+ uint64_t keyid_,
keymaster_purpose_t purpose_,
const keymaster1_device_t* device_,
keymaster_key_characteristics_t* characteristics_,
sp<IBinder> appToken_)
: handle(handle_),
+ keyid(keyid_),
purpose(purpose_),
device(device_),
characteristics(characteristics_),
diff --git a/keystore/operation.h b/keystore/operation.h
index d0e65a5..6806388 100644
--- a/keystore/operation.h
+++ b/keystore/operation.h
@@ -47,12 +47,13 @@ typedef std::unique_ptr<keymaster_key_characteristics_t, keymaster_key_character
class OperationMap {
public:
OperationMap(IBinder::DeathRecipient* deathRecipient);
- sp<IBinder> addOperation(keymaster_operation_handle_t handle, keymaster_purpose_t purpose,
- const keymaster1_device_t* dev, sp<IBinder> appToken,
- keymaster_key_characteristics_t* characteristics, bool pruneable);
- bool hasOperation(sp<IBinder> token);
+ sp<IBinder> addOperation(keymaster_operation_handle_t handle, uint64_t keyid,
+ keymaster_purpose_t purpose, const keymaster1_device_t* dev,
+ sp<IBinder> appToken, keymaster_key_characteristics_t* characteristics,
+ bool pruneable);
bool getOperation(sp<IBinder> token, keymaster_operation_handle_t* outHandle,
- keymaster_purpose_t* outPurpose, const keymaster1_device_t** outDev,
+ uint64_t* outKeyid, keymaster_purpose_t* outPurpose,
+ const keymaster1_device_t** outDev,
const keymaster_key_characteristics_t** outCharacteristics);
bool removeOperation(sp<IBinder> token);
bool hasPruneableOperation();
@@ -66,10 +67,11 @@ private:
void removeOperationTracking(sp<IBinder> token, sp<IBinder> appToken);
struct Operation {
Operation();
- Operation(keymaster_operation_handle_t handle, keymaster_purpose_t purpose,
+ Operation(keymaster_operation_handle_t handle, uint64_t keyid, keymaster_purpose_t purpose,
const keymaster1_device_t* device,
keymaster_key_characteristics_t* characteristics, sp<IBinder> appToken);
keymaster_operation_handle_t handle;
+ uint64_t keyid;
keymaster_purpose_t purpose;
const keymaster1_device_t* device;
Unique_keymaster_key_characteristics characteristics;