blob: e9adf483e21470e94044ae625a05ae097ebbf471 [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-Pal5ebca512022-03-24 16:45:51 +010016from iatverifier.attest_token_verifier import AttestationClaim as Claim
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020017from iatverifier.util import recursive_bytes_to_strings, read_keyfile, get_cose_alg_from_key
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020018from iatverifier.psa_iot_profile1_token_verifier import PSAIoTProfile1TokenVerifier
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,
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020031 }
32
33 parser = argparse.ArgumentParser(
34 description='''
35 Validates a signed Initial Attestation Token (IAT), checking
36 that the signature is valid, the token contian the required
37 fields, and those fields are in a valid format.
38 ''')
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010039 parser.add_argument('--psa-iot-profile1-keyfile',
40 help='''Path to the key in PEM format that should be used to
41 verify the token. If this is not specified, the token signature
42 will not be checked.''')
43 parser.add_argument('--cca-platform-token-keyfile',
44 help='''Path to the key in PEM format that should be used to
45 verify the CCA platform token. If this is not specified, the
46 token signature will not be checked.''')
47 parser.add_argument('--cca-realm-token-keyfile',
48 help='''Path to the key in PEM format that should be used to
49 verify the CCA Realm token. If this is not specified, the
50 token signature will not be checked.''')
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020051 parser.add_argument('tokenfile',
52 help='''
53 path to a file containing a signed IAT.
54 ''')
55 parser.add_argument('-K', '--keep-going', action='store_true',
56 help='''
57 Do not stop upon encountering a validation error.
58 ''')
59 parser.add_argument('-p', '--print-iat', action='store_true',
60 help='''
61 Print the decoded token in JSON format.
62 ''')
63 parser.add_argument('-s', '--strict', action='store_true',
64 help='''
65 Report failure if unknown claim is encountered.
66 ''')
67 parser.add_argument('-c', '--check-protected-header', action='store_true',
68 help='''
69 Check the presence and content of COSE protected header.
70 ''')
71 parser.add_argument('-m', '--method', choices=['sign', 'mac'], default='sign',
72 help='''
73 Specify how this token is wrapped -- whether Sign1Message or
74 Mac0Message COSE structure is used.
75 ''')
76 parser.add_argument('-t', '--token-type',
77 help='''The type of the Token.''',
78 choices=token_verifiers.keys(),
79 required=True)
80
81 args = parser.parse_args()
82
83 logging.basicConfig(level=logging.INFO)
84
85 config = VerifierConfiguration(keep_going=args.keep_going, strict=args.strict)
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020086 if args.method == 'mac':
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020087 method = AttestationTokenVerifier.SIGN_METHOD_MAC0
88 else:
89 method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020090
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010091 key_checked = False
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020092
93 verifier_class = token_verifiers[args.token_type]
94 if verifier_class == PSAIoTProfile1TokenVerifier:
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010095 key_checked = args.psa_iot_profile1_keyfile
96 key = read_keyfile(keyfile=args.psa_iot_profile1_keyfile, method=method)
97 if method == AttestationTokenVerifier.SIGN_METHOD_SIGN1:
98 cose_alg = get_cose_alg_from_key(key, AttestationTokenVerifier.COSE_ALG_ES256)
99 else:
100 cose_alg = AttestationTokenVerifier.COSE_ALG_HS256
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200101 verifier = PSAIoTProfile1TokenVerifier(
102 method=method,
103 cose_alg=cose_alg,
104 signing_key=key,
105 configuration=config)
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100106 elif verifier_class == CCATokenVerifier:
107 if method != AttestationTokenVerifier.SIGN_METHOD_SIGN1:
108 logger.error('Only sign1 method is supported by this token type.\n\t'.format(verifier_class))
109 sys.exit(1)
110 key_checked = args.cca_platform_token_keyfile and args.cca_realm_token_keyfile
111 platform_token_key = read_keyfile(args.cca_platform_token_keyfile, method)
112 realm_token_key = read_keyfile(args.cca_realm_token_keyfile, method)
113 realm_token_method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
114 platform_token_method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
115 realm_token_cose_alg = get_cose_alg_from_key(
116 realm_token_key,
117 AttestationTokenVerifier.COSE_ALG_ES384)
118 platform_token_cose_alg = get_cose_alg_from_key(
119 platform_token_key,
120 AttestationTokenVerifier.COSE_ALG_ES384)
121 verifier = CCATokenVerifier(
122 realm_token_method=realm_token_method,
123 realm_token_cose_alg=realm_token_cose_alg,
124 realm_token_key=realm_token_key,
125 platform_token_method=platform_token_method,
126 platform_token_cose_alg=platform_token_cose_alg,
127 platform_token_key=platform_token_key,
128 configuration=config)
129 elif verifier_class == CCAPlatformTokenVerifier:
130 key_checked = args.cca_platform_token_keyfile
131 key = read_keyfile(args.cca_platform_token_keyfile, method)
132 cose_alg = get_cose_alg_from_key(key, AttestationTokenVerifier.COSE_ALG_ES384)
133 verifier = CCAPlatformTokenVerifier(
134 method=AttestationTokenVerifier.SIGN_METHOD_SIGN1,
135 cose_alg=cose_alg,
136 signing_key=key,
137 configuration=config,
138 necessity=None)
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(),
147 verify=True,
148 check_p_header=args.check_protected_header,
149 lower_case_key=False)
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100150 if key_checked:
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200151 print('Signature OK')
152 print('Token format OK')
153 except ValueError as exc:
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100154 logger.error(f'Token verification failed:\n\t{exc}')
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +0200155 sys.exit(1)
156
157 if args.print_iat:
158 print('Token:')
159 json.dump(recursive_bytes_to_strings(token, in_place=True),
160 sys.stdout, indent=4)
161 print('')
162
163if __name__ == '__main__':
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200164 main()