blob: e43c9fad0951f0124b7a5363d658f94f36cb5479 [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:
70 # FixMe: If RSE_SYMMETRIC_PROVISIONING is OFF, should we use directly
71 # the encrypt_key without deriving another one?
72 encrypt_key = key_derivation.derive_symmetric_key(**kdf_args,
73 input_key = encrypt_key,
74 length = 32
75 )
76
77 if not iv:
78 iv = secrets.token_bytes(12) + int(0).to_bytes(4, 'little')
79
80 encrypted_data = encrypt_algs[encrypt_alg](
81 data = data,
82 key = encrypt_key,
83 iv = iv)
84 return iv, encrypted_data
85
86script_description = """
87Encrypt some data
88"""
89if __name__ == "__main__":
90 import argparse
91
92 parser = argparse.ArgumentParser(allow_abbrev=False,
93 formatter_class=argparse.ArgumentDefaultsHelpFormatter,
94 description=script_description)
95 parser.add_argument("--log_level", help="log level", required=False, default="ERROR", choices=logging._levelToName.values())
96 parser.add_argument("--data", help="data to sign", type=arg_type_bytes, required=True)
97
98 add_arguments(parser, required=True)
99
100 args = parser.parse_args()
101 logger.setLevel(args.log_level)
102 config = parse_args(args)
103 config |= parse_args_automatically(args, ["data"])
104
105 print(encrypt_data(**config)[1].hex())