diff --git a/kmip/core/objects.py b/kmip/core/objects.py index b29c110..614f35e 100644 --- a/kmip/core/objects.py +++ b/kmip/core/objects.py @@ -172,6 +172,172 @@ class Attribute(Struct): return NotImplemented +class Nonce(primitives.Struct): + """ + A struct representing a Nonce object. + + Attributes: + nonce_id (bytes): A binary string representing the ID of the nonce + value. + nonce_value (bytes): A binary string representing a random value. + """ + + def __init__(self, nonce_id=None, nonce_value=None): + """ + Construct a Nonce struct. + + Args: + nonce_id (bytes): A binary string representing the ID of the nonce + value. Optional, defaults to None. Required for encoding and + decoding. + nonce_value (bytes): A binary string representing a random value. + Optional, defaults to None. Required for encoding and decoding. + """ + super(Nonce, self).__init__(tag=enums.Tags.NONCE) + + self._nonce_id = None + self._nonce_value = None + + self.nonce_id = nonce_id + self.nonce_value = nonce_value + + @property + def nonce_id(self): + if self._nonce_id: + return self._nonce_id.value + else: + return None + + @nonce_id.setter + def nonce_id(self, value): + if value is None: + self._nonce_id = None + elif isinstance(value, six.binary_type): + self._nonce_id = primitives.ByteString( + value=value, + tag=enums.Tags.NONCE_ID + ) + else: + raise TypeError("Nonce ID must be bytes.") + + @property + def nonce_value(self): + if self._nonce_value: + return self._nonce_value.value + else: + return None + + @nonce_value.setter + def nonce_value(self, value): + if value is None: + self._nonce_value = None + elif isinstance(value, six.binary_type): + self._nonce_value = primitives.ByteString( + value=value, + tag=enums.Tags.NONCE_VALUE + ) + else: + raise TypeError("Nonce value must be bytes.") + + def read(self, input_stream): + """ + Read the data encoding the Nonce struct and decode it into its + constituent parts. + + Args: + input_stream (stream): A data stream containing encoded object + data, supporting a read method; usually a BytearrayStream + object. + + Raises: + ValueError: Raised if the nonce ID or nonce value is missing from + the encoding. + """ + super(Nonce, self).read(input_stream) + local_stream = BytearrayStream(input_stream.read(self.length)) + + if self.is_tag_next(enums.Tags.NONCE_ID, local_stream): + self._nonce_id = primitives.ByteString( + tag=enums.Tags.NONCE_ID + ) + self._nonce_id.read(local_stream) + else: + raise ValueError( + "Nonce encoding missing the nonce ID." + ) + + if self.is_tag_next(enums.Tags.NONCE_VALUE, local_stream): + self._nonce_value = primitives.ByteString( + tag=enums.Tags.NONCE_VALUE + ) + self._nonce_value.read(local_stream) + else: + raise ValueError( + "Nonce encoding missing the nonce value." + ) + + self.is_oversized(local_stream) + + def write(self, output_stream): + """ + Write the data encoding the Nonce 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. + + Raises: + ValueError: Raised if the nonce ID or nonce value is not defined. + """ + local_stream = BytearrayStream() + + if self._nonce_id: + self._nonce_id.write(local_stream) + else: + raise ValueError("Nonce struct is missing the nonce ID.") + + if self._nonce_value: + self._nonce_value.write(local_stream) + else: + raise ValueError("Nonce struct is missing the nonce value.") + + self.length = local_stream.length() + super(Nonce, self).write(output_stream) + output_stream.write(local_stream.buffer) + + def __eq__(self, other): + if isinstance(other, Nonce): + if self.nonce_id != other.nonce_id: + return False + elif self.nonce_value != other.nonce_value: + return False + else: + return True + else: + return NotImplemented + + def __ne__(self, other): + if isinstance(other, Nonce): + return not (self == other) + else: + return NotImplemented + + def __repr__(self): + args = ", ".join([ + "nonce_id={}".format(self.nonce_id), + "nonce_value={}".format(self.nonce_value) + ]) + return "Nonce({})".format(args) + + def __str__(self): + body = ", ".join([ + "'nonce_id': {}".format(self.nonce_id), + "'nonce_value': {}".format(self.nonce_value) + ]) + return "{" + body + "}" + + @six.add_metaclass(abc.ABCMeta) class CredentialValue(primitives.Struct): """ @@ -634,6 +800,274 @@ class DeviceCredential(CredentialValue): }) +class AttestationCredential(CredentialValue): + """ + A struct representing an AttestationCredential object. + + Attributes: + nonce: A nonce value obtained from the key management server. + attestation_type: The type of attestation being used. + attestation_measurement: The attestation measurement of the client. + attestation_assertion: The attestation assertion from a third party. + """ + + def __init__(self, + nonce=None, + attestation_type=None, + attestation_measurement=None, + attestation_assertion=None): + """ + Construct an AttestationCredential struct. + + Args: + nonce (Nonce): A Nonce structure containing nonce data obtained + from the key management server. Optional, defaults to None. + Required for encoding and decoding. + attestation_type (enum): An AttestationType enumeration specifying + the type of attestation being used. Optional, defaults to None. + Required for encoding and decoding. + attestation_measurement (bytes): The device identifier for the + credential. Optional, defaults to None. Required for encoding + and decoding if the attestation assertion is not provided. + attestation_assertion (bytes): The network identifier for the + credential. Optional, defaults to None. Required for encoding + and decoding if the attestation measurement is not provided. + """ + super(AttestationCredential, self).__init__(tag=Tags.CREDENTIAL_VALUE) + + self._nonce = None + self._attestation_type = None + self._attestation_measurement = None + self._attestation_assertion = None + + self.nonce = nonce + self.attestation_type = attestation_type + self.attestation_measurement = attestation_measurement + self.attestation_assertion = attestation_assertion + + @property + def nonce(self): + return self._nonce + + @nonce.setter + def nonce(self, value): + if value is None: + self._nonce = None + elif isinstance(value, Nonce): + self._nonce = value + else: + raise TypeError("Nonce must be a Nonce struct.") + + @property + def attestation_type(self): + if self._attestation_type: + return self._attestation_type.value + else: + return None + + @attestation_type.setter + def attestation_type(self, value): + if value is None: + self._attestation_type = None + elif isinstance(value, enums.AttestationType): + self._attestation_type = Enumeration( + enums.AttestationType, + value=value, + tag=Tags.ATTESTATION_TYPE + ) + else: + raise TypeError( + "Attestation type must be an AttestationType enumeration." + ) + + @property + def attestation_measurement(self): + if self._attestation_measurement: + return self._attestation_measurement.value + else: + return None + + @attestation_measurement.setter + def attestation_measurement(self, value): + if value is None: + self._attestation_measurement = None + elif isinstance(value, six.binary_type): + self._attestation_measurement = primitives.ByteString( + value=value, + tag=enums.Tags.ATTESTATION_MEASUREMENT + ) + else: + raise TypeError("Attestation measurement must be bytes.") + + @property + def attestation_assertion(self): + if self._attestation_assertion: + return self._attestation_assertion.value + else: + return None + + @attestation_assertion.setter + def attestation_assertion(self, value): + if value is None: + self._attestation_assertion = None + elif isinstance(value, six.binary_type): + self._attestation_assertion = primitives.ByteString( + value=value, + tag=enums.Tags.ATTESTATION_ASSERTION + ) + else: + raise TypeError("Attestation assertion must be bytes.") + + def read(self, input_stream): + """ + Read the data encoding the AttestationCredential struct and decode it + into its constituent parts. + + Args: + input_stream (stream): A data stream containing encoded object + data, supporting a read method; usually a BytearrayStream + object. + + Raises: + ValueError: Raised if either the nonce or attestation type are + missing from the encoding. Also raised if neither the + attestation measurement nor the attestation assertion are + included in the encoding. + + """ + super(AttestationCredential, self).read(input_stream) + local_stream = BytearrayStream(input_stream.read(self.length)) + + if self.is_tag_next(enums.Tags.NONCE, local_stream): + self._nonce = Nonce() + self._nonce.read(local_stream) + else: + raise ValueError( + "Attestation credential encoding is missing the nonce." + ) + + if self.is_tag_next(enums.Tags.ATTESTATION_TYPE, local_stream): + self._attestation_type = primitives.Enumeration( + enums.AttestationType, + tag=enums.Tags.ATTESTATION_TYPE + ) + self._attestation_type.read(local_stream) + else: + raise ValueError( + "Attestation credential encoding is missing the attestation " + "type." + ) + + self._attestation_measurement = None + if self.is_tag_next(enums.Tags.ATTESTATION_MEASUREMENT, local_stream): + self._attestation_measurement = primitives.ByteString( + tag=enums.Tags.ATTESTATION_MEASUREMENT + ) + self._attestation_measurement.read(local_stream) + + self._attestation_assertion = None + if self.is_tag_next(enums.Tags.ATTESTATION_ASSERTION, local_stream): + self._attestation_assertion = primitives.ByteString( + tag=enums.Tags.ATTESTATION_ASSERTION + ) + self._attestation_assertion.read(local_stream) + + if ((self._attestation_measurement is None) and + (self._attestation_assertion is None)): + raise ValueError( + "Attestation credential encoding is missing either the " + "attestation measurement or the attestation assertion." + ) + + self.is_oversized(local_stream) + + def write(self, output_stream): + """ + Write the data encoding the AttestationCredential 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. + + Raises: + ValueError: Raised if either the nonce or attestation type are + not defined. Also raised if neither the attestation measurement + nor the attestation assertion are defined. + """ + local_stream = BytearrayStream() + + if self._nonce: + self._nonce.write(local_stream) + else: + raise ValueError( + "Attestation credential struct is missing the nonce." + ) + + if self._attestation_type: + self._attestation_type.write(local_stream) + else: + raise ValueError( + "Attestation credential struct is missing the attestation " + "type." + ) + + if self._attestation_measurement: + self._attestation_measurement.write(local_stream) + if self._attestation_assertion: + self._attestation_assertion.write(local_stream) + + if ((self._attestation_measurement is None) and + (self._attestation_assertion is None)): + raise ValueError( + "Attestation credential struct is missing either the " + "attestation measurement or the attestation assertion." + ) + + self.length = local_stream.length() + super(AttestationCredential, self).write(output_stream) + output_stream.write(local_stream.buffer) + + def __eq__(self, other): + if isinstance(other, AttestationCredential): + if self.nonce != other.nonce: + return False + elif self.attestation_type != other.attestation_type: + return False + elif self.attestation_measurement != other.attestation_measurement: + return False + elif self.attestation_assertion != other.attestation_assertion: + return False + else: + return True + else: + return NotImplemented + + def __ne__(self, other): + if isinstance(other, AttestationCredential): + return not (self == other) + else: + return NotImplemented + + def __repr__(self): + args = ", ".join([ + "nonce={}".format(repr(self.nonce)), + "attestation_type={}".format(self.attestation_type), + "attestation_measurement={}".format(self.attestation_measurement), + "attestation_assertion={}".format(self.attestation_assertion) + ]) + return "AttestationCredential({})".format(args) + + def __str__(self): + return "{" \ + "'nonce': " + str(self.nonce) + ", " \ + "'attestation_type': " + str(self.attestation_type) + ", " \ + "'attestation_measurement': " + \ + str(self.attestation_measurement) + ", " \ + "'attestation_assertion': " + \ + str(self.attestation_assertion) + "}" + + class Credential(primitives.Struct): """ A struct representing a Credential object. @@ -734,8 +1168,9 @@ class Credential(primitives.Struct): self._credential_value = UsernamePasswordCredential() elif self.credential_type == enums.CredentialType.DEVICE: self._credential_value = DeviceCredential() + elif self.credential_type == enums.CredentialType.ATTESTATION: + self._credential_value = AttestationCredential() else: - # TODO (peter-hamilton) Add case for Attestation. raise ValueError( "Credential encoding includes unrecognized credential " "type." diff --git a/kmip/tests/unit/core/objects/test_credentials.py b/kmip/tests/unit/core/objects/test_credentials.py index 09561e0..e20f797 100644 --- a/kmip/tests/unit/core/objects/test_credentials.py +++ b/kmip/tests/unit/core/objects/test_credentials.py @@ -13,6 +13,8 @@ # License for the specific language governing permissions and limitations # under the License. +import enum +import mock import testtools from kmip import enums @@ -20,6 +22,382 @@ from kmip.core import objects from kmip.core import utils +class TestNonce(testtools.TestCase): + """ + Test suite for the Nonce struct. + """ + + def setUp(self): + super(TestNonce, self).setUp() + + # There are no Nonce encodings available in any of the KMIP testing + # documents. The following encodings were adapted from other structure + # encodings present in the KMIP testing suite. + # + # This encoding matches the following set of values: + # Nonce + # Nonce ID - 1 + # Nonce Value - 0x0001020304050607 + self.full_encoding = utils.BytearrayStream( + b'\x42\x00\xC8\x01\x00\x00\x00\x20' + b'\x42\x00\xC9\x08\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00' + b'\x42\x00\xCA\x08\x00\x00\x00\x08\x00\x01\x02\x03\x04\x05\x06\x07' + ) + self.encoding_missing_nonce_id = utils.BytearrayStream( + b'\x42\x00\xC8\x01\x00\x00\x00\x10' + b'\x42\x00\xCA\x08\x00\x00\x00\x08\x00\x01\x02\x03\x04\x05\x06\x07' + ) + self.encoding_missing_nonce_value = utils.BytearrayStream( + b'\x42\x00\xC8\x01\x00\x00\x00\x10' + b'\x42\x00\xC9\x08\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00' + ) + + def tearDown(self): + super(TestNonce, self).tearDown() + + def test_init(self): + """ + Test that a Nonce struct can be constructed without arguments. + """ + nonce = objects.Nonce() + + self.assertEqual(None, nonce.nonce_id) + self.assertEqual(None, nonce.nonce_value) + + def test_init_with_args(self): + """ + Test that a Nonce struct can be constructed with arguments. + """ + nonce = objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x00\x01\x02\x03\x04\x05\x06\x07' + ) + + self.assertEqual(b'\x01', nonce.nonce_id) + self.assertEqual( + b'\x00\x01\x02\x03\x04\x05\x06\x07', + nonce.nonce_value + ) + + def test_invalid_nonce_id(self): + """ + Test that a TypeError is raised when an invalid value is used to set + the nonce ID of a Nonce struct. + """ + kwargs = {'nonce_id': 0} + self.assertRaisesRegexp( + TypeError, + "Nonce ID must be bytes.", + objects.Nonce, + **kwargs + ) + + nonce = objects.Nonce() + args = (nonce, "nonce_id", 0) + self.assertRaisesRegexp( + TypeError, + "Nonce ID must be bytes.", + setattr, + *args + ) + + def test_invalid_nonce_value(self): + """ + Test that a TypeError is raised when an invalid value is used to set + the nonce value of a Nonce struct. + """ + kwargs = {'nonce_value': 0} + self.assertRaisesRegexp( + TypeError, + "Nonce value must be bytes.", + objects.Nonce, + **kwargs + ) + + nonce = objects.Nonce() + args = (nonce, "nonce_value", 0) + self.assertRaisesRegexp( + TypeError, + "Nonce value must be bytes.", + setattr, + *args + ) + + def test_read(self): + """ + Test that a Nonce struct can be read from a data stream. + """ + nonce = objects.Nonce() + + self.assertEqual(None, nonce.nonce_id) + self.assertEqual(None, nonce.nonce_value) + + nonce.read(self.full_encoding) + + self.assertEqual(b'\x01', nonce.nonce_id) + self.assertEqual( + b'\x00\x01\x02\x03\x04\x05\x06\x07', + nonce.nonce_value + ) + + def test_read_missing_nonce_id(self): + """ + Test that a ValueError gets raised when attempting to read a + Nonce struct from a data stream missing the nonce ID data. + """ + nonce = objects.Nonce() + + self.assertEqual(None, nonce.nonce_id) + self.assertEqual(None, nonce.nonce_value) + + args = (self.encoding_missing_nonce_id, ) + self.assertRaisesRegexp( + ValueError, + "Nonce encoding missing the nonce ID.", + nonce.read, + *args + ) + + def test_read_missing_nonce_value(self): + """ + Test that a ValueError gets raised when attempting to read a + Nonce struct from a data stream missing the nonce value data. + """ + nonce = objects.Nonce() + + self.assertEqual(None, nonce.nonce_id) + self.assertEqual(None, nonce.nonce_value) + + args = (self.encoding_missing_nonce_value, ) + self.assertRaisesRegexp( + ValueError, + "Nonce encoding missing the nonce value.", + nonce.read, + *args + ) + + def test_write(self): + """ + Test that a Nonce struct can be written to a data stream. + """ + nonce = objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x00\x01\x02\x03\x04\x05\x06\x07' + ) + stream = utils.BytearrayStream() + + nonce.write(stream) + + self.assertEqual(len(self.full_encoding), len(stream)) + self.assertEqual(str(self.full_encoding), str(stream)) + + def test_write_missing_nonce_id(self): + """ + Test that a ValueError gets raised when attempting to write a + Nonce struct missing nonce ID data to a data stream. + """ + nonce = objects.Nonce( + nonce_value=b'\x00\x01\x02\x03\x04\x05\x06\x07' + ) + stream = utils.BytearrayStream() + + args = (stream, ) + self.assertRaisesRegexp( + ValueError, + "Nonce struct is missing the nonce ID.", + nonce.write, + *args + ) + + def test_write_missing_nonce_value(self): + """ + Test that a ValueError gets raised when attempting to write a + Nonce struct missing nonce value data to a data stream. + """ + nonce = objects.Nonce( + nonce_id=b'\x01' + ) + stream = utils.BytearrayStream() + + args = (stream, ) + self.assertRaisesRegexp( + ValueError, + "Nonce struct is missing the nonce value.", + nonce.write, + *args + ) + + def test_equal_on_equal(self): + """ + Test that the equality operator returns True when comparing two + Nonce structs with the same data. + """ + a = objects.Nonce() + b = objects.Nonce() + + self.assertTrue(a == b) + self.assertTrue(b == a) + + a = objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x00\x01\x02\x03' + ) + b = objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x00\x01\x02\x03' + ) + + self.assertTrue(a == b) + self.assertTrue(b == a) + + def test_equal_on_not_equal_nonce_id(self): + """ + Test that the equality operator returns False when comparing two + Nonce structs with different nonce IDs. + """ + a = objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x00\x01\x02\x03' + ) + b = objects.Nonce( + nonce_id=b'\x02', + nonce_value=b'\x00\x01\x02\x03' + ) + + self.assertFalse(a == b) + self.assertFalse(b == a) + + def test_equal_on_not_equal_nonce_value(self): + """ + Test that the equality operator returns False when comparing two + Nonce structs with different nonce values. + """ + a = objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x00\x01\x02\x03' + ) + b = objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x03\x02\x01\x00' + ) + + 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 + Nonce structs with different types. + """ + a = objects.Nonce() + 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 + Nonce structs with the same data. + """ + a = objects.Nonce() + b = objects.Nonce() + + self.assertFalse(a != b) + self.assertFalse(b != a) + + a = objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x00\x01\x02\x03' + ) + b = objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x00\x01\x02\x03' + ) + + self.assertFalse(a != b) + self.assertFalse(b != a) + + def test_not_equal_on_not_equal_nonce_id(self): + """ + Test that the inequality operator returns True when comparing two + Nonce structs with different nonce IDs. + """ + a = objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x00\x01\x02\x03' + ) + b = objects.Nonce( + nonce_id=b'\x02', + nonce_value=b'\x00\x01\x02\x03' + ) + + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_not_equal_on_not_equal_nonce_value(self): + """ + Test that the inequality operator returns True when comparing two + Nonce structs with different nonce values. + """ + a = objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x00\x01\x02\x03' + ) + b = objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x03\x02\x01\x00' + ) + + 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 + Nonce structs with different types. + """ + a = objects.Nonce() + b = 'invalid' + + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_repr(self): + """ + Test that repr can be applied to a Nonce struct. + """ + credential = objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x00\x01\x02\x03\x04\x05\x06\x07' + ) + expected = ( + "Nonce(" + "nonce_id=" + str(b'\x01') + ", " + "nonce_value=" + str(b'\x00\x01\x02\x03\x04\x05\x06\x07') + ")" + ) + observed = repr(credential) + + self.assertEqual(expected, observed) + + def test_str(self): + """ + Test that str can be applied to a Nonce struct. + """ + credential = objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x00\x01\x02\x03\x04\x05\x06\x07' + ) + expected = ", ".join([ + "'nonce_id': {}".format(b'\x01'), + "'nonce_value': {}".format(b'\x00\x01\x02\x03\x04\x05\x06\x07') + ]) + expected = "{" + expected + "}" + observed = str(credential) + + self.assertEqual(expected, observed) + + class TestUsernamePasswordCredential(testtools.TestCase): """ Test suite for the UsernamePasswordCredential struct. @@ -1336,6 +1714,788 @@ class TestDeviceCredential(testtools.TestCase): self.assertEqual(expected, observed) +class TestAttestationCredential(testtools.TestCase): + """ + Test suite for the AttestationCredential struct. + """ + + def setUp(self): + super(TestAttestationCredential, self).setUp() + + # There are no AttestationCredential encodings available in any of the + # KMIP testing documents. The following encodings were adapted from + # other structure encodings present in the KMIP testing suite. + # + # This encoding matches the following set of values: + # AttestationCredential + # Nonce + # Nonce ID - 1 + # Nonce Value - 0x0001020304050607 + # AttestationType - TPM Quote + # AttestationMeasurement - 0xFFFFFFFFFFFFFFFF + # AttestationAssertion - 0x1111111111111111 + self.full_encoding = utils.BytearrayStream( + b'\x42\x00\x25\x01\x00\x00\x00\x58' + b'\x42\x00\xC8\x01\x00\x00\x00\x20' + b'\x42\x00\xC9\x08\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00' + b'\x42\x00\xCA\x08\x00\x00\x00\x08\x00\x01\x02\x03\x04\x05\x06\x07' + b'\x42\x00\xC7\x05\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x00' + b'\x42\x00\xCB\x08\x00\x00\x00\x08\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF' + b'\x42\x00\xCC\x08\x00\x00\x00\x08\x11\x11\x11\x11\x11\x11\x11\x11' + ) + self.encoding_missing_nonce = utils.BytearrayStream( + b'\x42\x00\x25\x01\x00\x00\x00\x30' + b'\x42\x00\xC7\x05\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x00' + b'\x42\x00\xCB\x08\x00\x00\x00\x08\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF' + b'\x42\x00\xCC\x08\x00\x00\x00\x08\x11\x11\x11\x11\x11\x11\x11\x11' + ) + self.encoding_missing_attestation_type = utils.BytearrayStream( + b'\x42\x00\x25\x01\x00\x00\x00\x48' + b'\x42\x00\xC8\x01\x00\x00\x00\x20' + b'\x42\x00\xC9\x08\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00' + b'\x42\x00\xCA\x08\x00\x00\x00\x08\x00\x01\x02\x03\x04\x05\x06\x07' + b'\x42\x00\xCB\x08\x00\x00\x00\x08\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF' + b'\x42\x00\xCC\x08\x00\x00\x00\x08\x11\x11\x11\x11\x11\x11\x11\x11' + ) + self.encoding_missing_attestation_measurement = utils.BytearrayStream( + b'\x42\x00\x25\x01\x00\x00\x00\x48' + b'\x42\x00\xC8\x01\x00\x00\x00\x20' + b'\x42\x00\xC9\x08\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00' + b'\x42\x00\xCA\x08\x00\x00\x00\x08\x00\x01\x02\x03\x04\x05\x06\x07' + b'\x42\x00\xC7\x05\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x00' + b'\x42\x00\xCC\x08\x00\x00\x00\x08\x11\x11\x11\x11\x11\x11\x11\x11' + ) + self.encoding_missing_attestation_assertion = utils.BytearrayStream( + b'\x42\x00\x25\x01\x00\x00\x00\x48' + b'\x42\x00\xC8\x01\x00\x00\x00\x20' + b'\x42\x00\xC9\x08\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00' + b'\x42\x00\xCA\x08\x00\x00\x00\x08\x00\x01\x02\x03\x04\x05\x06\x07' + b'\x42\x00\xC7\x05\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x00' + b'\x42\x00\xCB\x08\x00\x00\x00\x08\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF' + ) + self.encoding_missing_attestation = utils.BytearrayStream( + b'\x42\x00\x25\x01\x00\x00\x00\x38' + b'\x42\x00\xC8\x01\x00\x00\x00\x20' + b'\x42\x00\xC9\x08\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00' + b'\x42\x00\xCA\x08\x00\x00\x00\x08\x00\x01\x02\x03\x04\x05\x06\x07' + b'\x42\x00\xC7\x05\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x00' + ) + + def tearDown(self): + super(TestAttestationCredential, self).tearDown() + + def test_init(self): + """ + Test that an AttestationCredential struct can be constructed without + arguments. + """ + credential = objects.AttestationCredential() + + self.assertEqual(None, credential.nonce) + self.assertEqual(None, credential.attestation_type) + self.assertEqual(None, credential.attestation_measurement) + self.assertEqual(None, credential.attestation_assertion) + + def test_init_with_args(self): + """ + Test that an AttestationCredential struct can be constructed with + arguments. + """ + credential = objects.AttestationCredential( + nonce=objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x00\x01\x02\x03\x04\x05\x06\x07' + ), + attestation_type=enums.AttestationType.TPM_QUOTE, + attestation_measurement=b'\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF', + attestation_assertion=b'\x11\x11\x11\x11\x11\x11\x11\x11' + ) + + self.assertEqual( + objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x00\x01\x02\x03\x04\x05\x06\x07' + ), + credential.nonce + ) + self.assertEqual( + enums.AttestationType.TPM_QUOTE, + credential.attestation_type + ) + self.assertEqual( + b'\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF', + credential.attestation_measurement + ) + self.assertEqual( + b'\x11\x11\x11\x11\x11\x11\x11\x11', + credential.attestation_assertion + ) + + def test_invalid_nonce(self): + """ + Test that a TypeError is raised when an invalid value is used to set + the nonce of an AttestationCredential struct. + """ + kwargs = {"nonce": "invalid"} + self.assertRaisesRegexp( + TypeError, + "Nonce must be a Nonce struct.", + objects.AttestationCredential, + **kwargs + ) + + credential = objects.AttestationCredential() + args = (credential, "nonce", 0) + self.assertRaisesRegexp( + TypeError, + "Nonce must be a Nonce struct.", + setattr, + *args + ) + + def test_invalid_attestation_type(self): + """ + Test that a TypeError is raised when an invalid value is used to set + the attestation type of an AttestationCredential struct. + """ + kwargs = {"attestation_type": "invalid"} + self.assertRaisesRegexp( + TypeError, + "Attestation type must be an AttestationType enumeration.", + objects.AttestationCredential, + **kwargs + ) + + credential = objects.AttestationCredential() + args = (credential, "attestation_type", 0) + self.assertRaisesRegexp( + TypeError, + "Attestation type must be an AttestationType enumeration.", + setattr, + *args + ) + + def test_invalid_attestation_measurement(self): + """ + Test that a TypeError is raised when an invalid value is used to set + the attestation measurement of an AttestationCredential struct. + """ + kwargs = {"attestation_measurement": 0} + self.assertRaisesRegexp( + TypeError, + "Attestation measurement must be bytes.", + objects.AttestationCredential, + **kwargs + ) + + credential = objects.AttestationCredential() + args = (credential, "attestation_measurement", 0) + self.assertRaisesRegexp( + TypeError, + "Attestation measurement must be bytes.", + setattr, + *args + ) + + def test_invalid_attestation_assertion(self): + """ + Test that a TypeError is raised when an invalid value is used to set + the attestation assertion of an AttestationCredential struct. + """ + kwargs = {"attestation_assertion": 0} + self.assertRaisesRegexp( + TypeError, + "Attestation assertion must be bytes.", + objects.AttestationCredential, + **kwargs + ) + + credential = objects.AttestationCredential() + args = (credential, "attestation_assertion", 0) + self.assertRaisesRegexp( + TypeError, + "Attestation assertion must be bytes.", + setattr, + *args + ) + + def test_read(self): + """ + Test that an AttestationCredential struct can be read from a data + stream. + """ + credential = objects.AttestationCredential() + + self.assertEqual(None, credential.nonce) + self.assertEqual(None, credential.attestation_type) + self.assertEqual(None, credential.attestation_measurement) + self.assertEqual(None, credential.attestation_assertion) + + credential.read(self.full_encoding) + + self.assertEqual( + objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x00\x01\x02\x03\x04\x05\x06\x07' + ), + credential.nonce + ) + self.assertEqual( + enums.AttestationType.TPM_QUOTE, + credential.attestation_type + ) + self.assertEqual( + b'\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF', + credential.attestation_measurement + ) + self.assertEqual( + b'\x11\x11\x11\x11\x11\x11\x11\x11', + credential.attestation_assertion + ) + + def test_read_missing_nonce(self): + """ + Test that a ValueError gets raised when attempting to read an + AttestationCredential struct from a data stream missing the nonce data. + """ + credential = objects.AttestationCredential() + + self.assertEqual(None, credential.nonce) + self.assertEqual(None, credential.attestation_type) + self.assertEqual(None, credential.attestation_measurement) + self.assertEqual(None, credential.attestation_assertion) + + args = (self.encoding_missing_nonce, ) + self.assertRaisesRegexp( + ValueError, + "Attestation credential encoding is missing the nonce.", + credential.read, + *args + ) + + def test_read_missing_attestation_type(self): + """ + Test that a ValueError gets raised when attempting to read an + AttestationCredential struct from a data stream missing the + attestation type data. + """ + credential = objects.AttestationCredential() + + self.assertEqual(None, credential.nonce) + self.assertEqual(None, credential.attestation_type) + self.assertEqual(None, credential.attestation_measurement) + self.assertEqual(None, credential.attestation_assertion) + + args = (self.encoding_missing_attestation_type, ) + self.assertRaisesRegexp( + ValueError, + "Attestation credential encoding is missing the attestation type.", + credential.read, + *args + ) + + def test_read_missing_attestation_measurement(self): + """ + Test that an AttestationCredential struct can be read from a data + stream missing the attestation measurement data. + """ + credential = objects.AttestationCredential() + + self.assertEqual(None, credential.nonce) + self.assertEqual(None, credential.attestation_type) + self.assertEqual(None, credential.attestation_measurement) + self.assertEqual(None, credential.attestation_assertion) + + credential.read(self.encoding_missing_attestation_measurement) + + self.assertEqual( + objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x00\x01\x02\x03\x04\x05\x06\x07' + ), + credential.nonce + ) + self.assertEqual( + enums.AttestationType.TPM_QUOTE, + credential.attestation_type + ) + self.assertEqual(None, credential.attestation_measurement) + self.assertEqual( + b'\x11\x11\x11\x11\x11\x11\x11\x11', + credential.attestation_assertion + ) + + def test_read_missing_attestation_assertion(self): + """ + Test that an AttestationCredential struct can be read from a data + stream missing the attestation assertion data. + """ + + credential = objects.AttestationCredential() + + self.assertEqual(None, credential.nonce) + self.assertEqual(None, credential.attestation_type) + self.assertEqual(None, credential.attestation_measurement) + self.assertEqual(None, credential.attestation_assertion) + + credential.read(self.encoding_missing_attestation_assertion) + + self.assertEqual( + objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x00\x01\x02\x03\x04\x05\x06\x07' + ), + credential.nonce + ) + self.assertEqual( + enums.AttestationType.TPM_QUOTE, + credential.attestation_type + ) + self.assertEqual( + b'\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF', + credential.attestation_measurement + ) + self.assertEqual(None, credential.attestation_assertion) + + def test_read_missing_attestation_measurement_and_assertion(self): + """ + Test that a ValueError gets raised when attempting to read an + AttestationCredential struct from a data stream missing both the + attestation measurement and attestation assertion data. + """ + credential = objects.AttestationCredential() + + self.assertEqual(None, credential.nonce) + self.assertEqual(None, credential.attestation_type) + self.assertEqual(None, credential.attestation_measurement) + self.assertEqual(None, credential.attestation_assertion) + + args = (self.encoding_missing_attestation, ) + self.assertRaisesRegexp( + ValueError, + "Attestation credential encoding is missing either the " + "attestation measurement or the attestation assertion.", + credential.read, + *args + ) + + def test_write(self): + """ + Test that an AttestationCredential struct can be written to a data + stream. + """ + credential = objects.AttestationCredential( + nonce=objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x00\x01\x02\x03\x04\x05\x06\x07' + ), + attestation_type=enums.AttestationType.TPM_QUOTE, + attestation_measurement=b'\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF', + attestation_assertion=b'\x11\x11\x11\x11\x11\x11\x11\x11' + ) + stream = utils.BytearrayStream() + + credential.write(stream) + + self.assertEqual(len(self.full_encoding), len(stream)) + self.assertEqual(str(self.full_encoding), str(stream)) + + def test_write_missing_nonce(self): + """ + Test that a ValueError gets raised when attempting to write an + AttestationCredential struct missing nonce data to a data stream. + """ + credential = objects.AttestationCredential( + attestation_type=enums.AttestationType.TPM_QUOTE, + attestation_measurement=b'\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF', + attestation_assertion=b'\x11\x11\x11\x11\x11\x11\x11\x11' + ) + stream = utils.BytearrayStream() + + args = (stream, ) + self.assertRaisesRegexp( + ValueError, + "Attestation credential struct is missing the nonce.", + credential.write, + *args + ) + + def test_write_missing_attestation_type(self): + """ + Test that a ValueError gets raised when attempting to write an + AttestationCredential struct missing nonce data to a data stream. + """ + credential = objects.AttestationCredential( + nonce=objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x00\x01\x02\x03\x04\x05\x06\x07' + ), + attestation_measurement=b'\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF', + attestation_assertion=b'\x11\x11\x11\x11\x11\x11\x11\x11' + ) + stream = utils.BytearrayStream() + + args = (stream, ) + self.assertRaisesRegexp( + ValueError, + "Attestation credential struct is missing the attestation type.", + credential.write, + *args + ) + + def test_write_missing_attestation_measurement(self): + """ + Test that an AttestationCredential struct can be written to a data + stream missing attestation measurement data. + """ + credential = objects.AttestationCredential( + nonce=objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x00\x01\x02\x03\x04\x05\x06\x07' + ), + attestation_type=enums.AttestationType.TPM_QUOTE, + attestation_assertion=b'\x11\x11\x11\x11\x11\x11\x11\x11' + ) + stream = utils.BytearrayStream() + + credential.write(stream) + + self.assertEqual( + len(self.encoding_missing_attestation_measurement), + len(stream) + ) + self.assertEqual( + str(self.encoding_missing_attestation_measurement), + str(stream) + ) + + def test_write_missing_attestation_assertion(self): + """ + Test that an AttestationCredential struct can be written to a data + stream missing attestation assertion data. + """ + credential = objects.AttestationCredential( + nonce=objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x00\x01\x02\x03\x04\x05\x06\x07' + ), + attestation_type=enums.AttestationType.TPM_QUOTE, + attestation_measurement=b'\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF' + ) + stream = utils.BytearrayStream() + + credential.write(stream) + + self.assertEqual( + len(self.encoding_missing_attestation_assertion), + len(stream) + ) + self.assertEqual( + str(self.encoding_missing_attestation_assertion), + str(stream) + ) + + def test_write_missing_attestation_measurement_and_assertion(self): + """ + Test that a ValueError gets raised when attempting to write an + AttestationCredential struct missing both attestation measurement and + attestation assertion data to a data stream. + """ + credential = objects.AttestationCredential( + nonce=objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x00\x01\x02\x03\x04\x05\x06\x07' + ), + attestation_type=enums.AttestationType.TPM_QUOTE + ) + stream = utils.BytearrayStream() + + args = (stream, ) + self.assertRaisesRegexp( + ValueError, + "Attestation credential struct is missing either the attestation " + "measurement or the attestation assertion.", + credential.write, + *args + ) + + def test_equal_on_equal(self): + """ + Test that the equality operator returns True when comparing two + AttestationCredential structs with the same data. + """ + a = objects.AttestationCredential() + b = objects.AttestationCredential() + + self.assertTrue(a == b) + self.assertTrue(b == a) + + a = objects.AttestationCredential( + nonce=objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x00\x01\x02\x03\x04\x05\x06\x07' + ), + attestation_type=enums.AttestationType.TPM_QUOTE, + attestation_measurement=b'\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF', + attestation_assertion=b'\x11\x11\x11\x11\x11\x11\x11\x11' + ) + b = objects.AttestationCredential( + nonce=objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x00\x01\x02\x03\x04\x05\x06\x07' + ), + attestation_type=enums.AttestationType.TPM_QUOTE, + attestation_measurement=b'\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF', + attestation_assertion=b'\x11\x11\x11\x11\x11\x11\x11\x11' + ) + + self.assertTrue(a == b) + self.assertTrue(b == a) + + def test_equal_on_not_equal_nonce(self): + """ + Test that the equality operator returns False when comparing two + AttestationCredential structs with different nonce values. + """ + a = objects.AttestationCredential( + nonce=objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x00\x01\x02\x03\x04\x05\x06\x07' + ) + ) + b = objects.AttestationCredential( + nonce=objects.Nonce( + nonce_id=b'\x02', + nonce_value=b'\x07\x06\x05\x04\x03\x02\x01\x00' + ) + ) + + self.assertFalse(a == b) + self.assertFalse(b == a) + + def test_equal_on_not_equal_attestation_type(self): + """ + Test that the equality operator returns False when comparing two + AttestationCredential structs with different attestation types. + """ + a = objects.AttestationCredential( + attestation_type=enums.AttestationType.TPM_QUOTE + ) + b = objects.AttestationCredential( + attestation_type=enums.AttestationType.SAML_ASSERTION + ) + + self.assertFalse(a == b) + self.assertFalse(b == a) + + def test_equal_on_not_equal_attestation_measurement(self): + """ + Test that the equality operator returns False when comparing two + AttestationCredential structs with different attestation measurements. + """ + a = objects.AttestationCredential( + attestation_measurement=b'\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF' + ) + b = objects.AttestationCredential( + attestation_measurement=b'\x11\x11\x11\x11\x11\x11\x11\x11' + ) + + self.assertFalse(a == b) + self.assertFalse(b == a) + + def test_equal_on_not_equal_attestation_assertion(self): + """ + Test that the equality operator returns False when comparing two + AttestationCredential structs with different attestation assertions. + """ + a = objects.AttestationCredential( + attestation_assertion=b'\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF' + ) + b = objects.AttestationCredential( + attestation_assertion=b'\x11\x11\x11\x11\x11\x11\x11\x11' + ) + + 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 + AttestationCredential structs with different types. + """ + a = objects.AttestationCredential() + 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 + AttestationCredential structs with the same data. + """ + a = objects.AttestationCredential() + b = objects.AttestationCredential() + + self.assertFalse(a != b) + self.assertFalse(b != a) + + a = objects.AttestationCredential( + nonce=objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x00\x01\x02\x03\x04\x05\x06\x07' + ), + attestation_type=enums.AttestationType.TPM_QUOTE, + attestation_measurement=b'\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF', + attestation_assertion=b'\x11\x11\x11\x11\x11\x11\x11\x11' + ) + b = objects.AttestationCredential( + nonce=objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x00\x01\x02\x03\x04\x05\x06\x07' + ), + attestation_type=enums.AttestationType.TPM_QUOTE, + attestation_measurement=b'\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF', + attestation_assertion=b'\x11\x11\x11\x11\x11\x11\x11\x11' + ) + + self.assertFalse(a != b) + self.assertFalse(b != a) + + def test_not_equal_on_not_equal_nonce(self): + """ + Test that the inequality operator returns True when comparing two + AttestationCredential structs with different nonce values. + """ + a = objects.AttestationCredential( + nonce=objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x00\x01\x02\x03\x04\x05\x06\x07' + ) + ) + b = objects.AttestationCredential( + nonce=objects.Nonce( + nonce_id=b'\x02', + nonce_value=b'\x07\x06\x05\x04\x03\x02\x01\x00' + ) + ) + + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_not_equal_on_not_equal_attestation_type(self): + """ + Test that the inequality operator returns True when comparing two + AttestationCredential structs with different attestation types. + """ + a = objects.AttestationCredential( + attestation_type=enums.AttestationType.TPM_QUOTE + ) + b = objects.AttestationCredential( + attestation_type=enums.AttestationType.SAML_ASSERTION + ) + + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_not_equal_on_not_equal_attestation_measurement(self): + """ + Test that the inequality operator returns True when comparing two + AttestationCredential structs with different attestation measurements. + """ + a = objects.AttestationCredential( + attestation_measurement=b'\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF' + ) + b = objects.AttestationCredential( + attestation_measurement=b'\x11\x11\x11\x11\x11\x11\x11\x11' + ) + + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_not_equal_on_not_equal_attestation_assertion(self): + """ + Test that the inequality operator returns True when comparing two + AttestationCredential structs with different attestation assertions. + """ + a = objects.AttestationCredential( + attestation_assertion=b'\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF' + ) + b = objects.AttestationCredential( + attestation_assertion=b'\x11\x11\x11\x11\x11\x11\x11\x11' + ) + + 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 + AttestationCredential structs with different types. + """ + a = objects.AttestationCredential() + b = 'invalid' + + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_repr(self): + """ + Test that repr can be applied to an AttestationCredential struct. + """ + credential = objects.AttestationCredential( + nonce=objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x00\x01\x02\x03\x04\x05\x06\x07' + ), + attestation_type=enums.AttestationType.TPM_QUOTE, + attestation_measurement=b'\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF', + attestation_assertion=b'\x11\x11\x11\x11\x11\x11\x11\x11' + ) + expected = ( + "AttestationCredential(" + "nonce=Nonce(" + "nonce_id=" + str(b'\x01') + ", " + "nonce_value=" + str(b'\x00\x01\x02\x03\x04\x05\x06\x07') + "), " + "attestation_type=AttestationType.TPM_QUOTE, " + "attestation_measurement=" + + str(b'\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF') + ", " + "attestation_assertion=" + + str(b'\x11\x11\x11\x11\x11\x11\x11\x11') + ")" + ) + observed = repr(credential) + + self.assertEqual(expected, observed) + + def test_str(self): + """ + Test that str can be applied to an AttestationCredential struct. + """ + credential = objects.AttestationCredential( + nonce=objects.Nonce( + nonce_id=b'\x01', + nonce_value=b'\x00\x01\x02\x03\x04\x05\x06\x07' + ), + attestation_type=enums.AttestationType.TPM_QUOTE, + attestation_measurement=b'\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF', + attestation_assertion=b'\x11\x11\x11\x11\x11\x11\x11\x11' + ) + expected = "{" \ + "'nonce': {" \ + "'nonce_id': " + str(b'\x01') + ", " \ + "'nonce_value': " + \ + str(b'\x00\x01\x02\x03\x04\x05\x06\x07') + "}, " \ + "'attestation_type': " + \ + str(enums.AttestationType.TPM_QUOTE) + ", " \ + "'attestation_measurement': " + \ + str(b'\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF') + ", " \ + "'attestation_assertion': " + \ + str(b'\x11\x11\x11\x11\x11\x11\x11\x11') + "}" + observed = str(credential) + + self.assertEqual(expected, observed) + + class TestCredential(testtools.TestCase): """ Test suite for the Credential struct. @@ -1375,7 +2535,7 @@ class TestCredential(testtools.TestCase): ) self.encoding_unknown_credential_type = utils.BytearrayStream( b'\x42\x00\x23\x01\x00\x00\x00\x40' - b'\x42\x00\x24\x05\x00\x00\x00\x04\x00\x00\x00\x03\x00\x00\x00\x00' + b'\x42\x00\x24\x05\x00\x00\x00\x04\x00\x00\x00\xFF\x00\x00\x00\x00' b'\x42\x00\x25\x01\x00\x00\x00\x28' b'\x42\x00\x99\x07\x00\x00\x00\x04' b'\x46\x72\x65\x64\x00\x00\x00\x00' @@ -1559,6 +2719,14 @@ class TestCredential(testtools.TestCase): *args ) + @mock.patch( + 'kmip.core.enums.CredentialType', + enum.Enum( + 'FakeCredentialType', + [(i.name, i.value) for i in enums.CredentialType] + + [('UNKNOWN', 0x000000FF)] + ) + ) def test_read_unknown_credential_type(self): """ Test that a ValueError gets raised when attempting to read a