Engine/Echo Protocol
Introduction and rationale
Echo is a protocol in the Distribution family.
Echo does not deliver any security property: it is only used to initiate TOFU. The Echo protocol in fact partly destroys privacy — which is why it can be switched off, session-wise. It is enabled by default.
Echo allows the first message with content in an exchange to be protected, when it otherwise would not be.
Protocol
There are only two messages:
- Ping;
- Pong.
A communication partner Alice can send a Ping message to a communication partner Bob, usually attaching her sender key. Bob, if he so desires, can reply with a Pong message to Alice, also usually attaching his sender key. Upon reception of Bob’s Pong message Alice is notified.
The Pong message from Bob to Alice can already be encrypted, and so will be any further communication between the two.
There is no requirement for the transport to be reliable or to deliver messages in order. The recipient of a Ping message may chose not to respond with a Pong.
Protocol state and message fields
Echo is a stateless protocol except for the data involved in a challenge/response exchange, and in rate-limitation. The challenge/response machinery only serves to recognise forged Pong messages.
The echo_challange
field is a new column of the Identity
table in the management database, set to a non-NULL
value (a copy of the random UUID which was sent) only for the identities to which we have sent a Ping message.
The only message fields are the challenge in Ping (a copy of which is stored as echo_challenge
) and a response in Pong (UUID equal to the challenge in the Ping message to which the Pong message is a reply).
Another new column named last_echo_timestamp
exists in the Identity
table for the purpose of rate-limiting Echo messages sent by us (with any session, on one device) to the same recipient Identity.
We rate-limit both Ping and Pong messages:
- we rate-limit Ping messages in order not to send a flood of messages when we are waiting for a response;
- we rate-limit Pong messages in order to avoid DoS attacks in which the message rate is amplified, which can happen in mailing lists.
The macro PEP_MINIMUM_ECHO_MESSAGES_PERIOD_IN_SECONDS
defined in src/echo_api.h
defines the minimum time elapsed between Echo messages sent to the same identity from one device.
Engine API
The public API for the Echo protocol is simple.
config_enable_echo_protocol
void config_enable_echo_protocol(PEP_SESSION session,
bool enable);
In the given session, enable or disable the Distribution.Echo protocol: enable iff enable
is true
. The protocol is enabled by default.
config_enable_echo_in_outgoing_message_rating_preview
void config_enable_echo_in_outgoing_message_rating_preview(PEP_SESSION session,
bool enable);
In the given session alter the behaviour of outgoing_message_rating_preview
: Ping messages will be sent from it iff enable
is true
(and if the Echo protocol is enabled). Ping messages from outgoing_message_rating_preview
are enabled by default.
Disabling Echo on message rating preview while the Echo protocol is otherwise enabled is intended as a performance optimisation: outgoing_message_rating_preview
should execute quickly.
Whenever the Echo protocol is enabled outgoing_message_rating
also sends Ping messages to unknown recipients known to be p≡p-using identities (it is possible to recognise some p≡p identities as such thanks to media keys). outgoing_message_rating
is allowed to execute more slowly (which is the entire reason for outgoing_message_rating_preview
’s existence) and therefore no way of disabling Ping messages from outgoing_message_rating
is needed.
The SYNC_NOTIFY_OUTGOING_RATING_CHANGE
notification
The enum
type hidden in the definition of sync_handshake_signal
has been enriched by a new case, SYNC_NOTIFY_OUTGOING_RATING_CHANGE
.
When decrypt_message
receives a valid (meaning with the expected response) Pong message it sends a SYNC_NOTIFY_OUTGOING_RATING_CHANGE
notification. This is intended for an interactive application displaying a colour for an outgoing message being composed: upon reception of a Pong message the rating, and therefore colour, of the message being composed might change. The application should recompute the rating and display a new colour: thanks to this feature the colour of a message might “spontaneously” change from no-colour to yellow while it is being composed, thanks to a quick Ping
/Pong
exchange with a new recipient, invisible to the application user.
The fact that notifications unrelated to the Sync protocol are handled under the “SYNC_
” or “sync_
” namespace is a historical artefact: while notifications were born with the Sync protocol they are no longer limited to it.
SYNC_NOTIFY_OUTGOING_RATING_CHANGE
caveats
Adapter and application developers should be informed about some caveats about SYNC_NOTIFY_OUTGOING_RATING_CHANGE
.
Notifications, Engine sessions and threads
The Engine sends this notification by calling s->notifyHandshake
, a C function pointer contained in the PEP_SESSION
s which was involved in decrypting the Pong message. If the adapter uses one Engine session per thread this means that notifyHandshake
will only be called in one thread, and that thread will be the same which decrypted the Pong message — not necessarily the same thread handling the graphical user interface. It is the adapter’s or application’s responsibility to ensure that notifyHandshake
is actually set in the correct thread; the Engine has no control over the multiple sessions that may exist across threads in the same memory space.
Adapters can register callbacks for notifications though the Engine function register_sync_callbacks
.
Unknown notifications
Not every current application supports SYNC_NOTIFY_OUTGOING_RATING_CHANGE
at this time; however this is not a serious problem.
Since applications have always been supposed to ignore unknown notifications the introduction of SYNC_NOTIFY_OUTGOING_RATING_CHANGE
does not constitute an incompatible API change.
If notifyHandshake
is not set in the appropriate session the Engine will simply not send the notification, while still correctly handling key distribution from the Pong message.
So when an application ignores a SYNC_NOTIFY_OUTGOING_RATING_CHANGE
event from the Engine the effect will be the application displaying the outgoing message with a worse colour than it should: in particular an outgoing message being composed might be presented as no-colour instead of yellow.
Unnecessary API functions
There is no API call for directly sending Ping messages; such messages are sent automatically where needed. There is no API call for sending Pong messages either: a Pong message is automatically sent as a reply to Ping when the Distribution.Echo protocol is enabled.
There is no API for handling a Ping message: Ping messages are automatically handled by decrypt_message
.
An application may handle Pong messages (after decrypting and, crucially, importing keys) through the SYNC_NOTIFY_OUTGOING_RATING_CHANGE
notification.
Protocol use cases
- When a reliable message is received and some recipients are unknown to us, we automatically send a Ping message to each unknown recipient. This will help retrieving their keys, which will be useful in the event of a message from us to them;
- Even when we receive an unprotected message we may know, thanks to media keys, that some recipients unknown to us are in fact p≡p-using identities. In that case we send a Ping message to each unknown identity known to use p≡p, which again will be useful in case of future exchanges with them;
- A Ping message is sent to each recipient of a message being composed who is known to be a p≡p-using identity (thanks to media keys) but is still unknown. If maximum performance is desired one can disable Ping messages from
outgoing_message_rating_preview
(but not fromoutgoing_message_rating
) throughconfig_enable_echo_in_outgoing_message_rating_preview
, described above. - also see Docu on Echo and Session
More use cases may be added in the future now that the infrastructure is ready and solid. The internal function send_ping
is easy to use.