Xoodoo Cookbook
Xoodoo Cookbook
Joan Daemen2 , Seth Hoffert, Michaël Peeters1 , Gilles Van Assche1 and
Ronny Van Keer1
1
STMicroelectronics
2
Radboud University
1 Introduction
In [2] we presented new parallel modes of use of permutations for encryption, authentica-
tion, session authenticated encryption and wide block ciphers under the umbrella name
Farfalle. We also proposed concrete instantiations called Kravatte by plugging in the
Keccak-p[1600, nr ] permutation with 6 rounds. All-over, Kravatte is very fast on a
wide range of platforms but can hardly be called lightweight: it operates on a large state
giving rise to considerable overhead on low-end CPUs and has for short inputs a relatively
large overhead per byte.
It therefore makes sense to consider instantiating Farfalle with a smaller permutation,
somewhere between 256 and 400 bits wide. Taking Keccak-p[400, nr ] is problematic as it
is defined in terms of operations on 16-bit lanes. The permutation Gimli [1] has the nice
feature that it has a state of 384 bits and a round function that lends itself to low-end 32-
bit CPUs but also vectorization and dedicated hardware. Unfortunately, its propagation
properties are less than what could be expected. For constructing a Farfalle instance with
128-bit security strength one would have to take a relatively high number of rounds.
For that reason we took the initiative to design a permutation with the same width and
objectives as Gimli, but with more favorable propagation properties. We called the result
Xoodoo and it can be seen as a porting of the Keccak-p design approach to a Gimli-
shaped state. In this document we specify this permutation and a suite of cryptographic
functions built as modes of Xoodoo. This suite covers the symmetric-key crypto functions
and we expect it to be very efficient on a wide range of CPUs and in dedicated hardware
while having a comfortable safety margin. This makes the Xoodoo suite very competitive
to, e.g., block cipher based crypto.
Xoofff is the central instance of the suite, covering keyed symmetric crypto functions.
For more lightweight applications, we add Xoodyak to the suite, a compact and versatile
cryptographic object that is suitable for most symmetric-key functions, including hashing,
pseudo-random bit generation, authentication, encryption and authenticated encryption.
This document does not include extensive design rationale or analysis, nor does it
provide performance benchmarks. For this, please see [8]. Its purpose is to expose the
Xoodoo cipher suite to the cryptographic research community and security practicioners
by serving as specification and security claim reference. At this stage the security claims
serve as a challenge for cryptanalists and only a distant promise of security strength for
users. This promise will gain in credibility as over time third-party cryptanalysis and
public scrutiny accumulate.
Additionally, a reference implementation in C++ of Xoodoo and the members of the
Xoodoo suite is available in [13] and optimized implementations in C and assembler in
the eXtended (or Xoodoo and) Keccak Code Package (XKCP) [23].
Over time, we may add more cryptographic functions to the Xoodoo suite. When
that is the case, we will update this document accordingly. In ISO/IEC terminology this
would be called a standing document.
1.1 Notation
The set of all bit strings is denoted Z∗2 and ϵ is the empty string. The size in bits of
the string X is denoted |X|. We denote a sequence of m strings X (0) to X (m−1) as
X (m−1) ◦ · · · ◦ X (1) ◦ X (0) . The set of all sequences of strings is denoted (Z∗2 )∗ and ∅ is
the sequence containing no strings at all. Similarly, the set of all sequences containing at
least one string is denoted (Z∗2 )+ .
2
Definition 1 ([8, 22]). A deck function takes as input a secret key K and a sequence of
an arbitrary number of strings X (m−1) ◦ · · · ◦ X (0) ∈ (Z∗2 )+ , produces a potentially infinite
string of bits and takes from it the range starting from a specified offset q ∈ N and for a
specified length n ∈ N. We denote this as
( )
Z = 0n + FK X (m−1) ◦ · · · ◦ X (0) ≪ q .
As such, we will indicate the modes we define this document and that we will instan-
tiate with Xoofff by the prefix Deck. The modes on top of Farfalle specified in [2] may
as well be renamed by replacing the prefix Farfalle by Deck. To avoid confusion, we will
not do that.
Like a deck function, a dec function should allow efficient incremental computing.
3
We use the abbreviation SAE to indicate session authenticated encryption in general.
The generic term SAE should not be confused with Farfalle-SAE, that is a particular SAE
mode of a deck function specified in [2].
1.5 Overview
We specify the core of all functions in the Xoodoo suite, the Xoodoo[nr ] family of
permutations, in Section 2. We depict in Figure 1 all suite members and their relations.
They are the following:
• The Xoofff deck function, specified in Section 3. We obtain this deck function
by instantiating Farfalle with Xoodoo and suitable rolling functions and make a
security claim.
• The Xoofff-SANE SAE scheme, specified in Section 4. We obtain this by defining
an SAE mode of deck functions called Deck-SANE and instantiate it with Xoofff.
Xoofff-SANE relies on user-provided nonces for confidentiality.
4
Xoodoo
Farfalle-WBC Farfalle-WBC
Farfalle-WBC-AE
Figure 1: Overview of the Xoodoo suite, with the schemes in boxes and the modes
indicated on the edges. All schemes and the modes in black print are specified in this
document, the modes in grey are defined in [2].
5
2 Xoodoo
Xoodoo is a family of permutations parameterized by its number of rounds nr and de-
noted Xoodoo[nr ].
Xoodoo has a classical iterated structure: It iteratively applies a round function to
a state. The state consists of 3 equally sized horizontal planes, each one consisting of 4
parallel 32-bit lanes. Similarly, the state can be seen as a set of 128 columns of 3 bits,
arranged in a 4 × 32 array. The planes are indexed by y, with plane y = 0 at the bottom
and plane y = 2 at the top. Within a lane, we index bits with z. The lanes within a
plane are indexed by x, so the position of a lane in the state is determined by the two
coordinates (x, y). The bits of the state are indexed by (x, y, z) and the columns by (x, z).
Sheets are the arrays of three lanes on top of each other and they are indexed by x. The
Xoodoo state is illustrated in Figure 2.
The permutation consists of the iteration of a round function Ri that has 5 steps: a
mixing layer θ, a plane shifting ρwest , the addition of round constants ι, a non-linear layer
χ and another plane shifting ρeast .
We specify Xoodoo in Algorithm 1, completely in terms of operations on planes and
use thereby the notational conventions we specify in Table 1. We illustrate the step
mappings in a series of figures: the χ operation in Figure 3, the θ operation in Figure 4,
the ρeast and ρwest operations in Figure 5.
The round constants Ci are planes with a single non-zero lane at x = 0, denoted as ci .
We specify the value of this lane for indices −11 to 0 in Table 2 and refer to Appendix A
for the specification of the round constants for any index.
Finally, in many applications the state must be specified as a 384-bit string s with
the bits indexed by i. The mapping from the three-dimensional indexing (x, y, z) and i is
given by i = z + 32(x + 4y).
6
z z z z z
y y y y y
x x x x x
lane plane state sheet column
Figure 2: Toy version of the Xoodoo state, with lanes reduced to 8 bits, and different
parts of the state highlighted.
Table 2: The round constants ci with −11 ≤ i ≤ 0, in hexadecimal notation (the least
significant bit is at z = 0).
i ci i ci i ci i ci
−11 0x00000058 −8 0x000000D0 −5 0x00000060 −2 0x000000F0
−10 0x00000038 −7 0x00000120 −4 0x0000002C −1 0x000001A0
−9 0x000003C0 −6 0x00000014 −3 0x00000380 0 0x00000012
7
2
complement
0
+ =
fold
0 0
8
Table 3: Notational conventions for specification of the rolling functions
Ay,x Lane x of plane Ay
B An auxiliary variable that has the shape of a plane
Ay,x ≪ v Cyclic shift of lane Ay,x moving bit from x to x + v
Ay,x ≪ v Shift of lane Ay,x moving bit from x to x + v, setting bits x < v to 0
Ay,x + Ay′ ,x′ Bitwise sum (XOR) of lanes Ay,x and Ay′ ,x′
Ay,x · Ay′ ,x′ Bitwise product (AND) of lanes Ay,x and Ay′ ,x′
3 Xoofff
Xoofff is a deck function obtained by applying the Farfalle construction on Xoodoo[6]
and two rolling functions: rollXc for rolling the input masks and rollXe for rolling the state.
We specify them with operations on the lanes of the state, following the conventions of
Table 1 and Table 3.
The input mask rolling function rollXc updates a state A in the following way:
The state rolling function rollXe updates a state A in the following way:
9
• M is the online or data complexity expressed in the total number of input and output
blocks processed by XoofffKi (·).
In (1), the first term accounts for the effort to find one of the u secret keys by exhaustive
search, and for the probability that two keys are equal. The second term expresses that
the complexity of recovering the accumulator or any rolling state inside Xoofff must be
as hard as recovering 192 secret bits. The third term expresses the effort to find a collision
in the accumulator.
The fourth and fifth terms only apply if the adversary has access to a quantum com-
puter. The fourth term accounts for a quantum search (or quantum amplification algo-
′
rithm) to find one of the u keys [11,√ 7]. The probability of success after √N iterations is
2 ′ ′
sin ((2N + 1) θ) with θ = arcsin u/2 . We upper bound this as 2N u/2κ . The fifth
κ
with L the array of the distinct key lengths in use and ul the number of keys of length l.
4 Xoofff-SANE
Xoofff-SANE is an SAE function built on top of Xoofff with a mode we introduce in
this document called Deck-SANE: deck function based Session Authentication and Nonce-
based Encryption. This mode keeps track of a nonce and the sequence of messages in
a string sequence called the history. It encrypts the plaintext of a message by adding
a keystream that is the result of applying the deck function to the history covering all
previous messages in this session. The consequence is that for confidentiality, the history
must be unique across all sessions for a given key. For that reason, Deck-SANE initializes
the history at the beginning of a session with a user-provided nonce.
10
• a message (A, P ) with A ̸= ϵ and P ̸= ϵ,
Both message sequences extend the history with C||1 ◦ A||0, so the tag returned by
wrap(A, P ) in the first case and the tag returned by wrap(ϵ, P ) in the second case are
equal. A situation where an adversary could exploit this would be if the sender intends
on sending two messages: one containing metadata only, followed by another containing
plaintext only. We would have T1 = wrap(A, ϵ) then (C, T2 ) = wrap(ϵ, P ). The adversary
withholds T1 , and passes off (A, C) as a single message with resulting tag T2 . The receiver
is unable to detect this and successfully authenticates the message, and returns garbled
plaintext. We fix this in Deck-SANE by using an additional frame bit that toggles on
every message.
4.2 Deck-SANE
We define the SAE mode for deck functions Deck-SANE in Algorithm 2. The session
presents the history to a deck function for generating tags and keystream. Starting a
session initializes the history to a nonce N and returns a tag.
From then on, it supports messages consisting of metadata A and/or plaintext P .
Deck-SANE wraps a message in four phases:
4. Tag generation: It generates the tag by applying the deck function to the history.
Note that a tag authenticates the full history of the session up to that point. Unwrapping
is similar.
Deck-SANE has two length parameters: the tag length t and an alignment unit length
ℓ. It reserves the first t bits of the output of the deck function for tags and takes keystream
from the output of the deck function from an offset that is the smallest multiple of ℓ not
shorter than t. It applies domain separation between metadata and ciphertext strings
in the history to skip the second phase for plaintext-only messages or the first and third
phase for metadata-only or even empty messages. Moreover, Deck-SANE has an attribute
e that takes the 1-bit string value 0 or 1 and toggles at each call to (un)wrap. Hence, the
individual calls to (un)wrap can be identified in the history without ambiguity.
4.3 Xoofff-SANE
Definition 4 (Xoofff-SANE). Xoofff-SANE is Deck-SANE(F, t, ℓ) with
• F = Xoofff,
• ℓ = 8 bits.
11
Algorithm 2 Definition of Deck-SANE(F, t, ℓ)
Parameters: deck function F , tag length t ∈ N and alignment unit length ℓ ∈ N
∗ ∗
⌈ t ⌉ taking key K ∈ Z2 and nonce N ∈ Z2 , and returning tag T ∈ Z2
t
Initialization
offset = ℓ ℓ : the smallest multiple of ℓ not smaller than t
e ← 01
history ← N
T ← 0t + FK (history)
return T
|P |
Wrap taking metadata A ∈ Z∗2 and plaintext P ∈ Z∗2 , and returning ciphertext C ∈ Z2
and tag T ∈ Zt2
C ← P + FK (history) ≪ offset
if |A| > 0 OR |P | = 0 then
history ← A||0||e ◦ history
if |P | > 0 then
history ← C||1||e ◦ history
T ← 0t + FK (history)
e ← e + 11
return C, T
Unwrap taking metadata A ∈ Z∗2 , ciphertext C ∈ Z∗2 and tag T ∈ Zt2 , and returning
|C|
plaintext P ∈ Z2 or an error
P ← C + FK (history) ≪ offset
if |A| > 0 OR |C| = 0 then
history ← A||0||e ◦ history
if |C| > 0 then
history ← C||1||e ◦ history
T ′ ← 0t + FK (history)
e ← e + 11
if T ′ = T then
return P
else
return error!
5 Xoofff-SANSE
Xoofff-SANSE is an SAE function built on top of Xoofff with a mode we introduce
in this document called Deck-SANSE: deck function based Session Authentication and
Nonce-Synthetic-based Encryption. Where Deck-SANE requires to user to ensure that
each session is started with a unique combination of key and nonce for confidentiality,
in Deck-SANSE this requirement is relaxed. It does this by constructing a nonce of the
metadata and plaintext with a generalization of Synthetic IV method of [19]. Similar to
Deck-SANE, encryption of plaintext is done by adding a keystream that is the output of
the deck function to a history. The difference is in what is covered in that history: In
Deck-SANSE, it covers all previous messages and the current message. In order to allow
decryption, this is realized through the tag: the history for the keystream generation
contains previous messages, the metadata of the current message and the tag. The tag is
computed before the keystream generation and covers the history of all messages, including
the current one. The consequence is that even if two sessions have equal history up to
some point and then have different plaintexts, they will likely lead to different tags and the
12
keystreams will be unrelated. Confidentiality still breaks down when these tags collide
and the user can eliminate the risk of (history,tag) collisions altogether by including a
nonce in the metadata of the first message. In any case, as long as two sessions have the
same sequence of messages, they will produce the same sequence of cryptograms. This is
unavoidable in a deterministic SAE scheme.
5.2 Deck-SANSE
Deck-SANSE combines the SIV approach with the session support of Deck-SANE. We
define it in Algorithm 3. Deck-SANSE wraps a message in four phases:
2. Tag generation: It generates the tag by applying the deck function to the history,
extended with the plaintext of the current messsage, if non-empty.
5.3 Xoofff-SANSE
Definition 5 (Xoofff-SANSE). Xoofff-SANSE is Deck-SANSE(F, t) with
• F = Xoofff and
• t = 256 bits.
We take a 256-bit tag because collisions in the tag are likely to appear after generating
2t/2 tags and we target 128-bit security.
13
Algorithm 3 Definition of Deck-SANSE(F, t)
Parameters: deck function F and tag length t ∈ N
Initialization
e ← 01
history is initialized to the empty string sequence
|P |
Wrap taking metadata A ∈ Z∗2 and plaintext P ∈ Z∗2 , and returning ciphertext C ∈ Z2
and tag T ∈ Zt2
if |A| > 0 OR |P | = 0 then
history ← A||0||e ◦ history
if |P | > 0 then
T ← 0t + FK (P ||01||e ◦ history)
C ← P + FK (T ||11||e ◦ history)
history ← P ||01||e ◦ history
else
T ← 0t + FK (history)
e ← e + 11
return C, T
Unwrap taking metadata A ∈ Z∗2 , ciphertext C ∈ Z∗2 and tag T ∈ Zt2 , and returning
|C|
plaintext P ∈ Z2 or an error
if |A| > 0 OR |C| = 0 then
history ← A||0||e ◦ history
if |C| > 0 then
P ← C + FK (T ||11||e ◦ history)
history ← P ||01||e ◦ history
T ′ ← 0t + FK (history)
e ← e + 11
if T ′ = T then
return P
else
return error!
14
• pc = Xoodoo[6],
• pd = Id,
• pe = Xoodoo[6],
• rollc = rollXc and
• rolle = rollXe
with Id the identity permutation.
We make the following security claim on Xoofffie:
Claim 2. Let K = (K0 , . . . , Ku−1 ) be an array of u secret keys, each uniformly and
independently chosen from Zκ2 with κ < 384. Consider an adversary that can query a
function with chosen inputs (X, ∆, i), with M ∈ (Z∗2 )+ , ∆ ∈ Z∗2 and i ∈ Zu that is one of
the two following, without knowing which one:
• RO(∆ + XoofffieKi (X)): the sum of the output of Xoofffie and an offset ∆,
and truncated to the length of that offset, and this filtered by random oracle RO.
• RO2 (i, X, ∆): random oracle RO applied to the combination of the three inputs.
Then, the distinguishing advantage is at most:
M M2
+ , (3)
2128 2∆min −4
with ∆min the minimum length of ∆ over the adversary’s queries. Note that the adversary
can not make direct queries to RO.
This claim expresses a differential uniformity property. When trying to distinguish
RO(∆+XoofffieKi (X)) from RO(i, X, ∆), the adversary is limited to observing equality
in the expression ∆ + XoofffieKi (X) for chosen inputs (i, X, ∆). In other words, an
adversary succeeds if she can find XoofffieK outputs with a predictable difference ∆,
i.e., XoofffieKi (X) + XoofffieKj (Y ) = ∆ for (i, X) ̸= (j, Y ). The output blurring by
a random oracle prevents state or key retrieval in the absence of collisions and hence the
bound only contains terms related to generating collisions. The first term in (3) covers
collisions in the accumulator and the second term in ∆min -bit outputs. For an ideal
2
function the second term would be birthday bound 2∆M min +1
. We tolerate some non-ideal
behaviour by multiplying the birthday expression by a factor 25 .
15
Claim 3. Let K = (K0 , . . . , Ku−1 ) be an array of u secret keys, each uniformly and
independently chosen from Zκ2 with κ < 384 and let PKi (·) with i ∈ Zu be instances of
Xoofff-WBC. Each of these instances support two interfaces:
We express as Advsprp the probability of distinguishing PKi (W, ·) from an array of uni-
formly and independently drawn random permutations πi,W,n indexed by the key index i,
the value of W and the length n = |P | = |C|, where the adversary can query the inverse
permutations.
Let nmin be the minimum length n among all the queries. The Advsprp is claimed to
be upper bounded by
M2
(1) + n /2−8 . (4)
2 min
Here, N , N ′ and M are as in Claim 1, except that M also counts the number of input
and output blocks processed by Xoofffie.
The terms in (4) are those of Claim 1 and an additional term. The additional term
covers the case of an adversary obtaining a collision in one of the branches of the Feistel
network, see [2] for details. We relate this to the ability of doing this in the first and last
rounds, that make use of Xoofffie. In this use case, it has ∆min ≥ nmin /2 − 4 and hence
2
M2
the term 2∆Mmin −4
becomes 2nmin /2−8 .
• H = Xoofffie,
• G = Xoofff,
• ℓ = 8 bits,
• t = 128 bits.
7 Xoodyak
In this section, we specify Xoodyak, a versatile cryptographic object that is suitable for
most symmetric-key functions, including hashing, pseudo-random bit generation, authen-
tication, encryption and authenticated encryption. It is based on the duplex construction,
and in particular on its full-state (FSKD) variant when it is fed with a secret key [3, 9].
It is stateful and shares features with Markku Saarinen’s Blinker [20], Mike Hamburg’s
Strobe protocol framework [12] and Trevor Perrin’s Stateful Hash Objects (SHO) [17]. In
16
practice, Xoodyak is straightforward to use and its implementation can be shared for
many different use cases. The mode of operation employed in Xoodyak is called Cyclist,
as a lightweight counterpart to Keyak’s Motorist mode [5]. It is simpler than Motorist,
mainly thanks to the absence of parallel variants. Another important difference is that
Cyclist is not limited to authenticated encryption, but rather offers fine-grained services,
à la Strobe, and supports hashing.
7.1 Notation
Xoodyak works with bytes, i.e., a sequence of 8 bits, and in the sequel we assume that
all strings have a length that is multiple of 8 bits. The length in bytes of a string X is
denoted |X|8 , which is equal to its bit length divided by 8. We denote with enc8 (x) a byte
whose value is the integer x ∈ Z256 . Byte values are noted in hexadecimal in a typewriter
font enclosed in single quotes, e.g., ‘1A‘ is a byte whose value is the integer 26.
The state of a Cyclist object will depend on the sequence of calls to it and on its
inputs. More precisely, the intention is that any output depends on the sequence of all
input strings and of all input calls so far, and that any two subsequent output strings are
in different domains. It does not only depend on the concatenation of input strings, but
also on their boundaries without ambiguity. For instance, a call to Absorb(X) means
the output will depend on X ◦ Absorb, while a call to Encrypt(P ) will make the output
depend also on P ◦ Crypt. However, some dependency comes as a side-effect of other
17
Table 4: Symbols and strings appended to the process history.
Hash mode:
Absorb(X) X ◦ Absorb
Squeeze(ℓ) after another Squeeze() Blocknhash (ℓ) ◦ Squeeze
Squeeze(ℓ) (otherwise) Blocknhash (ℓ)
Keyed mode:
Cyclist(K, id, counter) counter ◦ id ◦ AbsorbKey
Absorb(X) X ◦ Absorb
C ← Encrypt(P ) P ◦ Crypt
P ← Decrypt(C) P ◦ Crypt
Squeeze(ℓ) Blocknkout (ℓ) ◦ Squeeze
SqueezeKey(ℓ) Blocknkout (ℓ) ◦ SqueezeKey
Ratchet() Ratchet
design criteria, like minimizing the memory footprint. As a result, the state also depends
on the number of blocks in the previous calls to Squeeze() and the previously processed
plaintext blocks in Encrypt() or Decrypt().
Together, everything that influences the output of a Cyclist object, as returned by
Squeeze(), SqueezeKey() or as keystream produced by Encrypt(), is captured by the
process history, see Definition 9 below. When in keyed mode, the output also depends on
the secret key absorbed upon initialization, although the key is not part of the process
history itself. This ensures the security claim can be properly expressed in an indistin-
guishability setting where the adversary has full control on the process history but not on
the secret key, see Claim 5.
Definition 9. The process history (or history for short) is a sequence of strings and
symbols in (Z∗2 ∪ S)∗ , with
At initialization of the Cyclist object, the history is initialized to ∅. Then, each call to
the Cyclist object appends symbols and strings according to Table 4, where
( ⌈ ⌉ ) ( ⌈ ⌉ )
ℓ ℓ
nhash (ℓ) = max 0, −1 and nkout (ℓ) = max 0, −1 .
Rhash Rkout
In addition, the process history is updated with the Rkout -byte blocks of plaintext as they
are processed by Encrypt() or Decrypt().
The Cyclist mode of operation is defined in Algorithms 4 and 5.
18
Algorithm 4 Definition of Cyclist[f, Rhash , Rkin , Rkout , ℓratchet ]
Instantiation: cyclist ← Cyclist[f, Rhash , Rkin , Rkout , ℓratchet ](K, id, counter)
′
Phase and state: (phase, s) ← (up, ‘00‘f.b )
Mode and absorb rate: (mode, Rabsorb , Rsqueeze ) ← (hash, Rhash , Rhash )
if K not empty then AbsorbKey(K, id, counter)
Interface: Absorb(X)
AbsorbAny(X, Rabsorb , ‘03‘ (absorb))
Interface: Y ← Squeeze(ℓ)
return SqueezeAny(ℓ, ‘40‘ (squeeze))
19
Algorithm 5 Internal interfaces of Cyclist[f, Rhash , Rkin , Rkout , ℓratchet ]
Internal interface: AbsorbAny(X, r, cD )
for all blocks Xi in Split(X, r) do
if phase ̸= up then Up(0, ‘00‘)
Down(Xi , cD if first block else ‘00‘)
20
in calls to Xoodoo[12] or its inverse. We exclude from the claim weaknesses due to the
mere fact that the function can be described compactly and can be efficiently executed, e.g.,
the so-called random oracle implementation impossibility [14], as well as properties that
cannot be modeled as a single-stage game [18].
This means that Xoodyak hashing has essentially the same claimed security as, e.g.,
SHAKE128 [15].
Claim 5. Let K = (K0 , . . . , Ku−1 ) be an array of u secret keys, each uniformly and
independently chosen from Zκ2 with κ ≤ 256 and κ a multiple of 8. Then, the advantage
of distinguishing the array of Xoodyak objects after initialization with Cyclist(Ki , ·, ·)
with i ∈ Zu from an array of random oracles RO(i, h), where h ∈ (Z∗2 ∪ S)∗ is a process
history, is at most
( ) ( )
qiv N + u2 N (L + Ω)N + L+Ω+12 M2 Mq
κ
+ 184 + 192
+ 382 + min(192+κ,384) . (5)
2 2 2 2 2
Here we follow the notation of the generic security bound of the FSKD [9], namely:
• N is the computational complexity expressed in the (computationally equivalent)
number of executions of Xoodoo[12].
• M is the online or data complexity expressed in the total number of input and output
blocks processed by Xoodyak.
• q ≤ M is the total number of initializations in keyed mode.
• Ω ≤ M is the number of blocks, in keyed mode, that overwrite the outer state and
for which the adversary gets a subsequent output block. In particular, this counts
the number of blocks processed by Decrypt(·) for which the adversary can also get
the corresponding key stream value or other subsequent output (e.g., in the case of
the release of unverified plaintext in authenticated encryption). And it also counts
the number of calls to Ratchet() followed by Squeeze(ℓ) or SqueezeKey(ℓ) with
ℓ ̸= 0.
• L ≤ M is the number of blocks, in keyed mode, for which the adversary knows the
value of the outer state from a previous query and can choose the input block value
(e.g., in the case of authentication without a nonce, or of authenticated encryption
with nonce repetition). This includes the number of times a call to Absorb() follows
a call to Squeeze(ℓ) or to SqueezeKey(ℓ) with ℓ ̸= 0.
• qiv ≤ u is the maximum number of keys that are used with the same id, i.e.,
Claims 4 and 5 ensure Xoodyak has 128 bits of security both in hash and keyed modes
(assuming κ ≥ 128). Regarding the data complexity, it depends on the values of q, Ω and
L, for which we will see concrete examples in Section 7.4. Given that they are bounded
by M , Xoodyak resists to a data complexity of up to 264 blocks, as the probability in
Eq. (5) is negligible as long as N ≪ 2128 and M ≪ 264 . In the particular case of L+Ω = 0,
it resists even higher data complexities, as the probability remains negligible also when
M ≪ 2160 .
The parameter qiv relates to the possible security degradations in the case of multi-
target attacks, as an exhaustive key search would erode security by log2 qiv ≤ log2 u bits
in this case. However, when the protocol ensures qiv = 1, there is no degradation and the
security remains at min(128, κ) bits even in the case of multi-target attacks.
21
7.4 Using Xoodyak
Xoodyak, as a Cyclist object, can be started in hash mode and therefore used as a hash
function. Alternatively, one can start Xoodyak in keyed mode and, e.g., to use it as a
deck function or for duplex-like session authenticated encryption. In this section, we cover
use cases in this order, first in hash mode, then in keyed mode, then some combination of
both.
Cyclist(ϵ, ϵ, ϵ)
Absorb(x)
Squeeze(n)
This sequence is the nominal sequence for using Xoodyak as a XOF. Its security is
summarized in the following Corollary.
Corollary 1. Assume that Xoodyak satisfies Claim 4. Then, this hash function has the
following security strength levels, with n the output size in bytes:
Xoodyak can also naturally implement a dec function and process a sequence of
strings. Here the output depends on the sequence as such and not just on the concatena-
tion of the different strings and, in this sense it is similar to TupleHash [16]. To compute
a n-byte digest over the sequence x3 ◦ x2 ◦ x1 , one does:
Cyclist(ϵ, ϵ, ϵ)
Absorb(x1 )
Absorb(x2 )
Absorb(x3 )
Squeeze(n)
A XOF can be implemented in a stateful manner and can come with an interface
that allows for requesting more output bits. This is the so-called extendable output
feature, and for Cyclist this is provided quite naturally by the Squeeze() function.
Here, some care must be taken for interoperability: For supporting use cases such as
the one in Section 7.6.4, Cyclist considers squeezing calls as being in distinct domains.
This means a Cyclist objects with some given history, the n + m bytes returned by
Squeeze(n) || Squeeze(m) and Squeeze(n + m) will be the same in the first n bytes
and differ in the last m bytes. If an extendable output is required without this feature,
an interface can be built to allow incremental squeeze calls. For instance, an interface
SqueezeMore() would behave such that calling Squeeze(n) followed by SqueezeMore(m)
is equivalent to calling Squeeze(n + m) in the first place.
22
7.6 Keyed mode
In keyed mode, Xoodyak can naturally implement a deck function, although we focus
instead on duplex-based ways to perform authentication and (authenticated) encryption.
To use Xoodyak as a keyed object, one starts it with Cyclist(K, id, counter) where
K is a secret key with a fixed length of κ bits. We first show how to use the id and
counter parameters, to counteract multi-target attacks and to handle the nonce, then
discuss various kinds of authenticated encryption use cases.
Let us assume that we wish to target a security strength level of 128 bits including
multi-target attacks. Xoodyak can achieve this in two ways.
• We extend the length of the secret key. By setting κ = 128 + log2 u, then the term
qiv N
2κ becomes
qiv N N
≤ 128 .
2128+log2 u 2
• We make the key identifier id globally unique among the u keys and therefore ensure
that qiv = 1. Then, there is no degradation for exhaustive key search in a multi-
target setting, and the key size can be equal to the target security strength level, so
κ = 128 in this example.
23
get a tag of t = 16 bytes, we make the following sequence of calls:
Cyclist(K, id, ϵ)
Absorb(nonce)
Absorb(A)
C ← Encrypt(P )
T ← Squeeze(t)
return (C, T )
Cyclist(K, id, ϵ)
Absorb(nonce)
Absorb(A)
P ← Decrypt(C)
T ′ ← Squeeze(t)
if T = T ′ then
return P
else
return ⊥
If the nonce is not repeated and if the decryption does not leak unverified decrypted
ciphertexts, then we have L = Ω = 0 here, see Claim 5. The resulting simplified security
claim is given in the following corollary.
Corollary 2. Assume that (1) Xoodyak indeed satisfies Claim 5; (2) this authenticated
encryption scheme is fed with a single κ-bit key with κ ≤ 192; (3) it is implemented
such that the nonce is not repeated and the decryption does not leak unverified decrypted
ciphertexts. Then, it can be distinguished from an ideal scheme with an advantage whose
dominating terms are:
N N M2
κ
+ 184 + 192+κ .
2 2 2
This translates into the following security strength levels assuming a t-byte tag (the com-
plexities are in bits):
computation data
plaintext confidentiality min(184, κ, 8t) 96 + κ/2
plaintext integrity min(184, κ, 8t) 96 + κ/2
associated data integrity min(184, κ, 8t) 96 + κ/2
Cyclist(K, id, ϵ)
Absorb(nonce)
Absorb(A1 )
C1 ← Encrypt(P1 )
T1 ← Squeeze(t)
⇒ output (C1 , T1 ) and wait for next message
Absorb(A2 )
24
C2 ← Encrypt(P2 )
T2 ← Squeeze(t)
⇒ output (C2 , T2 ) and wait for next message
Absorb(A3 )
T3 ← Squeeze(t)
⇒ output T3 and wait for next message
C4 ← Encrypt(P4 )
T4 ← Squeeze(t)
⇒ output (C4 , T4 ) and wait for next message
T5 ← Squeeze(t)
⇒ output T5 and wait for next message
In this example, T2 authenticates (A2 , P2 ) ◦ (A1 , P1 ). The third message has no plain-
text, the fourth message has no associated data, and the fifth message is empty. In such
a sequence, the convention is that the call to Squeeze() ends a message. Since it appears
in the processing history, there is no ambiguity on the boundaries of the messages even if
some of the elements (or both) are empty.
The use of empty messages may be clearer in the case of a session shared by two (or
more) communicating devices, where each device takes a turn. A device may have nothing
to say and so skips its turn by just producing a tag.
To relate to Claim 5, we have to determine L by counting the number of invocations
to Absorb() that follow Squeeze(). If the nonce is not repeated and if the decryption
does not leak unverified decrypted ciphertexts, we have L = T − q, with T the number of
messages processed (or tags produced), and Ω = 0.
7.6.5 Ratchet
At any time in keyed mode, the user can call Ratchet(). This causes part of the state
to be overwritten with zeroes, thereby making it computationally infeasible to compute
the state value before the call to Ratchet().
In an authenticated encryption scheme, the call to Ratchet() can be typically in-
serted either just before producing the tag or just after. The advantage of calling it just
before the tag is that it is most efficient: It requires only one extra call to the permutation
f . An advantage of calling it just after the tag is that its processing can be done asyn-
chronously, while the ciphertext is being transmitted and it waits for the next message.
Unless Ratchet() is the last call, the number of calls to it must be counted in Ω.
Cyclist(K, id, ϵ)
Absorb(nonce)
Absorb(A)
C ← Encrypt(P )
Ratchet() {either here . . . }
T ← Squeeze(t)
Ratchet() {. . . or here}
25
K1 ← K and i ← 1
while necessary do
Initialize a new Xoodyak instance with Cyclist(Ki , ϵ, ϵ)
Ki+1 ← SqueezeKey(ℓsub ) {and store Ki+1 by overwriting Ki }
Ratchet() {optional}
Absorb(Ai )
Ci ← Encrypt(Pi )
Ti ← Squeeze(t)
⇒ output (Ci , Ti ) and wait for next message
i←i+1
Here ℓsub should be chosen large enough to avoid collisions, say ℓsub = 32 bytes (256
bits). Assuming that there are no collisions in the subkeys, L = 0 and Ω is the number of
calls to Ratchet().
Using Cyclist this way offers resilience against side channel attacks, as the long-term
key is not exposed any more and can even be discarded as soon as the first subkey is derived.
The key to attack becomes a moving target, just like the state in session authenticated
encryption.
N N MN + M2
κ
+ 184 + .
2 2 2192
This translates into the following security strength levels assuming a t-byte tag (the com-
plexities are in bits):
26
computation data
plaintext confidentiality (nominal case) min(128, κ, 8t) 64
plaintext confidentiality (misuse case) - -
plaintext integrity min(128, κ, 8t) 64
associated data integrity min(128, κ, 8t) 64
Cyclist(ϵ, ϵ, ϵ)
Absorb(ID of the chosen protocol)
Absorb(KA ) {Alice’s public key}
Absorb(KB ) {Bob’s public key}
Absorb(KAB ) {Their common secret produced with Diffie-Hellman}
KD ← Squeeze(ℓ)
Cyclist(KD , ϵ, ϵ)
Absorb(nonce)
Absorb(A)
C ← Encrypt(P )
T ← Squeeze(t)
return (C, T )
Acknowledgement
We thank Bart Mennink and Guido Bertoni for useful discussion, Ted Krovetz for finding
and reporting to us the flaw in Farfalle-SIV, as noted in Section 5.1 and Johan De Meulder
for his contributions on the early stages of the definition of Xoodoo.
References
[1] D. J. Bernstein, S. Kölbl, S. Lucks, P. Maat Costa Massolino, F. Mendel, K. Nawaz,
T. Schneider, P. Schwabe, F.-X. Standaert, Y. Todo, and B. Viguier, Gimli : A cross-
platform permutation, Cryptographic Hardware and Embedded Systems - CHES 2017,
Proceedings (W. Fischer and N. Homma, eds.), Lecture Notes in Computer Science,
vol. 10529, Springer, 2017, pp. 299–320.
[2] G. Bertoni, J. Daemen, S. Hoffert, M. Peeters, G. Van Assche, and R. Van Keer,
Farfalle: parallel permutation-based cryptography, IACR Trans. Symmetric Cryptol.
2017 (2017), no. 4, 1–38.
27
[3] G. Bertoni, J. Daemen, M. Peeters, and G. Van Assche, Duplexing the sponge: Single-
pass authenticated encryption and other applications, Selected Areas in Cryptography
- SAC 2011, Revised Selected Papers (A. Miri and S. Vaudenay, eds.), Lecture Notes
in Computer Science, vol. 7118, Springer, 2011, pp. 320–337.
[4] G. Bertoni, J. Daemen, M. Peeters, G. Van Assche, and R. Van Keer, CAESAR
submission: Ketje v2, September 2016, https://keccak.team/ketje.html.
[5] , CAESAR submission: Keyak v2, document version 2.2, September 2016,
https://keccak.team/keyak.html.
[6] E. Biham, How to decrypt or even substitute des-encrypted messages in 228 steps,
Inf. Process. Lett. 84 (2002), no. 3, 117–124.
[8] J. Daemen, S. Hoffert, G. Van Assche, and R. Van Keer, The design of Xoodoo and
Xoofff, IACR Trans. Symmetric Cryptol. 2018 (2018), no. 4, 1–38.
[9] J. Daemen, B. Mennink, and G. Van Assche, Full-state keyed duplex with built-in
multi-user support, Advances in Cryptology - ASIACRYPT 2017, Proceedings, Part
II (T. Takagi and T. Peyrin, eds.), Lecture Notes in Computer Science, vol. 10625,
Springer, 2017, pp. 606–637.
[10] T. Dierks and E. Rescorla, The transport layer security (TLS) protocol version 1.2,
Network Working Group of the IETF, RFC 5246, August 2008.
[11] L. K. Grover, A fast quantum mechanical algorithm for database search, Proceedings
of the 28th Annual ACM Symposium on the Theory of Computing, May 1996 (Gary L.
Miller, ed.), ACM, 1996, pp. 212–219.
[12] M. Hamburg, The STROBE protocol framework, Real World Crypto, 2017.
[15] NIST, Federal information processing standard 202, SHA-3 standard: Permutation-
based hash and extendable-output functions, August 2015, http://dx.doi.org/10.
6028/NIST.FIPS.202.
28
[19] P. Rogaway and T. Shrimpton, A provable-security treatment of the key-wrap prob-
lem, Advances in Cryptology - EUROCRYPT 2006, Proceedings (S. Vaudenay, ed.),
Lecture Notes in Computer Science, vol. 4004, Springer, 2006, pp. 373–390.
[20] M.-J. O. Saarinen, Beyond modes: Building a secure record protocol from a cryp-
tographic sponge permutation, Topics in Cryptology - CT-RSA 2014. Proceedings
(J. Benaloh, ed.), Lecture Notes in Computer Science, vol. 8366, Springer, 2014,
pp. 270–285.
[21] M. M. I. Taha and P. Schaumont, Side-channel countermeasure for SHA-3 at almost-
zero area overhead, 2014 IEEE International Symposium on Hardware-Oriented Se-
curity and Trust, HOST 2014, IEEE Computer Society, 2014, pp. 93–96.
[22] G. Van Assche, On dec(k) functions, INDOCRYPT 2018, December 2018, https:
//keccak.team/files/OnDecAndDeckFunctions-Indocrypt2018.pdf.
[23] G. Van Assche, R. Van Keer, and Contributors, Extended Keccak code package,
August 2018, https://github.com/XKCP/XKCP.
[24] T. Ylonen and C. Lonvick, The secure shell (SSH) protocol architecture, Network
Working Group of the IETF, RFC 4251, January 2006.
29
Table 5: The round constants with indices -11 to 0
i qi si ci in hex
−11 1 + t 3 t3 + t4 + t6 0x00000058
−10 t + t2 2 t3 + t4 + t5 0x00000038
−9 1 + t + t2 6 t6 + t7 + t8 + t9 0x000003C0
−8 1 + t2 4 t4 + t6 + t7 0x000000D0
−7 1 5 t5 + t8 0x00000120
−6 t 1 t2 + t4 0x00000014
−5 t2 3 t5 + t6 0x00000060
−4 1 + t 2 t2 + t3 + t5 0x0000002C
−3 t + t2 6 t7 + t8 + t9 0x00000380
−2 1 + t + t2 4 t4 + t5 + t6 + t7 0x000000F0
−1 1 + t2 5 t5 + t7 + t8 0x000001A0
0 1 1 t1 + t4 0x00000012
The sequence of polynomials qi (t) has period 7 and the sequence of offsets si has period
6. It follows that the sequence of round constants Ci (t) have period 42. An instance of
Xoodoo with r rounds uses the round constants with indices 1 − r to 0. We list the round
constants with indices −11 to 0 in Table 5.
30
B Single-page definition sheet
Modes specified in this document:
• Deck-SANE(F, t, ℓ)
• Deck-SANSE(F, t)
• Farfalle-WBC-AE[H, G, ℓ, t]
Members of the Xoodoo suite, built on top of Xoodoo[nr ]: Xoodoo with nr rounds:
• Xoofff≜Farfalle[Xoodoo[6], Xoodoo[6], Xoodoo[6], Xoodoo[6], rollXc , rollXe ]
31
C Change log
C.1 14 March 2019
This version adds Xoodyak to the Xoodoo suite, see Section 7.
32