Skip to main content Link Menu Expand (external link) Document Search Copy Copied

created at 2021-04-12

Basics

  • PRF를 통한 forward secrecy.

  • Certificate를 통한 authentication.

  • Encrypt ALPN(e.g. http/2) data

  • Handshake/Record/… Layers

Where is TLS?

스크린샷 2022-06-06 오후 4 16 39

Before TLS, Server create CSR

  1. A -> Certificate Authority

CSR(Certificate Signing Request) : A’s pub_key + identity + sign(A’s priv_key,(A’s pub_key, identity))

  1. Certificate Authority -> A

check A’s sign and sign with Certificate Authority’s priv_key

A’s Certificate : CSR + sign(Certificate Authority’s priv_key, content1)

  1. A -> B

with A’s Certificate

  1. B

verify A’s Certificate with Certificate Authority’s pub_key

Man in the Middle can not replace A’s pub_key with their pub_key.

[CSR]

  • Country Name, State or Province Name, Locality Name, Organization, Organization Unit, Common Name

스크린샷 2022-06-06 오후 11 22 58

     Server                               CA
     [CSR]CSR data + public key + Server's algorithm + sign
     -------->
                                          verify
                               <-------- [Certificate] CSR + CA public key + CA's algorithm + CA's sign

TLS Handshake Protocol

TLS 1.2v Initial Handshake

     Client                                               Server

     [ClientHello]:"TLS versions, random number, cipher suites, ALPNs(http/2), session Ticket or ID(0 length)"
     (empty SessionTicket extension)-------->
                                                    [ServerHello]:"TLS version, Server's random number, cipher suite, compression method, session Ticket or ID(0 length)"
                                                    [Certificate]*:"RSA public key"
                                              [ServerKeyExchange]*:"DHE Server's public key"
                                             [CertificateRequest]* (if it is needed)
                                  <--------     [ServerHelloDone]*:"empty"
     [Certificate]* (if it is needed, in here we only describe one way)
     [ClientKeyExchange]:"DHE Client's public key, Client's random number"
     [CertificateVerify]* (if it is needed)
     caculate pre_master_secret: combine(Client's private key, Server's public key), this is symmetric key = 1024/2048 bits
     generate master_secret: (TLS 1.2 use HMAC): PRF(pre_master_secret + "master secret" + ClientHello.random + ServerHello.random) 48 bytes
     ChangeCipherSpec:(Tell Server that just from now on, every msg will be encrypted)
     [Finished]:"master_secret, HASH([ClientHello] ~ [Finished]), string('finished')"
                                  -------->
                                              verify Client's [Finished], if hash and keys driven from master_secret are correct, NewSessionTicket starts
                                              [NewSessionTicket]:"HASH(Client's [Finished], Server's [Finished])"
                                                  This
                                                  message MUST NOT be sent if the server did not include a
                                                  SessionTicket extension in the ServerHello
                                              [ChangeCipherSpec]:(Tell Client that just from now on, every msg will be encrypted)
                                  <--------           [Finished]:"master_secret, HASH([ServerHello]~[Finished])"
     Application Data             <------->     Application Data

TLS 1.3v Handshake RFC#8446

     Client                                           Server

     Key  ^ ClientHello
     Exch | + key_share*         send A,g,p: A = g^a (mod p)
          | + signature_algorithms*
          | + psk_key_exchange_modes*
          v + pre_shared_key*       -------->
                                              ServerHello  ^ Key
                                             + key_share*  | Exch      send B: B = g^b (mod p), driven Pre-Shard-Key(PSK) = A^b (mod p)
                                        + pre_shared_key*  v           
                                    {EncryptedExtensions}  ^  Server   send Encrypted message m'=GCM(Key=K,IV=Client's random + Server's random, M=Extensions from Client)
                                    {CertificateRequest*}  v  Params
                                           {Certificate*}  ^           Server's pub_key, sign, CAs' pub_key, signs
                                     {CertificateVerify*}  | Auth      sign(RSA priv_key, handshake context+certificate)
                                               {Finished}  v           send HMAC(all handshake)
                           <--------  [Application Data*]
            driven Pre-Shard-Key(PSK) = B^a (mod p)
          ^ {Certificate*}     
     Auth | {CertificateVerify*}
          v {Finished}             send HMAC(all handshake)
                                    -------->
            [Application Data]      <------->  [Application Data]

                   +  Indicates noteworthy extensions sent in the
                      previously noted message.

                   *  Indicates optional or situation-dependent
                      messages/extensions that are not always sent.

                   {} Indicates messages protected using key PSK :

                   [] Indicates messages protected using key Kn : HKDF
                      derived from [[sender](https://datatracker.ietf.org/doc/html/rfc8446#ref-sender)]_application_traffic_secret_N.

TLS 1.3v PSK->Master Secret 도출과정

                0
                |
                v
      PSK ->  HKDF-Extract = Early Secret
                |
                +-----> Derive-Secret(., "ext binder" | "res binder", "")
                |                     = binder_key
                |
                +-----> Derive-Secret(., "c e traffic", ClientHello)
                |                     = client_early_traffic_secret
                |
                +-----> Derive-Secret(., "e exp master", ClientHello)
                |                     = early_exporter_master_secret
                v
          Derive-Secret(., "derived", "")
                |
                v
      (EC)DHE -> HKDF-Extract = Handshake Secret
                |
                +-----> Derive-Secret(., "c hs traffic",
                |                     ClientHello...ServerHello)
                |                     = client_handshake_traffic_secret
                |
                +-----> Derive-Secret(., "s hs traffic",
                |                     ClientHello...ServerHello)
                |                     = server_handshake_traffic_secret
                v
          Derive-Secret(., "derived", "")
                |
                v
      0 -> HKDF-Extract = Master Secret
                |
                +-----> Derive-Secret(., "c ap traffic",
                |                     ClientHello...server Finished)
                |                     = client_application_traffic_secret_0
                |
                +-----> Derive-Secret(., "s ap traffic",
                |                     ClientHello...server Finished)
                |                     = server_application_traffic_secret_0
                |
                +-----> Derive-Secret(., "exp master",
                |                     ClientHello...server Finished)
                |                     = exporter_master_secret
                |
                +-----> Derive-Secret(., "res master",
                                      ClientHello...client Finished)
                                      = resumption_master_secret

After TLS Full Handshake

      Client                                               Server
                                <--------      [NewSessionTicket] 다중 티켓 가능


  struct {
      uint32 ticket_lifetime;
      uint32 ticket_age_add;
      opaque ticket_nonce<0..255>;       Unique
      opaque ticket<1..2^16-1>;          PSK identity: we can self-encryption or else(we simply verify ticket with clients extensions)
      Extension extensions<0..2^16-2>;
  } NewSessionTicket;

Resumption with PSK identity(ticket)

      Client                                               Server
     Subsequent Handshake:
      ClientHello
      + key_share*
      + pre_shared_key          -------->
                                                      ServerHello
                                                 + pre_shared_key
                                                     + key_share*
                                            {EncryptedExtensions}
                                                       {Finished}
                                <--------     [Application Data*]
      {Finished}                -------->
      [Application Data]        <------->      [Application Data]

0-RTT Data

When clients and servers share a PSK, TLS 1.3 allows clients to send data on the first flight.

Client’s encrypted Application Data is not forward secret!!!(변경되지 않음)

     Client                                               Server

     ClientHello
     + early_data
     + key_share*
     + psk_key_exchange_modes
     + pre_shared_key
     (Application Data*)     -------->
                                                     ServerHello
                                                + pre_shared_key
                                                    + key_share*
                                           {EncryptedExtensions}
                                                   + early_data*
                                                      {Finished}
                             <--------       [Application Data*]
     (EndOfEarlyData)
     {Finished}              -------->
     [Application Data]      <------->        [Application Data]

           () Indicates messages protected using keys
              derived from a client_early_traffic_secret.

Structures

Structure of [ClientHello] message 1.3v:

  uint16 ProtocolVersion;
  opaque Random[32];
  uint8 CipherSuite[2];    /* Cryptographic suite selector */
  struct {
      ProtocolVersion legacy_version = 0x0303;    /* TLS v1.2 */
      Random random;
      opaque legacy_session_id<0..32>;
      CipherSuite cipher_suites<2..2^16-2>;
      opaque legacy_compression_methods<1..2^8-1>;
      Extension extensions<8..2^16-1>;
  } ClientHello;

Structure of [ServerHello] message 1.3v:

  struct {
      ProtocolVersion legacy_version = 0x0303;    /* TLS v1.2 */
      Random random; /* 32 bytes! */
      opaque legacy_session_id_echo<0..32>;
      CipherSuite cipher_suite;
      uint8 legacy_compression_method = 0;
      Extension extensions<6..2^16-1>;
  } ServerHello;


struct {
    ExtensionType extension_type;
    opaque extension_data<0..2^16-1>;
} Extension;

enum {
    server_name(0),                             /* [RFC 6066](https://datatracker.ietf.org/doc/html/rfc6066) */
    max_fragment_length(1),                     /* [RFC 6066](https://datatracker.ietf.org/doc/html/rfc6066) */
    status_request(5),                          /* [RFC 6066](https://datatracker.ietf.org/doc/html/rfc6066) */
    supported_groups(10),                       /* [RFC 8422](https://datatracker.ietf.org/doc/html/rfc8422), 7919 */
    signature_algorithms(13),                   /* [RFC 8446](https://datatracker.ietf.org/doc/html/rfc8446) */
    use_srtp(14),                               /* [RFC 5764](https://datatracker.ietf.org/doc/html/rfc5764) */
    heartbeat(15),                              /* [RFC 6520](https://datatracker.ietf.org/doc/html/rfc6520) */
    application_layer_protocol_negotiation(16), /* [RFC 7301](https://datatracker.ietf.org/doc/html/rfc7301) */
    signed_certificate_timestamp(18),           /* [RFC 6962](https://datatracker.ietf.org/doc/html/rfc6962) */
    client_certificate_type(19),                /* [RFC 7250](https://datatracker.ietf.org/doc/html/rfc7250) */
    server_certificate_type(20),                /* [RFC 7250](https://datatracker.ietf.org/doc/html/rfc7250) */
    padding(21),                                /* [RFC 7685](https://datatracker.ietf.org/doc/html/rfc7685) */
    pre_shared_key(41),                         /* [RFC 8446](https://datatracker.ietf.org/doc/html/rfc8446) */
    early_data(42),                             /* [RFC 8446](https://datatracker.ietf.org/doc/html/rfc8446) */
    supported_versions(43),                     /* [RFC 8446](https://datatracker.ietf.org/doc/html/rfc8446) */
    cookie(44),                                 /* [RFC 8446](https://datatracker.ietf.org/doc/html/rfc8446) */
    psk_key_exchange_modes(45),                 /* [RFC 8446](https://datatracker.ietf.org/doc/html/rfc8446) */
    certificate_authorities(47),                /* [RFC 8446](https://datatracker.ietf.org/doc/html/rfc8446) */
    oid_filters(48),                            /* [RFC 8446](https://datatracker.ietf.org/doc/html/rfc8446) */
    post_handshake_auth(49),                    /* [RFC 8446](https://datatracker.ietf.org/doc/html/rfc8446) */
    signature_algorithms_cert(50),              /* [RFC 8446](https://datatracker.ietf.org/doc/html/rfc8446) */
    key_share(51),                              /* [RFC 8446](https://datatracker.ietf.org/doc/html/rfc8446) */
    (65535)
} ExtensionType;

Structure of [ServerKeyExchange] message:

  struct {
      select (KeyExchangeAlgorithm) {
          case dh_anon:
              ServerDHParams params;
          case dhe_dss:
          
          /* 우리는 DHE_RSA 사용할 것임. */
          case dhe_rsa:
              ServerDHParams params; <- have (Y, g, p) Y = g^a (mod p)
              digitally-signed struct {
                  opaque client_random[32];
                  opaque server_random[32];
                  ServerDHParams params;
              } signed_params;

          case rsa:
          case dh_dss:
          case dh_rsa:
              struct {} ;
             /* message is omitted for rsa, dh_dss, and dh_rsa */
          /* may be extended, e.g., for ECDH -- see [[TLSECC](https://datatracker.ietf.org/doc/html/rfc5246#ref-TLSECC)] */
      };
  } ServerKeyExchange;

[ClientKeyExchange]

  struct {
      select (KeyExchangeAlgorithm) {
          case rsa:
              EncryptedPreMasterSecret;
          case dhe_dss:
          case dhe_rsa:
          case dh_dss:
          case dh_rsa:
          case dh_anon:
              ClientDiffieHellmanPublic; <- have (Z) Z = g^b (mod p)
      } exchange_keys;
  } ClientKeyExchange;

implementations of master_secret generation in Golang with RFC#5246 Section 5 and RFC#2104

스크린샷 2022-06-07 오전 12 47 48

스크린샷 2022-06-07 오전 12 48 08

스크린샷 2022-06-07 오전 12 48 14

스크린샷 2022-06-07 오전 12 49 27

스크린샷 2022-06-07 오전 12 50 20

  • Here, A(0) = seed = concatenate(Server’s random number, Client’s random number)
  • pHash = HMAC(pre_master_secret, A(0)) + HMAC(pre_master_secret, A(1)) + HMAC(pre_master_secret, A(2)) + … (where + indicates concatenation.)
  • master_secret = pHash

As public key operation(e.g. RSA) takes such computational resource of server, TLS provides session ID for shortcut

TLS Record Protocol

TLS record protocol is a separate sub-protocol which is used to actually encrypt and transmit upper level protocol data such as HTTP

In Picture

[Chain Of Trust with Certificate Authority] root -> intermediate -> leaf

스크린샷 2022-06-05 오후 3 16 33

from TECHSCHOOL

스크린샷 2022-06-05 오후 6 15 46

For TLS_AES256_GCM_SHA384,

  1. SHA384 algorithm hashing handshake data+verification data in 384 bits.
  2. 384 into 3 blocks(128 bits), and with GCM encryption algorithms Server generate last GMAC(TAG) that also encrypt AEAD.
  3. Thus Server MAC = TAG from GCM

스크린샷 2022-06-05 오후 6 23 04

After Initial handshakes Client receive PSK(Pre-Shared Key) identity, i.e. token.

In Server, they store like this

Client’s PSK —- ticket1, ticket2, ticket3, ticket4, …

And later when Client want to handshake with Server again, send ([ticket1, ticket2, …], client’s DHE pub_key)

Server inspect whether Client’s tickets are expired(failed to provide forward secrecy). If failed, full-handshake start with Client.

스크린샷 2022-06-05 오후 6 23 27

스크린샷 2022-06-05 오후 6 27 04