blob: 3e003b6a3d651d6ba41402a1b86d37f98605d650 [file] [log] [blame]
Tom Joseph77531db2017-01-10 15:44:44 +05301#pragma once
2
Tom Joseph77531db2017-01-10 15:44:44 +05303#include <array>
4#include <vector>
Vernon Mauery9b307be2017-11-22 09:28:16 -08005#include "rmcp.hpp"
Tom Joseph77531db2017-01-10 15:44:44 +05306
7namespace cipher
8{
9
10namespace integrity
11{
12
Tom Joseph3563f8f2017-05-08 15:42:54 +053013/**
Tom Joseph77531db2017-01-10 15:44:44 +053014 * @enum Integrity Algorithms
15 *
16 * The Integrity Algorithm Number specifies the algorithm used to generate the
17 * contents for the AuthCode “signature” field that accompanies authenticated
18 * IPMI v2.0/RMCP+ messages once the session has been established. If the
19 * Integrity Algorithm is none the AuthCode value is not calculated and the
20 * AuthCode field in the message is not present.
21 */
22enum class Algorithms : uint8_t
23{
24 NONE, // Mandatory
25 HMAC_SHA1_96, // Mandatory
26 HMAC_MD5_128, // Optional
27 MD5_128, // Optional
28 HMAC_SHA256_128, // Optional
29};
30
Tom Joseph3563f8f2017-05-08 15:42:54 +053031/**
Tom Joseph77531db2017-01-10 15:44:44 +053032 * @class Interface
33 *
34 * Interface is the base class for the Integrity Algorithms.
35 * Unless otherwise specified, the integrity algorithm is applied to the packet
36 * data starting with the AuthType/Format field up to and including the field
37 * that immediately precedes the AuthCode field itself.
38 */
39class Interface
40{
41 public:
Tom Joseph3563f8f2017-05-08 15:42:54 +053042 /**
Tom Joseph77531db2017-01-10 15:44:44 +053043 * @brief Constructor for Interface
44 *
Tom Joseph77531db2017-01-10 15:44:44 +053045 * @param[in] - AuthCode length
46 */
Vernon Mauery9b307be2017-11-22 09:28:16 -080047 explicit Interface(size_t authLength)
48 : authCodeLength(authLength) {}
Tom Joseph77531db2017-01-10 15:44:44 +053049
50 Interface() = delete;
51 virtual ~Interface() = default;
52 Interface(const Interface&) = default;
53 Interface& operator=(const Interface&) = default;
54 Interface(Interface&&) = default;
55 Interface& operator=(Interface&&) = default;
56
Tom Joseph3563f8f2017-05-08 15:42:54 +053057 /**
Tom Joseph77531db2017-01-10 15:44:44 +053058 * @brief Verify the integrity data of the packet
59 *
60 * @param[in] packet - Incoming IPMI packet
61 * @param[in] packetLen - Packet length excluding authCode
62 * @param[in] integrityData - Iterator to the authCode in the packet
63 *
64 * @return true if authcode in the packet is equal to one generated
65 * using integrity algorithm on the packet data, false otherwise
66 */
67 bool virtual verifyIntegrityData(
Vernon Mauery70fd29c2017-11-30 13:11:43 -080068 const std::vector<uint8_t>& packet,
Tom Joseph77531db2017-01-10 15:44:44 +053069 const size_t packetLen,
Vernon Mauery70fd29c2017-11-30 13:11:43 -080070 std::vector<uint8_t>::const_iterator integrityData) const = 0;
Tom Joseph77531db2017-01-10 15:44:44 +053071
Tom Joseph3563f8f2017-05-08 15:42:54 +053072 /**
Tom Joseph77531db2017-01-10 15:44:44 +053073 * @brief Generate integrity data for the outgoing IPMI packet
74 *
75 * @param[in] input - Outgoing IPMI packet
76 *
77 * @return authcode for the outgoing IPMI packet
78 *
79 */
Vernon Mauery70fd29c2017-11-30 13:11:43 -080080 std::vector<uint8_t> virtual generateIntegrityData(
81 const std::vector<uint8_t>& input) const = 0;
Tom Joseph77531db2017-01-10 15:44:44 +053082
Tom Joseph1e7aa192017-02-24 17:16:49 +053083 /**
84 * @brief Check if the Integrity algorithm is supported
85 *
86 * @param[in] algo - integrity algorithm
87 *
88 * @return true if algorithm is supported else false
89 *
90 */
91 static bool isAlgorithmSupported(Algorithms algo)
92 {
93 if (algo == Algorithms::NONE || algo == Algorithms::HMAC_SHA1_96)
94 {
95 return true;
96 }
97 else
98 {
99 return false;
100 }
101 }
102
Vernon Mauery9b307be2017-11-22 09:28:16 -0800103 /**
104 * @brief Generate additional keying material based on SIK
105 *
106 * @note
107 * The IPMI 2.0 spec only states that the additional keying material is
108 * generated by running HMAC(constN) using SIK as the key. It does not
109 * state whether this is the integrity algorithm or the authentication
110 * algorithm. Other implementations of the RMCP+ algorithm (ipmitool
111 * and ipmiutil) are not consistent on this matter. But it does not
112 * really matter because based on any of the defined cipher suites, the
113 * integrity and authentication algorithms are both based on the same
114 * digest method (integrity::Algorithms::HMAC_SHA1_96 uses SHA1 and
115 * rakp_auth::Algorithms::RAKP_HMAC_SHA1 uses SHA1). None of the
116 * defined cipher suites mix and match digests for integrity and
117 * authentication. Generating Kn belongs in either the integrity or
118 * authentication classes, so in this implementation, integrity has
119 * been chosen.
120 *
121 * @param[in] sik - session integrity key
122 * @param[in] data - 20-byte Const_n
123 *
124 * @return on success returns the Kn based on this integrity class
125 *
126 */
127 std::vector<uint8_t> virtual generateKn(
128 const std::vector<uint8_t>& sik,
129 const rmcp::Const_n& data) const = 0;
130
Tom Joseph3563f8f2017-05-08 15:42:54 +0530131 /** @brief Authcode field
132 *
133 * AuthCode field length varies based on the integrity algorithm, for
134 * HMAC-SHA1-96 the authcode field is 12 bytes. For HMAC-SHA256-128 and
135 * HMAC-MD5-128 the authcode field is 16 bytes.
Tom Joseph77531db2017-01-10 15:44:44 +0530136 */
137 size_t authCodeLength;
138
139 protected:
140
Tom Joseph3563f8f2017-05-08 15:42:54 +0530141 /** @brief K1 key used to generated the integrity data. */
Vernon Mauery9b307be2017-11-22 09:28:16 -0800142 std::vector<uint8_t> k1;
Tom Joseph77531db2017-01-10 15:44:44 +0530143};
144
Tom Joseph3563f8f2017-05-08 15:42:54 +0530145/**
Tom Josephd212a6d2017-01-10 15:48:40 +0530146 * @class AlgoSHA1
147 *
148 * @brief Implementation of the HMAC-SHA1-96 Integrity algorithm
149 *
150 * HMAC-SHA1-96 take the Session Integrity Key and use it to generate K1. K1 is
151 * then used as the key for use in HMAC to produce the AuthCode field.
152 * For “one-key” logins, the user’s key (password) is used in the creation of
153 * the Session Integrity Key. When the HMAC-SHA1-96 Integrity Algorithm is used
154 * the resulting AuthCode field is 12 bytes (96 bits).
155 */
156class AlgoSHA1 final : public Interface
157{
158 public:
159 static constexpr size_t SHA1_96_AUTHCODE_LENGTH = 12;
160
Tom Joseph3563f8f2017-05-08 15:42:54 +0530161 /**
Tom Josephd212a6d2017-01-10 15:48:40 +0530162 * @brief Constructor for AlgoSHA1
163 *
164 * @param[in] - Session Integrity Key
165 */
Vernon Mauery9b307be2017-11-22 09:28:16 -0800166 explicit AlgoSHA1(const std::vector<uint8_t>& sik);
Tom Josephd212a6d2017-01-10 15:48:40 +0530167
168 AlgoSHA1() = delete;
169 ~AlgoSHA1() = default;
170 AlgoSHA1(const AlgoSHA1&) = default;
171 AlgoSHA1& operator=(const AlgoSHA1&) = default;
172 AlgoSHA1(AlgoSHA1&&) = default;
173 AlgoSHA1& operator=(AlgoSHA1&&) = default;
174
Tom Joseph3563f8f2017-05-08 15:42:54 +0530175 /**
Tom Josephd212a6d2017-01-10 15:48:40 +0530176 * @brief Verify the integrity data of the packet
177 *
178 * @param[in] packet - Incoming IPMI packet
179 * @param[in] length - Length of the data in the packet to calculate
180 * the integrity data
181 * @param[in] integrityData - Iterator to the authCode in the packet
182 *
183 * @return true if authcode in the packet is equal to one generated
184 * using integrity algorithm on the packet data, false otherwise
185 */
186 bool verifyIntegrityData(
Vernon Mauery70fd29c2017-11-30 13:11:43 -0800187 const std::vector<uint8_t>& packet,
Tom Josephd212a6d2017-01-10 15:48:40 +0530188 const size_t length,
Vernon Mauery70fd29c2017-11-30 13:11:43 -0800189 std::vector<uint8_t>::const_iterator integrityData)
190 const override;
Tom Josephd212a6d2017-01-10 15:48:40 +0530191
Tom Joseph3563f8f2017-05-08 15:42:54 +0530192 /**
Tom Josephd212a6d2017-01-10 15:48:40 +0530193 * @brief Generate integrity data for the outgoing IPMI packet
194 *
195 * @param[in] input - Outgoing IPMI packet
196 *
197 * @return on success return the integrity data for the outgoing IPMI
198 * packet
199 */
Vernon Mauery70fd29c2017-11-30 13:11:43 -0800200 std::vector<uint8_t> generateIntegrityData(
201 const std::vector<uint8_t>& packet) const override;
Tom Josephd212a6d2017-01-10 15:48:40 +0530202
Vernon Mauery9b307be2017-11-22 09:28:16 -0800203 /**
204 * @brief Generate additional keying material based on SIK
205 *
206 * @param[in] sik - session integrity key
207 * @param[in] data - 20-byte Const_n
208 *
209 * @return on success returns the Kn based on HMAC-SHA1
210 *
211 */
212 std::vector<uint8_t> generateKn(
213 const std::vector<uint8_t>& sik,
214 const rmcp::Const_n& const_n) const;
215
Tom Josephd212a6d2017-01-10 15:48:40 +0530216 private:
Tom Joseph3563f8f2017-05-08 15:42:54 +0530217 /**
Tom Josephd212a6d2017-01-10 15:48:40 +0530218 * @brief Generate HMAC based on HMAC-SHA1-96 algorithm
219 *
220 * @param[in] input - pointer to the message
221 * @param[in] length - length of the message
222 *
223 * @return on success returns the message authentication code
224 *
225 */
Vernon Mauery70fd29c2017-11-30 13:11:43 -0800226 std::vector<uint8_t> generateHMAC(const uint8_t* input,
227 const size_t len) const;
Tom Josephd212a6d2017-01-10 15:48:40 +0530228};
229
Tom Joseph77531db2017-01-10 15:44:44 +0530230}// namespace integrity
231
232}// namespace cipher
233