blob: 684ece0b286ab0162dde7f68ff214391f7878473 [file] [log] [blame]
# -----------------------------------------------------------------------------
# Copyright (c) 2022, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
# -----------------------------------------------------------------------------
from collections.abc import Iterable
import logging
from iatverifier.attest_token_verifier import AttestationClaim, NonVerifiedClaim, CompositeAttestClaim
logger = logging.getLogger('iat-verifiers')
class CCARealmChallengeClaim(AttestationClaim):
def __init__(self, verifier, expected_challenge_byte, necessity=AttestationClaim.MANDATORY):
super().__init__(verifier=verifier, necessity=necessity)
self.expected_challenge_byte = expected_challenge_byte
def get_claim_key(self=None):
return 10
def get_claim_name(self=None):
return 'CCA_REALM_CHALLENGE'
def verify(self, value):
self._validate_bytestring_length_equals(value, self.get_claim_name(), 64)
if self.expected_challenge_byte is not None:
for i, b in enumerate(value):
if b != self.expected_challenge_byte:
print (f'Challenge = {value}')
msg = 'Invalid CHALLENGE byte at {:d}: 0x{:02x} instead of 0x{:02x}'
self.verifier.error(msg.format(i, b, self.expected_challenge_byte))
break
self.verify_count += 1
class CCARealmPersonalizationValue(AttestationClaim):
def get_claim_key(self=None):
return 44235
def get_claim_name(self=None):
return 'CCA_REALM_PERSONALIZATION_VALUE'
def verify(self, value):
self._validate_bytestring_length_equals(value, self.get_claim_name(), 64)
self.verify_count += 1
class CCARealmInitialMeasurementClaim(AttestationClaim):
def get_claim_key(self=None):
return 44238
def get_claim_name(self=None):
return 'CCA_REALM_INITIAL_MEASUREMENT'
def verify(self, value):
self._check_type(self.get_claim_name(), value, bytes)
self.verify_count += 1
class CCARealmExtensibleMeasurementsClaim(AttestationClaim):
def get_claim_key(self=None):
return 44239
def get_claim_name(self=None):
return 'CCA_REALM_EXTENSIBLE_MEASUREMENTS'
def verify(self, value):
min_measurement_count = 4
max_measurement_count = 4
if not isinstance(value, Iterable):
msg = 'Invalid {:s}: Value must be a list.'
self.verifier.error(msg.format(self.get_claim_name()))
if len(value) < min_measurement_count or len(value) > max_measurement_count:
msg = 'Invalid {:s}: Value must be a list of min {:d} elements and max {:d} elements.'
self.verifier.error(msg.format(self.get_claim_name(), min_measurement_count,
max_measurement_count))
for v in value:
self._validate_bytestring_length_one_of(v, self.get_claim_name()+f'[{str()}]', [32, 64])
self.verify_count += 1
class CCARealmHashAlgorithmIdClaim(NonVerifiedClaim):
def get_claim_key(self=None):
return 44236
def get_claim_name(self=None):
return 'CCA_REALM_HASH_ALGM_ID'
@classmethod
def is_utf_8(cls):
return True
class CCARealmPubKeyHashAlgorithmIdClaim(NonVerifiedClaim):
def get_claim_key(self=None):
return 44240
def get_claim_name(self=None):
return 'CCA_REALM_PUB_KEY_HASH_ALGO_ID'
@classmethod
def is_utf_8(cls):
return True
class CCARealmPubKeyClaim(AttestationClaim):
def get_claim_key(self=None):
return 44237
def get_claim_name(self=None):
return 'CCA_REALM_PUB_KEY'
def verify(self, value):
self._validate_bytestring_length_equals(value, self.get_claim_name(), 97)
self.verify_count += 1
class CCAAttestationProfileClaim(AttestationClaim):
def get_claim_key(self=None):
return 265
def get_claim_name(self=None):
return 'CCA_ATTESTATION_PROFILE'
@classmethod
def is_utf_8(cls):
return True
def verify(self, value):
expected_value = "http://arm.com/CCA-SSD/1.0.0"
self._check_type(self.get_claim_name(), value, str)
if value != expected_value:
msg = 'Invalid Attest profile "{}": must be "{}"'
self.verifier.error(msg.format(value, expected_value))
self.verify_count += 1
class CCAPlatformChallengeClaim(AttestationClaim):
def get_claim_key(self=None):
return 10
def get_claim_name(self=None):
return 'CCA_PLATFORM_CHALLENGE'
def verify(self, value):
self._validate_bytestring_length_one_of(value, self.get_claim_name(), [32, 48, 64])
self.verify_count += 1
class CCAPlatformImplementationIdClaim(AttestationClaim):
def get_claim_key(self=None):
return 2396
def get_claim_name(self=None):
return 'CCA_PLATFORM_IMPLEMENTATION_ID'
def verify(self, value):
self._validate_bytestring_length_equals(value, self.get_claim_name(), 32)
self.verify_count += 1
class CCAPlatformInstanceIdClaim(AttestationClaim):
def get_claim_key(self=None):
return 256
def get_claim_name(self=None):
return 'CCA_PLATFORM_INSTANCE_ID'
def verify(self, value):
self._validate_bytestring_length_between(value, self.get_claim_name(), 7, 33)
if value[0] != 0x01:
msg = 'Invalid Instance ID first byte "0x{:02x}": must be "0x01"'
self.verifier.error(msg.format(value[0]))
self.verify_count += 1
class CCAPlatformConfigClaim(AttestationClaim):
def get_claim_key(self=None):
return 2401
def get_claim_name(self=None):
return 'CCA_PLATFORM_CONFIG'
def verify(self, value):
self._check_type(self.get_claim_name(), value, bytes)
self.verify_count += 1
class CCAPlatformLifecycleClaim(AttestationClaim):
SL_VALUES= [
("UNKNOWN", 0x0000, 0x00ff),
("ASSEMBLY_AND_TEST", 0x1000, 0x10ff),
("CCA_PLATFORM_ROT_PROVISIONING", 0x2000, 0x20ff),
("SECURED", 0x3000, 0x30ff),
("NON_CCA_PLATFORM_ROT_DEBUG", 0x4000, 0x40ff),
("RECOVERABLE_CCA_PLATFORM_ROT_DEBUG", 0x5000, 0x50ff),
("DECOMMISSIONED", 0x6000, 0x60ff),
]
def get_claim_key(self=None):
return 2395
def get_claim_name(self=None):
return 'CCA_PLATFORM_LIFECYCLE'
@classmethod
def parse_raw(cls, raw_value):
try:
int_value = int(raw_value, 16)
except ValueError:
# It is not a hex number. Try to decode known text values
pass
for text, min, max in cls.SL_VALUES:
if raw_value.startswith(text.lower()):
raw_value = raw_value[len(text):]
else:
continue
if len(raw_value) == 0:
return min
assert raw_value.startswith("_0x")
raw_value = raw_value[3:]
int_value = int(raw_value, 16)
assert(min <= int_value <= max)
return int_value
assert False
@classmethod
def get_formatted_value(cls, value):
for text, min, max in cls.SL_VALUES:
if min <= value <= max:
return f"{text}_{value:04x}".lower()
return f"INVALID_{value:04x}"
def verify(self, value):
self._check_type(self.get_claim_name, value, int)
value_valid = False
for _, min, max in CCAPlatformLifecycleClaim.SL_VALUES:
if min <= value <= max:
value_valid = True
break
if not value_valid:
msg = 'Invalid Platform Lifecycle claim "0x{:02x}"'
self.verifier.error(msg.format(value))
self.verify_count += 1
class CCASwCompHashAlgIdClaim(NonVerifiedClaim):
def get_claim_key(self=None):
return 6
def get_claim_name(self=None):
return 'CCA_SW_COMPONENT_HASH_ID'
@classmethod
def is_utf_8(cls):
return True
class CCAPlatformSwComponentsClaim(CompositeAttestClaim):
def get_claim_key(self=None):
return 2399
def get_claim_name(self=None):
return 'CCA_PLATFORM_SW_COMPONENTS'
class CCAPlatformVerificationServiceClaim(NonVerifiedClaim):
def get_claim_key(self=None):
return 2400
def get_claim_name(self=None):
return 'CCA_PLATFORM_VERIFICATION_SERVICE'
@classmethod
def is_utf_8(cls):
return True
class CCAPlatformHashAlgorithmIdClaim(NonVerifiedClaim):
def get_claim_key(self=None):
return 2402
def get_claim_name(self=None):
return 'CCA_PLATFORM_HASH_ALGO_ID'
@classmethod
def is_utf_8(cls):
return True