int main(int argc, register char **argv) { register char *curchar; char cKeyChar; int nKeyLen; // initialize // memset(freqtab, '\0', 256 * sizeof(int)); // memset(&header, '\0', sizeof(header)); for (i = 0; (i < 256); i++) freqtab[i] = '\0'; // set default encryption key for (i = 0, cKeyChar = ' '; i < BC_MAX_USER_KEY; i++) { cKeyChar += (int)szDefKeyOffsets[i]; cEncKey[i] = cKeyChar; } header.usSignature = 0xEBBE; // set compression signature szInputName[0] = szOutputName[0] = '\0'; // check for too few args or "batcomp /?" if ((argc == 1) || (stricmp(argv[1],"/?") == 0)) usage(); // parse command line for (argv++ ; argc > 1; argv++, argc--) { if (**argv == '/') { switch (toupper((*argv)[1])) { case 'O': fOverwrite = 1; continue; case 'Q': fQuiet = 1; continue; case 'K': fKillComments = 1; continue; case 'E': // Set encryption flag, copy key (or as much of it as we need) fEncrypt = 1; if ((nKeyLen = (int)strlen(&((*argv)[2]))) > 0) memcpy(cEncKey, &((*argv)[2]), (nKeyLen > BC_MAX_USER_KEY) ? BC_MAX_USER_KEY : nKeyLen); continue; default: usage(); } } if (szInputName[0] == '\0') strcpy(szInputName, *argv); else if (szOutputName[0] == '\0') strcpy(szOutputName, *argv); else usage(); } if (szInputName[0] == 0) usage(); if (fQuiet == 0) printf(COPYRIGHT, PROGNAME); if (szOutputName[0] == 0) { strcpy(szOutputName, szInputName); // check if it gets too long? if ((out_ext = strrchr(szOutputName, '.')) == NULL) out_ext = szOutputName + strlen(szOutputName); strcpy(out_ext, ".btm"); } if (fQuiet == 0) printf(COMPMSG, szInputName, szOutputName); // need full filename expansion here?? if (stricmp(szInputName, szOutputName) == 0) error(ERR_SAMENAME); // holler if no overwrite and output exists if ((fOverwrite == 0) && (sopen(szOutputName, (O_RDONLY | O_BINARY), SH_DENYNO) != -1)) error(ERR_OVERWRITE); // open input, deny read-write mode in case we get fooled and this is output as well! if ((in = sopen(szInputName, (O_RDONLY | O_BINARY), SH_DENYRW)) == -1) error(ERR_INPUT_OPEN); // rewind & read the file header read(in,(void *)&lCompressed,4); // check for input file already compressed if ((lCompressed & 0xFFFF) == 0xBEEB) error(ERR_ALREADY_COMPRESSED); // rewind input file lseek(in,0L,0); // open output if ((out = sopen(szOutputName, (O_CREAT | O_TRUNC | O_RDWR | O_BINARY), SH_DENYRW, (S_IREAD | S_IWRITE))) == -1) error(ERR_OUTPUT_OPEN); // loop for two passes for (pass = 1; (pass <= 2); pass++) { uLines = 0; // clear line count if (pass == 2) { // output (unfinished) header if (fEncrypt) { // set up encryption key, encrypt common character table TripleKey(cEncKey); EncryptDecrypt(NULL, (char _far *)cEncKey, (char _far *)header.cCommon, BC_COM_SIZE); } data_out((char *)(&header), sizeof(header), 0, 0); if (fEncrypt) { // put common character table back like it was, also // leaves encryption system in its post-table state // for use in encrypting text stream EncryptDecrypt(NULL, (char _far *)cEncKey, (char _far *)header.cCommon, BC_COM_SIZE); // output dummy (gibberish) data for encryption key data_out((char *)(&freqtab), BC_MAX_USER_KEY, 0, 0); } // set buffer address dataptr = szOutputBuffer; } // back up to start if (lseek(in, 0L, SEEK_SET) == -1L) error(ERR_INPUT_SEEK); while (getline(szInputBuffer) > 0) { // scan or translate line // strip trailing whitespace strip_trailing(szInputBuffer); // skip blank lines and comments if (fKillComments && ((szInputBuffer[0] == '\0') || (strnicmp(szInputBuffer,"::",2) == 0))) continue; // check for REM if (fKillComments && ((strnicmp(szInputBuffer, "rem ", 4) == 0) && (strnicmp(szInputBuffer, "rem >", 5) != 0))) continue; if (fQuiet == 0) printf(COMPLINE, ++uLines); curchar = szInputBuffer; if (pass == 1) { // pass 1, scan the line // accum. char counts for ( ; (*curchar != '\0'); curchar++) freqtab[(int)*curchar]++; } else { // pass 2, translate the line // count line length including CR i = (int)strlen(szInputBuffer); nTotalBytes += i; if ((lTotalInput += (i + 1)) >= 0xFFE0L) error(ERR_TOO_BIG); // compress & output each character for ( ; *curchar; curchar++) { char *comptr; if ((comptr = memchr(header.cCommon, *curchar, BC_COM_SIZE)) == NULL) { // not in table, 3 nibbles nibble_out(0); nibble_out((char)(*curchar & 0xF)); nibble_out((char)(*curchar >> 4)); } else if (comptr >= max_one_nib) { // last part of table, 2 nibbles nibble_out(1); nibble_out((char)(comptr - max_one_nib)); } else { // beginning of table, just one nibble nibble_out((char)(comptr - header.cCommon + 2)); } } } }
void WHartNetworkData::TransmitIndicate(const WHartLocalStatus& localStatus, WHartPriority priority, const WHartDllAddress& dllSrc, WHartPayload& npdu) { // LOG_DEBUG("TransmitIndicate: localStatus=" << localStatus.status << ", priority=" << priority << ", dllSrc=" // << dllSrc << ", NPDU=" << npdu); BinaryStream stream; STREAM_INIT(&stream, npdu.data, npdu.dataLen); //parse network header uint8_t controlByte; STREAM_READ_UINT8(&stream, &controlByte); uint8_t ttl; STREAM_READ_UINT8(&stream, &ttl); uint16_t asn; STREAM_READ_UINT16(&stream, &asn); //HACK:[andrei.petrut] - write ASN to common data so it can be used in the next packet... commonData.lastReadASN = asn; uint16_t graphID; STREAM_READ_UINT16(&stream, &graphID); WHartAddress dest; StreamReadNetAddress(&stream, dest, (controlByte & CONTROLTYPE_DESTADDRESS_MASK) == 0); WHartAddress src; StreamReadNetAddress(&stream, src, (controlByte & CONTROLTYPE_SRCADDRESS_MASK) == 0); //TODO:[andy] - implement isBroadcast bool isForMe = (dest == commonData.myNickname || dest == commonData.myUniqueID); bool isBroadcast = false; bool isSourceRoute = ((controlByte & CONTROLTYPE_1STSOURCEROUTE_MASK) != 0); WHartShortAddress proxy = 0; if (controlByte & CONTROLTYPE_PROXYROUTE_MASK) { STREAM_READ_UINT16(&stream, &proxy); } Route tempRoute; if (isSourceRoute) { tempRoute.destinationType = Route::dtSourceRoute; tempRoute.graphID = graphID; for (int i = 0; i < 4; i++) { WHartShortAddress addr; STREAM_READ_UINT16(&stream, &addr); if (addr != 0xFFFF) { tempRoute.sourceRoutePath.push_back(addr); } } if (controlByte & CONTROLTYPE_2NDSOURCEROUTE_MASK) { for (int i = 0; i < 4; i++) { WHartShortAddress addr; STREAM_READ_UINT16(&stream, &addr); if (addr != 0xFFFF) { tempRoute.sourceRoutePath.push_back(addr); } } } } // LOG_DEBUG("TransmitIndicate: isForMe=" << (int) isForMe << ", isBroadcast=" << (int) isBroadcast << ", isSourceRoute=" << (int)isSourceRoute << ", destAddress=" // << dest << ", TTL=" << ToStringHexa(ttl) << ", ASN=" << ToStringHexa(asn) << ", graphID=" // << ToStringHexa(graphID)); if (isForMe || isBroadcast) { uint8_t securityControl; //contain session STREAM_READ_UINT8(&stream, &securityControl); WHartSessionKey::SessionKeyCode sessionKey = (WHartSessionKey::SessionKeyCode) (securityControl & 0x0F); uint8_t sessionType = securityControl & SECURITYCONTROL_SECURITYTYPE_MASK; //if join flow detected OnJoinCalback is called, in order to create session with the new device/ap if it is //provisioned correctly if ((sessionType == WHartSessionKey::joinKeyed) && (OnJoinCallback)) { OnJoinCallback(src); } SessionTable::iterator session = FindSession(src, sessionKey); if (session == sessionTable.end()) { LOG_WARN("Session for Dest=" << src << "with type=" << (int) sessionKey << " not found! packet droped."); return;//invalid session } else { // LOG_DEBUG("Session used for packet is=" << sessionKey << " and dest=" << src << " and sessionID=" << (int)session->sessionID); } uint32_t counter; if (sessionType == WHartSessionKey::sessionKeyed) { uint8_t lsbNonce; STREAM_READ_UINT8(&stream, &lsbNonce); // LOG_DEBUG("Read small nonce counter = " << (int)lsbNonce << " . Need to reconstruct nonce counter..."); // LOG_DEBUG("Session counter = " << session->receiveNonceCounter << // " Session history size = " << sizeof(session->nonceCounterHistory)<< // " and compare value=" << ((1 + ((int)session->receiveNonceCounter & 0xFF) - (int)sizeof(session->nonceCounterHistory) * 8))); counter = ReconstructNonceCounter(*session, lsbNonce); // LOG_DEBUG("Reconstructed nonce counter=" << counter); } else { STREAM_READ_UINT32(&stream, &counter); // LOG_DEBUG("Read entire nonce counter=" << counter); } // reconstruct nonce counter end WHartPayload spdu(stream.nextByte, stream.remainingBytes); uint8_t dataTPDU[CommonData::MAX_PAYLOAD]; WHartPayload tpdu(dataTPDU, sizeof(dataTPDU)); // LOG_DEBUG("Creating PDU with size=" << stream.nextByte - npdu.data << " with stream next byte=" // << nlib::detail::BytesToString(stream.nextByte, stream.nextByte - npdu.data)); CryptoStatus decryptStatus = EncryptDecrypt(*session, counter, WHartPayload(npdu.data, stream.nextByte - npdu.data), spdu, tpdu, src, dest, false); if (decryptStatus != whartcsSuccess) { LOG_WARN("transmitIndicate failed to decrypt Error=" << CryptoStatusToString(decryptStatus)); return; } //reconstruct nonce counter if (sessionType == WHartSessionKey::joinKeyed) // join flow { LOG_DEBUG("Join flow detected."); session->receiveNonceCounter = counter; } else { int noncePosition = session->receiveNonceCounter - counter; if (noncePosition > (int) (NONCECOUNTERHISTORY_BIT_LENGTH)) { //discard packet LOG_INFO("Received packet with nonce counter outside of the sliding window (nonce=" << counter << ", windowStart=" << session->receiveNonceCounter << ", windowSize=" << (int) NONCECOUNTERHISTORY_BIT_LENGTH << "). Discarding packet..."); return; } if (noncePosition < 0) { // LOG_DEBUG("New nonce received (old=" << session->receiveNonceCounter << ", new=" << counter << ". Sliding window to accommodate new nonce (with steps=" << -noncePosition << ")..."); if (noncePosition <= -32) { session->nonceCounterHistory = 0; } else { session->nonceCounterHistory = session->nonceCounterHistory >> (-noncePosition); } noncePosition = 0; session->receiveNonceCounter = counter; } uint32_t mask = 0x01 << (NONCECOUNTERHISTORY_BIT_LENGTH - noncePosition - 1); if (session->nonceCounterHistory & mask) { // already received packet with this nonce, discard LOG_WARN("Already received packet with nonce=" << counter << " from src=" << src << ". Discarding..."); return; } // mark nonce in history session->nonceCounterHistory = session->nonceCounterHistory | mask; } //forward to upper ++nextRoutedHandler; WHartHandle handle = MAKE_WHARTHANDLE(1, nextRoutedHandler); // LOG_DEBUG("transmitIndicate forward to TL" << " handle=" << handle << ", src=" << src << ", priority=" // << priority << ", TPDU=" << tpdu); upper->TransmitIndicate(handle, src, priority, tpdu, (WHartSessionKey::SessionKeyCode) (securityControl & 0x0F)); } else
int main(int argc, char **argv) { unsigned char szLine[LINE_MAX + 1], szKey[KEY_LEN + 1]; char szVarName[32], szVarVal[LINE_MAX + 1]; char szInName[256], szOutName[256], szOutBuf[LINE_MAX + 1]; char *pExt, *pNewLine; int fhIn, fhOut, i, nLen; if (argc < 3) error("Too few parameters"); // Copy the key if (strnicmp(argv[1], "/p", 2) == 0) { // /P means we have a product name for (i = 0; i < NUM_PRODUCTS; i++) { if (stricmp(argv[1] + 2, pszProdList[i]) == 0) { memcpy(szKey, acProdKeys[i], KEY_LEN); szKey[KEY_LEN] = '\0'; break; } if (i == (NUM_PRODUCTS - 1)) error("Invalid product name"); } } else { // Not a product name, must be the real key strcpy(szKey, argv[1]); if (strlen(szKey) != KEY_LEN) error("Key length error"); } // Get input name strcpy(szInName, argv[2]); // Get or set output name if (argc > 3) strcpy(szOutName, argv[3]); else { strcpy(szOutName, szInName); if ((pExt = strrchr(szOutName, '.')) != NULL) *pExt = '\0'; strcat(szOutName, ".h"); } // Open files if ((fhIn = _open(szInName, _O_RDONLY | _O_BINARY)) == -1) error("Cannot open input file"); if ((fhOut = _open(szOutName, (_O_CREAT | _O_TRUNC | _O_RDWR | _O_TEXT), (_S_IREAD | _S_IWRITE))) == -1) error("Cannot open output file"); // Process each line while (ReadLine(fhIn, szLine)) { // If it starts with #enc, encrypt it and output original text // as a comment and encrypted text as an array if (strnicmp(szLine, "#enc ", 5) == 0) { // Parse name and value if (sscanf(szLine, "%*s %32s \"%255[^\"]\"", szVarName, szVarVal) != 2) error("Invalid input data"); nLen = strlen(szVarVal); // Output original name and text as comment sprintf(szOutBuf, "// %s = \"%s\"\n", szVarName, szVarVal); // Replace ASCII 04s with CR/LF for (pNewLine = szVarVal; ((pNewLine = strchr(pNewLine, '\x04')) != NULL); pNewLine += 2 ) { *pNewLine = '\n'; // strcpy( pNewLine, pNewLine + 1 ); // strins( pNewLine, "\r\n" ); } // Encrypt it EncryptDecrypt(NULL, szKey, szVarVal, nLen); // Dump to output, max 64 charactes per line WriteText(fhOut, szOutBuf); sprintf(szOutBuf, "unsigned char %s[] = {%d, ", szVarName, nLen); WriteText(fhOut, szOutBuf); for (i = 0; i < nLen; i++) { if ((i > 0) && ((i % 64) == 0)) WriteText(fhOut, "\\\n "); sprintf(szOutBuf, "0x%.02X", (unsigned int)szVarVal[i]); WriteText(fhOut, szOutBuf); if (i != (nLen - 1)) WriteText(fhOut, ", "); } WriteText(fhOut, "};\n"); } else { // Not an encryption line, just copy it to output strcat(szLine, "\n"); WriteText(fhOut, szLine); } } return 0; }