From a8713fc9093f03ba5e018dd4b36eba808773b61a 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 49e43be..3752a0a 100644 --- a/kmip/pie/factory.py +++ b/kmip/pie/factory.py @@ -68,6 +68,10 @@ class ObjectFactory: 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 @@ class ObjectFactory: 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 @@ class ObjectFactory: 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 22607f4..dd7b99d 100644 --- a/kmip/services/server/engine.py +++ b/kmip/services/server/engine.py @@ -123,7 +123,7 @@ class KmipEngine(object): 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 0276433..c52360f 100644 --- a/kmip/tests/unit/pie/test_factory.py +++ b/kmip/tests/unit/pie/test_factory.py @@ -430,6 +430,88 @@ class TestObjectFactory(testtools.TestCase): 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 @@ class TestObjectFactory(testtools.TestCase): 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 148b2af..1dbc4c2 100644 --- a/kmip/tests/unit/services/server/test_engine.py +++ b/kmip/tests/unit/services/server/test_engine.py @@ -3494,11 +3494,11 @@ class TestKmipEngine(testtools.TestCase): 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,