From 50b0ae9feee454a198b4d5e11a8ea8f25fa79de1 Mon Sep 17 00:00:00 2001 From: Peter Hamilton Date: Mon, 24 Jul 2017 13:52:21 -0400 Subject: [PATCH] Add server support for Getting wrapped keys This change adds support for retrieving wrapped keys from the KMIP server. The only supported key wrapping algorithm currently is the AES-based NIST Key Wrap algorithm (RFC 3394). MAC/signing is not supported for key wrapping. Attribute-bundling with the wrapped key value is not supported. Wrapping of the entire key block TTLV encoding is not supported. Various additional error cases are included and checked for. Unit tests covering the additions to Get are included. --- kmip/core/exceptions.py | 22 + kmip/services/server/engine.py | 112 ++- .../tests/unit/services/server/test_engine.py | 688 +++++++++++++++++- 3 files changed, 788 insertions(+), 34 deletions(-) diff --git a/kmip/core/exceptions.py b/kmip/core/exceptions.py index 63a4cc3..368e5b2 100644 --- a/kmip/core/exceptions.py +++ b/kmip/core/exceptions.py @@ -57,6 +57,28 @@ class CryptographicFailure(KmipError): ) +class EncodingOptionError(KmipError): + """ + An encoding error generated during key wrapping. + + This error is generated during key wrapping when a requested encoding + option is not supported or is incompatible with other settings in the + key wrapping request (e.g., attributes are requested with the key but + the encoding does not support wrapping attributes with the key value). + """ + def __init__(self, message): + """ + Create an EncodingOptionError. + + Args: + message (string): A string containing information about the error. + """ + super(EncodingOptionError, self).__init__( + reason=enums.ResultReason.ENCODING_OPTION_ERROR, + message=message + ) + + class IllegalOperation(KmipError): """ An error generated when an improper operation is attempted. The operation diff --git a/kmip/services/server/engine.py b/kmip/services/server/engine.py index a0f6c7e..a3b539f 100644 --- a/kmip/services/server/engine.py +++ b/kmip/services/server/engine.py @@ -30,7 +30,7 @@ from kmip.core import attributes from kmip.core import enums from kmip.core import exceptions -from kmip.core.objects import MACData +from kmip.core.objects import MACData, KeyWrappingData from kmip.core.factories import attributes as attribute_factory from kmip.core.factories import secrets @@ -1389,14 +1389,6 @@ class KmipEngine(object): "Key compression is not supported." ) - if payload.key_wrapping_specification: - raise exceptions.PermissionDenied( - "Key wrapping is not supported." - ) - - # TODO (peterhamilton) Process key wrapping information - # 1. Error check wrapping keys for accessibility and usability - managed_object = self._get_object_with_access_controls( unique_identifier, enums.Operation.GET @@ -1426,7 +1418,107 @@ class KmipEngine(object): ) ) - core_secret = self._build_core_object(managed_object) + if payload.key_wrapping_specification: + key_wrapping_spec = payload.key_wrapping_specification + wrapping_method = key_wrapping_spec.wrapping_method + + if wrapping_method != enums.WrappingMethod.ENCRYPT: + raise exceptions.OperationNotSupported( + "Wrapping method '{0}' is not supported.".format( + wrapping_method + ) + ) + + if key_wrapping_spec.encryption_key_information: + key_info = key_wrapping_spec.encryption_key_information + encryption_key_uuid = key_info.unique_identifier + encryption_key_params = key_info.cryptographic_parameters + + try: + key = self._get_object_with_access_controls( + encryption_key_uuid, + enums.Operation.GET + ) + except Exception: + raise exceptions.ItemNotFound( + "Wrapping key does not exist." + ) + + if key._object_type != enums.ObjectType.SYMMETRIC_KEY: + raise exceptions.IllegalOperation( + "The wrapping encryption key specified by the " + "encryption key information is not a key." + ) + + if key.state != enums.State.ACTIVE: + raise exceptions.PermissionDenied( + "Encryption key {0} must be activated to be used for " + "key wrapping.".format(encryption_key_uuid) + ) + + mask = enums.CryptographicUsageMask.WRAP_KEY + if mask not in key.cryptographic_usage_masks: + raise exceptions.PermissionDenied( + "The WrapKey bit must be set in the cryptographic " + "usage mask of encryption key {0} for it to be used " + "for key wrapping.".format(encryption_key_uuid) + ) + + if key_wrapping_spec.attribute_names: + raise exceptions.IllegalOperation( + "Wrapping object attributes is not supported." + ) + + encoding_option = key_wrapping_spec.encoding_option + if encoding_option != enums.EncodingOption.NO_ENCODING: + raise exceptions.EncodingOptionError( + "Encoding option '{0}' is not supported.".format( + encoding_option + ) + ) + + self._logger.info("Wrapping {0} {1} with {2} {3}.".format( + ''.join([x.capitalize() for x in object_type.split('_')]), + managed_object.unique_identifier, + ''.join( + [x.capitalize() for x in key._object_type.name.split( + '_' + )] + ), + encryption_key_uuid + )) + + result = self._cryptography_engine.wrap_key( + key_material=managed_object.value, + wrapping_method=key_wrapping_spec.wrapping_method, + key_wrap_algorithm=encryption_key_params.block_cipher_mode, + encryption_key=key.value + ) + + wrapped_object = copy.deepcopy(managed_object) + wrapped_object.value = result + + core_secret = self._build_core_object(wrapped_object) + key_wrapping_data = KeyWrappingData( + wrapping_method=wrapping_method, + encryption_key_information=key_info, + encoding_option=encoding_option + ) + core_secret.key_block.key_wrapping_data = key_wrapping_data + + elif key_wrapping_spec.mac_signature_key_information: + raise exceptions.PermissionDenied( + "Key wrapping with MAC/signing key information is not " + "supported." + ) + else: + raise exceptions.PermissionDenied( + "Either the encryption key information or the " + "MAC/signature key information must be specified for key " + "wrapping to be performed." + ) + else: + core_secret = self._build_core_object(managed_object) response_payload = get.GetResponsePayload( object_type=managed_object._object_type, diff --git a/kmip/tests/unit/services/server/test_engine.py b/kmip/tests/unit/services/server/test_engine.py index 4407063..240b359 100644 --- a/kmip/tests/unit/services/server/test_engine.py +++ b/kmip/tests/unit/services/server/test_engine.py @@ -3735,10 +3735,10 @@ class TestKmipEngine(testtools.TestCase): e._data_session.commit() - def test_get_with_unsupported_features(self): + def test_get_unsupported_key_compression(self): """ - Test that the right errors are generated when unsupported features - are used in a Get request. + Test that the right error is generated when key compression is + provided in a Get request. """ e = engine.KmipEngine() e._data_store = self.engine @@ -3763,27 +3763,6 @@ class TestKmipEngine(testtools.TestCase): "Processing operation: Get" ) - e._logger.reset_mock() - - # Test that specifying the key wrapping specification generates an - # error. - payload = get.GetRequestPayload( - key_wrapping_specification=objects.KeyWrappingSpecification() - ) - - args = (payload, ) - regex = "Key wrapping is not supported." - six.assertRaisesRegex( - self, - exceptions.PermissionDenied, - regex, - e._process_get, - *args - ) - e._logger.info.assert_any_call( - "Processing operation: Get" - ) - def test_get_with_key_format_type(self): """ Test that the key format type is handled properly in a Get request. @@ -3922,6 +3901,667 @@ class TestKmipEngine(testtools.TestCase): *args ) + def test_get_wrapped_key(self): + """ + Test that a Get request for a wrapped key can be processed correctly. + """ + e = engine.KmipEngine() + e._data_store = self.engine + e._data_store_session_factory = self.session_factory + e._data_session = e._data_store_session_factory() + e._logger = mock.MagicMock() + e._cryptography_engine.logger = mock.MagicMock() + + wrapping_key = pie_objects.SymmetricKey( + enums.CryptographicAlgorithm.AES, + 128, + ( + b'\x00\x01\x02\x03\x04\x05\x06\x07' + b'\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F' + ), + [enums.CryptographicUsageMask.WRAP_KEY] + ) + wrapping_key.state = enums.State.ACTIVE + + unwrapped_key = pie_objects.SymmetricKey( + enums.CryptographicAlgorithm.AES, + 128, + ( + b'\x00\x11\x22\x33\x44\x55\x66\x77' + b'\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF' + ), + [enums.CryptographicUsageMask.ENCRYPT] + ) + + e._data_session.add(wrapping_key) + e._data_session.add(unwrapped_key) + e._data_session.commit() + e._data_session = e._data_store_session_factory() + + wrapping_key_uuid = str(wrapping_key.unique_identifier) + unwrapped_key_uuid = str(unwrapped_key.unique_identifier) + + cryptographic_parameters = attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.NIST_KEY_WRAP + ) + payload = get.GetRequestPayload( + unique_identifier=unwrapped_key_uuid, + key_wrapping_specification=objects.KeyWrappingSpecification( + wrapping_method=enums.WrappingMethod.ENCRYPT, + encryption_key_information=objects.EncryptionKeyInformation( + unique_identifier=wrapping_key_uuid, + cryptographic_parameters=cryptographic_parameters + ), + encoding_option=enums.EncodingOption.NO_ENCODING + ) + ) + + response_payload = e._process_get(payload) + + e._logger.info.assert_any_call("Processing operation: Get") + e._logger.info.assert_any_call( + "Wrapping SymmetricKey 2 with SymmetricKey 1." + ) + self.assertEqual( + enums.ObjectType.SYMMETRIC_KEY, + response_payload.object_type + ) + self.assertEqual( + unwrapped_key_uuid, + response_payload.unique_identifier + ) + self.assertIsInstance( + response_payload.secret, + secrets.SymmetricKey + ) + self.assertEqual( + ( + b'\x1F\xA6\x8B\x0A\x81\x12\xB4\x47' + b'\xAE\xF3\x4B\xD8\xFB\x5A\x7B\x82' + b'\x9D\x3E\x86\x23\x71\xD2\xCF\xE5' + ), + response_payload.secret.key_block.key_value.key_material.value + ) + self.assertIsInstance( + response_payload.secret.key_block.key_wrapping_data, + objects.KeyWrappingData + ) + k = response_payload.secret.key_block.key_wrapping_data + self.assertEqual( + enums.WrappingMethod.ENCRYPT, + k.wrapping_method + ) + self.assertIsInstance( + k.encryption_key_information, + objects.EncryptionKeyInformation + ) + self.assertEqual( + '1', + k.encryption_key_information.unique_identifier + ) + self.assertIsInstance( + k.encryption_key_information.cryptographic_parameters, + attributes.CryptographicParameters + ) + c = k.encryption_key_information.cryptographic_parameters + self.assertEqual( + enums.BlockCipherMode.NIST_KEY_WRAP, + c.block_cipher_mode + ) + self.assertEqual( + enums.EncodingOption.NO_ENCODING, + k.encoding_option + ) + + def test_get_wrapped_key_unsupported_mac_sig(self): + """ + Test that the right error is thrown when key wrapping is requested + via MAC/signing in a Get request. + """ + e = engine.KmipEngine() + e._data_store = self.engine + e._data_store_session_factory = self.session_factory + e._data_session = e._data_store_session_factory() + e._logger = mock.MagicMock() + e._cryptography_engine.logger = mock.MagicMock() + + wrapping_key = pie_objects.SymmetricKey( + enums.CryptographicAlgorithm.AES, + 128, + ( + b'\x00\x01\x02\x03\x04\x05\x06\x07' + b'\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F' + ), + [enums.CryptographicUsageMask.WRAP_KEY] + ) + wrapping_key.state = enums.State.ACTIVE + + unwrapped_key = pie_objects.SymmetricKey( + enums.CryptographicAlgorithm.AES, + 128, + ( + b'\x00\x11\x22\x33\x44\x55\x66\x77' + b'\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF' + ), + [enums.CryptographicUsageMask.ENCRYPT] + ) + + e._data_session.add(wrapping_key) + e._data_session.add(unwrapped_key) + e._data_session.commit() + e._data_session = e._data_store_session_factory() + + wrapping_key_uuid = str(wrapping_key.unique_identifier) + unwrapped_key_uuid = str(unwrapped_key.unique_identifier) + cryptographic_parameters = attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.NIST_KEY_WRAP + ) + payload = get.GetRequestPayload( + unique_identifier=unwrapped_key_uuid, + key_wrapping_specification=objects.KeyWrappingSpecification( + wrapping_method=enums.WrappingMethod.MAC_SIGN, + mac_signature_key_information=objects. + MACSignatureKeyInformation( + unique_identifier=wrapping_key_uuid, + cryptographic_parameters=cryptographic_parameters + ), + encoding_option=enums.EncodingOption.NO_ENCODING + ) + ) + + args = (payload, ) + self.assertRaisesRegexp( + exceptions.OperationNotSupported, + "Wrapping method '{0}' is not supported.".format( + enums.WrappingMethod.MAC_SIGN + ), + e._process_get, + *args + ) + + def test_get_wrapped_key_unsupported_mac_sign_key_info(self): + """ + Test that the right error is thrown when key wrapping is requested + with MAC/signing key information in a Get request. + """ + e = engine.KmipEngine() + e._data_store = self.engine + e._data_store_session_factory = self.session_factory + e._data_session = e._data_store_session_factory() + e._logger = mock.MagicMock() + e._cryptography_engine.logger = mock.MagicMock() + + wrapping_key = pie_objects.SymmetricKey( + enums.CryptographicAlgorithm.AES, + 128, + ( + b'\x00\x01\x02\x03\x04\x05\x06\x07' + b'\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F' + ), + [enums.CryptographicUsageMask.WRAP_KEY] + ) + wrapping_key.state = enums.State.ACTIVE + + unwrapped_key = pie_objects.SymmetricKey( + enums.CryptographicAlgorithm.AES, + 128, + ( + b'\x00\x11\x22\x33\x44\x55\x66\x77' + b'\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF' + ), + [enums.CryptographicUsageMask.ENCRYPT] + ) + + e._data_session.add(wrapping_key) + e._data_session.add(unwrapped_key) + e._data_session.commit() + e._data_session = e._data_store_session_factory() + + wrapping_key_uuid = str(wrapping_key.unique_identifier) + unwrapped_key_uuid = str(unwrapped_key.unique_identifier) + cryptographic_parameters = attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.NIST_KEY_WRAP + ) + payload = get.GetRequestPayload( + unique_identifier=unwrapped_key_uuid, + key_wrapping_specification=objects.KeyWrappingSpecification( + wrapping_method=enums.WrappingMethod.ENCRYPT, + mac_signature_key_information=objects. + MACSignatureKeyInformation( + unique_identifier=wrapping_key_uuid, + cryptographic_parameters=cryptographic_parameters + ), + encoding_option=enums.EncodingOption.NO_ENCODING + ) + ) + + args = (payload, ) + self.assertRaisesRegexp( + exceptions.PermissionDenied, + "Key wrapping with MAC/signing key information is not supported.", + e._process_get, + *args + ) + + def test_get_wrapped_key_missing_key_information(self): + """ + Test that the right error is thrown when key wrapping is requested + with no settings in a Get request. + """ + e = engine.KmipEngine() + e._data_store = self.engine + e._data_store_session_factory = self.session_factory + e._data_session = e._data_store_session_factory() + e._logger = mock.MagicMock() + e._cryptography_engine.logger = mock.MagicMock() + + unwrapped_key = pie_objects.SymmetricKey( + enums.CryptographicAlgorithm.AES, + 128, + ( + b'\x00\x11\x22\x33\x44\x55\x66\x77' + b'\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF' + ), + [enums.CryptographicUsageMask.ENCRYPT] + ) + + e._data_session.add(unwrapped_key) + e._data_session.commit() + e._data_session = e._data_store_session_factory() + + unwrapped_key_uuid = str(unwrapped_key.unique_identifier) + payload = get.GetRequestPayload( + unique_identifier=unwrapped_key_uuid, + key_wrapping_specification=objects.KeyWrappingSpecification( + wrapping_method=enums.WrappingMethod.ENCRYPT, + encoding_option=enums.EncodingOption.NO_ENCODING + ) + ) + + args = (payload, ) + self.assertRaisesRegexp( + exceptions.PermissionDenied, + "Either the encryption key information or the MAC/signature key " + "information must be specified for key wrapping to be performed.", + e._process_get, + *args + ) + + def test_get_wrapped_key_nonexistent_wrapping_key(self): + """ + Test that the right error is thrown when key wrapping is requested + with a nonexistent wrapping key in a Get request. + """ + e = engine.KmipEngine() + e._data_store = self.engine + e._data_store_session_factory = self.session_factory + e._data_session = e._data_store_session_factory() + e._logger = mock.MagicMock() + e._cryptography_engine.logger = mock.MagicMock() + + unwrapped_key = pie_objects.SymmetricKey( + enums.CryptographicAlgorithm.AES, + 128, + ( + b'\x00\x11\x22\x33\x44\x55\x66\x77' + b'\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF' + ), + [enums.CryptographicUsageMask.ENCRYPT] + ) + + e._data_session.add(unwrapped_key) + e._data_session.commit() + e._data_session = e._data_store_session_factory() + + unwrapped_key_uuid = str(unwrapped_key.unique_identifier) + + cryptographic_parameters = attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.NIST_KEY_WRAP + ) + payload = get.GetRequestPayload( + unique_identifier=unwrapped_key_uuid, + key_wrapping_specification=objects.KeyWrappingSpecification( + wrapping_method=enums.WrappingMethod.ENCRYPT, + encryption_key_information=objects.EncryptionKeyInformation( + unique_identifier='invalid', + cryptographic_parameters=cryptographic_parameters + ), + encoding_option=enums.EncodingOption.NO_ENCODING + ) + ) + + args = (payload, ) + self.assertRaisesRegexp( + exceptions.ItemNotFound, + "Wrapping key does not exist.", + e._process_get, + *args + ) + + def test_get_wrapped_key_non_wrapping_key(self): + """ + Test that the right error is thrown when key wrapping is requested + with a non-wrapping key in a Get request. + """ + e = engine.KmipEngine() + e._data_store = self.engine + e._data_store_session_factory = self.session_factory + e._data_session = e._data_store_session_factory() + e._logger = mock.MagicMock() + e._cryptography_engine.logger = mock.MagicMock() + + wrapping_key = pie_objects.SecretData( + ( + b'\x00\x01\x02\x03\x04\x05\x06\x07' + b'\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F' + ), + enums.SecretDataType.SEED, + masks=[enums.CryptographicUsageMask.WRAP_KEY] + ) + wrapping_key.state = enums.State.ACTIVE + + unwrapped_key = pie_objects.SymmetricKey( + enums.CryptographicAlgorithm.AES, + 128, + ( + b'\x00\x11\x22\x33\x44\x55\x66\x77' + b'\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF' + ), + [enums.CryptographicUsageMask.ENCRYPT] + ) + + e._data_session.add(wrapping_key) + e._data_session.add(unwrapped_key) + e._data_session.commit() + e._data_session = e._data_store_session_factory() + + wrapping_key_uuid = str(wrapping_key.unique_identifier) + unwrapped_key_uuid = str(unwrapped_key.unique_identifier) + + cryptographic_parameters = attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.NIST_KEY_WRAP + ) + payload = get.GetRequestPayload( + unique_identifier=unwrapped_key_uuid, + key_wrapping_specification=objects.KeyWrappingSpecification( + wrapping_method=enums.WrappingMethod.ENCRYPT, + encryption_key_information=objects.EncryptionKeyInformation( + unique_identifier=wrapping_key_uuid, + cryptographic_parameters=cryptographic_parameters + ), + encoding_option=enums.EncodingOption.NO_ENCODING + ) + ) + + args = (payload, ) + self.assertRaisesRegexp( + exceptions.IllegalOperation, + "The wrapping encryption key specified by the encryption key " + "information is not a key.", + e._process_get, + *args + ) + + def test_get_wrapped_key_inactive_wrapping_key(self): + """ + Test that the right error is thrown when key wrapping is requested + with an inactive wrapping key in a Get request. + """ + e = engine.KmipEngine() + e._data_store = self.engine + e._data_store_session_factory = self.session_factory + e._data_session = e._data_store_session_factory() + e._logger = mock.MagicMock() + e._cryptography_engine.logger = mock.MagicMock() + + wrapping_key = pie_objects.SymmetricKey( + enums.CryptographicAlgorithm.AES, + 128, + ( + b'\x00\x01\x02\x03\x04\x05\x06\x07' + b'\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F' + ), + [enums.CryptographicUsageMask.WRAP_KEY] + ) + + unwrapped_key = pie_objects.SymmetricKey( + enums.CryptographicAlgorithm.AES, + 128, + ( + b'\x00\x11\x22\x33\x44\x55\x66\x77' + b'\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF' + ), + [enums.CryptographicUsageMask.ENCRYPT] + ) + + e._data_session.add(wrapping_key) + e._data_session.add(unwrapped_key) + e._data_session.commit() + e._data_session = e._data_store_session_factory() + + wrapping_key_uuid = str(wrapping_key.unique_identifier) + unwrapped_key_uuid = str(unwrapped_key.unique_identifier) + + cryptographic_parameters = attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.NIST_KEY_WRAP + ) + payload = get.GetRequestPayload( + unique_identifier=unwrapped_key_uuid, + key_wrapping_specification=objects.KeyWrappingSpecification( + wrapping_method=enums.WrappingMethod.ENCRYPT, + encryption_key_information=objects.EncryptionKeyInformation( + unique_identifier=wrapping_key_uuid, + cryptographic_parameters=cryptographic_parameters + ), + encoding_option=enums.EncodingOption.NO_ENCODING + ) + ) + + args = (payload, ) + self.assertRaisesRegexp( + exceptions.PermissionDenied, + "Encryption key 1 must be activated to be used for key " + "wrapping.", + e._process_get, + *args + ) + + def test_get_wrapped_key_invalid_wrapping_key(self): + """ + Test that the right error is thrown when key wrapping is requested + with a wrapping key not designated for key wrapping in a Get request. + """ + e = engine.KmipEngine() + e._data_store = self.engine + e._data_store_session_factory = self.session_factory + e._data_session = e._data_store_session_factory() + e._logger = mock.MagicMock() + e._cryptography_engine.logger = mock.MagicMock() + + wrapping_key = pie_objects.SymmetricKey( + enums.CryptographicAlgorithm.AES, + 128, + ( + b'\x00\x01\x02\x03\x04\x05\x06\x07' + b'\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F' + ), + [enums.CryptographicUsageMask.ENCRYPT] + ) + wrapping_key.state = enums.State.ACTIVE + + unwrapped_key = pie_objects.SymmetricKey( + enums.CryptographicAlgorithm.AES, + 128, + ( + b'\x00\x11\x22\x33\x44\x55\x66\x77' + b'\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF' + ), + [enums.CryptographicUsageMask.ENCRYPT] + ) + + e._data_session.add(wrapping_key) + e._data_session.add(unwrapped_key) + e._data_session.commit() + e._data_session = e._data_store_session_factory() + + wrapping_key_uuid = str(wrapping_key.unique_identifier) + unwrapped_key_uuid = str(unwrapped_key.unique_identifier) + + cryptographic_parameters = attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.NIST_KEY_WRAP + ) + payload = get.GetRequestPayload( + unique_identifier=unwrapped_key_uuid, + key_wrapping_specification=objects.KeyWrappingSpecification( + wrapping_method=enums.WrappingMethod.ENCRYPT, + encryption_key_information=objects.EncryptionKeyInformation( + unique_identifier=wrapping_key_uuid, + cryptographic_parameters=cryptographic_parameters + ), + encoding_option=enums.EncodingOption.NO_ENCODING + ) + ) + + args = (payload, ) + self.assertRaisesRegexp( + exceptions.PermissionDenied, + "The WrapKey bit must be set in the cryptographic usage mask of " + "encryption key 1 for it to be used for key wrapping.", + e._process_get, + *args + ) + + def test_get_wrapped_key_unsupported_attribute_wrapping(self): + """ + Test that the right error is thrown when key wrapping is requested + with attribute names in a Get request. + """ + e = engine.KmipEngine() + e._data_store = self.engine + e._data_store_session_factory = self.session_factory + e._data_session = e._data_store_session_factory() + e._logger = mock.MagicMock() + e._cryptography_engine.logger = mock.MagicMock() + + wrapping_key = pie_objects.SymmetricKey( + enums.CryptographicAlgorithm.AES, + 128, + ( + b'\x00\x01\x02\x03\x04\x05\x06\x07' + b'\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F' + ), + [enums.CryptographicUsageMask.WRAP_KEY] + ) + wrapping_key.state = enums.State.ACTIVE + + unwrapped_key = pie_objects.SymmetricKey( + enums.CryptographicAlgorithm.AES, + 128, + ( + b'\x00\x11\x22\x33\x44\x55\x66\x77' + b'\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF' + ), + [enums.CryptographicUsageMask.ENCRYPT] + ) + + e._data_session.add(wrapping_key) + e._data_session.add(unwrapped_key) + e._data_session.commit() + e._data_session = e._data_store_session_factory() + + wrapping_key_uuid = str(wrapping_key.unique_identifier) + unwrapped_key_uuid = str(unwrapped_key.unique_identifier) + + cryptographic_parameters = attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.NIST_KEY_WRAP + ) + payload = get.GetRequestPayload( + unique_identifier=unwrapped_key_uuid, + key_wrapping_specification=objects.KeyWrappingSpecification( + wrapping_method=enums.WrappingMethod.ENCRYPT, + encryption_key_information=objects.EncryptionKeyInformation( + unique_identifier=wrapping_key_uuid, + cryptographic_parameters=cryptographic_parameters + ), + attribute_names=['Cryptographic Algorithm'], + encoding_option=enums.EncodingOption.NO_ENCODING + ) + ) + + args = (payload, ) + self.assertRaisesRegexp( + exceptions.IllegalOperation, + "Wrapping object attributes is not supported.", + e._process_get, + *args + ) + + def test_get_wrapped_key_invalid_encoding(self): + """ + Test that the right error is thrown when key wrapping is requested + with an unsupported encoding option in a Get request. + """ + e = engine.KmipEngine() + e._data_store = self.engine + e._data_store_session_factory = self.session_factory + e._data_session = e._data_store_session_factory() + e._logger = mock.MagicMock() + e._cryptography_engine.logger = mock.MagicMock() + + wrapping_key = pie_objects.SymmetricKey( + enums.CryptographicAlgorithm.AES, + 128, + ( + b'\x00\x01\x02\x03\x04\x05\x06\x07' + b'\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F' + ), + [enums.CryptographicUsageMask.WRAP_KEY] + ) + wrapping_key.state = enums.State.ACTIVE + + unwrapped_key = pie_objects.SymmetricKey( + enums.CryptographicAlgorithm.AES, + 128, + ( + b'\x00\x11\x22\x33\x44\x55\x66\x77' + b'\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF' + ), + [enums.CryptographicUsageMask.ENCRYPT] + ) + + e._data_session.add(wrapping_key) + e._data_session.add(unwrapped_key) + e._data_session.commit() + e._data_session = e._data_store_session_factory() + + wrapping_key_uuid = str(wrapping_key.unique_identifier) + unwrapped_key_uuid = str(unwrapped_key.unique_identifier) + + cryptographic_parameters = attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.NIST_KEY_WRAP + ) + payload = get.GetRequestPayload( + unique_identifier=unwrapped_key_uuid, + key_wrapping_specification=objects.KeyWrappingSpecification( + wrapping_method=enums.WrappingMethod.ENCRYPT, + encryption_key_information=objects.EncryptionKeyInformation( + unique_identifier=wrapping_key_uuid, + cryptographic_parameters=cryptographic_parameters + ), + encoding_option=enums.EncodingOption.TTLV_ENCODING + ) + ) + + args = (payload, ) + self.assertRaisesRegexp( + exceptions.EncodingOptionError, + "Encoding option '{0}' is not supported.".format( + enums.EncodingOption.TTLV_ENCODING + ), + e._process_get, + *args + ) + def test_get_attributes(self): """ Test that a GetAttributes request can be processed correctly.