Branch data Line data Source code
1 : : /**
2 : : * Copyright Notice:
3 : : * Copyright 2025-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_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 : : /* -=[Log Message Phase]=- */
126 : : #if LIBSPDM_ENABLE_MSG_LOG
127 : 1 : libspdm_append_msg_log(spdm_context, spdm_response, spdm_response_size);
128 : : #endif /* LIBSPDM_ENABLE_MSG_LOG */
129 : :
130 : 5 : receive_done:
131 : 5 : libspdm_release_receiver_buffer(spdm_context);
132 : :
133 : 5 : return status;
134 : : }
135 : :
136 : 10 : libspdm_return_t libspdm_send_event(void *spdm_context, uint32_t session_id, uint32_t event_count,
137 : : size_t events_list_size, void *events_list)
138 : : {
139 : : size_t retry;
140 : : uint64_t retry_delay_time;
141 : : libspdm_return_t status;
142 : : libspdm_context_t *context;
143 : :
144 : 10 : context = spdm_context;
145 : 10 : context->crypto_request = false;
146 : 10 : retry = context->retry_times;
147 : 10 : retry_delay_time = context->retry_delay_time;
148 : :
149 : : do {
150 : 10 : status = libspdm_try_send_event(context, session_id, event_count, events_list_size,
151 : : events_list);
152 [ + - ]: 10 : if (status != LIBSPDM_STATUS_BUSY_PEER) {
153 : 10 : return status;
154 : : }
155 : :
156 : 0 : libspdm_sleep(retry_delay_time);
157 [ # # ]: 0 : } while (retry-- != 0);
158 : :
159 : 0 : return status;
160 : : }
161 : : #endif /* LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP */
|