This section reuses much of the scheme defined in
Section 2.1 of
RFC 4462 and combines it with the scheme defined in
Section 4 of
RFC 5656; in particular, all checks and verification steps prescribed in
Section 4 of
RFC 5656 apply here as well.
The key-agreement schemes "ECDHE-Curve25519" and "ECDHE-Curve448" perform the Diffie-Hellman protocol using the functions X25519 and X448, respectively. Implementations
MUST compute these functions using the algorithms described in [
RFC 7748]. When they do so, implementations
MUST check whether the computed Diffie-Hellman shared secret is the all-zero value and abort if so, as described in
Section 6 of
RFC 7748. Alternative implementations of these functions
SHOULD abort when either the client or the server input forces the shared secret to one of a small set of values, as described in Sections
6 and
7 of [
RFC 7748].
This section defers to [
RFC 7546] as the source of information on GSS-API context establishment operations, Section
3 being the most relevant. All security considerations described in [
RFC 7546] apply here, too.
The parties each generate an ephemeral key pair, according to Section 3.2.1 of [
SEC1v2]. Keys are verified upon receipt by the parties according to Section 3.2.3.1 of [
SEC1v2].
For NIST curves, the keys use the uncompressed point representation and
MUST be converted using the algorithm in Section 2.3.4 of [
SEC1v2]. If the conversion fails or the point is transmitted using the compressed representation, the key exchange
MUST fail.
A GSS context is established according to
Section 4 of
RFC 5656; the client initiates the establishment using GSS_Init_sec_context(), and the server responds to it using GSS_Accept_sec_context(). For the negotiation, the client
MUST set mutual_req_flag and integ_req_flag to "true". In addition, deleg_req_flag
MAY be set to "true" to request access delegation, if requested by the user. Since the key exchange process authenticates only the host, the setting of anon_req_flag is immaterial to this process. If the client does not support the "gssapi-keyex" user authentication method described in
Section 4 of
RFC 4462, or does not intend to use that method in conjunction with the GSS-API context established during key exchange, then anon_req_flag
SHOULD be set to "true". Otherwise, this flag
MAY be set to "true" if the client wishes to hide its identity. This key exchange process will exchange only a single message token once the context has been established; therefore, the replay_det_req_flag and sequence_req_flag
SHOULD be set to "false".
The client
MUST include its public key with the first message it sends to the server during this process; if the server receives more than one key or none at all, the key exchange
MUST fail.
During GSS context establishment, multiple tokens may be exchanged by the client and the server. When the GSS context is established (major_status is GSS_S_COMPLETE), the parties check that mutual_state and integ_avail are both "true". If not, the key exchange
MUST fail.
Once a party receives the peer's public key, it proceeds to compute a shared secret K. For NIST curves, the computation is done according to Section 3.3.1 of [
SEC1v2], and the resulting value z is converted to the octet string K using the conversion defined in Section 2.3.5 of [
SEC1v2]. For curve25519 and curve448, the algorithms in
Section 6 of
RFC 7748 are used instead.
To verify the integrity of the handshake, peers use the hash function defined by the selected key exchange method to calculate H:
H = hash(V_C || V_S || I_C || I_S || K_S || Q_C || Q_S || K).
The server uses the GSS_GetMIC() call with H as the payload to generate a Message Integrity Code (MIC). The GSS_VerifyMIC() call is used by the client to verify the MIC.
If any GSS_Init_sec_context() or GSS_Accept_sec_context() returns a major_status other than GSS_S_COMPLETE or GSS_S_CONTINUE_NEEDED, or any other GSS-API call returns a major_status other than GSS_S_COMPLETE, the key exchange
MUST fail. The same recommendations expressed in
Section 2.1 of
RFC 4462 are followed with regard to error reporting.
The following is an overview of the key exchange process:
Client Server
------ ------
Generates ephemeral key pair.
Calls GSS_Init_sec_context().
SSH_MSG_KEXGSS_INIT --------------->
Verifies received key.
(Optional) <------------- SSH_MSG_KEXGSS_HOSTKEY
(Loop)
| Calls GSS_Accept_sec_context().
| <------------ SSH_MSG_KEXGSS_CONTINUE
| Calls GSS_Init_sec_context().
| SSH_MSG_KEXGSS_CONTINUE ------------>
Calls GSS_Accept_sec_context().
Generates ephemeral key pair.
Computes shared secret.
Computes hash H.
Calls GSS_GetMIC( H ) = MIC.
<------------ SSH_MSG_KEXGSS_COMPLETE
Verifies received key.
Computes shared secret.
Computes hash H.
Calls GSS_VerifyMIC( MIC, H ).
This is implemented with the following messages:
The client sends:
byte SSH_MSG_KEXGSS_INIT
string output_token (from GSS_Init_sec_context())
string Q_C, client's ephemeral public key octet string
The server may respond with:
byte SSH_MSG_KEXGSS_HOSTKEY
string server public host key and certificates (K_S)
The server sends:
byte SSH_MSG_KEXGSS_CONTINUE
string output_token (from GSS_Accept_sec_context())
Each time the client receives the message described above, it makes another call to GSS_Init_sec_context().
The client sends:
byte SSH_MSG_KEXGSS_CONTINUE
string output_token (from GSS_Init_sec_context())
As the final message, the server sends the following if an output_token is produced:
byte SSH_MSG_KEXGSS_COMPLETE
string Q_S, server's ephemeral public key octet string
string mic_token (MIC of H)
boolean TRUE
string output_token (from GSS_Accept_sec_context())
If no output_token is produced, the server sends:
byte SSH_MSG_KEXGSS_COMPLETE
string Q_S, server's ephemeral public key octet string
string mic_token (MIC of H)
boolean FALSE
The hash H is computed as the HASH hash of the concatenation of the following:
string V_C, the client's version string (CR, NL excluded)
string V_S, server's version string (CR, NL excluded)
string I_C, payload of the client's SSH_MSG_KEXINIT
string I_S, payload of the server's SSH_MSG_KEXINIT
string K_S, server's public host key
string Q_C, client's ephemeral public key octet string
string Q_S, server's ephemeral public key octet string
mpint K, shared secret
This value is called the "exchange hash", and it is used to authenticate the key exchange. The exchange hash
SHOULD be kept secret. If no SSH_MSG_KEXGSS_HOSTKEY message has been sent by the server or received by the client, then the empty string is used in place of K_S when computing the exchange hash.
Since this key exchange method does not require the host key to be used for any encryption operations, the SSH_MSG_KEXGSS_HOSTKEY message is
OPTIONAL. If the "null" host key algorithm described in
Section 5 of
RFC 4462 is used, this message
MUST NOT be sent.
If the client receives an SSH_MSG_KEXGSS_CONTINUE message after a call to GSS_Init_sec_context() has returned a major_status code of GSS_S_COMPLETE, a protocol error has occurred, and the key exchange
MUST fail.
If the client receives an SSH_MSG_KEXGSS_COMPLETE message and a call to GSS_Init_sec_context() does not result in a major_status code of GSS_S_COMPLETE, a protocol error has occurred, and the key exchange
MUST fail.