blob: 828b56b5b9a54b372d1dab30e99a861690615969 [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
17/*
18 * @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
38/*
39 * @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
62 /*
63 * @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(
77 std::vector<uint8_t>& input) const = 0;
78
79 /*
80 * @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(
93 std::vector<uint8_t>& input) const = 0;
94
95 // User Key is hardcoded to PASSW0RD till the IPMI User account
96 // management is in place.
97 std::array<uint8_t, USER_KEY_MAX_LENGTH> userKey = {"PASSW0RD"};
98
99 // Managed System Random Number
100 std::array<uint8_t, BMC_RANDOM_NUMBER_LEN> bmcRandomNum;
101
102 // Remote Console Random Number
103 std::array<uint8_t, REMOTE_CONSOLE_RANDOM_NUMBER_LEN> rcRandomNum;
104
105 // Session Integrity Key
106 std::vector<uint8_t> sessionIntegrityKey;
Tom Josephdd1be1a2017-01-10 16:10:29 +0530107
108 /*
109 * Integrity Algorithm is activated and set in the session data only
110 * once the session setup is succeeded in the RAKP34 command. But the
111 * integrity algorithm is negotiated in the Open Session Request command
Tom Josephba11f792017-01-24 18:21:45 +0530112 * . So the integrity algorithm successfully negotiated is stored
113 * in the authentication algorithm's instance.
Tom Josephdd1be1a2017-01-10 16:10:29 +0530114 */
115 integrity::Algorithms intAlgo;
Tom Josephba11f792017-01-24 18:21:45 +0530116
117 /*
118 * Confidentiality Algorithm is activated and set in the session data
119 * only once the session setup is succeeded in the RAKP34 command. But
120 * the confidentiality algorithm is negotiated in the Open Session
121 * Request command. So the confidentiality algorithm successfully
122 * negotiated is stored in the authentication algorithm's instance.
123 */
124 crypt::Algorithms cryptAlgo;
Tom Joseph8c0446c2016-08-05 07:13:07 -0500125};
126
127/*
128 * @class AlgoSHA1
129 *
130 * RAKP-HMAC-SHA1 specifies the use of RAKP messages for the key exchange
131 * portion of establishing the session, and that HMAC-SHA1 (per [RFC2104]) is
132 * used to create 20-byte Key Exchange Authentication Code fields in RAKP
133 * Message 2 and RAKP Message 3. HMAC-SHA1-96(per [RFC2404]) is used for
134 * generating a 12-byte Integrity Check Value field for RAKP Message 4.
135 */
136
137class AlgoSHA1 : public Interface
138{
139 public:
Tom Josephba11f792017-01-24 18:21:45 +0530140 explicit AlgoSHA1(integrity::Algorithms intAlgo,
141 crypt::Algorithms cryptAlgo) :
142 Interface(intAlgo, cryptAlgo) {}
143
Tom Josephdd1be1a2017-01-10 16:10:29 +0530144 AlgoSHA1() = delete;
Tom Joseph8c0446c2016-08-05 07:13:07 -0500145 ~AlgoSHA1() = default;
146 AlgoSHA1(const AlgoSHA1&) = default;
147 AlgoSHA1& operator=(const AlgoSHA1&) = default;
148 AlgoSHA1(AlgoSHA1&&) = default;
149 AlgoSHA1& operator=(AlgoSHA1&&) = default;
150
151 std::vector<uint8_t> generateHMAC(std::vector<uint8_t>& input) const
152 override;
153
154 std::vector<uint8_t> generateICV(std::vector<uint8_t>& input) const
155 override;
156};
157
158}// namespace auth
159
160}// namespace cipher
161