blob: 0d869c7d9e9f2b560140b3fe0a74f058d1de4c6f [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
Tom Joseph77531db2017-01-10 15:44:44 +053013using Key = std::array<uint8_t, SHA_DIGEST_LENGTH>;
14
15/*
16 * RSP needs more keying material than can be provided by session integrity key
17 * alone. As a result all keying material for the RSP integrity algorithms
18 * will be generated by processing a pre-defined set of constants using HMAC per
19 * [RFC2104], keyed by SIK. These constants are constructed using a hexadecimal
20 * octet value repeated up to the HMAC block size in length starting with the
21 * constant 01h. This mechanism can be used to derive up to 255
22 * HMAC-block-length pieces of keying material from a single SIK. For the
23 * mandatory integrity algorithm HMAC-SHA1-96, processing the following
24 * constant will generate the required amount of keying material.
25 */
26constexpr Key const1 = { 0x01, 0x01, 0x01, 0x01, 0x01,
27 0x01, 0x01, 0x01, 0x01, 0x01,
28 0x01, 0x01, 0x01, 0x01, 0x01,
29 0x01, 0x01, 0x01, 0x01, 0x01
30 };
31
Tom Joseph3563f8f2017-05-08 15:42:54 +053032/**
Tom Joseph77531db2017-01-10 15:44:44 +053033 * @enum Integrity Algorithms
34 *
35 * The Integrity Algorithm Number specifies the algorithm used to generate the
36 * contents for the AuthCode “signature” field that accompanies authenticated
37 * IPMI v2.0/RMCP+ messages once the session has been established. If the
38 * Integrity Algorithm is none the AuthCode value is not calculated and the
39 * AuthCode field in the message is not present.
40 */
41enum class Algorithms : uint8_t
42{
43 NONE, // Mandatory
44 HMAC_SHA1_96, // Mandatory
45 HMAC_MD5_128, // Optional
46 MD5_128, // Optional
47 HMAC_SHA256_128, // Optional
48};
49
Tom Joseph3563f8f2017-05-08 15:42:54 +053050/**
Tom Joseph77531db2017-01-10 15:44:44 +053051 * @class Interface
52 *
53 * Interface is the base class for the Integrity Algorithms.
54 * Unless otherwise specified, the integrity algorithm is applied to the packet
55 * data starting with the AuthType/Format field up to and including the field
56 * that immediately precedes the AuthCode field itself.
57 */
58class Interface
59{
60 public:
Tom Joseph3563f8f2017-05-08 15:42:54 +053061 /**
Tom Joseph77531db2017-01-10 15:44:44 +053062 * @brief Constructor for Interface
63 *
64 * @param[in] - Session Integrity Key to generate K1
65 * @param[in] - Additional keying material to generate K1
66 * @param[in] - AuthCode length
67 */
Vernon Mauery70fd29c2017-11-30 13:11:43 -080068 explicit Interface(const std::vector<uint8_t>& sik,
Tom Joseph77531db2017-01-10 15:44:44 +053069 const Key& addKey,
70 size_t authLength);
71
72 Interface() = delete;
73 virtual ~Interface() = default;
74 Interface(const Interface&) = default;
75 Interface& operator=(const Interface&) = default;
76 Interface(Interface&&) = default;
77 Interface& operator=(Interface&&) = default;
78
Tom Joseph3563f8f2017-05-08 15:42:54 +053079 /**
Tom Joseph77531db2017-01-10 15:44:44 +053080 * @brief Verify the integrity data of the packet
81 *
82 * @param[in] packet - Incoming IPMI packet
83 * @param[in] packetLen - Packet length excluding authCode
84 * @param[in] integrityData - Iterator to the authCode in the packet
85 *
86 * @return true if authcode in the packet is equal to one generated
87 * using integrity algorithm on the packet data, false otherwise
88 */
89 bool virtual verifyIntegrityData(
Vernon Mauery70fd29c2017-11-30 13:11:43 -080090 const std::vector<uint8_t>& packet,
Tom Joseph77531db2017-01-10 15:44:44 +053091 const size_t packetLen,
Vernon Mauery70fd29c2017-11-30 13:11:43 -080092 std::vector<uint8_t>::const_iterator integrityData) const = 0;
Tom Joseph77531db2017-01-10 15:44:44 +053093
Tom Joseph3563f8f2017-05-08 15:42:54 +053094 /**
Tom Joseph77531db2017-01-10 15:44:44 +053095 * @brief Generate integrity data for the outgoing IPMI packet
96 *
97 * @param[in] input - Outgoing IPMI packet
98 *
99 * @return authcode for the outgoing IPMI packet
100 *
101 */
Vernon Mauery70fd29c2017-11-30 13:11:43 -0800102 std::vector<uint8_t> virtual generateIntegrityData(
103 const std::vector<uint8_t>& input) const = 0;
Tom Joseph77531db2017-01-10 15:44:44 +0530104
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 Joseph3563f8f2017-05-08 15:42:54 +0530125 /** @brief Authcode field
126 *
127 * AuthCode field length varies based on the integrity algorithm, for
128 * HMAC-SHA1-96 the authcode field is 12 bytes. For HMAC-SHA256-128 and
129 * HMAC-MD5-128 the authcode field is 16 bytes.
Tom Joseph77531db2017-01-10 15:44:44 +0530130 */
131 size_t authCodeLength;
132
133 protected:
134
Tom Joseph3563f8f2017-05-08 15:42:54 +0530135 /** @brief K1 key used to generated the integrity data. */
Tom Joseph77531db2017-01-10 15:44:44 +0530136 Key K1;
137};
138
Tom Joseph3563f8f2017-05-08 15:42:54 +0530139/**
Tom Josephd212a6d2017-01-10 15:48:40 +0530140 * @class AlgoSHA1
141 *
142 * @brief Implementation of the HMAC-SHA1-96 Integrity algorithm
143 *
144 * HMAC-SHA1-96 take the Session Integrity Key and use it to generate K1. K1 is
145 * then used as the key for use in HMAC to produce the AuthCode field.
146 * For “one-key” logins, the user’s key (password) is used in the creation of
147 * the Session Integrity Key. When the HMAC-SHA1-96 Integrity Algorithm is used
148 * the resulting AuthCode field is 12 bytes (96 bits).
149 */
150class AlgoSHA1 final : public Interface
151{
152 public:
153 static constexpr size_t SHA1_96_AUTHCODE_LENGTH = 12;
154
Tom Joseph3563f8f2017-05-08 15:42:54 +0530155 /**
Tom Josephd212a6d2017-01-10 15:48:40 +0530156 * @brief Constructor for AlgoSHA1
157 *
158 * @param[in] - Session Integrity Key
159 */
Vernon Mauery70fd29c2017-11-30 13:11:43 -0800160 explicit AlgoSHA1(const std::vector<uint8_t>& sik) :
Tom Josephd212a6d2017-01-10 15:48:40 +0530161 Interface(sik, const1, SHA1_96_AUTHCODE_LENGTH) {}
162
163 AlgoSHA1() = delete;
164 ~AlgoSHA1() = default;
165 AlgoSHA1(const AlgoSHA1&) = default;
166 AlgoSHA1& operator=(const AlgoSHA1&) = default;
167 AlgoSHA1(AlgoSHA1&&) = default;
168 AlgoSHA1& operator=(AlgoSHA1&&) = default;
169
Tom Joseph3563f8f2017-05-08 15:42:54 +0530170 /**
Tom Josephd212a6d2017-01-10 15:48:40 +0530171 * @brief Verify the integrity data of the packet
172 *
173 * @param[in] packet - Incoming IPMI packet
174 * @param[in] length - Length of the data in the packet to calculate
175 * the integrity data
176 * @param[in] integrityData - Iterator to the authCode in the packet
177 *
178 * @return true if authcode in the packet is equal to one generated
179 * using integrity algorithm on the packet data, false otherwise
180 */
181 bool verifyIntegrityData(
Vernon Mauery70fd29c2017-11-30 13:11:43 -0800182 const std::vector<uint8_t>& packet,
Tom Josephd212a6d2017-01-10 15:48:40 +0530183 const size_t length,
Vernon Mauery70fd29c2017-11-30 13:11:43 -0800184 std::vector<uint8_t>::const_iterator integrityData)
185 const override;
Tom Josephd212a6d2017-01-10 15:48:40 +0530186
Tom Joseph3563f8f2017-05-08 15:42:54 +0530187 /**
Tom Josephd212a6d2017-01-10 15:48:40 +0530188 * @brief Generate integrity data for the outgoing IPMI packet
189 *
190 * @param[in] input - Outgoing IPMI packet
191 *
192 * @return on success return the integrity data for the outgoing IPMI
193 * packet
194 */
Vernon Mauery70fd29c2017-11-30 13:11:43 -0800195 std::vector<uint8_t> generateIntegrityData(
196 const std::vector<uint8_t>& packet) const override;
Tom Josephd212a6d2017-01-10 15:48:40 +0530197
198 private:
Tom Joseph3563f8f2017-05-08 15:42:54 +0530199 /**
Tom Josephd212a6d2017-01-10 15:48:40 +0530200 * @brief Generate HMAC based on HMAC-SHA1-96 algorithm
201 *
202 * @param[in] input - pointer to the message
203 * @param[in] length - length of the message
204 *
205 * @return on success returns the message authentication code
206 *
207 */
Vernon Mauery70fd29c2017-11-30 13:11:43 -0800208 std::vector<uint8_t> generateHMAC(const uint8_t* input,
209 const size_t len) const;
Tom Josephd212a6d2017-01-10 15:48:40 +0530210};
211
Tom Joseph77531db2017-01-10 15:44:44 +0530212}// namespace integrity
213
214}// namespace cipher
215