The DoIt remote-activation protocol
-----------------------------------

DoIt is a simple protocol for allowing remote systems you have
logged into from a PC to connect back to that PC, run applications,
and access the Windows clipboard.

DoIt assumes you have _already_ solved the key-distribution problem;
it relies on a binary shared secret between the two sides. This can
be of any size (encryption and MAC keys are derived from the secret
by cryptographic hashing, so the size of the secret doesn't matter).

At the beginning of the connection, each side sends a nonce to the
other, in SSH2 string form (a 32-bit big-endian integer giving the
length of the nonce, followed by the binary nonce data). Nonces need
not be truly random or unpredictable, just (probabilistically)
unique to prevent replay attacks. An adequate way to compute a nonce
would be to hash the current time.

The normal protocol greeting is as follows:

  uint32                       protocol-version
  uint32                       nonce-length
  data[nonce-length]           nonce
  uint32                       secret-id-length
  data[secret-id-length]       secret-id

The protocol-version described in this document is 0x10004.

The secret-id is a SHA-256 hash of the following data:

  char                         "I"
  uint32                       nonce-length
  data[nonce-length]           nonce
  uint32                       secret-preid-length
  data[secret-preid-length]    secret-preid

and the secret-preid in turn is a SHA-256 hash of the following data:

  char                         "i"
  uint32                       nonce-length
  data[nonce-length]           nonce
  uint32                       shared-secret-length
  data[shared-secret-length]   shared-secret

There is an alternative server-side protocol greeting available, for
the situation where service is currently unavailable:

  uint32                       protocol-version
  uint32                       message-length
  data[message-length]         message
  uint32                       error-indicator = 0xFFFFFFFF

All further communication takes place in binary packets with the
following format:

  data[ciphertext-length]      ciphertext
  data[32]                     MAC

in which the MAC is used to verify the encrypted packet-data (details
below), and then the packet-data is decrypted after its MAC is
validated. The 'ciphertext-length' for each packet is known in advance
(see below), and is never transmitted explicitly.

These ciphertext+MAC packets decrypt to a sequence of 'chunks', each
with the following format:

  uint32                       data-length
  byte                         padding-length
  data[data-length]            data
  data[padding-length]         padding

in which 'padding' is random, at least one byte long, and brings the
total length of the block to a multiple of the cipher block size.

A chunk is composed of either one or two binary packets. The first
packet of a chunk always has ciphertext-length equal to the block size
of the cipher. After verifying the MAC on that packet and decrypting
it, the receiver obtains enough data to find out the total length of
ciphertext in the packet _pair_ (namely 5 + data-length +
padding-length). If this is equal to one cipher block, then the entire
chunk is already complete, and was contained in the packet that has
already been transmitted; if not, then a second packet is transmitted
immediately afterwards, whose ciphertext-length is equal to the
chunk's total length minus the one cipher block that was transmitted
in the first packet.

For example:

  16-byte chunk   ->   initial packet with ciphertext-length 16
                       no followup packet

  32-byte chunk   ->   initial packet with ciphertext-length 16
                       followup packet with ciphertext-length 16

  48-byte chunk   ->   initial packet with ciphertext-length 16
                       followup packet with ciphertext-length 32

The packets' ciphertext is encrypted using 128-bit AES in counter
mode, with the IV being treated as a big-endian 128-bit integer which
is encrypted through AES to generate 128 bits of keystream and then
incremented by 1 (with wraparound if necessary).

The encryption key used on each side to encrypt outgoing data is the
first 128 bits of a SHA-256 hash of the following:

  char                         "K"
  uint32                       shared-secret-length
  data[shared-secret-length]   shared-secret
  uint32                       our-nonce-length
  data[our-nonce-length]       our-nonce
  uint32                       their-nonce-length
  data[their-nonce-length]     their-nonce

The encryption key used on each side to decrypt _incoming_ data is
therefore the same except that the two nonces are interchanged
(since this is the way round the peer will have generated its
outgoing encryption key).

The IV is derived similarly, but uses "I" instead of "K" at the
start.

The MAC in each packet is an HMAC-SHA-256 of the concatenation of the
ciphertext of _all_ packets in that direction, up to and including the
one being verified. The MAC key used by each side for outgoing data is
a full 256-bit SHA-256 hash of the following data:

  char                         "M"
  uint32                       shared-secret-length
  data[shared-secret-length]   shared-secret
  uint32                       our-nonce-length
  data[our-nonce-length]       our-nonce
  uint32                       their-nonce-length
  data[their-nonce-length]     their-nonce

The MAC key used on each side to verify _incoming_ data is therefore
the same except that the two nonces are interchanged (since this is
the way round the peer will have generated its outgoing MAC key).

The maximum packet data length is 1024 bytes (to aid verification of
decryption). This is also the maximum length of a nonce.
