From 9ee86e01ecb396cc523271d525d5588515dc56be Mon Sep 17 00:00:00 2001 From: Karolin Varner Date: Sun, 10 Aug 2025 17:43:50 +0200 Subject: [PATCH] feat(whitepaper): Comprehensive reference about packages, labels, and symmetric keys used in protocol --- papers/whitepaper.md | 97 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 90 insertions(+), 7 deletions(-) diff --git a/papers/whitepaper.md b/papers/whitepaper.md index bd67509..efddb69 100644 --- a/papers/whitepaper.md +++ b/papers/whitepaper.md @@ -118,7 +118,20 @@ Using a combination of two KEMs – Classic McEliece for static keys and Kyber f Rosenpass uses libsodium [@libsodium] as cryptographic backend for hash, AEAD, and XAEAD, and liboqs [@liboqs] for the post-quantum-secure KEMs. -## Variables {#variables} +## Packages {#packages} + +The packages, their contents, and their type IDs are graphically represented in Fig. \ref{img:MessageTypes}. Their purposes are: + +* \textbf{Envelope} – This is not a package on its own; it is the envelope all the other packages are put into. +* \textbf{InitHello} – First package of the handshake, from initiator to responder. +* \textbf{RespHello} – Second package of the handshake, from responder to initiator. +* \textbf{InitConf} – Third package of the handshake, from initiator to responder. +* \textbf{EmptyData} – Empty payload package. Used as acknowledgment to abort data retransmission (see Secs. \ref{payload-keys}, \ref{packet-loss}, and function `enter_live()` in Sec. \ref{fn:enter_live}). +* \textbf{Data} – Transmission of actual payload data is not used in Rosenpass, but the package is still specified since it is part of WireGuard (see Sec. \ref{payload-keys} and function `enter_live()` in Sec. \ref{fn:enter_live}). +* \textbf{CookieReply} – Used for proof-of-IP-ownership-based denial-of-service mitigation (see Sec. \ref{dos-mitigation}). +* \textbf{biscuit} – This is not a stand-alone package; instead, it is an encrypted fragment present in \textbf{RespHello} and \textbf{InitConf}. + +## Variables and Domain Separators {#variables} ### KEM Keypairs and Ciphertexts @@ -141,7 +154,7 @@ These values use a naming scheme consisting of four lower-case characters. The f Besides the initiator and responder roles, we define the roles `mine` and `theirs` (`m`/`t`). These are sometimes used in the code when the assignment to initiator or responder roles is flexible. As an example, “this server's” static secret key is `sskm`, and the peer's public key is `spkt`. -### IDs +### IDs {#peer-ids} Rosenpass uses two types of ID variables. See Figure \ref{img:HashingTree} for how the IDs are calculated. @@ -168,6 +181,68 @@ We mix all key material (e.g. `psk`) into the chaining key and derive symmetric The protocol allows for multiple `osk`s to be generated; each of these keys is labeled with a domain separator to make sure different key usages are always given separate keys. The domain separator for using Rosenpass and WireGuard together is a token generated using the domain separator sequence `["rosenpass.eu", "wireguard psk"]` (see Fig. \ref{img:HashingTree}), as described in \ref{protocol-extension-wireguard-psk}. Third-parties using Rosenpass-keys for other purposes are asked to define their own protocol-extensions. Standard protocol extensions are described in \ref{protocol-extensions}. +#### Symmetric Keys and Nonces for payload data transmission {#payload-keys} + +Keys generated by the Rosenpass key exchange could be used for encryption of payload data if post-quantum security but not hybrid post-quantum security is a goal. Despite this, we do not generally offer payload transmission in the protocol. Instead, the Rosenpass protocol focuses on providing a key exchange, letting external applications handle data transmission. When used with WireGuard, the default use case, this integration also ensures hybrid security. + +Still we specify the `Data` and `EmptyData` packets. `Data` is not used, but we still specify it as the same packet is also present in WireGuard. `EmptyData` is used for packet retransmission (see Sec. \ref{packet-loss}). + +We also specify how symmetric keys are generated for payload encryption. See Sec. {#live-session-state} and the function `enter_live()` (Sec. \ref{fn:enter_live}). + +Keys and nonces for this purpose use the following naming scheme: + +\begin{namepartpicture} +\namepart{tx=Transmission,rx=Reception} +\namepart[3.5cm]{k=Key,n=Nonce} +\namepart[7cm]{i=Initiator,r=Responder,m=Mine,t=Theirs} +\begin{scope}[decoration={brace,amplitude=5mm},thick] +\namebraceright{tx}{rx} +\namebraceleft{k}{n} +\namebraceright{k}{n} +\namebraceleft{i}{t} +\end{scope} +\end{namepartpicture} + +Note that this scheme is deliberately redundant. For instance, when we are the initiator, then `txki = rxki = txkm = rxkt`. I.e. the initiator's transmission key is the responder's reception key. Since we are the initiator, the initiator's transmission key is also the transmission key of `mine` and the reception key of `theirs`. + +There also is a -- now deprecated -- naming scheme: + +\begin{namepartpicture} +\namepart{ini=Initiator,res=Responder,hs=Handshake} +\SingleNamePart[3.5cm]{enc}{\textunderscore{}enc}{Encryption} +\begin{scope}[decoration={brace,amplitude=5mm},thick] +\namebraceright{ini}{hs} +\namebraceleft{enc}{enc} +\end{scope} +\end{namepartpicture} + +`ini_enc = txki = rxkr` and `res_enc = txkr = rxki`, but this usage is deprecated. The third name `hs_enc` is for encryption as part of the key exchange itself; this name is still in use. + +### Labels + +Fig. \ref{img:HashingTree} specifies multiple domain separators for various uses. + +* `PROTOCOL` (`[0, PROTOCOL]`) – The global domain separator; used to generate more domain separators. + +Immediately below the global domain separator, you can find: + +* `"mac"` – Network package integrity verification and pre-authentication with `spkt`. See Sec. \ref{envelope-mac-field}. +* `"cookie"` – Denial of Service mitigation through proof-of-ip ownership. See Sec. \ref{dos-mitigation}. +* `"peer id"` – Generation of peer ids. See Sec. \ref{peer-ids}. +* `"biscuit additional data"` – Storing the protocol state in encrypted cookies so the responder is stateless. See Sec. \ref{hs-state-and-biscuits}. +* `"chaining key init"` – Starting point for the execution of the actual rosenpass protocol. +* `"chaining key extract"` – Key derivation from the current protocol state, the chaining key. See Sec. \ref{symmetric-keys}. + +Below `"chaining key extract"`, there are multiple labels, generating domain separators for deriving keys for various purposes during the execution of the protocol. + +It is important to understand that there are two phases for these labels, e.g. applying the `"mix"` label produces a random fixed-size hash value we call `mix`. Not the label `"mix"` but the resulting hash value is used to derive keys during protocol execution. This allows us to use very complicated label structures for key derivation without losing efficiency. + +The different labels are: + +* `"mix"` – Mixing further values into the chaining key; i.e. into the protocol state. +* `"user"` – Labels for external uses; these are what generate the `osk` (output shared key). See Sec. \ref{symmetric-keys}. +* `"handshake encryption"` – Used when encrypting data using a shared key as part of the protocol execution; e.g. used to generate the `auth` (authentication tag) fields in protocol packages. +* `"initiator session encryption"` and `"responder session encryption"` – For transmission of data after the key-exchange finishes. See Sec. \ref{symmetric-keys}. ## Hashes @@ -244,7 +319,7 @@ For each peer, the server stores: * `biscuit_used` – The `biscuit_no` from the last biscuit accepted for the peer as part of InitConf processing * `hash_function` – The hash function, SHAKE256 or BLAKE2s, used with the peer. -### Handshake State and Biscuits +### Handshake State and Biscuits {#hs-state-and-biscuits} The initiator stores the following local state for each ongoing handshake: @@ -267,7 +342,7 @@ The biscuit is encrypted with the `XAEAD` primitive and a randomly chosen nonce. The `biscuit_key` used to encrypt biscuits should be rotated every two minutes. Implementations should keep two biscuit keys in memory at any given time to avoid having to drop packages when `biscuit_key` is rotated. -### Live Session State +### Live Session State {#live-session-state} * `ck` – The chaining key * `sidm` – Our session ID (“mine”) @@ -417,6 +492,8 @@ fn load_biscuit(nct) { } ``` +\phantomsection\label{fn:enter_live} + Entering the live session is very simple in Rosenpass – we just use `extract_key` with dedicated identifiers to derive initiator and responder keys. ```pseudorust @@ -462,7 +539,7 @@ The responder code handling InitConf needs to deal with the biscuits and package ICR5 and ICR6 perform biscuit replay protection using the biscuit number. This is not handled in `load_biscuit()` itself because there is the case that `biscuit_no = biscuit_used` which needs to be dealt with for retransmission handling. -### Denial of Service Mitigation and Cookies +### Denial of Service Mitigation and Cookies {#dos-mitigation} Rosenpass derives its cookie-based DoS mitigation technique for a responder when receiving InitHello messages from Wireguard [@wg]. @@ -483,7 +560,7 @@ cookie_encrypted = XAEAD(lhash("cookie-key", spkm), nonce, cookie_value, mac_pee where `cookie_secret` is a secret variable that changes every two minutes to a random value. Moreover, `lhash` is always instantiated with SHAKE256 when computing `cookie_value` for compatability reasons. `initiator_host_info` is used to identify the initiator host, and is implementation-specific for the client. This paramaters used to identify the host must be carefully chosen to ensure there is a unique mapping, especially when using IPv4 and IPv6 addresses to identify the host (such as taking care of IPv6 link-local addresses). `cookie_value` is a truncated 16 byte value from the above hash operation. `mac_peer` is the `mac` field of the peer's handshake message to which message is the reply. -#### Envelope `mac` Field +#### Envelope `mac` Field {#envelope-mac-field} Similar to `mac.1` in Wireguard handshake messages, the `mac` field of a Rosenpass envelope from a handshake packet sender's point of view consists of the following: @@ -528,7 +605,7 @@ MAX_QUEUED_INCOMING_HANDSHAKES_THRESHOLD = 4096 LAST_UNDER_LOAD_WINDOW = 1 //seconds ``` -## Dealing with Packet Loss +## Dealing with Packet Loss {#packet-loss} The initiator deals with packet loss by storing the messages it sends to the responder and retransmitting them in randomized, exponentially increasing intervals until they get a response. Receiving RespHello terminates retransmission of InitHello. A Data or EmptyData message serves as acknowledgement of receiving InitConf and terminates its retransmission. @@ -676,6 +753,12 @@ still, creating this implementation was a great achievement. During the process, Steffen discovered a large number of possible improvements for the whitepaper. With this update, we are addressing those issues. +Changes, in particular: + +1. Added a comprehensive reference about labels used in the protocol +2. Added a comprehensive reference about symmetric keys and nonces used for encryption/decryption (`txki`, `txni`, `ini_enc`, `hs_enc`, …) +3. Added a comprehensive reference about packages used. + #### 2025-06-24 – Specifying the `osk` used for WireGuard as a protocol extension \vspace{0.5em}