From f6e5b3adef2c9cc827d20b36fc3e184237003cc1 Mon Sep 17 00:00:00 2001 From: Peter Hamilton Date: Fri, 20 Sep 2019 10:38:16 -0400 Subject: [PATCH] Add conversion utilities for SplitKey objects This change adds conversion utilities for SplitKey objects, allowing for conversions between the Pie and Core object spaces. The server is also updated to recognize the new Pie SplitKey object. Unit tests have been added and tweaked to accommodate these changes. Partially implements #545 --- kmip/pie/factory.py | 47 +++++ kmip/services/server/engine.py | 2 +- kmip/tests/unit/pie/test_factory.py | 164 ++++++++++++++++++ .../tests/unit/services/server/test_engine.py | 4 +- 4 files changed, 214 insertions(+), 3 deletions(-) diff --git a/kmip/pie/factory.py b/kmip/pie/factory.py index 49e43bee..3752a0a4 100644 --- a/kmip/pie/factory.py +++ b/kmip/pie/factory.py @@ -68,6 +68,10 @@ def convert(self, obj): return self._build_core_opaque_object(obj) elif isinstance(obj, secrets.OpaqueObject): return self._build_pie_opaque_object(obj) + elif isinstance(obj, pobjects.SplitKey): + return self._build_core_split_key(obj) + elif isinstance(obj, secrets.SplitKey): + return self._build_pie_split_key(obj) else: raise TypeError("object type unsupported and cannot be converted") @@ -125,6 +129,23 @@ def _build_pie_opaque_object(self, obj): value = obj.opaque_data_value.value return pobjects.OpaqueObject(value, opaque_type) + def _build_pie_split_key(self, secret): + algorithm = secret.key_block.cryptographic_algorithm.value + return pobjects.SplitKey( + cryptographic_algorithm=algorithm, + cryptographic_length=secret.key_block.cryptographic_length.value, + key_value=secret.key_block.key_value.key_material.value, + key_format_type=secret.key_block.key_format_type.value, + key_wrapping_data=self._build_key_wrapping_data( + secret.key_block.key_wrapping_data + ), + split_key_parts=secret.split_key_parts, + key_part_identifier=secret.key_part_identifier, + split_key_threshold=secret.split_key_threshold, + split_key_method=secret.split_key_method, + prime_field_size=secret.prime_field_size + ) + def _build_core_key(self, key, cls): algorithm = key.cryptographic_algorithm length = key.cryptographic_length @@ -170,6 +191,32 @@ def _build_core_secret_data(self, secret): return secrets.SecretData(data_type, key_block) + def _build_core_split_key(self, secret): + key_material = cobjects.KeyMaterial(secret.value) + key_value = cobjects.KeyValue(key_material) + key_block = cobjects.KeyBlock( + key_format_type=misc.KeyFormatType(secret.key_format_type), + key_compression_type=None, + key_value=key_value, + cryptographic_algorithm=attributes.CryptographicAlgorithm( + secret.cryptographic_algorithm + ), + cryptographic_length=attributes.CryptographicLength( + secret.cryptographic_length + ), + key_wrapping_data=cobjects.KeyWrappingData( + **secret.key_wrapping_data + ) + ) + return secrets.SplitKey( + split_key_parts=secret.split_key_parts, + key_part_identifier=secret.key_part_identifier, + split_key_threshold=secret.split_key_threshold, + split_key_method=secret.split_key_method, + prime_field_size=secret.prime_field_size, + key_block=key_block + ) + def _build_core_opaque_object(self, obj): opaque_type = obj.opaque_type value = obj.value diff --git a/kmip/services/server/engine.py b/kmip/services/server/engine.py index 22607f47..dd7b99d7 100644 --- a/kmip/services/server/engine.py +++ b/kmip/services/server/engine.py @@ -123,7 +123,7 @@ def __init__(self, policies=None, database_path=None): enums.ObjectType.SYMMETRIC_KEY: objects.SymmetricKey, enums.ObjectType.PUBLIC_KEY: objects.PublicKey, enums.ObjectType.PRIVATE_KEY: objects.PrivateKey, - enums.ObjectType.SPLIT_KEY: None, + enums.ObjectType.SPLIT_KEY: objects.SplitKey, enums.ObjectType.TEMPLATE: None, enums.ObjectType.SECRET_DATA: objects.SecretData, enums.ObjectType.OPAQUE_DATA: objects.OpaqueObject diff --git a/kmip/tests/unit/pie/test_factory.py b/kmip/tests/unit/pie/test_factory.py index 02764337..c52360f4 100644 --- a/kmip/tests/unit/pie/test_factory.py +++ b/kmip/tests/unit/pie/test_factory.py @@ -430,6 +430,88 @@ def test_convert_opaque_object_core_to_pie(self): self.assertEqual(enums.OpaqueDataType.NONE, pie_obj.opaque_type) self.assertEqual(self.opaque_bytes, pie_obj.value) + def test_convert_split_key_pie_to_core(self): + """ + Test that a Pie split key object can be converted into a core split + key object. + """ + pie_split_key = pobjects.SplitKey( + cryptographic_algorithm=enums.CryptographicAlgorithm.AES, + cryptographic_length=128, + key_value=self.symmetric_bytes, + cryptographic_usage_masks=[enums.CryptographicUsageMask.EXPORT], + name="Split Key", + key_format_type=enums.KeyFormatType.RAW, + key_wrapping_data=None, + split_key_parts=3, + key_part_identifier=1, + split_key_threshold=2, + split_key_method=enums.SplitKeyMethod.XOR, + prime_field_size=None + ) + core_split_key = self.factory.convert(pie_split_key) + + self.assertIsInstance(core_split_key, secrets.SplitKey) + self._test_core_key( + core_split_key, + enums.CryptographicAlgorithm.AES, + 128, + self.symmetric_bytes, + enums.KeyFormatType.RAW + ) + self.assertEqual(3, core_split_key.split_key_parts) + self.assertEqual(1, core_split_key.key_part_identifier) + self.assertEqual(2, core_split_key.split_key_threshold) + self.assertEqual( + enums.SplitKeyMethod.XOR, + core_split_key.split_key_method + ) + self.assertIsNone(core_split_key.prime_field_size) + + def test_convert_split_key_core_to_pie(self): + """ + Test that a core split key object can be converted into a Pie split + key object. + """ + key_block = cobjects.KeyBlock( + key_format_type=misc.KeyFormatType(enums.KeyFormatType.RAW), + key_compression_type=None, + key_value=cobjects.KeyValue( + cobjects.KeyMaterial(self.symmetric_bytes) + ), + cryptographic_algorithm=attributes.CryptographicAlgorithm( + enums.CryptographicAlgorithm.AES + ), + cryptographic_length=attributes.CryptographicLength(128), + key_wrapping_data=None + ) + core_split_key = secrets.SplitKey( + split_key_parts=3, + key_part_identifier=1, + split_key_threshold=2, + split_key_method=enums.SplitKeyMethod.XOR, + prime_field_size=None, + key_block=key_block + ) + pie_split_key = self.factory.convert(core_split_key) + + self.assertIsInstance(pie_split_key, pobjects.SplitKey) + self._test_pie_key( + pie_split_key, + enums.CryptographicAlgorithm.AES, + 128, + self.symmetric_bytes, + enums.KeyFormatType.RAW + ) + self.assertEqual(3, pie_split_key.split_key_parts) + self.assertEqual(1, pie_split_key.key_part_identifier) + self.assertEqual(2, pie_split_key.split_key_threshold) + self.assertEqual( + enums.SplitKeyMethod.XOR, + pie_split_key.split_key_method + ) + self.assertIsNone(pie_split_key.prime_field_size) + def test_build_pie_symmetric_key(self): """ Test that a core SymmetricKey object can be converted into a Pie @@ -531,6 +613,88 @@ def test_build_pie_certificate_on_invalid_type(self): self.assertRaises( TypeError, self.factory._build_pie_certificate, *args) + def test_build_core_split_key(self): + """ + Test that a Pie split key object can be converted into a core key + object. + """ + pie_split_key = pobjects.SplitKey( + cryptographic_algorithm=enums.CryptographicAlgorithm.AES, + cryptographic_length=128, + key_value=self.symmetric_bytes, + cryptographic_usage_masks=[enums.CryptographicUsageMask.EXPORT], + name="Split Key", + key_format_type=enums.KeyFormatType.RAW, + key_wrapping_data=None, + split_key_parts=3, + key_part_identifier=1, + split_key_threshold=2, + split_key_method=enums.SplitKeyMethod.XOR, + prime_field_size=None + ) + core_split_key = self.factory._build_core_split_key(pie_split_key) + + self.assertIsInstance(core_split_key, secrets.SplitKey) + self._test_core_key( + core_split_key, + enums.CryptographicAlgorithm.AES, + 128, + self.symmetric_bytes, + enums.KeyFormatType.RAW + ) + self.assertEqual(3, core_split_key.split_key_parts) + self.assertEqual(1, core_split_key.key_part_identifier) + self.assertEqual(2, core_split_key.split_key_threshold) + self.assertEqual( + enums.SplitKeyMethod.XOR, + core_split_key.split_key_method + ) + self.assertIsNone(core_split_key.prime_field_size) + + def test_build_pie_split_key(self): + """ + Test that a core split key object can be converted into a Pie split + key object. + """ + key_block = cobjects.KeyBlock( + key_format_type=misc.KeyFormatType(enums.KeyFormatType.RAW), + key_compression_type=None, + key_value=cobjects.KeyValue( + cobjects.KeyMaterial(self.symmetric_bytes) + ), + cryptographic_algorithm=attributes.CryptographicAlgorithm( + enums.CryptographicAlgorithm.AES + ), + cryptographic_length=attributes.CryptographicLength(128), + key_wrapping_data=None + ) + core_split_key = secrets.SplitKey( + split_key_parts=3, + key_part_identifier=1, + split_key_threshold=2, + split_key_method=enums.SplitKeyMethod.XOR, + prime_field_size=None, + key_block=key_block + ) + pie_split_key = self.factory._build_pie_split_key(core_split_key) + + self.assertIsInstance(pie_split_key, pobjects.SplitKey) + self._test_pie_key( + pie_split_key, + enums.CryptographicAlgorithm.AES, + 128, + self.symmetric_bytes, + enums.KeyFormatType.RAW + ) + self.assertEqual(3, pie_split_key.split_key_parts) + self.assertEqual(1, pie_split_key.key_part_identifier) + self.assertEqual(2, pie_split_key.split_key_threshold) + self.assertEqual( + enums.SplitKeyMethod.XOR, + pie_split_key.split_key_method + ) + self.assertIsNone(pie_split_key.prime_field_size) + def _test_core_key(self, key, algorithm, length, value, format_type): key_block = key.key_block self.assertIsInstance(key_block, cobjects.KeyBlock) diff --git a/kmip/tests/unit/services/server/test_engine.py b/kmip/tests/unit/services/server/test_engine.py index 148b2af4..1dbc4c2f 100644 --- a/kmip/tests/unit/services/server/test_engine.py +++ b/kmip/tests/unit/services/server/test_engine.py @@ -3494,11 +3494,11 @@ def test_register_unsupported_object_type(self): e._data_session = e._data_store_session_factory() e._logger = mock.MagicMock() - object_type = enums.ObjectType.SPLIT_KEY + object_type = enums.ObjectType.TEMPLATE payload = payloads.RegisterRequestPayload(object_type=object_type) args = (payload, ) - regex = "The SplitKey object type is not supported." + regex = "The Template object type is not supported." six.assertRaisesRegex( self, exceptions.InvalidField,