blob: 4271c13d55074939e0b979720fe6087976a4869f [file] [log] [blame]
Tom Joseph4e57ada2016-08-10 06:51:12 -05001#include "message_parsers.hpp"
2
Tom Joseph4e57ada2016-08-10 06:51:12 -05003#include "endian.hpp"
4#include "main.hpp"
5#include "message.hpp"
6#include "sessions_manager.hpp"
7
Vernon Mauery9e801a22018-10-12 13:20:49 -07008#include <memory>
9
Tom Joseph4e57ada2016-08-10 06:51:12 -050010namespace message
11{
12
13namespace parser
14{
15
Vernon Maueryd999ffc2018-10-25 09:16:05 -070016std::tuple<std::shared_ptr<Message>, SessionHeader>
Vernon Mauery9e801a22018-10-12 13:20:49 -070017 unflatten(std::vector<uint8_t>& inPacket)
Tom Joseph4e57ada2016-08-10 06:51:12 -050018{
19 // Check if the packet has atleast the size of the RMCP Header
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +030020 if (inPacket.size() < sizeof(RmcpHeader_t))
Tom Joseph4e57ada2016-08-10 06:51:12 -050021 {
22 throw std::runtime_error("RMCP Header missing");
23 }
24
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +030025 auto rmcpHeaderPtr = reinterpret_cast<RmcpHeader_t*>(inPacket.data());
Tom Joseph4e57ada2016-08-10 06:51:12 -050026
27 // Verify if the fields in the RMCP header conforms to the specification
28 if ((rmcpHeaderPtr->version != RMCP_VERSION) ||
29 (rmcpHeaderPtr->rmcpSeqNum != RMCP_SEQ) ||
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +030030 (rmcpHeaderPtr->classOfMsg < static_cast<uint8_t>(ClassOfMsg::ASF) &&
31 rmcpHeaderPtr->classOfMsg > static_cast<uint8_t>(ClassOfMsg::OEM)))
Tom Joseph4e57ada2016-08-10 06:51:12 -050032 {
33 throw std::runtime_error("RMCP Header is invalid");
34 }
35
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +030036 if (rmcpHeaderPtr->classOfMsg == static_cast<uint8_t>(ClassOfMsg::ASF))
37 {
38#ifndef RMCP_PING
39 throw std::runtime_error("RMCP Ping is not supported");
40#else
41 return std::make_tuple(asfparser::unflatten(inPacket),
42 SessionHeader::IPMI15);
43#endif // RMCP_PING
44 }
45
46 auto sessionHeaderPtr = reinterpret_cast<BasicHeader_t*>(inPacket.data());
47
Tom Joseph4e57ada2016-08-10 06:51:12 -050048 // Read the Session Header and invoke the parser corresponding to the
49 // header type
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +030050 switch (static_cast<SessionHeader>(sessionHeaderPtr->format.formatType))
Tom Joseph4e57ada2016-08-10 06:51:12 -050051 {
52 case SessionHeader::IPMI15:
53 {
54 return std::make_tuple(ipmi15parser::unflatten(inPacket),
55 SessionHeader::IPMI15);
56 }
57 case SessionHeader::IPMI20:
58 {
59 return std::make_tuple(ipmi20parser::unflatten(inPacket),
60 SessionHeader::IPMI20);
61 }
62 default:
63 {
64 throw std::runtime_error("Invalid Session Header");
65 }
66 }
67}
68
Vernon Maueryd999ffc2018-10-25 09:16:05 -070069std::vector<uint8_t> flatten(std::shared_ptr<Message> outMessage,
Vernon Mauery224f36a2018-10-25 08:52:23 -070070 SessionHeader authType,
71 std::shared_ptr<session::Session> session)
Tom Joseph4e57ada2016-08-10 06:51:12 -050072{
73 // Call the flatten routine based on the header type
74 switch (authType)
75 {
76 case SessionHeader::IPMI15:
77 {
78 return ipmi15parser::flatten(outMessage, session);
79 }
80 case SessionHeader::IPMI20:
81 {
82 return ipmi20parser::flatten(outMessage, session);
83 }
84 default:
85 {
86 return {};
87 }
88 }
89}
90
91} // namespace parser
92
93namespace ipmi15parser
94{
95
Vernon Maueryd999ffc2018-10-25 09:16:05 -070096std::shared_ptr<Message> unflatten(std::vector<uint8_t>& inPacket)
Tom Joseph4e57ada2016-08-10 06:51:12 -050097{
Tom Joseph4e57ada2016-08-10 06:51:12 -050098 if (inPacket.size() < sizeof(SessionHeader_t))
99 {
100 throw std::runtime_error("IPMI1.5 Session Header Missing");
101 }
102
Tom Joseph4e57ada2016-08-10 06:51:12 -0500103 auto header = reinterpret_cast<SessionHeader_t*>(inPacket.data());
104
Vernon Mauery779e7e12021-06-08 16:24:45 -0700105 uint32_t sessionID = endian::from_ipmi(header->sessId);
106 if (sessionID != session::sessionZero)
107 {
108 throw std::runtime_error("IPMI1.5 session packets are unsupported");
109 }
110
111 auto message = std::make_shared<Message>();
112
Tom Joseph4e57ada2016-08-10 06:51:12 -0500113 message->payloadType = PayloadType::IPMI;
Vernon Mauery779e7e12021-06-08 16:24:45 -0700114 message->bmcSessionID = session::sessionZero;
Tom Joseph6a560762017-01-10 15:30:28 +0530115 message->sessionSeqNum = endian::from_ipmi(header->sessSeqNum);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500116 message->isPacketEncrypted = false;
117 message->isPacketAuthenticated = false;
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +0300118 message->rmcpMsgClass =
119 static_cast<ClassOfMsg>(header->base.rmcp.classOfMsg);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500120
Zhikui Ren2b1edef2020-07-24 14:32:13 -0700121 // Confirm the number of data bytes received correlates to
122 // the packet length in the header
Vernon Mauerya71b1ba2021-06-08 15:53:46 -0700123 size_t payloadLen = header->payloadLength;
124 if ((payloadLen == 0) || (inPacket.size() < (sizeof(*header) + payloadLen)))
Zhikui Ren2b1edef2020-07-24 14:32:13 -0700125 {
126 throw std::runtime_error("Invalid data length");
127 }
128
Vernon Mauery9e801a22018-10-12 13:20:49 -0700129 (message->payload)
130 .assign(inPacket.data() + sizeof(SessionHeader_t),
131 inPacket.data() + sizeof(SessionHeader_t) + payloadLen);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500132
133 return message;
134}
135
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700136std::vector<uint8_t> flatten(std::shared_ptr<Message> outMessage,
Vernon Mauery224f36a2018-10-25 08:52:23 -0700137 std::shared_ptr<session::Session> session)
Tom Joseph4e57ada2016-08-10 06:51:12 -0500138{
139 std::vector<uint8_t> packet(sizeof(SessionHeader_t));
140
141 // Insert Session Header into the Packet
142 auto header = reinterpret_cast<SessionHeader_t*>(packet.data());
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +0300143 header->base.rmcp.version = parser::RMCP_VERSION;
144 header->base.rmcp.reserved = 0x00;
145 header->base.rmcp.rmcpSeqNum = parser::RMCP_SEQ;
146 header->base.rmcp.classOfMsg = static_cast<uint8_t>(ClassOfMsg::IPMI);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500147 header->base.format.formatType =
148 static_cast<uint8_t>(parser::SessionHeader::IPMI15);
149 header->sessSeqNum = 0;
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700150 header->sessId = endian::to_ipmi(outMessage->rcSessionID);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500151
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700152 header->payloadLength = static_cast<uint8_t>(outMessage->payload.size());
Tom Joseph4e57ada2016-08-10 06:51:12 -0500153
154 // Insert the Payload into the Packet
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700155 packet.insert(packet.end(), outMessage->payload.begin(),
156 outMessage->payload.end());
Tom Joseph4e57ada2016-08-10 06:51:12 -0500157
158 // Insert the Session Trailer
159 packet.resize(packet.size() + sizeof(SessionTrailer_t));
Vernon Mauery9e801a22018-10-12 13:20:49 -0700160 auto trailer =
161 reinterpret_cast<SessionTrailer_t*>(packet.data() + packet.size());
Tom Joseph4e57ada2016-08-10 06:51:12 -0500162 trailer->legacyPad = 0x00;
163
164 return packet;
165}
166
167} // namespace ipmi15parser
168
169namespace ipmi20parser
170{
171
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700172std::shared_ptr<Message> unflatten(std::vector<uint8_t>& inPacket)
Tom Joseph4e57ada2016-08-10 06:51:12 -0500173{
174 // Check if the packet has atleast the Session Header
175 if (inPacket.size() < sizeof(SessionHeader_t))
176 {
177 throw std::runtime_error("IPMI2.0 Session Header Missing");
178 }
179
Tom Joseph4e57ada2016-08-10 06:51:12 -0500180 auto header = reinterpret_cast<SessionHeader_t*>(inPacket.data());
181
Vernon Mauery1ab1c6b2021-06-08 15:54:41 -0700182 uint32_t sessionID = endian::from_ipmi(header->sessId);
183
Vernon Mauery2085ae02021-06-10 11:51:00 -0700184 auto session = session::Manager::get().getSession(sessionID);
Vernon Mauery1ab1c6b2021-06-08 15:54:41 -0700185 if (!session)
186 {
187 throw std::runtime_error("RMCP+ message from unknown session");
188 }
189
190 auto message = std::make_shared<Message>();
191
Vernon Mauery9e801a22018-10-12 13:20:49 -0700192 message->payloadType = static_cast<PayloadType>(header->payloadType & 0x3F);
Vernon Mauery1ab1c6b2021-06-08 15:54:41 -0700193 message->bmcSessionID = sessionID;
Tom Joseph6a560762017-01-10 15:30:28 +0530194 message->sessionSeqNum = endian::from_ipmi(header->sessSeqNum);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500195 message->isPacketEncrypted =
196 ((header->payloadType & PAYLOAD_ENCRYPT_MASK) ? true : false);
197 message->isPacketAuthenticated =
198 ((header->payloadType & PAYLOAD_AUTH_MASK) ? true : false);
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +0300199 message->rmcpMsgClass =
200 static_cast<ClassOfMsg>(header->base.rmcp.classOfMsg);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500201
Vernon Mauerya71b1ba2021-06-08 15:53:46 -0700202 // Confirm the number of data bytes received correlates to
203 // the packet length in the header
204 size_t payloadLen = endian::from_ipmi(header->payloadLength);
205 if ((payloadLen == 0) || (inPacket.size() < (sizeof(*header) + payloadLen)))
206 {
207 throw std::runtime_error("Invalid data length");
208 }
Tom Joseph4e57ada2016-08-10 06:51:12 -0500209
Vernon Mauery1ab1c6b2021-06-08 15:54:41 -0700210 bool integrityMismatch =
211 session->isIntegrityAlgoEnabled() && !message->isPacketAuthenticated;
212 bool encryptMismatch =
213 session->isCryptAlgoEnabled() && !message->isPacketEncrypted;
214
215 if (sessionID != session::sessionZero &&
216 (integrityMismatch || encryptMismatch))
217 {
218 throw std::runtime_error("unencrypted or unauthenticated message");
219 }
220
Tom Joseph5fa487c2017-01-20 12:42:39 +0530221 if (message->isPacketAuthenticated)
Tom Joseph64703f42017-01-10 17:03:48 +0530222 {
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700223 if (!(internal::verifyPacketIntegrity(inPacket, message, payloadLen)))
Tom Joseph64703f42017-01-10 17:03:48 +0530224 {
225 throw std::runtime_error("Packet Integrity check failed");
226 }
227 }
228
Tom Joseph78478a82017-01-26 14:24:29 +0530229 // Decrypt the payload if the payload is encrypted
230 if (message->isPacketEncrypted)
231 {
232 // Assign the decrypted payload to the IPMI Message
Vernon Mauery9e801a22018-10-12 13:20:49 -0700233 message->payload =
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700234 internal::decryptPayload(inPacket, message, payloadLen);
Tom Joseph78478a82017-01-26 14:24:29 +0530235 }
236 else
237 {
238 message->payload.assign(inPacket.begin() + sizeof(SessionHeader_t),
239 inPacket.begin() + sizeof(SessionHeader_t) +
Vernon Mauery9e801a22018-10-12 13:20:49 -0700240 payloadLen);
Tom Joseph78478a82017-01-26 14:24:29 +0530241 }
242
Tom Joseph4e57ada2016-08-10 06:51:12 -0500243 return message;
244}
245
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700246std::vector<uint8_t> flatten(std::shared_ptr<Message> outMessage,
Vernon Mauery224f36a2018-10-25 08:52:23 -0700247 std::shared_ptr<session::Session> session)
Tom Joseph4e57ada2016-08-10 06:51:12 -0500248{
249 std::vector<uint8_t> packet(sizeof(SessionHeader_t));
250
251 SessionHeader_t* header = reinterpret_cast<SessionHeader_t*>(packet.data());
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +0300252 header->base.rmcp.version = parser::RMCP_VERSION;
253 header->base.rmcp.reserved = 0x00;
254 header->base.rmcp.rmcpSeqNum = parser::RMCP_SEQ;
255 header->base.rmcp.classOfMsg = static_cast<uint8_t>(ClassOfMsg::IPMI);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500256 header->base.format.formatType =
257 static_cast<uint8_t>(parser::SessionHeader::IPMI20);
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700258 header->payloadType = static_cast<uint8_t>(outMessage->payloadType);
259 header->sessId = endian::to_ipmi(outMessage->rcSessionID);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500260
261 // Add session sequence number
262 internal::addSequenceNumber(packet, session);
263
Tom Joseph1404bca2017-01-26 14:17:02 +0530264 size_t payloadLen = 0;
265
Tom Joseph75362832017-01-26 15:17:04 +0530266 // Encrypt the payload if needed
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700267 if (outMessage->isPacketEncrypted)
Tom Joseph75362832017-01-26 15:17:04 +0530268 {
269 header->payloadType |= PAYLOAD_ENCRYPT_MASK;
270 auto cipherPayload = internal::encryptPayload(outMessage);
271 payloadLen = cipherPayload.size();
272 header->payloadLength = endian::to_ipmi<uint16_t>(cipherPayload.size());
273
274 // Insert the encrypted payload into the outgoing IPMI packet
275 packet.insert(packet.end(), cipherPayload.begin(), cipherPayload.end());
276 }
277 else
278 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700279 header->payloadLength =
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700280 endian::to_ipmi<uint16_t>(outMessage->payload.size());
281 payloadLen = outMessage->payload.size();
Tom Joseph75362832017-01-26 15:17:04 +0530282
283 // Insert the Payload into the Packet
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700284 packet.insert(packet.end(), outMessage->payload.begin(),
285 outMessage->payload.end());
Tom Joseph75362832017-01-26 15:17:04 +0530286 }
Tom Joseph4e57ada2016-08-10 06:51:12 -0500287
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700288 if (outMessage->isPacketAuthenticated)
Tom Joseph64703f42017-01-10 17:03:48 +0530289 {
Tom Josephb882dbb2019-02-09 23:13:48 +0530290 header = reinterpret_cast<SessionHeader_t*>(packet.data());
291 header->payloadType |= PAYLOAD_AUTH_MASK;
Tom Joseph1404bca2017-01-26 14:17:02 +0530292 internal::addIntegrityData(packet, outMessage, payloadLen);
Tom Joseph64703f42017-01-10 17:03:48 +0530293 }
294
Tom Joseph4e57ada2016-08-10 06:51:12 -0500295 return packet;
296}
297
298namespace internal
299{
300
Vernon Mauery224f36a2018-10-25 08:52:23 -0700301void addSequenceNumber(std::vector<uint8_t>& packet,
302 std::shared_ptr<session::Session> session)
Tom Joseph4e57ada2016-08-10 06:51:12 -0500303{
304 SessionHeader_t* header = reinterpret_cast<SessionHeader_t*>(packet.data());
305
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +0530306 if (header->sessId == session::sessionZero)
Tom Joseph4e57ada2016-08-10 06:51:12 -0500307 {
308 header->sessSeqNum = 0x00;
309 }
310 else
311 {
Vernon Mauery224f36a2018-10-25 08:52:23 -0700312 auto seqNum = session->sequenceNums.increment();
Tom Joseph6a560762017-01-10 15:30:28 +0530313 header->sessSeqNum = endian::to_ipmi(seqNum);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500314 }
315}
316
Tom Joseph64703f42017-01-10 17:03:48 +0530317bool verifyPacketIntegrity(const std::vector<uint8_t>& packet,
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700318 const std::shared_ptr<Message> message,
319 size_t payloadLen)
Tom Joseph64703f42017-01-10 17:03:48 +0530320{
Tom Joseph64703f42017-01-10 17:03:48 +0530321 /*
322 * Padding bytes are added to cause the number of bytes in the data range
323 * covered by the AuthCode(Integrity Data) field to be a multiple of 4 bytes
324 * .If present each integrity Pad byte is set to FFh. The following logic
325 * calculates the number of padding bytes added in the IPMI packet.
326 */
Tom Joseph5a2d3ce2017-02-01 20:18:37 +0530327 auto paddingLen = 4 - ((payloadLen + 2) & 3);
Tom Joseph64703f42017-01-10 17:03:48 +0530328
329 auto sessTrailerPos = sizeof(SessionHeader_t) + payloadLen + paddingLen;
330
Zhikui Ren2b1edef2020-07-24 14:32:13 -0700331 // verify packet size includes trailer struct starts at sessTrailerPos
332 if (packet.size() < (sessTrailerPos + sizeof(SessionTrailer_t)))
333 {
334 return false;
335 }
336
Vernon Mauery9e801a22018-10-12 13:20:49 -0700337 auto trailer = reinterpret_cast<const SessionTrailer_t*>(packet.data() +
338 sessTrailerPos);
Tom Joseph64703f42017-01-10 17:03:48 +0530339
340 // Check trailer->padLength against paddingLen, both should match up,
341 // return false if the lengths don't match
Tom Joseph5fa487c2017-01-20 12:42:39 +0530342 if (trailer->padLength != paddingLen)
Tom Joseph64703f42017-01-10 17:03:48 +0530343 {
344 return false;
345 }
346
Vernon Mauery2085ae02021-06-10 11:51:00 -0700347 auto session = session::Manager::get().getSession(message->bmcSessionID);
Tom Joseph64703f42017-01-10 17:03:48 +0530348
349 auto integrityAlgo = session->getIntegrityAlgo();
350
351 // Check if Integrity data length is as expected, check integrity data
352 // length is same as the length expected for the Integrity Algorithm that
353 // was negotiated during the session open process.
Tom Joseph5fa487c2017-01-20 12:42:39 +0530354 if ((packet.size() - sessTrailerPos - sizeof(SessionTrailer_t)) !=
Vernon Mauery9e801a22018-10-12 13:20:49 -0700355 integrityAlgo->authCodeLength)
Tom Joseph64703f42017-01-10 17:03:48 +0530356 {
357 return false;
358 }
359
360 auto integrityIter = packet.cbegin();
361 std::advance(integrityIter, sessTrailerPos + sizeof(SessionTrailer_t));
362
363 // The integrity data is calculated from the AuthType/Format field up to and
364 // including the field that immediately precedes the AuthCode field itself.
365 size_t length = packet.size() - integrityAlgo->authCodeLength -
366 message::parser::RMCP_SESSION_HEADER_SIZE;
367
368 return integrityAlgo->verifyIntegrityData(packet, length, integrityIter);
369}
370
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700371void addIntegrityData(std::vector<uint8_t>& packet,
372 const std::shared_ptr<Message> message, size_t payloadLen)
Tom Joseph64703f42017-01-10 17:03:48 +0530373{
Tom Joseph64703f42017-01-10 17:03:48 +0530374 // The following logic calculates the number of padding bytes to be added to
375 // IPMI packet. If needed each integrity Pad byte is set to FFh.
Tom Joseph5a2d3ce2017-02-01 20:18:37 +0530376 auto paddingLen = 4 - ((payloadLen + 2) & 3);
Tom Joseph64703f42017-01-10 17:03:48 +0530377 packet.insert(packet.end(), paddingLen, 0xFF);
378
379 packet.resize(packet.size() + sizeof(SessionTrailer_t));
380
Vernon Mauery9e801a22018-10-12 13:20:49 -0700381 auto trailer = reinterpret_cast<SessionTrailer_t*>(
382 packet.data() + packet.size() - sizeof(SessionTrailer_t));
Tom Joseph64703f42017-01-10 17:03:48 +0530383
384 trailer->padLength = paddingLen;
385 trailer->nextHeader = parser::RMCP_MESSAGE_CLASS_IPMI;
386
Vernon Mauery2085ae02021-06-10 11:51:00 -0700387 auto session = session::Manager::get().getSession(message->bmcSessionID);
Tom Joseph64703f42017-01-10 17:03:48 +0530388
Vernon Mauery9e801a22018-10-12 13:20:49 -0700389 auto integrityData =
390 session->getIntegrityAlgo()->generateIntegrityData(packet);
Tom Joseph64703f42017-01-10 17:03:48 +0530391
392 packet.insert(packet.end(), integrityData.begin(), integrityData.end());
393}
394
Tom Joseph78478a82017-01-26 14:24:29 +0530395std::vector<uint8_t> decryptPayload(const std::vector<uint8_t>& packet,
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700396 const std::shared_ptr<Message> message,
397 size_t payloadLen)
Tom Joseph78478a82017-01-26 14:24:29 +0530398{
Vernon Mauery2085ae02021-06-10 11:51:00 -0700399 auto session = session::Manager::get().getSession(message->bmcSessionID);
Tom Joseph78478a82017-01-26 14:24:29 +0530400
Vernon Mauery9e801a22018-10-12 13:20:49 -0700401 return session->getCryptAlgo()->decryptPayload(
402 packet, sizeof(SessionHeader_t), payloadLen);
Tom Joseph78478a82017-01-26 14:24:29 +0530403}
404
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700405std::vector<uint8_t> encryptPayload(std::shared_ptr<Message> message)
Tom Joseph75362832017-01-26 15:17:04 +0530406{
Vernon Mauery2085ae02021-06-10 11:51:00 -0700407 auto session = session::Manager::get().getSession(message->bmcSessionID);
Tom Joseph75362832017-01-26 15:17:04 +0530408
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700409 return session->getCryptAlgo()->encryptPayload(message->payload);
Tom Joseph75362832017-01-26 15:17:04 +0530410}
411
Tom Joseph4e57ada2016-08-10 06:51:12 -0500412} // namespace internal
413
414} // namespace ipmi20parser
415
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +0300416#ifdef RMCP_PING
417namespace asfparser
418{
419std::shared_ptr<Message> unflatten(std::vector<uint8_t>& inPacket)
420{
421 auto message = std::make_shared<Message>();
422
423 auto header = reinterpret_cast<AsfMessagePing_t*>(inPacket.data());
424
425 message->payloadType = PayloadType::IPMI;
426 message->rmcpMsgClass = ClassOfMsg::ASF;
427 message->asfMsgTag = header->msgTag;
428
429 return message;
430}
431
432std::vector<uint8_t> flatten(uint8_t asfMsgTag)
433{
434 std::vector<uint8_t> packet(sizeof(AsfMessagePong_t));
435
436 // Insert RMCP header into the Packet
437 auto header = reinterpret_cast<AsfMessagePong_t*>(packet.data());
438 header->ping.rmcp.version = parser::RMCP_VERSION;
439 header->ping.rmcp.reserved = 0x00;
440 header->ping.rmcp.rmcpSeqNum = parser::RMCP_SEQ;
441 header->ping.rmcp.classOfMsg = static_cast<uint8_t>(ClassOfMsg::ASF);
442
443 // No OEM-specific capabilities exist, therefore the second
444 // IANA Enterprise Number contains the same IANA(4542)
445 header->ping.iana = header->iana = endian::to_ipmi(parser::ASF_IANA);
446 header->ping.msgType = static_cast<uint8_t>(RmcpMsgType::PONG);
447 header->ping.msgTag = asfMsgTag;
448 header->ping.reserved = 0x00;
449 header->ping.dataLen =
450 parser::RMCP_ASF_PONG_DATA_LEN; // as per spec 13.2.4,
451
452 header->iana = parser::ASF_IANA;
453 header->oemDefined = 0x00;
454 header->suppEntities = parser::ASF_SUPP_ENT;
455 header->suppInteract = parser::ASF_SUPP_INT;
456 header->reserved1 = 0x00;
457 header->reserved2 = 0x00;
458
459 return packet;
460}
461
462} // namespace asfparser
463#endif // RMCP_PING
464
Tom Joseph4e57ada2016-08-10 06:51:12 -0500465} // namespace message