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_requester_lib.h"
8 : #include "internal/libspdm_secured_message_lib.h"
9 :
10 : #if (LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP) && \
11 : ((LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP) || (LIBSPDM_ENABLE_CAPABILITY_PSK_CAP))
12 :
13 15 : libspdm_return_t libspdm_get_encap_response_key_update(void *spdm_context,
14 : size_t request_size,
15 : void *request,
16 : size_t *response_size,
17 : void *response)
18 : {
19 : uint32_t session_id;
20 : spdm_key_update_response_t *spdm_response;
21 : spdm_key_update_request_t *spdm_request;
22 : libspdm_context_t *context;
23 : libspdm_session_info_t *session_info;
24 : libspdm_session_state_t session_state;
25 : spdm_key_update_request_t *prev_spdm_request;
26 : spdm_key_update_request_t spdm_key_init_update_operation;
27 : bool result;
28 :
29 15 : context = spdm_context;
30 15 : spdm_request = request;
31 :
32 15 : if (libspdm_get_connection_version(context) < SPDM_MESSAGE_VERSION_11) {
33 0 : return libspdm_generate_encap_error_response(
34 : context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
35 : SPDM_KEY_UPDATE, response_size, response);
36 : }
37 :
38 15 : if (spdm_request->header.spdm_version != libspdm_get_connection_version(context)) {
39 0 : return libspdm_generate_encap_error_response(
40 : context, SPDM_ERROR_CODE_VERSION_MISMATCH,
41 : 0, response_size, response);
42 : }
43 :
44 15 : if (!libspdm_is_capabilities_flag_supported(
45 : context, true,
46 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_UPD_CAP,
47 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_UPD_CAP)) {
48 1 : return libspdm_generate_encap_error_response(
49 : context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
50 : SPDM_KEY_UPDATE, response_size, response);
51 : }
52 :
53 14 : if (!context->last_spdm_request_session_id_valid) {
54 1 : if (libspdm_get_connection_version(context) >= SPDM_MESSAGE_VERSION_12) {
55 0 : return libspdm_generate_encap_error_response(context,
56 : SPDM_ERROR_CODE_SESSION_REQUIRED, 0,
57 : response_size, response);
58 : } else {
59 1 : return libspdm_generate_encap_error_response(context,
60 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
61 : response_size, response);
62 : }
63 : }
64 13 : session_id = context->last_spdm_request_session_id;
65 : session_info =
66 13 : libspdm_get_session_info_via_session_id(context, session_id);
67 13 : if (session_info == NULL) {
68 0 : return libspdm_generate_encap_error_response(
69 : context, SPDM_ERROR_CODE_INVALID_REQUEST, 0,
70 : response_size, response);
71 : }
72 13 : session_state = libspdm_secured_message_get_session_state(
73 : session_info->secured_message_context);
74 13 : if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
75 1 : return libspdm_generate_encap_error_response(
76 : context, SPDM_ERROR_CODE_INVALID_REQUEST, 0,
77 : response_size, response);
78 : }
79 :
80 : /* this message can only be in secured session
81 : * thus don't need to consider transport layer padding, just check its exact size */
82 12 : if (request_size != sizeof(spdm_key_update_request_t)) {
83 2 : return libspdm_generate_encap_error_response(
84 : context, SPDM_ERROR_CODE_INVALID_REQUEST, 0,
85 : response_size, response);
86 : }
87 :
88 : /*last key operation*/
89 10 : prev_spdm_request = &(session_info->last_key_update_request);
90 :
91 : /*the end status of the successful key update overall flow*/
92 10 : libspdm_zero_mem(&spdm_key_init_update_operation, sizeof(spdm_key_update_request_t));
93 :
94 10 : result = true;
95 10 : switch (spdm_request->header.param1) {
96 5 : case SPDM_KEY_UPDATE_OPERATIONS_TABLE_UPDATE_KEY:
97 5 : if (!libspdm_consttime_is_mem_equal(prev_spdm_request,
98 : &spdm_key_init_update_operation,
99 : sizeof(spdm_key_update_request_t))) {
100 1 : result = false;
101 1 : break;
102 : }
103 4 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
104 : "libspdm_create_update_session_data_key[%x] Responder\n",
105 : session_id));
106 4 : result = libspdm_create_update_session_data_key(
107 : session_info->secured_message_context,
108 : LIBSPDM_KEY_UPDATE_ACTION_RESPONDER);
109 :
110 : /*save the last update operation*/
111 4 : libspdm_copy_mem(prev_spdm_request, sizeof(spdm_key_update_request_t),
112 : spdm_request, request_size);
113 4 : break;
114 1 : case SPDM_KEY_UPDATE_OPERATIONS_TABLE_UPDATE_ALL_KEYS:
115 1 : result = false;
116 1 : break;
117 3 : case SPDM_KEY_UPDATE_OPERATIONS_TABLE_VERIFY_NEW_KEY:
118 3 : if (prev_spdm_request->header.param1 != SPDM_KEY_UPDATE_OPERATIONS_TABLE_UPDATE_KEY) {
119 3 : result = false;
120 3 : break;
121 : }
122 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
123 : "libspdm_activate_update_session_data_key[%x] Responder new\n",
124 : session_id));
125 0 : result = libspdm_activate_update_session_data_key(
126 : session_info->secured_message_context,
127 : LIBSPDM_KEY_UPDATE_ACTION_RESPONDER, true);
128 :
129 : /*clear last_key_update_request*/
130 0 : libspdm_zero_mem(prev_spdm_request, sizeof(spdm_key_update_request_t));
131 0 : break;
132 1 : default:
133 1 : result = false;
134 1 : break;
135 : }
136 :
137 10 : if (!result) {
138 6 : return libspdm_generate_encap_error_response(
139 : context, SPDM_ERROR_CODE_INVALID_REQUEST, 0,
140 : response_size, response);
141 : }
142 :
143 4 : libspdm_reset_message_buffer_via_request_code(context, session_info,
144 4 : spdm_request->header.request_response_code);
145 :
146 4 : LIBSPDM_ASSERT(*response_size >= sizeof(spdm_key_update_response_t));
147 4 : *response_size = sizeof(spdm_key_update_response_t);
148 4 : libspdm_zero_mem(response, *response_size);
149 4 : spdm_response = response;
150 :
151 4 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
152 4 : spdm_response->header.request_response_code = SPDM_KEY_UPDATE_ACK;
153 4 : spdm_response->header.param1 = spdm_request->header.param1;
154 4 : spdm_response->header.param2 = spdm_request->header.param2;
155 :
156 4 : return LIBSPDM_STATUS_SUCCESS;
157 : }
158 :
159 : #endif /* LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP && (...) */
|