blob: 13f9a9355bc8810e955ffac1c32dd58a5ca85095 [file] [log] [blame]
Jens Wiklander4edd96e2023-08-31 10:29:18 +02001#!/usr/bin/env python3
2# SPDX-License-Identifier: BSD-2-Clause
3#
4# Copyright (c) 2023, Linaro Limited
5#
6
7import sys
8
9
10def hex_parse(str):
11 try:
12 h = bytes.fromhex(str)
13 except ValueError as e:
14 try:
15 # Try to pad with a '0' nibble in front
16 h = bytes.fromhex('0' + str)
17 print('Odd number of nibbles in hexadecimal string',
18 file=sys.stderr)
19 raise e
20 except ValueError:
21 raise e
22 return h
23
24
25def get_args():
26 import argparse
27 import textwrap
28
29 parser = argparse.ArgumentParser(
30 allow_abbrev=False,
31 description='''Derive an RPMB key from the Hardware Unique Key used
32 by OP-TEE and the CID of the RPMB.''',
33 epilog='''Note that the derived key matches what the
34 __huk_subkey_derive() would produce. If huk_subkey_derive()
35 is overridden to call another function, please don't use
36 this script''')
37
38 parser.add_argument('--quiet', action='store_true', default=False,
39 help='''Gives only the hexstring of the RPMB key as
40 output, intended for scripting''')
41 parser.add_argument('--testkey', action='store_true', default=False,
42 help='''Outputs the hardcoded test key''')
43 parser.add_argument('--huk', type=hex_parse,
44 help='''Hardware Unique Key (16 bytes), as returned
45 by the platform specific function
46 tee_otp_get_hw_unique_key() in OP-TEE''')
47 parser.add_argument('--cid', type=hex_parse, help='CID (16 bytes)')
48 parser.add_argument('--compat', action='store_true', default=False,
49 help='''Generates a backwards compatible key,
50 only to be used if OP-TEE is build with
51 CFG_CORE_HUK_SUBKEY_COMPAT=y''')
52
53 return parser.parse_args()
54
55
56def derive_key(huk, cid, compat):
57 import struct
58 from cryptography.hazmat.primitives import hashes, hmac
59
60 # Prepare the CID and Clear the PRV (Product revision) and CRC (CRC7
61 # checksum) fields as OP-TEE does.
62 data = bytearray(cid)
63 data[9] = 0
64 data[15] = 0
65
66 # This is how __huk_subkey_derive() is implemented, if huk_subkey_derive()
67 # is overridden the key derived here may not match what OP-TEE is using
68 #
69 # HUK is as tee_otp_get_hw_unique_key() in OP-TEE returns it
70 h = hmac.HMAC(huk, hashes.SHA256())
71 if not compat:
72 usage_word = struct.pack('<I', 0)
73 h.update(usage_word)
74 h.update(data)
75 return h.finalize()
76
77
78def main():
79 args = get_args()
80
81 if args.testkey:
82 if args.cid or args.huk or args.compat:
83 print('--cid, --huk, or --compat '
84 'cannot be given together with --testkey')
85 sys.exit(1)
86 # The test key hardcoded in OP-TEE
87 key = bytes.fromhex('''D3 EB 3E C3 6E 33 4C 9F
88 98 8C E2 C0 B8 59 54 61
89 0D 2B CF 86 64 84 4D F2
90 AB 56 E6 C6 1B B7 01 E4''')
91 else:
92 if not args.cid:
93 print('--cid is required without --testkey')
94 sys.exit(1)
95
96 if not args.huk:
97 print('--huk is required without --testkey')
98 sys.exit(1)
99
100 if len(args.cid) != 16:
101 print(f'Invalid CID length, expected 16 bytes got {len(args.cid)}',
102 file=sys.stderr)
103 sys.exit(1)
104
105 if len(args.huk) != 16:
106 print(f'Invalid HUK length, expected 16 bytes got {len(args.huk)}',
107 file=sys.stderr)
108 sys.exit(1)
109
110 if not args.quiet:
111 print(f'HUK: {args.huk.hex()} length {len(args.huk)}')
112 print(f'RPMB CID: {args.cid.hex()} length {len(args.cid)}')
113
114 key = derive_key(args.huk, args.cid, args.compat)
115
116 if args.quiet:
117 print(key.hex())
118 else:
119 print(f'RPMB key: {key.hex()}')
120 print(f' length {len(key)}')
121 if args.testkey:
122 print('''
123*********************************************************************
124*** Please note that the test key should only be used for testing ***
125*** purposes since it's well known and the same for all devices. ***
126*********************************************************************''')
127 else:
128 print('''
129Please take care to double-check the provided input since writing the RPMB
130key is an irreversible step.''')
131
132
133if __name__ == "__main__":
134 main()