blob: 919571291e2b4be93cdf83101c393e8f5563cd31 [file] [log] [blame]
Mate Toth-Pal51b61982022-03-17 14:19:30 +01001#!/usr/bin/env python3
2#-------------------------------------------------------------------------------
Mate Toth-Pal6e1d7742025-04-17 11:00:09 +02003# Copyright (c) 2019-2025, Arm Limited. All rights reserved.
Mate Toth-Pal51b61982022-03-17 14:19:30 +01004#
5# SPDX-License-Identifier: BSD-3-Clause
6#
7#-------------------------------------------------------------------------------
8
Mate Toth-Palb9057ff2022-04-29 16:03:21 +02009"""CLI tool for compiling token from a yaml file"""
10
Mate Toth-Pal51b61982022-03-17 14:19:30 +010011import argparse
12import logging
13import os
14import sys
15
Thomas Fossatif4e1ca32024-08-16 16:01:31 +000016from pycose.algorithms import Es256, Es384, HMAC256
17
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020018from iatverifier.util import read_token_map, convert_map_to_token, read_keyfile
19from iatverifier.util import get_cose_alg_from_key
Mate Toth-Pal51b61982022-03-17 14:19:30 +010020from iatverifier.psa_iot_profile1_token_verifier import PSAIoTProfile1TokenVerifier
Tamas Ban1e7944a2022-07-04 13:09:03 +020021from iatverifier.psa_2_0_0_token_verifier import PSA_2_0_0_TokenVerifier
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010022from iatverifier.attest_token_verifier import AttestationTokenVerifier, VerifierConfiguration
23from iatverifier.cca_token_verifier import CCATokenVerifier, CCAPlatformTokenVerifier
Mate Toth-Pal51b61982022-03-17 14:19:30 +010024
25if __name__ == '__main__':
26 logging.basicConfig(level=logging.INFO)
27
Mate Toth-Pal6978f7c2022-03-30 14:38:55 +020028 token_verifiers = {
29 "PSA-IoT-Profile1-token": PSAIoTProfile1TokenVerifier,
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010030 "CCA-token": CCATokenVerifier,
31 "CCA-plat-token": CCAPlatformTokenVerifier,
Tamas Ban1e7944a2022-07-04 13:09:03 +020032 "PSA-2.0.0-token": PSA_2_0_0_TokenVerifier,
Mate Toth-Pal6978f7c2022-03-30 14:38:55 +020033 }
34
Mate Toth-Pal51b61982022-03-17 14:19:30 +010035 parser = argparse.ArgumentParser()
36 parser.add_argument('source', help='Token source in YAML format')
37 parser.add_argument('-o', '--outfile',
38 help='''Output file for the compiled token. If this is not
39 specified, the token will be written to standard output.''')
Mate Toth-Pala8b46b12022-10-07 13:30:54 +020040 parser.add_argument('-k', '--key',
Mate Toth-Pal51b61982022-03-17 14:19:30 +010041 help='''Path to the key in PEM format that should be used to
42 sign the token. If this is not specified, the token will be
43 unsigned.''')
Mate Toth-Pala8b46b12022-10-07 13:30:54 +020044 parser.add_argument('--platform-key',
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010045 help='''Path to the key in PEM format that should be used to
46 sign the CCA platform token. If this is not specified,
47 the token will be unsigned.''')
Mate Toth-Pala8b46b12022-10-07 13:30:54 +020048 parser.add_argument('--realm-key',
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010049 help='''Path to the key in PEM format that should be used to
50 sign the CCA Realm token. If this is not specified, the
51 token will be unsigned.''')
Mate Toth-Pal1527a3c2022-11-30 11:27:54 +010052 parser.add_argument('-m', '--method', choices=['sign', 'mac', 'raw'], default='sign',
53 help='''
54 Specify how this token is to be wrapped -- whether Sign1Message or
55 Mac0Message COSE structure is to be used. In case of 'raw' no COSE envelope is
56 added to the compiled token.
57 ''')
Mate Toth-Pal6978f7c2022-03-30 14:38:55 +020058 parser.add_argument('-t', '--token-type',
59 help='''The type of the Token.''',
60 choices=token_verifiers.keys(),
61 required=True)
Mate Toth-Pal6e1d7742025-04-17 11:00:09 +020062 parser.add_argument('--gen-token-indicator',
63 help='''Expect token indicator in the cbor.''',
64 action='store_true')
Mate Toth-Pal51b61982022-03-17 14:19:30 +010065
66 args = parser.parse_args()
Mate Toth-Pal51b61982022-03-17 14:19:30 +010067
Mate Toth-Pal1527a3c2022-11-30 11:27:54 +010068 if args.method == 'mac':
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020069 METHOD = AttestationTokenVerifier.SIGN_METHOD_MAC0
Mate Toth-Pal1527a3c2022-11-30 11:27:54 +010070 elif args.method == 'raw':
Mate Toth-Pala8b46b12022-10-07 13:30:54 +020071 if args.key:
Mate Toth-Pal51b61982022-03-17 14:19:30 +010072 raise ValueError('A keyfile cannot be specified with --raw.')
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020073 METHOD = AttestationTokenVerifier.SIGN_METHOD_RAW
Mate Toth-Pal1527a3c2022-11-30 11:27:54 +010074 elif args.method == 'sign':
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020075 METHOD = AttestationTokenVerifier.SIGN_METHOD_SIGN1
Mate Toth-Pal1527a3c2022-11-30 11:27:54 +010076 else:
77 assert False
Mate Toth-Pal51b61982022-03-17 14:19:30 +010078
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010079 configuration = VerifierConfiguration(strict=True, keep_going=False)
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020080
81 verifier_class = token_verifiers[args.token_type]
82 if verifier_class == PSAIoTProfile1TokenVerifier:
Mate Toth-Pala8b46b12022-10-07 13:30:54 +020083 key = read_keyfile(args.key, METHOD)
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010084 if METHOD == AttestationTokenVerifier.SIGN_METHOD_SIGN1:
Thomas Fossatif4e1ca32024-08-16 16:01:31 +000085 cose_alg = get_cose_alg_from_key(key, Es256)
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010086 else:
Thomas Fossatif4e1ca32024-08-16 16:01:31 +000087 cose_alg = HMAC256
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020088 verifier = PSAIoTProfile1TokenVerifier(
89 method=METHOD,
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010090 cose_alg=cose_alg,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020091 signing_key=key,
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010092 configuration=configuration)
93 elif verifier_class == CCATokenVerifier:
94 if METHOD != AttestationTokenVerifier.SIGN_METHOD_SIGN1:
95 logging.error('Only sign1 method is supported by this token type.\n\t')
96 sys.exit(1)
Mate Toth-Pala8b46b12022-10-07 13:30:54 +020097 platform_token_key = read_keyfile(args.platform_key, METHOD)
98 realm_token_key = read_keyfile(args.realm_key, METHOD)
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010099 realm_token_method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
100 platform_token_method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
Thomas Fossatif4e1ca32024-08-16 16:01:31 +0000101 realm_token_cose_alg = get_cose_alg_from_key(realm_token_key, Es384)
102 platform_token_cose_alg = get_cose_alg_from_key(platform_token_key, Es384)
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100103 verifier = CCATokenVerifier(
104 realm_token_method=realm_token_method,
105 realm_token_cose_alg=realm_token_cose_alg,
106 realm_token_key=realm_token_key,
107 platform_token_method=platform_token_method,
108 platform_token_cose_alg=platform_token_cose_alg,
109 platform_token_key=platform_token_key,
110 configuration=configuration)
111 elif verifier_class == CCAPlatformTokenVerifier:
Mate Toth-Pala8b46b12022-10-07 13:30:54 +0200112 key_checked = args.platform_key
113 key = read_keyfile(args.platform_key, METHOD)
Thomas Fossatif4e1ca32024-08-16 16:01:31 +0000114 cose_alg = get_cose_alg_from_key(key, Es384)
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100115 verifier = CCAPlatformTokenVerifier(
116 method=AttestationTokenVerifier.SIGN_METHOD_SIGN1,
117 cose_alg=cose_alg,
118 signing_key=key,
119 configuration=configuration,
Mate Toth-Pal6e1d7742025-04-17 11:00:09 +0200120 necessity=None,
121 has_type_indicator=args.gen_token_indicator)
Tamas Ban1e7944a2022-07-04 13:09:03 +0200122 elif verifier_class == PSA_2_0_0_TokenVerifier:
Mate Toth-Pala8b46b12022-10-07 13:30:54 +0200123 key_checked = args.key
124 key = read_keyfile(keyfile=args.key, method=METHOD)
Tamas Ban1e7944a2022-07-04 13:09:03 +0200125 if METHOD == AttestationTokenVerifier.SIGN_METHOD_SIGN1:
Thomas Fossatif4e1ca32024-08-16 16:01:31 +0000126 cose_alg = get_cose_alg_from_key(key, Es256)
Tamas Ban1e7944a2022-07-04 13:09:03 +0200127 else:
Thomas Fossatif4e1ca32024-08-16 16:01:31 +0000128 cose_alg = HMAC256
Tamas Ban1e7944a2022-07-04 13:09:03 +0200129 verifier = PSA_2_0_0_TokenVerifier(
130 method=METHOD,
131 cose_alg=cose_alg,
132 signing_key=key,
133 configuration=configuration)
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200134 else:
135 logging.error(f'Invalid token type:{verifier_class}\n\t')
136 sys.exit(1)
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100137 token_map = read_token_map(args.source)
138
139 if args.outfile:
140 with open(args.outfile, 'wb') as wfh:
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200141 convert_map_to_token(
142 token_map,
143 verifier,
144 wfh,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200145 name_as_key=True,
146 parse_raw_value=True)
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100147 else:
148 with os.fdopen(sys.stdout.fileno(), 'wb') as wfh:
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200149 convert_map_to_token(
150 token_map,
151 verifier,
152 wfh,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200153 name_as_key=True,
154 parse_raw_value=True)