From 5c5012f524582cd643d5260f28a21a70a0855fd5 Mon Sep 17 00:00:00 2001 From: Peter Hamilton Date: Sat, 3 Mar 2018 09:08:50 -0500 Subject: [PATCH] Add AttestationCredential support This change adds an implementation of the AttestationCredential introduced in KMIP 1.2. The underlying Nonce struct is included. Unit test suites for both objects are provided. Finally, the Credential struct has also been updated to support the new credential type. --- kmip/core/objects.py | 437 +++++- .../unit/core/objects/test_credentials.py | 1170 ++++++++++++++++- 2 files changed, 1605 insertions(+), 2 deletions(-) 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