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 : 18 : uint8_t libspdm_tcp_get_sequence_number(uint64_t sequence_number,
13 : : uint8_t *sequence_number_buffer)
14 : : {
15 : 18 : return SPDM_TCP_SEQUENCE_NUMBER_COUNT;
16 : : }
17 : :
18 : 10 : uint32_t libspdm_tcp_get_max_random_number_count(void)
19 : : {
20 : 10 : return SPDM_TCP_MAX_RANDOM_NUMBER_COUNT;
21 : : }
22 : :
23 : 18 : spdm_version_number_t libspdm_tcp_get_secured_spdm_version(
24 : : spdm_version_number_t secured_message_version)
25 : : {
26 : 18 : 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 : 18 : 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 [ - + ]: 18 : if (message_size > UINT16_MAX) {
49 : 0 : return LIBSPDM_STATUS_BUFFER_FULL;
50 : : }
51 : :
52 : 18 : if (*transport_message_size <
53 [ + + ]: 18 : 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 : 16 : *transport_message_size =
60 : 16 : message_size + sizeof(spdm_tcp_binding_header_t);
61 : 16 : *transport_message = (uint8_t *)message - sizeof(spdm_tcp_binding_header_t);
62 : 16 : tcp_message_header = *transport_message;
63 : 16 : tcp_message_header->payload_length = (uint16_t)message_size;
64 : 16 : tcp_message_header->binding_version = 0x1;
65 : :
66 [ + + ]: 16 : 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 : 8 : tcp_message_header->message_type = SPDM_TCP_MESSAGE_TYPE_OUT_OF_SESSION;
75 : : }
76 : :
77 : 16 : 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 : LIBSPDM_ASSERT(transport_message_size > sizeof(spdm_tcp_binding_header_t));
100 [ - + ]: 28 : if (transport_message_size <= sizeof(spdm_tcp_binding_header_t)) {
101 : 0 : return LIBSPDM_STATUS_INVALID_MSG_SIZE;
102 : : }
103 : :
104 : 28 : tcp_message_header = transport_message;
105 : :
106 [ + + + ]: 28 : switch (tcp_message_header->message_type) {
107 : 16 : case SPDM_TCP_MESSAGE_TYPE_IN_SESSION:
108 : 16 : LIBSPDM_ASSERT(session_id != NULL);
109 [ - + ]: 16 : if (session_id == NULL) {
110 : 0 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
111 : : }
112 [ + + ]: 16 : if (transport_message_size <=
113 : : sizeof(spdm_tcp_binding_header_t) + sizeof(uint32_t)) {
114 : 2 : return LIBSPDM_STATUS_INVALID_MSG_SIZE;
115 : : }
116 : 14 : *session_id = (uint32_t *)((uint8_t *)transport_message +
117 : : sizeof(spdm_tcp_binding_header_t));
118 : 14 : break;
119 : :
120 : 8 : case SPDM_TCP_MESSAGE_TYPE_OUT_OF_SESSION:
121 [ + - ]: 8 : if (session_id != NULL) {
122 : 8 : *session_id = NULL;
123 : : }
124 : 8 : break;
125 : :
126 : 4 : default:
127 : 4 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
128 : : }
129 : :
130 : 22 : if (tcp_message_header->payload_length >
131 [ + + ]: 22 : transport_message_size - sizeof(spdm_tcp_binding_header_t)) {
132 : 2 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
133 : : }
134 : :
135 : 20 : *message_size = tcp_message_header->payload_length;
136 : 20 : *message = (uint8_t *)transport_message + sizeof(spdm_tcp_binding_header_t);
137 : :
138 : 20 : return LIBSPDM_STATUS_SUCCESS;
139 : : }
140 : :
141 : :
142 : 8 : libspdm_return_t libspdm_tcp_encode_discovery_message(uint8_t message_type,
143 : : size_t *transport_message_size,
144 : : void **transport_message)
145 : : {
146 [ + + + + ]: 8 : if ((message_type != SPDM_TCP_MESSAGE_TYPE_ROLE_INQUIRY &&
147 : : (message_type < SPDM_TCP_MESSAGE_TYPE_ERROR_TOO_LARGE ||
148 : : message_type > SPDM_TCP_MESSAGE_TYPE_ERROR_RESERVED_MAX))){
149 : 2 : return LIBSPDM_STATUS_INVALID_PARAMETER;
150 : : }
151 : :
152 [ + + ]: 6 : if (*transport_message_size < sizeof(spdm_tcp_binding_header_t)) {
153 : 2 : *transport_message_size = sizeof(spdm_tcp_binding_header_t);
154 : 2 : return LIBSPDM_STATUS_BUFFER_TOO_SMALL;
155 : : }
156 : :
157 : 4 : *transport_message_size = sizeof(spdm_tcp_binding_header_t);
158 : 4 : spdm_tcp_binding_header_t *tcp_header = (spdm_tcp_binding_header_t *)(*transport_message);
159 : :
160 : 4 : tcp_header->payload_length = 0;
161 : 4 : tcp_header->binding_version = 0x01;
162 : 4 : tcp_header->message_type = message_type;
163 : :
164 : 4 : return LIBSPDM_STATUS_SUCCESS;
165 : : }
166 : :
167 : :
168 : 16 : libspdm_return_t libspdm_tcp_decode_discovery_message(size_t transport_message_size,
169 : : const void *transport_message,
170 : : uint8_t *message_type)
171 : : {
172 [ + + ]: 16 : if (transport_message_size < sizeof(spdm_tcp_binding_header_t)) {
173 : 2 : return LIBSPDM_STATUS_INVALID_MSG_SIZE;
174 : : }
175 : :
176 : 14 : const spdm_tcp_binding_header_t *tcp_header = (const spdm_tcp_binding_header_t *)transport_message;
177 : :
178 [ + + ]: 14 : if (tcp_header->binding_version != 0x01) {
179 : 2 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
180 : : }
181 : :
182 [ + + ]: 12 : if (tcp_header->payload_length != 0) {
183 : 6 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
184 : : }
185 : :
186 : 6 : uint8_t type = tcp_header->message_type;
187 [ + + + - ]: 6 : if (type != SPDM_TCP_MESSAGE_TYPE_ROLE_INQUIRY &&
188 : : (type < SPDM_TCP_MESSAGE_TYPE_ERROR_TOO_LARGE || type > SPDM_TCP_MESSAGE_TYPE_ERROR_RESERVED_MAX)) {
189 : 2 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
190 : : }
191 : :
192 : 4 : *message_type = type;
193 : :
194 : 4 : return LIBSPDM_STATUS_SUCCESS;
195 : : }
196 : :
197 : :
198 : 10 : uint32_t libspdm_transport_tcp_get_header_size(
199 : : void *spdm_context)
200 : : {
201 : 10 : return sizeof(spdm_tcp_binding_header_t) + sizeof(spdm_secured_message_cipher_header_t);
202 : : }
|