blob: 7b895c518bf2c1bccfbf9bf0cac578b19dc6d8a5 [file] [log] [blame]
Tom Joseph77531db2017-01-10 15:44:44 +05301#pragma once
2
3#include <openssl/sha.h>
4#include <array>
5#include <vector>
6
7namespace cipher
8{
9
10namespace integrity
11{
12
13using Buffer = std::vector<uint8_t>;
14using Key = std::array<uint8_t, SHA_DIGEST_LENGTH>;
15
16/*
17 * RSP needs more keying material than can be provided by session integrity key
18 * alone. As a result all keying material for the RSP integrity algorithms
19 * will be generated by processing a pre-defined set of constants using HMAC per
20 * [RFC2104], keyed by SIK. These constants are constructed using a hexadecimal
21 * octet value repeated up to the HMAC block size in length starting with the
22 * constant 01h. This mechanism can be used to derive up to 255
23 * HMAC-block-length pieces of keying material from a single SIK. For the
24 * mandatory integrity algorithm HMAC-SHA1-96, processing the following
25 * constant will generate the required amount of keying material.
26 */
27constexpr Key const1 = { 0x01, 0x01, 0x01, 0x01, 0x01,
28 0x01, 0x01, 0x01, 0x01, 0x01,
29 0x01, 0x01, 0x01, 0x01, 0x01,
30 0x01, 0x01, 0x01, 0x01, 0x01
31 };
32
33/*
34 * @enum Integrity Algorithms
35 *
36 * The Integrity Algorithm Number specifies the algorithm used to generate the
37 * contents for the AuthCode “signature” field that accompanies authenticated
38 * IPMI v2.0/RMCP+ messages once the session has been established. If the
39 * Integrity Algorithm is none the AuthCode value is not calculated and the
40 * AuthCode field in the message is not present.
41 */
42enum class Algorithms : uint8_t
43{
44 NONE, // Mandatory
45 HMAC_SHA1_96, // Mandatory
46 HMAC_MD5_128, // Optional
47 MD5_128, // Optional
48 HMAC_SHA256_128, // Optional
49};
50
51/*
52 * @class Interface
53 *
54 * Interface is the base class for the Integrity Algorithms.
55 * Unless otherwise specified, the integrity algorithm is applied to the packet
56 * data starting with the AuthType/Format field up to and including the field
57 * that immediately precedes the AuthCode field itself.
58 */
59class Interface
60{
61 public:
62 /*
63 * @brief Constructor for Interface
64 *
65 * @param[in] - Session Integrity Key to generate K1
66 * @param[in] - Additional keying material to generate K1
67 * @param[in] - AuthCode length
68 */
69 explicit Interface(const Buffer& sik,
70 const Key& addKey,
71 size_t authLength);
72
73 Interface() = delete;
74 virtual ~Interface() = default;
75 Interface(const Interface&) = default;
76 Interface& operator=(const Interface&) = default;
77 Interface(Interface&&) = default;
78 Interface& operator=(Interface&&) = default;
79
80 /*
81 * @brief Verify the integrity data of the packet
82 *
83 * @param[in] packet - Incoming IPMI packet
84 * @param[in] packetLen - Packet length excluding authCode
85 * @param[in] integrityData - Iterator to the authCode in the packet
86 *
87 * @return true if authcode in the packet is equal to one generated
88 * using integrity algorithm on the packet data, false otherwise
89 */
90 bool virtual verifyIntegrityData(
91 const Buffer& packet,
92 const size_t packetLen,
93 Buffer::const_iterator integrityData) const = 0;
94
95 /*
96 * @brief Generate integrity data for the outgoing IPMI packet
97 *
98 * @param[in] input - Outgoing IPMI packet
99 *
100 * @return authcode for the outgoing IPMI packet
101 *
102 */
103 Buffer virtual generateIntegrityData(const Buffer& input) const = 0;
104
Tom Joseph1e7aa192017-02-24 17:16:49 +0530105 /**
106 * @brief Check if the Integrity algorithm is supported
107 *
108 * @param[in] algo - integrity algorithm
109 *
110 * @return true if algorithm is supported else false
111 *
112 */
113 static bool isAlgorithmSupported(Algorithms algo)
114 {
115 if (algo == Algorithms::NONE || algo == Algorithms::HMAC_SHA1_96)
116 {
117 return true;
118 }
119 else
120 {
121 return false;
122 }
123 }
124
Tom Joseph77531db2017-01-10 15:44:44 +0530125 /*
126 * AuthCode field length varies based on the integrity algorithm, for
127 * HMAC-SHA1-96 the authcode field is 12 bytes. For HMAC-SHA256-128 and
128 * HMAC-MD5-128 the authcode field is 16 bytes.
129 */
130 size_t authCodeLength;
131
132 protected:
133
134 // K1 key used to generated the integrity data
135 Key K1;
136};
137
Tom Josephd212a6d2017-01-10 15:48:40 +0530138/*
139 * @class AlgoSHA1
140 *
141 * @brief Implementation of the HMAC-SHA1-96 Integrity algorithm
142 *
143 * HMAC-SHA1-96 take the Session Integrity Key and use it to generate K1. K1 is
144 * then used as the key for use in HMAC to produce the AuthCode field.
145 * For “one-key” logins, the user’s key (password) is used in the creation of
146 * the Session Integrity Key. When the HMAC-SHA1-96 Integrity Algorithm is used
147 * the resulting AuthCode field is 12 bytes (96 bits).
148 */
149class AlgoSHA1 final : public Interface
150{
151 public:
152 static constexpr size_t SHA1_96_AUTHCODE_LENGTH = 12;
153
154 /*
155 * @brief Constructor for AlgoSHA1
156 *
157 * @param[in] - Session Integrity Key
158 */
159 explicit AlgoSHA1(const Buffer& sik) :
160 Interface(sik, const1, SHA1_96_AUTHCODE_LENGTH) {}
161
162 AlgoSHA1() = delete;
163 ~AlgoSHA1() = default;
164 AlgoSHA1(const AlgoSHA1&) = default;
165 AlgoSHA1& operator=(const AlgoSHA1&) = default;
166 AlgoSHA1(AlgoSHA1&&) = default;
167 AlgoSHA1& operator=(AlgoSHA1&&) = default;
168
169 /*
170 * @brief Verify the integrity data of the packet
171 *
172 * @param[in] packet - Incoming IPMI packet
173 * @param[in] length - Length of the data in the packet to calculate
174 * the integrity data
175 * @param[in] integrityData - Iterator to the authCode in the packet
176 *
177 * @return true if authcode in the packet is equal to one generated
178 * using integrity algorithm on the packet data, false otherwise
179 */
180 bool verifyIntegrityData(
181 const Buffer& packet,
182 const size_t length,
183 Buffer::const_iterator integrityData) const override;
184
185 /*
186 * @brief Generate integrity data for the outgoing IPMI packet
187 *
188 * @param[in] input - Outgoing IPMI packet
189 *
190 * @return on success return the integrity data for the outgoing IPMI
191 * packet
192 */
193 Buffer generateIntegrityData(const Buffer& packet) const override;
194
195 private:
196 /*
197 * @brief Generate HMAC based on HMAC-SHA1-96 algorithm
198 *
199 * @param[in] input - pointer to the message
200 * @param[in] length - length of the message
201 *
202 * @return on success returns the message authentication code
203 *
204 */
205 Buffer generateHMAC(const uint8_t* input, const size_t len) const;
206};
207
Tom Joseph77531db2017-01-10 15:44:44 +0530208}// namespace integrity
209
210}// namespace cipher
211