blob: a4dbcc47a7d5b9333f4791d4b158e9f2d5ad4a08 [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>
Andrew Geissler9d9b7632020-05-17 09:18:05 -05007#include <cstddef>
Andrew Geissler7408e762020-05-17 08:56:05 -05008#include <string>
Vernon Mauery9e801a22018-10-12 13:20:49 -07009#include <vector>
10
Tom Joseph8c0446c2016-08-05 07:13:07 -050011namespace cipher
12{
13namespace rakp_auth
14{
Tom Joseph8c0446c2016-08-05 07:13:07 -050015constexpr size_t USER_KEY_MAX_LENGTH = 20;
16constexpr size_t BMC_RANDOM_NUMBER_LEN = 16;
17constexpr size_t REMOTE_CONSOLE_RANDOM_NUMBER_LEN = 16;
18
Tom Joseph3563f8f2017-05-08 15:42:54 +053019/**
Tom Joseph8c0446c2016-08-05 07:13:07 -050020 * @enum RAKP Authentication Algorithms
21 *
22 * RMCP+ Authenticated Key-Exchange Protocol (RAKP)
23 *
24 * RAKP-None is not supported as per the following recommendation
25 * (https://www.us-cert.gov/ncas/alerts/TA13-207A)
26 * ("cipher 0" is an option enabled by default on many IPMI enabled devices that
27 * allows authentication to be bypassed. Disable "cipher 0" to prevent
28 * attackers from bypassing authentication and sending arbitrary IPMI commands.)
29 */
30enum class Algorithms : uint8_t
31{
Tom Josephfe5a6452018-07-30 18:15:12 +053032 RAKP_NONE = 0, // Mandatory (implemented, not supported)
33 RAKP_HMAC_SHA1, // Mandatory (implemented, default choice in ipmitool)
34 RAKP_HMAC_MD5, // Optional (not implemented)
35 RAKP_HMAC_SHA256, // Optional (implemented, best available)
Tom Joseph8c0446c2016-08-05 07:13:07 -050036 // Reserved used to indicate an invalid authentication algorithm
37 RAKP_HMAC_INVALID = 0xB0
38};
39
Tom Joseph3563f8f2017-05-08 15:42:54 +053040/**
Tom Joseph8c0446c2016-08-05 07:13:07 -050041 * @class Interface
42 *
43 * Interface is the base class for the Authentication Algorithms.
44 * The Authentication Algorithm specifies the type of authentication “handshake”
45 * process that is used and identifies any particular variations of hashing or
46 * signature algorithm that is used as part of the process.
47 *
48 */
49class Interface
50{
Vernon Mauery9e801a22018-10-12 13:20:49 -070051 public:
52 explicit Interface(integrity::Algorithms intAlgo,
53 crypt::Algorithms cryptAlgo) :
Patrick Williams84256242024-08-16 15:20:21 -040054 intAlgo(intAlgo), cryptAlgo(cryptAlgo)
George Liubc8958f2022-07-04 09:29:49 +080055 {}
Tom Josephba11f792017-01-24 18:21:45 +053056
Vernon Mauery9e801a22018-10-12 13:20:49 -070057 Interface() = delete;
58 virtual ~Interface() = default;
59 Interface(const Interface&) = default;
60 Interface& operator=(const Interface&) = default;
61 Interface(Interface&&) = default;
62 Interface& operator=(Interface&&) = default;
Tom Joseph8c0446c2016-08-05 07:13:07 -050063
Vernon Mauery9e801a22018-10-12 13:20:49 -070064 /**
65 * @brief Generate the Hash Message Authentication Code
66 *
67 * This API is invoked to generate the Key Exchange Authentication Code
68 * in the RAKP2 and RAKP4 sequence and for generating the Session
69 * Integrity Key.
70 *
71 * @param input message
72 *
73 * @return hash output
74 *
75 * @note The user key which is the secret key for the hash operation
76 * needs to be set before this operation.
77 */
78 std::vector<uint8_t> virtual generateHMAC(
79 const std::vector<uint8_t>& input) const = 0;
Tom Joseph8c0446c2016-08-05 07:13:07 -050080
Vernon Mauery9e801a22018-10-12 13:20:49 -070081 /**
82 * @brief Generate the Integrity Check Value
83 *
84 * This API is invoked in the RAKP4 sequence for generating the
85 * Integrity Check Value.
86 *
87 * @param input message
88 *
89 * @return hash output
90 *
91 * @note The session integrity key which is the secret key for the
92 * hash operation needs to be set before this operation.
93 */
94 std::vector<uint8_t> virtual generateICV(
95 const std::vector<uint8_t>& input) const = 0;
Tom Joseph8c0446c2016-08-05 07:13:07 -050096
Vernon Mauery9e801a22018-10-12 13:20:49 -070097 /**
98 * @brief Check if the Authentication algorithm is supported
99 *
100 * @param[in] algo - authentication algorithm
101 *
102 * @return true if algorithm is supported else false
103 *
104 */
105 static bool isAlgorithmSupported(Algorithms algo)
106 {
Suryakanth Sekar4c494392020-03-31 13:22:43 +0530107 if (algo == Algorithms::RAKP_HMAC_SHA256)
Vernon Mauery9b307be2017-11-22 09:28:16 -0800108 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700109 return true;
Vernon Mauery9b307be2017-11-22 09:28:16 -0800110 }
Vernon Mauery9e801a22018-10-12 13:20:49 -0700111 else
112 {
113 return false;
114 }
115 }
Vernon Mauery9b307be2017-11-22 09:28:16 -0800116
Vernon Mauery9e801a22018-10-12 13:20:49 -0700117 // User Key is hardcoded to PASSW0RD till the IPMI User account
118 // management is in place.
119 std::array<uint8_t, USER_KEY_MAX_LENGTH> userKey = {"0penBmc"};
Tom Joseph8c0446c2016-08-05 07:13:07 -0500120
Vernon Mauery9e801a22018-10-12 13:20:49 -0700121 // Managed System Random Number
122 std::array<uint8_t, BMC_RANDOM_NUMBER_LEN> bmcRandomNum;
Tom Joseph8c0446c2016-08-05 07:13:07 -0500123
Vernon Mauery9e801a22018-10-12 13:20:49 -0700124 // Remote Console Random Number
125 std::array<uint8_t, REMOTE_CONSOLE_RANDOM_NUMBER_LEN> rcRandomNum;
Tom Joseph8c0446c2016-08-05 07:13:07 -0500126
Vernon Mauery9e801a22018-10-12 13:20:49 -0700127 // Session Integrity Key
128 std::vector<uint8_t> sessionIntegrityKey;
Tom Josephdd1be1a2017-01-10 16:10:29 +0530129
Vernon Mauery9e801a22018-10-12 13:20:49 -0700130 /**
131 * 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
134 * . So the integrity algorithm successfully negotiated is stored
135 * in the authentication algorithm's instance.
136 */
137 integrity::Algorithms intAlgo;
Tom Josephba11f792017-01-24 18:21:45 +0530138
Vernon Mauery9e801a22018-10-12 13:20:49 -0700139 /**
140 * 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{
Vernon Mauery9e801a22018-10-12 13:20:49 -0700161 public:
162 static constexpr size_t integrityCheckValueLength = 12;
Vernon Mauery2207f512017-11-30 10:48:08 -0800163
Vernon Mauery9e801a22018-10-12 13:20:49 -0700164 explicit AlgoSHA1(integrity::Algorithms intAlgo,
165 crypt::Algorithms cryptAlgo) :
166 Interface(intAlgo, cryptAlgo)
George Liubc8958f2022-07-04 09:29:49 +0800167 {}
Tom Josephba11f792017-01-24 18:21:45 +0530168
Vernon Mauery9e801a22018-10-12 13:20:49 -0700169 AlgoSHA1() = delete;
170 ~AlgoSHA1() = default;
171 AlgoSHA1(const AlgoSHA1&) = default;
172 AlgoSHA1& operator=(const AlgoSHA1&) = default;
173 AlgoSHA1(AlgoSHA1&&) = default;
174 AlgoSHA1& operator=(AlgoSHA1&&) = default;
Tom Joseph8c0446c2016-08-05 07:13:07 -0500175
Vernon Mauery9e801a22018-10-12 13:20:49 -0700176 std::vector<uint8_t>
177 generateHMAC(const std::vector<uint8_t>& input) const override;
Tom Joseph8c0446c2016-08-05 07:13:07 -0500178
Vernon Mauery9e801a22018-10-12 13:20:49 -0700179 std::vector<uint8_t>
180 generateICV(const std::vector<uint8_t>& input) const override;
Tom Joseph8c0446c2016-08-05 07:13:07 -0500181};
182
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800183/**
184 * @class AlgoSHA256
185 *
186 * RAKP-HMAC-SHA256 specifies the use of RAKP messages for the key exchange
187 * portion of establishing the session, and that HMAC-SHA256 (per [FIPS 180-2]
188 * and [RFC4634] and is used to create a 32-byte Key Exchange Authentication
189 * Code fields in RAKP Message 2 and RAKP Message 3. HMAC-SHA256-128 (per
190 * [RFC4868]) is used for generating a 16-byte Integrity Check Value field for
191 * RAKP Message 4.
192 */
193
194class AlgoSHA256 : public Interface
195{
Vernon Mauery9e801a22018-10-12 13:20:49 -0700196 public:
197 static constexpr size_t integrityCheckValueLength = 16;
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800198
Vernon Mauery9e801a22018-10-12 13:20:49 -0700199 explicit AlgoSHA256(integrity::Algorithms intAlgo,
200 crypt::Algorithms cryptAlgo) :
201 Interface(intAlgo, cryptAlgo)
George Liubc8958f2022-07-04 09:29:49 +0800202 {}
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800203
Vernon Mauery9e801a22018-10-12 13:20:49 -0700204 ~AlgoSHA256() = default;
205 AlgoSHA256(const AlgoSHA256&) = default;
206 AlgoSHA256& operator=(const AlgoSHA256&) = default;
207 AlgoSHA256(AlgoSHA256&&) = default;
208 AlgoSHA256& operator=(AlgoSHA256&&) = default;
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800209
Vernon Mauery9e801a22018-10-12 13:20:49 -0700210 std::vector<uint8_t>
211 generateHMAC(const std::vector<uint8_t>& input) const override;
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800212
Vernon Mauery9e801a22018-10-12 13:20:49 -0700213 std::vector<uint8_t>
214 generateICV(const std::vector<uint8_t>& input) const override;
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800215};
216
Vernon Mauery9e801a22018-10-12 13:20:49 -0700217} // namespace rakp_auth
Tom Joseph8c0446c2016-08-05 07:13:07 -0500218
Vernon Mauery9e801a22018-10-12 13:20:49 -0700219} // namespace cipher