Add initial support for rescoping.
This code does not yet validate that rescoping is authorized. A future
CL will integrate rescoping enforcement.
Change-Id: Iff66860630eef717562bce7c534a09d80b85a7a3
diff --git a/google_keymaster_test.cpp b/google_keymaster_test.cpp
index 6fc5b0b..2b94ed9 100644
--- a/google_keymaster_test.cpp
+++ b/google_keymaster_test.cpp
@@ -467,6 +467,14 @@
return response.error;
}
+ keymaster_error_t Rescope(const AuthorizationSet& new_params,
+ keymaster_key_blob_t* rescoped_blob,
+ keymaster_key_characteristics_t** rescoped_characteristics) {
+ return device()->rescope(device(), new_params.data(), new_params.size(), &blob_,
+ &client_id_, NULL /* app data */, rescoped_blob,
+ rescoped_characteristics);
+ }
+
void CheckHmacTestVector(string key, string message, keymaster_digest_t digest,
string expected_mac) {
ASSERT_EQ(KM_ERROR_OK,
@@ -2368,5 +2376,75 @@
device()->add_rng_entropy(device(), reinterpret_cast<const uint8_t*>("foo"), 3));
}
+typedef KeymasterTest RescopingTest;
+TEST_F(RescopingTest, KeyWithRescopingNotUsable) {
+ ASSERT_EQ(KM_ERROR_OK,
+ GenerateKey(ParamBuilder().AesEncryptionKey(128).OcbMode(4096, 16).Option(
+ TAG_RESCOPING_ADD, KM_TAG_MAC_LENGTH)));
+ // TODO(swillden): Add a better error code for this.
+ EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB, BeginOperation(KM_PURPOSE_ENCRYPT));
+}
+
+TEST_F(RescopingTest, RescopeSymmetric) {
+ ASSERT_EQ(KM_ERROR_OK, GenerateKey(ParamBuilder()
+ .AesEncryptionKey(128)
+ .OcbMode(4096, 16)
+ .Option(TAG_RESCOPING_ADD, KM_TAG_MAC_LENGTH)
+ .Option(TAG_RESCOPING_DEL, KM_TAG_MAC_LENGTH)));
+ EXPECT_FALSE(contains(sw_enforced(), TAG_MAC_LENGTH, 15));
+ EXPECT_TRUE(contains(sw_enforced(), TAG_MAC_LENGTH, 16));
+
+ keymaster_key_blob_t rescoped_blob;
+ keymaster_key_characteristics_t* rescoped_characteristics;
+ AuthorizationSet new_params =
+ ParamBuilder().AesEncryptionKey(128).OcbMode(4096, 15 /* note changed */).build();
+
+ ASSERT_EQ(KM_ERROR_OK, Rescope(new_params, &rescoped_blob, &rescoped_characteristics));
+ ASSERT_TRUE(rescoped_characteristics != NULL);
+
+ EXPECT_EQ(0, rescoped_characteristics->hw_enforced.length);
+ AuthorizationSet auths(rescoped_characteristics->sw_enforced);
+ keymaster_free_characteristics(rescoped_characteristics);
+ free(rescoped_characteristics);
+ free(const_cast<uint8_t*>(rescoped_blob.key_material));
+
+ EXPECT_TRUE(contains(auths, TAG_ALGORITHM, KM_ALGORITHM_AES));
+ EXPECT_TRUE(contains(auths, TAG_MAC_LENGTH, 15));
+ EXPECT_FALSE(contains(auths, TAG_MAC_LENGTH, 16));
+}
+
+TEST_F(RescopingTest, RescopeRsa) {
+ ASSERT_EQ(KM_ERROR_OK, GenerateKey(ParamBuilder()
+ .RsaEncryptionKey(256)
+ .Option(TAG_RESCOPING_ADD, KM_TAG_PURPOSE)
+ .Option(TAG_RESCOPING_DEL, KM_TAG_PURPOSE)));
+ EXPECT_TRUE(contains(sw_enforced(), TAG_PURPOSE, KM_PURPOSE_ENCRYPT));
+ EXPECT_TRUE(contains(sw_enforced(), TAG_PURPOSE, KM_PURPOSE_DECRYPT));
+ EXPECT_FALSE(contains(sw_enforced(), TAG_PURPOSE, KM_PURPOSE_SIGN));
+ EXPECT_FALSE(contains(sw_enforced(), TAG_PURPOSE, KM_PURPOSE_VERIFY));
+
+ keymaster_key_blob_t rescoped_blob;
+ keymaster_key_characteristics_t* rescoped_characteristics;
+ AuthorizationSet new_params = ParamBuilder().RsaSigningKey(256).build();
+
+ ASSERT_EQ(KM_ERROR_OK, Rescope(new_params, &rescoped_blob, &rescoped_characteristics));
+ ASSERT_TRUE(rescoped_characteristics != NULL);
+
+ EXPECT_EQ(0, rescoped_characteristics->hw_enforced.length);
+ AuthorizationSet auths(rescoped_characteristics->sw_enforced);
+ keymaster_free_characteristics(rescoped_characteristics);
+ free(rescoped_characteristics);
+ free(const_cast<uint8_t*>(rescoped_blob.key_material));
+
+ EXPECT_FALSE(contains(auths, TAG_PURPOSE, KM_PURPOSE_ENCRYPT));
+ EXPECT_FALSE(contains(auths, TAG_PURPOSE, KM_PURPOSE_DECRYPT));
+ EXPECT_TRUE(contains(auths, TAG_PURPOSE, KM_PURPOSE_SIGN));
+ EXPECT_TRUE(contains(auths, TAG_PURPOSE, KM_PURPOSE_VERIFY));
+}
+
+// TODO(swillden): When adding rescoping enforcement, include tests that verify that tags
+// corresponding to intrinsic attributes of keys, like RSA public exponent, or symmetric key size,
+// may not be changed.
+
} // namespace test
} // namespace keymaster