blob: 20f55b9a541d2688c1c7fd510f03200228343acd [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{
Tom Josephfe5a6452018-07-30 18:15:12 +053028 NONE, /**< No encryption (mandatory , not supported) */
Tom Josephd08b5232017-01-24 18:15:39 +053029 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) */
32};
33
34/**
35 * @class Interface
36 *
37 * Interface is the base class for the Confidentiality Algorithms.
38 */
39class Interface
40{
41 public:
42 /**
43 * @brief Constructor for Interface
Tom Josephd08b5232017-01-24 18:15:39 +053044 */
Vernon Mauery9b307be2017-11-22 09:28:16 -080045 explicit Interface(const std::vector<uint8_t>& k2)
46 : k2(k2) {}
Tom Josephd08b5232017-01-24 18:15:39 +053047
48 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;
54
55 /**
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 */
Vernon Mauery70fd29c2017-11-30 13:11:43 -080064 virtual std::vector<uint8_t> decryptPayload(
65 const std::vector<uint8_t>& packet,
Tom Josephd08b5232017-01-24 18:15:39 +053066 const size_t sessHeaderLen,
67 const size_t payloadLen) const = 0;
68
69 /**
70 * @brief Encrypt the outgoing payload
71 *
72 * @param[in] payload - plain payload for the outgoing IPMI packet
73 *
74 * @return encrypted payload if the operation is successful
75 *
76 */
Vernon Mauery70fd29c2017-11-30 13:11:43 -080077 virtual std::vector<uint8_t> encryptPayload(
78 std::vector<uint8_t>& payload) const = 0;
Tom Josephd08b5232017-01-24 18:15:39 +053079
Tom Joseph2f0bd0e2017-01-24 18:24:27 +053080 /**
81 * @brief Check if the Confidentiality algorithm is supported
82 *
83 * @param[in] algo - confidentiality algorithm
84 *
85 * @return true if algorithm is supported else false
86 *
87 */
88 static bool isAlgorithmSupported(Algorithms algo)
89 {
Tom Josephfe5a6452018-07-30 18:15:12 +053090 if (algo == Algorithms::AES_CBC_128)
Tom Joseph2f0bd0e2017-01-24 18:24:27 +053091 {
92 return true;
93 }
94 else
95 {
96 return false;
97 }
98 }
99
Tom Josephd08b5232017-01-24 18:15:39 +0530100 protected:
101
Tom Joseph54690652017-02-16 20:25:23 +0530102 /**
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 */
Vernon Mauery70fd29c2017-11-30 13:11:43 -0800107 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{
124 public:
125 static constexpr size_t AESCBC128ConfHeader = 16;
126 static constexpr size_t AESCBC128BlockSize = 16;
127
128 /**
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530129 * 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>
138 confPadBytes =
139 { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
140 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
141
142 /**
143 * @brief Constructor for AlgoAES128
144 *
145 * @param[in] - Session Integrity key
146 */
Vernon Mauery9b307be2017-11-22 09:28:16 -0800147 explicit AlgoAES128(const std::vector<uint8_t>& k2) : Interface(k2) {}
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530148
149 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;
155
156 /**
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 */
Vernon Mauery70fd29c2017-11-30 13:11:43 -0800165 std::vector<uint8_t> decryptPayload(
166 const std::vector<uint8_t>& packet,
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530167 const size_t sessHeaderLen,
168 const size_t payloadLen) const override;
169
170 /**
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 */
Vernon Mauery70fd29c2017-11-30 13:11:43 -0800178 std::vector<uint8_t> encryptPayload(
179 std::vector<uint8_t>& payload) const override;
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530180
181 private:
182
183 /**
184 * @brief Decrypt the passed data
185 *
186 * @param[in] iv - Initialization vector
187 * @param[in] input - Pointer to input data
188 * @param[in] inputLen - Length of input data
189 *
190 * @return decrypted data if the operation is successful
191 */
Vernon Mauery70fd29c2017-11-30 13:11:43 -0800192 std::vector<uint8_t> decryptData(const uint8_t* iv,
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530193 const uint8_t* input,
194 const int inputLen) const;
195
196 /**
197 * @brief Encrypt the passed data
198 *
199 * @param[in] input - Pointer to input data
200 * @param[in] inputLen - Length of input data
201 *
202 * @return encrypted data if the operation is successful
203 */
Vernon Mauery70fd29c2017-11-30 13:11:43 -0800204 std::vector<uint8_t> encryptData(const uint8_t* input,
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530205 const int inputLen) const;
206};
207
Tom Josephd08b5232017-01-24 18:15:39 +0530208}// namespace crypt
209
210}// namespace cipher
211