1 Introduction

Due to the rise of cloud computing, most people living in countries with active digital economies can expect a significant amount of information about them to be stored on cloud platforms. Cloud computing offers economies of scale for computational resources with ease of management, elasticity, and fault tolerance driving further centralization. While cloud computing is ubiquitously employed for building modern online service, it also poses security and privacy risks. Cloud storage and computation are outside the control of the data owner and users currently have no mechanism to verify whether the third-party operator, even with good intentions, can handle their data with confidentiality and integrity guarantees. Hardware-Based Solutions. To overcome these limitations, trusted execution environments (TEEs), such as Intel SGX [27], ARM Trustzone [45], RISC-V Keystone [29, 38], AMD-SEV [33] provide an appealing way to build secure systems. TEEs provide a hardware-protected secure memory region called a secure enclave whose residing code and data are isolated from any layers in the software stack including the operating system and/or the hypervisor. In addition, TEEs offer remote attestation for proving their trustworthiness to third-parties. In particular, the remote attestation enables a remote party to verify that an enclave has a specific identity and is indeed running on a genuine TEE hardware platform. Given they promise a hardware-assisted secure abstraction, TEEs are now commercially offered by major cloud computing providers including Microsoft Azure [47], Google Cloud [46], and Alibaba Cloud [5].

Modeling Challenges. While TEEs provide a promising building block, it is not straightforward to design secure applications on top of TEEs. In particular applications face the following three challenges: (1) Most practical applications require combining trusted and untrusted components for improved performance and a low trusted computing base; (2) TEEs are designed to protect only the volatile, in-memory, “stateless” computations and data. Unfortunately, this abstraction is insufficient for most practical applications, which rely on stateful computation on untrusted storage mediums (SSDs, disks). Ensuring security for such untrusted storage mediums is challenging because TEEs are prone to rollback attacks; and lastly, (3) TEE hardware designs are prone to numerous side channel attacks exploiting memory access patterns, cache timing channels, etc. These side channel attacks have the potential to completely compromise the confidentiality, integrity, and authenticity (remote attestation) of enclaves.

Therefore, it is important to carefully model the security achieved by the protocols of such systems as well as the assumptions in the cryptography and the hardware, and the trust afforded in protocol participants. Ideally such modelling must be compositional to facilitate the construction of larger systems based on smaller hardware and cryptography components. Given a sufficiently expressive model of TEEs, they can be used as a powerful setup assumption to realise many protocols.

The model of Pass, Shi, and Tramer (PST) [44] takes an initial step towards modelling protocols employing TEEs. The PST model provides a compositional functionality for attested execution and shows how to instantiate various primitives impossible in the standard model, as well as some limitations of TEEs. The PST model was first weakened in [52], which provides a compelling example of how an excessively weak enclave, susceptible to side channel attacks that break confidentiality (but not integrity and authenticity), can still be used as setup for useful cryptographic primitives. Both models, however, live at two opposite extremes, and thus fail to capture realistic instantiations of real world trusted execution.

Functional Encryption and Limitations. One of the core primitives that enables privacy preserving computation and storage is Functional Encryption (FE), introduced by [16]. FE is a generalisation of Attribute/Identify Based Encryption [48, 49], that enables authorized entities to compute over encrypted data, and learn the results in the clear. In particular, parties possessing the so-called functional key, \(\mathsf {sk}_f\), for the function f, can compute f(x), where x is the plaintext, by applying the decryption algorithm on \(\mathsf {sk}_f\) and an encryption of x. Access to the functional key is regulated by a trusted third party. While out of scope for our work, identifying such a party is an interesting question that requires establishing metrics for the trustworthiness of entities we might want to be able to decrypt functions, and the kind of functions that should be authorised for a given level of trust. An obvious option for the role of trusted authority would be that of a data protection authority, who can investigate the data protection practices of organisations and levy fines in case these are violated. Another approach could be decentralising this role, by allowing the functional key to be generated collectively by a number of data owners [1, 23].

FE is a very powerful primitive but in practice highly non-trivial to construct. Motivated by the inefficiency of existing instantiations of FE for arbitrary functions, the work of [28] introduces \(\mathsf {Iron}\), which is a practically efficient protocol that realises FE based on Intel’s SGX. In [28] the authors formally prove security of the proposed protocol, however their proof is in the standalone setting. In a related work, Matt and Maurer [41] show (building on [3]) that composable functional encryption (CFE) is impossible to achieve in the standard model, but achievable in the random oracle model. For another important variant of the primitive, namely, randomized functional encryption, existing constructions [2, 30, 37], are limited in the sense that they require a new functional key for each invocation of the function, i.e., decryptions with the same functional key always return the same output. Finally, existing notions of FE only capture stateless functionalities, which we believe further restricts the usefulness and applicability of the primitive. For instance, imagine a financial institution that sets its global lending rate based on the total liquidity of its members. Financial statements can be sent, encrypted, by each member, with each of these transactions updating the global view for the decryptor, who can then compute the function’s result in real time.

Given the above limitations, in this work we leverage the power of hardware assisted computation to construct FE for a broader class of functionalities under the strongest notion of composable security.

1.1 Our Contributions

We consider a generalization of FE to arbitrary stateful and probabilistic functionalities (\(\mathrm {FESR}\)), that subsumes multi-client FE [23] and enables cryptographic computations in a natural way, due to the availability of internal randomness. Our contributions are as follows:

  • We formally define functional encryption for stateful and randomized functionalities (\(\mathrm {FESR}\)), in the Universal Composition (UC) setting [28].

  • We construct the protocol \(\mathsf {Steel}\) and prove that it realizes \(\mathrm {FESR}\) in the newly introduced Universal Composition with Global Subroutines (UCGS) model [9]. Our main building blocks are: (1) the functional encryption scheme of [28] and (2) the global attestation functionality of PST. Our treatment lifts the PST model to the UCGS setting, and by easily adapting our proofs one can also establish the UCGS-security of [28].

  • Finally, we introduce a weaker functionality for attested execution in the UCGS model to allow rollback and forking attacks, and use it to demonstrate that \(\mathsf {Steel}\) does not protect against these. Finally, we sketch possible mitigation techniques.

1.2 Technical Overview

Attested Execution via the Global Attestation Functionality \(G_{\mathsf {att}}\) of PST [44]. Our UC protocols assume access to the global attestation functionality, \(G_{\mathsf {att}}\), that captures the core abstraction provided by a broad class of attested execution processors, such as Intel SGX [27]. It models multiple hardware-protected memory regions of a TEE, called secure enclaves. Each enclave contains trusted code and data. In combination with a call-gate mechanism to control entry and exit into the trusted execution environment, this guarantees that this memory can only be accessed by the enclave it belongs to, i.e., the enclave memory is protected from concurrent enclaves and other (privileged) code on the platform. TEE processing environments guarantee the authenticity, the integrity and the confidentiality of their executing code, data and runtime states, e.g. CPU registers, memory and others.

\(G_{\mathsf {att}}\) is parametrised by a signature scheme and a registry that captures all the platforms that are equipped with an attested execution processor. At a high level, \(G_{\mathsf {att}}\) allows parties to register programs and ask for evaluations over arbitrary inputs, while also receiving signatures that ensure correctness of the computation. Since the manufacturer’s signing key pair can be used in multiple protocols simultaneously, \(G_{\mathsf {att}}\) is defined as a global functionality that uses the same key pair across sessions.

Universal Composition with Global Subroutines [10]. In our work we model global information using the newly introduced UCGS framework, which resolves inconsistencies in GUC [19], an earlier work that aims to model executions in the presence of global functionalities. UCGS handles such executions via a management protocol, that combines the target protocol and one or more instances of the global functionality, and creates an embedding within the standard UC framework. In our work, \(G_{\mathsf {att}}\) (cf. Sect. 2.2) is modeled as a global functionality in the UCGS framework (updating the original PST formulation in GUC).

Setting, Adversarial Model and Security. Our treatment considers three types of parties namely, encryptors, denoted by \(\mathsf {A}\), decryptors, denoted by \(\mathsf {B}\), as well as a single party that corresponds to the trusted authority, denoted by \(\mathsf {C}\). The adversary is allowed to corrupt parties in \(\mathsf {B}\) and request for evaluations of functions of it’s choice over messages encrypted by parties in \(\mathsf {A}\). We then require correctness of the computation, meaning that the state for each function has not been tampered with by the adversary, as well as confidentiality of the encrypted message, which ensures that the adversary learns only the output of the computation (and any information implied by it) and nothing more. Our treatment covers both stateful and randomized functionalities.

\(\mathsf {Steel}\): UCGS-secure FE for Stateful and Randomized Functionalities. \(\mathsf {Steel}\) is executed by the sets of parties discussed above, where besides encryptors, all other parties receive access to \(G_{\mathsf {att}}\), abstracting an execution in the presence of secure hardware enclaves. Our protocol is based on \(\mathsf {Iron}\) [28], so we briefly revisit the main protocol operations: (1) Setup, executed by the trusted party \(\mathsf {C}\), installs a key management enclave (\(\mathsf {KME}\)), running a program to generate public-key encryption and digital signature, key pairs. The public keys are published, while the equivalent secrets are kept encrypted in storage (using SGX’s terminology, the memory is sealed). Each of the decryptors installs a decryption enclave (DE), and attests its authenticity to the KME to receive the secret key for the encryption scheme over a secure channel. (2) KeyGen, on input function \(\mathrm {F}\), calls \(\mathsf {KME}\), where the latter produces a signature on the measurement of an instantiated enclave that computes \(\mathrm {F}\). (3) When Encrypt is called by an encryptor, it uses the published public encryption key to encrypt a message and sends the ciphertext to the intended recipients. (4) Decrypt is executed by a decrypting party seeking to compute some function \(\mathrm {F}\) on a ciphertext. This operation instantiates a matching function enclave (or resume an existing one), whose role is that of computing the functional decryption, if an authorised functional key is provided.

\(\mathsf {Steel}{}\) consists of the above operations, with the appropriate modifications to enable stateful functionalities. In addition, \(\mathsf {Steel}{}\) provides some simplifications over the \(\mathsf {Iron}\) protocol. In particular, we repurpose attestation’s signature capabilities to supplant the need for a separate signature scheme to generate functional keys, and thus minimise the trusted computing base. In practice, a functional key for a function \(\mathrm {F}\) can be produced by just letting the key generation process return \(\mathrm {F}\); as part of \(G_{\mathsf {att}}\)’s execution, this produces an attestation signature \(\sigma \) over \(\mathrm {F}\), which becomes the functional key \(\mathsf {sk}_{\mathrm {F}}\) for that function, provided the generating enclave id is also made public (a requirement for verification, due to the signature syntax of attestation in \(G_{\mathsf {att}}\)).

The statefulness of functional encryption is simply enabled by adding a state array to each functional enclave. The array is also stored locally by the corresponding decryption enclave, and is updated for every decryption of a given function. Similar to [44], a curious artefact in the protocol’s modeling is the addition of a “backdoor” that programs the output of the function evaluation subroutine, such that, if a specific argument is set on the input, the function evaluation returns the value of that argument. The reason for this addition is to enable simulation of signatures over function evaluations that have already been computed using the ideal functionality. We note that this addition does not impact correctness, as the state array is not modified if the backdoor is used, nor confidentiality, since the output of this subroutine is never passed to any other party besides the caller \(\mathsf {B}\). Finally, a further addition is that our protocol requires the addition of a proof of plaintext knowledge on top of the underlying encryption scheme. The \(\mathsf {Steel}\) protocol definition is presented in Sect. 4.

Security of \(\mathsf {Steel}\). Our protocol uses an existentially unforgeable under chosen message attacks (EU-CMA) signature scheme, \(\mathsf {\Sigma }\), a CCA-secure public-key encryption scheme, \(\mathsf {PKE}\), and a non-interactive zero knowledge scheme, \(\mathsf {N}\). Informally, \(\mathsf {\Sigma }\) provides the guarantees required for realizing attested computation (as discussed above), \(\mathsf {PKE}\) is used to protect the communication between enclaves, and for protecting the encryptors’ inputs. For the latter usage, it is possible to reduce the security requirement to CPA-security as we additionally compute a simulation-extractable NIZK proof of well-formedness of the ciphertext that guarantees non-malleability.

Our proof is via a sequence of hybrids in which we prove that the real world protocol execution w.r.t. \(\mathsf {Steel}\) is indistinguishable from the ideal execution, in the presence of an ideal functionality that captures FE for stateful and randomized functionalities. The goal is to prove that the decryptor learns nothing more than an authorized function of the private input plaintext, thus our hybrids gradually fake all relevant information accessed by the adversary. In the first hybrid,Footnote 1 all signature verifications w.r.t. the attestation key are replaced by an idealized verification process, that only accepts message/signature pairs that have been computed honestly (i.e., we omit verification via \(\mathsf {\Sigma }\)). Indistinguishability is proven via reduction to the EU-CMA security of \(\mathsf {\Sigma }\). Next we fake all ciphertexts exchanged between enclaves that carry the decryption key for the target ciphertext, over which the function is evaluated (those hybrids require reductions to the CCA security of \(\mathsf {PKE}\)).Footnote 2 The next hybrid substitutes ZK proofs over the target plaintexts with simulated ones, and indistinguishability with the previous one reduces to the zero knowledge property of \(\mathsf {N}\). Then, for maliciously generated ciphertexts under \(\mathsf {PKE}\) – which might result via tampering with honestly generated encryptors’ ciphertexts – instead of using the decryption operation of \(\mathsf {PKE}\), our simulator recovers the corresponding plaintext using the extractability property of \(\mathsf {N}\). Finally, we fake all ciphertexts of \(\mathsf {PKE}\), that encrypt the inputs to the functions (this reduces to CPA security). Note that, in [28], the adversary outputs the target message, which is then being encrypted and used as a parameter to the ideal world functionality that is accessed by the simulator in a black box way. In this work, we consider a stronger setting in which the adversary directly outputs ciphertexts of it’s choice. While in the classic setting for Functional Encryption (where \(\mathsf {Iron}\) lives) simulation security is easily achieved by asking the adversarial enclave to produce an evaluation for the challenge ciphertext, in \(\mathrm {FESR}\) the simulator is required to conduct all decryptions through the ideal functionality, so that the decryptor’s state for that function can be updated. We address the above challenge by using the extractability property of NIZKs: for maliciously generated ciphertexts our simulator extracts the original plaintext and ask the ideal \(\mathrm {FESR}\) functionality for it’s evaluation. Simulation-extractable NIZK can be efficiently instantiated, e.g., using zk-SNARKs [12]. Security of our protocol is formally proven in Sect. 5. The simulator therein provided could be easily adapted to show that the \(\mathsf {Iron}\) protocol UCGS-realises Functional Encryption, by replacing the NIZK operations for maliciously generated ciphertexts with a decryption from the enclave, as described above.

Rollback and Forking Attacks. Modeling attested execution via \(G_{\mathsf {att}}\) facilitates composable protocol design, however, such a functionality cannot be easily realized since real world adversaries can perform highly non-trivial rollback and forking attacks against hardware components. In Sect. 6, we define a weaker functionality for attested execution, called \(G^{\mathsf {rollback}}_{\mathsf {att}}\), that aims to capture rollback and forking attacks. To achieve this, we replace the enclave storage array in \(G_{\mathsf {att}}\) with a tree data structure. While the honest party only ever accesses the last leaf of the tree (equivalent to a linked list), a corrupt party is able to provide an arbitrary path within the tree. This allows them to rollback the enclave, by re-executing a previous (non-leaf) state, and to support multiple forks of the program by interactively selecting different sibling branches. We give an example \(\mathrm {FESR}\) function where we can show that correctness does not hold if \(G^{\mathsf {rollback}}_{\mathsf {att}}\) is used instead of \(G_{\mathsf {att}}\) within \(\mathsf {Steel}\), and discuss how countermeasures from the rollback protection literature can be adopted to address these attacks, with a consideration on efficiency.

1.3 Related Work

Hardware is frequently used to improve performance or circumvent impossibility results, e.g. [4, 26, 42]. As a relevant example, Chung et al. [25] show how to use of stateless hardware tokens to implement functional encryption.

The use of attestation has been widely adopted in the design of computer systems to bootstrap security [43]. In addition to formalising attested execution, Pass, Shi and Tramer (PST) [44] show that two-party computation is realisable in UC only if both parties have access to attested execution, and fair two-party computation is also possible if additionally both secure processors have access to a trusted clock. The PST model is the first work to formalise attested execution in the UC framework. The compositional aspect of UC allows for the reused of the model in several successive works [22, 24, 52, 54]. Other attempts at providing a formal model for attested execution include the game-based models of Barbosa et al. [15], Bahmani et al. [13], Fisch et al. [28]. The latter model arises from the need to evaluate the security of \(\mathsf {Iron}\), a hardware-based realisation of functional encryption, which was later extended to verifiable functional encryption in Suzuki et al. [51].

Rollback attacks (also known as reset attacks in the cryptographic literature) are a common attack vectors against third-party untrusted computing infrastructure. An attacker who is in control of the underlying infrastructure can at times simply restart the system to restore a previous system state. Yilek [55] presents a general attack that is applicable to both virtual machine and enclave executions: it shows that an adversary capable of executing multiple rollback attacks on IND-CCA or IND-CPA secure encryption schemes might learn information about encrypted messages by running the encryption algorithm on multiple messages with the same randomness. In the absence of true hardware-based randomness that cannot be rolled back, these kinds of attacks can be mitigated using hedged encryption, a type of key-wrap scheme [32], such that for each encryption round, the original random coin and the plaintext are passed through a pseudorandom function to generate the randomness for the ciphertext.

The area of rollback attacks on TEEs is well studied. Platforms like SGX [21], TPMs [39], etc. provide trusted monotonic counters, from which it is possible to bootstrap rollback-resilient storage. However, trusted counters are too slow for most practical applications. Furthermore, they wear out after a short period of time. As their lifetime is limited, they are unreliable for applications that require frequent updates [40]. Moreover, an adversary that is aware of this vulnerability can attack protocols that rely exclusively on counters, by instantiating a malicious enclave on the same platform that artificially damages the counters.

To overcome the limitation of SGX counters, ROTE [40] uses a consensus protocol to build a distributed trusted counter service, with performance necessarily reduced through several rounds of network communication. In the same spirit, Ariadne [50] is an optimized (local) synchronous technique to increment the counter by a single bit flip for deterministic enclaves.

Speicher [14] and Palaemon [31] proposed an asynchronous trusted counter interface, which provide a systematic trade-off between performance and rollback protection, addressing some limitations of synchronous counters. The asynchronous counter is backed up by a synchronous counter interface with a period of vulnerability, where an adversary can rollback the state of a TEE-equipped storage server in a system until the last stable synchronous point. To protect against such attacks, these systems rely on the clients to keep the changes in their local cache until the counter stabilizes to the next synchronisation point.

Lightweight Collective Memory (Brandenburger et al. [17]) is a proposed framework that claims to achieve fork-linearizability: each honest client that communicates with a TEE (on an untrusted server that might be rolled back) can detect if the server is being inconsistent in their responses to any of the protocol clients (i.e. if they introduce any forks or non-linearity in their responses). Finally, [35, 36, 53], protect hardware memory against active attacks, while [6, 34], protect cryptographic hardware against tampering and Trojan injection attacks, respectively.

2 Preliminaries

2.1 UC Background

Universal Composability (UC), introduced by Canetti [18], is a security framework that enables the security analysis of cryptographic protocols. It supports the setting where multiple instances of the same, or different protocols, can be executed concurrently. Many extensions and variants of the framework have been proposed over the years; our treatment is based on the recently released Universal Composability with Global Subroutines framework (UCGS) [10] and the 2020 version of UC [18]. We briefly summarise the aspects of UC and UCGS necessary to understand our work.

Universal Composability. Consider two systems of PPT interactive Turing machine instances \((\pi ,\mathcal {A},\mathcal {Z})\) and \((\phi ,\mathcal {S},\mathcal {Z})\), where \(\mathcal {Z}\) is the initial instance, and \(\pi ,\mathcal {A}\) (and respectively \(\phi ,\mathcal {S}\)) have comparable runtime balanced by the inputs of \(\mathcal {Z}\). We say that the two systems are indistinguishable if \(\mathcal {Z}\) making calls to \(\pi ,\mathcal {A}\) (resp. \(\phi ,\mathcal {S}\)) cannot distinguish which system it is located in. The two systems are commonly referred to as the real and ideal world (respectively). \(\mathcal {Z}\) can make calls to instances within the protocol by assuming the (external) identity of arbitrary instances (as defined by the control function). Depending on the protocol settings, it might be necessary to restrict the external identities available to the environment. A \(\xi \)-identity-bounded environment is limited to assume external identities as specified by \(\xi \), a polynomial time boolean predicate on the current system configuration.

We now recall a few definitions. Please consult [10, 18] or our full version for the formal definitions of terms such as balanced, respecting, exposing, compliant.

Definition 1

(UC emulation [18]). Given two PPT protocols \(\pi ,\phi \) and some predicate \(\xi \), we say that \(\pi \) UC-emulates \(\phi \) with respect to \(\xi \)-identity bound environments (or \(\pi \) \(\xi \)-UC-emulates \(\phi \)) if for any balanced \(\xi \)-identity-bounded environment and any PPT adversary, there exists a PPT simulator \(\mathcal {S}\) such that the systems \((\phi ,\mathcal {S},\mathcal {Z})\) and \((\pi ,\mathcal {A},\mathcal {Z})\) are indistinguishable.

Given a protocol \(\pi \) which UC-emulates a protocol \(\phi \), and a third protocol \(\rho \), which calls \(\phi \) as a subroutine, we can construct a protocol where all calls to \(\phi \) are replaced with calls to \(\pi \), denoted as \(\rho ^{\phi \rightarrow \pi }\).

Theorem 1

(Universal Composition [18]). Given PPT protocols \(\pi ,\phi ,\rho \) and predicate \(\xi \), if \(\pi ,\phi \) are both subroutine respecting and subroutine exposing , \(\rho \) is \((\pi ,\phi ,\xi )\)-compliant and \(\pi \) \(\xi \)-UC-emulates \(\phi \), then protocol \(\rho ^{\phi \rightarrow \pi }\) UC-emulates \(\rho \)

By the composition theorem, any protocol that leverages subroutine \(\phi \) in its execution can now be instantiated using protocol \(\pi \).

UCGS. As the name suggests, generalised UC (GUC) [19] is an important generalization of the UC model. It accounts for the existence of a shared subroutine \(\gamma \), such that both \(\rho \) and its subroutine \(\pi \) (regardless of how many instances of \(\pi \) are called by \(\rho \)) can have \(\gamma \) as a subroutine. The presence of the global subroutine allows proving protocols that rely on some powerful functionality that needs to be globally accessible, such as a public key infrastructure (PKI) [20], a global clock [8], or trusted hardware [44].

Unfortunately GUC has inconsistencies and has not been updated from the 2007 to the 2020 version of UC.Footnote 3 Universal Composability with Global Subroutines [10] aims to rectify these issues by embedding UC emulation in the presence of a global protocol within the standard UC framework.

To achieve this, a protocol \(\pi \) with access to subroutine \(\gamma \) is replaced by a new structured protocol \(\mu = M[\pi ,\gamma ]\), known as management protocol; \(\mu \) allows multiplexing a single instance of \(\pi \) and \(\gamma \) into however many are required by \(\rho \), by transforming the session and party identifiers. \(\mu \) is a subroutine exposing protocol, and is given access to an execution graph directory instance, which tracks existing machines within the protocol, and the list of subroutine calls (implemented as a structured protocol). The execution graph directory can be queried by all instances within the extended session of \(\mu \), and is used to redirect the outputs of \(\pi \) and \(\gamma \) to the correct machine.

Below we revisit the UC emulation with global subroutines definition from [10].

Definition 2

(UC Emulation with Global Subroutines [10]). Given protocols \(\pi ,\phi ,\text {and }\gamma \), \(\pi \) \(\xi \)-UC emulates \(\phi \) in the presence of \(\gamma \) if \(M[\pi ,\gamma ]\) \(\xi \)-UC emulates \(M[\phi ,\gamma ]\)

Now we state the main UCGS theorem.

Theorem 2

(Universal Composition with Global Subroutines [10]). Given subroutine-exposing protocols \(\pi ,\phi ,\rho ,\text {and }\gamma \), if \(\gamma \) is a \(\phi \)-regular setup and subroutine respecting, \(\phi ,\pi \) are \(\gamma \)-subroutine respecting, \(\rho \) is \((\pi ,\phi ,\xi )\)-compliant and \((\pi ,M[x,\gamma ],\xi )\)-compliant for \(x \in \{\phi ,\pi \}\), then if \(\pi \) \(\xi \)-UC-emulates \(\phi \) in the presence of \(\gamma \), the protocol \(\rho ^{\phi \rightarrow \pi }\) UC-emulates \(\rho \) in the presence of \(\gamma \).

2.2 The \(G_{\mathsf {att}}\) Functionality

We now reproduce the \(G_{\mathsf {att}}\) global functionality defined in the PST model [44]. The functionality is parameterised with a signature scheme and a registry to capture all platforms with a TEE. The below functionality diverges from the original one in that we let \(\mathsf {vk}\) be a global variable, accessible by enclave programs as \(G_{\mathsf {att}}.\mathsf {vk}\). This allows us to use \(G_{\mathsf {att}}\) for protocols where the enclave program does not trust the caller to its procedures to pass genuine inputs, making it necessary to conduct the verification of attestation from within the enclave.

figure a

The \(G_{\mathsf {att}}\) functionality is a generalisation over other TEE formalisations, such as the one in [28], which tries to closely model some SGX implementation details. For instance, their hardware primitive distinguishes between local and remote attestation by exposing two sets of functions to produce and verify reports (for local attestation) and quotes (for remote attestation). Both data structure include enclave metadata, a tag that can uniquely identify the running program, input and output to the computation and some authentication primitive based on the former (MAC for local reports, signature for remote quotes). The \(G_{\mathsf {att}}\) primitive, intended as an abstraction over different vendor implementations, removes much of this detail: both local and remote attestation consist in verifying the output of a resume call to some enclave through a public verification key, available both to machines with and without enclave capabilities. The output of computations is similarly the (anonymous) id of the enclave, the UC session id, some unique encode for the code computed by the enclave (which could be its source code, or its hash), and the output of the computation. Unlike in the \(\mathsf {Iron}\) model, input does not have to be included in the attested return value, but if security requires parties to verify input, the function ca return it as part of its output. On enclave installation, its memory contents are initialised by the specification of its code; this initial memory state is represented by symbol \(\emptyset \).

3 Functional Encryption for Stateful and Randomized Functionalities

In this section we define the ideal functionality of functional encryption for stateful and randomized functionalities (\(\mathrm {FESR}\)).

\(\mathrm {FESR}\) syntax.

  • (Setup): given security parameter \(1^{\lambda }\) as input, \(\mathsf {KeyGen}\) outputs master keypair \(\mathsf {mpk},\mathsf {msk}\)

  • (Key generation): \(\mathsf {Setup}\) takes \(\mathsf {msk}, \mathrm {F}\in \mathtt {F}\) and returns functional key \(\mathsf {sk}_{\mathrm {F}}\)

  • (Encryption): given string \(\mathsf {x} \in \mathcal {X}\) and \(\mathsf {mpk}\), \(\mathsf {Enc}\) returns ciphertext \(\mathsf {ct}\) or an error

  • (Decryption): on evaluation over some ciphertext ct and functional key \(\mathsf {sk}_{\mathrm {F}}\), \(\mathsf {Dec}\) returns \(\mathsf {y} \in \mathcal {Y}\)

While the above definition matches with that of classical functional encryption, we inject non-determinism and statefulness (respectively) by adding two additional inputs to functions in the allowed function class

$$\mathtt {F}: \mathcal {X}\times \mathcal {S}\times \mathcal {R}\rightarrow \mathcal {Y}\times \mathcal {S}$$

where \(\mathcal {S}= \{0,1\}^{s(\lambda )}, \mathcal {R}= \{0,1\}^{r(\lambda )}\) for polynomials \(s(\cdot )\) and \(r(\cdot )\).

3.1 Properties of \(\mathrm {FESR}\)

Matt and Maurer [41] shows that the notion of functional encryption is equivalent, up to assumed resources, to that of an access control (AC) repository, where some parties \(\mathsf {A}\) are allowed to upload data, and other parties \(\mathsf {B}\) are allowed to retrieve some function on that data, if they have received authorisation (granted by a party \(\mathsf {C}\)). A party \(\mathsf {B}\) does not learn anything else about the stored data, besides the function they are authorised to compute (and length leakage \(\mathrm {F}_0\)).

To allow stateful and randomized functions, we extend the function class with support for private state and randomness as above. Whenever \(\mathsf {B}\) accesses a function on the data from the repository, the repository draws fresh randomness, evaluates the function on the old state. The function updates the state and evaluates to a value. Intuitively, this ideal world AC repository models both confidentiality and correctness:

Confidentiality. Confidentiality holds as \(\mathsf {B}\) does not learn anything about the data besides the evaluations of these stateful randomized functions.

Correctness. A stateful functionality defines a stateful automaton, a set of states \(\mathcal {S}\), the initial state \(\emptyset \in \mathcal {S}\), a probabilistic transition function \(\delta : \mathcal {X}\times \mathcal {S}\rightarrow \mathcal {Y}\times \mathcal {S}\). For every transition, a new input is sampled from \(\mathcal {R}\) and given to \(\mathrm {F}\) along with the input, to determine the next state. The transition function determines, for a given input and the current state, the probability \(\Pr _{\delta }\) that the automaton will find itself in a certain next state, as well as an output value. Correctness requires that all consecutive outputs must always be justified by some input and a state reachable via \(\delta \) from \(\emptyset \).

Correctness holds for the ideal world AC repository as \(\mathsf {B}\) can make exactly those state transitions by accessing a function on the data from the repository.

3.2 UC Functionality

Our treatment considers the existence of several parties of type \(\mathsf {A}\) (encryptors), \(\mathsf {B}\) (decryptors), and a singular trusted authority \(\mathsf {C}\). The latter is allowed to run the \(\mathsf {KeyGen},\mathsf {Setup}\) algorithms; parties of type \(\mathsf {A}\) run \(\mathsf {Enc}\), and those of type \(\mathsf {B}\) run \(\mathsf {Dec}\). The set of all decryptors (resp. encryptors) is denoted by \(\mathbf {B}\) (resp. \(\mathbf {A}\)). When the functionality receives a message from such a party, their UC extended id is used to distinguish who the sender is and store or retrieve the appropriate data. For simplicity, in our ideal functionality we refer to all parties by their type, with the implied assumption that it might refer to multiple distinct UC parties. For the sake of conciseness, we also omit including the \(\mathsf {sid}\) parameter as an argument to every message.

The functionality reproduces the four algorithms that comprise functional encryption. During \(\mathsf {KeyGen}\), a record \(\mathcal {P}\) is initialised for all t instances of \(\mathsf {B}\), to record the authorised functions for each instance, and its state. The \(\mathsf {Setup}\) call marks a certain \(\mathsf {B}\) as authorised to decrypt function \(\mathrm {F}\), and initialises its state to \(\emptyset \). The \(\mathsf {Enc}\) call allows a party \(\mathsf {A}\), \(\mathsf {B}\), to provide some input \(\mathrm {x}\), and receive a unique identifying handle \(\mathsf {h}\). This handle can then be provided, along with some \(\mathrm {F}\), to a decryption party to obtain an evaluation of \(\mathrm {F}\) on the message stored therein. Performing the computation will also result in updating the state stored in \(\mathcal {P}\).

figure b

The functionality is defined for possible corruptions of parties in \(\mathbf {B}\), \(\mathbf {A}\). If \(\mathsf {C}\) is corrupted, we can no longer guarantee the evaluation to be correct, since \(\mathsf {C}\) might authorize the adversary to compute any function in \(\mathtt {F}\). In this scenario, we allow the adversary to learn the original message value \(\mathrm {x}\) and to provide an arbitrary evaluation \(\mathrm {y}\).

Note that, our definition is along the lines of [11, 41], however, as opposed to [11], in which \(\mathsf {A}\) and/or \(\mathsf {C}\) might also get corrupted, in this work we primarily focus on the security guarantees provided by FE, which is confidentiality of the encrypted message against malicious decryptors, \(\mathsf {B}\). Yet, it provides security against malicious encryptors, \(\mathsf {A}\), thus it satisfies input consistency, which was originally introduced by [11]. In addition, our definition is the first one that captures stateful and randomized functionalities, where the latter refers to the standard notion of randomized functionalities in which each invocation of the function uses independent randomness. Therefore, our protocol achieves a stronger notion of randomized \(\mathsf {FE}\) than [2, 30, 37], which require a new functional key for each invocation of the function, i.e., decryptions with the same functional key always return the same output.

Both correctness and confidentiality clearly hold for the ideal functionality by inspection of the 4 lines \(\mathrm {r}\leftarrow \mathcal {R}\), \(\mathsf {s}\leftarrow \mathcal {P}[\mathsf {B},\mathrm {F}]\), \((\mathrm {y},\mathsf {s}') \leftarrow \mathrm {F}(\mathrm {x},\mathsf {s},\mathrm {r})\), and \(\mathcal {P}[\mathsf {B},\mathrm {F}] \leftarrow \mathsf {s}'\).

4 A UC-Formulation of \(\mathsf {Steel}\)

In this section we present \(\mathsf {Steel}\) in the UCGS setting. As we already state above, our treatment involves three roles: the key generation party \(\mathsf {C}\), the decryption parties \(\mathbf {B}\), and the encryption parties \(\mathbf {A}\). Among them, only the encryptor does not need to have access to an enclave. Like the \(\mathrm {FESR}\) functionality, the protocol fulfills confidentiality and correctness in the face of an adversarial \(\mathsf {B}\). We do not give any guarantees of security for corrupted \(\mathsf {A},\mathsf {C}\); although we remark informally that, as long as its enclave is secure, a corrupted \(\mathsf {C}\) has little chances of learning the secret key. Besides the evaluation of any function in \(\mathtt {F}\) it authorises itself to decrypt, it can also fake or extract from proofs of ciphertext validity \(\pi \) by authorizing a fake reference string \(\mathsf {crs}\). Before formally presenting our protocol we highlight important assumptions and conventions:

  • For simplicity of presentation, we assume a single instance each for \(\mathsf {A}\), \(\mathsf {B}\)

  • all communication between parties \((\alpha ,\beta )\) occurs over secure channels \(\mathcal {SC}^{\beta }_{\alpha },\mathcal {SC}^{\alpha }_{\beta }\)

  • Functional keys are (attestation) signatures by an enclave \(\mathsf {prog}_{\mathsf {\mathsf {KME}}}\) on input \((\mathrm {keygen},\mathrm {F})\) for some function \(\mathrm {F}\); it is easy, given a list of keys, to retrieve the one which authorises decryptions of \(\mathrm {F}\)

  • keyword fetch retrieves a stored variable from memory and aborts if the value is not found

  • on keyword \(\mathbf{assert} ~\), the program checks that an expression is true, and proceeds to the next line, aborting otherwise

  • all variables within an enclave are erased after use, unless saved to encrypted memory through the store keyword

Protocol \(\mathsf {Steel}\) is parameterised by a function family \(\mathtt {F}: \mathcal {X}\times \mathcal {S}\times \mathcal {R}\rightarrow \mathcal {Y}\times \mathcal {S}\), UC parties \(\mathsf {A},\mathsf {B},\mathsf {C}\), a CCA secure public key encryption scheme \(\mathsf {PKE}\), a EU-CMA secure signature scheme \(\Sigma \), a Robust non-interactive zero-knowledge scheme \(\mathsf {N}\), and security parameter \(\lambda \).

figure c
figure d
figure e

As we mention in the Introduction, our modeling considers a “backdoor” in the \(\mathsf {prog}_{\mathsf {\mathsf {FE}}}.\mathrm {run}\) subroutine, such that, if the last argument is set, the subroutine just returns the value of that argument, along with a label declaring computation. The addition of the label computed is necessary, otherwise the backdoor would allow producing an attested value for the public key generated in subroutine \(\mathsf {prog}_{\mathsf {\mathsf {FE}}}.\mathrm {init}\).

As a further addition we strengthen the encryption scheme with a plaintext proof of knowledge (PPoK). For public key \(\mathsf {pk}\), ciphertext \(\mathsf {ct}\), plaintext \(\mathrm {m}\), ciphertext randomness \(\mathrm {r}\), the relation \( R =\{(\mathsf {pk},\mathsf {ct}), (\mathrm {m},\mathrm {r}) | \mathsf {ct}= \mathsf {PKE}.\mathsf {Enc}(\mathsf {mpk}, \mathrm {m};\mathrm {r})\}\) defines the language \(\mathrm {L}_{ R }\) of correctly computed ciphertexts. As a chosen-plaintext secure \(\mathsf {PKE}\) scheme becomes CCA secure when extended with a simulation-extractable PPoK this is a natural strengthening of the CCA security requirement of \(\mathsf {Iron}\). However, it enables the simulator to extract valid plaintexts from all adversarial ciphertexts. In our security proof the simulator will submit these plaintexts to \(\mathrm {FESR}\) on behalf of the corrupt \(\mathsf {B}\) to keep the decryption states of the real and ideal world synchronized.

5 UC-Security of \(\mathsf {Steel}\)

We now prove the security of \(\mathsf {Steel}\) in the UCGS framework. To make the PST model compatible with the UCGS model, we first define the identity bound \(\xi \).

The Identity Bound \(\xi \) on the Environment. Our restrictions are similar to [44], namely we assume that the environment can access \(G_{\mathsf {att}}\) in the following ways: (1) Acting as a corrupt party, and (2) acting as an honest party but only for non-challenge protocol instances.

We now prove our main theorem.

Theorem 3

\(\mathsf {Steel}{}\) (Sect. 4) UC-realizes the \(\mathrm {FESR}\) functionality (Sect. 3) in the presence of the global functionality \(G_{\mathsf {att}}\) and local functionalities \(\mathcal {CRS},\mathcal {REP},\mathcal {SC}\), with respect to the identity bound \(\xi \) defined above.

We present a simulator algorithm such that, for all probabilistic adversaries running in polynomial time with the ability of corrupting \(\mathsf {B}\). Following [41], our proof considers static corruption of a single party \(\mathsf {B}\), we did, however, not encounter any road-blocks to adaptive corruption of multiple decryptors besides increased proof notational complexity. The environment is unable to distinguish between an execution of the \(\mathsf {Steel}\) protocol in the real world, and the protocol consisting of \(\mathcal {S}_{\mathrm {FESR}}\), dummy parties \(\mathsf {A}\), \(\mathsf {C}\) and ideal functionality \(\mathrm {FESR}\). Both protocols have access to the shared global subroutines of \(G_{\mathsf {att}}\). While hybrid functionalities \(\mathcal {REP}\), \(\mathcal {SC}\), \(\mathcal {CRS}\) (for their definition, see the full version) are only available in the real world and need to be reproduced by the simulator, we use \(\mathcal {SC}\) in the simulator to denote simulated channels, either between the simulator and corrupted parties (for corrupt parties), or between the simulator and itself (for honest parties).

Given protocols \(\mathsf {Steel}\), \(\mathrm {FESR}\), and \(G_{\mathsf {att}}\), \(\mathsf {Steel}\) \(\xi \)-UC emulates \(\mathrm {FESR}\) in the presence of \(G_{\mathsf {att}}\) if \(M[\mathsf {Steel},G_{\mathsf {att}}]\) \(\xi \)-UC emulates \(M[\mathrm {FESR},G_{\mathsf {att}}]\) (see Definition 2). We focus or exposition on the messages exchanged between the environment and the machine instances executing \(\mathsf {Steel}\), \(\mathrm {FESR}\), and \(G_{\mathsf {att}}\), since the machine M is simply routing messages; i.e., whenever \(\mathcal {Z}\) wants to interact with the protocol, M simply forwards the message to the corresponding party; the same holds for \(G_{\mathsf {att}}\).

The simulator operates in the ideal world, where we have the environment \(\mathcal {Z}\) sending message to dummy protocol parties which forward their inputs to the ideal functionality \(\mathrm {FESR}\). \(\mathcal {S}_{\mathrm {FESR}}\) is activated either by an incoming message from a corrupted party or the adversary, or when \(\mathrm {FESR}\) sends a message to the ideal world adversary. As \(\mathcal {A}\) is a dummy adversary which normally forwards all queries between the corrupt party and the environment, \(\mathcal {S}_{\mathrm {FESR}}\) gets to see all messages \(\mathcal {Z}\) sends to \(\mathcal {A}\). The simulator is allowed to send messages to the \(\mathrm {FESR}\) and \(G_{\mathsf {att}}\) functionalities impersonating corrupt parties. In the current setting, the only party that can be corrupted such that \(\mathrm {FESR}\) still gives non trivial guarantees is party \(\mathsf {B}\). Thus, whenever the real world adversary or the ideal world simulator call \(G_{\mathsf {att}}.\mathsf {install}\) and \(G_{\mathsf {att}}.\mathsf {resume}\) for the challenge protocol instance, they must do so using an extended identity of \(\mathsf {B}\).

figure f
figure g
figure h

Designing the Simulation. The ideal functionality \(\mathrm {FESR}\) and protocol \(\mathsf {Steel}\) share the same interface consisting of messages , , , . During \(\mathsf {Steel}\)’s , the protocol generates public parameters when first run, and provisions the encrypted secret key to the enclaves of \(\mathsf {B}\). As neither of these operations are executed by the ideal functionality, we need to simulate them, generating and distributing keys outside of party \(\mathsf {C}\).

As in \(\mathsf {Steel}{}\), we distribute the public encryption key on behalf of \(\mathsf {C}\) to any newly registered \(\mathsf {B}\) and \(\mathsf {A}\) over secure channels. Once \(\mathsf {B}\) has received this message, it will try to obtain the (encrypted) decryption key for the global \(\mathsf {PKE}\) scheme from party \(\mathsf {C}\) and its \(\mathrm {provision}\) subroutine of \(\mathsf {prog}_{\mathsf {\mathsf {KME}}}\). Since \(\mathsf {C}\) is a dummy party in the ideal world, it would not respond to this request, so we let \(\mathcal {S}_{\mathrm {FESR}}\) respond. In \(\mathsf {Steel}{}\) key parameters are generated within the key management enclave, and communication of the encrypted secret key to the decryption enclave produces an attestation signature. Thus, the simulator, which can access \(G_{\mathsf {att}}\) impersonating \(\mathsf {B}\), is required to install an enclave. Because of the property of anonymous attestation, the environment cannot distinguish whether the new enclave was installed on \(\mathsf {B}\) or \(\mathsf {C}\). If the environment tries to resume the program running under \(\mathsf {eid}_{\mathsf {\mathsf {KME}}}\) through \(\mathsf {B}\), this is intercepted and dropped by the simulator.

Before sending the encrypted secret key, the simulator verifies that \(\mathsf {B}\)’s public key was correctly produced by an attested decryption enclave, and was initialised with the correct parameters. If an honest enclave has been instantiated and we can verify that it uses \(\mathsf {pk}_{KD},\mathsf {eid}_{\mathsf {\mathsf {KME}}},\mathsf {crs}\), we can safely send the encrypted \(\mathsf {sk}\) to the corrupted party as no one can retrieve the decryption key from outside the enclave.

On message from the functionality after a call to , \(\mathcal {S}_{\mathrm {FESR}}\) simply produces a functional key by running the appropriate \(\mathsf {prog}_{\mathsf {\mathsf {KME}}}\) procedure through \(G_{\mathsf {att}}\). Similarly, on receiving for \(\mathcal {REP}\), \(\mathcal {S}_{\mathrm {FESR}}\) produces an encryption of a canonical message (a string of zeros) and simulates the response.

When the request to compute the functional decryption of the corresponding ciphertext is sent to \(\mathsf {prog}_{\mathsf {\mathsf {FE}}}[\mathrm {F}]\), we verify that the party \(\mathsf {B}\) has adhered to the \(\mathsf {Steel}\) protocol execution, aborting if any of the required enclave installation or execution steps have been omitted, or if any of the requests were made with dishonest parameters generated outside the enclave execution (we can verify this through the attestation of enclave execution). If the ciphertext was not obtained through a request to \(\mathcal {REP}\), we use the NIZK extractor to learn the plaintext \(\mathrm {m}\) and submit a message to \(\mathrm {FESR}\) on behalf of the corrupt \(\mathsf {B}\). This guarantees that the state of \(\mathrm {FESR}\) is in sync with the state of \(\mathsf {prog}_{\mathsf {\mathsf {FE}}}[\mathrm {F}]\) in the real world.

If all such checks succeed, and the provided functional key is valid, \(\mathcal {S}_{\mathrm {FESR}}\) fetches the decryption from the ideal functionality. While the \(\mathsf {Steel}\) protocol ignores the value of the attested execution of \(\mathrm {run}\), we can expect the adversary to check its result for authenticity. Therefore, it is necessary to pass the result of our decryption \(\mathrm {y}\) through the backdoor we constructed in \(\mathsf {prog}_{\mathsf {\mathsf {FE}}}[\mathrm {F}]\). This will produce an authentic attestation signature on \(\mathrm {y}\), which will pass any verification check convincingly (as discussed in the previous section, the backdoor does not otherwise impact the security of the protocol).

The full proof of security is available in the full version; for an overview, refer to Sect. 1.2.

6 Rollback and Forking Attacks

While the Attested Execution functionality modelled by \(G_{\mathsf {att}}\) is a meaningful first step for modeling attested execution, it is easy to argue that it is not realisable (in a UC-emulation sense) by any of the existing Trusted Execution Environment platforms to date. In a follow-up paper, Tramer et al. [52] weaken the original \(G_{\mathsf {att}}\) model to allow complete leakage of the memory state. This is perhaps an excessively strong model, as the use of side channel attacks might only allow a portion of the memory or randomness to be learned by the adversary. Additionally, there are many other classes of attacks that can not be expressed by this model. We now extend the \(G_{\mathsf {att}}\) functionality to model rollback and forking attacks against an enclave.

6.1 \(G^{\mathsf {rollback}}_{\mathsf {att}}\) Functionality

Our model of rollback and forking attacks is drawn from the formulation expressed in Matetic et al. [40], but with PST’s improved modelling of attestation, which does not assume perfectly secure authenticated reads/writes between the attester and the enclave.

Matetic et al. model rollback by distinguishing between enclaves and enclave instances. Enclave instances have a distinct memory state, while sharing the same code. As with \(G_{\mathsf {att}}\), where the outside world has to call subroutines individually, the environment is not allowed to interact directly with a program once it is instantiated, except for pausing, resuming, or deleting enclave instances. Additionally, their model provides functions to store encrypted memory outside the enclave (Seal) and load memory back (Unseal).

In a typical rollback attack, an attacker crashes an enclave, erasing its volatile memory. As the enclave instance is restarted, it attempts to restart from the current state snapshot. By replacing this with a stale snapshot, the attacker is able to rewind the enclave state.

In a forking attack an attacker manages to run two instances of the same enclave concurrently, such that, once the state of one instance is changed by an external operation, querying the other instance will result in an outdated state. This relies on both enclaves producing signature that at the minimum attest the same program. On a system where attestation uniquely identifies each copy of the enclave, a forking attack can still be launched by an attacker conducting multiple rollback attacks and feeding different stale snapshots to a single enclave copy [17].

Our new functionality \(G^{\mathsf {rollback}}_{\mathsf {att}}\) employs this idea to model the effect of both rollback and forking attacks. We replace the internal \(\mathsf {mem}\) variable of \(G_{\mathsf {att}}\) with a tree data structure. The honest caller to the functionality will always continue execution from the memory state of an existing leaf of the tree while an adversary can specify an arbitrary node of the tree (through a unique node identifier), to which the state of the enclave gets reset. The output \(\mathsf {mem}'\) will then be appended as a new child branch to the tree. To model a rollback attack, the adversary specifies the parent node for the next call to \(\mathsf {resume}\) (or any ancestor node to execute a second rollback). To model a forking attack, the adversary can interactively choose nodes in different branches of the tree. The functionality is parameterised with a signature scheme and a registry to capture all platforms with a TEE, like in the original formulation.

figure i

The proposed rollback model is perhaps somewhat reductive, as it only allows “discrete” rollback operations, where memory states are quantised by program subroutines. It is conceivable that real world attackers would have a finer-grained rollback model, where they can interrupt the subroutine’s execution, and resume from an arbitrary instruction.

Attack on Stateful Functional Encryption. Although our protocol uses probabilistic primitives, we deem the generic reset attack presented in [55] unrealistic for TEE platforms such as SGX, where an enclave is allowed direct access to a hardware-based source of randomness [7].

On the other hand, it easy to find a protocol-specific rollback attack on \(\mathsf {Steel}\). While \(\mathrm {F}\)’s state remains secret to a corrupt \(\mathsf {B}\) interacting with \(G^{\mathsf {rollback}}_{\mathsf {att}}\) (the memory is still sealed when stored), an adversary can make enclave calls produce results that would be impossible in the simpler model. As an example, take the following function from \(\mathtt {F}\) that allows setting a key and sampling the output of a PRF function \(\mathrm {F}\) for a single message:

figure j

An adversary who has completed initialisation of its decryption enclave with enclave id \(\mathsf {eid}_{\mathsf {\mathsf {DE}}}\), obtained a functional key \(\mathsf {sk}\) through the execution of \(\mathrm {keygen}\) on \(\mathsf {eid}_{\mathsf {KME}}\), and initialised a functional enclave for \(\textsc {PRF-Wrapper}\) with enclave id \(\mathsf {eid}_{\mathsf {\mathrm {F}}}\), public key \(\mathsf {pk}_{\mathsf {FD}}\) and attestation \(\sigma _{\mathsf {}}\), executes the current operations for three ciphertexts \(\mathsf {ct}_{\mathrm {K}},\mathsf {ct}_{\mathrm {x}},\mathsf {ct}_{\mathrm {x'}}\), encrypting a key \(\mathrm {K}\) and plaintexts \(\mathrm {x,x'}\):

figure k

As a result of this execution trace, the adversary violates correctness by inserting an illegal transition (with input \(\epsilon \)) in the stateful automaton for PRF-Wrapper, from state \(\mathsf {access(\mathsf {tree},\mathsf {node}'. child )}=\vec {1}\) back to \(\mathsf {access(\mathsf {tree},\mathsf {node}')}=[K]\), and then back to state \(\vec {1}\) with input \(\mathrm {x}'\). The adversary can then obtain the illegal set of values \(\mathrm {y} \leftarrow \mathrm {F}_{\mathrm {K}}(\mathrm {x})\) and \(\mathrm {y}' \leftarrow \mathrm {F}_{\mathrm {K}}(\mathrm {x}')\), whereas in the ideal world after obtaining \(\mathrm {y}\), the only possible output for the function would be \(\bot \) (the only legal transition from state \(\vec {1}\) leads back to itself). The simulator is unable to address this attack, as the memory state is internal to the ideal functionality, and the key will always be erased after the second call.

One might think that the simulator could respond by sampling a value from the uniform distribution and feed it through the enclave’s backdoor; however, the environment can reveal the key \(\mathrm {k}\) and messages \(\mathrm {x,x'}\) to the adversary, or conversely the adversary could reveal the uniform value to the environment. Thus the environment can trivially distinguish between the honest PRF output and the uniform distribution, and thus between the real and ideal world. Note that this communication between environment and adversary is necessary for universal composition as this leakage of \(\mathrm {k,x,x'}\) could happen as part of a wider protocol employing functional encryption.

Mitigation Techniques. In Sect. 1.3, we showed that rollback resilience for trusted execution environments is an active area of research, with many competing protocols. However, most solutions inevitably entail a performance trade-off.

Due to the modular nature of \(\mathsf {Steel}\), it is possible to minimise the performance impact. Observe that party \(\mathsf {B}\) instantiates a single DE and multiple FE. We can reduce the performance penalty by making only DE rollback resilient. We guarantee correctness despite rollbacks of FE, by encoding a counter alongside the function state for each \(\mathrm {F}\). On a decryption request, the \(\mathsf {prog}_{\mathsf {FE}}\) enclave is required to check in with the \(\mathsf {prog}_{\mathsf {DE}}\) enclave to retrieve the decryption key as part of the \(\mathrm {provision}\) call. To enable rollback resilience, we include the counter stored by \(\mathsf {prog}_{\mathsf {FE}}\) as an additional parameter of this call. \(\mathsf {prog}_{\mathsf {DE}}\) compares the counter received for the current evaluation of \(\mathrm {F}\) with the one received during the last evaluation, and authorises the transfer of the secret key only if greater. Before evaluating the function, \(\mathsf {prog}_{\mathsf {FE}}\) increases and stores its local counter.

To achieve rollback resilience for the \(\mathsf {prog}_{\mathsf {DE}}\) enclave, we can rely on existing techniques in the literature, such as augmenting the enclave with asynchronous monotonic counters [14], or using protocols like LCM [17] or ROTE [40]. Formalising how these protocols can be combined with the \(G^{\mathsf {rollback}}_{\mathsf {att}}\) functionality to achieve the fully secure \(G_{\mathsf {att}}\) is left for future work.

We also note that Stateless functional encryption as implemented in IRON is resilient to rollback and forking because there is little state held between computation. Since we assume \(\mathsf {C}\) is honest, the only programs liable to be attacked are DE and FE[F].

DE stores PKE Parameters after init setup, and the decrypted master secret key after complete setup. The adversary could try to gain some advantage by creating multiple PKE pairs before authenticating with the authority, but will never has access to the raw sk unless combining it with a leakage attack. Denial of Service is possible by creating concurrent enclaves (either DE or FE) with different PKs, and passing encrypted ciphertexts to the “wrong” copy which would be unable to decrypt (but it’s not clear what the advantage of using rollback attacks would be, as the adversary could always conduct a DoS attack by denying the necessary resources to the enclave).