Open lihongjie0209 opened 3 years ago
这个协议属于tls中的底层协议, 用于消息的压缩, 加密, hash计算和发送等功能
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.
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.
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:
Exchange hello messages to agree on algorithms, exchange random values, and check for session resumption.
Exchange the necessary cryptographic parameters to allow the client and server to agree on a premaster secret.
Exchange certificates and cryptographic information to allow the client and server to authenticate themselves.
Generate a master secret from the premaster secret and exchanged random values.
Provide security parameters to the record layer.
Allow the client and server to verify that their peer has calculated the same security parameters and that the handshake occurred without tampering by an attacker.
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
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.
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.
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.
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:
The certificate type MUST be X.509v3, unless explicitly negotiated otherwise (e.g., [TLSPGP]).
The end entity certificate's public key (and associated restrictions) MUST be compatible with the selected key exchange algorithm.
Key Exchange Alg. Certificate Key Type
RSA RSA public key; the certificate MUST allow the RSA_PSK key to be used for encryption (the keyEncipherment bit MUST be set if the key usage extension is present). Note: RSA_PSK is defined in [TLSPSK].
DHE_RSA RSA public key; the certificate MUST allow the ECDHE_RSA key to be used for signing (the digitalSignature bit MUST be set if the key usage extension is present) with the signature scheme and hash algorithm that will be employed in the server key exchange message. Note: ECDHE_RSA is defined in [TLSECC].
DHE_DSS DSA public key; the certificate MUST allow the key to be used for signing with the hash algorithm that will be employed in the server key exchange message.
DH_DSS Diffie-Hellman public key; the keyAgreement bit DH_RSA MUST be set if the key usage extension is present.
ECDH_ECDSA ECDH-capable public key; the public key MUST ECDH_RSA use a curve and point format supported by the client, as described in [TLSECC].
ECDHE_ECDSA ECDSA-capable public key; the certificate MUST allow the key to be used for signing with the hash algorithm that will be employed in the server key exchange message. The public key MUST use a curve and point format supported by the client, as described in [TLSECC].
The "server_name" and "trusted_ca_keys" extensions [TLSEXT] are used to guide certificate selection.
If the client provided a "signature_algorithms" extension, then all certificates provided by the server MUST be signed by a hash/signature algorithm pair that appears in that extension. Note that this implies that a certificate containing a key for one signature algorithm MAY be signed using a different signature algorithm (for instance, an RSA key signed with a DSA key). This is a departure from TLS 1.1, which required that the algorithms be the same. Note that this also implies that the DH_DSS, DH_RSA, ECDH_ECDSA, and ECDH_RSA key exchange algorithms do not restrict the algorithm used to sign the certificate. Fixed DH certificates MAY be signed with any hash/signature algorithm pair appearing in the extension. The names DH_DSS, DH_RSA, ECDH_ECDSA, and ECDH_RSA are historical.
If the server has multiple certificates, it chooses one of them based on the above-mentioned criteria (in addition to other criteria, such as transport layer endpoint, local configuration and preferences, etc.). If the server has a single certificate, it SHOULD attempt to validate that it meets these criteria.
Note that there are certificates that use algorithms and/or algorithm combinations that cannot be currently used with TLS. For example, a certificate with RSASSA-PSS signature key (id-RSASSA-PSS OID in SubjectPublicKeyInfo) cannot be used because TLS defines no corresponding signature algorithm.
As cipher suites that specify new key exchange methods are specified for the TLS protocol, they will imply the certificate format and the required encoded keying information.
基于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.
服务器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;
根据服务器的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;
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
where + indicates concatenation.
A() is defined as:
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:
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: