18bb10b79STom Joseph #include "rakp12.hpp" 28bb10b79STom Joseph 38bb10b79STom Joseph #include <openssl/rand.h> 48bb10b79STom Joseph 58bb10b79STom Joseph #include <algorithm> 68bb10b79STom Joseph #include <iomanip> 78bb10b79STom Joseph #include <iostream> 88bb10b79STom Joseph 98bb10b79STom Joseph #include "comm_module.hpp" 108bb10b79STom Joseph #include "endian.hpp" 118bb10b79STom Joseph #include "guid.hpp" 128bb10b79STom Joseph #include "main.hpp" 138bb10b79STom Joseph 148bb10b79STom Joseph namespace command 158bb10b79STom Joseph { 168bb10b79STom Joseph 1718a45e9dSTom Joseph std::vector<uint8_t> RAKP12(const std::vector<uint8_t>& inPayload, 188bb10b79STom Joseph const message::Handler& handler) 198bb10b79STom Joseph { 208bb10b79STom Joseph std::cout << ">> RAKP12\n"; 218bb10b79STom Joseph 228bb10b79STom Joseph std::vector<uint8_t> outPayload(sizeof(RAKP2response)); 2318a45e9dSTom Joseph auto request = reinterpret_cast<const RAKP1request*>(inPayload.data()); 248bb10b79STom Joseph auto response = reinterpret_cast<RAKP2response*>(outPayload.data()); 258bb10b79STom Joseph 268bb10b79STom Joseph // Session ID zero is reserved for Session Setup 278bb10b79STom Joseph if(endian::from_ipmi(request->managedSystemSessionID) == 288bb10b79STom Joseph session::SESSION_ZERO) 298bb10b79STom Joseph { 308bb10b79STom Joseph std::cerr << "RAKP12: BMC invalid Session ID\n"; 318bb10b79STom Joseph response->rmcpStatusCode = 328bb10b79STom Joseph static_cast<uint8_t>(RAKP_ReturnCode::INVALID_SESSION_ID); 338bb10b79STom Joseph return outPayload; 348bb10b79STom Joseph } 358bb10b79STom Joseph 368bb10b79STom Joseph std::shared_ptr<session::Session> session; 378bb10b79STom Joseph try 388bb10b79STom Joseph { 398bb10b79STom Joseph session = (std::get<session::Manager&>(singletonPool).getSession( 408bb10b79STom Joseph endian::from_ipmi(request->managedSystemSessionID))).lock(); 418bb10b79STom Joseph } 428bb10b79STom Joseph catch (std::exception& e) 438bb10b79STom Joseph { 448bb10b79STom Joseph std::cerr << e.what() << "\n"; 458bb10b79STom Joseph response->rmcpStatusCode = 468bb10b79STom Joseph static_cast<uint8_t>(RAKP_ReturnCode::INVALID_SESSION_ID); 478bb10b79STom Joseph return outPayload; 488bb10b79STom Joseph } 498bb10b79STom Joseph 508bb10b79STom Joseph // Update transaction time 518bb10b79STom Joseph session->updateLastTransactionTime(); 528bb10b79STom Joseph 538bb10b79STom Joseph auto rcSessionID = endian::to_ipmi(session->getRCSessionID()); 548bb10b79STom Joseph auto bmcSessionID = endian::to_ipmi(session->getBMCSessionID()); 558bb10b79STom Joseph auto authAlgo = session->getAuthAlgo(); 568bb10b79STom Joseph 578bb10b79STom Joseph /* 588bb10b79STom Joseph * Generate Key Authentication Code - RAKP 2 598bb10b79STom Joseph * 608bb10b79STom Joseph * 1) Remote Console Session ID - 4 bytes 618bb10b79STom Joseph * 2) Managed System Session ID - 4 bytes 628bb10b79STom Joseph * 3) Remote Console Random Number - 16 bytes 638bb10b79STom Joseph * 4) Managed System Random Number - 16 bytes 648bb10b79STom Joseph * 5) Managed System GUID - 16 bytes 658bb10b79STom Joseph * 6) Requested Privilege Level - 1 byte 668bb10b79STom Joseph * 7) User Name Length Byte - 1 byte (0 for 'null' username) 678bb10b79STom Joseph * 8) User Name - variable (absent for 'null' username) 688bb10b79STom Joseph */ 698bb10b79STom Joseph 708bb10b79STom Joseph std::vector<uint8_t> input; 718bb10b79STom Joseph input.resize(sizeof(rcSessionID) + sizeof(bmcSessionID) + 728bb10b79STom Joseph cipher::rakp_auth::REMOTE_CONSOLE_RANDOM_NUMBER_LEN + 738bb10b79STom Joseph cipher::rakp_auth::BMC_RANDOM_NUMBER_LEN + 748bb10b79STom Joseph BMC_GUID_LEN + sizeof(request->req_max_privilege_level) + 758bb10b79STom Joseph sizeof(request->user_name_len)); 768bb10b79STom Joseph 778bb10b79STom Joseph auto iter = input.begin(); 788bb10b79STom Joseph 798bb10b79STom Joseph // Remote Console Session ID 808bb10b79STom Joseph std::copy_n(reinterpret_cast<uint8_t*>(&rcSessionID), 818bb10b79STom Joseph sizeof(rcSessionID), iter); 828bb10b79STom Joseph std::advance(iter, sizeof(rcSessionID)); 838bb10b79STom Joseph 848bb10b79STom Joseph // Managed System Session ID 858bb10b79STom Joseph std::copy_n(reinterpret_cast<uint8_t*>(&bmcSessionID), sizeof(bmcSessionID), 868bb10b79STom Joseph iter); 878bb10b79STom Joseph std::advance(iter, sizeof(bmcSessionID)); 888bb10b79STom Joseph 898bb10b79STom Joseph // Copy the Remote Console Random Number from the RAKP1 request to the 908bb10b79STom Joseph // Authentication Algorithm 9118a45e9dSTom Joseph std::copy_n(reinterpret_cast<const uint8_t*> 928bb10b79STom Joseph (request->remote_console_random_number), 938bb10b79STom Joseph cipher::rakp_auth::REMOTE_CONSOLE_RANDOM_NUMBER_LEN, 948bb10b79STom Joseph authAlgo->rcRandomNum.begin()); 958bb10b79STom Joseph 968bb10b79STom Joseph std::copy(authAlgo->rcRandomNum.begin(), authAlgo->rcRandomNum.end(), 978bb10b79STom Joseph iter); 988bb10b79STom Joseph std::advance(iter, cipher::rakp_auth::REMOTE_CONSOLE_RANDOM_NUMBER_LEN); 998bb10b79STom Joseph 1008bb10b79STom Joseph // Generate the Managed System Random Number 1018bb10b79STom Joseph if (!RAND_bytes(input.data() + sizeof(rcSessionID) + sizeof(bmcSessionID) + 1028bb10b79STom Joseph cipher::rakp_auth::REMOTE_CONSOLE_RANDOM_NUMBER_LEN, 1038bb10b79STom Joseph cipher::rakp_auth::BMC_RANDOM_NUMBER_LEN)) 1048bb10b79STom Joseph { 1058bb10b79STom Joseph response->rmcpStatusCode = 1068bb10b79STom Joseph static_cast<uint8_t>(RAKP_ReturnCode::INSUFFICIENT_RESOURCE); 1078bb10b79STom Joseph return outPayload; 1088bb10b79STom Joseph } 1098bb10b79STom Joseph 1108bb10b79STom Joseph // Copy the Managed System Random Number to the Authentication Algorithm 1118bb10b79STom Joseph std::copy_n(iter, cipher::rakp_auth::BMC_RANDOM_NUMBER_LEN, 1128bb10b79STom Joseph authAlgo->bmcRandomNum.begin()); 1138bb10b79STom Joseph std::advance(iter, cipher::rakp_auth::BMC_RANDOM_NUMBER_LEN); 1148bb10b79STom Joseph 1158bb10b79STom Joseph // Managed System GUID 116*83029cb8STom Joseph std::copy_n(cache::guid.data(), cache::guid.size(), iter); 1178bb10b79STom Joseph std::advance(iter, BMC_GUID_LEN); 1188bb10b79STom Joseph 1198bb10b79STom Joseph // Requested Privilege Level 1208bb10b79STom Joseph session->curPrivLevel = static_cast<session::Privilege> 1218bb10b79STom Joseph (request->req_max_privilege_level); 1228bb10b79STom Joseph std::copy_n(&(request->req_max_privilege_level), 1238bb10b79STom Joseph sizeof(request->req_max_privilege_level), iter); 1248bb10b79STom Joseph std::advance(iter, sizeof(request->req_max_privilege_level)); 1258bb10b79STom Joseph 1268bb10b79STom Joseph // Set Max Privilege to ADMIN 1278bb10b79STom Joseph session->maxPrivLevel = session::Privilege::ADMIN; 1288bb10b79STom Joseph 1298bb10b79STom Joseph // User Name Length Byte 1308bb10b79STom Joseph std::copy_n(&(request->user_name_len), sizeof(request->user_name_len), 1318bb10b79STom Joseph iter); 1328bb10b79STom Joseph 1338bb10b79STom Joseph // Generate Key Exchange Authentication Code - RAKP2 1348bb10b79STom Joseph auto output = authAlgo->generateHMAC(input); 1358bb10b79STom Joseph 1368bb10b79STom Joseph response->messageTag = request->messageTag; 1378bb10b79STom Joseph response->rmcpStatusCode = static_cast<uint8_t>(RAKP_ReturnCode::NO_ERROR); 1388bb10b79STom Joseph response->reserved = 0; 1398bb10b79STom Joseph response->remoteConsoleSessionID = rcSessionID ; 1408bb10b79STom Joseph 1418bb10b79STom Joseph // Copy Managed System Random Number to the Response 1428bb10b79STom Joseph std::copy(authAlgo->bmcRandomNum.begin(), authAlgo->bmcRandomNum.end(), 1438bb10b79STom Joseph response->managed_system_random_number); 1448bb10b79STom Joseph 1458bb10b79STom Joseph // Copy System GUID to the Response 146*83029cb8STom Joseph std::copy_n(cache::guid.data(), 147*83029cb8STom Joseph cache::guid.size(), 148*83029cb8STom Joseph response->managed_system_guid); 1498bb10b79STom Joseph 1508bb10b79STom Joseph // Insert the HMAC output into the payload 1518bb10b79STom Joseph outPayload.insert(outPayload.end(), output.begin(), output.end()); 1528bb10b79STom Joseph 1538bb10b79STom Joseph std::cout << "<< RAKP12\n"; 1548bb10b79STom Joseph return outPayload; 1558bb10b79STom Joseph } 1568bb10b79STom Joseph 1578bb10b79STom Joseph } // namespace command 158