Line data Source code
1 : /**
2 : * Copyright Notice:
3 : * Copyright 2021-2025 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 : #include "internal/libspdm_secured_message_lib.h"
9 :
10 : #if LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP
11 :
12 2 : libspdm_return_t libspdm_get_encap_request_key_update(libspdm_context_t *spdm_context,
13 : size_t *encap_request_size,
14 : void *encap_request)
15 : {
16 : spdm_key_update_request_t *spdm_request;
17 : uint32_t session_id;
18 : libspdm_session_info_t *session_info;
19 : libspdm_session_state_t session_state;
20 : bool result;
21 :
22 2 : spdm_context->encap_context.last_encap_request_size = 0;
23 :
24 2 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
25 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
26 : }
27 :
28 2 : if (!libspdm_is_capabilities_flag_supported(
29 : spdm_context, false,
30 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_UPD_CAP,
31 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_UPD_CAP)) {
32 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
33 : }
34 :
35 2 : if (!spdm_context->last_spdm_request_session_id_valid) {
36 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
37 : }
38 2 : session_id = spdm_context->last_spdm_request_session_id;
39 : session_info =
40 2 : libspdm_get_session_info_via_session_id(spdm_context, session_id);
41 2 : if (session_info == NULL) {
42 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
43 : }
44 2 : session_state = libspdm_secured_message_get_session_state(
45 : session_info->secured_message_context);
46 2 : if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
47 0 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
48 : }
49 :
50 2 : LIBSPDM_ASSERT(*encap_request_size >= sizeof(spdm_key_update_request_t));
51 2 : *encap_request_size = sizeof(spdm_key_update_request_t);
52 :
53 2 : spdm_request = encap_request;
54 :
55 2 : spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
56 2 : spdm_request->header.request_response_code = SPDM_KEY_UPDATE;
57 :
58 2 : libspdm_reset_message_buffer_via_request_code(spdm_context, session_info,
59 2 : spdm_request->header.request_response_code);
60 :
61 2 : if (spdm_context->encap_context.last_encap_request_header
62 2 : .request_response_code != SPDM_KEY_UPDATE) {
63 2 : spdm_request->header.param1 =
64 : SPDM_KEY_UPDATE_OPERATIONS_TABLE_UPDATE_KEY;
65 2 : spdm_request->header.param2 = 0;
66 2 : if (!libspdm_get_random_number(sizeof(spdm_request->header.param2),
67 : &spdm_request->header.param2)) {
68 0 : return LIBSPDM_STATUS_LOW_ENTROPY;
69 : }
70 : } else {
71 0 : spdm_request->header.param1 =
72 : SPDM_KEY_UPDATE_OPERATIONS_TABLE_VERIFY_NEW_KEY;
73 0 : spdm_request->header.param2 = 1;
74 0 : if (!libspdm_get_random_number(sizeof(spdm_request->header.param2),
75 : &spdm_request->header.param2)) {
76 0 : return LIBSPDM_STATUS_LOW_ENTROPY;
77 : }
78 :
79 : /* Create new key*/
80 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
81 : "libspdm_create_update_session_data_key[%x] Responder\n",
82 : session_id));
83 0 : result = libspdm_create_update_session_data_key(
84 : session_info->secured_message_context,
85 : LIBSPDM_KEY_UPDATE_ACTION_RESPONDER);
86 0 : if (!result) {
87 0 : return LIBSPDM_STATUS_CRYPTO_ERROR;
88 : }
89 0 : libspdm_trigger_key_update_callback(
90 : spdm_context, session_id, LIBSPDM_KEY_UPDATE_OPERATION_CREATE_UPDATE,
91 : LIBSPDM_KEY_UPDATE_ACTION_RESPONDER);
92 :
93 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
94 : "libspdm_activate_update_session_data_key[%x] Responder new\n",
95 : session_id));
96 0 : result = libspdm_activate_update_session_data_key(
97 : session_info->secured_message_context,
98 : LIBSPDM_KEY_UPDATE_ACTION_RESPONDER, true);
99 0 : if (!result) {
100 0 : return LIBSPDM_STATUS_CRYPTO_ERROR;
101 : }
102 0 : libspdm_trigger_key_update_callback(
103 : spdm_context, session_id, LIBSPDM_KEY_UPDATE_OPERATION_COMMIT_UPDATE,
104 : LIBSPDM_KEY_UPDATE_ACTION_RESPONDER);
105 : }
106 :
107 2 : libspdm_copy_mem(&spdm_context->encap_context.last_encap_request_header,
108 : sizeof(spdm_context->encap_context.last_encap_request_header),
109 2 : &spdm_request->header, sizeof(spdm_message_header_t));
110 2 : spdm_context->encap_context.last_encap_request_size =
111 2 : *encap_request_size;
112 :
113 2 : return LIBSPDM_STATUS_SUCCESS;
114 : }
115 :
116 6 : libspdm_return_t libspdm_process_encap_response_key_update(
117 : libspdm_context_t *spdm_context, size_t encap_response_size,
118 : const void *encap_response, bool *need_continue)
119 : {
120 : spdm_key_update_request_t *spdm_request;
121 : const spdm_key_update_response_t *spdm_response;
122 : size_t spdm_response_size;
123 : uint32_t session_id;
124 : libspdm_session_info_t *session_info;
125 : libspdm_session_state_t session_state;
126 :
127 6 : if (!spdm_context->last_spdm_request_session_id_valid) {
128 1 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
129 : }
130 5 : session_id = spdm_context->last_spdm_request_session_id;
131 : session_info =
132 5 : libspdm_get_session_info_via_session_id(spdm_context, session_id);
133 5 : if (session_info == NULL) {
134 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
135 : }
136 5 : session_state = libspdm_secured_message_get_session_state(
137 : session_info->secured_message_context);
138 5 : if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
139 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
140 : }
141 :
142 5 : spdm_request =
143 : (void *)&spdm_context->encap_context.last_encap_request_header;
144 :
145 5 : spdm_response = encap_response;
146 5 : spdm_response_size = encap_response_size;
147 :
148 5 : if (spdm_response->header.spdm_version != libspdm_get_connection_version (spdm_context)) {
149 0 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
150 : }
151 :
152 5 : if (spdm_response->header.request_response_code == SPDM_ERROR) {
153 1 : if (spdm_response->header.param1 == SPDM_ERROR_CODE_DECRYPT_ERROR) {
154 1 : libspdm_free_session_id(spdm_context, session_id);
155 1 : return LIBSPDM_STATUS_SESSION_MSG_ERROR;
156 : }
157 : }
158 :
159 : /* this message can only be in secured session
160 : * thus don't need to consider transport layer padding, just check its exact size */
161 4 : if ((spdm_response_size != sizeof(spdm_key_update_response_t)) ||
162 4 : (spdm_response->header.request_response_code !=
163 4 : SPDM_KEY_UPDATE_ACK) ||
164 4 : (spdm_response->header.param1 != spdm_request->header.param1) ||
165 3 : (spdm_response->header.param2 != spdm_request->header.param2)) {
166 1 : if (spdm_request->header.param1 !=
167 : SPDM_KEY_UPDATE_OPERATIONS_TABLE_VERIFY_NEW_KEY) {
168 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_key_update[%x] failed\n",
169 : session_id));
170 : } else {
171 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "SpdmVerifyKey[%x] failed\n",
172 : session_id));
173 : }
174 1 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
175 : }
176 :
177 3 : if (spdm_request->header.param1 !=
178 : SPDM_KEY_UPDATE_OPERATIONS_TABLE_VERIFY_NEW_KEY) {
179 2 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_key_update[%x] success\n",
180 : session_id));
181 2 : *need_continue = true;
182 : } else {
183 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "SpdmVerifyKey[%x] Success\n", session_id));
184 1 : *need_continue = false;
185 : }
186 :
187 3 : return LIBSPDM_STATUS_SUCCESS;
188 : }
189 :
190 : #endif /* LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP*/
|