diff options
author | Shawn Willden <swillden@google.com> | 2015-08-13 20:49:53 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2015-08-13 20:49:53 +0000 |
commit | c2120744da8d0612ad54484b314f94e1e6e3a167 (patch) | |
tree | 1fb0ca7ad10b52be6d6f4bf0ffe781faa698cbaf | |
parent | cbfdeefef7a12fcb383e8b0f840771f6983927aa (diff) | |
parent | 55268b5b037a8c3537602b1073ad624455d3672d (diff) | |
download | android_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.cpp | 248 |
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, ¶ms.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, ¶ms.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, ¶ms.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) { |