blob: e7af67fbb97330773e56c29612bf8fa870bf0f5f [file] [log] [blame]
Tom Josephd08b5232017-01-24 18:15:39 +05301#pragma once
2
Tom Josephd08b5232017-01-24 18:15:39 +05303#include <array>
Andrew Geissler7b645012021-05-17 16:25:47 -05004#include <cstddef>
Vernon Mauery9b307be2017-11-22 09:28:16 -08005#include <cstdint>
Tom Josephd08b5232017-01-24 18:15:39 +05306#include <vector>
7
8namespace cipher
9{
10
11namespace crypt
12{
13
Tom Josephd08b5232017-01-24 18:15:39 +053014/**
15 * @enum Confidentiality Algorithms
16 *
17 * The Confidentiality Algorithm Number specifies the encryption/decryption
18 * algorithm field that is used for encrypted payload data under the session.
19 * The ‘encrypted’ bit in the payload type field being set identifies packets
20 * with payloads that include data that is encrypted per this specification.
21 * When payload data is encrypted, there may be additional “Confidentiality
22 * Header” and/or “Confidentiality Trailer” fields that are included within the
23 * payload. The size and definition of those fields is specific to the
Tom Josephfe5a6452018-07-30 18:15:12 +053024 * particular confidentiality algorithm. Based on security recommendations
25 * encrypting IPMI traffic is preferred, so NONE is not supported.
Tom Josephd08b5232017-01-24 18:15:39 +053026 */
27enum class Algorithms : uint8_t
28{
Vernon Mauery9e801a22018-10-12 13:20:49 -070029 NONE, /**< No encryption (mandatory , not supported) */
30 AES_CBC_128, /**< AES-CBC-128 Algorithm (mandatory option) */
31 xRC4_128, /**< xRC4-128 Algorithm (optional option) */
32 xRC4_40, /**< xRC4-40 Algorithm (optional option) */
Tom Josephd08b5232017-01-24 18:15:39 +053033};
34
35/**
36 * @class Interface
37 *
38 * Interface is the base class for the Confidentiality Algorithms.
39 */
40class Interface
41{
Vernon Mauery9e801a22018-10-12 13:20:49 -070042 public:
43 /**
44 * @brief Constructor for Interface
45 */
Patrick Williams099fb092023-05-10 07:50:31 -050046 explicit Interface(const std::vector<uint8_t>& k2) : k2(k2) {}
Tom Josephd08b5232017-01-24 18:15:39 +053047
Vernon Mauery9e801a22018-10-12 13:20:49 -070048 Interface() = delete;
49 virtual ~Interface() = default;
50 Interface(const Interface&) = default;
51 Interface& operator=(const Interface&) = default;
52 Interface(Interface&&) = default;
53 Interface& operator=(Interface&&) = default;
Tom Josephd08b5232017-01-24 18:15:39 +053054
Vernon Mauery9e801a22018-10-12 13:20:49 -070055 /**
56 * @brief Decrypt the incoming payload
57 *
58 * @param[in] packet - Incoming IPMI packet
59 * @param[in] sessHeaderLen - Length of the IPMI Session Header
60 * @param[in] payloadLen - Length of the encrypted IPMI payload
61 *
62 * @return decrypted payload if the operation is successful
63 */
Patrick Williams84256242024-08-16 15:20:21 -040064 virtual std::vector<uint8_t> decryptPayload(
65 const std::vector<uint8_t>& packet, const size_t sessHeaderLen,
66 const size_t payloadLen) const = 0;
Tom Josephd08b5232017-01-24 18:15:39 +053067
Vernon Mauery9e801a22018-10-12 13:20:49 -070068 /**
69 * @brief Encrypt the outgoing payload
70 *
71 * @param[in] payload - plain payload for the outgoing IPMI packet
72 *
73 * @return encrypted payload if the operation is successful
74 *
75 */
76 virtual std::vector<uint8_t>
77 encryptPayload(std::vector<uint8_t>& payload) const = 0;
Tom Josephd08b5232017-01-24 18:15:39 +053078
Vernon Mauery9e801a22018-10-12 13:20:49 -070079 /**
80 * @brief Check if the Confidentiality algorithm is supported
81 *
82 * @param[in] algo - confidentiality algorithm
83 *
84 * @return true if algorithm is supported else false
85 *
86 */
87 static bool isAlgorithmSupported(Algorithms algo)
88 {
89 if (algo == Algorithms::AES_CBC_128)
Tom Joseph2f0bd0e2017-01-24 18:24:27 +053090 {
Vernon Mauery9e801a22018-10-12 13:20:49 -070091 return true;
Tom Joseph2f0bd0e2017-01-24 18:24:27 +053092 }
Vernon Mauery9e801a22018-10-12 13:20:49 -070093 else
94 {
95 return false;
96 }
97 }
Tom Joseph2f0bd0e2017-01-24 18:24:27 +053098
Vernon Mauery9e801a22018-10-12 13:20:49 -070099 protected:
100 /**
101 * @brief The Cipher Key is the first 128-bits of key “K2”, K2 is
102 * generated by processing a pre-defined constant keyed by Session
103 * Integrity Key (SIK) that was created during session activation.
104 */
105 std::vector<uint8_t> k2;
Tom Josephd08b5232017-01-24 18:15:39 +0530106};
107
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530108/**
109 * @class AlgoAES128
110 *
111 * @brief Implementation of the AES-CBC-128 Confidentiality algorithm
112 *
113 * AES-128 uses a 128-bit Cipher Key. The Cipher Key is the first 128-bits of
114 * key “K2”.Once the Cipher Key has been generated it is used to encrypt
115 * the payload data. The payload data is padded to make it an integral numbers
116 * of blocks in length (a block is 16 bytes for AES). The payload is then
117 * encrypted one block at a time from the lowest data offset to the highest
118 * using Cipher_Key as specified in AES.
119 */
120class AlgoAES128 final : public Interface
121{
Vernon Mauery9e801a22018-10-12 13:20:49 -0700122 public:
123 static constexpr size_t AESCBC128ConfHeader = 16;
124 static constexpr size_t AESCBC128BlockSize = 16;
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530125
Vernon Mauery9e801a22018-10-12 13:20:49 -0700126 /**
127 * If confidentiality bytes are present, the value of the first byte is
128 * one (01h). and all subsequent bytes shall have a monotonically
129 * increasing value (e.g., 02h, 03h, 04h, etc). The receiver, as an
130 * additional check for proper decryption, shall check the value of each
131 * byte of Confidentiality Pad. For AES algorithm, the pad bytes will
132 * range from 0 to 15 bytes. This predefined array would help in
133 * doing the additional check.
134 */
135 static constexpr std::array<uint8_t, AESCBC128BlockSize - 1> confPadBytes =
136 {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
137 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530138
Vernon Mauery9e801a22018-10-12 13:20:49 -0700139 /**
140 * @brief Constructor for AlgoAES128
141 *
142 * @param[in] - Session Integrity key
143 */
Patrick Williams099fb092023-05-10 07:50:31 -0500144 explicit AlgoAES128(const std::vector<uint8_t>& k2) : Interface(k2) {}
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530145
Vernon Mauery9e801a22018-10-12 13:20:49 -0700146 AlgoAES128() = delete;
147 ~AlgoAES128() = default;
148 AlgoAES128(const AlgoAES128&) = default;
149 AlgoAES128& operator=(const AlgoAES128&) = default;
150 AlgoAES128(AlgoAES128&&) = default;
151 AlgoAES128& operator=(AlgoAES128&&) = default;
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530152
Vernon Mauery9e801a22018-10-12 13:20:49 -0700153 /**
154 * @brief Decrypt the incoming payload
155 *
156 * @param[in] packet - Incoming IPMI packet
157 * @param[in] sessHeaderLen - Length of the IPMI Session Header
158 * @param[in] payloadLen - Length of the encrypted IPMI payload
159 *
160 * @return decrypted payload if the operation is successful
161 */
162 std::vector<uint8_t> decryptPayload(const std::vector<uint8_t>& packet,
163 const size_t sessHeaderLen,
164 const size_t payloadLen) const override;
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530165
Vernon Mauery9e801a22018-10-12 13:20:49 -0700166 /**
167 * @brief Encrypt the outgoing payload
168 *
169 * @param[in] payload - plain payload for the outgoing IPMI packet
170 *
171 * @return encrypted payload if the operation is successful
172 *
173 */
174 std::vector<uint8_t>
175 encryptPayload(std::vector<uint8_t>& payload) const override;
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530176
Vernon Mauery9e801a22018-10-12 13:20:49 -0700177 private:
178 /**
179 * @brief Decrypt the passed data
180 *
181 * @param[in] iv - Initialization vector
182 * @param[in] input - Pointer to input data
183 * @param[in] inputLen - Length of input data
184 *
185 * @return decrypted data if the operation is successful
186 */
187 std::vector<uint8_t> decryptData(const uint8_t* iv, const uint8_t* input,
188 const int inputLen) const;
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530189
Vernon Mauery9e801a22018-10-12 13:20:49 -0700190 /**
191 * @brief Encrypt the passed data
192 *
193 * @param[in] input - Pointer to input data
194 * @param[in] inputLen - Length of input data
195 *
196 * @return encrypted data if the operation is successful
197 */
198 std::vector<uint8_t> encryptData(const uint8_t* input,
199 const int inputLen) const;
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530200};
201
Vernon Mauery9e801a22018-10-12 13:20:49 -0700202} // namespace crypt
Tom Josephd08b5232017-01-24 18:15:39 +0530203
Vernon Mauery9e801a22018-10-12 13:20:49 -0700204} // namespace cipher