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_EVENT_CAP
10 :
11 10 : static libspdm_return_t libspdm_try_send_event(
12 : libspdm_context_t *spdm_context, uint32_t session_id,
13 : uint32_t event_count, size_t events_list_size, void *events_list)
14 : {
15 : libspdm_return_t status;
16 : libspdm_session_info_t *session_info;
17 : spdm_send_event_request_t *spdm_request;
18 : size_t spdm_request_size;
19 : spdm_event_ack_response_t *spdm_response;
20 : size_t spdm_response_size;
21 : size_t transport_header_size;
22 : uint8_t *message;
23 : size_t message_size;
24 :
25 : /* -=[Check Parameters Phase]=- */
26 10 : LIBSPDM_ASSERT(event_count != 0);
27 10 : LIBSPDM_ASSERT(events_list_size != 0);
28 10 : LIBSPDM_ASSERT(events_list != NULL);
29 :
30 10 : session_info = libspdm_get_session_info_via_session_id(spdm_context, session_id);
31 :
32 10 : if (session_info == NULL) {
33 0 : LIBSPDM_ASSERT(false);
34 0 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
35 : }
36 10 : if (libspdm_secured_message_get_session_state(session_info->secured_message_context) !=
37 : LIBSPDM_SESSION_STATE_ESTABLISHED) {
38 0 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
39 : }
40 :
41 : /* -=[Verify State Phase]=- */
42 10 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_13) {
43 1 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
44 : }
45 9 : if (!libspdm_is_capabilities_flag_supported(
46 : spdm_context, true, SPDM_GET_CAPABILITIES_REQUEST_FLAGS_EVENT_CAP, 0)) {
47 1 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
48 : }
49 :
50 : /* -=[Construct Request Phase]=- */
51 8 : transport_header_size = spdm_context->local_context.capability.transport_header_size;
52 8 : status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message);
53 8 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
54 1 : return status;
55 : }
56 7 : LIBSPDM_ASSERT (message_size >= transport_header_size +
57 : spdm_context->local_context.capability.transport_tail_size);
58 7 : spdm_request = (void *)(message + transport_header_size);
59 7 : spdm_request_size = message_size - transport_header_size -
60 7 : spdm_context->local_context.capability.transport_tail_size;
61 :
62 7 : if (spdm_request_size < sizeof(spdm_send_event_request_t) + events_list_size) {
63 0 : libspdm_release_sender_buffer(spdm_context);
64 0 : return LIBSPDM_STATUS_BUFFER_TOO_SMALL;
65 : }
66 :
67 7 : spdm_request->header.spdm_version = libspdm_get_connection_version(spdm_context);
68 7 : spdm_request->header.request_response_code = SPDM_SEND_EVENT;
69 7 : spdm_request->header.param1 = 0;
70 7 : spdm_request->header.param2 = 0;
71 7 : spdm_request->event_count = event_count;
72 :
73 7 : libspdm_copy_mem(spdm_request + 1, spdm_request_size - sizeof(spdm_send_event_request_t),
74 : events_list, events_list_size);
75 :
76 7 : spdm_request_size = sizeof(spdm_send_event_request_t) + events_list_size;
77 :
78 : /* -=[Send Request Phase]=- */
79 7 : status = libspdm_send_spdm_request(spdm_context, &session_id, spdm_request_size, spdm_request);
80 7 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
81 1 : libspdm_release_sender_buffer (spdm_context);
82 1 : return status;
83 : }
84 :
85 6 : libspdm_release_sender_buffer(spdm_context);
86 6 : spdm_request = (void *)spdm_context->last_spdm_request;
87 :
88 : /* -=[Receive Response Phase]=- */
89 6 : status = libspdm_acquire_receiver_buffer(spdm_context, &message_size, (void **)&message);
90 6 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
91 1 : return status;
92 : }
93 5 : LIBSPDM_ASSERT (message_size >= transport_header_size);
94 5 : spdm_response = (void *)(message);
95 5 : spdm_response_size = message_size;
96 :
97 5 : status = libspdm_receive_spdm_response(
98 : spdm_context, &session_id, &spdm_response_size, (void **)&spdm_response);
99 5 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
100 1 : goto receive_done;
101 : }
102 :
103 : /* -=[Validate Response Phase]=- */
104 4 : if (spdm_response_size != sizeof(spdm_event_ack_response_t)) {
105 1 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
106 1 : goto receive_done;
107 : }
108 3 : if (spdm_response->header.request_response_code == SPDM_ERROR) {
109 0 : status = libspdm_handle_error_response_main(
110 : spdm_context, &session_id,
111 : &spdm_response_size, (void **)&spdm_response,
112 : SPDM_SEND_EVENT, SPDM_EVENT_ACK);
113 0 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
114 0 : goto receive_done;
115 : }
116 3 : } else if (spdm_response->header.request_response_code != SPDM_EVENT_ACK) {
117 1 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
118 1 : goto receive_done;
119 : }
120 2 : if (spdm_response->header.spdm_version != spdm_request->header.spdm_version) {
121 1 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
122 1 : goto receive_done;
123 : }
124 :
125 1 : receive_done:
126 5 : libspdm_release_receiver_buffer(spdm_context);
127 :
128 5 : return status;
129 : }
130 :
131 10 : libspdm_return_t libspdm_send_event(void *spdm_context, uint32_t session_id, uint32_t event_count,
132 : size_t events_list_size, void *events_list)
133 : {
134 : size_t retry;
135 : uint64_t retry_delay_time;
136 : libspdm_return_t status;
137 : libspdm_context_t *context;
138 :
139 10 : context = spdm_context;
140 10 : context->crypto_request = false;
141 10 : retry = context->retry_times;
142 10 : retry_delay_time = context->retry_delay_time;
143 :
144 : do {
145 10 : status = libspdm_try_send_event(context, session_id, event_count, events_list_size,
146 : events_list);
147 10 : if (status != LIBSPDM_STATUS_BUSY_PEER) {
148 10 : return status;
149 : }
150 :
151 0 : libspdm_sleep(retry_delay_time);
152 0 : } while (retry-- != 0);
153 :
154 0 : return status;
155 : }
156 : #endif /* LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP */
|