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