summaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
authorTom Joseph <tomjoseph@in.ibm.com>2018-03-21 21:17:33 +0530
committerVernon Mauery <vernon.mauery@linux.intel.com>2018-04-16 22:25:57 +0000
commit7cbe22866c633d8e5b427503e1b1a363f45641a3 (patch)
tree4acff2038ac5de8afda3fed49000142faf9b2290 /app
parent6ccf8818b1c5370684368bba17eb3661a3085d22 (diff)
downloadphosphor-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')
-rw-r--r--app/channel.cpp139
-rw-r--r--app/channel.hpp64
2 files changed, 203 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;
+}
diff --git a/app/channel.hpp b/app/channel.hpp
index 1391d62..79522e4 100644
--- a/app/channel.hpp
+++ b/app/channel.hpp
@@ -1,4 +1,5 @@
#include "ipmid.hpp"
+#include "nlohmann/json.hpp"
/** @brief The set channel access IPMI command.
*
@@ -57,3 +58,66 @@ ipmi_ret_t ipmi_app_channel_info(
ipmi_data_len_t data_len,
ipmi_context_t context);
+/** @brief Implementation of get channel cipher suites command
+ *
+ * @param[in] netfn - Net Function
+ * @param[in] cmd - Command
+ * @param[in] request - Request pointer
+ * @param[in,out] response - Response pointer
+ * @param[in,out] data_len - Data Length
+ * @param[in] context - Context
+ *
+ * @return IPMI_CC_OK on success, non-zero otherwise.
+ */
+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);
+
+namespace cipher
+{
+
+static constexpr auto defaultChannelNumber = 1;
+static constexpr auto listTypeMask = 0x80;
+static constexpr auto listCipherSuite = 0x80;
+static constexpr auto listIndexMask = 0x3F;
+static constexpr auto respSize = 16;
+
+using Json = nlohmann::json;
+static constexpr auto configFile =
+ "/usr/share/ipmi-providers/cipher_list.json";
+static constexpr auto cipher = "cipher";
+static constexpr auto stdCipherSuite = 0xC0;
+static constexpr auto oemCipherSuite = 0xC1;
+static constexpr auto oem = "oemiana";
+static constexpr auto auth = "authentication";
+static constexpr auto integrity = "integrity";
+static constexpr auto integrityTag = 0x40;
+static constexpr auto conf = "confidentiality";
+static constexpr auto confTag = 0x80;
+
+} //namespace cipher
+
+/** @struct GetChannelCipherRequest
+ *
+ * IPMI payload for Get Channel Cipher Suites command request
+ */
+struct GetChannelCipherRequest
+{
+ uint8_t channelNumber; //!< Channel Number
+ uint8_t payloadType; //!< Payload type number
+ uint8_t listIndex; //!< List Index
+} __attribute__((packed));
+
+/** @struct GetChannelCipherRespHeader
+ *
+ * IPMI payload for Get Channel Cipher Suites command response header
+ */
+struct GetChannelCipherRespHeader
+{
+ uint8_t channelNumber; //!< Channel Number
+} __attribute__((packed));
+
+
OpenPOWER on IntegriCloud