summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Willden <swillden@google.com>2015-08-13 20:49:53 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2015-08-13 20:49:53 +0000
commitc2120744da8d0612ad54484b314f94e1e6e3a167 (patch)
tree1fb0ca7ad10b52be6d6f4bf0ffe781faa698cbaf
parentcbfdeefef7a12fcb383e8b0f840771f6983927aa (diff)
parent55268b5b037a8c3537602b1073ad624455d3672d (diff)
downloadandroid_system_security-c2120744da8d0612ad54484b314f94e1e6e3a167.tar.gz
android_system_security-c2120744da8d0612ad54484b314f94e1e6e3a167.tar.bz2
android_system_security-c2120744da8d0612ad54484b314f94e1e6e3a167.zip
Merge "Wrap incomplete keymaster1 implementations with sw keymaster." into mnc-dr-dev
-rw-r--r--keystore/keystore.cpp248
1 files changed, 175 insertions, 73 deletions
diff --git a/keystore/keystore.cpp b/keystore/keystore.cpp
index 65a8ea9..0906abf 100644
--- a/keystore/keystore.cpp
+++ b/keystore/keystore.cpp
@@ -80,6 +80,7 @@
#define VALUE_SIZE 32768
#define PASSWORD_SIZE VALUE_SIZE
+using keymaster::SoftKeymasterDevice;
struct BIGNUM_Delete {
void operator()(BIGNUM* p) const {
@@ -109,36 +110,112 @@ struct PKCS8_PRIV_KEY_INFO_Delete {
};
typedef UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> Unique_PKCS8_PRIV_KEY_INFO;
-static int keymaster_device_initialize(keymaster1_device_t** dev) {
- int rc;
+static int keymaster0_device_initialize(const hw_module_t* mod, keymaster1_device_t** dev) {
+ assert(mod->module_api_version < KEYMASTER_MODULE_API_VERSION_1_0);
+ ALOGI("Found keymaster0 module %s, version %x", mod->name, mod->module_api_version);
- const hw_module_t* mod;
- keymaster::SoftKeymasterDevice* softkeymaster = NULL;
- rc = hw_get_module_by_class(KEYSTORE_HARDWARE_MODULE_ID, NULL, &mod);
+ UniquePtr<SoftKeymasterDevice> soft_keymaster(new SoftKeymasterDevice);
+ keymaster0_device_t* km0_device = NULL;
+ keymaster_error_t error = KM_ERROR_OK;
+
+ int rc = keymaster0_open(mod, &km0_device);
if (rc) {
- ALOGE("could not find any keystore module");
- goto out;
+ ALOGE("Error opening keystore keymaster0 device.");
+ goto err;
}
- rc = mod->methods->open(mod, KEYSTORE_KEYMASTER, reinterpret_cast<struct hw_device_t**>(dev));
+ if (km0_device->flags & KEYMASTER_SOFTWARE_ONLY) {
+ ALOGI("Keymaster0 module is software-only. Using SoftKeymasterDevice instead.");
+ km0_device->common.close(&km0_device->common);
+ km0_device = NULL;
+ // SoftKeymasterDevice will be deleted by keymaster_device_release()
+ *dev = soft_keymaster.release()->keymaster_device();
+ return 0;
+ }
+
+ ALOGE("Wrapping keymaster0 module %s with SoftKeymasterDevice", mod->name);
+ error = soft_keymaster->SetHardwareDevice(km0_device);
+ km0_device = NULL; // SoftKeymasterDevice has taken ownership.
+ if (error != KM_ERROR_OK) {
+ ALOGE("Got error %d from SetHardwareDevice", error);
+ rc = error;
+ goto err;
+ }
+
+ // SoftKeymasterDevice will be deleted by keymaster_device_release()
+ *dev = soft_keymaster.release()->keymaster_device();
+ return 0;
+
+err:
+ if (km0_device)
+ km0_device->common.close(&km0_device->common);
+ *dev = NULL;
+ return rc;
+}
+
+static int keymaster1_device_initialize(const hw_module_t* mod, keymaster1_device_t** dev) {
+ assert(mod->module_api_version >= KEYMASTER_MODULE_API_VERSION_1_0);
+ ALOGI("Found keymaster1 module %s, version %x", mod->name, mod->module_api_version);
+
+ UniquePtr<SoftKeymasterDevice> soft_keymaster(new SoftKeymasterDevice);
+ keymaster1_device_t* km1_device = NULL;
+ keymaster_error_t error = KM_ERROR_OK;
+
+ int rc = keymaster1_open(mod, &km1_device);
if (rc) {
- ALOGE("could not open keymaster device in %s (%s)",
- KEYSTORE_HARDWARE_MODULE_ID, strerror(-rc));
- goto out;
+ ALOGE("Error %d opening keystore keymaster1 device", rc);
+ goto err;
+ }
+
+ error = soft_keymaster->SetHardwareDevice(km1_device);
+ km1_device = NULL; // SoftKeymasterDevice has taken ownership.
+ if (error != KM_ERROR_OK) {
+ ALOGE("Got error %d from SetHardwareDevice", error);
+ rc = error;
+ goto err;
}
- // Wrap older hardware modules with a softkeymaster adapter.
- if ((*dev)->common.module->module_api_version >= KEYMASTER_MODULE_API_VERSION_1_0) {
+ if (!soft_keymaster->Keymaster1DeviceIsGood()) {
+ ALOGI("Keymaster1 module is incomplete, using SoftKeymasterDevice wrapper");
+ // SoftKeymasterDevice will be deleted by keymaster_device_release()
+ *dev = soft_keymaster.release()->keymaster_device();
+ return 0;
+ } else {
+ ALOGI("Keymaster1 module is good, destroying wrapper and re-opening");
+ soft_keymaster.reset(NULL);
+ rc = keymaster1_open(mod, &km1_device);
+ if (rc) {
+ ALOGE("Error %d re-opening keystore keymaster1 device.", rc);
+ goto err;
+ }
+ *dev = km1_device;
return 0;
}
- softkeymaster =
- new keymaster::SoftKeymasterDevice(reinterpret_cast<keymaster0_device_t*>(*dev));
- *dev = softkeymaster->keymaster_device();
- return 0;
-out:
+err:
+ if (km1_device)
+ km1_device->common.close(&km1_device->common);
*dev = NULL;
return rc;
+
+}
+
+static int keymaster_device_initialize(keymaster1_device_t** dev) {
+ const hw_module_t* mod;
+
+ int rc = hw_get_module_by_class(KEYSTORE_HARDWARE_MODULE_ID, NULL, &mod);
+ if (rc) {
+ ALOGI("Could not find any keystore module, using software-only implementation.");
+ // SoftKeymasterDevice will be deleted by keymaster_device_release()
+ *dev = (new SoftKeymasterDevice)->keymaster_device();
+ return 0;
+ }
+
+ if (mod->module_api_version < KEYMASTER_MODULE_API_VERSION_1_0) {
+ return keymaster0_device_initialize(mod, dev);
+ } else {
+ return keymaster1_device_initialize(mod, dev);
+ }
}
// softkeymaster_logger appears not to be used in keystore, but it installs itself as the
@@ -146,10 +223,8 @@ out:
static keymaster::SoftKeymasterLogger softkeymaster_logger;
static int fallback_keymaster_device_initialize(keymaster1_device_t** dev) {
- keymaster::SoftKeymasterDevice* softkeymaster =
- new keymaster::SoftKeymasterDevice();
- *dev = softkeymaster->keymaster_device();
- // softkeymaster will be freed by *dev->close_device; don't delete here.
+ *dev = (new SoftKeymasterDevice)->keymaster_device();
+ // SoftKeymasterDevice will be deleted by keymaster_device_release()
return 0;
}
@@ -157,6 +232,34 @@ static void keymaster_device_release(keymaster1_device_t* dev) {
dev->common.close(&dev->common);
}
+static void add_legacy_key_authorizations(int keyType, std::vector<keymaster_key_param_t>* params) {
+ params->push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_SIGN));
+ params->push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_VERIFY));
+ params->push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_ENCRYPT));
+ params->push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_DECRYPT));
+ params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_NONE));
+ if (keyType == EVP_PKEY_RSA) {
+ params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_SIGN));
+ params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_ENCRYPT));
+ params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_PSS));
+ params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_OAEP));
+ }
+ params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_NONE));
+ params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_MD5));
+ params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA1));
+ params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_224));
+ params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_256));
+ params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_384));
+ params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_512));
+ params->push_back(keymaster_param_bool(KM_TAG_ALL_USERS));
+ params->push_back(keymaster_param_bool(KM_TAG_NO_AUTH_REQUIRED));
+ params->push_back(keymaster_param_date(KM_TAG_ORIGINATION_EXPIRE_DATETIME, LLONG_MAX));
+ params->push_back(keymaster_param_date(KM_TAG_USAGE_EXPIRE_DATETIME, LLONG_MAX));
+ params->push_back(keymaster_param_date(KM_TAG_ACTIVE_DATETIME, 0));
+ uint64_t now = keymaster::java_time(time(NULL));
+ params->push_back(keymaster_param_date(KM_TAG_CREATION_DATETIME, now));
+}
+
/***************
* PERMISSIONS *
***************/
@@ -1229,9 +1332,11 @@ public:
}
if (keyBlob.getType() == ::TYPE_KEY_PAIR) {
- // A device doesn't have to implement delete_keypair.
- if (mDevice->delete_keypair != NULL && !keyBlob.isFallback()) {
- if (mDevice->delete_keypair(mDevice, keyBlob.getValue(), keyBlob.getLength())) {
+ // A device doesn't have to implement delete_key.
+ if (mDevice->delete_key != NULL && !keyBlob.isFallback()) {
+ keymaster_key_blob_t blob = {keyBlob.getValue(),
+ static_cast<size_t>(keyBlob.getLength())};
+ if (mDevice->delete_key(mDevice, &blob)) {
rc = ::SYSTEM_ERROR;
}
}
@@ -1324,35 +1429,58 @@ public:
ResponseCode importKey(const uint8_t* key, size_t keyLen, const char* filename, uid_t userId,
int32_t flags) {
- uint8_t* data;
- size_t dataLength;
- int rc;
-
- if (mDevice->import_keypair == NULL) {
- ALOGE("Keymaster doesn't support import!");
- return SYSTEM_ERROR;
+ Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &key, keyLen));
+ if (!pkcs8.get()) {
+ return ::SYSTEM_ERROR;
+ }
+ Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
+ if (!pkey.get()) {
+ return ::SYSTEM_ERROR;
+ }
+ int type = EVP_PKEY_type(pkey->type);
+ android::KeymasterArguments params;
+ add_legacy_key_authorizations(type, &params.params);
+ switch (type) {
+ case EVP_PKEY_RSA:
+ params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_RSA));
+ break;
+ case EVP_PKEY_EC:
+ params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM,
+ KM_ALGORITHM_EC));
+ break;
+ default:
+ ALOGW("Unsupported key type %d", type);
+ return ::SYSTEM_ERROR;
}
+ std::vector<keymaster_key_param_t> opParams(params.params);
+ const keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
+ keymaster_blob_t input = {key, keyLen};
+ keymaster_key_blob_t blob = {nullptr, 0};
bool isFallback = false;
- rc = mDevice->import_keypair(mDevice, key, keyLen, &data, &dataLength);
- if (rc) {
+ keymaster_error_t error = mDevice->import_key(mDevice, &inParams, KM_KEY_FORMAT_PKCS8,
+ &input, &blob, NULL /* characteristics */);
+ if (error != KM_ERROR_OK){
+ ALOGE("Keymaster error %d importing key pair, falling back", error);
+
/*
- * Maybe the device doesn't support this type of key. Try to use the
- * software fallback keymaster implementation. This is a little bit
- * lazier than checking the PKCS#8 key type, but the software
- * implementation will do that anyway.
+ * There should be no way to get here. Fallback shouldn't ever really happen
+ * because the main device may be many (SW, KM0/SW hybrid, KM1/SW hybrid), but it must
+ * provide full support of the API. In any case, we'll do the fallback just for
+ * consistency... and I suppose to cover for broken HW implementations.
*/
- rc = mFallbackDevice->import_keypair(mFallbackDevice, key, keyLen, &data, &dataLength);
+ error = mFallbackDevice->import_key(mFallbackDevice, &inParams, KM_KEY_FORMAT_PKCS8,
+ &input, &blob, NULL /* characteristics */);
isFallback = true;
- if (rc) {
- ALOGE("Error while importing keypair: %d", rc);
+ if (error) {
+ ALOGE("Keymaster error while importing key pair with fallback: %d", error);
return SYSTEM_ERROR;
}
}
- Blob keyBlob(data, dataLength, NULL, 0, TYPE_KEY_PAIR);
- free(data);
+ Blob keyBlob(blob.key_material, blob.key_material_size, NULL, 0, TYPE_KEYMASTER_10);
+ free(const_cast<uint8_t*>(blob.key_material));
keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
keyBlob.setFallback(isFallback);
@@ -1920,7 +2048,7 @@ public:
}
KeymasterArguments params;
- addLegacyKeyAuthorizations(params.params, keyType);
+ add_legacy_key_authorizations(keyType, &params.params);
switch (keyType) {
case EVP_PKEY_EC: {
@@ -1999,7 +2127,7 @@ public:
}
int type = EVP_PKEY_type(pkey->type);
KeymasterArguments params;
- addLegacyKeyAuthorizations(params.params, type);
+ add_legacy_key_authorizations(type, &params.params);
switch (type) {
case EVP_PKEY_RSA:
params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_RSA));
@@ -2272,6 +2400,7 @@ public:
// If the HW device didn't support generate_key or generate_key failed
// fall back to the software implementation.
if (rc && fallback->generate_key != NULL) {
+ ALOGW("Primary keymaster device failed to generate key, falling back to SW.");
isFallback = true;
if (!entropy) {
rc = KM_ERROR_OK;
@@ -2375,6 +2504,7 @@ public:
rc = device->import_key(device, &inParams, format,&input, &blob, &out);
}
if (rc && fallback->import_key != NULL) {
+ ALOGW("Primary keymaster device failed to import key, falling back to SW.");
isFallback = true;
rc = fallback->import_key(fallback, &inParams, format, &input, &blob, &out);
}
@@ -2998,34 +3128,6 @@ private:
return ::SYSTEM_ERROR;
}
- void addLegacyKeyAuthorizations(std::vector<keymaster_key_param_t>& params, int keyType) {
- params.push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_SIGN));
- params.push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_VERIFY));
- params.push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_ENCRYPT));
- params.push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_DECRYPT));
- params.push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_NONE));
- if (keyType == EVP_PKEY_RSA) {
- params.push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_SIGN));
- params.push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_ENCRYPT));
- params.push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_PSS));
- params.push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_OAEP));
- }
- params.push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_NONE));
- params.push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_MD5));
- params.push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA1));
- params.push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_224));
- params.push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_256));
- params.push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_384));
- params.push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_512));
- params.push_back(keymaster_param_bool(KM_TAG_ALL_USERS));
- params.push_back(keymaster_param_bool(KM_TAG_NO_AUTH_REQUIRED));
- params.push_back(keymaster_param_date(KM_TAG_ORIGINATION_EXPIRE_DATETIME, LLONG_MAX));
- params.push_back(keymaster_param_date(KM_TAG_USAGE_EXPIRE_DATETIME, LLONG_MAX));
- params.push_back(keymaster_param_date(KM_TAG_ACTIVE_DATETIME, 0));
- uint64_t now = keymaster::java_time(time(NULL));
- params.push_back(keymaster_param_date(KM_TAG_CREATION_DATETIME, now));
- }
-
keymaster_key_param_t* getKeyAlgorithm(keymaster_key_characteristics_t* characteristics) {
for (size_t i = 0; i < characteristics->hw_enforced.length; i++) {
if (characteristics->hw_enforced.params[i].tag == KM_TAG_ALGORITHM) {