aboutsummaryrefslogtreecommitdiff
path: root/spec/ssh-protocols.md
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ssh-protocols.md')
-rw-r--r--spec/ssh-protocols.md298
1 files changed, 298 insertions, 0 deletions
diff --git a/spec/ssh-protocols.md b/spec/ssh-protocols.md
new file mode 100644
index 0000000..bcc0a3a
--- /dev/null
+++ b/spec/ssh-protocols.md
@@ -0,0 +1,298 @@
+# Tor Project SSH protocol extensions
+
+The
+[SSH protocol](https://datatracker.ietf.org/doc/html/rfc4251)
+provides various extension facilities.
+
+The Tor Project has defined some extensions,
+using the
+[domain-name-based extension facility](https://datatracker.ietf.org/doc/html/rfc4250#section-4.6.1).
+The Tor Project uses names ending `@spec.torproject.org`.
+
+| Id(s) | Namespace | Summary | Specification<br>link (retrieved at) |
+|----------|--------------|----------|-------------------------------------|
+| **`ed25519-expaneded@`** | [Public key algorithm](https://datatracker.ietf.org/doc/html/rfc4250#section-4.11.3) (in SSH/OpenSSH key file) | Expanded ed25519 private key | [Arti keystore types]
+| **`x25519@`** | [Public key algorithm](https://datatracker.ietf.org/doc/html/rfc4250#section-4.11.3) (in SSH/OpenSSH key file) | X25519 keys | [Arti keystore types] |
+
+## Registration process
+
+New entries may be added to this table
+after peer review by the Tor Project developers,
+via
+[gitlab](https://gitlab.torproject.org/tpo/core/torspec)
+merge request.
+
+The specification links may be to external documents,
+not managed as part of the Tor Specifications.
+Or, they may be links to specific sections of the Tor Specifications,
+or to Proposals.
+External links should be dated, for ease of future reference.
+
+Ideally, before a protocol is deployed,
+its specification should be transferred to the Tor Specifications
+(and the link in the table adjusted).
+
+## Interpretation
+
+This section uses
+the notation and conventions from
+[`PROTOCOL.key`](https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.key?annotate=HEAD))
+and
+SSH including [RFC4251 s5](https://datatracker.ietf.org/doc/html/rfc4251#section-5)),
+not those from the rest of the Tor Specifications.
+
+### Interpreting the table
+
+For example, the row for `x25519@` indicates that:
+
+ * The Tor Project has assigned `x25519@spec.torproject.org`
+ * In the namespace of public key algorithms -
+ see [RFC4250 table 4.11.3](https://datatracker.ietf.org/doc/html/rfc4250#section-4.11.3),
+ but only when found within an SSH/OpenSSH format key file.
+ * The meaning of this name is summarised as "X25519 private key"
+ * The full details can be found at the linked text,
+ which is part of the Arti keystore section, below.
+
+The registered names resemble email addresses,
+but they are **not email addresses**
+and mail to them will not be delivered.
+
+For further information, consult the linked specifications.
+
+## SSH key types for the Arti keystore
+
+[Arti keystore types]: #ssh-key-types-for-the-arti-keystore
+
+The
+[Arti keystore](https://tpo.pages.torproject.net/core/doc/rust/tor_keymgr/index.html)
+stores private keys
+in OpenSSH key format
+(and, sometimes, public keys, in SSH format).
+But it needs to store some key types that are
+not used in the SSH protocols.
+So the following key types are defined.
+
+These are in the namespace of Public Key Algorithms
+([RFC4250 4.11.3](https://datatracker.ietf.org/doc/html/rfc4250#section-4.11.3))
+but they are only meaningful in
+OpenSSH format private key files
+([OpenSSH `PROTOCOL.key` document](https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.key?annotate=HEAD))
+and
+SSH public key files
+([RFC4716 3.4](https://datatracker.ietf.org/doc/html/rfc4716#section-3.4)).
+
+In each case we specify/reference
+ * the name of the "public key algorithm" (RFC4250 4.11.3),
+ * the underlying cryptographic algorithm(s),
+ * the public key data
+ ("key/certificate data" in
+ [RFC4253 6.6](https://datatracker.ietf.org/doc/html/rfc4253#section-6.6)),
+ see [Encoding of the public key data](#encoding-of-the-public-key-data)
+ * the private key data
+ (see [Encoding of the private key data](#encoding-of-the-private-key-data))
+
+### Encoding of the public key data
+
+OpenSSH `PROTOCOL.key` does not clearly state
+the contents of the `publickey1`/`publickey2`/`publickeyN` fields
+in the outer (unencrypted) section (`PROTOCOL.key` s1),
+so we state it here.
+
+Each `publickey` consists of the encoded public key
+as per
+[RFC4253 6.6](https://datatracker.ietf.org/doc/html/rfc4253#section-6.6)
+(under "Certificates and public keys are encoded as follows").
+
+So the overall format of this part of the file is:
+
+```
+ uint32 number of keys, N
+ string publickey1, where the contained binary data is:
+ string public key algorithm name (RFC4250 table 4.11.3)
+ byte[] public key data (algorithm-specific)
+ ... keys 2 to N-1 inclusive, each as for publickey1 ...
+ string publickeyN (as for publickey1)
+```
+
+### Encoding of the private key data
+
+OpenSSH `PROTOCOL.key` defines
+the representation of the private key data as, simply:
+"using the same rules as used for SSH agent".
+However,
+no specific section is referred to;
+the SSH agent protocol is only available as
+an Internet Draft
+[draft-miller-ssh-agent-04](https://datatracker.ietf.org/doc/html/draft-miller-ssh-agent-04);
+and, the actual encoding used by OpenSSH is hard to relate
+to that document.
+So we document our understanding here.
+
+The contents of each `privatekey1`/`privatekey2`/`privatekeyN` is:
+
+```
+ string public key algorithm name (RFC4250 table 4.11.3)
+ byte[] public key data (algorithm-specific)
+ byte[] private key data (algorithm-specific)
+```
+
+> Note that this depends on the reader knowing the public key algorithm.
+> The public key data must be self-delimiting,
+> since the file format doesn't provide a separate length field.
+> Although here we discuss only algorithms whose
+> public key data, and private key data,
+> are each a single `string`, that is not always the case:
+> for example,
+> the `ssh-rsa` algorithm's key data formats are sequences of `mpint`s
+> without any surrounding overall length.
+>
+> Note also that the encrypted section does not separately state
+> the number of keys or their total length.
+> The reader must keep reading until it encounters either the end,
+> or something that looks like padding (starting with a byte 0x01).
+
+### `x25519@spec.torproject.org`
+
+These refer to keys for
+X25519,
+ie, Diffie-Hellman on
+Curve25519,
+as per
+[RFC7748 6.1](https://datatracker.ietf.org/doc/html/rfc7748#section-6.1).
+and
+[s5](https://datatracker.ietf.org/doc/html/rfc7748#section-5).
+
+The public key data is:
+```
+ string wrapper for the following fixed-length data:
+ byte[32] the u-coordinate encoded as u[] from RFC7748 s5
+```
+
+The private key data is:
+```
+ string wrapper for the following fixed-length data:
+ byte[32] the scalar k encoded according to RFC7748 s5
+```
+
+k MUST be stored as the true scalar value.
+So if the private key was generated from 32 random bytes
+according to the procedure described in RFC7748 s5
+"in order to decode 32 random bytes as an integer scalar".
+the value stored MUST be the "clamped" form:
+that is, the value
+*after* the transformation.
+If a stored value is a byte string which doesn't represent
+a valid scalar according to RFC7748 s5
+(i.e. an "unclamped" value)
+it SHOULD be rejected;
+if it is not rejected,
+it MUST NOT be used unchanged, but MUST instead be clamped.
+
+Keys whose `string` wrapper is not of the expected length MUST be rejected.
+
+> <span id="useless-string">The
+> `string` wrapper is useless,
+> but the same wrapper approach is used in official SSH for
+> ed25519 public keys ([RFC8709
+> s4](https://datatracker.ietf.org/doc/html/rfc8709#name-public-key-format)).
+> and for ed25519 private keys in the SSH agent protocol
+> ([draft-miller-ssh-agent-04 4.2.3](https://datatracker.ietf.org/doc/html/draft-miller-ssh-agent-04#section-4.2.3)).
+> We do the same here for consistency
+> (and implementation convenience).</span>
+
+> X25519 keys are
+> [interconvertible with ed25519 keys](dir-spec/converting-to-ed25519.md).
+> So, it would be possible to store the ed25519 form instead,
+> and convert on load/save.
+> However, we use a different key type
+> to avoid needing conversions during load/save, and
+> to avoid key type punning and accidental key misuse:
+> using the same key material for different algorithms is a poor idea.
+
+### `ed25519-expanded@spec.torproject.org`
+
+These refer to the expanded form of private keys for
+ed25519
+([RFC8032](https://datatracker.ietf.org/doc/html/rfc8032)).
+
+This key type appears within OpenSSH private key files.
+When it does, the `ed25519-expanded@spec.torproject.org`
+algorithm name is used for
+the private key (`PROTOCOL.key` section 3, `privatekey1` etc.)
+but also for
+the public key (`PROTOCOL.key` section 1, `publickey1` etc.).
+
+> In `PROTOCOL.key` we interpret the requirement that there be
+> "matching" public and private keys
+> to include the requirement that
+> the public key algorithm name strings must be the same.
+
+> In the Arti keystore a private key file
+> whose filename ends with `.ed25519_private`
+> may contain either
+> a standard ed25519 keypair with SSH type `ed25519`
+> or
+> an `ed25519-expanded@spec.torproject.org` keypair.
+
+`ed25519-expanded@spec.torproject.org`
+SHOULD NOT appear in RFC4716 *public* key files.
+Software which is aware of this key type
+MUST NOT generate such public key files
+and SHOULD reject them on loading.
+(Software handling keys in a type-agnostic manner
+MAY, and probably will, process such files without complaint.)
+
+> These rules are because
+> public keys should always be advertised as `ed25519`
+> even if the private key is only available as `ed25519-expanded@`:
+> this avoids leaking information about the key generation process
+> to relying parties,
+> and simplifies certification and verification.
+
+> Arti will provide a utility to convert
+> anomalous RFC4716 public key files
+> containing keys declared to be of type
+> `ed25519-expanded@spec.torproject.org`
+> to fully conforming files containg `ed25519` keys.
+> In other circumstances Arti will reject such anomalous files.
+
+The public key data is the same as for the official `ed25519` type:
+```
+ string wrapper for the following fixed-length data:
+ byte[32] the actual public key, ENC(A) from RFC8032 3.2
+```
+(Reference: [RFC8032 3.2](https://datatracker.ietf.org/doc/html/rfc8032#section-3.2).)
+
+The private key data is as follows:
+```
+ string wrapper for the following fixed-length data:
+ byte[32] ENC(s) as per RFC8032 3.2, "expanded secret key"
+ byte[32] `h_b...h_(2b-1)` as per RFC8032 3.3, "separation nonce"
+```
+(References: `ENC(s)` in [RFC8032 3.2](https://datatracker.ietf.org/doc/html/rfc8032#section-3.2);
+`h_b || ... || h_(2b-1)` as per [RFC8032 3.3](https://datatracker.ietf.org/doc/html/rfc8032#section-3.3).)
+
+Keys whose `string` wrapper is not of the expected length MUST be rejected.
+
+> [As with `x25519`, the `string` wrapper is useless](#useless-string).
+> We adopt it here for the same reasons.
+
+This private key format does not provide a way to convey or establish
+a corresponding (unexpanded, standard) ed25519 private key `k`.
+
+> The ed25519 standards define the private key for ed25519
+> as a 32-byte secret `k`.
+> `k` is then hashed and processed into parameters used for signing,
+> and the public key for verification.
+> The `ed25519-expanded@spec.torproject.org` can represent private keys
+> which can be used with the ed25519 signature algorithm,
+> and for which a corresponding working public key is known,
+> but for which there is no known value of `k`
+> (the "real ed25519" private key).
+> Allowing such keys can be convenient when
+> one wishes to find private keys whose public keys have particular patterns,
+> for example when trying to find a `.onion` domain
+> for a [Tor Hidden Service](rend-spec/).
+> This format is also used where
+> [blinded ed25519 keys](rend-spec/keyblinding-scheme.md)
+> need to be stored.