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