blob: 10647726748f4d838aaf009c42129a773b88e949 [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 */
46 explicit Interface(const std::vector<uint8_t>& k2) : k2(k2)
George Liubc8958f2022-07-04 09:29:49 +080047 {}
Tom Josephd08b5232017-01-24 18:15:39 +053048
Vernon Mauery9e801a22018-10-12 13:20:49 -070049 Interface() = delete;
50 virtual ~Interface() = default;
51 Interface(const Interface&) = default;
52 Interface& operator=(const Interface&) = default;
53 Interface(Interface&&) = default;
54 Interface& operator=(Interface&&) = default;
Tom Josephd08b5232017-01-24 18:15:39 +053055
Vernon Mauery9e801a22018-10-12 13:20:49 -070056 /**
57 * @brief Decrypt the incoming payload
58 *
59 * @param[in] packet - Incoming IPMI packet
60 * @param[in] sessHeaderLen - Length of the IPMI Session Header
61 * @param[in] payloadLen - Length of the encrypted IPMI payload
62 *
63 * @return decrypted payload if the operation is successful
64 */
65 virtual std::vector<uint8_t>
66 decryptPayload(const std::vector<uint8_t>& packet,
67 const size_t sessHeaderLen,
68 const size_t payloadLen) const = 0;
Tom Josephd08b5232017-01-24 18:15:39 +053069
Vernon Mauery9e801a22018-10-12 13:20:49 -070070 /**
71 * @brief Encrypt the outgoing payload
72 *
73 * @param[in] payload - plain payload for the outgoing IPMI packet
74 *
75 * @return encrypted payload if the operation is successful
76 *
77 */
78 virtual std::vector<uint8_t>
79 encryptPayload(std::vector<uint8_t>& payload) const = 0;
Tom Josephd08b5232017-01-24 18:15:39 +053080
Vernon Mauery9e801a22018-10-12 13:20:49 -070081 /**
82 * @brief Check if the Confidentiality algorithm is supported
83 *
84 * @param[in] algo - confidentiality algorithm
85 *
86 * @return true if algorithm is supported else false
87 *
88 */
89 static bool isAlgorithmSupported(Algorithms algo)
90 {
91 if (algo == Algorithms::AES_CBC_128)
Tom Joseph2f0bd0e2017-01-24 18:24:27 +053092 {
Vernon Mauery9e801a22018-10-12 13:20:49 -070093 return true;
Tom Joseph2f0bd0e2017-01-24 18:24:27 +053094 }
Vernon Mauery9e801a22018-10-12 13:20:49 -070095 else
96 {
97 return false;
98 }
99 }
Tom Joseph2f0bd0e2017-01-24 18:24:27 +0530100
Vernon Mauery9e801a22018-10-12 13:20:49 -0700101 protected:
102 /**
103 * @brief The Cipher Key is the first 128-bits of key “K2”, K2 is
104 * generated by processing a pre-defined constant keyed by Session
105 * Integrity Key (SIK) that was created during session activation.
106 */
107 std::vector<uint8_t> k2;
Tom Josephd08b5232017-01-24 18:15:39 +0530108};
109
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530110/**
111 * @class AlgoAES128
112 *
113 * @brief Implementation of the AES-CBC-128 Confidentiality algorithm
114 *
115 * AES-128 uses a 128-bit Cipher Key. The Cipher Key is the first 128-bits of
116 * key “K2”.Once the Cipher Key has been generated it is used to encrypt
117 * the payload data. The payload data is padded to make it an integral numbers
118 * of blocks in length (a block is 16 bytes for AES). The payload is then
119 * encrypted one block at a time from the lowest data offset to the highest
120 * using Cipher_Key as specified in AES.
121 */
122class AlgoAES128 final : public Interface
123{
Vernon Mauery9e801a22018-10-12 13:20:49 -0700124 public:
125 static constexpr size_t AESCBC128ConfHeader = 16;
126 static constexpr size_t AESCBC128BlockSize = 16;
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530127
Vernon Mauery9e801a22018-10-12 13:20:49 -0700128 /**
129 * If confidentiality bytes are present, the value of the first byte is
130 * one (01h). and all subsequent bytes shall have a monotonically
131 * increasing value (e.g., 02h, 03h, 04h, etc). The receiver, as an
132 * additional check for proper decryption, shall check the value of each
133 * byte of Confidentiality Pad. For AES algorithm, the pad bytes will
134 * range from 0 to 15 bytes. This predefined array would help in
135 * doing the additional check.
136 */
137 static constexpr std::array<uint8_t, AESCBC128BlockSize - 1> confPadBytes =
138 {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
139 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530140
Vernon Mauery9e801a22018-10-12 13:20:49 -0700141 /**
142 * @brief Constructor for AlgoAES128
143 *
144 * @param[in] - Session Integrity key
145 */
146 explicit AlgoAES128(const std::vector<uint8_t>& k2) : Interface(k2)
George Liubc8958f2022-07-04 09:29:49 +0800147 {}
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530148
Vernon Mauery9e801a22018-10-12 13:20:49 -0700149 AlgoAES128() = delete;
150 ~AlgoAES128() = default;
151 AlgoAES128(const AlgoAES128&) = default;
152 AlgoAES128& operator=(const AlgoAES128&) = default;
153 AlgoAES128(AlgoAES128&&) = default;
154 AlgoAES128& operator=(AlgoAES128&&) = default;
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530155
Vernon Mauery9e801a22018-10-12 13:20:49 -0700156 /**
157 * @brief Decrypt the incoming payload
158 *
159 * @param[in] packet - Incoming IPMI packet
160 * @param[in] sessHeaderLen - Length of the IPMI Session Header
161 * @param[in] payloadLen - Length of the encrypted IPMI payload
162 *
163 * @return decrypted payload if the operation is successful
164 */
165 std::vector<uint8_t> decryptPayload(const std::vector<uint8_t>& packet,
166 const size_t sessHeaderLen,
167 const size_t payloadLen) const override;
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530168
Vernon Mauery9e801a22018-10-12 13:20:49 -0700169 /**
170 * @brief Encrypt the outgoing payload
171 *
172 * @param[in] payload - plain payload for the outgoing IPMI packet
173 *
174 * @return encrypted payload if the operation is successful
175 *
176 */
177 std::vector<uint8_t>
178 encryptPayload(std::vector<uint8_t>& payload) const override;
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530179
Vernon Mauery9e801a22018-10-12 13:20:49 -0700180 private:
181 /**
182 * @brief Decrypt the passed data
183 *
184 * @param[in] iv - Initialization vector
185 * @param[in] input - Pointer to input data
186 * @param[in] inputLen - Length of input data
187 *
188 * @return decrypted data if the operation is successful
189 */
190 std::vector<uint8_t> decryptData(const uint8_t* iv, const uint8_t* input,
191 const int inputLen) const;
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530192
Vernon Mauery9e801a22018-10-12 13:20:49 -0700193 /**
194 * @brief Encrypt the passed data
195 *
196 * @param[in] input - Pointer to input data
197 * @param[in] inputLen - Length of input data
198 *
199 * @return encrypted data if the operation is successful
200 */
201 std::vector<uint8_t> encryptData(const uint8_t* input,
202 const int inputLen) const;
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530203};
204
Vernon Mauery9e801a22018-10-12 13:20:49 -0700205} // namespace crypt
Tom Josephd08b5232017-01-24 18:15:39 +0530206
Vernon Mauery9e801a22018-10-12 13:20:49 -0700207} // namespace cipher