Line data Source code
1 : /**
2 : * Copyright Notice:
3 : * Copyright 2021-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 : #include "internal/libspdm_responder_lib.h"
7 :
8 : #if LIBSPDM_ENABLE_CAPABILITY_CERT_CAP
9 :
10 1650 : libspdm_return_t libspdm_get_response_certificate(libspdm_context_t *spdm_context,
11 : size_t request_size,
12 : const void *request,
13 : size_t *response_size,
14 : void *response)
15 : {
16 : const spdm_get_certificate_request_t *spdm_request;
17 : spdm_certificate_response_t *spdm_response;
18 : uint16_t offset;
19 : uint16_t length;
20 : size_t remainder_length;
21 : uint8_t slot_id;
22 : libspdm_return_t status;
23 : size_t response_capacity;
24 : libspdm_session_info_t *session_info;
25 : libspdm_session_state_t session_state;
26 :
27 1650 : spdm_request = request;
28 :
29 : /* -=[Check Parameters Phase]=- */
30 1650 : LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_GET_CERTIFICATE);
31 :
32 1650 : if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
33 0 : return libspdm_generate_error_response(spdm_context,
34 : SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
35 : response_size, response);
36 : }
37 1650 : if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
38 3 : return libspdm_responder_handle_response_state(
39 : spdm_context,
40 3 : spdm_request->header.request_response_code,
41 : response_size, response);
42 : }
43 1647 : if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
44 1 : return libspdm_generate_error_response(spdm_context,
45 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
46 : 0, response_size, response);
47 : }
48 1646 : session_info = NULL;
49 1646 : if (spdm_context->last_spdm_request_session_id_valid) {
50 6 : session_info = libspdm_get_session_info_via_session_id(
51 : spdm_context,
52 : spdm_context->last_spdm_request_session_id);
53 6 : if (session_info == NULL) {
54 0 : return libspdm_generate_error_response(
55 : spdm_context,
56 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
57 : response_size, response);
58 : }
59 6 : session_state = libspdm_secured_message_get_session_state(
60 : session_info->secured_message_context);
61 6 : if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
62 0 : return libspdm_generate_error_response(
63 : spdm_context,
64 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
65 : response_size, response);
66 : }
67 : }
68 1646 : if (!libspdm_is_capabilities_flag_supported(
69 : spdm_context, false, 0,
70 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_CAP)) {
71 0 : return libspdm_generate_error_response(
72 : spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
73 : SPDM_GET_CERTIFICATE, response_size, response);
74 : }
75 :
76 1646 : if (request_size < sizeof(spdm_get_certificate_request_t)) {
77 0 : return libspdm_generate_error_response(spdm_context,
78 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
79 : response_size, response);
80 : }
81 :
82 1646 : slot_id = spdm_request->header.param1 & SPDM_GET_CERTIFICATE_REQUEST_SLOT_ID_MASK;
83 :
84 1646 : if (slot_id >= SPDM_MAX_SLOT_COUNT) {
85 1 : return libspdm_generate_error_response(spdm_context,
86 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
87 : response_size, response);
88 : }
89 :
90 1645 : if ((spdm_context->local_context.cert_slot_reset_mask & (1 << slot_id)) != 0) {
91 1 : LIBSPDM_ASSERT(spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12);
92 1 : return libspdm_generate_error_response(spdm_context,
93 : SPDM_ERROR_CODE_RESET_REQUIRED, 0,
94 : response_size, response);
95 : }
96 :
97 1644 : if (spdm_context->local_context.local_cert_chain_provision[slot_id] == NULL) {
98 0 : return libspdm_generate_error_response(
99 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
100 : 0, response_size, response);
101 : }
102 :
103 1644 : offset = spdm_request->offset;
104 1644 : length = spdm_request->length;
105 :
106 1644 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
107 1 : if (spdm_request->header.param2 &
108 : SPDM_GET_CERTIFICATE_REQUEST_ATTRIBUTES_SLOT_SIZE_REQUESTED) {
109 1 : offset = 0;
110 1 : length = 0;
111 : }
112 : }
113 :
114 1644 : if (offset >= spdm_context->local_context.local_cert_chain_provision_size[slot_id]) {
115 126 : return libspdm_generate_error_response(spdm_context,
116 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
117 : response_size, response);
118 : }
119 :
120 1518 : if (!libspdm_is_capabilities_flag_supported(spdm_context, false,
121 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHUNK_CAP,
122 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHUNK_CAP)) {
123 1515 : if (length > LIBSPDM_MAX_CERT_CHAIN_BLOCK_LEN) {
124 67 : length = LIBSPDM_MAX_CERT_CHAIN_BLOCK_LEN;
125 : }
126 : }
127 1518 : if ((size_t)(offset + length) > spdm_context->local_context.
128 1518 : local_cert_chain_provision_size[slot_id]) {
129 18 : length = (uint16_t)(spdm_context->local_context.local_cert_chain_provision_size[slot_id] -
130 : offset);
131 : }
132 1518 : remainder_length = spdm_context->local_context.local_cert_chain_provision_size[slot_id] -
133 1518 : (length + offset);
134 :
135 1518 : libspdm_reset_message_buffer_via_request_code(spdm_context, session_info,
136 1518 : spdm_request->header.request_response_code);
137 :
138 1518 : LIBSPDM_ASSERT(*response_size >= sizeof(spdm_certificate_response_t) + length);
139 1518 : response_capacity = *response_size;
140 1518 : *response_size = sizeof(spdm_certificate_response_t) + length;
141 1518 : libspdm_zero_mem(response, *response_size);
142 1518 : spdm_response = response;
143 :
144 1518 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
145 1518 : spdm_response->header.request_response_code = SPDM_CERTIFICATE;
146 1518 : spdm_response->header.param1 = slot_id;
147 1518 : spdm_response->header.param2 = 0;
148 1518 : if ((spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) &&
149 1 : spdm_context->connection_info.multi_key_conn_rsp) {
150 0 : spdm_response->header.param2 = spdm_context->local_context.local_cert_info[slot_id];
151 : }
152 :
153 1518 : spdm_response->portion_length = length;
154 1518 : spdm_response->remainder_length = (uint16_t)remainder_length;
155 :
156 1518 : libspdm_copy_mem(spdm_response + 1, response_capacity - sizeof(spdm_certificate_response_t),
157 : (const uint8_t *)spdm_context->local_context
158 1518 : .local_cert_chain_provision[slot_id] + offset, length);
159 :
160 1518 : if (session_info == NULL) {
161 : /* Log to transcript. */
162 1514 : const size_t spdm_request_size = sizeof(spdm_get_certificate_request_t);
163 :
164 1514 : status = libspdm_append_message_b(spdm_context, spdm_request, spdm_request_size);
165 1514 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
166 0 : return libspdm_generate_error_response(spdm_context,
167 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
168 : response_size, response);
169 : }
170 :
171 1514 : status = libspdm_append_message_b(spdm_context, spdm_response, *response_size);
172 1514 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
173 0 : return libspdm_generate_error_response(spdm_context,
174 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
175 : response_size, response);
176 : }
177 : }
178 :
179 1518 : if (spdm_context->connection_info.connection_state <
180 : LIBSPDM_CONNECTION_STATE_AFTER_CERTIFICATE) {
181 13 : libspdm_set_connection_state(spdm_context, LIBSPDM_CONNECTION_STATE_AFTER_CERTIFICATE);
182 : }
183 :
184 1518 : return LIBSPDM_STATUS_SUCCESS;
185 : }
186 :
187 : #endif /* LIBSPDM_ENABLE_CAPABILITY_CERT_CAP */
|