Line data Source code
1 : /**
2 : * Copyright Notice:
3 : * Copyright 2023-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_responder_lib.h"
8 :
9 : #if LIBSPDM_ENABLE_VENDOR_DEFINED_MESSAGES
10 :
11 : /* expected number of bytes for VENDOR MESSAGE HEADERS */
12 : #define SPDM_VENDOR_DEFINED_FIXED_HEADER_LEN 7
13 :
14 3 : libspdm_return_t libspdm_register_vendor_get_id_callback_func(void *spdm_context,
15 : libspdm_vendor_get_id_callback_func resp_callback)
16 : {
17 :
18 3 : libspdm_context_t *context = (libspdm_context_t *)spdm_context;
19 3 : context->vendor_response_get_id = resp_callback;
20 3 : return LIBSPDM_STATUS_SUCCESS;
21 : }
22 :
23 4 : libspdm_return_t libspdm_register_vendor_callback_func(void *spdm_context,
24 : libspdm_vendor_response_callback_func resp_callback)
25 : {
26 :
27 4 : libspdm_context_t *context = (libspdm_context_t *)spdm_context;
28 4 : context->vendor_response_callback = resp_callback;
29 4 : return LIBSPDM_STATUS_SUCCESS;
30 : }
31 :
32 5 : libspdm_return_t libspdm_get_vendor_defined_response(libspdm_context_t *spdm_context,
33 : size_t request_size,
34 : const void *request,
35 : size_t *response_size,
36 : void *response)
37 : {
38 : const spdm_vendor_defined_request_msg_t *spdm_request;
39 : spdm_vendor_defined_response_msg_t *spdm_response;
40 : uint16_t header_length;
41 5 : size_t response_capacity = 0;
42 5 : libspdm_return_t status = LIBSPDM_STATUS_SUCCESS;
43 :
44 5 : libspdm_session_info_t *session_info = NULL;
45 5 : libspdm_session_state_t session_state = 0;
46 5 : const uint32_t *session_id = NULL;
47 5 : uint8_t *resp_data = NULL;
48 : const uint8_t *req_vendor_id;
49 : const uint8_t *req_data;
50 5 : uint16_t resp_size = 0;
51 5 : uint16_t req_size = 0;
52 :
53 : /* -=[Check Parameters Phase]=- */
54 5 : if (request == NULL ||
55 4 : response == NULL ||
56 : response_size == NULL) {
57 1 : return LIBSPDM_STATUS_INVALID_PARAMETER;
58 : }
59 :
60 4 : if (spdm_context->last_spdm_request_session_id_valid) {
61 1 : session_info = libspdm_get_session_info_via_session_id(
62 : spdm_context,
63 : spdm_context->last_spdm_request_session_id);
64 1 : if (session_info == NULL) {
65 0 : return libspdm_generate_error_response(
66 : spdm_context,
67 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
68 : response_size, response);
69 : }
70 1 : session_state = libspdm_secured_message_get_session_state(
71 : session_info->secured_message_context);
72 1 : if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
73 0 : return libspdm_generate_error_response(
74 : spdm_context,
75 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
76 : response_size, response);
77 : }
78 1 : session_id = &session_info->session_id;
79 : }
80 :
81 : /* Check if caller is using the old Vendor Defined API. */
82 4 : if ((spdm_context->vendor_response_callback == NULL ||
83 2 : spdm_context->vendor_response_get_id == NULL)) {
84 2 : if (spdm_context->get_response_func != NULL) {
85 1 : return ((libspdm_get_response_func)spdm_context->get_response_func)(
86 : spdm_context,
87 : session_id,
88 : false,
89 : request_size,
90 : request,
91 : response_size,
92 : response);
93 : } else
94 1 : return libspdm_generate_error_response(spdm_context,
95 : SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
96 : SPDM_VENDOR_DEFINED_REQUEST,
97 : response_size, response);
98 : }
99 :
100 2 : spdm_request = request;
101 :
102 2 : if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
103 0 : return libspdm_generate_error_response(spdm_context,
104 : SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
105 : response_size, response);
106 : }
107 2 : if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
108 0 : return libspdm_responder_handle_response_state(
109 : spdm_context,
110 0 : spdm_request->header.request_response_code,
111 : response_size, response);
112 : }
113 2 : if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
114 0 : return libspdm_generate_error_response(spdm_context,
115 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
116 : 0, response_size, response);
117 : }
118 :
119 2 : if (request_size < sizeof(spdm_vendor_defined_request_msg_t)) {
120 0 : return libspdm_generate_error_response(spdm_context,
121 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
122 : response_size, response);
123 : }
124 2 : if (request_size < sizeof(spdm_vendor_defined_request_msg_t) +
125 2 : spdm_request->len + sizeof(uint16_t)) {
126 0 : return libspdm_generate_error_response(spdm_context,
127 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
128 : response_size, response);
129 : }
130 :
131 2 : req_vendor_id = ((const uint8_t *)request) + sizeof(spdm_vendor_defined_request_msg_t);
132 2 : req_size = *(const uint16_t *)(req_vendor_id + spdm_request->len);
133 :
134 2 : if (request_size < sizeof(spdm_vendor_defined_request_msg_t) +
135 2 : spdm_request->len + sizeof(uint16_t) + req_size) {
136 0 : return libspdm_generate_error_response(spdm_context,
137 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
138 : response_size, response);
139 : }
140 :
141 2 : libspdm_reset_message_buffer_via_request_code(spdm_context, NULL,
142 2 : spdm_request->header.request_response_code);
143 :
144 : /* length of spdm request/response header before payload start */
145 2 : header_length = sizeof(spdm_vendor_defined_response_msg_t) + spdm_request->len +
146 : sizeof(uint16_t);
147 :
148 2 : LIBSPDM_ASSERT(*response_size >= header_length);
149 : LIBSPDM_ASSERT(
150 : sizeof(spdm_vendor_defined_response_msg_t) == SPDM_VENDOR_DEFINED_FIXED_HEADER_LEN);
151 2 : response_capacity = *response_size - header_length;
152 2 : libspdm_zero_mem(response, header_length);
153 2 : spdm_response = response;
154 :
155 2 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
156 2 : spdm_response->header.request_response_code = SPDM_VENDOR_DEFINED_RESPONSE;
157 2 : spdm_response->header.param1 = 0;
158 2 : spdm_response->header.param2 = 0;
159 :
160 : /* SPDM Response format
161 : * 1 byte SPDMVersion
162 : * 1 byte RequestResponseCode
163 : * 2 bytes Reserved
164 : * 2 bytes StandardID
165 : * 1 bytes VendorID Length Len1, based on StandardID
166 : * Len1 bytes VendorID
167 : * 2 bytes Response Length Len2
168 : * Len2 bytes Response Payload
169 : */
170 :
171 : /* replace capacity with size */
172 2 : spdm_response->len = SPDM_MAX_VENDOR_ID_LENGTH;
173 2 : resp_data = ((uint8_t *)response) + sizeof(spdm_vendor_defined_response_msg_t);
174 :
175 2 : req_data = ((const uint8_t *)request) +
176 : sizeof(spdm_vendor_defined_request_msg_t) +
177 2 : ((const spdm_vendor_defined_request_msg_t*)request)->len +
178 : sizeof(uint16_t);
179 :
180 2 : status = spdm_context->vendor_response_get_id(
181 : spdm_context,
182 : #if LIBSPDM_PASS_SESSION_ID
183 : session_id,
184 : #endif
185 : &spdm_response->standard_id,
186 : &spdm_response->len,
187 : resp_data);
188 :
189 : /* move pointer and adjust buffer size */
190 2 : resp_data += spdm_response->len + sizeof(uint16_t);
191 2 : response_capacity -= spdm_response->len + sizeof(uint16_t);
192 2 : resp_size = (uint16_t)response_capacity;
193 :
194 2 : status = spdm_context->vendor_response_callback(spdm_context,
195 : #if LIBSPDM_PASS_SESSION_ID
196 : session_id,
197 : #endif
198 2 : spdm_request->standard_id,
199 2 : spdm_request->len,
200 : req_vendor_id, req_size, req_data,
201 : &resp_size,
202 : resp_data);
203 :
204 : /* store back the response payload size */
205 2 : *((uint16_t*)(resp_data - sizeof(uint16_t))) = resp_size;
206 2 : *response_size = resp_size + (size_t)header_length;
207 :
208 : LIBSPDM_ASSERT(sizeof(spdm_vendor_defined_request_msg_t) ==
209 : SPDM_VENDOR_DEFINED_FIXED_HEADER_LEN);
210 :
211 2 : return status;
212 : }
213 :
214 : #endif /* LIBSPDM_ENABLE_VENDOR_DEFINED_MESSAGES */
|