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