blob: 6ed0b47a01c22a09066657b4f5f0de87f356f632 [file] [log] [blame]
Tom Joseph8c0446c2016-08-05 07:13:07 -05001#pragma once
2
Tom Josephba11f792017-01-24 18:21:45 +05303#include "crypt_algo.hpp"
Tom Josephdd1be1a2017-01-10 16:10:29 +05304#include "integrity_algo.hpp"
Tom Joseph8c0446c2016-08-05 07:13:07 -05005
Vernon Mauery9e801a22018-10-12 13:20:49 -07006#include <array>
7#include <vector>
8
Tom Joseph8c0446c2016-08-05 07:13:07 -05009namespace cipher
10{
11namespace rakp_auth
12{
Tom Joseph8c0446c2016-08-05 07:13:07 -050013constexpr size_t USER_KEY_MAX_LENGTH = 20;
14constexpr size_t BMC_RANDOM_NUMBER_LEN = 16;
15constexpr size_t REMOTE_CONSOLE_RANDOM_NUMBER_LEN = 16;
Tom Joseph56527b92018-03-21 19:31:58 +053016extern const std::string userName;
Tom Joseph8c0446c2016-08-05 07:13:07 -050017
Tom Joseph3563f8f2017-05-08 15:42:54 +053018/**
Tom Joseph8c0446c2016-08-05 07:13:07 -050019 * @enum RAKP Authentication Algorithms
20 *
21 * RMCP+ Authenticated Key-Exchange Protocol (RAKP)
22 *
23 * RAKP-None is not supported as per the following recommendation
24 * (https://www.us-cert.gov/ncas/alerts/TA13-207A)
25 * ("cipher 0" is an option enabled by default on many IPMI enabled devices that
26 * allows authentication to be bypassed. Disable "cipher 0" to prevent
27 * attackers from bypassing authentication and sending arbitrary IPMI commands.)
28 */
29enum class Algorithms : uint8_t
30{
Tom Josephfe5a6452018-07-30 18:15:12 +053031 RAKP_NONE = 0, // Mandatory (implemented, not supported)
32 RAKP_HMAC_SHA1, // Mandatory (implemented, default choice in ipmitool)
33 RAKP_HMAC_MD5, // Optional (not implemented)
34 RAKP_HMAC_SHA256, // Optional (implemented, best available)
Tom Joseph8c0446c2016-08-05 07:13:07 -050035 // Reserved used to indicate an invalid authentication algorithm
36 RAKP_HMAC_INVALID = 0xB0
37};
38
Tom Joseph3563f8f2017-05-08 15:42:54 +053039/**
Tom Joseph8c0446c2016-08-05 07:13:07 -050040 * @class Interface
41 *
42 * Interface is the base class for the Authentication Algorithms.
43 * The Authentication Algorithm specifies the type of authentication “handshake”
44 * process that is used and identifies any particular variations of hashing or
45 * signature algorithm that is used as part of the process.
46 *
47 */
48class Interface
49{
Vernon Mauery9e801a22018-10-12 13:20:49 -070050 public:
51 explicit Interface(integrity::Algorithms intAlgo,
52 crypt::Algorithms cryptAlgo) :
53 intAlgo(intAlgo),
54 cryptAlgo(cryptAlgo)
55 {
56 }
Tom Josephba11f792017-01-24 18:21:45 +053057
Vernon Mauery9e801a22018-10-12 13:20:49 -070058 Interface() = delete;
59 virtual ~Interface() = default;
60 Interface(const Interface&) = default;
61 Interface& operator=(const Interface&) = default;
62 Interface(Interface&&) = default;
63 Interface& operator=(Interface&&) = default;
Tom Joseph8c0446c2016-08-05 07:13:07 -050064
Vernon Mauery9e801a22018-10-12 13:20:49 -070065 /**
66 * @brief Generate the Hash Message Authentication Code
67 *
68 * This API is invoked to generate the Key Exchange Authentication Code
69 * in the RAKP2 and RAKP4 sequence and for generating the Session
70 * Integrity Key.
71 *
72 * @param input message
73 *
74 * @return hash output
75 *
76 * @note The user key which is the secret key for the hash operation
77 * needs to be set before this operation.
78 */
79 std::vector<uint8_t> virtual generateHMAC(
80 const std::vector<uint8_t>& input) const = 0;
Tom Joseph8c0446c2016-08-05 07:13:07 -050081
Vernon Mauery9e801a22018-10-12 13:20:49 -070082 /**
83 * @brief Generate the Integrity Check Value
84 *
85 * This API is invoked in the RAKP4 sequence for generating the
86 * Integrity Check Value.
87 *
88 * @param input message
89 *
90 * @return hash output
91 *
92 * @note The session integrity key which is the secret key for the
93 * hash operation needs to be set before this operation.
94 */
95 std::vector<uint8_t> virtual generateICV(
96 const std::vector<uint8_t>& input) const = 0;
Tom Joseph8c0446c2016-08-05 07:13:07 -050097
Vernon Mauery9e801a22018-10-12 13:20:49 -070098 /**
99 * @brief Check if the Authentication algorithm is supported
100 *
101 * @param[in] algo - authentication algorithm
102 *
103 * @return true if algorithm is supported else false
104 *
105 */
106 static bool isAlgorithmSupported(Algorithms algo)
107 {
Suryakanth Sekar4c494392020-03-31 13:22:43 +0530108 if (algo == Algorithms::RAKP_HMAC_SHA256)
Vernon Mauery9b307be2017-11-22 09:28:16 -0800109 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700110 return true;
Vernon Mauery9b307be2017-11-22 09:28:16 -0800111 }
Vernon Mauery9e801a22018-10-12 13:20:49 -0700112 else
113 {
114 return false;
115 }
116 }
Vernon Mauery9b307be2017-11-22 09:28:16 -0800117
Vernon Mauery9e801a22018-10-12 13:20:49 -0700118 // User Key is hardcoded to PASSW0RD till the IPMI User account
119 // management is in place.
120 std::array<uint8_t, USER_KEY_MAX_LENGTH> userKey = {"0penBmc"};
Tom Joseph8c0446c2016-08-05 07:13:07 -0500121
Vernon Mauery9e801a22018-10-12 13:20:49 -0700122 // Managed System Random Number
123 std::array<uint8_t, BMC_RANDOM_NUMBER_LEN> bmcRandomNum;
Tom Joseph8c0446c2016-08-05 07:13:07 -0500124
Vernon Mauery9e801a22018-10-12 13:20:49 -0700125 // Remote Console Random Number
126 std::array<uint8_t, REMOTE_CONSOLE_RANDOM_NUMBER_LEN> rcRandomNum;
Tom Joseph8c0446c2016-08-05 07:13:07 -0500127
Vernon Mauery9e801a22018-10-12 13:20:49 -0700128 // Session Integrity Key
129 std::vector<uint8_t> sessionIntegrityKey;
Tom Josephdd1be1a2017-01-10 16:10:29 +0530130
Vernon Mauery9e801a22018-10-12 13:20:49 -0700131 /**
132 * Integrity Algorithm is activated and set in the session data only
133 * once the session setup is succeeded in the RAKP34 command. But the
134 * integrity algorithm is negotiated in the Open Session Request command
135 * . So the integrity algorithm successfully negotiated is stored
136 * in the authentication algorithm's instance.
137 */
138 integrity::Algorithms intAlgo;
Tom Josephba11f792017-01-24 18:21:45 +0530139
Vernon Mauery9e801a22018-10-12 13:20:49 -0700140 /**
141 * Confidentiality Algorithm is activated and set in the session data
142 * only once the session setup is succeeded in the RAKP34 command. But
143 * the confidentiality algorithm is negotiated in the Open Session
144 * Request command. So the confidentiality algorithm successfully
145 * negotiated is stored in the authentication algorithm's instance.
146 */
147 crypt::Algorithms cryptAlgo;
Tom Joseph8c0446c2016-08-05 07:13:07 -0500148};
149
Tom Joseph3563f8f2017-05-08 15:42:54 +0530150/**
Tom Joseph8c0446c2016-08-05 07:13:07 -0500151 * @class AlgoSHA1
152 *
153 * RAKP-HMAC-SHA1 specifies the use of RAKP messages for the key exchange
154 * portion of establishing the session, and that HMAC-SHA1 (per [RFC2104]) is
155 * used to create 20-byte Key Exchange Authentication Code fields in RAKP
156 * Message 2 and RAKP Message 3. HMAC-SHA1-96(per [RFC2404]) is used for
157 * generating a 12-byte Integrity Check Value field for RAKP Message 4.
158 */
159
160class AlgoSHA1 : public Interface
161{
Vernon Mauery9e801a22018-10-12 13:20:49 -0700162 public:
163 static constexpr size_t integrityCheckValueLength = 12;
Vernon Mauery2207f512017-11-30 10:48:08 -0800164
Vernon Mauery9e801a22018-10-12 13:20:49 -0700165 explicit AlgoSHA1(integrity::Algorithms intAlgo,
166 crypt::Algorithms cryptAlgo) :
167 Interface(intAlgo, cryptAlgo)
168 {
169 }
Tom Josephba11f792017-01-24 18:21:45 +0530170
Vernon Mauery9e801a22018-10-12 13:20:49 -0700171 AlgoSHA1() = delete;
172 ~AlgoSHA1() = default;
173 AlgoSHA1(const AlgoSHA1&) = default;
174 AlgoSHA1& operator=(const AlgoSHA1&) = default;
175 AlgoSHA1(AlgoSHA1&&) = default;
176 AlgoSHA1& operator=(AlgoSHA1&&) = default;
Tom Joseph8c0446c2016-08-05 07:13:07 -0500177
Vernon Mauery9e801a22018-10-12 13:20:49 -0700178 std::vector<uint8_t>
179 generateHMAC(const std::vector<uint8_t>& input) const override;
Tom Joseph8c0446c2016-08-05 07:13:07 -0500180
Vernon Mauery9e801a22018-10-12 13:20:49 -0700181 std::vector<uint8_t>
182 generateICV(const std::vector<uint8_t>& input) const override;
Tom Joseph8c0446c2016-08-05 07:13:07 -0500183};
184
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800185/**
186 * @class AlgoSHA256
187 *
188 * RAKP-HMAC-SHA256 specifies the use of RAKP messages for the key exchange
189 * portion of establishing the session, and that HMAC-SHA256 (per [FIPS 180-2]
190 * and [RFC4634] and is used to create a 32-byte Key Exchange Authentication
191 * Code fields in RAKP Message 2 and RAKP Message 3. HMAC-SHA256-128 (per
192 * [RFC4868]) is used for generating a 16-byte Integrity Check Value field for
193 * RAKP Message 4.
194 */
195
196class AlgoSHA256 : public Interface
197{
Vernon Mauery9e801a22018-10-12 13:20:49 -0700198 public:
199 static constexpr size_t integrityCheckValueLength = 16;
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800200
Vernon Mauery9e801a22018-10-12 13:20:49 -0700201 explicit AlgoSHA256(integrity::Algorithms intAlgo,
202 crypt::Algorithms cryptAlgo) :
203 Interface(intAlgo, cryptAlgo)
204 {
205 }
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800206
Vernon Mauery9e801a22018-10-12 13:20:49 -0700207 ~AlgoSHA256() = default;
208 AlgoSHA256(const AlgoSHA256&) = default;
209 AlgoSHA256& operator=(const AlgoSHA256&) = default;
210 AlgoSHA256(AlgoSHA256&&) = default;
211 AlgoSHA256& operator=(AlgoSHA256&&) = default;
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800212
Vernon Mauery9e801a22018-10-12 13:20:49 -0700213 std::vector<uint8_t>
214 generateHMAC(const std::vector<uint8_t>& input) const override;
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800215
Vernon Mauery9e801a22018-10-12 13:20:49 -0700216 std::vector<uint8_t>
217 generateICV(const std::vector<uint8_t>& input) const override;
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800218};
219
Vernon Mauery9e801a22018-10-12 13:20:49 -0700220} // namespace rakp_auth
Tom Joseph8c0446c2016-08-05 07:13:07 -0500221
Vernon Mauery9e801a22018-10-12 13:20:49 -0700222} // namespace cipher