blob: a95eadefe647c1c9e9ad0d608a1d3f3c49cd739b [file] [log] [blame]
Mate Toth-Pal51b61982022-03-17 14:19:30 +01001# -----------------------------------------------------------------------------
2# Copyright (c) 2019-2022, Arm Limited. All rights reserved.
Thomas Fossati833ca652024-04-26 08:47:09 +00003# Copyright (c) 2024, Linaro 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"""Helper utilities for CLI tools and tests"""
10
Mate Toth-Pal51b61982022-03-17 14:19:30 +010011from collections.abc import Iterable
12from copy import deepcopy
13import logging
14
15import base64
Mate Toth-Pal51b61982022-03-17 14:19:30 +010016import yaml
Thomas Fossati833ca652024-04-26 08:47:09 +000017import yaml_include
Mate Toth-Pal51b61982022-03-17 14:19:30 +010018from ecdsa import SigningKey, VerifyingKey
Mate Toth-Palbb187d02022-04-26 16:01:51 +020019from iatverifier.attest_token_verifier import AttestationTokenVerifier
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020020from cbor2 import CBOREncoder
Mate Toth-Pal51b61982022-03-17 14:19:30 +010021
22_logger = logging.getLogger("util")
23
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020024_known_curves = {
25 "NIST256p": AttestationTokenVerifier.COSE_ALG_ES256,
26 "NIST384p": AttestationTokenVerifier.COSE_ALG_ES384,
27 "NIST521p": AttestationTokenVerifier.COSE_ALG_ES512,
28}
29
Mate Toth-Pale305e552022-10-07 14:04:53 +020030def convert_map_to_token(token_map, verifier, wfh, *, name_as_key, parse_raw_value):
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020031 """
32 Convert a map to token and write the result to a file.
33 """
34 encoder = CBOREncoder(wfh)
35 verifier.convert_map_to_token(
36 encoder,
37 token_map,
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020038 name_as_key=name_as_key,
39 parse_raw_value=parse_raw_value,
40 root=True)
Mate Toth-Pal51b61982022-03-17 14:19:30 +010041
42
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020043def read_token_map(file):
44 """
45 Read a yaml file and return a map
46 """
Thomas Fossati833ca652024-04-26 08:47:09 +000047 yaml.add_constructor("!inc", yaml_include.Constructor(base_dir='.'), Loader=yaml.SafeLoader)
48
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020049 if hasattr(file, 'read'):
Thomas Fossati833ca652024-04-26 08:47:09 +000050 raw = yaml.load(file, Loader=yaml.SafeLoader)
Mate Toth-Pal51b61982022-03-17 14:19:30 +010051 else:
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020052 with open(file, encoding="utf8") as file_obj:
Thomas Fossati833ca652024-04-26 08:47:09 +000053 raw = yaml.load(file_obj, Loader=yaml.SafeLoader)
Mate Toth-Pal51b61982022-03-17 14:19:30 +010054
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020055 return raw
Mate Toth-Pal51b61982022-03-17 14:19:30 +010056
57
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020058def recursive_bytes_to_strings(token, in_place=False):
59 """
60 Transform the map in 'token' by changing changing bytes to base64 encoded form.
Mate Toth-Pal51b61982022-03-17 14:19:30 +010061
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020062 if 'in_place' is True, 'token' is modified, a new map is returned otherwise.
63 """
Mate Toth-Pal51b61982022-03-17 14:19:30 +010064 if in_place:
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020065 result = token
Mate Toth-Pal51b61982022-03-17 14:19:30 +010066 else:
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020067 result = deepcopy(token)
Mate Toth-Pal51b61982022-03-17 14:19:30 +010068
69 if hasattr(result, 'items'):
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020070 for key, value in result.items():
71 result[key] = recursive_bytes_to_strings(value, in_place=True)
Mate Toth-Pal51b61982022-03-17 14:19:30 +010072 elif (isinstance(result, Iterable) and
73 not isinstance(result, (str, bytes))):
74 result = [recursive_bytes_to_strings(r, in_place=True)
75 for r in result]
76 elif isinstance(result, bytes):
77 result = str(base64.b16encode(result))
78
79 return result
80
81
82def read_keyfile(keyfile, method=AttestationTokenVerifier.SIGN_METHOD_SIGN1):
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020083 """
84 Read a keyfile and return the key
85 """
Mate Toth-Pal51b61982022-03-17 14:19:30 +010086 if keyfile:
87 if method == AttestationTokenVerifier.SIGN_METHOD_SIGN1:
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020088 return _read_sign1_key(keyfile)
Mate Toth-Pal51b61982022-03-17 14:19:30 +010089 if method == AttestationTokenVerifier.SIGN_METHOD_MAC0:
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020090 return _read_hmac_key(keyfile)
Mate Toth-Pal51b61982022-03-17 14:19:30 +010091 err_msg = 'Unexpected method "{}"; must be one of: sign, mac'
92 raise ValueError(err_msg.format(method))
93
94 return None
95
Mate Toth-Pal5ebca512022-03-24 16:45:51 +010096def get_cose_alg_from_key(key, default):
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020097 """Extract the algorithm from the key if possible
Mate Toth-Pal51b61982022-03-17 14:19:30 +010098
Mate Toth-Palb9057ff2022-04-29 16:03:21 +020099 Returns the signature algorithm ID defined by COSE
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100100 If key is None, default is returned.
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200101 """
Mate Toth-Pal5ebca512022-03-24 16:45:51 +0100102 if key is None:
103 return default
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200104 if not hasattr(key, "curve"):
105 raise ValueError("Key has no curve specified in it.")
106 return _known_curves[key.curve.name]
107
108def _read_sign1_key(keyfile):
109 with open(keyfile, 'rb') as file_obj:
110 raw_key = file_obj.read()
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100111 try:
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200112 key = SigningKey.from_pem(raw_key)
113 except Exception as exc:
114 signing_key_error = str(exc)
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100115
116 try:
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200117 key = VerifyingKey.from_pem(raw_key)
118 except Exception as vexc:
119 verifying_key_error = str(vexc)
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100120
121 msg = 'Bad key file "{}":\n\tpubkey error: {}\n\tprikey error: {}'
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200122 raise ValueError(msg.format(keyfile, verifying_key_error, signing_key_error)) from vexc
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100123 return key
124
125
Mate Toth-Palb9057ff2022-04-29 16:03:21 +0200126def _read_hmac_key(keyfile):
Mate Toth-Pal51b61982022-03-17 14:19:30 +0100127 return open(keyfile, 'rb').read()