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 :
12 15 : libspdm_return_t libspdm_get_encap_response_key_update(void *spdm_context,
13 : size_t request_size,
14 : void *request,
15 : size_t *response_size,
16 : void *response)
17 : {
18 : uint32_t session_id;
19 : spdm_key_update_response_t *spdm_response;
20 : spdm_key_update_request_t *spdm_request;
21 : libspdm_context_t *context;
22 : libspdm_session_info_t *session_info;
23 : libspdm_session_state_t session_state;
24 : spdm_key_update_request_t *prev_spdm_request;
25 : spdm_key_update_request_t spdm_key_init_update_operation;
26 : bool result;
27 :
28 15 : context = spdm_context;
29 15 : spdm_request = request;
30 :
31 15 : if (libspdm_get_connection_version(context) < SPDM_MESSAGE_VERSION_11) {
32 0 : return libspdm_generate_encap_error_response(
33 : context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
34 : SPDM_KEY_UPDATE, response_size, response);
35 : }
36 :
37 15 : if (spdm_request->header.spdm_version != libspdm_get_connection_version(context)) {
38 0 : return libspdm_generate_encap_error_response(
39 : context, SPDM_ERROR_CODE_VERSION_MISMATCH,
40 : 0, response_size, response);
41 : }
42 :
43 15 : if (!libspdm_is_capabilities_flag_supported(
44 : context, true,
45 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_UPD_CAP,
46 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_UPD_CAP)) {
47 1 : return libspdm_generate_encap_error_response(
48 : context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
49 : SPDM_KEY_UPDATE, response_size, response);
50 : }
51 :
52 14 : if (!context->last_spdm_request_session_id_valid) {
53 1 : if (libspdm_get_connection_version(context) >= SPDM_MESSAGE_VERSION_12) {
54 0 : return libspdm_generate_encap_error_response(context,
55 : SPDM_ERROR_CODE_SESSION_REQUIRED, 0,
56 : response_size, response);
57 : } else {
58 1 : return libspdm_generate_encap_error_response(context,
59 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
60 : response_size, response);
61 : }
62 : }
63 13 : session_id = context->last_spdm_request_session_id;
64 : session_info =
65 13 : libspdm_get_session_info_via_session_id(context, session_id);
66 13 : if (session_info == NULL) {
67 0 : return libspdm_generate_encap_error_response(
68 : context, SPDM_ERROR_CODE_INVALID_REQUEST, 0,
69 : response_size, response);
70 : }
71 13 : session_state = libspdm_secured_message_get_session_state(
72 : session_info->secured_message_context);
73 13 : if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
74 1 : return libspdm_generate_encap_error_response(
75 : context, SPDM_ERROR_CODE_INVALID_REQUEST, 0,
76 : response_size, response);
77 : }
78 :
79 : /* this message can only be in secured session
80 : * thus don't need to consider transport layer padding, just check its exact size */
81 12 : if (request_size != sizeof(spdm_key_update_request_t)) {
82 2 : return libspdm_generate_encap_error_response(
83 : context, SPDM_ERROR_CODE_INVALID_REQUEST, 0,
84 : response_size, response);
85 : }
86 :
87 : /*last key operation*/
88 10 : prev_spdm_request = &(session_info->last_key_update_request);
89 :
90 : /*the end status of the successful key update overall flow*/
91 10 : libspdm_zero_mem(&spdm_key_init_update_operation, sizeof(spdm_key_update_request_t));
92 :
93 10 : result = true;
94 10 : switch (spdm_request->header.param1) {
95 5 : case SPDM_KEY_UPDATE_OPERATIONS_TABLE_UPDATE_KEY:
96 5 : if(!libspdm_consttime_is_mem_equal(prev_spdm_request,
97 : &spdm_key_init_update_operation,
98 : sizeof(spdm_key_update_request_t))) {
99 1 : result = false;
100 1 : break;
101 : }
102 4 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
103 : "libspdm_create_update_session_data_key[%x] Responder\n",
104 : session_id));
105 4 : result = libspdm_create_update_session_data_key(
106 : session_info->secured_message_context,
107 : LIBSPDM_KEY_UPDATE_ACTION_RESPONDER);
108 :
109 : /*save the last update operation*/
110 4 : libspdm_copy_mem(prev_spdm_request, sizeof(spdm_key_update_request_t),
111 : spdm_request, request_size);
112 4 : break;
113 1 : case SPDM_KEY_UPDATE_OPERATIONS_TABLE_UPDATE_ALL_KEYS:
114 1 : result = false;
115 1 : break;
116 3 : case SPDM_KEY_UPDATE_OPERATIONS_TABLE_VERIFY_NEW_KEY:
117 3 : if(prev_spdm_request->header.param1 !=
118 : 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*/
|