1 /**
2 * Copyright Notice:
3 * Copyright 2021-2022 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
libspdm_init_connection(void * spdm_context,bool get_version_only)9 libspdm_return_t libspdm_init_connection(void *spdm_context, bool get_version_only)
10 {
11 libspdm_return_t status;
12 libspdm_context_t *context;
13
14 context = spdm_context;
15
16 status = libspdm_get_version(context, NULL, NULL);
17 if (LIBSPDM_STATUS_IS_ERROR(status)) {
18 return status;
19 }
20
21 if (!get_version_only) {
22 status = libspdm_get_capabilities(context);
23 if (LIBSPDM_STATUS_IS_ERROR(status)) {
24 return status;
25 }
26 status = libspdm_negotiate_algorithms(context);
27 if (LIBSPDM_STATUS_IS_ERROR(status)) {
28 return status;
29 }
30 }
31 return LIBSPDM_STATUS_SUCCESS;
32 }
33
34 #if (LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP) || (LIBSPDM_ENABLE_CAPABILITY_PSK_CAP)
libspdm_start_session(void * spdm_context,bool use_psk,const void * psk_hint,uint16_t psk_hint_size,uint8_t measurement_hash_type,uint8_t slot_id,uint8_t session_policy,uint32_t * session_id,uint8_t * heartbeat_period,void * measurement_hash)35 libspdm_return_t libspdm_start_session(void *spdm_context, bool use_psk,
36 const void *psk_hint,
37 uint16_t psk_hint_size,
38 uint8_t measurement_hash_type,
39 uint8_t slot_id,
40 uint8_t session_policy,
41 uint32_t *session_id,
42 uint8_t *heartbeat_period,
43 void *measurement_hash)
44 {
45 libspdm_return_t status;
46 libspdm_context_t *context;
47
48 #if LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP
49 libspdm_session_info_t *session_info;
50 uint8_t req_slot_id_param;
51 #endif /* LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP*/
52
53 context = spdm_context;
54 status = LIBSPDM_STATUS_UNSUPPORTED_CAP;
55
56 if (!use_psk) {
57 #if LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP
58 status = libspdm_send_receive_key_exchange(
59 context, measurement_hash_type, slot_id, session_policy,
60 session_id, heartbeat_period, &req_slot_id_param,
61 measurement_hash);
62 if (LIBSPDM_STATUS_IS_ERROR(status)) {
63 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
64 "libspdm_start_session - libspdm_send_receive_key_exchange - %p\n",
65 status));
66 return status;
67 }
68
69 session_info = libspdm_get_session_info_via_session_id(context, *session_id);
70 if (session_info == NULL) {
71 LIBSPDM_ASSERT(false);
72 return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
73 }
74
75 switch (session_info->mut_auth_requested) {
76 case 0:
77 break;
78 case SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED:
79 #if !(LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP)
80 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
81 "libspdm_start_session - unsupported mut_auth_requested - 0x%x\n",
82 session_info->mut_auth_requested));
83 return LIBSPDM_STATUS_INVALID_MSG_FIELD;
84 #endif
85 break;
86 case SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_ENCAP_REQUEST:
87 case SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_GET_DIGESTS:
88 #if (LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP) && (LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP)
89 status = libspdm_encapsulated_request(
90 context, session_id,
91 session_info->mut_auth_requested,
92 &req_slot_id_param);
93 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
94 "libspdm_start_session - libspdm_encapsulated_request - %p\n", status));
95 if (LIBSPDM_STATUS_IS_ERROR(status)) {
96 return status;
97 }
98 #else
99 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
100 "libspdm_start_session - unsupported mut_auth_requested - 0x%x\n",
101 session_info->mut_auth_requested));
102 return LIBSPDM_STATUS_INVALID_MSG_FIELD;
103 #endif /* (LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP) && (LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP) */
104 break;
105 default:
106 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
107 "libspdm_start_session - unknown mut_auth_requested - 0x%x\n",
108 session_info->mut_auth_requested));
109 return LIBSPDM_STATUS_INVALID_MSG_FIELD;
110 }
111
112 if (req_slot_id_param == 0xF) {
113 req_slot_id_param = 0xFF;
114 }
115 status = libspdm_send_receive_finish(context, *session_id, req_slot_id_param);
116 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
117 "libspdm_start_session - libspdm_send_receive_finish - %p\n", status));
118 #else /* LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP*/
119 LIBSPDM_ASSERT(false);
120 return LIBSPDM_STATUS_UNSUPPORTED_CAP;
121 #endif /* LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP*/
122 } else {
123 #if LIBSPDM_ENABLE_CAPABILITY_PSK_CAP
124 status = libspdm_send_receive_psk_exchange(
125 context, psk_hint, psk_hint_size,
126 measurement_hash_type, session_policy, session_id,
127 heartbeat_period, measurement_hash);
128 if (LIBSPDM_STATUS_IS_ERROR(status)) {
129 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
130 "libspdm_start_session - libspdm_send_receive_psk_exchange - %p\n",
131 status));
132 return status;
133 }
134
135 /* send PSK_FINISH only if Responder supports context.*/
136 if (libspdm_is_capabilities_flag_supported(
137 context, true, 0,
138 SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP_RESPONDER_WITH_CONTEXT)) {
139 status = libspdm_send_receive_psk_finish(context, *session_id);
140 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
141 "libspdm_start_session - libspdm_send_receive_psk_finish - %p\n",
142 status));
143 }
144 #endif /* LIBSPDM_ENABLE_CAPABILITY_PSK_CAP*/
145 }
146 return status;
147 }
148
libspdm_start_session_ex(void * spdm_context,bool use_psk,const void * psk_hint,uint16_t psk_hint_size,uint8_t measurement_hash_type,uint8_t slot_id,uint8_t session_policy,uint32_t * session_id,uint8_t * heartbeat_period,void * measurement_hash,const void * requester_random_in,size_t requester_random_in_size,void * requester_random,size_t * requester_random_size,void * responder_random,size_t * responder_random_size,const void * requester_opaque_data,size_t requester_opaque_data_size,void * responder_opaque_data,size_t * responder_opaque_data_size)149 libspdm_return_t libspdm_start_session_ex(void *spdm_context, bool use_psk,
150 const void *psk_hint,
151 uint16_t psk_hint_size,
152 uint8_t measurement_hash_type,
153 uint8_t slot_id,
154 uint8_t session_policy,
155 uint32_t *session_id,
156 uint8_t *heartbeat_period,
157 void *measurement_hash,
158 const void *requester_random_in,
159 size_t requester_random_in_size,
160 void *requester_random,
161 size_t *requester_random_size,
162 void *responder_random,
163 size_t *responder_random_size,
164 const void *requester_opaque_data,
165 size_t requester_opaque_data_size,
166 void *responder_opaque_data,
167 size_t *responder_opaque_data_size)
168 {
169 libspdm_return_t status;
170 libspdm_context_t *context;
171
172 #if LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP
173 libspdm_session_info_t *session_info;
174 uint8_t req_slot_id_param;
175 #endif /* LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP */
176
177 context = spdm_context;
178 status = LIBSPDM_STATUS_UNSUPPORTED_CAP;
179
180 if (!use_psk) {
181 #if LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP
182 LIBSPDM_ASSERT (
183 requester_random_in_size == 0 || requester_random_in_size == SPDM_RANDOM_DATA_SIZE);
184 LIBSPDM_ASSERT (
185 requester_random_size == NULL || *requester_random_size == SPDM_RANDOM_DATA_SIZE);
186 LIBSPDM_ASSERT (
187 responder_random_size == NULL || *responder_random_size == SPDM_RANDOM_DATA_SIZE);
188 status = libspdm_send_receive_key_exchange_ex(
189 context, measurement_hash_type, slot_id, session_policy,
190 session_id, heartbeat_period, &req_slot_id_param,
191 measurement_hash, requester_random_in,
192 requester_random, responder_random,
193 requester_opaque_data, requester_opaque_data_size,
194 responder_opaque_data, responder_opaque_data_size);
195 if (LIBSPDM_STATUS_IS_ERROR(status)) {
196 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
197 "libspdm_start_session - libspdm_send_receive_key_exchange - %p\n",
198 status));
199 return status;
200 }
201
202 session_info = libspdm_get_session_info_via_session_id(context, *session_id);
203 if (session_info == NULL) {
204 LIBSPDM_ASSERT(false);
205 return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
206 }
207
208 switch (session_info->mut_auth_requested) {
209 case 0:
210 break;
211 case SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED:
212 #if !(LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP)
213 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
214 "libspdm_start_session - unsupported mut_auth_requested - 0x%x\n",
215 session_info->mut_auth_requested));
216 return LIBSPDM_STATUS_INVALID_MSG_FIELD;
217 #endif
218 break;
219 case SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_ENCAP_REQUEST:
220 case SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_GET_DIGESTS:
221 #if (LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP) && (LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP)
222 status = libspdm_encapsulated_request(
223 context, session_id,
224 session_info->mut_auth_requested,
225 &req_slot_id_param);
226 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
227 "libspdm_start_session - libspdm_encapsulated_request - %p\n", status));
228 if (LIBSPDM_STATUS_IS_ERROR(status)) {
229 return status;
230 }
231 #else
232 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
233 "libspdm_start_session - unsupported mut_auth_requested - 0x%x\n",
234 session_info->mut_auth_requested));
235 return LIBSPDM_STATUS_INVALID_MSG_FIELD;
236 #endif /* (LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP) && (LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP) */
237 break;
238 default:
239 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
240 "libspdm_start_session - unknown mut_auth_requested - 0x%x\n",
241 session_info->mut_auth_requested));
242 return LIBSPDM_STATUS_INVALID_MSG_FIELD;
243 }
244
245 if (req_slot_id_param == 0xF) {
246 req_slot_id_param = 0xFF;
247 }
248 status = libspdm_send_receive_finish(context, *session_id, req_slot_id_param);
249 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
250 "libspdm_start_session - libspdm_send_receive_finish - %p\n", status));
251 #else /* LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP*/
252 LIBSPDM_ASSERT(false);
253 return LIBSPDM_STATUS_UNSUPPORTED_CAP;
254 #endif /* LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP*/
255 } else {
256 #if LIBSPDM_ENABLE_CAPABILITY_PSK_CAP
257 status = libspdm_send_receive_psk_exchange_ex(
258 context, psk_hint, psk_hint_size,
259 measurement_hash_type, session_policy, session_id,
260 heartbeat_period, measurement_hash,
261 requester_random_in, requester_random_in_size,
262 requester_random, requester_random_size,
263 responder_random, responder_random_size,
264 requester_opaque_data, requester_opaque_data_size,
265 responder_opaque_data, responder_opaque_data_size);
266 if (LIBSPDM_STATUS_IS_ERROR(status)) {
267 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
268 "libspdm_start_session - libspdm_send_receive_psk_exchange - %p\n",
269 status));
270 return status;
271 }
272
273 /* send PSK_FINISH only if Responder supports context.*/
274 if (libspdm_is_capabilities_flag_supported(
275 context, true, 0,
276 SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP_RESPONDER_WITH_CONTEXT)) {
277 status = libspdm_send_receive_psk_finish(context, *session_id);
278 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
279 "libspdm_start_session - libspdm_send_receive_psk_finish - %p\n",
280 status));
281 }
282 #else /* LIBSPDM_ENABLE_CAPABILITY_PSK_CAP*/
283 LIBSPDM_ASSERT(false);
284 return LIBSPDM_STATUS_UNSUPPORTED_CAP;
285 #endif /* LIBSPDM_ENABLE_CAPABILITY_PSK_CAP*/
286 }
287
288 return status;
289 }
290
libspdm_stop_session(void * spdm_context,uint32_t session_id,uint8_t end_session_attributes)291 libspdm_return_t libspdm_stop_session(void *spdm_context, uint32_t session_id,
292 uint8_t end_session_attributes)
293 {
294 libspdm_return_t status;
295 libspdm_context_t *context;
296
297 context = spdm_context;
298
299 status = libspdm_send_receive_end_session(context, session_id, end_session_attributes);
300 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_stop_session - %p\n", status));
301
302 return status;
303 }
304 #endif /* (LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP) || (LIBSPDM_ENABLE_CAPABILITY_PSK_CAP) */
305
libspdm_send_data(void * spdm_context,const uint32_t * session_id,bool is_app_message,const void * request,size_t request_size)306 libspdm_return_t libspdm_send_data(void *spdm_context, const uint32_t *session_id,
307 bool is_app_message,
308 const void *request, size_t request_size)
309 {
310 libspdm_return_t status;
311 libspdm_context_t *context;
312 spdm_message_header_t *spdm_request;
313 size_t spdm_request_size;
314 uint8_t *message;
315 size_t message_size;
316 size_t transport_header_size;
317
318 context = spdm_context;
319 transport_header_size = context->local_context.capability.transport_header_size;
320
321 status = libspdm_acquire_sender_buffer(context, &message_size, (void **)&message);
322 if (LIBSPDM_STATUS_IS_ERROR(status)) {
323 return status;
324 }
325 LIBSPDM_ASSERT (message_size >= transport_header_size +
326 context->local_context.capability.transport_tail_size);
327 spdm_request = (void *)(message + transport_header_size);
328 spdm_request_size = message_size - transport_header_size -
329 context->local_context.capability.transport_tail_size;
330 libspdm_copy_mem (spdm_request, spdm_request_size, request, request_size);
331 spdm_request_size = request_size;
332
333 status = libspdm_send_request(context, session_id, is_app_message,
334 spdm_request_size, spdm_request);
335
336 libspdm_release_sender_buffer(context);
337
338 return status;
339 }
340
libspdm_receive_data(void * spdm_context,const uint32_t * session_id,bool is_app_message,void * response,size_t * response_size)341 libspdm_return_t libspdm_receive_data(void *spdm_context, const uint32_t *session_id,
342 bool is_app_message,
343 void *response, size_t *response_size)
344 {
345 libspdm_return_t status;
346 libspdm_context_t *context;
347 spdm_error_response_t *spdm_response;
348 size_t spdm_response_size;
349 uint8_t *message;
350 size_t message_size;
351
352 context = spdm_context;
353
354 status = libspdm_acquire_receiver_buffer(context, &message_size, (void **)&message);
355 if (LIBSPDM_STATUS_IS_ERROR(status)) {
356 return status;
357 }
358
359 spdm_response = (void *)(message);
360 spdm_response_size = message_size;
361
362 status = libspdm_receive_response(context, session_id, is_app_message,
363 &spdm_response_size, (void **)&spdm_response);
364 if (LIBSPDM_STATUS_IS_ERROR(status)) {
365 libspdm_release_receiver_buffer (context);
366 return status;
367 }
368
369 if (spdm_response->header.request_response_code == SPDM_ERROR) {
370 if ((spdm_response->header.param1 == SPDM_ERROR_CODE_DECRYPT_ERROR) &&
371 (session_id != NULL)) {
372 libspdm_free_session_id(context, *session_id);
373 libspdm_release_receiver_buffer (context);
374 return LIBSPDM_STATUS_SESSION_MSG_ERROR;
375 }
376 }
377
378 if (*response_size >= spdm_response_size) {
379 libspdm_copy_mem (response, *response_size, spdm_response, spdm_response_size);
380 *response_size = spdm_response_size;
381 } else {
382 *response_size = spdm_response_size;
383 libspdm_release_receiver_buffer (context);
384 return LIBSPDM_STATUS_BUFFER_TOO_SMALL;
385 }
386
387 libspdm_release_receiver_buffer(context);
388
389 return LIBSPDM_STATUS_SUCCESS;
390 }
391
libspdm_send_receive_data(void * spdm_context,const uint32_t * session_id,bool is_app_message,const void * request,size_t request_size,void * response,size_t * response_size)392 libspdm_return_t libspdm_send_receive_data(void *spdm_context, const uint32_t *session_id,
393 bool is_app_message,
394 const void *request, size_t request_size,
395 void *response, size_t *response_size)
396 {
397 libspdm_return_t status;
398
399 status = libspdm_send_data(spdm_context, session_id, is_app_message, request, request_size);
400
401 if (LIBSPDM_STATUS_IS_ERROR(status)) {
402 return status;
403 }
404
405 return libspdm_receive_data(spdm_context, session_id, is_app_message, response, response_size);
406 }
407