summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Bires <jbires@google.com>2022-04-01 21:42:32 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2022-04-01 21:42:32 +0000
commitecb3a6eaaaa978728d1ce9ad7ba13ca9b6e839d4 (patch)
treede3b8d8657128cd8ac8623b08c0bb8c4768ab60f
parentb90ce8637ca0df179e9d5655f077c515c0d9d006 (diff)
parentf360090d424668e42a77b9548f202225c6891248 (diff)
downloadkeymaster-ecb3a6eaaaa978728d1ce9ad7ba13ca9b6e839d4.tar.gz
Merge "Add version and impl info field to EncryptedKey" am: 0b18dcb337 am: f360090d42
Original change: https://android-review.googlesource.com/c/platform/system/keymaster/+/2037587 Change-Id: Ib8febc918fa255fc664c12a500dbcd3718e65422 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--include/keymaster/key_blob_utils/auth_encrypted_key_blob.h8
-rw-r--r--key_blob_utils/auth_encrypted_key_blob.cpp51
-rw-r--r--tests/Android.bp2
-rw-r--r--tests/key_blob_test.cpp44
4 files changed, 86 insertions, 19 deletions
diff --git a/include/keymaster/key_blob_utils/auth_encrypted_key_blob.h b/include/keymaster/key_blob_utils/auth_encrypted_key_blob.h
index b611d9c..ea9ff0f 100644
--- a/include/keymaster/key_blob_utils/auth_encrypted_key_blob.h
+++ b/include/keymaster/key_blob_utils/auth_encrypted_key_blob.h
@@ -34,6 +34,8 @@ enum AuthEncryptedBlobFormat : uint8_t {
AES_OCB = 0,
AES_GCM_WITH_SW_ENFORCED = 1,
AES_GCM_WITH_SECURE_DELETION = 2,
+ AES_GCM_WITH_SW_ENFORCED_VERSIONED = 3,
+ AES_GCM_WITH_SECURE_DELETION_VERSIONED = 4,
};
/**
@@ -69,6 +71,8 @@ struct EncryptedKey {
KeymasterKeyBlob ciphertext;
Buffer nonce;
Buffer tag;
+ uint32_t kdf_version;
+ int32_t addl_info;
};
struct DeserializedKey {
@@ -118,4 +122,8 @@ KmErrorOr<KeymasterKeyBlob> DecryptKey(const DeserializedKey& key, const Authori
const SecureDeletionData& secure_deletion_data,
const KeymasterKeyBlob& master_key);
+bool requiresSecureDeletion(const AuthEncryptedBlobFormat& fmt);
+
+bool isVersionedFormat(const AuthEncryptedBlobFormat& fmt);
+
} // namespace keymaster
diff --git a/key_blob_utils/auth_encrypted_key_blob.cpp b/key_blob_utils/auth_encrypted_key_blob.cpp
index e6ee3bf..3cdcf5c 100644
--- a/key_blob_utils/auth_encrypted_key_blob.cpp
+++ b/key_blob_utils/auth_encrypted_key_blob.cpp
@@ -51,7 +51,7 @@ KmErrorOr<Buffer> BuildDerivationInfo(const AuthEncryptedBlobFormat format, //
const AuthorizationSet& sw_enforced, //
const AuthorizationSet& hidden,
const SecureDeletionData& secure_deletion_data) {
- bool use_sdd = (format == AES_GCM_WITH_SECURE_DELETION);
+ bool use_sdd = requiresSecureDeletion(format);
size_t info_len =
hidden.SerializedSize() + hw_enforced.SerializedSize() + sw_enforced.SerializedSize();
@@ -204,13 +204,16 @@ KmErrorOr<KeymasterKeyBlob> SerializeAuthEncryptedBlob(const EncryptedKey& encry
const AuthorizationSet& hw_enforced,
const AuthorizationSet& sw_enforced,
uint32_t key_slot) {
- bool use_key_slot = (encrypted_key.format == AES_GCM_WITH_SECURE_DELETION);
+ bool use_key_slot = requiresSecureDeletion(encrypted_key.format);
size_t size = 1 /* version byte */ + encrypted_key.nonce.SerializedSize() +
encrypted_key.ciphertext.SerializedSize() + encrypted_key.tag.SerializedSize() +
hw_enforced.SerializedSize() + sw_enforced.SerializedSize();
if (use_key_slot) size += sizeof(key_slot);
-
+ if (isVersionedFormat(encrypted_key.format)) {
+ size += sizeof(encrypted_key.kdf_version);
+ size += sizeof(encrypted_key.addl_info);
+ }
KeymasterKeyBlob retval;
if (!retval.Reset(size)) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
@@ -221,6 +224,10 @@ KmErrorOr<KeymasterKeyBlob> SerializeAuthEncryptedBlob(const EncryptedKey& encry
buf = encrypted_key.nonce.Serialize(buf, end);
buf = encrypted_key.ciphertext.Serialize(buf, end);
buf = encrypted_key.tag.Serialize(buf, end);
+ if (isVersionedFormat(encrypted_key.format)) {
+ buf = append_uint32_to_buf(buf, end, encrypted_key.kdf_version);
+ buf = append_uint32_to_buf(buf, end, encrypted_key.addl_info);
+ }
buf = hw_enforced.Serialize(buf, end);
buf = sw_enforced.Serialize(buf, end);
if (use_key_slot) buf = append_uint32_to_buf(buf, end, key_slot);
@@ -243,17 +250,28 @@ KmErrorOr<DeserializedKey> DeserializeAuthEncryptedBlob(const KeymasterKeyBlob&
retval.encrypted_key.format = static_cast<AuthEncryptedBlobFormat>(*(*buf_ptr)++);
if (!retval.encrypted_key.nonce.Deserialize(buf_ptr, end) || //
!retval.encrypted_key.ciphertext.Deserialize(buf_ptr, end) || //
- !retval.encrypted_key.tag.Deserialize(buf_ptr, end) || //
- !retval.hw_enforced.Deserialize(buf_ptr, end) || //
- !retval.sw_enforced.Deserialize(buf_ptr, end)) {
+ !retval.encrypted_key.tag.Deserialize(buf_ptr, end)) {
return KM_ERROR_INVALID_KEY_BLOB;
}
- if (retval.encrypted_key.format == AES_GCM_WITH_SECURE_DELETION &&
- !copy_uint32_from_buf(buf_ptr, end, &retval.key_slot)) {
+ if (isVersionedFormat(retval.encrypted_key.format)) {
+ if (!copy_uint32_from_buf(buf_ptr, end, &retval.encrypted_key.kdf_version) ||
+ !copy_uint32_from_buf(buf_ptr, end, &retval.encrypted_key.addl_info)) {
+ return KM_ERROR_INVALID_KEY_BLOB;
+ }
+ }
+
+ if (!retval.hw_enforced.Deserialize(buf_ptr, end) || //
+ !retval.sw_enforced.Deserialize(buf_ptr, end)) {
return KM_ERROR_INVALID_KEY_BLOB;
}
+ if (requiresSecureDeletion(retval.encrypted_key.format)) {
+ if (!copy_uint32_from_buf(buf_ptr, end, &retval.key_slot)) {
+ return KM_ERROR_INVALID_KEY_BLOB;
+ }
+ }
+
if (*buf_ptr != end) return KM_ERROR_INVALID_KEY_BLOB;
switch (retval.encrypted_key.format) {
@@ -266,6 +284,8 @@ KmErrorOr<DeserializedKey> DeserializeAuthEncryptedBlob(const KeymasterKeyBlob&
case AES_GCM_WITH_SW_ENFORCED:
case AES_GCM_WITH_SECURE_DELETION:
+ case AES_GCM_WITH_SW_ENFORCED_VERSIONED:
+ case AES_GCM_WITH_SECURE_DELETION_VERSIONED:
if (retval.encrypted_key.nonce.available_read() != kAesGcmNonceLength ||
retval.encrypted_key.tag.available_read() != kAesGcmTagLength) {
return KM_ERROR_INVALID_KEY_BLOB;
@@ -298,7 +318,9 @@ EncryptKey(const KeymasterKeyBlob& plaintext, AuthEncryptedBlobFormat format,
}
case AES_GCM_WITH_SW_ENFORCED:
- case AES_GCM_WITH_SECURE_DELETION: {
+ case AES_GCM_WITH_SECURE_DELETION:
+ case AES_GCM_WITH_SW_ENFORCED_VERSIONED:
+ case AES_GCM_WITH_SECURE_DELETION_VERSIONED: {
auto nonce = generate_nonce(random, kAesGcmNonceLength);
if (!nonce) return nonce.error();
return AesGcmEncryptKey(hw_enforced, sw_enforced, hidden, secure_deletion_data, master_key,
@@ -325,6 +347,8 @@ KmErrorOr<KeymasterKeyBlob> DecryptKey(const DeserializedKey& key, const Authori
case AES_GCM_WITH_SW_ENFORCED:
case AES_GCM_WITH_SECURE_DELETION:
+ case AES_GCM_WITH_SW_ENFORCED_VERSIONED:
+ case AES_GCM_WITH_SECURE_DELETION_VERSIONED:
return AesGcmDecryptKey(key, hidden, secure_deletion_data, master_key);
}
@@ -332,4 +356,13 @@ KmErrorOr<KeymasterKeyBlob> DecryptKey(const DeserializedKey& key, const Authori
return KM_ERROR_INVALID_KEY_BLOB;
}
+bool requiresSecureDeletion(const AuthEncryptedBlobFormat& fmt) {
+ return fmt == AES_GCM_WITH_SECURE_DELETION || fmt == AES_GCM_WITH_SECURE_DELETION_VERSIONED;
+}
+
+bool isVersionedFormat(const AuthEncryptedBlobFormat& fmt) {
+ return fmt == AES_GCM_WITH_SW_ENFORCED_VERSIONED ||
+ fmt == AES_GCM_WITH_SECURE_DELETION_VERSIONED;
+}
+
} // namespace keymaster
diff --git a/tests/Android.bp b/tests/Android.bp
index ea1c8e4..d5ea46b 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -9,7 +9,6 @@ package {
shared_test_libs = [
"libbase",
- "libcppbor_external",
"libcrypto",
"libcutils",
"libhidlbase",
@@ -21,6 +20,7 @@ shared_test_libs = [
]
static_test_libs = [
+ "libcppbor_external",
"libsoftkeymasterdevice",
"libcppcose_rkp",
]
diff --git a/tests/key_blob_test.cpp b/tests/key_blob_test.cpp
index b8ec193..f50d4fe 100644
--- a/tests/key_blob_test.cpp
+++ b/tests/key_blob_test.cpp
@@ -138,7 +138,8 @@ TEST_P(KeyBlobTest, EncryptDecrypt) {
ASSERT_TRUE(deserialized.isOk());
EXPECT_EQ(hw_enforced_, deserialized->hw_enforced);
EXPECT_EQ(sw_enforced_, deserialized->sw_enforced);
- if (GetParam() == AES_GCM_WITH_SECURE_DELETION) {
+ if (GetParam() == AES_GCM_WITH_SECURE_DELETION ||
+ GetParam() == AES_GCM_WITH_SECURE_DELETION_VERSIONED) {
EXPECT_EQ(key_slot, deserialized->key_slot);
} else {
EXPECT_EQ(0U, deserialized->key_slot);
@@ -379,7 +380,9 @@ TEST_P(KeyBlobTest, DupBufferToolarge) {
INSTANTIATE_TEST_SUITE_P(AllFormats, KeyBlobTest,
::testing::Values(AES_OCB, AES_GCM_WITH_SW_ENFORCED,
- AES_GCM_WITH_SECURE_DELETION),
+ AES_GCM_WITH_SECURE_DELETION,
+ AES_GCM_WITH_SW_ENFORCED_VERSIONED,
+ AES_GCM_WITH_SECURE_DELETION_VERSIONED),
[](const ::testing::TestParamInfo<KeyBlobTest::ParamType>& info) {
switch (info.param) {
case AES_OCB:
@@ -388,16 +391,39 @@ INSTANTIATE_TEST_SUITE_P(AllFormats, KeyBlobTest,
return "AES_GCM_WITH_SW_ENFORCED";
case AES_GCM_WITH_SECURE_DELETION:
return "AES_GCM_WITH_SECURE_DELETION";
+ case AES_GCM_WITH_SW_ENFORCED_VERSIONED:
+ return "AES_GCM_WITH_SW_ENFORCED_VERSIONED";
+ case AES_GCM_WITH_SECURE_DELETION_VERSIONED:
+ return "AES_GCM_WITH_SECURE_DELETION_VERSIONED";
}
CHECK(false) << "Shouldn't be able to get here";
return "Unexpected";
});
-// Tests that only apply to AES_GCM_WITH_SECURE_DELETION; we don't parameterize these.
using SecureDeletionTest = KeyBlobTest;
-TEST_F(SecureDeletionTest, WrongFactoryResetSecret) {
- ASSERT_EQ(KM_ERROR_OK, Encrypt(AES_GCM_WITH_SECURE_DELETION));
+INSTANTIATE_TEST_SUITE_P(SecureDeletionFormats, SecureDeletionTest,
+ ::testing::Values(AES_GCM_WITH_SECURE_DELETION,
+ AES_GCM_WITH_SECURE_DELETION_VERSIONED),
+ [](const ::testing::TestParamInfo<KeyBlobTest::ParamType>& info) {
+ switch (info.param) {
+ case AES_OCB:
+ return "AES_OCB";
+ case AES_GCM_WITH_SW_ENFORCED:
+ return "AES_GCM_WITH_SW_ENFORCED";
+ case AES_GCM_WITH_SECURE_DELETION:
+ return "AES_GCM_WITH_SECURE_DELETION";
+ case AES_GCM_WITH_SW_ENFORCED_VERSIONED:
+ return "AES_GCM_WITH_SW_ENFORCED_VERSIONED";
+ case AES_GCM_WITH_SECURE_DELETION_VERSIONED:
+ return "AES_GCM_WITH_SECURE_DELETION_VERSIONED";
+ }
+ CHECK(false) << "Shouldn't be able to get here";
+ return "Unexpected";
+ });
+
+TEST_P(SecureDeletionTest, WrongFactoryResetSecret) {
+ ASSERT_EQ(KM_ERROR_OK, Encrypt(GetParam()));
ASSERT_EQ(KM_ERROR_OK, Serialize());
SecureDeletionData wrong_secure_deletion(std::move(secure_deletion_data_));
@@ -410,8 +436,8 @@ TEST_F(SecureDeletionTest, WrongFactoryResetSecret) {
EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB, result.error());
}
-TEST_F(SecureDeletionTest, WrongSecureDeletionSecret) {
- ASSERT_EQ(KM_ERROR_OK, Encrypt(AES_GCM_WITH_SECURE_DELETION));
+TEST_P(SecureDeletionTest, WrongSecureDeletionSecret) {
+ ASSERT_EQ(KM_ERROR_OK, Encrypt(GetParam()));
ASSERT_EQ(KM_ERROR_OK, Serialize());
SecureDeletionData wrong_secure_deletion(std::move(secure_deletion_data_));
@@ -424,8 +450,8 @@ TEST_F(SecureDeletionTest, WrongSecureDeletionSecret) {
EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB, result.error());
}
-TEST_F(SecureDeletionTest, WrongSecureDeletionKeySlot) {
- ASSERT_EQ(KM_ERROR_OK, Encrypt(AES_GCM_WITH_SECURE_DELETION));
+TEST_P(SecureDeletionTest, WrongSecureDeletionKeySlot) {
+ ASSERT_EQ(KM_ERROR_OK, Encrypt(GetParam()));
ASSERT_EQ(KM_ERROR_OK, Serialize());
SecureDeletionData wrong_secure_deletion(std::move(secure_deletion_data_));