Skip to content

Registration Tagging and Signaling

Jack Wampler edited this page May 11, 2020 · 1 revision

Motivation

In Dark Decoys we don't need to decrypt the original flow, and station engineers agree that if we have a chance not to import OpenSSL, then we should not import OpenSSL. However, we used to have variable-length protobuf in a header of first HTTP request, which we don't want to decrypt anymore.

We do however need multiple cryptographic keys now. And we do want a variable-length sized protobuf in there for extensibility.

New tag format

High-level decryption algorithm:

  1. extract shared_secret from Representative and generate encryption keys
  2. decrypt Fixed-Size Payload, which will contain size of Variable-Size Payload
  3. decrypt Variable-Size Payload
[     VSP    ][VSP GMAC][Representative][ FSP  ][ FSP GMAC ][ Suffix ]
 \ variable* /  \ 16* /   \ 32 bytes* /  \ 6* /  \   16*  /  \  4   /

* before base64-style encoding. Actual size on the wire will increase by 33%.

Representative

Same old stuff. Grab eligator-transformed representative of client's public key, combine it with station's private key, get 32 byte-long shared_secret.

Located at 92 bytes offset from the end. Calculations(from the end):

  • [16 bytes] GMAC for the whole TLS record
  • [4 bytes] suffix
  • [16 bytes] GMAC from FSP encryption
  • [6 bytes] FSP
  • [32 bytes] representative

(32 + 6 + 16) / 3 * 4 + 4 + 16 = 92

Key derivation

Use HKDF to expand and extract with following parameters

  • PRK = SHA256
  • SECRET = shared_secret, derived from representative
  • SALT = []byte{"tapdancetapdancetapdancetapdance"}
  • INFO = nil

This gives us a Key Derivation Function, that is able to generate a stream, which we then use to derive multiple secure keys of any length:

  1. FSP_key = first 16 bytes from HKDF
  2. FSP_iv = next 12 bytes
  3. VSP_key = next 16 bytes
  4. VSP_iv = next 12 bytes
  5. new_master_secret = next 48 bytes
  6. DarkDecoy_seed = next 16 bytes

FSP - fixed-size payload

Encrypted with AES-128-GCM, using FSP_key and FSP_iv.

  • size of encrypted VSP [2 bytes, BigEndian uint16] - MUST be divisible by 3
  • flags [1 byte]
  • Unassigned [3 bytes]

VSP - variable-size payload

Contains ClientToStation protobuf.

Suffix

4 bytes long.
Allows us to append \r\n\r\n at the end of the request to complete it. For incomplete requests, may be filled with anything in ASCII range.