blob: 6bd32d0951b97f9ea1c64966b2c5def9c6cfad4e [file] [log] [blame]
Tom Joseph8c0446c2016-08-05 07:13:07 -05001#pragma once
2
3#include <array>
4#include <vector>
Tom Josephba11f792017-01-24 18:21:45 +05305#include "crypt_algo.hpp"
Tom Josephdd1be1a2017-01-10 16:10:29 +05306#include "integrity_algo.hpp"
Tom Joseph8c0446c2016-08-05 07:13:07 -05007
8namespace cipher
9{
10namespace rakp_auth
11{
Tom Joseph8c0446c2016-08-05 07:13:07 -050012constexpr size_t USER_KEY_MAX_LENGTH = 20;
13constexpr size_t BMC_RANDOM_NUMBER_LEN = 16;
14constexpr size_t REMOTE_CONSOLE_RANDOM_NUMBER_LEN = 16;
Tom Joseph56527b92018-03-21 19:31:58 +053015extern const std::string userName;
Tom Joseph8c0446c2016-08-05 07:13:07 -050016
Tom Joseph3563f8f2017-05-08 15:42:54 +053017/**
Tom Joseph8c0446c2016-08-05 07:13:07 -050018 * @enum RAKP Authentication Algorithms
19 *
20 * RMCP+ Authenticated Key-Exchange Protocol (RAKP)
21 *
22 * RAKP-None is not supported as per the following recommendation
23 * (https://www.us-cert.gov/ncas/alerts/TA13-207A)
24 * ("cipher 0" is an option enabled by default on many IPMI enabled devices that
25 * allows authentication to be bypassed. Disable "cipher 0" to prevent
26 * attackers from bypassing authentication and sending arbitrary IPMI commands.)
27 */
28enum class Algorithms : uint8_t
29{
30 RAKP_NONE = 0, // Mandatory
31 RAKP_HMAC_SHA1, // Mandatory
32 RAKP_HMAC_MD5, // Optional
33 RAKP_HMAC_SHA256, // Optional
34 // Reserved used to indicate an invalid authentication algorithm
35 RAKP_HMAC_INVALID = 0xB0
36};
37
Tom Joseph3563f8f2017-05-08 15:42:54 +053038/**
Tom Joseph8c0446c2016-08-05 07:13:07 -050039 * @class Interface
40 *
41 * Interface is the base class for the Authentication Algorithms.
42 * The Authentication Algorithm specifies the type of authentication “handshake”
43 * process that is used and identifies any particular variations of hashing or
44 * signature algorithm that is used as part of the process.
45 *
46 */
47class Interface
48{
49 public:
Tom Josephba11f792017-01-24 18:21:45 +053050 explicit Interface(integrity::Algorithms intAlgo,
51 crypt::Algorithms cryptAlgo) :
52 intAlgo(intAlgo),
53 cryptAlgo(cryptAlgo) {}
54
Tom Josephdd1be1a2017-01-10 16:10:29 +053055 Interface() = delete;
Tom Joseph8c0446c2016-08-05 07:13:07 -050056 virtual ~Interface() = default;
57 Interface(const Interface&) = default;
58 Interface& operator=(const Interface&) = default;
59 Interface(Interface&&) = default;
60 Interface& operator=(Interface&&) = default;
61
Tom Joseph3563f8f2017-05-08 15:42:54 +053062 /**
Tom Joseph8c0446c2016-08-05 07:13:07 -050063 * @brief Generate the Hash Message Authentication Code
64 *
65 * This API is invoked to generate the Key Exchange Authentication Code
66 * in the RAKP2 and RAKP4 sequence and for generating the Session
67 * Integrity Key.
68 *
69 * @param input message
70 *
71 * @return hash output
72 *
73 * @note The user key which is the secret key for the hash operation
74 * needs to be set before this operation.
75 */
76 std::vector<uint8_t> virtual generateHMAC(
Vernon Mauery70fd29c2017-11-30 13:11:43 -080077 const std::vector<uint8_t>& input) const = 0;
Tom Joseph8c0446c2016-08-05 07:13:07 -050078
Tom Joseph3563f8f2017-05-08 15:42:54 +053079 /**
Tom Joseph8c0446c2016-08-05 07:13:07 -050080 * @brief Generate the Integrity Check Value
81 *
82 * This API is invoked in the RAKP4 sequence for generating the
83 * Integrity Check Value.
84 *
85 * @param input message
86 *
87 * @return hash output
88 *
89 * @note The session integrity key which is the secret key for the
90 * hash operation needs to be set before this operation.
91 */
92 std::vector<uint8_t> virtual generateICV(
Vernon Mauery70fd29c2017-11-30 13:11:43 -080093 const std::vector<uint8_t>& input) const = 0;
Tom Joseph8c0446c2016-08-05 07:13:07 -050094
Vernon Mauery9b307be2017-11-22 09:28:16 -080095 /**
96 * @brief Check if the Authentication algorithm is supported
97 *
98 * @param[in] algo - authentication algorithm
99 *
100 * @return true if algorithm is supported else false
101 *
102 */
103 static bool isAlgorithmSupported(Algorithms algo)
104 {
105 if (algo == Algorithms::RAKP_NONE ||
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800106 algo == Algorithms::RAKP_HMAC_SHA1 ||
107 algo == Algorithms::RAKP_HMAC_SHA256)
Vernon Mauery9b307be2017-11-22 09:28:16 -0800108 {
109 return true;
110 }
111 else
112 {
113 return false;
114 }
115 }
116
Tom Joseph8c0446c2016-08-05 07:13:07 -0500117 // User Key is hardcoded to PASSW0RD till the IPMI User account
118 // management is in place.
Tom Josephe2e97662017-03-02 17:12:46 +0530119 std::array<uint8_t, USER_KEY_MAX_LENGTH> userKey = {"0penBmc"};
Tom Joseph8c0446c2016-08-05 07:13:07 -0500120
121 // Managed System Random Number
122 std::array<uint8_t, BMC_RANDOM_NUMBER_LEN> bmcRandomNum;
123
124 // Remote Console Random Number
125 std::array<uint8_t, REMOTE_CONSOLE_RANDOM_NUMBER_LEN> rcRandomNum;
126
127 // Session Integrity Key
128 std::vector<uint8_t> sessionIntegrityKey;
Tom Josephdd1be1a2017-01-10 16:10:29 +0530129
Tom Joseph3563f8f2017-05-08 15:42:54 +0530130 /**
Tom Josephdd1be1a2017-01-10 16:10:29 +0530131 * Integrity Algorithm is activated and set in the session data only
132 * once the session setup is succeeded in the RAKP34 command. But the
133 * integrity algorithm is negotiated in the Open Session Request command
Tom Josephba11f792017-01-24 18:21:45 +0530134 * . So the integrity algorithm successfully negotiated is stored
135 * in the authentication algorithm's instance.
Tom Josephdd1be1a2017-01-10 16:10:29 +0530136 */
137 integrity::Algorithms intAlgo;
Tom Josephba11f792017-01-24 18:21:45 +0530138
Tom Joseph3563f8f2017-05-08 15:42:54 +0530139 /**
Tom Josephba11f792017-01-24 18:21:45 +0530140 * Confidentiality Algorithm is activated and set in the session data
141 * only once the session setup is succeeded in the RAKP34 command. But
142 * the confidentiality algorithm is negotiated in the Open Session
143 * Request command. So the confidentiality algorithm successfully
144 * negotiated is stored in the authentication algorithm's instance.
145 */
146 crypt::Algorithms cryptAlgo;
Tom Joseph8c0446c2016-08-05 07:13:07 -0500147};
148
Tom Joseph3563f8f2017-05-08 15:42:54 +0530149/**
Tom Joseph8c0446c2016-08-05 07:13:07 -0500150 * @class AlgoSHA1
151 *
152 * RAKP-HMAC-SHA1 specifies the use of RAKP messages for the key exchange
153 * portion of establishing the session, and that HMAC-SHA1 (per [RFC2104]) is
154 * used to create 20-byte Key Exchange Authentication Code fields in RAKP
155 * Message 2 and RAKP Message 3. HMAC-SHA1-96(per [RFC2404]) is used for
156 * generating a 12-byte Integrity Check Value field for RAKP Message 4.
157 */
158
159class AlgoSHA1 : public Interface
160{
161 public:
Vernon Mauery2207f512017-11-30 10:48:08 -0800162 static constexpr size_t integrityCheckValueLength = 12;
163
Tom Josephba11f792017-01-24 18:21:45 +0530164 explicit AlgoSHA1(integrity::Algorithms intAlgo,
165 crypt::Algorithms cryptAlgo) :
166 Interface(intAlgo, cryptAlgo) {}
167
Tom Josephdd1be1a2017-01-10 16:10:29 +0530168 AlgoSHA1() = delete;
Tom Joseph8c0446c2016-08-05 07:13:07 -0500169 ~AlgoSHA1() = default;
170 AlgoSHA1(const AlgoSHA1&) = default;
171 AlgoSHA1& operator=(const AlgoSHA1&) = default;
172 AlgoSHA1(AlgoSHA1&&) = default;
173 AlgoSHA1& operator=(AlgoSHA1&&) = default;
174
Vernon Mauery70fd29c2017-11-30 13:11:43 -0800175 std::vector<uint8_t> generateHMAC(
176 const std::vector<uint8_t>& input) const override;
Tom Joseph8c0446c2016-08-05 07:13:07 -0500177
Vernon Mauery70fd29c2017-11-30 13:11:43 -0800178 std::vector<uint8_t> generateICV(
179 const std::vector<uint8_t>& input) const override;
Tom Joseph8c0446c2016-08-05 07:13:07 -0500180};
181
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800182/**
183 * @class AlgoSHA256
184 *
185 * RAKP-HMAC-SHA256 specifies the use of RAKP messages for the key exchange
186 * portion of establishing the session, and that HMAC-SHA256 (per [FIPS 180-2]
187 * and [RFC4634] and is used to create a 32-byte Key Exchange Authentication
188 * Code fields in RAKP Message 2 and RAKP Message 3. HMAC-SHA256-128 (per
189 * [RFC4868]) is used for generating a 16-byte Integrity Check Value field for
190 * RAKP Message 4.
191 */
192
193class AlgoSHA256 : public Interface
194{
195 public:
196 static constexpr size_t integrityCheckValueLength = 16;
197
198 explicit AlgoSHA256(integrity::Algorithms intAlgo,
199 crypt::Algorithms cryptAlgo) :
200 Interface(intAlgo, cryptAlgo) {}
201
202 ~AlgoSHA256() = default;
203 AlgoSHA256(const AlgoSHA256&) = default;
204 AlgoSHA256& operator=(const AlgoSHA256&) = default;
205 AlgoSHA256(AlgoSHA256&&) = default;
206 AlgoSHA256& operator=(AlgoSHA256&&) = default;
207
208 std::vector<uint8_t> generateHMAC(
209 const std::vector<uint8_t>& input) const override;
210
211 std::vector<uint8_t> generateICV(
212 const std::vector<uint8_t>& input) const override;
213};
214
Tom Joseph8c0446c2016-08-05 07:13:07 -0500215}// namespace auth
216
217}// namespace cipher
218