| #pragma once |
| |
| #include <array> |
| #include <cstdint> |
| #include <vector> |
| |
| namespace cipher |
| { |
| |
| namespace crypt |
| { |
| |
| /** |
| * @enum Confidentiality Algorithms |
| * |
| * The Confidentiality Algorithm Number specifies the encryption/decryption |
| * algorithm field that is used for encrypted payload data under the session. |
| * The ‘encrypted’ bit in the payload type field being set identifies packets |
| * with payloads that include data that is encrypted per this specification. |
| * When payload data is encrypted, there may be additional “Confidentiality |
| * Header” and/or “Confidentiality Trailer” fields that are included within the |
| * payload. The size and definition of those fields is specific to the |
| * particular confidentiality algorithm. Based on security recommendations |
| * encrypting IPMI traffic is preferred, so NONE is not supported. |
| */ |
| enum class Algorithms : uint8_t |
| { |
| NONE, /**< No encryption (mandatory , not supported) */ |
| AES_CBC_128, /**< AES-CBC-128 Algorithm (mandatory option) */ |
| xRC4_128, /**< xRC4-128 Algorithm (optional option) */ |
| xRC4_40, /**< xRC4-40 Algorithm (optional option) */ |
| }; |
| |
| /** |
| * @class Interface |
| * |
| * Interface is the base class for the Confidentiality Algorithms. |
| */ |
| class Interface |
| { |
| public: |
| /** |
| * @brief Constructor for Interface |
| */ |
| explicit Interface(const std::vector<uint8_t>& k2) : k2(k2) |
| { |
| } |
| |
| Interface() = delete; |
| virtual ~Interface() = default; |
| Interface(const Interface&) = default; |
| Interface& operator=(const Interface&) = default; |
| Interface(Interface&&) = default; |
| Interface& operator=(Interface&&) = default; |
| |
| /** |
| * @brief Decrypt the incoming payload |
| * |
| * @param[in] packet - Incoming IPMI packet |
| * @param[in] sessHeaderLen - Length of the IPMI Session Header |
| * @param[in] payloadLen - Length of the encrypted IPMI payload |
| * |
| * @return decrypted payload if the operation is successful |
| */ |
| virtual std::vector<uint8_t> |
| decryptPayload(const std::vector<uint8_t>& packet, |
| const size_t sessHeaderLen, |
| const size_t payloadLen) const = 0; |
| |
| /** |
| * @brief Encrypt the outgoing payload |
| * |
| * @param[in] payload - plain payload for the outgoing IPMI packet |
| * |
| * @return encrypted payload if the operation is successful |
| * |
| */ |
| virtual std::vector<uint8_t> |
| encryptPayload(std::vector<uint8_t>& payload) const = 0; |
| |
| /** |
| * @brief Check if the Confidentiality algorithm is supported |
| * |
| * @param[in] algo - confidentiality algorithm |
| * |
| * @return true if algorithm is supported else false |
| * |
| */ |
| static bool isAlgorithmSupported(Algorithms algo) |
| { |
| if (algo == Algorithms::AES_CBC_128) |
| { |
| return true; |
| } |
| else |
| { |
| return false; |
| } |
| } |
| |
| protected: |
| /** |
| * @brief The Cipher Key is the first 128-bits of key “K2”, K2 is |
| * generated by processing a pre-defined constant keyed by Session |
| * Integrity Key (SIK) that was created during session activation. |
| */ |
| std::vector<uint8_t> k2; |
| }; |
| |
| /** |
| * @class AlgoAES128 |
| * |
| * @brief Implementation of the AES-CBC-128 Confidentiality algorithm |
| * |
| * AES-128 uses a 128-bit Cipher Key. The Cipher Key is the first 128-bits of |
| * key “K2”.Once the Cipher Key has been generated it is used to encrypt |
| * the payload data. The payload data is padded to make it an integral numbers |
| * of blocks in length (a block is 16 bytes for AES). The payload is then |
| * encrypted one block at a time from the lowest data offset to the highest |
| * using Cipher_Key as specified in AES. |
| */ |
| class AlgoAES128 final : public Interface |
| { |
| public: |
| static constexpr size_t AESCBC128ConfHeader = 16; |
| static constexpr size_t AESCBC128BlockSize = 16; |
| |
| /** |
| * If confidentiality bytes are present, the value of the first byte is |
| * one (01h). and all subsequent bytes shall have a monotonically |
| * increasing value (e.g., 02h, 03h, 04h, etc). The receiver, as an |
| * additional check for proper decryption, shall check the value of each |
| * byte of Confidentiality Pad. For AES algorithm, the pad bytes will |
| * range from 0 to 15 bytes. This predefined array would help in |
| * doing the additional check. |
| */ |
| static constexpr std::array<uint8_t, AESCBC128BlockSize - 1> confPadBytes = |
| {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, |
| 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}; |
| |
| /** |
| * @brief Constructor for AlgoAES128 |
| * |
| * @param[in] - Session Integrity key |
| */ |
| explicit AlgoAES128(const std::vector<uint8_t>& k2) : Interface(k2) |
| { |
| } |
| |
| AlgoAES128() = delete; |
| ~AlgoAES128() = default; |
| AlgoAES128(const AlgoAES128&) = default; |
| AlgoAES128& operator=(const AlgoAES128&) = default; |
| AlgoAES128(AlgoAES128&&) = default; |
| AlgoAES128& operator=(AlgoAES128&&) = default; |
| |
| /** |
| * @brief Decrypt the incoming payload |
| * |
| * @param[in] packet - Incoming IPMI packet |
| * @param[in] sessHeaderLen - Length of the IPMI Session Header |
| * @param[in] payloadLen - Length of the encrypted IPMI payload |
| * |
| * @return decrypted payload if the operation is successful |
| */ |
| std::vector<uint8_t> decryptPayload(const std::vector<uint8_t>& packet, |
| const size_t sessHeaderLen, |
| const size_t payloadLen) const override; |
| |
| /** |
| * @brief Encrypt the outgoing payload |
| * |
| * @param[in] payload - plain payload for the outgoing IPMI packet |
| * |
| * @return encrypted payload if the operation is successful |
| * |
| */ |
| std::vector<uint8_t> |
| encryptPayload(std::vector<uint8_t>& payload) const override; |
| |
| private: |
| /** |
| * @brief Decrypt the passed data |
| * |
| * @param[in] iv - Initialization vector |
| * @param[in] input - Pointer to input data |
| * @param[in] inputLen - Length of input data |
| * |
| * @return decrypted data if the operation is successful |
| */ |
| std::vector<uint8_t> decryptData(const uint8_t* iv, const uint8_t* input, |
| const int inputLen) const; |
| |
| /** |
| * @brief Encrypt the passed data |
| * |
| * @param[in] input - Pointer to input data |
| * @param[in] inputLen - Length of input data |
| * |
| * @return encrypted data if the operation is successful |
| */ |
| std::vector<uint8_t> encryptData(const uint8_t* input, |
| const int inputLen) const; |
| }; |
| |
| } // namespace crypt |
| |
| } // namespace cipher |