blob: 80a1dfc226c776c09a0257b2e322d0d623036f98 [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-Pal5ebca512022-03-24 16:45:51 +010040 parser.add_argument('--psa-iot-profile1-keyfile',
41 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.''')
44 parser.add_argument('--cca-platform-token-keyfile',
45 help='''Path to the key in PEM format that should be used to
46 verify the CCA platform token. If this is not specified, the
47 token signature will not be checked.''')
48 parser.add_argument('--cca-realm-token-keyfile',
49 help='''Path to the key in PEM format that should be used to
50 verify the CCA Realm token. If this is not specified, the
51 token signature will not be checked.''')
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020052 parser.add_argument('tokenfile',
53 help='''
54 path to a file containing a signed IAT.
55 ''')
56 parser.add_argument('-K', '--keep-going', action='store_true',
57 help='''
58 Do not stop upon encountering a validation error.
59 ''')
60 parser.add_argument('-p', '--print-iat', action='store_true',
61 help='''
62 Print the decoded token in JSON format.
63 ''')
64 parser.add_argument('-s', '--strict', action='store_true',
65 help='''
66 Report failure if unknown claim is encountered.
67 ''')
68 parser.add_argument('-c', '--check-protected-header', action='store_true',
69 help='''
70 Check the presence and content of COSE protected header.
71 ''')
72 parser.add_argument('-m', '--method', choices=['sign', 'mac'], default='sign',
73 help='''
74 Specify how this token is wrapped -- whether Sign1Message or
75 Mac0Message COSE structure is used.
76 ''')
77 parser.add_argument('-t', '--token-type',
78 help='''The type of the Token.''',
79 choices=token_verifiers.keys(),
80 required=True)
81
82 args = parser.parse_args()
83
84 logging.basicConfig(level=logging.INFO)
85
86 config = VerifierConfiguration(keep_going=args.keep_going, strict=args.strict)
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020087 if args.method == 'mac':
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020088 method = AttestationTokenVerifier.SIGN_METHOD_MAC0
89 else:
90 method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020091
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010092 key_checked = False
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020093
94 verifier_class = token_verifiers[args.token_type]
95 if verifier_class == PSAIoTProfile1TokenVerifier:
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010096 key_checked = args.psa_iot_profile1_keyfile
97 key = read_keyfile(keyfile=args.psa_iot_profile1_keyfile, method=method)
98 if method == AttestationTokenVerifier.SIGN_METHOD_SIGN1:
99 cose_alg = get_cose_alg_from_key(key, AttestationTokenVerifier.COSE_ALG_ES256)
100 else:
101 cose_alg = AttestationTokenVerifier.COSE_ALG_HS256
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200102 verifier = PSAIoTProfile1TokenVerifier(
103 method=method,
104 cose_alg=cose_alg,
105 signing_key=key,
106 configuration=config)
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100107 elif verifier_class == CCATokenVerifier:
108 if method != AttestationTokenVerifier.SIGN_METHOD_SIGN1:
109 logger.error('Only sign1 method is supported by this token type.\n\t'.format(verifier_class))
110 sys.exit(1)
111 key_checked = args.cca_platform_token_keyfile and args.cca_realm_token_keyfile
112 platform_token_key = read_keyfile(args.cca_platform_token_keyfile, method)
113 realm_token_key = read_keyfile(args.cca_realm_token_keyfile, method)
114 realm_token_method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
115 platform_token_method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
116 realm_token_cose_alg = get_cose_alg_from_key(
117 realm_token_key,
118 AttestationTokenVerifier.COSE_ALG_ES384)
119 platform_token_cose_alg = get_cose_alg_from_key(
120 platform_token_key,
121 AttestationTokenVerifier.COSE_ALG_ES384)
122 verifier = CCATokenVerifier(
123 realm_token_method=realm_token_method,
124 realm_token_cose_alg=realm_token_cose_alg,
125 realm_token_key=realm_token_key,
126 platform_token_method=platform_token_method,
127 platform_token_cose_alg=platform_token_cose_alg,
128 platform_token_key=platform_token_key,
129 configuration=config)
130 elif verifier_class == CCAPlatformTokenVerifier:
131 key_checked = args.cca_platform_token_keyfile
132 key = read_keyfile(args.cca_platform_token_keyfile, method)
133 cose_alg = get_cose_alg_from_key(key, AttestationTokenVerifier.COSE_ALG_ES384)
134 verifier = CCAPlatformTokenVerifier(
135 method=AttestationTokenVerifier.SIGN_METHOD_SIGN1,
136 cose_alg=cose_alg,
137 signing_key=key,
138 configuration=config,
139 necessity=None)
Tamas Ban1e7944a2022-07-04 13:09:03 +0200140 elif verifier_class == PSA_2_0_0_TokenVerifier:
141 key_checked = args.psa_iot_profile1_keyfile
142 key = read_keyfile(keyfile=args.psa_iot_profile1_keyfile, method=method)
143 if method == AttestationTokenVerifier.SIGN_METHOD_SIGN1:
144 cose_alg = get_cose_alg_from_key(key, AttestationTokenVerifier.COSE_ALG_ES256)
145 else:
146 cose_alg = AttestationTokenVerifier.COSE_ALG_HS256
147 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 +0200148 else:
149 logger.error(f'Invalid token type:{verifier_class}\n\t')
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +0200150 sys.exit(1)
151
152 try:
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200153 with open(args.tokenfile, 'rb') as token_file:
154 token = verifier.parse_token(
155 token=token_file.read(),
156 verify=True,
157 check_p_header=args.check_protected_header,
158 lower_case_key=False)
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100159 if key_checked:
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200160 print('Signature OK')
161 print('Token format OK')
162 except ValueError as exc:
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100163 logger.error(f'Token verification failed:\n\t{exc}')
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +0200164 sys.exit(1)
165
166 if args.print_iat:
167 print('Token:')
168 json.dump(recursive_bytes_to_strings(token, in_place=True),
169 sys.stdout, indent=4)
170 print('')
171
172if __name__ == '__main__':
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200173 main()