18bb10b79STom Joseph #include "rakp12.hpp"
28bb10b79STom Joseph 
39e801a2bSVernon Mauery #include "comm_module.hpp"
49e801a2bSVernon Mauery #include "endian.hpp"
59e801a2bSVernon Mauery #include "guid.hpp"
62085ae07SVernon Mauery #include "sessions_manager.hpp"
79e801a2bSVernon Mauery 
88bb10b79STom Joseph #include <openssl/rand.h>
98bb10b79STom Joseph 
10bc8958feSGeorge Liu #include <ipmid/types.hpp>
11*7b7f25f7SGeorge Liu #include <phosphor-logging/lg2.hpp>
12bc8958feSGeorge Liu 
138bb10b79STom Joseph #include <algorithm>
1456527b93STom Joseph #include <cstring>
158bb10b79STom Joseph #include <iomanip>
168bb10b79STom Joseph 
178bb10b79STom Joseph namespace command
188bb10b79STom Joseph {
198bb10b79STom Joseph 
20ecb32fbcSAppaRao Puli bool isChannelAccessModeEnabled(const uint8_t accessMode)
21ecb32fbcSAppaRao Puli {
22ecb32fbcSAppaRao Puli     return accessMode !=
23ecb32fbcSAppaRao Puli            static_cast<uint8_t>(ipmi::EChannelAccessMode::disabled);
24ecb32fbcSAppaRao Puli }
25ecb32fbcSAppaRao Puli 
260e0546f1Ssunitakx void logInvalidLoginRedfishEvent(const std::string& journalMsg,
270e0546f1Ssunitakx                                  const std::optional<std::string>& messageArgs)
280e0546f1Ssunitakx {
290e0546f1Ssunitakx     static constexpr std::string_view openBMCMessageRegistryVersion = "0.1.";
300e0546f1Ssunitakx     std::string messageID = "OpenBMC." +
310e0546f1Ssunitakx                             std::string(openBMCMessageRegistryVersion) +
320e0546f1Ssunitakx                             "InvalidLoginAttempted";
33*7b7f25f7SGeorge Liu     lg2::error(
34*7b7f25f7SGeorge Liu         "message: {MSG}, id: {REDFISH_MESSAGE_ID}, args: {REDFISH_MESSAGE_ARGS}",
35*7b7f25f7SGeorge Liu         "MSG", journalMsg, "REDFISH_MESSAGE_ID", messageID,
36*7b7f25f7SGeorge Liu         "REDFISH_MESSAGE_ARGS", messageArgs.value());
370e0546f1Ssunitakx }
3818a45e9dSTom Joseph std::vector<uint8_t> RAKP12(const std::vector<uint8_t>& inPayload,
39be1470ccSGeorge Liu                             std::shared_ptr<message::Handler>& /* handler */)
408bb10b79STom Joseph {
4118a45e9dSTom Joseph     auto request = reinterpret_cast<const RAKP1request*>(inPayload.data());
422b1edef0SZhikui Ren     // verify inPayload minimum size
432b1edef0SZhikui Ren     if (inPayload.size() < (sizeof(*request) - userNameMaxLen))
442b1edef0SZhikui Ren     {
452b1edef0SZhikui Ren         std::vector<uint8_t> errorPayload{IPMI_CC_REQ_DATA_LEN_INVALID};
462b1edef0SZhikui Ren         return errorPayload;
472b1edef0SZhikui Ren     }
482b1edef0SZhikui Ren 
492b1edef0SZhikui Ren     std::vector<uint8_t> outPayload(sizeof(RAKP2response));
508bb10b79STom Joseph     auto response = reinterpret_cast<RAKP2response*>(outPayload.data());
518bb10b79STom Joseph 
528bb10b79STom Joseph     // Session ID zero is reserved for Session Setup
538bb10b79STom Joseph     if (endian::from_ipmi(request->managedSystemSessionID) ==
54f8a34fc4SSuryakanth Sekar         session::sessionZero)
558bb10b79STom Joseph     {
56*7b7f25f7SGeorge Liu         lg2::info("RAKP12: BMC invalid Session ID");
578bb10b79STom Joseph         response->rmcpStatusCode =
588bb10b79STom Joseph             static_cast<uint8_t>(RAKP_ReturnCode::INVALID_SESSION_ID);
598bb10b79STom Joseph         return outPayload;
608bb10b79STom Joseph     }
618bb10b79STom Joseph 
628bb10b79STom Joseph     std::shared_ptr<session::Session> session;
638bb10b79STom Joseph     try
648bb10b79STom Joseph     {
652085ae07SVernon Mauery         session = session::Manager::get().getSession(
662085ae07SVernon Mauery             endian::from_ipmi(request->managedSystemSessionID));
678bb10b79STom Joseph     }
6812d199b2SPatrick Williams     catch (const std::exception& e)
698bb10b79STom Joseph     {
70*7b7f25f7SGeorge Liu         lg2::error("RAKP12 : session not found: {ERROR}", "ERROR", e);
718bb10b79STom Joseph         response->rmcpStatusCode =
728bb10b79STom Joseph             static_cast<uint8_t>(RAKP_ReturnCode::INVALID_SESSION_ID);
738bb10b79STom Joseph         return outPayload;
748bb10b79STom Joseph     }
758bb10b79STom Joseph 
769e801a2bSVernon Mauery     auto rakp1Size =
779e801a2bSVernon Mauery         sizeof(RAKP1request) - (userNameMaxLen - request->user_name_len);
7856527b93STom Joseph 
790e0546f1Ssunitakx     std::string message = "Invalid login attempted via RCMPP interface ";
8056527b93STom Joseph     // Validate user name length in the message
8156527b93STom Joseph     if (request->user_name_len > userNameMaxLen ||
8256527b93STom Joseph         inPayload.size() != rakp1Size)
8356527b93STom Joseph     {
8456527b93STom Joseph         response->rmcpStatusCode =
8556527b93STom Joseph             static_cast<uint8_t>(RAKP_ReturnCode::INVALID_NAME_LENGTH);
860e0546f1Ssunitakx         logInvalidLoginRedfishEvent(message);
8756527b93STom Joseph         return outPayload;
8856527b93STom Joseph     }
8956527b93STom Joseph 
9056527b93STom Joseph     session->userName.assign(request->user_name, request->user_name_len);
9156527b93STom Joseph 
928bb10b79STom Joseph     // Update transaction time
938bb10b79STom Joseph     session->updateLastTransactionTime();
948bb10b79STom Joseph 
958bb10b79STom Joseph     auto rcSessionID = endian::to_ipmi(session->getRCSessionID());
968bb10b79STom Joseph     auto bmcSessionID = endian::to_ipmi(session->getBMCSessionID());
978bb10b79STom Joseph     auto authAlgo = session->getAuthAlgo();
988bb10b79STom Joseph 
998bb10b79STom Joseph     /*
1008bb10b79STom Joseph      * Generate Key Authentication Code - RAKP 2
1018bb10b79STom Joseph      *
1028bb10b79STom Joseph      * 1) Remote Console Session ID - 4 bytes
1038bb10b79STom Joseph      * 2) Managed System Session ID - 4 bytes
1048bb10b79STom Joseph      * 3) Remote Console Random Number - 16 bytes
1058bb10b79STom Joseph      * 4) Managed System Random Number - 16 bytes
1068bb10b79STom Joseph      * 5) Managed System GUID - 16 bytes
1078bb10b79STom Joseph      * 6) Requested Privilege Level - 1 byte
1088bb10b79STom Joseph      * 7) User Name Length Byte - 1 byte (0 for 'null' username)
1098bb10b79STom Joseph      * 8) User Name - variable (absent for 'null' username)
1108bb10b79STom Joseph      */
1118bb10b79STom Joseph 
1128bb10b79STom Joseph     std::vector<uint8_t> input;
1138bb10b79STom Joseph     input.resize(sizeof(rcSessionID) + sizeof(bmcSessionID) +
1148bb10b79STom Joseph                  cipher::rakp_auth::REMOTE_CONSOLE_RANDOM_NUMBER_LEN +
1159e801a2bSVernon Mauery                  cipher::rakp_auth::BMC_RANDOM_NUMBER_LEN + BMC_GUID_LEN +
1169e801a2bSVernon Mauery                  sizeof(request->req_max_privilege_level) +
1179e801a2bSVernon Mauery                  sizeof(request->user_name_len) + session->userName.size());
1188bb10b79STom Joseph 
1198bb10b79STom Joseph     auto iter = input.begin();
1208bb10b79STom Joseph 
1218bb10b79STom Joseph     // Remote Console Session ID
1229e801a2bSVernon Mauery     std::copy_n(reinterpret_cast<uint8_t*>(&rcSessionID), sizeof(rcSessionID),
1239e801a2bSVernon Mauery                 iter);
1248bb10b79STom Joseph     std::advance(iter, sizeof(rcSessionID));
1258bb10b79STom Joseph 
1268bb10b79STom Joseph     // Managed System Session ID
1278bb10b79STom Joseph     std::copy_n(reinterpret_cast<uint8_t*>(&bmcSessionID), sizeof(bmcSessionID),
1288bb10b79STom Joseph                 iter);
1298bb10b79STom Joseph     std::advance(iter, sizeof(bmcSessionID));
1308bb10b79STom Joseph 
1318bb10b79STom Joseph     // Copy the Remote Console Random Number from the RAKP1 request to the
1328bb10b79STom Joseph     // Authentication Algorithm
1339e801a2bSVernon Mauery     std::copy_n(
1349e801a2bSVernon Mauery         reinterpret_cast<const uint8_t*>(request->remote_console_random_number),
1358bb10b79STom Joseph         cipher::rakp_auth::REMOTE_CONSOLE_RANDOM_NUMBER_LEN,
1368bb10b79STom Joseph         authAlgo->rcRandomNum.begin());
1378bb10b79STom Joseph 
1389e801a2bSVernon Mauery     std::copy(authAlgo->rcRandomNum.begin(), authAlgo->rcRandomNum.end(), iter);
1398bb10b79STom Joseph     std::advance(iter, cipher::rakp_auth::REMOTE_CONSOLE_RANDOM_NUMBER_LEN);
1408bb10b79STom Joseph 
1418bb10b79STom Joseph     // Generate the Managed System Random Number
1428bb10b79STom Joseph     if (!RAND_bytes(input.data() + sizeof(rcSessionID) + sizeof(bmcSessionID) +
1438bb10b79STom Joseph                         cipher::rakp_auth::REMOTE_CONSOLE_RANDOM_NUMBER_LEN,
1448bb10b79STom Joseph                     cipher::rakp_auth::BMC_RANDOM_NUMBER_LEN))
1458bb10b79STom Joseph     {
1468bb10b79STom Joseph         response->rmcpStatusCode =
1478bb10b79STom Joseph             static_cast<uint8_t>(RAKP_ReturnCode::INSUFFICIENT_RESOURCE);
1488bb10b79STom Joseph         return outPayload;
1498bb10b79STom Joseph     }
150d5a4f45eSRichard Marian Thomaiyar     // As stated in Set Session Privilege Level command in IPMI Spec, when
1512555e2ecSjayaprakash Mutyala     // creating a session through Activate command / RAKP 1 message, it must
1522555e2ecSjayaprakash Mutyala     // be established with USER privilege as well as all other sessions are
1532555e2ecSjayaprakash Mutyala     // initially set to USER privilege, regardless of the requested maximum
1542555e2ecSjayaprakash Mutyala     // privilege.
1552555e2ecSjayaprakash Mutyala     if (!(static_cast<session::Privilege>(request->req_max_privilege_level &
156d5a4f45eSRichard Marian Thomaiyar                                           session::reqMaxPrivMask) >
1572555e2ecSjayaprakash Mutyala           session::Privilege::CALLBACK))
158d5a4f45eSRichard Marian Thomaiyar     {
1592555e2ecSjayaprakash Mutyala         response->rmcpStatusCode =
1602555e2ecSjayaprakash Mutyala             static_cast<uint8_t>(RAKP_ReturnCode::UNAUTH_ROLE_PRIV);
1612555e2ecSjayaprakash Mutyala         return outPayload;
162d5a4f45eSRichard Marian Thomaiyar     }
1632555e2ecSjayaprakash Mutyala     session->currentPrivilege(static_cast<uint8_t>(session::Privilege::USER));
1642555e2ecSjayaprakash Mutyala 
1654021b1f7STom Joseph     session->reqMaxPrivLevel =
1664021b1f7STom Joseph         static_cast<session::Privilege>(request->req_max_privilege_level);
167d91fd9d2SRichard Marian Thomaiyar     if (request->user_name_len == 0)
168127748a8SRichard Marian Thomaiyar     {
169d91fd9d2SRichard Marian Thomaiyar         // Bail out, if user name is not specified.
170d91fd9d2SRichard Marian Thomaiyar         // Yes, NULL user name is not supported for security reasons.
171127748a8SRichard Marian Thomaiyar         response->rmcpStatusCode =
172127748a8SRichard Marian Thomaiyar             static_cast<uint8_t>(RAKP_ReturnCode::UNAUTH_NAME);
1730e0546f1Ssunitakx         logInvalidLoginRedfishEvent(message);
174127748a8SRichard Marian Thomaiyar         return outPayload;
175127748a8SRichard Marian Thomaiyar     }
176127748a8SRichard Marian Thomaiyar 
177127748a8SRichard Marian Thomaiyar     // Perform user name based lookup
178127748a8SRichard Marian Thomaiyar     std::string userName(request->user_name, request->user_name_len);
17905c1447dSJayaprakash Mutyala     ipmi::SecureString passwd;
180127748a8SRichard Marian Thomaiyar     uint8_t userId = ipmi::ipmiUserGetUserId(userName);
181127748a8SRichard Marian Thomaiyar     if (userId == ipmi::invalidUserId)
182127748a8SRichard Marian Thomaiyar     {
183127748a8SRichard Marian Thomaiyar         response->rmcpStatusCode =
184127748a8SRichard Marian Thomaiyar             static_cast<uint8_t>(RAKP_ReturnCode::UNAUTH_NAME);
1850e0546f1Ssunitakx         logInvalidLoginRedfishEvent(message);
186127748a8SRichard Marian Thomaiyar         return outPayload;
187127748a8SRichard Marian Thomaiyar     }
188127748a8SRichard Marian Thomaiyar     // check user is enabled before proceeding.
189127748a8SRichard Marian Thomaiyar     bool userEnabled = false;
190127748a8SRichard Marian Thomaiyar     ipmi::ipmiUserCheckEnabled(userId, userEnabled);
191127748a8SRichard Marian Thomaiyar     if (!userEnabled)
192127748a8SRichard Marian Thomaiyar     {
193127748a8SRichard Marian Thomaiyar         response->rmcpStatusCode =
194127748a8SRichard Marian Thomaiyar             static_cast<uint8_t>(RAKP_ReturnCode::INACTIVE_ROLE);
1950e0546f1Ssunitakx         logInvalidLoginRedfishEvent(message);
196127748a8SRichard Marian Thomaiyar         return outPayload;
197127748a8SRichard Marian Thomaiyar     }
1984c4694efSRichard Marian Thomaiyar     // Get the user password for RAKP message authenticate
1994c4694efSRichard Marian Thomaiyar     passwd = ipmi::ipmiUserGetPassword(userName);
2004c4694efSRichard Marian Thomaiyar     if (passwd.empty())
2014c4694efSRichard Marian Thomaiyar     {
2024c4694efSRichard Marian Thomaiyar         response->rmcpStatusCode =
2034c4694efSRichard Marian Thomaiyar             static_cast<uint8_t>(RAKP_ReturnCode::UNAUTH_NAME);
2040e0546f1Ssunitakx         logInvalidLoginRedfishEvent(message);
2054c4694efSRichard Marian Thomaiyar         return outPayload;
2064c4694efSRichard Marian Thomaiyar     }
207b31e9695SAyushi Smriti     // Check whether user is already locked for failed attempts
208b31e9695SAyushi Smriti     if (!ipmi::ipmiUserPamAuthenticate(userName, passwd))
209b31e9695SAyushi Smriti     {
210*7b7f25f7SGeorge Liu         lg2::error(
211*7b7f25f7SGeorge Liu             "Authentication failed - user already locked out, user id: {ID}",
212*7b7f25f7SGeorge Liu             "ID", userId);
213b31e9695SAyushi Smriti 
214b31e9695SAyushi Smriti         response->rmcpStatusCode =
215b31e9695SAyushi Smriti             static_cast<uint8_t>(RAKP_ReturnCode::UNAUTH_NAME);
2160e0546f1Ssunitakx         logInvalidLoginRedfishEvent(message);
217b31e9695SAyushi Smriti         return outPayload;
218b31e9695SAyushi Smriti     }
219d9c86bb7SSaravanan Palanisamy 
220d9c86bb7SSaravanan Palanisamy     uint8_t chNum = static_cast<uint8_t>(getInterfaceIndex());
221127748a8SRichard Marian Thomaiyar     // Get channel based access information
222992e53c7SRichard Marian Thomaiyar     if ((ipmi::ipmiUserGetPrivilegeAccess(
223992e53c7SRichard Marian Thomaiyar              userId, chNum, session->sessionUserPrivAccess) != IPMI_CC_OK) ||
224992e53c7SRichard Marian Thomaiyar         (ipmi::getChannelAccessData(chNum, session->sessionChannelAccess) !=
225992e53c7SRichard Marian Thomaiyar          IPMI_CC_OK))
226127748a8SRichard Marian Thomaiyar     {
227127748a8SRichard Marian Thomaiyar         response->rmcpStatusCode =
228127748a8SRichard Marian Thomaiyar             static_cast<uint8_t>(RAKP_ReturnCode::INACTIVE_ROLE);
2290e0546f1Ssunitakx         logInvalidLoginRedfishEvent(message);
230127748a8SRichard Marian Thomaiyar         return outPayload;
231127748a8SRichard Marian Thomaiyar     }
232ecb32fbcSAppaRao Puli     if (!isChannelAccessModeEnabled(session->sessionChannelAccess.accessMode))
233ecb32fbcSAppaRao Puli     {
234*7b7f25f7SGeorge Liu         lg2::error("Channel access mode disabled.");
235ecb32fbcSAppaRao Puli         response->rmcpStatusCode =
236ecb32fbcSAppaRao Puli             static_cast<uint8_t>(RAKP_ReturnCode::INACTIVE_ROLE);
2370e0546f1Ssunitakx         logInvalidLoginRedfishEvent(message);
238ecb32fbcSAppaRao Puli         return outPayload;
239ecb32fbcSAppaRao Puli     }
240992e53c7SRichard Marian Thomaiyar     if (session->sessionUserPrivAccess.privilege >
241992e53c7SRichard Marian Thomaiyar         static_cast<uint8_t>(session::Privilege::OEM))
2427e5d38d2SRichard Marian Thomaiyar     {
2437e5d38d2SRichard Marian Thomaiyar         response->rmcpStatusCode =
2447e5d38d2SRichard Marian Thomaiyar             static_cast<uint8_t>(RAKP_ReturnCode::INACTIVE_ROLE);
2450e0546f1Ssunitakx         logInvalidLoginRedfishEvent(message);
2467e5d38d2SRichard Marian Thomaiyar         return outPayload;
2477e5d38d2SRichard Marian Thomaiyar     }
248f8a34fc4SSuryakanth Sekar     session->channelNum(chNum);
249f8a34fc4SSuryakanth Sekar     session->userID(userId);
2502555e2ecSjayaprakash Mutyala     // minimum privilege of Channel / User / session::privilege::USER
251d5a4f45eSRichard Marian Thomaiyar     // has to be used as session current privilege level
252127748a8SRichard Marian Thomaiyar     uint8_t minPriv = 0;
253992e53c7SRichard Marian Thomaiyar     if (session->sessionChannelAccess.privLimit <
254992e53c7SRichard Marian Thomaiyar         session->sessionUserPrivAccess.privilege)
255127748a8SRichard Marian Thomaiyar     {
256992e53c7SRichard Marian Thomaiyar         minPriv = session->sessionChannelAccess.privLimit;
257127748a8SRichard Marian Thomaiyar     }
258127748a8SRichard Marian Thomaiyar     else
259127748a8SRichard Marian Thomaiyar     {
260992e53c7SRichard Marian Thomaiyar         minPriv = session->sessionUserPrivAccess.privilege;
261127748a8SRichard Marian Thomaiyar     }
262f8a34fc4SSuryakanth Sekar     if (session->currentPrivilege() > minPriv)
263127748a8SRichard Marian Thomaiyar     {
264f8a34fc4SSuryakanth Sekar         session->currentPrivilege(static_cast<uint8_t>(minPriv));
265127748a8SRichard Marian Thomaiyar     }
266d91fd9d2SRichard Marian Thomaiyar     // For username / privilege lookup, fail with UNAUTH_NAME, if requested
267d8e92fe1SRichard Marian Thomaiyar     // max privilege does not match user privilege
268d91fd9d2SRichard Marian Thomaiyar     if (((request->req_max_privilege_level & userNameOnlyLookupMask) ==
269d91fd9d2SRichard Marian Thomaiyar          userNamePrivLookup) &&
270d8e92fe1SRichard Marian Thomaiyar         ((request->req_max_privilege_level & session::reqMaxPrivMask) !=
271992e53c7SRichard Marian Thomaiyar          session->sessionUserPrivAccess.privilege))
272d91fd9d2SRichard Marian Thomaiyar     {
273*7b7f25f7SGeorge Liu         lg2::info("Username/Privilege lookup failed for requested privilege");
274d91fd9d2SRichard Marian Thomaiyar         response->rmcpStatusCode =
275d91fd9d2SRichard Marian Thomaiyar             static_cast<uint8_t>(RAKP_ReturnCode::UNAUTH_NAME);
2760e0546f1Ssunitakx 
2770e0546f1Ssunitakx         logInvalidLoginRedfishEvent(message);
278d91fd9d2SRichard Marian Thomaiyar         return outPayload;
279d91fd9d2SRichard Marian Thomaiyar     }
280127748a8SRichard Marian Thomaiyar 
281127748a8SRichard Marian Thomaiyar     std::fill(authAlgo->userKey.data(),
282127748a8SRichard Marian Thomaiyar               authAlgo->userKey.data() + authAlgo->userKey.size(), 0);
283127748a8SRichard Marian Thomaiyar     std::copy_n(passwd.c_str(), passwd.size(), authAlgo->userKey.data());
28499b87849SRichard Marian Thomaiyar 
2858bb10b79STom Joseph     // Copy the Managed System Random Number to the Authentication Algorithm
2868bb10b79STom Joseph     std::copy_n(iter, cipher::rakp_auth::BMC_RANDOM_NUMBER_LEN,
2878bb10b79STom Joseph                 authAlgo->bmcRandomNum.begin());
2888bb10b79STom Joseph     std::advance(iter, cipher::rakp_auth::BMC_RANDOM_NUMBER_LEN);
2898bb10b79STom Joseph 
2908bb10b79STom Joseph     // Managed System GUID
29183029cb8STom Joseph     std::copy_n(cache::guid.data(), cache::guid.size(), iter);
2928bb10b79STom Joseph     std::advance(iter, BMC_GUID_LEN);
2938bb10b79STom Joseph 
2948bb10b79STom Joseph     // Requested Privilege Level
2958bb10b79STom Joseph     std::copy_n(&(request->req_max_privilege_level),
2968bb10b79STom Joseph                 sizeof(request->req_max_privilege_level), iter);
2978bb10b79STom Joseph     std::advance(iter, sizeof(request->req_max_privilege_level));
2988bb10b79STom Joseph 
2998bb10b79STom Joseph     // User Name Length Byte
3008bb10b79STom Joseph     std::copy_n(&(request->user_name_len), sizeof(request->user_name_len),
3018bb10b79STom Joseph                 iter);
30256527b93STom Joseph     std::advance(iter, sizeof(request->user_name_len));
30356527b93STom Joseph 
30456527b93STom Joseph     std::copy_n(session->userName.data(), session->userName.size(), iter);
3058bb10b79STom Joseph 
3068bb10b79STom Joseph     // Generate Key Exchange Authentication Code - RAKP2
3078bb10b79STom Joseph     auto output = authAlgo->generateHMAC(input);
3088bb10b79STom Joseph 
3098bb10b79STom Joseph     response->messageTag = request->messageTag;
3108bb10b79STom Joseph     response->rmcpStatusCode = static_cast<uint8_t>(RAKP_ReturnCode::NO_ERROR);
3118bb10b79STom Joseph     response->reserved = 0;
3128bb10b79STom Joseph     response->remoteConsoleSessionID = rcSessionID;
3138bb10b79STom Joseph 
3148bb10b79STom Joseph     // Copy Managed System Random Number to the Response
3158bb10b79STom Joseph     std::copy(authAlgo->bmcRandomNum.begin(), authAlgo->bmcRandomNum.end(),
3168bb10b79STom Joseph               response->managed_system_random_number);
3178bb10b79STom Joseph 
3188bb10b79STom Joseph     // Copy System GUID to the Response
3199e801a2bSVernon Mauery     std::copy_n(cache::guid.data(), cache::guid.size(),
32083029cb8STom Joseph                 response->managed_system_guid);
3218bb10b79STom Joseph 
3228bb10b79STom Joseph     // Insert the HMAC output into the payload
3238bb10b79STom Joseph     outPayload.insert(outPayload.end(), output.begin(), output.end());
3248bb10b79STom Joseph     return outPayload;
3258bb10b79STom Joseph }
3268bb10b79STom Joseph 
3278bb10b79STom Joseph } // namespace command
328