133 lines
4.6 KiB
C
133 lines
4.6 KiB
C
#include "ch32v30x_rtc.h"
|
|
#include "lib/config.h"
|
|
#include "lib/ed25519/ed_25519.h"
|
|
#include "meshcore/meshframing.h"
|
|
#include "meshcore/packets/encrypted.h"
|
|
#include "meshcore/packetstructs.h"
|
|
#include "anonymous.h"
|
|
#include "util/hexdump.h"
|
|
#include <stdlib.h>
|
|
|
|
#define TAG "Anonymous"
|
|
|
|
void sendAnonymousRequest (NodeEntry *targetNode, const uint8_t *password, uint32_t sync) {
|
|
uint8_t passwordLen = strlen ((const char *)password);
|
|
FrameStruct frame;
|
|
uint8_t offset = 0;
|
|
|
|
// 1. Frame header
|
|
frame.header = ((targetNode->path.pathLen > 0) ? ROUTE_TYPE_DIRECT : ROUTE_TYPE_FLOOD) | PAYLOAD_TYPE_ANON_REQ | PAYLOAD_VERSION_0;
|
|
|
|
// 2. Payload header (unencrypted)
|
|
frame.payload[offset++] = targetNode->pubKey[0];
|
|
|
|
memcpy (frame.payload + offset, persistent.pubkey, 32);
|
|
offset += 32;
|
|
|
|
// 3. Build plaintext payload
|
|
uint8_t plaintext[32];
|
|
uint8_t p = 0;
|
|
|
|
uint32_t last_seen_rt = RTC_GetCounter();
|
|
plaintext[p++] = (last_seen_rt >> 0) & 0xFF;
|
|
plaintext[p++] = (last_seen_rt >> 8) & 0xFF;
|
|
plaintext[p++] = (last_seen_rt >> 16) & 0xFF;
|
|
plaintext[p++] = (last_seen_rt >> 24) & 0xFF;
|
|
|
|
if (targetNode->type == NODE_TYPE_ROOM_SERVER) {
|
|
plaintext[p++] = (sync >> 0) & 0xFF;
|
|
plaintext[p++] = (sync >> 8) & 0xFF;
|
|
plaintext[p++] = (sync >> 16) & 0xFF;
|
|
plaintext[p++] = (sync >> 24) & 0xFF;
|
|
}
|
|
|
|
if (passwordLen > 16) {
|
|
passwordLen = 16;
|
|
}
|
|
memcpy (plaintext + p, password, passwordLen);
|
|
p += passwordLen;
|
|
|
|
size_t outputLen;
|
|
// 4. Encrypt + MAC
|
|
encrypt_then_mac (
|
|
targetNode->secret,
|
|
32,
|
|
plaintext,
|
|
p,
|
|
frame.payload + offset,
|
|
&outputLen);
|
|
|
|
offset += outputLen;
|
|
|
|
// 5. Finalize and send
|
|
frame.payloadLen = offset;
|
|
memcpy(&(frame.path), &(targetNode->path), sizeof(frame.path));
|
|
|
|
hexdump ("Anon payload", frame.payload, frame.payloadLen);
|
|
|
|
sendFrame (frame);
|
|
}
|
|
|
|
AnonymousRequestPayload decodeAnonReq (FrameStruct frame) {
|
|
uint8_t index = 0;
|
|
AnonymousRequestPayload anonReq;
|
|
anonReq.destinationHash = frame.payload[index++];
|
|
memcpy (anonReq.pubKey, &(frame.payload[index]), sizeof (anonReq.pubKey));
|
|
index += sizeof (anonReq.pubKey);
|
|
anonReq.cipherMAC = frame.payload[index];
|
|
anonReq.cipherMAC |= frame.payload[index + 1] << 8;
|
|
NodeEntry *foundNode = getNode (anonReq.pubKey[0]);
|
|
if (foundNode == NULL) {
|
|
foundNode = getNextNode();
|
|
|
|
strcpy (foundNode->name, "Anonymous node");
|
|
memcpy (foundNode->pubKey, anonReq.pubKey, sizeof (foundNode->pubKey));
|
|
ed25519_key_exchange ((unsigned char *)foundNode->secret, anonReq.pubKey, persistent.privkey);
|
|
foundNode->gps_latitude = 0;
|
|
foundNode->gps_longitude = 0;
|
|
// ADD PATH
|
|
foundNode->type = 0;
|
|
foundNode->last_seen_lt = RTC_GetCounter();
|
|
}
|
|
mac_then_decrypt (foundNode->secret, 32, &(frame.payload[index]), frame.payloadLen - index, anonReq.payload);
|
|
anonReq.payloadLen = frame.payloadLen - index - 2;
|
|
uint8_t index2 = 0;
|
|
foundNode->last_seen_rt = anonReq.payload[index2++];
|
|
foundNode->last_seen_rt |= anonReq.payload[index2++] << 8;
|
|
foundNode->last_seen_rt |= anonReq.payload[index2++] << 16;
|
|
foundNode->last_seen_rt |= anonReq.payload[index2++] << 24;
|
|
|
|
if (persistent.nodeType == NODE_TYPE_ROOM_SERVER) {
|
|
foundNode->sync_timestamp = anonReq.payload[index2++];
|
|
foundNode->sync_timestamp |= anonReq.payload[index2++] << 8;
|
|
foundNode->sync_timestamp |= anonReq.payload[index2++] << 16;
|
|
foundNode->sync_timestamp |= anonReq.payload[index2++] << 24;
|
|
}
|
|
|
|
uint8_t passwordLen = anonReq.payloadLen - index2;
|
|
if (passwordLen > 16) {
|
|
passwordLen = 16;
|
|
}
|
|
uint8_t passwordBuf[16];
|
|
memcpy (passwordBuf, &(anonReq.payload[index2]), passwordLen);
|
|
if (memcmp (passwordBuf, persistent.password, sizeof (persistent.password)) == 0) {
|
|
foundNode->authenticated = 1;
|
|
Response resp;
|
|
resp.tag = RTC_GetCounter();
|
|
uint8_t index3 = 0;
|
|
uint32_t randOut = rand();
|
|
resp.data[index3++] = RESP_SERVER_LOGIN_OK;
|
|
resp.data[index3++] = 0;//legacy
|
|
resp.data[index3++] = 1;//isadmin
|
|
resp.data[index3++] = PERM_ACL_ADMIN;//permissions
|
|
resp.data[index3++] = randOut & 0xFF;//rng
|
|
resp.data[index3++] = (randOut >> 8) & 0xFF;
|
|
resp.data[index3++] = (randOut >> 16) & 0xFF;
|
|
resp.data[index3++] = (randOut >> 24) & 0xFF;
|
|
resp.data[index3++] = FIRMWARE_VER_LEVEL;
|
|
resp.dataLen = index3;
|
|
sendEncryptedResponse(foundNode, &resp);
|
|
}
|
|
|
|
return anonReq;
|
|
} |