diff options
author | Max Bires <jbires@google.com> | 2022-04-01 21:07:51 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2022-04-01 21:07:51 +0000 |
commit | 0b18dcb3370dcca15c41cb03de9341ce715b8503 (patch) | |
tree | de3b8d8657128cd8ac8623b08c0bb8c4768ab60f | |
parent | b4b33a4073a52199d17430ebe31e8dae4ab4a2ff (diff) | |
parent | 5569b04a43855707b9ff2586f3d6bedd375a9f03 (diff) | |
download | keymaster-0b18dcb3370dcca15c41cb03de9341ce715b8503.tar.gz |
Merge "Add version and impl info field to EncryptedKey"
-rw-r--r-- | include/keymaster/key_blob_utils/auth_encrypted_key_blob.h | 8 | ||||
-rw-r--r-- | key_blob_utils/auth_encrypted_key_blob.cpp | 51 | ||||
-rw-r--r-- | tests/Android.bp | 2 | ||||
-rw-r--r-- | tests/key_blob_test.cpp | 44 |
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_)); |