diff --git a/docs/illustrated.css b/docs/illustrated.css index 1140328..36ec527 100644 --- a/docs/illustrated.css +++ b/docs/illustrated.css @@ -19,6 +19,13 @@ --act-hov-btn9: hsl(21, 88%, 51%); --act-btn-shadow: hsl(25, 91%, 40%); --act-btn-border: hsl(33, 90%, 45%); + + --pad-btn0: hsl(205, 96%, 54%); + --pad-btn9: hsl(195, 91%, 54%); + --pad-hov-btn0: hsl(200, 94%, 52%); + --pad-hov-btn9: hsl(190, 88%, 51%); + --pad-btn-shadow: hsl(195, 91%, 40%); + --pad-btn-border: hsl(203, 90%, 45%); } /* remove focus rings for non-keyboard users */ @@ -436,13 +443,13 @@ button.annotate-toggle { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 1em; padding: .4em 1.7em .45em; - text-shadow: 0 1px 1px var(--act-btn-shadow); border-radius: .5em; box-shadow: 1px 1px 1px rgba(0,0,0,0.3); color: #fff; - border: solid 1px var(--act-btn-border); background: linear-gradient(180deg, var(--act-btn0) 1%, var(--act-btn9) 100%); + text-shadow: 0 1px 1px var(--act-btn-shadow); + border: solid 1px var(--act-btn-border); } button.annotate-toggle:hover { text-decoration: none; @@ -458,6 +465,17 @@ button#openCloseAll { min-width: 8em; } +button#expandCollapsePadding { + padding: .4em 1.3em .45em; + background: linear-gradient(180deg, var(--pad-btn0) 1%, var(--pad-btn9) 100%); + text-shadow: 0 1px 1px var(--pad-btn-shadow); + border: solid 1px var(--pad-btn-border); +} +button#expandCollapsePadding:hover { + + background: linear-gradient(180deg, var(--pad-hov-btn0) 1%, var(--pad-hov-btn9) 100%); +} + /***** print mode *****/ .print-mode { cursor: pointer; diff --git a/docs/illustrated.js b/docs/illustrated.js index f0818f9..6461f60 100644 --- a/docs/illustrated.js +++ b/docs/illustrated.js @@ -175,6 +175,33 @@ }); }; + ill.expandCollapsePadding = (btn, event) => { + ill.cancel(event); + btn = btn || document.getElementById('expandCollapsePadding'); + if (!btn) return; + + // check if we are expanding or collapsing + let action = btn.dataset['lblState']; + + // toggle expanded / collapsed padding sections + [].forEach.call(document.querySelectorAll(".padding-long"), (el) => { + el.style.display = action === 'expand' ? '' : 'none'; + }); + [].forEach.call(document.querySelectorAll(".padding-short"), (el) => { + el.style.display = action === 'expand' ? 'none' : ''; + }); + + // Update button text + let newButtonState = action === 'expand' ? 'collapse' : 'expand'; + if (btn && btn.dataset['lblState'] !== newButtonState) { + // swap text w/ lbl-toggle, then swap state + let tmp = btn.textContent; + btn.textContent = btn.dataset['lblToggle']; + btn.dataset['lblToggle'] = tmp; + btn.dataset['lblState'] = newButtonState; + } + }; + /** * Open or close all elements on the page * @param {string} openOrClose - "open" or "close" diff --git a/docs/index.html b/docs/index.html index 1fe490a..2ecab97 100644 --- a/docs/index.html +++ b/docs/index.html @@ -37,7 +37,7 @@

The Illustrated Obfs4 Connection

Every byte explained and reproduced

- +

In this demonstration a client connects to a server, @@ -56,13 +56,22 @@

Every byte explained and reproduced

- +
+
- +
+ + +
+ +
+ +
- -
+
Client Key Exchange Generation
@@ -223,8 +231,7 @@

IAT Mode

- -
+
Client Handshake
@@ -232,417 +239,124 @@

IAT Mode The session begins with the client saying "Hello". The client provides information including the following:
    -
  • client random data (used later in the handshake) -
  • a list of cipher suites that the client supports -
  • a list of public keys that the server might find suitable for key exchange -
  • protocol versions that the client can support +
  • client ephemeral session public key representative +
  • padding of random length between 4096 and 8192 bytes. +
  • mark indicating that the client knows the servers Node ID +
  • MAC value ensuring that the contents of the packet have not been modified.
+ While this will not typically fit in a single TCP packet, for the sake of this demonstration + it will be presented as a single packet. Also, as the elligator2 representative + is a deterministic transformation of the public key, session ephemeral keys should + never be re-used, or the client handshake messages will begin with identical byte + sequences.

- Record Header - - 16 03 01 00 f8 - -
- TLS sessions are broken into the sending - and receiving of "records", which are blocks - of data with a type, a protocol version, - and a length. -
    -
  • 16 - type is 0x16 (handshake record) -
  • 03 01 - protocol version is "3,1" (also known as TLS 1.0) -
  • 00 f8 - 0xF8 (248) bytes of handshake message follows -
- Interestingly the version in this record - is "3,1" (TLS 1.0) instead of "3,4" (TLS 1.3). - This is done for interoperability with earlier - implementations. -
-
- - - Handshake Header + Elligator2 Encoded Public Representative - 01 00 00 f4 + f4 d0 5d f7 8e c6 f6 7a c1 04 31 99 63 ca c0 97 64 ba 89 0f 89 25 28 16 9d cb bf db 16 66 a7 bd
- Each handshake message starts with a type and a length. -
    -
  • 01 - handshake message type 0x01 (client hello) -
  • 00 00 f4 - 0xF4 (244) bytes of client hello data follows -
+ Each handshake message starts with the client's x255519 public key encoded using + the Elligator2 encoding scheme.
- Client Version - - 03 03 + Padding + + da 88 ..(4092B).. e4 c3 -
- A protocol version of "3,3" (meaning TLS 1.2) - is given. Because middleboxes have been - created and widely deployed that do not - allow protocol versions that - they do not recognize, the TLS 1.3 session - must be disguised as a TLS 1.2 session. - This field is no - longer used for version negotiation and - is hardcoded to the 1.2 version. Instead, - version negotiation is performed using the - "Supported Versions" extension below. -

- The unusual version number ("3,3" representing - TLS 1.2) is due to TLS 1.0 being a minor - revision of the SSL 3.0 protocol. Therefore - TLS 1.0 is represented by "3,1", TLS 1.1 is - "3,2", and so on. -
-
- - - Client Random - - 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e - 1f +
- The client provides 32 bytes of random data. This data will be used later in the session. - In this example we've made the random data a predictable string. -
-
- - - Session ID - - 20 e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd - fe - ff - -
- In previous versions of TLS the client could - provide an ID of a previously negotiated - session, which allows the server and client - to skip the time and cost of negotiating new keys. -

- In TLS 1.3 this "session resume" is done via the more flexible - PSK (pre-shared keys) mechanism, so this - field is no longer needed for that purpose. - Instead, a non-empty value in this field is - used to trigger "middlebox compatibility - mode" which helps TLS 1.3 sessions to be - disguised as resumed TLS 1.2 sessions. The - client has generated random data to populate - this field. + In obfs4 the client pads the handshake message with random bytes to a length between + 4096 and 8192 bytes. This padding is used to make the handshake message a non-uniform + length such that the size of the first packet would be a strong indication of the + specific protocol being used.
    -
  • 20 - 0x20 (32) bytes of session ID follow -
  • e0 e1 ... fe ff - fake session ID +
  • da 88 ... e4 c3 - bytes drawn form prng source.
- Cipher Suites + Steganographic Mark - 00 08 13 02 13 03 13 01 00 ff + 13 02 13 03 13 01 00 ff 13 02 13 03 13 01 00 ff
- The client provides an ordered list of which - cipher suites it will support for encryption. - The list is in the order preferred by the - client, with highest preference first. -

- In TLS 1.3 the list of possible cipher - suites has been greatly reduced. All the - remaining suites are AEAD algorithms which - provide stronger encryption guarantees than - many previous suites with an easier all-in-one - implementation. -
    -
  • 00 08 - 8 bytes of cipher suite data -
  • 13 02 - assigned value for TLS_AES_256_GCM_SHA384 -
  • 13 03 - assigned value for TLS_CHACHA20_POLY1305_SHA256 -
  • 13 01 - assigned value for TLS_AES_128_GCM_SHA256 -
  • 00 ff - assigned value for TLS_EMPTY_RENEGOTIATION_INFO_SCSV -
-
-
+ As the obfs4 handshake is (ideally) indistinguishable from uniform random bytes, + the client includes a steganographic mark in the handshake message to securely + indicate that it wishes to establish a connection. The mark is an HMAC that + uses the server's public key and node ID as hte key and + the client's ephemeral public key as the message. While the HMAC-SHA256 would + usually result in 32 bytes, only the first 16 bytes are used for the mark. - - Compression Methods - - 01 00 - -
- Previous versions of TLS supported - compression, which was found to leak - information about the encrypted data allowing - it to be read (see CRIME). -

- TLS 1.3 no longer allows compression, so - this field is always a single entry with - the "null" compression method which performs - no change to the data. -
    -
  • 01 - 1 bytes of compression methods -
  • 00 - assigned value for "null" compression -
-
-
+


HMAC-SHA256-128(ServerPubkey | NodeID, REPR) - - Extensions Length - - 00 a3 - -

- The client has provided a list of optional - extensions which the server can use to - take action or enable new features. -
    -
  • 00 a3 - the extensions will take 0xA3 (163) bytes of data -
- Each extension will start with two bytes - that indicate which extension it is, followed - by a two-byte content length field, followed - by the contents of the extension. -
-
+

where: +

    +
  • ServerPubkey - The obfs4 servers 32 byte public x25519 identity key +
  • NodeID - The obfs4 servers 20 byte identifier value +
  • REPR - The clients Elligator2 encoded public key representative +
+ - - Extension - Server Name - - 00 00 00 18 00 16 00 00 13 65 78 61 6d 70 6c 65 2e 75 6c 66 68 65 69 6d 2e 6e 65 74 - -
- The client has provided the name of the - server it is contacting, also known as SNI - (Server Name Indication). -

- Without this extension an HTTPS server would - not be able to provide service for multiple - hostnames (virtual hosts) on a single IP address - because it couldn't know which - hostname's certificate to send until - after the TLS session was negotiated and the - HTTP request was made. -
    -
  • 00 00 - assigned value for extension "server name" -
  • 00 18 - 0x18 (24) bytes of "server name" extension data follows -
  • 00 16 - 0x16 (22) bytes of first (and only) list entry follows -
  • 00 - list entry is type 0x00 "DNS hostname" -
  • 00 13 - 0x13 (19) bytes of hostname follows -
  • 65 78 61 ... 6e 65 74 - "example.ulfheim.net" -
-
-
+

Python sample code to produce the hmac value:

- - Extension - EC Point Formats - - 00 0b 00 04 03 00 01 02 - -
- The client has indicated that it supports receiving - elliptic curve data points in the following compression formats: -
    -
  • 00 0b - assigned value for extension "ec point formats" -
  • 00 04 - 4 bytes of format types follow -
  • 03 - 3 bytes of format types follow -
  • 00 - assigned value for format "uncompressed" -
  • 01 - assigned value for format "ansiX962_compressed_prime" -
  • 02 - assigned value for format "ansiX962_compressed_char2" -
+ +
import hmac
+import hashlib
+
+server_pubkey = b'\x9f\xd7\xad\x6d\xcf\xf4\x29\x8d\xd3\xf9\x6d\x5b\x1b\x2a\xf9\x10\xa0\x53\x5b\x14\x88\xd7\xf8\xfa\xbb\x34\x9a\x98\x28\x80\xb6\x15'
+node_id = b''
+hmac_key = server_pubkey + node_id
+msg = b''
+h = hmac.new( hmac_key, msg, hashlib.sha256 )
+digest = h.hexdigest()
+print( digest[:len(digest)/2] )
+
+
- Extension - Supported Groups + Message Authentication - 00 0a 00 16 00 14 00 1d 00 17 00 1e 00 19 00 18 01 00 01 01 01 02 01 03 01 04 + 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
- The client has indicated that it supports - elliptic curve (EC) cryptography for ten curve types. - To make this extension more generic for - other cryptography types it calls these - "supported groups" instead of "supported - curves". -

- This list is presented in descending order - of the client's preference. -
    -
  • 00 0a - assigned value for extension "supported groups" -
  • 00 16 - 0x16 (22) bytes of "supported group" extension data follows -
  • 00 14 - 0x14 (20) bytes of data are in the curves list -
  • 00 1d - assigned value for the curve "x25519" -
  • 00 17 - assigned value for the curve "secp256r1" -
  • 00 1e - assigned value for the curve "x448" -
  • 00 19 - assigned value for the curve "secp521r1" -
  • 00 18 - assigned value for the curve "secp384r1" -
  • 01 00 - assigned value for the curve "ffdhe2048" -
  • 01 01 - assigned value for the curve "ffdhe3072" -
  • 01 02 - assigned value for the curve "ffdhe4096" -
  • 01 03 - assigned value for the curve "ffdhe6144" -
  • 01 04 - assigned value for the curve "ffdhe8192" -
-
-
+ In order to ensure that the contents of the handshake message have not been + tampered with in transit, the client includes a second HMAC value using the same + key as the steganographic mark, but covering the contents of the entire handshake + message. - - Extension - Session Ticket - - 00 23 00 00 - -
- The client indicates it has no session ticket - to provide for this connection. -
    -
  • 00 23 - assigned value for extension "Session Ticket" -
  • 00 00 - 0 bytes of "Session Ticket" extension data follows -
-
-
+ Again the HMAC-SHA256 value is truncated to 16 bytes. - - Extension - Encrypt-Then-MAC - - 00 16 00 00 - -
- The client indicates it can support EtM, which prevents - certain vulnerabilities in - earlier versions of TLS. In - TLS 1.3 this mechanism is always used, so this extension - will have no effect in this session. +

If we consider the handshake so far to be [ REPR | PAD | MARK ] where:

    -
  • 00 16 - assigned value for extension "Encrypt Then MAC" -
  • 00 00 - 0 bytes of "Encrypt Then MAC" extension data follows +
  • REPR - The clients Elligator2 encoded public key representative +
  • PAD - Padding bytes +
  • MARK - Steganographic mark
-
-
- - Extension - Extended Master Secret - - 00 17 00 00 - -
- The client indicates support for extra cryptographic operations - which prevent vulnerabilities in earlier versions of TLS (see RFC 7627 for details). - In TLS 1.3 the vulnerabilities are no longer present, so this extension - will have no effect in this session. +

The message authentication is: +

HMAC-SHA256-128(serverIdentity | NodeID, REPR | PAD | MARK | E)

    -
  • 00 17 - assigned value for extension "Extended Master Secret" -
  • 00 00 - 0 bytes of "Extended Master Secret" extension data follows +
  • E - string representation of the number of hours since the UNIX epoch
+

The inclusion of the time stamp in the HMAC makes it so that the server only ever + accepts a given handshake message sent within a controlled number of hours. The server + can then keep a record of the client public keys and handshakes that it has seen + within that time window to prevent replay attacks. +

To produce this hmac value in python the code block in the above Steganographic Mark + block can be used with the msg variable set to the entire handshake message + with the appended epoch string value.

- - Extension - Signature Algorithms - - 00 0d 00 1e 00 1c 04 03 05 03 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 05 08 06 04 01 05 - 01 - 06 01 - -
- This extension indicates which signature - algorithms the client supports. This can - influence the certificate that the server - presents to the client, as well as the - signature that is sent by the server in - the CertificateVerify record. -

- This list is presented in descending order - of the client's preference. -
    -
  • 00 0d - assigned value for extension "Signature Algorithms" -
  • 00 1e - 0x1E (30) bytes of "Signature Algorithms" extension data follows -
  • 00 1c - 0x1C (28) bytes of data are in the following list of algorithms -
  • 04 03 - assigned value for ECDSA-SECP256r1-SHA256 -
  • 05 03 - assigned value for ECDSA-SECP384r1-SHA384 -
  • 06 03 - assigned value for ECDSA-SECP521r1-SHA512 -
  • 08 07 - assigned value for ED25519 -
  • 08 08 - assigned value for ED448 -
  • 08 09 - assigned value for RSA-PSS-PSS-SHA256 -
  • 08 0a - assigned value for RSA-PSS-PSS-SHA384 -
  • 08 0b - assigned value for RSA-PSS-PSS-SHA512 -
  • 08 04 - assigned value for RSA-PSS-RSAE-SHA256 -
  • 08 05 - assigned value for RSA-PSS-RSAE-SHA384 -
  • 08 06 - assigned value for RSA-PSS-RSAE-SHA512 -
  • 04 01 - assigned value for RSA-PKCS1-SHA256 -
  • 05 01 - assigned value for RSA-PKCS1-SHA384 -
  • 06 01 - assigned value for RSA-PKCS1-SHA512 -
-
-
- - - Extension - Supported Versions - - 00 2b 00 03 02 03 04 - -
- The client indicates its support of TLS 1.3. This is the only indication in the - Client Hello record that hints the client supports TLS 1.3, since - for compatibility reasons it has otherwise pretended to be a TLS 1.2 connection - attempt. -
    -
  • 00 2b - assigned value for extension "Supported Versions" -
  • 00 03 - 3 bytes of "Supported Versions" extension data follows -
  • 02 - 2 bytes of TLS versions follow -
  • 03 04 - assigned value for TLS 1.3 -
-
-
- - - Extension - PSK Key Exchange Modes - - 00 2d 00 02 01 01 - -
- The client indicates the modes available - for establishing keys from pre-shared keys - (PSKs). Since we do not use PSKs in this - session, this extension has no effect. -
    -
  • 00 2d - assigned value for extension "PSK Key Exchange Modes" -
  • 00 02 - 2 bytes of "PSK Key Exchange Modes" extension data follows -
  • 01 - 1 bytes of exchange modes follow -
  • 01 - assigned value for "PSK with (EC)DHE key establishment" -
-
-
- - - Extension - Key Share - - 00 33 00 26 00 24 00 1d 00 20 35 80 72 d6 36 58 80 d1 ae ea 32 9a df 91 21 38 38 51 ed 21 a2 - 8e - 3b 75 e9 65 d0 d2 cd 16 62 54 - -
- The client sends one or more ephemeral public keys - using algorithm(s) that it thinks the server - will support. This allows the - rest of the handshake after the ClientHello - and ServerHello messages to be encrypted, - unlike previous protocol versions where the - handshake was sent in the clear. -
    -
  • 00 33 - assigned value for extension "Key Share" -
  • 00 26 - 0x26 (38) bytes of "Key Share" extension data follows -
  • 00 24 - 0x24 (36) bytes of key share data follows -
  • 00 1d - assigned value for x25519 (key exchange via curve25519) -
  • 00 20 - 0x20 (32) bytes of public key follows -
  • 35 80 ... 62 54 - public key from the step "Client Key Exchange Generation" -
-
-
@@ -840,182 +554,194 @@

IAT Mode
The server says "Hello" back. The server provides information including the following:
    -
  • server random data (used later in the handshake) -
  • a selected cipher suite -
  • a public key for key exchange -
  • the negotiated protocol version +
  • server ephemeral session public key representative +
  • obfs4 NTOR handshake authentication +
  • padding of random length between 4096 and 8192 bytes. +
  • mark indicating that the client knows the servers Node ID +
  • MAC value ensuring that the contents of the packet have not been modified. +
  • encrypted message containing prng seed for client to use for padding
- Record Header + Elligator2 Encoded Public Representative - 16 03 03 00 7a + TODO: Add Server Representative
- TLS sessions are broken into the sending - and receiving of "records", which are blocks - of data with a type, a protocol version, - and a length. -
    -
  • 16 - type is 0x16 (handshake record) -
  • 03 03 - legacy protocol version of "3,3" (TLS 1.2) -
  • 00 7a - 0x7A (122) bytes of handshake message follows -
+ Each handshake message starts with the client's x255519 public key encoded using + the Elligator2 encoding scheme.
- Handshake Header + Obfs4 NTOR Handshake Authentication - 02 00 00 76 + TODO: NTOR Authentication value from Server Secrets Calc
- Each handshake message starts with a type and a length. -
    -
  • 02 - handshake message type 0x02 (server hello) -
  • 00 00 76 - 0x76 (118) bytes of server hello data follows -
+ Each handshake message starts with the client's x255519 public key encoded using + the Elligator2 encoding scheme.
- Server Version - - 03 03 + Padding + + da 88 ..(4092B).. e4 c3 + +
- A protocol version of "3,3" (meaning TLS 1.2) - is given. Because middleboxes have been - created and widely deployed that do not - allow protocol versions that - they do not recognize, the TLS 1.3 session - must be disguised as a TLS 1.2 session. - This field is no - longer used for version negotiation and - is hardcoded to the 1.2 version. Instead, - version negotiation is performed using the - "Supported Versions" extension below. -

- The unusual version number ("3,3" representing - TLS 1.2) is due to TLS 1.0 being a minor - revision of the SSL 3.0 protocol. Therefore - TLS 1.0 is represented by "3,1", TLS 1.1 is - "3,2", and so on. + In obfs4 the client pads the handshake message with random bytes to a length between + 4096 and 8192 bytes. This padding is used to make the handshake message a non-uniform + length such that the size of the first packet would be a strong indication of the + specific protocol being used. +
    +
  • da 88 ... e4 c3 - bytes drawn form prng source. +
- Server Random + Steganographic Mark - 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e - 8f + TODO: compute mark
- The server provides 32 bytes of random data. This data will be used later in the session. - In this example we've made the random data a predictable string. + As the obfs4 handshake is (ideally) indistinguishable from uniform random bytes, + the client includes a steganographic mark in the handshake message to securely + indicate that it wishes to establish a connection. The mark is an HMAC that + uses the server's public key and node ID as hte key and + the client's ephemeral public key as the message. While the HMAC-SHA256 would + usually result in 32 bytes, only the first 16 bytes are used for the mark. + +


HMAC-SHA256-128(ServerPubkey | NodeID, REPR) + +

where: +

    +
  • ServerPubkey - The obfs4 servers 32 byte public x25519 identity key +
  • NodeID - The obfs4 servers 20 byte identifier value +
  • REPR - The clients Elligator2 encoded public key representative +
+ + +

Python sample code to produce the hmac value: + +

import hmac
+import hashlib
+
+server_pubkey = b'\x9f\xd7\xad\x6d\xcf\xf4\x29\x8d\xd3\xf9\x6d\x5b\x1b\x2a\xf9\x10\xa0\x53\x5b\x14\x88\xd7\xf8\xfa\xbb\x34\x9a\x98\x28\x80\xb6\x15'
+node_id = b''
+hmac_key = server_pubkey + node_id
+msg = b''
+h = hmac.new( hmac_key, msg, hashlib.sha256 )
+digest = h.hexdigest()
+print( digest[:len(digest)/2] )
+
- Session ID + Message Authentication - 20 e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd - fe - ff + TODO: Compute MAC
- This legacy field is no longer used to - identify and re-use sessions. Instead, the - server echos the session ID provided by the - client, if any. + In order to ensure that the contents of the handshake message have not been + tampered with in transit, the client includes a second HMAC value using the same + key as the steganographic mark, but covering the contents of the entire handshake + message. + + Again the HMAC-SHA256 value is truncated to 16 bytes. + +

If we consider the handshake so far to be [ REPR | PAD | MARK ] where:

    -
  • 20 - 0x20 (32) bytes of session ID follow -
  • e0 e1 ... fe ff - session ID copied from Client Hello +
  • REPR - The clients Elligator2 encoded public key representative +
  • PAD - Padding bytes +
  • MARK - Steganographic mark
-
-
- - Cipher Suite - - 13 02 - -
- The server has selected cipher suite 0x1302 - (TLS_AES_256_GCM_SHA384) from the list of options given by the client. +

The message authentication is: +

HMAC-SHA256-128(serverIdentity | NodeID, REPR | PAD | MARK | E) +

    +
  • E - string representation of the number of hours since the UNIX epoch +
+

The inclusion of the time stamp in the HMAC makes it so that the server only ever + accepts a given handshake message sent within a controlled number of hours. The server + can then keep a record of the client public keys and handshakes that it has seen + within that time window to prevent replay attacks. +

To produce this hmac value in python the code block in the above Steganographic Mark + block can be used with the msg variable set to the entire handshake message + with the appended epoch string value.

- - Compression Method + + Encrypted Data - 00 + 5c 71 16 0c da 85 f1 44
- The server has selected compression method - 0x00 ("Null", which performs no compression) - from the list of options given by the client. + This data is encrypted with the server application key. +

+ See below for the decrypted data.
- - Extensions Length - - 00 2e - +
+
Decryption
- The server has returned a list of extensions - to the client. Because the server is - forbidden from replying with an extension - that the client did not send in its hello - message, the server knows that the client - will understand and support all extensions listed. -
    -
  • 00 2e - the extensions will take 0x2E (46) bytes of data -
-
- + This data is encrypted using the client + application key and the client application IV that were + generated during the "Client Application Keys + Calc" step. The IV will be modified + by XOR'ing it by the count of records that + have already been encrypted with this key, + which in this case is 0. The process also + takes as input the 5-byte record header + that this record begins with, as authenticated + data that must match for the decryption to + succeed. +

+ Because the openssl command line + tool does not yet support AEAD ciphers, + I've written command line tools to both + decrypt + and encrypt + this data. + +
### from the "Client Application Keys Calc" step
+    $ key=de2f4c7672723a692319873e5c227606691a32d1c59d8b9f51dbb9352e9ca9cc
+    $ iv=bb007956f474b25de902432f
+    ### from this record
+    $ recdata=1703030015
+    $ authtag=73aaabf5b82fbf9a2961bcde10038a32
+    $ recordnum=0
+    ### may need to add -I and -L flags for include and lib dirs
+    $ cc -o aes_256_gcm_decrypt aes_256_gcm_decrypt.c -lssl -lcrypto
+    $ echo "82 81 39 cb 7b" | xxd -r -p > /tmp/msg3
+    $ cat /tmp/msg3 \
+      | ./aes_256_gcm_decrypt $iv $recordnum $key $recdata $authtag \
+      | hexdump -C
 
-                    
-                        Extension - Supported Versions
-                        
-                            00 2b 00 02 03 04
-                        
-                        
- The server indicates the negotiated TLS version of 1.3. -
    -
  • 00 2b - assigned value for extension "Supported Versions" -
  • 00 02 - 2 bytes of "Supported Versions" extension data follows -
  • 03 04 - assigned value for TLS 1.3 -
+ 00000000 70 69 6e 67 17 |ping.| +
+
-
+

- - Extension - Key Share + + PRNG Seed Message - 00 33 00 24 00 1d 00 20 9f d7 ad 6d cf f4 29 8d d3 f9 6d 5b 1b 2a f9 10 a0 53 5b 14 88 d7 f8 - fa - bb 34 9a 98 28 80 b6 15 + 01 00 18 f6 de 0e a1 f2 61 c8 1f bf e8 54 5b 23 91 60 9c 7d 2b fe bc be 45 9e 34
- The server sends a public key using the algorithm - of the public key sent by the client. Once this is sent - encryption keys can be calculated and the rest of the - handshake will be encrypted, - unlike previous protocol versions where the - handshake was sent in the clear. -
    -
  • 00 33 - assigned value for extension "Key Share" -
  • 00 24 - 0x24 (36) bytes of "Key Share" extension data follows -
  • 00 1d - assigned value for x25519 (key exchange via curve25519) -
  • 00 20 - 0x20 (32) bytes of public key follows -
  • 9f d7 ... b6 15 - public key from the step "Server Key Exchange Generation" -
+ This message is explained in its own section below.
-
+