blob: b6fda94a8ec64a00e4ecd7da48ee93845aa283c9 [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{
12
13constexpr size_t USER_KEY_MAX_LENGTH = 20;
14constexpr size_t BMC_RANDOM_NUMBER_LEN = 16;
15constexpr size_t REMOTE_CONSOLE_RANDOM_NUMBER_LEN = 16;
16
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 ||
106 algo == Algorithms::RAKP_HMAC_SHA1)
107 {
108 return true;
109 }
110 else
111 {
112 return false;
113 }
114 }
115
Tom Joseph8c0446c2016-08-05 07:13:07 -0500116 // User Key is hardcoded to PASSW0RD till the IPMI User account
117 // management is in place.
Tom Josephe2e97662017-03-02 17:12:46 +0530118 std::array<uint8_t, USER_KEY_MAX_LENGTH> userKey = {"0penBmc"};
Tom Joseph8c0446c2016-08-05 07:13:07 -0500119
120 // Managed System Random Number
121 std::array<uint8_t, BMC_RANDOM_NUMBER_LEN> bmcRandomNum;
122
123 // Remote Console Random Number
124 std::array<uint8_t, REMOTE_CONSOLE_RANDOM_NUMBER_LEN> rcRandomNum;
125
126 // Session Integrity Key
127 std::vector<uint8_t> sessionIntegrityKey;
Tom Josephdd1be1a2017-01-10 16:10:29 +0530128
Tom Joseph3563f8f2017-05-08 15:42:54 +0530129 /**
Tom Josephdd1be1a2017-01-10 16:10:29 +0530130 * Integrity Algorithm is activated and set in the session data only
131 * once the session setup is succeeded in the RAKP34 command. But the
132 * integrity algorithm is negotiated in the Open Session Request command
Tom Josephba11f792017-01-24 18:21:45 +0530133 * . So the integrity algorithm successfully negotiated is stored
134 * in the authentication algorithm's instance.
Tom Josephdd1be1a2017-01-10 16:10:29 +0530135 */
136 integrity::Algorithms intAlgo;
Tom Josephba11f792017-01-24 18:21:45 +0530137
Tom Joseph3563f8f2017-05-08 15:42:54 +0530138 /**
Tom Josephba11f792017-01-24 18:21:45 +0530139 * Confidentiality Algorithm is activated and set in the session data
140 * only once the session setup is succeeded in the RAKP34 command. But
141 * the confidentiality algorithm is negotiated in the Open Session
142 * Request command. So the confidentiality algorithm successfully
143 * negotiated is stored in the authentication algorithm's instance.
144 */
145 crypt::Algorithms cryptAlgo;
Tom Joseph8c0446c2016-08-05 07:13:07 -0500146};
147
Tom Joseph3563f8f2017-05-08 15:42:54 +0530148/**
Tom Joseph8c0446c2016-08-05 07:13:07 -0500149 * @class AlgoSHA1
150 *
151 * RAKP-HMAC-SHA1 specifies the use of RAKP messages for the key exchange
152 * portion of establishing the session, and that HMAC-SHA1 (per [RFC2104]) is
153 * used to create 20-byte Key Exchange Authentication Code fields in RAKP
154 * Message 2 and RAKP Message 3. HMAC-SHA1-96(per [RFC2404]) is used for
155 * generating a 12-byte Integrity Check Value field for RAKP Message 4.
156 */
157
158class AlgoSHA1 : public Interface
159{
160 public:
Vernon Mauery2207f512017-11-30 10:48:08 -0800161 static constexpr size_t integrityCheckValueLength = 12;
162
Tom Josephba11f792017-01-24 18:21:45 +0530163 explicit AlgoSHA1(integrity::Algorithms intAlgo,
164 crypt::Algorithms cryptAlgo) :
165 Interface(intAlgo, cryptAlgo) {}
166
Tom Josephdd1be1a2017-01-10 16:10:29 +0530167 AlgoSHA1() = delete;
Tom Joseph8c0446c2016-08-05 07:13:07 -0500168 ~AlgoSHA1() = default;
169 AlgoSHA1(const AlgoSHA1&) = default;
170 AlgoSHA1& operator=(const AlgoSHA1&) = default;
171 AlgoSHA1(AlgoSHA1&&) = default;
172 AlgoSHA1& operator=(AlgoSHA1&&) = default;
173
Vernon Mauery70fd29c2017-11-30 13:11:43 -0800174 std::vector<uint8_t> generateHMAC(
175 const std::vector<uint8_t>& input) const override;
Tom Joseph8c0446c2016-08-05 07:13:07 -0500176
Vernon Mauery70fd29c2017-11-30 13:11:43 -0800177 std::vector<uint8_t> generateICV(
178 const std::vector<uint8_t>& input) const override;
Tom Joseph8c0446c2016-08-05 07:13:07 -0500179};
180
181}// namespace auth
182
183}// namespace cipher
184