blob: f3c41d03008303e33442b889d191e921c53cad44 [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.''')
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020048 parser.add_argument('tokenfile',
49 help='''
50 path to a file containing a signed IAT.
51 ''')
52 parser.add_argument('-K', '--keep-going', action='store_true',
53 help='''
54 Do not stop upon encountering a validation error.
55 ''')
56 parser.add_argument('-p', '--print-iat', action='store_true',
57 help='''
58 Print the decoded token in JSON format.
59 ''')
60 parser.add_argument('-s', '--strict', action='store_true',
61 help='''
62 Report failure if unknown claim is encountered.
63 ''')
64 parser.add_argument('-c', '--check-protected-header', action='store_true',
65 help='''
66 Check the presence and content of COSE protected header.
67 ''')
68 parser.add_argument('-m', '--method', choices=['sign', 'mac'], default='sign',
69 help='''
70 Specify how this token is wrapped -- whether Sign1Message or
71 Mac0Message COSE structure is used.
72 ''')
73 parser.add_argument('-t', '--token-type',
74 help='''The type of the Token.''',
75 choices=token_verifiers.keys(),
76 required=True)
77
78 args = parser.parse_args()
79
80 logging.basicConfig(level=logging.INFO)
81
82 config = VerifierConfiguration(keep_going=args.keep_going, strict=args.strict)
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020083 if args.method == 'mac':
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020084 method = AttestationTokenVerifier.SIGN_METHOD_MAC0
85 else:
86 method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020087
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010088 key_checked = False
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020089
90 verifier_class = token_verifiers[args.token_type]
91 if verifier_class == PSAIoTProfile1TokenVerifier:
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010092 key_checked = args.psa_iot_profile1_keyfile
93 key = read_keyfile(keyfile=args.psa_iot_profile1_keyfile, method=method)
94 if method == AttestationTokenVerifier.SIGN_METHOD_SIGN1:
95 cose_alg = get_cose_alg_from_key(key, AttestationTokenVerifier.COSE_ALG_ES256)
96 else:
97 cose_alg = AttestationTokenVerifier.COSE_ALG_HS256
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020098 verifier = PSAIoTProfile1TokenVerifier(
99 method=method,
100 cose_alg=cose_alg,
101 signing_key=key,
102 configuration=config)
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100103 elif verifier_class == CCATokenVerifier:
104 if method != AttestationTokenVerifier.SIGN_METHOD_SIGN1:
105 logger.error('Only sign1 method is supported by this token type.\n\t'.format(verifier_class))
106 sys.exit(1)
Mate Toth-Palb21ae522022-09-01 12:02:21 +0200107 key_checked = args.cca_platform_token_keyfile
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100108 platform_token_key = read_keyfile(args.cca_platform_token_keyfile, method)
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100109 realm_token_method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
110 platform_token_method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
111 realm_token_cose_alg = get_cose_alg_from_key(
Mate Toth-Palb21ae522022-09-01 12:02:21 +0200112 None,
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100113 AttestationTokenVerifier.COSE_ALG_ES384)
114 platform_token_cose_alg = get_cose_alg_from_key(
115 platform_token_key,
116 AttestationTokenVerifier.COSE_ALG_ES384)
117 verifier = CCATokenVerifier(
118 realm_token_method=realm_token_method,
119 realm_token_cose_alg=realm_token_cose_alg,
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100120 platform_token_method=platform_token_method,
121 platform_token_cose_alg=platform_token_cose_alg,
122 platform_token_key=platform_token_key,
123 configuration=config)
124 elif verifier_class == CCAPlatformTokenVerifier:
125 key_checked = args.cca_platform_token_keyfile
126 key = read_keyfile(args.cca_platform_token_keyfile, method)
127 cose_alg = get_cose_alg_from_key(key, AttestationTokenVerifier.COSE_ALG_ES384)
128 verifier = CCAPlatformTokenVerifier(
129 method=AttestationTokenVerifier.SIGN_METHOD_SIGN1,
130 cose_alg=cose_alg,
131 signing_key=key,
132 configuration=config,
133 necessity=None)
Tamas Ban1e7944a2022-07-04 13:09:03 +0200134 elif verifier_class == PSA_2_0_0_TokenVerifier:
135 key_checked = args.psa_iot_profile1_keyfile
136 key = read_keyfile(keyfile=args.psa_iot_profile1_keyfile, method=method)
137 if method == AttestationTokenVerifier.SIGN_METHOD_SIGN1:
138 cose_alg = get_cose_alg_from_key(key, AttestationTokenVerifier.COSE_ALG_ES256)
139 else:
140 cose_alg = AttestationTokenVerifier.COSE_ALG_HS256
141 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 +0200142 else:
143 logger.error(f'Invalid token type:{verifier_class}\n\t')
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +0200144 sys.exit(1)
145
146 try:
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200147 with open(args.tokenfile, 'rb') as token_file:
148 token = verifier.parse_token(
149 token=token_file.read(),
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200150 check_p_header=args.check_protected_header,
151 lower_case_key=False)
Mate Toth-Palc7404e92022-07-15 11:11:13 +0200152 token.verify()
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100153 if key_checked:
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200154 print('Signature OK')
155 print('Token format OK')
156 except ValueError as exc:
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100157 logger.error(f'Token verification failed:\n\t{exc}')
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +0200158 sys.exit(1)
159
160 if args.print_iat:
161 print('Token:')
Mate Toth-Palc7404e92022-07-15 11:11:13 +0200162 token_map = token.get_token_map()
163 json.dump(recursive_bytes_to_strings(token_map, in_place=True),
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +0200164 sys.stdout, indent=4)
165 print('')
166
167if __name__ == '__main__':
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200168 main()