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