Mate Toth-Pal | 51b6198 | 2022-03-17 14:19:30 +0100 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
| 2 | #------------------------------------------------------------------------------- |
Mate Toth-Pal | 6e1d774 | 2025-04-17 11:00:09 +0200 | [diff] [blame] | 3 | # Copyright (c) 2019-2025, Arm Limited. All rights reserved. |
Mate Toth-Pal | 51b6198 | 2022-03-17 14:19:30 +0100 | [diff] [blame] | 4 | # |
| 5 | # SPDX-License-Identifier: BSD-3-Clause |
| 6 | # |
| 7 | #------------------------------------------------------------------------------- |
| 8 | |
Mate Toth-Pal | b9057ff | 2022-04-29 16:03:21 +0200 | [diff] [blame] | 9 | """CLI tool for compiling token from a yaml file""" |
| 10 | |
Mate Toth-Pal | 51b6198 | 2022-03-17 14:19:30 +0100 | [diff] [blame] | 11 | import argparse |
| 12 | import logging |
| 13 | import os |
| 14 | import sys |
| 15 | |
Thomas Fossati | f4e1ca3 | 2024-08-16 16:01:31 +0000 | [diff] [blame] | 16 | from pycose.algorithms import Es256, Es384, HMAC256 |
| 17 | |
Mate Toth-Pal | b9057ff | 2022-04-29 16:03:21 +0200 | [diff] [blame] | 18 | from iatverifier.util import read_token_map, convert_map_to_token, read_keyfile |
| 19 | from iatverifier.util import get_cose_alg_from_key |
Mate Toth-Pal | 51b6198 | 2022-03-17 14:19:30 +0100 | [diff] [blame] | 20 | from iatverifier.psa_iot_profile1_token_verifier import PSAIoTProfile1TokenVerifier |
Tamas Ban | 1e7944a | 2022-07-04 13:09:03 +0200 | [diff] [blame] | 21 | from iatverifier.psa_2_0_0_token_verifier import PSA_2_0_0_TokenVerifier |
Mate Toth-Pal | 5ebca51 | 2022-03-24 16:45:51 +0100 | [diff] [blame] | 22 | from iatverifier.attest_token_verifier import AttestationTokenVerifier, VerifierConfiguration |
| 23 | from iatverifier.cca_token_verifier import CCATokenVerifier, CCAPlatformTokenVerifier |
Mate Toth-Pal | 51b6198 | 2022-03-17 14:19:30 +0100 | [diff] [blame] | 24 | |
| 25 | if __name__ == '__main__': |
| 26 | logging.basicConfig(level=logging.INFO) |
| 27 | |
Mate Toth-Pal | 6978f7c | 2022-03-30 14:38:55 +0200 | [diff] [blame] | 28 | token_verifiers = { |
| 29 | "PSA-IoT-Profile1-token": PSAIoTProfile1TokenVerifier, |
Mate Toth-Pal | 5ebca51 | 2022-03-24 16:45:51 +0100 | [diff] [blame] | 30 | "CCA-token": CCATokenVerifier, |
| 31 | "CCA-plat-token": CCAPlatformTokenVerifier, |
Tamas Ban | 1e7944a | 2022-07-04 13:09:03 +0200 | [diff] [blame] | 32 | "PSA-2.0.0-token": PSA_2_0_0_TokenVerifier, |
Mate Toth-Pal | 6978f7c | 2022-03-30 14:38:55 +0200 | [diff] [blame] | 33 | } |
| 34 | |
Mate Toth-Pal | 51b6198 | 2022-03-17 14:19:30 +0100 | [diff] [blame] | 35 | 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-Pal | a8b46b1 | 2022-10-07 13:30:54 +0200 | [diff] [blame] | 40 | parser.add_argument('-k', '--key', |
Mate Toth-Pal | 51b6198 | 2022-03-17 14:19:30 +0100 | [diff] [blame] | 41 | 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-Pal | a8b46b1 | 2022-10-07 13:30:54 +0200 | [diff] [blame] | 44 | parser.add_argument('--platform-key', |
Mate Toth-Pal | 5ebca51 | 2022-03-24 16:45:51 +0100 | [diff] [blame] | 45 | 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-Pal | a8b46b1 | 2022-10-07 13:30:54 +0200 | [diff] [blame] | 48 | parser.add_argument('--realm-key', |
Mate Toth-Pal | 5ebca51 | 2022-03-24 16:45:51 +0100 | [diff] [blame] | 49 | 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-Pal | 1527a3c | 2022-11-30 11:27:54 +0100 | [diff] [blame] | 52 | 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-Pal | 6978f7c | 2022-03-30 14:38:55 +0200 | [diff] [blame] | 58 | parser.add_argument('-t', '--token-type', |
| 59 | help='''The type of the Token.''', |
| 60 | choices=token_verifiers.keys(), |
| 61 | required=True) |
Mate Toth-Pal | 6e1d774 | 2025-04-17 11:00:09 +0200 | [diff] [blame] | 62 | parser.add_argument('--gen-token-indicator', |
| 63 | help='''Expect token indicator in the cbor.''', |
| 64 | action='store_true') |
Mate Toth-Pal | 51b6198 | 2022-03-17 14:19:30 +0100 | [diff] [blame] | 65 | |
| 66 | args = parser.parse_args() |
Mate Toth-Pal | 51b6198 | 2022-03-17 14:19:30 +0100 | [diff] [blame] | 67 | |
Mate Toth-Pal | 1527a3c | 2022-11-30 11:27:54 +0100 | [diff] [blame] | 68 | if args.method == 'mac': |
Mate Toth-Pal | b9057ff | 2022-04-29 16:03:21 +0200 | [diff] [blame] | 69 | METHOD = AttestationTokenVerifier.SIGN_METHOD_MAC0 |
Mate Toth-Pal | 1527a3c | 2022-11-30 11:27:54 +0100 | [diff] [blame] | 70 | elif args.method == 'raw': |
Mate Toth-Pal | a8b46b1 | 2022-10-07 13:30:54 +0200 | [diff] [blame] | 71 | if args.key: |
Mate Toth-Pal | 51b6198 | 2022-03-17 14:19:30 +0100 | [diff] [blame] | 72 | raise ValueError('A keyfile cannot be specified with --raw.') |
Mate Toth-Pal | b9057ff | 2022-04-29 16:03:21 +0200 | [diff] [blame] | 73 | METHOD = AttestationTokenVerifier.SIGN_METHOD_RAW |
Mate Toth-Pal | 1527a3c | 2022-11-30 11:27:54 +0100 | [diff] [blame] | 74 | elif args.method == 'sign': |
Mate Toth-Pal | b9057ff | 2022-04-29 16:03:21 +0200 | [diff] [blame] | 75 | METHOD = AttestationTokenVerifier.SIGN_METHOD_SIGN1 |
Mate Toth-Pal | 1527a3c | 2022-11-30 11:27:54 +0100 | [diff] [blame] | 76 | else: |
| 77 | assert False |
Mate Toth-Pal | 51b6198 | 2022-03-17 14:19:30 +0100 | [diff] [blame] | 78 | |
Mate Toth-Pal | 5ebca51 | 2022-03-24 16:45:51 +0100 | [diff] [blame] | 79 | configuration = VerifierConfiguration(strict=True, keep_going=False) |
Mate Toth-Pal | b9057ff | 2022-04-29 16:03:21 +0200 | [diff] [blame] | 80 | |
| 81 | verifier_class = token_verifiers[args.token_type] |
| 82 | if verifier_class == PSAIoTProfile1TokenVerifier: |
Mate Toth-Pal | a8b46b1 | 2022-10-07 13:30:54 +0200 | [diff] [blame] | 83 | key = read_keyfile(args.key, METHOD) |
Mate Toth-Pal | 5ebca51 | 2022-03-24 16:45:51 +0100 | [diff] [blame] | 84 | if METHOD == AttestationTokenVerifier.SIGN_METHOD_SIGN1: |
Thomas Fossati | f4e1ca3 | 2024-08-16 16:01:31 +0000 | [diff] [blame] | 85 | cose_alg = get_cose_alg_from_key(key, Es256) |
Mate Toth-Pal | 5ebca51 | 2022-03-24 16:45:51 +0100 | [diff] [blame] | 86 | else: |
Thomas Fossati | f4e1ca3 | 2024-08-16 16:01:31 +0000 | [diff] [blame] | 87 | cose_alg = HMAC256 |
Mate Toth-Pal | b9057ff | 2022-04-29 16:03:21 +0200 | [diff] [blame] | 88 | verifier = PSAIoTProfile1TokenVerifier( |
| 89 | method=METHOD, |
Mate Toth-Pal | 5ebca51 | 2022-03-24 16:45:51 +0100 | [diff] [blame] | 90 | cose_alg=cose_alg, |
Mate Toth-Pal | b9057ff | 2022-04-29 16:03:21 +0200 | [diff] [blame] | 91 | signing_key=key, |
Mate Toth-Pal | 5ebca51 | 2022-03-24 16:45:51 +0100 | [diff] [blame] | 92 | 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-Pal | a8b46b1 | 2022-10-07 13:30:54 +0200 | [diff] [blame] | 97 | platform_token_key = read_keyfile(args.platform_key, METHOD) |
| 98 | realm_token_key = read_keyfile(args.realm_key, METHOD) |
Mate Toth-Pal | 5ebca51 | 2022-03-24 16:45:51 +0100 | [diff] [blame] | 99 | realm_token_method = AttestationTokenVerifier.SIGN_METHOD_SIGN1 |
| 100 | platform_token_method = AttestationTokenVerifier.SIGN_METHOD_SIGN1 |
Thomas Fossati | f4e1ca3 | 2024-08-16 16:01:31 +0000 | [diff] [blame] | 101 | 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-Pal | 5ebca51 | 2022-03-24 16:45:51 +0100 | [diff] [blame] | 103 | 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-Pal | a8b46b1 | 2022-10-07 13:30:54 +0200 | [diff] [blame] | 112 | key_checked = args.platform_key |
| 113 | key = read_keyfile(args.platform_key, METHOD) |
Thomas Fossati | f4e1ca3 | 2024-08-16 16:01:31 +0000 | [diff] [blame] | 114 | cose_alg = get_cose_alg_from_key(key, Es384) |
Mate Toth-Pal | 5ebca51 | 2022-03-24 16:45:51 +0100 | [diff] [blame] | 115 | verifier = CCAPlatformTokenVerifier( |
| 116 | method=AttestationTokenVerifier.SIGN_METHOD_SIGN1, |
| 117 | cose_alg=cose_alg, |
| 118 | signing_key=key, |
| 119 | configuration=configuration, |
Mate Toth-Pal | 6e1d774 | 2025-04-17 11:00:09 +0200 | [diff] [blame] | 120 | necessity=None, |
| 121 | has_type_indicator=args.gen_token_indicator) |
Tamas Ban | 1e7944a | 2022-07-04 13:09:03 +0200 | [diff] [blame] | 122 | elif verifier_class == PSA_2_0_0_TokenVerifier: |
Mate Toth-Pal | a8b46b1 | 2022-10-07 13:30:54 +0200 | [diff] [blame] | 123 | key_checked = args.key |
| 124 | key = read_keyfile(keyfile=args.key, method=METHOD) |
Tamas Ban | 1e7944a | 2022-07-04 13:09:03 +0200 | [diff] [blame] | 125 | if METHOD == AttestationTokenVerifier.SIGN_METHOD_SIGN1: |
Thomas Fossati | f4e1ca3 | 2024-08-16 16:01:31 +0000 | [diff] [blame] | 126 | cose_alg = get_cose_alg_from_key(key, Es256) |
Tamas Ban | 1e7944a | 2022-07-04 13:09:03 +0200 | [diff] [blame] | 127 | else: |
Thomas Fossati | f4e1ca3 | 2024-08-16 16:01:31 +0000 | [diff] [blame] | 128 | cose_alg = HMAC256 |
Tamas Ban | 1e7944a | 2022-07-04 13:09:03 +0200 | [diff] [blame] | 129 | verifier = PSA_2_0_0_TokenVerifier( |
| 130 | method=METHOD, |
| 131 | cose_alg=cose_alg, |
| 132 | signing_key=key, |
| 133 | configuration=configuration) |
Mate Toth-Pal | b9057ff | 2022-04-29 16:03:21 +0200 | [diff] [blame] | 134 | else: |
| 135 | logging.error(f'Invalid token type:{verifier_class}\n\t') |
| 136 | sys.exit(1) |
Mate Toth-Pal | 51b6198 | 2022-03-17 14:19:30 +0100 | [diff] [blame] | 137 | token_map = read_token_map(args.source) |
| 138 | |
| 139 | if args.outfile: |
| 140 | with open(args.outfile, 'wb') as wfh: |
Mate Toth-Pal | b9057ff | 2022-04-29 16:03:21 +0200 | [diff] [blame] | 141 | convert_map_to_token( |
| 142 | token_map, |
| 143 | verifier, |
| 144 | wfh, |
Mate Toth-Pal | b9057ff | 2022-04-29 16:03:21 +0200 | [diff] [blame] | 145 | name_as_key=True, |
| 146 | parse_raw_value=True) |
Mate Toth-Pal | 51b6198 | 2022-03-17 14:19:30 +0100 | [diff] [blame] | 147 | else: |
| 148 | with os.fdopen(sys.stdout.fileno(), 'wb') as wfh: |
Mate Toth-Pal | b9057ff | 2022-04-29 16:03:21 +0200 | [diff] [blame] | 149 | convert_map_to_token( |
| 150 | token_map, |
| 151 | verifier, |
| 152 | wfh, |
Mate Toth-Pal | b9057ff | 2022-04-29 16:03:21 +0200 | [diff] [blame] | 153 | name_as_key=True, |
| 154 | parse_raw_value=True) |