From 8f64de2badece334075d950d719b68fa9e988dff Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Fri, 18 Oct 2024 16:24:08 -0700 Subject: [PATCH 1/3] m --- src/aws_encryption_sdk/key_providers/base.py | 7 +-- .../manifests/master_key.py | 43 ++++++++++++++++--- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/src/aws_encryption_sdk/key_providers/base.py b/src/aws_encryption_sdk/key_providers/base.py index a855ee596..5fa99cc1c 100644 --- a/src/aws_encryption_sdk/key_providers/base.py +++ b/src/aws_encryption_sdk/key_providers/base.py @@ -12,6 +12,7 @@ ConfigMismatchError, DecryptKeyError, IncorrectMasterKeyError, + InvalidDataKeyError, InvalidKeyIdError, MasterKeyProviderError, ) @@ -256,7 +257,7 @@ def decrypt_data_key(self, encrypted_data_key, algorithm, encryption_context): # //# input encryption context. data_key = master_key.decrypt_data_key(encrypted_data_key, algorithm, encryption_context) - except (IncorrectMasterKeyError, DecryptKeyError) as error: + except (IncorrectMasterKeyError, DecryptKeyError, InvalidDataKeyError) as error: _LOGGER.debug( "%s raised when attempting to decrypt data key with master key %s", repr(error), @@ -304,8 +305,8 @@ def decrypt_data_key_from_list(self, encrypted_data_keys, algorithm, encryption_ try: data_key = self.decrypt_data_key(encrypted_data_key, algorithm, encryption_context) # MasterKeyProvider.decrypt_data_key throws DecryptKeyError - # but MasterKey.decrypt_data_key throws IncorrectMasterKeyError - except (DecryptKeyError, IncorrectMasterKeyError): + # but MasterKey.decrypt_data_key throws IncorrectMasterKeyError and InvalidDataKeyError + except (DecryptKeyError, IncorrectMasterKeyError, InvalidDataKeyError): continue else: break diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/master_key.py b/test_vector_handlers/src/awses_test_vectors/manifests/master_key.py index 49b517eae..7295db43c 100644 --- a/test_vector_handlers/src/awses_test_vectors/manifests/master_key.py +++ b/test_vector_handlers/src/awses_test_vectors/manifests/master_key.py @@ -290,6 +290,40 @@ def scenario_spec(self): return spec +class TestVectorsMultiMasterKeyProvider(MasterKeyProvider): + """ + Provider for other MasterKeyProviders. + Acts as a "multi" MasterKeyProvider for use in test vectors. + + There is some disagreement between the spec + and how Python ESDK implements MasterKey; + this class fills that gap. + + In the ESDK-Python, MasterKey extends MasterKeyProvider; + i.e. MasterKey "is a" MasterKeyProvider; isinstance(some_master_key, MasterKeyProvider) == True. + + However, MasterKey overrides MasterKeyProvider's `decrypt_data_key` method. + From AWS ESDK specification: + "A master key MUST supply itself and MUST NOT supply any other master keys." + https://github.com/awslabs/aws-encryption-sdk-specification/blob/master/framework/master-key-interface.md#get-master-key + + This suggests that this "is a" relationship is not entirely true. + + master_key_provider_from_master_key_specs uses this class to provide all loaded MasterKeyProviders (or MasterKeys) + from an interface that supports supplying other master keys. + """ + + _config_class = MasterKeyProviderConfig + provider_id = "aws-test-vectors-multi-master-key-provider" + + def add_key(self, key_provider): + self._members.append(key_provider) + + def _new_master_key(self, key_id): + # This MKP does not have a key associated with it. + raise InvalidKeyIdError() + + def master_key_provider_from_master_key_specs(keys, master_key_specs): # type: (KeysManifest, Iterable[MasterKeySpec]) -> MasterKeyProvider """Build and combine all master key providers identified by the provided specs and @@ -302,8 +336,7 @@ def master_key_provider_from_master_key_specs(keys, master_key_specs): :rtype: MasterKeyProvider """ master_keys = [spec.master_key(keys) for spec in master_key_specs] - primary = master_keys[0] - others = master_keys[1:] - for master_key in others: - primary.add_master_key_provider(master_key) - return primary + mkp = TestVectorsMultiMasterKeyProvider() + for master_key in master_keys: + mkp.add_key(master_key) + return mkp From 1dbca82fdd78da3996334e1e4894e30805d777d9 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Fri, 18 Oct 2024 16:27:32 -0700 Subject: [PATCH 2/3] m --- .../src/awses_test_vectors/manifests/master_key.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/master_key.py b/test_vector_handlers/src/awses_test_vectors/manifests/master_key.py index 7295db43c..825828ad9 100644 --- a/test_vector_handlers/src/awses_test_vectors/manifests/master_key.py +++ b/test_vector_handlers/src/awses_test_vectors/manifests/master_key.py @@ -302,15 +302,16 @@ class TestVectorsMultiMasterKeyProvider(MasterKeyProvider): In the ESDK-Python, MasterKey extends MasterKeyProvider; i.e. MasterKey "is a" MasterKeyProvider; isinstance(some_master_key, MasterKeyProvider) == True. - However, MasterKey overrides MasterKeyProvider's `decrypt_data_key` method. From AWS ESDK specification: "A master key MUST supply itself and MUST NOT supply any other master keys." https://github.com/awslabs/aws-encryption-sdk-specification/blob/master/framework/master-key-interface.md#get-master-key - This suggests that this "is a" relationship is not entirely true. + The MasterKey class overrides MasterKeyProvider's `decrypt_data_key` method to correct this gap. + However, this modification suggests that this "is a" relationship is not entirely true. - master_key_provider_from_master_key_specs uses this class to provide all loaded MasterKeyProviders (or MasterKeys) - from an interface that supports supplying other master keys. + master_key_provider_from_master_key_specs expects to return a MasterKeyProvider, not a MasterKey. + master_key_provider_from_master_key_specs uses this class to always return a MasterKeyProvider + that wraps any MasterKeyProvider or MasterKey loaded from a spec. """ _config_class = MasterKeyProviderConfig @@ -321,6 +322,7 @@ def add_key(self, key_provider): def _new_master_key(self, key_id): # This MKP does not have a key associated with it. + # ESDK-Python will find keys in _members. raise InvalidKeyIdError() From c7e254ae4a1345f1cb9ade3bde7c85b65a86aed4 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Fri, 18 Oct 2024 16:34:18 -0700 Subject: [PATCH 3/3] m --- .../src/awses_test_vectors/manifests/master_key.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test_vector_handlers/src/awses_test_vectors/manifests/master_key.py b/test_vector_handlers/src/awses_test_vectors/manifests/master_key.py index 825828ad9..a81c37a03 100644 --- a/test_vector_handlers/src/awses_test_vectors/manifests/master_key.py +++ b/test_vector_handlers/src/awses_test_vectors/manifests/master_key.py @@ -7,8 +7,9 @@ """ import attr import six +from aws_encryption_sdk.exceptions import InvalidKeyIdError from aws_encryption_sdk.identifiers import EncryptionKeyType, WrappingAlgorithm -from aws_encryption_sdk.key_providers.base import MasterKeyProvider # noqa pylint: disable=unused-import +from aws_encryption_sdk.key_providers.base import MasterKeyProvider, MasterKeyProviderConfig from aws_encryption_sdk.key_providers.kms import ( # noqa pylint: disable=unused-import DiscoveryFilter, KMSMasterKey, @@ -316,8 +317,10 @@ class TestVectorsMultiMasterKeyProvider(MasterKeyProvider): _config_class = MasterKeyProviderConfig provider_id = "aws-test-vectors-multi-master-key-provider" + _members = [] def add_key(self, key_provider): + """Add a MKP to the list of configured MKPs.""" self._members.append(key_provider) def _new_master_key(self, key_id):