diff options
Diffstat (limited to '')
-rw-r--r-- | PROTOCOL | 715 | ||||
-rw-r--r-- | PROTOCOL.agent | 84 | ||||
-rw-r--r-- | PROTOCOL.certkeys | 321 | ||||
-rw-r--r-- | PROTOCOL.chacha20poly1305 | 107 | ||||
-rw-r--r-- | PROTOCOL.key | 71 | ||||
-rw-r--r-- | PROTOCOL.krl | 171 | ||||
-rw-r--r-- | PROTOCOL.mux | 298 | ||||
-rw-r--r-- | PROTOCOL.sshsig | 100 | ||||
-rw-r--r-- | PROTOCOL.u2f | 309 |
9 files changed, 2176 insertions, 0 deletions
diff --git a/PROTOCOL b/PROTOCOL new file mode 100644 index 0000000..27804d0 --- /dev/null +++ b/PROTOCOL @@ -0,0 +1,715 @@ +This documents OpenSSH's deviations and extensions to the published SSH +protocol. + +Note that OpenSSH's sftp and sftp-server implement revision 3 of the SSH +filexfer protocol described in: + +https://www.openssh.com/txt/draft-ietf-secsh-filexfer-02.txt + +Newer versions of the draft will not be supported, though some features +are individually implemented as extensions described below. + +The protocol used by OpenSSH's ssh-agent is described in the file +PROTOCOL.agent + +1. Transport protocol changes + +1.1. transport: Protocol 2 MAC algorithm "umac-64@openssh.com" + +This is a new transport-layer MAC method using the UMAC algorithm +(rfc4418). This method is identical to the "umac-64" method documented +in: + +https://www.openssh.com/txt/draft-miller-secsh-umac-01.txt + +1.2. transport: Protocol 2 compression algorithm "zlib@openssh.com" + +This transport-layer compression method uses the zlib compression +algorithm (identical to the "zlib" method in rfc4253), but delays the +start of compression until after authentication has completed. This +avoids exposing compression code to attacks from unauthenticated users. + +The method is documented in: + +https://www.openssh.com/txt/draft-miller-secsh-compression-delayed-00.txt + +1.3. transport: New public key algorithms "ssh-rsa-cert-v01@openssh.com", + "ssh-dsa-cert-v01@openssh.com", + "ecdsa-sha2-nistp256-cert-v01@openssh.com", + "ecdsa-sha2-nistp384-cert-v01@openssh.com" and + "ecdsa-sha2-nistp521-cert-v01@openssh.com" + +OpenSSH introduces new public key algorithms to support certificate +authentication for users and host keys. These methods are documented +in the file PROTOCOL.certkeys + +1.4. transport: Elliptic Curve cryptography + +OpenSSH supports ECC key exchange and public key authentication as +specified in RFC5656. Only the ecdsa-sha2-nistp256, ecdsa-sha2-nistp384 +and ecdsa-sha2-nistp521 curves over GF(p) are supported. Elliptic +curve points encoded using point compression are NOT accepted or +generated. + +1.5 transport: Protocol 2 Encrypt-then-MAC MAC algorithms + +OpenSSH supports MAC algorithms, whose names contain "-etm", that +perform the calculations in a different order to that defined in RFC +4253. These variants use the so-called "encrypt then MAC" ordering, +calculating the MAC over the packet ciphertext rather than the +plaintext. This ordering closes a security flaw in the SSH transport +protocol, where decryption of unauthenticated ciphertext provided a +"decryption oracle" that could, in conjunction with cipher flaws, reveal +session plaintext. + +Specifically, the "-etm" MAC algorithms modify the transport protocol +to calculate the MAC over the packet ciphertext and to send the packet +length unencrypted. This is necessary for the transport to obtain the +length of the packet and location of the MAC tag so that it may be +verified without decrypting unauthenticated data. + +As such, the MAC covers: + + mac = MAC(key, sequence_number || packet_length || encrypted_packet) + +where "packet_length" is encoded as a uint32 and "encrypted_packet" +contains: + + byte padding_length + byte[n1] payload; n1 = packet_length - padding_length - 1 + byte[n2] random padding; n2 = padding_length + +1.6 transport: AES-GCM + +OpenSSH supports the AES-GCM algorithm as specified in RFC 5647. +Because of problems with the specification of the key exchange +the behaviour of OpenSSH differs from the RFC as follows: + +AES-GCM is only negotiated as the cipher algorithms +"aes128-gcm@openssh.com" or "aes256-gcm@openssh.com" and never as +an MAC algorithm. Additionally, if AES-GCM is selected as the cipher +the exchanged MAC algorithms are ignored and there doesn't have to be +a matching MAC. + +1.7 transport: chacha20-poly1305@openssh.com authenticated encryption + +OpenSSH supports authenticated encryption using ChaCha20 and Poly1305 +as described in PROTOCOL.chacha20poly1305. + +1.8 transport: curve25519-sha256@libssh.org key exchange algorithm + +OpenSSH supports the use of ECDH in Curve25519 for key exchange as +described at: +http://git.libssh.org/users/aris/libssh.git/plain/doc/curve25519-sha256@libssh.org.txt?h=curve25519 + +This is identical to curve25519-sha256 as later published in RFC8731. + +2. Connection protocol changes + +2.1. connection: Channel write close extension "eow@openssh.com" + +The SSH connection protocol (rfc4254) provides the SSH_MSG_CHANNEL_EOF +message to allow an endpoint to signal its peer that it will send no +more data over a channel. Unfortunately, there is no symmetric way for +an endpoint to request that its peer should cease sending data to it +while still keeping the channel open for the endpoint to send data to +the peer. + +This is desirable, since it saves the transmission of data that would +otherwise need to be discarded and it allows an endpoint to signal local +processes of the condition, e.g. by closing the corresponding file +descriptor. + +OpenSSH implements a channel extension message to perform this +signalling: "eow@openssh.com" (End Of Write). This message is sent by +an endpoint when the local output of a session channel is closed or +experiences a write error. The message is formatted as follows: + + byte SSH_MSG_CHANNEL_REQUEST + uint32 recipient channel + string "eow@openssh.com" + boolean FALSE + +On receiving this message, the peer SHOULD cease sending data of +the channel and MAY signal the process from which the channel data +originates (e.g. by closing its read file descriptor). + +As with the symmetric SSH_MSG_CHANNEL_EOF message, the channel does +remain open after a "eow@openssh.com" has been sent and more data may +still be sent in the other direction. This message does not consume +window space and may be sent even if no window space is available. + +NB. due to certain broken SSH implementations aborting upon receipt +of this message (in contravention of RFC4254 section 5.4), this +message is only sent to OpenSSH peers (identified by banner). +Other SSH implementations may be listed to receive this message +upon request. + +2.2. connection: disallow additional sessions extension + "no-more-sessions@openssh.com" + +Most SSH connections will only ever request a single session, but a +attacker may abuse a running ssh client to surreptitiously open +additional sessions under their control. OpenSSH provides a global +request "no-more-sessions@openssh.com" to mitigate this attack. + +When an OpenSSH client expects that it will never open another session +(i.e. it has been started with connection multiplexing disabled), it +will send the following global request: + + byte SSH_MSG_GLOBAL_REQUEST + string "no-more-sessions@openssh.com" + char want-reply + +On receipt of such a message, an OpenSSH server will refuse to open +future channels of type "session" and instead immediately abort the +connection. + +Note that this is not a general defence against compromised clients +(that is impossible), but it thwarts a simple attack. + +NB. due to certain broken SSH implementations aborting upon receipt +of this message, the no-more-sessions request is only sent to OpenSSH +servers (identified by banner). Other SSH implementations may be +listed to receive this message upon request. + +2.3. connection: Tunnel forward extension "tun@openssh.com" + +OpenSSH supports layer 2 and layer 3 tunnelling via the "tun@openssh.com" +channel type. This channel type supports forwarding of network packets +with datagram boundaries intact between endpoints equipped with +interfaces like the BSD tun(4) device. Tunnel forwarding channels are +requested by the client with the following packet: + + byte SSH_MSG_CHANNEL_OPEN + string "tun@openssh.com" + uint32 sender channel + uint32 initial window size + uint32 maximum packet size + uint32 tunnel mode + uint32 remote unit number + +The "tunnel mode" parameter specifies whether the tunnel should forward +layer 2 frames or layer 3 packets. It may take one of the following values: + + SSH_TUNMODE_POINTOPOINT 1 /* layer 3 packets */ + SSH_TUNMODE_ETHERNET 2 /* layer 2 frames */ + +The "tunnel unit number" specifies the remote interface number, or may +be 0x7fffffff to allow the server to automatically choose an interface. A +server that is not willing to open a client-specified unit should refuse +the request with a SSH_MSG_CHANNEL_OPEN_FAILURE error. On successful +open, the server should reply with SSH_MSG_CHANNEL_OPEN_SUCCESS. + +Once established the client and server may exchange packet or frames +over the tunnel channel by encapsulating them in SSH protocol strings +and sending them as channel data. This ensures that packet boundaries +are kept intact. Specifically, packets are transmitted using normal +SSH_MSG_CHANNEL_DATA packets: + + byte SSH_MSG_CHANNEL_DATA + uint32 recipient channel + string data + +The contents of the "data" field for layer 3 packets is: + + uint32 packet length + uint32 address family + byte[packet length - 4] packet data + +The "address family" field identifies the type of packet in the message. +It may be one of: + + SSH_TUN_AF_INET 2 /* IPv4 */ + SSH_TUN_AF_INET6 24 /* IPv6 */ + +The "packet data" field consists of the IPv4/IPv6 datagram itself +without any link layer header. + +The contents of the "data" field for layer 2 packets is: + + uint32 packet length + byte[packet length] frame + +The "frame" field contains an IEEE 802.3 Ethernet frame, including +header. + +2.4. connection: Unix domain socket forwarding + +OpenSSH supports local and remote Unix domain socket forwarding +using the "streamlocal" extension. Forwarding is initiated as per +TCP sockets but with a single path instead of a host and port. + +Similar to direct-tcpip, direct-streamlocal is sent by the client +to request that the server make a connection to a Unix domain socket. + + byte SSH_MSG_CHANNEL_OPEN + string "direct-streamlocal@openssh.com" + uint32 sender channel + uint32 initial window size + uint32 maximum packet size + string socket path + string reserved + uint32 reserved + +Similar to forwarded-tcpip, forwarded-streamlocal is sent by the +server when the client has previously send the server a streamlocal-forward +GLOBAL_REQUEST. + + byte SSH_MSG_CHANNEL_OPEN + string "forwarded-streamlocal@openssh.com" + uint32 sender channel + uint32 initial window size + uint32 maximum packet size + string socket path + string reserved for future use + +The reserved field is not currently defined and is ignored on the +remote end. It is intended to be used in the future to pass +information about the socket file, such as ownership and mode. +The client currently sends the empty string for this field. + +Similar to tcpip-forward, streamlocal-forward is sent by the client +to request remote forwarding of a Unix domain socket. + + byte SSH2_MSG_GLOBAL_REQUEST + string "streamlocal-forward@openssh.com" + boolean TRUE + string socket path + +Similar to cancel-tcpip-forward, cancel-streamlocal-forward is sent +by the client cancel the forwarding of a Unix domain socket. + + byte SSH2_MSG_GLOBAL_REQUEST + string "cancel-streamlocal-forward@openssh.com" + boolean FALSE + string socket path + +2.5. connection: hostkey update and rotation "hostkeys-00@openssh.com" +and "hostkeys-prove-00@openssh.com" + +OpenSSH supports a protocol extension allowing a server to inform +a client of all its protocol v.2 host keys after user-authentication +has completed. + + byte SSH_MSG_GLOBAL_REQUEST + string "hostkeys-00@openssh.com" + char 0 /* want-reply */ + string[] hostkeys + +Upon receiving this message, a client should check which of the +supplied host keys are present in known_hosts. + +Note that the server may send key types that the client does not +support. The client should disregard such keys if they are received. + +If the client identifies any keys that are not present for the host, +it should send a "hostkeys-prove@openssh.com" message to request the +server prove ownership of the private half of the key. + + byte SSH_MSG_GLOBAL_REQUEST + string "hostkeys-prove-00@openssh.com" + char 1 /* want-reply */ + string[] hostkeys + +When a server receives this message, it should generate a signature +using each requested key over the following: + + string "hostkeys-prove-00@openssh.com" + string session identifier + string hostkey + +These signatures should be included in the reply, in the order matching +the hostkeys in the request: + + byte SSH_MSG_REQUEST_SUCCESS + string[] signatures + +When the client receives this reply (and not a failure), it should +validate the signatures and may update its known_hosts file, adding keys +that it has not seen before and deleting keys for the server host that +are no longer offered. + +These extensions let a client learn key types that it had not previously +encountered, thereby allowing it to potentially upgrade from weaker +key algorithms to better ones. It also supports graceful key rotation: +a server may offer multiple keys of the same type for a period (to +give clients an opportunity to learn them using this extension) before +removing the deprecated key from those offered. + +2.6. connection: SIGINFO support for "signal" channel request + +The SSH channels protocol (RFC4254 section 6.9) supports sending a +signal to a session attached to a channel. OpenSSH supports one +extension signal "INFO@openssh.com" that allows sending SIGINFO on +BSD-derived systems. + +3. Authentication protocol changes + +3.1. Host-bound public key authentication + +This is trivial change to the traditional "publickey" authentication +method. The authentication request is identical to the original method +but for the name and one additional field: + + byte SSH2_MSG_USERAUTH_REQUEST + string username + string "ssh-connection" + string "publickey-hostbound-v00@openssh.com" + bool has_signature + string pkalg + string public key + string server host key + +Because the entire SSH2_MSG_USERAUTH_REQUEST message is included in +the signed data, this ensures that a binding between the destination +user, the server identity and the session identifier is visible to the +signer. OpenSSH uses this binding via signed data to implement per-key +restrictions in ssh-agent. + +A server may advertise this method using the SSH2_MSG_EXT_INFO +mechanism (RFC8308), with the following message: + + string "publickey-hostbound@openssh.com" + string "0" (version) + +Clients should prefer host-bound authentication when advertised by +server. + +4. SFTP protocol changes + +4.1. sftp: Reversal of arguments to SSH_FXP_SYMLINK + +When OpenSSH's sftp-server was implemented, the order of the arguments +to the SSH_FXP_SYMLINK method was inadvertently reversed. Unfortunately, +the reversal was not noticed until the server was widely deployed. Since +fixing this to follow the specification would cause incompatibility, the +current order was retained. For correct operation, clients should send +SSH_FXP_SYMLINK as follows: + + uint32 id + string targetpath + string linkpath + +4.2. sftp: Server extension announcement in SSH_FXP_VERSION + +OpenSSH's sftp-server lists the extensions it supports using the +standard extension announcement mechanism in the SSH_FXP_VERSION server +hello packet: + + uint32 3 /* protocol version */ + string ext1-name + string ext1-version + string ext2-name + string ext2-version + ... + string extN-name + string extN-version + +Each extension reports its integer version number as an ASCII encoded +string, e.g. "1". The version will be incremented if the extension is +ever changed in an incompatible way. The server MAY advertise the same +extension with multiple versions (though this is unlikely). Clients MUST +check the version number before attempting to use the extension. + +4.3. sftp: Extension request "posix-rename@openssh.com" + +This operation provides a rename operation with POSIX semantics, which +are different to those provided by the standard SSH_FXP_RENAME in +draft-ietf-secsh-filexfer-02.txt. This request is implemented as a +SSH_FXP_EXTENDED request with the following format: + + uint32 id + string "posix-rename@openssh.com" + string oldpath + string newpath + +On receiving this request the server will perform the POSIX operation +rename(oldpath, newpath) and will respond with a SSH_FXP_STATUS message. +This extension is advertised in the SSH_FXP_VERSION hello with version +"1". + +4.4. sftp: Extension requests "statvfs@openssh.com" and + "fstatvfs@openssh.com" + +These requests correspond to the statvfs and fstatvfs POSIX system +interfaces. The "statvfs@openssh.com" request operates on an explicit +pathname, and is formatted as follows: + + uint32 id + string "statvfs@openssh.com" + string path + +The "fstatvfs@openssh.com" operates on an open file handle: + + uint32 id + string "fstatvfs@openssh.com" + string handle + +These requests return a SSH_FXP_STATUS reply on failure. On success they +return the following SSH_FXP_EXTENDED_REPLY reply: + + uint32 id + uint64 f_bsize /* file system block size */ + uint64 f_frsize /* fundamental fs block size */ + uint64 f_blocks /* number of blocks (unit f_frsize) */ + uint64 f_bfree /* free blocks in file system */ + uint64 f_bavail /* free blocks for non-root */ + uint64 f_files /* total file inodes */ + uint64 f_ffree /* free file inodes */ + uint64 f_favail /* free file inodes for to non-root */ + uint64 f_fsid /* file system id */ + uint64 f_flag /* bit mask of f_flag values */ + uint64 f_namemax /* maximum filename length */ + +The values of the f_flag bitmask are as follows: + + #define SSH_FXE_STATVFS_ST_RDONLY 0x1 /* read-only */ + #define SSH_FXE_STATVFS_ST_NOSUID 0x2 /* no setuid */ + +Both the "statvfs@openssh.com" and "fstatvfs@openssh.com" extensions are +advertised in the SSH_FXP_VERSION hello with version "2". + +4.5. sftp: Extension request "hardlink@openssh.com" + +This request is for creating a hard link to a regular file. This +request is implemented as a SSH_FXP_EXTENDED request with the +following format: + + uint32 id + string "hardlink@openssh.com" + string oldpath + string newpath + +On receiving this request the server will perform the operation +link(oldpath, newpath) and will respond with a SSH_FXP_STATUS message. +This extension is advertised in the SSH_FXP_VERSION hello with version +"1". + +4.6. sftp: Extension request "fsync@openssh.com" + +This request asks the server to call fsync(2) on an open file handle. + + uint32 id + string "fsync@openssh.com" + string handle + +On receiving this request, a server will call fsync(handle_fd) and will +respond with a SSH_FXP_STATUS message. + +This extension is advertised in the SSH_FXP_VERSION hello with version +"1". + +4.7. sftp: Extension request "lsetstat@openssh.com" + +This request is like the "setstat" command, but sets file attributes on +symlinks. It is implemented as a SSH_FXP_EXTENDED request with the +following format: + + uint32 id + string "lsetstat@openssh.com" + string path + ATTRS attrs + +See the "setstat" command for more details. + +This extension is advertised in the SSH_FXP_VERSION hello with version +"1". + +4.8. sftp: Extension request "limits@openssh.com" + +This request is used to determine various limits the server might impose. +Clients should not attempt to exceed these limits as the server might sever +the connection immediately. + + uint32 id + string "limits@openssh.com" + +The server will respond with a SSH_FXP_EXTENDED_REPLY reply: + + uint32 id + uint64 max-packet-length + uint64 max-read-length + uint64 max-write-length + uint64 max-open-handles + +The 'max-packet-length' applies to the total number of bytes in a +single SFTP packet. Servers SHOULD set this at least to 34000. + +The 'max-read-length' is the largest length in a SSH_FXP_READ packet. +Even if the client requests a larger size, servers will usually respond +with a shorter SSH_FXP_DATA packet. Servers SHOULD set this at least to +32768. + +The 'max-write-length' is the largest length in a SSH_FXP_WRITE packet +the server will accept. Servers SHOULD set this at least to 32768. + +The 'max-open-handles' is the maximum number of active handles that the +server allows (e.g. handles created by SSH_FXP_OPEN and SSH_FXP_OPENDIR +packets). Servers MAY count internal file handles against this limit +(e.g. system logging or stdout/stderr), so clients SHOULD NOT expect to +open this many handles in practice. + +If the server doesn't enforce a specific limit, then the field may be +set to 0. This implies the server relies on the OS to enforce limits +(e.g. available memory or file handles), and such limits might be +dynamic. The client SHOULD take care to not try to exceed reasonable +limits. + +This extension is advertised in the SSH_FXP_VERSION hello with version +"1". + +4.9. sftp: Extension request "expand-path@openssh.com" + +This request supports canonicalisation of relative paths and +those that need tilde-expansion, i.e. "~", "~/..." and "~user/..." +These paths are expanded using shell-like rules and the resultant +path is canonicalised similarly to SSH2_FXP_REALPATH. + +It is implemented as a SSH_FXP_EXTENDED request with the following +format: + + uint32 id + string "expand-path@openssh.com" + string path + +Its reply is the same format as that of SSH2_FXP_REALPATH. + +This extension is advertised in the SSH_FXP_VERSION hello with version +"1". + +4.10. sftp: Extension request "copy-data" + +This request asks the server to copy data from one open file handle and +write it to a different open file handle. This avoids needing to transfer +the data across the network twice (a download followed by an upload). + + byte SSH_FXP_EXTENDED + uint32 id + string "copy-data" + string read-from-handle + uint64 read-from-offset + uint64 read-data-length + string write-to-handle + uint64 write-to-offset + +The server will copy read-data-length bytes starting from +read-from-offset from the read-from-handle and write them to +write-to-handle starting from write-to-offset, and then respond with a +SSH_FXP_STATUS message. + +It's equivalent to issuing a series of SSH_FXP_READ requests on +read-from-handle and a series of requests of SSH_FXP_WRITE on +write-to-handle. + +If read-from-handle and write-to-handle are the same, the server will +fail the request and respond with a SSH_FX_INVALID_PARAMETER message. + +If read-data-length is 0, then the server will read data from the +read-from-handle until EOF is reached. + +This extension is advertised in the SSH_FXP_VERSION hello with version +"1". + +This request is identical to the "copy-data" request documented in: + +https://tools.ietf.org/html/draft-ietf-secsh-filexfer-extensions-00#section-7 + +4.11. sftp: Extension request "home-directory" + +This request asks the server to expand the specified user's home directory. +An empty username implies the current user. This can be used by the client +to expand ~/ type paths locally. + + byte SSH_FXP_EXTENDED + uint32 id + string "home-directory" + string username + +This extension is advertised in the SSH_FXP_VERSION hello with version +"1". + +This provides similar information as the "expand-path@openssh.com" extension. + +This request is identical to the "home-directory" request documented in: + +https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-extensions-00#section-5 + +4.12. sftp: Extension request "users-groups-by-id@openssh.com" + +This request asks the server to return user and/or group names that +correspond to one or more IDs (e.g. as returned from a SSH_FXP_STAT +request). This may be used by the client to provide usernames in +directory listings. + + byte SSH_FXP_EXTENDED + uint32 id + string "users-groups-by-id@openssh.com" + string uids + string gids + +Where "uids" and "gids" consists of one or more integer user or group +identifiers: + + uint32 id-0 + ... + +The server will reply with a SSH_FXP_EXTENDED_REPLY: + + byte SSH_FXP_EXTENDED_REPLY + string usernames + string groupnames + +Where "username" and "groupnames" consists of names in identical request +order to "uids" and "gids" respectively: + + string name-0 + ... + +If a name cannot be identified for a given user or group ID, an empty +string will be returned in its place. + +It is acceptable for either "uids" or "gids" to be an empty set, in +which case the respective "usernames" or "groupnames" list will also +be empty. + +This extension is advertised in the SSH_FXP_VERSION hello with version +"1". + +5. Miscellaneous changes + +5.1 Public key format + +OpenSSH public keys, as generated by ssh-keygen(1) and appearing in +authorized_keys files, are formatted as a single line of text consisting +of the public key algorithm name followed by a base64-encoded key blob. +The public key blob (before base64 encoding) is the same format used for +the encoding of public keys sent on the wire: as described in RFC4253 +section 6.6 for RSA and DSA keys, RFC5656 section 3.1 for ECDSA keys +and the "New public key formats" section of PROTOCOL.certkeys for the +OpenSSH certificate formats. + +5.2 Private key format + +OpenSSH private keys, as generated by ssh-keygen(1) use the format +described in PROTOCOL.key by default. As a legacy option, PEM format +(RFC7468) private keys are also supported for RSA, DSA and ECDSA keys +and were the default format before OpenSSH 7.8. + +5.3 KRL format + +OpenSSH supports a compact format for Key Revocation Lists (KRLs). This +format is described in the PROTOCOL.krl file. + +5.4 Connection multiplexing + +OpenSSH's connection multiplexing uses messages as described in +PROTOCOL.mux over a Unix domain socket for communications between a +master instance and later clients. + +5.5. Agent protocol extensions + +OpenSSH extends the usual agent protocol. These changes are documented +in the PROTOCOL.agent file. + +$OpenBSD: PROTOCOL,v 1.48 2022/11/07 01:53:01 dtucker Exp $ diff --git a/PROTOCOL.agent b/PROTOCOL.agent new file mode 100644 index 0000000..dba76b0 --- /dev/null +++ b/PROTOCOL.agent @@ -0,0 +1,84 @@ +The SSH agent protocol is described in +https://tools.ietf.org/html/draft-miller-ssh-agent-04 + +This file documents OpenSSH's extensions to the agent protocol. + +1. session-bind@openssh.com extension + +This extension allows a ssh client to bind an agent connection to a +particular SSH session identifier as derived from the initial key +exchange (as per RFC4253 section 7.2) and the host key used for that +exchange. This binding is verifiable at the agent by including the +initial KEX signature made by the host key. + +The message format is: + + byte SSH_AGENTC_EXTENSION (0x1b) + string session-bind@openssh.com + string hostkey + string session identifier + string signature + bool is_forwarding + +Where 'hostkey' is the encoded server host public key, 'session +identifier' is the exchange hash derived from the initial key +exchange, 'signature' is the server's signature of the session +identifier using the private hostkey, as sent in the final +SSH2_MSG_KEXDH_REPLY/SSH2_MSG_KEXECDH_REPLY message of the initial key +exchange. 'is_forwarding' is a flag indicating whether this connection +should be bound for user authentication or forwarding. + +When an agent received this message, it will verify the signature and +check the consistency of its contents, including refusing to accept +a duplicate session identifier, or any attempt to bind a connection +previously bound for authentication. It will then then record the +binding for the life of the connection for use later in testing per-key +destination constraints. + +2. restrict-destination-v00@openssh.com key constraint extension + +The key constraint extension supports destination- and forwarding path- +restricted keys. It may be attached as a constraint when keys or +smartcard keys are added to an agent. + + byte SSH_AGENT_CONSTRAIN_EXTENSION (0xff) + string restrict-destination-v00@openssh.com + constraint[] constraints + +Where a constraint consists of: + + string from_username (must be empty) + string from_hostname + keyspec[] from_hostkeys + string to_username + string to_hostname + keyspec[] to_hostkeys + +And a keyspec consists of: + + string keyblob + bool is_ca + +When receiving this message, the agent will ensure that the +'from_username' field is empty, and that 'to_hostname' and 'to_hostkeys' +have been supplied (empty 'from_hostname' and 'from_hostkeys' are valid +and signify the initial hop from the host running ssh-agent). The agent +will then record the constraint against the key. + +Subsequent operations on this key including add/remove/request +identities and, in particular, signature requests will check the key +constraints against the session-bind@openssh.com bindings recorded for +the agent connection over which they were received. + +3. SSH_AGENT_CONSTRAIN_MAXSIGN key constraint + +This key constraint allows communication to an agent of the maximum +number of signatures that may be made with an XMSS key. The format of +the constraint is: + + byte SSH_AGENT_CONSTRAIN_MAXSIGN (0x03) + uint32 max_signatures + +This option is only valid for XMSS keys. + +$OpenBSD: PROTOCOL.agent,v 1.18 2022/09/21 22:26:50 dtucker Exp $ diff --git a/PROTOCOL.certkeys b/PROTOCOL.certkeys new file mode 100644 index 0000000..68622e6 --- /dev/null +++ b/PROTOCOL.certkeys @@ -0,0 +1,321 @@ +This document describes a simple public-key certificate authentication +system for use by SSH. + +Background +---------- + +The SSH protocol currently supports a simple public key authentication +mechanism. Unlike other public key implementations, SSH eschews the use +of X.509 certificates and uses raw keys. This approach has some benefits +relating to simplicity of configuration and minimisation of attack +surface, but it does not support the important use-cases of centrally +managed, passwordless authentication and centrally certified host keys. + +These protocol extensions build on the simple public key authentication +system already in SSH to allow certificate-based authentication. The +certificates used are not traditional X.509 certificates, with numerous +options and complex encoding rules, but something rather more minimal: a +key, some identity information and usage options that have been signed +with some other trusted key. + +A sshd server may be configured to allow authentication via certified +keys, by extending the existing ~/.ssh/authorized_keys mechanism to +allow specification of certification authority keys in addition to +raw user keys. The ssh client will support automatic verification of +acceptance of certified host keys, by adding a similar ability to +specify CA keys in ~/.ssh/known_hosts. + +All certificate types include certification information along with the +public key that is used to sign challenges. In OpenSSH, ssh-keygen +performs the CA signing operation. + +Certified keys are represented using new key types: + + ssh-rsa-cert-v01@openssh.com + ssh-dss-cert-v01@openssh.com + ecdsa-sha2-nistp256-cert-v01@openssh.com + ecdsa-sha2-nistp384-cert-v01@openssh.com + ecdsa-sha2-nistp521-cert-v01@openssh.com + ssh-ed25519-cert-v01@openssh.com + +Two additional types exist for RSA certificates to force use of +SHA-2 signatures (SHA-256 and SHA-512 respectively): + + rsa-sha2-256-cert-v01@openssh.com + rsa-sha2-512-cert-v01@openssh.com + +These RSA/SHA-2 types should not appear in keys at rest or transmitted +on the wire, but do appear in a SSH_MSG_KEXINIT's host-key algorithms +field or in the "public key algorithm name" field of a "publickey" +SSH_USERAUTH_REQUEST to indicate that the signature will use the +specified algorithm. + +Protocol extensions +------------------- + +The SSH wire protocol includes several extensibility mechanisms. +These modifications shall take advantage of namespaced public key +algorithm names to add support for certificate authentication without +breaking the protocol - implementations that do not support the +extensions will simply ignore them. + +Authentication using the new key formats described below proceeds +using the existing SSH "publickey" authentication method described +in RFC4252 section 7. + +New public key formats +---------------------- + +The certificate key types take a similar high-level format (note: data +types and encoding are as per RFC4251 section 5). The serialised wire +encoding of these certificates is also used for storing them on disk. + +#define SSH_CERT_TYPE_USER 1 +#define SSH_CERT_TYPE_HOST 2 + +RSA certificate + + string "ssh-rsa-cert-v01@openssh.com" + string nonce + mpint e + mpint n + uint64 serial + uint32 type + string key id + string valid principals + uint64 valid after + uint64 valid before + string critical options + string extensions + string reserved + string signature key + string signature + +DSA certificate + + string "ssh-dss-cert-v01@openssh.com" + string nonce + mpint p + mpint q + mpint g + mpint y + uint64 serial + uint32 type + string key id + string valid principals + uint64 valid after + uint64 valid before + string critical options + string extensions + string reserved + string signature key + string signature + +ECDSA certificate + + string "ecdsa-sha2-nistp256-cert-v01@openssh.com" | + "ecdsa-sha2-nistp384-cert-v01@openssh.com" | + "ecdsa-sha2-nistp521-cert-v01@openssh.com" + string nonce + string curve + string public_key + uint64 serial + uint32 type + string key id + string valid principals + uint64 valid after + uint64 valid before + string critical options + string extensions + string reserved + string signature key + string signature + +ED25519 certificate + + string "ssh-ed25519-cert-v01@openssh.com" + string nonce + string pk + uint64 serial + uint32 type + string key id + string valid principals + uint64 valid after + uint64 valid before + string critical options + string extensions + string reserved + string signature key + string signature + +The nonce field is a CA-provided random bitstring of arbitrary length +(but typically 16 or 32 bytes) included to make attacks that depend on +inducing collisions in the signature hash infeasible. + +e and n are the RSA exponent and public modulus respectively. + +p, q, g, y are the DSA parameters as described in FIPS-186-2. + +curve and public key are respectively the ECDSA "[identifier]" and "Q" +defined in section 3.1 of RFC5656. + +pk is the encoded Ed25519 public key as defined by RFC8032. + +serial is an optional certificate serial number set by the CA to +provide an abbreviated way to refer to certificates from that CA. +If a CA does not wish to number its certificates, it must set this +field to zero. + +type specifies whether this certificate is for identification of a user +or a host using a SSH_CERT_TYPE_... value. + +key id is a free-form text field that is filled in by the CA at the time +of signing; the intention is that the contents of this field are used to +identify the identity principal in log messages. + +"valid principals" is a string containing zero or more principals as +strings packed inside it. These principals list the names for which this +certificate is valid; hostnames for SSH_CERT_TYPE_HOST certificates and +usernames for SSH_CERT_TYPE_USER certificates. As a special case, a +zero-length "valid principals" field means the certificate is valid for +any principal of the specified type. + +"valid after" and "valid before" specify a validity period for the +certificate. Each represents a time in seconds since 1970-01-01 +00:00:00. A certificate is considered valid if: + + valid after <= current time < valid before + +critical options is a set of zero or more key options encoded as +below. All such options are "critical" in the sense that an implementation +must refuse to authorise a key that has an unrecognised option. + +extensions is a set of zero or more optional extensions. These extensions +are not critical, and an implementation that encounters one that it does +not recognise may safely ignore it. + +Generally, critical options are used to control features that restrict +access where extensions are used to enable features that grant access. +This ensures that certificates containing unknown restrictions do not +inadvertently grant access while allowing new protocol features to be +enabled via extensions without breaking certificates' backwards +compatibility. + +The reserved field is currently unused and is ignored in this version of +the protocol. + +The signature key field contains the CA key used to sign the +certificate. The valid key types for CA keys are ssh-rsa, +ssh-dss, ssh-ed25519 and the ECDSA types ecdsa-sha2-nistp256, +ecdsa-sha2-nistp384, ecdsa-sha2-nistp521. "Chained" certificates, where +the signature key type is a certificate type itself are NOT supported. +Note that it is possible for a RSA certificate key to be signed by a +Ed25519 or ECDSA CA key and vice-versa. + +signature is computed over all preceding fields from the initial string +up to, and including the signature key. Signatures are computed and +encoded according to the rules defined for the CA's public key algorithm +(RFC4253 section 6.6 for ssh-rsa and ssh-dss, RFC5656 for the ECDSA +types, and RFC8032 for Ed25519). + +Critical options +---------------- + +The critical options section of the certificate specifies zero or more +options on the certificate's validity. The format of this field +is a sequence of zero or more tuples: + + string name + string data + +Options must be lexically ordered by "name" if they appear in the +sequence. Each named option may only appear once in a certificate. + +The name field identifies the option and the data field encodes +option-specific information (see below). All options are +"critical"; if an implementation does not recognise a option, +then the validating party should refuse to accept the certificate. + +Custom options should append the originating author or organisation's +domain name to the option name, e.g. "my-option@example.com". + +No critical options are defined for host certificates at present. The +supported user certificate options and the contents and structure of +their data fields are: + +Name Format Description +----------------------------------------------------------------------------- +force-command string Specifies a command that is executed + (replacing any the user specified on the + ssh command-line) whenever this key is + used for authentication. + +source-address string Comma-separated list of source addresses + from which this certificate is accepted + for authentication. Addresses are + specified in CIDR format (nn.nn.nn.nn/nn + or hhhh::hhhh/nn). + If this option is not present, then + certificates may be presented from any + source address. + +verify-required empty Flag indicating that signatures made + with this certificate must assert FIDO + user verification (e.g. PIN or + biometric). This option only makes sense + for the U2F/FIDO security key types that + support this feature in their signature + formats. + +Extensions +---------- + +The extensions section of the certificate specifies zero or more +non-critical certificate extensions. The encoding and ordering of +extensions in this field is identical to that of the critical options, +as is the requirement that each name appear only once. + +If an implementation does not recognise an extension, then it should +ignore it. + +Custom options should append the originating author or organisation's +domain name to the option name, e.g. "my-option@example.com". + +No extensions are defined for host certificates at present. The +supported user certificate extensions and the contents and structure of +their data fields are: + +Name Format Description +----------------------------------------------------------------------------- +no-touch-required empty Flag indicating that signatures made + with this certificate need not assert + FIDO user presence. This option only + makes sense for the U2F/FIDO security + key types that support this feature in + their signature formats. + +permit-X11-forwarding empty Flag indicating that X11 forwarding + should be permitted. X11 forwarding will + be refused if this option is absent. + +permit-agent-forwarding empty Flag indicating that agent forwarding + should be allowed. Agent forwarding + must not be permitted unless this + option is present. + +permit-port-forwarding empty Flag indicating that port-forwarding + should be allowed. If this option is + not present, then no port forwarding will + be allowed. + +permit-pty empty Flag indicating that PTY allocation + should be permitted. In the absence of + this option PTY allocation will be + disabled. + +permit-user-rc empty Flag indicating that execution of + ~/.ssh/rc should be permitted. Execution + of this script will not be permitted if + this option is not present. + +$OpenBSD: PROTOCOL.certkeys,v 1.19 2021/06/05 13:47:00 naddy Exp $ diff --git a/PROTOCOL.chacha20poly1305 b/PROTOCOL.chacha20poly1305 new file mode 100644 index 0000000..0bfff28 --- /dev/null +++ b/PROTOCOL.chacha20poly1305 @@ -0,0 +1,107 @@ +This document describes the chacha20-poly1305@openssh.com authenticated +encryption cipher supported by OpenSSH. + +Background +---------- + +ChaCha20 is a stream cipher designed by Daniel Bernstein and described +in [1]. It operates by permuting 128 fixed bits, 128 or 256 bits of key, +a 64 bit nonce and a 64 bit counter into 64 bytes of output. This output +is used as a keystream, with any unused bytes simply discarded. + +Poly1305[2], also by Daniel Bernstein, is a one-time Carter-Wegman MAC +that computes a 128 bit integrity tag given a message and a single-use +256 bit secret key. + +The chacha20-poly1305@openssh.com combines these two primitives into an +authenticated encryption mode. The construction used is based on that +proposed for TLS by Adam Langley in [3], but differs in the layout of +data passed to the MAC and in the addition of encryption of the packet +lengths. + +Negotiation +----------- + +The chacha20-poly1305@openssh.com offers both encryption and +authentication. As such, no separate MAC is required. If the +chacha20-poly1305@openssh.com cipher is selected in key exchange, +the offered MAC algorithms are ignored and no MAC is required to be +negotiated. + +Detailed Construction +--------------------- + +The chacha20-poly1305@openssh.com cipher requires 512 bits of key +material as output from the SSH key exchange. This forms two 256 bit +keys (K_1 and K_2), used by two separate instances of chacha20. +The first 256 bits constitute K_2 and the second 256 bits become +K_1. + +The instance keyed by K_1 is a stream cipher that is used only +to encrypt the 4 byte packet length field. The second instance, +keyed by K_2, is used in conjunction with poly1305 to build an AEAD +(Authenticated Encryption with Associated Data) that is used to encrypt +and authenticate the entire packet. + +Two separate cipher instances are used here so as to keep the packet +lengths confidential but not create an oracle for the packet payload +cipher by decrypting and using the packet length prior to checking +the MAC. By using an independently-keyed cipher instance to encrypt the +length, an active attacker seeking to exploit the packet input handling +as a decryption oracle can learn nothing about the payload contents or +its MAC (assuming key derivation, ChaCha20 and Poly1305 are secure). + +The AEAD is constructed as follows: for each packet, generate a Poly1305 +key by taking the first 256 bits of ChaCha20 stream output generated +using K_2, an IV consisting of the packet sequence number encoded as an +uint64 under the SSH wire encoding rules and a ChaCha20 block counter of +zero. The K_2 ChaCha20 block counter is then set to the little-endian +encoding of 1 (i.e. {1, 0, 0, 0, 0, 0, 0, 0}) and this instance is used +for encryption of the packet payload. + +Packet Handling +--------------- + +When receiving a packet, the length must be decrypted first. When 4 +bytes of ciphertext length have been received, they may be decrypted +using the K_1 key, a nonce consisting of the packet sequence number +encoded as a uint64 under the usual SSH wire encoding and a zero block +counter to obtain the plaintext length. + +Once the entire packet has been received, the MAC MUST be checked +before decryption. A per-packet Poly1305 key is generated as described +above and the MAC tag calculated using Poly1305 with this key over the +ciphertext of the packet length and the payload together. The calculated +MAC is then compared in constant time with the one appended to the +packet and the packet decrypted using ChaCha20 as described above (with +K_2, the packet sequence number as nonce and a starting block counter of +1). + +To send a packet, first encode the 4 byte length and encrypt it using +K_1. Encrypt the packet payload (using K_2) and append it to the +encrypted length. Finally, calculate a MAC tag and append it. + +Rekeying +-------- + +ChaCha20 must never reuse a {key, nonce} for encryption nor may it be +used to encrypt more than 2^70 bytes under the same {key, nonce}. The +SSH Transport protocol (RFC4253) recommends a far more conservative +rekeying every 1GB of data sent or received. If this recommendation +is followed, then chacha20-poly1305@openssh.com requires no special +handling in this area. + +References +---------- + +[1] "ChaCha, a variant of Salsa20", Daniel Bernstein + http://cr.yp.to/chacha/chacha-20080128.pdf + +[2] "The Poly1305-AES message-authentication code", Daniel Bernstein + http://cr.yp.to/mac/poly1305-20050329.pdf + +[3] "ChaCha20 and Poly1305 based Cipher Suites for TLS", Adam Langley + http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-03 + +$OpenBSD: PROTOCOL.chacha20poly1305,v 1.5 2020/02/21 00:04:43 dtucker Exp $ + diff --git a/PROTOCOL.key b/PROTOCOL.key new file mode 100644 index 0000000..cbf7a70 --- /dev/null +++ b/PROTOCOL.key @@ -0,0 +1,71 @@ +This document describes the private key format for OpenSSH. + +1. Overall format + +The key consists of a header, a list of public keys, and +an encrypted list of matching private keys. + +#define AUTH_MAGIC "openssh-key-v1" + + byte[] AUTH_MAGIC + string ciphername + string kdfname + string kdfoptions + uint32 number of keys N + string publickey1 + string publickey2 + ... + string publickeyN + string encrypted, padded list of private keys + +2. KDF options for kdfname "bcrypt" + +The options: + + string salt + uint32 rounds + +are concatenated and represented as a string. + +3. Unencrypted list of N private keys + +The list of privatekey/comment pairs is padded with the +bytes 1, 2, 3, ... until the total length is a multiple +of the cipher block size. + + uint32 checkint + uint32 checkint + byte[] privatekey1 + string comment1 + byte[] privatekey2 + string comment2 + ... + string privatekeyN + string commentN + byte 1 + byte 2 + byte 3 + ... + byte padlen % 255 + +where each private key is encoded using the same rules as used for +SSH agent. + +Before the key is encrypted, a random integer is assigned +to both checkint fields so successful decryption can be +quickly checked by verifying that both checkint fields +hold the same value. + +4. Encryption + +The KDF is used to derive a key, IV (and other values required by +the cipher) from the passphrase. These values are then used to +encrypt the unencrypted list of private keys. + +5. No encryption + +For unencrypted keys the cipher "none" and the KDF "none" +are used with empty passphrases. The options if the KDF "none" +are the empty string. + +$OpenBSD: PROTOCOL.key,v 1.3 2022/07/01 04:45:50 djm Exp $ diff --git a/PROTOCOL.krl b/PROTOCOL.krl new file mode 100644 index 0000000..115f80e --- /dev/null +++ b/PROTOCOL.krl @@ -0,0 +1,171 @@ +This describes the key/certificate revocation list format for OpenSSH. + +1. Overall format + +The KRL consists of a header and zero or more sections. The header is: + +#define KRL_MAGIC 0x5353484b524c0a00ULL /* "SSHKRL\n\0" */ +#define KRL_FORMAT_VERSION 1 + + uint64 KRL_MAGIC + uint32 KRL_FORMAT_VERSION + uint64 krl_version + uint64 generated_date + uint64 flags + string reserved + string comment + +Where "krl_version" is a version number that increases each time the KRL +is modified, "generated_date" is the time in seconds since 1970-01-01 +00:00:00 UTC that the KRL was generated, "comment" is an optional comment +and "reserved" an extension field whose contents are currently ignored. +No "flags" are currently defined. + +Following the header are zero or more sections, each consisting of: + + byte section_type + string section_data + +Where "section_type" indicates the type of the "section_data". An exception +to this is the KRL_SECTION_SIGNATURE section, that has a slightly different +format (see below). + +The available section types are: + +#define KRL_SECTION_CERTIFICATES 1 +#define KRL_SECTION_EXPLICIT_KEY 2 +#define KRL_SECTION_FINGERPRINT_SHA1 3 +#define KRL_SECTION_SIGNATURE 4 +#define KRL_SECTION_FINGERPRINT_SHA256 5 + +2. Certificate section + +These sections use type KRL_SECTION_CERTIFICATES to revoke certificates by +serial number or key ID. The consist of the CA key that issued the +certificates to be revoked and a reserved field whose contents is currently +ignored. + + string ca_key + string reserved + +Where "ca_key" is the standard SSH wire serialisation of the CA's +public key. Alternately, "ca_key" may be an empty string to indicate +the certificate section applies to all CAs (this is most useful when +revoking key IDs). + +Followed by one or more sections: + + byte cert_section_type + string cert_section_data + +The certificate section types are: + +#define KRL_SECTION_CERT_SERIAL_LIST 0x20 +#define KRL_SECTION_CERT_SERIAL_RANGE 0x21 +#define KRL_SECTION_CERT_SERIAL_BITMAP 0x22 +#define KRL_SECTION_CERT_KEY_ID 0x23 + +2.1 Certificate serial list section + +This section is identified as KRL_SECTION_CERT_SERIAL_LIST. It revokes +certificates by listing their serial numbers. The cert_section_data in this +case contains: + + uint64 revoked_cert_serial + uint64 ... + +This section may appear multiple times. + +2.2. Certificate serial range section + +These sections use type KRL_SECTION_CERT_SERIAL_RANGE and hold +a range of serial numbers of certificates: + + uint64 serial_min + uint64 serial_max + +All certificates in the range serial_min <= serial <= serial_max are +revoked. + +This section may appear multiple times. + +2.3. Certificate serial bitmap section + +Bitmap sections use type KRL_SECTION_CERT_SERIAL_BITMAP and revoke keys +by listing their serial number in a bitmap. + + uint64 serial_offset + mpint revoked_keys_bitmap + +A bit set at index N in the bitmap corresponds to revocation of a keys with +serial number (serial_offset + N). + +This section may appear multiple times. + +2.4. Revoked key ID sections + +KRL_SECTION_CERT_KEY_ID sections revoke particular certificate "key +ID" strings. This may be useful in revoking all certificates +associated with a particular identity, e.g. a host or a user. + + string key_id[0] + ... + +This section must contain at least one "key_id". This section may appear +multiple times. + +3. Explicit key sections + +These sections, identified as KRL_SECTION_EXPLICIT_KEY, revoke keys +(not certificates). They are less space efficient than serial numbers, +but are able to revoke plain keys. + + string public_key_blob[0] + .... + +This section must contain at least one "public_key_blob". The blob +must be a raw key (i.e. not a certificate). + +This section may appear multiple times. + +4. SHA1/SHA256 fingerprint sections + +These sections, identified as KRL_SECTION_FINGERPRINT_SHA1 and +KRL_SECTION_FINGERPRINT_SHA256, revoke plain keys (i.e. not +certificates) by listing their hashes: + + string public_key_hash[0] + .... + +This section must contain at least one "public_key_hash". The hash blob +is obtained by taking the SHA1 or SHA256 hash of the public key blob. +Hashes in this section must appear in numeric order, treating each hash +as a big-endian integer. + +This section may appear multiple times. + +5. KRL signature sections + +The KRL_SECTION_SIGNATURE section serves a different purpose to the +preceding ones: to provide cryptographic authentication of a KRL that +is retrieved over a channel that does not provide integrity protection. +Its format is slightly different to the previously-described sections: +in order to simplify the signature generation, it includes as a "body" +two string components instead of one. + + byte KRL_SECTION_SIGNATURE + string signature_key + string signature + +The signature is calculated over the entire KRL from the KRL_MAGIC +to this subsection's "signature_key", including both and using the +signature generation rules appropriate for the type of "signature_key". + +This section must appear last in the KRL. If multiple signature sections +appear, they must appear consecutively at the end of the KRL file. + +Implementations that retrieve KRLs over untrusted channels must verify +signatures. Signature sections are optional for KRLs distributed by +trusted means. + +$OpenBSD: PROTOCOL.krl,v 1.5 2018/09/12 01:21:34 djm Exp $ diff --git a/PROTOCOL.mux b/PROTOCOL.mux new file mode 100644 index 0000000..5a3dd5f --- /dev/null +++ b/PROTOCOL.mux @@ -0,0 +1,298 @@ +This document describes the multiplexing protocol used by ssh(1)'s +ControlMaster connection-sharing. + +Multiplexing starts with a ssh(1) configured to act as a multiplexing +master. This will cause ssh(1) to listen on a Unix domain socket for +requests from clients. Clients communicate over this socket using a +simple packetised protocol, where each message is proceeded with +a length and message type in SSH uint32 wire format: + + uint32 packet length + uint32 packet type + ... packet body + +Most messages from the client to the server contain a "request id" +field. This field is returned in replies as "client request id" to +facilitate matching of responses to requests. + +Many multiplexing (mux) client requests yield immediate responses from +the mux process; requesting a forwarding, performing an alive check or +requesting the master terminate itself fall in to this category. + +The most common use of multiplexing however is to maintain multiple +concurrent sessions. These are supported via two separate modes: + +"Passenger" clients start by requesting a new session with a +MUX_C_NEW_SESSION message and passing stdio file descriptors over the +Unix domain control socket. The passenger client then waits until it is +signaled or the mux server closes the session. This mode is so named as +the client waits around while the mux server does all the driving. + +Stdio forwarding (requested using MUX_C_NEW_STDIO_FWD) is another +example of passenger mode; the client passes the stdio file descriptors +and passively waits for something to happen. + +"Proxy" clients, requested using MUX_C_PROXY, work quite differently. In +this mode, the mux client/server connection socket will stop speaking +the multiplexing protocol and start proxying SSH connection protocol +messages between the client and server. The client therefore must +speak a significant subset of the SSH protocol, but in return is able +to access basically the full suite of connection protocol features. +Moreover, as no file descriptor passing is required, the connection +supporting a proxy client may itself be forwarded or relayed to another +host if necessary. + +1. Connection setup + +When a multiplexing connection is made to a ssh(1) operating as a +ControlMaster from a client ssh(1), the first action of each is send +a hello messages to its peer: + + uint32 MUX_MSG_HELLO + uint32 protocol version + string extension name [optional] + string extension value [optional] + ... + +The current version of the mux protocol is 4. A client should refuse +to connect to a master that speaks an unsupported protocol version. + +Following the version identifier are zero or more extensions represented +as a name/value pair. No extensions are currently defined. + +2. Opening a passenger mode session + +To open a new multiplexed session in passenger mode, a client sends the +following request: + + uint32 MUX_C_NEW_SESSION + uint32 request id + string reserved + bool want tty flag + bool want X11 forwarding flag + bool want agent flag + bool subsystem flag + uint32 escape char + string terminal type + string command + string environment string 0 [optional] + ... + +To disable the use of an escape character, "escape char" may be set +to 0xffffffff. "terminal type" is generally set to the value of +$TERM. zero or more environment strings may follow the command. + +The client then sends its standard input, output and error file +descriptors (in that order) using Unix domain socket control messages. + +The contents of "reserved" are currently ignored. + +If successful, the server will reply with MUX_S_SESSION_OPENED + + uint32 MUX_S_SESSION_OPENED + uint32 client request id + uint32 session id + +Otherwise it will reply with an error: MUX_S_PERMISSION_DENIED or +MUX_S_FAILURE. + +Once the server has received the fds, it will respond with MUX_S_OK +indicating that the session is up. The client now waits for the +session to end. When it does, the server will send an exit status +message: + + uint32 MUX_S_EXIT_MESSAGE + uint32 session id + uint32 exit value + +The client should exit with this value to mimic the behaviour of a +non-multiplexed ssh(1) connection. Two additional cases that the +client must cope with are it receiving a signal itself and the +server disconnecting without sending an exit message. + +A master may also send a MUX_S_TTY_ALLOC_FAIL before MUX_S_EXIT_MESSAGE +if remote TTY allocation was unsuccessful. The client may use this to +return its local tty to "cooked" mode. + + uint32 MUX_S_TTY_ALLOC_FAIL + uint32 session id + +3. Requesting passenger-mode stdio forwarding + +A client may request the master to establish a stdio forwarding: + + uint32 MUX_C_NEW_STDIO_FWD + uint32 request id + string reserved + string connect host + string connect port + +The client then sends its standard input and output file descriptors +(in that order) using Unix domain socket control messages. + +The contents of "reserved" are currently ignored. + +A server may reply with a MUX_S_SESSION_OPENED, a MUX_S_PERMISSION_DENIED +or a MUX_S_FAILURE. + +4. Health checks + +The client may request a health check/PID report from a server: + + uint32 MUX_C_ALIVE_CHECK + uint32 request id + +The server replies with: + + uint32 MUX_S_ALIVE + uint32 client request id + uint32 server pid + +5. Remotely terminating a master + +A client may request that a master terminate immediately: + + uint32 MUX_C_TERMINATE + uint32 request id + +The server will reply with one of MUX_S_OK or MUX_S_PERMISSION_DENIED. + +6. Requesting establishment of port forwards + +A client may request the master to establish a port forward: + + uint32 MUX_C_OPEN_FWD + uint32 request id + uint32 forwarding type + string listen host + uint32 listen port + string connect host + uint32 connect port + +forwarding type may be MUX_FWD_LOCAL, MUX_FWD_REMOTE, MUX_FWD_DYNAMIC. + +If listen port is (unsigned int) -2, then the listen host is treated as +a unix socket path name. + +If connect port is (unsigned int) -2, then the connect host is treated +as a unix socket path name. + +A server may reply with a MUX_S_OK, a MUX_S_REMOTE_PORT, a +MUX_S_PERMISSION_DENIED or a MUX_S_FAILURE. + +For dynamically allocated listen port the server replies with + + uint32 MUX_S_REMOTE_PORT + uint32 client request id + uint32 allocated remote listen port + +7. Requesting closure of port forwards + +Note: currently unimplemented (server will always reply with MUX_S_FAILURE). + +A client may request the master to close a port forward: + + uint32 MUX_C_CLOSE_FWD + uint32 request id + uint32 forwarding type + string listen host + uint32 listen port + string connect host + uint32 connect port + +A server may reply with a MUX_S_OK, a MUX_S_PERMISSION_DENIED or a +MUX_S_FAILURE. + +8. Requesting shutdown of mux listener + +A client may request the master to stop accepting new multiplexing requests +and remove its listener socket. + + uint32 MUX_C_STOP_LISTENING + uint32 request id + +A server may reply with a MUX_S_OK, a MUX_S_PERMISSION_DENIED or a +MUX_S_FAILURE. + +9. Requesting proxy mode + +A client may request that the control connection be placed in proxy +mode: + + uint32 MUX_C_PROXY + uint32 request id + +When a mux master receives this message, it will reply with a +confirmation: + + uint32 MUX_S_PROXY + uint32 request id + +And go into proxy mode. All subsequent data over the connection will +be formatted as unencrypted, unpadded, SSH transport messages: + + uint32 packet length + byte 0 (padding length) + byte packet type + byte[packet length - 2] ... + +The mux master will accept most connection messages and global requests, +and will translate channel identifiers to ensure that the proxy client has +globally unique channel numbers (i.e. a proxy client need not worry about +collisions with other clients). + +10. Status messages + +The MUX_S_OK message is empty: + + uint32 MUX_S_OK + uint32 client request id + +The MUX_S_PERMISSION_DENIED and MUX_S_FAILURE include a reason: + + uint32 MUX_S_PERMISSION_DENIED + uint32 client request id + string reason + + uint32 MUX_S_FAILURE + uint32 client request id + string reason + +11. Protocol numbers + +#define MUX_MSG_HELLO 0x00000001 +#define MUX_C_NEW_SESSION 0x10000002 +#define MUX_C_ALIVE_CHECK 0x10000004 +#define MUX_C_TERMINATE 0x10000005 +#define MUX_C_OPEN_FWD 0x10000006 +#define MUX_C_CLOSE_FWD 0x10000007 +#define MUX_C_NEW_STDIO_FWD 0x10000008 +#define MUX_C_STOP_LISTENING 0x10000009 +#define MUX_S_OK 0x80000001 +#define MUX_S_PERMISSION_DENIED 0x80000002 +#define MUX_S_FAILURE 0x80000003 +#define MUX_S_EXIT_MESSAGE 0x80000004 +#define MUX_S_ALIVE 0x80000005 +#define MUX_S_SESSION_OPENED 0x80000006 +#define MUX_S_REMOTE_PORT 0x80000007 +#define MUX_S_TTY_ALLOC_FAIL 0x80000008 + +#define MUX_FWD_LOCAL 1 +#define MUX_FWD_REMOTE 2 +#define MUX_FWD_DYNAMIC 3 + +XXX TODO +XXX extended status (e.g. report open channels / forwards) +XXX lock (maybe) +XXX watch in/out traffic (pre/post crypto) +XXX inject packet (what about replies) +XXX server->client error/warning notifications +XXX send signals via mux +XXX ^Z support in passengers +XXX extensions for multi-agent +XXX extensions for multi-X11 +XXX session inspection via master +XXX signals via mux request +XXX list active connections via mux + +$OpenBSD: PROTOCOL.mux,v 1.13 2022/01/01 01:55:30 jsg Exp $ diff --git a/PROTOCOL.sshsig b/PROTOCOL.sshsig new file mode 100644 index 0000000..78457dd --- /dev/null +++ b/PROTOCOL.sshsig @@ -0,0 +1,100 @@ +This document describes a lightweight SSH Signature format +that is compatible with SSH keys and wire formats. + +At present, only detached and armored signatures are supported. + +1. Armored format + +The Armored SSH signatures consist of a header, a base64 +encoded blob, and a footer. + +The header is the string "-----BEGIN SSH SIGNATURE-----" +followed by a newline. The footer is the string +"-----END SSH SIGNATURE-----" immediately after a newline. + +The header MUST be present at the start of every signature. +Files containing the signature MUST start with the header. +Likewise, the footer MUST be present at the end of every +signature. + +The base64 encoded blob SHOULD be broken up by newlines +every 76 characters. + +Example: + +-----BEGIN SSH SIGNATURE----- +U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgJKxoLBJBivUPNTUJUSslQTt2hD +jozKvHarKeN8uYFqgAAAADZm9vAAAAAAAAAFMAAAALc3NoLWVkMjU1MTkAAABAKNC4IEbt +Tq0Fb56xhtuE1/lK9H9RZJfON4o6hE9R4ZGFX98gy0+fFJ/1d2/RxnZky0Y7GojwrZkrHT +FgCqVWAQ== +-----END SSH SIGNATURE----- + +2. Blob format + +#define MAGIC_PREAMBLE "SSHSIG" +#define SIG_VERSION 0x01 + + byte[6] MAGIC_PREAMBLE + uint32 SIG_VERSION + string publickey + string namespace + string reserved + string hash_algorithm + string signature + +The publickey field MUST contain the serialisation of the +public key used to make the signature using the usual SSH +encoding rules, i.e RFC4253, RFC5656, +draft-ietf-curdle-ssh-ed25519-ed448, etc. + +Verifiers MUST reject signatures with versions greater than those +they support. + +The purpose of the namespace value is to specify a unambiguous +interpretation domain for the signature, e.g. file signing. +This prevents cross-protocol attacks caused by signatures +intended for one intended domain being accepted in another. +The namespace value MUST NOT be the empty string. + +The reserved value is present to encode future information +(e.g. tags) into the signature. Implementations should ignore +the reserved field if it is not empty. + +Data to be signed is first hashed with the specified hash_algorithm. +This is done to limit the amount of data presented to the signature +operation, which may be of concern if the signing key is held in limited +or slow hardware or on a remote ssh-agent. The supported hash algorithms +are "sha256" and "sha512". + +The signature itself is made using the SSH signature algorithm and +encoding rules for the chosen key type. For RSA signatures, the +signature algorithm must be "rsa-sha2-512" or "rsa-sha2-256" (i.e. +not the legacy RSA-SHA1 "ssh-rsa"). + +This blob is encoded as a string using the RFC4253 encoding +rules and base64 encoded to form the middle part of the +armored signature. + + +3. Signed Data, of which the signature goes into the blob above + +#define MAGIC_PREAMBLE "SSHSIG" + + byte[6] MAGIC_PREAMBLE + string namespace + string reserved + string hash_algorithm + string H(message) + +The preamble is the six-byte sequence "SSHSIG". It is included to +ensure that manual signatures can never be confused with any message +signed during SSH user or host authentication. + +The reserved value is present to encode future information +(e.g. tags) into the signature. Implementations should ignore +the reserved field if it is not empty. + +The data is concatenated and passed to the SSH signing +function. + +$OpenBSD: PROTOCOL.sshsig,v 1.4 2020/08/31 00:17:41 djm Exp $ diff --git a/PROTOCOL.u2f b/PROTOCOL.u2f new file mode 100644 index 0000000..f8ca56b --- /dev/null +++ b/PROTOCOL.u2f @@ -0,0 +1,309 @@ +This document describes OpenSSH's support for U2F/FIDO security keys. + +Background +---------- + +U2F is an open standard for two-factor authentication hardware, widely +used for user authentication to websites. U2F tokens are ubiquitous, +available from a number of manufacturers and are currently by far the +cheapest way for users to achieve hardware-backed credential storage. + +The U2F protocol however cannot be trivially used as an SSH protocol key +type as both the inputs to the signature operation and the resultant +signature differ from those specified for SSH. For similar reasons, +integration of U2F devices cannot be achieved via the PKCS#11 API. + +U2F also offers a number of features that are attractive in the context +of SSH authentication. They can be configured to require indication +of "user presence" for each signature operation (typically achieved +by requiring the user touch the key). They also offer an attestation +mechanism at key enrollment time that can be used to prove that a +given key is backed by hardware. Finally the signature format includes +a monotonic signature counter that can be used (at scale) to detect +concurrent use of a private key, should it be extracted from hardware. + +U2F private keys are generated through an enrollment operation, +which takes an application ID - a URL-like string, typically "ssh:" +in this case, but a HTTP origin for the case of web authentication, +and a challenge string (typically randomly generated). The enrollment +operation returns a public key, a key handle that must be used to invoke +the hardware-backed private key, some flags and signed attestation +information that may be used to verify that a private key is hosted on a +particular hardware instance. + +It is common for U2F hardware to derive private keys from the key handle +in conjunction with a small per-device secret that is unique to the +hardware, thus requiring little on-device storage for an effectively +unlimited number of supported keys. This drives the requirement that +the key handle be supplied for each signature operation. U2F tokens +primarily use ECDSA signatures in the NIST-P256 field, though the FIDO2 +standard specifies additional key types, including one based on Ed25519. + +Use of U2F security keys does not automatically imply multi-factor +authentication. From sshd's perspective, a security key constitutes a +single factor of authentication, even if protected by a PIN or biometric +authentication. To enable multi-factor authentication in ssh, please +refer to the AuthenticationMethods option in sshd_config(5). + + +SSH U2F Key formats +------------------- + +OpenSSH integrates U2F as new key and corresponding certificate types: + + sk-ecdsa-sha2-nistp256@openssh.com + sk-ecdsa-sha2-nistp256-cert-v01@openssh.com + sk-ssh-ed25519@openssh.com + sk-ssh-ed25519-cert-v01@openssh.com + +While each uses ecdsa-sha256-nistp256 as the underlying signature primitive, +keys require extra information in the public and private keys, and in +the signature object itself. As such they cannot be made compatible with +the existing ecdsa-sha2-nistp* key types. + +The format of a sk-ecdsa-sha2-nistp256@openssh.com public key is: + + string "sk-ecdsa-sha2-nistp256@openssh.com" + string curve name + ec_point Q + string application (user-specified, but typically "ssh:") + +The corresponding private key contains: + + string "sk-ecdsa-sha2-nistp256@openssh.com" + string curve name + ec_point Q + string application (user-specified, but typically "ssh:") + uint8 flags + string key_handle + string reserved + +The format of a sk-ssh-ed25519@openssh.com public key is: + + string "sk-ssh-ed25519@openssh.com" + string public key + string application (user-specified, but typically "ssh:") + +With a private half consisting of: + + string "sk-ssh-ed25519@openssh.com" + string public key + string application (user-specified, but typically "ssh:") + uint8 flags + string key_handle + string reserved + +The certificate form for SSH U2F keys appends the usual certificate +information to the public key: + + string "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com" + string nonce + string curve name + ec_point Q + string application + uint64 serial + uint32 type + string key id + string valid principals + uint64 valid after + uint64 valid before + string critical options + string extensions + string reserved + string signature key + string signature + +and for security key ed25519 certificates: + + string "sk-ssh-ed25519-cert-v01@openssh.com" + string nonce + string public key + string application + uint64 serial + uint32 type + string key id + string valid principals + uint64 valid after + uint64 valid before + string critical options + string extensions + string reserved + string signature key + string signature + +Both security key certificates use the following encoding for private keys: + + string type (e.g. "sk-ssh-ed25519-cert-v01@openssh.com") + string pubkey (the above key/cert structure) + string application + uint8 flags + string key_handle + string reserved + +During key generation, the hardware also returns attestation information +that may be used to cryptographically prove that a given key is +hardware-backed. Unfortunately, the protocol required for this proof is +not privacy-preserving and may be used to identify U2F tokens with at +least manufacturer and batch number granularity. For this reason, we +choose not to include this information in the public key or save it by +default. + +Attestation information is useful for out-of-band key and certificate +registration workflows, e.g. proving to a CA that a key is backed +by trusted hardware before it will issue a certificate. To support this +case, OpenSSH optionally allows retaining the attestation information +at the time of key generation. It will take the following format: + + string "ssh-sk-attest-v01" + string attestation certificate + string enrollment signature + string authenticator data (CBOR encoded) + uint32 reserved flags + string reserved string + +A previous version of this format, emitted prior to OpenSSH 8.4 omitted +the authenticator data. + + string "ssh-sk-attest-v00" + string attestation certificate + string enrollment signature + uint32 reserved flags + string reserved string + +OpenSSH treats the attestation certificate and enrollment signatures as +opaque objects and does no interpretation of them itself. + +SSH U2F signatures +------------------ + +In addition to the message to be signed, the U2F signature operation +requires the key handle and a few additional parameters. The signature +is signed over a blob that consists of: + + byte[32] SHA256(application) + byte flags (including "user present", extensions present) + uint32 counter + byte[] extensions + byte[32] SHA256(message) + +No extensions are yet defined for SSH use. If any are defined in the future, +it will be possible to infer their presence from the contents of the "flags" +value. + +The signature returned from U2F hardware takes the following format: + + byte flags (including "user present") + uint32 counter + byte[] ecdsa_signature (in X9.62 format). + +For use in the SSH protocol, we wish to avoid server-side parsing of ASN.1 +format data in the pre-authentication attack surface. Therefore, the +signature format used on the wire in SSH2_USERAUTH_REQUEST packets will +be reformatted to better match the existing signature encoding: + + string "sk-ecdsa-sha2-nistp256@openssh.com" + string ecdsa_signature + byte flags + uint32 counter + +Where the "ecdsa_signature" field follows the RFC5656 ECDSA signature +encoding: + + mpint r + mpint s + +For Ed25519 keys the signature is encoded as: + + string "sk-ssh-ed25519@openssh.com" + string signature + byte flags + uint32 counter + +webauthn signatures +------------------- + +The W3C/FIDO webauthn[1] standard defines a mechanism for a web browser to +interact with FIDO authentication tokens. This standard builds upon the +FIDO standards, but requires different signature contents to raw FIDO +messages. OpenSSH supports ECDSA/p256 webauthn signatures through the +"webauthn-sk-ecdsa-sha2-nistp256@openssh.com" signature algorithm. + +The wire encoding for a webauthn-sk-ecdsa-sha2-nistp256@openssh.com +signature is similar to the sk-ecdsa-sha2-nistp256@openssh.com format: + + string "webauthn-sk-ecdsa-sha2-nistp256@openssh.com" + string ecdsa_signature + byte flags + uint32 counter + string origin + string clientData + string extensions + +Where "origin" is the HTTP origin making the signature, "clientData" is +the JSON-like structure signed by the browser and "extensions" are any +extensions used in making the signature. + +[1] https://www.w3.org/TR/webauthn-2/ + +ssh-agent protocol extensions +----------------------------- + +ssh-agent requires a protocol extension to support U2F keys. At +present the closest analogue to Security Keys in ssh-agent are PKCS#11 +tokens, insofar as they require a middleware library to communicate with +the device that holds the keys. Unfortunately, the protocol message used +to add PKCS#11 keys to ssh-agent does not include any way to send the +key handle to the agent as U2F keys require. + +To avoid this, without having to add wholly new messages to the agent +protocol, we will use the existing SSH2_AGENTC_ADD_ID_CONSTRAINED message +with a new key constraint extension to encode a path to the middleware +library for the key. The format of this constraint extension would be: + + byte SSH_AGENT_CONSTRAIN_EXTENSION + string sk-provider@openssh.com + string middleware path + +This constraint-based approach does not present any compatibility +problems. + +OpenSSH integration +------------------- + +U2F tokens may be attached via a number of means, including USB and NFC. +The USB interface is standardised around a HID protocol, but we want to +be able to support other transports as well as dummy implementations for +regress testing. For this reason, OpenSSH shall support a dynamically- +loaded middleware libraries to communicate with security keys, but offer +support for the common case of USB HID security keys internally. + +The middleware library need only expose a handful of functions and +numbers listed in sk-api.h. Included in the defined numbers is a +SSH_SK_VERSION_MAJOR that should be incremented for each incompatible +API change. + +miscellaneous options may be passed to the middleware as a NULL- +terminated array of pointers to struct sk_option. The middleware may +ignore unsupported or unknown options unless the "required" flag is set, +in which case it should return failure if an unsupported option is +requested. + +At present the following options names are supported: + + "device" + + Specifies a specific FIDO device on which to perform the + operation. The value in this field is interpreted by the + middleware but it would be typical to specify a path to + a /dev node for the device in question. + + "user" + + Specifies the FIDO2 username used when enrolling a key, + overriding OpenSSH's default of using an all-zero username. + +In OpenSSH, the middleware will be invoked by using a similar mechanism to +ssh-pkcs11-helper to provide address-space containment of the +middleware from ssh-agent. + +$OpenBSD: PROTOCOL.u2f,v 1.26 2020/09/09 03:08:01 djm Exp $ |