| // Copyright 2024 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "dbus_mock.hpp" |
| #include "hoth_util.hpp" |
| #include "hoth_util_impl.hpp" |
| |
| #include <xyz/openbmc_project/Control/Hoth/error.hpp> |
| |
| #include <algorithm> |
| #include <cstdint> |
| #include <numeric> |
| #include <vector> |
| |
| #include <gmock/gmock.h> |
| #include <gtest/gtest.h> |
| |
| using namespace ::testing; |
| using CommandFailure = |
| sdbusplus::xyz::openbmc_project::Control::Hoth::Error::CommandFailure; |
| using ResponseFailure = |
| sdbusplus::xyz::openbmc_project::Control::Hoth::Error::ResponseFailure; |
| |
| namespace ipmi_hoth |
| { |
| |
| using namespace internal; |
| |
| class HothUtilTest : public ::testing::Test |
| { |
| protected: |
| HothUtilTest() : hothUtil(std::make_unique<HothUtilImpl>(HothUtilImpl())) {} |
| |
| std::unique_ptr<HothUtil> hothUtil; |
| }; |
| |
| TEST_F(HothUtilTest, Checksum) |
| { |
| uint8_t header[] = {1, 3, 5, 7}; |
| uint8_t body[] = {2, 4, 6, 8}; |
| |
| // (1 + 3 + 5 + 7) + (2 + 4 + 6 + 8) = 36 |
| EXPECT_EQ(36, HothUtil::calculateChecksum(header, body)); |
| |
| // Now test what happens if the sum exceeds 256. |
| body[0] = 200; |
| body[1] = 202; |
| |
| // (1 + 3 + 5 + 7) + (200 + 202 + 6 + 8) = 432 |
| // 432 % 256 = 176 |
| EXPECT_EQ(176, HothUtil::calculateChecksum(header, body)); |
| } |
| |
| TEST_F(HothUtilTest, WrapECSKMHSSRequest) |
| { |
| std::vector<uint8_t> request(15); |
| std::generate(request.begin(), request.end(), std::rand); |
| std::vector<uint8_t> reqBytes; |
| reqBytes = std::move(hothUtil->wrapECSKMHSSRequest(request)); |
| EXPECT_FALSE(reqBytes.empty()); |
| EXPECT_EQ(0, HothUtil::calculateChecksum(reqBytes)); |
| } |
| |
| TEST_F(HothUtilTest, ReadSKMHSS) |
| { |
| std::vector<uint8_t> reqBytes; |
| reqBytes = std::move(hothUtil->readSKMHSS(0)); |
| EXPECT_FALSE(reqBytes.empty()); |
| EXPECT_EQ(0, HothUtil::calculateChecksum(reqBytes)); |
| |
| reqBytes = std::move(hothUtil->readSKMHSS(1)); |
| EXPECT_FALSE(reqBytes.empty()); |
| EXPECT_EQ(0, HothUtil::calculateChecksum(reqBytes)); |
| |
| reqBytes = std::move(hothUtil->readSKMHSS(2)); |
| EXPECT_FALSE(reqBytes.empty()); |
| EXPECT_EQ(0, HothUtil::calculateChecksum(reqBytes)); |
| |
| reqBytes = std::move(hothUtil->readSKMHSS(3)); |
| EXPECT_FALSE(reqBytes.empty()); |
| EXPECT_EQ(0, HothUtil::calculateChecksum(reqBytes)); |
| } |
| |
| TEST_F(HothUtilTest, WriteSKMHSS) |
| { |
| std::vector<uint8_t> payload(128); |
| std::vector<uint8_t> reqBytes; |
| std::generate(payload.begin(), payload.end(), std::rand); |
| EXPECT_THROW(hothUtil->writeSKMHSS(0, payload), CommandFailure); |
| EXPECT_TRUE(reqBytes.empty()); |
| |
| payload.resize(64); |
| reqBytes = std::move(hothUtil->writeSKMHSS(1, payload)); |
| EXPECT_FALSE(reqBytes.empty()); |
| EXPECT_EQ(0, HothUtil::calculateChecksum(reqBytes)); |
| |
| payload = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 0, 0, 1, 110, 205, 147, 54, 43, 0, 0, 1, 1, 175, 58, 9, 239}; |
| EXPECT_NO_THROW(hothUtil->writeSKMHSS(0, payload)); |
| EXPECT_NO_THROW(hothUtil->writeSKMHSS(1, payload)); |
| EXPECT_NO_THROW(hothUtil->writeSKMHSS(2, payload)); |
| EXPECT_NO_THROW(hothUtil->writeSKMHSS(3, payload)); |
| } |
| |
| TEST_F(HothUtilTest, DeleteSKMHSS) |
| { |
| std::vector<uint8_t> reqBytes; |
| reqBytes = std::move(hothUtil->deleteSKMHSS(0)); |
| EXPECT_FALSE(reqBytes.empty()); |
| EXPECT_EQ(0, HothUtil::calculateChecksum(reqBytes)); |
| |
| reqBytes = std::move(hothUtil->deleteSKMHSS(1)); |
| EXPECT_FALSE(reqBytes.empty()); |
| EXPECT_EQ(0, HothUtil::calculateChecksum(reqBytes)); |
| |
| reqBytes = std::move(hothUtil->deleteSKMHSS(2)); |
| EXPECT_FALSE(reqBytes.empty()); |
| EXPECT_EQ(0, HothUtil::calculateChecksum(reqBytes)); |
| |
| reqBytes = std::move(hothUtil->deleteSKMHSS(3)); |
| EXPECT_FALSE(reqBytes.empty()); |
| EXPECT_EQ(0, HothUtil::calculateChecksum(reqBytes)); |
| } |
| |
| TEST_F(HothUtilTest, PayloadECResponse) |
| { |
| std::vector<uint8_t> validRsp = {0x03, 0xfd, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00}; |
| EXPECT_NO_THROW(hothUtil->payloadECResponse(validRsp)); |
| |
| std::vector<uint8_t> rspShortLength = {0x03, 0xfd}; |
| EXPECT_THROW(hothUtil->payloadECResponse(rspShortLength), ResponseFailure); |
| |
| std::vector<uint8_t> rspVersionErr = {0x05, 0xfb, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00}; |
| EXPECT_THROW(hothUtil->payloadECResponse(rspVersionErr), ResponseFailure); |
| |
| std::vector<uint8_t> rspNonZeroRC = {0x03, 0xfc, 0x01, 0x00, |
| 0x00, 0x00, 0x00, 0x00}; |
| EXPECT_THROW(hothUtil->payloadECResponse(rspNonZeroRC), ResponseFailure); |
| |
| std::vector<uint8_t> rspExpectedNonZeroRC = {0x03, 0xf4, 0x09, 0x00, |
| 0x00, 0x00, 0x00, 0x00}; |
| EXPECT_NO_THROW(hothUtil->payloadECResponse(rspExpectedNonZeroRC)); |
| |
| std::vector<uint8_t> payload(64); |
| std::generate(payload.begin(), payload.end(), std::rand); |
| uint8_t payloadSum = |
| std::accumulate(std::begin(payload), std::end(payload), 0) % 256; |
| uint8_t checksum = 0x100 - (0x03 + 0x40 + payloadSum) % 256; |
| std::vector<uint8_t> validRspWithRandomHss = {0x03, 0x00, 0x00, 0x00, |
| 0x40, 0x00, 0x00, 0x00}; |
| validRspWithRandomHss[1] = checksum; |
| validRspWithRandomHss.insert(validRspWithRandomHss.end(), payload.begin(), |
| payload.end()); |
| auto data = hothUtil->payloadECResponse(validRspWithRandomHss); |
| EXPECT_EQ(std::vector<uint8_t>(data.begin(), data.end()), payload); |
| } |
| |
| } // namespace ipmi_hoth |