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
This commit is contained in:
Peter Hamilton 2019-09-20 10:38:16 -04:00 committed by Peter Hamilton
parent 84ab77cd8d
commit a8713fc909
4 changed files with 214 additions and 3 deletions

View File

@ -68,6 +68,10 @@ class ObjectFactory:
return self._build_core_opaque_object(obj) return self._build_core_opaque_object(obj)
elif isinstance(obj, secrets.OpaqueObject): elif isinstance(obj, secrets.OpaqueObject):
return self._build_pie_opaque_object(obj) 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: else:
raise TypeError("object type unsupported and cannot be converted") raise TypeError("object type unsupported and cannot be converted")
@ -125,6 +129,23 @@ class ObjectFactory:
value = obj.opaque_data_value.value value = obj.opaque_data_value.value
return pobjects.OpaqueObject(value, opaque_type) 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): def _build_core_key(self, key, cls):
algorithm = key.cryptographic_algorithm algorithm = key.cryptographic_algorithm
length = key.cryptographic_length length = key.cryptographic_length
@ -170,6 +191,32 @@ class ObjectFactory:
return secrets.SecretData(data_type, key_block) 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): def _build_core_opaque_object(self, obj):
opaque_type = obj.opaque_type opaque_type = obj.opaque_type
value = obj.value value = obj.value

View File

@ -123,7 +123,7 @@ class KmipEngine(object):
enums.ObjectType.SYMMETRIC_KEY: objects.SymmetricKey, enums.ObjectType.SYMMETRIC_KEY: objects.SymmetricKey,
enums.ObjectType.PUBLIC_KEY: objects.PublicKey, enums.ObjectType.PUBLIC_KEY: objects.PublicKey,
enums.ObjectType.PRIVATE_KEY: objects.PrivateKey, enums.ObjectType.PRIVATE_KEY: objects.PrivateKey,
enums.ObjectType.SPLIT_KEY: None, enums.ObjectType.SPLIT_KEY: objects.SplitKey,
enums.ObjectType.TEMPLATE: None, enums.ObjectType.TEMPLATE: None,
enums.ObjectType.SECRET_DATA: objects.SecretData, enums.ObjectType.SECRET_DATA: objects.SecretData,
enums.ObjectType.OPAQUE_DATA: objects.OpaqueObject enums.ObjectType.OPAQUE_DATA: objects.OpaqueObject

View File

@ -430,6 +430,88 @@ class TestObjectFactory(testtools.TestCase):
self.assertEqual(enums.OpaqueDataType.NONE, pie_obj.opaque_type) self.assertEqual(enums.OpaqueDataType.NONE, pie_obj.opaque_type)
self.assertEqual(self.opaque_bytes, pie_obj.value) 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): def test_build_pie_symmetric_key(self):
""" """
Test that a core SymmetricKey object can be converted into a Pie Test that a core SymmetricKey object can be converted into a Pie
@ -531,6 +613,88 @@ class TestObjectFactory(testtools.TestCase):
self.assertRaises( self.assertRaises(
TypeError, self.factory._build_pie_certificate, *args) 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): def _test_core_key(self, key, algorithm, length, value, format_type):
key_block = key.key_block key_block = key.key_block
self.assertIsInstance(key_block, cobjects.KeyBlock) self.assertIsInstance(key_block, cobjects.KeyBlock)

View File

@ -3494,11 +3494,11 @@ class TestKmipEngine(testtools.TestCase):
e._data_session = e._data_store_session_factory() e._data_session = e._data_store_session_factory()
e._logger = mock.MagicMock() e._logger = mock.MagicMock()
object_type = enums.ObjectType.SPLIT_KEY object_type = enums.ObjectType.TEMPLATE
payload = payloads.RegisterRequestPayload(object_type=object_type) payload = payloads.RegisterRequestPayload(object_type=object_type)
args = (payload, ) args = (payload, )
regex = "The SplitKey object type is not supported." regex = "The Template object type is not supported."
six.assertRaisesRegex( six.assertRaisesRegex(
self, self,
exceptions.InvalidField, exceptions.InvalidField,