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