Branch data Line data Source code
1 : : /**
2 : : * Copyright Notice:
3 : : * Copyright 2021-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_responder_lib.h"
8 : :
9 : : #pragma pack(1)
10 : : typedef struct {
11 : : spdm_message_header_t header;
12 : : uint8_t reserved;
13 : : uint8_t version_number_entry_count;
14 : : spdm_version_number_t version_number_entry[SPDM_MAX_VERSION_COUNT];
15 : : } libspdm_version_response_mine_t;
16 : : #pragma pack()
17 : :
18 : 2 : static libspdm_return_t generate_invalid_version_error(size_t *response_size, void *response)
19 : : {
20 : : spdm_error_response_t *spdm_response;
21 : :
22 : 2 : spdm_response = response;
23 : 2 : *response_size = sizeof(spdm_error_response_t);
24 : :
25 : 2 : spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_10;
26 : 2 : spdm_response->header.request_response_code = SPDM_ERROR;
27 : 2 : spdm_response->header.param1 = SPDM_ERROR_CODE_VERSION_MISMATCH;
28 : 2 : spdm_response->header.param2 = 0;
29 : :
30 : 2 : return LIBSPDM_STATUS_SUCCESS;
31 : : }
32 : :
33 : 18 : libspdm_return_t libspdm_get_response_version(libspdm_context_t *spdm_context, size_t request_size,
34 : : const void *request,
35 : : size_t *response_size,
36 : : void *response)
37 : : {
38 : : const spdm_get_version_request_t *spdm_request;
39 : : libspdm_version_response_mine_t *spdm_response;
40 : : libspdm_return_t status;
41 : :
42 : 18 : spdm_request = request;
43 : :
44 : : /* -=[Check Parameters Phase]=- */
45 [ - + ]: 18 : LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_GET_VERSION);
46 : :
47 : : /* -=[Validate Request Phase]=- */
48 [ + + ]: 18 : if (request_size < sizeof(spdm_get_version_request_t)) {
49 : 1 : return libspdm_generate_error_response(spdm_context,
50 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
51 : : response_size, response);
52 : : }
53 : :
54 [ + + ]: 17 : if (spdm_context->last_spdm_request_session_id_valid) {
55 : 1 : return libspdm_generate_error_response(spdm_context,
56 : : SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
57 : : 0, response_size, response);
58 : : }
59 : :
60 [ + + ]: 16 : if (spdm_request->header.spdm_version != SPDM_MESSAGE_VERSION_10) {
61 : : /* If the GET_VERSION request is improperly formed then the version of the error message
62 : : * must be 1.0, regardless of what the negotiated version is. */
63 : 2 : return generate_invalid_version_error(response_size, response);
64 : : }
65 : :
66 : 14 : libspdm_set_connection_state(spdm_context, LIBSPDM_CONNECTION_STATE_NOT_STARTED);
67 : :
68 [ + + ]: 14 : if (spdm_context->response_state == LIBSPDM_RESPONSE_STATE_NEED_RESYNC) {
69 : : /* receiving a GET_VERSION resets a need to resynchronization*/
70 : 1 : spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL;
71 : : }
72 : :
73 : : #if LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP
74 : 14 : libspdm_reset_all_encap_state(spdm_context);
75 : : #endif /* LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP */
76 : :
77 [ + + ]: 14 : if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
78 : 1 : return libspdm_responder_handle_response_state(
79 : : spdm_context,
80 : 1 : spdm_request->header.request_response_code,
81 : : response_size, response);
82 : : }
83 : :
84 : : /* -=[Process Request Phase]=- */
85 : 13 : libspdm_reset_context(spdm_context);
86 : :
87 : 13 : request_size = sizeof(spdm_get_version_request_t);
88 : 13 : status = libspdm_append_message_a(spdm_context, spdm_request, request_size);
89 [ + + ]: 13 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
90 : 1 : return libspdm_generate_error_response(spdm_context,
91 : : SPDM_ERROR_CODE_UNSPECIFIED, 0,
92 : : response_size, response);
93 : : }
94 : :
95 : : /* -=[Construct Response Phase]=- */
96 [ - + ]: 12 : LIBSPDM_ASSERT(*response_size >= sizeof(libspdm_version_response_mine_t));
97 : 12 : *response_size =
98 : 12 : sizeof(spdm_version_response_t) +
99 : 12 : spdm_context->local_context.version.spdm_version_count *
100 : : sizeof(spdm_version_number_t);
101 : 12 : libspdm_zero_mem(response, *response_size);
102 : 12 : spdm_response = response;
103 : :
104 : 12 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
105 : 12 : spdm_response->header.request_response_code = SPDM_VERSION;
106 : 12 : spdm_response->header.param1 = 0;
107 : 12 : spdm_response->header.param2 = 0;
108 : 12 : spdm_response->version_number_entry_count =
109 : 12 : spdm_context->local_context.version.spdm_version_count;
110 : 12 : libspdm_copy_mem(spdm_response->version_number_entry,
111 : : sizeof(spdm_response->version_number_entry),
112 : 12 : spdm_context->local_context.version.spdm_version,
113 : : sizeof(spdm_version_number_t) *
114 : 12 : spdm_context->local_context.version.spdm_version_count);
115 : :
116 : 12 : status = libspdm_append_message_a(spdm_context, spdm_response, *response_size);
117 [ + + ]: 12 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
118 : 1 : libspdm_reset_message_a(spdm_context);
119 : 1 : return libspdm_generate_error_response(spdm_context,
120 : : SPDM_ERROR_CODE_UNSPECIFIED, 0,
121 : : response_size, response);
122 : : }
123 : :
124 : : /* -=[Update State Phase]=- */
125 : 11 : libspdm_set_connection_state(spdm_context, LIBSPDM_CONNECTION_STATE_AFTER_VERSION);
126 : :
127 : : /*Set the role of device*/
128 : 11 : spdm_context->local_context.is_requester = false;
129 : :
130 : 11 : return LIBSPDM_STATUS_SUCCESS;
131 : : }
|