Line data Source code
1 : /**
2 : * Copyright Notice:
3 : * Copyright 2024-2025 DMTF. All rights reserved.
4 : * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
5 : **/
6 :
7 : #include <stdarg.h>
8 : #include <stddef.h>
9 : #include <setjmp.h>
10 : #include <stdint.h>
11 : #include <stdlib.h>
12 : #include <stdio.h>
13 : #include <assert.h>
14 : #include <string.h>
15 :
16 : #include <base.h>
17 : #include "library/memlib.h"
18 : #include "spdm_device_secret_lib_internal.h"
19 : #include "internal/libspdm_common_lib.h"
20 :
21 : #if (LIBSPDM_ENABLE_CAPABILITY_MEL_CAP) || (LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP)
22 :
23 : #define LIBSPDM_MAX_MEASUREMENT_EXTENSION_LOG_SIZE 0x1000
24 : uint8_t m_libspdm_mel[LIBSPDM_MAX_MEASUREMENT_EXTENSION_LOG_SIZE];
25 :
26 : #endif /* (LIBSPDM_ENABLE_CAPABILITY_MEL_CAP) || (LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP) */
27 :
28 : #if (LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP) || (LIBSPDM_ENABLE_CAPABILITY_MEL_CAP)
29 26 : void libspdm_generate_mel(uint32_t measurement_hash_algo)
30 : {
31 : spdm_measurement_extension_log_dmtf_t *measurement_extension_log;
32 : spdm_mel_entry_dmtf_t *mel_entry1;
33 : spdm_mel_entry_dmtf_t *mel_entry2;
34 : spdm_mel_entry_dmtf_t *mel_entry3;
35 :
36 26 : uint8_t rom_informational[] = "ROM";
37 26 : uint8_t bootfv_informational[] = "Boot FW";
38 26 : uint32_t version = 0x0100030A;
39 :
40 : /*generate MEL*/
41 26 : measurement_extension_log = (spdm_measurement_extension_log_dmtf_t *)m_libspdm_mel;
42 :
43 26 : measurement_extension_log->number_of_entries = 3;
44 26 : measurement_extension_log->mel_entries_len =
45 26 : measurement_extension_log->number_of_entries * sizeof(spdm_mel_entry_dmtf_t) +
46 26 : sizeof(rom_informational) - 1 + sizeof(bootfv_informational) - 1 + sizeof(version);
47 26 : measurement_extension_log->reserved = 0;
48 :
49 : /*MEL Entry 1: informational ROM */
50 26 : mel_entry1 = (spdm_mel_entry_dmtf_t *)((uint8_t *)measurement_extension_log +
51 : sizeof(spdm_measurement_extension_log_dmtf_t));
52 26 : mel_entry1->mel_index = 1;
53 26 : mel_entry1->meas_index = LIBSPDM_MEASUREMENT_INDEX_HEM;
54 26 : libspdm_write_uint24(mel_entry1->reserved, 0);
55 26 : mel_entry1->measurement_block_dmtf_header.dmtf_spec_measurement_value_type =
56 : SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_INFORMATIONAL |
57 : SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_RAW_BIT_STREAM;
58 26 : mel_entry1->measurement_block_dmtf_header.dmtf_spec_measurement_value_size =
59 : sizeof(rom_informational) - 1;
60 26 : libspdm_copy_mem((void *)(mel_entry1 + 1), sizeof(rom_informational) - 1,
61 : rom_informational, sizeof(rom_informational) - 1);
62 :
63 : /*MEL Entry 2: informational Boot FW */
64 26 : mel_entry2 = (spdm_mel_entry_dmtf_t *)((uint8_t *)(mel_entry1 + 1) +
65 : sizeof(rom_informational) - 1);
66 26 : mel_entry2->mel_index = 2;
67 26 : mel_entry2->meas_index = LIBSPDM_MEASUREMENT_INDEX_HEM;
68 26 : libspdm_write_uint24(mel_entry2->reserved, 0);
69 26 : mel_entry2->measurement_block_dmtf_header.dmtf_spec_measurement_value_type =
70 : SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_INFORMATIONAL |
71 : SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_RAW_BIT_STREAM;
72 26 : mel_entry2->measurement_block_dmtf_header.dmtf_spec_measurement_value_size =
73 : sizeof(bootfv_informational) - 1;
74 26 : libspdm_copy_mem((void *)(mel_entry2 + 1), sizeof(bootfv_informational) - 1,
75 : bootfv_informational, sizeof(bootfv_informational) - 1);
76 :
77 : /*MEL Entry 3: version 0x0100030A */
78 26 : mel_entry3 = (spdm_mel_entry_dmtf_t *)((uint8_t *)(mel_entry2 + 1) +
79 : sizeof(bootfv_informational) - 1);
80 26 : mel_entry3->mel_index = 3;
81 26 : mel_entry3->meas_index = LIBSPDM_MEASUREMENT_INDEX_HEM;
82 26 : libspdm_write_uint24(mel_entry3->reserved, 0);
83 26 : mel_entry3->measurement_block_dmtf_header.dmtf_spec_measurement_value_type =
84 : SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_VERSION |
85 : SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_RAW_BIT_STREAM;
86 26 : mel_entry3->measurement_block_dmtf_header.dmtf_spec_measurement_value_size = sizeof(version);
87 26 : libspdm_copy_mem((void *)(mel_entry3 + 1), sizeof(version), &version, sizeof(version));
88 26 : }
89 : #endif /*(LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP) || (LIBSPDM_ENABLE_CAPABILITY_MEL_CAP)*/
90 :
91 : #if LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP
92 : /**
93 : * Fill image hash measurement block.
94 : *
95 : * @return measurement block size.
96 : **/
97 170 : size_t libspdm_fill_measurement_image_hash_block (
98 : bool use_bit_stream,
99 : uint32_t measurement_hash_algo,
100 : uint8_t measurements_index,
101 : spdm_measurement_block_dmtf_t *measurement_block
102 : )
103 : {
104 : size_t hash_size;
105 : uint8_t data[LIBSPDM_MEASUREMENT_RAW_DATA_SIZE];
106 : bool result;
107 :
108 170 : hash_size = libspdm_get_measurement_hash_size(measurement_hash_algo);
109 :
110 : measurement_block->measurement_block_common_header
111 170 : .index = measurements_index;
112 : measurement_block->measurement_block_common_header
113 170 : .measurement_specification =
114 : SPDM_MEASUREMENT_SPECIFICATION_DMTF;
115 :
116 170 : libspdm_set_mem(data, sizeof(data), (uint8_t)(measurements_index));
117 :
118 170 : if (!use_bit_stream) {
119 : measurement_block->measurement_block_dmtf_header
120 169 : .dmtf_spec_measurement_value_type =
121 169 : (measurements_index - 1);
122 : measurement_block->measurement_block_dmtf_header
123 169 : .dmtf_spec_measurement_value_size =
124 169 : (uint16_t)hash_size;
125 :
126 : measurement_block->measurement_block_common_header
127 169 : .measurement_size =
128 169 : (uint16_t)(sizeof(spdm_measurement_block_dmtf_header_t) +
129 169 : (uint16_t)hash_size);
130 :
131 169 : result = libspdm_measurement_hash_all(
132 : measurement_hash_algo, data,
133 : sizeof(data),
134 169 : (void *)(measurement_block + 1));
135 169 : if (!result) {
136 0 : return 0;
137 : }
138 :
139 169 : return sizeof(spdm_measurement_block_dmtf_t) + hash_size;
140 :
141 : } else {
142 : measurement_block->measurement_block_dmtf_header
143 1 : .dmtf_spec_measurement_value_type =
144 1 : (measurements_index - 1) |
145 : SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_RAW_BIT_STREAM;
146 : measurement_block->measurement_block_dmtf_header
147 1 : .dmtf_spec_measurement_value_size =
148 : (uint16_t)sizeof(data);
149 :
150 : measurement_block->measurement_block_common_header
151 1 : .measurement_size =
152 : (uint16_t)(sizeof(spdm_measurement_block_dmtf_header_t) +
153 : (uint16_t)sizeof(data));
154 :
155 1 : libspdm_copy_mem((void *)(measurement_block + 1), sizeof(data), data, sizeof(data));
156 :
157 1 : return sizeof(spdm_measurement_block_dmtf_t) + sizeof(data);
158 : }
159 : }
160 :
161 : /**
162 : * Fill svn measurement block.
163 : *
164 : * @return measurement block size.
165 : **/
166 15 : size_t libspdm_fill_measurement_svn_block (
167 : spdm_measurement_block_dmtf_t *measurement_block
168 : )
169 : {
170 : spdm_measurements_secure_version_number_t svn;
171 :
172 : measurement_block->measurement_block_common_header
173 15 : .index = LIBSPDM_MEASUREMENT_INDEX_SVN;
174 : measurement_block->measurement_block_common_header
175 15 : .measurement_specification =
176 : SPDM_MEASUREMENT_SPECIFICATION_DMTF;
177 :
178 15 : svn = 0x7;
179 :
180 : measurement_block->measurement_block_dmtf_header
181 15 : .dmtf_spec_measurement_value_type =
182 : SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_SECURE_VERSION_NUMBER |
183 : SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_RAW_BIT_STREAM;
184 : measurement_block->measurement_block_dmtf_header
185 15 : .dmtf_spec_measurement_value_size =
186 : (uint16_t)sizeof(svn);
187 :
188 : measurement_block->measurement_block_common_header
189 15 : .measurement_size =
190 : (uint16_t)(sizeof(spdm_measurement_block_dmtf_header_t) +
191 : (uint16_t)sizeof(svn));
192 :
193 15 : libspdm_copy_mem((void *)(measurement_block + 1), sizeof(svn), (void *)&svn, sizeof(svn));
194 :
195 15 : return sizeof(spdm_measurement_block_dmtf_t) + sizeof(svn);
196 : }
197 :
198 : /**
199 : * Fill HEM measurement block.
200 : *
201 : * @param measurement_block A pointer to store measurement block.
202 : * @param measurement_hash_algo Indicates the measurement hash algorithm.
203 : * It must align with measurement_hash_alg
204 : * (SPDM_ALGORITHMS_MEASUREMENT_HASH_ALGO_*)
205 : *
206 : * @return measurement block size.
207 : **/
208 15 : size_t libspdm_fill_measurement_hem_block (
209 : spdm_measurement_block_dmtf_t *measurement_block, uint32_t measurement_hash_algo
210 : )
211 : {
212 : size_t hash_size;
213 : spdm_measurement_extension_log_dmtf_t *measurement_extension_log;
214 : spdm_mel_entry_dmtf_t *mel_entry;
215 : uint32_t index;
216 : uint8_t *verify_hem;
217 :
218 15 : if (measurement_hash_algo == SPDM_ALGORITHMS_MEASUREMENT_HASH_ALGO_RAW_BIT_STREAM_ONLY) {
219 0 : return 0;
220 : }
221 :
222 15 : libspdm_generate_mel(measurement_hash_algo);
223 :
224 15 : hash_size = libspdm_get_measurement_hash_size(measurement_hash_algo);
225 15 : if (measurement_block == NULL) {
226 0 : return sizeof(spdm_measurement_block_dmtf_t) + hash_size;
227 : }
228 :
229 : /*MEL*/
230 15 : measurement_extension_log = (spdm_measurement_extension_log_dmtf_t *)m_libspdm_mel;
231 :
232 : /*generate measurement block*/
233 : measurement_block->measurement_block_common_header
234 15 : .index = LIBSPDM_MEASUREMENT_INDEX_HEM;
235 : measurement_block->measurement_block_common_header
236 15 : .measurement_specification =
237 : SPDM_MEASUREMENT_SPECIFICATION_DMTF;
238 :
239 : measurement_block->measurement_block_dmtf_header
240 15 : .dmtf_spec_measurement_value_type =
241 : SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_HASH_EXTEND_MEASUREMENT;
242 : measurement_block->measurement_block_dmtf_header
243 15 : .dmtf_spec_measurement_value_size =
244 15 : (uint16_t)hash_size;
245 :
246 : measurement_block->measurement_block_common_header
247 15 : .measurement_size =
248 15 : (uint16_t)(sizeof(spdm_measurement_block_dmtf_header_t) +
249 15 : (uint16_t)hash_size);
250 :
251 15 : verify_hem = malloc(measurement_extension_log->mel_entries_len + hash_size);
252 15 : if (verify_hem == NULL) {
253 0 : return 0;
254 : }
255 :
256 15 : libspdm_zero_mem(verify_hem, measurement_extension_log->mel_entries_len + hash_size);
257 15 : mel_entry = (spdm_mel_entry_dmtf_t *)((uint8_t *)measurement_extension_log +
258 : sizeof(spdm_measurement_extension_log_dmtf_t));
259 60 : for (index = 0; index < measurement_extension_log->number_of_entries; index++) {
260 45 : libspdm_copy_mem(
261 45 : verify_hem + hash_size,
262 45 : measurement_extension_log->mel_entries_len,
263 : mel_entry,
264 : sizeof(spdm_mel_entry_dmtf_t) +
265 45 : mel_entry->measurement_block_dmtf_header.dmtf_spec_measurement_value_size);
266 :
267 45 : if (!libspdm_measurement_hash_all(
268 : measurement_hash_algo,
269 : verify_hem,
270 45 : hash_size + sizeof(spdm_mel_entry_dmtf_t) +
271 45 : mel_entry->measurement_block_dmtf_header.dmtf_spec_measurement_value_size,
272 : verify_hem
273 : )) {
274 0 : free(verify_hem);
275 0 : return 0;
276 : }
277 45 : mel_entry = (spdm_mel_entry_dmtf_t *)
278 45 : ((uint8_t *)mel_entry + sizeof(spdm_mel_entry_dmtf_t)+
279 45 : mel_entry->measurement_block_dmtf_header.dmtf_spec_measurement_value_size);
280 : }
281 :
282 15 : libspdm_copy_mem((void *)(measurement_block + 1), hash_size, verify_hem, hash_size);
283 15 : free(verify_hem);
284 15 : return sizeof(spdm_measurement_block_dmtf_t) + hash_size;
285 : }
286 :
287 : /**
288 : * Fill manifest measurement block.
289 : *
290 : * @return measurement block size.
291 : **/
292 15 : size_t libspdm_fill_measurement_manifest_block (
293 : spdm_measurement_block_dmtf_t *measurement_block
294 : )
295 : {
296 : uint8_t data[LIBSPDM_MEASUREMENT_MANIFEST_SIZE];
297 :
298 : measurement_block->measurement_block_common_header
299 15 : .index = SPDM_MEASUREMENT_BLOCK_MEASUREMENT_INDEX_MEASUREMENT_MANIFEST;
300 : measurement_block->measurement_block_common_header
301 15 : .measurement_specification =
302 : SPDM_MEASUREMENT_SPECIFICATION_DMTF;
303 :
304 15 : libspdm_set_mem(data, sizeof(data),
305 : (uint8_t)SPDM_MEASUREMENT_BLOCK_MEASUREMENT_INDEX_MEASUREMENT_MANIFEST);
306 :
307 : measurement_block->measurement_block_dmtf_header
308 15 : .dmtf_spec_measurement_value_type =
309 : SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_MEASUREMENT_MANIFEST |
310 : SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_RAW_BIT_STREAM;
311 : measurement_block->measurement_block_dmtf_header
312 15 : .dmtf_spec_measurement_value_size =
313 : (uint16_t)sizeof(data);
314 :
315 : measurement_block->measurement_block_common_header
316 15 : .measurement_size =
317 : (uint16_t)(sizeof(spdm_measurement_block_dmtf_header_t) +
318 : (uint16_t)sizeof(data));
319 :
320 15 : libspdm_copy_mem((void *)(measurement_block + 1), sizeof(data), data, sizeof(data));
321 :
322 15 : return sizeof(spdm_measurement_block_dmtf_t) + sizeof(data);
323 : }
324 :
325 : /**
326 : * Fill device mode measurement block.
327 : *
328 : * @return measurement block size.
329 : **/
330 15 : size_t libspdm_fill_measurement_device_mode_block (
331 : spdm_measurement_block_dmtf_t *measurement_block
332 : )
333 : {
334 : spdm_measurements_device_mode_t device_mode;
335 :
336 : measurement_block->measurement_block_common_header
337 15 : .index = SPDM_MEASUREMENT_BLOCK_MEASUREMENT_INDEX_DEVICE_MODE;
338 : measurement_block->measurement_block_common_header
339 15 : .measurement_specification =
340 : SPDM_MEASUREMENT_SPECIFICATION_DMTF;
341 :
342 15 : device_mode.operational_mode_capabilities =
343 : SPDM_MEASUREMENT_DEVICE_OPERATION_MODE_MANUFACTURING_MODE |
344 : SPDM_MEASUREMENT_DEVICE_OPERATION_MODE_VALIDATION_MODE |
345 : SPDM_MEASUREMENT_DEVICE_OPERATION_MODE_NORMAL_MODE |
346 : SPDM_MEASUREMENT_DEVICE_OPERATION_MODE_RECOVERY_MODE |
347 : SPDM_MEASUREMENT_DEVICE_OPERATION_MODE_RMA_MODE |
348 : SPDM_MEASUREMENT_DEVICE_OPERATION_MODE_DECOMMISSIONED_MODE;
349 15 : device_mode.operational_mode_state =
350 : SPDM_MEASUREMENT_DEVICE_OPERATION_MODE_NORMAL_MODE;
351 15 : device_mode.device_mode_capabilities =
352 : SPDM_MEASUREMENT_DEVICE_MODE_NON_INVASIVE_DEBUG_MODE_IS_ACTIVE |
353 : SPDM_MEASUREMENT_DEVICE_MODE_INVASIVE_DEBUG_MODE_IS_ACTIVE |
354 : SPDM_MEASUREMENT_DEVICE_MODE_NON_INVASIVE_DEBUG_MODE_HAS_BEEN_ACTIVE |
355 : SPDM_MEASUREMENT_DEVICE_MODE_INVASIVE_DEBUG_MODE_HAS_BEEN_ACTIVE |
356 : SPDM_MEASUREMENT_DEVICE_MODE_INVASIVE_DEBUG_MODE_HAS_BEEN_ACTIVE_AFTER_MFG;
357 15 : device_mode.device_mode_state =
358 : SPDM_MEASUREMENT_DEVICE_MODE_NON_INVASIVE_DEBUG_MODE_IS_ACTIVE |
359 : SPDM_MEASUREMENT_DEVICE_MODE_INVASIVE_DEBUG_MODE_HAS_BEEN_ACTIVE_AFTER_MFG;
360 :
361 : measurement_block->measurement_block_dmtf_header
362 15 : .dmtf_spec_measurement_value_type =
363 : SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_DEVICE_MODE |
364 : SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_RAW_BIT_STREAM;
365 : measurement_block->measurement_block_dmtf_header
366 15 : .dmtf_spec_measurement_value_size =
367 : (uint16_t)sizeof(device_mode);
368 :
369 : measurement_block->measurement_block_common_header
370 15 : .measurement_size =
371 : (uint16_t)(sizeof(spdm_measurement_block_dmtf_header_t) +
372 : (uint16_t)sizeof(device_mode));
373 :
374 15 : libspdm_copy_mem((void *)(measurement_block + 1), sizeof(device_mode),
375 : (void *)&device_mode, sizeof(device_mode));
376 :
377 15 : return sizeof(spdm_measurement_block_dmtf_t) + sizeof(device_mode);
378 : }
379 :
380 : bool g_check_measurement_request_context = false;
381 : uint64_t g_measurement_request_context;
382 :
383 137 : libspdm_return_t libspdm_measurement_collection(
384 : void *spdm_context,
385 : spdm_version_number_t spdm_version,
386 : uint8_t measurement_specification,
387 : uint32_t measurement_hash_algo,
388 : uint8_t measurements_index,
389 : uint8_t request_attribute,
390 : size_t request_context_size,
391 : const void *request_context,
392 : uint8_t *content_changed,
393 : uint8_t *measurements_count,
394 : void *measurements,
395 : size_t *measurements_size)
396 : {
397 : spdm_measurement_block_dmtf_t *measurement_block;
398 : size_t hash_size;
399 : uint8_t index;
400 : size_t total_size_needed;
401 : bool use_bit_stream;
402 : size_t measurement_block_size;
403 :
404 137 : if ((measurement_specification != SPDM_MEASUREMENT_SPECIFICATION_DMTF) ||
405 : (measurement_hash_algo == 0)) {
406 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
407 : }
408 :
409 137 : if (g_check_measurement_request_context) {
410 0 : if ((spdm_version >> SPDM_VERSION_NUMBER_SHIFT_BIT) >= SPDM_MESSAGE_VERSION_13) {
411 0 : LIBSPDM_ASSERT(request_context_size == SPDM_REQ_CONTEXT_SIZE);
412 0 : LIBSPDM_ASSERT(libspdm_read_uint64(request_context) == g_measurement_request_context);
413 : } else {
414 0 : LIBSPDM_ASSERT(request_context_size == 0);
415 0 : LIBSPDM_ASSERT(request_context == NULL);
416 : }
417 : }
418 :
419 137 : hash_size = libspdm_get_measurement_hash_size(measurement_hash_algo);
420 137 : LIBSPDM_ASSERT(hash_size != 0);
421 :
422 137 : use_bit_stream = false;
423 137 : if ((measurement_hash_algo == SPDM_ALGORITHMS_MEASUREMENT_HASH_ALGO_RAW_BIT_STREAM_ONLY) ||
424 137 : ((request_attribute & SPDM_GET_MEASUREMENTS_REQUEST_ATTRIBUTES_RAW_BIT_STREAM_REQUESTED) !=
425 : 0)) {
426 1 : use_bit_stream = true;
427 : }
428 :
429 137 : if (measurements_index ==
430 : SPDM_GET_MEASUREMENTS_REQUEST_MEASUREMENT_OPERATION_TOTAL_NUMBER_OF_MEASUREMENTS) {
431 11 : *measurements_count = LIBSPDM_MEASUREMENT_BLOCK_NUMBER;
432 11 : goto successful_return;
433 126 : } else if (measurements_index ==
434 : SPDM_GET_MEASUREMENTS_REQUEST_MEASUREMENT_OPERATION_ALL_MEASUREMENTS) {
435 :
436 : /* Calculate total_size_needed based on hash algo selected.
437 : * If we have an hash algo, then the first HASH_NUMBER elements will be
438 : * hash values, otherwise HASH_NUMBER raw bitstream values.*/
439 15 : if (!use_bit_stream) {
440 15 : total_size_needed =
441 : LIBSPDM_MEASUREMENT_BLOCK_HASH_NUMBER *
442 15 : (sizeof(spdm_measurement_block_dmtf_t) + hash_size);
443 : } else {
444 0 : total_size_needed =
445 : LIBSPDM_MEASUREMENT_BLOCK_HASH_NUMBER *
446 : (sizeof(spdm_measurement_block_dmtf_t) + LIBSPDM_MEASUREMENT_RAW_DATA_SIZE);
447 : }
448 : /* Next one - SVN is always raw bitstream data.*/
449 15 : total_size_needed +=
450 : (sizeof(spdm_measurement_block_dmtf_t) +
451 : sizeof(spdm_measurements_secure_version_number_t));
452 : /* Next one - HEM is always digest data.*/
453 15 : total_size_needed +=
454 : (sizeof(spdm_measurement_block_dmtf_t) + hash_size);
455 : /* Next one - manifest is always raw bitstream data.*/
456 15 : total_size_needed +=
457 : (sizeof(spdm_measurement_block_dmtf_t) + LIBSPDM_MEASUREMENT_MANIFEST_SIZE);
458 : /* Next one - device_mode is always raw bitstream data.*/
459 15 : total_size_needed +=
460 : (sizeof(spdm_measurement_block_dmtf_t) + sizeof(spdm_measurements_device_mode_t));
461 :
462 15 : LIBSPDM_ASSERT(total_size_needed <= *measurements_size);
463 15 : if (total_size_needed > *measurements_size) {
464 0 : return LIBSPDM_STATUS_BUFFER_TOO_SMALL;
465 : }
466 :
467 15 : *measurements_size = total_size_needed;
468 15 : *measurements_count = LIBSPDM_MEASUREMENT_BLOCK_NUMBER;
469 15 : measurement_block = measurements;
470 :
471 : /* The first HASH_NUMBER blocks may be hash values or raw bitstream*/
472 75 : for (index = 1; index <= LIBSPDM_MEASUREMENT_BLOCK_HASH_NUMBER; index++) {
473 60 : measurement_block_size = libspdm_fill_measurement_image_hash_block (use_bit_stream,
474 : measurement_hash_algo,
475 : index,
476 : measurement_block);
477 60 : if (measurement_block_size == 0) {
478 0 : return LIBSPDM_STATUS_MEAS_INTERNAL_ERROR;
479 : }
480 60 : measurement_block = (void *)((uint8_t *)measurement_block + measurement_block_size);
481 : }
482 : /* Next one - SVN is always raw bitstream data.*/
483 : {
484 15 : measurement_block_size = libspdm_fill_measurement_svn_block (measurement_block);
485 15 : measurement_block = (void *)((uint8_t *)measurement_block + measurement_block_size);
486 : }
487 : /* Next one - HEM is always digest data.*/
488 : {
489 15 : measurement_block_size = libspdm_fill_measurement_hem_block (measurement_block,
490 : measurement_hash_algo);
491 15 : measurement_block = (void *)((uint8_t *)measurement_block + measurement_block_size);
492 : }
493 : /* Next one - manifest is always raw bitstream data.*/
494 : {
495 15 : measurement_block_size = libspdm_fill_measurement_manifest_block (measurement_block);
496 15 : measurement_block = (void *)((uint8_t *)measurement_block + measurement_block_size);
497 : }
498 : /* Next one - device_mode is always raw bitstream data.*/
499 : {
500 15 : measurement_block_size = libspdm_fill_measurement_device_mode_block (measurement_block);
501 15 : measurement_block = (void *)((uint8_t *)measurement_block + measurement_block_size);
502 : }
503 :
504 15 : goto successful_return;
505 : } else {
506 : /* One Index */
507 111 : if (measurements_index <= LIBSPDM_MEASUREMENT_BLOCK_HASH_NUMBER) {
508 110 : if (!use_bit_stream) {
509 109 : total_size_needed =
510 : sizeof(spdm_measurement_block_dmtf_t) +
511 : hash_size;
512 : } else {
513 1 : total_size_needed =
514 : sizeof(spdm_measurement_block_dmtf_t) +
515 : LIBSPDM_MEASUREMENT_RAW_DATA_SIZE;
516 : }
517 110 : LIBSPDM_ASSERT(total_size_needed <= *measurements_size);
518 110 : if (total_size_needed > *measurements_size) {
519 0 : return LIBSPDM_STATUS_BUFFER_TOO_SMALL;
520 : }
521 :
522 110 : *measurements_count = 1;
523 110 : *measurements_size = total_size_needed;
524 :
525 110 : measurement_block = measurements;
526 110 : measurement_block_size = libspdm_fill_measurement_image_hash_block (use_bit_stream,
527 : measurement_hash_algo,
528 : measurements_index,
529 : measurement_block);
530 110 : if (measurement_block_size == 0) {
531 0 : return LIBSPDM_STATUS_MEAS_INTERNAL_ERROR;
532 : }
533 1 : } else if (measurements_index == LIBSPDM_MEASUREMENT_INDEX_SVN) {
534 0 : total_size_needed =
535 : sizeof(spdm_measurement_block_dmtf_t) +
536 : sizeof(spdm_measurements_secure_version_number_t);
537 0 : LIBSPDM_ASSERT(total_size_needed <= *measurements_size);
538 0 : if (total_size_needed > *measurements_size) {
539 0 : return LIBSPDM_STATUS_BUFFER_TOO_SMALL;
540 : }
541 :
542 0 : *measurements_count = 1;
543 0 : *measurements_size = total_size_needed;
544 :
545 0 : measurement_block = measurements;
546 0 : measurement_block_size = libspdm_fill_measurement_svn_block (measurement_block);
547 0 : if (measurement_block_size == 0) {
548 0 : return LIBSPDM_STATUS_MEAS_INTERNAL_ERROR;
549 : }
550 1 : } else if (measurements_index == LIBSPDM_MEASUREMENT_INDEX_HEM) {
551 0 : total_size_needed =
552 : sizeof(spdm_measurement_block_dmtf_t) + hash_size;
553 0 : LIBSPDM_ASSERT(total_size_needed <= *measurements_size);
554 0 : if (total_size_needed > *measurements_size) {
555 0 : return LIBSPDM_STATUS_BUFFER_TOO_SMALL;
556 : }
557 :
558 0 : *measurements_count = 1;
559 0 : *measurements_size = total_size_needed;
560 :
561 0 : measurement_block = measurements;
562 0 : measurement_block_size = libspdm_fill_measurement_hem_block (measurement_block,
563 : measurement_hash_algo);
564 0 : if (measurement_block_size == 0) {
565 0 : return LIBSPDM_STATUS_MEAS_INTERNAL_ERROR;
566 : }
567 1 : } else if (measurements_index ==
568 : SPDM_MEASUREMENT_BLOCK_MEASUREMENT_INDEX_MEASUREMENT_MANIFEST) {
569 0 : total_size_needed =
570 : sizeof(spdm_measurement_block_dmtf_t) +
571 : LIBSPDM_MEASUREMENT_MANIFEST_SIZE;
572 0 : LIBSPDM_ASSERT(total_size_needed <= *measurements_size);
573 0 : if (total_size_needed > *measurements_size) {
574 0 : return LIBSPDM_STATUS_BUFFER_TOO_SMALL;
575 : }
576 :
577 0 : *measurements_count = 1;
578 0 : *measurements_size = total_size_needed;
579 :
580 0 : measurement_block = measurements;
581 0 : measurement_block_size = libspdm_fill_measurement_manifest_block (measurement_block);
582 0 : if (measurement_block_size == 0) {
583 0 : return LIBSPDM_STATUS_MEAS_INTERNAL_ERROR;
584 : }
585 1 : } else if (measurements_index == SPDM_MEASUREMENT_BLOCK_MEASUREMENT_INDEX_DEVICE_MODE) {
586 0 : total_size_needed =
587 : sizeof(spdm_measurement_block_dmtf_t) +
588 : sizeof(spdm_measurements_device_mode_t);
589 0 : LIBSPDM_ASSERT(total_size_needed <= *measurements_size);
590 0 : if (total_size_needed > *measurements_size) {
591 0 : return LIBSPDM_STATUS_BUFFER_TOO_SMALL;
592 : }
593 :
594 0 : *measurements_count = 1;
595 0 : *measurements_size = total_size_needed;
596 :
597 0 : measurement_block = measurements;
598 0 : measurement_block_size = libspdm_fill_measurement_device_mode_block (measurement_block);
599 0 : if (measurement_block_size == 0) {
600 0 : return LIBSPDM_STATUS_MEAS_INTERNAL_ERROR;
601 : }
602 : } else {
603 1 : *measurements_count = 0;
604 1 : return LIBSPDM_STATUS_MEAS_INVALID_INDEX;
605 : }
606 : }
607 :
608 136 : successful_return:
609 136 : if ((content_changed != NULL) &&
610 126 : ((spdm_version >> SPDM_VERSION_NUMBER_SHIFT_BIT) >= SPDM_MESSAGE_VERSION_12)) {
611 : /* return content change*/
612 9 : if ((request_attribute & SPDM_GET_MEASUREMENTS_REQUEST_ATTRIBUTES_GENERATE_SIGNATURE) !=
613 : 0) {
614 7 : *content_changed = SPDM_MEASUREMENTS_RESPONSE_CONTENT_NO_CHANGE_DETECTED;
615 : } else {
616 2 : *content_changed = SPDM_MEASUREMENTS_RESPONSE_CONTENT_CHANGE_NO_DETECTION;
617 : }
618 : }
619 :
620 136 : return LIBSPDM_STATUS_SUCCESS;
621 : }
622 :
623 : size_t libspdm_secret_lib_meas_opaque_data_size;
624 :
625 122 : bool libspdm_measurement_opaque_data(
626 : void *spdm_context,
627 : spdm_version_number_t spdm_version,
628 : uint8_t measurement_specification,
629 : uint32_t measurement_hash_algo,
630 : uint8_t measurement_index,
631 : uint8_t request_attribute,
632 : size_t request_context_size,
633 : const void *request_context,
634 : void *opaque_data,
635 : size_t *opaque_data_size)
636 : {
637 : size_t index;
638 :
639 122 : LIBSPDM_ASSERT(libspdm_secret_lib_meas_opaque_data_size <= *opaque_data_size);
640 :
641 122 : if (g_check_measurement_request_context) {
642 0 : if ((spdm_version >> SPDM_VERSION_NUMBER_SHIFT_BIT) >= SPDM_MESSAGE_VERSION_13) {
643 0 : LIBSPDM_ASSERT(request_context_size == SPDM_REQ_CONTEXT_SIZE);
644 0 : LIBSPDM_ASSERT(libspdm_read_uint64(request_context) == g_measurement_request_context);
645 : } else {
646 0 : LIBSPDM_ASSERT(request_context_size == 0);
647 0 : LIBSPDM_ASSERT(request_context == NULL);
648 : }
649 : }
650 :
651 122 : *opaque_data_size = libspdm_secret_lib_meas_opaque_data_size;
652 :
653 218 : for (index = 0; index < *opaque_data_size; index++)
654 : {
655 96 : ((uint8_t *)opaque_data)[index] = (uint8_t)index;
656 : }
657 :
658 122 : return true;
659 : }
660 :
661 10 : bool libspdm_generate_measurement_summary_hash(
662 : void *spdm_context,
663 : spdm_version_number_t spdm_version, uint32_t base_hash_algo,
664 : uint8_t measurement_specification, uint32_t measurement_hash_algo,
665 : uint8_t measurement_summary_hash_type,
666 : uint8_t *measurement_summary_hash,
667 : uint32_t measurement_summary_hash_size)
668 : {
669 : uint8_t measurement_data[LIBSPDM_MAX_MEASUREMENT_RECORD_SIZE];
670 : size_t index;
671 : spdm_measurement_block_dmtf_t *cached_measurement_block;
672 : size_t measurement_data_size;
673 : size_t measurement_block_size;
674 : uint8_t device_measurement[LIBSPDM_MAX_MEASUREMENT_RECORD_SIZE];
675 : uint8_t device_measurement_count;
676 : size_t device_measurement_size;
677 : libspdm_return_t status;
678 : bool result;
679 :
680 10 : switch (measurement_summary_hash_type) {
681 0 : case SPDM_REQUEST_NO_MEASUREMENT_SUMMARY_HASH:
682 0 : return false;
683 :
684 10 : case SPDM_REQUEST_TCB_COMPONENT_MEASUREMENT_HASH:
685 : case SPDM_REQUEST_ALL_MEASUREMENTS_HASH:
686 10 : if (measurement_summary_hash_size != libspdm_get_hash_size(base_hash_algo)) {
687 0 : return false;
688 : }
689 :
690 : /* get all measurement data*/
691 10 : device_measurement_size = sizeof(device_measurement);
692 10 : status = libspdm_measurement_collection(
693 : spdm_context,
694 : spdm_version, measurement_specification,
695 : measurement_hash_algo,
696 : 0xFF, /* Get all measurements*/
697 : 0,
698 : 0,
699 : NULL,
700 : NULL,
701 : &device_measurement_count, device_measurement,
702 : &device_measurement_size);
703 10 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
704 0 : return false;
705 : }
706 :
707 : /* double confirm that MeasurementData internal size is correct*/
708 10 : measurement_data_size = 0;
709 10 : cached_measurement_block = (void *)device_measurement;
710 90 : for (index = 0; index < device_measurement_count; index++) {
711 80 : measurement_block_size =
712 : sizeof(spdm_measurement_block_common_header_t) +
713 : cached_measurement_block
714 : ->measurement_block_common_header
715 80 : .measurement_size;
716 80 : LIBSPDM_ASSERT(cached_measurement_block
717 : ->measurement_block_common_header
718 : .measurement_size ==
719 : sizeof(spdm_measurement_block_dmtf_header_t) +
720 : cached_measurement_block
721 : ->measurement_block_dmtf_header
722 : .dmtf_spec_measurement_value_size);
723 80 : measurement_data_size +=
724 : cached_measurement_block
725 : ->measurement_block_common_header
726 80 : .measurement_size;
727 80 : cached_measurement_block =
728 80 : (void *)((size_t)cached_measurement_block +
729 : measurement_block_size);
730 : }
731 :
732 10 : LIBSPDM_ASSERT(measurement_data_size <=
733 : LIBSPDM_MAX_MEASUREMENT_RECORD_SIZE);
734 :
735 : /* get required data and hash them*/
736 10 : cached_measurement_block = (void *)device_measurement;
737 10 : measurement_data_size = 0;
738 90 : for (index = 0; index < device_measurement_count; index++) {
739 80 : measurement_block_size =
740 : sizeof(spdm_measurement_block_common_header_t) +
741 : cached_measurement_block
742 : ->measurement_block_common_header
743 80 : .measurement_size;
744 : /* filter unneeded data*/
745 80 : if ((measurement_summary_hash_type ==
746 40 : SPDM_REQUEST_ALL_MEASUREMENTS_HASH) ||
747 : ((cached_measurement_block
748 : ->measurement_block_dmtf_header
749 40 : .dmtf_spec_measurement_value_type &
750 : SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_MASK) ==
751 : SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_IMMUTABLE_ROM)) {
752 50 : libspdm_copy_mem(&measurement_data[measurement_data_size],
753 : sizeof(measurement_data)
754 50 : - (&measurement_data[measurement_data_size] - measurement_data),
755 : cached_measurement_block,
756 : sizeof(cached_measurement_block->
757 : measurement_block_common_header) +
758 : cached_measurement_block->measurement_block_common_header
759 50 : .measurement_size);
760 50 : measurement_data_size +=
761 : sizeof(cached_measurement_block->measurement_block_common_header) +
762 : cached_measurement_block
763 : ->measurement_block_common_header
764 50 : .measurement_size;
765 : }
766 80 : cached_measurement_block =
767 80 : (void *)((size_t)cached_measurement_block +
768 : measurement_block_size);
769 : }
770 :
771 10 : result = libspdm_hash_all(base_hash_algo, measurement_data,
772 : measurement_data_size, measurement_summary_hash);
773 10 : if (!result) {
774 0 : return false;
775 : }
776 10 : break;
777 0 : default:
778 0 : return false;
779 : break;
780 : }
781 10 : return true;
782 : }
783 : #endif /* LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP */
784 :
785 : #if LIBSPDM_ENABLE_CAPABILITY_MEL_CAP
786 : /*Collect the measurement extension log.*/
787 11 : bool libspdm_measurement_extension_log_collection(
788 : void *spdm_context,
789 : uint8_t mel_specification,
790 : uint8_t measurement_specification,
791 : uint32_t measurement_hash_algo,
792 : void **spdm_mel,
793 : size_t *spdm_mel_size)
794 : {
795 : spdm_measurement_extension_log_dmtf_t *measurement_extension_log;
796 :
797 11 : if ((measurement_specification !=
798 11 : SPDM_MEASUREMENT_SPECIFICATION_DMTF) ||
799 11 : (mel_specification != SPDM_MEL_SPECIFICATION_DMTF) ||
800 : (measurement_hash_algo == 0)) {
801 0 : return false;
802 : }
803 :
804 11 : libspdm_generate_mel(measurement_hash_algo);
805 :
806 11 : measurement_extension_log = (spdm_measurement_extension_log_dmtf_t *)m_libspdm_mel;
807 11 : *spdm_mel = (spdm_measurement_extension_log_dmtf_t *)m_libspdm_mel;
808 11 : *spdm_mel_size = (size_t)(measurement_extension_log->mel_entries_len) +
809 : sizeof(spdm_measurement_extension_log_dmtf_t);
810 11 : return true;
811 : }
812 : #endif /* LIBSPDM_ENABLE_CAPABILITY_MEL_CAP */
|