blob: ccea2a4a31284a5a9920d0feb6b990775106694c [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 ''')
60 parser.add_argument('-c', '--check-protected-header', action='store_true',
61 help='''
62 Check the presence and content of COSE protected header.
63 ''')
64 parser.add_argument('-m', '--method', choices=['sign', 'mac'], default='sign',
65 help='''
66 Specify how this token is wrapped -- whether Sign1Message or
67 Mac0Message COSE structure is used.
68 ''')
69 parser.add_argument('-t', '--token-type',
70 help='''The type of the Token.''',
71 choices=token_verifiers.keys(),
72 required=True)
73
74 args = parser.parse_args()
75
76 logging.basicConfig(level=logging.INFO)
77
78 config = VerifierConfiguration(keep_going=args.keep_going, strict=args.strict)
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020079 if args.method == 'mac':
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020080 method = AttestationTokenVerifier.SIGN_METHOD_MAC0
81 else:
82 method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020083
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010084 key_checked = False
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020085
86 verifier_class = token_verifiers[args.token_type]
87 if verifier_class == PSAIoTProfile1TokenVerifier:
Mate Toth-Pala8b46b12022-10-07 13:30:54 +020088 key_checked = args.key
89 key = read_keyfile(keyfile=args.key, method=method)
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010090 if method == AttestationTokenVerifier.SIGN_METHOD_SIGN1:
91 cose_alg = get_cose_alg_from_key(key, AttestationTokenVerifier.COSE_ALG_ES256)
92 else:
93 cose_alg = AttestationTokenVerifier.COSE_ALG_HS256
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020094 verifier = PSAIoTProfile1TokenVerifier(
95 method=method,
96 cose_alg=cose_alg,
97 signing_key=key,
98 configuration=config)
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010099 elif verifier_class == CCATokenVerifier:
100 if method != AttestationTokenVerifier.SIGN_METHOD_SIGN1:
101 logger.error('Only sign1 method is supported by this token type.\n\t'.format(verifier_class))
102 sys.exit(1)
Mate Toth-Pala8b46b12022-10-07 13:30:54 +0200103 key_checked = args.key
104 platform_token_key = read_keyfile(args.key, method)
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100105 realm_token_method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
106 platform_token_method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
107 realm_token_cose_alg = get_cose_alg_from_key(
Mate Toth-Palb21ae522022-09-01 12:02:21 +0200108 None,
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100109 AttestationTokenVerifier.COSE_ALG_ES384)
110 platform_token_cose_alg = get_cose_alg_from_key(
111 platform_token_key,
112 AttestationTokenVerifier.COSE_ALG_ES384)
113 verifier = CCATokenVerifier(
114 realm_token_method=realm_token_method,
115 realm_token_cose_alg=realm_token_cose_alg,
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100116 platform_token_method=platform_token_method,
117 platform_token_cose_alg=platform_token_cose_alg,
118 platform_token_key=platform_token_key,
119 configuration=config)
120 elif verifier_class == CCAPlatformTokenVerifier:
Mate Toth-Pala8b46b12022-10-07 13:30:54 +0200121 key_checked = args.key
122 key = read_keyfile(args.key, method)
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100123 cose_alg = get_cose_alg_from_key(key, AttestationTokenVerifier.COSE_ALG_ES384)
124 verifier = CCAPlatformTokenVerifier(
125 method=AttestationTokenVerifier.SIGN_METHOD_SIGN1,
126 cose_alg=cose_alg,
127 signing_key=key,
128 configuration=config,
129 necessity=None)
Tamas Ban1e7944a2022-07-04 13:09:03 +0200130 elif verifier_class == PSA_2_0_0_TokenVerifier:
Mate Toth-Pala8b46b12022-10-07 13:30:54 +0200131 key_checked = args.key
132 key = read_keyfile(keyfile=args.key, method=method)
Tamas Ban1e7944a2022-07-04 13:09:03 +0200133 if method == AttestationTokenVerifier.SIGN_METHOD_SIGN1:
134 cose_alg = get_cose_alg_from_key(key, AttestationTokenVerifier.COSE_ALG_ES256)
135 else:
136 cose_alg = AttestationTokenVerifier.COSE_ALG_HS256
137 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 +0200138 else:
139 logger.error(f'Invalid token type:{verifier_class}\n\t')
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +0200140 sys.exit(1)
141
142 try:
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200143 with open(args.tokenfile, 'rb') as token_file:
144 token = verifier.parse_token(
145 token=token_file.read(),
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200146 check_p_header=args.check_protected_header,
147 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()