(D)TLS1. Three secrets of tls1 3 deep decryption

This section focuses on tls1 3. Make an in-depth analysis of the common conceptual knowledge in the protocol.

HKDF algorithm

Key derivation is to generate one or more keys from a key. At tls1 2 protocol uses pseudo-random number generation function (PRF), which is based on SHA256 or higher strength one-way hash algorithm. And in tls1 3 is used in the agreement RFC5869 HKDF algorithm (HMAC based extract and expand key derivation function) defined in, which is a key derivation method based on HMAC.

HKDF calculation is divided into two steps: Extract and Expand. The implementation of HKDF can be referred to OpenSSL_HKDF.

Extract

   HKDF-Extract(salt, IKM) -> PRK

   Options:
      Hash     a hash function; HashLen denotes the length of the
               hash function output in octets

   Inputs:
      salt     optional salt value (a non-secret random value);
               if not provided, it is set to a string of HashLen zeros.
      IKM      input keying material

   Output:
      PRK      a pseudorandom key (of HashLen octets)

   The output PRK is calculated as follows:

   PRK = HMAC-Hash(salt, IKM)

It can be seen that the Extract operation of HKDF is HMAC calculation. Take HMAC-SHA256 as an example. The input parameter is salt salt. If it is not provided, it is the default setting of 32 bytes of all zeros; IKM, enter the key material. The output is a 32 byte pseudo-random key.

Expand

   HKDF-Expand(PRK, info, L) -> OKM

   Options:
      Hash     a hash function; HashLen denotes the length of the
               hash function output in octets
   Inputs:
      PRK      a pseudorandom key of at least HashLen octets
               (usually, the output from the extract step)
      info     optional context and application specific information
               (can be a zero-length string)
      L        length of output keying material in octets
               (<= 255*HashLen)
   Output:
      OKM      output keying material (of L octets)

   The output OKM is calculated as follows:

   N = ceil(L/HashLen)
   T = T(1) | T(2) | T(3) | ... | T(N)
   OKM = first L octets of T

   where:
   T(0) = empty string (zero length)
   T(1) = HMAC-Hash(PRK, T(0) | info | 0x01)
   T(2) = HMAC-Hash(PRK, T(1) | info | 0x02)
   T(3) = HMAC-Hash(PRK, T(2) | info | 0x03)
   ...

It can be seen that the Expand operation of HKDF is still HMAC calculation. Taking HMAC-SHA256 as an example, the input parameters are: PRK, a pseudo-random key of at least 32 bytes, which is usually the output of the Extract step; Info, an optional value, which can be "", l, and the expected output key material length (less than 255 * 32 bytes). The output parameter is the key material with a length of L bytes. Assuming you want to Expand your own key, the calculation steps are: find the number of rounds N=ceil(48/32)=2(+1 rounded); T(0) = empty, length 0; T(1)=HMAC-SHA256(PRK, T(0) | info | 0x01), the second parameter is T(0), info, and the number of rounds 0x01; T(2)=HMAC-SHA256(PRK, T(1) | info | 0x02), the second parameter is T(0), info, and the number of rounds 0x02; OKM= T(1) | T(2) combined to form the first 48 bytes of 64 bytes of data.

Key calculation

At tls1 In the handshake phase, different secret parameters are used to generate the actually used key materials. Since both SeverHello and ClientHello use random numbers in the handshake process, each traffic secret is different.

Key scheme

TLS1. The key derivation process of 3 makes full use of HKDF algorithm. There are two calculation operations defined here: HKDF Extract and derive secret. HKDF Extract is the Extract step in the previous HKDF algorithm, and derive secret is defined as follows (from RFC8446 Section 7.1):

Derive-Secret(Secret, Label, Messages) = 
HKDF-Expand-Label(Secret, Label, Transcript-Hash(Messages), Hash.length)

Hkdf expand label is defined as:

HKDF-Expand-Label(Secret, Label, Context, Length) =
HKDF-Expand(Secret, HkdfLabel, Length)

Where HkdfLablel is defined as:

struct {
    uint16 length = Length;
    opaque label<7..255> = "tls13 " + Label;
    opaque context<0..255> = Context;
} HkdfLabel;

Therefore, the final definition is:

Derive-Secret(Secret, Label, Messages) = HKDF-Expand(Secret, HkdfLabel, Hash.length)
HkdfLabel = Hash.length + Label.length + "tls13 " + Label + Hash.length + Transcript-Hash(Messages)

The figure below shows tls1 3 key derivation scheme during Handshake:
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-ngb1G9FD-1624077457869)(images / key derivation diagram. bmp)]

The picture is difficult to understand. We need to analyze it separately horizontally and vertically, where 0 means that the salt of hkdf extract is a full 0 string.

Vertically:

  1. Input PSK as IKM and 0 as salt into hkdf extract function to obtain the output Early Secret;
  2. Take Early Secret as Secret, "derived" as Label and "" as Messages, and enter the derive Secret function to obtain a temporary key material 1;
  3. Take the key negotiated by * * (EC)DHE key as IKM, and input the temporary key material 1 as salt into hkdf extract function to obtain the output Handshake Secret * *;
  4. Similarly, take Handshake Secret as Secret, "derived" as Label and "" as Messages, and enter the Derive -Secret function to obtain another temporary key material 2;
  5. Similarly, input 0 as IKM and temporary key material 2 as salt into hkdf extract function to obtain the output Master Secret.

Horizontally:

  1. For Early Secret, different secret: binders can be obtained by using the derive secret function_ key,client_early_traffic_secret ,early_exporter_master_secret ;
  2. Similarly, for Handshake Secret, you can get: * * client_handshake_traffic_secret **,server_handshake_traffic_secret ;
  3. Similarly, for Master Secret, you can get: client_application_traffic_secret_0 ,server_application_traffic_secret_0 ,exporter_master_secret ,resumption_master_secret .

In fact, these secrets are not used as keys for encrypting data. They can be understood as temporary variables generated to calculate the Key key.

Traffic key calculation

The key actually used for encryption and decryption is calculated as follows:

[sender]_write_key = HKDF-Expand-Label(Secret, "key", "", key_length)
[sender]_write_iv = HKDF-Expand-Label(Secret, "iv", "", iv_length)

Sender refers to the sender, that is, the client or server uses different keys in the sending direction and receiving direction. The Secret values of different recording layers are as follows

+-------------------+---------------------------------------+
| Record Type 		| Secret 								|
+-------------------+---------------------------------------+
| 0-RTT Application | client_early_traffic_secret 			|
| Handshake 		| [sender]_handshake_traffic_secret 	|
| Application Data 	| [sender]_application_traffic_secret_N |
+-------------------+---------------------------------------+

AEAD algorithm

AEAD (authenticated encryption with associated data) is the authentication encryption algorithm using associated data. See RFC5116 . TLS1.3. The protocol enforces the use of AEAD algorithm to protect the recording layer load, commonly AES-CCM and AES-GCM algorithms.

TLS1.3 the structure of plaintext and ciphertext used for AEAD operation is as follows (excerpted from RFC8446 Section 5.2):

struct {
    opaque content[TLSPlaintext.length];
    ContentType type;
    uint8 zeros[length_of_padding];
} TLSInnerPlaintext;
struct {
    ContentType opaque_type = application_data; /* 23 */
    ProtocolVersion legacy_record_version = 0x0303; /* TLS v1.2 */
    uint16 length;
    opaque encrypted_record[TLSCiphertext.length];
} TLSCiphertext;

Session recovery

0-RTT

Key update

Binder

ersion = 0x0303; /* TLS v1.2 */
uint16 length;
opaque encrypted_record[TLSCiphertext.length];
} TLSCiphertext;



# Session recovery

# 0-RTT

# Key update

# Binder

Keywords: tls

Added by coffeecup on Fri, 28 Jan 2022 20:03:30 +0200