feat(whitepaper): Comprehensive reference about packages, labels, and symmetric keys used in protocol

This commit is contained in:
Karolin Varner
2025-08-10 17:43:50 +02:00
parent 3721996f2d
commit 9ee86e01ec

View File

@@ -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}