1 #include "rakp12.hpp" 2 3 #include "comm_module.hpp" 4 #include "endian.hpp" 5 #include "guid.hpp" 6 #include "main.hpp" 7 8 #include <openssl/rand.h> 9 10 #include <algorithm> 11 #include <cstring> 12 #include <iomanip> 13 #include <iostream> 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) 39 .getSession( 40 endian::from_ipmi(request->managedSystemSessionID))) 41 .lock(); 42 } 43 catch (std::exception& e) 44 { 45 std::cerr << e.what() << "\n"; 46 response->rmcpStatusCode = 47 static_cast<uint8_t>(RAKP_ReturnCode::INVALID_SESSION_ID); 48 return outPayload; 49 } 50 51 auto rakp1Size = 52 sizeof(RAKP1request) - (userNameMaxLen - request->user_name_len); 53 54 // Validate user name length in the message 55 if (request->user_name_len > userNameMaxLen || 56 inPayload.size() != rakp1Size) 57 { 58 response->rmcpStatusCode = 59 static_cast<uint8_t>(RAKP_ReturnCode::INVALID_NAME_LENGTH); 60 return outPayload; 61 } 62 63 session->userName.assign(request->user_name, request->user_name_len); 64 65 // Validate the user name if the username is provided 66 if (request->user_name_len && 67 (session->userName != cipher::rakp_auth::userName)) 68 { 69 response->rmcpStatusCode = 70 static_cast<uint8_t>(RAKP_ReturnCode::UNAUTH_NAME); 71 return outPayload; 72 } 73 74 // Update transaction time 75 session->updateLastTransactionTime(); 76 77 auto rcSessionID = endian::to_ipmi(session->getRCSessionID()); 78 auto bmcSessionID = endian::to_ipmi(session->getBMCSessionID()); 79 auto authAlgo = session->getAuthAlgo(); 80 81 /* 82 * Generate Key Authentication Code - RAKP 2 83 * 84 * 1) Remote Console Session ID - 4 bytes 85 * 2) Managed System Session ID - 4 bytes 86 * 3) Remote Console Random Number - 16 bytes 87 * 4) Managed System Random Number - 16 bytes 88 * 5) Managed System GUID - 16 bytes 89 * 6) Requested Privilege Level - 1 byte 90 * 7) User Name Length Byte - 1 byte (0 for 'null' username) 91 * 8) User Name - variable (absent for 'null' username) 92 */ 93 94 std::vector<uint8_t> input; 95 input.resize(sizeof(rcSessionID) + sizeof(bmcSessionID) + 96 cipher::rakp_auth::REMOTE_CONSOLE_RANDOM_NUMBER_LEN + 97 cipher::rakp_auth::BMC_RANDOM_NUMBER_LEN + BMC_GUID_LEN + 98 sizeof(request->req_max_privilege_level) + 99 sizeof(request->user_name_len) + session->userName.size()); 100 101 auto iter = input.begin(); 102 103 // Remote Console Session ID 104 std::copy_n(reinterpret_cast<uint8_t*>(&rcSessionID), sizeof(rcSessionID), 105 iter); 106 std::advance(iter, sizeof(rcSessionID)); 107 108 // Managed System Session ID 109 std::copy_n(reinterpret_cast<uint8_t*>(&bmcSessionID), sizeof(bmcSessionID), 110 iter); 111 std::advance(iter, sizeof(bmcSessionID)); 112 113 // Copy the Remote Console Random Number from the RAKP1 request to the 114 // Authentication Algorithm 115 std::copy_n( 116 reinterpret_cast<const uint8_t*>(request->remote_console_random_number), 117 cipher::rakp_auth::REMOTE_CONSOLE_RANDOM_NUMBER_LEN, 118 authAlgo->rcRandomNum.begin()); 119 120 std::copy(authAlgo->rcRandomNum.begin(), authAlgo->rcRandomNum.end(), 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 = 144 static_cast<session::Privilege>(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(), cache::guid.size(), 173 response->managed_system_guid); 174 175 // Insert the HMAC output into the payload 176 outPayload.insert(outPayload.end(), output.begin(), output.end()); 177 return outPayload; 178 } 179 180 } // namespace command 181