1 /*
2 * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include "psa/crypto.h"
9 #include "mbedtls/cmac.h"
10
11 #include <stdint.h>
12 #include <stdio.h>
13 #include <string.h>
14
load_bl1_2_hash(uint8_t * bl1_2_hash)15 int load_bl1_2_hash(uint8_t *bl1_2_hash)
16 {
17 FILE *bl1_2_hash_file;
18 size_t read_bytes;
19
20 bl1_2_hash_file = fopen(BL1_2_HASH_PATH, "rb");
21 if (bl1_2_hash_file == NULL) {
22 return 1;
23 }
24
25 read_bytes = fread(bl1_2_hash, 1, 32, bl1_2_hash_file);
26 if (read_bytes != 32) {
27 return 1;
28 }
29
30 fclose(bl1_2_hash_file);
31
32 return 0;
33 }
34
load_guk(uint8_t * guk)35 int load_guk(uint8_t *guk)
36 {
37 FILE *guk_file;
38 size_t read_bytes;
39
40 guk_file = fopen(GUK_PATH, "rb");
41 if (guk_file == NULL) {
42 return 1;
43 }
44
45 read_bytes = fread(guk, 1, 32, guk_file);
46 if (read_bytes != 32) {
47 return 1;
48 }
49
50 fclose(guk_file);
51
52 return 0;
53 }
54
generate_boot_state(uint8_t * bl1_2_hash,uint8_t * boot_state)55 int generate_boot_state(uint8_t *bl1_2_hash, uint8_t *boot_state)
56 {
57 uint8_t context[PSA_HASH_LENGTH(PSA_ALG_SHA_256) + 3 * sizeof(uint32_t)];
58 uint32_t reprovisioning_bits = 0;
59 uint32_t lcs = 3;
60 #ifdef TP_MODE_TCI
61 uint32_t tp_mode = 0x111155AA;
62 #endif
63 #ifdef TP_MODE_PCI
64 uint32_t tp_mode = 0x2222AA55;
65 #endif
66
67 memcpy(context, &lcs, sizeof(uint32_t));
68
69 memcpy(context + sizeof(uint32_t), &tp_mode, sizeof(uint32_t));
70
71 memcpy(context + (2 * sizeof(uint32_t)), &reprovisioning_bits, sizeof(uint32_t));
72
73 memcpy(context + (3 * sizeof(uint32_t)), bl1_2_hash, 32);
74
75 return mbedtls_sha256(context, sizeof(context), boot_state, 0);
76 }
77
generate_seed(uint8_t * boot_state,uint8_t * guk,uint8_t * seed_buf)78 int generate_seed(uint8_t *boot_state, uint8_t *guk, uint8_t *seed_buf)
79 {
80 uint8_t label[] = "BL1_CPAK_SEED_DERIVATION";
81 uint8_t state[PSA_HASH_LENGTH(PSA_ALG_SHA_256) + sizeof(label) + sizeof(uint8_t)
82 + (sizeof(uint32_t) * 2)];
83 uint32_t seed_output_length = 32;
84 uint32_t block_index = 1;
85 psa_status_t status;
86 int rc;
87
88 memcpy(state, &block_index, sizeof(uint32_t));
89 memcpy(state + sizeof(uint32_t), label, sizeof(label));
90 memset(state + sizeof(uint32_t) + sizeof(label), 0, sizeof(uint8_t));
91 memcpy(state + sizeof(uint32_t) + sizeof(label) + sizeof(uint8_t),
92 boot_state, 32);
93 memcpy(state + sizeof(uint32_t) + sizeof(label) + sizeof(uint8_t) + 32,
94 &seed_output_length, sizeof(uint32_t));
95
96 rc = mbedtls_cipher_cmac(mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_ECB),
97 guk, 256, state, sizeof(state), seed_buf);
98 if (rc) {
99 return rc;
100 }
101
102 block_index += 1;
103 memcpy(state, &block_index, sizeof(uint32_t));
104
105 rc = mbedtls_cipher_cmac(mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_ECB),
106 guk, 256, state, sizeof(state), seed_buf + 16);
107 if (rc) {
108 return rc;
109 }
110
111 return 0;
112 }
113
derive_key(uint8_t * seed_buf,psa_key_handle_t * cpak_handle)114 int derive_key(uint8_t *seed_buf, psa_key_handle_t *cpak_handle)
115 {
116 psa_status_t status;
117 size_t output_key_len;
118 psa_key_attributes_t seed_attributes = PSA_KEY_ATTRIBUTES_INIT;
119 psa_key_attributes_t output_attr = PSA_KEY_ATTRIBUTES_INIT;
120 psa_key_handle_t seed_key = PSA_KEY_HANDLE_INIT;
121 psa_key_derivation_operation_t op = PSA_KEY_DERIVATION_OPERATION_INIT;
122 psa_set_key_type(&seed_attributes, PSA_KEY_TYPE_DERIVE);
123 psa_set_key_algorithm(&seed_attributes, PSA_ALG_HKDF(PSA_ALG_SHA_256));
124 psa_set_key_bits(&seed_attributes, 256);
125 psa_set_key_usage_flags(&seed_attributes, PSA_KEY_USAGE_DERIVE);
126
127 status = psa_import_key(&seed_attributes, seed_buf, 32, &seed_key);
128 if (status != PSA_SUCCESS) {
129 return 1;
130 }
131
132 status = psa_key_derivation_setup(&op, PSA_ALG_HKDF(PSA_ALG_SHA_256));
133 if (status != PSA_SUCCESS) {
134 goto err_release_seed_key;
135 }
136
137 status = psa_key_derivation_input_key(&op, PSA_KEY_DERIVATION_INPUT_SECRET,
138 seed_key);
139 if (status != PSA_SUCCESS) {
140 goto err_release_op;
141 }
142
143 status = psa_key_derivation_input_bytes(&op, PSA_KEY_DERIVATION_INPUT_INFO,
144 NULL, 0);
145 if (status != PSA_SUCCESS) {
146 goto err_release_op;
147 }
148
149 psa_set_key_type(&output_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
150 psa_set_key_algorithm(&output_attr, PSA_ALG_ECDSA(PSA_ALG_SHA_384));
151 psa_set_key_bits(&output_attr, 384);
152 psa_set_key_usage_flags(&output_attr, PSA_KEY_USAGE_EXPORT);
153
154 status = psa_key_derivation_output_key(&output_attr, &op, cpak_handle);
155 if (status != PSA_SUCCESS) {
156 goto err_release_op;
157 }
158
159 status = psa_key_derivation_abort(&op);
160 if (status != PSA_SUCCESS) {
161 goto err_release_seed_key;
162 }
163
164 status = psa_destroy_key(seed_key);
165 if (status != PSA_SUCCESS) {
166 return 1;
167 }
168
169 return 0;
170
171 err_release_output_key:
172 (void)psa_destroy_key(*cpak_handle);
173
174 err_release_op:
175 (void)psa_key_derivation_abort(&op);
176
177 err_release_seed_key:
178 (void)psa_destroy_key(seed_key);
179
180 return 1;
181 }
182
export_pubkey(psa_key_handle_t cpak_handle)183 int export_pubkey(psa_key_handle_t cpak_handle)
184 {
185 psa_status_t status;
186 uint8_t cpak_buf[128];
187 size_t cpak_size;
188 FILE *cpak_output_file;
189 size_t written_bytes;
190
191 status = psa_export_public_key(cpak_handle, cpak_buf, sizeof(cpak_buf),
192 &cpak_size);
193 if (status != PSA_SUCCESS) {
194 return 1;
195 }
196
197 cpak_output_file = fopen(CPAK_OUTPUT_PATH, "wb");
198 if (cpak_output_file == NULL) {
199 return 1;
200 }
201
202 written_bytes = fwrite(cpak_buf, 1, cpak_size, cpak_output_file);
203 if (written_bytes != cpak_size) {
204 return 1;
205 }
206
207 return 0;
208 }
209
main(int argc,char * argv[])210 int main (int argc, char *argv[])
211 {
212 int rc;
213 uint8_t bl1_2_hash[PSA_HASH_LENGTH(PSA_ALG_SHA_256)];
214 uint8_t boot_state[PSA_HASH_LENGTH(PSA_ALG_SHA_256)];
215 uint8_t guk[32];
216 uint8_t seed_buf[32];
217 psa_key_handle_t cpak_handle;
218
219 rc = psa_crypto_init();
220 if (rc) {
221 printf("psa init failed\r\n");
222 return rc;
223 }
224
225 rc = load_bl1_2_hash(bl1_2_hash);
226 if (rc) {
227 printf("bl1_2_hash load failed\r\n");
228 return rc;
229 }
230
231 rc = load_guk(guk);
232 if (rc) {
233 printf("GUK load failed\r\n");
234 return rc;
235 }
236
237 rc = generate_boot_state(bl1_2_hash, boot_state);
238 if (rc) {
239 printf("boot state generation failed\r\n");
240 return rc;
241 }
242
243 rc = generate_seed(boot_state, guk, seed_buf);
244 if (rc) {
245 printf("cpak seed generation failed\r\n");
246 return rc;
247 }
248
249 rc = derive_key(seed_buf, &cpak_handle);
250 if (rc) {
251 printf("cpak derivation failed\r\n");
252 return rc;
253 }
254
255 rc = export_pubkey(cpak_handle);
256 if (rc) {
257 printf("cpak output failed\r\n");
258 }
259
260 return 0;
261 }
262