diff options
author | Tom Joseph <tomjoseph@in.ibm.com> | 2018-03-21 21:17:33 +0530 |
---|---|---|
committer | Vernon Mauery <vernon.mauery@linux.intel.com> | 2018-04-16 22:25:57 +0000 |
commit | 7cbe22866c633d8e5b427503e1b1a363f45641a3 (patch) | |
tree | 4acff2038ac5de8afda3fed49000142faf9b2290 /app/channel.cpp | |
parent | 6ccf8818b1c5370684368bba17eb3661a3085d22 (diff) | |
download | phosphor-host-ipmid-7cbe22866c633d8e5b427503e1b1a363f45641a3.tar.gz phosphor-host-ipmid-7cbe22866c633d8e5b427503e1b1a363f45641a3.zip |
Implement Get Channel Cipher Suites command
Change-Id: I8c808ce7e2bbd3ae5e225573138d7e04871f1643
Signed-off-by: Tom Joseph <tomjoseph@in.ibm.com>
Diffstat (limited to 'app/channel.cpp')
-rw-r--r-- | app/channel.cpp | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/app/channel.cpp b/app/channel.cpp index 000c11e..3134683 100644 --- a/app/channel.cpp +++ b/app/channel.cpp @@ -4,6 +4,7 @@ #include "utils.hpp" #include "net.hpp" +#include <fstream> #include <string> #include <arpa/inet.h> @@ -118,3 +119,141 @@ ipmi_ret_t ipmi_app_channel_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd, return rc; } + +namespace cipher +{ + +/** @brief Get the supported Cipher records + * + * The cipher records are read from the JSON file and converted into cipher + * suite record format mentioned in the IPMI specification. The records can be + * either OEM or standard cipher. Each json entry is parsed and converted into + * the cipher record format and pushed into the vector. + * + * @return vector containing all the cipher suite records. + * + */ +std::vector<uint8_t> getCipherRecords() +{ + std::vector<uint8_t> records; + + std::ifstream jsonFile(configFile); + if (!jsonFile.is_open()) + { + log<level::ERR>("Channel Cipher suites file not found"); + elog<InternalFailure>(); + } + + auto data = Json::parse(jsonFile, nullptr, false); + if (data.is_discarded()) + { + log<level::ERR>("Parsing channel cipher suites JSON failed"); + elog<InternalFailure>(); + } + + for (const auto& record : data) + { + if (record.find(oem) != record.end()) + { + // OEM cipher suite - 0xC1 + records.push_back(oemCipherSuite); + // Cipher Suite ID + records.push_back(record.value(cipher, 0)); + // OEM IANA - 3 bytes + records.push_back(record.value(oem, 0)); + records.push_back(record.value(oem, 0) >> 8); + records.push_back(record.value(oem, 0) >> 16); + + } + else + { + // OEM cipher suite - 0xC0 + records.push_back(stdCipherSuite); + // Cipher Suite ID + records.push_back(record.value(cipher, 0)); + } + + // Authentication algorithm number + records.push_back(record.value(auth, 0)); + // Integrity algorithm number + records.push_back(record.value(integrity, 0) | integrityTag); + // Confidentiality algorithm number + records.push_back(record.value(conf, 0) | confTag); + } + + return records; +} + +} //namespace cipher + +ipmi_ret_t getChannelCipherSuites(ipmi_netfn_t netfn, + ipmi_cmd_t cmd, + ipmi_request_t request, + ipmi_response_t response, + ipmi_data_len_t data_len, + ipmi_context_t context) +{ + static std::vector<uint8_t> records; + static auto recordInit = false; + + auto requestData = + reinterpret_cast<const GetChannelCipherRequest*>(request); + + + if (*data_len < sizeof(GetChannelCipherRequest)) + { + *data_len = 0; + return IPMI_CC_REQ_DATA_LEN_INVALID; + } + + *data_len = 0; + + // Support only for list algorithms by cipher suite + if (cipher::listCipherSuite != + (requestData->listIndex & cipher::listTypeMask)) + { + return IPMI_CC_INVALID_FIELD_REQUEST; + } + + if (!recordInit) + { + try + { + records = cipher::getCipherRecords(); + recordInit = true; + } + catch (const std::exception &e) + { + return IPMI_CC_UNSPECIFIED_ERROR; + } + } + + // List index(00h-3Fh), 0h selects the first set of 16, 1h selects the next + // set of 16 and so on. + auto index = static_cast<size_t>( + requestData->listIndex & cipher::listIndexMask); + + // Calculate the number of record data bytes to be returned. + auto start = std::min(index * cipher::respSize, records.size()); + auto end = std::min((index * cipher::respSize) + cipher::respSize, + records.size()); + auto size = end - start; + + auto responseData = reinterpret_cast<GetChannelCipherRespHeader*> + (response); + responseData->channelNumber = cipher::defaultChannelNumber; + + if (!size) + { + *data_len = sizeof(GetChannelCipherRespHeader); + } + else + { + std::copy_n(records.data() + start, + size, + static_cast<uint8_t*>(response) + 1); + *data_len = size + sizeof(GetChannelCipherRespHeader); + } + + return IPMI_CC_OK; +} |