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 "library/spdm_transport_tcp_lib.h"
8 : : #include "internal/libspdm_common_lib.h"
9 : : #include "hal/library/memlib.h"
10 : : #include "industry_standard/spdm_tcp_binding.h"
11 : :
12 : 20 : uint8_t libspdm_tcp_get_sequence_number(uint64_t sequence_number,
13 : : uint8_t *sequence_number_buffer)
14 : : {
15 : 20 : return SPDM_TCP_SEQUENCE_NUMBER_COUNT;
16 : : }
17 : :
18 : 12 : uint32_t libspdm_tcp_get_max_random_number_count(void)
19 : : {
20 : 12 : return SPDM_TCP_MAX_RANDOM_NUMBER_COUNT;
21 : : }
22 : :
23 : 20 : spdm_version_number_t libspdm_tcp_get_secured_spdm_version(
24 : : spdm_version_number_t secured_message_version)
25 : : {
26 : 20 : return secured_message_version;
27 : : }
28 : :
29 : : /**
30 : : * Encode a normal message or secured message to a transport message.
31 : : *
32 : : * @param session_id Indicates if it is a secured message protected via SPDM session.
33 : : * If session_id is NULL, it is a normal message.
34 : : * If session_id is NOT NULL, it is a secured message.
35 : : * @param message_size size in bytes of the message data buffer.
36 : : * @param message A pointer to a source buffer to store the message.
37 : : * @param transport_message_size size in bytes of the transport message data buffer.
38 : : * @param transport_message A pointer to a destination buffer to store the transport message.
39 : : **/
40 : 14 : libspdm_return_t libspdm_tcp_encode_message(const uint32_t *session_id, size_t message_size,
41 : : void *message,
42 : : size_t *transport_message_size,
43 : : void **transport_message)
44 : : {
45 : : uint32_t data32;
46 : : spdm_tcp_binding_header_t *tcp_message_header;
47 : :
48 [ - + ]: 14 : if (message_size > UINT16_MAX) {
49 : 0 : return LIBSPDM_STATUS_BUFFER_FULL;
50 : : }
51 : :
52 : 14 : if (*transport_message_size <
53 [ + + ]: 14 : message_size + sizeof(spdm_tcp_binding_header_t)) {
54 : 2 : *transport_message_size = message_size +
55 : : sizeof(spdm_tcp_binding_header_t);
56 : 2 : return LIBSPDM_STATUS_BUFFER_TOO_SMALL;
57 : : }
58 : :
59 : 12 : *transport_message_size =
60 : 12 : message_size + sizeof(spdm_tcp_binding_header_t);
61 : 12 : *transport_message = (uint8_t *)message - sizeof(spdm_tcp_binding_header_t);
62 : 12 : tcp_message_header = *transport_message;
63 : 12 : tcp_message_header->payload_length = (uint16_t)message_size;
64 : 12 : tcp_message_header->binding_version = 0x1;
65 : :
66 [ + + ]: 12 : if (session_id != NULL) {
67 : 8 : tcp_message_header->message_type = SPDM_TCP_MESSAGE_TYPE_IN_SESSION;
68 : 8 : data32 = libspdm_read_uint32((const uint8_t *)message);
69 : 8 : LIBSPDM_ASSERT(*session_id == data32);
70 [ - + ]: 8 : if (*session_id != data32) {
71 : 0 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
72 : : }
73 : : } else {
74 : 4 : tcp_message_header->message_type = SPDM_TCP_MESSAGE_TYPE_OUT_OF_SESSION;
75 : : }
76 : :
77 : 12 : return LIBSPDM_STATUS_SUCCESS;
78 : : }
79 : :
80 : :
81 : : /**
82 : : * Decode a transport message to a normal message or secured message.
83 : : *
84 : : * @param session_id Indicates if it is a secured message protected via SPDM session.
85 : : * If *session_id is NULL, it is a normal message.
86 : : * If *session_id is NOT NULL, it is a secured message.
87 : : * @param transport_message_size size in bytes of the transport message data buffer.
88 : : * @param transport_message A pointer to a source buffer to store the transport message.
89 : : * @param message_size size in bytes of the message data buffer.
90 : : * @param message A pointer to a destination buffer to store the message.
91 : : **/
92 : 28 : libspdm_return_t libspdm_tcp_decode_message(uint32_t **session_id,
93 : : size_t transport_message_size,
94 : : void *transport_message,
95 : : size_t *message_size, void **message)
96 : : {
97 : : const spdm_tcp_binding_header_t *tcp_message_header;
98 : :
99 [ + + ]: 28 : if (transport_message_size <= sizeof(spdm_tcp_binding_header_t)) {
100 : 4 : return LIBSPDM_STATUS_INVALID_MSG_SIZE;
101 : : }
102 : :
103 : 24 : tcp_message_header = transport_message;
104 : :
105 [ + + ]: 24 : if (tcp_message_header->binding_version != 0x01) {
106 : 4 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
107 : : }
108 : :
109 [ + + + ]: 20 : switch (tcp_message_header->message_type) {
110 : 12 : case SPDM_TCP_MESSAGE_TYPE_IN_SESSION:
111 : 12 : LIBSPDM_ASSERT(session_id != NULL);
112 [ - + ]: 12 : if (session_id == NULL) {
113 : 0 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
114 : : }
115 [ + + ]: 12 : if (transport_message_size <=
116 : : sizeof(spdm_tcp_binding_header_t) + sizeof(uint32_t)) {
117 : 2 : return LIBSPDM_STATUS_INVALID_MSG_SIZE;
118 : : }
119 : 10 : *session_id = (uint32_t *)((uint8_t *)transport_message +
120 : : sizeof(spdm_tcp_binding_header_t));
121 : 10 : break;
122 : :
123 : 6 : case SPDM_TCP_MESSAGE_TYPE_OUT_OF_SESSION:
124 [ + - ]: 6 : if (session_id != NULL) {
125 : 6 : *session_id = NULL;
126 : : }
127 : 6 : break;
128 : :
129 : 2 : default:
130 : 2 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
131 : : }
132 : :
133 : 16 : if (tcp_message_header->payload_length >
134 [ + + ]: 16 : transport_message_size - sizeof(spdm_tcp_binding_header_t)) {
135 : 2 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
136 : : }
137 : :
138 : 14 : *message_size = tcp_message_header->payload_length;
139 : 14 : *message = (uint8_t *)transport_message + sizeof(spdm_tcp_binding_header_t);
140 : :
141 : 14 : return LIBSPDM_STATUS_SUCCESS;
142 : : }
143 : :
144 : :
145 : 8 : libspdm_return_t libspdm_tcp_encode_discovery_message(uint8_t message_type,
146 : : size_t *transport_message_size,
147 : : void **transport_message)
148 : : {
149 [ + + + + ]: 8 : if ((message_type != SPDM_TCP_MESSAGE_TYPE_ROLE_INQUIRY &&
150 : : (message_type < SPDM_TCP_MESSAGE_TYPE_ERROR_TOO_LARGE ||
151 : : message_type > SPDM_TCP_MESSAGE_TYPE_ERROR_RESERVED_MAX))){
152 : 2 : return LIBSPDM_STATUS_INVALID_PARAMETER;
153 : : }
154 : :
155 [ + + ]: 6 : if (*transport_message_size < sizeof(spdm_tcp_binding_header_t)) {
156 : 2 : *transport_message_size = sizeof(spdm_tcp_binding_header_t);
157 : 2 : return LIBSPDM_STATUS_BUFFER_TOO_SMALL;
158 : : }
159 : :
160 : 4 : *transport_message_size = sizeof(spdm_tcp_binding_header_t);
161 : 4 : spdm_tcp_binding_header_t *tcp_header = (spdm_tcp_binding_header_t *)(*transport_message);
162 : :
163 : 4 : tcp_header->payload_length = 0;
164 : 4 : tcp_header->binding_version = 0x01;
165 : 4 : tcp_header->message_type = message_type;
166 : :
167 : 4 : return LIBSPDM_STATUS_SUCCESS;
168 : : }
169 : :
170 : :
171 : 16 : libspdm_return_t libspdm_tcp_decode_discovery_message(size_t transport_message_size,
172 : : const void *transport_message,
173 : : uint8_t *message_type)
174 : : {
175 [ + + ]: 16 : if (transport_message_size < sizeof(spdm_tcp_binding_header_t)) {
176 : 2 : return LIBSPDM_STATUS_INVALID_MSG_SIZE;
177 : : }
178 : :
179 : 14 : const spdm_tcp_binding_header_t *tcp_header = (const spdm_tcp_binding_header_t *)transport_message;
180 : :
181 [ + + ]: 14 : if (tcp_header->binding_version != 0x01) {
182 : 2 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
183 : : }
184 : :
185 [ + + ]: 12 : if (tcp_header->payload_length != 0) {
186 : 6 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
187 : : }
188 : :
189 : 6 : uint8_t type = tcp_header->message_type;
190 [ + + + - ]: 6 : if (type != SPDM_TCP_MESSAGE_TYPE_ROLE_INQUIRY &&
191 : : (type < SPDM_TCP_MESSAGE_TYPE_ERROR_TOO_LARGE || type > SPDM_TCP_MESSAGE_TYPE_ERROR_RESERVED_MAX)) {
192 : 2 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
193 : : }
194 : :
195 : 4 : *message_type = type;
196 : :
197 : 4 : return LIBSPDM_STATUS_SUCCESS;
198 : : }
199 : :
200 : :
201 : 10 : uint32_t libspdm_transport_tcp_get_header_size(
202 : : void *spdm_context)
203 : : {
204 : 10 : return sizeof(spdm_tcp_binding_header_t) + sizeof(spdm_secured_message_cipher_header_t);
205 : : }
|