1 #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 14 namespace command 15 { 16 17 std::vector<uint8_t> RAKP12(const 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<const 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<const 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 std::copy_n(cache::guid.data(), cache::guid.size(), iter); 117 std::advance(iter, BMC_GUID_LEN); 118 119 // Requested Privilege Level 120 session->curPrivLevel = static_cast<session::Privilege> 121 (request->req_max_privilege_level); 122 std::copy_n(&(request->req_max_privilege_level), 123 sizeof(request->req_max_privilege_level), iter); 124 std::advance(iter, sizeof(request->req_max_privilege_level)); 125 126 // Set Max Privilege to ADMIN 127 session->maxPrivLevel = session::Privilege::ADMIN; 128 129 // User Name Length Byte 130 std::copy_n(&(request->user_name_len), sizeof(request->user_name_len), 131 iter); 132 133 // Generate Key Exchange Authentication Code - RAKP2 134 auto output = authAlgo->generateHMAC(input); 135 136 response->messageTag = request->messageTag; 137 response->rmcpStatusCode = static_cast<uint8_t>(RAKP_ReturnCode::NO_ERROR); 138 response->reserved = 0; 139 response->remoteConsoleSessionID = rcSessionID ; 140 141 // Copy Managed System Random Number to the Response 142 std::copy(authAlgo->bmcRandomNum.begin(), authAlgo->bmcRandomNum.end(), 143 response->managed_system_random_number); 144 145 // Copy System GUID to the Response 146 std::copy_n(cache::guid.data(), 147 cache::guid.size(), 148 response->managed_system_guid); 149 150 // Insert the HMAC output into the payload 151 outPayload.insert(outPayload.end(), output.begin(), output.end()); 152 153 std::cout << "<< RAKP12\n"; 154 return outPayload; 155 } 156 157 } // namespace command 158