blob: 647ed0d5459a64b27bcf2119f9b930aafb08d7a7 [file] [log] [blame]
Mate Toth-Pal51b61982022-03-17 14:19:30 +01001#!/usr/bin/env python3
2#-------------------------------------------------------------------------------
3# Copyright (c) 2019-2022, Arm Limited. All rights reserved.
4#
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
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020016from iatverifier.util import read_token_map, convert_map_to_token, read_keyfile
17from iatverifier.util import get_cose_alg_from_key
Mate Toth-Pal51b61982022-03-17 14:19:30 +010018from iatverifier.psa_iot_profile1_token_verifier import PSAIoTProfile1TokenVerifier
Tamas Ban1e7944a2022-07-04 13:09:03 +020019from iatverifier.psa_2_0_0_token_verifier import PSA_2_0_0_TokenVerifier
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010020from iatverifier.attest_token_verifier import AttestationTokenVerifier, VerifierConfiguration
21from iatverifier.cca_token_verifier import CCATokenVerifier, CCAPlatformTokenVerifier
Mate Toth-Pal51b61982022-03-17 14:19:30 +010022
23if __name__ == '__main__':
24 logging.basicConfig(level=logging.INFO)
25
Mate Toth-Pal6978f7c2022-03-30 14:38:55 +020026 token_verifiers = {
27 "PSA-IoT-Profile1-token": PSAIoTProfile1TokenVerifier,
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010028 "CCA-token": CCATokenVerifier,
29 "CCA-plat-token": CCAPlatformTokenVerifier,
Tamas Ban1e7944a2022-07-04 13:09:03 +020030 "PSA-2.0.0-token": PSA_2_0_0_TokenVerifier,
Mate Toth-Pal6978f7c2022-03-30 14:38:55 +020031 }
32
Mate Toth-Pal51b61982022-03-17 14:19:30 +010033 parser = argparse.ArgumentParser()
34 parser.add_argument('source', help='Token source in YAML format')
35 parser.add_argument('-o', '--outfile',
36 help='''Output file for the compiled token. If this is not
37 specified, the token will be written to standard output.''')
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010038 parser.add_argument('--psa-iot-profile1-keyfile',
Mate Toth-Pal51b61982022-03-17 14:19:30 +010039 help='''Path to the key in PEM format that should be used to
40 sign the token. If this is not specified, the token will be
41 unsigned.''')
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010042 parser.add_argument('--cca-platform-token-keyfile',
43 help='''Path to the key in PEM format that should be used to
44 sign the CCA platform token. If this is not specified,
45 the token will be unsigned.''')
46 parser.add_argument('--cca-realm-token-keyfile',
47 help='''Path to the key in PEM format that should be used to
48 sign the CCA Realm token. If this is not specified, the
49 token will be unsigned.''')
Mate Toth-Pal51b61982022-03-17 14:19:30 +010050 group = parser.add_mutually_exclusive_group()
Mate Toth-Palbdb475e2022-04-24 12:11:22 +020051 parser.add_argument('-a', '--add-protected-header', action='store_true',
52 help='''
53 Add protected header to the COSE wrapper.
54 ''')
Mate Toth-Pal51b61982022-03-17 14:19:30 +010055 group.add_argument('-r', '--raw', action='store_true',
56 help='''Generate raw CBOR and do not create a signature
57 or COSE wrapper.''')
58 group.add_argument('-m', '--hmac', action='store_true',
59 help='''Generate a token wrapped in a Mac0 rather than
60 Sign1 COSE structure.''')
Mate Toth-Pal6978f7c2022-03-30 14:38:55 +020061 parser.add_argument('-t', '--token-type',
62 help='''The type of the Token.''',
63 choices=token_verifiers.keys(),
64 required=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-Pal51b61982022-03-17 14:19:30 +010068 if args.hmac:
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020069 METHOD = AttestationTokenVerifier.SIGN_METHOD_MAC0
Mate Toth-Pal51b61982022-03-17 14:19:30 +010070 elif args.raw:
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010071 if args.psa_iot_profile1_keyfile:
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-Pal51b61982022-03-17 14:19:30 +010074 else:
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020075 METHOD = AttestationTokenVerifier.SIGN_METHOD_SIGN1
Mate Toth-Pal51b61982022-03-17 14:19:30 +010076
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010077 configuration = VerifierConfiguration(strict=True, keep_going=False)
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020078
79 verifier_class = token_verifiers[args.token_type]
80 if verifier_class == PSAIoTProfile1TokenVerifier:
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010081 key = read_keyfile(args.psa_iot_profile1_keyfile, METHOD)
82 if METHOD == AttestationTokenVerifier.SIGN_METHOD_SIGN1:
83 cose_alg = get_cose_alg_from_key(
84 key,
85 AttestationTokenVerifier.COSE_ALG_ES256)
86 else:
87 cose_alg = AttestationTokenVerifier.COSE_ALG_HS256
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)
97 platform_token_key = read_keyfile(args.cca_platform_token_keyfile, METHOD)
98 realm_token_key = read_keyfile(args.cca_realm_token_keyfile, METHOD)
99 realm_token_method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
100 platform_token_method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
101 realm_token_cose_alg = get_cose_alg_from_key(
102 realm_token_key,
103 AttestationTokenVerifier.COSE_ALG_ES384)
104 platform_token_cose_alg = get_cose_alg_from_key(
105 platform_token_key,
106 AttestationTokenVerifier.COSE_ALG_ES384)
107 verifier = CCATokenVerifier(
108 realm_token_method=realm_token_method,
109 realm_token_cose_alg=realm_token_cose_alg,
110 realm_token_key=realm_token_key,
111 platform_token_method=platform_token_method,
112 platform_token_cose_alg=platform_token_cose_alg,
113 platform_token_key=platform_token_key,
114 configuration=configuration)
115 elif verifier_class == CCAPlatformTokenVerifier:
116 key_checked = args.cca_platform_token_keyfile
117 key = read_keyfile(args.cca_platform_token_keyfile, METHOD)
118 cose_alg = get_cose_alg_from_key(key, AttestationTokenVerifier.COSE_ALG_ES384)
119 verifier = CCAPlatformTokenVerifier(
120 method=AttestationTokenVerifier.SIGN_METHOD_SIGN1,
121 cose_alg=cose_alg,
122 signing_key=key,
123 configuration=configuration,
124 necessity=None)
Tamas Ban1e7944a2022-07-04 13:09:03 +0200125 elif verifier_class == PSA_2_0_0_TokenVerifier:
126 key_checked = args.psa_iot_profile1_keyfile
127 key = read_keyfile(keyfile=args.psa_iot_profile1_keyfile, method=METHOD)
128 if METHOD == AttestationTokenVerifier.SIGN_METHOD_SIGN1:
129 cose_alg = get_cose_alg_from_key(key, AttestationTokenVerifier.COSE_ALG_ES256)
130 else:
131 cose_alg = AttestationTokenVerifier.COSE_ALG_HS256
132 verifier = PSA_2_0_0_TokenVerifier(
133 method=METHOD,
134 cose_alg=cose_alg,
135 signing_key=key,
136 configuration=configuration)
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200137 else:
138 logging.error(f'Invalid token type:{verifier_class}\n\t')
139 sys.exit(1)
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100140 token_map = read_token_map(args.source)
141
142 if args.outfile:
143 with open(args.outfile, 'wb') as wfh:
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200144 convert_map_to_token(
145 token_map,
146 verifier,
147 wfh,
148 add_p_header=args.add_protected_header,
149 name_as_key=True,
150 parse_raw_value=True)
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100151 else:
152 with os.fdopen(sys.stdout.fileno(), 'wb') as wfh:
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200153 convert_map_to_token(
154 token_map,
155 verifier,
156 wfh,
157 add_p_header=args.add_protected_header,
158 name_as_key=True,
159 parse_raw_value=True)