blob: 5cd1e81633123a5140f2cadfb6ca97af0d95d320 [file] [log] [blame]
Mate Toth-Pal530106f2022-05-03 15:29:49 +02001#!/usr/bin/env python3
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +02002# -----------------------------------------------------------------------------
3# Copyright (c) 2019-2022, Arm Limited. All rights reserved.
Mate Toth-Pal51b61982022-03-17 14:19:30 +01004#
5# SPDX-License-Identifier: BSD-3-Clause
6#
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +02007# -----------------------------------------------------------------------------
Mate Toth-Pal51b61982022-03-17 14:19:30 +01008
Mate Toth-Palb9057ff2022-04-29 16:03:21 +02009"""CLI script for verifying an IAT."""
10
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020011import argparse
12import json
13import logging
14import sys
15
Thomas Fossatif4e1ca32024-08-16 16:01:31 +000016from pycose.algorithms import Es256, Es384, HMAC256
17
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020018from iatverifier.util import recursive_bytes_to_strings, read_keyfile, get_cose_alg_from_key
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020019from iatverifier.psa_iot_profile1_token_verifier import PSAIoTProfile1TokenVerifier
Tamas Ban1e7944a2022-07-04 13:09:03 +020020from iatverifier.psa_2_0_0_token_verifier import PSA_2_0_0_TokenVerifier
Mate Toth-Palbb187d02022-04-26 16:01:51 +020021from iatverifier.attest_token_verifier import VerifierConfiguration, AttestationTokenVerifier
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010022from iatverifier.cca_token_verifier import CCATokenVerifier, CCAPlatformTokenVerifier
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020023
24logger = logging.getLogger('iat-verify')
25
26def main():
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020027 """Main function for verifying an IAT"""
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020028
29 token_verifiers = {
30 "PSA-IoT-Profile1-token": PSAIoTProfile1TokenVerifier,
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010031 "CCA-token": CCATokenVerifier,
32 "CCA-plat-token": CCAPlatformTokenVerifier,
Tamas Ban1e7944a2022-07-04 13:09:03 +020033 "PSA-2.0.0-token": PSA_2_0_0_TokenVerifier,
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020034 }
35
36 parser = argparse.ArgumentParser(
37 description='''
38 Validates a signed Initial Attestation Token (IAT), checking
39 that the signature is valid, the token contian the required
40 fields, and those fields are in a valid format.
41 ''')
Mate Toth-Pala8b46b12022-10-07 13:30:54 +020042 parser.add_argument('-k', '--key',
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010043 help='''Path to the key in PEM format that should be used to
44 verify the token. If this is not specified, the token signature
45 will not be checked.''')
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020046 parser.add_argument('tokenfile',
47 help='''
48 path to a file containing a signed IAT.
49 ''')
50 parser.add_argument('-K', '--keep-going', action='store_true',
51 help='''
52 Do not stop upon encountering a validation error.
53 ''')
54 parser.add_argument('-p', '--print-iat', action='store_true',
55 help='''
56 Print the decoded token in JSON format.
57 ''')
58 parser.add_argument('-s', '--strict', action='store_true',
59 help='''
60 Report failure if unknown claim is encountered.
61 ''')
Mate Toth-Pal1527a3c2022-11-30 11:27:54 +010062 parser.add_argument('-m', '--method', choices=['sign', 'mac', 'raw'], default='sign',
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020063 help='''
64 Specify how this token is wrapped -- whether Sign1Message or
Mate Toth-Pal1527a3c2022-11-30 11:27:54 +010065 Mac0Message COSE structure is used. In case of 'raw' no COSE envelope is
66 expected.
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020067 ''')
68 parser.add_argument('-t', '--token-type',
69 help='''The type of the Token.''',
70 choices=token_verifiers.keys(),
71 required=True)
72
73 args = parser.parse_args()
74
75 logging.basicConfig(level=logging.INFO)
76
77 config = VerifierConfiguration(keep_going=args.keep_going, strict=args.strict)
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020078 if args.method == 'mac':
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020079 method = AttestationTokenVerifier.SIGN_METHOD_MAC0
Mate Toth-Pal1527a3c2022-11-30 11:27:54 +010080 elif args.method == 'raw':
81 if args.key:
82 raise ValueError('A keyfile cannot be specified with --raw.')
83 method = AttestationTokenVerifier.SIGN_METHOD_RAW
84 elif args.method == 'sign':
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020085 method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
Mate Toth-Pal1527a3c2022-11-30 11:27:54 +010086 else:
87 assert False
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020088
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010089 key_checked = False
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020090
91 verifier_class = token_verifiers[args.token_type]
92 if verifier_class == PSAIoTProfile1TokenVerifier:
Mate Toth-Pala8b46b12022-10-07 13:30:54 +020093 key_checked = args.key
94 key = read_keyfile(keyfile=args.key, method=method)
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010095 if method == AttestationTokenVerifier.SIGN_METHOD_SIGN1:
Thomas Fossatif4e1ca32024-08-16 16:01:31 +000096 cose_alg = get_cose_alg_from_key(key, Es256)
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010097 else:
Thomas Fossatif4e1ca32024-08-16 16:01:31 +000098 cose_alg = HMAC256
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020099 verifier = PSAIoTProfile1TokenVerifier(
100 method=method,
101 cose_alg=cose_alg,
102 signing_key=key,
103 configuration=config)
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100104 elif verifier_class == CCATokenVerifier:
105 if method != AttestationTokenVerifier.SIGN_METHOD_SIGN1:
106 logger.error('Only sign1 method is supported by this token type.\n\t'.format(verifier_class))
107 sys.exit(1)
Mate Toth-Pala8b46b12022-10-07 13:30:54 +0200108 key_checked = args.key
109 platform_token_key = read_keyfile(args.key, method)
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100110 realm_token_method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
111 platform_token_method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
Thomas Fossatif4e1ca32024-08-16 16:01:31 +0000112 realm_token_cose_alg = get_cose_alg_from_key(None, Es384)
113 platform_token_cose_alg = get_cose_alg_from_key(platform_token_key, Es384)
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100114 verifier = CCATokenVerifier(
115 realm_token_method=realm_token_method,
116 realm_token_cose_alg=realm_token_cose_alg,
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100117 platform_token_method=platform_token_method,
118 platform_token_cose_alg=platform_token_cose_alg,
119 platform_token_key=platform_token_key,
120 configuration=config)
121 elif verifier_class == CCAPlatformTokenVerifier:
Mate Toth-Pala8b46b12022-10-07 13:30:54 +0200122 key_checked = args.key
123 key = read_keyfile(args.key, method)
Thomas Fossatif4e1ca32024-08-16 16:01:31 +0000124 cose_alg = get_cose_alg_from_key(key, Es384)
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100125 verifier = CCAPlatformTokenVerifier(
126 method=AttestationTokenVerifier.SIGN_METHOD_SIGN1,
127 cose_alg=cose_alg,
128 signing_key=key,
129 configuration=config,
130 necessity=None)
Tamas Ban1e7944a2022-07-04 13:09:03 +0200131 elif verifier_class == PSA_2_0_0_TokenVerifier:
Mate Toth-Pala8b46b12022-10-07 13:30:54 +0200132 key_checked = args.key
133 key = read_keyfile(keyfile=args.key, method=method)
Tamas Ban1e7944a2022-07-04 13:09:03 +0200134 if method == AttestationTokenVerifier.SIGN_METHOD_SIGN1:
Thomas Fossatif4e1ca32024-08-16 16:01:31 +0000135 cose_alg = get_cose_alg_from_key(key, Es256)
Tamas Ban1e7944a2022-07-04 13:09:03 +0200136 else:
Thomas Fossatif4e1ca32024-08-16 16:01:31 +0000137 cose_alg = HMAC256
Tamas Ban1e7944a2022-07-04 13:09:03 +0200138 verifier = PSA_2_0_0_TokenVerifier(method=method, cose_alg=cose_alg, signing_key=key, configuration=config)
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200139 else:
140 logger.error(f'Invalid token type:{verifier_class}\n\t')
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +0200141 sys.exit(1)
142
143 try:
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200144 with open(args.tokenfile, 'rb') as token_file:
145 token = verifier.parse_token(
146 token=token_file.read(),
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200147 lower_case_key=False)
Mate Toth-Palc7404e92022-07-15 11:11:13 +0200148 token.verify()
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100149 if key_checked:
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200150 print('Signature OK')
151 print('Token format OK')
152 except ValueError as exc:
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100153 logger.error(f'Token verification failed:\n\t{exc}')
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +0200154 sys.exit(1)
155
156 if args.print_iat:
157 print('Token:')
Mate Toth-Palc7404e92022-07-15 11:11:13 +0200158 token_map = token.get_token_map()
159 json.dump(recursive_bytes_to_strings(token_map, in_place=True),
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +0200160 sys.stdout, indent=4)
161 print('')
162
163if __name__ == '__main__':
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200164 main()