From 7cbe22866c633d8e5b427503e1b1a363f45641a3 Mon Sep 17 00:00:00 2001 From: Tom Joseph Date: Wed, 21 Mar 2018 21:17:33 +0530 Subject: Implement Get Channel Cipher Suites command Change-Id: I8c808ce7e2bbd3ae5e225573138d7e04871f1643 Signed-off-by: Tom Joseph --- app/channel.cpp | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) (limited to 'app/channel.cpp') 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 #include #include @@ -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 getCipherRecords() +{ + std::vector records; + + std::ifstream jsonFile(configFile); + if (!jsonFile.is_open()) + { + log("Channel Cipher suites file not found"); + elog(); + } + + auto data = Json::parse(jsonFile, nullptr, false); + if (data.is_discarded()) + { + log("Parsing channel cipher suites JSON failed"); + elog(); + } + + 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 records; + static auto recordInit = false; + + auto requestData = + reinterpret_cast(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( + 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 + (response); + responseData->channelNumber = cipher::defaultChannelNumber; + + if (!size) + { + *data_len = sizeof(GetChannelCipherRespHeader); + } + else + { + std::copy_n(records.data() + start, + size, + static_cast(response) + 1); + *data_len = size + sizeof(GetChannelCipherRespHeader); + } + + return IPMI_CC_OK; +} -- cgit v1.2.1