blob: 1249d80d9fc40cbcce32e5044641c53a1613687d [file] [log] [blame]
Tom Joseph8bb10b72016-12-06 17:47:56 +05301#include "rakp12.hpp"
2
3#include <openssl/rand.h>
4
5#include <algorithm>
6#include <iomanip>
7#include <iostream>
8
9#include "comm_module.hpp"
10#include "endian.hpp"
11#include "guid.hpp"
12#include "main.hpp"
13
14namespace command
15{
16
17std::vector<uint8_t> RAKP12(std::vector<uint8_t>& inPayload,
18 const message::Handler& handler)
19{
20 std::cout << ">> RAKP12\n";
21
22 std::vector<uint8_t> outPayload(sizeof(RAKP2response));
23 auto request = reinterpret_cast<RAKP1request*>(inPayload.data());
24 auto response = reinterpret_cast<RAKP2response*>(outPayload.data());
25
26 // Session ID zero is reserved for Session Setup
27 if(endian::from_ipmi(request->managedSystemSessionID) ==
28 session::SESSION_ZERO)
29 {
30 std::cerr << "RAKP12: BMC invalid Session ID\n";
31 response->rmcpStatusCode =
32 static_cast<uint8_t>(RAKP_ReturnCode::INVALID_SESSION_ID);
33 return outPayload;
34 }
35
36 std::shared_ptr<session::Session> session;
37 try
38 {
39 session = (std::get<session::Manager&>(singletonPool).getSession(
40 endian::from_ipmi(request->managedSystemSessionID))).lock();
41 }
42 catch (std::exception& e)
43 {
44 std::cerr << e.what() << "\n";
45 response->rmcpStatusCode =
46 static_cast<uint8_t>(RAKP_ReturnCode::INVALID_SESSION_ID);
47 return outPayload;
48 }
49
50 // Update transaction time
51 session->updateLastTransactionTime();
52
53 auto rcSessionID = endian::to_ipmi(session->getRCSessionID());
54 auto bmcSessionID = endian::to_ipmi(session->getBMCSessionID());
55 auto authAlgo = session->getAuthAlgo();
56
57 /*
58 * Generate Key Authentication Code - RAKP 2
59 *
60 * 1) Remote Console Session ID - 4 bytes
61 * 2) Managed System Session ID - 4 bytes
62 * 3) Remote Console Random Number - 16 bytes
63 * 4) Managed System Random Number - 16 bytes
64 * 5) Managed System GUID - 16 bytes
65 * 6) Requested Privilege Level - 1 byte
66 * 7) User Name Length Byte - 1 byte (0 for 'null' username)
67 * 8) User Name - variable (absent for 'null' username)
68 */
69
70 std::vector<uint8_t> input;
71 input.resize(sizeof(rcSessionID) + sizeof(bmcSessionID) +
72 cipher::rakp_auth::REMOTE_CONSOLE_RANDOM_NUMBER_LEN +
73 cipher::rakp_auth::BMC_RANDOM_NUMBER_LEN +
74 BMC_GUID_LEN + sizeof(request->req_max_privilege_level) +
75 sizeof(request->user_name_len));
76
77 auto iter = input.begin();
78
79 // Remote Console Session ID
80 std::copy_n(reinterpret_cast<uint8_t*>(&rcSessionID),
81 sizeof(rcSessionID), iter);
82 std::advance(iter, sizeof(rcSessionID));
83
84 // Managed System Session ID
85 std::copy_n(reinterpret_cast<uint8_t*>(&bmcSessionID), sizeof(bmcSessionID),
86 iter);
87 std::advance(iter, sizeof(bmcSessionID));
88
89 // Copy the Remote Console Random Number from the RAKP1 request to the
90 // Authentication Algorithm
91 std::copy_n(reinterpret_cast<uint8_t*>
92 (request->remote_console_random_number),
93 cipher::rakp_auth::REMOTE_CONSOLE_RANDOM_NUMBER_LEN,
94 authAlgo->rcRandomNum.begin());
95
96 std::copy(authAlgo->rcRandomNum.begin(), authAlgo->rcRandomNum.end(),
97 iter);
98 std::advance(iter, cipher::rakp_auth::REMOTE_CONSOLE_RANDOM_NUMBER_LEN);
99
100 // Generate the Managed System Random Number
101 if (!RAND_bytes(input.data() + sizeof(rcSessionID) + sizeof(bmcSessionID) +
102 cipher::rakp_auth::REMOTE_CONSOLE_RANDOM_NUMBER_LEN,
103 cipher::rakp_auth::BMC_RANDOM_NUMBER_LEN))
104 {
105 response->rmcpStatusCode =
106 static_cast<uint8_t>(RAKP_ReturnCode::INSUFFICIENT_RESOURCE);
107 return outPayload;
108 }
109
110 // Copy the Managed System Random Number to the Authentication Algorithm
111 std::copy_n(iter, cipher::rakp_auth::BMC_RANDOM_NUMBER_LEN,
112 authAlgo->bmcRandomNum.begin());
113 std::advance(iter, cipher::rakp_auth::BMC_RANDOM_NUMBER_LEN);
114
115 // Managed System GUID
116 auto guid = getSystemGUID();
117 std::copy_n(guid.data(), guid.size(), iter);
118 std::advance(iter, BMC_GUID_LEN);
119
120 // Requested Privilege Level
121 session->curPrivLevel = static_cast<session::Privilege>
122 (request->req_max_privilege_level);
123 std::copy_n(&(request->req_max_privilege_level),
124 sizeof(request->req_max_privilege_level), iter);
125 std::advance(iter, sizeof(request->req_max_privilege_level));
126
127 // Set Max Privilege to ADMIN
128 session->maxPrivLevel = session::Privilege::ADMIN;
129
130 // User Name Length Byte
131 std::copy_n(&(request->user_name_len), sizeof(request->user_name_len),
132 iter);
133
134 // Generate Key Exchange Authentication Code - RAKP2
135 auto output = authAlgo->generateHMAC(input);
136
137 response->messageTag = request->messageTag;
138 response->rmcpStatusCode = static_cast<uint8_t>(RAKP_ReturnCode::NO_ERROR);
139 response->reserved = 0;
140 response->remoteConsoleSessionID = rcSessionID ;
141
142 // Copy Managed System Random Number to the Response
143 std::copy(authAlgo->bmcRandomNum.begin(), authAlgo->bmcRandomNum.end(),
144 response->managed_system_random_number);
145
146 // Copy System GUID to the Response
147 std::copy_n(guid.data(), guid.size(), response->managed_system_guid);
148
149 // Insert the HMAC output into the payload
150 outPayload.insert(outPayload.end(), output.begin(), output.end());
151
152 std::cout << "<< RAKP12\n";
153 return outPayload;
154}
155
156} // namespace command