4 releases

0.7.3 Aug 23, 2024
0.7.2 Aug 16, 2024
0.7.1 Mar 18, 2024
0.7.0 Mar 18, 2024

#1037 in Cryptography

45 downloads per month

LGPL-3.0-only

1MB
9K SLoC

otrr

OTR in rust.

status work-in-progress, OTRv4 functional, tested against otr4j, further fine-tuning likely when gaining adoption.

An (minimal) "example" client is available at echonetwork, which is used for interoperability testing with otr4j.

Goals

  • OTRv4 + OTR 3 (OTRv2 and earlier are not supported)
  • Structured for security:
    • security-sensitive primitives in separate module (crypto)
    • strictly separated states resulting in strictly separated secrets
  • not multi-threaded

Changelog

Changelog

0.7.3

  • Fragment-assembly: update tick value on every fragment. Highest tick value represents the (incomplete) message most recently updated with an incoming fragment.
  • Fragment-assembly: practical, liberal maximum fragment size of 250 KiB to prevent abuse. Fragments are refused when exceeding this limit.
  • Fragment-assembly: practical, liberal maximum message size of 100 MiB to prevent abuse. All fragments of a message are evicted when their combined size exceeds this limit.

0.7.2

  • Fragment-assembly: set maximum limit of 100 (incomplete) messages. After reaching this limit, the oldest message will be removed from the assembler.
  • Marked message-queuing as "won't fix"; explanation added to "Known issues" section.
  • Added changelog section in README.md.

0.7.1

  • Moved working notes to lib.rs comments.

0.7.0

Initial release.

Design

TODO write design considerations here

TODO document implementation considerations, such as periodically calling `expire` to facilitate session expiration. (Or find a good way to have it timed, thread-safe without causing interference.)

Under consideration

  • Persistence for known public keys, previously verified identities (SMP), etc.
Checklist

☐: feature, ☑: implemented, ✔: verified

Functionality:

  • ☑ Normal messages:
    • ☑ Plaintext message
    • ☑ Whitespace-tagged message
    • ☑ Query message
    • ☑ Error message
  • ☑ Authenticated Key Exchange (AKE)
  • ☑ Socialist Millionaire's Protocol (SMP)
    • ☑ SMP zero-knowledge secret verificaton (w/ or w/o user-provided question)
    • ☑ Manual verification (SSID)
  • ☑ DSA signatures
  • ☑ Encryption
  • ☑ OTR-encoding
    • ☑ Reading
    • ☑ Writing
  • ☐ Policies:
    • REQUIRE_ENCRYPTION take appropriate actions given that active policy requires encryption.
    • WHITESPACE_START_AKE automatically initiate AKE when whitespace tag is received.
    • ERROR_START_AKE initiate AKE upon receiving error message.
    • ☐ ability to change policy for account or individual instance (during use).
  • ☑ Fragmentation:
    • ☑ Assemble fragments of incoming message.
    • ☑ Fragment outgoing messages.
    • ☑ Limit number of incomplete distinct messages for OTRv4.
  • ☐ Heartbeat-messages: keep session alive and ensure regular key rotation.
  • ✕ Store plaintext message for transmission under right circumstances (i.e. REQUIRE_ENCRYPTION policy, in-progress AKE, etc.)
    This is removed from otr4j and will not be implemented here. See "known issues" below for details.
  • ☐ Expose the Extra Symmetric Key (TLV type 8 in OTR3, TLV type 7 in OTRv4)
  • ☑ Session expiration
    Session expiration is provided only as a method-call. This is currently an action that the host (chat-application) must perform.
  • OTR 3:
    • ☑ Instance-tags (distinguish multiple clients for the same account)
    • ☑ Fragmentation with instance-tags.
  • OTRv4:
    • ☑ Upgraded cryptographic primitives, DAKE, Double-Ratchet, mixed ephemeral keys
    • ☑ Client-profiles
    • ☑ Fragmentation with identifier
    • ☑ FIXME continue itemizing and include incomplete parts ...
    • ☐ Out-of-order message-keys:
      • ☑ messages in order,
      • ☑ skipping messages,
      • ☐ message-keys from skipped keys store, i.e. out-of-order reception

Operational:

  • Fragments and reassembly (exact limits open for discussion):
    • ☑ Maximum number of incomplete messages: 100
    • ☑ Maximum fragment size: 250 kiB
    • ☑ Maximum message size: 100 MiB
    • ☐ Maximum over-all memory usage for fragments store
    • ☑ Logging reports on dropped fragments/messages that exceed limits.
  • ☑ The interactive DAKE is an independent state-machine. This ensures that the protocol only transitions away after DAKE has completed successfully. It is not possible to trigger DAKE starts causing OTRv4 to transition away from encrypted-messaging state.
  • ☑ Single instance of Account represents single account on a chat network: allows for specific identity (DSA keypair), chat network/transport.
  • ☐ Per-account thread-safe implementation. (Not yet determined necessary.)
    Given that most messages can be processed one at a time, most benefit is derived from having separate tasks for session expiration and heartbeats. However, these may be interleaved with message processing.

Developmental:

  • ☑ No logic for managing multiple accounts:
    We keep this separated and up to the client to implement as necessary. Essentially, just tying the Account to the corresponding chat account logic is sufficient, and additional management risks prescribing a certain structure to the host application (e.g. chat application).
  • ☐ API for managing multiple accounts, keys, policies?
  • ☐ Unit tests: too few tests, even though rust syntax is that expressive.
  • ☐ Resilient to faulty implementations of Host as provided by the client.
    At this moment it is not clear how to do this: std::panic::catch_unwind is not guaranteed to catch and handle all panics.

Known issues

  • (Will not be implemented) Message-queue for delayed sending: the idea is to queue messages under certain policies or when sending messages while the (D)AKE is in progress. However, as of OTR version 3, instance-tags were added to support distinguishing and identifying multiple clients operating under the same account when OTR sessions are active. Upon establishing an OTR session, sessions may be established simultaneously for each of the active clients - each having their own instance-tag. Stored messages would be sent to the (first) established session, which may not be the client you intended the messages to go to. In addition, the client that supports only lower protocol versions, will likely establish a session fastest.
  • How to deal with multiple instances, "default instance", "selected/active instance"? Especially when dealing with incidental reception of plaintext messages while encrypted session is established for some instance.
  • The OTR specification documents that any message payload is in UTF-8 and may contain HTML. However, this makes it ambiguous for how the content should be interpreted and results and risks may very per chat network.
  • There is no convention on how the Extra Symmetric Key should be used.

Dependencies

~17MB
~379K SLoC