<?xml version="1.0" encoding="utf-8"?>
<?xml-model href="rfc7991bis.rnc"?>
<!-- <?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?> --> 
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<rfc
  xmlns:xi="http://www.w3.org/2001/XInclude"
  category="std"
  docName="draft-ietf-sshm-hostkey-update-00"
  ipr="trust200902"
  obsoletes=""
  updates=""
  consensus="true"
  submissionType="IETF"
  xml:lang="en"
  version="3">
<!-- 
    * docName should be the name of your draft
    * category should be one of std, bcp, info, exp, historic
    * ipr should be one of trust200902, noModificationTrust200902, noDerivativesTrust200902, pre5378Trust200902
    * updates can be an RFC number as NNNN.
    * obsoletes can be an RFC number as NNNN 
-->

<front>
	<title>Host key update mechanism for SSH</title>
	<seriesInfo name="Internet-Draft" value="draft-ietf-sshm-hostkey-update-00"/>
	<author fullname="Damien Miller" initials="D." surname="Miller">
		<organization>OpenSSH</organization>
		<address>
			<email>djm@openssh.com</email>  
			<uri>https://www.openssh.com/</uri>
		</address>
	</author>
	<date />
	<area>General</area>
	<workgroup>Internet Engineering Task Force</workgroup>
	<keyword>ssh</keyword>
	<keyword>hostkey</keyword>
	<keyword>rotation</keyword>
	<abstract>
		<t>
		This document describes an extension to allow a Secure Shell
		(SSH) server to inform a client of the full set of host keys
		it supports. This may be used for graceful host key rotation
		and to provide keys for additional signature algorithms to
		the client, supporting algorithm agility.
		</t>
	</abstract>
</front>

<middle>
<section><name>Introduction</name>
	<t>
	Secure Shell (SSH) is a cryptographic protocol for secure remote
	connections and login over untrusted networks.
	The SSH transport layer <xref target="RFC4253" /> includes server
	authentication though a public key signature.
	The signature algorithm used for this authentication is negotiated
	between the client and server at the start of the key agreement
	subprotocol, and the final message sent by the server at the completion
	of key agreement typically contains a signature made using the
	negotiated algorithm.
	</t>
	<t>
	Excluding certified keys such as "pgp-sign-rsa"
	(<xref target="RFC4253" section="6.6" />) or OpenSSH certificates
	(<xref target="I-D.miller-ssh-cert" />), the SSH protocol does not
	specify any way for a client to learn the host keys of a server.
	Public keys may be shared out-of-band but are more commonly learned
	for a given server the first time a client connects to it and
	trusted thereafter. This is the origin of the Trust on First Use (TOFU)
	pattern.
	</t>
	<t>
	There is no facility in the SSH transport protocol that allows a
	server to gracefully rotate its host keys. Unless coordinated
	out-of-band, a server changing host keys in this model is a hard break
	of connection trust, as any client that had learned the previous host
	key would now be met with an unexpected and untrusted key attempting to
	authenticate the final key exchange. This situation is effectively
	indistinguishable from an on-path adversary hijacking the connection.
	</t>
	<t>
	Similarly, the SSH transport protocol offers no way for a server to
	inform the client of keys for alternate signature algorithms that it
	supports; if learning keys in-band, the client must learn the key
	for each signature algorithm separately, and there is no way to use
	a previously-learned key to bootstrap trust for another.
	</t>
	<t>
	This document describes a simple extension to the SSH protocol that
	provides a mechanism for a server to advertise its full set of host
	keys to a client, and to prove possession of the requisite private
	key material for each of them.
	</t>
	<t>
	This extension takes the form of a pair of global requests
	(<xref target="RFC4254" section="4" />): "hostkeys", sent by a
	server to advertise its set of keys and "hostkeys-prove", which
	may be sent by a client to request a server prove possession of
	the private keys corresponding to one or more of these keys.
	</t>
	<t>
	Although this extension addresses a missing feature of the
	SSH transport protocol (<xref target="RFC4253" />), it is implemented
	using a message defined for the SSH connection protocol
	(<xref target="RFC4254" />), a notionally higher protocol layer.
	The reason for this is that the transport protocol lacks a defined
	extension message type and because some SSH protocol implementation
	will terminate the connection when a transport message of unsupported
	type is received, whereas connection protocol global requests are
	explicitly specified to gracefully fail when an endpoint does not
	support them.
	</t>
	<section anchor="requirements"><name>Requirements Language</name>
		<t>
		The key words "MUST", "MUST NOT", "REQUIRED", "SHALL",
	        "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT
	        RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
	        interpreted as described in BCP 14 <xref target="RFC2119"/>
	        <xref target="RFC8174"/> when, and only when, they appear in
	        all capitals, as shown here.
		</t>
	</section>
</section>
    
<section><name>Protocol</name>
	<t>
	As mentioned above, this extension consists of a pair of
	global requests: "hostkeys" and "hostkeys-prove". These are
	both messages of type SSH_MSG_GLOBAL_REQUEST
	(<xref target="RFC4254" section="4" />).
	</t>
	<t>
	These messages may only be sent
	after the SSH authentication subprotocol (<xref target="RFC4252"/>)
	has has completed, as signalled by the server sending
	SSH_MSG_USERAUTH_SUCCESS. They MUST NOT be sent prior to the
	completion of user authentication.
	</t>
	<t>
	Messages described here use the standard SSH protocol wire encoding
	types defined in <xref target="RFC4251" section="5" />.
	</t>
	<section anchor="hostkeys" title="hostkeys advertisment">
		<t>
		This message is sent by a server to inform a client of the
		public keys it supports. It is typically sent
		immediately after user authentication succeeds, but MAY be
		sent at any time later. It MUST NOT be sent more than once
		by a server over the course of a given SSH transport connection.
		</t>
		<sourcecode>
    byte             SSH_MSG_GLOBAL_REQUEST
    string           "hostkeys" or "hostkeys-00@openssh.com"
    char             0 /* do not want reply */
    string[]         hostkeys
		</sourcecode>
		<t>
		Where "hostkeys" consists of one or more public key blobs
		encoded as described in <xref target="pubkeyblob" />.
		Identical host keys MUST NOT be repeated in this message, i.e.
		every host key in the set must be unique.
		</t>
		<t>
		When a client receives this message, it MAY compare the
		set of host keys contained therein with the host keys it
		had recorded for the server. In cases where the client had
		previously recorded a host key but that key is no longer in
		the advertised set, it MAY delete or disable the key locally.
		In cases where the server advertised new, additional host keys
		that the client had not previously recorded, the client SHOULD
		request the server prove possession of the corresponding private
		key using the following request.
		</t>
	</section>
	<section anchor="prove" title="hostkeys-prove request">
		<t>
		This message is sent by a client to request a server prove
		possession of the private key material corresponding to
		one or more public keys. It is typically sent after a client
		has received a "hostkeys" advertisement to request private key
		possession proofs only for keys it has not seen before.
		</t>
		<sourcecode>
    byte             SSH_MSG_GLOBAL_REQUEST
    string           "hostkeys-prove"
    char             1 /* do want reply */
    string[]         hostkeys
		</sourcecode>
		<t>
		Where "hostkeys" consists of one or more public key blobs
		encoded as described in <xref target="pubkeyblob" />.
		All hostkeys in this request MUST BE unique; no key may be
		repeated.
		</t>
		<t>
		A server MUST reply to this request either with the success
		message defined below or a SSH_MSG_REQUEST_FAILURE if the server
		(in case of failure or unwillness to service the request).
		If a client receives such a failure, it MUST NOT trust any new
		keys provided in the initial "hostkeys" message.
		</t>
		<t>
		On success, the server returns the following message:
		</t>
		<sourcecode>
    byte             SSH_MSG_REQUEST_SUCCESS
    string[]         signatures
		</sourcecode>
		<t>
		Where "signatures" consists signatures made by the requested
		"hostkeys". The number of signatures present MUST be identical
		to the number of host keys requested and they MUST appear in
		identical order to their counterpart host keys.
		</t>
		<t>
		Each signature is made by signing the following structure with
		the corresponding key and using the signature algorithm and
		encoding as it is specified for SSH (e.g.
		<xref target="RFC5656" section="3.1.1" /> for "ecdsa-sha2-*
		keys).
		Note that RSA host keys, which unlike other key types used in
		SSH can support multiple signature algorithms, have additional
		rules described below in <xref target="ugh-rsa" />.
		</t>
		<sourcecode>
    string           "hostkeys-prove-0"
    string           session identifier
    string           hostkey
		</sourcecode>
		<t>
		Where the "hostkey" is the host key in question, also encoded
		as described in <xref target="pubkeyblob" />, and "session
		identifier" is the session identifier derived during the initial
		SSH transport key exchange as described in
		<xref target="RFC4253" section="7.2" />.
		</t>
		<t>
		When a client receives a proof for new host keys, it MUST
		verify the signature for each, after which it MAY record the
		new host key as valid for the server.
		</t>
		<section anchor="ugh-rsa" title="Special handling for RSA host keys">
			<t>
			Most key types used in SSH support only a single
			signature algorithm, but RSA keys are an exception in
			that they can generate signatures that use SHA-1,
			SHA-256 or SHA-512 as the signature hash. Which variant
			is used for host key signatures is negotiated at the
			start of key agreement via the algorithm names
			"ssh-rsa" (RSA-SHA1), "rsa-sha2-256" or "rsa-sha2-512".
			</t>
			<t>
			If a RSA signature algorithm was selected during
			initial key agreement, then the same algorithm MUST
			be used for signing hostkey proofs for any RSA keys
			the server supports. An exception to this is if
			"ssh-rsa" (i.e. the insecure RSA-SHA1 mode) was
			negotiated, in which case the "hostkeys-prove"
			request MUST fail and the server shall return a
			SSH_MSG_REQUEST_FAILURE.
			</t>
			<t>
			To avoid this situation, a server MAY skip advertising
			hostkeys when "ssh-rsa" is the negotiated host key
			signature algorithm. Alternately a server MAY exclude
			RSA host keys from the "hostkeys" advertisment message
			if other host key types are available.
			</t>
			<t>
			If a non-RSA host key signature algorithm was selected
			during initial key agreement, then either of the
			"rsa-sha2-256" or "rsa-sha2-512" signature algorithms
			may be used to sign a proof for a RSA host key.
			</t>
		</section>
		<section anchor="legacy-proof" title="Legacy vendor-specific hostkey proof request">
			<t>
			Existing implementations support the hostkey proof
			extension under a vendor-specific name, which appears
			in both the request name and in the signed data.
			To retain compatibility, implementations MAY support
			the vendor names in addition to the assigned names
			in this document.
			A hostkey proof request using the vendor-specific name
			will be:
			</t>
			<sourcecode>
    byte             SSH_MSG_GLOBAL_REQUEST
    string           "hostkeys-prove-00@openssh.com"
    char             1 /* do want reply */
    string[]         hostkeys
			</sourcecode>
			<t>
			When accepting a hostkey proof request that uses the
			vendor-specifc name, clients and server MUST generate
			and verify signatures over a structure that also uses
			the vendor-specific name:
			</t>
			<sourcecode>
    string           "hostkeys-prove-00@openssh.com"
    string           session identifier
    string           hostkey
			</sourcecode>
		</section>
	</section>
	<section anchor="pubkeyblob" title="Public key encoding">
		<t>
		In this extension, keys are encoded as strings using the
		the standard SSH wire encoding for public keys. SSH protocol
		key encodings are defined in
		<xref target="RFC4253" /> for "ssh-rsa" and "ssh-dss" keys,
		in <xref target="RFC5656" /> for "ecdsa-sha2-*" keys and in
		<xref target="RFC8709" /> for "ssh-ed25519" and "ssh-ed448"
		keys.
		</t>
	</section>
	<section anchor="adv" title="Advertising support for this extension">
		<t>
		Support for this extension may be advertised by a SSH
		protocol server using the <xref target="RFC8308" /> extension
		mechanism using the name "hostkeys" in the
		SSH_MSG_EXT_INFO message.
		</t>
		<sourcecode>
    string           "hostkeys"
    string           "0" (version)
		</sourcecode>
		<t>
		Note that this extension predates the existence
		of the <xref target="RFC8308" /> extension mechanism and
		several widely-deployed SSH implementations that support it
		do not advertise their ability to do so.
		</t>
		<t>
		As global request messages are required by
		<xref target="RFC4254" /> to be gracefully ignored by an
		endpoint that does not support them, implementations MAY
		opportunistically use this extension via the vendor-specific
		names in the absence of an <xref target="RFC8308" />
		advertisement using the vendor-specific names mentioned above.
		</t>
		<t>
		Likewise, clients and server MAY implement the vendor-specific
		names in addition to the ones described here (though note the
		special handling required for proof messages in
		<xref target="legacy-proof" />). However, if a
		an endpoint advertises support for this extension via the
		EXT_INFO mechanism, the peer SHOULD use the standard global
		request names to invoke it instead of the vendor-specific names.
		</t>
	</section>
</section>

<section><name>Motivations</name>
	<t>
	There are two motivating applications for this extension: graceful
	host key rotation and signature algorithm agility.
	</t>
	<section title="Host key rotation">
		<t>
		With a degree of planning and coordination, this extension
		may be used to gracefully rotate a server's host keys.
		To do this, a server begins by advertising via this extension
		one or more host keys in addition to the ones that it
		currently offers by default.
		As clients that support this extension connect to the server,
		these host keys will be learned and recorded as valid keys for
		the server.
		After some grace interval, or when all identified clients are
		known to have connected at least once, the original host keys
		may be removed from the server and clients will now use the
		new keys by default without a discontinuity of trust.
		</t>
	</section>
	<section title="Algorithm agility">
		<t>
		This case is similar to host key rotation, except to note
		that it is possible to advertise host keys of entirely different
		signature algorithms.
		By following a process similar to the above host key rotation
		scheme, and assuming the SSH clients support them,
		it is possible to retire weak or poorly-performing
		signature algorithms in favour of better ones. In the near
		future, it is likely this mechanism will be useful to assist
		the deployment of Post-Quantum signature schemes without
		trust discontinuities.
		</t>
	</section>
</section>

<section anchor="IANA"><name>IANA Considerations</name>
	<t>
	This extension requires two existing registries to be modified.
	</t>
	<section title="Additions to SSH Connection Protocol Global Request Names">
		<t>
		IANA is requested to insert the following entries into the
		table Connection Protocol Global Request Names
		<xref target="IANA-SSH-GLOBALREQS" /> under Secure Shell (SSH)
		Protocol Parameters <xref target="RFC4250" />.
		</t>
<table>
<thead>
<tr><th>Request Type</th><th>Reference</th></tr>
</thead>
<tbody>
<tr><td>hostkeys</td><td>thisrfc, <xref target="hostkeys" /></td></tr>
<tr><td>hostkeys-prove-0</td><td>thisrfc, <xref target="prove" /></td></tr>
</tbody>
</table>
	</section>
	<section title="Additions to SSH Extension Names">
		<t>
		IANA is requested to insert the following entry into the
		table Extension Names
		<xref target="IANA-SSH-EXT" /> under Secure Shell (SSH)
		Protocol Parameters <xref target="RFC4250" />.
		</t>
<table>
<thead>
<tr><th>Extension Name</th><th>Reference</th></tr>
</thead>
<tbody>
<tr><td>hostkeys</td><td>thisrfc, <xref target="adv" /></td></tr>
</tbody>
</table>
	</section>
</section>

<section anchor="Security"><name>Security Considerations</name>
	<t>
	This extension defines a mechanism for cryptographic key management,
	which always needs careful handling. This section calls attention to
	some specific areas of concern.
	</t>
	<section title="Trusting keys">
		<t>
	This mechanism cannot be used to estabish trust in a SSH server where
	it no key was previously trusted. Specifically, if a client learned a
	host key from an on-path adversary rather than the intended destination
	host, then this extension cannot improve this situation. Keys learned
	though this mechanism can never be more trustworthy than the key used
	to establish the SSH transport session.
		</t>
	</section>
	<section title="Dangers of ignoring proof of private key possession">
		<t>
	This host key update mechanism operates using two messages: an
	advertisement of host keys and a proof of private key possession.
	SSH implementations that implement this extension MUST implement
	support for both messages and MUST NOT record new host keys without
	verifying private key possession proofs.
		</t>
		<t>
	Supporting the advertisment
	component alone, or recording host keys without checking their private
	key possession proofs allows an attack where a malicious server
	advertises a host key for a different legitimate server. If that host
	key is recorded and subsequently used by a client when connecting to the
	malicious server, then the malicious server could forward the connection
	to the legitimate server. This may result in actions intended to be
	performed on the malicious server being instead performed on the
	legitimate one.
		</t>
	</section>
	<section title="Denial of service">
		<t>
	This extension may require servers perform additional cryptographic
	signature operations, and require clients to perform additional
	verification operations. Implementation should enforce some limit on
	the maximum number of keys they will accept for both the "hostkeys" and
	"hostkeys-prove" messages.
		</t>
	</section>
	<section title="Weak signature algorithms">
		<t>
	Implementations that retain support for the weak "ssh-rsa" (RSA-SHA1)
	signature algorithm must pay careful attention to the considerations
	in <xref target="ugh-rsa" />. Similar special handling may be required
	in future if other signature algorithms are found to be weak.
		</t>
	</section>
	<section title="Timing attack considerations">
		<t>
	This mechanism provides a way for a SSH client to request additional
	signatures using the host private keys. In doing so, it magnifies the
	attack surface for observing timing discrepancies in the signature
	operation. Although a malicious client has little control over the
	signed data, implementations should be aware of this situation and
	ensure that "hostkeys-prove" replies do not reveal information useful
	towards recovering the private key itself.
		</t>
	</section>
</section>

<section anchor="implstatus"><name>Implementation Status</name>
	<t>
	This section records the status of known implementations of the
	protocol defined by this specification at the time of posting of
	this Internet-Draft, and is based on a proposal described in
	<xref target="RFC7942" />. The description of implementations in
	this section is intended to assist the IETF in its decision processes
	in progressing drafts to RFCs. Please note that the listing of any
	individual implementation here does not imply endorsement by the
	IETF. Furthermore, no effort has been spent to verify the
	information presented here that was supplied by IETF contributors.
	This is not intended as, and must not be construed to be, a
	catalog of available implementations or their features. Readers
	are advised to note that other implementations may exist.
	</t>
	<t>
	According to <xref target="RFC7942" />, "this will allow reviewers
	and working groups to assign due consideration to documents that
	have the benefit of running code, which may serve as evidence of
	valuable experimentation and feedback that have made the implemented
	protocols more mature. It is up to the individual working groups
	to use this information as they see fit".
	</t>
	<t>
	The following example projects maintain an implementation of this
	protocol, all using the vendor-specific names described above.
	</t>
	<dl>
		<dt>OpenSSH</dt>
		<dd>
		<t>
		OpenSSH is the originating implementation of this extension and
		has supported them since 2015.
		</t>
		<t>
		Website: https://www.openssh.com/
		</t>
		</dd>

		<dt>AsyncSSH</dt>
		<dd>
		<t>
		AsyncSSH is an implementation of the SSHv2 protocol on top
		of the Python asyncio framework. It added support for
		this extension in 2024.
		</t>
		<t>
		Website: https://github.com/ronf/asyncssh
		</t>
		</dd>

		<dt>Github</dt>
		<dd>
		<t>
		The SSH implementation used by Github supports this extension.
		</t>
		<t>
		Website: https://github.com/
		</t>
		</dd>

		<dt>Russh</dt>
		<dd>
		<t>
		Russsh has implemented this extension since 2023.
		</t>
		<t>
		Website: https://github.com/Eugeny/russh
		</t>
		</dd>

		<dt>Apache Mina</dt>
		<dd>
		<t>
		The Apache Mina ssh implementation has supported this extension
		since 2015.
		</t>
		<t>
		Website: https://mina.apache.org/
		</t>
		</dd>
	</dl>
	<t>
		This list is not exhaustive.
	</t>
</section>
</middle>

<back>
<references>
	<name>References</name>
	<references><name>Normative References</name>
		<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml" />
		<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.4250.xml" />
		<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.4251.xml" />
		<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.4252.xml" />
		<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.4253.xml" />
		<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.4254.xml" />
		<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.5656.xml" />
		<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.7942.xml" />
		<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml" />
		<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8308.xml" />
		<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8709.xml" />
		<xi:include href="https://datatracker.ietf.org/doc/bibxml3/draft-miller-ssh-cert-03.xml" />
	</references>

	<references><name>Informative References</name>
			<reference anchor="IANA-SSH-GLOBALREQS" target="https://www.iana.org/assignments/ssh-parameters/"><front>
			<title>Connection Protocol Global Request Names</title>
			<author>
				<organization>IANA</organization>
			</author>
		</front></reference>       
			<reference anchor="IANA-SSH-EXT" target="https://www.iana.org/assignments/ssh-parameters/"><front>
			<title>Extension Names</title>
			<author>
				<organization>IANA</organization>
			</author>
		</front></reference>       

	</references>
</references>

<section anchor="Acknowledgments" numbered="false"><name>Acknowledgments</name>
	<t>
	Jann Horn provided valuable feedback during the development of
	this extension. Rich Salz helped improve this document.
	</t>
</section>

</back>
</rfc>
