datatracker.ietf.org
SMTP サーバー・クライアントが両方とも複数の TLS バージョンをサポートしていて、使う TLS バージョンを指定してないとき、STARTTLS で使われる TLS バージョンはどのように決まるのか、というニッチな疑問の解答が欲しいの続き。RFC 8446 を読んで解決した。
TL;DR クライアントとサーバー両方が対応している最も新しいバージョンが使われる。
- TLS 1.3 で追加された(?)
supported_versions
という拡張メッセージが肝
- クライアントは対応している TLS バージョンを、好ましい順にすべて
ClientHello.supported_versions
に含める
- TLS 1.3 と 1.2 をサポートしてるクライアントがどっちを優先したいと主張するのかは、おそらく実装依存だろうが、まあ大抵はより新しいバージョンを優先的に選ぶのだろう
- クライアントは
ClientHello.legacy_version
にも対応している TLS バージョンを含める
- これも、TLS 1.2 と 1.1 をサポートしてるクライアントがどっちを選ぶかはおそらく実装依存で、まあ新しいほう(1.2)を選ぶのだろう
- サーバーは
supported_versions
があればそのバージョンを、なければ ClientHello.legacy_version
を採用し、サーバーがそのバージョンの TLS に対応してればそのバージョンで TLS handshake を進め、対応してなければアボートする
TLS 1.3 ClientHello messages always
contain extensions (minimally "supported_versions", otherwise, they
will be interpreted as TLS 1.2 ClientHello messages)
4.2.1. Supported Versions
The "supported_versions" extension is used by the client to indicate
which versions of TLS it supports and by the server to indicate which
version it is using. The extension contains a list of supported
versions in preference order, with the most preferred version first.
Implementations of this specification MUST send this extension in the
ClientHello containing all versions of TLS which they are prepared to
negotiate (for this specification, that means minimally 0x0304, but
if previous versions of TLS are allowed to be negotiated, they MUST
be present as well).
If this extension is not present, servers which are compliant with
this specification and which also support TLS 1.2 MUST negotiate
TLS 1.2 or prior as specified in [RFC5246], even if
ClientHello.legacy_version is 0x0304 or later. Servers MAY abort the
handshake upon receiving a ClientHello with legacy_version 0x0304 or
later.
If this extension is present in the ClientHello, servers MUST NOT use
the ClientHello.legacy_version value for version negotiation and MUST
use only the "supported_versions" extension to determine client
preferences. Servers MUST only select a version of TLS present in
that extension and MUST ignore any unknown versions that are present
in that extension. Note that this mechanism makes it possible to
negotiate a version prior to TLS 1.2 if one side supports a sparse
range. Implementations of TLS 1.3 which choose to support prior
versions of TLS SHOULD support TLS 1.2. Servers MUST be prepared to
receive ClientHellos that include this extension but do not include
0x0304 in the list of versions.
A server which negotiates a version of TLS prior to TLS 1.3 MUST set
ServerHello.version and MUST NOT send the "supported_versions"
extension. A server which negotiates TLS 1.3 MUST respond by sending
a "supported_versions" extension containing the selected version
value (0x0304). It MUST set the ServerHello.legacy_version field to
0x0303 (TLS 1.2). *Clients MUST check for this extension prior to
processing the rest of the ServerHello (although they will have to
parse the ServerHello in order to read the extension). If this
extension is present, clients MUST ignore the
ServerHello.legacy_version value and MUST use only the
"supported_versions" extension to determine the selected version. If
the "supported_versions" extension in the ServerHello contains a
version not offered by the client or contains a version prior to
TLS 1.3, the client MUST abort the handshake with an
"illegal_parameter" alert.
Appendix D. Backward Compatibility
The TLS protocol provides a built-in mechanism for version
negotiation between endpoints potentially supporting different
versions of TLS.
TLS 1.x and SSL 3.0 use compatible ClientHello messages. Servers can
also handle clients trying to use future versions of TLS as long as
the ClientHello format remains compatible and there is at least one
protocol version supported by both the client and the server.
Version negotiation is performed using only the handshake versions
(ClientHello.legacy_version and ServerHello.legacy_version, as well
as the ClientHello, HelloRetryRequest, and ServerHello
"supported_versions" extensions).
↑これは TLS 1.3 の話。
D.1. Negotiating with an Older Server
A TLS 1.3 client who wishes to negotiate with servers that do not
support TLS 1.3 will send a normal TLS 1.3 ClientHello containing
0x0303 (TLS 1.2) in ClientHello.legacy_version but with the correct
version(s) in the "supported_versions" extension. If the server does
not support TLS 1.3, it will respond with a ServerHello containing an
older version number. If the client agrees to use this version, the
negotiation will proceed as appropriate for the negotiated protocol.
If the version chosen by the server is not supported by the client
(or is not acceptable), the client MUST abort the handshake with a
"protocol_version" alert.
D.2. Negotiating with an Older Client
A TLS server can also receive a ClientHello indicating a version
number smaller than its highest supported version. If the
"supported_versions" extension is present, the server MUST negotiate
using that extension as described in Section 4.2.1. If the
"supported_versions" extension is not present, the server MUST
negotiate the minimum of ClientHello.legacy_version and TLS 1.2. For
example, if the server supports TLS 1.0, 1.1, and 1.2, and
legacy_version is TLS 1.0, the server will proceed with a TLS 1.0
ServerHello. If the "supported_versions" extension is absent and the
server only supports versions greater than
ClientHello.legacy_version, the server MUST abort the handshake with
a "protocol_version" alert.