diff --git a/kmip/core/objects.py b/kmip/core/objects.py index 78f616a..bb75369 100644 --- a/kmip/core/objects.py +++ b/kmip/core/objects.py @@ -1061,84 +1061,299 @@ class KeyWrappingData(Struct): pass -# 2.1.6 -class KeyWrappingSpecification(Struct): - - class AttributeName(TextString): - - def __init__(self, value=None): - super(KeyWrappingSpecification.AttributeName, self).__init__( - value, Tags.ATTRIBUTE_NAME) +class KeyWrappingSpecification(primitives.Struct): + """ + A set of values needed for key wrapping functionality. + """ def __init__(self, wrapping_method=None, encryption_key_information=None, mac_signature_key_information=None, - attribute_name=None, + attribute_names=None, encoding_option=None): + """ + Construct a KeyWrappingSpecification struct. + + Args: + wrapping_method (WrappingMethod): An enumeration value that + specifies the method to use to wrap the key value. Optional, + defaults to None. Required for encoding and decoding. + encryption_key_information (EncryptionKeyInformation): A struct + containing the unique identifier of the encryption key and + associated cryptographic parameters. Optional, defaults to + None. + mac_signature_key_information (MACSignatureKeyInformation): A + struct containing the unique identifier of the MAC/signature + key and associated cryptographic parameters. Optional, + defaults to None. + attribute_names (list): A list of strings representing the names + of attributes that should be wrapped with the key material. + Optional, defaults to None. + encoding_option (EncodingOption): An enumeration value that + specifies the encoding of the key value before it is wrapped. + Optional, defaults to None. + """ super(KeyWrappingSpecification, self).__init__( - tag=Tags.KEY_WRAPPING_SPECIFICATION) + tag=Tags.KEY_WRAPPING_SPECIFICATION + ) + + self._wrapping_method = None + self._encryption_key_information = None + self._mac_signature_key_information = None + self._attribute_names = None + self._encoding_option = None + self.wrapping_method = wrapping_method self.encryption_key_information = encryption_key_information self.mac_signature_key_information = mac_signature_key_information - self.attribute_name = attribute_name + self.attribute_names = attribute_names self.encoding_option = encoding_option - def read(self, istream): - super(KeyWrappingSpecification, self).read(istream) - tstream = BytearrayStream(istream.read(self.length)) + @property + def wrapping_method(self): + if self._wrapping_method: + return self._wrapping_method.value + else: + return None - self.wrapping_method = WrappingMethod() - self.wrapping_method.read(tstream) + @wrapping_method.setter + def wrapping_method(self, value): + if value is None: + self._wrapping_method = None + elif isinstance(value, enums.WrappingMethod): + self._wrapping_method = Enumeration( + enums.WrappingMethod, + value=value, + tag=Tags.WRAPPING_METHOD + ) + else: + raise TypeError( + "Wrapping method must be a WrappingMethod enumeration." + ) - if self.is_tag_next(Tags.ENCRYPTION_KEY_INFORMATION, tstream): - self.encryption_key_information = EncryptionKeyInformation() - self.encryption_key_information.read(tstream) + @property + def encryption_key_information(self): + return self._encryption_key_information - if self.is_tag_next(Tags.MAC_SIGNATURE_KEY_INFORMATION, tstream): - self.mac_signature_key_information = MACSignatureKeyInformation() - self.mac_signature_key_information.read(tstream) + @encryption_key_information.setter + def encryption_key_information(self, value): + if value is None: + self._encryption_key_information = None + elif isinstance(value, EncryptionKeyInformation): + self._encryption_key_information = value + else: + raise TypeError( + "Encryption key information must be an " + "EncryptionKeyInformation struct." + ) - if self.is_tag_next(Tags.ATTRIBUTE_NAME, tstream): - self.attribute_name = KeyWrappingSpecification.AttributeName() - self.attribute_name.read(tstream) + @property + def mac_signature_key_information(self): + return self._mac_signature_key_information - if self.is_tag_next(Tags.ENCODING_OPTION, tstream): - self.encoding_option = EncodingOption() - self.encoding_option.read(tstream) + @mac_signature_key_information.setter + def mac_signature_key_information(self, value): + if value is None: + self._mac_signature_key_information = None + elif isinstance(value, MACSignatureKeyInformation): + self._mac_signature_key_information = value + else: + raise TypeError( + "MAC/signature key information must be an " + "MACSignatureKeyInformation struct." + ) - self.is_oversized(tstream) - self.validate() + @property + def attribute_names(self): + if self._attribute_names: + attribute_names = [] + for i in self._attribute_names: + attribute_names.append(i.value) + return attribute_names + else: + return None - def write(self, ostream): - tstream = BytearrayStream() + @attribute_names.setter + def attribute_names(self, value): + if value is None: + self._attribute_names = None + elif isinstance(value, list): + attribute_names = [] + for i in value: + if isinstance(i, six.string_types): + attribute_names.append( + primitives.TextString( + value=i, + tag=enums.Tags.ATTRIBUTE_NAME + ) + ) + else: + raise TypeError( + "Attribute names must be a list of strings." + ) + self._attribute_names = attribute_names + else: + raise TypeError("Attribute names must be a list of strings.") - # Write the contents of the key wrapping data - self.wrapping_method.write(tstream) + @property + def encoding_option(self): + if self._encoding_option: + return self._encoding_option.value + else: + return None - if self.encryption_key_information is not None: - self.encryption_key_information.write(tstream) - if self.mac_signature_key_information is not None: - self.mac_signature_key_information.write(tstream) - if self.attribute_name is not None: - self.attribute_name.write(tstream) - if self.encoding_option is not None: - self.encoding_option.write(tstream) + @encoding_option.setter + def encoding_option(self, value): + if value is None: + self._encoding_option = None + elif isinstance(value, enums.EncodingOption): + self._encoding_option = Enumeration( + enums.EncodingOption, + value=value, + tag=Tags.ENCODING_OPTION + ) + else: + raise TypeError( + "Encoding option must be an EncodingOption enumeration." + ) - # Write the length and value of the key wrapping data - self.length = tstream.length() - super(KeyWrappingSpecification, self).write(ostream) - ostream.write(tstream.buffer) + def read(self, input_stream): + """ + Read the data encoding the KeyWrappingSpecification struct and decode + it into its constituent parts. - def validate(self): - self.__validate() + Args: + input_stream (stream): A data stream containing encoded object + data, supporting a read method; usually a BytearrayStream + object. + """ + super(KeyWrappingSpecification, self).read(input_stream) + local_stream = BytearrayStream(input_stream.read(self.length)) - def __validate(self): - # TODO (peter-hamilton) Finish implementation. - pass + if self.is_tag_next(enums.Tags.WRAPPING_METHOD, local_stream): + self._wrapping_method = primitives.Enumeration( + enum=enums.WrappingMethod, + tag=enums.Tags.WRAPPING_METHOD + ) + self._wrapping_method.read(local_stream) + else: + raise ValueError( + "Invalid struct missing the wrapping method attribute." + ) + + if self.is_tag_next( + enums.Tags.ENCRYPTION_KEY_INFORMATION, + local_stream + ): + self._encryption_key_information = EncryptionKeyInformation() + self._encryption_key_information.read(local_stream) + if self.is_tag_next( + enums.Tags.MAC_SIGNATURE_KEY_INFORMATION, + local_stream + ): + self._mac_signature_key_information = MACSignatureKeyInformation() + self._mac_signature_key_information.read(local_stream) + + attribute_names = [] + while self.is_tag_next(enums.Tags.ATTRIBUTE_NAME, local_stream): + attribute_name = primitives.TextString( + tag=enums.Tags.ATTRIBUTE_NAME + ) + attribute_name.read(local_stream) + attribute_names.append(attribute_name) + self._attribute_names = attribute_names + + if self.is_tag_next(enums.Tags.ENCODING_OPTION, local_stream): + self._encoding_option = primitives.Enumeration( + enum=enums.EncodingOption, + tag=enums.Tags.ENCODING_OPTION + ) + self._encoding_option.read(local_stream) + + self.is_oversized(local_stream) + + def write(self, output_stream): + """ + Write the data encoding the KeyWrappingSpecification struct to a + stream. + + Args: + output_stream (stream): A data stream in which to encode object + data, supporting a write method; usually a BytearrayStream + object. + """ + local_stream = BytearrayStream() + + if self._wrapping_method: + self._wrapping_method.write(local_stream) + else: + raise ValueError( + "Invalid struct missing the wrapping method attribute." + ) + + if self._encryption_key_information: + self._encryption_key_information.write(local_stream) + if self._mac_signature_key_information: + self._mac_signature_key_information.write(local_stream) + if self._attribute_names: + for unique_identifier in self._attribute_names: + unique_identifier.write(local_stream) + if self._encoding_option: + self._encoding_option.write(local_stream) + + self.length = local_stream.length() + super(KeyWrappingSpecification, self).write(output_stream) + output_stream.write(local_stream.buffer) + + def __eq__(self, other): + if isinstance(other, KeyWrappingSpecification): + if self.wrapping_method != other.wrapping_method: + return False + elif self.encryption_key_information != \ + other.encryption_key_information: + return False + elif self.mac_signature_key_information != \ + other.mac_signature_key_information: + return False + elif self.attribute_names != other.attribute_names: + return False + elif self.encoding_option != other.encoding_option: + return False + else: + return True + + def __ne__(self, other): + if isinstance(other, KeyWrappingSpecification): + return not self == other + else: + return NotImplemented + + def __repr__(self): + args = ", ".join([ + "wrapping_method={0}".format(self.wrapping_method), + "encryption_key_information={0}".format( + repr(self.encryption_key_information) + ), + "mac_signature_key_information={0}".format( + repr(self.mac_signature_key_information) + ), + "attribute_names={0}".format(self.attribute_names), + "encoding_option={0}".format(self.encoding_option) + ]) + return "KeyWrappingSpecification({0})".format(args) + + def __str__(self): + return str({ + 'wrapping_method': self.wrapping_method, + 'encryption_key_information': self.encryption_key_information, + 'mac_signature_key_information': + self.mac_signature_key_information, + 'attribute_names': self.attribute_names, + 'encoding_option': self.encoding_option + }) -# 2.1.8 class TemplateAttribute(Struct): def __init__(self, diff --git a/kmip/tests/unit/core/objects/test_objects.py b/kmip/tests/unit/core/objects/test_objects.py index 2d4886a..416689a 100644 --- a/kmip/tests/unit/core/objects/test_objects.py +++ b/kmip/tests/unit/core/objects/test_objects.py @@ -1204,3 +1204,930 @@ class TestMACSignatureKeyInformation(testtools.TestCase): observed = str(mac_signature_key_information) self.assertEqual(expected, observed) + + +class TestKeyWrappingSpecification(testtools.TestCase): + """ + Test suite for the KeyWrappingSpecification struct. + """ + + def setUp(self): + super(TestKeyWrappingSpecification, self).setUp() + + # Encoding obtained in part from the KMIP 1.1 testing document, + # Sections 14.1 and 14.2. The rest was built by hand. + # + # This encoding matches the following set of values: + # + # Wrapping Method - Encrypt + # Encryption Key Information + # Unique Identifier - 100182d5-72b8-47aa-8383-4d97d512e98a + # Cryptographic Parameters + # Block Cipher Mode - NIST_KEY_WRAP + # MAC/Signature Key Information + # Unique Identifier - 100182d5-72b8-47aa-8383-4d97d512e98a + # Cryptographic Parameters + # Block Cipher Mode - NIST_KEY_WRAP + # Attribute Names + # Cryptographic Usage Mask + # Encoding Option - NO_ENCODING + + self.full_encoding = BytearrayStream( + b'\x42\x00\x47\x01\x00\x00\x00\xE0' + b'\x42\x00\x9E\x05\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x00' + b'\x42\x00\x36\x01\x00\x00\x00\x48' + b'\x42\x00\x94\x07\x00\x00\x00\x24' + b'\x31\x30\x30\x31\x38\x32\x64\x35\x2D\x37\x32\x62\x38\x2D\x34\x37' + b'\x61\x61\x2D\x38\x33\x38\x33\x2D\x34\x64\x39\x37\x64\x35\x31\x32' + b'\x65\x39\x38\x61\x00\x00\x00\x00' + b'\x42\x00\x2B\x01\x00\x00\x00\x10' + b'\x42\x00\x11\x05\x00\x00\x00\x04\x00\x00\x00\x0D\x00\x00\x00\x00' + b'\x42\x00\x4E\x01\x00\x00\x00\x48' + b'\x42\x00\x94\x07\x00\x00\x00\x24' + b'\x31\x30\x30\x31\x38\x32\x64\x35\x2D\x37\x32\x62\x38\x2D\x34\x37' + b'\x61\x61\x2D\x38\x33\x38\x33\x2D\x34\x64\x39\x37\x64\x35\x31\x32' + b'\x65\x39\x38\x61\x00\x00\x00\x00' + b'\x42\x00\x2B\x01\x00\x00\x00\x10' + b'\x42\x00\x11\x05\x00\x00\x00\x04\x00\x00\x00\x0D\x00\x00\x00\x00' + b'\x42\x00\x0A\x07\x00\x00\x00\x18' + b'\x43\x72\x79\x70\x74\x6F\x67\x72\x61\x70\x68\x69\x63\x20\x55\x73' + b'\x61\x67\x65\x20\x4D\x61\x73\x6B' + b'\x42\x00\xA3\x05\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x00' + ) + + # Adapted from the full encoding above. This encoding matches the + # following set of values: + # + # Wrapping Method - Encrypt + # Encryption Key Information + # Unique Identifier - 100182d5-72b8-47aa-8383-4d97d512e98a + # Cryptographic Parameters + # Block Cipher Mode - NIST_KEY_WRAP + + self.partial_encoding = BytearrayStream( + b'\x42\x00\x47\x01\x00\x00\x00\x60' + b'\x42\x00\x9E\x05\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x00' + b'\x42\x00\x36\x01\x00\x00\x00\x48' + b'\x42\x00\x94\x07\x00\x00\x00\x24' + b'\x31\x30\x30\x31\x38\x32\x64\x35\x2D\x37\x32\x62\x38\x2D\x34\x37' + b'\x61\x61\x2D\x38\x33\x38\x33\x2D\x34\x64\x39\x37\x64\x35\x31\x32' + b'\x65\x39\x38\x61\x00\x00\x00\x00' + b'\x42\x00\x2B\x01\x00\x00\x00\x10' + b'\x42\x00\x11\x05\x00\x00\x00\x04\x00\x00\x00\x0D\x00\x00\x00\x00' + ) + + self.empty_encoding = BytearrayStream( + b'\x42\x00\x47\x01\x00\x00\x00\x00' + ) + + def tearDown(self): + super(TestKeyWrappingSpecification, self).tearDown() + + def test_init(self): + """ + Test that a KeyWrappingSpecification struct can be constructed with + no arguments. + """ + key_wrapping_specification = objects.KeyWrappingSpecification() + + self.assertEqual(None, key_wrapping_specification.wrapping_method) + self.assertEqual( + None, + key_wrapping_specification.encryption_key_information + ) + self.assertEqual( + None, + key_wrapping_specification.mac_signature_key_information + ) + self.assertEqual(None, key_wrapping_specification.attribute_names) + self.assertEqual(None, key_wrapping_specification.encoding_option) + + def test_init_with_args(self): + """ + Test that a KeyWrappingSpecification struct can be constructed with + valid values. + """ + encryption_key_information = objects.EncryptionKeyInformation( + unique_identifier="12345678-9012-3456-7890-123456789012", + cryptographic_parameters=attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.CTR + ) + ) + mac_signature_key_information = objects.MACSignatureKeyInformation( + unique_identifier="00000000-1111-2222-3333-444444444444", + cryptographic_parameters=attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.NIST_KEY_WRAP + ) + ) + key_wrapping_specification = objects.KeyWrappingSpecification( + wrapping_method=enums.WrappingMethod.ENCRYPT, + encryption_key_information=encryption_key_information, + mac_signature_key_information=mac_signature_key_information, + attribute_names=[ + 'Cryptographic Algorithm', + 'Cryptographic Length', + 'Cryptographic Usage Mask' + ], + encoding_option=enums.EncodingOption.TTLV_ENCODING + ) + + self.assertEqual( + enums.WrappingMethod.ENCRYPT, + key_wrapping_specification.wrapping_method + ) + self.assertIsInstance( + key_wrapping_specification.encryption_key_information, + objects.EncryptionKeyInformation + ) + e = key_wrapping_specification.encryption_key_information + self.assertEqual( + "12345678-9012-3456-7890-123456789012", + e.unique_identifier + ) + self.assertIsInstance( + e.cryptographic_parameters, + attributes.CryptographicParameters + ) + self.assertEqual( + enums.BlockCipherMode.CTR, + e.cryptographic_parameters.block_cipher_mode + ) + self.assertIsInstance( + key_wrapping_specification.mac_signature_key_information, + objects.MACSignatureKeyInformation + ) + m = key_wrapping_specification.mac_signature_key_information + self.assertEqual( + "00000000-1111-2222-3333-444444444444", + m.unique_identifier + ) + self.assertIsInstance( + m.cryptographic_parameters, + attributes.CryptographicParameters + ) + self.assertEqual( + enums.BlockCipherMode.NIST_KEY_WRAP, + m.cryptographic_parameters.block_cipher_mode + ) + self.assertIsInstance( + key_wrapping_specification.attribute_names, + list + ) + self.assertEqual(3, len(key_wrapping_specification.attribute_names)) + self.assertEqual( + 'Cryptographic Algorithm', + key_wrapping_specification.attribute_names[0] + ) + self.assertEqual( + 'Cryptographic Length', + key_wrapping_specification.attribute_names[1] + ) + self.assertEqual( + 'Cryptographic Usage Mask', + key_wrapping_specification.attribute_names[2] + ) + self.assertEqual( + enums.EncodingOption.TTLV_ENCODING, + key_wrapping_specification.encoding_option + ) + + def test_invalid_wrapping_method(self): + """ + Test that a TypeError is raised when an invalid value is used to set + the wrapping method of a KeyWrappingSpecification struct. + """ + kwargs = {'wrapping_method': 'invalid'} + self.assertRaisesRegexp( + TypeError, + "Wrapping method must be a WrappingMethod enumeration.", + objects.KeyWrappingSpecification, + **kwargs + ) + + args = (objects.KeyWrappingSpecification(), 'wrapping_method', 0) + self.assertRaisesRegexp( + TypeError, + "Wrapping method must be a WrappingMethod enumeration.", + setattr, + *args + ) + + def test_invalid_encryption_key_information(self): + """ + Test that a TypeError is raised when an invalid value is used to set + the encryption key information of a KeyWrappingSpecification struct. + """ + kwargs = {'encryption_key_information': 'invalid'} + self.assertRaisesRegexp( + TypeError, + "Encryption key information must be an EncryptionKeyInformation " + "struct.", + objects.KeyWrappingSpecification, + **kwargs + ) + + args = ( + objects.KeyWrappingSpecification(), + 'encryption_key_information', + 'invalid' + ) + self.assertRaisesRegexp( + TypeError, + "Encryption key information must be an EncryptionKeyInformation " + "struct.", + setattr, + *args + ) + + def test_invalid_mac_signature_key_information(self): + """ + Test that a TypeError is raised when an invalid value is used to set + the MAC/signature key information of a KeyWrappingSpecification + struct. + """ + kwargs = {'mac_signature_key_information': 'invalid'} + self.assertRaisesRegexp( + TypeError, + "MAC/signature key information must be an " + "MACSignatureKeyInformation struct.", + objects.KeyWrappingSpecification, + **kwargs + ) + + args = ( + objects.KeyWrappingSpecification(), + 'mac_signature_key_information', + 'invalid' + ) + self.assertRaisesRegexp( + TypeError, + "MAC/signature key information must be an " + "MACSignatureKeyInformation struct.", + setattr, + *args + ) + + def test_invalid_attribute_names(self): + """ + Test that a TypeError is raised when an invalid value is used to set + the attribute names of a KeyWrappingSpecification struct. + """ + kwargs = {'attribute_names': 'invalid'} + self.assertRaisesRegexp( + TypeError, + "Attribute names must be a list of strings.", + objects.KeyWrappingSpecification, + **kwargs + ) + + args = ( + objects.KeyWrappingSpecification(), + 'attribute_names', + ['valid', 0] + ) + self.assertRaisesRegexp( + TypeError, + "Attribute names must be a list of strings.", + setattr, + *args + ) + + def test_invalid_encoding_option(self): + """ + Test that a TypeError is raised when an invalid value is used to set + the encoding option of a KeyWrappingSpecification struct. + """ + kwargs = {'encoding_option': 'invalid'} + self.assertRaisesRegexp( + TypeError, + "Encoding option must be an EncodingOption enumeration.", + objects.KeyWrappingSpecification, + **kwargs + ) + + args = ( + objects.KeyWrappingSpecification(), + 'encoding_option', + 'invalid' + ) + self.assertRaisesRegexp( + TypeError, + "Encoding option must be an EncodingOption enumeration.", + setattr, + *args + ) + + def test_read(self): + """ + Test that a KeyWrappingSpecification struct can be read from a data + stream. + """ + key_wrapping_specification = objects.KeyWrappingSpecification() + + self.assertEqual(None, key_wrapping_specification.wrapping_method) + self.assertEqual( + None, + key_wrapping_specification.encryption_key_information + ) + self.assertEqual( + None, + key_wrapping_specification.mac_signature_key_information + ) + self.assertEqual(None, key_wrapping_specification.attribute_names) + self.assertEqual(None, key_wrapping_specification.encoding_option) + + key_wrapping_specification.read(self.full_encoding) + + self.assertEqual( + enums.WrappingMethod.ENCRYPT, + key_wrapping_specification.wrapping_method + ) + self.assertIsInstance( + key_wrapping_specification.encryption_key_information, + objects.EncryptionKeyInformation + ) + e = key_wrapping_specification.encryption_key_information + self.assertEqual( + "100182d5-72b8-47aa-8383-4d97d512e98a", + e.unique_identifier + ) + self.assertIsInstance( + e.cryptographic_parameters, + attributes.CryptographicParameters + ) + self.assertEqual( + enums.BlockCipherMode.NIST_KEY_WRAP, + e.cryptographic_parameters.block_cipher_mode + ) + self.assertIsInstance( + key_wrapping_specification.mac_signature_key_information, + objects.MACSignatureKeyInformation + ) + m = key_wrapping_specification.mac_signature_key_information + self.assertEqual( + "100182d5-72b8-47aa-8383-4d97d512e98a", + m.unique_identifier + ) + self.assertIsInstance( + m.cryptographic_parameters, + attributes.CryptographicParameters + ) + self.assertEqual( + enums.BlockCipherMode.NIST_KEY_WRAP, + m.cryptographic_parameters.block_cipher_mode + ) + self.assertIsInstance( + key_wrapping_specification.attribute_names, + list + ) + self.assertEqual( + 'Cryptographic Usage Mask', + key_wrapping_specification.attribute_names[0] + ) + self.assertEqual( + enums.EncodingOption.NO_ENCODING, + key_wrapping_specification.encoding_option + ) + + def test_read_partial(self): + """ + Test that a KeyWrappingSpecification struct can be read from a + partial data stream. + """ + key_wrapping_specification = objects.KeyWrappingSpecification() + + self.assertEqual(None, key_wrapping_specification.wrapping_method) + self.assertEqual( + None, + key_wrapping_specification.encryption_key_information + ) + self.assertEqual( + None, + key_wrapping_specification.mac_signature_key_information + ) + self.assertEqual(None, key_wrapping_specification.attribute_names) + self.assertEqual(None, key_wrapping_specification.encoding_option) + + key_wrapping_specification.read(self.partial_encoding) + + self.assertEqual( + enums.WrappingMethod.ENCRYPT, + key_wrapping_specification.wrapping_method + ) + self.assertIsInstance( + key_wrapping_specification.encryption_key_information, + objects.EncryptionKeyInformation + ) + e = key_wrapping_specification.encryption_key_information + self.assertEqual( + "100182d5-72b8-47aa-8383-4d97d512e98a", + e.unique_identifier + ) + self.assertIsInstance( + e.cryptographic_parameters, + attributes.CryptographicParameters + ) + self.assertEqual( + enums.BlockCipherMode.NIST_KEY_WRAP, + e.cryptographic_parameters.block_cipher_mode + ) + self.assertIsNone( + key_wrapping_specification.mac_signature_key_information + ) + self.assertIsNone( + key_wrapping_specification.attribute_names + ) + self.assertIsNone( + key_wrapping_specification.encoding_option + ) + + def test_read_invalid(self): + """ + Test that a ValueError gets raised when a required + MACSignatureKeyInformation field is missing from the struct encoding. + """ + key_wrapping_specification = objects.KeyWrappingSpecification() + args = (self.empty_encoding,) + self.assertRaisesRegexp( + ValueError, + "Invalid struct missing the wrapping method attribute.", + key_wrapping_specification.read, + *args + ) + + def test_write(self): + """ + Test that a KeyWrappingSpecification struct can be written to a data + stream. + """ + key_wrapping_specification = objects.KeyWrappingSpecification( + wrapping_method=enums.WrappingMethod.ENCRYPT, + encryption_key_information=objects.EncryptionKeyInformation( + unique_identifier="100182d5-72b8-47aa-8383-4d97d512e98a", + cryptographic_parameters=attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.NIST_KEY_WRAP + ) + ), + mac_signature_key_information=objects.MACSignatureKeyInformation( + unique_identifier="100182d5-72b8-47aa-8383-4d97d512e98a", + cryptographic_parameters=attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.NIST_KEY_WRAP + ) + ), + attribute_names=['Cryptographic Usage Mask'], + encoding_option=enums.EncodingOption.NO_ENCODING + ) + stream = BytearrayStream() + key_wrapping_specification.write(stream) + + self.assertEqual(len(self.full_encoding), len(stream)) + self.assertEqual(str(self.full_encoding), str(stream)) + + def test_write_partial(self): + """ + Test that a partially defined KeyWrappingSpecification struct can be + written to a data stream. + """ + key_wrapping_specification = objects.KeyWrappingSpecification( + wrapping_method=enums.WrappingMethod.ENCRYPT, + encryption_key_information=objects.EncryptionKeyInformation( + unique_identifier="100182d5-72b8-47aa-8383-4d97d512e98a", + cryptographic_parameters=attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.NIST_KEY_WRAP + ) + ) + ) + stream = BytearrayStream() + key_wrapping_specification.write(stream) + + self.assertEqual(len(self.partial_encoding), len(stream)) + self.assertEqual(str(self.partial_encoding), str(stream)) + + def test_write_invalid(self): + """ + Test that a ValueError gets raised when a required + KeyWrappingSpecification field is missing when encoding the struct. + """ + key_wrapping_specification = objects.KeyWrappingSpecification() + stream = utils.BytearrayStream() + args = (stream,) + self.assertRaisesRegexp( + ValueError, + "Invalid struct missing the wrapping method attribute.", + key_wrapping_specification.write, + *args + ) + + def test_equal_on_equal(self): + """ + Test that the equality operator returns True when comparing two + KeyWrappingSpecification structs with the same data. + """ + a = objects.KeyWrappingSpecification() + b = objects.KeyWrappingSpecification() + + self.assertTrue(a == b) + self.assertTrue(b == a) + + a = objects.KeyWrappingSpecification( + wrapping_method=enums.WrappingMethod.ENCRYPT, + encryption_key_information=objects.EncryptionKeyInformation( + unique_identifier="100182d5-72b8-47aa-8383-4d97d512e98a", + cryptographic_parameters=attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.NIST_KEY_WRAP + ) + ), + attribute_names=['Cryptographic Usage Mask'], + encoding_option=enums.EncodingOption.NO_ENCODING + ) + b = objects.KeyWrappingSpecification( + wrapping_method=enums.WrappingMethod.ENCRYPT, + encryption_key_information=objects.EncryptionKeyInformation( + unique_identifier="100182d5-72b8-47aa-8383-4d97d512e98a", + cryptographic_parameters=attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.NIST_KEY_WRAP + ) + ), + attribute_names=['Cryptographic Usage Mask'], + encoding_option=enums.EncodingOption.NO_ENCODING + ) + + self.assertTrue(a == b) + self.assertTrue(b == a) + + def test_equal_on_not_equal_wrapping_method(self): + """ + Test that the equality operator returns False when comparing two + KeyWrappingSpecification structs with different wrapping methods. + """ + a = objects.KeyWrappingSpecification( + wrapping_method=enums.WrappingMethod.ENCRYPT + ) + b = objects.KeyWrappingSpecification( + wrapping_method=enums.WrappingMethod.MAC_SIGN + ) + + self.assertFalse(a == b) + self.assertFalse(b == a) + + def test_equal_on_not_equal_encryption_key_information(self): + """ + Test that the equality operator returns False when comparing two + KeyWrappingSpecification structs with different encryption key + information. + """ + a = objects.KeyWrappingSpecification( + encryption_key_information=objects.EncryptionKeyInformation( + unique_identifier="100182d5-72b8-ffff-8383-4d97d512e98a", + cryptographic_parameters=attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.CBC + ) + ) + ) + b = objects.KeyWrappingSpecification( + encryption_key_information=objects.EncryptionKeyInformation( + unique_identifier="100182d5-72b8-47aa-8383-4d97d512e98a", + cryptographic_parameters=attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.NIST_KEY_WRAP + ) + ) + ) + + self.assertFalse(a == b) + self.assertFalse(b == a) + + def test_equal_on_not_equal_mac_signature_key_information(self): + """ + Test that the equality operator returns False when comparing two + KeyWrappingSpecification structs with different MAC/signature key + information. + """ + a = objects.KeyWrappingSpecification( + mac_signature_key_information=objects.MACSignatureKeyInformation( + unique_identifier="100182d5-72b8-47aa-8383-4d97d512e98a", + cryptographic_parameters=attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.NIST_KEY_WRAP + ) + ) + ) + b = objects.KeyWrappingSpecification( + mac_signature_key_information=objects.MACSignatureKeyInformation( + unique_identifier="100182d5-72b8-ffff-8383-4d97d512e98a", + cryptographic_parameters=attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.CBC + ) + ) + ) + + self.assertFalse(a == b) + self.assertFalse(b == a) + + def test_equal_on_not_equal_attribute_names(self): + """ + Test that the equality operator returns False when comparing two + KeyWrappingSpecification structs with different attribute names. + """ + a = objects.KeyWrappingSpecification( + attribute_names=[ + 'Cryptographic Algorithm', + 'Cryptographic Length' + ] + ) + b = objects.KeyWrappingSpecification( + attribute_names=['Cryptographic Usage Mask'] + ) + + self.assertFalse(a == b) + self.assertFalse(b == a) + + def test_equal_on_not_equal_encoding_option(self): + """ + Test that the equality operator returns False when comparing two + KeyWrappingSpecification structs with different encoding options. + """ + a = objects.KeyWrappingSpecification( + encoding_option=enums.EncodingOption.NO_ENCODING + ) + b = objects.KeyWrappingSpecification( + encoding_option=enums.EncodingOption.TTLV_ENCODING + ) + + self.assertFalse(a == b) + self.assertFalse(b == a) + + def test_equal_on_type_mismatch(self): + """ + Test that the equality operator returns False when comparing two + KeyWrappingSpecification structs with different types. + """ + a = objects.KeyWrappingSpecification() + b = 'invalid' + + self.assertFalse(a == b) + self.assertFalse(b == a) + + def test_not_equal_on_equal(self): + """ + Test that the inequality operator returns False when comparing two + KeyWrappingSpecification structs with the same data. + """ + a = objects.KeyWrappingSpecification() + b = objects.KeyWrappingSpecification() + + self.assertFalse(a != b) + self.assertFalse(b != a) + + a = objects.KeyWrappingSpecification( + wrapping_method=enums.WrappingMethod.ENCRYPT, + encryption_key_information=objects.EncryptionKeyInformation( + unique_identifier="100182d5-72b8-47aa-8383-4d97d512e98a", + cryptographic_parameters=attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.NIST_KEY_WRAP + ) + ), + attribute_names=['Cryptographic Usage Mask'], + encoding_option=enums.EncodingOption.NO_ENCODING + ) + b = objects.KeyWrappingSpecification( + wrapping_method=enums.WrappingMethod.ENCRYPT, + encryption_key_information=objects.EncryptionKeyInformation( + unique_identifier="100182d5-72b8-47aa-8383-4d97d512e98a", + cryptographic_parameters=attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.NIST_KEY_WRAP + ) + ), + attribute_names=['Cryptographic Usage Mask'], + encoding_option=enums.EncodingOption.NO_ENCODING + ) + + self.assertFalse(a != b) + self.assertFalse(b != a) + + def test_not_equal_on_not_equal_wrapping_method(self): + """ + Test that the inequality operator returns True when comparing two + KeyWrappingSpecification structs with different wrapping methods. + """ + a = objects.KeyWrappingSpecification( + wrapping_method=enums.WrappingMethod.ENCRYPT + ) + b = objects.KeyWrappingSpecification( + wrapping_method=enums.WrappingMethod.MAC_SIGN + ) + + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_not_equal_on_not_equal_encryption_key_information(self): + """ + Test that the inequality operator returns True when comparing two + KeyWrappingSpecification structs with different encryption key + information. + """ + a = objects.KeyWrappingSpecification( + encryption_key_information=objects.EncryptionKeyInformation( + unique_identifier="100182d5-72b8-ffff-8383-4d97d512e98a", + cryptographic_parameters=attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.CBC + ) + ) + ) + b = objects.KeyWrappingSpecification( + encryption_key_information=objects.EncryptionKeyInformation( + unique_identifier="100182d5-72b8-47aa-8383-4d97d512e98a", + cryptographic_parameters=attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.NIST_KEY_WRAP + ) + ) + ) + + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_not_equal_on_not_equal_mac_signature_key_information(self): + """ + Test that the inequality operator returns True when comparing two + KeyWrappingSpecification structs with different MAC/signature key + information. + """ + a = objects.KeyWrappingSpecification( + mac_signature_key_information=objects.MACSignatureKeyInformation( + unique_identifier="100182d5-72b8-47aa-8383-4d97d512e98a", + cryptographic_parameters=attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.NIST_KEY_WRAP + ) + ) + ) + b = objects.KeyWrappingSpecification( + mac_signature_key_information=objects.MACSignatureKeyInformation( + unique_identifier="100182d5-72b8-ffff-8383-4d97d512e98a", + cryptographic_parameters=attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.CBC + ) + ) + ) + + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_not_equal_on_not_equal_attribute_names(self): + """ + Test that the inequality operator returns True when comparing two + KeyWrappingSpecification structs with different attribute names. + """ + a = objects.KeyWrappingSpecification( + attribute_names=[ + 'Cryptographic Algorithm', + 'Cryptographic Length' + ] + ) + b = objects.KeyWrappingSpecification( + attribute_names=['Cryptographic Usage Mask'] + ) + + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_not_equal_on_not_equal_encoding_option(self): + """ + Test that the inequality operator returns True when comparing two + KeyWrappingSpecification structs with different encoding options. + """ + a = objects.KeyWrappingSpecification( + encoding_option=enums.EncodingOption.NO_ENCODING + ) + b = objects.KeyWrappingSpecification( + encoding_option=enums.EncodingOption.TTLV_ENCODING + ) + + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_not_equal_on_type_mismatch(self): + """ + Test that the inequality operator returns True when comparing two + KeyWrappingSpecification structs with different types. + """ + a = objects.KeyWrappingSpecification() + b = 'invalid' + + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_repr(self): + """ + Test that repr can be applied to an KeyWrappingSpecification struct. + """ + key_wrapping_specification = objects.KeyWrappingSpecification( + wrapping_method=enums.WrappingMethod.ENCRYPT, + encryption_key_information=objects.EncryptionKeyInformation( + unique_identifier="100182d5-72b8-ffff-8383-4d97d512e98a", + cryptographic_parameters=attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.NIST_KEY_WRAP + ) + ), + mac_signature_key_information=objects.MACSignatureKeyInformation( + unique_identifier="100182d5-72b8-47aa-8383-4d97d512e98a", + cryptographic_parameters=attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.CBC + ) + ), + attribute_names=[ + 'Cryptographic Algorithm', + 'Cryptographic Length' + ], + encoding_option=enums.EncodingOption.TTLV_ENCODING + ) + + expected = ( + "KeyWrappingSpecification(" + "wrapping_method=WrappingMethod.ENCRYPT, " + "encryption_key_information=EncryptionKeyInformation(" + "unique_identifier='100182d5-72b8-ffff-8383-4d97d512e98a', " + "cryptographic_parameters=CryptographicParameters(" + "block_cipher_mode=BlockCipherMode.NIST_KEY_WRAP, " + "padding_method=None, " + "hashing_algorithm=None, " + "key_role_type=None, " + "digital_signature_algorithm=None, " + "cryptographic_algorithm=None, " + "random_iv=None, " + "iv_length=None, " + "tag_length=None, " + "fixed_field_length=None, " + "invocation_field_length=None, " + "counter_length=None, " + "initial_counter_value=None)), " + "mac_signature_key_information=MACSignatureKeyInformation(" + "unique_identifier='100182d5-72b8-47aa-8383-4d97d512e98a', " + "cryptographic_parameters=CryptographicParameters(" + "block_cipher_mode=BlockCipherMode.CBC, " + "padding_method=None, " + "hashing_algorithm=None, " + "key_role_type=None, " + "digital_signature_algorithm=None, " + "cryptographic_algorithm=None, " + "random_iv=None, " + "iv_length=None, " + "tag_length=None, " + "fixed_field_length=None, " + "invocation_field_length=None, " + "counter_length=None, " + "initial_counter_value=None)), " + "attribute_names=[" + "'Cryptographic Algorithm', 'Cryptographic Length'], " + "encoding_option=EncodingOption.TTLV_ENCODING)" + ) + observed = repr(key_wrapping_specification) + + self.assertEqual(expected, observed) + + def test_str(self): + """ + Test that str can be applied to a KeyWrappingSpecification struct. + """ + key_wrapping_specification = objects.KeyWrappingSpecification( + wrapping_method=enums.WrappingMethod.ENCRYPT, + encryption_key_information=objects.EncryptionKeyInformation( + unique_identifier="100182d5-72b8-ffff-8383-4d97d512e98a", + cryptographic_parameters=attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.NIST_KEY_WRAP + ) + ), + mac_signature_key_information=objects.MACSignatureKeyInformation( + unique_identifier="100182d5-72b8-47aa-8383-4d97d512e98a", + cryptographic_parameters=attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.CBC + ) + ), + attribute_names=[ + 'Cryptographic Algorithm', + 'Cryptographic Length' + ], + encoding_option=enums.EncodingOption.TTLV_ENCODING + ) + + expected = str({ + 'wrapping_method': enums.WrappingMethod.ENCRYPT, + 'encryption_key_information': objects.EncryptionKeyInformation( + unique_identifier="100182d5-72b8-ffff-8383-4d97d512e98a", + cryptographic_parameters=attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.NIST_KEY_WRAP + ) + ), + 'mac_signature_key_information': + objects.MACSignatureKeyInformation( + unique_identifier="100182d5-72b8-47aa-8383-4d97d512e98a", + cryptographic_parameters=attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.CBC + ) + ), + 'attribute_names': [ + 'Cryptographic Algorithm', + 'Cryptographic Length' + ], + 'encoding_option': enums.EncodingOption.TTLV_ENCODING + }) + observed = str(key_wrapping_specification) + + self.assertEqual(expected, observed)