Add CCA attestation token verifier
This commit adds classes to verify CCA attestation token. A CCA
attestation token is defined by the document DEN0137 Realm Management
Monitor specification found here:
https://developer.arm.com/documentation/den0137/a/?lang=en
The commit
* Adds claim classes for CCA attestation token claims.
* Adds verifier classes CCA attestation token
* Adds CCA tokens to CLI scripts and change parameters to be possible to
specify multiple signing keys
* Adds sample cbor and yaml and key files to demonstrate CCA attestation
token
Change-Id: Ia88a5ce4af334143452e87d29975826165502409
Signed-off-by: Mate Toth-Pal <mate.toth-pal@arm.com>
diff --git a/iat-verifier/scripts/check_iat b/iat-verifier/scripts/check_iat
index 4778b39..e9adf48 100755
--- a/iat-verifier/scripts/check_iat
+++ b/iat-verifier/scripts/check_iat
@@ -13,9 +13,11 @@
import logging
import sys
+from iatverifier.attest_token_verifier import AttestationClaim as Claim
from iatverifier.util import recursive_bytes_to_strings, read_keyfile, get_cose_alg_from_key
from iatverifier.psa_iot_profile1_token_verifier import PSAIoTProfile1TokenVerifier
from iatverifier.attest_token_verifier import VerifierConfiguration, AttestationTokenVerifier
+from iatverifier.cca_token_verifier import CCATokenVerifier, CCAPlatformTokenVerifier
logger = logging.getLogger('iat-verify')
@@ -24,6 +26,8 @@
token_verifiers = {
"PSA-IoT-Profile1-token": PSAIoTProfile1TokenVerifier,
+ "CCA-token": CCATokenVerifier,
+ "CCA-plat-token": CCAPlatformTokenVerifier,
}
parser = argparse.ArgumentParser(
@@ -32,10 +36,18 @@
that the signature is valid, the token contian the required
fields, and those fields are in a valid format.
''')
- parser.add_argument('-k', '--keyfile',
- help='''
- Path to a file containing signing key in PEM format.
- ''')
+ parser.add_argument('--psa-iot-profile1-keyfile',
+ help='''Path to the key in PEM format that should be used to
+ verify the token. If this is not specified, the token signature
+ will not be checked.''')
+ parser.add_argument('--cca-platform-token-keyfile',
+ help='''Path to the key in PEM format that should be used to
+ verify the CCA platform token. If this is not specified, the
+ token signature will not be checked.''')
+ parser.add_argument('--cca-realm-token-keyfile',
+ help='''Path to the key in PEM format that should be used to
+ verify the CCA Realm token. If this is not specified, the
+ token signature will not be checked.''')
parser.add_argument('tokenfile',
help='''
path to a file containing a signed IAT.
@@ -76,23 +88,54 @@
else:
method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
- key = read_keyfile(keyfile=args.keyfile, method=method)
-
- if args.method == 'mac':
- cose_alg = AttestationTokenVerifier.COSE_ALG_HS256
- else:
- if key is not None:
- cose_alg = get_cose_alg_from_key(key)
- else:
- cose_alg = AttestationTokenVerifier.COSE_ALG_ES256
+ key_checked = False
verifier_class = token_verifiers[args.token_type]
if verifier_class == PSAIoTProfile1TokenVerifier:
+ key_checked = args.psa_iot_profile1_keyfile
+ key = read_keyfile(keyfile=args.psa_iot_profile1_keyfile, method=method)
+ if method == AttestationTokenVerifier.SIGN_METHOD_SIGN1:
+ cose_alg = get_cose_alg_from_key(key, AttestationTokenVerifier.COSE_ALG_ES256)
+ else:
+ cose_alg = AttestationTokenVerifier.COSE_ALG_HS256
verifier = PSAIoTProfile1TokenVerifier(
method=method,
cose_alg=cose_alg,
signing_key=key,
configuration=config)
+ elif verifier_class == CCATokenVerifier:
+ if method != AttestationTokenVerifier.SIGN_METHOD_SIGN1:
+ logger.error('Only sign1 method is supported by this token type.\n\t'.format(verifier_class))
+ sys.exit(1)
+ key_checked = args.cca_platform_token_keyfile and args.cca_realm_token_keyfile
+ platform_token_key = read_keyfile(args.cca_platform_token_keyfile, method)
+ realm_token_key = read_keyfile(args.cca_realm_token_keyfile, method)
+ realm_token_method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
+ platform_token_method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
+ realm_token_cose_alg = get_cose_alg_from_key(
+ realm_token_key,
+ AttestationTokenVerifier.COSE_ALG_ES384)
+ platform_token_cose_alg = get_cose_alg_from_key(
+ platform_token_key,
+ AttestationTokenVerifier.COSE_ALG_ES384)
+ verifier = CCATokenVerifier(
+ realm_token_method=realm_token_method,
+ realm_token_cose_alg=realm_token_cose_alg,
+ realm_token_key=realm_token_key,
+ platform_token_method=platform_token_method,
+ platform_token_cose_alg=platform_token_cose_alg,
+ platform_token_key=platform_token_key,
+ configuration=config)
+ elif verifier_class == CCAPlatformTokenVerifier:
+ key_checked = args.cca_platform_token_keyfile
+ key = read_keyfile(args.cca_platform_token_keyfile, method)
+ cose_alg = get_cose_alg_from_key(key, AttestationTokenVerifier.COSE_ALG_ES384)
+ verifier = CCAPlatformTokenVerifier(
+ method=AttestationTokenVerifier.SIGN_METHOD_SIGN1,
+ cose_alg=cose_alg,
+ signing_key=key,
+ configuration=config,
+ necessity=None)
else:
logger.error(f'Invalid token type:{verifier_class}\n\t')
sys.exit(1)
@@ -104,11 +147,11 @@
verify=True,
check_p_header=args.check_protected_header,
lower_case_key=False)
- if args.keyfile:
+ if key_checked:
print('Signature OK')
print('Token format OK')
except ValueError as exc:
- logger.error(f'Could not extract IAT from COSE:\n\t{exc}')
+ logger.error(f'Token verification failed:\n\t{exc}')
sys.exit(1)
if args.print_iat:
diff --git a/iat-verifier/scripts/compile_token b/iat-verifier/scripts/compile_token
index 7fa9816..2783cf6 100755
--- a/iat-verifier/scripts/compile_token
+++ b/iat-verifier/scripts/compile_token
@@ -16,14 +16,16 @@
from iatverifier.util import read_token_map, convert_map_to_token, read_keyfile
from iatverifier.util import get_cose_alg_from_key
from iatverifier.psa_iot_profile1_token_verifier import PSAIoTProfile1TokenVerifier
-from iatverifier.attest_token_verifier import AttestationTokenVerifier
-
+from iatverifier.attest_token_verifier import AttestationTokenVerifier, VerifierConfiguration
+from iatverifier.cca_token_verifier import CCATokenVerifier, CCAPlatformTokenVerifier
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
token_verifiers = {
"PSA-IoT-Profile1-token": PSAIoTProfile1TokenVerifier,
+ "CCA-token": CCATokenVerifier,
+ "CCA-plat-token": CCAPlatformTokenVerifier,
}
parser = argparse.ArgumentParser()
@@ -31,10 +33,18 @@
parser.add_argument('-o', '--outfile',
help='''Output file for the compiled token. If this is not
specified, the token will be written to standard output.''')
- parser.add_argument('-k', '--keyfile',
+ parser.add_argument('--psa-iot-profile1-keyfile',
help='''Path to the key in PEM format that should be used to
sign the token. If this is not specified, the token will be
unsigned.''')
+ parser.add_argument('--cca-platform-token-keyfile',
+ help='''Path to the key in PEM format that should be used to
+ sign the CCA platform token. If this is not specified,
+ the token will be unsigned.''')
+ parser.add_argument('--cca-realm-token-keyfile',
+ help='''Path to the key in PEM format that should be used to
+ sign the CCA Realm token. If this is not specified, the
+ token will be unsigned.''')
group = parser.add_mutually_exclusive_group()
parser.add_argument('-a', '--add-protected-header', action='store_true',
help='''
@@ -56,27 +66,60 @@
if args.hmac:
METHOD = AttestationTokenVerifier.SIGN_METHOD_MAC0
elif args.raw:
- if args.keyfile:
+ if args.psa_iot_profile1_keyfile:
raise ValueError('A keyfile cannot be specified with --raw.')
METHOD = AttestationTokenVerifier.SIGN_METHOD_RAW
else:
METHOD = AttestationTokenVerifier.SIGN_METHOD_SIGN1
- key = read_keyfile(args.keyfile, METHOD)
-
- COSE_ALG = None
- if args.hmac:
- COSE_ALG = AttestationTokenVerifier.COSE_ALG_HS256
- elif not args.raw:
- COSE_ALG = get_cose_alg_from_key(key)
+ configuration = VerifierConfiguration(strict=True, keep_going=False)
verifier_class = token_verifiers[args.token_type]
if verifier_class == PSAIoTProfile1TokenVerifier:
+ key = read_keyfile(args.psa_iot_profile1_keyfile, METHOD)
+ if METHOD == AttestationTokenVerifier.SIGN_METHOD_SIGN1:
+ cose_alg = get_cose_alg_from_key(
+ key,
+ AttestationTokenVerifier.COSE_ALG_ES256)
+ else:
+ cose_alg = AttestationTokenVerifier.COSE_ALG_HS256
verifier = PSAIoTProfile1TokenVerifier(
method=METHOD,
- cose_alg=COSE_ALG,
+ cose_alg=cose_alg,
signing_key=key,
- configuration=None)
+ configuration=configuration)
+ elif verifier_class == CCATokenVerifier:
+ if METHOD != AttestationTokenVerifier.SIGN_METHOD_SIGN1:
+ logging.error('Only sign1 method is supported by this token type.\n\t')
+ sys.exit(1)
+ platform_token_key = read_keyfile(args.cca_platform_token_keyfile, METHOD)
+ realm_token_key = read_keyfile(args.cca_realm_token_keyfile, METHOD)
+ realm_token_method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
+ platform_token_method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
+ realm_token_cose_alg = get_cose_alg_from_key(
+ realm_token_key,
+ AttestationTokenVerifier.COSE_ALG_ES384)
+ platform_token_cose_alg = get_cose_alg_from_key(
+ platform_token_key,
+ AttestationTokenVerifier.COSE_ALG_ES384)
+ verifier = CCATokenVerifier(
+ realm_token_method=realm_token_method,
+ realm_token_cose_alg=realm_token_cose_alg,
+ realm_token_key=realm_token_key,
+ platform_token_method=platform_token_method,
+ platform_token_cose_alg=platform_token_cose_alg,
+ platform_token_key=platform_token_key,
+ configuration=configuration)
+ elif verifier_class == CCAPlatformTokenVerifier:
+ key_checked = args.cca_platform_token_keyfile
+ key = read_keyfile(args.cca_platform_token_keyfile, METHOD)
+ cose_alg = get_cose_alg_from_key(key, AttestationTokenVerifier.COSE_ALG_ES384)
+ verifier = CCAPlatformTokenVerifier(
+ method=AttestationTokenVerifier.SIGN_METHOD_SIGN1,
+ cose_alg=cose_alg,
+ signing_key=key,
+ configuration=configuration,
+ necessity=None)
else:
logging.error(f'Invalid token type:{verifier_class}\n\t')
sys.exit(1)
diff --git a/iat-verifier/scripts/decompile_token b/iat-verifier/scripts/decompile_token
index b64fa59..58bc9cf 100755
--- a/iat-verifier/scripts/decompile_token
+++ b/iat-verifier/scripts/decompile_token
@@ -15,6 +15,7 @@
import yaml
from iatverifier.psa_iot_profile1_token_verifier import PSAIoTProfile1TokenVerifier
from iatverifier.attest_token_verifier import AttestationTokenVerifier
+from iatverifier.cca_token_verifier import CCATokenVerifier, CCAPlatformTokenVerifier
if __name__ == '__main__':
@@ -22,6 +23,8 @@
token_verifiers = {
"PSA-IoT-Profile1-token": PSAIoTProfile1TokenVerifier,
+ "CCA-token": CCATokenVerifier,
+ "CCA-plat-token": CCAPlatformTokenVerifier,
}
parser = argparse.ArgumentParser()
@@ -40,7 +43,29 @@
verifier = PSAIoTProfile1TokenVerifier(
method=AttestationTokenVerifier.SIGN_METHOD_SIGN1,
cose_alg=AttestationTokenVerifier.COSE_ALG_ES256,
- signing_key=None, configuration=None)
+ signing_key=None,
+ configuration=None)
+ elif verifier_class == CCATokenVerifier:
+ realm_token_method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
+ platform_token_method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
+ realm_token_cose_alg = AttestationTokenVerifier.COSE_ALG_ES384
+ platform_token_cose_alg = AttestationTokenVerifier.COSE_ALG_ES384
+ verifier = CCATokenVerifier(
+ realm_token_method=realm_token_method,
+ realm_token_cose_alg=realm_token_cose_alg,
+ realm_token_key=None,
+ platform_token_method=platform_token_method,
+ platform_token_cose_alg=platform_token_cose_alg,
+ platform_token_key=None,
+ configuration=None)
+ elif verifier_class == CCAPlatformTokenVerifier:
+ cose_alg = AttestationTokenVerifier.COSE_ALG_ES384
+ verifier = CCAPlatformTokenVerifier(
+ method=AttestationTokenVerifier.SIGN_METHOD_SIGN1,
+ cose_alg=cose_alg,
+ signing_key=None,
+ configuration=None,
+ necessity=None)
else:
logging.error(f'Invalid token type:{verifier_class}\n\t')
sys.exit(1)