Verifying Constant-Time Implementations
Total Page:16
File Type:pdf, Size:1020Kb
Verifying Constant-Time Implementations José Bacelar Almeida, HASLab/INESC TEC and University of Minho; Manuel Barbosa, HASLab/INESC TEC and DCC FCUP; Gilles Barthe and François Dupressoir, IMDEA Software Institute; Michael Emmi, Bell Labs and Nokia https://www.usenix.org/conference/usenixsecurity16/technical-sessions/presentation/almeida This paper is included in the Proceedings of the 25th USENIX Security Symposium August 10–12, 2016 • Austin, TX ISBN 978-1-931971-32-4 Open access to the Proceedings of the 25th USENIX Security Symposium is sponsored by USENIX Verifying Constant-Time Implementations José Bacelar Almeida Manuel Barbosa HASLab - INESC TEC & Univ. Minho HASLab - INESC TEC & DCC FCUP Gilles Barthe François Dupressoir Michael Emmi IMDEA Software Institute IMDEA Software Institute Bell Labs, Nokia Abstract in the execution platform [23] or by interacting remotely The constant-time programming discipline is an effective with the implementation through a network. Notable ex- countermeasure against timing attacks, which can lead to amples of the latter include Brumley and Boneh’s key complete breaks of otherwise secure systems. However, recovery attacks against OpenSSL’s implementation of adhering to constant-time programming is hard on its the RSA decryption operation [15]; and the Canvel et own, and extremely hard under additional efficiency and al. [16] and Lucky 13 [4] timing-based padding-oracle legacy constraints. This makes automated verification of attacks, that recover application data from SSL/TLS con- constant-time code an essential component for building nections [38]. A different class of timing attacks exploit secure software. side-effects of cache-collisions; here the attacker infers We propose a novel approach for verifying constant- memory-access patterns of the target program — which time security of real-world code. Our approach is able may depend on secret data — from the memory latency to validate implementations that locally and intentionally correlation created by cache sharing between processes violate the constant-time policy, when such violations hosted on the same machine [11, 31]. It has been demon- are benign and leak no more information than the pub- strated in practice that these attacks allow the recovery of lic outputs of the computation. Such implementations, secret key material, such as complete AES keys [21]. which are used in cryptographic libraries to obtain impor- As a countermeasure, many security practitioners mit- tant speedups or to comply with legacy APIs, would be igate vulnerability by adopting so-called constant-time declared insecure by all prior solutions. programming disciplines. A common principle of such We implement our approach in a publicly available, disciplines governs programs’ control-flow paths in order cross-platform, and fully automated prototype, ct-verif, to protect against attacks based on measuring execution that leverages the SMACK and Boogie tools and verifies time and branch-prediction attacks, requiring that paths optimized LLVM implementations. We present verifica- do not depend on program secrets. On its own, this charac- tion results obtained over a wide range of constant-time terization is roughly equivalent to security in the program components from the NaCl, OpenSSL, FourQ and other counter model [29] in which program counter values do off-the-shelf libraries. The diversity and scale of our ex- not depend on program secrets. Stronger constant-time amples, as well as the fact that we deal with top-level policies also govern programs’ memory-access patterns APIs rather than being limited to low-level leaf functions, in order to protect against cache-timing attacks, requiring distinguishes ct-verif from prior tools. that accessed memory addresses do not depend on pro- Our approach is based on a simple reduction of gram secrets. Further refinements govern the operands of constant-time security of a program P to safety of a prod- program operations, e.g., requiring that inputs to certain uct program Q that simulates two executions of P. We operations do not depend on program secrets, as the exe- formalize and verify the reduction for a core high-level cution time of some machine instructions, notably integer language using the Coq proof assistant. division and floating point operations, may depend on the values of their operands. 1 Introduction Although constant-time security policies are the most effective and widely-used software-based countermea- Timing attacks pose a serious threat to otherwise secure sures against timing attacks [11, 25, 20], writing constant- software systems. Such attacks can be mounted by mea- time implementations can be difficult. Indeed, doing so suring the execution time of an implementation directly requires the use of low-level programming languages or 1 USENIX Association 25th USENIX Security Symposium 53 compiler knowledge, and forces developers to deviate dicating which inputs and outputs should be considered from conventional programming practices. For instance, public, the verification of our examples does not require the program if b then x := v1 else x := v2 may be re- user intervention, can handle existing (complete and non- placed with the less conventional x := b v +(1 b) v . modified) implementations, and is fully automated. ∗ 1 − ∗ 2 Furthermore, the observable properties of a program ex- One strength of our verification technique is that it is ecution are generally not evident from its source code, agnostic as to the representation of programs and could be e.g., due to optimizations made by compilers or due to performed on source code, intermediate representations, platform-specific behaviours. or machine code. From a theoretical point of view, our This raises the question of how to validate constant- approach to verifying constant-time policies is a sound time implementations. A recently disclosed timing leak and complete reduction of the security of a program P in OpenSSL’s DSA signing [19] procedure demonstrates to the assertion-safety of a program Q, meaning that P that writing constant-time code is complex and requires is constant-time (w.r.t. the chosen policy) if and only if some form of validation. The recent case of Amazon’s Q is assertion-safe. We formalize and verify the method s2n library also demonstrates that the deployment of less for a core high-level language using the Coq proof as- rigid timing countermeasures is extremely hard to val- sistant. Our reduction is inspired from prior work on idate: soon after its release, two patches1 were issued self-composition [10, 37] and product programs [40, 9], for protection against timing attacks [3, 5], the second of and constructs Q as a product of P with itself—each exe- which exploits a timing-related vulnerability introduced cution of Q encodes two executions of P. However, our when fixing the first. These vulnerabilities eluded both ex- approach is unique in that it exploits the key feature of tensive code review and testing, suggesting that standard constant-time policies: program paths must be indepen- software validation processes are an inadequate defense dent of program secrets. This allows a succinct construc- against timing vulnerabilities, and that more rigorous anal- tion for Q since each path of Q need only correspond to ysis techniques are necessary. a single control path3 of P — path divergence of the two In this work, we develop a unifying formal foundation executions of P would violate constant-time. Our method for constant-time programming policies, along with a for- is practical precisely because of this optimization: the mal and fully automated verification technique. Our for- product program Q has only as many paths as P itself, malism is parameterized by a flexible leakage model that and its verification can be fully automated. captures the various constant-time policies used in prac- Making use of this reduction in practice raises the is- tice, including path-based, address-based, and operand- sue of choosing the programming language over which based characterizations, wherein program paths, accessed verification is carried out. On the one hand, to obtain memory addresses, and operand sizes, respectively, are a faithful correspondence with the executable program independent of program secrets. Importantly, our for- under attacker scrutiny, one wants to be as close as pos- malism is precise with respect to the characterization of sible to the machine-executed assembly code. On the program secrets, distinguishing not only between public other hand, building robust and sustainable tools is made and private input values, but also between private and easier by existing robust and sustainable frameworks and publicly observable output values. While this distinction infrastructure. Our ct-verif prototype performs verifica- poses technical and theoretical challenges, constant-time tion of constant-time properties at the level of optimized implementations in cryptographic libraries like OpenSSL LLVM assembly code, which represents a sweet spot in include optimizations for which paths, addresses, and the design space outlined by the above requirements. operands are contingent not only on public input values, Indeed, performing verification after most optimization but also on publicly observable output values. Consid- passes ensures that the program, which may have been ering only input values as non-secret information would written in a higher-level such as C, preserves the constant- thus incorrectly characterize those implementations as time policy