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) */
|