Raef Coles | 59cf5d8 | 2024-12-09 15:41:13 +0000 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
| 2 | #------------------------------------------------------------------------------- |
| 3 | # SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors |
| 4 | # |
| 5 | # SPDX-License-Identifier: BSD-3-Clause |
| 6 | # |
| 7 | #------------------------------------------------------------------------------- |
| 8 | |
| 9 | import argparse |
| 10 | |
| 11 | import logging |
Raef Coles | cfc3124 | 2025-04-04 09:38:47 +0100 | [diff] [blame^] | 12 | logger = logging.getLogger("TF-M.{}".format(__name__)) |
Raef Coles | 59cf5d8 | 2024-12-09 15:41:13 +0000 | [diff] [blame] | 13 | |
| 14 | import arg_utils |
| 15 | import sign_data |
| 16 | import encrypt_data |
| 17 | |
| 18 | from cryptography.hazmat.primitives.ciphers.aead import AESCCM |
| 19 | import secrets |
| 20 | |
| 21 | def _sign_then_encrypt_aes_ccm(data : bytes, |
| 22 | sign_and_encrypt_key : bytes, |
| 23 | aad : bytes = bytes(0), |
| 24 | iv : bytes = None, |
| 25 | tag_length : int = 16, |
| 26 | **kwargs, |
| 27 | ): |
| 28 | if not iv: |
| 29 | iv = secrets.token_bytes(12) |
| 30 | |
| 31 | output = AESCCM(sign_and_encrypt_key, tag_length=tag_length).encrypt(nonce=iv, |
| 32 | data=data, |
| 33 | associated_data=aad) |
| 34 | signature = output[-tag_length:] |
| 35 | ciphertext = output[:-tag_length] |
| 36 | logger.info("Encrypting with IV {}".format(iv.hex())) |
| 37 | logger.info("Encrypting with key {}".format(sign_and_encrypt_key.hex())) |
| 38 | return iv, ciphertext, signature |
| 39 | |
| 40 | combined_algs = { |
| 41 | "AES_CCM": _sign_then_encrypt_aes_ccm, |
| 42 | } |
| 43 | |
| 44 | def add_arguments(parser : argparse.ArgumentParser, |
| 45 | prefix : str = "", |
| 46 | required : bool = True, |
| 47 | ) -> None: |
| 48 | arg_utils.add_prefixed_argument(parser, "sign_and_encrypt_key", prefix, |
| 49 | help="combined sign/encrypt key input file", |
| 50 | type=arg_utils.arg_type_bytes, required=False) |
| 51 | arg_utils.add_prefixed_argument(parser, "sign_and_encrypt_alg", prefix, |
| 52 | help="combined sign/encrypt algorithm", |
| 53 | choices=combined_algs.keys(), required=False) |
| 54 | encrypt_data.add_arguments(parser, prefix, False) |
| 55 | sign_data.add_arguments(parser, prefix, False) |
| 56 | |
| 57 | def parse_args(args : argparse.Namespace, |
| 58 | prefix : str = "", |
| 59 | ) -> dict: |
| 60 | out = arg_utils.parse_args_automatically(args, ["sign_and_encrypt_alg", |
| 61 | "sign_and_encrypt_key"], prefix) |
| 62 | |
| 63 | out |= sign_data.parse_args(args, prefix) |
| 64 | out |= encrypt_data.parse_args(args, prefix) |
| 65 | |
| 66 | arg_utils.incompatible_arg(args, "sign_and_encrypt_alg", "sign_alg") |
| 67 | arg_utils.incompatible_arg(args, "sign_and_encrypt_alg", "encrypt_alg") |
| 68 | |
| 69 | return out |
| 70 | |
| 71 | def sign_then_encrypt_data(data : bytes, |
| 72 | sign_and_encrypt_alg : str = None, |
| 73 | aad : bytes = bytes(0), |
| 74 | **kwargs, |
| 75 | ) -> bytes: |
| 76 | if sign_and_encrypt_alg: |
| 77 | return combined_algs[sign_and_encrypt_alg](data=data, aad=aad, **kwargs) |
| 78 | else: |
| 79 | iv, ciphertext = encrypt_data.encrypt_data(data=data, **kwargs) |
| 80 | return iv, ciphertext, sign_data.sign_data(data=aad + data, **kwargs) |
| 81 | |
| 82 | script_description = """ |
| 83 | """ |
| 84 | if __name__ == "__main__": |
| 85 | import argparse |
| 86 | |
| 87 | parser = argparse.ArgumentParser(allow_abbrev=False, |
| 88 | formatter_class=argparse.ArgumentDefaultsHelpFormatter, |
| 89 | description=script_description) |
| 90 | parser.add_argument("--log_level", help="log level", required=False, default="ERROR", choices=logging._levelToName.values()) |
| 91 | |
| 92 | args = parser.parse_args() |
Raef Coles | cfc3124 | 2025-04-04 09:38:47 +0100 | [diff] [blame^] | 93 | logging.getLogger("TF-M").setLevel(args.log_level) |
| 94 | logger.addHandler(logging.StreamHandler()) |