diff options
author | Shawn Willden <swillden@google.com> | 2015-05-11 06:53:34 -0600 |
---|---|---|
committer | Shawn Willden <swillden@google.com> | 2015-05-12 11:29:39 +0000 |
commit | 125e4866f98eb1b5ad65a563afd34aca215d983d (patch) | |
tree | f57ed3560bee9d195bd5b7510e2217915c1ee5c9 | |
parent | c442467181d8a9427c83fea4f0a272c8a7b46043 (diff) | |
download | android_system_keymaster-125e4866f98eb1b5ad65a563afd34aca215d983d.tar.gz android_system_keymaster-125e4866f98eb1b5ad65a563afd34aca215d983d.tar.bz2 android_system_keymaster-125e4866f98eb1b5ad65a563afd34aca215d983d.zip |
Remove rescoping support.
Change-Id: Ia8e36e41e04f15befccbb7b4138f599849facd28
(cherry picked from commit 0c14b2c5f42abdab58118106d5a7117a88d4a324)
-rw-r--r-- | ec_key.cpp | 15 | ||||
-rw-r--r-- | ec_key.h | 12 | ||||
-rw-r--r-- | google_keymaster.cpp | 30 | ||||
-rw-r--r-- | google_keymaster_messages.cpp | 40 | ||||
-rw-r--r-- | google_keymaster_messages_test.cpp | 29 | ||||
-rw-r--r-- | google_keymaster_test.cpp | 75 | ||||
-rw-r--r-- | google_keymaster_test_utils.cpp | 7 | ||||
-rw-r--r-- | google_keymaster_test_utils.h | 3 | ||||
-rw-r--r-- | include/keymaster/google_keymaster.h | 1 | ||||
-rw-r--r-- | include/keymaster/google_keymaster_messages.h | 42 | ||||
-rw-r--r-- | include/keymaster/keymaster_tags.h | 2 | ||||
-rw-r--r-- | include/keymaster/soft_keymaster_device.h | 7 | ||||
-rw-r--r-- | key.cpp | 6 | ||||
-rw-r--r-- | key.h | 4 | ||||
-rw-r--r-- | keymaster_enforcement.cpp | 82 | ||||
-rw-r--r-- | keymaster_enforcement.h | 23 | ||||
-rw-r--r-- | keymaster_enforcement_test.cpp | 186 | ||||
-rw-r--r-- | rsa_key.cpp | 15 | ||||
-rw-r--r-- | rsa_key.h | 20 | ||||
-rw-r--r-- | soft_keymaster_device.cpp | 34 | ||||
-rw-r--r-- | symmetric_key.cpp | 15 | ||||
-rw-r--r-- | symmetric_key.h | 8 |
22 files changed, 20 insertions, 636 deletions
@@ -125,21 +125,6 @@ Key* EcKeyFactory::ImportKey(const AuthorizationSet& key_description, return new EcKey(ec_key.release(), authorizations); } -Key* EcKeyFactory::RescopeKey(const UnencryptedKeyBlob& blob, - const AuthorizationSet& new_authorizations, - keymaster_error_t* error) { - if (!error) - return NULL; - - EcKey original_key(blob, error); - if (*error != KM_ERROR_OK) - return NULL; - - EcKey* new_key = new EcKey(original_key.ec_key_.release(), new_authorizations); - *error = new_key ? KM_ERROR_OK : KM_ERROR_MEMORY_ALLOCATION_FAILED; - return new_key; -} - /* static */ EC_GROUP* EcKeyFactory::choose_group(size_t key_size_bits) { switch (key_size_bits) { @@ -25,13 +25,11 @@ namespace keymaster { class EcKeyFactory : public AsymmetricKeyFactory { public: - virtual Key* GenerateKey(const AuthorizationSet& key_description, keymaster_error_t* error); - virtual Key* ImportKey(const AuthorizationSet& key_description, - keymaster_key_format_t key_format, const uint8_t* key_data, - size_t key_data_length, keymaster_error_t* error); - virtual Key* LoadKey(const UnencryptedKeyBlob& blob, keymaster_error_t* error); - virtual Key* RescopeKey(const UnencryptedKeyBlob& blob, - const AuthorizationSet& new_authorizations, keymaster_error_t* error); + Key* GenerateKey(const AuthorizationSet& key_description, keymaster_error_t* error) override; + Key* ImportKey(const AuthorizationSet& key_description, keymaster_key_format_t key_format, + const uint8_t* key_data, size_t key_data_length, + keymaster_error_t* error) override; + Key* LoadKey(const UnencryptedKeyBlob& blob, keymaster_error_t* error) override; private: static EC_GROUP* choose_group(size_t key_size_bits); diff --git a/google_keymaster.cpp b/google_keymaster.cpp index 12fdc18..981d25b 100644 --- a/google_keymaster.cpp +++ b/google_keymaster.cpp @@ -222,12 +222,6 @@ void GoogleKeymaster::BeginOperation(const BeginOperationRequest& request, return; // TODO(swillden): Move this check to a general authorization checker. - if (key->rescopable()) { - response->error = KM_ERROR_RESCOPABLE_KEY_NOT_USABLE; - return; - } - - // TODO(swillden): Move this check to a general authorization checker. if (!key->authorizations().Contains(TAG_PURPOSE, request.purpose)) { // TODO(swillden): Consider introducing error codes for unauthorized usages. response->error = KM_ERROR_INCOMPATIBLE_PURPOSE; @@ -318,30 +312,6 @@ void GoogleKeymaster::ExportKey(const ExportKeyRequest& request, ExportKeyRespon } } -void GoogleKeymaster::Rescope(const RescopeRequest& request, RescopeResponse* response) { - if (response == NULL) - return; - - UniquePtr<UnencryptedKeyBlob> blob( - LoadKeyBlob(request.key_blob, request.additional_params, &response->error)); - if (response->error != KM_ERROR_OK) - return; - - KeyFactory* factory = KeyFactoryRegistry::Get(blob->algorithm()); - if (!factory) { - response->error = KM_ERROR_UNSUPPORTED_ALGORITHM; - return; - } - - UniquePtr<Key> key; - key.reset(factory->RescopeKey(*blob, request.new_authorizations, &response->error)); - if (response->error != KM_ERROR_OK) - return; - - assert(is_hardware() == blob->is_hardware()); - response->error = SerializeKey(key.get(), blob->origin(), &response->key_blob, - &response->enforced, &response->unenforced); -} void GoogleKeymaster::ImportKey(const ImportKeyRequest& request, ImportKeyResponse* response) { if (response == NULL) return; diff --git a/google_keymaster_messages.cpp b/google_keymaster_messages.cpp index 44cf5cf..5e8f63b 100644 --- a/google_keymaster_messages.cpp +++ b/google_keymaster_messages.cpp @@ -396,44 +396,4 @@ bool GetVersionResponse::NonErrorDeserialize(const uint8_t** buf_ptr, const uint return true; } -void RescopeRequest::SetKeyMaterial(const void* key_material, size_t length) { - set_key_blob(&key_blob, key_material, length); -} - -size_t RescopeRequest::SerializedSize() const { - return key_blob_size(key_blob) + additional_params.SerializedSize() + - new_authorizations.SerializedSize(); -} - -uint8_t* RescopeRequest::Serialize(uint8_t* buf, const uint8_t* end) const { - buf = serialize_key_blob(key_blob, buf, end); - buf = additional_params.Serialize(buf, end); - return new_authorizations.Serialize(buf, end); -} - -bool RescopeRequest::Deserialize(const uint8_t** buf_ptr, const uint8_t* end) { - return deserialize_key_blob(&key_blob, buf_ptr, end) && - additional_params.Deserialize(buf_ptr, end) && - new_authorizations.Deserialize(buf_ptr, end); -} - -void RescopeResponse::SetKeyMaterial(const void* key_material, size_t length) { - set_key_blob(&key_blob, key_material, length); -} - -size_t RescopeResponse::NonErrorSerializedSize() const { - return key_blob_size(key_blob) + enforced.SerializedSize() + unenforced.SerializedSize(); -} - -uint8_t* RescopeResponse::NonErrorSerialize(uint8_t* buf, const uint8_t* end) const { - buf = serialize_key_blob(key_blob, buf, end); - buf = enforced.Serialize(buf, end); - return unenforced.Serialize(buf, end); -} - -bool RescopeResponse::NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) { - return deserialize_key_blob(&key_blob, buf_ptr, end) && enforced.Deserialize(buf_ptr, end) && - unenforced.Deserialize(buf_ptr, end); -} - } // namespace keymaster diff --git a/google_keymaster_messages_test.cpp b/google_keymaster_messages_test.cpp index 107822f..1eda0d8 100644 --- a/google_keymaster_messages_test.cpp +++ b/google_keymaster_messages_test.cpp @@ -445,33 +445,6 @@ TEST(RoundTrip, AddEntropyRequest) { } } -TEST(RoundTrip, RescopeRequest) { - for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) { - RescopeRequest msg(ver); - msg.additional_params.Reinitialize(params, array_length(params)); - msg.new_authorizations.Reinitialize(params, array_length(params)); - - UniquePtr<RescopeRequest> deserialized(round_trip(ver, msg, 160)); - EXPECT_EQ(msg.new_authorizations, deserialized->new_authorizations); - } -} - -TEST(RoundTrip, RescopeResponse) { - for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) { - RescopeResponse msg(ver); - msg.error = KM_ERROR_OK; - msg.enforced.Reinitialize(params, array_length(params)); - msg.unenforced.Reinitialize(params, array_length(params)); - msg.SetKeyMaterial("foo", 3); - - UniquePtr<RescopeResponse> deserialized(round_trip(ver, msg, 167)); - EXPECT_EQ(msg.enforced, deserialized->enforced); - EXPECT_EQ(msg.unenforced, deserialized->unenforced); - EXPECT_EQ(3U, deserialized->key_blob.key_material_size); - EXPECT_EQ(0, memcmp("foo", deserialized->key_blob.key_material, 3)); - } -} - uint8_t msgbuf[] = { 220, 88, 183, 255, 71, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 228, 174, 98, 187, 191, 135, 253, 200, 51, 230, 114, 247, 151, 109, @@ -536,8 +509,6 @@ GARBAGE_TEST(ImportKeyRequest); GARBAGE_TEST(ImportKeyResponse); GARBAGE_TEST(ExportKeyRequest); GARBAGE_TEST(ExportKeyResponse); -GARBAGE_TEST(RescopeRequest); -GARBAGE_TEST(RescopeResponse); // The macro doesn't work on this one. TEST(GarbageTest, SupportedResponse) { diff --git a/google_keymaster_test.cpp b/google_keymaster_test.cpp index eeda13c..500967a 100644 --- a/google_keymaster_test.cpp +++ b/google_keymaster_test.cpp @@ -1806,80 +1806,5 @@ TEST_F(AddEntropyTest, AddEntropy) { 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(AuthorizationSetBuilder().AesEncryptionKey(128).EcbMode().Authorization( - TAG_RESCOPING_ADD, KM_TAG_PURPOSE))); - // TODO(swillden): Add a better error code for this. - EXPECT_EQ(KM_ERROR_RESCOPABLE_KEY_NOT_USABLE, BeginOperation(KM_PURPOSE_ENCRYPT)); -} - -TEST_F(RescopingTest, RescopeSymmetric) { - ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder() - .AesEncryptionKey(128) - .EcbMode() - .Authorization(TAG_RESCOPING_ADD, KM_TAG_PURPOSE) - .Authorization(TAG_RESCOPING_DEL, KM_TAG_PURPOSE))); - EXPECT_FALSE(contains(sw_enforced(), TAG_PURPOSE, KM_PURPOSE_SIGN)); - EXPECT_TRUE(contains(sw_enforced(), TAG_PURPOSE, KM_PURPOSE_ENCRYPT)); - - keymaster_key_blob_t rescoped_blob; - keymaster_key_characteristics_t* rescoped_characteristics; - AuthorizationSet new_params = - AuthorizationSetBuilder().AesKey(128).Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN).build(); - - ASSERT_EQ(KM_ERROR_OK, Rescope(new_params, &rescoped_blob, &rescoped_characteristics)); - ASSERT_TRUE(rescoped_characteristics != NULL); - - EXPECT_EQ(0U, 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_PURPOSE, KM_PURPOSE_SIGN)); - EXPECT_FALSE(contains(auths, TAG_PURPOSE, KM_PURPOSE_ENCRYPT)); -} - -TEST_F(RescopingTest, RescopeRsa) { - ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder() - .RsaEncryptionKey(256, 3) - .Padding(KM_PAD_RSA_OAEP) - .Authorization(TAG_RESCOPING_ADD, KM_TAG_PURPOSE) - .Authorization(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 = AuthorizationSetBuilder() - .RsaSigningKey(256, 3) - .Digest(KM_DIGEST_SHA_2_256) - .Padding(KM_PAD_RSA_PSS) - .build(); - - ASSERT_EQ(KM_ERROR_OK, Rescope(new_params, &rescoped_blob, &rescoped_characteristics)); - ASSERT_TRUE(rescoped_characteristics != NULL); - - EXPECT_EQ(0U, 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 diff --git a/google_keymaster_test_utils.cpp b/google_keymaster_test_utils.cpp index c0b696d..6b892de 100644 --- a/google_keymaster_test_utils.cpp +++ b/google_keymaster_test_utils.cpp @@ -536,13 +536,6 @@ keymaster_error_t Keymaster1Test::ExportKey(keymaster_key_format_t format, strin return error; } -keymaster_error_t -Keymaster1Test::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 Keymaster1Test::CheckHmacTestVector(string key, string message, keymaster_digest_t digest, string expected_mac) { ASSERT_EQ(KM_ERROR_OK, diff --git a/google_keymaster_test_utils.h b/google_keymaster_test_utils.h index 3471b52..2f5e887 100644 --- a/google_keymaster_test_utils.h +++ b/google_keymaster_test_utils.h @@ -182,9 +182,6 @@ class Keymaster1Test : public testing::Test { keymaster_error_t GetVersion(uint8_t* major, uint8_t* minor, uint8_t* subminor); - keymaster_error_t Rescope(const AuthorizationSet& new_params, - keymaster_key_blob_t* rescoped_blob, - keymaster_key_characteristics_t** rescoped_characteristics); std::string ProcessMessage(keymaster_purpose_t purpose, const std::string& message); std::string ProcessMessage(keymaster_purpose_t purpose, const std::string& message, const AuthorizationSet& begin_params, diff --git a/include/keymaster/google_keymaster.h b/include/keymaster/google_keymaster.h index f603a9a..3f904d6 100644 --- a/include/keymaster/google_keymaster.h +++ b/include/keymaster/google_keymaster.h @@ -62,7 +62,6 @@ class GoogleKeymaster { void GenerateKey(const GenerateKeyRequest& request, GenerateKeyResponse* response); void GetKeyCharacteristics(const GetKeyCharacteristicsRequest& request, GetKeyCharacteristicsResponse* response); - void Rescope(const RescopeRequest& request, RescopeResponse* response); void ImportKey(const ImportKeyRequest& request, ImportKeyResponse* response); void ExportKey(const ExportKeyRequest& request, ExportKeyResponse* response); void BeginOperation(const BeginOperationRequest& request, BeginOperationResponse* response); diff --git a/include/keymaster/google_keymaster_messages.h b/include/keymaster/google_keymaster_messages.h index f8549d8..22a3dec 100644 --- a/include/keymaster/google_keymaster_messages.h +++ b/include/keymaster/google_keymaster_messages.h @@ -399,48 +399,6 @@ struct GetVersionResponse : public KeymasterResponse { uint8_t subminor_ver; }; -struct RescopeRequest : public KeymasterMessage { - RescopeRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) { - key_blob.key_material = NULL; - key_blob.key_material_size = 0; - } - ~RescopeRequest() { delete[] key_blob.key_material; } - - void SetKeyMaterial(const void* key_material, size_t length); - void SetKeyMaterial(const keymaster_key_blob_t& blob) { - SetKeyMaterial(blob.key_material, blob.key_material_size); - } - - size_t SerializedSize() const; - uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const; - bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end); - - keymaster_key_blob_t key_blob; - AuthorizationSet additional_params; - AuthorizationSet new_authorizations; -}; - -struct RescopeResponse : public KeymasterResponse { - RescopeResponse(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterResponse(ver) { - key_blob.key_material = NULL; - key_blob.key_material_size = 0; - } - ~RescopeResponse() { delete[] key_blob.key_material; } - - void SetKeyMaterial(const void* key_material, size_t length); - void SetKeyMaterial(const keymaster_key_blob_t& blob) { - SetKeyMaterial(blob.key_material, blob.key_material_size); - } - - size_t NonErrorSerializedSize() const; - uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const; - bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end); - - keymaster_key_blob_t key_blob; - AuthorizationSet enforced; - AuthorizationSet unenforced; -}; - } // namespace keymaster #endif // SYSTEM_KEYMASTER_GOOGLE_KEYMASTER_MESSAGES_H_ diff --git a/include/keymaster/keymaster_tags.h b/include/keymaster/keymaster_tags.h index da28e72..88ed74b 100644 --- a/include/keymaster/keymaster_tags.h +++ b/include/keymaster/keymaster_tags.h @@ -199,8 +199,6 @@ DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_DIGEST, keymaster_digest_t); DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_DIGEST_OLD, keymaster_digest_t); DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_PADDING, keymaster_padding_t); DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_PADDING_OLD, keymaster_padding_t); -DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_RESCOPING_ADD, keymaster_tag_t); -DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_RESCOPING_DEL, keymaster_tag_t); DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_BLOB_USAGE_REQUIREMENTS, keymaster_key_blob_usage_requirements_t); DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_ORIGIN, keymaster_key_origin_t); diff --git a/include/keymaster/soft_keymaster_device.h b/include/keymaster/soft_keymaster_device.h index 4accf74..87be472 100644 --- a/include/keymaster/soft_keymaster_device.h +++ b/include/keymaster/soft_keymaster_device.h @@ -120,13 +120,6 @@ class SoftKeymasterDevice { const keymaster_blob_t* client_id, const keymaster_blob_t* app_data, keymaster_key_characteristics_t** character); - static keymaster_error_t rescope(const keymaster1_device_t* dev, - const keymaster_key_param_t* new_params, - size_t new_params_count, const keymaster_key_blob_t* key_blob, - const keymaster_blob_t* client_id, - const keymaster_blob_t* app_data, - keymaster_key_blob_t* rescoped_key_blob, - keymaster_key_characteristics_t** characteristics); static keymaster_error_t import_key(const keymaster1_device_t* dev, const keymaster_key_param_t* params, size_t params_count, keymaster_key_format_t key_format, const uint8_t* key_data, @@ -31,10 +31,4 @@ Key::Key(const KeyBlob& blob) { authorizations_.push_back(blob.enforced()); } -bool Key::rescopable() const { - size_t rescope_tag_count = authorizations_.GetTagCount(TAG_RESCOPING_ADD) + - authorizations_.GetTagCount(TAG_RESCOPING_DEL); - return rescope_tag_count > 0; -} - } // namespace keymaster @@ -46,9 +46,6 @@ class KeyFactory { keymaster_key_format_t key_format, const uint8_t* key_data, size_t key_data_length, keymaster_error_t* error) = 0; virtual Key* LoadKey(const UnencryptedKeyBlob& blob, keymaster_error_t* error) = 0; - virtual Key* RescopeKey(const UnencryptedKeyBlob& blob, - const AuthorizationSet& new_authorizations, - keymaster_error_t* error) = 0; // Informational methods. virtual const keymaster_key_format_t* SupportedImportFormats(size_t* format_count) = 0; @@ -78,7 +75,6 @@ class Key { size_t* size) const = 0; const AuthorizationSet& authorizations() const { return authorizations_; } - bool rescopable() const; protected: Key(const KeyBlob& blob); diff --git a/keymaster_enforcement.cpp b/keymaster_enforcement.cpp index 5b3af69..5dd6c58 100644 --- a/keymaster_enforcement.cpp +++ b/keymaster_enforcement.cpp @@ -131,9 +131,7 @@ keymaster_error_t KeymasterEnforcement::AuthorizeOperation(const keymaster_purpo case KM_TAG_NONCE: case KM_TAG_RETURN_UNAUTHED: - /* Tags handled in AuthorizeRescope and not used for operations. */ - case KM_TAG_RESCOPING_ADD: - case KM_TAG_RESCOPING_DEL: + /* Tags not used for operations. */ case KM_TAG_BLOB_USAGE_REQUIREMENTS: /* Algorithm specific parameters not used for access control. */ @@ -259,84 +257,6 @@ keymaster_error_t KeymasterEnforcement::AuthenticationIsFresh(const keymaster_ke } } -bool KeymasterEnforcement::valid_rescope_del(const AuthorizationSet& auth_set, - const keymaster_tag_t tag) const { - int tag_index = auth_set.find(KM_TAG_RESCOPING_DEL); - while (tag_index >= 0) { - if (static_cast<keymaster_tag_t>(auth_set[tag_index].integer) == tag) { - return true; - } - tag_index = auth_set.find(KM_TAG_RESCOPING_DEL, tag_index); - } - - return false; -} - -bool KeymasterEnforcement::valid_rescope_add(const AuthorizationSet& auth_set, - const keymaster_tag_t tag) const { - int tag_index = auth_set.find(KM_TAG_RESCOPING_ADD); - while (tag_index >= 0) { - if (static_cast<keymaster_tag_t>(auth_set[tag_index].integer) == tag) { - return true; - } - tag_index = auth_set.find(KM_TAG_RESCOPING_ADD, tag_index); - } - - return false; -} - -keymaster_error_t -KeymasterEnforcement::AuthorizeRescope(const AuthorizationSet& old_auth_set, - const AuthorizationSet& new_auth_set) const { - keymaster_error_t return_error = KM_ERROR_OK; - /* TODO(swillden): Require authentication. */ - - /* - * For each tag in the old AuthenticationSet that is not in the new AuthenticationSet test - * that the tag is validly deleted. For each tag in the old AuthenticationSet that has a - * different value in the new AuthenticationSet, test that the tag can be validly deleted and - * added. - */ - for (unsigned int i = 0; i < old_auth_set.size(); i++) { - keymaster_key_param_t kkp_old = old_auth_set[i]; - if (kkp_old.tag == KM_TAG_RESCOPING_ADD || kkp_old.tag == KM_TAG_RESCOPING_DEL) { - continue; - } - int newIndex = new_auth_set.find(kkp_old.tag, -1); - if (newIndex < 0) { - if (!valid_rescope_del(old_auth_set, kkp_old.tag)) { - return KM_ERROR_INVALID_RESCOPING; - } - } else { - keymaster_key_param_t kkp_new = new_auth_set[newIndex]; - if (!(kkp_old == kkp_new) && (!valid_rescope_add(old_auth_set, kkp_old.tag) || - !valid_rescope_del(old_auth_set, kkp_old.tag))) { - return KM_ERROR_INVALID_RESCOPING; - } - } - } - - /** - * For each tag in the new Authentication set that is absent in the old AuthenticationSet test - * that the tag can validly been added. We do not need to test tags with different values in - * this loop because they will have all ben handled previously. - */ - for (unsigned int i = 0; i < new_auth_set.size(); i++) { - keymaster_key_param_t kkp_new = new_auth_set[i]; - if (kkp_new.tag == KM_TAG_RESCOPING_ADD || kkp_new.tag == KM_TAG_RESCOPING_DEL) { - continue; - } - int old_index = old_auth_set.find(kkp_new.tag, -1); - if (old_index < 0) { - if (!valid_rescope_add(old_auth_set, kkp_new.tag)) { - return KM_ERROR_INVALID_RESCOPING; - } - } - } - - return return_error; -} - void KeymasterEnforcement::update_key_access_time(const km_id_t keyid) { accessTimeMap.update_key_access_time(keyid, get_current_time()); } diff --git a/keymaster_enforcement.h b/keymaster_enforcement.h index c751586..0f70ea9 100644 --- a/keymaster_enforcement.h +++ b/keymaster_enforcement.h @@ -50,13 +50,6 @@ class KeymasterEnforcement { const AuthorizationSet& auth_set, const uid_t uid); /** - * Ensures that all access control criteria are met for a rescope including added and deleted - * parameters. Returns KM_ERROR_OK if all criteria is met. - */ - keymaster_error_t AuthorizeRescope(const AuthorizationSet& old_auth_set, - const AuthorizationSet& new_auth_set) const; - - /** * This is maintained in system/core/include/cutiles/multiuser.h but copied here so that this * code can be reused without access to the core Android libs. */ @@ -107,8 +100,8 @@ class KeymasterEnforcement { keymaster_error_t UserAuthenticated(const keymaster_key_param_t param, const uid_t uid); /* - * Handles KM_TAG_RESCOPE_AUTH_TIMEOUT and KM_TAG_AUTH_TIMEOUT tags. Returns KM_ERROR_OK if the - * last time the user authenticated is within the required freshness. + * Handles KM_TAG_AUTH_TIMEOUT tags. Returns KM_ERROR_OK if the last time the user + * authenticated is within the required freshness. */ keymaster_error_t AuthenticationIsFresh(const keymaster_key_param_t param, const time_t current_time) const; @@ -143,18 +136,6 @@ class KeymasterEnforcement { }; /* - * Returns true if it is valid to delete tag from authSet. It is valid to be deleted if authSet - * contains a KM_TAG_RESCOPING_DEL parameter with tag as it's value. - */ - bool valid_rescope_add(const AuthorizationSet& auth_set, const keymaster_tag_t tag) const; - - /* - * Returns true if it is valid to add tag to the authSet. It is valid to be added if authSet - * contains a KM_TAG_RESCOPING_ADD parameter with tag as it's value. - */ - bool valid_rescope_del(const AuthorizationSet& auth_set, const keymaster_tag_t tag) const; - - /* * Tests if the purpose is a valid member of keymaster_purpose_t and if the purpose is among * those listed in the AuthorizationSet and returns KM_ERROR_OK if so and an appropriate error * otherwise. diff --git a/keymaster_enforcement_test.cpp b/keymaster_enforcement_test.cpp index 8cded39..550204e 100644 --- a/keymaster_enforcement_test.cpp +++ b/keymaster_enforcement_test.cpp @@ -77,10 +77,6 @@ class KeymasterBaseTest : public ::testing::Test { (appId2 % KeymasterEnforcement::MULTIUSER_APP_PER_USER_RANGE); }; -class RescopeBaseTest : public KeymasterBaseTest { - friend class KeymasterEnforcement; -}; - TEST_F(KeymasterBaseTest, TEST_VALID_KEY_PERIOD_NO_TAGS) { keymaster_key_param_t params[] = { sign_param, @@ -255,188 +251,6 @@ TEST_F(KeymasterBaseTest, TEST_VALID_TIME_BETWEEN_OPS) { ASSERT_EQ(KM_ERROR_OK, kmer2); } -TEST_F(KeymasterBaseTest, TEST_NO_RESCOPES) { - keymaster_key_param_t params1[] = { - Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA), - Authorization(TAG_USER_ID, 1), - }; - keymaster_key_param_t params2[] = { - Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA), - Authorization(TAG_USER_ID, 1), - }; - - KeymasterEnforcement kmen; - AuthorizationSet auth_set1(params1, 3); - AuthorizationSet auth_set2(params2, 3); - - ASSERT_EQ(KM_ERROR_OK, kmen.AuthorizeRescope(auth_set1, auth_set2)); -} - -TEST_F(RescopeBaseTest, TEST_VALID_RESCOPE_ADD) { - keymaster_key_param_t params1[] = { - Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), - Authorization(TAG_RESCOPING_ADD, KM_TAG_MAX_USES_PER_BOOT), - Authorization(TAG_RESCOPING_ADD, KM_TAG_USAGE_EXPIRE_DATETIME), - Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA), Authorization(TAG_USER_ID, 1), - Authorization(TAG_RESCOPING_DEL, KM_TAG_USER_ID), - }; - - keymaster_key_param_t params2[] = { - Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA), - Authorization(TAG_USER_ID, 1), Authorization(TAG_MAX_USES_PER_BOOT, 1), - }; - - keymaster_key_param_t params3[] = { - Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA), - Authorization(TAG_USER_ID, 1), Authorization(TAG_USAGE_EXPIRE_DATETIME, future_time), - }; - - KeymasterEnforcement kmen; - AuthorizationSet auth_set1(params1, 6); - AuthorizationSet auth_set2(params2, 4); - AuthorizationSet auth_set3(params3, 4); - - ASSERT_EQ(KM_ERROR_OK, kmen.AuthorizeRescope(auth_set1, auth_set2)); - ASSERT_EQ(KM_ERROR_OK, kmen.AuthorizeRescope(auth_set1, auth_set3)); -} - -TEST_F(RescopeBaseTest, TEST_VALID_RESCOPE_DEL) { - keymaster_key_param_t params1[] = { - Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), - Authorization(TAG_RESCOPING_ADD, KM_TAG_MAX_USES_PER_BOOT), - Authorization(TAG_RESCOPING_ADD, KM_TAG_USAGE_EXPIRE_DATETIME), - Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA), Authorization(TAG_USER_ID, 1), - Authorization(TAG_RESCOPING_DEL, KM_TAG_USER_ID), - }; - - keymaster_key_param_t params2[] = { - Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA), - }; - - KeymasterEnforcement kmen; - AuthorizationSet auth_set1(params1, 6); - AuthorizationSet auth_set2(params2, 2); - - ASSERT_EQ(KM_ERROR_OK, kmen.AuthorizeRescope(auth_set1, auth_set2)); -} - -TEST_F(RescopeBaseTest, TEST_VALID_RESCOPE_ADD_DEL) { - keymaster_key_param_t params1[] = { - Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA), - Authorization(TAG_USER_ID, 1), - - Authorization(TAG_RESCOPING_ADD, KM_TAG_MAX_USES_PER_BOOT), - Authorization(TAG_RESCOPING_ADD, KM_TAG_USAGE_EXPIRE_DATETIME), - Authorization(TAG_RESCOPING_DEL, KM_TAG_USER_ID), - }; - - keymaster_key_param_t params2[] = { - Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA), - Authorization(TAG_MAX_USES_PER_BOOT, 1), Authorization(TAG_USAGE_EXPIRE_DATETIME, 128), - }; - - keymaster_key_param_t params3[] = { - Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA), - Authorization(TAG_MAX_USES_PER_BOOT, 1), Authorization(TAG_USER_ID, 1), - Authorization(TAG_USAGE_EXPIRE_DATETIME, 128), - }; - - keymaster_key_param_t params4[] = { - Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA), Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), - }; - - KeymasterEnforcement kmen; - AuthorizationSet auth_set1(params1, 6); - AuthorizationSet auth_set2(params2, 4); - AuthorizationSet auth_set3(params3, 5); - AuthorizationSet auth_set4(params4, 2); - - ASSERT_EQ(KM_ERROR_OK, kmen.AuthorizeRescope(auth_set1, auth_set2)); - ASSERT_EQ(KM_ERROR_OK, kmen.AuthorizeRescope(auth_set1, auth_set3)); - ASSERT_EQ(KM_ERROR_OK, kmen.AuthorizeRescope(auth_set1, auth_set4)); -} - -TEST_F(RescopeBaseTest, TEST_INVALID_RESCOPE_ADD) { - keymaster_key_param_t params1[] = { - Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), - Authorization(TAG_RESCOPING_ADD, KM_TAG_USAGE_EXPIRE_DATETIME), - Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA), Authorization(TAG_USER_ID, 1), - Authorization(TAG_RESCOPING_DEL, KM_TAG_USER_ID), - }; - - keymaster_key_param_t params2[] = { - Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA), - Authorization(TAG_USER_ID, 1), Authorization(TAG_MAX_USES_PER_BOOT, 1), - }; - - KeymasterEnforcement kmen; - AuthorizationSet auth_set1(params1, 6); - AuthorizationSet auth_set2(params2, 4); - - ASSERT_EQ(KM_ERROR_INVALID_RESCOPING, kmen.AuthorizeRescope(auth_set1, auth_set2)); -} - -TEST_F(RescopeBaseTest, TEST_INVALID_RESCOPE_DEL) { - keymaster_key_param_t params1[] = { - Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), - Authorization(TAG_RESCOPING_ADD, KM_TAG_USAGE_EXPIRE_DATETIME), - Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA), - Authorization(TAG_RESCOPING_DEL, KM_TAG_PURPOSE), Authorization(TAG_USER_ID, 1), - }; - - keymaster_key_param_t params2[] = { - Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA), - }; - - KeymasterEnforcement kmen; - AuthorizationSet auth_set1(params1, 5); - AuthorizationSet auth_set2(params2, 2); - - ASSERT_EQ(KM_ERROR_INVALID_RESCOPING, kmen.AuthorizeRescope(auth_set1, auth_set2)); -} - -TEST_F(RescopeBaseTest, TEST_INVALID_RESCOPE_ADD_DEL) { - keymaster_key_param_t params1[] = { - Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA), Authorization(TAG_USER_ID, 1), - Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), - Authorization(TAG_ORIGINATION_EXPIRE_DATETIME, past_time), - Authorization(TAG_RESCOPING_ADD, KM_TAG_ORIGINATION_EXPIRE_DATETIME), - }; - - keymaster_key_param_t params2[] = { - Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), Authorization(TAG_MAX_USES_PER_BOOT, 1), - Authorization(TAG_USAGE_EXPIRE_DATETIME, 128), - }; - - keymaster_key_param_t params3[] = { - Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), Authorization(TAG_MAX_USES_PER_BOOT, 1), - Authorization(TAG_USER_ID, 2), Authorization(TAG_USAGE_EXPIRE_DATETIME, 128), - }; - - keymaster_key_param_t params4[] = { - Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA), Authorization(TAG_USER_ID, 2), - Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), - }; - - keymaster_key_param_t params5[] = { - Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA), Authorization(TAG_USER_ID, 1), - Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), - Authorization(TAG_ORIGINATION_EXPIRE_DATETIME, future_time), - }; - - KeymasterEnforcement kmen; - AuthorizationSet auth_set1(params1, 5); - AuthorizationSet auth_set2(params2, 3); - AuthorizationSet auth_set3(params3, 4); - AuthorizationSet auth_set4(params4, 3); - AuthorizationSet auth_set5(params5, 4); - - ASSERT_EQ(KM_ERROR_INVALID_RESCOPING, kmen.AuthorizeRescope(auth_set1, auth_set2)); - ASSERT_EQ(KM_ERROR_INVALID_RESCOPING, kmen.AuthorizeRescope(auth_set1, auth_set3)); - ASSERT_EQ(KM_ERROR_INVALID_RESCOPING, kmen.AuthorizeRescope(auth_set1, auth_set4)); - ASSERT_EQ(KM_ERROR_INVALID_RESCOPING, kmen.AuthorizeRescope(auth_set1, auth_set5)); -} - TEST_F(KeymasterBaseTest, TEST_USER_ID) { keymaster_key_param_t params[] = { Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN), Authorization(TAG_USER_ID, valid_user_id), diff --git a/rsa_key.cpp b/rsa_key.cpp index c92bab0..0f7ff44 100644 --- a/rsa_key.cpp +++ b/rsa_key.cpp @@ -143,21 +143,6 @@ Key* RsaKeyFactory::ImportKey(const AuthorizationSet& key_description, return new RsaKey(rsa_key.release(), authorizations); } -Key* RsaKeyFactory::RescopeKey(const UnencryptedKeyBlob& blob, - const AuthorizationSet& new_authorizations, - keymaster_error_t* error) { - if (!error) - return NULL; - - RsaKey original_key(blob, error); - if (*error != KM_ERROR_OK) - return NULL; - - RsaKey* new_key = new RsaKey(original_key.rsa_key_.release(), new_authorizations); - *error = new_key ? KM_ERROR_OK : KM_ERROR_MEMORY_ALLOCATION_FAILED; - return new_key; -} - RsaKey::RsaKey(const UnencryptedKeyBlob& blob, keymaster_error_t* error) : AsymmetricKey(blob) { if (error) *error = LoadKey(blob); @@ -25,14 +25,12 @@ namespace keymaster { class RsaKeyFactory : public AsymmetricKeyFactory { public: - virtual keymaster_algorithm_t registry_key() const { return KM_ALGORITHM_RSA; } - virtual Key* GenerateKey(const AuthorizationSet& key_description, keymaster_error_t* error); - virtual Key* ImportKey(const AuthorizationSet& key_description, - keymaster_key_format_t key_format, const uint8_t* key_data, - size_t key_data_length, keymaster_error_t* error); - virtual Key* LoadKey(const UnencryptedKeyBlob& blob, keymaster_error_t* error); - virtual Key* RescopeKey(const UnencryptedKeyBlob& blob, - const AuthorizationSet& new_authorizations, keymaster_error_t* error); + keymaster_algorithm_t registry_key() const override { return KM_ALGORITHM_RSA; } + Key* GenerateKey(const AuthorizationSet& key_description, keymaster_error_t* error); + Key* ImportKey(const AuthorizationSet& key_description, keymaster_key_format_t key_format, + const uint8_t* key_data, size_t key_data_length, + keymaster_error_t* error) override; + Key* LoadKey(const UnencryptedKeyBlob& blob, keymaster_error_t* error) override; }; class RsaOperationFactory; @@ -45,9 +43,9 @@ class RsaKey : public AsymmetricKey { RsaKey(const UnencryptedKeyBlob& blob, keymaster_error_t* error); RsaKey(RSA* rsa_key, const AuthorizationSet& auths) : AsymmetricKey(auths), rsa_key_(rsa_key) {} - virtual int evp_key_type() { return EVP_PKEY_RSA; } - virtual bool InternalToEvp(EVP_PKEY* pkey) const; - virtual bool EvpToInternal(const EVP_PKEY* pkey); + int evp_key_type() override { return EVP_PKEY_RSA; } + bool InternalToEvp(EVP_PKEY* pkey) const override; + bool EvpToInternal(const EVP_PKEY* pkey) override; bool SupportedMode(keymaster_purpose_t purpose, keymaster_padding_t padding); bool SupportedMode(keymaster_purpose_t purpose, keymaster_digest_t digest); diff --git a/soft_keymaster_device.cpp b/soft_keymaster_device.cpp index 4de8c2e..7d4f16c 100644 --- a/soft_keymaster_device.cpp +++ b/soft_keymaster_device.cpp @@ -101,7 +101,6 @@ SoftKeymasterDevice::SoftKeymasterDevice() : impl_(new GoogleSoftKeymaster(16)) device_.add_rng_entropy = add_rng_entropy; device_.generate_key = generate_key; device_.get_key_characteristics = get_key_characteristics; - device_.rescope = rescope; device_.import_key = import_key; device_.export_key = export_key; device_.delete_key = NULL; @@ -679,39 +678,6 @@ keymaster_error_t SoftKeymasterDevice::get_key_characteristics( } /* static */ -keymaster_error_t SoftKeymasterDevice::rescope( - const keymaster1_device_t* dev, const keymaster_key_param_t* new_params, - size_t new_params_count, const keymaster_key_blob_t* key_blob, - const keymaster_blob_t* client_id, const keymaster_blob_t* app_data, - keymaster_key_blob_t* rescoped_key_blob, keymaster_key_characteristics_t** characteristics) { - if (!key_blob || !key_blob->key_material || !new_params) - return KM_ERROR_UNEXPECTED_NULL_POINTER; - - if (!rescoped_key_blob) - return KM_ERROR_OUTPUT_PARAMETER_NULL; - - RescopeRequest request; - request.SetKeyMaterial(*key_blob); - AddClientAndAppData(client_id, app_data, &request); - request.new_authorizations.Reinitialize(new_params, new_params_count); - - RescopeResponse response; - convert_device(dev)->impl_->Rescope(request, &response); - if (response.error != KM_ERROR_OK) - return response.error; - - rescoped_key_blob->key_material_size = response.key_blob.key_material_size; - uint8_t* tmp = reinterpret_cast<uint8_t*>(malloc(rescoped_key_blob->key_material_size)); - memcpy(tmp, response.key_blob.key_material, response.key_blob.key_material_size); - rescoped_key_blob->key_material = tmp; - - if (characteristics) - *characteristics = BuildCharacteristics(response.enforced, response.unenforced); - - return KM_ERROR_OK; -} - -/* static */ keymaster_error_t SoftKeymasterDevice::import_key( const keymaster1_device_t* dev, const keymaster_key_param_t* params, size_t params_count, keymaster_key_format_t key_format, const uint8_t* key_data, size_t key_data_length, diff --git a/symmetric_key.cpp b/symmetric_key.cpp index 8066b10..e1ce39f 100644 --- a/symmetric_key.cpp +++ b/symmetric_key.cpp @@ -98,21 +98,6 @@ SymmetricKey* SymmetricKeyFactory::CreateKeyAndValidateSize(const AuthorizationS return key.release(); } -Key* SymmetricKeyFactory::RescopeKey(const UnencryptedKeyBlob& blob, - const AuthorizationSet& new_authorizations, - keymaster_error_t* error) { - if (!error) - return NULL; - - UniquePtr<SymmetricKey> key(CreateKey(new_authorizations)); - key->key_data_size_ = blob.unencrypted_key_material_length(); - key->key_data_.reset(new uint8_t[key->key_data_size_]); - memcpy(key->key_data_.get(), blob.unencrypted_key_material(), key->key_data_size_); - - *error = KM_ERROR_OK; - return key.release(); -} - SymmetricKey::SymmetricKey(const UnencryptedKeyBlob& blob, keymaster_error_t* error) : Key(blob), key_data_size_(blob.unencrypted_key_material_length()) { key_data_.reset(new uint8_t[key_data_size_]); diff --git a/symmetric_key.h b/symmetric_key.h index 46f4f3f..85dbce3 100644 --- a/symmetric_key.h +++ b/symmetric_key.h @@ -24,11 +24,9 @@ namespace keymaster { class SymmetricKey; class SymmetricKeyFactory : public KeyFactory { - virtual Key* GenerateKey(const AuthorizationSet& key_description, keymaster_error_t* error); - virtual Key* ImportKey(const AuthorizationSet&, keymaster_key_format_t, const uint8_t*, size_t, - keymaster_error_t* error); - virtual Key* RescopeKey(const UnencryptedKeyBlob& blob, - const AuthorizationSet& new_authorizations, keymaster_error_t* error); + Key* GenerateKey(const AuthorizationSet& key_description, keymaster_error_t* error) override; + Key* ImportKey(const AuthorizationSet&, keymaster_key_format_t, const uint8_t*, size_t, + keymaster_error_t* error) override; virtual const keymaster_key_format_t* SupportedImportFormats(size_t* format_count); virtual const keymaster_key_format_t* SupportedExportFormats(size_t* format_count) { |