blob: 366f2b0adbbff6c124bcae2816c90a424af59c63 [file] [log] [blame]
Tom Josephd08b5232017-01-24 18:15:39 +05301#pragma once
2
Tom Josephd08b5232017-01-24 18:15:39 +05303#include <array>
Vernon Mauery9b307be2017-11-22 09:28:16 -08004#include <cstdint>
Tom Josephd08b5232017-01-24 18:15:39 +05305#include <vector>
6
7namespace cipher
8{
9
10namespace crypt
11{
12
Tom Josephd08b5232017-01-24 18:15:39 +053013/**
14 * @enum Confidentiality Algorithms
15 *
16 * The Confidentiality Algorithm Number specifies the encryption/decryption
17 * algorithm field that is used for encrypted payload data under the session.
18 * The ‘encrypted’ bit in the payload type field being set identifies packets
19 * with payloads that include data that is encrypted per this specification.
20 * When payload data is encrypted, there may be additional “Confidentiality
21 * Header” and/or “Confidentiality Trailer” fields that are included within the
22 * payload. The size and definition of those fields is specific to the
Tom Josephfe5a6452018-07-30 18:15:12 +053023 * particular confidentiality algorithm. Based on security recommendations
24 * encrypting IPMI traffic is preferred, so NONE is not supported.
Tom Josephd08b5232017-01-24 18:15:39 +053025 */
26enum class Algorithms : uint8_t
27{
Vernon Mauery9e801a22018-10-12 13:20:49 -070028 NONE, /**< No encryption (mandatory , not supported) */
29 AES_CBC_128, /**< AES-CBC-128 Algorithm (mandatory option) */
30 xRC4_128, /**< xRC4-128 Algorithm (optional option) */
31 xRC4_40, /**< xRC4-40 Algorithm (optional option) */
Tom Josephd08b5232017-01-24 18:15:39 +053032};
33
34/**
35 * @class Interface
36 *
37 * Interface is the base class for the Confidentiality Algorithms.
38 */
39class Interface
40{
Vernon Mauery9e801a22018-10-12 13:20:49 -070041 public:
42 /**
43 * @brief Constructor for Interface
44 */
45 explicit Interface(const std::vector<uint8_t>& k2) : k2(k2)
46 {
47 }
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)
147 {
148 }
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530149
Vernon Mauery9e801a22018-10-12 13:20:49 -0700150 AlgoAES128() = delete;
151 ~AlgoAES128() = default;
152 AlgoAES128(const AlgoAES128&) = default;
153 AlgoAES128& operator=(const AlgoAES128&) = default;
154 AlgoAES128(AlgoAES128&&) = default;
155 AlgoAES128& operator=(AlgoAES128&&) = default;
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530156
Vernon Mauery9e801a22018-10-12 13:20:49 -0700157 /**
158 * @brief Decrypt the incoming payload
159 *
160 * @param[in] packet - Incoming IPMI packet
161 * @param[in] sessHeaderLen - Length of the IPMI Session Header
162 * @param[in] payloadLen - Length of the encrypted IPMI payload
163 *
164 * @return decrypted payload if the operation is successful
165 */
166 std::vector<uint8_t> decryptPayload(const std::vector<uint8_t>& packet,
167 const size_t sessHeaderLen,
168 const size_t payloadLen) const override;
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530169
Vernon Mauery9e801a22018-10-12 13:20:49 -0700170 /**
171 * @brief Encrypt the outgoing payload
172 *
173 * @param[in] payload - plain payload for the outgoing IPMI packet
174 *
175 * @return encrypted payload if the operation is successful
176 *
177 */
178 std::vector<uint8_t>
179 encryptPayload(std::vector<uint8_t>& payload) const override;
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530180
Vernon Mauery9e801a22018-10-12 13:20:49 -0700181 private:
182 /**
183 * @brief Decrypt the passed data
184 *
185 * @param[in] iv - Initialization vector
186 * @param[in] input - Pointer to input data
187 * @param[in] inputLen - Length of input data
188 *
189 * @return decrypted data if the operation is successful
190 */
191 std::vector<uint8_t> decryptData(const uint8_t* iv, const uint8_t* input,
192 const int inputLen) const;
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530193
Vernon Mauery9e801a22018-10-12 13:20:49 -0700194 /**
195 * @brief Encrypt the passed data
196 *
197 * @param[in] input - Pointer to input data
198 * @param[in] inputLen - Length of input data
199 *
200 * @return encrypted data if the operation is successful
201 */
202 std::vector<uint8_t> encryptData(const uint8_t* input,
203 const int inputLen) const;
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530204};
205
Vernon Mauery9e801a22018-10-12 13:20:49 -0700206} // namespace crypt
Tom Josephd08b5232017-01-24 18:15:39 +0530207
Vernon Mauery9e801a22018-10-12 13:20:49 -0700208} // namespace cipher