Line data Source code
1 : /**
2 : * Copyright Notice:
3 : * Copyright 2024 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 :
9 : #if LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP
10 :
11 : typedef struct {
12 : spdm_message_header_t header;
13 : uint8_t total_key_pairs;
14 : uint8_t key_pair_id;
15 : uint16_t capabilities;
16 : uint16_t key_usage_capabilities;
17 : uint16_t current_key_usage;
18 : uint32_t asym_algo_capabilities;
19 : uint32_t current_asym_algo;
20 : uint16_t public_key_info_len;
21 : uint8_t assoc_cert_slot_mask;
22 : uint8_t public_key_info[SPDM_MAX_PUBLIC_KEY_INFO_LEN];
23 : } libspdm_key_pair_info_response_max_t;
24 :
25 : /**
26 : * This function sends GET_KEY_PAIR_INFO and receives KEY_PAIR_INFO *
27 : *
28 : * @param context A pointer to the SPDM context.
29 : *
30 : **/
31 2 : static libspdm_return_t libspdm_try_get_key_pair_info(libspdm_context_t *spdm_context,
32 : const uint32_t *session_id,
33 : uint8_t key_pair_id,
34 : uint8_t *total_key_pairs,
35 : uint16_t *capabilities,
36 : uint16_t *key_usage_capabilities,
37 : uint16_t *current_key_usage,
38 : uint32_t *asym_algo_capabilities,
39 : uint32_t *current_asym_algo,
40 : uint8_t *assoc_cert_slot_mask,
41 : uint16_t *public_key_info_len,
42 : void *public_key_info
43 : )
44 : {
45 : libspdm_return_t status;
46 : spdm_get_key_pair_info_request_t *spdm_request;
47 : size_t spdm_request_size;
48 : libspdm_key_pair_info_response_max_t *spdm_response;
49 : size_t spdm_response_size;
50 : uint8_t *message;
51 : size_t message_size;
52 : size_t transport_header_size;
53 : libspdm_session_info_t *session_info;
54 : libspdm_session_state_t session_state;
55 :
56 : /* -=[Check Parameters Phase]=- */
57 2 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_13) {
58 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
59 : }
60 :
61 2 : if (key_pair_id == 0) {
62 0 : return LIBSPDM_STATUS_INVALID_PARAMETER;
63 : }
64 :
65 : /* -=[Verify State Phase]=- */
66 2 : if (!libspdm_is_capabilities_flag_supported(
67 : spdm_context, true, 0,
68 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_GET_KEY_PAIR_INFO_CAP)) {
69 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
70 : }
71 2 : if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
72 0 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
73 : }
74 :
75 2 : session_info = NULL;
76 2 : if (session_id != NULL) {
77 0 : session_info = libspdm_get_session_info_via_session_id(spdm_context, *session_id);
78 0 : if (session_info == NULL) {
79 0 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
80 : }
81 0 : session_state = libspdm_secured_message_get_session_state(
82 : session_info->secured_message_context);
83 0 : if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
84 0 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
85 : }
86 : }
87 :
88 : /* -=[Construct Request Phase]=- */
89 2 : transport_header_size = spdm_context->local_context.capability.transport_header_size;
90 2 : status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message);
91 2 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
92 0 : return status;
93 : }
94 2 : LIBSPDM_ASSERT (message_size >= transport_header_size +
95 : spdm_context->local_context.capability.transport_tail_size);
96 2 : spdm_request = (void *)(message + transport_header_size);
97 2 : spdm_request_size = message_size - transport_header_size -
98 2 : spdm_context->local_context.capability.transport_tail_size;
99 :
100 2 : LIBSPDM_ASSERT(spdm_request_size >= sizeof(spdm_get_key_pair_info_request_t));
101 2 : spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
102 2 : spdm_request->header.request_response_code = SPDM_GET_KEY_PAIR_INFO;
103 2 : spdm_request->header.param1 = 0;
104 2 : spdm_request->header.param2 = 0;
105 2 : spdm_request->key_pair_id = key_pair_id;
106 2 : spdm_request_size = sizeof(spdm_get_key_pair_info_request_t);
107 :
108 : /* -=[Send Request Phase]=- */
109 2 : status = libspdm_send_spdm_request(spdm_context, session_id, spdm_request_size, spdm_request);
110 2 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
111 1 : libspdm_release_sender_buffer (spdm_context);
112 1 : return status;
113 : }
114 1 : libspdm_release_sender_buffer (spdm_context);
115 1 : spdm_request = (void *)spdm_context->last_spdm_request;
116 :
117 : /* -=[Receive Response Phase]=- */
118 1 : status = libspdm_acquire_receiver_buffer (spdm_context, &message_size, (void **)&message);
119 1 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
120 0 : return status;
121 : }
122 1 : LIBSPDM_ASSERT (message_size >= transport_header_size);
123 1 : spdm_response = (void *)(message);
124 1 : spdm_response_size = message_size;
125 :
126 1 : status = libspdm_receive_spdm_response(
127 : spdm_context, session_id, &spdm_response_size, (void **)&spdm_response);
128 1 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
129 0 : goto receive_done;
130 : }
131 :
132 : /* -=[Validate Response Phase]=- */
133 1 : if (spdm_response_size < sizeof(spdm_message_header_t)) {
134 0 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
135 0 : goto receive_done;
136 : }
137 1 : if (spdm_response->header.spdm_version != spdm_request->header.spdm_version) {
138 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
139 0 : goto receive_done;
140 : }
141 1 : if (spdm_response->header.request_response_code == SPDM_ERROR) {
142 0 : status = libspdm_handle_error_response_main(
143 : spdm_context, session_id,
144 : &spdm_response_size,
145 : (void **)&spdm_response, SPDM_GET_KEY_PAIR_INFO, SPDM_KEY_PAIR_INFO);
146 0 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
147 0 : goto receive_done;
148 : }
149 1 : } else if (spdm_response->header.request_response_code != SPDM_KEY_PAIR_INFO) {
150 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
151 0 : goto receive_done;
152 : }
153 :
154 1 : if ((spdm_response->key_pair_id != key_pair_id) ||
155 1 : (spdm_response->key_pair_id > (spdm_response->total_key_pairs))) {
156 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
157 0 : goto receive_done;
158 : }
159 :
160 1 : if (spdm_response_size < sizeof(spdm_key_pair_info_response_t)) {
161 0 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
162 0 : goto receive_done;
163 : }
164 :
165 1 : if (spdm_response_size < sizeof(spdm_key_pair_info_response_t) +
166 1 : spdm_response->public_key_info_len) {
167 0 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
168 0 : goto receive_done;
169 : }
170 1 : spdm_response_size = sizeof(spdm_key_pair_info_response_t) + spdm_response->public_key_info_len;
171 :
172 : /* -=[Process Response Phase]=- */
173 1 : *key_usage_capabilities = (spdm_response->key_usage_capabilities) & SPDM_KEY_USAGE_BIT_MASK;
174 1 : if (*key_usage_capabilities == 0) {
175 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
176 0 : goto receive_done;
177 : }
178 1 : *current_key_usage = (spdm_response->current_key_usage) & SPDM_KEY_USAGE_BIT_MASK;
179 1 : if ((*key_usage_capabilities | *current_key_usage) != *key_usage_capabilities) {
180 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
181 0 : goto receive_done;
182 : }
183 :
184 1 : *asym_algo_capabilities = (spdm_response->asym_algo_capabilities) &
185 : SPDM_KEY_PAIR_ASYM_ALGO_CAP_MASK;
186 1 : if (*asym_algo_capabilities == 0) {
187 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
188 0 : goto receive_done;
189 : }
190 1 : *current_asym_algo = (spdm_response->current_asym_algo) & SPDM_KEY_PAIR_ASYM_ALGO_CAP_MASK;
191 1 : if (!libspdm_onehot0(*current_asym_algo)) {
192 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
193 0 : goto receive_done;
194 : }
195 1 : if ((*asym_algo_capabilities | *current_asym_algo) != *asym_algo_capabilities) {
196 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
197 0 : goto receive_done;
198 : }
199 :
200 : /*If responder doesn't support SET_KEY_PAIR_INFO_CAP,the capabilities should be 0*/
201 1 : if ((!libspdm_is_capabilities_flag_supported(
202 : spdm_context, true, 0,
203 0 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_SET_KEY_PAIR_INFO_CAP)) &&
204 0 : ((spdm_response->capabilities & SPDM_KEY_PAIR_CAP_MASK) != 0)) {
205 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
206 0 : goto receive_done;
207 : }
208 :
209 1 : *total_key_pairs = spdm_response->total_key_pairs;
210 1 : *capabilities = spdm_response->capabilities & SPDM_KEY_PAIR_CAP_MASK;
211 :
212 1 : if (*public_key_info_len < spdm_response->public_key_info_len) {
213 0 : status = LIBSPDM_STATUS_BUFFER_FULL;
214 0 : goto receive_done;
215 : }
216 1 : *public_key_info_len = spdm_response->public_key_info_len;
217 1 : *assoc_cert_slot_mask = spdm_response->assoc_cert_slot_mask;
218 :
219 1 : libspdm_copy_mem(public_key_info,
220 1 : spdm_response->public_key_info_len,
221 1 : spdm_response->public_key_info,
222 1 : spdm_response->public_key_info_len);
223 :
224 1 : status = LIBSPDM_STATUS_SUCCESS;
225 :
226 : /* -=[Log Message Phase]=- */
227 : #if LIBSPDM_ENABLE_MSG_LOG
228 1 : libspdm_append_msg_log(spdm_context, spdm_response, spdm_response_size);
229 : #endif /* LIBSPDM_ENABLE_MSG_LOG */
230 :
231 1 : receive_done:
232 1 : libspdm_release_receiver_buffer (spdm_context);
233 1 : return status;
234 : }
235 :
236 2 : libspdm_return_t libspdm_get_key_pair_info(void *spdm_context, const uint32_t *session_id,
237 : uint8_t key_pair_id, uint8_t *total_key_pairs,
238 : uint16_t *capabilities,
239 : uint16_t *key_usage_capabilities,
240 : uint16_t *current_key_usage,
241 : uint32_t *asym_algo_capabilities,
242 : uint32_t *current_asym_algo,
243 : uint8_t *assoc_cert_slot_mask,
244 : uint16_t *public_key_info_len,
245 : void *public_key_info
246 : )
247 : {
248 : libspdm_context_t *context;
249 : size_t retry;
250 : uint64_t retry_delay_time;
251 : libspdm_return_t status;
252 :
253 2 : context = spdm_context;
254 2 : context->crypto_request = true;
255 2 : retry = context->retry_times;
256 2 : retry_delay_time = context->retry_delay_time;
257 : do {
258 2 : status = libspdm_try_get_key_pair_info(context, session_id, key_pair_id,
259 : total_key_pairs, capabilities,
260 : key_usage_capabilities, current_key_usage,
261 : asym_algo_capabilities, current_asym_algo,
262 : assoc_cert_slot_mask, public_key_info_len,
263 : public_key_info);
264 2 : if (status != LIBSPDM_STATUS_BUSY_PEER) {
265 2 : return status;
266 : }
267 :
268 0 : libspdm_sleep(retry_delay_time);
269 0 : } while (retry-- != 0);
270 :
271 0 : return status;
272 : }
273 :
274 : #endif /* LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP */
|