blob: b3d8dbda5872392c9933595c49999869ee7da206 [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
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700103 auto message = std::make_shared<Message>();
Tom Joseph4e57ada2016-08-10 06:51:12 -0500104
105 auto header = reinterpret_cast<SessionHeader_t*>(inPacket.data());
106
107 message->payloadType = PayloadType::IPMI;
Tom Joseph6a560762017-01-10 15:30:28 +0530108 message->bmcSessionID = endian::from_ipmi(header->sessId);
109 message->sessionSeqNum = endian::from_ipmi(header->sessSeqNum);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500110 message->isPacketEncrypted = false;
111 message->isPacketAuthenticated = false;
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +0300112 message->rmcpMsgClass =
113 static_cast<ClassOfMsg>(header->base.rmcp.classOfMsg);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500114
Zhikui Ren2b1edef2020-07-24 14:32:13 -0700115 // Confirm the number of data bytes received correlates to
116 // the packet length in the header
Vernon Mauerya71b1ba2021-06-08 15:53:46 -0700117 size_t payloadLen = header->payloadLength;
118 if ((payloadLen == 0) || (inPacket.size() < (sizeof(*header) + payloadLen)))
Zhikui Ren2b1edef2020-07-24 14:32:13 -0700119 {
120 throw std::runtime_error("Invalid data length");
121 }
122
Vernon Mauery9e801a22018-10-12 13:20:49 -0700123 (message->payload)
124 .assign(inPacket.data() + sizeof(SessionHeader_t),
125 inPacket.data() + sizeof(SessionHeader_t) + payloadLen);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500126
127 return message;
128}
129
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700130std::vector<uint8_t> flatten(std::shared_ptr<Message> outMessage,
Vernon Mauery224f36a2018-10-25 08:52:23 -0700131 std::shared_ptr<session::Session> session)
Tom Joseph4e57ada2016-08-10 06:51:12 -0500132{
133 std::vector<uint8_t> packet(sizeof(SessionHeader_t));
134
135 // Insert Session Header into the Packet
136 auto header = reinterpret_cast<SessionHeader_t*>(packet.data());
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +0300137 header->base.rmcp.version = parser::RMCP_VERSION;
138 header->base.rmcp.reserved = 0x00;
139 header->base.rmcp.rmcpSeqNum = parser::RMCP_SEQ;
140 header->base.rmcp.classOfMsg = static_cast<uint8_t>(ClassOfMsg::IPMI);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500141 header->base.format.formatType =
142 static_cast<uint8_t>(parser::SessionHeader::IPMI15);
143 header->sessSeqNum = 0;
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700144 header->sessId = endian::to_ipmi(outMessage->rcSessionID);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500145
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700146 header->payloadLength = static_cast<uint8_t>(outMessage->payload.size());
Tom Joseph4e57ada2016-08-10 06:51:12 -0500147
148 // Insert the Payload into the Packet
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700149 packet.insert(packet.end(), outMessage->payload.begin(),
150 outMessage->payload.end());
Tom Joseph4e57ada2016-08-10 06:51:12 -0500151
152 // Insert the Session Trailer
153 packet.resize(packet.size() + sizeof(SessionTrailer_t));
Vernon Mauery9e801a22018-10-12 13:20:49 -0700154 auto trailer =
155 reinterpret_cast<SessionTrailer_t*>(packet.data() + packet.size());
Tom Joseph4e57ada2016-08-10 06:51:12 -0500156 trailer->legacyPad = 0x00;
157
158 return packet;
159}
160
161} // namespace ipmi15parser
162
163namespace ipmi20parser
164{
165
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700166std::shared_ptr<Message> unflatten(std::vector<uint8_t>& inPacket)
Tom Joseph4e57ada2016-08-10 06:51:12 -0500167{
168 // Check if the packet has atleast the Session Header
169 if (inPacket.size() < sizeof(SessionHeader_t))
170 {
171 throw std::runtime_error("IPMI2.0 Session Header Missing");
172 }
173
Tom Joseph4e57ada2016-08-10 06:51:12 -0500174 auto header = reinterpret_cast<SessionHeader_t*>(inPacket.data());
175
Vernon Mauery1ab1c6b2021-06-08 15:54:41 -0700176 uint32_t sessionID = endian::from_ipmi(header->sessId);
177
178 auto session =
179 std::get<session::Manager&>(singletonPool).getSession(sessionID);
180 if (!session)
181 {
182 throw std::runtime_error("RMCP+ message from unknown session");
183 }
184
185 auto message = std::make_shared<Message>();
186
Vernon Mauery9e801a22018-10-12 13:20:49 -0700187 message->payloadType = static_cast<PayloadType>(header->payloadType & 0x3F);
Vernon Mauery1ab1c6b2021-06-08 15:54:41 -0700188 message->bmcSessionID = sessionID;
Tom Joseph6a560762017-01-10 15:30:28 +0530189 message->sessionSeqNum = endian::from_ipmi(header->sessSeqNum);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500190 message->isPacketEncrypted =
191 ((header->payloadType & PAYLOAD_ENCRYPT_MASK) ? true : false);
192 message->isPacketAuthenticated =
193 ((header->payloadType & PAYLOAD_AUTH_MASK) ? true : false);
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +0300194 message->rmcpMsgClass =
195 static_cast<ClassOfMsg>(header->base.rmcp.classOfMsg);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500196
Vernon Mauerya71b1ba2021-06-08 15:53:46 -0700197 // Confirm the number of data bytes received correlates to
198 // the packet length in the header
199 size_t payloadLen = endian::from_ipmi(header->payloadLength);
200 if ((payloadLen == 0) || (inPacket.size() < (sizeof(*header) + payloadLen)))
201 {
202 throw std::runtime_error("Invalid data length");
203 }
Tom Joseph4e57ada2016-08-10 06:51:12 -0500204
Vernon Mauery1ab1c6b2021-06-08 15:54:41 -0700205 bool integrityMismatch =
206 session->isIntegrityAlgoEnabled() && !message->isPacketAuthenticated;
207 bool encryptMismatch =
208 session->isCryptAlgoEnabled() && !message->isPacketEncrypted;
209
210 if (sessionID != session::sessionZero &&
211 (integrityMismatch || encryptMismatch))
212 {
213 throw std::runtime_error("unencrypted or unauthenticated message");
214 }
215
Tom Joseph5fa487c2017-01-20 12:42:39 +0530216 if (message->isPacketAuthenticated)
Tom Joseph64703f42017-01-10 17:03:48 +0530217 {
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700218 if (!(internal::verifyPacketIntegrity(inPacket, message, payloadLen)))
Tom Joseph64703f42017-01-10 17:03:48 +0530219 {
220 throw std::runtime_error("Packet Integrity check failed");
221 }
222 }
223
Tom Joseph78478a82017-01-26 14:24:29 +0530224 // Decrypt the payload if the payload is encrypted
225 if (message->isPacketEncrypted)
226 {
227 // Assign the decrypted payload to the IPMI Message
Vernon Mauery9e801a22018-10-12 13:20:49 -0700228 message->payload =
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700229 internal::decryptPayload(inPacket, message, payloadLen);
Tom Joseph78478a82017-01-26 14:24:29 +0530230 }
231 else
232 {
233 message->payload.assign(inPacket.begin() + sizeof(SessionHeader_t),
234 inPacket.begin() + sizeof(SessionHeader_t) +
Vernon Mauery9e801a22018-10-12 13:20:49 -0700235 payloadLen);
Tom Joseph78478a82017-01-26 14:24:29 +0530236 }
237
Tom Joseph4e57ada2016-08-10 06:51:12 -0500238 return message;
239}
240
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700241std::vector<uint8_t> flatten(std::shared_ptr<Message> outMessage,
Vernon Mauery224f36a2018-10-25 08:52:23 -0700242 std::shared_ptr<session::Session> session)
Tom Joseph4e57ada2016-08-10 06:51:12 -0500243{
244 std::vector<uint8_t> packet(sizeof(SessionHeader_t));
245
246 SessionHeader_t* header = reinterpret_cast<SessionHeader_t*>(packet.data());
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +0300247 header->base.rmcp.version = parser::RMCP_VERSION;
248 header->base.rmcp.reserved = 0x00;
249 header->base.rmcp.rmcpSeqNum = parser::RMCP_SEQ;
250 header->base.rmcp.classOfMsg = static_cast<uint8_t>(ClassOfMsg::IPMI);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500251 header->base.format.formatType =
252 static_cast<uint8_t>(parser::SessionHeader::IPMI20);
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700253 header->payloadType = static_cast<uint8_t>(outMessage->payloadType);
254 header->sessId = endian::to_ipmi(outMessage->rcSessionID);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500255
256 // Add session sequence number
257 internal::addSequenceNumber(packet, session);
258
Tom Joseph1404bca2017-01-26 14:17:02 +0530259 size_t payloadLen = 0;
260
Tom Joseph75362832017-01-26 15:17:04 +0530261 // Encrypt the payload if needed
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700262 if (outMessage->isPacketEncrypted)
Tom Joseph75362832017-01-26 15:17:04 +0530263 {
264 header->payloadType |= PAYLOAD_ENCRYPT_MASK;
265 auto cipherPayload = internal::encryptPayload(outMessage);
266 payloadLen = cipherPayload.size();
267 header->payloadLength = endian::to_ipmi<uint16_t>(cipherPayload.size());
268
269 // Insert the encrypted payload into the outgoing IPMI packet
270 packet.insert(packet.end(), cipherPayload.begin(), cipherPayload.end());
271 }
272 else
273 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700274 header->payloadLength =
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700275 endian::to_ipmi<uint16_t>(outMessage->payload.size());
276 payloadLen = outMessage->payload.size();
Tom Joseph75362832017-01-26 15:17:04 +0530277
278 // Insert the Payload into the Packet
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700279 packet.insert(packet.end(), outMessage->payload.begin(),
280 outMessage->payload.end());
Tom Joseph75362832017-01-26 15:17:04 +0530281 }
Tom Joseph4e57ada2016-08-10 06:51:12 -0500282
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700283 if (outMessage->isPacketAuthenticated)
Tom Joseph64703f42017-01-10 17:03:48 +0530284 {
Tom Josephb882dbb2019-02-09 23:13:48 +0530285 header = reinterpret_cast<SessionHeader_t*>(packet.data());
286 header->payloadType |= PAYLOAD_AUTH_MASK;
Tom Joseph1404bca2017-01-26 14:17:02 +0530287 internal::addIntegrityData(packet, outMessage, payloadLen);
Tom Joseph64703f42017-01-10 17:03:48 +0530288 }
289
Tom Joseph4e57ada2016-08-10 06:51:12 -0500290 return packet;
291}
292
293namespace internal
294{
295
Vernon Mauery224f36a2018-10-25 08:52:23 -0700296void addSequenceNumber(std::vector<uint8_t>& packet,
297 std::shared_ptr<session::Session> session)
Tom Joseph4e57ada2016-08-10 06:51:12 -0500298{
299 SessionHeader_t* header = reinterpret_cast<SessionHeader_t*>(packet.data());
300
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +0530301 if (header->sessId == session::sessionZero)
Tom Joseph4e57ada2016-08-10 06:51:12 -0500302 {
303 header->sessSeqNum = 0x00;
304 }
305 else
306 {
Vernon Mauery224f36a2018-10-25 08:52:23 -0700307 auto seqNum = session->sequenceNums.increment();
Tom Joseph6a560762017-01-10 15:30:28 +0530308 header->sessSeqNum = endian::to_ipmi(seqNum);
Tom Joseph4e57ada2016-08-10 06:51:12 -0500309 }
310}
311
Tom Joseph64703f42017-01-10 17:03:48 +0530312bool verifyPacketIntegrity(const std::vector<uint8_t>& packet,
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700313 const std::shared_ptr<Message> message,
314 size_t payloadLen)
Tom Joseph64703f42017-01-10 17:03:48 +0530315{
Tom Joseph64703f42017-01-10 17:03:48 +0530316 /*
317 * Padding bytes are added to cause the number of bytes in the data range
318 * covered by the AuthCode(Integrity Data) field to be a multiple of 4 bytes
319 * .If present each integrity Pad byte is set to FFh. The following logic
320 * calculates the number of padding bytes added in the IPMI packet.
321 */
Tom Joseph5a2d3ce2017-02-01 20:18:37 +0530322 auto paddingLen = 4 - ((payloadLen + 2) & 3);
Tom Joseph64703f42017-01-10 17:03:48 +0530323
324 auto sessTrailerPos = sizeof(SessionHeader_t) + payloadLen + paddingLen;
325
Zhikui Ren2b1edef2020-07-24 14:32:13 -0700326 // verify packet size includes trailer struct starts at sessTrailerPos
327 if (packet.size() < (sessTrailerPos + sizeof(SessionTrailer_t)))
328 {
329 return false;
330 }
331
Vernon Mauery9e801a22018-10-12 13:20:49 -0700332 auto trailer = reinterpret_cast<const SessionTrailer_t*>(packet.data() +
333 sessTrailerPos);
Tom Joseph64703f42017-01-10 17:03:48 +0530334
335 // Check trailer->padLength against paddingLen, both should match up,
336 // return false if the lengths don't match
Tom Joseph5fa487c2017-01-20 12:42:39 +0530337 if (trailer->padLength != paddingLen)
Tom Joseph64703f42017-01-10 17:03:48 +0530338 {
339 return false;
340 }
341
Vernon Maueryae1fda42018-10-15 12:55:34 -0700342 auto session = std::get<session::Manager&>(singletonPool)
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700343 .getSession(message->bmcSessionID);
Tom Joseph64703f42017-01-10 17:03:48 +0530344
345 auto integrityAlgo = session->getIntegrityAlgo();
346
347 // Check if Integrity data length is as expected, check integrity data
348 // length is same as the length expected for the Integrity Algorithm that
349 // was negotiated during the session open process.
Tom Joseph5fa487c2017-01-20 12:42:39 +0530350 if ((packet.size() - sessTrailerPos - sizeof(SessionTrailer_t)) !=
Vernon Mauery9e801a22018-10-12 13:20:49 -0700351 integrityAlgo->authCodeLength)
Tom Joseph64703f42017-01-10 17:03:48 +0530352 {
353 return false;
354 }
355
356 auto integrityIter = packet.cbegin();
357 std::advance(integrityIter, sessTrailerPos + sizeof(SessionTrailer_t));
358
359 // The integrity data is calculated from the AuthType/Format field up to and
360 // including the field that immediately precedes the AuthCode field itself.
361 size_t length = packet.size() - integrityAlgo->authCodeLength -
362 message::parser::RMCP_SESSION_HEADER_SIZE;
363
364 return integrityAlgo->verifyIntegrityData(packet, length, integrityIter);
365}
366
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700367void addIntegrityData(std::vector<uint8_t>& packet,
368 const std::shared_ptr<Message> message, size_t payloadLen)
Tom Joseph64703f42017-01-10 17:03:48 +0530369{
Tom Joseph64703f42017-01-10 17:03:48 +0530370 // The following logic calculates the number of padding bytes to be added to
371 // IPMI packet. If needed each integrity Pad byte is set to FFh.
Tom Joseph5a2d3ce2017-02-01 20:18:37 +0530372 auto paddingLen = 4 - ((payloadLen + 2) & 3);
Tom Joseph64703f42017-01-10 17:03:48 +0530373 packet.insert(packet.end(), paddingLen, 0xFF);
374
375 packet.resize(packet.size() + sizeof(SessionTrailer_t));
376
Vernon Mauery9e801a22018-10-12 13:20:49 -0700377 auto trailer = reinterpret_cast<SessionTrailer_t*>(
378 packet.data() + packet.size() - sizeof(SessionTrailer_t));
Tom Joseph64703f42017-01-10 17:03:48 +0530379
380 trailer->padLength = paddingLen;
381 trailer->nextHeader = parser::RMCP_MESSAGE_CLASS_IPMI;
382
Vernon Maueryae1fda42018-10-15 12:55:34 -0700383 auto session = std::get<session::Manager&>(singletonPool)
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700384 .getSession(message->bmcSessionID);
Tom Joseph64703f42017-01-10 17:03:48 +0530385
Vernon Mauery9e801a22018-10-12 13:20:49 -0700386 auto integrityData =
387 session->getIntegrityAlgo()->generateIntegrityData(packet);
Tom Joseph64703f42017-01-10 17:03:48 +0530388
389 packet.insert(packet.end(), integrityData.begin(), integrityData.end());
390}
391
Tom Joseph78478a82017-01-26 14:24:29 +0530392std::vector<uint8_t> decryptPayload(const std::vector<uint8_t>& packet,
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700393 const std::shared_ptr<Message> message,
394 size_t payloadLen)
Tom Joseph78478a82017-01-26 14:24:29 +0530395{
Vernon Maueryae1fda42018-10-15 12:55:34 -0700396 auto session = std::get<session::Manager&>(singletonPool)
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700397 .getSession(message->bmcSessionID);
Tom Joseph78478a82017-01-26 14:24:29 +0530398
Vernon Mauery9e801a22018-10-12 13:20:49 -0700399 return session->getCryptAlgo()->decryptPayload(
400 packet, sizeof(SessionHeader_t), payloadLen);
Tom Joseph78478a82017-01-26 14:24:29 +0530401}
402
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700403std::vector<uint8_t> encryptPayload(std::shared_ptr<Message> message)
Tom Joseph75362832017-01-26 15:17:04 +0530404{
Vernon Maueryae1fda42018-10-15 12:55:34 -0700405 auto session = std::get<session::Manager&>(singletonPool)
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700406 .getSession(message->bmcSessionID);
Tom Joseph75362832017-01-26 15:17:04 +0530407
Vernon Maueryd999ffc2018-10-25 09:16:05 -0700408 return session->getCryptAlgo()->encryptPayload(message->payload);
Tom Joseph75362832017-01-26 15:17:04 +0530409}
410
Tom Joseph4e57ada2016-08-10 06:51:12 -0500411} // namespace internal
412
413} // namespace ipmi20parser
414
Kirill Pakhomovde7dd5c2021-02-27 18:45:22 +0300415#ifdef RMCP_PING
416namespace asfparser
417{
418std::shared_ptr<Message> unflatten(std::vector<uint8_t>& inPacket)
419{
420 auto message = std::make_shared<Message>();
421
422 auto header = reinterpret_cast<AsfMessagePing_t*>(inPacket.data());
423
424 message->payloadType = PayloadType::IPMI;
425 message->rmcpMsgClass = ClassOfMsg::ASF;
426 message->asfMsgTag = header->msgTag;
427
428 return message;
429}
430
431std::vector<uint8_t> flatten(uint8_t asfMsgTag)
432{
433 std::vector<uint8_t> packet(sizeof(AsfMessagePong_t));
434
435 // Insert RMCP header into the Packet
436 auto header = reinterpret_cast<AsfMessagePong_t*>(packet.data());
437 header->ping.rmcp.version = parser::RMCP_VERSION;
438 header->ping.rmcp.reserved = 0x00;
439 header->ping.rmcp.rmcpSeqNum = parser::RMCP_SEQ;
440 header->ping.rmcp.classOfMsg = static_cast<uint8_t>(ClassOfMsg::ASF);
441
442 // No OEM-specific capabilities exist, therefore the second
443 // IANA Enterprise Number contains the same IANA(4542)
444 header->ping.iana = header->iana = endian::to_ipmi(parser::ASF_IANA);
445 header->ping.msgType = static_cast<uint8_t>(RmcpMsgType::PONG);
446 header->ping.msgTag = asfMsgTag;
447 header->ping.reserved = 0x00;
448 header->ping.dataLen =
449 parser::RMCP_ASF_PONG_DATA_LEN; // as per spec 13.2.4,
450
451 header->iana = parser::ASF_IANA;
452 header->oemDefined = 0x00;
453 header->suppEntities = parser::ASF_SUPP_ENT;
454 header->suppInteract = parser::ASF_SUPP_INT;
455 header->reserved1 = 0x00;
456 header->reserved2 = 0x00;
457
458 return packet;
459}
460
461} // namespace asfparser
462#endif // RMCP_PING
463
Tom Joseph4e57ada2016-08-10 06:51:12 -0500464} // namespace message