blob: ca4dbca7bdbe84c90b5ea3b95d3360a37b83872e [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
23 * particular confidentiality algorithm.
24 */
25enum class Algorithms : uint8_t
26{
27 NONE, /**< No encryption (mandatory option) */
28 AES_CBC_128, /**< AES-CBC-128 Algorithm (mandatory option) */
29 xRC4_128, /**< xRC4-128 Algorithm (optional option) */
30 xRC4_40, /**< xRC4-40 Algorithm (optional option) */
31};
32
33/**
34 * @class Interface
35 *
36 * Interface is the base class for the Confidentiality Algorithms.
37 */
38class Interface
39{
40 public:
41 /**
42 * @brief Constructor for Interface
Tom Josephd08b5232017-01-24 18:15:39 +053043 */
Vernon Mauery9b307be2017-11-22 09:28:16 -080044 explicit Interface(const std::vector<uint8_t>& k2)
45 : k2(k2) {}
Tom Josephd08b5232017-01-24 18:15:39 +053046
47 Interface() = delete;
48 virtual ~Interface() = default;
49 Interface(const Interface&) = default;
50 Interface& operator=(const Interface&) = default;
51 Interface(Interface&&) = default;
52 Interface& operator=(Interface&&) = default;
53
54 /**
55 * @brief Decrypt the incoming payload
56 *
57 * @param[in] packet - Incoming IPMI packet
58 * @param[in] sessHeaderLen - Length of the IPMI Session Header
59 * @param[in] payloadLen - Length of the encrypted IPMI payload
60 *
61 * @return decrypted payload if the operation is successful
62 */
Vernon Mauery70fd29c2017-11-30 13:11:43 -080063 virtual std::vector<uint8_t> decryptPayload(
64 const std::vector<uint8_t>& packet,
Tom Josephd08b5232017-01-24 18:15:39 +053065 const size_t sessHeaderLen,
66 const size_t payloadLen) const = 0;
67
68 /**
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 */
Vernon Mauery70fd29c2017-11-30 13:11:43 -080076 virtual std::vector<uint8_t> encryptPayload(
77 std::vector<uint8_t>& payload) const = 0;
Tom Josephd08b5232017-01-24 18:15:39 +053078
Tom Joseph2f0bd0e2017-01-24 18:24:27 +053079 /**
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::NONE || algo == Algorithms::AES_CBC_128)
90 {
91 return true;
92 }
93 else
94 {
95 return false;
96 }
97 }
98
Tom Josephd08b5232017-01-24 18:15:39 +053099 protected:
100
Tom Joseph54690652017-02-16 20:25:23 +0530101 /**
102 * @brief The Cipher Key is the first 128-bits of key “K2”, K2 is
103 * generated by processing a pre-defined constant keyed by Session
104 * Integrity Key (SIK) that was created during session activation.
105 */
Vernon Mauery70fd29c2017-11-30 13:11:43 -0800106 std::vector<uint8_t> k2;
Tom Josephd08b5232017-01-24 18:15:39 +0530107};
108
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530109/**
110 * @class AlgoAES128
111 *
112 * @brief Implementation of the AES-CBC-128 Confidentiality algorithm
113 *
114 * AES-128 uses a 128-bit Cipher Key. The Cipher Key is the first 128-bits of
115 * key “K2”.Once the Cipher Key has been generated it is used to encrypt
116 * the payload data. The payload data is padded to make it an integral numbers
117 * of blocks in length (a block is 16 bytes for AES). The payload is then
118 * encrypted one block at a time from the lowest data offset to the highest
119 * using Cipher_Key as specified in AES.
120 */
121class AlgoAES128 final : public Interface
122{
123 public:
124 static constexpr size_t AESCBC128ConfHeader = 16;
125 static constexpr size_t AESCBC128BlockSize = 16;
126
127 /**
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530128 * If confidentiality bytes are present, the value of the first byte is
129 * one (01h). and all subsequent bytes shall have a monotonically
130 * increasing value (e.g., 02h, 03h, 04h, etc). The receiver, as an
131 * additional check for proper decryption, shall check the value of each
132 * byte of Confidentiality Pad. For AES algorithm, the pad bytes will
133 * range from 0 to 15 bytes. This predefined array would help in
134 * doing the additional check.
135 */
136 static constexpr std::array<uint8_t, AESCBC128BlockSize -1>
137 confPadBytes =
138 { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
139 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
140
141 /**
142 * @brief Constructor for AlgoAES128
143 *
144 * @param[in] - Session Integrity key
145 */
Vernon Mauery9b307be2017-11-22 09:28:16 -0800146 explicit AlgoAES128(const std::vector<uint8_t>& k2) : Interface(k2) {}
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530147
148 AlgoAES128() = delete;
149 ~AlgoAES128() = default;
150 AlgoAES128(const AlgoAES128&) = default;
151 AlgoAES128& operator=(const AlgoAES128&) = default;
152 AlgoAES128(AlgoAES128&&) = default;
153 AlgoAES128& operator=(AlgoAES128&&) = default;
154
155 /**
156 * @brief Decrypt the incoming payload
157 *
158 * @param[in] packet - Incoming IPMI packet
159 * @param[in] sessHeaderLen - Length of the IPMI Session Header
160 * @param[in] payloadLen - Length of the encrypted IPMI payload
161 *
162 * @return decrypted payload if the operation is successful
163 */
Vernon Mauery70fd29c2017-11-30 13:11:43 -0800164 std::vector<uint8_t> decryptPayload(
165 const std::vector<uint8_t>& packet,
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530166 const size_t sessHeaderLen,
167 const size_t payloadLen) const override;
168
169 /**
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 */
Vernon Mauery70fd29c2017-11-30 13:11:43 -0800177 std::vector<uint8_t> encryptPayload(
178 std::vector<uint8_t>& payload) const override;
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530179
180 private:
181
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 */
Vernon Mauery70fd29c2017-11-30 13:11:43 -0800191 std::vector<uint8_t> decryptData(const uint8_t* iv,
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530192 const uint8_t* input,
193 const int inputLen) const;
194
195 /**
196 * @brief Encrypt the passed data
197 *
198 * @param[in] input - Pointer to input data
199 * @param[in] inputLen - Length of input data
200 *
201 * @return encrypted data if the operation is successful
202 */
Vernon Mauery70fd29c2017-11-30 13:11:43 -0800203 std::vector<uint8_t> encryptData(const uint8_t* input,
Tom Joseph06f7a3c2017-01-25 14:32:05 +0530204 const int inputLen) const;
205};
206
Tom Josephd08b5232017-01-24 18:15:39 +0530207}// namespace crypt
208
209}// namespace cipher
210