finish protobuf definitions

This commit is contained in:
c0repwn3r 2023-03-16 18:28:46 -04:00
parent 5ee02573e1
commit 84a0c435db
Signed by: core
GPG Key ID: FDBF740DADDCEECF
7 changed files with 266 additions and 56 deletions

20
.idea/protoeditor.xml Normal file
View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProtobufLanguageSettings">
<option name="autoConfigEnabled" value="false" />
<option name="importPathEntries">
<list>
<ImportPathEntry>
<option name="location" value="file://$PROJECT_DIR$/src" />
</ImportPathEntry>
<ImportPathEntry>
<option name="location" value="file://$USER_HOME$/.cache/JetBrains/CLion2022.3/protoeditor" />
</ImportPathEntry>
<ImportPathEntry>
<option name="location" value="file://$PROJECT_DIR$/palmdef" />
</ImportPathEntry>
</list>
</option>
<option name="descriptorPath" value="google/protobuf/descriptor.proto" />
</component>
</project>

View File

@ -0,0 +1,70 @@
syntax = "proto3";
/*
This file contains message definitions for packets sent via encrypted reflection.
These packets have the directions EC2R and ER2C (encrypted client to relay, encrypted relay to client)
These packets are assigned the ID block 0x30-0x4f.
*/
// Consult palm.proto for how the channel_id is calculated.
// Sent by the client to set the channel being requested for this session.
// If the channel has already been set, this value of this packet will be ignored, and this packet will only function
// as a "request status update" packet.
// Consult the channel_id of the PalmER2CChannelStatusPacket to see what channel was actually sent by the server.
// The client should send this packet every 15 seconds, to function as a keepalive. After 20 seconds, the server will timeout the client.
message PalmEC2RRelayRequestPacket {
enum packet_info { unknown = 0; type = 0x30; }
bytes channel_id = 1; // The hash of the PMK. Used to identify the channel to the relay, without it knowing the channel name, or the key used for cryptographic operations.
int32 session_id = 2; // The same session_id used in previous packets, used to identify this session.
}
// Sent by the server to update the client on the status of the channel they are set to.
// This is sent in two cases:
// 1. immediately in reply to a PalmEC2RRelayRequestPacket
// 2. when the state changes
message PalmER2CChannelStatusPacket {
enum packet_info { unknown = 0; type = 0x31; }
enum channel_state_t {
UNKNOWN_CHANNEL_STATE = 0;
CHANNEL_NOT_READY = 1;
CHANNEL_IN_USE = 2;
}
bytes channel_id = 1; // The ID of the channel that was requested. Consult palm.proto for how this value is calculated.
int32 session_id = 2; // The same session_id used in previous packets, used to identify this session.
channel_state_t state = 3; // The state of the channel.
}
// Sent by the server to inform the client that it may now send data via the relay.
message PalmER2CChannelReadyPacket {
enum packet_info { unknown = 0; type = 0x32; }
bytes channel_id = 1; // The ID of the channel that is now ready.
int32 session_id = 2; // The same session_id used in previous packets, used to identify this session.
bool is_initiator = 3; // Is this client the initiator? This should be set to true on one of the clients, and false on the other.
}
// Sent by the client to request that a packet be relayed to the other party
message PalmEC2RRelayDataPacket {
enum packet_info { unknown = 0; type = 0x33; }
bytes channel_id = 1; // The ID of the channel to relay data to.
int32 session_id = 2; // The same session_id used in previous packets, used to identify this session.
bytes data = 3; // The protobuf-encoded data to send to the other client
}
// Sent by the server to tell the client to give it the data sent by the other client
message PalmER2CRelayedDataPacket {
enum packet_info { unknown = 0; type = 0x34; }
bytes channel_id = 1; // The ID of the channel to relay data to.
int32 session_id = 2; // The same session_id used in previous packets, used to identify this session.
bytes data = 3; // The protobuf-encoded data sent by the other client
}

View File

@ -0,0 +1,23 @@
syntax = "proto3";
/*
This file contains message definitions for packets sent via encrypted tunneling.
These packets have the directions EI2R and ER2I (encrypted initiator to receiver, encrypted receiver to initiator).
These packets are assigned the ID block 0x70-0x8f.
*/
// Sent by the initiator to send arbitrary encrypted data to the receiver
message PalmEI2RRelayDataPacket {
enum packet_info { unknown = 0; type = 0x70; }
bytes data = 3; // The arbitrary data sent to the other party
}
// Sent by the receiver to send arbitrary encrypted data to the initiator
message PalmER2IRelayDataPacket {
enum packet_info { unknown = 0; type = 0x71; }
bytes data = 3; // The arbitrary data sent to the other party
}

94
palmdef/palm.proto Normal file
View File

@ -0,0 +1,94 @@
syntax = "proto3";
/*
Palm Protocol Framework
Palm is a dead-simple relaying protocol used to get data from A to B privately, securely and anonymously.
These set of files provide a protobuf3 schema for parsing palm packets over-the-wire.
Please note that after PalmR2CHandshakeFinishPacket, the entire datastream is encrypted with a stream cipher.
It will need to be decrypted before it can be deserialized.
There are four types of messages that can be sent:
1. (C2R, R2C) Reflected, unencrypted. This type of message is unencrypted, and is communication between the client and the relay. This is called "reflection".\
2. (EC2R, ER2C) Reflected, encrypted. This type of message is the same as unencrypted reflection, but is stream encrypted.
3. (I2R, R2I) Tunneled, unencrypted. This type of message is unencrypted, and is passed through the relay. Although this packet is "unencrypted", it is still encrypted both ways via the relay connection - just the actual packet data is not encrypted and is readable by the relay.
4. (EI2R, ER2I) Tunneled, encrypted. Similarly to unencrypted tunnel, this is passed through the relay. However, the actual packet data is also encrypted.
Packets do NOT have sequential packet IDs. They are assigned in blocks.
- 0x00-0x0f Internal packets. Reserved.
- 0x10-0x2f Unencrypted reflection.
- 0x30-0x4f Encrypted reflection.
- 0x50-0x6f Unencrypted tunnel.
- 0x70-0x8f Encrypted tunnel.
- 0x90-0xdf Implementation-specific packets
- 0xe0-0xff Internal packets. Reserved.
Palm relays have static keys and must be trusted by clients.
Relays are entered into clients via a palm url:
palm[+<transport>]://[ip/domain]:[port]/[public key, hex-encoded]
<transport> is the pluggable transport used to encapsulate the Palm protocol. Please note that it is outside the scope of Palm to verify that the transport of the client and server will match.
If no transport is provided, `tcp` will be used, which will use a raw tcp connection. All clients and servers must support at least the `tcp` transport.
For example, a relay using the "websocket" transport (required by all servers), on 1.2.3.4 port 5678, with the public key 957e7ccbebe84854d1cbcc59a4a2d993b9877e186745190722c78d72d6a9a218,
would be entered into a client as follows:
palm+websocket://1.2.3.4:5678/957e7ccbebe84854d1cbcc59a4a2d993b9877e186745190722c78d72d6a9a218
The connection with a server is a relatively simple state machine.
Client state machine:
- Handshaking (after sending the handshake start)
- WaitingHandshakeResponse (before receiving the handshake finish)
- RelayConnected (after receiving the handshake finish)
- WaitingForPeer (after sending channel wait)
- Relayed (have an active relayed connection to the peer)
- Disconnected (after being disconnected from the server)
Relay state machine:
- Handshaking (after receiving the handshake start)
- WaitingRelayRequest (after sending the handshake finish)
- WaitingForPeer (after sending channel not ready)
- Relaying (after sending channel ready to client)
- Disconnected (after the client has disconnected)
Initiator (one of the peers, chosen randomly by the server) state machine:
- Handshaking (after sending handshake start)
- WaitingPeerRespponse (before receiving the handshake finish)
- Tunneled (after receiving the handshake finish)
- Disconnected (after the connection has been closed)
Receiver (the other peer, chosen randomly by the server) state machine:
- Handshaking (before receiving handshake start)
- Tunneled (after sending handshake finish)
- Disconnected (after the connection has been closed)
Cryptography
Palm uses a simple set of cryptographic functions.
- BLAKE2s (32-byte digest) is used for hashing.
- ChaCha20Poly1305 is used for authenticated encryption of data.
Channel Identifiers and Keys
The channel ID (channel_id, cid) and pre-shared master key (pmk) are very important values, used in almost all of the cryptography
inside Palm. Given a user-friendly channel name channel_name, the two keys can be generated as follows:
pmk = BLAKE2s(channel_name)
channel_id = BLAKE2s(pmk)
*/
import "unencrypted_reflection.proto";
import "encrypted_reflection.proto";
import "unencrypted_tunnel.proto";
import "encrypted_tunnel.proto";
// The core message, used to serialize all other packets.
message PalmPacket {
int32 packet_id = 1; // What is the Packet ID of this packet?
bytes packet_data = 2; // Protobuf-encoded bytearray containing actual packet data. Might be encrypted.
}

View File

@ -1,56 +0,0 @@
syntax = "proto3";
/*
There are four types of messages that palm can send.
1. Unencrypted reflection. This is unencrypted communication between a relay and a client.
2. Encrypted reflection. This is encrypted communication between a relay and a client.
3. Unencrypted tunnel. This is unencrypted communication between a client and a client, through a relay. Note that it is encrypted both ways via encrypted reflection.
4. Encrypted tunnel. This is doubly-encrypted communcation between a client and a client, through a relay.
The following convention is used:
C2R Client to Relay - Reflection
R2C Relay to Client - Reflection
I2R Initiating Client to Receiving Client - Tunneled
R2I Receiving Client to Initiating Client - Tunneled
*/
/////// UNENCRYPTED REFLECTION ///////
// Sent by client at start of connection
message PalmC2RHandshakeStart {
bytes ClientPublicKey = 1; // 32-byte X25519 public key
bytes SessionIV = 2; // 12-byte randomized IV generated by the client
bytes Check = 3; // 32-byte randomized value used to check encryption
}
// Sent by relay in response to PalmC2RHandshakeStart
message PalmR2CHandshakeFinish {
bytes ServerPublicKey = 1; // 32-byte X25519 public key
bytes Check = 2; // The same 32-byte value provided in PalmC2SHandshakeStart, used to tie this response to the original session
}
/////// ENCRYPTED REFLECTED MESSAGES ///////
// Sent by client after receiving PalmR2CHandshakeFinish.
// Used by the client to request a room on the server.
message PalmC2RRelayRequest {
bytes Check = 1; // The same 32-byte value used in initial reflected handshake, ties this to the session.
string ChannelID = 2; // The string channel ID this client is requested to be routed to.
}
// Represents the states a room/channel can be in.
enum PalmRoomStatus {
NotReady = 0; // Waiting for a peer to join
Ready = 1; // A peer has joined, and the relay is ready to relay the connection
InUse = 2; // This channel is already in use and cannot be used currently
}
// Send at *any time* by the server to indicate the current status of the server.
// Must also be sent in response to PalmC2RRelayRequest to indicate the current status of the room.
// If the other peer is disconnected, PalmR2CChannelStatus will be sent again with Status = NotReady;
// The client must handle this correctly.
message PalmR2CChannelStatus {
bytes Check = 1; // The same 32-byte value used in previous packets, ties this packet to the session.
string ChannelID = 2; // The channel that the client requested.
PalmRoomStatus Status = 3; // The current status of the room.
}

View File

@ -0,0 +1,34 @@
syntax = "proto3";
/*
This file contains message definitions for packets sent via unencrypted reflection.
These packets have the directions C2R and R2C (client to relay, relay to client)
These packets are assigned the ID block 0x10-0x2f.
*/
// Sent by the client to the relay to initialize the connection. Sends the relay the client's public key and a randomized session ID
// used by the server to perform X25519 to enable encryption.
message PalmC2RHandshakeStart {
enum packet_info { invalid = 0; type = 0x10; }
bytes client_public_key = 1; // The client's X25519 public key. This should be generated afresh for this session.
int32 session_id = 2; // A random 4-byte integer, used to uniquely identify this session.
bytes iv = 3; // A random 12-byte IV used for encryption
}
// Sent by the server to the client to finish initializing the connection. Sends the client the relay's public key,
// so the client and the server can both enable encryption.
message PalmR2CHandshakeFinish {
enum packet_info { invalid = 0; type = 0x11; }
// The relay's public key. As opposed to the client public key, relay keys are static -
// it is very, very important to check the relay's identity to make sure you aren't being MITMd.
// Clients should authenticate this against a previously known value.
// See the main palm.proto file for how this will be given to a client.
bytes relay_public_key = 1;
int32 session_id = 2; // The same 4-byte integer sent by the client in PalmC2RHandshakeStart.
bytes iv = 3; // A random 12-byte IV used for encryption
}
// After these two packets, stream encryption is enabled on the client and server

View File

@ -0,0 +1,25 @@
syntax = "proto3";
/*
This file contains message definitions for packets sent via unencrypted tunneling.
These packets have the directions I2R and R2I (initiator to receiver, receiver to initiator)
These packets are assigned the ID block 0x50-0x6f.
*/
// Sent by the initiator to the receiver, over the encrypted tunnel, to start the handshake.
message PalmI2RHandshakeStartPacket {
enum packet_info { invalid = 0; type = 0x50; }
bytes initiator_public_key = 1; // The initiator's X25519 public key. This should be generated afresh for this session.
int32 check = 2; // A random 4-byte integer, used to verify encryption is working properly.
bytes iv = 3; // A random 12-byte IV used for encryption
}
// Sent by the initiator to the receiver, over the encrypted tunnel, to start the handshake.
message PalmR2IHandshakeFinishPacket {
enum packet_info { invalid = 0; type = 0x51; }
bytes receiver_public_key = 1; // The initiator's X25519 public key. This should be generated afresh for this session.
int32 check_encrypted = 2; // The same check value from the handshake start, encrypted in the same way the packets will eventually be encrypted.
}