blob: ca47e9112827906749eb592dbf8f58b33c7c6d88 [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
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020016from iatverifier.util import recursive_bytes_to_strings, read_keyfile, get_cose_alg_from_key
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020017from iatverifier.psa_iot_profile1_token_verifier import PSAIoTProfile1TokenVerifier
Tamas Ban1e7944a2022-07-04 13:09:03 +020018from iatverifier.psa_2_0_0_token_verifier import PSA_2_0_0_TokenVerifier
Mate Toth-Palbb187d02022-04-26 16:01:51 +020019from iatverifier.attest_token_verifier import VerifierConfiguration, AttestationTokenVerifier
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010020from iatverifier.cca_token_verifier import CCATokenVerifier, CCAPlatformTokenVerifier
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020021
22logger = logging.getLogger('iat-verify')
23
24def main():
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020025 """Main function for verifying an IAT"""
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020026
27 token_verifiers = {
28 "PSA-IoT-Profile1-token": PSAIoTProfile1TokenVerifier,
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010029 "CCA-token": CCATokenVerifier,
30 "CCA-plat-token": CCAPlatformTokenVerifier,
Tamas Ban1e7944a2022-07-04 13:09:03 +020031 "PSA-2.0.0-token": PSA_2_0_0_TokenVerifier,
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020032 }
33
34 parser = argparse.ArgumentParser(
35 description='''
36 Validates a signed Initial Attestation Token (IAT), checking
37 that the signature is valid, the token contian the required
38 fields, and those fields are in a valid format.
39 ''')
Mate Toth-Pala8b46b12022-10-07 13:30:54 +020040 parser.add_argument('-k', '--key',
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010041 help='''Path to the key in PEM format that should be used to
42 verify the token. If this is not specified, the token signature
43 will not be checked.''')
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020044 parser.add_argument('tokenfile',
45 help='''
46 path to a file containing a signed IAT.
47 ''')
48 parser.add_argument('-K', '--keep-going', action='store_true',
49 help='''
50 Do not stop upon encountering a validation error.
51 ''')
52 parser.add_argument('-p', '--print-iat', action='store_true',
53 help='''
54 Print the decoded token in JSON format.
55 ''')
56 parser.add_argument('-s', '--strict', action='store_true',
57 help='''
58 Report failure if unknown claim is encountered.
59 ''')
Mate Toth-Pal1527a3c2022-11-30 11:27:54 +010060 parser.add_argument('-m', '--method', choices=['sign', 'mac', 'raw'], default='sign',
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020061 help='''
62 Specify how this token is wrapped -- whether Sign1Message or
Mate Toth-Pal1527a3c2022-11-30 11:27:54 +010063 Mac0Message COSE structure is used. In case of 'raw' no COSE envelope is
64 expected.
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020065 ''')
66 parser.add_argument('-t', '--token-type',
67 help='''The type of the Token.''',
68 choices=token_verifiers.keys(),
69 required=True)
70
71 args = parser.parse_args()
72
73 logging.basicConfig(level=logging.INFO)
74
75 config = VerifierConfiguration(keep_going=args.keep_going, strict=args.strict)
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020076 if args.method == 'mac':
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020077 method = AttestationTokenVerifier.SIGN_METHOD_MAC0
Mate Toth-Pal1527a3c2022-11-30 11:27:54 +010078 elif args.method == 'raw':
79 if args.key:
80 raise ValueError('A keyfile cannot be specified with --raw.')
81 method = AttestationTokenVerifier.SIGN_METHOD_RAW
82 elif args.method == 'sign':
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020083 method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
Mate Toth-Pal1527a3c2022-11-30 11:27:54 +010084 else:
85 assert False
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020086
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010087 key_checked = False
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020088
89 verifier_class = token_verifiers[args.token_type]
90 if verifier_class == PSAIoTProfile1TokenVerifier:
Mate Toth-Pala8b46b12022-10-07 13:30:54 +020091 key_checked = args.key
92 key = read_keyfile(keyfile=args.key, method=method)
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010093 if method == AttestationTokenVerifier.SIGN_METHOD_SIGN1:
94 cose_alg = get_cose_alg_from_key(key, AttestationTokenVerifier.COSE_ALG_ES256)
95 else:
96 cose_alg = AttestationTokenVerifier.COSE_ALG_HS256
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020097 verifier = PSAIoTProfile1TokenVerifier(
98 method=method,
99 cose_alg=cose_alg,
100 signing_key=key,
101 configuration=config)
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100102 elif verifier_class == CCATokenVerifier:
103 if method != AttestationTokenVerifier.SIGN_METHOD_SIGN1:
104 logger.error('Only sign1 method is supported by this token type.\n\t'.format(verifier_class))
105 sys.exit(1)
Mate Toth-Pala8b46b12022-10-07 13:30:54 +0200106 key_checked = args.key
107 platform_token_key = read_keyfile(args.key, method)
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100108 realm_token_method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
109 platform_token_method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
110 realm_token_cose_alg = get_cose_alg_from_key(
Mate Toth-Palb21ae522022-09-01 12:02:21 +0200111 None,
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100112 AttestationTokenVerifier.COSE_ALG_ES384)
113 platform_token_cose_alg = get_cose_alg_from_key(
114 platform_token_key,
115 AttestationTokenVerifier.COSE_ALG_ES384)
116 verifier = CCATokenVerifier(
117 realm_token_method=realm_token_method,
118 realm_token_cose_alg=realm_token_cose_alg,
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100119 platform_token_method=platform_token_method,
120 platform_token_cose_alg=platform_token_cose_alg,
121 platform_token_key=platform_token_key,
122 configuration=config)
123 elif verifier_class == CCAPlatformTokenVerifier:
Mate Toth-Pala8b46b12022-10-07 13:30:54 +0200124 key_checked = args.key
125 key = read_keyfile(args.key, method)
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100126 cose_alg = get_cose_alg_from_key(key, AttestationTokenVerifier.COSE_ALG_ES384)
127 verifier = CCAPlatformTokenVerifier(
128 method=AttestationTokenVerifier.SIGN_METHOD_SIGN1,
129 cose_alg=cose_alg,
130 signing_key=key,
131 configuration=config,
132 necessity=None)
Tamas Ban1e7944a2022-07-04 13:09:03 +0200133 elif verifier_class == PSA_2_0_0_TokenVerifier:
Mate Toth-Pala8b46b12022-10-07 13:30:54 +0200134 key_checked = args.key
135 key = read_keyfile(keyfile=args.key, method=method)
Tamas Ban1e7944a2022-07-04 13:09:03 +0200136 if method == AttestationTokenVerifier.SIGN_METHOD_SIGN1:
137 cose_alg = get_cose_alg_from_key(key, AttestationTokenVerifier.COSE_ALG_ES256)
138 else:
139 cose_alg = AttestationTokenVerifier.COSE_ALG_HS256
140 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 +0200141 else:
142 logger.error(f'Invalid token type:{verifier_class}\n\t')
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +0200143 sys.exit(1)
144
145 try:
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200146 with open(args.tokenfile, 'rb') as token_file:
147 token = verifier.parse_token(
148 token=token_file.read(),
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200149 lower_case_key=False)
Mate Toth-Palc7404e92022-07-15 11:11:13 +0200150 token.verify()
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100151 if key_checked:
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200152 print('Signature OK')
153 print('Token format OK')
154 except ValueError as exc:
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100155 logger.error(f'Token verification failed:\n\t{exc}')
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +0200156 sys.exit(1)
157
158 if args.print_iat:
159 print('Token:')
Mate Toth-Palc7404e92022-07-15 11:11:13 +0200160 token_map = token.get_token_map()
161 json.dump(recursive_bytes_to_strings(token_map, in_place=True),
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +0200162 sys.stdout, indent=4)
163 print('')
164
165if __name__ == '__main__':
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200166 main()