blob: e4eacc906446eb168f287be9071bda7d1e170ccd [file] [log] [blame]
Raef Coles59cf5d82024-12-09 15:41:13 +00001#!/usr/bin/env python3
2#-------------------------------------------------------------------------------
3# SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
4#
5# SPDX-License-Identifier: BSD-3-Clause
6#
7#-------------------------------------------------------------------------------
8
9from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
10
11import key_derivation
12
13import argparse
14import logging
15logger = logging.getLogger("TF-M")
16from arg_utils import *
17import secrets
18
19def _encrypt_aes_ctr(data : bytes,
20 iv : bytes,
21 key : bytes
22 ) -> bytes:
23 assert len(iv) >= 8
24
25 if len(iv) < 16:
26 iv += bytes(16 - len(iv))
27
28 c = Cipher(algorithms.AES(key), modes.CTR(iv))
29 return c.encryptor().update(data)
30
31encrypt_algs = {
32 "AES_CTR": _encrypt_aes_ctr,
33}
34
35def add_arguments(parser : argparse.ArgumentParser,
36 prefix : str = "",
37 required : bool = True,
38 ) -> None:
39 add_prefixed_argument(parser, "encrypt_key", prefix, help="encryption key input file",
40 required=required, type=arg_type_bytes)
41 add_prefixed_argument(parser, "encrypt_alg", prefix, help="encryption algorithm",
42 choices=encrypt_algs.keys(), required=required)
43 add_prefixed_argument(parser, "iv", prefix, help="encryption intial value",
44 type=arg_type_bytes, required=False)
45
46 key_derivation.add_arguments(parser, prefix, required=False)
47
48def parse_args(args : argparse.Namespace,
49 prefix : str = "",
50 ) -> dict:
51 out = parse_args_automatically(args, ["encrypt_alg", "encrypt_key", "iv"], prefix)
52 out["kdf_args"] = key_derivation.parse_args(args)
53
54 return out
55
56def encrypt_data(data : bytes,
57 encrypt_key : bytes,
58 encrypt_alg : str,
59 kdf_args : dict,
60 iv : bytes = None,
61 **kwargs,
62 ) -> (bytes, bytes):
63 if not data:
64 return iv, data
65
66 assert(encrypt_key)
67 assert(encrypt_alg)
68
69 if kdf_args:
Raef Coles59cf5d82024-12-09 15:41:13 +000070 encrypt_key = key_derivation.derive_symmetric_key(**kdf_args,
71 input_key = encrypt_key,
72 length = 32
73 )
74
75 if not iv:
76 iv = secrets.token_bytes(12) + int(0).to_bytes(4, 'little')
77
78 encrypted_data = encrypt_algs[encrypt_alg](
79 data = data,
80 key = encrypt_key,
81 iv = iv)
82 return iv, encrypted_data
83
84script_description = """
85Encrypt some data
86"""
87if __name__ == "__main__":
88 import argparse
89
90 parser = argparse.ArgumentParser(allow_abbrev=False,
91 formatter_class=argparse.ArgumentDefaultsHelpFormatter,
92 description=script_description)
93 parser.add_argument("--log_level", help="log level", required=False, default="ERROR", choices=logging._levelToName.values())
94 parser.add_argument("--data", help="data to sign", type=arg_type_bytes, required=True)
95
96 add_arguments(parser, required=True)
97
98 args = parser.parse_args()
99 logger.setLevel(args.log_level)
100 config = parse_args(args)
101 config |= parse_args_automatically(args, ["data"])
102
103 print(encrypt_data(**config)[1].hex())