void CBaseObj::SendRefMsg(Msg &pMsg) { assert(m_GateIDMax < gateinfo_count); for (int i = m_GateIDMin; i <= m_GateIDMax; ++i) { gateinfo[i]->Reset(); } static bool bNeeSendMsg = false; static msgtail tail; std::unordered_map<uint32, CBaseObj *> *playerlist = GetAoiList(); std::unordered_map<uint32, CBaseObj *>::iterator iter = playerlist->begin(); for (; iter != playerlist->end(); ++iter) { if (iter->second->IsPlayer()) { CPlayer * p = (CPlayer *)iter->second; if (FuncUti::isValidCret(p)) { int32 gateid = p->GetGateID(); if (gateid >= 0 && gateid < gateinfo_count) { if (gateid > m_GateIDMax) { m_GateIDMax = gateid; } else if (gateid < m_GateIDMin) { m_GateIDMin = gateid; } if (gateinfo[gateid]->gate == nullptr) { gateinfo[gateid]->gate = p->GetGateInfo(); } gateinfo[gateid]->nClientId[gateinfo[gateid]->nCount] = p->GetClientID(); gateinfo[gateid]->nCount += 1; } } } } static bool bIsPlayer = false; bIsPlayer = IsPlayer(); if (bNeeSendMsg || bIsPlayer) { if (bIsPlayer) { CPlayer *p = (CPlayer *)this; int32 gateid = p->GetGateID(); if (gateid >= 0 && gateid < gateinfo_count) { if (gateid > m_GateIDMax) { m_GateIDMax = gateid; } else if (gateid < m_GateIDMin) { m_GateIDMin = gateid; } if (gateinfo[gateid]->gate == nullptr) { gateinfo[gateid]->gate = p->GetGateInfo(); } gateinfo[gateid]->nClientId[gateinfo[gateid]->nCount] = p->GetClientID(); gateinfo[gateid]->nCount += 1; } } bNeeSendMsg = false; MessagePack pkmain; pkmain.PushInt32(pMsg.GetLength()); pkmain.PushBlock(&pMsg, pMsg.GetLength()); int32 pkmainlen = pkmain.GetLength(); for (int i = m_GateIDMin; i < m_GateIDMax; ++i) { if (gateinfo[i]->nCount > 0) { tail.id = 0; for (int j = 0; j < gateinfo[i]->nCount; ++j) { pkmain.PushInt32(gateinfo[i]->nClientId[j]); --tail.id; } GameGatewayMgr.SendMsg(gateinfo[i]->gate, pkmain, &tail, sizeof(tail)); pkmain.SetLength(pkmainlen); pkmain.m_index = pkmainlen - (int32)sizeof(Msg); } } } }
//----------------------------------------------------------------------------- // <Security::EncryptMessage> // Encrypt and send a Z-Wave message securely. //----------------------------------------------------------------------------- bool Security::EncryptMessage ( uint8 const* _nonce ) { #if 1 if( m_nonceTimer.GetMilliseconds() > 10000 ) { // The nonce was not received within 10 seconds // of us sending the nonce request. Send it again RequestNonce(); return false; } // Fetch the next payload from the queue and encapsulate it m_queueMutex->Lock(); if( m_queue.empty() ) { // Nothing to do m_queueMutex->Release(); return false; } SecurityPayload * payload = m_queue.front(); m_queue.pop_front(); //uint32 queueSize = m_queue.size(); m_queueMutex->Unlock(); #else uint32 queueSize = m_queue.size(); struct SecurityPayload payload; payload.m_length = 7; payload.m_part = 0; uint8 tmpdata[7] = {0x62, 0x03, 0x00, 0x10, 0x02, 0xfe, 0xfe}; for (int i = 0; i < payload.m_length; i++) payload.m_data[i] = tmpdata[i]; #endif // Encapsulate the message fragment /* MessageEncapNonceGet doesn't seem to work */ //Msg* msg = new Msg( (queueSize>1) ? "SecurityCmd_MessageEncapNonceGet" : "SecurityCmd_MessageEncap", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); string LogMessage("SecurityCmd_MessageEncap ("); LogMessage.append(payload->logmsg); LogMessage.append(")"); Msg* msg = new Msg( LogMessage, GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); msg->Append( GetNodeId() ); msg->Append( payload->m_length + 20 ); msg->Append( GetCommandClassId() ); //msg->Append( (queueSize>1) ? SecurityCmd_MessageEncapNonceGet : SecurityCmd_MessageEncap ); msg->Append( SecurityCmd_MessageEncap ); /* create the iv * */ uint8 initializationVector[16]; /* the first 8 bytes of a outgoing IV are random */ for (int i = 0; i < 8; i++) { //initializationVector[i] = (rand()%0xFF)+1; initializationVector[i] = 0xAA; } /* the remaining 8 bytes are the NONCE we got from the device */ for (int i = 0; i < 8; i++) { initializationVector[8+i] = _nonce[i]; } /* Append the first 8 bytes of the initialization vector * to the message. The remaining 8 bytes are the NONCE we recieved from * the node, and is ommitted from sending back to the Node. But we use the full 16 bytes to * as the IV to encrypt out message. */ for(int i=0; i<8; ++i ) { msg->Append( initializationVector[i] ); } // Append the sequence data uint8 sequence = 0; if( payload->m_part == 0 ) { sequence = 0; } else if( payload->m_part == 1 ) { sequence = (++m_sequenceCounter) & 0x0f; sequence |= 0x10; // Sequenced, first frame } if( payload->m_part == 2 ) { sequence = m_sequenceCounter & 0x0f; sequence |= 0x30; // Sequenced, second frame } /* at most, the payload will be 28 bytes + 1 byte for the Sequence. */ uint8 plaintextmsg[32]; plaintextmsg[0] = sequence; for (int i = 0; i < payload->m_length; i++) plaintextmsg[i+1] = payload->m_data[i]; /* Append the message payload after encrypting it with AES-OFB (key is EncryptPassword, * full IV (16 bytes - 8 Random and 8 NONCE) and payload.m_data */ PrintHex("Input Packet:", plaintextmsg, payload->m_length+1); #ifdef DEBUG PrintHex("IV:", initializationVector, 16); #endif uint8 encryptedpayload[30]; aes_mode_reset(this->EncryptKey); if (aes_ofb_encrypt(plaintextmsg, encryptedpayload, payload->m_length+1, initializationVector, this->EncryptKey) == EXIT_FAILURE) { Log::Write(LogLevel_Warning, GetNodeId(), "Failed to Encrypt Packet"); delete msg; return false; } #ifdef DEBUG PrintHex("Encrypted Output", encryptedpayload, payload->m_length+1); /* The Following Code attempts to Decrypt the Packet and Verify */ /* the first 8 bytes of a outgoing IV are random */ for (int i = 0; i < 8; i++) { //initializationVector[i] = (rand()%0xFF)+1; initializationVector[i] = 0xAA; } /* the remaining 8 bytes are the NONCE we got from the device */ for (int i = 0; i < 8; i++) { initializationVector[8+i] = _nonce[i]; } aes_mode_reset(this->EncryptKey); uint8 tmpoutput[16]; if (aes_ofb_encrypt(encryptedpayload, tmpoutput, payload->m_length+1, initializationVector, this->EncryptKey) == EXIT_FAILURE) { Log::Write(LogLevel_Warning, GetNodeId(), "Failed to Encrypt Packet"); delete msg; return false; } PrintHex("Decrypted output", tmpoutput, payload->m_length+1); #endif for(int i=0; i<payload->m_length+1; ++i ) { msg->Append( encryptedpayload[i] ); } // Append the nonce identifier :) msg->Append(_nonce[0]); /* Append space for the authentication data Set with AES-CBCMAC (key is AuthPassword, * Full IV (16 bytes - 8 random and 8 NONCE) and sequence|SrcNode|DstNode|payload.m_length|payload.m_data * */ /* Regenerate IV */ /* the first 8 bytes of a outgoing IV are random */ for (int i = 0; i < 8; i++) { //initializationVector[i] = (rand()%0xFF)+1; initializationVector[i] = 0xAA; } /* the remaining 8 bytes are the NONCE we got from the device */ for (int i = 0; i < 8; i++) { initializationVector[8+i] = _nonce[i]; } uint8 mac[8]; this->GenerateAuthentication(&msg->GetBuffer()[7], msg->GetLength()+2, GetDriver()->GetNodeId(), GetNodeId(), initializationVector, mac); for(int i=0; i<8; ++i ) { msg->Append( mac[i] ); } #ifdef DEBUG PrintHex("Auth", mac, 8); #endif msg->Append( GetDriver()->GetTransmitOptions() ); #ifdef DEBUG PrintHex("Outgoing", msg->GetBuffer(), msg->GetLength()); #endif GetDriver()->SendMsg(msg, Driver::MsgQueue_Security); /* finally, if the message we just sent is a NetworkKeySet, then we need to reset our Network Key here * as the reply we will get back will be encrypted with the new Network key */ if ((this->m_networkkeyset == false) && (payload->m_data[0] == 0x98) && (payload->m_data[1] == 0x06)) { Log::Write(LogLevel_Info, GetNodeId(), "Reseting Network Key after Inclusion"); this->m_networkkeyset = true; SetupNetworkKey(); } delete payload; return true; }