Branch data Line data Source code
1 : : /**
2 : : * Copyright Notice:
3 : : * Copyright 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 "internal/libspdm_requester_lib.h"
8 : :
9 : : #if (LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP) && (LIBSPDM_EVENT_RECIPIENT_SUPPORT)
10 : :
11 : 8 : libspdm_return_t libspdm_get_encap_response_event_ack(void *spdm_context,
12 : : size_t request_size,
13 : : void *request,
14 : : size_t *response_size,
15 : : void *response)
16 : : {
17 : : spdm_send_event_request_t *spdm_request;
18 : : spdm_event_ack_response_t *spdm_response;
19 : : libspdm_context_t *context;
20 : : uint32_t session_id;
21 : : libspdm_session_info_t *session_info;
22 : : libspdm_session_state_t session_state;
23 : : uint64_t index;
24 : : uint32_t prev_event_instance_id;
25 : : uint32_t event_instance_id_min;
26 : : uint32_t event_instance_id_max;
27 : : bool events_list_is_sequential;
28 : : uint8_t *ptr;
29 : 8 : const uint8_t *end_ptr = (uint8_t *)request + request_size;
30 : : size_t calculated_request_size;
31 : :
32 : 8 : context = spdm_context;
33 : 8 : spdm_request = request;
34 : :
35 [ - + ]: 8 : if (libspdm_get_connection_version(context) < SPDM_MESSAGE_VERSION_13) {
36 : 0 : return libspdm_generate_encap_error_response(
37 : : context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST, SPDM_SEND_EVENT, response_size, response);
38 : : }
39 [ - + ]: 8 : if (spdm_request->header.spdm_version != libspdm_get_connection_version(context)) {
40 : 0 : return libspdm_generate_encap_error_response(
41 : : context, SPDM_ERROR_CODE_VERSION_MISMATCH, 0, response_size, response);
42 : : }
43 [ - + ]: 8 : if (!libspdm_is_capabilities_flag_supported(
44 : : context, true, 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EVENT_CAP)) {
45 : 0 : return libspdm_generate_encap_error_response(
46 : : context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST, SPDM_SEND_EVENT, response_size, response);
47 : : }
48 [ - + ]: 8 : if (!context->last_spdm_request_session_id_valid) {
49 : 0 : return libspdm_generate_encap_error_response(
50 : : context, SPDM_ERROR_CODE_SESSION_REQUIRED, 0, response_size, response);
51 : : }
52 : :
53 : 8 : session_id = context->last_spdm_request_session_id;
54 : 8 : session_info = libspdm_get_session_info_via_session_id(context, session_id);
55 [ - + ]: 8 : if (session_info == NULL) {
56 : 0 : return libspdm_generate_encap_error_response(
57 : : context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
58 : : }
59 : :
60 : 8 : session_state = libspdm_secured_message_get_session_state(
61 : : session_info->secured_message_context);
62 [ - + ]: 8 : if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
63 : 0 : return libspdm_generate_encap_error_response(
64 : : context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
65 : : }
66 : :
67 : 8 : libspdm_reset_message_buffer_via_request_code(context, NULL,
68 : 8 : spdm_request->header.request_response_code);
69 : :
70 [ - + ]: 8 : if (!libspdm_check_for_space((uint8_t *)request, end_ptr, sizeof(spdm_send_event_request_t))) {
71 : 0 : return libspdm_generate_encap_error_response(
72 : : context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
73 : : }
74 : :
75 [ + + ]: 8 : if (spdm_request->event_count == 0) {
76 : 1 : return libspdm_generate_encap_error_response(
77 : : context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
78 : : }
79 : :
80 : 7 : ptr = (uint8_t *)(spdm_request + 1);
81 : :
82 : 7 : event_instance_id_min = UINT32_MAX;
83 : 7 : event_instance_id_max = 0;
84 : 7 : events_list_is_sequential = true;
85 : :
86 : 7 : calculated_request_size = sizeof(spdm_send_event_request_t);
87 : :
88 : : /* Parse and validate all events for size and fields. */
89 [ + + ]: 20 : for (index = 0; index < spdm_request->event_count; index++) {
90 : : uint32_t event_instance_id;
91 : : uint8_t svh_id;
92 : : uint8_t svh_vendor_id_len;
93 : : uint16_t event_type_id;
94 : : uint16_t event_detail_len;
95 : :
96 [ + + ]: 14 : if (!libspdm_check_for_space(ptr, end_ptr,
97 : : sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint8_t) +
98 : : sizeof(uint8_t))) {
99 : 1 : return libspdm_generate_encap_error_response(
100 : : context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
101 : : }
102 : :
103 : 13 : event_instance_id = libspdm_read_uint32(ptr);
104 : :
105 [ + + + - ]: 13 : if ((index != 0) && events_list_is_sequential) {
106 [ + + ]: 6 : if (event_instance_id != (prev_event_instance_id + 1)) {
107 : 2 : events_list_is_sequential = false;
108 : : }
109 : : }
110 [ + + ]: 13 : if (event_instance_id < event_instance_id_min) {
111 : 8 : event_instance_id_min = event_instance_id;
112 : : }
113 [ + + ]: 13 : if (event_instance_id > event_instance_id_max) {
114 : 12 : event_instance_id_max = event_instance_id;
115 : : }
116 : 13 : prev_event_instance_id = event_instance_id;
117 : :
118 : 13 : ptr += sizeof(uint32_t) + sizeof(uint32_t);
119 : 13 : svh_id = *ptr;
120 : 13 : ptr += sizeof(uint8_t);
121 : 13 : svh_vendor_id_len = *ptr;
122 : 13 : ptr += sizeof(uint8_t);
123 : :
124 [ - + ]: 13 : if (!libspdm_validate_svh_vendor_id_len(svh_id, svh_vendor_id_len)) {
125 : 0 : return libspdm_generate_encap_error_response(
126 : : context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
127 : : }
128 : :
129 [ - + ]: 13 : if (!libspdm_check_for_space(
130 : 13 : ptr, end_ptr, (size_t)svh_vendor_id_len + sizeof(uint16_t) + sizeof(uint16_t))) {
131 : 0 : return libspdm_generate_encap_error_response(
132 : : context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
133 : : }
134 : :
135 : 13 : ptr += svh_vendor_id_len;
136 : :
137 : 13 : event_type_id = libspdm_read_uint16(ptr);
138 : 13 : ptr += sizeof(uint16_t);
139 : 13 : event_detail_len = libspdm_read_uint16(ptr);
140 : 13 : ptr += sizeof(uint16_t);
141 : :
142 [ + - ]: 13 : if (svh_id == SPDM_REGISTRY_ID_DMTF) {
143 [ - + ]: 13 : if (!libspdm_validate_dmtf_event_type(event_type_id, event_detail_len)) {
144 : 0 : return libspdm_generate_encap_error_response(
145 : : context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
146 : : }
147 : : }
148 : :
149 [ - + ]: 13 : if (!libspdm_check_for_space(ptr, end_ptr, (size_t)event_detail_len)) {
150 : 0 : return libspdm_generate_encap_error_response(
151 : : context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
152 : : }
153 : :
154 : 13 : ptr += event_detail_len;
155 : 13 : calculated_request_size += sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint8_t) +
156 : 13 : sizeof(uint8_t) + (size_t)svh_vendor_id_len + sizeof(uint16_t) +
157 : 13 : sizeof(uint16_t) + (size_t)event_detail_len;
158 : : }
159 : :
160 : : /* Event must be sent in a secure session so message size can be calculated exactly. */
161 [ + + ]: 6 : if (request_size != calculated_request_size) {
162 : 1 : return libspdm_generate_encap_error_response(
163 : : context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
164 : : }
165 : :
166 : : /* If event instance IDs are not sequential then ensure there are no gaps or duplicates before
167 : : * sending individual events to Integrator. */
168 [ + + ]: 5 : if (!events_list_is_sequential) {
169 : 2 : void *event_data = spdm_request + 1;
170 : :
171 [ + + ]: 2 : if ((event_instance_id_max - event_instance_id_min + 1) != spdm_request->event_count) {
172 : 1 : return libspdm_generate_encap_error_response(
173 : : context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
174 : : }
175 : :
176 [ + + ]: 3 : for (index = 0; index < spdm_request->event_count; index++) {
177 [ - + ]: 2 : if (libspdm_find_event_instance_id(event_data, spdm_request->event_count,
178 : 2 : event_instance_id_min + (uint32_t)index) == NULL) {
179 : 0 : return libspdm_generate_encap_error_response(
180 : : context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
181 : : }
182 : : }
183 : : }
184 : :
185 [ + - ]: 4 : if (context->process_event != NULL) {
186 : 4 : const void *next_event_data = spdm_request + 1;
187 : :
188 [ + + ]: 13 : for (index = 0; index < spdm_request->event_count; index++) {
189 [ + + ]: 9 : if (events_list_is_sequential) {
190 [ - + ]: 7 : if (!libspdm_parse_and_send_event(
191 : : context, session_id, next_event_data, &next_event_data)) {
192 : 0 : return libspdm_generate_encap_error_response(
193 : : context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
194 : : }
195 : : } else {
196 : : const void *event_data;
197 : :
198 : 2 : event_data = libspdm_find_event_instance_id(
199 : : next_event_data, spdm_request->event_count,
200 : 2 : event_instance_id_min + (uint32_t)index);
201 [ - + ]: 2 : if (event_data == NULL) {
202 : 0 : return libspdm_generate_encap_error_response(
203 : : context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
204 : : }
205 : :
206 [ - + ]: 2 : if (!libspdm_parse_and_send_event(context, session_id, event_data, NULL)) {
207 : 0 : return libspdm_generate_encap_error_response(
208 : : context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
209 : : }
210 : : }
211 : : }
212 : : }
213 : :
214 : 4 : spdm_response = response;
215 : :
216 : 4 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
217 : 4 : spdm_response->header.request_response_code = SPDM_EVENT_ACK;
218 : 4 : spdm_response->header.param1 = 0;
219 : 4 : spdm_response->header.param2 = 0;
220 : :
221 : 4 : *response_size = sizeof(spdm_event_ack_response_t);
222 : :
223 : 4 : return LIBSPDM_STATUS_SUCCESS;
224 : : }
225 : :
226 : : #endif /* (LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP) && (LIBSPDM_EVENT_RECIPIENT_SUPPORT) */
|