Compare commits

..

No commits in common. "master" and "v1.1.0" have entirely different histories.

7 changed files with 64 additions and 59 deletions

1
.gitignore vendored
View File

@ -1,7 +1,6 @@
.idea .idea
server/config.yml server/config.yml
.vscode .vscode
*.ino.cpp
# ---> Python # ---> Python
# Byte-compiled / optimized / DLL files # Byte-compiled / optimized / DLL files

View File

@ -257,10 +257,11 @@ bool TeleClientUDP::notify(byte event, const char* payload)
if (wifi.connected()) if (wifi.connected())
{ {
#if SERVER_ENCRYPTION_ENABLE == 1 #if SERVER_ENCRYPTION_ENABLE == 1
unsigned int encrypted_len; char *orig_send_buf = netbuf.buffer();
unsigned char* encrypted_buf = encrypt_buffer(netbuf.buffer(), netbuf.length(), &encrypted_len); unsigned int orig_send_buf_len = netbuf.length();
bool wifi_send = wifi.send((const char *)encrypted_buf, encrypted_len); unsigned char encrypted_buf[12 + orig_send_buf_len + 16];
free(encrypted_buf); encrypt_string((unsigned char *)orig_send_buf, orig_send_buf_len, encrypted_buf);
if (!wifi.send((const char *)encrypted_buf, sizeof(encrypted_buf))) break;
#else #else
if (!wifi.send(netbuf.buffer(), netbuf.length())) break; if (!wifi.send(netbuf.buffer(), netbuf.length())) break;
#endif #endif
@ -269,11 +270,11 @@ bool TeleClientUDP::notify(byte event, const char* payload)
#endif #endif
{ {
#if SERVER_ENCRYPTION_ENABLE == 1 #if SERVER_ENCRYPTION_ENABLE == 1
unsigned int encrypted_len; char *orig_send_buf = netbuf.buffer();
unsigned char* encrypted_buf = encrypt_buffer(netbuf.buffer(), netbuf.length(), &encrypted_len); unsigned int orig_send_buf_len = netbuf.length();
bool cell_send = cell.send((const char *)encrypted_buf, encrypted_len); unsigned char encrypted_buf[12 + orig_send_buf_len + 16];
free(encrypted_buf); encrypt_string((unsigned char *)orig_send_buf, orig_send_buf_len, encrypted_buf);
if (!cell_send) break; if (!cell.send((const char *)encrypted_buf, sizeof(encrypted_buf))) break;
#else #else
if (!cell.send(netbuf.buffer(), netbuf.length())) break; if (!cell.send(netbuf.buffer(), netbuf.length())) break;
#endif #endif

View File

@ -65,11 +65,33 @@ void decrypt_string(const unsigned char *input, size_t length, unsigned char *ou
// Decrypt the input data // Decrypt the input data
size_t decryptedLength = length - sizeof(nonce) - chachaPoly.tagSize(); size_t decryptedLength = length - sizeof(nonce) - chachaPoly.tagSize();
chachaPoly.decrypt(output, input + sizeof(nonce), decryptedLength); chachaPoly.decrypt(output, input + sizeof(nonce), decryptedLength);
// String decryptedString = "";
// for (size_t i = 0; i < decryptedLength; i++) {
// decryptedString += (char)output[i];
// }
// Serial.println(decryptedString);
const unsigned char *tagPtr = input + sizeof(nonce) + decryptedLength; // actual tag const unsigned char *tagPtr = input + sizeof(nonce) + decryptedLength; // actual tag
uint8_t computedTag[16]; // computed tag uint8_t computedTag[16]; // computed tag
chachaPoly.computeTag(computedTag, sizeof(computedTag)); chachaPoly.computeTag(computedTag, sizeof(computedTag));
// Serial.print("Tag: ");
// for (size_t i = 0; i < chachaPoly.tagSize(); i++) {
// Serial.print(tagPtr[i], HEX);
// Serial.print(" ");
// }
// Serial.println();
// Serial.print("Computed Tag: ");
// for (size_t i = 0; i < sizeof(computedTag); i++) {
// Serial.print(computedTag[i], HEX);
// Serial.print(" ");
// }
// Serial.println();
///// BEGIN TAG VERIFY
// The crypto library implementation of tag verification crashes.
// Can never match if the expected tag length is too long. // Can never match if the expected tag length is too long.
if (chachaPoly.tagSize() > 16) { if (chachaPoly.tagSize() > 16) {
Serial.println("[CHACHA] Authentication failed: expected tag length is too long"); Serial.println("[CHACHA] Authentication failed: expected tag length is too long");
@ -78,28 +100,17 @@ void decrypt_string(const unsigned char *input, size_t length, unsigned char *ou
} }
// Compute the tag and check it. // Compute the tag and check it.
// The crypto library implementation of tag verification crashes.
bool equal = secure_compare(computedTag, tagPtr, chachaPoly.tagSize()); bool equal = secure_compare(computedTag, tagPtr, chachaPoly.tagSize());
clean(computedTag); clean(computedTag);
if (!equal) { if (!equal) {
Serial.println("[CHACHA] Authentication failed!"); Serial.println("[CHACHA] Authentication failed!");
output[0] = '\0'; output[0] = '\0';
return; return;
} }
///// END TAG VERIFY
output[decryptedLength] = '\0'; output[decryptedLength] = '\0';
chachaPoly.clear(); chachaPoly.clear();
} }
unsigned char* encrypt_buffer(char* buf, unsigned int len, unsigned int* encrypted_len) {
// Increase the size of encrypted_buf to hold the nonce, the encrypted data, and the authentication tag.
unsigned char* encrypted_buf = (unsigned char*)malloc(12 + len + 16); // 12 bytes for nonce and 16 bytes for tag
if(!encrypted_buf) {
// handle error
return NULL;
}
encrypt_string((unsigned char *)buf, len, encrypted_buf);
*encrypted_len = 12 + len + 16;
return encrypted_buf;
}

View File

@ -6,5 +6,4 @@
void encrypt_string(const unsigned char *input, size_t length, unsigned char *output); void encrypt_string(const unsigned char *input, size_t length, unsigned char *output);
void decrypt_string(const unsigned char *input, size_t length, unsigned char *output); void decrypt_string(const unsigned char *input, size_t length, unsigned char *output);
void print_hex(const unsigned char *data, size_t length); void print_hex(const unsigned char *data, size_t length);
unsigned char* encrypt_buffer(char* buf, unsigned int len, unsigned int* encrypted_len);

View File

@ -62,12 +62,6 @@ PID_POLLING_INFO obdData[]= {
{PID_TIMING_ADVANCE, 2}, {PID_TIMING_ADVANCE, 2},
{PID_COOLANT_TEMP, 3}, {PID_COOLANT_TEMP, 3},
{PID_INTAKE_TEMP, 3}, {PID_INTAKE_TEMP, 3},
{PID_ODOMETER, 3},
{PID_DISTANCE, 3},
{PID_AMBIENT_TEMP, 2},
{PID_ENGINE_OIL_TEMP, 2},
{PID_FUEL_LEVEL, 1}
}; };
CBufferManager bufman; CBufferManager bufman;
@ -1013,11 +1007,12 @@ void telemetry(void* inst)
#endif #endif
#if SERVER_ENCRYPTION_ENABLE == 1 #if SERVER_ENCRYPTION_ENABLE == 1
unsigned int encrypted_len; char *orig_send_buf = store.buffer();
unsigned char* encrypted_buf = encrypt_buffer(store.buffer(), store.length(), &encrypted_len); unsigned int orig_send_buf_len = store.length();
bool transmit_success = teleClient.transmit((const char *)encrypted_buf, encrypted_len); // Increase the size of encrypted_buf to hold the nonce, the encrypted data, and the authentication tag.
free(encrypted_buf); unsigned char encrypted_buf[12 + orig_send_buf_len + 16]; // 12 bytes for nonce and 16 bytes for tag
if (transmit_success) { encrypt_string((unsigned char *)orig_send_buf, orig_send_buf_len, encrypted_buf);
if (teleClient.transmit((const char *)encrypted_buf, sizeof(encrypted_buf))) {
#else #else
if (teleClient.transmit(store.buffer(), store.length())) { if (teleClient.transmit(store.buffer(), store.length())) {
#endif #endif

View File

@ -107,7 +107,7 @@ void CStorageRAM::header(const char* devid)
void CStorageRAM::tailer() void CStorageRAM::tailer()
{ {
if (m_cache[m_cacheBytes - 1] == ',') m_cacheBytes--; if (m_cache[m_cacheBytes - 1] == ',') m_cacheBytes--;
m_cacheBytes += sprintf(m_cache + m_cacheBytes, "*%02X", (unsigned int)checksum(m_cache, m_cacheBytes)); m_cacheBytes += sprintf(m_cache + m_cacheBytes, "*%X", (unsigned int)checksum(m_cache, m_cacheBytes));
} }
void CStorageRAM::untailer() void CStorageRAM::untailer()

View File

@ -84,22 +84,21 @@ func main() {
// Handle the message. // Handle the message.
go func(addr *net.UDPAddr, buf []byte, n int) { go func(addr *net.UDPAddr, buf []byte, n int) {
// Do the decryption.
var plaintext []byte var plaintext []byte
shouldEncrypt := true if len(buf[:n]) > 0 {
recievedContent := buf[:n] plaintext, err = encryption.Decrypt(key, buf[:n]) // Use only the part of the buffer that has data.
if len(recievedContent) > 0 {
plaintext, err = encryption.Decrypt(key, recievedContent) // Use only the part of the buffer that has data.
if err != nil { if err != nil {
logger.Warningf(formatLogMsg(addr.IP.String(), dest.Address, dest.Port, fmt.Sprintf(`Error decrypting message: %s. Length: %d, Raw: "%s"`, err, len(recievedContent), recievedContent))) rawHex := hex.EncodeToString(buf[:n])
plaintext = recievedContent // Don't bother with decryption. logger.Warnf(formatLogMsg(addr.IP.String(), dest.Address, dest.Port, fmt.Sprintf(`Error decrypting message: %s. Length: %d, Raw: "%s"`, err, len(rawHex), rawHex)))
shouldEncrypt = false plaintext = buf[:n] // Forward the raw message to the backend without bothering with decryption.
} else { if len(plaintext) > 0 {
logger.Infof(formatLogMsg(addr.IP.String(), dest.Address, dest.Port, string(plaintext))) logger.Warningf("Encryption failed, possibly recieved unencrypted message -- %s", plaintext)
}
} }
} else { } else {
// If empty message. // If empty message.
plaintext = recievedContent plaintext = buf[:n]
shouldEncrypt = false
} }
forwardAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", dest.Address, dest.Port)) forwardAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", dest.Address, dest.Port))
@ -108,12 +107,14 @@ func main() {
return return
} }
// Create a new UDP address for listening to the backend server's response.
listenAddr, err := net.ResolveUDPAddr("udp", ":0") // Let the OS pick a free port. listenAddr, err := net.ResolveUDPAddr("udp", ":0") // Let the OS pick a free port.
if err != nil { if err != nil {
logger.Fatalln("Error resolving listen address:", err) logger.Fatalln("Error resolving listen address:", err)
return return
} }
// Create a new UDP listener for the backend server's response.
listenConn, err := net.ListenUDP("udp", listenAddr) listenConn, err := net.ListenUDP("udp", listenAddr)
if err != nil { if err != nil {
logger.Fatalln("Error listening for backend response:", err) logger.Fatalln("Error listening for backend response:", err)
@ -121,6 +122,7 @@ func main() {
} }
defer listenConn.Close() defer listenConn.Close()
// Dial the backend server without binding a local address.
forwardConn, err := net.DialUDP("udp", nil, forwardAddr) forwardConn, err := net.DialUDP("udp", nil, forwardAddr)
if err != nil { if err != nil {
logger.Fatalln("Error dialing to forward address:", err) logger.Fatalln("Error dialing to forward address:", err)
@ -143,15 +145,11 @@ func main() {
return return
} }
var encryptedBackendResponse []byte // Encrypt the backend's response.
if shouldEncrypt { encryptedBackendResponse, err := encryption.Encrypt(key, backendResponse[:n])
encryptedBackendResponse, err = encryption.Encrypt(key, backendResponse[:n]) if err != nil {
if err != nil { logger.Errorf(formatLogMsg(addr.IP.String(), dest.Address, dest.Port, fmt.Sprintf("Error encrypting response: %s", err)))
logger.Errorf(formatLogMsg(addr.IP.String(), dest.Address, dest.Port, fmt.Sprintf("Error encrypting response: %s", err))) return
return
}
} else {
encryptedBackendResponse = backendResponse
} }
// Forward the encrypted backend response to the client. // Forward the encrypted backend response to the client.
@ -160,6 +158,8 @@ func main() {
logger.Errorf(formatLogMsg(addr.IP.String(), dest.Address, dest.Port, fmt.Sprintf("Error forwarding response to client: %s", err))) logger.Errorf(formatLogMsg(addr.IP.String(), dest.Address, dest.Port, fmt.Sprintf("Error forwarding response to client: %s", err)))
return return
} }
logger.Infof(formatLogMsg(addr.IP.String(), dest.Address, dest.Port, string(plaintext)))
}(addr, buf, n) }(addr, buf, n)
} }
}(port, dest) }(port, dest)