blob: 4778b3902420c2b2a7d686392140013c76523ef2 [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
Mate Toth-Palbb187d02022-04-26 16:01:51 +020018from iatverifier.attest_token_verifier import VerifierConfiguration, AttestationTokenVerifier
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020019
20logger = logging.getLogger('iat-verify')
21
22def main():
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020023 """Main function for verifying an IAT"""
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020024
25 token_verifiers = {
26 "PSA-IoT-Profile1-token": PSAIoTProfile1TokenVerifier,
27 }
28
29 parser = argparse.ArgumentParser(
30 description='''
31 Validates a signed Initial Attestation Token (IAT), checking
32 that the signature is valid, the token contian the required
33 fields, and those fields are in a valid format.
34 ''')
35 parser.add_argument('-k', '--keyfile',
36 help='''
37 Path to a file containing signing key in PEM format.
38 ''')
39 parser.add_argument('tokenfile',
40 help='''
41 path to a file containing a signed IAT.
42 ''')
43 parser.add_argument('-K', '--keep-going', action='store_true',
44 help='''
45 Do not stop upon encountering a validation error.
46 ''')
47 parser.add_argument('-p', '--print-iat', action='store_true',
48 help='''
49 Print the decoded token in JSON format.
50 ''')
51 parser.add_argument('-s', '--strict', action='store_true',
52 help='''
53 Report failure if unknown claim is encountered.
54 ''')
55 parser.add_argument('-c', '--check-protected-header', action='store_true',
56 help='''
57 Check the presence and content of COSE protected header.
58 ''')
59 parser.add_argument('-m', '--method', choices=['sign', 'mac'], default='sign',
60 help='''
61 Specify how this token is wrapped -- whether Sign1Message or
62 Mac0Message COSE structure is used.
63 ''')
64 parser.add_argument('-t', '--token-type',
65 help='''The type of the Token.''',
66 choices=token_verifiers.keys(),
67 required=True)
68
69 args = parser.parse_args()
70
71 logging.basicConfig(level=logging.INFO)
72
73 config = VerifierConfiguration(keep_going=args.keep_going, strict=args.strict)
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020074 if args.method == 'mac':
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020075 method = AttestationTokenVerifier.SIGN_METHOD_MAC0
76 else:
77 method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020078
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020079 key = read_keyfile(keyfile=args.keyfile, method=method)
80
81 if args.method == 'mac':
82 cose_alg = AttestationTokenVerifier.COSE_ALG_HS256
83 else:
84 if key is not None:
85 cose_alg = get_cose_alg_from_key(key)
86 else:
87 cose_alg = AttestationTokenVerifier.COSE_ALG_ES256
88
89 verifier_class = token_verifiers[args.token_type]
90 if verifier_class == PSAIoTProfile1TokenVerifier:
91 verifier = PSAIoTProfile1TokenVerifier(
92 method=method,
93 cose_alg=cose_alg,
94 signing_key=key,
95 configuration=config)
96 else:
97 logger.error(f'Invalid token type:{verifier_class}\n\t')
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +020098 sys.exit(1)
99
100 try:
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200101 with open(args.tokenfile, 'rb') as token_file:
102 token = verifier.parse_token(
103 token=token_file.read(),
104 verify=True,
105 check_p_header=args.check_protected_header,
106 lower_case_key=False)
107 if args.keyfile:
108 print('Signature OK')
109 print('Token format OK')
110 except ValueError as exc:
111 logger.error(f'Could not extract IAT from COSE:\n\t{exc}')
Mate Toth-Pal1cb66cd2022-04-26 15:40:07 +0200112 sys.exit(1)
113
114 if args.print_iat:
115 print('Token:')
116 json.dump(recursive_bytes_to_strings(token, in_place=True),
117 sys.stdout, indent=4)
118 print('')
119
120if __name__ == '__main__':
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200121 main()