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 :
9 : #if (LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP) || (LIBSPDM_ENABLE_CAPABILITY_PSK_CAP)
10 :
11 8 : libspdm_return_t libspdm_get_response_heartbeat(libspdm_context_t *spdm_context,
12 : size_t request_size,
13 : const void *request,
14 : size_t *response_size,
15 : void *response)
16 : {
17 : spdm_heartbeat_response_t *spdm_response;
18 : const spdm_heartbeat_request_t *spdm_request;
19 : libspdm_session_info_t *session_info;
20 : libspdm_session_state_t session_state;
21 :
22 8 : spdm_request = request;
23 :
24 : /* -=[Check Parameters Phase]=- */
25 8 : LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_HEARTBEAT);
26 :
27 8 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
28 0 : return libspdm_generate_error_response(spdm_context,
29 : SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
30 : SPDM_HEARTBEAT,
31 : response_size, response);
32 : }
33 :
34 8 : if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
35 0 : return libspdm_generate_error_response(spdm_context,
36 : SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
37 : response_size, response);
38 : }
39 8 : if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
40 3 : return libspdm_responder_handle_response_state(
41 : spdm_context,
42 3 : spdm_request->header.request_response_code,
43 : response_size, response);
44 : }
45 5 : if (!libspdm_is_capabilities_flag_supported(
46 : spdm_context, false,
47 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
48 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
49 0 : return libspdm_generate_error_response(spdm_context,
50 : SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
51 : SPDM_HEARTBEAT, response_size, response);
52 : }
53 5 : if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
54 1 : return libspdm_generate_error_response(spdm_context,
55 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
56 : 0, response_size, response);
57 : }
58 :
59 4 : if (!spdm_context->last_spdm_request_session_id_valid) {
60 0 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
61 0 : return libspdm_generate_error_response(spdm_context,
62 : SPDM_ERROR_CODE_SESSION_REQUIRED, 0,
63 : response_size, response);
64 : } else {
65 0 : return libspdm_generate_error_response(spdm_context,
66 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
67 : response_size, response);
68 : }
69 : }
70 4 : session_info = libspdm_get_session_info_via_session_id(
71 : spdm_context, spdm_context->last_spdm_request_session_id);
72 4 : if (session_info == NULL) {
73 0 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
74 0 : return libspdm_generate_error_response(spdm_context,
75 : SPDM_ERROR_CODE_SESSION_REQUIRED, 0,
76 : response_size, response);
77 : } else {
78 0 : return libspdm_generate_error_response(spdm_context,
79 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
80 : response_size, response);
81 : }
82 : }
83 4 : session_state = libspdm_secured_message_get_session_state(
84 : session_info->secured_message_context);
85 4 : if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
86 0 : return libspdm_generate_error_response(spdm_context,
87 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
88 : response_size, response);
89 : }
90 :
91 : /* this message can only be in secured session
92 : * thus don't need to consider transport layer padding, just check its exact size */
93 4 : if (request_size != sizeof(spdm_heartbeat_request_t)) {
94 1 : return libspdm_generate_error_response(spdm_context,
95 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
96 : response_size, response);
97 : }
98 :
99 3 : if (session_info->heartbeat_period == 0) {
100 1 : return libspdm_generate_error_response(spdm_context,
101 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
102 : response_size, response);
103 : }
104 :
105 2 : libspdm_reset_message_buffer_via_request_code(spdm_context, session_info,
106 2 : spdm_request->header.request_response_code);
107 :
108 2 : LIBSPDM_ASSERT(*response_size >= sizeof(spdm_heartbeat_response_t));
109 2 : *response_size = sizeof(spdm_heartbeat_response_t);
110 2 : libspdm_zero_mem(response, *response_size);
111 2 : spdm_response = response;
112 :
113 2 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
114 2 : spdm_response->header.request_response_code = SPDM_HEARTBEAT_ACK;
115 2 : spdm_response->header.param1 = 0;
116 2 : spdm_response->header.param2 = 0;
117 :
118 2 : return LIBSPDM_STATUS_SUCCESS;
119 : }
120 :
121 : #endif /* (LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP) || (LIBSPDM_ENABLE_CAPABILITY_PSK_CAP) */
|