Change KeyMint KeyCharacteristics
Support key characteristics with three security levels, and don't
store unenforced authorizations with keys or bind them to keys.
Bug: 163606833
Test: Build
Change-Id: I05fbb15ddc8eca20723a06d7df0c129d4cc940a0
diff --git a/keystore2/src/km_compat/certificate_test.cpp b/keystore2/src/km_compat/certificate_test.cpp
index 9307569..d6bece7 100644
--- a/keystore2/src/km_compat/certificate_test.cpp
+++ b/keystore2/src/km_compat/certificate_test.cpp
@@ -49,14 +49,12 @@
if (!device) {
return ScopedAStatus::fromStatus(STATUS_NAME_NOT_FOUND);
}
- ByteArray blob;
- KeyCharacteristics characteristics;
- std::vector<Certificate> certChain;
- auto status = device->generateKey(keyParams, &blob, &characteristics, &certChain);
+ KeyCreationResult creationResult;
+ auto status = device->generateKey(keyParams, &creationResult);
if (!status.isOk()) {
return status;
}
- return certChain;
+ return creationResult.certificateChain;
}
static void ensureCertChainSize(const std::variant<std::vector<Certificate>, ScopedAStatus>& result,
diff --git a/keystore2/src/km_compat/km_compat.cpp b/keystore2/src/km_compat/km_compat.cpp
index c9af80d..d6b7940 100644
--- a/keystore2/src/km_compat/km_compat.cpp
+++ b/keystore2/src/km_compat/km_compat.cpp
@@ -73,12 +73,13 @@
return kps;
}
-static KeyCharacteristics
-convertKeyCharacteristicsFromLegacy(const V4_0_KeyCharacteristics& legacyKc) {
+static std::vector<KeyCharacteristics>
+convertKeyCharacteristicsFromLegacy(KeyMintSecurityLevel securityLevel,
+ const V4_0_KeyCharacteristics& legacyKc) {
KeyCharacteristics kc;
- kc.softwareEnforced = convertKeyParametersFromLegacy(legacyKc.softwareEnforced);
- kc.hardwareEnforced = convertKeyParametersFromLegacy(legacyKc.hardwareEnforced);
- return kc;
+ kc.securityLevel = securityLevel;
+ kc.authorizations = convertKeyParametersFromLegacy(legacyKc.hardwareEnforced);
+ return {kc};
}
static V4_0_KeyFormat convertKeyFormatToLegacy(const KeyFormat& kf) {
@@ -140,8 +141,10 @@
// TODO: What do I do about the version number? Is it the version of the device I get?
auto result = mDevice->getHardwareInfo([&](auto securityLevel, const auto& keymasterName,
const auto& keymasterAuthorName) {
- _aidl_return->securityLevel =
+ securityLevel_ =
static_cast<::aidl::android::hardware::security::keymint::SecurityLevel>(securityLevel);
+
+ _aidl_return->securityLevel = securityLevel_;
_aidl_return->keyMintName = keymasterName;
_aidl_return->keyMintAuthorName = keymasterAuthorName;
});
@@ -166,34 +169,32 @@
}
ScopedAStatus KeyMintDevice::generateKey(const std::vector<KeyParameter>& in_keyParams,
- ByteArray* out_generatedKeyBlob,
- KeyCharacteristics* out_generatedKeyCharacteristics,
- std::vector<Certificate>* out_outCertChain) {
+ KeyCreationResult* out_creationResult) {
auto legacyKeyParams = convertKeyParametersToLegacy(in_keyParams);
V4_0_ErrorCode errorCode;
auto result = mDevice->generateKey(
legacyKeyParams, [&](V4_0_ErrorCode error, const hidl_vec<uint8_t>& keyBlob,
const V4_0_KeyCharacteristics& keyCharacteristics) {
errorCode = error;
- out_generatedKeyBlob->data = keyBlob;
- *out_generatedKeyCharacteristics =
- convertKeyCharacteristicsFromLegacy(keyCharacteristics);
+ out_creationResult->keyBlob = keyBlob;
+ out_creationResult->keyCharacteristics =
+ convertKeyCharacteristicsFromLegacy(securityLevel_, keyCharacteristics);
});
if (!result.isOk()) {
return ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(ResponseCode::SYSTEM_ERROR));
}
if (errorCode == V4_0_ErrorCode::OK) {
- auto cert = getCertificate(in_keyParams, out_generatedKeyBlob->data);
+ auto cert = getCertificate(in_keyParams, out_creationResult->keyBlob);
if (std::holds_alternative<V4_0_ErrorCode>(cert)) {
auto code = std::get<V4_0_ErrorCode>(cert);
// We return OK in successful cases that do not generate a certificate.
if (code != V4_0_ErrorCode::OK) {
errorCode = code;
- deleteKey(out_generatedKeyBlob->data);
+ deleteKey(out_creationResult->keyBlob);
}
} else {
- *out_outCertChain = std::get<std::vector<Certificate>>(cert);
+ out_creationResult->certificateChain = std::get<std::vector<Certificate>>(cert);
}
}
return convertErrorCode(errorCode);
@@ -202,36 +203,34 @@
ScopedAStatus KeyMintDevice::importKey(const std::vector<KeyParameter>& in_inKeyParams,
KeyFormat in_inKeyFormat,
const std::vector<uint8_t>& in_inKeyData,
- ByteArray* out_outImportedKeyBlob,
- KeyCharacteristics* out_outImportedKeyCharacteristics,
- std::vector<Certificate>* out_outCertChain) {
+ KeyCreationResult* out_creationResult) {
auto legacyKeyParams = convertKeyParametersToLegacy(in_inKeyParams);
auto legacyKeyFormat = convertKeyFormatToLegacy(in_inKeyFormat);
V4_0_ErrorCode errorCode;
- auto result =
- mDevice->importKey(legacyKeyParams, legacyKeyFormat, in_inKeyData,
- [&](V4_0_ErrorCode error, const hidl_vec<uint8_t>& keyBlob,
- const V4_0_KeyCharacteristics& keyCharacteristics) {
- errorCode = error;
- out_outImportedKeyBlob->data = keyBlob;
- *out_outImportedKeyCharacteristics =
- convertKeyCharacteristicsFromLegacy(keyCharacteristics);
- });
+ auto result = mDevice->importKey(legacyKeyParams, legacyKeyFormat, in_inKeyData,
+ [&](V4_0_ErrorCode error, const hidl_vec<uint8_t>& keyBlob,
+ const V4_0_KeyCharacteristics& keyCharacteristics) {
+ errorCode = error;
+ out_creationResult->keyBlob = keyBlob;
+ out_creationResult->keyCharacteristics =
+ convertKeyCharacteristicsFromLegacy(
+ securityLevel_, keyCharacteristics);
+ });
if (!result.isOk()) {
return ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(ResponseCode::SYSTEM_ERROR));
}
if (errorCode == V4_0_ErrorCode::OK) {
- auto cert = getCertificate(in_inKeyParams, out_outImportedKeyBlob->data);
+ auto cert = getCertificate(in_inKeyParams, out_creationResult->keyBlob);
if (std::holds_alternative<V4_0_ErrorCode>(cert)) {
auto code = std::get<V4_0_ErrorCode>(cert);
// We return OK in successful cases that do not generate a certificate.
if (code != V4_0_ErrorCode::OK) {
errorCode = code;
- deleteKey(out_outImportedKeyBlob->data);
+ deleteKey(out_creationResult->keyBlob);
}
} else {
- *out_outCertChain = std::get<std::vector<Certificate>>(cert);
+ out_creationResult->certificateChain = std::get<std::vector<Certificate>>(cert);
}
}
return convertErrorCode(errorCode);
@@ -241,20 +240,19 @@
const std::vector<uint8_t>& in_inWrappedKeyData,
const std::vector<uint8_t>& in_inWrappingKeyBlob, const std::vector<uint8_t>& in_inMaskingKey,
const std::vector<KeyParameter>& in_inUnwrappingParams, int64_t in_inPasswordSid,
- int64_t in_inBiometricSid, ByteArray* out_outImportedKeyBlob,
- KeyCharacteristics* out_outImportedKeyCharacteristics) {
+ int64_t in_inBiometricSid, KeyCreationResult* out_creationResult) {
auto legacyUnwrappingParams = convertKeyParametersToLegacy(in_inUnwrappingParams);
V4_0_ErrorCode errorCode;
- auto result =
- mDevice->importWrappedKey(in_inWrappedKeyData, in_inWrappingKeyBlob, in_inMaskingKey,
- legacyUnwrappingParams, in_inPasswordSid, in_inBiometricSid,
- [&](V4_0_ErrorCode error, const hidl_vec<uint8_t>& keyBlob,
- const V4_0_KeyCharacteristics& keyCharacteristics) {
- errorCode = error;
- out_outImportedKeyBlob->data = keyBlob;
- *out_outImportedKeyCharacteristics =
- convertKeyCharacteristicsFromLegacy(keyCharacteristics);
- });
+ auto result = mDevice->importWrappedKey(
+ in_inWrappedKeyData, in_inWrappingKeyBlob, in_inMaskingKey, legacyUnwrappingParams,
+ in_inPasswordSid, in_inBiometricSid,
+ [&](V4_0_ErrorCode error, const hidl_vec<uint8_t>& keyBlob,
+ const V4_0_KeyCharacteristics& keyCharacteristics) {
+ errorCode = error;
+ out_creationResult->keyBlob = keyBlob;
+ out_creationResult->keyCharacteristics =
+ convertKeyCharacteristicsFromLegacy(securityLevel_, keyCharacteristics);
+ });
if (!result.isOk()) {
return ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(ResponseCode::SYSTEM_ERROR));
diff --git a/keystore2/src/km_compat/km_compat.h b/keystore2/src/km_compat/km_compat.h
index 904d391..0634c26 100644
--- a/keystore2/src/km_compat/km_compat.h
+++ b/keystore2/src/km_compat/km_compat.h
@@ -30,6 +30,7 @@
using ::aidl::android::hardware::security::keymint::Certificate;
using ::aidl::android::hardware::security::keymint::HardwareAuthToken;
using ::aidl::android::hardware::security::keymint::KeyCharacteristics;
+using ::aidl::android::hardware::security::keymint::KeyCreationResult;
using ::aidl::android::hardware::security::keymint::KeyFormat;
using ::aidl::android::hardware::security::keymint::KeyMintHardwareInfo;
using ::aidl::android::hardware::security::keymint::KeyParameter;
@@ -84,21 +85,16 @@
VerificationToken* _aidl_return) override;
ScopedAStatus addRngEntropy(const std::vector<uint8_t>& in_data) override;
ScopedAStatus generateKey(const std::vector<KeyParameter>& in_keyParams,
- ByteArray* out_generatedKeyBlob,
- KeyCharacteristics* out_generatedKeyCharacteristics,
- std::vector<Certificate>* out_outCertChain) override;
+ KeyCreationResult* out_creationResult) override;
ScopedAStatus importKey(const std::vector<KeyParameter>& in_inKeyParams,
KeyFormat in_inKeyFormat, const std::vector<uint8_t>& in_inKeyData,
- ByteArray* out_outImportedKeyBlob,
- KeyCharacteristics* out_outImportedKeyCharacteristics,
- std::vector<Certificate>* out_outCertChain) override;
+ KeyCreationResult* out_creationResult) override;
ScopedAStatus importWrappedKey(const std::vector<uint8_t>& in_inWrappedKeyData,
const std::vector<uint8_t>& in_inWrappingKeyBlob,
const std::vector<uint8_t>& in_inMaskingKey,
const std::vector<KeyParameter>& in_inUnwrappingParams,
int64_t in_inPasswordSid, int64_t in_inBiometricSid,
- ByteArray* out_outImportedKeyBlob,
- KeyCharacteristics* out_outImportedKeyCharacteristics) override;
+ KeyCreationResult* out_creationResult) override;
ScopedAStatus upgradeKey(const std::vector<uint8_t>& in_inKeyBlobToUpgrade,
const std::vector<KeyParameter>& in_inUpgradeParams,
std::vector<uint8_t>* _aidl_return) override;
@@ -121,6 +117,7 @@
private:
std::optional<V4_0_ErrorCode> signCertificate(const std::vector<KeyParameter>& keyParams,
const std::vector<uint8_t>& keyBlob, X509* cert);
+ KeyMintSecurityLevel securityLevel_;
};
class KeyMintOperation : public aidl::android::hardware::security::keymint::BnKeyMintOperation {
diff --git a/keystore2/src/km_compat/lib.rs b/keystore2/src/km_compat/lib.rs
index 36f1303..6d3aa96 100644
--- a/keystore2/src/km_compat/lib.rs
+++ b/keystore2/src/km_compat/lib.rs
@@ -28,10 +28,9 @@
use super::*;
use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
- Algorithm::Algorithm, BeginResult::BeginResult, BlockMode::BlockMode, ByteArray::ByteArray,
- Certificate::Certificate, Digest::Digest, ErrorCode::ErrorCode,
- HardwareAuthToken::HardwareAuthToken, IKeyMintDevice::IKeyMintDevice,
- KeyCharacteristics::KeyCharacteristics, KeyFormat::KeyFormat, KeyParameter::KeyParameter,
+ Algorithm::Algorithm, BeginResult::BeginResult, BlockMode::BlockMode, Digest::Digest,
+ ErrorCode::ErrorCode, HardwareAuthToken::HardwareAuthToken, IKeyMintDevice::IKeyMintDevice,
+ KeyCreationResult::KeyCreationResult, KeyFormat::KeyFormat, KeyParameter::KeyParameter,
KeyParameterArray::KeyParameterArray, KeyParameterValue::KeyParameterValue,
KeyPurpose::KeyPurpose, PaddingMode::PaddingMode, SecurityLevel::SecurityLevel, Tag::Tag,
};
@@ -72,17 +71,10 @@
}
// TODO: If I only need the key itself, don't return the other things.
- fn generate_key(
- legacy: &dyn IKeyMintDevice,
- kps: Vec<KeyParameter>,
- ) -> (ByteArray, KeyCharacteristics, Vec<Certificate>) {
- let mut blob = ByteArray { data: vec![] };
- let mut characteristics = KeyCharacteristics::default();
- let mut cert_chain = vec![];
- let result = legacy.generateKey(&kps, &mut blob, &mut characteristics, &mut cert_chain);
- assert!(result.is_ok(), "{:?}", result);
- assert_ne!(blob.data.len(), 0);
- (blob, characteristics, cert_chain)
+ fn generate_key(legacy: &dyn IKeyMintDevice, kps: Vec<KeyParameter>) -> KeyCreationResult {
+ let creation_result = legacy.generateKey(&kps).expect("Failed to generate key");
+ assert_ne!(creation_result.keyBlob.len(), 0);
+ creation_result
}
fn generate_rsa_key(legacy: &dyn IKeyMintDevice, encrypt: bool, attest: bool) -> Vec<u8> {
@@ -123,14 +115,14 @@
value: KeyParameterValue::Blob(vec![42; 8]),
});
}
- let (blob, _, cert_chain) = generate_key(legacy, kps);
+ let creation_result = generate_key(legacy, kps);
if attest {
// TODO: Will this always be greater than 1?
- assert!(cert_chain.len() > 1);
+ assert!(creation_result.certificateChain.len() > 1);
} else {
- assert_eq!(cert_chain.len(), 1);
+ assert_eq!(creation_result.certificateChain.len(), 1);
}
- blob.data
+ creation_result.keyBlob
}
#[test]
@@ -160,23 +152,15 @@
}];
let kf = KeyFormat::RAW;
let kd = [0; 16];
- let mut blob = ByteArray { data: vec![] };
- let mut characteristics = KeyCharacteristics::default();
- let mut cert_chain = vec![];
- let result =
- legacy.importKey(&kps, kf, &kd, &mut blob, &mut characteristics, &mut cert_chain);
- assert!(result.is_ok(), "{:?}", result);
- assert_ne!(blob.data.len(), 0);
- assert_eq!(cert_chain.len(), 0);
+ let creation_result = legacy.importKey(&kps, kf, &kd).expect("Failed to import key");
+ assert_ne!(creation_result.keyBlob.len(), 0);
+ assert_eq!(creation_result.certificateChain.len(), 0);
}
#[test]
fn test_import_wrapped_key() {
let legacy = get_device();
- let mut blob = ByteArray { data: vec![] };
- let mut characteristics = KeyCharacteristics::default();
- let result =
- legacy.importWrappedKey(&[], &[], &[], &[], 0, 0, &mut blob, &mut characteristics);
+ let result = legacy.importWrappedKey(&[], &[], &[], &[], 0, 0);
// TODO: This test seems to fail on cuttlefish. How should I test it?
assert!(result.is_err());
}
@@ -238,9 +222,9 @@
value: KeyParameterValue::KeyPurpose(KeyPurpose::DECRYPT),
},
];
- let (blob, _, cert_chain) = generate_key(legacy, kps);
- assert_eq!(cert_chain.len(), 0);
- blob.data
+ let creation_result = generate_key(legacy, kps);
+ assert_eq!(creation_result.certificateChain.len(), 0);
+ creation_result.keyBlob
}
fn begin(
diff --git a/keystore2/src/km_compat/slot_test.cpp b/keystore2/src/km_compat/slot_test.cpp
index e56fb37..0859ddf 100644
--- a/keystore2/src/km_compat/slot_test.cpp
+++ b/keystore2/src/km_compat/slot_test.cpp
@@ -46,14 +46,12 @@
KMV1::makeKeyParameter(KMV1::TAG_PURPOSE, KeyPurpose::ENCRYPT),
KMV1::makeKeyParameter(KMV1::TAG_PURPOSE, KeyPurpose::DECRYPT),
});
- ByteArray blob;
- KeyCharacteristics characteristics;
- std::vector<Certificate> cert;
- auto status = device->generateKey(keyParams, &blob, &characteristics, &cert);
+ KeyCreationResult creationResult;
+ auto status = device->generateKey(keyParams, &creationResult);
if (!status.isOk()) {
return {};
}
- return blob.data;
+ return creationResult.keyBlob;
}
static std::variant<BeginResult, ScopedAStatus> begin(std::shared_ptr<KeyMintDevice> device,
@@ -151,16 +149,14 @@
KMV1::makeKeyParameter(KMV1::TAG_PURPOSE, KeyPurpose::SIGN),
KMV1::makeKeyParameter(KMV1::TAG_NO_AUTH_REQUIRED, true),
});
- ByteArray blob;
- KeyCharacteristics characteristics;
- std::vector<Certificate> cert;
- status = device->generateKey(kps, &blob, &characteristics, &cert);
+ KeyCreationResult creationResult;
+ status = device->generateKey(kps, &creationResult);
ASSERT_TRUE(!status.isOk());
ASSERT_EQ(status.getServiceSpecificError(),
static_cast<int32_t>(ErrorCode::TOO_MANY_OPERATIONS));
// But generating a certificate with signCert does not use a slot.
kps.pop_back();
- status = device->generateKey(kps, &blob, &characteristics, &cert);
+ status = device->generateKey(kps, &creationResult);
ASSERT_TRUE(status.isOk());
// Destructing operations should free up their slots.