lihongjie0209 / myblog

4 stars 0 forks source link

TLS 协议 #270

Open lihongjie0209 opened 3 years ago

lihongjie0209 commented 3 years ago

HMAC and the Pseudorandom Function

主要的目的是完整性校验和随机数生成

随机数生成的逻辑有点类似CBC, 前一个的输出就是后一个的输入, 通过迭代生成不同长度的随机数

The TLS record layer uses a keyed Message Authentication Code (MAC) to protect message integrity. The cipher suites defined in this document use a construction known as HMAC, described in [HMAC], which is based on a hash function. Other cipher suites MAY define their own MAC constructions, if needed.

In addition, a construction is required to do expansion of secrets into blocks of data for the purposes of key generation or validation. This pseudorandom function (PRF) takes as input a secret, a seed, and an identifying label and produces an output of arbitrary length.

In this section, we define one PRF, based on HMAC. This PRF with the SHA-256 hash function is used for all cipher suites defined in this document and in TLS documents published prior to this document when TLS 1.2 is negotiated. New cipher suites MUST explicitly specify a PRF and, in general, SHOULD use the TLS PRF with SHA-256 or a stronger standard hash function.

First, we define a data expansion function, P_hash(secret, data), that uses a single hash function to expand a secret and seed into an arbitrary quantity of output:

Dierks & Rescorla Standards Track [Page 14]

RFC 5246 TLS August 2008

  P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +
                         HMAC_hash(secret, A(2) + seed) +
                         HMAC_hash(secret, A(3) + seed) + ...

where + indicates concatenation.

A() is defined as:

  A(0) = seed
  A(i) = HMAC_hash(secret, A(i-1))

P_hash can be iterated as many times as necessary to produce the required quantity of data. For example, if P_SHA256 is being used to create 80 bytes of data, it will have to be iterated three times (through A(3)), creating 96 bytes of output data; the last 16 bytes of the final iteration will then be discarded, leaving 80 bytes of output data.

TLS's PRF is created by applying P_hash to the secret as:

  PRF(secret, label, seed) = P_<hash>(secret, label + seed)

The label is an ASCII string. It should be included in the exact form it is given without a length byte or trailing null character. For example, the label "slithy toves" would be processed by hashing the following bytes:

  73 6C 69 74 68 79 20 74 6F 76 65 73
lihongjie0209 commented 3 years ago

The TLS Record Protocol

这个协议属于tls中的底层协议, 用于消息的压缩, 加密, hash计算和发送等功能

image

The TLS Record Protocol is a layered protocol. At each layer, messages may include fields for length, description, and content. The Record Protocol takes messages to be transmitted, fragments the data into manageable blocks, optionally compresses the data, applies a MAC, encrypts, and transmits the result. Received data is decrypted, verified, decompressed, reassembled, and then delivered to higher-level clients.

分组

The record layer fragments information blocks into TLSPlaintext records carrying data in chunks of 2^14 bytes or less. Client message boundaries are not preserved in the record layer (i.e., multiple client messages of the same ContentType MAY be coalesced into a single TLSPlaintext record, or a single message MAY be fragmented across several records).

      struct {
          uint8 major;
          uint8 minor;
      } ProtocolVersion;

      enum {
          change_cipher_spec(20), alert(21), handshake(22),
          application_data(23), (255)
      } ContentType;

      struct {
          ContentType type;
          ProtocolVersion version;
          uint16 length;
          opaque fragment[TLSPlaintext.length];
      } TLSPlaintext;

   type
      The higher-level protocol used to process the enclosed fragment.

version The version of the protocol being employed. This document describes TLS Version 1.2, which uses the version { 3, 3 }. The version value 3.3 is historical, deriving from the use of {3, 1} for TLS 1.0. (See Appendix A.1.) Note that a client that supports multiple versions of TLS may not know what version will be employed before it receives the ServerHello. See Appendix E for discussion about what record layer version number should be employed for ClientHello.

length The length (in bytes) of the following TLSPlaintext.fragment. The length MUST NOT exceed 2^14.

fragment The application data. This data is transparent and treated as an independent block to be dealt with by the higher-level protocol specified by the type field.

Implementations MUST NOT send zero-length fragments of Handshake, Alert, or ChangeCipherSpec content types. Zero-length fragments of Application data MAY be sent as they are potentially useful as a traffic analysis countermeasure.

压缩

All records are compressed using the compression algorithm defined in the current session state. There is always an active compression algorithm; however, initially it is defined as CompressionMethod.null. The compression algorithm translates a TLSPlaintext structure into a TLSCompressed structure. Compression functions are initialized with default state information whenever a connection state is made active. [RFC3749] describes compression algorithms for TLS.

Compression must be lossless and may not increase the content length by more than 1024 bytes. If the decompression function encounters a TLSCompressed.fragment that would decompress to a length in excess of 2^14 bytes, it MUST report a fatal decompression failure error.

Dierks & Rescorla Standards Track [Page 20]

RFC 5246 TLS August 2008

  struct {
      ContentType type;       /* same as TLSPlaintext.type */
      ProtocolVersion version;/* same as TLSPlaintext.version */
      uint16 length;
      opaque fragment[TLSCompressed.length];
  } TLSCompressed;

length The length (in bytes) of the following TLSCompressed.fragment. The length MUST NOT exceed 2^14 + 1024.

fragment The compressed form of TLSPlaintext.fragment.

  Note: A CompressionMethod.null operation is an identity operation;
  no fields are altered.

  Implementation note: Decompression functions are responsible for
  ensuring that messages cannot cause internal buffer overflows.

加密

  The encryption and MAC functions translate a TLSCompressed
  structure into a TLSCiphertext.  The decryption functions reverse
  the process.  The MAC of the record also includes a sequence
  number so that missing, extra, or repeated messages are
  detectable.

  struct {
      ContentType type;
      ProtocolVersion version;
      uint16 length;
      select (SecurityParameters.cipher_type) {
          case stream: GenericStreamCipher;
          case block:  GenericBlockCipher;
          case aead:   GenericAEADCipher;
      } fragment;
  } TLSCiphertext;

type The type field is identical to TLSCompressed.type.

version The version field is identical to TLSCompressed.version.

length The length (in bytes) of the following TLSCiphertext.fragment. The length MUST NOT exceed 2^14 + 2048.

fragment The encrypted form of TLSCompressed.fragment, with the MAC.

lihongjie0209 commented 3 years ago

密钥生成

The Record Protocol requires an algorithm to generate keys required by the current connection state (see Appendix A.6) from the security parameters provided by the handshake protocol.

Dierks & Rescorla Standards Track [Page 25]

RFC 5246 TLS August 2008

The master secret is expanded into a sequence of secure bytes, which is then split to a client write MAC key, a server write MAC key, a client write encryption key, and a server write encryption key. Each of these is generated from the byte sequence in that order. Unused values are empty. Some AEAD ciphers may additionally require a client write IV and a server write IV (see Section 6.2.3.3).

When keys and MAC keys are generated, the master secret is used as an entropy source.

To generate the key material, compute

  key_block = PRF(SecurityParameters.master_secret,
                  "key expansion",
                  SecurityParameters.server_random +
                  SecurityParameters.client_random);

until enough output has been generated. Then, the key_block is partitioned as follows:

  client_write_MAC_key[SecurityParameters.mac_key_length]
  server_write_MAC_key[SecurityParameters.mac_key_length]
  client_write_key[SecurityParameters.enc_key_length]
  server_write_key[SecurityParameters.enc_key_length]
  client_write_IV[SecurityParameters.fixed_iv_length]
  server_write_IV[SecurityParameters.fixed_iv_length]

Currently, the client_write_IV and server_write_IV are only generated for implicit nonce techniques as described in Section 3.2.1 of [AEAD].

Implementation note: The currently defined cipher suite which requires the most material is AES_256_CBC_SHA256. It requires 2 x 32 byte keys and 2 x 32 byte MAC keys, for a total 128 bytes of key material.

lihongjie0209 commented 3 years ago

TLS 握手协议

The cryptographic parameters of the session state are produced by the TLS Handshake Protocol, which operates on top of the TLS record layer. When a TLS client and server first start communicating, they agree on a protocol version, select cryptographic algorithms, optionally authenticate each other, and use public-key encryption techniques to generate shared secrets.

The TLS Handshake Protocol involves the following steps:

      Client                                               Server

      ClientHello                  -------->
                                                      ServerHello
                                                     Certificate*
                                               ServerKeyExchange*
                                              CertificateRequest*
                                   <--------      ServerHelloDone
      Certificate*
      ClientKeyExchange
      CertificateVerify*
      [ChangeCipherSpec]
      Finished                     -------->
                                               [ChangeCipherSpec]
                                   <--------             Finished
      Application Data             <------->     Application Data

             Figure 1.  Message flow for a full handshake
lihongjie0209 commented 3 years ago

TLS 简短握手协议

When the client and server decide to resume a previous session or duplicate an existing session (instead of negotiating new security parameters), the message flow is as follows:

The client sends a ClientHello using the Session ID of the session to be resumed. The server then checks its session cache for a match. If a match is found, and the server is willing to re-establish the connection under the specified session state, it will send a ServerHello with the same Session ID value. At this point, both client and server MUST send ChangeCipherSpec messages and proceed directly to Finished messages. Once the re-establishment is complete, the client and server MAY begin to exchange application layer data. (See flow chart below.) If a Session ID match is not found, the server generates a new session ID, and the TLS client and server perform a full handshake.

      Client                                                Server

      ClientHello                   -------->
                                                       ServerHello
                                                [ChangeCipherSpec]
                                    <--------             Finished
      [ChangeCipherSpec]
      Finished                      -------->
      Application Data              <------->     Application Data
      Figure 2.  Message flow for an abbreviated handshake

The contents and significance of each message will be presented in detail in the following sections.

lihongjie0209 commented 3 years ago

Client Hello

When this message will be sent:

  When a client first connects to a server, it is required to send
  the ClientHello as its first message.  The client can also send a
  ClientHello in response to a HelloRequest or on its own initiative
  in order to renegotiate the security parameters in an existing
  connection.

Structure of this message:

  The ClientHello message includes a random structure, which is used
  later in the protocol.

     struct {
         uint32 gmt_unix_time;
         opaque random_bytes[28];
     } Random;

  gmt_unix_time
     The current time and date in standard UNIX 32-bit format
     (seconds since the midnight starting Jan 1, 1970, UTC, ignoring
     leap seconds) according to the sender's internal clock.  Clocks
     are not required to be set correctly by the basic TLS protocol;
     higher-level or application protocols may define additional
     requirements.  Note that, for historical reasons, the data
     element is named using GMT, the predecessor of the current
     worldwide time base, UTC.

  random_bytes
     28 bytes generated by a secure random number generator.

The ClientHello message includes a variable-length session identifier. If not empty, the value identifies a session between the same client and server whose security parameters the client wishes to reuse. The session identifier MAY be from an earlier connection,

Dierks & Rescorla Standards Track [Page 39]

RFC 5246 TLS August 2008

this connection, or from another currently active connection. The second option is useful if the client only wishes to update the random structures and derived values of a connection, and the third option makes it possible to establish several independent secure connections without repeating the full handshake protocol. These independent connections may occur sequentially or simultaneously; a SessionID becomes valid when the handshake negotiating it completes with the exchange of Finished messages and persists until it is removed due to aging or because a fatal error was encountered on a connection associated with the session. The actual contents of the SessionID are defined by the server.

  opaque SessionID<0..32>;

Warning: Because the SessionID is transmitted without encryption or immediate MAC protection, servers MUST NOT place confidential information in session identifiers or let the contents of fake session identifiers cause any breach of security. (Note that the content of the handshake as a whole, including the SessionID, is protected by the Finished messages exchanged at the end of the handshake.)

The cipher suite list, passed from the client to the server in the ClientHello message, contains the combinations of cryptographic algorithms supported by the client in order of the client's preference (favorite choice first). Each cipher suite defines a key exchange algorithm, a bulk encryption algorithm (including secret key length), a MAC algorithm, and a PRF. The server will select a cipher suite or, if no acceptable choices are presented, return a handshake failure alert and close the connection. If the list contains cipher suites the server does not recognize, support, or wish to use, the server MUST ignore those cipher suites, and process the remaining ones as usual.

  uint8 CipherSuite[2];    /* Cryptographic suite selector */

The ClientHello includes a list of compression algorithms supported by the client, ordered according to the client's preference.

  enum { null(0), (255) } CompressionMethod;

  struct {
      ProtocolVersion client_version;
      Random random;
      SessionID session_id;
      CipherSuite cipher_suites<2..2^16-2>;
      CompressionMethod compression_methods<1..2^8-1>;
      select (extensions_present) {
          case false:
              struct {};
          case true:
              Extension extensions<0..2^16-1>;
      };
  } ClientHello;

TLS allows extensions to follow the compression_methods field in an extensions block. The presence of extensions can be detected by determining whether there are bytes following the compression_methods at the end of the ClientHello. Note that this method of detecting optional data differs from the normal TLS method of having a variable-length field, but it is used for compatibility with TLS before extensions were defined.

client_version The version of the TLS protocol by which the client wishes to communicate during this session. This SHOULD be the latest (highest valued) version supported by the client. For this version of the specification, the version will be 3.3 (see Appendix E for details about backward compatibility).

random A client-generated random structure.

session_id The ID of a session the client wishes to use for this connection. This field is empty if no session_id is available, or if the client wishes to generate new security parameters.

cipher_suites This is a list of the cryptographic options supported by the client, with the client's first preference first. If the session_id field is not empty (implying a session resumption request), this vector MUST include at least the cipher_suite from that session. Values are defined in Appendix A.5.

compression_methods This is a list of the compression methods supported by the client, sorted by client preference. If the session_id field is not empty (implying a session resumption request), it MUST include the

  compression_method from that session.  This vector MUST contain,
  and all implementations MUST support, CompressionMethod.null.
  Thus, a client and server will always be able to agree on a
  compression method.

extensions Clients MAY request extended functionality from servers by sending data in the extensions field. The actual "Extension" format is defined in Section 7.4.1.4.

In the event that a client requests additional functionality using extensions, and this functionality is not supplied by the server, the client MAY abort the handshake. A server MUST accept ClientHello messages both with and without the extensions field, and (as for all other messages) it MUST check that the amount of data in the message precisely matches one of these formats; if not, then it MUST send a fatal "decode_error" alert.

After sending the ClientHello message, the client waits for a ServerHello message. Any handshake message returned by the server, except for a HelloRequest, is treated as a fatal error.

lihongjie0209 commented 3 years ago

Server Hello

When this message will be sent:

  The server will send this message in response to a ClientHello
  message when it was able to find an acceptable set of algorithms.
  If it cannot find such a match, it will respond with a handshake
  failure alert.

Structure of this message:

  struct {
      ProtocolVersion server_version;
      Random random;
      SessionID session_id;
      CipherSuite cipher_suite;
      CompressionMethod compression_method;
      select (extensions_present) {
          case false:
              struct {};
          case true:
              Extension extensions<0..2^16-1>;
      };
  } ServerHello;

The presence of extensions can be detected by determining whether there are bytes following the compression_method field at the end of the ServerHello.

server_version This field will contain the lower of that suggested by the client in the client hello and the highest supported by the server. For this version of the specification, the version is 3.3. (See Appendix E for details about backward compatibility.)

random This structure is generated by the server and MUST be independently generated from the ClientHello.random.

session_id This is the identity of the session corresponding to this connection. If the ClientHello.session_id was non-empty, the server will look in its session cache for a match. If a match is found and the server is willing to establish the new connection using the specified session state, the server will respond with the same value as was supplied by the client. This indicates a resumed session and dictates that the parties must proceed directly to the Finished messages. Otherwise, this field will contain a different value identifying the new session. The server may return an empty session_id to indicate that the session will not be cached and therefore cannot be resumed. If a session is resumed, it must be resumed using the same cipher suite it was originally negotiated with. Note that there is no requirement that the server resume any session even if it had formerly provided a session_id. Clients MUST be prepared to do a full negotiation -- including negotiating new cipher suites -- during any handshake.

cipher_suite The single cipher suite selected by the server from the list in ClientHello.cipher_suites. For resumed sessions, this field is the value from the state of the session being resumed.

compression_method The single compression algorithm selected by the server from the list in ClientHello.compression_methods. For resumed sessions, this field is the value from the resumed session state.

extensions A list of extensions. Note that only extensions offered by the client can appear in the server's list.

lihongjie0209 commented 3 years ago

Server Certificate Message

When this message will be sent:

  The server MUST send a Certificate message whenever the agreed-
  upon key exchange method uses certificates for authentication
  (this includes all key exchange methods defined in this document
  except DH_anon).  This message will always immediately follow the
  ServerHello message.

Meaning of this message:

  This message conveys the server's certificate chain to the client.

  The certificate MUST be appropriate for the negotiated cipher
  suite's key exchange algorithm and any negotiated extensions.

Dierks & Rescorla Standards Track [Page 47]

RFC 5246 TLS August 2008

Structure of this message:

  opaque ASN.1Cert<1..2^24-1>;

  struct {
      ASN.1Cert certificate_list<0..2^24-1>;
  } Certificate;

certificate_list This is a sequence (chain) of certificates. The sender's certificate MUST come first in the list. Each following certificate MUST directly certify the one preceding it. Because certificate validation requires that root keys be distributed independently, the self-signed certificate that specifies the root certificate authority MAY be omitted from the chain, under the assumption that the remote end must already possess it in order to validate it in any case.

The same message type and structure will be used for the client's response to a certificate request message. Note that a client MAY send no certificates if it does not have an appropriate certificate to send in response to the server's authentication request.

Note: PKCS #7 [PKCS7] is not used as the format for the certificate vector because PKCS #6 [PKCS6] extended certificates are not used. Also, PKCS #7 defines a SET rather than a SEQUENCE, making the task of parsing the list more difficult.

The following rules apply to the certificates sent by the server:

lihongjie0209 commented 3 years ago

Server Key Exchange Message

基于DH的密钥交换才需要

When this message will be sent:

  This message will be sent immediately after the server Certificate
  message (or the ServerHello message, if this is an anonymous
  negotiation).

  The ServerKeyExchange message is sent by the server only when the
  server Certificate message (if sent) does not contain enough data
  to allow the client to exchange a premaster secret.  This is true
  for the following key exchange methods:

     DHE_DSS
     DHE_RSA
     DH_anon

  It is not legal to send the ServerKeyExchange message for the
  following key exchange methods:

     RSA
     DH_DSS
     DH_RSA

  Other key exchange algorithms, such as those defined in [TLSECC],
  MUST specify whether the ServerKeyExchange message is sent or not;
  and if the message is sent, its contents.

Meaning of this message:

  This message conveys cryptographic information to allow the client
  to communicate the premaster secret: a Diffie-Hellman public key
  with which the client can complete a key exchange (with the result
  being the premaster secret) or a public key for some other
  algorithm.

Structure of this message:

  enum { dhe_dss, dhe_rsa, dh_anon, rsa, dh_dss, dh_rsa
        /* may be extended, e.g., for ECDH -- see [TLSECC] */
       } KeyExchangeAlgorithm;

  struct {
      opaque dh_p<1..2^16-1>;
      opaque dh_g<1..2^16-1>;
      opaque dh_Ys<1..2^16-1>;
  } ServerDHParams;     /* Ephemeral DH parameters */

  dh_p
     The prime modulus used for the Diffie-Hellman operation.

  dh_g
     The generator used for the Diffie-Hellman operation.

  dh_Ys
     The server's Diffie-Hellman public value (g^X mod p).

  struct {
      select (KeyExchangeAlgorithm) {
          case dh_anon:
              ServerDHParams params;
          case dhe_dss:
          case dhe_rsa:
              ServerDHParams params;
              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] */
      };
  } ServerKeyExchange;

  params
     The server's key exchange parameters.

  signed_params
     For non-anonymous key exchanges, a signature over the server's
     key exchange parameters.

If the client has offered the "signature_algorithms" extension, the signature algorithm and hash algorithm MUST be a pair listed in that extension. Note that there is a possibility for inconsistencies here. For instance, the client might offer DHE_DSS key exchange but omit any DSA pairs from its "signature_algorithms" extension. In order to negotiate correctly, the server MUST check any candidate cipher suites against the "signature_algorithms" extension before selecting them. This is somewhat inelegant but is a compromise designed to minimize changes to the original cipher suite design.

In addition, the hash and signature algorithms MUST be compatible with the key in the server's end-entity certificate. RSA keys MAY be used with any permitted hash algorithm, subject to restrictions in the certificate, if any.

Because DSA signatures do not contain any secure indication of hash algorithm, there is a risk of hash substitution if multiple hashes may be used with any key. Currently, DSA [DSS] may only be used with SHA-1. Future revisions of DSS [DSS-3] are expected to allow the use of other digest algorithms with DSA, as well as guidance as to which

digest algorithms should be used with each key size. In addition, future revisions of [PKIX] may specify mechanisms for certificates to indicate which digest algorithms are to be used with DSA.

As additional cipher suites are defined for TLS that include new key exchange algorithms, the server key exchange message will be sent if and only if the certificate type associated with the key exchange algorithm does not provide enough information for the client to exchange a premaster secret.

lihongjie0209 commented 3 years ago

Server Hello Done

服务器hello阶段结束

When this message will be sent:

  The ServerHelloDone message is sent by the server to indicate the
  end of the ServerHello and associated messages.  After sending
  this message, the server will wait for a client response.

Meaning of this message:

  This message means that the server is done sending messages to
  support the key exchange, and the client can proceed with its
  phase of the key exchange.

  Upon receipt of the ServerHelloDone message, the client SHOULD
  verify that the server provided a valid certificate, if required,
  and check that the server hello parameters are acceptable.

Structure of this message:

  struct { } ServerHelloDone;
lihongjie0209 commented 3 years ago

Client Key Exchange Message

根据服务器的hello 消息生成premaster 密钥, 通过非对称加密或者dh算法发送给服务器

When this message will be sent:

  This message is always sent by the client.  It MUST immediately
  follow the client certificate message, if it is sent.  Otherwise,
  it MUST be the first message sent by the client after it receives
  the ServerHelloDone message.

Meaning of this message:

  With this message, the premaster secret is set, either by direct
  transmission of the RSA-encrypted secret or by the transmission of
  Diffie-Hellman parameters that will allow each side to agree upon
  the same premaster secret.

  When the client is using an ephemeral Diffie-Hellman exponent,
  then this message contains the client's Diffie-Hellman public
  value.  If the client is sending a certificate containing a static
  DH exponent (i.e., it is doing fixed_dh client authentication),
  then this message MUST be sent but MUST be empty.

Structure of this message:

  The choice of messages depends on which key exchange method has
  been selected.  See Section 7.4.3 for the KeyExchangeAlgorithm
  definition.

Dierks & Rescorla Standards Track [Page 57]

RFC 5246 TLS August 2008

  struct {
      select (KeyExchangeAlgorithm) {
          case rsa:
              EncryptedPreMasterSecret;
          case dhe_dss:
          case dhe_rsa:
          case dh_dss:
          case dh_rsa:
          case dh_anon:
              ClientDiffieHellmanPublic;
      } exchange_keys;
  } ClientKeyExchange;