Skip to content

fix: MKPs attempt to decrypt with remaining keys if a preceding raw RSA key failed to decrypt #707

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/aws_encryption_sdk/key_providers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
ConfigMismatchError,
DecryptKeyError,
IncorrectMasterKeyError,
InvalidDataKeyError,
InvalidKeyIdError,
MasterKeyProviderError,
)
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -290,6 +291,44 @@ 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.

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

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 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
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):
# This MKP does not have a key associated with it.
# ESDK-Python will find keys in _members.
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
Expand All @@ -302,8 +341,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
Loading