Branch data Line data Source code
1 : : /**
2 : : * Copyright Notice:
3 : : * Copyright 2021-2026 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 "internal/libspdm_responder_lib.h"
8 : :
9 : : #if (LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP) && (LIBSPDM_SEND_GET_CERTIFICATE_SUPPORT)
10 : :
11 : 10 : libspdm_return_t libspdm_get_encap_request_get_digests(void *context,
12 : : const uint32_t *session_id,
13 : : size_t *encap_request_size,
14 : : void *encap_request)
15 : : {
16 : : libspdm_encap_context_t *encap_context;
17 : : spdm_get_digest_request_t *spdm_request;
18 : : libspdm_return_t status;
19 : : libspdm_context_t *spdm_context;
20 : :
21 : 10 : spdm_context = context;
22 : :
23 : 10 : encap_context = libspdm_get_encap_context(spdm_context, session_id);
24 [ + + ]: 10 : if (encap_context == NULL) {
25 : : /* session_id does not refer to an existing session. */
26 : 1 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
27 : : }
28 : :
29 : 9 : encap_context->last_encap_request_size = 0;
30 : :
31 [ - + ]: 9 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
32 : 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
33 : : }
34 : :
35 [ - + ]: 9 : if (!libspdm_is_capabilities_flag_supported(
36 : : spdm_context, false,
37 : : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CERT_CAP, 0)) {
38 : 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
39 : : }
40 : :
41 [ - + ]: 9 : LIBSPDM_ASSERT(*encap_request_size >= sizeof(spdm_get_digest_request_t));
42 : 9 : *encap_request_size = sizeof(spdm_get_digest_request_t);
43 : :
44 : 9 : spdm_request = encap_request;
45 : :
46 : 9 : spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
47 : 9 : spdm_request->header.request_response_code = SPDM_GET_DIGESTS;
48 : 9 : spdm_request->header.param1 = 0;
49 : 9 : spdm_request->header.param2 = 0;
50 : :
51 : 9 : status = libspdm_append_message_mut_b(spdm_context, spdm_request, *encap_request_size);
52 [ - + ]: 9 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
53 : 0 : return LIBSPDM_STATUS_BUFFER_FULL;
54 : : }
55 : :
56 : 9 : libspdm_copy_mem(&encap_context->last_encap_request_header,
57 : : sizeof(encap_context->last_encap_request_header),
58 : 9 : &spdm_request->header, sizeof(spdm_message_header_t));
59 : 9 : encap_context->last_encap_request_size = *encap_request_size;
60 : :
61 : 9 : return LIBSPDM_STATUS_SUCCESS;
62 : : }
63 : :
64 : 26 : libspdm_return_t libspdm_process_encap_response_digest(
65 : : libspdm_context_t *spdm_context, size_t encap_response_size,
66 : : const void *encap_response, bool *need_continue)
67 : : {
68 : : const spdm_digest_response_t *spdm_response;
69 : : size_t spdm_response_size;
70 : : size_t digest_size;
71 : : size_t digest_count;
72 : : size_t index;
73 : : libspdm_return_t status;
74 : : uint32_t session_id;
75 : : libspdm_session_info_t *session_info;
76 : : size_t additional_size;
77 : : spdm_key_pair_id_t *key_pair_id;
78 : : spdm_certificate_info_t *cert_info;
79 : : spdm_key_usage_bit_mask_t *key_usage_bit_mask;
80 : : size_t slot_index;
81 : : uint8_t cert_model;
82 : 26 : uint8_t zero_digest[LIBSPDM_MAX_HASH_SIZE] = {0};
83 : :
84 : 26 : spdm_response = encap_response;
85 : 26 : spdm_response_size = encap_response_size;
86 : :
87 [ + + ]: 26 : if (spdm_response_size < sizeof(spdm_message_header_t)) {
88 : 1 : return LIBSPDM_STATUS_INVALID_MSG_SIZE;
89 : : }
90 [ + + ]: 25 : if (spdm_response->header.spdm_version != libspdm_get_connection_version (spdm_context)) {
91 : 1 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
92 : : }
93 [ + + ]: 24 : if (spdm_response->header.request_response_code == SPDM_ERROR) {
94 : 7 : status = libspdm_handle_encap_error_response_main(spdm_response->header.param1);
95 [ + - ]: 7 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
96 : 7 : return status;
97 : : }
98 [ + + ]: 17 : } else if (spdm_response->header.request_response_code != SPDM_DIGESTS) {
99 : 2 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
100 : : }
101 [ - + ]: 15 : if (spdm_response_size < sizeof(spdm_digest_response_t)) {
102 : 0 : return LIBSPDM_STATUS_INVALID_MSG_SIZE;
103 : : }
104 : :
105 : 15 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "provisioned_slot_mask - 0x%02x\n",
106 : : spdm_response->header.param2));
107 [ + + ]: 15 : if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
108 : 3 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "supported_slot_mask - 0x%02x\n",
109 : : spdm_response->header.param1));
110 : 3 : if ((spdm_response->header.param1 & spdm_response->header.param2) !=
111 [ - + ]: 3 : spdm_response->header.param2) {
112 : 0 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
113 : : }
114 : : }
115 : :
116 : 15 : digest_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
117 : 15 : digest_count = 0;
118 : :
119 [ + + ]: 135 : for (index = 0; index < SPDM_MAX_SLOT_COUNT; index++) {
120 [ + + ]: 120 : if (spdm_response->header.param2 & (1 << index)) {
121 : 24 : digest_count++;
122 : : }
123 : : }
124 [ - + ]: 15 : if (digest_count == 0) {
125 : 0 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
126 : : }
127 : :
128 : 15 : additional_size = 0;
129 [ + + ]: 15 : if ((spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_13) &&
130 [ + + ]: 3 : spdm_context->connection_info.multi_key_conn_req) {
131 : 2 : additional_size = sizeof(spdm_key_pair_id_t) + sizeof(spdm_certificate_info_t) +
132 : : sizeof(spdm_key_usage_bit_mask_t);
133 : : }
134 : 15 : if (spdm_response_size <
135 [ - + ]: 15 : sizeof(spdm_digest_response_t) + digest_count * (digest_size + additional_size)) {
136 : 0 : return LIBSPDM_STATUS_INVALID_MSG_SIZE;
137 : : }
138 : 15 : spdm_response_size =
139 : 15 : sizeof(spdm_digest_response_t) + digest_count * (digest_size + additional_size);
140 : :
141 : 15 : status = libspdm_append_message_mut_b(spdm_context, spdm_response, spdm_response_size);
142 [ - + ]: 15 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
143 : 0 : return LIBSPDM_STATUS_BUFFER_FULL;
144 : : }
145 : :
146 [ + + ]: 15 : if (spdm_context->last_spdm_request_session_id_valid) {
147 : 5 : session_id = spdm_context->last_spdm_request_session_id;
148 : : } else {
149 : 10 : session_id = spdm_context->latest_session_id;
150 : : }
151 [ + + ]: 15 : if (session_id != INVALID_SESSION_ID) {
152 : 13 : session_info = libspdm_get_session_info_via_session_id(spdm_context, session_id);
153 : : } else {
154 : 2 : session_info = NULL;
155 : : }
156 [ + + ]: 15 : if (session_info != NULL) {
157 [ + + ]: 13 : if (spdm_context->connection_info.multi_key_conn_req) {
158 : 2 : status = libspdm_append_message_encap_d(session_info, spdm_response,
159 : : spdm_response_size);
160 [ - + ]: 2 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
161 : 0 : return LIBSPDM_STATUS_BUFFER_FULL;
162 : : }
163 : : }
164 : : }
165 : :
166 : 15 : key_pair_id =
167 : 15 : (spdm_key_pair_id_t *)((size_t)(spdm_response + 1) + digest_size * digest_count);
168 : 15 : cert_info =
169 : : (spdm_certificate_info_t *)((uint8_t *)key_pair_id + sizeof(spdm_key_pair_id_t) *
170 : : digest_count);
171 : 15 : key_usage_bit_mask =
172 : : (spdm_key_usage_bit_mask_t *)((uint8_t *)cert_info + sizeof(spdm_certificate_info_t) *
173 : : digest_count);
174 [ + + ]: 39 : for (index = 0; index < digest_count; index++) {
175 : 24 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "digest (0x%zx) - ", index));
176 : 24 : LIBSPDM_INTERNAL_DUMP_DATA(
177 : : (const uint8_t *)(spdm_response + 1) + (digest_size * index), digest_size);
178 : 24 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
179 : : }
180 [ + + ]: 15 : if ((spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_13) &&
181 [ + + ]: 3 : spdm_context->connection_info.multi_key_conn_req) {
182 [ + + ]: 11 : for (index = 0; index < digest_count; index++) {
183 : 9 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "key_pair_id (0x%zx) - 0x%02x\n", index,
184 : : key_pair_id[index]));
185 : : }
186 [ + + ]: 11 : for (index = 0; index < digest_count; index++) {
187 : 9 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "cert_info (0x%zx) - 0x%02x\n", index,
188 : : cert_info[index]));
189 : : }
190 [ + + ]: 11 : for (index = 0; index < digest_count; index++) {
191 : 9 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "key_usage_bit_mask (0x%zx) - 0x%04x\n", index,
192 : : key_usage_bit_mask[index]));
193 : : }
194 : : }
195 : :
196 : 15 : spdm_context->connection_info.peer_provisioned_slot_mask = spdm_response->header.param2;
197 [ + + ]: 15 : if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
198 : 3 : spdm_context->connection_info.peer_supported_slot_mask = spdm_response->header.param1;
199 : : } else {
200 : 12 : spdm_context->connection_info.peer_supported_slot_mask = spdm_response->header.param2;
201 : : }
202 : :
203 : 15 : libspdm_zero_mem(spdm_context->connection_info.peer_key_pair_id,
204 : : sizeof(spdm_context->connection_info.peer_key_pair_id));
205 : 15 : libspdm_zero_mem(spdm_context->connection_info.peer_cert_info,
206 : : sizeof(spdm_context->connection_info.peer_cert_info));
207 : 15 : libspdm_zero_mem(spdm_context->connection_info.peer_key_usage_bit_mask,
208 : : sizeof(spdm_context->connection_info.peer_key_usage_bit_mask));
209 : :
210 [ + + ]: 15 : if ((spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_13) &&
211 [ + + ]: 3 : spdm_context->connection_info.multi_key_conn_req) {
212 : 2 : slot_index = 0;
213 [ + + ]: 18 : for (index = 0; index < SPDM_MAX_SLOT_COUNT; index++) {
214 [ + + ]: 16 : if (spdm_response->header.param2 & (1 << index)) {
215 : 9 : spdm_context->connection_info.peer_key_pair_id[index] = key_pair_id[slot_index];
216 : 9 : cert_model = cert_info[slot_index] & SPDM_CERTIFICATE_INFO_CERT_MODEL_MASK;
217 [ - + ]: 9 : if (cert_model > SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT) {
218 : 0 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
219 : : }
220 [ + + ]: 9 : if (index == 0) {
221 [ - + ]: 2 : if (cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT) {
222 : 0 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
223 : : }
224 [ - + ]: 2 : if ((key_usage_bit_mask[slot_index] &
225 : : (SPDM_KEY_USAGE_BIT_MASK_KEY_EX_USE |
226 : : SPDM_KEY_USAGE_BIT_MASK_CHALLENGE_USE |
227 : : SPDM_KEY_USAGE_BIT_MASK_MEASUREMENT_USE |
228 : : SPDM_KEY_USAGE_BIT_MASK_ENDPOINT_INFO_USE)) == 0) {
229 : 0 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
230 : : }
231 : : }
232 [ - + ]: 9 : if ((cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_NONE) &&
233 [ # # ]: 0 : (!libspdm_consttime_is_mem_equal(
234 : 0 : (const uint8_t *)(spdm_response + 1) + digest_size * slot_index,
235 : : zero_digest,
236 : : digest_size))) {
237 : 0 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
238 : : }
239 : 9 : spdm_context->connection_info.peer_cert_info[index] = cert_model;
240 : 9 : spdm_context->connection_info.peer_key_usage_bit_mask[index] =
241 : 9 : key_usage_bit_mask[slot_index];
242 : 9 : slot_index++;
243 : : }
244 : : }
245 : : }
246 : :
247 : 15 : *need_continue = false;
248 : :
249 : 15 : return LIBSPDM_STATUS_SUCCESS;
250 : : }
251 : :
252 : : #endif /* (LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP) && (...) */
|