blob: 894a853a52d2d651f2e11fbdffef205d726540c4 [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;
Tom Joseph56527b92018-03-21 19:31:58 +053018extern const std::string userName;
Tom Joseph8c0446c2016-08-05 07:13:07 -050019
Tom Joseph3563f8f2017-05-08 15:42:54 +053020/**
Tom Joseph8c0446c2016-08-05 07:13:07 -050021 * @enum RAKP Authentication Algorithms
22 *
23 * RMCP+ Authenticated Key-Exchange Protocol (RAKP)
24 *
25 * RAKP-None is not supported as per the following recommendation
26 * (https://www.us-cert.gov/ncas/alerts/TA13-207A)
27 * ("cipher 0" is an option enabled by default on many IPMI enabled devices that
28 * allows authentication to be bypassed. Disable "cipher 0" to prevent
29 * attackers from bypassing authentication and sending arbitrary IPMI commands.)
30 */
31enum class Algorithms : uint8_t
32{
Tom Josephfe5a6452018-07-30 18:15:12 +053033 RAKP_NONE = 0, // Mandatory (implemented, not supported)
34 RAKP_HMAC_SHA1, // Mandatory (implemented, default choice in ipmitool)
35 RAKP_HMAC_MD5, // Optional (not implemented)
36 RAKP_HMAC_SHA256, // Optional (implemented, best available)
Tom Joseph8c0446c2016-08-05 07:13:07 -050037 // Reserved used to indicate an invalid authentication algorithm
38 RAKP_HMAC_INVALID = 0xB0
39};
40
Tom Joseph3563f8f2017-05-08 15:42:54 +053041/**
Tom Joseph8c0446c2016-08-05 07:13:07 -050042 * @class Interface
43 *
44 * Interface is the base class for the Authentication Algorithms.
45 * The Authentication Algorithm specifies the type of authentication “handshake”
46 * process that is used and identifies any particular variations of hashing or
47 * signature algorithm that is used as part of the process.
48 *
49 */
50class Interface
51{
Vernon Mauery9e801a22018-10-12 13:20:49 -070052 public:
53 explicit Interface(integrity::Algorithms intAlgo,
54 crypt::Algorithms cryptAlgo) :
55 intAlgo(intAlgo),
56 cryptAlgo(cryptAlgo)
57 {
58 }
Tom Josephba11f792017-01-24 18:21:45 +053059
Vernon Mauery9e801a22018-10-12 13:20:49 -070060 Interface() = delete;
61 virtual ~Interface() = default;
62 Interface(const Interface&) = default;
63 Interface& operator=(const Interface&) = default;
64 Interface(Interface&&) = default;
65 Interface& operator=(Interface&&) = default;
Tom Joseph8c0446c2016-08-05 07:13:07 -050066
Vernon Mauery9e801a22018-10-12 13:20:49 -070067 /**
68 * @brief Generate the Hash Message Authentication Code
69 *
70 * This API is invoked to generate the Key Exchange Authentication Code
71 * in the RAKP2 and RAKP4 sequence and for generating the Session
72 * Integrity Key.
73 *
74 * @param input message
75 *
76 * @return hash output
77 *
78 * @note The user key which is the secret key for the hash operation
79 * needs to be set before this operation.
80 */
81 std::vector<uint8_t> virtual generateHMAC(
82 const std::vector<uint8_t>& input) const = 0;
Tom Joseph8c0446c2016-08-05 07:13:07 -050083
Vernon Mauery9e801a22018-10-12 13:20:49 -070084 /**
85 * @brief Generate the Integrity Check Value
86 *
87 * This API is invoked in the RAKP4 sequence for generating the
88 * Integrity Check Value.
89 *
90 * @param input message
91 *
92 * @return hash output
93 *
94 * @note The session integrity key which is the secret key for the
95 * hash operation needs to be set before this operation.
96 */
97 std::vector<uint8_t> virtual generateICV(
98 const std::vector<uint8_t>& input) const = 0;
Tom Joseph8c0446c2016-08-05 07:13:07 -050099
Vernon Mauery9e801a22018-10-12 13:20:49 -0700100 /**
101 * @brief Check if the Authentication algorithm is supported
102 *
103 * @param[in] algo - authentication algorithm
104 *
105 * @return true if algorithm is supported else false
106 *
107 */
108 static bool isAlgorithmSupported(Algorithms algo)
109 {
Suryakanth Sekar4c494392020-03-31 13:22:43 +0530110 if (algo == Algorithms::RAKP_HMAC_SHA256)
Vernon Mauery9b307be2017-11-22 09:28:16 -0800111 {
Vernon Mauery9e801a22018-10-12 13:20:49 -0700112 return true;
Vernon Mauery9b307be2017-11-22 09:28:16 -0800113 }
Vernon Mauery9e801a22018-10-12 13:20:49 -0700114 else
115 {
116 return false;
117 }
118 }
Vernon Mauery9b307be2017-11-22 09:28:16 -0800119
Vernon Mauery9e801a22018-10-12 13:20:49 -0700120 // User Key is hardcoded to PASSW0RD till the IPMI User account
121 // management is in place.
122 std::array<uint8_t, USER_KEY_MAX_LENGTH> userKey = {"0penBmc"};
Tom Joseph8c0446c2016-08-05 07:13:07 -0500123
Vernon Mauery9e801a22018-10-12 13:20:49 -0700124 // Managed System Random Number
125 std::array<uint8_t, BMC_RANDOM_NUMBER_LEN> bmcRandomNum;
Tom Joseph8c0446c2016-08-05 07:13:07 -0500126
Vernon Mauery9e801a22018-10-12 13:20:49 -0700127 // Remote Console Random Number
128 std::array<uint8_t, REMOTE_CONSOLE_RANDOM_NUMBER_LEN> rcRandomNum;
Tom Joseph8c0446c2016-08-05 07:13:07 -0500129
Vernon Mauery9e801a22018-10-12 13:20:49 -0700130 // Session Integrity Key
131 std::vector<uint8_t> sessionIntegrityKey;
Tom Josephdd1be1a2017-01-10 16:10:29 +0530132
Vernon Mauery9e801a22018-10-12 13:20:49 -0700133 /**
134 * Integrity Algorithm is activated and set in the session data only
135 * once the session setup is succeeded in the RAKP34 command. But the
136 * integrity algorithm is negotiated in the Open Session Request command
137 * . So the integrity algorithm successfully negotiated is stored
138 * in the authentication algorithm's instance.
139 */
140 integrity::Algorithms intAlgo;
Tom Josephba11f792017-01-24 18:21:45 +0530141
Vernon Mauery9e801a22018-10-12 13:20:49 -0700142 /**
143 * Confidentiality Algorithm is activated and set in the session data
144 * only once the session setup is succeeded in the RAKP34 command. But
145 * the confidentiality algorithm is negotiated in the Open Session
146 * Request command. So the confidentiality algorithm successfully
147 * negotiated is stored in the authentication algorithm's instance.
148 */
149 crypt::Algorithms cryptAlgo;
Tom Joseph8c0446c2016-08-05 07:13:07 -0500150};
151
Tom Joseph3563f8f2017-05-08 15:42:54 +0530152/**
Tom Joseph8c0446c2016-08-05 07:13:07 -0500153 * @class AlgoSHA1
154 *
155 * RAKP-HMAC-SHA1 specifies the use of RAKP messages for the key exchange
156 * portion of establishing the session, and that HMAC-SHA1 (per [RFC2104]) is
157 * used to create 20-byte Key Exchange Authentication Code fields in RAKP
158 * Message 2 and RAKP Message 3. HMAC-SHA1-96(per [RFC2404]) is used for
159 * generating a 12-byte Integrity Check Value field for RAKP Message 4.
160 */
161
162class AlgoSHA1 : public Interface
163{
Vernon Mauery9e801a22018-10-12 13:20:49 -0700164 public:
165 static constexpr size_t integrityCheckValueLength = 12;
Vernon Mauery2207f512017-11-30 10:48:08 -0800166
Vernon Mauery9e801a22018-10-12 13:20:49 -0700167 explicit AlgoSHA1(integrity::Algorithms intAlgo,
168 crypt::Algorithms cryptAlgo) :
169 Interface(intAlgo, cryptAlgo)
170 {
171 }
Tom Josephba11f792017-01-24 18:21:45 +0530172
Vernon Mauery9e801a22018-10-12 13:20:49 -0700173 AlgoSHA1() = delete;
174 ~AlgoSHA1() = default;
175 AlgoSHA1(const AlgoSHA1&) = default;
176 AlgoSHA1& operator=(const AlgoSHA1&) = default;
177 AlgoSHA1(AlgoSHA1&&) = default;
178 AlgoSHA1& operator=(AlgoSHA1&&) = default;
Tom Joseph8c0446c2016-08-05 07:13:07 -0500179
Vernon Mauery9e801a22018-10-12 13:20:49 -0700180 std::vector<uint8_t>
181 generateHMAC(const std::vector<uint8_t>& input) const override;
Tom Joseph8c0446c2016-08-05 07:13:07 -0500182
Vernon Mauery9e801a22018-10-12 13:20:49 -0700183 std::vector<uint8_t>
184 generateICV(const std::vector<uint8_t>& input) const override;
Tom Joseph8c0446c2016-08-05 07:13:07 -0500185};
186
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800187/**
188 * @class AlgoSHA256
189 *
190 * RAKP-HMAC-SHA256 specifies the use of RAKP messages for the key exchange
191 * portion of establishing the session, and that HMAC-SHA256 (per [FIPS 180-2]
192 * and [RFC4634] and is used to create a 32-byte Key Exchange Authentication
193 * Code fields in RAKP Message 2 and RAKP Message 3. HMAC-SHA256-128 (per
194 * [RFC4868]) is used for generating a 16-byte Integrity Check Value field for
195 * RAKP Message 4.
196 */
197
198class AlgoSHA256 : public Interface
199{
Vernon Mauery9e801a22018-10-12 13:20:49 -0700200 public:
201 static constexpr size_t integrityCheckValueLength = 16;
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800202
Vernon Mauery9e801a22018-10-12 13:20:49 -0700203 explicit AlgoSHA256(integrity::Algorithms intAlgo,
204 crypt::Algorithms cryptAlgo) :
205 Interface(intAlgo, cryptAlgo)
206 {
207 }
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800208
Vernon Mauery9e801a22018-10-12 13:20:49 -0700209 ~AlgoSHA256() = default;
210 AlgoSHA256(const AlgoSHA256&) = default;
211 AlgoSHA256& operator=(const AlgoSHA256&) = default;
212 AlgoSHA256(AlgoSHA256&&) = default;
213 AlgoSHA256& operator=(AlgoSHA256&&) = default;
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800214
Vernon Mauery9e801a22018-10-12 13:20:49 -0700215 std::vector<uint8_t>
216 generateHMAC(const std::vector<uint8_t>& input) const override;
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800217
Vernon Mauery9e801a22018-10-12 13:20:49 -0700218 std::vector<uint8_t>
219 generateICV(const std::vector<uint8_t>& input) const override;
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800220};
221
Vernon Mauery9e801a22018-10-12 13:20:49 -0700222} // namespace rakp_auth
Tom Joseph8c0446c2016-08-05 07:13:07 -0500223
Vernon Mauery9e801a22018-10-12 13:20:49 -0700224} // namespace cipher