Line data Source code
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_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 1 : static libspdm_return_t generate_invalid_version_error(size_t *response_size, void *response)
19 : {
20 : spdm_error_response_t *spdm_response;
21 :
22 1 : spdm_response = response;
23 1 : *response_size = sizeof(spdm_error_response_t);
24 :
25 1 : spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_10;
26 1 : spdm_response->header.request_response_code = SPDM_ERROR;
27 1 : spdm_response->header.param1 = SPDM_ERROR_CODE_VERSION_MISMATCH;
28 1 : spdm_response->header.param2 = 0;
29 :
30 1 : return LIBSPDM_STATUS_SUCCESS;
31 : }
32 :
33 5 : 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 5 : spdm_request = request;
43 :
44 : /* -=[Check Parameters Phase]=- */
45 5 : LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_GET_VERSION);
46 :
47 : /* -=[Validate Request Phase]=- */
48 5 : if (request_size < sizeof(spdm_get_version_request_t)) {
49 0 : return libspdm_generate_error_response(spdm_context,
50 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
51 : response_size, response);
52 : }
53 :
54 5 : if (spdm_context->last_spdm_request_session_id_valid) {
55 0 : return libspdm_generate_error_response(spdm_context,
56 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
57 : 0, response_size, response);
58 : }
59 :
60 5 : 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 1 : return generate_invalid_version_error(response_size, response);
64 : }
65 :
66 4 : libspdm_set_connection_state(spdm_context, LIBSPDM_CONNECTION_STATE_NOT_STARTED);
67 :
68 4 : if ((spdm_context->response_state == LIBSPDM_RESPONSE_STATE_NEED_RESYNC) ||
69 3 : (spdm_context->response_state == LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP)) {
70 : /* receiving a GET_VERSION resets a need to resynchronization*/
71 1 : spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL;
72 : }
73 4 : if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
74 1 : return libspdm_responder_handle_response_state(
75 : spdm_context,
76 1 : spdm_request->header.request_response_code,
77 : response_size, response);
78 : }
79 :
80 : /* -=[Process Request Phase]=- */
81 3 : libspdm_reset_message_buffer_via_request_code(spdm_context, NULL,
82 3 : spdm_request->header.request_response_code);
83 :
84 3 : libspdm_reset_message_a(spdm_context);
85 3 : libspdm_reset_message_d(spdm_context);
86 3 : libspdm_reset_message_b(spdm_context);
87 3 : libspdm_reset_message_c(spdm_context);
88 :
89 3 : request_size = sizeof(spdm_get_version_request_t);
90 3 : status = libspdm_append_message_a(spdm_context, spdm_request, request_size);
91 3 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
92 0 : return libspdm_generate_error_response(spdm_context,
93 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
94 : response_size, response);
95 : }
96 :
97 3 : libspdm_reset_context(spdm_context);
98 :
99 : /* -=[Construct Response Phase]=- */
100 3 : LIBSPDM_ASSERT(*response_size >= sizeof(libspdm_version_response_mine_t));
101 3 : *response_size =
102 3 : sizeof(spdm_version_response_t) +
103 3 : spdm_context->local_context.version.spdm_version_count *
104 : sizeof(spdm_version_number_t);
105 3 : libspdm_zero_mem(response, *response_size);
106 3 : spdm_response = response;
107 :
108 3 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
109 3 : spdm_response->header.request_response_code = SPDM_VERSION;
110 3 : spdm_response->header.param1 = 0;
111 3 : spdm_response->header.param2 = 0;
112 3 : spdm_response->version_number_entry_count =
113 3 : spdm_context->local_context.version.spdm_version_count;
114 3 : libspdm_copy_mem(spdm_response->version_number_entry,
115 : sizeof(spdm_response->version_number_entry),
116 3 : spdm_context->local_context.version.spdm_version,
117 : sizeof(spdm_version_number_t) *
118 3 : spdm_context->local_context.version.spdm_version_count);
119 :
120 3 : status = libspdm_append_message_a(spdm_context, spdm_response, *response_size);
121 3 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
122 0 : libspdm_reset_message_a(spdm_context);
123 0 : return libspdm_generate_error_response(spdm_context,
124 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
125 : response_size, response);
126 : }
127 :
128 : /* -=[Update State Phase]=- */
129 3 : libspdm_set_connection_state(spdm_context, LIBSPDM_CONNECTION_STATE_AFTER_VERSION);
130 :
131 : /*Set the role of device*/
132 3 : spdm_context->local_context.is_requester = false;
133 :
134 3 : return LIBSPDM_STATUS_SUCCESS;
135 : }
|