blob: d9139535159b6e2717e7e15df57224d5bbaf21a8 [file] [log] [blame]
Tamas Banafc4f3c2024-08-13 11:46:58 +02001/*
Jackson Cooper-Driver90d89a02025-03-03 16:41:37 +00002 * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
Tamas Banafc4f3c2024-08-13 11:46:58 +02003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8#include <stdio.h>
9#include <stdlib.h>
10
11#include "dice_protection_environment.h"
12#include "dpe_client.h"
13#include "dpe_context_mngr.h"
14#include "dpe_cmd_decode.h"
15#include "dpe_cmd_encode.h"
16
17#include "cmd.h"
18#include "root_keys.h"
19
Tamas Ban628192c2024-08-13 13:35:58 +020020#include "test_framework.h"
21
22#include "dpe_test.h"
23#include "dpe_test_common.h"
24#include "dpe_test_data.h"
25#include "dpe_test_private.h"
26
Jackson Cooper-Driver90d89a02025-03-03 16:41:37 +000027#include "tfm_log_unpriv.h"
Tamas Banafc4f3c2024-08-13 11:46:58 +020028
29#define CLIENT_ID_NS -1
30
Tamas Ban628192c2024-08-13 13:35:58 +020031extern int retained_rot_ctx_handle;
32
33extern const struct dpe_test_data_t test_data[5];
34
35static const DiceInputValues dice_in = DEFAULT_DICE_INPUT;
36
37static const unsigned int cert_id_arr[4] = {
38 DPE_CERT_ID_INVALID, 1, 2, DPE_CERT_ID_SAME_AS_PARENT
39};
40
41/* Data for key derivation */
42static const char label[] = {
43 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
44 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
45 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
46 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
47 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
48 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
49 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
50 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
51 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
52 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
53 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
54 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
55 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
56 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
57 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
58 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
59};
60
61/*
62 * Valid COSE_Key from RFC8152:
63 * https://datatracker.ietf.org/doc/html/rfc8152#appendix-C.7.1
64 */
65static const char ext_pub_key[] = {
66 0xA5, 0x20, 0x01, 0x21, 0x58, 0x20, 0x65, 0xED, 0xA5, 0xA1, 0x25, 0x77, 0xC2, 0xBA, 0xE8,
67 0x29, 0x43, 0x7F, 0xE3, 0x38, 0x70, 0x1A, 0x10, 0xAA, 0xA3, 0x75, 0xE1, 0xBB, 0x5B, 0x5D,
68 0xE1, 0x08, 0xDE, 0x43, 0x9C, 0x08, 0x55, 0x1D, 0x22, 0x58, 0x20, 0x1E, 0x52, 0xED, 0x75,
69 0x70, 0x11, 0x63, 0xF7, 0xF9, 0xE4, 0x0D, 0xDF, 0x9F, 0x34, 0x1B, 0x3D, 0xC9, 0xBA, 0x86,
70 0x0A, 0xF7, 0xE0, 0xCA, 0x7C, 0xA7, 0xE9, 0xEE, 0xCD, 0x00, 0x84, 0xD1, 0x9C, 0x01, 0x02,
71 0x02, 0x58, 0x24, 0x6D, 0x65, 0x72, 0x69, 0x61, 0x64, 0x6F, 0x63, 0x2E, 0x62, 0x72, 0x61,
72 0x6E, 0x64, 0x79, 0x62, 0x75, 0x63, 0x6B, 0x40, 0x62, 0x75, 0x63, 0x6B, 0x6C, 0x61, 0x6E,
73 0x64, 0x2E, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65,
74};
75
76struct dc_fuzz_input_raw {
77 unsigned char test_data_id;
78 unsigned char cert_id;
79 unsigned char retain_parent_context;
80 unsigned char allow_new_context_to_derive;
81 unsigned char create_certificate;
82 unsigned char return_certificate;
83 unsigned char allow_new_context_to_export;
84 unsigned char export_cdi;
85};
86
87struct ck_fuzz_input_raw {
88 unsigned char test_data_id;
89 unsigned char retain_context;
90 unsigned char use_external_key;
91 unsigned char label_size;
92};
93
94struct gcc_fuzz_input_raw {
95 unsigned char test_data_id;
96 unsigned char retain_context;
97 unsigned char clear_from_context;
98};
99
100struct gcc_fuzz_input {
101 unsigned char test_data_id;
102 bool retain_context;
103 bool clear_from_context;
104};
105
106union dpe_cmd {
107 struct dc_fuzz_input_raw dc_raw;
108 struct ck_fuzz_input_raw ck_raw;
109 struct gcc_fuzz_input_raw gcc_raw;
110};
111
112struct rnd_cmd_fuzz_input_raw {
113 unsigned char cmd_id;
114 union dpe_cmd cmd;
115};
116
Tamas Banafc4f3c2024-08-13 11:46:58 +0200117static void print_buf(const unsigned char *buf, size_t size)
118{
119 size_t i;
120
121 if (buf != NULL) {
122 for (i = 0; i < size; ++i) {
123 if ((i & 0xF) == 0) {
Jackson Cooper-Driver90d89a02025-03-03 16:41:37 +0000124 VERBOSE_UNPRIV_RAW("\n");
Tamas Banafc4f3c2024-08-13 11:46:58 +0200125 }
126 if (buf[i] < 0x10) {
Jackson Cooper-Driver90d89a02025-03-03 16:41:37 +0000127 VERBOSE_UNPRIV_RAW(" 0%x", buf[i]);
Tamas Banafc4f3c2024-08-13 11:46:58 +0200128 } else {
Jackson Cooper-Driver90d89a02025-03-03 16:41:37 +0000129 VERBOSE_UNPRIV_RAW(" %x", buf[i]);
Tamas Banafc4f3c2024-08-13 11:46:58 +0200130 }
131 }
132 }
Jackson Cooper-Driver90d89a02025-03-03 16:41:37 +0000133 VERBOSE_UNPRIV_RAW("\n");
134 VERBOSE_UNPRIV_RAW("\n");
Tamas Banafc4f3c2024-08-13 11:46:58 +0200135}
136
Tamas Ban628192c2024-08-13 13:35:58 +0200137static void build_internal_state(int *context_handle, unsigned char test_data_id)
138{
139 struct test_result_t test_ret = {0};
140 int err;
141
Jackson Cooper-Driver90d89a02025-03-03 16:41:37 +0000142 VERBOSE_UNPRIV_RAW("\nDeriving RoT context:\n");
Tamas Ban628192c2024-08-13 13:35:58 +0200143 derive_rot_certificate_context(&test_ret);
144 if (test_ret.val != TEST_PASSED) {
145 printf("ERROR: RoT context derivation failed\n");
146 exit(1);
147 }
148
149 if (test_data_id < ARRAY_SIZE(test_data)) {
Jackson Cooper-Driver90d89a02025-03-03 16:41:37 +0000150 VERBOSE_UNPRIV_RAW("\nBuilding internal state: test_data[%d]\n", test_data_id);
Tamas Ban628192c2024-08-13 13:35:58 +0200151 err = build_certificate_chain(&test_data[test_data_id]);
152 if (err) {
153 printf("\nERROR: Building certificate chain based on test data failed: %d\n", err);
154 exit(1);
155 }
Jackson Cooper-Driver90d89a02025-03-03 16:41:37 +0000156 VERBOSE_UNPRIV_RAW("Building internal state: Done\n\n");
Tamas Ban628192c2024-08-13 13:35:58 +0200157 *context_handle = get_last_context_handle(&test_data[test_data_id]);
158 } else {
Jackson Cooper-Driver90d89a02025-03-03 16:41:37 +0000159 VERBOSE_UNPRIV_RAW("Building internal state: No\n\n");
Tamas Ban628192c2024-08-13 13:35:58 +0200160 *context_handle = retained_rot_ctx_handle;
161 }
162}
163
164static void
165map_rnd_cmd_input(enum cmd *cmd, const char *cmd_in_buf, size_t cmd_in_size)
166{
167 struct rnd_cmd_fuzz_input_raw *rnd_cmd_raw;
168
169 /* If input is longer than just truncate it */
170 rnd_cmd_raw = (struct rnd_cmd_fuzz_input_raw *)cmd_in_buf;
171
172 *cmd = rnd_cmd_raw->cmd_id % MAX_CMD_VAL;
173}
174
175static dpe_error_t
176rnd_cmd(const char *cmd_in_buf, size_t cmd_in_size, int *context_handle)
177{
178 enum cmd cmd;
179
180 map_rnd_cmd_input(&cmd, cmd_in_buf, cmd_in_size);
181
182 /* The internal state based on test_data[] will be built by the invoked
183 * commnad later.
184 */
185
186 /* The first byte was consumed, it determines the DPE command type */
187 return exec_dpe_cmd(cmd, cmd_in_buf + 1, cmd_in_size - 1, context_handle);
188}
189
190/* Set a valid handle in the CBOR encoded commands */
191//static void update_context_handle(const char *buf, size_t len, int ctx_handle)
192//{
193////TODO: If internal state is built up before command execution, then the
194//// hard-coded context_handle must be updated to a valid one.
195//}
196
Tamas Banafc4f3c2024-08-13 11:46:58 +0200197static dpe_error_t
198cbor_cmd(const char *cmd_in_buf, size_t cmd_in_size, int *context_handle)
199{
200 char cmd_out_buf[2 * 4096];
201 size_t cmd_out_size = sizeof(cmd_out_buf);
202 dpe_error_t err;
203
Tamas Ban628192c2024-08-13 13:35:58 +0200204 //TODO: Might test with pre-built internal state
205 //build_internal_state(context_handle, 0);
206 //update_context_handle(cmd_in_buf, cmd_in_size, context_handle);
207
Tamas Banafc4f3c2024-08-13 11:46:58 +0200208 (void)context_handle;
209
Jackson Cooper-Driver90d89a02025-03-03 16:41:37 +0000210 VERBOSE_UNPRIV_RAW("DPE request (%ld):\n", cmd_in_size);
Tamas Banafc4f3c2024-08-13 11:46:58 +0200211 print_buf(cmd_in_buf, cmd_in_size);
212
213 err = dpe_command_decode(CLIENT_ID_NS,
214 cmd_in_buf, cmd_in_size,
215 cmd_out_buf, &cmd_out_size);
216
Jackson Cooper-Driver90d89a02025-03-03 16:41:37 +0000217 VERBOSE_UNPRIV_RAW("DPE response (%ld):\n", cmd_out_size);
Tamas Banafc4f3c2024-08-13 11:46:58 +0200218 print_buf(cmd_out_buf, cmd_out_size);
219
220 return err;
221}
222
Tamas Ban628192c2024-08-13 13:35:58 +0200223static bool map_to_bool(unsigned char val)
224{
225 return (val % 2) ? true : false;
226}
227
228/*
229 * Restrict the inputs:
230 * - cert_id: Only allow 4 different valid values
231 * - bools: Ensure that true and false values appears equally frequent
232 */
233static void
234map_dc_input(struct derive_context_cmd_input_t *dc, unsigned char *test_data_id,
235 const char *cmd_in_buf, size_t cmd_in_size)
236{
237 struct dc_fuzz_input_raw *dc_raw;
238
239 /* If the input is longer than just truncate it */
240 dc_raw = (struct dc_fuzz_input_raw *)cmd_in_buf;
241
242 dc->cert_id = cert_id_arr[(dc_raw->cert_id % ARRAY_SIZE(cert_id_arr))];
243 dc->retain_parent_context = map_to_bool(dc_raw->retain_parent_context);
244 dc->allow_new_context_to_derive = map_to_bool(dc_raw->allow_new_context_to_derive);
245 dc->create_certificate = map_to_bool(dc_raw->create_certificate);
246 dc->return_certificate = map_to_bool(dc_raw->return_certificate);
247 dc->allow_new_context_to_export = map_to_bool(dc_raw->allow_new_context_to_export);
248 dc->export_cdi = map_to_bool(dc_raw->export_cdi);
249
250 *test_data_id = dc_raw->test_data_id;
251}
252
253static dpe_error_t
254dc_cmd(const char *cmd_in_buf, size_t cmd_in_size, int *context_handle)
255{
256 struct derive_context_cmd_input_t dc_input = DEFAULT_DC_CMD_INPUT;
257 struct derive_context_cmd_output_t dc_output = {0};
258 dpe_error_t err;
259 unsigned char test_data_id;
260
261 ADD_CERT_BUF(dc_output, DICE_CERT_SIZE);
262 ADD_EXPORT_CDI_BUF(dc_output, DICE_MAX_ENCODED_CDI_SIZE);
263
264 map_dc_input(&dc_input, &test_data_id, cmd_in_buf, cmd_in_size);
265
266 build_internal_state(context_handle, test_data_id);
267
268 /* Set the next valid context_handle */
269 dc_input.context_handle = *context_handle;
270
271 err = CALL_DERIVE_CONTEXT(dc_input, dc_output);
272
273 if (dc_output.certificate_actual_size > 0) {
Jackson Cooper-Driver90d89a02025-03-03 16:41:37 +0000274 VERBOSE_UNPRIV_RAW("Certificate:\n");
Tamas Ban628192c2024-08-13 13:35:58 +0200275 print_buf(dc_output.certificate_buf,
276 dc_output.certificate_actual_size);
277 }
278
279 if (dc_output.exported_cdi_actual_size > 0) {
Jackson Cooper-Driver90d89a02025-03-03 16:41:37 +0000280 VERBOSE_UNPRIV_RAW("CDIs:\n");
Tamas Ban628192c2024-08-13 13:35:58 +0200281 print_buf(dc_output.exported_cdi_buf,
282 dc_output.exported_cdi_actual_size);
283 }
284
285 return err;
286}
287
288static void
289map_ck_input(struct certify_key_cmd_input_t *ck, unsigned char *test_data_id,
290 const char *cmd_in_buf, size_t cmd_in_size)
291{
292 struct ck_fuzz_input_raw *ck_raw;
293
294 /* If the input is longer than just truncate it */
295 ck_raw = (struct ck_fuzz_input_raw *)cmd_in_buf;
296
297 ck->retain_context = map_to_bool(ck_raw->retain_context);
298
299 if (map_to_bool(ck_raw->use_external_key)) {
300 ck->public_key = ext_pub_key;
301 ck->public_key_size = sizeof(ext_pub_key);
302 }
303
304 ck->label_size = (size_t)ck_raw->label_size;
305}
306
307static dpe_error_t
308ck_cmd(const char *cmd_in_buf, size_t cmd_in_size, int *context_handle)
309{
310 struct certify_key_cmd_input_t ck_input = DEFAULT_CK_CMD_INPUT;
311 struct certify_key_cmd_output_t ck_output = {0};
312 dpe_error_t err;
313 unsigned char test_data_id;
314
315 ADD_CERT_CHAIN_BUF(ck_output, 1650);
316 ADD_DERIVED_PUB_KEY_BUF(ck_output, DPE_ATTEST_PUB_KEY_SIZE);
317
318 map_ck_input(&ck_input, &test_data_id, cmd_in_buf, cmd_in_size);
319
320 build_internal_state(context_handle, test_data_id);
321
322 /* Set the next valid context_handle */
323 ck_input.context_handle = *context_handle;
324
325 err = CALL_CERTIFY_KEY(ck_input, ck_output);
326
327 if (ck_output.certificate_chain_actual_size > 0) {
Jackson Cooper-Driver90d89a02025-03-03 16:41:37 +0000328 VERBOSE_UNPRIV_RAW("Certificate:\n");
Tamas Ban628192c2024-08-13 13:35:58 +0200329 print_buf(ck_output.certificate_chain_buf,
330 ck_output.certificate_chain_actual_size);
331 }
332
333 if (ck_output.derived_public_key_actual_size > 0) {
Jackson Cooper-Driver90d89a02025-03-03 16:41:37 +0000334 VERBOSE_UNPRIV_RAW("Public key:\n");
Tamas Ban628192c2024-08-13 13:35:58 +0200335 print_buf(ck_output.derived_public_key_buf,
336 ck_output.derived_public_key_actual_size);
337 }
338
339 return err;
340}
341
342static void
343map_gcc_input(struct gcc_fuzz_input *gcc, unsigned char *test_data_id,
344 const char *cmd_in_buf, size_t cmd_in_size)
345{
346 struct gcc_fuzz_input_raw *gcc_raw;
347
348 /* If the input is longer than just truncate it */
349 gcc_raw = (struct gcc_fuzz_input_raw *)cmd_in_buf;
350
351 gcc->retain_context = map_to_bool(gcc_raw->retain_context);
352 gcc->clear_from_context = map_to_bool(gcc_raw->clear_from_context);
353}
354
355static dpe_error_t
356gcc_cmd(const char *cmd_in_buf, size_t cmd_in_size, int *context_handle)
357{
358 int new_context_handle;
359 struct gcc_fuzz_input gcc;
360 char cert_buf[4096];
361 size_t cert_size = 0;
362 dpe_error_t err;
363 unsigned char test_data_id;
364
365 map_gcc_input(&gcc, &test_data_id, cmd_in_buf, cmd_in_size);
366
367 build_internal_state(context_handle, test_data_id);
368
369 err = dpe_get_certificate_chain(*context_handle,
370 gcc.retain_context,
371 gcc.clear_from_context,
372 cert_buf,
373 sizeof(cert_buf),
374 &cert_size,
375 &new_context_handle);
376
377 if (cert_size > 0) {
Jackson Cooper-Driver90d89a02025-03-03 16:41:37 +0000378 VERBOSE_UNPRIV_RAW("Certificate:\n");
Tamas Ban628192c2024-08-13 13:35:58 +0200379 print_buf(cert_buf, cert_size);
380 }
381
382 return err;
383}
384
Tamas Banafc4f3c2024-08-13 11:46:58 +0200385/*
386 * DPE Library Init:
387 * - crypto_lib
388 * - platform
389 * - context manager
390 */
391void dpe_lib_init(int *context_handle)
392{
393 int ret;
394 dpe_error_t err;
395
396 ret = psa_crypto_init();
397 if (ret != 0) {
398 printf("ERROR: Crypto init failed! (%d)\n", ret);
399 exit(1);
400 }
401
402 ret = register_rot_cdi();
403 if (ret != 0) {
404 printf("ERROR: RoT CDI registration failed! (%d)\n", ret);
405 exit(1);
406 }
407
408 ret = register_root_attest_key();
409 if (ret != 0) {
410 printf("ERROR: Root attest key registration failed! (%d)\n", ret);
411 exit(1);
412 }
413
414 err = initialise_context_mngr(context_handle);
415 if (err != DPE_NO_ERROR) {
416 printf("ERROR: Context manager init failed (%d)\n", err);
417 exit(1);
418 }
419}
420
421dpe_error_t exec_dpe_cmd(enum cmd cmd, const char *cmd_in_buf,
422 size_t cmd_in_size, int *context_handle)
423{
424 switch(cmd) {
425 case CBOR:
426 return cbor_cmd(cmd_in_buf, cmd_in_size, context_handle);
Tamas Ban628192c2024-08-13 13:35:58 +0200427 case DC:
428 return dc_cmd(cmd_in_buf, cmd_in_size, context_handle);
429 case CK:
430 return ck_cmd(cmd_in_buf, cmd_in_size, context_handle);
431 case GCC:
432 return gcc_cmd(cmd_in_buf, cmd_in_size, context_handle);
433 case RND:
434 return rnd_cmd(cmd_in_buf, cmd_in_size, context_handle);
Tamas Banafc4f3c2024-08-13 11:46:58 +0200435 default:
436 printf("ERROR: Unknown command\n");
437 exit(1);
438 }
439}